resetting manifest requested domain to floor
[platform/upstream/libxml2.git] / xmlschemas.c
1 /*
2  * schemas.c : implementation of the XML Schema handling and
3  *             schema validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <veillard@redhat.com>
8  */
9
10 /*
11  * TODO:
12  *   - when types are redefined in includes, check that all
13  *     types in the redef list are equal
14  *     -> need a type equality operation.
15  *   - if we don't intend to use the schema for schemas, we
16  *     need to validate all schema attributes (ref, type, name)
17  *     against their types.
18  *   - Eliminate item creation for: ??
19  *
20  * URGENT TODO:
21  *   - For xsi-driven schema acquisition, augment the IDCs after every
22  *     acquisition episode (xmlSchemaAugmentIDC).
23  *
24  * NOTES:
25  *   - Elimated item creation for: <restriction>, <extension>,
26  *     <simpleContent>, <complexContent>, <list>, <union>
27  *
28  * PROBLEMS:
29  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31  *     XPath will have trouble to resolve to this namespace, since not known.
32  *
33  *
34  * CONSTRAINTS:
35  *
36  * Schema Component Constraint:
37  *   All Group Limited (cos-all-limited)
38  *   Status: complete
39  *   (1.2)
40  *     In xmlSchemaGroupDefReferenceTermFixup() and
41  *   (2)
42  *     In xmlSchemaParseModelGroup()
43  *     TODO: Actually this should go to component-level checks,
44  *     but is done here due to performance. Move it to an other layer
45  *     is schema construction via an API is implemented.
46  */
47 #define IN_LIBXML
48 #include "libxml.h"
49
50 #ifdef LIBXML_SCHEMAS_ENABLED
51
52 #include <string.h>
53 #include <libxml/xmlmemory.h>
54 #include <libxml/parser.h>
55 #include <libxml/parserInternals.h>
56 #include <libxml/hash.h>
57 #include <libxml/uri.h>
58 #include <libxml/xmlschemas.h>
59 #include <libxml/schemasInternals.h>
60 #include <libxml/xmlschemastypes.h>
61 #include <libxml/xmlautomata.h>
62 #include <libxml/xmlregexp.h>
63 #include <libxml/dict.h>
64 #include <libxml/encoding.h>
65 #include <libxml/xmlIO.h>
66 #ifdef LIBXML_PATTERN_ENABLED
67 #include <libxml/pattern.h>
68 #endif
69 #ifdef LIBXML_READER_ENABLED
70 #include <libxml/xmlreader.h>
71 #endif
72
73 /* #define DEBUG 1 */
74
75 /* #define DEBUG_CONTENT 1 */
76
77 /* #define DEBUG_TYPE 1 */
78
79 /* #define DEBUG_CONTENT_REGEXP 1 */
80
81 /* #define DEBUG_AUTOMATA 1 */
82
83 /* #define DEBUG_IDC */
84
85 /* #define DEBUG_IDC_NODE_TABLE */
86
87 /* #define WXS_ELEM_DECL_CONS_ENABLED */
88
89 #ifdef DEBUG_IDC
90  #ifndef DEBUG_IDC_NODE_TABLE
91   #define DEBUG_IDC_NODE_TABLE
92  #endif
93 #endif
94
95 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
96
97 #define ENABLE_REDEFINE
98
99 /* #define ENABLE_NAMED_LOCALS */
100
101 /* #define ENABLE_IDC_NODE_TABLES_TEST */
102
103 #define DUMP_CONTENT_MODEL
104
105 #ifdef LIBXML_READER_ENABLED
106 /* #define XML_SCHEMA_READER_ENABLED */
107 #endif
108
109 #define UNBOUNDED (1 << 30)
110 #define TODO                                                            \
111     xmlGenericError(xmlGenericErrorContext,                             \
112             "Unimplemented block at %s:%d\n",                           \
113             __FILE__, __LINE__);
114
115 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
116
117 /*
118  * The XML Schemas namespaces
119  */
120 static const xmlChar *xmlSchemaNs = (const xmlChar *)
121     "http://www.w3.org/2001/XMLSchema";
122
123 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124     "http://www.w3.org/2001/XMLSchema-instance";
125
126 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127     "http://www.w3.org/2000/xmlns/";
128
129 /*
130 * Come casting macros.
131 */
132 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
133 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
134 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
135 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
136 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
137 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
138 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
139 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
140 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
141 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
142 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
143 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
144 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
145 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
146 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
147 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
148 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
149
150 /*
151 * Macros to query common properties of components.
152 */
153 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
154
155 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
156 /*
157 * Macros for element declarations.
158 */
159 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
160
161 #define WXS_SUBST_HEAD(item) (item)->refDecl
162 /*
163 * Macros for attribute declarations.
164 */
165 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
166 /*
167 * Macros for attribute uses.
168 */
169 #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
170
171 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
172
173 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
174
175 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
176 /*
177 * Macros for attribute groups.
178 */
179 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
180 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
181 /*
182 * Macros for particles.
183 */
184 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
185
186 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
187
188 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
189
190 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
191 /*
192 * Macros for model groups definitions.
193 */
194 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
195 /*
196 * Macros for model groups.
197 */
198 #define WXS_IS_MODEL_GROUP(i) \
199     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
200      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
201      ((i)->type == XML_SCHEMA_TYPE_ALL))
202
203 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
204 /*
205 * Macros for schema buckets.
206 */
207 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
208     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
209
210 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
211     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
212
213 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
214
215 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
216 /*
217 * Macros for complex/simple types.
218 */
219 #define WXS_IS_ANYTYPE(i) \
220      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
221       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
222
223 #define WXS_IS_COMPLEX(i) \
224     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
225      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
226
227 #define WXS_IS_SIMPLE(item) \
228     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
229      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
230       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
231
232 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
233     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
234       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
235
236 #define WXS_IS_RESTRICTION(t) \
237     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
238
239 #define WXS_IS_EXTENSION(t) \
240     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
241
242 #define WXS_IS_TYPE_NOT_FIXED(i) \
243     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
244      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
245
246 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
247     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
248      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
249
250 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
251
252 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
253 /*
254 * Macros for exclusively for complex types.
255 */
256 #define WXS_HAS_COMPLEX_CONTENT(item) \
257     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
258      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
259      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
260
261 #define WXS_HAS_SIMPLE_CONTENT(item) \
262     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
263      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
264
265 #define WXS_HAS_MIXED_CONTENT(item) \
266     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
267
268 #define WXS_EMPTIABLE(t) \
269     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
270
271 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
272
273 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
274
275 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
276 /*
277 * Macros for exclusively for simple types.
278 */
279 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
280
281 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
282
283 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
284
285 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
286 /*
287 * Misc parser context macros.
288 */
289 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
290
291 #define WXS_HAS_BUCKETS(ctx) \
292 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
293 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
294
295 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
296
297 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
298
299 #define WXS_SCHEMA(ctx) (ctx)->schema
300
301 #define WXS_ADD_LOCAL(ctx, item) \
302     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
303
304 #define WXS_ADD_GLOBAL(ctx, item) \
305     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
306
307 #define WXS_ADD_PENDING(ctx, item) \
308     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
309 /*
310 * xmlSchemaItemList macros.
311 */
312 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
313 /*
314 * Misc macros.
315 */
316 #define IS_SCHEMA(node, type) \
317    ((node != NULL) && (node->ns != NULL) && \
318     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
319     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
320
321 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
322
323 /*
324 * Since we put the default/fixed values into the dict, we can
325 * use pointer comparison for those values.
326 * REMOVED: (xmlStrEqual((v1), (v2)))
327 */
328 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
329
330 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
331
332 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
333
334 #define HFAILURE if (res == -1) goto exit_failure;
335
336 #define HERROR if (res != 0) goto exit_error;
337
338 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
339 /*
340 * Some flags used for various schema constraints.
341 */
342 #define SUBSET_RESTRICTION  1<<0
343 #define SUBSET_EXTENSION    1<<1
344 #define SUBSET_SUBSTITUTION 1<<2
345 #define SUBSET_LIST         1<<3
346 #define SUBSET_UNION        1<<4
347
348 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
350
351 typedef struct _xmlSchemaItemList xmlSchemaItemList;
352 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
353 struct _xmlSchemaItemList {
354     void **items;  /* used for dynamic addition of schemata */
355     int nbItems; /* used for dynamic addition of schemata */
356     int sizeItems; /* used for dynamic addition of schemata */
357 };
358
359 #define XML_SCHEMA_CTXT_PARSER 1
360 #define XML_SCHEMA_CTXT_VALIDATOR 2
361
362 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364 struct _xmlSchemaAbstractCtxt {
365     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
366 };
367
368 typedef struct _xmlSchemaBucket xmlSchemaBucket;
369 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
370
371 #define XML_SCHEMA_SCHEMA_MAIN 0
372 #define XML_SCHEMA_SCHEMA_IMPORT 1
373 #define XML_SCHEMA_SCHEMA_INCLUDE 2
374 #define XML_SCHEMA_SCHEMA_REDEFINE 3
375
376 /**
377  * xmlSchemaSchemaRelation:
378  *
379  * Used to create a graph of schema relationships.
380  */
381 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383 struct _xmlSchemaSchemaRelation {
384     xmlSchemaSchemaRelationPtr next;
385     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386     const xmlChar *importNamespace;
387     xmlSchemaBucketPtr bucket;
388 };
389
390 #define XML_SCHEMA_BUCKET_MARKED 1<<0
391 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
392
393 struct _xmlSchemaBucket {
394     int type;
395     int flags;
396     const xmlChar *schemaLocation;
397     const xmlChar *origTargetNamespace;
398     const xmlChar *targetNamespace;
399     xmlDocPtr doc;
400     xmlSchemaSchemaRelationPtr relations;
401     int located;
402     int parsed;
403     int imported;
404     int preserveDoc;
405     xmlSchemaItemListPtr globals; /* Global components. */
406     xmlSchemaItemListPtr locals; /* Local components. */
407 };
408
409 /**
410  * xmlSchemaImport:
411  * (extends xmlSchemaBucket)
412  *
413  * Reflects a schema. Holds some information
414  * about the schema and its toplevel components. Duplicate
415  * toplevel components are not checked at this level.
416  */
417 typedef struct _xmlSchemaImport xmlSchemaImport;
418 typedef xmlSchemaImport *xmlSchemaImportPtr;
419 struct _xmlSchemaImport {
420     int type; /* Main OR import OR include. */
421     int flags;
422     const xmlChar *schemaLocation; /* The URI of the schema document. */
423     /* For chameleon includes, @origTargetNamespace will be NULL */
424     const xmlChar *origTargetNamespace;
425     /*
426     * For chameleon includes, @targetNamespace will be the
427     * targetNamespace of the including schema.
428     */
429     const xmlChar *targetNamespace;
430     xmlDocPtr doc; /* The schema node-tree. */
431     /* @relations will hold any included/imported/redefined schemas. */
432     xmlSchemaSchemaRelationPtr relations;
433     int located;
434     int parsed;
435     int imported;
436     int preserveDoc;
437     xmlSchemaItemListPtr globals;
438     xmlSchemaItemListPtr locals;
439     /* The imported schema. */
440     xmlSchemaPtr schema;
441 };
442
443 /*
444 * (extends xmlSchemaBucket)
445 */
446 typedef struct _xmlSchemaInclude xmlSchemaInclude;
447 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448 struct _xmlSchemaInclude {
449     int type;
450     int flags;
451     const xmlChar *schemaLocation;
452     const xmlChar *origTargetNamespace;
453     const xmlChar *targetNamespace;
454     xmlDocPtr doc;
455     xmlSchemaSchemaRelationPtr relations;
456     int located;
457     int parsed;
458     int imported;
459     int preserveDoc;
460     xmlSchemaItemListPtr globals; /* Global components. */
461     xmlSchemaItemListPtr locals; /* Local components. */
462
463     /* The owning main or import schema bucket. */
464     xmlSchemaImportPtr ownerImport;
465 };
466
467 /**
468  * xmlSchemaBasicItem:
469  *
470  * The abstract base type for schema components.
471  */
472 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474 struct _xmlSchemaBasicItem {
475     xmlSchemaTypeType type;
476 };
477
478 /**
479  * xmlSchemaAnnotItem:
480  *
481  * The abstract base type for annotated schema components.
482  * (Extends xmlSchemaBasicItem)
483  */
484 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486 struct _xmlSchemaAnnotItem {
487     xmlSchemaTypeType type;
488     xmlSchemaAnnotPtr annot;
489 };
490
491 /**
492  * xmlSchemaTreeItem:
493  *
494  * The abstract base type for tree-like structured schema components.
495  * (Extends xmlSchemaAnnotItem)
496  */
497 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499 struct _xmlSchemaTreeItem {
500     xmlSchemaTypeType type;
501     xmlSchemaAnnotPtr annot;
502     xmlSchemaTreeItemPtr next;
503     xmlSchemaTreeItemPtr children;
504 };
505
506
507 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
508 /**
509  * xmlSchemaAttributeUsePtr:
510  *
511  * The abstract base type for tree-like structured schema components.
512  * (Extends xmlSchemaTreeItem)
513  */
514 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516 struct _xmlSchemaAttributeUse {
517     xmlSchemaTypeType type;
518     xmlSchemaAnnotPtr annot;
519     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
520     /*
521     * The attr. decl. OR a QName-ref. to an attr. decl. OR
522     * a QName-ref. to an attribute group definition.
523     */
524     xmlSchemaAttributePtr attrDecl;
525
526     int flags;
527     xmlNodePtr node;
528     int occurs; /* required, optional */
529     const xmlChar * defValue;
530     xmlSchemaValPtr defVal;
531 };
532
533 /**
534  * xmlSchemaAttributeUseProhibPtr:
535  *
536  * A helper component to reflect attribute prohibitions.
537  * (Extends xmlSchemaBasicItem)
538  */
539 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541 struct _xmlSchemaAttributeUseProhib {
542     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
543     xmlNodePtr node;
544     const xmlChar *name;
545     const xmlChar *targetNamespace;
546     int isRef;
547 };
548
549 /**
550  * xmlSchemaRedef:
551  */
552 typedef struct _xmlSchemaRedef xmlSchemaRedef;
553 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554 struct _xmlSchemaRedef {
555     xmlSchemaRedefPtr next;
556     xmlSchemaBasicItemPtr item; /* The redefining component. */
557     xmlSchemaBasicItemPtr reference; /* The referencing component. */
558     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
559     const xmlChar *refName; /* The name of the to-be-redefined component. */
560     const xmlChar *refTargetNs; /* The target namespace of the
561                                    to-be-redefined comp. */
562     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
563 };
564
565 /**
566  * xmlSchemaConstructionCtxt:
567  */
568 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570 struct _xmlSchemaConstructionCtxt {
571     xmlSchemaPtr mainSchema; /* The main schema. */
572     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
573     xmlDictPtr dict;
574     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
575     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
576     xmlSchemaBucketPtr bucket; /* The current schema bucket */
577     xmlSchemaItemListPtr pending; /* All Components of all schemas that
578                                      need to be fixed. */
579     xmlHashTablePtr substGroups;
580     xmlSchemaRedefPtr redefs;
581     xmlSchemaRedefPtr lastRedef;
582 };
583
584 #define XML_SCHEMAS_PARSE_ERROR         1
585 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
586
587 struct _xmlSchemaParserCtxt {
588     int type;
589     void *errCtxt;             /* user specific error context */
590     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
591     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
592     int err;
593     int nberrors;
594     xmlStructuredErrorFunc serror;
595
596     xmlSchemaConstructionCtxtPtr constructor;
597     int ownsConstructor; /* TODO: Move this to parser *flags*. */
598
599     /* xmlSchemaPtr topschema;  */
600     /* xmlHashTablePtr namespaces;  */
601
602     xmlSchemaPtr schema;        /* The main schema in use */
603     int counter;
604
605     const xmlChar *URL;
606     xmlDocPtr doc;
607     int preserve;               /* Whether the doc should be freed  */
608
609     const char *buffer;
610     int size;
611
612     /*
613      * Used to build complex element content models
614      */
615     xmlAutomataPtr am;
616     xmlAutomataStatePtr start;
617     xmlAutomataStatePtr end;
618     xmlAutomataStatePtr state;
619
620     xmlDictPtr dict;            /* dictionnary for interned string names */
621     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
622     int options;
623     xmlSchemaValidCtxtPtr vctxt;
624     int isS4S;
625     int isRedefine;
626     int xsiAssemble;
627     int stop; /* If the parser should stop; i.e. a critical error. */
628     const xmlChar *targetNamespace;
629     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
630
631     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
632     int redefCounter; /* Used for redefinitions. */
633     xmlSchemaItemListPtr attrProhibs;
634 };
635
636 /**
637  * xmlSchemaQNameRef:
638  *
639  * A component reference item (not a schema component)
640  * (Extends xmlSchemaBasicItem)
641  */
642 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644 struct _xmlSchemaQNameRef {
645     xmlSchemaTypeType type;
646     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647     xmlSchemaTypeType itemType;
648     const xmlChar *name;
649     const xmlChar *targetNamespace;
650     xmlNodePtr node;
651 };
652
653 /**
654  * xmlSchemaParticle:
655  *
656  * A particle component.
657  * (Extends xmlSchemaTreeItem)
658  */
659 typedef struct _xmlSchemaParticle xmlSchemaParticle;
660 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661 struct _xmlSchemaParticle {
662     xmlSchemaTypeType type;
663     xmlSchemaAnnotPtr annot;
664     xmlSchemaTreeItemPtr next; /* next particle */
665     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666         a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667         etc.) */
668     int minOccurs;
669     int maxOccurs;
670     xmlNodePtr node;
671 };
672
673 /**
674  * xmlSchemaModelGroup:
675  *
676  * A model group component.
677  * (Extends xmlSchemaTreeItem)
678  */
679 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681 struct _xmlSchemaModelGroup {
682     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683     xmlSchemaAnnotPtr annot;
684     xmlSchemaTreeItemPtr next; /* not used */
685     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686     xmlNodePtr node;
687 };
688
689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
691 /**
692  * xmlSchemaModelGroupDef:
693  *
694  * A model group definition component.
695  * (Extends xmlSchemaTreeItem)
696  */
697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699 struct _xmlSchemaModelGroupDef {
700     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701     xmlSchemaAnnotPtr annot;
702     xmlSchemaTreeItemPtr next; /* not used */
703     xmlSchemaTreeItemPtr children; /* the "model group" */
704     const xmlChar *name;
705     const xmlChar *targetNamespace;
706     xmlNodePtr node;
707     int flags;
708 };
709
710 typedef struct _xmlSchemaIDC xmlSchemaIDC;
711 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712
713 /**
714  * xmlSchemaIDCSelect:
715  *
716  * The identity-constraint "field" and "selector" item, holding the
717  * XPath expression.
718  */
719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721 struct _xmlSchemaIDCSelect {
722     xmlSchemaIDCSelectPtr next;
723     xmlSchemaIDCPtr idc;
724     int index; /* an index position if significant for IDC key-sequences */
725     const xmlChar *xpath; /* the XPath expression */
726     void *xpathComp; /* the compiled XPath expression */
727 };
728
729 /**
730  * xmlSchemaIDC:
731  *
732  * The identity-constraint definition component.
733  * (Extends xmlSchemaAnnotItem)
734  */
735
736 struct _xmlSchemaIDC {
737     xmlSchemaTypeType type;
738     xmlSchemaAnnotPtr annot;
739     xmlSchemaIDCPtr next;
740     xmlNodePtr node;
741     const xmlChar *name;
742     const xmlChar *targetNamespace;
743     xmlSchemaIDCSelectPtr selector;
744     xmlSchemaIDCSelectPtr fields;
745     int nbFields;
746     xmlSchemaQNameRefPtr ref;
747 };
748
749 /**
750  * xmlSchemaIDCAug:
751  *
752  * The augmented IDC information used for validation.
753  */
754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756 struct _xmlSchemaIDCAug {
757     xmlSchemaIDCAugPtr next; /* next in a list */
758     xmlSchemaIDCPtr def; /* the IDC definition */
759     int keyrefDepth; /* the lowest tree level to which IDC
760                         tables need to be bubbled upwards */
761 };
762
763 /**
764  * xmlSchemaPSVIIDCKeySequence:
765  *
766  * The key sequence of a node table item.
767  */
768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770 struct _xmlSchemaPSVIIDCKey {
771     xmlSchemaTypePtr type;
772     xmlSchemaValPtr val;
773 };
774
775 /**
776  * xmlSchemaPSVIIDCNode:
777  *
778  * The node table item of a node table.
779  */
780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782 struct _xmlSchemaPSVIIDCNode {
783     xmlNodePtr node;
784     xmlSchemaPSVIIDCKeyPtr *keys;
785     int nodeLine;
786     int nodeQNameID;
787
788 };
789
790 /**
791  * xmlSchemaPSVIIDCBinding:
792  *
793  * The identity-constraint binding item of the [identity-constraint table].
794  */
795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797 struct _xmlSchemaPSVIIDCBinding {
798     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799     xmlSchemaIDCPtr definition; /* the IDC definition */
800     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801     int nbNodes; /* number of entries in the node table */
802     int sizeNodes; /* size of the node table */
803     xmlSchemaItemListPtr dupls;
804 };
805
806
807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809
810 #define XPATH_STATE_OBJ_MATCHES -2
811 #define XPATH_STATE_OBJ_BLOCKED -3
812
813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815
816 /**
817  * xmlSchemaIDCStateObj:
818  *
819  * The state object used to evaluate XPath expressions.
820  */
821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823 struct _xmlSchemaIDCStateObj {
824     int type;
825     xmlSchemaIDCStateObjPtr next; /* next if in a list */
826     int depth; /* depth of creation */
827     int *history; /* list of (depth, state-id) tuples */
828     int nbHistory;
829     int sizeHistory;
830     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831                                        matcher */
832     xmlSchemaIDCSelectPtr sel;
833     void *xpathCtxt;
834 };
835
836 #define IDC_MATCHER 0
837
838 /**
839  * xmlSchemaIDCMatcher:
840  *
841  * Used to evaluate IDC selectors (and fields).
842  */
843 struct _xmlSchemaIDCMatcher {
844     int type;
845     int depth; /* the tree depth at creation time */
846     xmlSchemaIDCMatcherPtr next; /* next in the list */
847     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849     int idcType;
850     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851                                          elements */
852     int sizeKeySeqs;
853     xmlSchemaItemListPtr targets; /* list of target-node
854                                      (xmlSchemaPSVIIDCNodePtr) entries */
855 };
856
857 /*
858 * Element info flags.
859 */
860 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
862 #define XML_SCHEMA_ELEM_INFO_NILLED            1<<2
863 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE        1<<3
864
865 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
866 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
867 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
868
869 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
870 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
871 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
872 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
873
874 /**
875  * xmlSchemaNodeInfo:
876  *
877  * Holds information of an element node.
878  */
879 struct _xmlSchemaNodeInfo {
880     int nodeType;
881     xmlNodePtr node;
882     int nodeLine;
883     const xmlChar *localName;
884     const xmlChar *nsName;
885     const xmlChar *value;
886     xmlSchemaValPtr val; /* the pre-computed value if any */
887     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
888
889     int flags; /* combination of node info flags */
890
891     int valNeeded;
892     int normVal;
893
894     xmlSchemaElementPtr decl; /* the element/attribute declaration */
895     int depth;
896     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
897                                             for the scope element*/
898     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
899                                            element */
900     xmlRegExecCtxtPtr regexCtxt;
901
902     const xmlChar **nsBindings; /* Namespace bindings on this element */
903     int nbNsBindings;
904     int sizeNsBindings;
905
906     int hasKeyrefs;
907     int appliedXPath; /* Indicates that an XPath has been applied. */
908 };
909
910 #define XML_SCHEMAS_ATTR_UNKNOWN 1
911 #define XML_SCHEMAS_ATTR_ASSESSED 2
912 #define XML_SCHEMAS_ATTR_PROHIBITED 3
913 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
914 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
915 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
916 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
917 #define XML_SCHEMAS_ATTR_DEFAULT 8
918 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
919 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
920 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
921 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
922 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
923 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
924 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
925 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
926 #define XML_SCHEMAS_ATTR_META 17
927 /*
928 * @metaType values of xmlSchemaAttrInfo.
929 */
930 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
931 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
932 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
933 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
934 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
935
936 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938 struct _xmlSchemaAttrInfo {
939     int nodeType;
940     xmlNodePtr node;
941     int nodeLine;
942     const xmlChar *localName;
943     const xmlChar *nsName;
944     const xmlChar *value;
945     xmlSchemaValPtr val; /* the pre-computed value if any */
946     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
947     int flags; /* combination of node info flags */
948
949     xmlSchemaAttributePtr decl; /* the attribute declaration */
950     xmlSchemaAttributeUsePtr use;  /* the attribute use */
951     int state;
952     int metaType;
953     const xmlChar *vcValue; /* the value constraint value */
954     xmlSchemaNodeInfoPtr parent;
955 };
956
957
958 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
959 /**
960  * xmlSchemaValidCtxt:
961  *
962  * A Schemas validation context
963  */
964 struct _xmlSchemaValidCtxt {
965     int type;
966     void *errCtxt;             /* user specific data block */
967     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
968     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
969     xmlStructuredErrorFunc serror;
970
971     xmlSchemaPtr schema;        /* The schema in use */
972     xmlDocPtr doc;
973     xmlParserInputBufferPtr input;
974     xmlCharEncoding enc;
975     xmlSAXHandlerPtr sax;
976     xmlParserCtxtPtr parserCtxt;
977     void *user_data; /* TODO: What is this for? */
978
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          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15163         xmlSchemaPCustomErr(ctxt,
15164             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15165             WXS_BASIC_CAST type, NULL,
15166             "A type, derived by list or union, must have "
15167             "the simple ur-type definition as base type, not '%s'",
15168             xmlSchemaGetComponentQName(&str, baseType));
15169         FREE_AND_NULL(str)
15170         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15171     }
15172     /*
15173     * Variety: One of {atomic, list, union}.
15174     */
15175     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15176         (! WXS_IS_LIST(type))) {
15177         xmlSchemaPCustomErr(ctxt,
15178             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15179             WXS_BASIC_CAST type, NULL,
15180             "The variety is absent", NULL);
15181         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15182     }
15183     /* TODO: Finish this. Hmm, is this finished? */
15184
15185     /*
15186     * 3 The {final} of the {base type definition} must not contain restriction.
15187     */
15188     if (xmlSchemaTypeFinalContains(baseType,
15189         XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15190         xmlSchemaPCustomErr(ctxt,
15191             XML_SCHEMAP_ST_PROPS_CORRECT_3,
15192             WXS_BASIC_CAST type, NULL,
15193             "The 'final' of its base type '%s' must not contain "
15194             "'restriction'",
15195             xmlSchemaGetComponentQName(&str, baseType));
15196         FREE_AND_NULL(str)
15197         return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15198     }
15199
15200     /*
15201     * 2 All simple type definitions must be derived ultimately from the ï¿½simple
15202     * ur-type definition (so� circular definitions are disallowed). That is, it
15203     * must be possible to reach a built-in primitive datatype or the ï¿½simple
15204     * ur-type definition� by repeatedly following the {base type definition}.
15205     *
15206     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15207     */
15208     return (0);
15209 }
15210
15211 /**
15212  * xmlSchemaCheckCOSSTRestricts:
15213  * @ctxt:  the schema parser context
15214  * @type:  the simple type definition
15215  *
15216  * Schema Component Constraint:
15217  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15218
15219  * Checks if the given @type (simpleType) is derived validly by restriction.
15220  * STATUS:
15221  *
15222  * Returns -1 on internal errors, 0 if the type is validly derived,
15223  * a positive error code otherwise.
15224  */
15225 static int
15226 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15227                              xmlSchemaTypePtr type)
15228 {
15229     xmlChar *str = NULL;
15230
15231     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15232         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15233             "given type is not a user-derived simpleType");
15234         return (-1);
15235     }
15236
15237     if (WXS_IS_ATOMIC(type)) {
15238         xmlSchemaTypePtr primitive;
15239         /*
15240         * 1.1 The {base type definition} must be an atomic simple
15241         * type definition or a built-in primitive datatype.
15242         */
15243         if (! WXS_IS_ATOMIC(type->baseType)) {
15244             xmlSchemaPCustomErr(pctxt,
15245                 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15246                 WXS_BASIC_CAST type, NULL,
15247                 "The base type '%s' is not an atomic simple type",
15248                 xmlSchemaGetComponentQName(&str, type->baseType));
15249             FREE_AND_NULL(str)
15250             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15251         }
15252         /* 1.2 The {final} of the {base type definition} must not contain
15253         * restriction.
15254         */
15255         /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15256         if (xmlSchemaTypeFinalContains(type->baseType,
15257             XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15258             xmlSchemaPCustomErr(pctxt,
15259                 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15260                 WXS_BASIC_CAST type, NULL,
15261                 "The final of its base type '%s' must not contain 'restriction'",
15262                 xmlSchemaGetComponentQName(&str, type->baseType));
15263             FREE_AND_NULL(str)
15264             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15265         }
15266
15267         /*
15268         * 1.3.1 DF must be an allowed constraining facet for the {primitive
15269         * type definition}, as specified in the appropriate subsection of 3.2
15270         * Primitive datatypes.
15271         */
15272         if (type->facets != NULL) {
15273             xmlSchemaFacetPtr facet;
15274             int ok = 1;
15275
15276             primitive = xmlSchemaGetPrimitiveType(type);
15277             if (primitive == NULL) {
15278                 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15279                     "failed to get primitive type");
15280                 return (-1);
15281             }
15282             facet = type->facets;
15283             do {
15284                 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15285                     ok = 0;
15286                     xmlSchemaPIllegalFacetAtomicErr(pctxt,
15287                         XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15288                         type, primitive, facet);
15289                 }
15290                 facet = facet->next;
15291             } while (facet != NULL);
15292             if (ok == 0)
15293                 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15294         }
15295         /*
15296         * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15297         * of the {base type definition} (call this BF),then the DF's {value}
15298         * must be a valid restriction of BF's {value} as defined in
15299         * [XML Schemas: Datatypes]."
15300         *
15301         * NOTE (1.3.2) Facet derivation constraints are currently handled in
15302         * xmlSchemaDeriveAndValidateFacets()
15303         */
15304     } else if (WXS_IS_LIST(type)) {
15305         xmlSchemaTypePtr itemType = NULL;
15306
15307         itemType = type->subtypes;
15308         if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15309             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15310                 "failed to evaluate the item type");
15311             return (-1);
15312         }
15313         if (WXS_IS_TYPE_NOT_FIXED(itemType))
15314             xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15315         /*
15316         * 2.1 The {item type definition} must have a {variety} of atomic or
15317         * union (in which case all the {member type definitions}
15318         * must be atomic).
15319         */
15320         if ((! WXS_IS_ATOMIC(itemType)) &&
15321             (! WXS_IS_UNION(itemType))) {
15322             xmlSchemaPCustomErr(pctxt,
15323                 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15324                 WXS_BASIC_CAST type, NULL,
15325                 "The item type '%s' does not have a variety of atomic or union",
15326                 xmlSchemaGetComponentQName(&str, itemType));
15327             FREE_AND_NULL(str)
15328             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15329         } else if (WXS_IS_UNION(itemType)) {
15330             xmlSchemaTypeLinkPtr member;
15331
15332             member = itemType->memberTypes;
15333             while (member != NULL) {
15334                 if (! WXS_IS_ATOMIC(member->type)) {
15335                     xmlSchemaPCustomErr(pctxt,
15336                         XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15337                         WXS_BASIC_CAST type, NULL,
15338                         "The item type is a union type, but the "
15339                         "member type '%s' of this item type is not atomic",
15340                         xmlSchemaGetComponentQName(&str, member->type));
15341                     FREE_AND_NULL(str)
15342                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15343                 }
15344                 member = member->next;
15345             }
15346         }
15347
15348         if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15349             xmlSchemaFacetPtr facet;
15350             /*
15351             * This is the case if we have: <simpleType><list ..
15352             */
15353             /*
15354             * 2.3.1
15355             * 2.3.1.1 The {final} of the {item type definition} must not
15356             * contain list.
15357             */
15358             if (xmlSchemaTypeFinalContains(itemType,
15359                 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15360                 xmlSchemaPCustomErr(pctxt,
15361                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15362                     WXS_BASIC_CAST type, NULL,
15363                     "The final of its item type '%s' must not contain 'list'",
15364                     xmlSchemaGetComponentQName(&str, itemType));
15365                 FREE_AND_NULL(str)
15366                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15367             }
15368             /*
15369             * 2.3.1.2 The {facets} must only contain the whiteSpace
15370             * facet component.
15371             * OPTIMIZE TODO: the S4S already disallows any facet
15372             * to be specified.
15373             */
15374             if (type->facets != NULL) {
15375                 facet = type->facets;
15376                 do {
15377                     if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15378                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15379                             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15380                             type, facet);
15381                         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15382                     }
15383                     facet = facet->next;
15384                 } while (facet != NULL);
15385             }
15386             /*
15387             * MAYBE TODO: (Hmm, not really) Datatypes states:
15388             * A ï¿½list� datatype can be ï¿½derived� from an ï¿½atomic� datatype
15389             * whose ï¿½lexical space� allows space (such as string or anyURI)or
15390             * a ï¿½union� datatype any of whose {member type definitions}'s
15391             * ï¿½lexical space� allows space.
15392             */
15393         } else {
15394             /*
15395             * This is the case if we have: <simpleType><restriction ...
15396             * I.e. the variety of "list" is inherited.
15397             */
15398             /*
15399             * 2.3.2
15400             * 2.3.2.1 The {base type definition} must have a {variety} of list.
15401             */
15402             if (! WXS_IS_LIST(type->baseType)) {
15403                 xmlSchemaPCustomErr(pctxt,
15404                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15405                     WXS_BASIC_CAST type, NULL,
15406                     "The base type '%s' must be a list type",
15407                     xmlSchemaGetComponentQName(&str, type->baseType));
15408                 FREE_AND_NULL(str)
15409                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15410             }
15411             /*
15412             * 2.3.2.2 The {final} of the {base type definition} must not
15413             * contain restriction.
15414             */
15415             if (xmlSchemaTypeFinalContains(type->baseType,
15416                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15417                 xmlSchemaPCustomErr(pctxt,
15418                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15419                     WXS_BASIC_CAST type, NULL,
15420                     "The 'final' of the base type '%s' must not contain 'restriction'",
15421                     xmlSchemaGetComponentQName(&str, type->baseType));
15422                 FREE_AND_NULL(str)
15423                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15424             }
15425             /*
15426             * 2.3.2.3 The {item type definition} must be validly derived
15427             * from the {base type definition}'s {item type definition} given
15428             * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15429             */
15430             {
15431                 xmlSchemaTypePtr baseItemType;
15432
15433                 baseItemType = type->baseType->subtypes;
15434                 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15435                     PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15436                         "failed to eval the item type of a base type");
15437                     return (-1);
15438                 }
15439                 if ((itemType != baseItemType) &&
15440                     (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15441                         baseItemType, 0) != 0)) {
15442                     xmlChar *strBIT = NULL, *strBT = NULL;
15443                     xmlSchemaPCustomErrExt(pctxt,
15444                         XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15445                         WXS_BASIC_CAST type, NULL,
15446                         "The item type '%s' is not validly derived from "
15447                         "the item type '%s' of the base type '%s'",
15448                         xmlSchemaGetComponentQName(&str, itemType),
15449                         xmlSchemaGetComponentQName(&strBIT, baseItemType),
15450                         xmlSchemaGetComponentQName(&strBT, type->baseType));
15451
15452                     FREE_AND_NULL(str)
15453                     FREE_AND_NULL(strBIT)
15454                     FREE_AND_NULL(strBT)
15455                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15456                 }
15457             }
15458
15459             if (type->facets != NULL) {
15460                 xmlSchemaFacetPtr facet;
15461                 int ok = 1;
15462                 /*
15463                 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15464                 * and enumeration facet components are allowed among the {facets}.
15465                 */
15466                 facet = type->facets;
15467                 do {
15468                     switch (facet->type) {
15469                         case XML_SCHEMA_FACET_LENGTH:
15470                         case XML_SCHEMA_FACET_MINLENGTH:
15471                         case XML_SCHEMA_FACET_MAXLENGTH:
15472                         case XML_SCHEMA_FACET_WHITESPACE:
15473                             /*
15474                             * TODO: 2.5.1.2 List datatypes
15475                             * The value of ï¿½whiteSpace� is fixed to the value collapse.
15476                             */
15477                         case XML_SCHEMA_FACET_PATTERN:
15478                         case XML_SCHEMA_FACET_ENUMERATION:
15479                             break;
15480                         default: {
15481                             xmlSchemaPIllegalFacetListUnionErr(pctxt,
15482                                 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15483                                 type, facet);
15484                             /*
15485                             * We could return, but it's nicer to report all
15486                             * invalid facets.
15487                             */
15488                             ok = 0;
15489                         }
15490                     }
15491                     facet = facet->next;
15492                 } while (facet != NULL);
15493                 if (ok == 0)
15494                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15495                 /*
15496                 * SPEC (2.3.2.5) (same as 1.3.2)
15497                 *
15498                 * NOTE (2.3.2.5) This is currently done in
15499                 * xmlSchemaDeriveAndValidateFacets()
15500                 */
15501             }
15502         }
15503     } else if (WXS_IS_UNION(type)) {
15504         /*
15505         * 3.1 The {member type definitions} must all have {variety} of
15506         * atomic or list.
15507         */
15508         xmlSchemaTypeLinkPtr member;
15509
15510         member = type->memberTypes;
15511         while (member != NULL) {
15512             if (WXS_IS_TYPE_NOT_FIXED(member->type))
15513                 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15514
15515             if ((! WXS_IS_ATOMIC(member->type)) &&
15516                 (! WXS_IS_LIST(member->type))) {
15517                 xmlSchemaPCustomErr(pctxt,
15518                     XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15519                     WXS_BASIC_CAST type, NULL,
15520                     "The member type '%s' is neither an atomic, nor a list type",
15521                     xmlSchemaGetComponentQName(&str, member->type));
15522                 FREE_AND_NULL(str)
15523                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15524             }
15525             member = member->next;
15526         }
15527         /*
15528         * 3.3.1 If the {base type definition} is the ï¿½simple ur-type
15529         * definition�
15530         */
15531         if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15532             /*
15533             * 3.3.1.1 All of the {member type definitions} must have a
15534             * {final} which does not contain union.
15535             */
15536             member = type->memberTypes;
15537             while (member != NULL) {
15538                 if (xmlSchemaTypeFinalContains(member->type,
15539                     XML_SCHEMAS_TYPE_FINAL_UNION)) {
15540                     xmlSchemaPCustomErr(pctxt,
15541                         XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15542                         WXS_BASIC_CAST type, NULL,
15543                         "The 'final' of member type '%s' contains 'union'",
15544                         xmlSchemaGetComponentQName(&str, member->type));
15545                     FREE_AND_NULL(str)
15546                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15547                 }
15548                 member = member->next;
15549             }
15550             /*
15551             * 3.3.1.2 The {facets} must be empty.
15552             */
15553             if (type->facetSet != NULL) {
15554                 xmlSchemaPCustomErr(pctxt,
15555                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15556                     WXS_BASIC_CAST type, NULL,
15557                     "No facets allowed", NULL);
15558                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15559             }
15560         } else {
15561             /*
15562             * 3.3.2.1 The {base type definition} must have a {variety} of union.
15563             * I.e. the variety of "list" is inherited.
15564             */
15565             if (! WXS_IS_UNION(type->baseType)) {
15566                 xmlSchemaPCustomErr(pctxt,
15567                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15568                     WXS_BASIC_CAST type, NULL,
15569                     "The base type '%s' is not a union type",
15570                     xmlSchemaGetComponentQName(&str, type->baseType));
15571                 FREE_AND_NULL(str)
15572                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15573             }
15574             /*
15575             * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15576             */
15577             if (xmlSchemaTypeFinalContains(type->baseType,
15578                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15579                 xmlSchemaPCustomErr(pctxt,
15580                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15581                     WXS_BASIC_CAST type, NULL,
15582                     "The 'final' of its base type '%s' must not contain 'restriction'",
15583                     xmlSchemaGetComponentQName(&str, type->baseType));
15584                 FREE_AND_NULL(str)
15585                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15586             }
15587             /*
15588             * 3.3.2.3 The {member type definitions}, in order, must be validly
15589             * derived from the corresponding type definitions in the {base
15590             * type definition}'s {member type definitions} given the empty set,
15591             * as defined in Type Derivation OK (Simple) (�3.14.6).
15592             */
15593             {
15594                 xmlSchemaTypeLinkPtr baseMember;
15595
15596                 /*
15597                 * OPTIMIZE: if the type is restricting, it has no local defined
15598                 * member types and inherits the member types of the base type;
15599                 * thus a check for equality can be skipped.
15600                 */
15601                 /*
15602                 * Even worse: I cannot see a scenario where a restricting
15603                 * union simple type can have other member types as the member
15604                 * types of it's base type. This check seems not necessary with
15605                 * respect to the derivation process in libxml2.
15606                 * But necessary if constructing types with an API.
15607                 */
15608                 if (type->memberTypes != NULL) {
15609                     member = type->memberTypes;
15610                     baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15611                     if ((member == NULL) && (baseMember != NULL)) {
15612                         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15613                             "different number of member types in base");
15614                     }
15615                     while (member != NULL) {
15616                         if (baseMember == NULL) {
15617                             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15618                             "different number of member types in base");
15619                         } else if ((member->type != baseMember->type) &&
15620                             (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15621                                 member->type, baseMember->type, 0) != 0)) {
15622                             xmlChar *strBMT = NULL, *strBT = NULL;
15623
15624                             xmlSchemaPCustomErrExt(pctxt,
15625                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15626                                 WXS_BASIC_CAST type, NULL,
15627                                 "The member type %s is not validly "
15628                                 "derived from its corresponding member "
15629                                 "type %s of the base type %s",
15630                                 xmlSchemaGetComponentQName(&str, member->type),
15631                                 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15632                                 xmlSchemaGetComponentQName(&strBT, type->baseType));
15633                             FREE_AND_NULL(str)
15634                             FREE_AND_NULL(strBMT)
15635                             FREE_AND_NULL(strBT)
15636                             return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15637                         }
15638                         member = member->next;
15639                         if (baseMember != NULL)
15640                             baseMember = baseMember->next;
15641                     }
15642                 }
15643             }
15644             /*
15645             * 3.3.2.4 Only pattern and enumeration facet components are
15646             * allowed among the {facets}.
15647             */
15648             if (type->facets != NULL) {
15649                 xmlSchemaFacetPtr facet;
15650                 int ok = 1;
15651
15652                 facet = type->facets;
15653                 do {
15654                     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15655                         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15656                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15657                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15658                                 type, facet);
15659                         ok = 0;
15660                     }
15661                     facet = facet->next;
15662                 } while (facet != NULL);
15663                 if (ok == 0)
15664                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15665
15666             }
15667             /*
15668             * SPEC (3.3.2.5) (same as 1.3.2)
15669             *
15670             * NOTE (3.3.2.5) This is currently done in
15671             * xmlSchemaDeriveAndValidateFacets()
15672             */
15673         }
15674     }
15675
15676     return (0);
15677 }
15678
15679 /**
15680  * xmlSchemaCheckSRCSimpleType:
15681  * @ctxt:  the schema parser context
15682  * @type:  the simple type definition
15683  *
15684  * Checks crc-simple-type constraints.
15685  *
15686  * Returns 0 if the constraints are satisfied,
15687  * if not a positive error code and -1 on internal
15688  * errors.
15689  */
15690 #if 0
15691 static int
15692 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15693                             xmlSchemaTypePtr type)
15694 {
15695     /*
15696     * src-simple-type.1 The corresponding simple type definition, if any,
15697     * must satisfy the conditions set out in Constraints on Simple Type
15698     * Definition Schema Components (�3.14.6).
15699     */
15700     if (WXS_IS_RESTRICTION(type)) {
15701         /*
15702         * src-simple-type.2 "If the <restriction> alternative is chosen,
15703         * either it must have a base [attribute] or a <simpleType> among its
15704         * [children], but not both."
15705         * NOTE: This is checked in the parse function of <restriction>.
15706         */
15707         /*
15708         *
15709         */
15710     } else if (WXS_IS_LIST(type)) {
15711         /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15712         * an itemType [attribute] or a <simpleType> among its [children],
15713         * but not both."
15714         *
15715         * NOTE: This is checked in the parse function of <list>.
15716         */
15717     } else if (WXS_IS_UNION(type)) {
15718         /*
15719         * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15720         */
15721     }
15722     return (0);
15723 }
15724 #endif
15725
15726 static int
15727 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15728 {
15729    if (ctxt->vctxt == NULL) {
15730         ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15731         if (ctxt->vctxt == NULL) {
15732             xmlSchemaPErr(ctxt, NULL,
15733                 XML_SCHEMAP_INTERNAL,
15734                 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15735                 "failed to create a temp. validation context.\n",
15736                 NULL, NULL);
15737             return (-1);
15738         }
15739         /* TODO: Pass user data. */
15740         xmlSchemaSetValidErrors(ctxt->vctxt,
15741             ctxt->error, ctxt->warning, ctxt->errCtxt);
15742         xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15743             ctxt->serror, ctxt->errCtxt);
15744     }
15745     return (0);
15746 }
15747
15748 static int
15749 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15750                              xmlNodePtr node,
15751                              xmlSchemaTypePtr type,
15752                              const xmlChar *value,
15753                              xmlSchemaValPtr *retVal,
15754                              int fireErrors,
15755                              int normalize,
15756                              int isNormalized);
15757
15758 /**
15759  * xmlSchemaParseCheckCOSValidDefault:
15760  * @pctxt:  the schema parser context
15761  * @type:  the simple type definition
15762  * @value: the default value
15763  * @node: an optional node (the holder of the value)
15764  *
15765  * Schema Component Constraint: Element Default Valid (Immediate)
15766  * (cos-valid-default)
15767  * This will be used by the parser only. For the validator there's
15768  * an other version.
15769  *
15770  * Returns 0 if the constraints are satisfied,
15771  * if not, a positive error code and -1 on internal
15772  * errors.
15773  */
15774 static int
15775 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15776                                    xmlNodePtr node,
15777                                    xmlSchemaTypePtr type,
15778                                    const xmlChar *value,
15779                                    xmlSchemaValPtr *val)
15780 {
15781     int ret = 0;
15782
15783     /*
15784     * cos-valid-default:
15785     * Schema Component Constraint: Element Default Valid (Immediate)
15786     * For a string to be a valid default with respect to a type
15787     * definition the appropriate case among the following must be true:
15788     */
15789     if WXS_IS_COMPLEX(type) {
15790         /*
15791         * Complex type.
15792         *
15793         * SPEC (2.1) "its {content type} must be a simple type definition
15794         * or mixed."
15795         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15796         * type}'s particle must be ï¿½emptiable� as defined by
15797         * Particle Emptiable (�3.9.6)."
15798         */
15799         if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15800             ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15801             /* NOTE that this covers (2.2.2) as well. */
15802             xmlSchemaPCustomErr(pctxt,
15803                 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15804                 WXS_BASIC_CAST type, type->node,
15805                 "For a string to be a valid default, the type definition "
15806                 "must be a simple type or a complex type with mixed content "
15807                 "and a particle emptiable", NULL);
15808             return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15809         }
15810     }
15811     /*
15812     * 1 If the type definition is a simple type definition, then the string
15813     * must be ï¿½valid� with respect to that definition as defined by String
15814     * Valid (�3.14.4).
15815     *
15816     * AND
15817     *
15818     * 2.2.1 If the {content type} is a simple type definition, then the
15819     * string must be ï¿½valid� with respect to that simple type definition
15820     * as defined by String Valid (�3.14.4).
15821     */
15822     if (WXS_IS_SIMPLE(type))
15823         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15824             type, value, val, 1, 1, 0);
15825     else if (WXS_HAS_SIMPLE_CONTENT(type))
15826         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15827             type->contentTypeDef, value, val, 1, 1, 0);
15828     else
15829         return (ret);
15830
15831     if (ret < 0) {
15832         PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15833             "calling xmlSchemaVCheckCVCSimpleType()");
15834     }
15835
15836     return (ret);
15837 }
15838
15839 /**
15840  * xmlSchemaCheckCTPropsCorrect:
15841  * @ctxt:  the schema parser context
15842  * @type:  the complex type definition
15843  *
15844  *.(4.6) Constraints on Complex Type Definition Schema Components
15845  * Schema Component Constraint:
15846  * Complex Type Definition Properties Correct (ct-props-correct)
15847  * STATUS: (seems) complete
15848  *
15849  * Returns 0 if the constraints are satisfied, a positive
15850  * error code if not and -1 if an internal error occured.
15851  */
15852 static int
15853 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15854                              xmlSchemaTypePtr type)
15855 {
15856     /*
15857     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15858     *
15859     * SPEC (1) "The values of the properties of a complex type definition must
15860     * be as described in the property tableau in The Complex Type Definition
15861     * Schema Component (�3.4.1), modulo the impact of Missing
15862     * Sub-components (�5.3)."
15863     */
15864     if ((type->baseType != NULL) &&
15865         (WXS_IS_SIMPLE(type->baseType)) &&
15866         (WXS_IS_EXTENSION(type) == 0)) {
15867         /*
15868         * SPEC (2) "If the {base type definition} is a simple type definition,
15869         * the {derivation method} must be extension."
15870         */
15871         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15872             XML_SCHEMAP_SRC_CT_1,
15873             NULL, WXS_BASIC_CAST type,
15874             "If the base type is a simple type, the derivation method must be "
15875             "'extension'", NULL, NULL);
15876         return (XML_SCHEMAP_SRC_CT_1);
15877     }
15878     /*
15879     * SPEC (3) "Circular definitions are disallowed, except for the ï¿½ur-type
15880     * definition�. That is, it must be possible to reach the ï¿½ur-type
15881     * definition by repeatedly following the {base type definition}."
15882     *
15883     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15884     */
15885     /*
15886     * NOTE that (4) and (5) need the following:
15887     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15888     *   - attribute group references need to be expanded already
15889     *   - simple types need to be typefixed already
15890     */
15891     if (type->attrUses &&
15892         (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15893     {
15894         xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15895         xmlSchemaAttributeUsePtr use, tmp;
15896         int i, j, hasId = 0;
15897
15898         for (i = uses->nbItems -1; i >= 0; i--) {
15899             use = uses->items[i];
15900
15901             /*
15902             * SPEC ct-props-correct
15903             * (4) "Two distinct attribute declarations in the
15904             * {attribute uses} must not have identical {name}s and
15905             * {target namespace}s."
15906             */
15907             if (i > 0) {
15908                 for (j = i -1; j >= 0; j--) {
15909                     tmp = uses->items[j];
15910                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
15911                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
15912                         (WXS_ATTRUSE_DECL_TNS(use) ==
15913                         WXS_ATTRUSE_DECL_TNS(tmp)))
15914                     {
15915                         xmlChar *str = NULL;
15916
15917                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15918                             XML_SCHEMAP_AG_PROPS_CORRECT,
15919                             NULL, WXS_BASIC_CAST type,
15920                             "Duplicate %s",
15921                             xmlSchemaGetComponentDesignation(&str, use),
15922                             NULL);
15923                         FREE_AND_NULL(str);
15924                         /*
15925                         * Remove the duplicate.
15926                         */
15927                         if (xmlSchemaItemListRemove(uses, i) == -1)
15928                             goto exit_failure;
15929                         goto next_use;
15930                     }
15931                 }
15932             }
15933             /*
15934             * SPEC ct-props-correct
15935             * (5) "Two distinct attribute declarations in the
15936             * {attribute uses} must not have {type definition}s which
15937             * are or are derived from ID."
15938             */
15939             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15940                 if (xmlSchemaIsDerivedFromBuiltInType(
15941                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15942                 {
15943                     if (hasId) {
15944                         xmlChar *str = NULL;
15945
15946                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15947                             XML_SCHEMAP_AG_PROPS_CORRECT,
15948                             NULL, WXS_BASIC_CAST type,
15949                             "There must not exist more than one attribute "
15950                             "declaration of type 'xs:ID' "
15951                             "(or derived from 'xs:ID'). The %s violates this "
15952                             "constraint",
15953                             xmlSchemaGetComponentDesignation(&str, use),
15954                             NULL);
15955                         FREE_AND_NULL(str);
15956                         if (xmlSchemaItemListRemove(uses, i) == -1)
15957                             goto exit_failure;
15958                     }
15959
15960                     hasId = 1;
15961                 }
15962             }
15963 next_use: {}
15964         }
15965     }
15966     return (0);
15967 exit_failure:
15968     return(-1);
15969 }
15970
15971 static int
15972 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15973                        xmlSchemaTypePtr typeB)
15974 {
15975     /*
15976     * TODO: This should implement component-identity
15977     * in the future.
15978     */
15979     if ((typeA == NULL) || (typeB == NULL))
15980         return (0);
15981     return (typeA == typeB);
15982 }
15983
15984 /**
15985  * xmlSchemaCheckCOSCTDerivedOK:
15986  * @ctxt:  the schema parser context
15987  * @type:  the to-be derived complex type definition
15988  * @baseType:  the base complex type definition
15989  * @set: the given set
15990  *
15991  * Schema Component Constraint:
15992  * Type Derivation OK (Complex) (cos-ct-derived-ok)
15993  *
15994  * STATUS: completed
15995  *
15996  * Returns 0 if the constraints are satisfied, or 1
15997  * if not.
15998  */
15999 static int
16000 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16001                              xmlSchemaTypePtr type,
16002                              xmlSchemaTypePtr baseType,
16003                              int set)
16004 {
16005     int equal = xmlSchemaAreEqualTypes(type, baseType);
16006     /* TODO: Error codes. */
16007     /*
16008     * SPEC "For a complex type definition (call it D, for derived)
16009     * to be validly derived from a type definition (call this
16010     * B, for base) given a subset of {extension, restriction}
16011     * all of the following must be true:"
16012     */
16013     if (! equal) {
16014         /*
16015         * SPEC (1) "If B and D are not the same type definition, then the
16016         * {derivation method} of D must not be in the subset."
16017         */
16018         if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16019             ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16020             return (1);
16021     } else {
16022         /*
16023         * SPEC (2.1) "B and D must be the same type definition."
16024         */
16025         return (0);
16026     }
16027     /*
16028     * SPEC (2.2) "B must be D's {base type definition}."
16029     */
16030     if (type->baseType == baseType)
16031         return (0);
16032     /*
16033     * SPEC (2.3.1) "D's {base type definition} must not be the ï¿½ur-type
16034     * definition�."
16035     */
16036     if (WXS_IS_ANYTYPE(type->baseType))
16037         return (1);
16038
16039     if (WXS_IS_COMPLEX(type->baseType)) {
16040         /*
16041         * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16042         * must be validly derived from B given the subset as defined by this
16043         * constraint."
16044         */
16045         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16046             baseType, set));
16047     } else {
16048         /*
16049         * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16050         * must be validly derived from B given the subset as defined in Type
16051         * Derivation OK (Simple) (�3.14.6).
16052         */
16053         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16054             baseType, set));
16055     }
16056 }
16057
16058 /**
16059  * xmlSchemaCheckCOSDerivedOK:
16060  * @type:  the derived simple type definition
16061  * @baseType:  the base type definition
16062  *
16063  * Calls:
16064  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16065  *
16066  * Checks wheter @type can be validly derived from @baseType.
16067  *
16068  * Returns 0 on success, an positive error code otherwise.
16069  */
16070 static int
16071 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16072                            xmlSchemaTypePtr type,
16073                            xmlSchemaTypePtr baseType,
16074                            int set)
16075 {
16076     if (WXS_IS_SIMPLE(type))
16077         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16078     else
16079         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16080 }
16081
16082 /**
16083  * xmlSchemaCheckCOSCTExtends:
16084  * @ctxt:  the schema parser context
16085  * @type:  the complex type definition
16086  *
16087  * (3.4.6) Constraints on Complex Type Definition Schema Components
16088  * Schema Component Constraint:
16089  * Derivation Valid (Extension) (cos-ct-extends)
16090  *
16091  * STATUS:
16092  *   missing:
16093  *     (1.5)
16094  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16095  *
16096  * Returns 0 if the constraints are satisfied, a positive
16097  * error code if not and -1 if an internal error occured.
16098  */
16099 static int
16100 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16101                            xmlSchemaTypePtr type)
16102 {
16103     xmlSchemaTypePtr base = type->baseType;
16104     /*
16105     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16106     * temporarily only.
16107     */
16108     /*
16109     * SPEC (1) "If the {base type definition} is a complex type definition,
16110     * then all of the following must be true:"
16111     */
16112     if (WXS_IS_COMPLEX(base)) {
16113         /*
16114         * SPEC (1.1) "The {final} of the {base type definition} must not
16115         * contain extension."
16116         */
16117         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16118             xmlSchemaPCustomErr(ctxt,
16119                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16120                 WXS_BASIC_CAST type, NULL,
16121                 "The 'final' of the base type definition "
16122                 "contains 'extension'", NULL);
16123             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16124         }
16125
16126         /*
16127         * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16128         * since they are automatically satisfied through the
16129         * inheriting mechanism.
16130         * Note that even if redefining components, the inheriting mechanism
16131         * is used.
16132         */
16133 #if 0
16134         /*
16135         * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16136         * uses}
16137         * of the complex type definition itself, that is, for every attribute
16138         * use in the {attribute uses} of the {base type definition}, there
16139         * must be an attribute use in the {attribute uses} of the complex
16140         * type definition itself whose {attribute declaration} has the same
16141         * {name}, {target namespace} and {type definition} as its attribute
16142         * declaration"
16143         */
16144         if (base->attrUses != NULL) {
16145             int i, j, found;
16146             xmlSchemaAttributeUsePtr use, buse;
16147
16148             for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16149                 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16150                 found = 0;
16151                 if (type->attrUses != NULL) {
16152                     use = (WXS_LIST_CAST type->attrUses)->items[j];
16153                     for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16154                     {
16155                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
16156                                 WXS_ATTRUSE_DECL_NAME(buse)) &&
16157                             (WXS_ATTRUSE_DECL_TNS(use) ==
16158                                 WXS_ATTRUSE_DECL_TNS(buse)) &&
16159                             (WXS_ATTRUSE_TYPEDEF(use) ==
16160                                 WXS_ATTRUSE_TYPEDEF(buse))
16161                         {
16162                             found = 1;
16163                             break;
16164                         }
16165                     }
16166                 }
16167                 if (! found) {
16168                     xmlChar *str = NULL;
16169
16170                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
16171                         XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16172                         NULL, WXS_BASIC_CAST type,
16173                         /*
16174                         * TODO: The report does not indicate that also the
16175                         * type needs to be the same.
16176                         */
16177                         "This type is missing a matching correspondent "
16178                         "for its {base type}'s %s in its {attribute uses}",
16179                         xmlSchemaGetComponentDesignation(&str,
16180                             buse->children),
16181                         NULL);
16182                     FREE_AND_NULL(str)
16183                 }
16184             }
16185         }
16186         /*
16187         * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16188         * definition must also have one, and the base type definition's
16189         * {attribute  wildcard}'s {namespace constraint} must be a subset
16190         * of the complex  type definition's {attribute wildcard}'s {namespace
16191         * constraint}, as defined by Wildcard Subset (�3.10.6)."
16192         */
16193
16194         /*
16195         * MAYBE TODO: Enable if ever needed. But this will be needed only
16196         * if created the type via a schema construction API.
16197         */
16198         if (base->attributeWildcard != NULL) {
16199             if (type->attributeWilcard == NULL) {
16200                 xmlChar *str = NULL;
16201
16202                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16203                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16204                     NULL, type,
16205                     "The base %s has an attribute wildcard, "
16206                     "but this type is missing an attribute wildcard",
16207                     xmlSchemaGetComponentDesignation(&str, base));
16208                 FREE_AND_NULL(str)
16209
16210             } else if (xmlSchemaCheckCOSNSSubset(
16211                 base->attributeWildcard, type->attributeWildcard))
16212             {
16213                 xmlChar *str = NULL;
16214
16215                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16216                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16217                     NULL, type,
16218                     "The attribute wildcard is not a valid "
16219                     "superset of the one in the base %s",
16220                     xmlSchemaGetComponentDesignation(&str, base));
16221                 FREE_AND_NULL(str)
16222             }
16223         }
16224 #endif
16225         /*
16226         * SPEC (1.4) "One of the following must be true:"
16227         */
16228         if ((type->contentTypeDef != NULL) &&
16229             (type->contentTypeDef == base->contentTypeDef)) {
16230             /*
16231             * SPEC (1.4.1) "The {content type} of the {base type definition}
16232             * and the {content type} of the complex type definition itself
16233             * must be the same simple type definition"
16234             * PASS
16235             */
16236         } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16237             (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16238             /*
16239             * SPEC (1.4.2) "The {content type} of both the {base type
16240             * definition} and the complex type definition itself must
16241             * be empty."
16242             * PASS
16243             */
16244         } else {
16245             /*
16246             * SPEC (1.4.3) "All of the following must be true:"
16247             */
16248             if (type->subtypes == NULL) {
16249                 /*
16250                 * SPEC 1.4.3.1 The {content type} of the complex type
16251                 * definition itself must specify a particle.
16252                 */
16253                 xmlSchemaPCustomErr(ctxt,
16254                     XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16255                     WXS_BASIC_CAST type, NULL,
16256                     "The content type must specify a particle", NULL);
16257                 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16258             }
16259             /*
16260             * SPEC (1.4.3.2) "One of the following must be true:"
16261             */
16262             if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16263                 /*
16264                 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16265                 * definition} must be empty.
16266                 * PASS
16267                 */
16268             } else {
16269                 /*
16270                 * SPEC (1.4.3.2.2) "All of the following must be true:"
16271                 */
16272                 if ((type->contentType != base->contentType) ||
16273                     ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16274                     (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16275                     /*
16276                     * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16277                     * or both must be element-only."
16278                     */
16279                     xmlSchemaPCustomErr(ctxt,
16280                         XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16281                         WXS_BASIC_CAST type, NULL,
16282                         "The content type of both, the type and its base "
16283                         "type, must either 'mixed' or 'element-only'", NULL);
16284                     return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16285                 }
16286                 /*
16287                 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16288                 * complex type definition must be a ï¿½valid extension�
16289                 * of the {base type definition}'s particle, as defined
16290                 * in Particle Valid (Extension) (�3.9.6)."
16291                 *
16292                 * NOTE that we won't check "Particle Valid (Extension)",
16293                 * since it is ensured by the derivation process in
16294                 * xmlSchemaTypeFixup(). We need to implement this when heading
16295                 * for a construction API
16296                 * TODO: !! This is needed to be checked if redefining a type !!
16297                 */
16298             }
16299             /*
16300             * URGENT TODO (1.5)
16301             */
16302         }
16303     } else {
16304         /*
16305         * SPEC (2) "If the {base type definition} is a simple type definition,
16306         * then all of the following must be true:"
16307         */
16308         if (type->contentTypeDef != base) {
16309             /*
16310             * SPEC (2.1) "The {content type} must be the same simple type
16311             * definition."
16312             */
16313             xmlSchemaPCustomErr(ctxt,
16314                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16315                 WXS_BASIC_CAST type, NULL,
16316                 "The content type must be the simple base type", NULL);
16317             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16318         }
16319         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16320             /*
16321             * SPEC (2.2) "The {final} of the {base type definition} must not
16322             * contain extension"
16323             * NOTE that this is the same as (1.1).
16324             */
16325             xmlSchemaPCustomErr(ctxt,
16326                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16327                 WXS_BASIC_CAST type, NULL,
16328                 "The 'final' of the base type definition "
16329                 "contains 'extension'", NULL);
16330             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16331         }
16332     }
16333     return (0);
16334 }
16335
16336 /**
16337  * xmlSchemaCheckDerivationOKRestriction:
16338  * @ctxt:  the schema parser context
16339  * @type:  the complex type definition
16340  *
16341  * (3.4.6) Constraints on Complex Type Definition Schema Components
16342  * Schema Component Constraint:
16343  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16344  *
16345  * STATUS:
16346  *   missing:
16347  *     (5.4.2) ???
16348  *
16349  * ATTENTION:
16350  * In XML Schema 1.1 this will be:
16351  * Validation Rule: Checking complex type subsumption
16352  *
16353  * Returns 0 if the constraints are satisfied, a positive
16354  * error code if not and -1 if an internal error occured.
16355  */
16356 static int
16357 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16358                                       xmlSchemaTypePtr type)
16359 {
16360     xmlSchemaTypePtr base;
16361
16362     /*
16363     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16364     * temporarily only.
16365     */
16366     base = type->baseType;
16367     if (! WXS_IS_COMPLEX(base)) {
16368         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16369             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16370             type->node, WXS_BASIC_CAST type,
16371             "The base type must be a complex type", NULL, NULL);
16372         return(ctxt->err);
16373     }
16374     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16375         /*
16376         * SPEC (1) "The {base type definition} must be a complex type
16377         * definition whose {final} does not contain restriction."
16378         */
16379         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16380             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16381             type->node, WXS_BASIC_CAST type,
16382             "The 'final' of the base type definition "
16383             "contains 'restriction'", NULL, NULL);
16384         return (ctxt->err);
16385     }
16386     /*
16387     * SPEC (2), (3) and (4)
16388     * Those are handled in a separate function, since the
16389     * same constraints are needed for redefinition of
16390     * attribute groups as well.
16391     */
16392     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16393         XML_SCHEMA_ACTION_DERIVE,
16394         WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16395         type->attrUses, base->attrUses,
16396         type->attributeWildcard,
16397         base->attributeWildcard) == -1)
16398     {
16399         return(-1);
16400     }
16401     /*
16402     * SPEC (5) "One of the following must be true:"
16403     */
16404     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16405         /*
16406         * SPEC (5.1) "The {base type definition} must be the
16407         * ï¿½ur-type definition�."
16408         * PASS
16409         */
16410     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16411             (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16412         /*
16413         * SPEC (5.2.1) "The {content type} of the complex type definition
16414         * must be a simple type definition"
16415         *
16416         * SPEC (5.2.2) "One of the following must be true:"
16417         */
16418         if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16419             (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16420         {
16421             int err;
16422             /*
16423             * SPEC (5.2.2.1) "The {content type} of the {base type
16424             * definition} must be a simple type definition from which
16425             * the {content type} is validly derived given the empty
16426             * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16427             *
16428             * ATTENTION TODO: This seems not needed if the type implicitely
16429             * derived from the base type.
16430             *
16431             */
16432             err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16433                 type->contentTypeDef, base->contentTypeDef, 0);
16434             if (err != 0) {
16435                 xmlChar *strA = NULL, *strB = NULL;
16436
16437                 if (err == -1)
16438                     return(-1);
16439                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16440                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16441                     NULL, WXS_BASIC_CAST type,
16442                     "The {content type} %s is not validly derived from the "
16443                     "base type's {content type} %s",
16444                     xmlSchemaGetComponentDesignation(&strA,
16445                         type->contentTypeDef),
16446                     xmlSchemaGetComponentDesignation(&strB,
16447                         base->contentTypeDef));
16448                 FREE_AND_NULL(strA);
16449                 FREE_AND_NULL(strB);
16450                 return(ctxt->err);
16451             }
16452         } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16453             (xmlSchemaIsParticleEmptiable(
16454                 (xmlSchemaParticlePtr) base->subtypes))) {
16455             /*
16456             * SPEC (5.2.2.2) "The {base type definition} must be mixed
16457             * and have a particle which is ï¿½emptiable� as defined in
16458             * Particle Emptiable (�3.9.6)."
16459             * PASS
16460             */
16461         } else {
16462             xmlSchemaPCustomErr(ctxt,
16463                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16464                 WXS_BASIC_CAST type, NULL,
16465                 "The content type of the base type must be either "
16466                 "a simple type or 'mixed' and an emptiable particle", NULL);
16467             return (ctxt->err);
16468         }
16469     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16470         /*
16471         * SPEC (5.3.1) "The {content type} of the complex type itself must
16472         * be empty"
16473         */
16474         if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16475             /*
16476             * SPEC (5.3.2.1) "The {content type} of the {base type
16477             * definition} must also be empty."
16478             * PASS
16479             */
16480         } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16481             (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16482             xmlSchemaIsParticleEmptiable(
16483                 (xmlSchemaParticlePtr) base->subtypes)) {
16484             /*
16485             * SPEC (5.3.2.2) "The {content type} of the {base type
16486             * definition} must be elementOnly or mixed and have a particle
16487             * which is ï¿½emptiable� as defined in Particle Emptiable (�3.9.6)."
16488             * PASS
16489             */
16490         } else {
16491             xmlSchemaPCustomErr(ctxt,
16492                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16493                 WXS_BASIC_CAST type, NULL,
16494                 "The content type of the base type must be either "
16495                 "empty or 'mixed' (or 'elements-only') and an emptiable "
16496                 "particle", NULL);
16497             return (ctxt->err);
16498         }
16499     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16500         WXS_HAS_MIXED_CONTENT(type)) {
16501         /*
16502         * SPEC (5.4.1.1) "The {content type} of the complex type definition
16503         * itself must be element-only"
16504         */
16505         if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16506             /*
16507             * SPEC (5.4.1.2) "The {content type} of the complex type
16508             * definition itself and of the {base type definition} must be
16509             * mixed"
16510             */
16511             xmlSchemaPCustomErr(ctxt,
16512                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16513                 WXS_BASIC_CAST type, NULL,
16514                 "If the content type is 'mixed', then the content type of the "
16515                 "base type must also be 'mixed'", NULL);
16516             return (ctxt->err);
16517         }
16518         /*
16519         * SPEC (5.4.2) "The particle of the complex type definition itself
16520         * must be a ï¿½valid restriction� of the particle of the {content
16521         * type} of the {base type definition} as defined in Particle Valid
16522         * (Restriction) (�3.9.6).
16523         *
16524         * URGENT TODO: (5.4.2)
16525         */
16526     } else {
16527         xmlSchemaPCustomErr(ctxt,
16528             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16529             WXS_BASIC_CAST type, NULL,
16530             "The type is not a valid restriction of its base type", NULL);
16531         return (ctxt->err);
16532     }
16533     return (0);
16534 }
16535
16536 /**
16537  * xmlSchemaCheckCTComponent:
16538  * @ctxt:  the schema parser context
16539  * @type:  the complex type definition
16540  *
16541  * (3.4.6) Constraints on Complex Type Definition Schema Components
16542  *
16543  * Returns 0 if the constraints are satisfied, a positive
16544  * error code if not and -1 if an internal error occured.
16545  */
16546 static int
16547 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16548                           xmlSchemaTypePtr type)
16549 {
16550     int ret;
16551     /*
16552     * Complex Type Definition Properties Correct
16553     */
16554     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16555     if (ret != 0)
16556         return (ret);
16557     if (WXS_IS_EXTENSION(type))
16558         ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16559     else
16560         ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16561     return (ret);
16562 }
16563
16564 /**
16565  * xmlSchemaCheckSRCCT:
16566  * @ctxt:  the schema parser context
16567  * @type:  the complex type definition
16568  *
16569  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16570  * Schema Representation Constraint:
16571  * Complex Type Definition Representation OK (src-ct)
16572  *
16573  * Returns 0 if the constraints are satisfied, a positive
16574  * error code if not and -1 if an internal error occured.
16575  */
16576 static int
16577 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16578                     xmlSchemaTypePtr type)
16579 {
16580     xmlSchemaTypePtr base;
16581     int ret = 0;
16582
16583     /*
16584     * TODO: Adjust the error codes here, as I used
16585     * XML_SCHEMAP_SRC_CT_1 only yet.
16586     */
16587     base = type->baseType;
16588     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16589         /*
16590         * 1 If the <complexContent> alternative is chosen, the type definition
16591         * ï¿½resolved� to by the ï¿½actual value� of the base [attribute]
16592         * must be a complex type definition;
16593         */
16594         if (! WXS_IS_COMPLEX(base)) {
16595             xmlChar *str = NULL;
16596             xmlSchemaPCustomErr(ctxt,
16597                 XML_SCHEMAP_SRC_CT_1,
16598                 WXS_BASIC_CAST type, type->node,
16599                 "If using <complexContent>, the base type is expected to be "
16600                 "a complex type. The base type '%s' is a simple type",
16601                 xmlSchemaFormatQName(&str, base->targetNamespace,
16602                 base->name));
16603             FREE_AND_NULL(str)
16604             return (XML_SCHEMAP_SRC_CT_1);
16605         }
16606     } else {
16607         /*
16608         * SPEC
16609         * 2 If the <simpleContent> alternative is chosen, all of the
16610         * following must be true:
16611         * 2.1 The type definition ï¿½resolved� to by the ï¿½actual value� of the
16612         * base [attribute] must be one of the following:
16613         */
16614         if (WXS_IS_SIMPLE(base)) {
16615             if (WXS_IS_EXTENSION(type) == 0) {
16616                 xmlChar *str = NULL;
16617                 /*
16618                 * 2.1.3 only if the <extension> alternative is also
16619                 * chosen, a simple type definition.
16620                 */
16621                 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16622                 xmlSchemaPCustomErr(ctxt,
16623                     XML_SCHEMAP_SRC_CT_1,
16624                     WXS_BASIC_CAST type, NULL,
16625                     "If using <simpleContent> and <restriction>, the base "
16626                     "type must be a complex type. The base type '%s' is "
16627                     "a simple type",
16628                     xmlSchemaFormatQName(&str, base->targetNamespace,
16629                         base->name));
16630                 FREE_AND_NULL(str)
16631                 return (XML_SCHEMAP_SRC_CT_1);
16632             }
16633         } else {
16634             /* Base type is a complex type. */
16635             if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16636                 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16637                 /*
16638                 * 2.1.1 a complex type definition whose {content type} is a
16639                 * simple type definition;
16640                 * PASS
16641                 */
16642                 if (base->contentTypeDef == NULL) {
16643                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16644                         WXS_BASIC_CAST type, NULL,
16645                         "Internal error: xmlSchemaCheckSRCCT, "
16646                         "'%s', base type has no content type",
16647                         type->name);
16648                     return (-1);
16649                 }
16650             } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16651                 (WXS_IS_RESTRICTION(type))) {
16652
16653                 /*
16654                 * 2.1.2 only if the <restriction> alternative is also
16655                 * chosen, a complex type definition whose {content type}
16656                 * is mixed and a particle emptiable.
16657                 */
16658                 if (! xmlSchemaIsParticleEmptiable(
16659                     (xmlSchemaParticlePtr) base->subtypes)) {
16660                     ret = XML_SCHEMAP_SRC_CT_1;
16661                 } else
16662                     /*
16663                     * Attention: at this point the <simpleType> child is in
16664                     * ->contentTypeDef (put there during parsing).
16665                     */
16666                     if (type->contentTypeDef == NULL) {
16667                     xmlChar *str = NULL;
16668                     /*
16669                     * 2.2 If clause 2.1.2 above is satisfied, then there
16670                     * must be a <simpleType> among the [children] of
16671                     * <restriction>.
16672                     */
16673                     /* TODO: Change error code to ..._SRC_CT_2_2. */
16674                     xmlSchemaPCustomErr(ctxt,
16675                         XML_SCHEMAP_SRC_CT_1,
16676                         WXS_BASIC_CAST type, NULL,
16677                         "A <simpleType> is expected among the children "
16678                         "of <restriction>, if <simpleContent> is used and "
16679                         "the base type '%s' is a complex type",
16680                         xmlSchemaFormatQName(&str, base->targetNamespace,
16681                         base->name));
16682                     FREE_AND_NULL(str)
16683                     return (XML_SCHEMAP_SRC_CT_1);
16684                 }
16685             } else {
16686                 ret = XML_SCHEMAP_SRC_CT_1;
16687             }
16688         }
16689         if (ret > 0) {
16690             xmlChar *str = NULL;
16691             if (WXS_IS_RESTRICTION(type)) {
16692                 xmlSchemaPCustomErr(ctxt,
16693                     XML_SCHEMAP_SRC_CT_1,
16694                     WXS_BASIC_CAST type, NULL,
16695                     "If <simpleContent> and <restriction> is used, the "
16696                     "base type must be a simple type or a complex type with "
16697                     "mixed content and particle emptiable. The base type "
16698                     "'%s' is none of those",
16699                     xmlSchemaFormatQName(&str, base->targetNamespace,
16700                     base->name));
16701             } else {
16702                 xmlSchemaPCustomErr(ctxt,
16703                     XML_SCHEMAP_SRC_CT_1,
16704                     WXS_BASIC_CAST type, NULL,
16705                     "If <simpleContent> and <extension> is used, the "
16706                     "base type must be a simple type. The base type '%s' "
16707                     "is a complex type",
16708                     xmlSchemaFormatQName(&str, base->targetNamespace,
16709                     base->name));
16710             }
16711             FREE_AND_NULL(str)
16712         }
16713     }
16714     /*
16715     * SPEC (3) "The corresponding complex type definition component must
16716     * satisfy the conditions set out in Constraints on Complex Type
16717     * Definition Schema Components (�3.4.6);"
16718     * NOTE (3) will be done in xmlSchemaTypeFixup().
16719     */
16720     /*
16721     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16722     * above for {attribute wildcard} is satisfied, the intensional
16723     * intersection must be expressible, as defined in Attribute Wildcard
16724     * Intersection (�3.10.6).
16725     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16726     */
16727     return (ret);
16728 }
16729
16730 #ifdef ENABLE_PARTICLE_RESTRICTION
16731 /**
16732  * xmlSchemaCheckParticleRangeOK:
16733  * @ctxt:  the schema parser context
16734  * @type:  the complex type definition
16735  *
16736  * (3.9.6) Constraints on Particle Schema Components
16737  * Schema Component Constraint:
16738  * Occurrence Range OK (range-ok)
16739  *
16740  * STATUS: complete
16741  *
16742  * Returns 0 if the constraints are satisfied, a positive
16743  * error code if not and -1 if an internal error occured.
16744  */
16745 static int
16746 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16747                               int bmin, int bmax)
16748 {
16749     if (rmin < bmin)
16750         return (1);
16751     if ((bmax != UNBOUNDED) &&
16752         (rmax > bmax))
16753         return (1);
16754     return (0);
16755 }
16756
16757 /**
16758  * xmlSchemaCheckRCaseNameAndTypeOK:
16759  * @ctxt:  the schema parser context
16760  * @r: the restricting element declaration particle
16761  * @b: the base element declaration particle
16762  *
16763  * (3.9.6) Constraints on Particle Schema Components
16764  * Schema Component Constraint:
16765  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16766  * (rcase-NameAndTypeOK)
16767  *
16768  * STATUS:
16769  *   MISSING (3.2.3)
16770  *   CLARIFY: (3.2.2)
16771  *
16772  * Returns 0 if the constraints are satisfied, a positive
16773  * error code if not and -1 if an internal error occured.
16774  */
16775 static int
16776 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16777                                  xmlSchemaParticlePtr r,
16778                                  xmlSchemaParticlePtr b)
16779 {
16780     xmlSchemaElementPtr elemR, elemB;
16781
16782     /* TODO: Error codes (rcase-NameAndTypeOK). */
16783     elemR = (xmlSchemaElementPtr) r->children;
16784     elemB = (xmlSchemaElementPtr) b->children;
16785     /*
16786     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16787     * the same."
16788     */
16789     if ((elemR != elemB) &&
16790         ((! xmlStrEqual(elemR->name, elemB->name)) ||
16791         (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16792         return (1);
16793     /*
16794     * SPEC (2) "R's occurrence range is a valid restriction of B's
16795     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16796     */
16797     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16798             b->minOccurs, b->maxOccurs) != 0)
16799         return (1);
16800     /*
16801     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16802     * {scope} are global."
16803     */
16804     if (elemR == elemB)
16805         return (0);
16806     /*
16807     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16808     */
16809     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16810         (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16811          return (1);
16812     /*
16813     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16814     * or is not fixed, or R's declaration's {value constraint} is fixed
16815     * with the same value."
16816     */
16817     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16818         ((elemR->value == NULL) ||
16819          ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16820          /* TODO: Equality of the initial value or normalized or canonical? */
16821          (! xmlStrEqual(elemR->value, elemB->value))))
16822          return (1);
16823     /*
16824     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16825     * definitions} is a subset of B's declaration's {identity-constraint
16826     * definitions}, if any."
16827     */
16828     if (elemB->idcs != NULL) {
16829         /* TODO */
16830     }
16831     /*
16832     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16833     * superset of B's declaration's {disallowed substitutions}."
16834     */
16835     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16836          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16837         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16838          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16839         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16840          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16841          return (1);
16842     /*
16843     * SPEC (3.2.5) "R's {type definition} is validly derived given
16844     * {extension, list, union} from B's {type definition}"
16845     *
16846     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16847     * set, if the corresponding constraints handle "restriction" and
16848     * "extension" only?
16849     *
16850     */
16851     {
16852         int set = 0;
16853
16854         set |= SUBSET_EXTENSION;
16855         set |= SUBSET_LIST;
16856         set |= SUBSET_UNION;
16857         if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16858             elemB->subtypes, set) != 0)
16859             return (1);
16860     }
16861     return (0);
16862 }
16863
16864 /**
16865  * xmlSchemaCheckRCaseNSCompat:
16866  * @ctxt:  the schema parser context
16867  * @r: the restricting element declaration particle
16868  * @b: the base wildcard particle
16869  *
16870  * (3.9.6) Constraints on Particle Schema Components
16871  * Schema Component Constraint:
16872  * Particle Derivation OK (Elt:Any -- NSCompat)
16873  * (rcase-NSCompat)
16874  *
16875  * STATUS: complete
16876  *
16877  * Returns 0 if the constraints are satisfied, a positive
16878  * error code if not and -1 if an internal error occured.
16879  */
16880 static int
16881 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16882                             xmlSchemaParticlePtr r,
16883                             xmlSchemaParticlePtr b)
16884 {
16885     /* TODO:Error codes (rcase-NSCompat). */
16886     /*
16887     * SPEC "For an element declaration particle to be a ï¿½valid restriction�
16888     * of a wildcard particle all of the following must be true:"
16889     *
16890     * SPEC (1) "The element declaration's {target namespace} is ï¿½valid�
16891     * with respect to the wildcard's {namespace constraint} as defined by
16892     * Wildcard allows Namespace Name (�3.10.4)."
16893     */
16894     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16895         ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16896         return (1);
16897     /*
16898     * SPEC (2) "R's occurrence range is a valid restriction of B's
16899     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16900     */
16901     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16902             b->minOccurs, b->maxOccurs) != 0)
16903         return (1);
16904
16905     return (0);
16906 }
16907
16908 /**
16909  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16910  * @ctxt:  the schema parser context
16911  * @r: the restricting element declaration particle
16912  * @b: the base model group particle
16913  *
16914  * (3.9.6) Constraints on Particle Schema Components
16915  * Schema Component Constraint:
16916  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16917  * (rcase-RecurseAsIfGroup)
16918  *
16919  * STATUS: TODO
16920  *
16921  * Returns 0 if the constraints are satisfied, a positive
16922  * error code if not and -1 if an internal error occured.
16923  */
16924 static int
16925 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16926                                     xmlSchemaParticlePtr r,
16927                                     xmlSchemaParticlePtr b)
16928 {
16929     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16930     TODO
16931     return (0);
16932 }
16933
16934 /**
16935  * xmlSchemaCheckRCaseNSSubset:
16936  * @ctxt:  the schema parser context
16937  * @r: the restricting wildcard particle
16938  * @b: the base wildcard particle
16939  *
16940  * (3.9.6) Constraints on Particle Schema Components
16941  * Schema Component Constraint:
16942  * Particle Derivation OK (Any:Any -- NSSubset)
16943  * (rcase-NSSubset)
16944  *
16945  * STATUS: complete
16946  *
16947  * Returns 0 if the constraints are satisfied, a positive
16948  * error code if not and -1 if an internal error occured.
16949  */
16950 static int
16951 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16952                                     xmlSchemaParticlePtr r,
16953                                     xmlSchemaParticlePtr b,
16954                                     int isAnyTypeBase)
16955 {
16956     /* TODO: Error codes (rcase-NSSubset). */
16957     /*
16958     * SPEC (1) "R's occurrence range is a valid restriction of B's
16959     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16960     */
16961     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16962             b->minOccurs, b->maxOccurs))
16963         return (1);
16964     /*
16965     * SPEC (2) "R's {namespace constraint} must be an intensional subset
16966     * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16967     */
16968     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16969         (xmlSchemaWildcardPtr) b->children))
16970         return (1);
16971     /*
16972     * SPEC (3) "Unless B is the content model wildcard of the ï¿½ur-type
16973     * definition�, R's {process contents} must be identical to or stronger
16974     * than B's {process contents}, where strict is stronger than lax is
16975     * stronger than skip."
16976     */
16977     if (! isAnyTypeBase) {
16978         if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16979             ((xmlSchemaWildcardPtr) b->children)->processContents)
16980             return (1);
16981     }
16982
16983     return (0);
16984 }
16985
16986 /**
16987  * xmlSchemaCheckCOSParticleRestrict:
16988  * @ctxt:  the schema parser context
16989  * @type:  the complex type definition
16990  *
16991  * (3.9.6) Constraints on Particle Schema Components
16992  * Schema Component Constraint:
16993  * Particle Valid (Restriction) (cos-particle-restrict)
16994  *
16995  * STATUS: TODO
16996  *
16997  * Returns 0 if the constraints are satisfied, a positive
16998  * error code if not and -1 if an internal error occured.
16999  */
17000 static int
17001 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17002                                   xmlSchemaParticlePtr r,
17003                                   xmlSchemaParticlePtr b)
17004 {
17005     int ret = 0;
17006
17007     /*part = WXS_TYPE_PARTICLE(type);
17008     basePart = WXS_TYPE_PARTICLE(base);
17009     */
17010
17011     TODO
17012
17013     /*
17014     * SPEC (1) "They are the same particle."
17015     */
17016     if (r == b)
17017         return (0);
17018
17019
17020     return (0);
17021 }
17022
17023 #if 0
17024 /**
17025  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17026  * @ctxt:  the schema parser context
17027  * @r: the model group particle
17028  * @b: the base wildcard particle
17029  *
17030  * (3.9.6) Constraints on Particle Schema Components
17031  * Schema Component Constraint:
17032  * Particle Derivation OK (All/Choice/Sequence:Any --
17033  *                         NSRecurseCheckCardinality)
17034  * (rcase-NSRecurseCheckCardinality)
17035  *
17036  * STATUS: TODO: subst-groups
17037  *
17038  * Returns 0 if the constraints are satisfied, a positive
17039  * error code if not and -1 if an internal error occured.
17040  */
17041 static int
17042 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17043                                              xmlSchemaParticlePtr r,
17044                                              xmlSchemaParticlePtr b)
17045 {
17046     xmlSchemaParticlePtr part;
17047     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17048     if ((r->children == NULL) || (r->children->children == NULL))
17049         return (-1);
17050     /*
17051     * SPEC "For a group particle to be a ï¿½valid restriction� of a
17052     * wildcard particle..."
17053     *
17054     * SPEC (1) "Every member of the {particles} of the group is a ï¿½valid
17055     * restriction� of the wildcard as defined by
17056     * Particle Valid (Restriction) (�3.9.6)."
17057     */
17058     part = (xmlSchemaParticlePtr) r->children->children;
17059     do {
17060         if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17061             return (1);
17062         part = (xmlSchemaParticlePtr) part->next;
17063     } while (part != NULL);
17064     /*
17065     * SPEC (2) "The effective total range of the group [...] is a
17066     * valid restriction of B's occurrence range as defined by
17067     * Occurrence Range OK (�3.9.6)."
17068     */
17069     if (xmlSchemaCheckParticleRangeOK(
17070             xmlSchemaGetParticleTotalRangeMin(r),
17071             xmlSchemaGetParticleTotalRangeMax(r),
17072             b->minOccurs, b->maxOccurs) != 0)
17073         return (1);
17074     return (0);
17075 }
17076 #endif
17077
17078 /**
17079  * xmlSchemaCheckRCaseRecurse:
17080  * @ctxt:  the schema parser context
17081  * @r: the <all> or <sequence> model group particle
17082  * @b: the base <all> or <sequence> model group particle
17083  *
17084  * (3.9.6) Constraints on Particle Schema Components
17085  * Schema Component Constraint:
17086  * Particle Derivation OK (All:All,Sequence:Sequence --
17087                            Recurse)
17088  * (rcase-Recurse)
17089  *
17090  * STATUS:  ?
17091  * TODO: subst-groups
17092  *
17093  * Returns 0 if the constraints are satisfied, a positive
17094  * error code if not and -1 if an internal error occured.
17095  */
17096 static int
17097 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17098                            xmlSchemaParticlePtr r,
17099                            xmlSchemaParticlePtr b)
17100 {
17101     /* xmlSchemaParticlePtr part; */
17102     /* TODO: Error codes (rcase-Recurse). */
17103     if ((r->children == NULL) || (b->children == NULL) ||
17104         (r->children->type != b->children->type))
17105         return (-1);
17106     /*
17107     * SPEC "For an all or sequence group particle to be a ï¿½valid
17108     * restriction� of another group particle with the same {compositor}..."
17109     *
17110     * SPEC (1) "R's occurrence range is a valid restriction of B's
17111     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17112     */
17113     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17114             b->minOccurs, b->maxOccurs))
17115         return (1);
17116
17117
17118     return (0);
17119 }
17120
17121 #endif
17122
17123 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17124     xmlSchemaPCustomErrExt(pctxt,      \
17125         XML_SCHEMAP_INVALID_FACET_VALUE, \
17126         WXS_BASIC_CAST fac1, fac1->node, \
17127         "It is an error for both '%s' and '%s' to be specified on the "\
17128         "same type definition", \
17129         BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17130         BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17131
17132 #define FACET_RESTR_ERR(fac1, msg) \
17133     xmlSchemaPCustomErr(pctxt,      \
17134         XML_SCHEMAP_INVALID_FACET_VALUE, \
17135         WXS_BASIC_CAST fac1, fac1->node, \
17136         msg, NULL);
17137
17138 #define FACET_RESTR_FIXED_ERR(fac) \
17139     xmlSchemaPCustomErr(pctxt, \
17140         XML_SCHEMAP_INVALID_FACET_VALUE, \
17141         WXS_BASIC_CAST fac, fac->node, \
17142         "The base type's facet is 'fixed', thus the value must not " \
17143         "differ", NULL);
17144
17145 static void
17146 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17147                         xmlSchemaFacetPtr facet1,
17148                         xmlSchemaFacetPtr facet2,
17149                         int lessGreater,
17150                         int orEqual,
17151                         int ofBase)
17152 {
17153     xmlChar *msg = NULL;
17154
17155     msg = xmlStrdup(BAD_CAST "'");
17156     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17157     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17158     if (lessGreater == 0)
17159         msg = xmlStrcat(msg, BAD_CAST " equal to");
17160     if (lessGreater == 1)
17161         msg = xmlStrcat(msg, BAD_CAST " greater than");
17162     else
17163         msg = xmlStrcat(msg, BAD_CAST " less than");
17164
17165     if (orEqual)
17166         msg = xmlStrcat(msg, BAD_CAST " or equal to");
17167     msg = xmlStrcat(msg, BAD_CAST " '");
17168     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17169     if (ofBase)
17170         msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17171     else
17172         msg = xmlStrcat(msg, BAD_CAST "'");
17173
17174     xmlSchemaPCustomErr(pctxt,
17175         XML_SCHEMAP_INVALID_FACET_VALUE,
17176         WXS_BASIC_CAST facet1, NULL,
17177         (const char *) msg, NULL);
17178
17179     if (msg != NULL)
17180         xmlFree(msg);
17181 }
17182
17183 /*
17184 * xmlSchemaDeriveAndValidateFacets:
17185 *
17186 * Schema Component Constraint: Simple Type Restriction (Facets)
17187 * (st-restrict-facets)
17188 */
17189 static int
17190 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17191                                  xmlSchemaTypePtr type)
17192 {
17193     xmlSchemaTypePtr base = type->baseType;
17194     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17195     xmlSchemaFacetPtr facet, bfacet,
17196         flength = NULL, ftotdig = NULL, ffracdig = NULL,
17197         fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17198         fmininc = NULL, fmaxinc = NULL,
17199         fminexc = NULL, fmaxexc = NULL,
17200         bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17201         bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17202         bfmininc = NULL, bfmaxinc = NULL,
17203         bfminexc = NULL, bfmaxexc = NULL;
17204     int res; /* err = 0, fixedErr; */
17205
17206     /*
17207     * SPEC st-restrict-facets 1:
17208     * "The {variety} of R is the same as that of B."
17209     */
17210     /*
17211     * SPEC st-restrict-facets 2:
17212     * "If {variety} is atomic, the {primitive type definition}
17213     * of R is the same as that of B."
17214     *
17215     * NOTE: we leave 1 & 2 out for now, since this will be
17216     * satisfied by the derivation process.
17217     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17218     */
17219     /*
17220     * SPEC st-restrict-facets 3:
17221     * "The {facets} of R are the union of S and the {facets}
17222     * of B, eliminating duplicates. To eliminate duplicates,
17223     * when a facet of the same kind occurs in both S and the
17224     * {facets} of B, the one in the {facets} of B is not
17225     * included, with the exception of enumeration and pattern
17226     * facets, for which multiple occurrences with distinct values
17227     * are allowed."
17228     */
17229
17230     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17231         return (0);
17232
17233     last = type->facetSet;
17234     if (last != NULL)
17235         while (last->next != NULL)
17236             last = last->next;
17237
17238     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17239         facet = cur->facet;
17240         switch (facet->type) {
17241             case XML_SCHEMA_FACET_LENGTH:
17242                 flength = facet; break;
17243             case XML_SCHEMA_FACET_MINLENGTH:
17244                 fminlen = facet; break;
17245             case XML_SCHEMA_FACET_MININCLUSIVE:
17246                 fmininc = facet; break;
17247             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17248                 fminexc = facet; break;
17249             case XML_SCHEMA_FACET_MAXLENGTH:
17250                 fmaxlen = facet; break;
17251             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17252                 fmaxinc = facet; break;
17253             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17254                 fmaxexc = facet; break;
17255             case XML_SCHEMA_FACET_TOTALDIGITS:
17256                 ftotdig = facet; break;
17257             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17258                 ffracdig = facet; break;
17259             default:
17260                 break;
17261         }
17262     }
17263     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17264         facet = cur->facet;
17265         switch (facet->type) {
17266             case XML_SCHEMA_FACET_LENGTH:
17267                 bflength = facet; break;
17268             case XML_SCHEMA_FACET_MINLENGTH:
17269                 bfminlen = facet; break;
17270             case XML_SCHEMA_FACET_MININCLUSIVE:
17271                 bfmininc = facet; break;
17272             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17273                 bfminexc = facet; break;
17274             case XML_SCHEMA_FACET_MAXLENGTH:
17275                 bfmaxlen = facet; break;
17276             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17277                 bfmaxinc = facet; break;
17278             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17279                 bfmaxexc = facet; break;
17280             case XML_SCHEMA_FACET_TOTALDIGITS:
17281                 bftotdig = facet; break;
17282             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17283                 bffracdig = facet; break;
17284             default:
17285                 break;
17286         }
17287     }
17288     /*
17289     * length and minLength or maxLength (2.2) + (3.2)
17290     */
17291     if (flength && (fminlen || fmaxlen)) {
17292         FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17293             "either of 'minLength' or 'maxLength' to be specified on "
17294             "the same type definition")
17295     }
17296     /*
17297     * Mutual exclusions in the same derivation step.
17298     */
17299     if ((fmaxinc) && (fmaxexc)) {
17300         /*
17301         * SCC "maxInclusive and maxExclusive"
17302         */
17303         FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17304     }
17305     if ((fmininc) && (fminexc)) {
17306         /*
17307         * SCC "minInclusive and minExclusive"
17308         */
17309         FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17310     }
17311
17312     if (flength && bflength) {
17313         /*
17314         * SCC "length valid restriction"
17315         * The values have to be equal.
17316         */
17317         res = xmlSchemaCompareValues(flength->val, bflength->val);
17318         if (res == -2)
17319             goto internal_error;
17320         if (res != 0)
17321             xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17322         if ((res != 0) && (bflength->fixed)) {
17323             FACET_RESTR_FIXED_ERR(flength)
17324         }
17325
17326     }
17327     if (fminlen && bfminlen) {
17328         /*
17329         * SCC "minLength valid restriction"
17330         * minLength >= BASE minLength
17331         */
17332         res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17333         if (res == -2)
17334             goto internal_error;
17335         if (res == -1)
17336             xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17337         if ((res != 0) && (bfminlen->fixed)) {
17338             FACET_RESTR_FIXED_ERR(fminlen)
17339         }
17340     }
17341     if (fmaxlen && bfmaxlen) {
17342         /*
17343         * SCC "maxLength valid restriction"
17344         * maxLength <= BASE minLength
17345         */
17346         res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17347         if (res == -2)
17348             goto internal_error;
17349         if (res == 1)
17350             xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17351         if ((res != 0) && (bfmaxlen->fixed)) {
17352             FACET_RESTR_FIXED_ERR(fmaxlen)
17353         }
17354     }
17355     /*
17356     * SCC "length and minLength or maxLength"
17357     */
17358     if (! flength)
17359         flength = bflength;
17360     if (flength) {
17361         if (! fminlen)
17362             fminlen = bfminlen;
17363         if (fminlen) {
17364             /* (1.1) length >= minLength */
17365             res = xmlSchemaCompareValues(flength->val, fminlen->val);
17366             if (res == -2)
17367                 goto internal_error;
17368             if (res == -1)
17369                 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17370         }
17371         if (! fmaxlen)
17372             fmaxlen = bfmaxlen;
17373         if (fmaxlen) {
17374             /* (2.1) length <= maxLength */
17375             res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17376             if (res == -2)
17377                 goto internal_error;
17378             if (res == 1)
17379                 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17380         }
17381     }
17382     if (fmaxinc) {
17383         /*
17384         * "maxInclusive"
17385         */
17386         if (fmininc) {
17387             /* SCC "maxInclusive >= minInclusive" */
17388             res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17389             if (res == -2)
17390                 goto internal_error;
17391             if (res == -1) {
17392                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17393             }
17394         }
17395         /*
17396         * SCC "maxInclusive valid restriction"
17397         */
17398         if (bfmaxinc) {
17399             /* maxInclusive <= BASE maxInclusive */
17400             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17401             if (res == -2)
17402                 goto internal_error;
17403             if (res == 1)
17404                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17405             if ((res != 0) && (bfmaxinc->fixed)) {
17406                 FACET_RESTR_FIXED_ERR(fmaxinc)
17407             }
17408         }
17409         if (bfmaxexc) {
17410             /* maxInclusive < BASE maxExclusive */
17411             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17412             if (res == -2)
17413                 goto internal_error;
17414             if (res != -1) {
17415                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17416             }
17417         }
17418         if (bfmininc) {
17419             /* maxInclusive >= BASE minInclusive */
17420             res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17421             if (res == -2)
17422                 goto internal_error;
17423             if (res == -1) {
17424                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17425             }
17426         }
17427         if (bfminexc) {
17428             /* maxInclusive > BASE minExclusive */
17429             res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17430             if (res == -2)
17431                 goto internal_error;
17432             if (res != 1) {
17433                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17434             }
17435         }
17436     }
17437     if (fmaxexc) {
17438         /*
17439         * "maxExclusive >= minExclusive"
17440         */
17441         if (fminexc) {
17442             res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17443             if (res == -2)
17444                 goto internal_error;
17445             if (res == -1) {
17446                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17447             }
17448         }
17449         /*
17450         * "maxExclusive valid restriction"
17451         */
17452         if (bfmaxexc) {
17453             /* maxExclusive <= BASE maxExclusive */
17454             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17455             if (res == -2)
17456                 goto internal_error;
17457             if (res == 1) {
17458                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17459             }
17460             if ((res != 0) && (bfmaxexc->fixed)) {
17461                 FACET_RESTR_FIXED_ERR(fmaxexc)
17462             }
17463         }
17464         if (bfmaxinc) {
17465             /* maxExclusive <= BASE maxInclusive */
17466             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17467             if (res == -2)
17468                 goto internal_error;
17469             if (res == 1) {
17470                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17471             }
17472         }
17473         if (bfmininc) {
17474             /* maxExclusive > BASE minInclusive */
17475             res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17476             if (res == -2)
17477                 goto internal_error;
17478             if (res != 1) {
17479                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17480             }
17481         }
17482         if (bfminexc) {
17483             /* maxExclusive > BASE minExclusive */
17484             res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17485             if (res == -2)
17486                 goto internal_error;
17487             if (res != 1) {
17488                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17489             }
17490         }
17491     }
17492     if (fminexc) {
17493         /*
17494         * "minExclusive < maxInclusive"
17495         */
17496         if (fmaxinc) {
17497             res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17498             if (res == -2)
17499                 goto internal_error;
17500             if (res != -1) {
17501                 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17502             }
17503         }
17504         /*
17505         * "minExclusive valid restriction"
17506         */
17507         if (bfminexc) {
17508             /* minExclusive >= BASE minExclusive */
17509             res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17510             if (res == -2)
17511                 goto internal_error;
17512             if (res == -1) {
17513                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17514             }
17515             if ((res != 0) && (bfminexc->fixed)) {
17516                 FACET_RESTR_FIXED_ERR(fminexc)
17517             }
17518         }
17519         if (bfmaxinc) {
17520             /* minExclusive <= BASE maxInclusive */
17521             res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17522             if (res == -2)
17523                 goto internal_error;
17524             if (res == 1) {
17525                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17526             }
17527         }
17528         if (bfmininc) {
17529             /* minExclusive >= BASE minInclusive */
17530             res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17531             if (res == -2)
17532                 goto internal_error;
17533             if (res == -1) {
17534                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17535             }
17536         }
17537         if (bfmaxexc) {
17538             /* minExclusive < BASE maxExclusive */
17539             res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17540             if (res == -2)
17541                 goto internal_error;
17542             if (res != -1) {
17543                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17544             }
17545         }
17546     }
17547     if (fmininc) {
17548         /*
17549         * "minInclusive < maxExclusive"
17550         */
17551         if (fmaxexc) {
17552             res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17553             if (res == -2)
17554                 goto internal_error;
17555             if (res != -1) {
17556                 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17557             }
17558         }
17559         /*
17560         * "minExclusive valid restriction"
17561         */
17562         if (bfmininc) {
17563             /* minInclusive >= BASE minInclusive */
17564             res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17565             if (res == -2)
17566                 goto internal_error;
17567             if (res == -1) {
17568                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17569             }
17570             if ((res != 0) && (bfmininc->fixed)) {
17571                 FACET_RESTR_FIXED_ERR(fmininc)
17572             }
17573         }
17574         if (bfmaxinc) {
17575             /* minInclusive <= BASE maxInclusive */
17576             res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17577             if (res == -2)
17578                 goto internal_error;
17579             if (res == 1) {
17580                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17581             }
17582         }
17583         if (bfminexc) {
17584             /* minInclusive > BASE minExclusive */
17585             res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17586             if (res == -2)
17587                 goto internal_error;
17588             if (res != 1)
17589                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17590         }
17591         if (bfmaxexc) {
17592             /* minInclusive < BASE maxExclusive */
17593             res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17594             if (res == -2)
17595                 goto internal_error;
17596             if (res != -1)
17597                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17598         }
17599     }
17600     if (ftotdig && bftotdig) {
17601         /*
17602         * SCC " totalDigits valid restriction"
17603         * totalDigits <= BASE totalDigits
17604         */
17605         res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17606         if (res == -2)
17607             goto internal_error;
17608         if (res == 1)
17609             xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17610             -1, 1, 1);
17611         if ((res != 0) && (bftotdig->fixed)) {
17612             FACET_RESTR_FIXED_ERR(ftotdig)
17613         }
17614     }
17615     if (ffracdig && bffracdig) {
17616         /*
17617         * SCC  "fractionDigits valid restriction"
17618         * fractionDigits <= BASE fractionDigits
17619         */
17620         res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17621         if (res == -2)
17622             goto internal_error;
17623         if (res == 1)
17624             xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17625             -1, 1, 1);
17626         if ((res != 0) && (bffracdig->fixed)) {
17627             FACET_RESTR_FIXED_ERR(ffracdig)
17628         }
17629     }
17630     /*
17631     * SCC "fractionDigits less than or equal to totalDigits"
17632     */
17633     if (! ftotdig)
17634         ftotdig = bftotdig;
17635     if (! ffracdig)
17636         ffracdig = bffracdig;
17637     if (ftotdig && ffracdig) {
17638         res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17639         if (res == -2)
17640             goto internal_error;
17641         if (res == 1)
17642             xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17643                 -1, 1, 0);
17644     }
17645     /*
17646     * *Enumerations* won' be added here, since only the first set
17647     * of enumerations in the ancestor-or-self axis is used
17648     * for validation, plus we need to use the base type of those
17649     * enumerations for whitespace.
17650     *
17651     * *Patterns*: won't be add here, since they are ORed at
17652     * type level and ANDed at ancestor level. This will
17653     * happed during validation by walking the base axis
17654     * of the type.
17655     */
17656     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17657         bfacet = cur->facet;
17658         /*
17659         * Special handling of enumerations and patterns.
17660         * TODO: hmm, they should not appear in the set, so remove this.
17661         */
17662         if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17663             (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17664             continue;
17665         /*
17666         * Search for a duplicate facet in the current type.
17667         */
17668         link = type->facetSet;
17669         /* err = 0; */
17670         /* fixedErr = 0; */
17671         while (link != NULL) {
17672             facet = link->facet;
17673             if (facet->type == bfacet->type) {
17674                 switch (facet->type) {
17675                     case XML_SCHEMA_FACET_WHITESPACE:
17676                         /*
17677                         * The whitespace must be stronger.
17678                         */
17679                         if (facet->whitespace < bfacet->whitespace) {
17680                             FACET_RESTR_ERR(facet,
17681                                 "The 'whitespace' value has to be equal to "
17682                                 "or stronger than the 'whitespace' value of "
17683                                 "the base type")
17684                         }
17685                         if ((bfacet->fixed) &&
17686                             (facet->whitespace != bfacet->whitespace)) {
17687                             FACET_RESTR_FIXED_ERR(facet)
17688                         }
17689                         break;
17690                     default:
17691                         break;
17692                 }
17693                 /* Duplicate found. */
17694                 break;
17695             }
17696             link = link->next;
17697         }
17698         /*
17699         * If no duplicate was found: add the base types's facet
17700         * to the set.
17701         */
17702         if (link == NULL) {
17703             link = (xmlSchemaFacetLinkPtr)
17704                 xmlMalloc(sizeof(xmlSchemaFacetLink));
17705             if (link == NULL) {
17706                 xmlSchemaPErrMemory(pctxt,
17707                     "deriving facets, creating a facet link", NULL);
17708                 return (-1);
17709             }
17710             link->facet = cur->facet;
17711             link->next = NULL;
17712             if (last == NULL)
17713                 type->facetSet = link;
17714             else
17715                 last->next = link;
17716             last = link;
17717         }
17718
17719     }
17720
17721     return (0);
17722 internal_error:
17723     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17724         "an error occured");
17725     return (-1);
17726 }
17727
17728 static int
17729 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17730                                              xmlSchemaTypePtr type)
17731 {
17732     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17733     /*
17734     * The actual value is then formed by replacing any union type
17735     * definition in the ï¿½explicit members� with the members of their
17736     * {member type definitions}, in order.
17737     *
17738     * TODO: There's a bug entry at
17739     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17740     * which indicates that we'll keep the union types the future.
17741     */
17742     link = type->memberTypes;
17743     while (link != NULL) {
17744
17745         if (WXS_IS_TYPE_NOT_FIXED(link->type))
17746             xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17747
17748         if (WXS_IS_UNION(link->type)) {
17749             subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17750             if (subLink != NULL) {
17751                 link->type = subLink->type;
17752                 if (subLink->next != NULL) {
17753                     lastLink = link->next;
17754                     subLink = subLink->next;
17755                     prevLink = link;
17756                     while (subLink != NULL) {
17757                         newLink = (xmlSchemaTypeLinkPtr)
17758                             xmlMalloc(sizeof(xmlSchemaTypeLink));
17759                         if (newLink == NULL) {
17760                             xmlSchemaPErrMemory(pctxt, "allocating a type link",
17761                                 NULL);
17762                             return (-1);
17763                         }
17764                         newLink->type = subLink->type;
17765                         prevLink->next = newLink;
17766                         prevLink = newLink;
17767                         newLink->next = lastLink;
17768
17769                         subLink = subLink->next;
17770                     }
17771                 }
17772             }
17773         }
17774         link = link->next;
17775     }
17776     return (0);
17777 }
17778
17779 static void
17780 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17781 {
17782     int has = 0, needVal = 0, normVal = 0;
17783
17784     has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17785     if (has) {
17786         needVal = (type->baseType->flags &
17787             XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17788         normVal = (type->baseType->flags &
17789             XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17790     }
17791     if (type->facets != NULL) {
17792         xmlSchemaFacetPtr fac;
17793
17794         for (fac = type->facets; fac != NULL; fac = fac->next) {
17795             switch (fac->type) {
17796                 case XML_SCHEMA_FACET_WHITESPACE:
17797                     break;
17798                 case XML_SCHEMA_FACET_PATTERN:
17799                     normVal = 1;
17800                     has = 1;
17801                     break;
17802                 case XML_SCHEMA_FACET_ENUMERATION:
17803                     needVal = 1;
17804                     normVal = 1;
17805                     has = 1;
17806                     break;
17807                 default:
17808                     has = 1;
17809                     break;
17810             }
17811         }
17812     }
17813     if (normVal)
17814         type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17815     if (needVal)
17816         type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17817     if (has)
17818         type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17819
17820     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17821         xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17822         /*
17823         * OPTIMIZE VAL TODO: Some facets need a computed value.
17824         */
17825         if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17826             (prim->builtInType != XML_SCHEMAS_STRING)) {
17827             type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17828         }
17829     }
17830 }
17831
17832 static int
17833 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17834 {
17835
17836
17837     /*
17838     * Evaluate the whitespace-facet value.
17839     */
17840     if (WXS_IS_LIST(type)) {
17841         type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17842         return (0);
17843     } else if (WXS_IS_UNION(type))
17844         return (0);
17845
17846     if (type->facetSet != NULL) {
17847         xmlSchemaFacetLinkPtr lin;
17848
17849         for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17850             if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17851                 switch (lin->facet->whitespace) {
17852                 case XML_SCHEMAS_FACET_PRESERVE:
17853                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17854                     break;
17855                 case XML_SCHEMAS_FACET_REPLACE:
17856                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17857                     break;
17858                 case XML_SCHEMAS_FACET_COLLAPSE:
17859                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17860                     break;
17861                 default:
17862                     return (-1);
17863                 }
17864                 return (0);
17865             }
17866         }
17867     }
17868     /*
17869     * For all ï¿½atomic� datatypes other than string (and types ï¿½derived�
17870     * by ï¿½restriction� from it) the value of whiteSpace is fixed to
17871     * collapse
17872     */
17873     {
17874         xmlSchemaTypePtr anc;
17875
17876         for (anc = type->baseType; anc != NULL &&
17877                 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17878                 anc = anc->baseType) {
17879
17880             if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17881                 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17882                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17883
17884                 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17885                     (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17886                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17887
17888                 } else
17889                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17890                 break;
17891             }
17892         }
17893     }
17894     return (0);
17895 }
17896
17897 static int
17898 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17899                           xmlSchemaTypePtr type)
17900 {
17901     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17902         return(0);
17903     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17904         return(0);
17905     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17906
17907     if (WXS_IS_LIST(type)) {
17908         /*
17909         * Corresponds to <simpleType><list>...
17910         */
17911         if (type->subtypes == NULL) {
17912             /*
17913             * This one is really needed, so get out.
17914             */
17915             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17916                 "list type has no item-type assigned");
17917             return(-1);
17918         }
17919     } else if (WXS_IS_UNION(type)) {
17920         /*
17921         * Corresponds to <simpleType><union>...
17922         */
17923         if (type->memberTypes == NULL) {
17924             /*
17925             * This one is really needed, so get out.
17926             */
17927             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17928                 "union type has no member-types assigned");
17929             return(-1);
17930         }
17931     } else {
17932         /*
17933         * Corresponds to <simpleType><restriction>...
17934         */
17935         if (type->baseType == NULL) {
17936             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17937                 "type has no base-type assigned");
17938             return(-1);
17939         }
17940         if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17941             if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17942                 return(-1);
17943         /*
17944         * Variety
17945         * If the <restriction> alternative is chosen, then the
17946         * {variety} of the {base type definition}.
17947         */
17948         if (WXS_IS_ATOMIC(type->baseType))
17949             type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17950         else if (WXS_IS_LIST(type->baseType)) {
17951             type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17952             /*
17953             * Inherit the itemType.
17954             */
17955             type->subtypes = type->baseType->subtypes;
17956         } else if (WXS_IS_UNION(type->baseType)) {
17957             type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17958             /*
17959             * NOTE that we won't assign the memberTypes of the base,
17960             * since this will make trouble when freeing them; we will
17961             * use a lookup function to access them instead.
17962             */
17963         }
17964     }
17965     return(0);
17966 }
17967
17968 #ifdef DEBUG_TYPE
17969 static void
17970 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17971                        xmlSchemaTypePtr type)
17972 {
17973     if (type->node != NULL) {
17974         xmlGenericError(xmlGenericErrorContext,
17975                         "Type of %s : %s:%d :", name,
17976                         type->node->doc->URL,
17977                         xmlGetLineNo(type->node));
17978     } else {
17979         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17980     }
17981     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17982         switch (type->contentType) {
17983             case XML_SCHEMA_CONTENT_SIMPLE:
17984                 xmlGenericError(xmlGenericErrorContext, "simple\n");
17985                 break;
17986             case XML_SCHEMA_CONTENT_ELEMENTS:
17987                 xmlGenericError(xmlGenericErrorContext, "elements\n");
17988                 break;
17989             case XML_SCHEMA_CONTENT_UNKNOWN:
17990                 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17991                 break;
17992             case XML_SCHEMA_CONTENT_EMPTY:
17993                 xmlGenericError(xmlGenericErrorContext, "empty\n");
17994                 break;
17995             case XML_SCHEMA_CONTENT_MIXED:
17996                 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17997                     type->subtypes))
17998                     xmlGenericError(xmlGenericErrorContext,
17999                         "mixed as emptiable particle\n");
18000                 else
18001                     xmlGenericError(xmlGenericErrorContext, "mixed\n");
18002                 break;
18003                 /* Removed, since not used. */
18004                 /*
18005                 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18006                 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18007                 break;
18008                 */
18009             case XML_SCHEMA_CONTENT_BASIC:
18010                 xmlGenericError(xmlGenericErrorContext, "basic\n");
18011                 break;
18012             default:
18013                 xmlGenericError(xmlGenericErrorContext,
18014                     "not registered !!!\n");
18015                 break;
18016         }
18017     }
18018 }
18019 #endif
18020
18021 /*
18022 * 3.14.6 Constraints on Simple Type Definition Schema Components
18023 */
18024 static int
18025 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18026                                  xmlSchemaTypePtr type)
18027 {
18028     int res, olderrs = pctxt->nberrors;
18029
18030     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18031         return(-1);
18032
18033     if (! WXS_IS_TYPE_NOT_FIXED(type))
18034         return(0);
18035
18036     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18037     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18038
18039     if (type->baseType == NULL) {
18040         PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18041             "missing baseType");
18042         goto exit_failure;
18043     }
18044     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18045         xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18046     /*
18047     * If a member type of a union is a union itself, we need to substitute
18048     * that member type for its member types.
18049     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18050     * types in WXS 1.1.
18051     */
18052     if ((type->memberTypes != NULL) &&
18053         (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18054         return(-1);
18055     /*
18056     * SPEC src-simple-type 1
18057     * "The corresponding simple type definition, if any, must satisfy
18058     * the conditions set out in Constraints on Simple Type Definition
18059     * Schema Components (�3.14.6)."
18060     */
18061     /*
18062     * Schema Component Constraint: Simple Type Definition Properties Correct
18063     * (st-props-correct)
18064     */
18065     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18066     HFAILURE HERROR
18067     /*
18068     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18069     * (cos-st-restricts)
18070     */
18071     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18072     HFAILURE HERROR
18073     /*
18074     * TODO: Removed the error report, since it got annoying to get an
18075     * extra error report, if anything failed until now.
18076     * Enable this if needed.
18077     *
18078     * xmlSchemaPErr(ctxt, type->node,
18079     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18080     *    "Simple type '%s' does not satisfy the constraints "
18081     *    "on simple type definitions.\n",
18082     *    type->name, NULL);
18083     */
18084     /*
18085     * Schema Component Constraint: Simple Type Restriction (Facets)
18086     * (st-restrict-facets)
18087     */
18088     res = xmlSchemaCheckFacetValues(type, pctxt);
18089     HFAILURE HERROR
18090     if ((type->facetSet != NULL) ||
18091         (type->baseType->facetSet != NULL)) {
18092         res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18093         HFAILURE HERROR
18094     }
18095     /*
18096     * Whitespace value.
18097     */
18098     res = xmlSchemaTypeFixupWhitespace(type);
18099     HFAILURE HERROR
18100     xmlSchemaTypeFixupOptimFacets(type);
18101
18102 exit_error:
18103 #ifdef DEBUG_TYPE
18104     xmlSchemaDebugFixedType(pctxt, type);
18105 #endif
18106     if (olderrs != pctxt->nberrors)
18107         return(pctxt->err);
18108     return(0);
18109
18110 exit_failure:
18111 #ifdef DEBUG_TYPE
18112     xmlSchemaDebugFixedType(pctxt, type);
18113 #endif
18114     return(-1);
18115 }
18116
18117 static int
18118 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18119                           xmlSchemaTypePtr type)
18120 {
18121     int res = 0, olderrs = pctxt->nberrors;
18122     xmlSchemaTypePtr baseType = type->baseType;
18123
18124     if (! WXS_IS_TYPE_NOT_FIXED(type))
18125         return(0);
18126     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18127     if (baseType == NULL) {
18128         PERROR_INT("xmlSchemaFixupComplexType",
18129             "missing baseType");
18130         goto exit_failure;
18131     }
18132     /*
18133     * Fixup the base type.
18134     */
18135     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18136         xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18137     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18138         /*
18139         * Skip fixup if the base type is invalid.
18140         * TODO: Generate a warning!
18141         */
18142         return(0);
18143     }
18144     /*
18145     * This basically checks if the base type can be derived.
18146     */
18147     res = xmlSchemaCheckSRCCT(pctxt, type);
18148     HFAILURE HERROR
18149     /*
18150     * Fixup the content type.
18151     */
18152     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18153         /*
18154         * Corresponds to <complexType><simpleContent>...
18155         */
18156         if ((WXS_IS_COMPLEX(baseType)) &&
18157             (baseType->contentTypeDef != NULL) &&
18158             (WXS_IS_RESTRICTION(type))) {
18159             xmlSchemaTypePtr contentBase, content;
18160 #ifdef ENABLE_NAMED_LOCALS
18161             char buf[30];
18162             const xmlChar *tmpname;
18163 #endif
18164             /*
18165             * SPEC (1) If <restriction> + base type is <complexType>,
18166             * "whose own {content type} is a simple type..."
18167             */
18168             if (type->contentTypeDef != NULL) {
18169                 /*
18170                 * SPEC (1.1) "the simple type definition corresponding to the
18171                 * <simpleType> among the [children] of <restriction> if there
18172                 * is one;"
18173                 * Note that this "<simpleType> among the [children]" was put
18174                 * into ->contentTypeDef during parsing.
18175                 */
18176                 contentBase = type->contentTypeDef;
18177                 type->contentTypeDef = NULL;
18178             } else {
18179                 /*
18180                 * (1.2) "...otherwise (<restriction> has no <simpleType>
18181                 * among its [children]), the simple type definition which
18182                 * is the {content type} of the ... base type."
18183                 */
18184                 contentBase = baseType->contentTypeDef;
18185             }
18186             /*
18187             * SPEC
18188             * "... a simple type definition which restricts the simple
18189             * type definition identified in clause 1.1 or clause 1.2
18190             * with a set of facet components"
18191             *
18192             * Create the anonymous simple type, which will be the content
18193             * type of the complex type.
18194             */
18195 #ifdef ENABLE_NAMED_LOCALS
18196             snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18197             tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18198             content = xmlSchemaAddType(pctxt, pctxt->schema,
18199                 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18200                 type->node, 0);
18201 #else
18202             content = xmlSchemaAddType(pctxt, pctxt->schema,
18203                 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18204                 type->node, 0);
18205 #endif
18206             if (content == NULL)
18207                 goto exit_failure;
18208             /*
18209             * We will use the same node as for the <complexType>
18210             * to have it somehow anchored in the schema doc.
18211             */
18212             content->type = XML_SCHEMA_TYPE_SIMPLE;
18213             content->baseType = contentBase;
18214             /*
18215             * Move the facets, previously anchored on the
18216             * complexType during parsing.
18217             */
18218             content->facets = type->facets;
18219             type->facets = NULL;
18220             content->facetSet = type->facetSet;
18221             type->facetSet = NULL;
18222
18223             type->contentTypeDef = content;
18224             if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18225                 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18226             /*
18227             * Fixup the newly created type. We don't need to check
18228             * for circularity here.
18229             */
18230             res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18231             HFAILURE HERROR
18232             res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18233             HFAILURE HERROR
18234
18235         } else if ((WXS_IS_COMPLEX(baseType)) &&
18236             (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18237             (WXS_IS_RESTRICTION(type))) {
18238             /*
18239             * SPEC (2) If <restriction> + base is a mixed <complexType> with
18240             * an emptiable particle, then a simple type definition which
18241             * restricts the <restriction>'s <simpleType> child.
18242             */
18243             if ((type->contentTypeDef == NULL) ||
18244                 (type->contentTypeDef->baseType == NULL)) {
18245                 /*
18246                 * TODO: Check if this ever happens.
18247                 */
18248                 xmlSchemaPCustomErr(pctxt,
18249                     XML_SCHEMAP_INTERNAL,
18250                     WXS_BASIC_CAST type, NULL,
18251                     "Internal error: xmlSchemaTypeFixup, "
18252                     "complex type '%s': the <simpleContent><restriction> "
18253                     "is missing a <simpleType> child, but was not catched "
18254                     "by xmlSchemaCheckSRCCT()", type->name);
18255                 goto exit_failure;
18256             }
18257         } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18258             /*
18259             * SPEC (3) If <extension> + base is <complexType> with
18260             * <simpleType> content, "...then the {content type} of that
18261             * complex type definition"
18262             */
18263             if (baseType->contentTypeDef == NULL) {
18264                 /*
18265                 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18266                 * should have catched this already.
18267                 */
18268                 xmlSchemaPCustomErr(pctxt,
18269                     XML_SCHEMAP_INTERNAL,
18270                     WXS_BASIC_CAST type, NULL,
18271                     "Internal error: xmlSchemaTypeFixup, "
18272                     "complex type '%s': the <extension>ed base type is "
18273                     "a complex type with no simple content type",
18274                     type->name);
18275                 goto exit_failure;
18276             }
18277             type->contentTypeDef = baseType->contentTypeDef;
18278         } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18279             /*
18280             * SPEC (4) <extension> + base is <simpleType>
18281             * "... then that simple type definition"
18282             */
18283             type->contentTypeDef = baseType;
18284         } else {
18285             /*
18286             * TODO: Check if this ever happens.
18287             */
18288             xmlSchemaPCustomErr(pctxt,
18289                 XML_SCHEMAP_INTERNAL,
18290                 WXS_BASIC_CAST type, NULL,
18291                 "Internal error: xmlSchemaTypeFixup, "
18292                 "complex type '%s' with <simpleContent>: unhandled "
18293                 "derivation case", type->name);
18294             goto exit_failure;
18295         }
18296     } else {
18297         int dummySequence = 0;
18298         xmlSchemaParticlePtr particle =
18299             (xmlSchemaParticlePtr) type->subtypes;
18300         /*
18301         * Corresponds to <complexType><complexContent>...
18302         *
18303         * NOTE that the effective mixed was already set during parsing of
18304         * <complexType> and <complexContent>; its flag value is
18305         * XML_SCHEMAS_TYPE_MIXED.
18306         *
18307         * Compute the "effective content":
18308         * (2.1.1) + (2.1.2) + (2.1.3)
18309         */
18310         if ((particle == NULL) ||
18311             ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18312             ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18313             (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18314             ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18315             (particle->minOccurs == 0))) &&
18316             ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18317             if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18318                 /*
18319                 * SPEC (2.1.4) "If the ï¿½effective mixed� is true, then
18320                 * a particle whose properties are as follows:..."
18321                 *
18322                 * Empty sequence model group with
18323                 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18324                 * NOTE that we sill assign it the <complexType> node to
18325                 * somehow anchor it in the doc.
18326                 */
18327                 if ((particle == NULL) ||
18328                     (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18329                     /*
18330                     * Create the particle.
18331                     */
18332                     particle = xmlSchemaAddParticle(pctxt,
18333                         type->node, 1, 1);
18334                     if (particle == NULL)
18335                         goto exit_failure;
18336                     /*
18337                     * Create the model group.
18338                     */ /* URGENT TODO: avoid adding to pending items. */
18339                     particle->children = (xmlSchemaTreeItemPtr)
18340                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18341                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18342                     if (particle->children == NULL)
18343                         goto exit_failure;
18344
18345                     type->subtypes = (xmlSchemaTypePtr) particle;
18346                 }
18347                 dummySequence = 1;
18348                 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18349             } else {
18350                 /*
18351                 * SPEC (2.1.5) "otherwise empty"
18352                 */
18353                 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18354             }
18355         } else {
18356             /*
18357             * SPEC (2.2) "otherwise the particle corresponding to the
18358             * <all>, <choice>, <group> or <sequence> among the
18359             * [children]."
18360             */
18361             type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18362         }
18363         /*
18364         * Compute the "content type".
18365         */
18366         if (WXS_IS_RESTRICTION(type)) {
18367             /*
18368             * SPEC (3.1) "If <restriction>..."
18369             * (3.1.1) + (3.1.2) */
18370             if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18371                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18372                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18373             }
18374         } else {
18375             /*
18376             * SPEC (3.2) "If <extension>..."
18377             */
18378             if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18379                 /*
18380                 * SPEC (3.2.1)
18381                 * "If the ï¿½effective content� is empty, then the
18382                 *  {content type} of the [...] base ..."
18383                 */
18384                 type->contentType = baseType->contentType;
18385                 type->subtypes = baseType->subtypes;
18386                 /*
18387                 * Fixes bug #347316:
18388                 * This is the case when the base type has a simple
18389                 * type definition as content.
18390                 */
18391                 type->contentTypeDef = baseType->contentTypeDef;
18392                 /*
18393                 * NOTE that the effective mixed is ignored here.
18394                 */
18395             } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18396                 /*
18397                 * SPEC (3.2.2)
18398                 */
18399                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18400                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18401             } else {
18402                 /*
18403                 * SPEC (3.2.3)
18404                 */
18405                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18406                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18407                     /*
18408                     * "A model group whose {compositor} is sequence and whose
18409                     * {particles} are..."
18410                     */
18411                 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18412                     (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18413                     ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18414                         XML_SCHEMA_TYPE_ALL))
18415                 {
18416                     /*
18417                     * SPEC cos-all-limited (1)
18418                     */
18419                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18420                         /* TODO: error code */
18421                         XML_SCHEMAP_COS_ALL_LIMITED,
18422                         WXS_ITEM_NODE(type), NULL,
18423                         "The type has an 'all' model group in its "
18424                         "{content type} and thus cannot be derived from "
18425                         "a non-empty type, since this would produce a "
18426                         "'sequence' model group containing the 'all' "
18427                         "model group; 'all' model groups are not "
18428                         "allowed to appear inside other model groups",
18429                         NULL, NULL);
18430
18431                 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18432                     (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18433                     ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18434                         XML_SCHEMA_TYPE_ALL))
18435                 {
18436                     /*
18437                     * SPEC cos-all-limited (1)
18438                     */
18439                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18440                         /* TODO: error code */
18441                         XML_SCHEMAP_COS_ALL_LIMITED,
18442                         WXS_ITEM_NODE(type), NULL,
18443                         "A type cannot be derived by extension from a type "
18444                         "which has an 'all' model group in its "
18445                         "{content type}, since this would produce a "
18446                         "'sequence' model group containing the 'all' "
18447                         "model group; 'all' model groups are not "
18448                         "allowed to appear inside other model groups",
18449                         NULL, NULL);
18450
18451                 } else if (! dummySequence) {
18452                     xmlSchemaTreeItemPtr effectiveContent =
18453                         (xmlSchemaTreeItemPtr) type->subtypes;
18454                     /*
18455                     * Create the particle.
18456                     */
18457                     particle = xmlSchemaAddParticle(pctxt,
18458                         type->node, 1, 1);
18459                     if (particle == NULL)
18460                         goto exit_failure;
18461                     /*
18462                     * Create the "sequence" model group.
18463                     */
18464                     particle->children = (xmlSchemaTreeItemPtr)
18465                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18466                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18467                     if (particle->children == NULL)
18468                         goto exit_failure;
18469                     WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18470                     /*
18471                     * SPEC "the particle of the {content type} of
18472                     * the ... base ..."
18473                     * Create a duplicate of the base type's particle
18474                     * and assign its "term" to it.
18475                     */
18476                     particle->children->children =
18477                         (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18478                         type->node,
18479                         ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18480                         ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18481                     if (particle->children->children == NULL)
18482                         goto exit_failure;
18483                     particle = (xmlSchemaParticlePtr)
18484                         particle->children->children;
18485                     particle->children =
18486                         ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18487                     /*
18488                     * SPEC "followed by the ï¿½effective content�."
18489                     */
18490                     particle->next = effectiveContent;
18491                     /*
18492                     * This all will result in:
18493                     * new-particle
18494                     *   --> new-sequence(
18495                     *         new-particle
18496                     *           --> base-model,
18497                     *         this-particle
18498                     *           --> this-model
18499                     *       )
18500                     */
18501                 } else {
18502                     /*
18503                     * This is the case when there is already an empty
18504                     * <sequence> with minOccurs==maxOccurs==1.
18505                     * Just add the base types's content type.
18506                     * NOTE that, although we miss to add an intermediate
18507                     * <sequence>, this should produce no difference to
18508                     * neither the regex compilation of the content model,
18509                     * nor to the complex type contraints.
18510                     */
18511                     particle->children->children =
18512                         (xmlSchemaTreeItemPtr) baseType->subtypes;
18513                 }
18514             }
18515         }
18516     }
18517     /*
18518     * Now fixup attribute uses:
18519     *   - expand attr. group references
18520     *     - intersect attribute wildcards
18521     *   - inherit attribute uses of the base type
18522     *   - inherit or union attr. wildcards if extending
18523     *   - apply attr. use prohibitions if restricting
18524     */
18525     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18526     HFAILURE HERROR
18527     /*
18528     * Apply the complex type component constraints; this will not
18529     * check attributes, since this is done in
18530     * xmlSchemaFixupTypeAttributeUses().
18531     */
18532     res = xmlSchemaCheckCTComponent(pctxt, type);
18533     HFAILURE HERROR
18534
18535 #ifdef DEBUG_TYPE
18536     xmlSchemaDebugFixedType(pctxt, type);
18537 #endif
18538     if (olderrs != pctxt->nberrors)
18539         return(pctxt->err);
18540     else
18541         return(0);
18542
18543 exit_error:
18544     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18545 #ifdef DEBUG_TYPE
18546     xmlSchemaDebugFixedType(pctxt, type);
18547 #endif
18548     return(pctxt->err);
18549
18550 exit_failure:
18551     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18552 #ifdef DEBUG_TYPE
18553     xmlSchemaDebugFixedType(pctxt, type);
18554 #endif
18555     return(-1);
18556 }
18557
18558
18559 /**
18560  * xmlSchemaTypeFixup:
18561  * @typeDecl:  the schema type definition
18562  * @ctxt:  the schema parser context
18563  *
18564  * Fixes the content model of the type.
18565  * URGENT TODO: We need an int result!
18566  */
18567 static int
18568 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18569                    xmlSchemaAbstractCtxtPtr actxt)
18570 {
18571     if (type == NULL)
18572         return(0);
18573     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18574         AERROR_INT("xmlSchemaTypeFixup",
18575             "this function needs a parser context");
18576         return(-1);
18577     }
18578     if (! WXS_IS_TYPE_NOT_FIXED(type))
18579         return(0);
18580     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18581         return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18582     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18583         return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18584     return(0);
18585 }
18586
18587 /**
18588  * xmlSchemaCheckFacet:
18589  * @facet:  the facet
18590  * @typeDecl:  the schema type definition
18591  * @pctxt:  the schema parser context or NULL
18592  * @name: the optional name of the type
18593  *
18594  * Checks and computes the values of facets.
18595  *
18596  * Returns 0 if valid, a positive error code if not valid and
18597  *         -1 in case of an internal or API error.
18598  */
18599 int
18600 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18601                     xmlSchemaTypePtr typeDecl,
18602                     xmlSchemaParserCtxtPtr pctxt,
18603                     const xmlChar * name ATTRIBUTE_UNUSED)
18604 {
18605     int ret = 0, ctxtGiven;
18606
18607     if ((facet == NULL) || (typeDecl == NULL))
18608         return(-1);
18609     /*
18610     * TODO: will the parser context be given if used from
18611     * the relaxNG module?
18612     */
18613     if (pctxt == NULL)
18614         ctxtGiven = 0;
18615     else
18616         ctxtGiven = 1;
18617
18618     switch (facet->type) {
18619         case XML_SCHEMA_FACET_MININCLUSIVE:
18620         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18621         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18622         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18623         case XML_SCHEMA_FACET_ENUMERATION: {
18624                 /*
18625                  * Okay we need to validate the value
18626                  * at that point.
18627                  */
18628                 xmlSchemaTypePtr base;
18629
18630                 /* 4.3.5.5 Constraints on enumeration Schema Components
18631                 * Schema Component Constraint: enumeration valid restriction
18632                 * It is an ï¿½error� if any member of {value} is not in the
18633                 * ï¿½value space� of {base type definition}.
18634                 *
18635                 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18636                 * The value ï¿½must� be in the
18637                 * ï¿½value space� of the ï¿½base type�.
18638                 */
18639                 /*
18640                 * This function is intended to deliver a compiled value
18641                 * on the facet. In this implementation of XML Schemata the
18642                 * type holding a facet, won't be a built-in type.
18643                 * Thus to ensure that other API
18644                 * calls (relaxng) do work, if the given type is a built-in
18645                 * type, we will assume that the given built-in type *is
18646                 * already* the base type.
18647                 */
18648                 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18649                     base = typeDecl->baseType;
18650                     if (base == NULL) {
18651                         PERROR_INT("xmlSchemaCheckFacet",
18652                             "a type user derived type has no base type");
18653                         return (-1);
18654                     }
18655                 } else
18656                     base = typeDecl;
18657
18658                 if (! ctxtGiven) {
18659                     /*
18660                     * A context is needed if called from RelaxNG.
18661                     */
18662                     pctxt = xmlSchemaNewParserCtxt("*");
18663                     if (pctxt == NULL)
18664                         return (-1);
18665                 }
18666                 /*
18667                 * NOTE: This call does not check the content nodes,
18668                 * since they are not available:
18669                 * facet->node is just the node holding the facet
18670                 * definition, *not* the attribute holding the *value*
18671                 * of the facet.
18672                 */
18673                 ret = xmlSchemaVCheckCVCSimpleType(
18674                     ACTXT_CAST pctxt, facet->node, base,
18675                     facet->value, &(facet->val), 1, 1, 0);
18676                 if (ret != 0) {
18677                     if (ret < 0) {
18678                         /* No error message for RelaxNG. */
18679                         if (ctxtGiven) {
18680                             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18681                                 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18682                                 "Internal error: xmlSchemaCheckFacet, "
18683                                 "failed to validate the value '%s' of the "
18684                                 "facet '%s' against the base type",
18685                                 facet->value, xmlSchemaFacetTypeToString(facet->type));
18686                         }
18687                         goto internal_error;
18688                     }
18689                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18690                     /* No error message for RelaxNG. */
18691                     if (ctxtGiven) {
18692                         xmlChar *str = NULL;
18693
18694                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18695                             ret, facet->node, WXS_BASIC_CAST facet,
18696                             "The value '%s' of the facet does not validate "
18697                             "against the base type '%s'",
18698                             facet->value,
18699                             xmlSchemaFormatQName(&str,
18700                                 base->targetNamespace, base->name));
18701                         FREE_AND_NULL(str);
18702                     }
18703                     goto exit;
18704                 } else if (facet->val == NULL) {
18705                     if (ctxtGiven) {
18706                         PERROR_INT("xmlSchemaCheckFacet",
18707                             "value was not computed");
18708                     }
18709                     TODO
18710                 }
18711                 break;
18712             }
18713         case XML_SCHEMA_FACET_PATTERN:
18714             facet->regexp = xmlRegexpCompile(facet->value);
18715             if (facet->regexp == NULL) {
18716                 ret = XML_SCHEMAP_REGEXP_INVALID;
18717                 /* No error message for RelaxNG. */
18718                 if (ctxtGiven) {
18719                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18720                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18721                         "The value '%s' of the facet 'pattern' is not a "
18722                         "valid regular expression",
18723                         facet->value, NULL);
18724                 }
18725             }
18726             break;
18727         case XML_SCHEMA_FACET_TOTALDIGITS:
18728         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18729         case XML_SCHEMA_FACET_LENGTH:
18730         case XML_SCHEMA_FACET_MAXLENGTH:
18731         case XML_SCHEMA_FACET_MINLENGTH:
18732
18733             if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18734                 ret = xmlSchemaValidatePredefinedType(
18735                     xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18736                     facet->value, &(facet->val));
18737             } else {
18738                 ret = xmlSchemaValidatePredefinedType(
18739                     xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18740                     facet->value, &(facet->val));
18741             }
18742             if (ret != 0) {
18743                 if (ret < 0) {
18744                     /* No error message for RelaxNG. */
18745                     if (ctxtGiven) {
18746                         PERROR_INT("xmlSchemaCheckFacet",
18747                             "validating facet value");
18748                     }
18749                     goto internal_error;
18750                 }
18751                 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18752                 /* No error message for RelaxNG. */
18753                 if (ctxtGiven) {
18754                     /* error code */
18755                     xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18756                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18757                         "The value '%s' of the facet '%s' is not a valid '%s'",
18758                         facet->value,
18759                         xmlSchemaFacetTypeToString(facet->type),
18760                         (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18761                             BAD_CAST "nonNegativeInteger" :
18762                             BAD_CAST "positiveInteger",
18763                         NULL);
18764                 }
18765             }
18766             break;
18767
18768         case XML_SCHEMA_FACET_WHITESPACE:{
18769                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18770                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18771                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18772                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18773                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18774                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18775                 } else {
18776                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18777                     /* No error message for RelaxNG. */
18778                     if (ctxtGiven) {
18779                         /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18780                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18781                             ret, facet->node, WXS_BASIC_CAST typeDecl,
18782                             "The value '%s' of the facet 'whitespace' is not "
18783                             "valid", facet->value, NULL);
18784                     }
18785                 }
18786             }
18787         default:
18788             break;
18789     }
18790 exit:
18791     if ((! ctxtGiven) && (pctxt != NULL))
18792         xmlSchemaFreeParserCtxt(pctxt);
18793     return (ret);
18794 internal_error:
18795     if ((! ctxtGiven) && (pctxt != NULL))
18796         xmlSchemaFreeParserCtxt(pctxt);
18797     return (-1);
18798 }
18799
18800 /**
18801  * xmlSchemaCheckFacetValues:
18802  * @typeDecl:  the schema type definition
18803  * @ctxt:  the schema parser context
18804  *
18805  * Checks the default values types, especially for facets
18806  */
18807 static int
18808 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18809                           xmlSchemaParserCtxtPtr pctxt)
18810 {
18811     int res, olderrs = pctxt->nberrors;
18812     const xmlChar *name = typeDecl->name;
18813     /*
18814     * NOTE: It is intended to use the facets list, instead
18815     * of facetSet.
18816     */
18817     if (typeDecl->facets != NULL) {
18818         xmlSchemaFacetPtr facet = typeDecl->facets;
18819
18820         /*
18821         * Temporarily assign the "schema" to the validation context
18822         * of the parser context. This is needed for NOTATION validation.
18823         */
18824         if (pctxt->vctxt == NULL) {
18825             if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18826                 return(-1);
18827         }
18828         pctxt->vctxt->schema = pctxt->schema;
18829         while (facet != NULL) {
18830             res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18831             HFAILURE
18832             facet = facet->next;
18833         }
18834         pctxt->vctxt->schema = NULL;
18835     }
18836     if (olderrs != pctxt->nberrors)
18837         return(pctxt->err);
18838     return(0);
18839 exit_failure:
18840     return(-1);
18841 }
18842
18843 /**
18844  * xmlSchemaGetCircModelGrDefRef:
18845  * @ctxtMGroup: the searched model group
18846  * @selfMGroup: the second searched model group
18847  * @particle: the first particle
18848  *
18849  * This one is intended to be used by
18850  * xmlSchemaCheckGroupDefCircular only.
18851  *
18852  * Returns the particle with the circular model group definition reference,
18853  * otherwise NULL.
18854  */
18855 static xmlSchemaTreeItemPtr
18856 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18857                               xmlSchemaTreeItemPtr particle)
18858 {
18859     xmlSchemaTreeItemPtr circ = NULL;
18860     xmlSchemaTreeItemPtr term;
18861     xmlSchemaModelGroupDefPtr gdef;
18862
18863     for (; particle != NULL; particle = particle->next) {
18864         term = particle->children;
18865         if (term == NULL)
18866             continue;
18867         switch (term->type) {
18868             case XML_SCHEMA_TYPE_GROUP:
18869                 gdef = (xmlSchemaModelGroupDefPtr) term;
18870                 if (gdef == groupDef)
18871                     return (particle);
18872                 /*
18873                 * Mark this model group definition to avoid infinite
18874                 * recursion on circular references not yet examined.
18875                 */
18876                 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18877                     continue;
18878                 if (gdef->children != NULL) {
18879                     gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18880                     circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18881                         gdef->children->children);
18882                     gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18883                     if (circ != NULL)
18884                         return (circ);
18885                 }
18886                 break;
18887             case XML_SCHEMA_TYPE_SEQUENCE:
18888             case XML_SCHEMA_TYPE_CHOICE:
18889             case XML_SCHEMA_TYPE_ALL:
18890                 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18891                 if (circ != NULL)
18892                     return (circ);
18893                 break;
18894             default:
18895                 break;
18896         }
18897     }
18898     return (NULL);
18899 }
18900
18901 /**
18902  * xmlSchemaCheckGroupDefCircular:
18903  * @item:  the model group definition
18904  * @ctxt:  the parser context
18905  * @name:  the name
18906  *
18907  * Checks for circular references to model group definitions.
18908  */
18909 static void
18910 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18911                                xmlSchemaParserCtxtPtr ctxt)
18912 {
18913     /*
18914     * Schema Component Constraint: Model Group Correct
18915     * 2 Circular groups are disallowed. That is, within the {particles}
18916     * of a group there must not be at any depth a particle whose {term}
18917     * is the group itself.
18918     */
18919     if ((item == NULL) ||
18920         (item->type != XML_SCHEMA_TYPE_GROUP) ||
18921         (item->children == NULL))
18922         return;
18923     {
18924         xmlSchemaTreeItemPtr circ;
18925
18926         circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18927         if (circ != NULL) {
18928             xmlChar *str = NULL;
18929             /*
18930             * TODO: The error report is not adequate: this constraint
18931             * is defined for model groups but not definitions, but since
18932             * there cannot be any circular model groups without a model group
18933             * definition (if not using a construction API), we check those
18934             * defintions only.
18935             */
18936             xmlSchemaPCustomErr(ctxt,
18937                 XML_SCHEMAP_MG_PROPS_CORRECT_2,
18938                 NULL, WXS_ITEM_NODE(circ),
18939                 "Circular reference to the model group definition '%s' "
18940                 "defined", xmlSchemaFormatQName(&str,
18941                     item->targetNamespace, item->name));
18942             FREE_AND_NULL(str)
18943             /*
18944             * NOTE: We will cut the reference to avoid further
18945             * confusion of the processor. This is a fatal error.
18946             */
18947             circ->children = NULL;
18948         }
18949     }
18950 }
18951
18952 /**
18953  * xmlSchemaModelGroupToModelGroupDefFixup:
18954  * @ctxt:  the parser context
18955  * @mg:  the model group
18956  *
18957  * Assigns the model group of model group definitions to the "term"
18958  * of the referencing particle.
18959  * In xmlSchemaResolveModelGroupParticleReferences the model group
18960  * definitions were assigned to the "term", since needed for the
18961  * circularity check.
18962  *
18963  * Schema Component Constraint:
18964  *     All Group Limited (cos-all-limited) (1.2)
18965  */
18966 static void
18967 xmlSchemaModelGroupToModelGroupDefFixup(
18968     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18969     xmlSchemaModelGroupPtr mg)
18970 {
18971     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18972
18973     while (particle != NULL) {
18974         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18975             ((WXS_PARTICLE_TERM(particle))->type !=
18976                 XML_SCHEMA_TYPE_GROUP))
18977         {
18978             particle = WXS_PTC_CAST particle->next;
18979             continue;
18980         }
18981         if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18982             /*
18983             * TODO: Remove the particle.
18984             */
18985             WXS_PARTICLE_TERM(particle) = NULL;
18986             particle = WXS_PTC_CAST particle->next;
18987             continue;
18988         }
18989         /*
18990         * Assign the model group to the {term} of the particle.
18991         */
18992         WXS_PARTICLE_TERM(particle) =
18993             WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18994
18995         particle = WXS_PTC_CAST particle->next;
18996     }
18997 }
18998
18999 /**
19000  * xmlSchemaCheckAttrGroupCircularRecur:
19001  * @ctxtGr: the searched attribute group
19002  * @attr: the current attribute list to be processed
19003  *
19004  * This one is intended to be used by
19005  * xmlSchemaCheckAttrGroupCircular only.
19006  *
19007  * Returns the circular attribute grou reference, otherwise NULL.
19008  */
19009 static xmlSchemaQNameRefPtr
19010 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19011                                      xmlSchemaItemListPtr list)
19012 {
19013     xmlSchemaAttributeGroupPtr gr;
19014     xmlSchemaQNameRefPtr ref, circ;
19015     int i;
19016     /*
19017     * We will search for an attribute group reference which
19018     * references the context attribute group.
19019     */
19020     for (i = 0; i < list->nbItems; i++) {
19021         ref = list->items[i];
19022         if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19023             (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19024             (ref->item != NULL))
19025         {
19026             gr = WXS_ATTR_GROUP_CAST ref->item;
19027             if (gr == ctxtGr)
19028                 return(ref);
19029             if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19030                 continue;
19031             /*
19032             * Mark as visited to avoid infinite recursion on
19033             * circular references not yet examined.
19034             */
19035             if ((gr->attrUses) &&
19036                 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19037             {
19038                 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19039                 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19040                     (xmlSchemaItemListPtr) gr->attrUses);
19041                 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19042                 if (circ != NULL)
19043                     return (circ);
19044             }
19045
19046         }
19047     }
19048     return (NULL);
19049 }
19050
19051 /**
19052  * xmlSchemaCheckAttrGroupCircular:
19053  * attrGr:  the attribute group definition
19054  * @ctxt:  the parser context
19055  * @name:  the name
19056  *
19057  * Checks for circular references of attribute groups.
19058  */
19059 static int
19060 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19061                                 xmlSchemaParserCtxtPtr ctxt)
19062 {
19063     /*
19064     * Schema Representation Constraint:
19065     * Attribute Group Definition Representation OK
19066     * 3 Circular group reference is disallowed outside <redefine>.
19067     * That is, unless this element information item's parent is
19068     * <redefine>, then among the [children], if any, there must
19069     * not be an <attributeGroup> with ref [attribute] which resolves
19070     * to the component corresponding to this <attributeGroup>. Indirect
19071     * circularity is also ruled out. That is, when QName resolution
19072     * (Schema Document) (�3.15.3) is applied to a ï¿½QName� arising from
19073     * any <attributeGroup>s with a ref [attribute] among the [children],
19074     * it must not be the case that a ï¿½QName� is encountered at any depth
19075     * which resolves to the component corresponding to this <attributeGroup>.
19076     */
19077     if (attrGr->attrUses == NULL)
19078         return(0);
19079     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19080         return(0);
19081     else {
19082         xmlSchemaQNameRefPtr circ;
19083
19084         circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19085             (xmlSchemaItemListPtr) attrGr->attrUses);
19086         if (circ != NULL) {
19087             xmlChar *str = NULL;
19088             /*
19089             * TODO: Report the referenced attr group as QName.
19090             */
19091             xmlSchemaPCustomErr(ctxt,
19092                 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19093                 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19094                 "Circular reference to the attribute group '%s' "
19095                 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19096             FREE_AND_NULL(str);
19097             /*
19098             * NOTE: We will cut the reference to avoid further
19099             * confusion of the processor.
19100             * BADSPEC TODO: The spec should define how to process in this case.
19101             */
19102             circ->item = NULL;
19103             return(ctxt->err);
19104         }
19105     }
19106     return(0);
19107 }
19108
19109 static int
19110 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19111                                   xmlSchemaAttributeGroupPtr attrGr);
19112
19113 /**
19114  * xmlSchemaExpandAttributeGroupRefs:
19115  * @pctxt: the parser context
19116  * @node: the node of the component holding the attribute uses
19117  * @completeWild: the intersected wildcard to be returned
19118  * @list: the attribute uses
19119  *
19120  * Substitutes contained attribute group references
19121  * for their attribute uses. Wilcards are intersected.
19122  * Attribute use prohibitions are removed from the list
19123  * and returned via the @prohibs list.
19124  * Pointlessness of attr. prohibs, if a matching attr. decl
19125  * is existent a well, are checked.
19126  */
19127 static int
19128 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19129                                   xmlSchemaBasicItemPtr item,
19130                                   xmlSchemaWildcardPtr *completeWild,
19131                                   xmlSchemaItemListPtr list,
19132                                   xmlSchemaItemListPtr prohibs)
19133 {
19134     xmlSchemaAttributeGroupPtr gr;
19135     xmlSchemaAttributeUsePtr use;
19136     xmlSchemaItemListPtr sublist;
19137     int i, j;
19138     int created = (*completeWild == NULL) ? 0 : 1;
19139
19140     if (prohibs)
19141         prohibs->nbItems = 0;
19142
19143     for (i = 0; i < list->nbItems; i++) {
19144         use = list->items[i];
19145
19146         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19147             if (prohibs == NULL) {
19148                 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19149                     "unexpected attr prohibition found");
19150                 return(-1);
19151             }
19152             /*
19153             * Remove from attribute uses.
19154             */
19155             if (xmlSchemaItemListRemove(list, i) == -1)
19156                 return(-1);
19157             i--;
19158             /*
19159             * Note that duplicate prohibitions were already
19160             * handled at parsing time.
19161             */
19162             /*
19163             * Add to list of prohibitions.
19164             */
19165             xmlSchemaItemListAddSize(prohibs, 2, use);
19166             continue;
19167         }
19168         if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19169             ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19170         {
19171             if ((WXS_QNAME_CAST use)->item == NULL)
19172                 return(-1);
19173             gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19174             /*
19175             * Expand the referenced attr. group.
19176             * TODO: remove this, this is done in a previous step, so
19177             * already done here.
19178             */
19179             if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19180                 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19181                     return(-1);
19182             }
19183             /*
19184             * Build the 'complete' wildcard; i.e. intersect multiple
19185             * wildcards.
19186             */
19187             if (gr->attributeWildcard != NULL) {
19188                 if (*completeWild == NULL) {
19189                     *completeWild = gr->attributeWildcard;
19190                 } else {
19191                     if (! created) {
19192                         xmlSchemaWildcardPtr tmpWild;
19193
19194                          /*
19195                         * Copy the first encountered wildcard as context,
19196                         * except for the annotation.
19197                         *
19198                         * Although the complete wildcard might not correspond
19199                         * to any node in the schema, we will anchor it on
19200                         * the node of the owner component.
19201                         */
19202                         tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19203                             XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19204                             WXS_ITEM_NODE(item));
19205                         if (tmpWild == NULL)
19206                             return(-1);
19207                         if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19208                             tmpWild, *completeWild) == -1)
19209                             return (-1);
19210                         tmpWild->processContents = (*completeWild)->processContents;
19211                         *completeWild = tmpWild;
19212                         created = 1;
19213                     }
19214
19215                     if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19216                         gr->attributeWildcard) == -1)
19217                         return(-1);
19218                 }
19219             }
19220             /*
19221             * Just remove the reference if the referenced group does not
19222             * contain any attribute uses.
19223             */
19224             sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19225             if ((sublist == NULL) || sublist->nbItems == 0) {
19226                 if (xmlSchemaItemListRemove(list, i) == -1)
19227                     return(-1);
19228                 i--;
19229                 continue;
19230             }
19231             /*
19232             * Add the attribute uses.
19233             */
19234             list->items[i] = sublist->items[0];
19235             if (sublist->nbItems != 1) {
19236                 for (j = 1; j < sublist->nbItems; j++) {
19237                     i++;
19238                     if (xmlSchemaItemListInsert(list,
19239                             sublist->items[j], i) == -1)
19240                         return(-1);
19241                 }
19242             }
19243         }
19244
19245     }
19246     /*
19247     * Handle pointless prohibitions of declared attributes.
19248     */
19249     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19250         xmlSchemaAttributeUseProhibPtr prohib;
19251
19252         for (i = prohibs->nbItems -1; i >= 0; i--) {
19253             prohib = prohibs->items[i];
19254             for (j = 0; j < list->nbItems; j++) {
19255                 use = list->items[j];
19256
19257                 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19258                     (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19259                 {
19260                     xmlChar *str = NULL;
19261
19262                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19263                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19264                         prohib->node, NULL,
19265                         "Skipping pointless attribute use prohibition "
19266                         "'%s', since a corresponding attribute use "
19267                         "exists already in the type definition",
19268                         xmlSchemaFormatQName(&str,
19269                             prohib->targetNamespace, prohib->name),
19270                         NULL, NULL);
19271                     FREE_AND_NULL(str);
19272                     /*
19273                     * Remove the prohibition.
19274                     */
19275                     if (xmlSchemaItemListRemove(prohibs, i) == -1)
19276                         return(-1);
19277                     break;
19278                 }
19279             }
19280         }
19281     }
19282     return(0);
19283 }
19284
19285 /**
19286  * xmlSchemaAttributeGroupExpandRefs:
19287  * @pctxt:  the parser context
19288  * @attrGr:  the attribute group definition
19289  *
19290  * Computation of:
19291  * {attribute uses} property
19292  * {attribute wildcard} property
19293  *
19294  * Substitutes contained attribute group references
19295  * for their attribute uses. Wilcards are intersected.
19296  */
19297 static int
19298 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19299                                   xmlSchemaAttributeGroupPtr attrGr)
19300 {
19301     if ((attrGr->attrUses == NULL) ||
19302         (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19303         return(0);
19304
19305     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19306     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19307         &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19308         return(-1);
19309     return(0);
19310 }
19311
19312 /**
19313  * xmlSchemaAttributeGroupExpandRefs:
19314  * @pctxt:  the parser context
19315  * @attrGr:  the attribute group definition
19316  *
19317  * Substitutes contained attribute group references
19318  * for their attribute uses. Wilcards are intersected.
19319  *
19320  * Schema Component Constraint:
19321  *    Attribute Group Definition Properties Correct (ag-props-correct)
19322  */
19323 static int
19324 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19325                                   xmlSchemaAttributeGroupPtr attrGr)
19326 {
19327     /*
19328     * SPEC ag-props-correct
19329     * (1) "The values of the properties of an attribute group definition
19330     * must be as described in the property tableau in The Attribute
19331     * Group Definition Schema Component (�3.6.1), modulo the impact of
19332     * Missing Sub-components (�5.3);"
19333     */
19334
19335     if ((attrGr->attrUses != NULL) &&
19336         (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19337     {
19338         xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19339         xmlSchemaAttributeUsePtr use, tmp;
19340         int i, j, hasId = 0;
19341
19342         for (i = uses->nbItems -1; i >= 0; i--) {
19343             use = uses->items[i];
19344             /*
19345             * SPEC ag-props-correct
19346             * (2) "Two distinct members of the {attribute uses} must not have
19347             * {attribute declaration}s both of whose {name}s match and whose
19348             * {target namespace}s are identical."
19349             */
19350             if (i > 0) {
19351                 for (j = i -1; j >= 0; j--) {
19352                     tmp = uses->items[j];
19353                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
19354                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
19355                         (WXS_ATTRUSE_DECL_TNS(use) ==
19356                         WXS_ATTRUSE_DECL_TNS(tmp)))
19357                     {
19358                         xmlChar *str = NULL;
19359
19360                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19361                             XML_SCHEMAP_AG_PROPS_CORRECT,
19362                             attrGr->node, WXS_BASIC_CAST attrGr,
19363                             "Duplicate %s",
19364                             xmlSchemaGetComponentDesignation(&str, use),
19365                             NULL);
19366                         FREE_AND_NULL(str);
19367                         /*
19368                         * Remove the duplicate.
19369                         */
19370                         if (xmlSchemaItemListRemove(uses, i) == -1)
19371                             return(-1);
19372                         goto next_use;
19373                     }
19374                 }
19375             }
19376             /*
19377             * SPEC ag-props-correct
19378             * (3) "Two distinct members of the {attribute uses} must not have
19379             * {attribute declaration}s both of whose {type definition}s are or
19380             * are derived from ID."
19381             * TODO: Does 'derived' include member-types of unions?
19382             */
19383             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19384                 if (xmlSchemaIsDerivedFromBuiltInType(
19385                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19386                 {
19387                     if (hasId) {
19388                         xmlChar *str = NULL;
19389
19390                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19391                             XML_SCHEMAP_AG_PROPS_CORRECT,
19392                             attrGr->node, WXS_BASIC_CAST attrGr,
19393                             "There must not exist more than one attribute "
19394                             "declaration of type 'xs:ID' "
19395                             "(or derived from 'xs:ID'). The %s violates this "
19396                             "constraint",
19397                             xmlSchemaGetComponentDesignation(&str, use),
19398                             NULL);
19399                         FREE_AND_NULL(str);
19400                         if (xmlSchemaItemListRemove(uses, i) == -1)
19401                             return(-1);
19402                     }
19403                     hasId = 1;
19404                 }
19405             }
19406 next_use: {}
19407         }
19408     }
19409     return(0);
19410 }
19411
19412 /**
19413  * xmlSchemaResolveAttrGroupReferences:
19414  * @attrgrpDecl:  the schema attribute definition
19415  * @ctxt:  the schema parser context
19416  * @name:  the attribute name
19417  *
19418  * Resolves references to attribute group definitions.
19419  */
19420 static int
19421 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19422                                     xmlSchemaParserCtxtPtr ctxt)
19423 {
19424     xmlSchemaAttributeGroupPtr group;
19425
19426     if (ref->item != NULL)
19427         return(0);
19428     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19429         ref->name,
19430         ref->targetNamespace);
19431     if (group == NULL) {
19432         xmlSchemaPResCompAttrErr(ctxt,
19433             XML_SCHEMAP_SRC_RESOLVE,
19434             NULL, ref->node,
19435             "ref", ref->name, ref->targetNamespace,
19436             ref->itemType, NULL);
19437         return(ctxt->err);
19438     }
19439     ref->item = WXS_BASIC_CAST group;
19440     return(0);
19441 }
19442
19443 /**
19444  * xmlSchemaCheckAttrPropsCorrect:
19445  * @item:  an schema attribute declaration/use
19446  * @ctxt:  a schema parser context
19447  * @name:  the name of the attribute
19448  *
19449  *
19450  * Schema Component Constraint:
19451  *    Attribute Declaration Properties Correct (a-props-correct)
19452  *
19453  * Validates the value constraints of an attribute declaration/use.
19454  * NOTE that this needs the simle type definitions to be already
19455  *   builded and checked.
19456  */
19457 static int
19458 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19459                                xmlSchemaAttributePtr attr)
19460 {
19461
19462     /*
19463     * SPEC a-props-correct (1)
19464     * "The values of the properties of an attribute declaration must
19465     * be as described in the property tableau in The Attribute
19466     * Declaration Schema Component (�3.2.1), modulo the impact of
19467     * Missing Sub-components (�5.3)."
19468     */
19469
19470     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19471         return(0);
19472
19473     if (attr->defValue != NULL) {
19474         int ret;
19475
19476         /*
19477         * SPEC a-props-correct (3)
19478         * "If the {type definition} is or is derived from ID then there
19479         * must not be a {value constraint}."
19480         */
19481         if (xmlSchemaIsDerivedFromBuiltInType(
19482             WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19483         {
19484             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19485                 XML_SCHEMAP_A_PROPS_CORRECT_3,
19486                 NULL, WXS_BASIC_CAST attr,
19487                 "Value constraints are not allowed if the type definition "
19488                 "is or is derived from xs:ID",
19489                 NULL, NULL);
19490             return(pctxt->err);
19491         }
19492         /*
19493         * SPEC a-props-correct (2)
19494         * "if there is a {value constraint}, the canonical lexical
19495         * representation of its value must be ï¿½valid� with respect
19496         * to the {type definition} as defined in String Valid (�3.14.4)."
19497         * TODO: Don't care about the *cononical* stuff here, this requirement
19498         * will be removed in WXS 1.1 anyway.
19499         */
19500         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19501             attr->node, WXS_ATTR_TYPEDEF(attr),
19502             attr->defValue, &(attr->defVal),
19503             1, 1, 0);
19504         if (ret != 0) {
19505             if (ret < 0) {
19506                 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19507                     "calling xmlSchemaVCheckCVCSimpleType()");
19508                 return(-1);
19509             }
19510             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19511                 XML_SCHEMAP_A_PROPS_CORRECT_2,
19512                 NULL, WXS_BASIC_CAST attr,
19513                 "The value of the value constraint is not valid",
19514                 NULL, NULL);
19515             return(pctxt->err);
19516         }
19517     }
19518
19519     return(0);
19520 }
19521
19522 static xmlSchemaElementPtr
19523 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19524                                  xmlSchemaElementPtr ancestor)
19525 {
19526     xmlSchemaElementPtr ret;
19527
19528     if (WXS_SUBST_HEAD(ancestor) == NULL)
19529         return (NULL);
19530     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19531         return (ancestor);
19532
19533     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19534         return (NULL);
19535     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19536     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19537         WXS_SUBST_HEAD(ancestor));
19538     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19539
19540     return (ret);
19541 }
19542
19543 /**
19544  * xmlSchemaCheckElemPropsCorrect:
19545  * @ctxt:  a schema parser context
19546  * @decl: the element declaration
19547  * @name:  the name of the attribute
19548  *
19549  * Schema Component Constraint:
19550  * Element Declaration Properties Correct (e-props-correct)
19551  *
19552  * STATUS:
19553  *   missing: (6)
19554  */
19555 static int
19556 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19557                                xmlSchemaElementPtr elemDecl)
19558 {
19559     int ret = 0;
19560     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19561     /*
19562     * SPEC (1) "The values of the properties of an element declaration
19563     * must be as described in the property tableau in The Element
19564     * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19565     * Sub-components (�5.3)."
19566     */
19567     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19568         xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19569
19570         xmlSchemaCheckElementDeclComponent(head, pctxt);
19571         /*
19572         * SPEC (3) "If there is a non-�absent� {substitution group
19573         * affiliation}, then {scope} must be global."
19574         */
19575         if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19576             xmlSchemaPCustomErr(pctxt,
19577                 XML_SCHEMAP_E_PROPS_CORRECT_3,
19578                 WXS_BASIC_CAST elemDecl, NULL,
19579                 "Only global element declarations can have a "
19580                 "substitution group affiliation", NULL);
19581             ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19582         }
19583         /*
19584         * TODO: SPEC (6) "Circular substitution groups are disallowed.
19585         * That is, it must not be possible to return to an element declaration
19586         * by repeatedly following the {substitution group affiliation}
19587         * property."
19588         */
19589         if (head == elemDecl)
19590             circ = head;
19591         else if (WXS_SUBST_HEAD(head) != NULL)
19592             circ = xmlSchemaCheckSubstGroupCircular(head, head);
19593         else
19594             circ = NULL;
19595         if (circ != NULL) {
19596             xmlChar *strA = NULL, *strB = NULL;
19597
19598             xmlSchemaPCustomErrExt(pctxt,
19599                 XML_SCHEMAP_E_PROPS_CORRECT_6,
19600                 WXS_BASIC_CAST circ, NULL,
19601                 "The element declaration '%s' defines a circular "
19602                 "substitution group to element declaration '%s'",
19603                 xmlSchemaGetComponentQName(&strA, circ),
19604                 xmlSchemaGetComponentQName(&strB, head),
19605                 NULL);
19606             FREE_AND_NULL(strA)
19607             FREE_AND_NULL(strB)
19608             ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19609         }
19610         /*
19611         * SPEC (4) "If there is a {substitution group affiliation},
19612         * the {type definition}
19613         * of the element declaration must be validly derived from the {type
19614         * definition} of the {substitution group affiliation}, given the value
19615         * of the {substitution group exclusions} of the {substitution group
19616         * affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19617         * (if the {type definition} is complex) or as defined in
19618         * Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19619         * simple)."
19620         *
19621         * NOTE: {substitution group exclusions} means the values of the
19622         * attribute "final".
19623         */
19624
19625         if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19626             int set = 0;
19627
19628             if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19629                 set |= SUBSET_EXTENSION;
19630             if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19631                 set |= SUBSET_RESTRICTION;
19632
19633             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19634                 WXS_ELEM_TYPEDEF(head), set) != 0) {
19635                 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19636
19637                 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19638                 xmlSchemaPCustomErrExt(pctxt,
19639                     XML_SCHEMAP_E_PROPS_CORRECT_4,
19640                     WXS_BASIC_CAST elemDecl, NULL,
19641                     "The type definition '%s' was "
19642                     "either rejected by the substitution group "
19643                     "affiliation '%s', or not validly derived from its type "
19644                     "definition '%s'",
19645                     xmlSchemaGetComponentQName(&strA, typeDef),
19646                     xmlSchemaGetComponentQName(&strB, head),
19647                     xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19648                 FREE_AND_NULL(strA)
19649                 FREE_AND_NULL(strB)
19650                 FREE_AND_NULL(strC)
19651             }
19652         }
19653     }
19654     /*
19655     * SPEC (5) "If the {type definition} or {type definition}'s
19656     * {content type}
19657     * is or is derived from ID then there must not be a {value constraint}.
19658     * Note: The use of ID as a type definition for elements goes beyond
19659     * XML 1.0, and should be avoided if backwards compatibility is desired"
19660     */
19661     if ((elemDecl->value != NULL) &&
19662         ((WXS_IS_SIMPLE(typeDef) &&
19663           xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19664          (WXS_IS_COMPLEX(typeDef) &&
19665           WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19666           xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19667             XML_SCHEMAS_ID)))) {
19668
19669         ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19670         xmlSchemaPCustomErr(pctxt,
19671             XML_SCHEMAP_E_PROPS_CORRECT_5,
19672             WXS_BASIC_CAST elemDecl, NULL,
19673             "The type definition (or type definition's content type) is or "
19674             "is derived from ID; value constraints are not allowed in "
19675             "conjunction with such a type definition", NULL);
19676     } else if (elemDecl->value != NULL) {
19677         int vcret;
19678         xmlNodePtr node = NULL;
19679
19680         /*
19681         * SPEC (2) "If there is a {value constraint}, the canonical lexical
19682         * representation of its value must be ï¿½valid� with respect to the
19683         * {type definition} as defined in Element Default Valid (Immediate)
19684         * (�3.3.6)."
19685         */
19686         if (typeDef == NULL) {
19687             xmlSchemaPErr(pctxt, elemDecl->node,
19688                 XML_SCHEMAP_INTERNAL,
19689                 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19690                 "type is missing... skipping validation of "
19691                 "the value constraint", NULL, NULL);
19692             return (-1);
19693         }
19694         if (elemDecl->node != NULL) {
19695             if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19696                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19697                     BAD_CAST "fixed");
19698             else
19699                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19700                     BAD_CAST "default");
19701         }
19702         vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19703             typeDef, elemDecl->value, &(elemDecl->defVal));
19704         if (vcret != 0) {
19705             if (vcret < 0) {
19706                 PERROR_INT("xmlSchemaElemCheckValConstr",
19707                     "failed to validate the value constraint of an "
19708                     "element declaration");
19709                 return (-1);
19710             }
19711             return (vcret);
19712         }
19713     }
19714
19715     return (ret);
19716 }
19717
19718 /**
19719  * xmlSchemaCheckElemSubstGroup:
19720  * @ctxt:  a schema parser context
19721  * @decl: the element declaration
19722  * @name:  the name of the attribute
19723  *
19724  * Schema Component Constraint:
19725  * Substitution Group (cos-equiv-class)
19726  *
19727  * In Libxml2 the subst. groups will be precomputed, in terms of that
19728  * a list will be built for each subst. group head, holding all direct
19729  * referents to this head.
19730  * NOTE that this function needs:
19731  *   1. circular subst. groups to be checked beforehand
19732  *   2. the declaration's type to be derived from the head's type
19733  *
19734  * STATUS:
19735  *
19736  */
19737 static void
19738 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19739                              xmlSchemaElementPtr elemDecl)
19740 {
19741     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19742         /* SPEC (1) "Its {abstract} is false." */
19743         (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19744         return;
19745     {
19746         xmlSchemaElementPtr head;
19747         xmlSchemaTypePtr headType, type;
19748         int set, methSet;
19749         /*
19750         * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19751         * {disallowed substitutions} as the blocking constraint, as defined in
19752         * Substitution Group OK (Transitive) (�3.3.6)."
19753         */
19754         for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19755             head = WXS_SUBST_HEAD(head)) {
19756             set = 0;
19757             methSet = 0;
19758             /*
19759             * The blocking constraints.
19760             */
19761             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19762                 continue;
19763             headType = head->subtypes;
19764             type = elemDecl->subtypes;
19765             if (headType == type)
19766                 goto add_member;
19767             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19768                 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19769             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19770                 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19771             /*
19772             * SPEC: Substitution Group OK (Transitive) (2.3)
19773             * "The set of all {derivation method}s involved in the
19774             * derivation of D's {type definition} from C's {type definition}
19775             * does not intersect with the union of the blocking constraint,
19776             * C's {prohibited substitutions} (if C is complex, otherwise the
19777             * empty set) and the {prohibited substitutions} (respectively the
19778             * empty set) of any intermediate {type definition}s in the
19779             * derivation of D's {type definition} from C's {type definition}."
19780             */
19781             /*
19782             * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19783             * subst.head axis, the methSet does not need to be computed for
19784             * the full depth over and over.
19785             */
19786             /*
19787             * The set of all {derivation method}s involved in the derivation
19788             */
19789             while ((type != NULL) && (type != headType)) {
19790                 if ((WXS_IS_EXTENSION(type)) &&
19791                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19792                     methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19793
19794                 if (WXS_IS_RESTRICTION(type) &&
19795                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19796                     methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19797
19798                 type = type->baseType;
19799             }
19800             /*
19801             * The {prohibited substitutions} of all intermediate types +
19802             * the head's type.
19803             */
19804             type = elemDecl->subtypes->baseType;
19805             while (type != NULL) {
19806                 if (WXS_IS_COMPLEX(type)) {
19807                     if ((type->flags &
19808                             XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19809                         ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19810                     set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19811                     if ((type->flags &
19812                             XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19813                         ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19814                     set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19815                 } else
19816                     break;
19817                 if (type == headType)
19818                     break;
19819                 type = type->baseType;
19820             }
19821             if ((set != 0) &&
19822                 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19823                 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19824                 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19825                 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19826                 continue;
19827             }
19828 add_member:
19829             xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19830             if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19831                 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19832         }
19833     }
19834 }
19835
19836 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19837 /**
19838  * xmlSchemaCheckElementDeclComponent
19839  * @pctxt: the schema parser context
19840  * @ctxtComponent: the context component (an element declaration)
19841  * @ctxtParticle: the first particle of the context component
19842  * @searchParticle: the element declaration particle to be analysed
19843  *
19844  * Schema Component Constraint: Element Declarations Consistent
19845  */
19846 static int
19847 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19848                                     xmlSchemaBasicItemPtr ctxtComponent,
19849                                     xmlSchemaParticlePtr ctxtParticle,
19850                                     xmlSchemaParticlePtr searchParticle,
19851                                     xmlSchemaParticlePtr curParticle,
19852                                     int search)
19853 {
19854     return(0);
19855
19856     int ret = 0;
19857     xmlSchemaParticlePtr cur = curParticle;
19858     if (curParticle == NULL) {
19859         return(0);
19860     }
19861     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19862         /*
19863         * Just return in this case. A missing "term" of the particle
19864         * might arise due to an invalid "term" component.
19865         */
19866         return(0);
19867     }
19868     while (cur != NULL) {
19869         switch (WXS_PARTICLE_TERM(cur)->type) {
19870             case XML_SCHEMA_TYPE_ANY:
19871                 break;
19872             case XML_SCHEMA_TYPE_ELEMENT:
19873                 if (search == 0) {
19874                     ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19875                         ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19876                     if (ret != 0)
19877                         return(ret);
19878                 } else {
19879                     xmlSchemaElementPtr elem =
19880                         WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19881                     /*
19882                     * SPEC Element Declarations Consistent:
19883                     * "If the {particles} contains, either directly,
19884                     * indirectly (that is, within the {particles} of a
19885                     * contained model group, recursively) or ï¿½implicitly�
19886                     * two or more element declaration particles with
19887                     * the same {name} and {target namespace}, then
19888                     * all their type definitions must be the same
19889                     * top-level definition [...]"
19890                     */
19891                     if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19892                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19893                         xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19894                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19895                     {
19896                         xmlChar *strA = NULL, *strB = NULL;
19897
19898                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19899                             /* TODO: error code */
19900                             XML_SCHEMAP_COS_NONAMBIG,
19901                             WXS_ITEM_NODE(cur), NULL,
19902                             "In the content model of %s, there are multiple "
19903                             "element declarations for '%s' with different "
19904                             "type definitions",
19905                             xmlSchemaGetComponentDesignation(&strA,
19906                                 ctxtComponent),
19907                             xmlSchemaFormatQName(&strB,
19908                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19909                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19910                         FREE_AND_NULL(strA);
19911                         FREE_AND_NULL(strB);
19912                         return(XML_SCHEMAP_COS_NONAMBIG);
19913                     }
19914                 }
19915                 break;
19916             case XML_SCHEMA_TYPE_SEQUENCE: {
19917                 break;
19918                 }
19919             case XML_SCHEMA_TYPE_CHOICE:{
19920                 /*
19921                 xmlSchemaTreeItemPtr sub;
19922
19923                 sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19924                 while (sub != NULL) {
19925                     ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19926                         ctxtParticle, ctxtElem);
19927                     if (ret != 0)
19928                         return(ret);
19929                     sub = sub->next;
19930                 }
19931                 */
19932                 break;
19933                 }
19934             case XML_SCHEMA_TYPE_ALL:
19935                 break;
19936             case XML_SCHEMA_TYPE_GROUP:
19937                 break;
19938             default:
19939                 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19940                     "xmlSchemaCheckElementDeclConsistent",
19941                     "found unexpected term of type '%s' in content model",
19942                     WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19943                 return(-1);
19944         }
19945         cur = (xmlSchemaParticlePtr) cur->next;
19946     }
19947
19948 exit:
19949     return(ret);
19950 }
19951 #endif
19952
19953 /**
19954  * xmlSchemaCheckElementDeclComponent
19955  * @item:  an schema element declaration/particle
19956  * @ctxt:  a schema parser context
19957  * @name:  the name of the attribute
19958  *
19959  * Validates the value constraints of an element declaration.
19960  * Adds substitution group members.
19961  */
19962 static void
19963 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19964                                    xmlSchemaParserCtxtPtr ctxt)
19965 {
19966     if (elemDecl == NULL)
19967         return;
19968     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19969         return;
19970     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19971     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19972         /*
19973         * Adds substitution group members.
19974         */
19975         xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19976     }
19977 }
19978
19979 /**
19980  * xmlSchemaResolveModelGroupParticleReferences:
19981  * @particle:  a particle component
19982  * @ctxt:  a parser context
19983  *
19984  * Resolves references of a model group's {particles} to
19985  * model group definitions and to element declarations.
19986  */
19987 static void
19988 xmlSchemaResolveModelGroupParticleReferences(
19989     xmlSchemaParserCtxtPtr ctxt,
19990     xmlSchemaModelGroupPtr mg)
19991 {
19992     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19993     xmlSchemaQNameRefPtr ref;
19994     xmlSchemaBasicItemPtr refItem;
19995
19996     /*
19997     * URGENT TODO: Test this.
19998     */
19999     while (particle != NULL) {
20000         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20001             ((WXS_PARTICLE_TERM(particle))->type !=
20002                 XML_SCHEMA_EXTRA_QNAMEREF))
20003         {
20004             goto next_particle;
20005         }
20006         ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20007         /*
20008         * Resolve the reference.
20009         * NULL the {term} by default.
20010         */
20011         particle->children = NULL;
20012
20013         refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20014             ref->itemType, ref->name, ref->targetNamespace);
20015         if (refItem == NULL) {
20016             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20017                 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20018                 ref->targetNamespace, ref->itemType, NULL);
20019             /* TODO: remove the particle. */
20020             goto next_particle;
20021         }
20022         if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20023             if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20024                 /* TODO: remove the particle. */
20025                 goto next_particle;
20026             /*
20027             * NOTE that we will assign the model group definition
20028             * itself to the "term" of the particle. This will ease
20029             * the check for circular model group definitions. After
20030             * that the "term" will be assigned the model group of the
20031             * model group definition.
20032             */
20033             if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20034                     XML_SCHEMA_TYPE_ALL) {
20035                 /*
20036                 * SPEC cos-all-limited (1)
20037                 * SPEC cos-all-limited (1.2)
20038                 * "It appears only as the value of one or both of the
20039                 * following properties:"
20040                 * (1.1) "the {model group} property of a model group
20041                 *        definition."
20042                 * (1.2) "the {term} property of a particle [... of] the "
20043                 * {content type} of a complex type definition."
20044                 */
20045                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20046                     /* TODO: error code */
20047                     XML_SCHEMAP_COS_ALL_LIMITED,
20048                     WXS_ITEM_NODE(particle), NULL,
20049                     "A model group definition is referenced, but "
20050                     "it contains an 'all' model group, which "
20051                     "cannot be contained by model groups",
20052                     NULL, NULL);
20053                 /* TODO: remove the particle. */
20054                 goto next_particle;
20055             }
20056             particle->children = (xmlSchemaTreeItemPtr) refItem;
20057         } else {
20058             /*
20059             * TODO: Are referenced element declarations the only
20060             * other components we expect here?
20061             */
20062             particle->children = (xmlSchemaTreeItemPtr) refItem;
20063         }
20064 next_particle:
20065         particle = WXS_PTC_CAST particle->next;
20066     }
20067 }
20068
20069 static int
20070 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20071                        xmlSchemaValPtr y)
20072 {
20073     xmlSchemaTypePtr tx, ty, ptx, pty;
20074     int ret;
20075
20076     while (x != NULL) {
20077         /* Same types. */
20078         tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20079         ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20080         ptx = xmlSchemaGetPrimitiveType(tx);
20081         pty = xmlSchemaGetPrimitiveType(ty);
20082         /*
20083         * (1) if a datatype T' is ï¿½derived� by ï¿½restriction� from an
20084         * atomic datatype T then the ï¿½value space� of T' is a subset of
20085         * the ï¿½value space� of T. */
20086         /*
20087         * (2) if datatypes T' and T'' are ï¿½derived� by ï¿½restriction�
20088         * from a common atomic ancestor T then the ï¿½value space�s of T'
20089         * and T'' may overlap.
20090         */
20091         if (ptx != pty)
20092             return(0);
20093         /*
20094         * We assume computed values to be normalized, so do a fast
20095         * string comparison for string based types.
20096         */
20097         if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20098             WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20099             if (! xmlStrEqual(
20100                 xmlSchemaValueGetAsString(x),
20101                 xmlSchemaValueGetAsString(y)))
20102                 return (0);
20103         } else {
20104             ret = xmlSchemaCompareValuesWhtsp(
20105                 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20106                 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20107             if (ret == -2)
20108                 return(-1);
20109             if (ret != 0)
20110                 return(0);
20111         }
20112         /*
20113         * Lists.
20114         */
20115         x = xmlSchemaValueGetNext(x);
20116         if (x != NULL) {
20117             y = xmlSchemaValueGetNext(y);
20118             if (y == NULL)
20119                 return (0);
20120         } else if (xmlSchemaValueGetNext(y) != NULL)
20121             return (0);
20122         else
20123             return (1);
20124     }
20125     return (0);
20126 }
20127
20128 /**
20129  * xmlSchemaResolveAttrUseReferences:
20130  * @item:  an attribute use
20131  * @ctxt:  a parser context
20132  *
20133  * Resolves the referenced attribute declaration.
20134  */
20135 static int
20136 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20137                                   xmlSchemaParserCtxtPtr ctxt)
20138 {
20139     if ((ctxt == NULL) || (ause == NULL))
20140         return(-1);
20141     if ((ause->attrDecl == NULL) ||
20142         (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20143         return(0);
20144
20145     {
20146         xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20147
20148         /*
20149         * TODO: Evaluate, what errors could occur if the declaration is not
20150         * found.
20151         */
20152         ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20153             ref->name, ref->targetNamespace);
20154         if (ause->attrDecl == NULL) {
20155             xmlSchemaPResCompAttrErr(ctxt,
20156                 XML_SCHEMAP_SRC_RESOLVE,
20157                 WXS_BASIC_CAST ause, ause->node,
20158                 "ref", ref->name, ref->targetNamespace,
20159                 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20160             return(ctxt->err);;
20161         }
20162     }
20163     return(0);
20164 }
20165
20166 /**
20167  * xmlSchemaCheckAttrUsePropsCorrect:
20168  * @ctxt:  a parser context
20169  * @use:  an attribute use
20170  *
20171  * Schema Component Constraint:
20172  * Attribute Use Correct (au-props-correct)
20173  *
20174  */
20175 static int
20176 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20177                              xmlSchemaAttributeUsePtr use)
20178 {
20179     if ((ctxt == NULL) || (use == NULL))
20180         return(-1);
20181     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20182         ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20183         return(0);
20184
20185     /*
20186     * SPEC au-props-correct (1)
20187     * "The values of the properties of an attribute use must be as
20188     * described in the property tableau in The Attribute Use Schema
20189     * Component (�3.5.1), modulo the impact of Missing
20190     * Sub-components (�5.3)."
20191     */
20192
20193     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20194         ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20195         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20196     {
20197         xmlSchemaPCustomErr(ctxt,
20198             XML_SCHEMAP_AU_PROPS_CORRECT_2,
20199             WXS_BASIC_CAST use, NULL,
20200             "The attribute declaration has a 'fixed' value constraint "
20201             ", thus the attribute use must also have a 'fixed' value "
20202             "constraint",
20203             NULL);
20204         return(ctxt->err);
20205     }
20206     /*
20207     * Compute and check the value constraint's value.
20208     */
20209     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20210         int ret;
20211         /*
20212         * TODO: The spec seems to be missing a check of the
20213         * value constraint of the attribute use. We will do it here.
20214         */
20215         /*
20216         * SPEC a-props-correct (3)
20217         */
20218         if (xmlSchemaIsDerivedFromBuiltInType(
20219             WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20220         {
20221             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20222                 XML_SCHEMAP_AU_PROPS_CORRECT,
20223                 NULL, WXS_BASIC_CAST use,
20224                 "Value constraints are not allowed if the type definition "
20225                 "is or is derived from xs:ID",
20226                 NULL, NULL);
20227             return(ctxt->err);
20228         }
20229
20230         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20231             use->node, WXS_ATTRUSE_TYPEDEF(use),
20232             use->defValue, &(use->defVal),
20233             1, 1, 0);
20234         if (ret != 0) {
20235             if (ret < 0) {
20236                 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20237                     "calling xmlSchemaVCheckCVCSimpleType()");
20238                 return(-1);
20239             }
20240             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20241                 XML_SCHEMAP_AU_PROPS_CORRECT,
20242                 NULL, WXS_BASIC_CAST use,
20243                 "The value of the value constraint is not valid",
20244                 NULL, NULL);
20245             return(ctxt->err);
20246         }
20247     }
20248     /*
20249     * SPEC au-props-correct (2)
20250     * "If the {attribute declaration} has a fixed
20251     * {value constraint}, then if the attribute use itself has a
20252     * {value constraint}, it must also be fixed and its value must match
20253     * that of the {attribute declaration}'s {value constraint}."
20254     */
20255     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20256         (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20257     {
20258         if (! xmlSchemaAreValuesEqual(use->defVal,
20259                 (WXS_ATTRUSE_DECL(use))->defVal))
20260         {
20261             xmlSchemaPCustomErr(ctxt,
20262                 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20263                 WXS_BASIC_CAST use, NULL,
20264                 "The 'fixed' value constraint of the attribute use "
20265                 "must match the attribute declaration's value "
20266                 "constraint '%s'",
20267                 (WXS_ATTRUSE_DECL(use))->defValue);
20268         }
20269         return(ctxt->err);
20270     }
20271     return(0);
20272 }
20273
20274
20275
20276
20277 /**
20278  * xmlSchemaResolveAttrTypeReferences:
20279  * @item:  an attribute declaration
20280  * @ctxt:  a parser context
20281  *
20282  * Resolves the referenced type definition component.
20283  */
20284 static int
20285 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20286                                    xmlSchemaParserCtxtPtr ctxt)
20287 {
20288     /*
20289     * The simple type definition corresponding to the <simpleType> element
20290     * information item in the [children], if present, otherwise the simple
20291     * type definition ï¿½resolved� to by the ï¿½actual value� of the type
20292     * [attribute], if present, otherwise the ï¿½simple ur-type definition�.
20293     */
20294     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20295         return(0);
20296     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20297     if (item->subtypes != NULL)
20298         return(0);
20299     if (item->typeName != NULL) {
20300         xmlSchemaTypePtr type;
20301
20302         type = xmlSchemaGetType(ctxt->schema, item->typeName,
20303             item->typeNs);
20304         if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20305             xmlSchemaPResCompAttrErr(ctxt,
20306                 XML_SCHEMAP_SRC_RESOLVE,
20307                 WXS_BASIC_CAST item, item->node,
20308                 "type", item->typeName, item->typeNs,
20309                 XML_SCHEMA_TYPE_SIMPLE, NULL);
20310             return(ctxt->err);
20311         } else
20312             item->subtypes = type;
20313
20314     } else {
20315         /*
20316         * The type defaults to the xs:anySimpleType.
20317         */
20318         item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20319     }
20320     return(0);
20321 }
20322
20323 /**
20324  * xmlSchemaResolveIDCKeyReferences:
20325  * @idc:  the identity-constraint definition
20326  * @ctxt:  the schema parser context
20327  * @name:  the attribute name
20328  *
20329  * Resolve keyRef references to key/unique IDCs.
20330  * Schema Component Constraint:
20331  *   Identity-constraint Definition Properties Correct (c-props-correct)
20332  */
20333 static int
20334 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20335                           xmlSchemaParserCtxtPtr pctxt)
20336 {
20337     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20338         return(0);
20339     if (idc->ref->name != NULL) {
20340         idc->ref->item = (xmlSchemaBasicItemPtr)
20341             xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20342                 idc->ref->targetNamespace);
20343         if (idc->ref->item == NULL) {
20344             /*
20345             * TODO: It is actually not an error to fail to resolve
20346             * at this stage. BUT we need to be that strict!
20347             */
20348             xmlSchemaPResCompAttrErr(pctxt,
20349                 XML_SCHEMAP_SRC_RESOLVE,
20350                 WXS_BASIC_CAST idc, idc->node,
20351                 "refer", idc->ref->name,
20352                 idc->ref->targetNamespace,
20353                 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20354             return(pctxt->err);
20355         } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20356             /*
20357             * SPEC c-props-correct (1)
20358             */
20359             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20360                 XML_SCHEMAP_C_PROPS_CORRECT,
20361                 NULL, WXS_BASIC_CAST idc,
20362                 "The keyref references a keyref",
20363                 NULL, NULL);
20364             idc->ref->item = NULL;
20365             return(pctxt->err);
20366         } else {
20367             if (idc->nbFields !=
20368                 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20369                 xmlChar *str = NULL;
20370                 xmlSchemaIDCPtr refer;
20371
20372                 refer = (xmlSchemaIDCPtr) idc->ref->item;
20373                 /*
20374                 * SPEC c-props-correct(2)
20375                 * "If the {identity-constraint category} is keyref,
20376                 * the cardinality of the {fields} must equal that of
20377                 * the {fields} of the {referenced key}.
20378                 */
20379                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20380                     XML_SCHEMAP_C_PROPS_CORRECT,
20381                     NULL, WXS_BASIC_CAST idc,
20382                     "The cardinality of the keyref differs from the "
20383                     "cardinality of the referenced key/unique '%s'",
20384                     xmlSchemaFormatQName(&str, refer->targetNamespace,
20385                         refer->name),
20386                     NULL);
20387                 FREE_AND_NULL(str)
20388                 return(pctxt->err);
20389             }
20390         }
20391     }
20392     return(0);
20393 }
20394
20395 static int
20396 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20397                                        xmlSchemaParserCtxtPtr pctxt)
20398 {
20399     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20400         prohib->targetNamespace) == NULL) {
20401
20402         xmlSchemaPResCompAttrErr(pctxt,
20403             XML_SCHEMAP_SRC_RESOLVE,
20404             NULL, prohib->node,
20405             "ref", prohib->name, prohib->targetNamespace,
20406             XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20407         return(XML_SCHEMAP_SRC_RESOLVE);
20408     }
20409     return(0);
20410 }
20411
20412 #define WXS_REDEFINED_TYPE(c) \
20413 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20414
20415 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20416 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20417
20418 #define WXS_REDEFINED_ATTR_GROUP(c) \
20419 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20420
20421 static int
20422 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20423 {
20424     int err = 0;
20425     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20426     xmlSchemaBasicItemPtr prev, item;
20427     int wasRedefined;
20428
20429     if (redef == NULL)
20430         return(0);
20431
20432     do {
20433         item = redef->item;
20434         /*
20435         * First try to locate the redefined component in the
20436         * schema graph starting with the redefined schema.
20437         * NOTE: According to this schema bug entry:
20438         *   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20439         *   it's not clear if the referenced component needs to originate
20440         *   from the <redefine>d schema _document_ or the schema; the latter
20441         *   would include all imported and included sub-schemas of the
20442         *   <redefine>d schema. Currenlty we latter approach is used.
20443         *   SUPPLEMENT: It seems that the WG moves towards the latter
20444         *   approach, so we are doing it right.
20445         *
20446         */
20447         prev = xmlSchemaFindRedefCompInGraph(
20448             redef->targetBucket, item->type,
20449             redef->refName, redef->refTargetNs);
20450         if (prev == NULL) {
20451             xmlChar *str = NULL;
20452             xmlNodePtr node;
20453
20454             /*
20455             * SPEC src-redefine:
20456             * (6.2.1) "The ï¿½actual value� of its own name attribute plus
20457             * target namespace must successfully ï¿½resolve� to a model
20458             * group definition in I."
20459             * (7.2.1) "The ï¿½actual value� of its own name attribute plus
20460             * target namespace must successfully ï¿½resolve� to an attribute
20461             * group definition in I."
20462
20463             *
20464             * Note that, if we are redefining with the use of references
20465             * to components, the spec assumes the src-resolve to be used;
20466             * but this won't assure that we search only *inside* the
20467             * redefined schema.
20468             */
20469             if (redef->reference)
20470                 node = WXS_ITEM_NODE(redef->reference);
20471             else
20472                 node = WXS_ITEM_NODE(item);
20473             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20474                 /*
20475                 * TODO: error code.
20476                 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20477                 * reference kind.
20478                 */
20479                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20480                 "The %s '%s' to be redefined could not be found in "
20481                 "the redefined schema",
20482                 WXS_ITEM_TYPE_NAME(item),
20483                 xmlSchemaFormatQName(&str, redef->refTargetNs,
20484                     redef->refName));
20485             FREE_AND_NULL(str);
20486             err = pctxt->err;
20487             redef = redef->next;
20488             continue;
20489         }
20490         /*
20491         * TODO: Obtaining and setting the redefinition state is really
20492         * clumsy.
20493         */
20494         wasRedefined = 0;
20495         switch (item->type) {
20496             case XML_SCHEMA_TYPE_COMPLEX:
20497             case XML_SCHEMA_TYPE_SIMPLE:
20498                 if ((WXS_TYPE_CAST prev)->flags &
20499                     XML_SCHEMAS_TYPE_REDEFINED)
20500                 {
20501                     wasRedefined = 1;
20502                     break;
20503                 }
20504                 /* Mark it as redefined. */
20505                 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20506                 /*
20507                 * Assign the redefined type to the
20508                 * base type of the redefining type.
20509                 * TODO: How
20510                 */
20511                 ((xmlSchemaTypePtr) item)->baseType =
20512                     (xmlSchemaTypePtr) prev;
20513                 break;
20514             case XML_SCHEMA_TYPE_GROUP:
20515                 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20516                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20517                 {
20518                     wasRedefined = 1;
20519                     break;
20520                 }
20521                 /* Mark it as redefined. */
20522                 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20523                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20524                 if (redef->reference != NULL) {
20525                     /*
20526                     * Overwrite the QName-reference with the
20527                     * referenced model group def.
20528                     */
20529                     (WXS_PTC_CAST redef->reference)->children =
20530                         WXS_TREE_CAST prev;
20531                 }
20532                 redef->target = prev;
20533                 break;
20534             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20535                 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20536                     XML_SCHEMAS_ATTRGROUP_REDEFINED)
20537                 {
20538                     wasRedefined = 1;
20539                     break;
20540                 }
20541                 (WXS_ATTR_GROUP_CAST prev)->flags |=
20542                     XML_SCHEMAS_ATTRGROUP_REDEFINED;
20543                 if (redef->reference != NULL) {
20544                     /*
20545                     * Assign the redefined attribute group to the
20546                     * QName-reference component.
20547                     * This is the easy case, since we will just
20548                     * expand the redefined group.
20549                     */
20550                     (WXS_QNAME_CAST redef->reference)->item = prev;
20551                     redef->target = NULL;
20552                 } else {
20553                     /*
20554                     * This is the complicated case: we need
20555                     * to apply src-redefine (7.2.2) at a later
20556                     * stage, i.e. when attribute group references
20557                     * have beed expanded and simple types have
20558                     * beed fixed.
20559                     */
20560                     redef->target = prev;
20561                 }
20562                 break;
20563             default:
20564                 PERROR_INT("xmlSchemaResolveRedefReferences",
20565                     "Unexpected redefined component type");
20566                 return(-1);
20567         }
20568         if (wasRedefined) {
20569             xmlChar *str = NULL;
20570             xmlNodePtr node;
20571
20572             if (redef->reference)
20573                 node = WXS_ITEM_NODE(redef->reference);
20574             else
20575                 node = WXS_ITEM_NODE(redef->item);
20576
20577             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20578                 /* TODO: error code. */
20579                 XML_SCHEMAP_SRC_REDEFINE,
20580                 node, NULL,
20581                 "The referenced %s was already redefined. Multiple "
20582                 "redefinition of the same component is not supported",
20583                 xmlSchemaGetComponentDesignation(&str, prev),
20584                 NULL);
20585             FREE_AND_NULL(str)
20586             err = pctxt->err;
20587             redef = redef->next;
20588             continue;
20589         }
20590         redef = redef->next;
20591     } while (redef != NULL);
20592
20593     return(err);
20594 }
20595
20596 static int
20597 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20598 {
20599     int err = 0;
20600     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20601     xmlSchemaBasicItemPtr item;
20602
20603     if (redef == NULL)
20604         return(0);
20605
20606     do {
20607         if (redef->target == NULL) {
20608             redef = redef->next;
20609             continue;
20610         }
20611         item = redef->item;
20612
20613         switch (item->type) {
20614             case XML_SCHEMA_TYPE_SIMPLE:
20615             case XML_SCHEMA_TYPE_COMPLEX:
20616                 /*
20617                 * Since the spec wants the {name} of the redefined
20618                 * type to be 'absent', we'll NULL it.
20619                 */
20620                 (WXS_TYPE_CAST redef->target)->name = NULL;
20621
20622                 /*
20623                 * TODO: Seems like there's nothing more to do. The normal
20624                 * inheritance mechanism is used. But not 100% sure.
20625                 */
20626                 break;
20627             case XML_SCHEMA_TYPE_GROUP:
20628                 /*
20629                 * URGENT TODO:
20630                 * SPEC src-redefine:
20631                 * (6.2.2) "The {model group} of the model group definition
20632                 * which corresponds to it per XML Representation of Model
20633                 * Group Definition Schema Components (�3.7.2) must be a
20634                 * ï¿½valid restriction� of the {model group} of that model
20635                 * group definition in I, as defined in Particle Valid
20636                 * (Restriction) (�3.9.6)."
20637                 */
20638                 break;
20639             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20640                 /*
20641                 * SPEC src-redefine:
20642                 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20643                 * the attribute group definition which corresponds to it
20644                 * per XML Representation of Attribute Group Definition Schema
20645                 * Components (�3.6.2) must be ï¿½valid restrictions� of the
20646                 * {attribute uses} and {attribute wildcard} of that attribute
20647                 * group definition in I, as defined in clause 2, clause 3 and
20648                 * clause 4 of Derivation Valid (Restriction, Complex)
20649                 * (�3.4.6) (where references to the base type definition are
20650                 * understood as references to the attribute group definition
20651                 * in I)."
20652                 */
20653                 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20654                     XML_SCHEMA_ACTION_REDEFINE,
20655                     item, redef->target,
20656                     (WXS_ATTR_GROUP_CAST item)->attrUses,
20657                     (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20658                     (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20659                     (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20660                 if (err == -1)
20661                     return(-1);
20662                 break;
20663             default:
20664                 break;
20665         }
20666         redef = redef->next;
20667     } while (redef != NULL);
20668     return(0);
20669 }
20670
20671
20672 static int
20673 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20674                        xmlSchemaBucketPtr bucket)
20675 {
20676     xmlSchemaBasicItemPtr item;
20677     int err;
20678     xmlHashTablePtr *table;
20679     const xmlChar *name;
20680     int i;
20681
20682 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20683     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20684         table = &(WXS_IMPBUCKET((c))->schema->slot); \
20685     else \
20686         table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20687
20688     /*
20689     * Add global components to the schema's hash tables.
20690     * This is the place where duplicate components will be
20691     * detected.
20692     * TODO: I think normally we should support imports of the
20693     *   same namespace from multiple locations. We don't do currently,
20694     *   but if we do then according to:
20695     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20696     *   we would need, if imported directly, to import redefined
20697     *   components as well to be able to catch clashing components.
20698     *   (I hope I'll still know what this means after some months :-()
20699     */
20700     if (bucket == NULL)
20701         return(-1);
20702     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20703         return(0);
20704     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20705
20706     for (i = 0; i < bucket->globals->nbItems; i++) {
20707         item = bucket->globals->items[i];
20708         table = NULL;
20709         switch (item->type) {
20710             case XML_SCHEMA_TYPE_COMPLEX:
20711             case XML_SCHEMA_TYPE_SIMPLE:
20712                 if (WXS_REDEFINED_TYPE(item))
20713                     continue;
20714                 name = (WXS_TYPE_CAST item)->name;
20715                 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20716                 break;
20717             case XML_SCHEMA_TYPE_ELEMENT:
20718                 name = (WXS_ELEM_CAST item)->name;
20719                 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20720                 break;
20721             case XML_SCHEMA_TYPE_ATTRIBUTE:
20722                 name = (WXS_ATTR_CAST item)->name;
20723                 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20724                 break;
20725             case XML_SCHEMA_TYPE_GROUP:
20726                 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20727                     continue;
20728                 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20729                 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20730                 break;
20731             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20732                 if (WXS_REDEFINED_ATTR_GROUP(item))
20733                     continue;
20734                 name = (WXS_ATTR_GROUP_CAST item)->name;
20735                 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20736                 break;
20737             case XML_SCHEMA_TYPE_IDC_KEY:
20738             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20739             case XML_SCHEMA_TYPE_IDC_KEYREF:
20740                 name = (WXS_IDC_CAST item)->name;
20741                 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20742                 break;
20743             case XML_SCHEMA_TYPE_NOTATION:
20744                 name = ((xmlSchemaNotationPtr) item)->name;
20745                 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20746                 break;
20747             default:
20748                 PERROR_INT("xmlSchemaAddComponents",
20749                     "Unexpected global component type");
20750                 continue;
20751         }
20752         if (*table == NULL) {
20753             *table = xmlHashCreateDict(10, pctxt->dict);
20754             if (*table == NULL) {
20755                 PERROR_INT("xmlSchemaAddComponents",
20756                     "failed to create a component hash table");
20757                 return(-1);
20758             }
20759         }
20760         err = xmlHashAddEntry(*table, name, item);
20761         if (err != 0) {
20762             xmlChar *str = NULL;
20763
20764             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20765                 XML_SCHEMAP_REDEFINED_TYPE,
20766                 WXS_ITEM_NODE(item),
20767                 WXS_BASIC_CAST item,
20768                 "A global %s '%s' does already exist",
20769                 WXS_ITEM_TYPE_NAME(item),
20770                 xmlSchemaGetComponentQName(&str, item));
20771             FREE_AND_NULL(str);
20772         }
20773     }
20774     /*
20775     * Process imported/included schemas.
20776     */
20777     if (bucket->relations != NULL) {
20778         xmlSchemaSchemaRelationPtr rel = bucket->relations;
20779         do {
20780             if ((rel->bucket != NULL) &&
20781                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20782                 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20783                     return(-1);
20784             }
20785             rel = rel->next;
20786         } while (rel != NULL);
20787     }
20788     return(0);
20789 }
20790
20791 static int
20792 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20793                          xmlSchemaBucketPtr rootBucket)
20794 {
20795     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20796     xmlSchemaTreeItemPtr item, *items;
20797     int nbItems, i, ret = 0;
20798     xmlSchemaBucketPtr oldbucket = con->bucket;
20799     xmlSchemaElementPtr elemDecl;
20800
20801 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20802
20803     if ((con->pending == NULL) ||
20804         (con->pending->nbItems == 0))
20805         return(0);
20806
20807     /*
20808     * Since xmlSchemaFixupComplexType() will create new particles
20809     * (local components), and those particle components need a bucket
20810     * on the constructor, we'll assure here that the constructor has
20811     * a bucket.
20812     * TODO: Think about storing locals _only_ on the main bucket.
20813     */
20814     if (con->bucket == NULL)
20815         con->bucket = rootBucket;
20816
20817     /* TODO:
20818     * SPEC (src-redefine):
20819     * (6.2) "If it has no such self-reference, then all of the
20820     * following must be true:"
20821
20822     * (6.2.2) The {model group} of the model group definition which
20823     * corresponds to it per XML Representation of Model Group
20824     * Definition Schema Components (�3.7.2) must be a ï¿½valid
20825     * restriction� of the {model group} of that model group definition
20826     * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20827     */
20828     xmlSchemaCheckSRCRedefineFirst(pctxt);
20829
20830     /*
20831     * Add global components to the schemata's hash tables.
20832     */
20833     xmlSchemaAddComponents(pctxt, rootBucket);
20834
20835     pctxt->ctxtType = NULL;
20836     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20837     nbItems = con->pending->nbItems;
20838     /*
20839     * Now that we have parsed *all* the schema document(s) and converted
20840     * them to schema components, we can resolve references, apply component
20841     * constraints, create the FSA from the content model, etc.
20842     */
20843     /*
20844     * Resolve references of..
20845     *
20846     * 1. element declarations:
20847     *   - the type definition
20848     *   - the substitution group affiliation
20849     * 2. simple/complex types:
20850     *   - the base type definition
20851     *   - the memberTypes of union types
20852     *   - the itemType of list types
20853     * 3. attributes declarations and attribute uses:
20854     *   - the type definition
20855     *   - if an attribute use, then the attribute declaration
20856     * 4. attribute group references:
20857     *   - the attribute group definition
20858     * 5. particles:
20859     *   - the term of the particle (e.g. a model group)
20860     * 6. IDC key-references:
20861     *   - the referenced IDC 'key' or 'unique' definition
20862     * 7. Attribute prohibitions which had a "ref" attribute.
20863     */
20864     for (i = 0; i < nbItems; i++) {
20865         item = items[i];
20866         switch (item->type) {
20867             case XML_SCHEMA_TYPE_ELEMENT:
20868                 xmlSchemaResolveElementReferences(
20869                     (xmlSchemaElementPtr) item, pctxt);
20870                 FIXHFAILURE;
20871                 break;
20872             case XML_SCHEMA_TYPE_COMPLEX:
20873             case XML_SCHEMA_TYPE_SIMPLE:
20874                 xmlSchemaResolveTypeReferences(
20875                     (xmlSchemaTypePtr) item, pctxt);
20876                 FIXHFAILURE;
20877                 break;
20878             case XML_SCHEMA_TYPE_ATTRIBUTE:
20879                 xmlSchemaResolveAttrTypeReferences(
20880                     (xmlSchemaAttributePtr) item, pctxt);
20881                 FIXHFAILURE;
20882                 break;
20883             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20884                 xmlSchemaResolveAttrUseReferences(
20885                     (xmlSchemaAttributeUsePtr) item, pctxt);
20886                 FIXHFAILURE;
20887                 break;
20888             case XML_SCHEMA_EXTRA_QNAMEREF:
20889                 if ((WXS_QNAME_CAST item)->itemType ==
20890                     XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20891                 {
20892                     xmlSchemaResolveAttrGroupReferences(
20893                         WXS_QNAME_CAST item, pctxt);
20894                 }
20895                 FIXHFAILURE;
20896                 break;
20897             case XML_SCHEMA_TYPE_SEQUENCE:
20898             case XML_SCHEMA_TYPE_CHOICE:
20899             case XML_SCHEMA_TYPE_ALL:
20900                 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20901                     WXS_MODEL_GROUP_CAST item);
20902                 FIXHFAILURE;
20903                 break;
20904             case XML_SCHEMA_TYPE_IDC_KEY:
20905             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20906             case XML_SCHEMA_TYPE_IDC_KEYREF:
20907                 xmlSchemaResolveIDCKeyReferences(
20908                     (xmlSchemaIDCPtr) item, pctxt);
20909                 FIXHFAILURE;
20910                 break;
20911             case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20912                 /*
20913                 * Handle attribue prohibition which had a
20914                 * "ref" attribute.
20915                 */
20916                 xmlSchemaResolveAttrUseProhibReferences(
20917                     WXS_ATTR_PROHIB_CAST item, pctxt);
20918                 FIXHFAILURE;
20919                 break;
20920             default:
20921                 break;
20922         }
20923     }
20924     if (pctxt->nberrors != 0)
20925         goto exit_error;
20926
20927     /*
20928     * Now that all references are resolved we
20929     * can check for circularity of...
20930     * 1. the base axis of type definitions
20931     * 2. nested model group definitions
20932     * 3. nested attribute group definitions
20933     * TODO: check for circual substitution groups.
20934     */
20935     for (i = 0; i < nbItems; i++) {
20936         item = items[i];
20937         /*
20938         * Let's better stop on the first error here.
20939         */
20940         switch (item->type) {
20941             case XML_SCHEMA_TYPE_COMPLEX:
20942             case XML_SCHEMA_TYPE_SIMPLE:
20943                 xmlSchemaCheckTypeDefCircular(
20944                     (xmlSchemaTypePtr) item, pctxt);
20945                 FIXHFAILURE;
20946                 if (pctxt->nberrors != 0)
20947                     goto exit_error;
20948                 break;
20949             case XML_SCHEMA_TYPE_GROUP:
20950                 xmlSchemaCheckGroupDefCircular(
20951                     (xmlSchemaModelGroupDefPtr) item, pctxt);
20952                 FIXHFAILURE;
20953                 if (pctxt->nberrors != 0)
20954                     goto exit_error;
20955                 break;
20956             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20957                 xmlSchemaCheckAttrGroupCircular(
20958                     (xmlSchemaAttributeGroupPtr) item, pctxt);
20959                 FIXHFAILURE;
20960                 if (pctxt->nberrors != 0)
20961                     goto exit_error;
20962                 break;
20963             default:
20964                 break;
20965         }
20966     }
20967     if (pctxt->nberrors != 0)
20968         goto exit_error;
20969     /*
20970     * Model group definition references:
20971     * Such a reference is reflected by a particle at the component
20972     * level. Until now the 'term' of such particles pointed
20973     * to the model group definition; this was done, in order to
20974     * ease circularity checks. Now we need to set the 'term' of
20975     * such particles to the model group of the model group definition.
20976     */
20977     for (i = 0; i < nbItems; i++) {
20978         item = items[i];
20979         switch (item->type) {
20980             case XML_SCHEMA_TYPE_SEQUENCE:
20981             case XML_SCHEMA_TYPE_CHOICE:
20982                 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20983                     WXS_MODEL_GROUP_CAST item);
20984                 break;
20985             default:
20986                 break;
20987         }
20988     }
20989     if (pctxt->nberrors != 0)
20990         goto exit_error;
20991     /*
20992     * Expand attribute group references of attribute group definitions.
20993     */
20994     for (i = 0; i < nbItems; i++) {
20995         item = items[i];
20996         switch (item->type) {
20997             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20998                 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20999                     WXS_ATTR_GROUP_HAS_REFS(item))
21000                 {
21001                     xmlSchemaAttributeGroupExpandRefs(pctxt,
21002                         WXS_ATTR_GROUP_CAST item);
21003                     FIXHFAILURE;
21004                 }
21005                 break;
21006             default:
21007                 break;
21008         }
21009     }
21010     if (pctxt->nberrors != 0)
21011         goto exit_error;
21012     /*
21013     * First compute the variety of simple types. This is needed as
21014     * a seperate step, since otherwise we won't be able to detect
21015     * circular union types in all cases.
21016     */
21017     for (i = 0; i < nbItems; i++) {
21018         item = items[i];
21019         switch (item->type) {
21020             case XML_SCHEMA_TYPE_SIMPLE:
21021                 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21022                     xmlSchemaFixupSimpleTypeStageOne(pctxt,
21023                         (xmlSchemaTypePtr) item);
21024                     FIXHFAILURE;
21025                 }
21026                 break;
21027             default:
21028                 break;
21029         }
21030     }
21031     if (pctxt->nberrors != 0)
21032         goto exit_error;
21033     /*
21034     * Detect circular union types. Note that this needs the variety to
21035     * be already computed.
21036     */
21037     for (i = 0; i < nbItems; i++) {
21038         item = items[i];
21039         switch (item->type) {
21040             case XML_SCHEMA_TYPE_SIMPLE:
21041                 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21042                     xmlSchemaCheckUnionTypeDefCircular(pctxt,
21043                         (xmlSchemaTypePtr) item);
21044                     FIXHFAILURE;
21045                 }
21046                 break;
21047             default:
21048                 break;
21049         }
21050     }
21051     if (pctxt->nberrors != 0)
21052         goto exit_error;
21053
21054     /*
21055     * Do the complete type fixup for simple types.
21056     */
21057     for (i = 0; i < nbItems; i++) {
21058         item = items[i];
21059         switch (item->type) {
21060             case XML_SCHEMA_TYPE_SIMPLE:
21061                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21062                     xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21063                     FIXHFAILURE;
21064                 }
21065                 break;
21066             default:
21067                 break;
21068         }
21069     }
21070     if (pctxt->nberrors != 0)
21071         goto exit_error;
21072     /*
21073     * At this point we need build and check all simple types.
21074     */
21075     /*
21076     * Apply contraints for attribute declarations.
21077     */
21078     for (i = 0; i < nbItems; i++) {
21079         item = items[i];
21080         switch (item->type) {
21081             case XML_SCHEMA_TYPE_ATTRIBUTE:
21082                 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21083                 FIXHFAILURE;
21084                 break;
21085             default:
21086                 break;
21087         }
21088     }
21089     if (pctxt->nberrors != 0)
21090         goto exit_error;
21091     /*
21092     * Apply constraints for attribute uses.
21093     */
21094     for (i = 0; i < nbItems; i++) {
21095         item = items[i];
21096         switch (item->type) {
21097             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21098                 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21099                     xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21100                         WXS_ATTR_USE_CAST item);
21101                     FIXHFAILURE;
21102                 }
21103                 break;
21104             default:
21105                 break;
21106         }
21107     }
21108     if (pctxt->nberrors != 0)
21109         goto exit_error;
21110
21111     /*
21112     * Apply constraints for attribute group definitions.
21113     */
21114     for (i = 0; i < nbItems; i++) {
21115         item = items[i];
21116         switch (item->type) {
21117         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21118             if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21119                 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21120             {
21121                 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21122                 FIXHFAILURE;
21123             }
21124             break;
21125         default:
21126             break;
21127         }
21128     }
21129     if (pctxt->nberrors != 0)
21130         goto exit_error;
21131
21132     /*
21133     * Apply constraints for redefinitions.
21134     */
21135     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21136         xmlSchemaCheckSRCRedefineSecond(pctxt);
21137     if (pctxt->nberrors != 0)
21138         goto exit_error;
21139
21140     /*
21141     * Complex types are builded and checked.
21142     */
21143     for (i = 0; i < nbItems; i++) {
21144         item = con->pending->items[i];
21145         switch (item->type) {
21146             case XML_SCHEMA_TYPE_COMPLEX:
21147                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21148                     xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21149                     FIXHFAILURE;
21150                 }
21151                 break;
21152             default:
21153                 break;
21154         }
21155     }
21156     if (pctxt->nberrors != 0)
21157         goto exit_error;
21158
21159     /*
21160     * The list could have changed, since xmlSchemaFixupComplexType()
21161     * will create particles and model groups in some cases.
21162     */
21163     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21164     nbItems = con->pending->nbItems;
21165
21166     /*
21167     * Apply some constraints for element declarations.
21168     */
21169     for (i = 0; i < nbItems; i++) {
21170         item = items[i];
21171         switch (item->type) {
21172             case XML_SCHEMA_TYPE_ELEMENT:
21173                 elemDecl = (xmlSchemaElementPtr) item;
21174
21175                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21176                 {
21177                     xmlSchemaCheckElementDeclComponent(
21178                         (xmlSchemaElementPtr) elemDecl, pctxt);
21179                     FIXHFAILURE;
21180                 }
21181
21182 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21183                 /*
21184                 * Schema Component Constraint: Element Declarations Consistent
21185                 * Apply this constraint to local types of element declarations.
21186                 */
21187                 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21188                     (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21189                     (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21190                 {
21191                     xmlSchemaCheckElementDeclConsistent(pctxt,
21192                         WXS_BASIC_CAST elemDecl,
21193                         WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21194                         NULL, NULL, 0);
21195                 }
21196 #endif
21197                 break;
21198             default:
21199                 break;
21200         }
21201     }
21202     if (pctxt->nberrors != 0)
21203         goto exit_error;
21204
21205     /*
21206     * Finally we can build the automaton from the content model of
21207     * complex types.
21208     */
21209
21210     for (i = 0; i < nbItems; i++) {
21211         item = items[i];
21212         switch (item->type) {
21213             case XML_SCHEMA_TYPE_COMPLEX:
21214                 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21215                 /* FIXHFAILURE; */
21216                 break;
21217             default:
21218                 break;
21219         }
21220     }
21221     if (pctxt->nberrors != 0)
21222         goto exit_error;
21223     /*
21224     * URGENT TODO: cos-element-consistent
21225     */
21226     goto exit;
21227
21228 exit_error:
21229     ret = pctxt->err;
21230     goto exit;
21231
21232 exit_failure:
21233     ret = -1;
21234
21235 exit:
21236     /*
21237     * Reset the constructor. This is needed for XSI acquisition, since
21238     * those items will be processed over and over again for every XSI
21239     * if not cleared here.
21240     */
21241     con->bucket = oldbucket;
21242     con->pending->nbItems = 0;
21243     if (con->substGroups != NULL) {
21244         xmlHashFree(con->substGroups,
21245             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21246         con->substGroups = NULL;
21247     }
21248     if (con->redefs != NULL) {
21249         xmlSchemaRedefListFree(con->redefs);
21250         con->redefs = NULL;
21251     }
21252     return(ret);
21253 }
21254 /**
21255  * xmlSchemaParse:
21256  * @ctxt:  a schema validation context
21257  *
21258  * parse a schema definition resource and build an internal
21259  * XML Shema struture which can be used to validate instances.
21260  *
21261  * Returns the internal XML Schema structure built from the resource or
21262  *         NULL in case of error
21263  */
21264 xmlSchemaPtr
21265 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21266 {
21267     xmlSchemaPtr mainSchema = NULL;
21268     xmlSchemaBucketPtr bucket = NULL;
21269     int res;
21270
21271     /*
21272     * This one is used if the schema to be parsed was specified via
21273     * the API; i.e. not automatically by the validated instance document.
21274     */
21275
21276     xmlSchemaInitTypes();
21277
21278     if (ctxt == NULL)
21279         return (NULL);
21280
21281     /* TODO: Init the context. Is this all we need?*/
21282     ctxt->nberrors = 0;
21283     ctxt->err = 0;
21284     ctxt->counter = 0;
21285
21286     /* Create the *main* schema. */
21287     mainSchema = xmlSchemaNewSchema(ctxt);
21288     if (mainSchema == NULL)
21289         goto exit_failure;
21290     /*
21291     * Create the schema constructor.
21292     */
21293     if (ctxt->constructor == NULL) {
21294         ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21295         if (ctxt->constructor == NULL)
21296             return(NULL);
21297         /* Take ownership of the constructor to be able to free it. */
21298         ctxt->ownsConstructor = 1;
21299     }
21300     ctxt->constructor->mainSchema = mainSchema;
21301     /*
21302     * Locate and add the schema document.
21303     */
21304     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21305         ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21306         NULL, NULL, &bucket);
21307     if (res == -1)
21308         goto exit_failure;
21309     if (res != 0)
21310         goto exit;
21311
21312     if (bucket == NULL) {
21313         /* TODO: Error code, actually we failed to *locate* the schema. */
21314         if (ctxt->URL)
21315             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21316                 NULL, NULL,
21317                 "Failed to locate the main schema resource at '%s'",
21318                 ctxt->URL, NULL);
21319         else
21320             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21321                 NULL, NULL,
21322                 "Failed to locate the main schema resource",
21323                     NULL, NULL);
21324         goto exit;
21325     }
21326     /* Then do the parsing for good. */
21327     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21328         goto exit_failure;
21329     if (ctxt->nberrors != 0)
21330         goto exit;
21331
21332     mainSchema->doc = bucket->doc;
21333     mainSchema->preserve = ctxt->preserve;
21334
21335     ctxt->schema = mainSchema;
21336
21337     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21338         goto exit_failure;
21339
21340     /*
21341     * TODO: This is not nice, since we cannot distinguish from the
21342     * result if there was an internal error or not.
21343     */
21344 exit:
21345     if (ctxt->nberrors != 0) {
21346         if (mainSchema) {
21347             xmlSchemaFree(mainSchema);
21348             mainSchema = NULL;
21349         }
21350         if (ctxt->constructor) {
21351             xmlSchemaConstructionCtxtFree(ctxt->constructor);
21352             ctxt->constructor = NULL;
21353             ctxt->ownsConstructor = 0;
21354         }
21355     }
21356     ctxt->schema = NULL;
21357     return(mainSchema);
21358 exit_failure:
21359     /*
21360     * Quite verbose, but should catch internal errors, which were
21361     * not communitated.
21362     */
21363     if (mainSchema) {
21364         xmlSchemaFree(mainSchema);
21365         mainSchema = NULL;
21366     }
21367     if (ctxt->constructor) {
21368         xmlSchemaConstructionCtxtFree(ctxt->constructor);
21369         ctxt->constructor = NULL;
21370         ctxt->ownsConstructor = 0;
21371     }
21372     PERROR_INT2("xmlSchemaParse",
21373         "An internal error occured");
21374     ctxt->schema = NULL;
21375     return(NULL);
21376 }
21377
21378 /**
21379  * xmlSchemaSetParserErrors:
21380  * @ctxt:  a schema validation context
21381  * @err:  the error callback
21382  * @warn:  the warning callback
21383  * @ctx:  contextual data for the callbacks
21384  *
21385  * Set the callback functions used to handle errors for a validation context
21386  */
21387 void
21388 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21389                          xmlSchemaValidityErrorFunc err,
21390                          xmlSchemaValidityWarningFunc warn, void *ctx)
21391 {
21392     if (ctxt == NULL)
21393         return;
21394     ctxt->error = err;
21395     ctxt->warning = warn;
21396     ctxt->errCtxt = ctx;
21397     if (ctxt->vctxt != NULL)
21398         xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21399 }
21400
21401 /**
21402  * xmlSchemaSetParserStructuredErrors:
21403  * @ctxt:  a schema parser context
21404  * @serror:  the structured error function
21405  * @ctx: the functions context
21406  *
21407  * Set the structured error callback
21408  */
21409 void
21410 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21411                                    xmlStructuredErrorFunc serror,
21412                                    void *ctx)
21413 {
21414     if (ctxt == NULL)
21415         return;
21416     ctxt->serror = serror;
21417     ctxt->errCtxt = ctx;
21418     if (ctxt->vctxt != NULL)
21419         xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21420 }
21421
21422 /**
21423  * xmlSchemaGetParserErrors:
21424  * @ctxt:  a XMl-Schema parser context
21425  * @err: the error callback result
21426  * @warn: the warning callback result
21427  * @ctx: contextual data for the callbacks result
21428  *
21429  * Get the callback information used to handle errors for a parser context
21430  *
21431  * Returns -1 in case of failure, 0 otherwise
21432  */
21433 int
21434 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21435                          xmlSchemaValidityErrorFunc * err,
21436                          xmlSchemaValidityWarningFunc * warn, void **ctx)
21437 {
21438         if (ctxt == NULL)
21439                 return(-1);
21440         if (err != NULL)
21441                 *err = ctxt->error;
21442         if (warn != NULL)
21443                 *warn = ctxt->warning;
21444         if (ctx != NULL)
21445                 *ctx = ctxt->errCtxt;
21446         return(0);
21447 }
21448
21449 /**
21450  * xmlSchemaFacetTypeToString:
21451  * @type:  the facet type
21452  *
21453  * Convert the xmlSchemaTypeType to a char string.
21454  *
21455  * Returns the char string representation of the facet type if the
21456  *     type is a facet and an "Internal Error" string otherwise.
21457  */
21458 static const xmlChar *
21459 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21460 {
21461     switch (type) {
21462         case XML_SCHEMA_FACET_PATTERN:
21463             return (BAD_CAST "pattern");
21464         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21465             return (BAD_CAST "maxExclusive");
21466         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21467             return (BAD_CAST "maxInclusive");
21468         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21469             return (BAD_CAST "minExclusive");
21470         case XML_SCHEMA_FACET_MININCLUSIVE:
21471             return (BAD_CAST "minInclusive");
21472         case XML_SCHEMA_FACET_WHITESPACE:
21473             return (BAD_CAST "whiteSpace");
21474         case XML_SCHEMA_FACET_ENUMERATION:
21475             return (BAD_CAST "enumeration");
21476         case XML_SCHEMA_FACET_LENGTH:
21477             return (BAD_CAST "length");
21478         case XML_SCHEMA_FACET_MAXLENGTH:
21479             return (BAD_CAST "maxLength");
21480         case XML_SCHEMA_FACET_MINLENGTH:
21481             return (BAD_CAST "minLength");
21482         case XML_SCHEMA_FACET_TOTALDIGITS:
21483             return (BAD_CAST "totalDigits");
21484         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21485             return (BAD_CAST "fractionDigits");
21486         default:
21487             break;
21488     }
21489     return (BAD_CAST "Internal Error");
21490 }
21491
21492 static xmlSchemaWhitespaceValueType
21493 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21494 {
21495     /*
21496     * The normalization type can be changed only for types which are derived
21497     * from xsd:string.
21498     */
21499     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21500         /*
21501         * Note that we assume a whitespace of preserve for anySimpleType.
21502         */
21503         if ((type->builtInType == XML_SCHEMAS_STRING) ||
21504             (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21505             return(XML_SCHEMA_WHITESPACE_PRESERVE);
21506         else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21507             return(XML_SCHEMA_WHITESPACE_REPLACE);
21508         else {
21509             /*
21510             * For all ï¿½atomic� datatypes other than string (and types ï¿½derived�
21511             * by ï¿½restriction� from it) the value of whiteSpace is fixed to
21512             * collapse
21513             * Note that this includes built-in list datatypes.
21514             */
21515             return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21516         }
21517     } else if (WXS_IS_LIST(type)) {
21518         /*
21519         * For list types the facet "whiteSpace" is fixed to "collapse".
21520         */
21521         return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21522     } else if (WXS_IS_UNION(type)) {
21523         return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21524     } else if (WXS_IS_ATOMIC(type)) {
21525         if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21526             return (XML_SCHEMA_WHITESPACE_PRESERVE);
21527         else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21528             return (XML_SCHEMA_WHITESPACE_REPLACE);
21529         else
21530             return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21531     }
21532     return (-1);
21533 }
21534
21535 /************************************************************************
21536  *                                                                      *
21537  *                      Simple type validation                          *
21538  *                                                                      *
21539  ************************************************************************/
21540
21541
21542 /************************************************************************
21543  *                                                                      *
21544  *                      DOM Validation code                             *
21545  *                                                                      *
21546  ************************************************************************/
21547
21548 /**
21549  * xmlSchemaAssembleByLocation:
21550  * @pctxt:  a schema parser context
21551  * @vctxt:  a schema validation context
21552  * @schema: the existing schema
21553  * @node: the node that fired the assembling
21554  * @nsName: the namespace name of the new schema
21555  * @location: the location of the schema
21556  *
21557  * Expands an existing schema by an additional schema.
21558  *
21559  * Returns 0 if the new schema is correct, a positive error code
21560  * number otherwise and -1 in case of an internal or API error.
21561  */
21562 static int
21563 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21564                             xmlSchemaPtr schema,
21565                             xmlNodePtr node,
21566                             const xmlChar *nsName,
21567                             const xmlChar *location)
21568 {
21569     int ret = 0;
21570     xmlSchemaParserCtxtPtr pctxt;
21571     xmlSchemaBucketPtr bucket = NULL;
21572
21573     if ((vctxt == NULL) || (schema == NULL))
21574         return (-1);
21575
21576     if (vctxt->pctxt == NULL) {
21577         VERROR_INT("xmlSchemaAssembleByLocation",
21578             "no parser context available");
21579         return(-1);
21580     }
21581     pctxt = vctxt->pctxt;
21582     if (pctxt->constructor == NULL) {
21583         PERROR_INT("xmlSchemaAssembleByLocation",
21584             "no constructor");
21585         return(-1);
21586     }
21587     /*
21588     * Acquire the schema document.
21589     */
21590     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21591         location, node);
21592     /*
21593     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21594     * the process will automatically change this to
21595     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21596     */
21597     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21598         location, NULL, NULL, 0, node, NULL, nsName,
21599         &bucket);
21600     if (ret != 0)
21601         return(ret);
21602     if (bucket == NULL) {
21603         /*
21604         * Generate a warning that the document could not be located.
21605         */
21606         xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21607             node, NULL,
21608             "The document at location '%s' could not be acquired",
21609             location, NULL, NULL);
21610         return(ret);
21611     }
21612     /*
21613     * The first located schema will be handled as if all other
21614     * schemas imported by XSI were imported by this first schema.
21615     */
21616     if ((bucket != NULL) &&
21617         (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21618         WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21619     /*
21620     * TODO: Is this handled like an import? I.e. is it not an error
21621     * if the schema cannot be located?
21622     */
21623     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21624         return(0);
21625     /*
21626     * We will reuse the parser context for every schema imported
21627     * directly via XSI. So reset the context.
21628     */
21629     pctxt->nberrors = 0;
21630     pctxt->err = 0;
21631     pctxt->doc = bucket->doc;
21632
21633     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21634     if (ret == -1) {
21635         pctxt->doc = NULL;
21636         goto exit_failure;
21637     }
21638     /* Paranoid error channelling. */
21639     if ((ret == 0) && (pctxt->nberrors != 0))
21640         ret = pctxt->err;
21641     if (pctxt->nberrors == 0) {
21642         /*
21643         * Only bother to fixup pending components, if there was
21644         * no error yet.
21645         * For every XSI acquired schema (and its sub-schemata) we will
21646         * fixup the components.
21647         */
21648         xmlSchemaFixupComponents(pctxt, bucket);
21649         ret = pctxt->err;
21650         /*
21651         * Not nice, but we need somehow to channel the schema parser
21652         * error to the validation context.
21653         */
21654         if ((ret != 0) && (vctxt->err == 0))
21655             vctxt->err = ret;
21656         vctxt->nberrors += pctxt->nberrors;
21657     } else {
21658         /* Add to validation error sum. */
21659         vctxt->nberrors += pctxt->nberrors;
21660     }
21661     pctxt->doc = NULL;
21662     return(ret);
21663 exit_failure:
21664     pctxt->doc = NULL;
21665     return (-1);
21666 }
21667
21668 static xmlSchemaAttrInfoPtr
21669 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21670                          int metaType)
21671 {
21672     if (vctxt->nbAttrInfos == 0)
21673         return (NULL);
21674     {
21675         int i;
21676         xmlSchemaAttrInfoPtr iattr;
21677
21678         for (i = 0; i < vctxt->nbAttrInfos; i++) {
21679             iattr = vctxt->attrInfos[i];
21680             if (iattr->metaType == metaType)
21681                 return (iattr);
21682         }
21683
21684     }
21685     return (NULL);
21686 }
21687
21688 /**
21689  * xmlSchemaAssembleByXSI:
21690  * @vctxt:  a schema validation context
21691  *
21692  * Expands an existing schema by an additional schema using
21693  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21694  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21695  * must be set to 1.
21696  *
21697  * Returns 0 if the new schema is correct, a positive error code
21698  * number otherwise and -1 in case of an internal or API error.
21699  */
21700 static int
21701 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21702 {
21703     const xmlChar *cur, *end;
21704     const xmlChar *nsname = NULL, *location;
21705     int count = 0;
21706     int ret = 0;
21707     xmlSchemaAttrInfoPtr iattr;
21708
21709     /*
21710     * Parse the value; we will assume an even number of values
21711     * to be given (this is how Xerces and XSV work).
21712     *
21713     * URGENT TODO: !! This needs to work for both
21714     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21715     * element !!
21716     */
21717     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21718         XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21719     if (iattr == NULL)
21720         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21721         XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21722     if (iattr == NULL)
21723         return (0);
21724     cur = iattr->value;
21725     do {
21726         /*
21727         * TODO: Move the string parsing mechanism away from here.
21728         */
21729         if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21730             /*
21731             * Get the namespace name.
21732             */
21733             while (IS_BLANK_CH(*cur))
21734                 cur++;
21735             end = cur;
21736             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21737                 end++;
21738             if (end == cur)
21739                 break;
21740             count++; /* TODO: Don't use the schema's dict. */
21741             nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21742             cur = end;
21743         }
21744         /*
21745         * Get the URI.
21746         */
21747         while (IS_BLANK_CH(*cur))
21748             cur++;
21749         end = cur;
21750         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21751             end++;
21752         if (end == cur) {
21753             if (iattr->metaType ==
21754                 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21755             {
21756                 /*
21757                 * If using @schemaLocation then tuples are expected.
21758                 * I.e. the namespace name *and* the document's URI.
21759                 */
21760                 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21761                     iattr->node, NULL,
21762                     "The value must consist of tuples: the target namespace "
21763                     "name and the document's URI", NULL, NULL, NULL);
21764             }
21765             break;
21766         }
21767         count++; /* TODO: Don't use the schema's dict. */
21768         location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21769         cur = end;
21770         ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21771             iattr->node, nsname, location);
21772         if (ret == -1) {
21773             VERROR_INT("xmlSchemaAssembleByXSI",
21774                 "assembling schemata");
21775             return (-1);
21776         }
21777     } while (*cur != 0);
21778     return (ret);
21779 }
21780
21781 static const xmlChar *
21782 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21783                          const xmlChar *prefix)
21784 {
21785     if (vctxt->sax != NULL) {
21786         int i, j;
21787         xmlSchemaNodeInfoPtr inode;
21788
21789         for (i = vctxt->depth; i >= 0; i--) {
21790             if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21791                 inode = vctxt->elemInfos[i];
21792                 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21793                     if (((prefix == NULL) &&
21794                             (inode->nsBindings[j] == NULL)) ||
21795                         ((prefix != NULL) && xmlStrEqual(prefix,
21796                             inode->nsBindings[j]))) {
21797
21798                         /*
21799                         * Note that the namespace bindings are already
21800                         * in a string dict.
21801                         */
21802                         return (inode->nsBindings[j+1]);
21803                     }
21804                 }
21805             }
21806         }
21807         return (NULL);
21808 #ifdef LIBXML_READER_ENABLED
21809     } else if (vctxt->reader != NULL) {
21810         xmlChar *nsName;
21811
21812         nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21813         if (nsName != NULL) {
21814             const xmlChar *ret;
21815
21816             ret = xmlDictLookup(vctxt->dict, nsName, -1);
21817             xmlFree(nsName);
21818             return (ret);
21819         } else
21820             return (NULL);
21821 #endif
21822     } else {
21823         xmlNsPtr ns;
21824
21825         if ((vctxt->inode->node == NULL) ||
21826             (vctxt->inode->node->doc == NULL)) {
21827             VERROR_INT("xmlSchemaLookupNamespace",
21828                 "no node or node's doc avaliable");
21829             return (NULL);
21830         }
21831         ns = xmlSearchNs(vctxt->inode->node->doc,
21832             vctxt->inode->node, prefix);
21833         if (ns != NULL)
21834             return (ns->href);
21835         return (NULL);
21836     }
21837 }
21838
21839 /*
21840 * This one works on the schema of the validation context.
21841 */
21842 static int
21843 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21844                           xmlSchemaPtr schema,
21845                           xmlNodePtr node,
21846                           const xmlChar *value,
21847                           xmlSchemaValPtr *val,
21848                           int valNeeded)
21849 {
21850     int ret;
21851
21852     if (vctxt && (vctxt->schema == NULL)) {
21853         VERROR_INT("xmlSchemaValidateNotation",
21854             "a schema is needed on the validation context");
21855         return (-1);
21856     }
21857     ret = xmlValidateQName(value, 1);
21858     if (ret != 0)
21859         return (ret);
21860     {
21861         xmlChar *localName = NULL;
21862         xmlChar *prefix = NULL;
21863
21864         localName = xmlSplitQName2(value, &prefix);
21865         if (prefix != NULL) {
21866             const xmlChar *nsName = NULL;
21867
21868             if (vctxt != NULL)
21869                 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21870             else if (node != NULL) {
21871                 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21872                 if (ns != NULL)
21873                     nsName = ns->href;
21874             } else {
21875                 xmlFree(prefix);
21876                 xmlFree(localName);
21877                 return (1);
21878             }
21879             if (nsName == NULL) {
21880                 xmlFree(prefix);
21881                 xmlFree(localName);
21882                 return (1);
21883             }
21884             if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21885                 if ((valNeeded) && (val != NULL)) {
21886                     (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21887                                                        xmlStrdup(nsName));
21888                     if (*val == NULL)
21889                         ret = -1;
21890                 }
21891             } else
21892                 ret = 1;
21893             xmlFree(prefix);
21894             xmlFree(localName);
21895         } else {
21896             if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21897                 if (valNeeded && (val != NULL)) {
21898                     (*val) = xmlSchemaNewNOTATIONValue(
21899                         BAD_CAST xmlStrdup(value), NULL);
21900                     if (*val == NULL)
21901                         ret = -1;
21902                 }
21903             } else
21904                 return (1);
21905         }
21906     }
21907     return (ret);
21908 }
21909
21910 static int
21911 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21912                        const xmlChar* lname,
21913                        const xmlChar* nsname)
21914 {
21915     int i;
21916
21917     lname = xmlDictLookup(vctxt->dict, lname, -1);
21918     if (lname == NULL)
21919         return(-1);
21920     if (nsname != NULL) {
21921         nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21922         if (nsname == NULL)
21923             return(-1);
21924     }
21925     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21926         if ((vctxt->nodeQNames->items [i] == lname) &&
21927             (vctxt->nodeQNames->items[i +1] == nsname))
21928             /* Already there */
21929             return(i);
21930     }
21931     /* Add new entry. */
21932     i = vctxt->nodeQNames->nbItems;
21933     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21934     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21935     return(i);
21936 }
21937
21938 /************************************************************************
21939  *                                                                      *
21940  *  Validation of identity-constraints (IDC)                            *
21941  *                                                                      *
21942  ************************************************************************/
21943
21944 /**
21945  * xmlSchemaAugmentIDC:
21946  * @idcDef: the IDC definition
21947  *
21948  * Creates an augmented IDC definition item.
21949  *
21950  * Returns the item, or NULL on internal errors.
21951  */
21952 static void
21953 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21954                     xmlSchemaValidCtxtPtr vctxt)
21955 {
21956     xmlSchemaIDCAugPtr aidc;
21957
21958     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21959     if (aidc == NULL) {
21960         xmlSchemaVErrMemory(vctxt,
21961             "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21962             NULL);
21963         return;
21964     }
21965     aidc->keyrefDepth = -1;
21966     aidc->def = idcDef;
21967     aidc->next = NULL;
21968     if (vctxt->aidcs == NULL)
21969         vctxt->aidcs = aidc;
21970     else {
21971         aidc->next = vctxt->aidcs;
21972         vctxt->aidcs = aidc;
21973     }
21974     /*
21975     * Save if we have keyrefs at all.
21976     */
21977     if ((vctxt->hasKeyrefs == 0) &&
21978         (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21979         vctxt->hasKeyrefs = 1;
21980 }
21981
21982 /**
21983  * xmlSchemaAugmentImportedIDC:
21984  * @imported: the imported schema
21985  *
21986  * Creates an augmented IDC definition for the imported schema.
21987  */
21988 static void
21989 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21990     if (imported->schema->idcDef != NULL) {
21991             xmlHashScan(imported->schema->idcDef ,
21992             (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21993     }
21994 }
21995
21996 /**
21997  * xmlSchemaIDCNewBinding:
21998  * @idcDef: the IDC definition of this binding
21999  *
22000  * Creates a new IDC binding.
22001  *
22002  * Returns the new IDC binding, NULL on internal errors.
22003  */
22004 static xmlSchemaPSVIIDCBindingPtr
22005 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22006 {
22007     xmlSchemaPSVIIDCBindingPtr ret;
22008
22009     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22010             sizeof(xmlSchemaPSVIIDCBinding));
22011     if (ret == NULL) {
22012         xmlSchemaVErrMemory(NULL,
22013             "allocating a PSVI IDC binding item", NULL);
22014         return (NULL);
22015     }
22016     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22017     ret->definition = idcDef;
22018     return (ret);
22019 }
22020
22021 /**
22022  * xmlSchemaIDCStoreNodeTableItem:
22023  * @vctxt: the WXS validation context
22024  * @item: the IDC node table item
22025  *
22026  * The validation context is used to store IDC node table items.
22027  * They are stored to avoid copying them if IDC node-tables are merged
22028  * with corresponding parent IDC node-tables (bubbling).
22029  *
22030  * Returns 0 if succeeded, -1 on internal errors.
22031  */
22032 static int
22033 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22034                                xmlSchemaPSVIIDCNodePtr item)
22035 {
22036     /*
22037     * Add to gobal list.
22038     */
22039     if (vctxt->idcNodes == NULL) {
22040         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22041             xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22042         if (vctxt->idcNodes == NULL) {
22043             xmlSchemaVErrMemory(vctxt,
22044                 "allocating the IDC node table item list", NULL);
22045             return (-1);
22046         }
22047         vctxt->sizeIdcNodes = 20;
22048     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22049         vctxt->sizeIdcNodes *= 2;
22050         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22051             xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22052             sizeof(xmlSchemaPSVIIDCNodePtr));
22053         if (vctxt->idcNodes == NULL) {
22054             xmlSchemaVErrMemory(vctxt,
22055                 "re-allocating the IDC node table item list", NULL);
22056             return (-1);
22057         }
22058     }
22059     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22060
22061     return (0);
22062 }
22063
22064 /**
22065  * xmlSchemaIDCStoreKey:
22066  * @vctxt: the WXS validation context
22067  * @item: the IDC key
22068  *
22069  * The validation context is used to store an IDC key.
22070  *
22071  * Returns 0 if succeeded, -1 on internal errors.
22072  */
22073 static int
22074 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22075                      xmlSchemaPSVIIDCKeyPtr key)
22076 {
22077     /*
22078     * Add to gobal list.
22079     */
22080     if (vctxt->idcKeys == NULL) {
22081         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22082             xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22083         if (vctxt->idcKeys == NULL) {
22084             xmlSchemaVErrMemory(vctxt,
22085                 "allocating the IDC key storage list", NULL);
22086             return (-1);
22087         }
22088         vctxt->sizeIdcKeys = 40;
22089     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22090         vctxt->sizeIdcKeys *= 2;
22091         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22092             xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22093             sizeof(xmlSchemaPSVIIDCKeyPtr));
22094         if (vctxt->idcKeys == NULL) {
22095             xmlSchemaVErrMemory(vctxt,
22096                 "re-allocating the IDC key storage list", NULL);
22097             return (-1);
22098         }
22099     }
22100     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22101
22102     return (0);
22103 }
22104
22105 /**
22106  * xmlSchemaIDCAppendNodeTableItem:
22107  * @bind: the IDC binding
22108  * @ntItem: the node-table item
22109  *
22110  * Appends the IDC node-table item to the binding.
22111  *
22112  * Returns 0 on success and -1 on internal errors.
22113  */
22114 static int
22115 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22116                                 xmlSchemaPSVIIDCNodePtr ntItem)
22117 {
22118     if (bind->nodeTable == NULL) {
22119         bind->sizeNodes = 10;
22120         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22121             xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22122         if (bind->nodeTable == NULL) {
22123             xmlSchemaVErrMemory(NULL,
22124                 "allocating an array of IDC node-table items", NULL);
22125             return(-1);
22126         }
22127     } else if (bind->sizeNodes <= bind->nbNodes) {
22128         bind->sizeNodes *= 2;
22129         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22130             xmlRealloc(bind->nodeTable, bind->sizeNodes *
22131                 sizeof(xmlSchemaPSVIIDCNodePtr));
22132         if (bind->nodeTable == NULL) {
22133             xmlSchemaVErrMemory(NULL,
22134                 "re-allocating an array of IDC node-table items", NULL);
22135             return(-1);
22136         }
22137     }
22138     bind->nodeTable[bind->nbNodes++] = ntItem;
22139     return(0);
22140 }
22141
22142 /**
22143  * xmlSchemaIDCAcquireBinding:
22144  * @vctxt: the WXS validation context
22145  * @matcher: the IDC matcher
22146  *
22147  * Looks up an PSVI IDC binding, for the IDC definition and
22148  * of the given matcher. If none found, a new one is created
22149  * and added to the IDC table.
22150  *
22151  * Returns an IDC binding or NULL on internal errors.
22152  */
22153 static xmlSchemaPSVIIDCBindingPtr
22154 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22155                           xmlSchemaIDCMatcherPtr matcher)
22156 {
22157     xmlSchemaNodeInfoPtr ielem;
22158
22159     ielem = vctxt->elemInfos[matcher->depth];
22160
22161     if (ielem->idcTable == NULL) {
22162         ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22163         if (ielem->idcTable == NULL)
22164             return (NULL);
22165         return(ielem->idcTable);
22166     } else {
22167         xmlSchemaPSVIIDCBindingPtr bind = NULL;
22168
22169         bind = ielem->idcTable;
22170         do {
22171             if (bind->definition == matcher->aidc->def)
22172                 return(bind);
22173             if (bind->next == NULL) {
22174                 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22175                 if (bind->next == NULL)
22176                     return (NULL);
22177                 return(bind->next);
22178             }
22179             bind = bind->next;
22180         } while (bind != NULL);
22181     }
22182     return (NULL);
22183 }
22184
22185 static xmlSchemaItemListPtr
22186 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22187                              xmlSchemaIDCMatcherPtr matcher)
22188 {
22189     if (matcher->targets == NULL)
22190         matcher->targets = xmlSchemaItemListCreate();
22191     return(matcher->targets);
22192 }
22193
22194 /**
22195  * xmlSchemaIDCFreeKey:
22196  * @key: the IDC key
22197  *
22198  * Frees an IDC key together with its compiled value.
22199  */
22200 static void
22201 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22202 {
22203     if (key->val != NULL)
22204         xmlSchemaFreeValue(key->val);
22205     xmlFree(key);
22206 }
22207
22208 /**
22209  * xmlSchemaIDCFreeBinding:
22210  *
22211  * Frees an IDC binding. Note that the node table-items
22212  * are not freed.
22213  */
22214 static void
22215 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22216 {
22217     if (bind->nodeTable != NULL)
22218         xmlFree(bind->nodeTable);
22219     if (bind->dupls != NULL)
22220         xmlSchemaItemListFree(bind->dupls);
22221     xmlFree(bind);
22222 }
22223
22224 /**
22225  * xmlSchemaIDCFreeIDCTable:
22226  * @bind: the first IDC binding in the list
22227  *
22228  * Frees an IDC table, i.e. all the IDC bindings in the list.
22229  */
22230 static void
22231 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22232 {
22233     xmlSchemaPSVIIDCBindingPtr prev;
22234
22235     while (bind != NULL) {
22236         prev = bind;
22237         bind = bind->next;
22238         xmlSchemaIDCFreeBinding(prev);
22239     }
22240 }
22241
22242 /**
22243  * xmlSchemaIDCFreeMatcherList:
22244  * @matcher: the first IDC matcher in the list
22245  *
22246  * Frees a list of IDC matchers.
22247  */
22248 static void
22249 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22250 {
22251     xmlSchemaIDCMatcherPtr next;
22252
22253     while (matcher != NULL) {
22254         next = matcher->next;
22255         if (matcher->keySeqs != NULL) {
22256             int i;
22257             for (i = 0; i < matcher->sizeKeySeqs; i++)
22258                 if (matcher->keySeqs[i] != NULL)
22259                     xmlFree(matcher->keySeqs[i]);
22260             xmlFree(matcher->keySeqs);
22261         }
22262         if (matcher->targets != NULL) {
22263             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22264                 int i;
22265                 xmlSchemaPSVIIDCNodePtr idcNode;
22266                 /*
22267                 * Node-table items for keyrefs are not stored globally
22268                 * to the validation context, since they are not bubbled.
22269                 * We need to free them here.
22270                 */
22271                 for (i = 0; i < matcher->targets->nbItems; i++) {
22272                     idcNode =
22273                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22274                     xmlFree(idcNode->keys);
22275                     xmlFree(idcNode);
22276                 }
22277             }
22278             xmlSchemaItemListFree(matcher->targets);
22279         }
22280         xmlFree(matcher);
22281         matcher = next;
22282     }
22283 }
22284
22285 /**
22286  * xmlSchemaIDCReleaseMatcherList:
22287  * @vctxt: the WXS validation context
22288  * @matcher: the first IDC matcher in the list
22289  *
22290  * Caches a list of IDC matchers for reuse.
22291  */
22292 static void
22293 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22294                                xmlSchemaIDCMatcherPtr matcher)
22295 {
22296     xmlSchemaIDCMatcherPtr next;
22297
22298     while (matcher != NULL) {
22299         next = matcher->next;
22300         if (matcher->keySeqs != NULL) {
22301             int i;
22302             /*
22303             * Don't free the array, but only the content.
22304             */
22305             for (i = 0; i < matcher->sizeKeySeqs; i++)
22306                 if (matcher->keySeqs[i] != NULL) {
22307                     xmlFree(matcher->keySeqs[i]);
22308                     matcher->keySeqs[i] = NULL;
22309                 }
22310         }
22311         if (matcher->targets) {
22312             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22313                 int i;
22314                 xmlSchemaPSVIIDCNodePtr idcNode;
22315                 /*
22316                 * Node-table items for keyrefs are not stored globally
22317                 * to the validation context, since they are not bubbled.
22318                 * We need to free them here.
22319                 */
22320                 for (i = 0; i < matcher->targets->nbItems; i++) {
22321                     idcNode =
22322                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22323                     xmlFree(idcNode->keys);
22324                     xmlFree(idcNode);
22325                 }
22326             }
22327             xmlSchemaItemListFree(matcher->targets);
22328             matcher->targets = NULL;
22329         }
22330         matcher->next = NULL;
22331         /*
22332         * Cache the matcher.
22333         */
22334         if (vctxt->idcMatcherCache != NULL)
22335             matcher->nextCached = vctxt->idcMatcherCache;
22336         vctxt->idcMatcherCache = matcher;
22337
22338         matcher = next;
22339     }
22340 }
22341
22342 /**
22343  * xmlSchemaIDCAddStateObject:
22344  * @vctxt: the WXS validation context
22345  * @matcher: the IDC matcher
22346  * @sel: the XPath information
22347  * @parent: the parent "selector" state object if any
22348  * @type: "selector" or "field"
22349  *
22350  * Creates/reuses and activates state objects for the given
22351  * XPath information; if the XPath expression consists of unions,
22352  * multiple state objects are created for every unioned expression.
22353  *
22354  * Returns 0 on success and -1 on internal errors.
22355  */
22356 static int
22357 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22358                         xmlSchemaIDCMatcherPtr matcher,
22359                         xmlSchemaIDCSelectPtr sel,
22360                         int type)
22361 {
22362     xmlSchemaIDCStateObjPtr sto;
22363
22364     /*
22365     * Reuse the state objects from the pool.
22366     */
22367     if (vctxt->xpathStatePool != NULL) {
22368         sto = vctxt->xpathStatePool;
22369         vctxt->xpathStatePool = sto->next;
22370         sto->next = NULL;
22371     } else {
22372         /*
22373         * Create a new state object.
22374         */
22375         sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22376         if (sto == NULL) {
22377             xmlSchemaVErrMemory(NULL,
22378                 "allocating an IDC state object", NULL);
22379             return (-1);
22380         }
22381         memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22382     }
22383     /*
22384     * Add to global list.
22385     */
22386     if (vctxt->xpathStates != NULL)
22387         sto->next = vctxt->xpathStates;
22388     vctxt->xpathStates = sto;
22389
22390     /*
22391     * Free the old xpath validation context.
22392     */
22393     if (sto->xpathCtxt != NULL)
22394         xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22395
22396     /*
22397     * Create a new XPath (pattern) validation context.
22398     */
22399     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22400         (xmlPatternPtr) sel->xpathComp);
22401     if (sto->xpathCtxt == NULL) {
22402         VERROR_INT("xmlSchemaIDCAddStateObject",
22403             "failed to create an XPath validation context");
22404         return (-1);
22405     }
22406     sto->type = type;
22407     sto->depth = vctxt->depth;
22408     sto->matcher = matcher;
22409     sto->sel = sel;
22410     sto->nbHistory = 0;
22411
22412 #ifdef DEBUG_IDC
22413     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22414         sto->sel->xpath);
22415 #endif
22416     return (0);
22417 }
22418
22419 /**
22420  * xmlSchemaXPathEvaluate:
22421  * @vctxt: the WXS validation context
22422  * @nodeType: the nodeType of the current node
22423  *
22424  * Evaluates all active XPath state objects.
22425  *
22426  * Returns the number of IC "field" state objects which resolved to
22427  * this node, 0 if none resolved and -1 on internal errors.
22428  */
22429 static int
22430 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22431                        xmlElementType nodeType)
22432 {
22433     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22434     int res, resolved = 0, depth = vctxt->depth;
22435
22436     if (vctxt->xpathStates == NULL)
22437         return (0);
22438
22439     if (nodeType == XML_ATTRIBUTE_NODE)
22440         depth++;
22441 #ifdef DEBUG_IDC
22442     {
22443         xmlChar *str = NULL;
22444         xmlGenericError(xmlGenericErrorContext,
22445             "IDC: EVAL on %s, depth %d, type %d\n",
22446             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22447                 vctxt->inode->localName), depth, nodeType);
22448         FREE_AND_NULL(str)
22449     }
22450 #endif
22451     /*
22452     * Process all active XPath state objects.
22453     */
22454     first = vctxt->xpathStates;
22455     sto = first;
22456     while (sto != head) {
22457 #ifdef DEBUG_IDC
22458         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22459             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22460                 sto->matcher->aidc->def->name, sto->sel->xpath);
22461         else
22462             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22463                 sto->matcher->aidc->def->name, sto->sel->xpath);
22464 #endif
22465         if (nodeType == XML_ELEMENT_NODE)
22466             res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22467                 vctxt->inode->localName, vctxt->inode->nsName);
22468         else
22469             res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22470                 vctxt->inode->localName, vctxt->inode->nsName);
22471
22472         if (res == -1) {
22473             VERROR_INT("xmlSchemaXPathEvaluate",
22474                 "calling xmlStreamPush()");
22475             return (-1);
22476         }
22477         if (res == 0)
22478             goto next_sto;
22479         /*
22480         * Full match.
22481         */
22482 #ifdef DEBUG_IDC
22483         xmlGenericError(xmlGenericErrorContext, "IDC:     "
22484             "MATCH\n");
22485 #endif
22486         /*
22487         * Register a match in the state object history.
22488         */
22489         if (sto->history == NULL) {
22490             sto->history = (int *) xmlMalloc(5 * sizeof(int));
22491             if (sto->history == NULL) {
22492                 xmlSchemaVErrMemory(NULL,
22493                     "allocating the state object history", NULL);
22494                 return(-1);
22495             }
22496             sto->sizeHistory = 5;
22497         } else if (sto->sizeHistory <= sto->nbHistory) {
22498             sto->sizeHistory *= 2;
22499             sto->history = (int *) xmlRealloc(sto->history,
22500                 sto->sizeHistory * sizeof(int));
22501             if (sto->history == NULL) {
22502                 xmlSchemaVErrMemory(NULL,
22503                     "re-allocating the state object history", NULL);
22504                 return(-1);
22505             }
22506         }
22507         sto->history[sto->nbHistory++] = depth;
22508
22509 #ifdef DEBUG_IDC
22510         xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22511             vctxt->depth);
22512 #endif
22513
22514         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22515             xmlSchemaIDCSelectPtr sel;
22516             /*
22517             * Activate state objects for the IDC fields of
22518             * the IDC selector.
22519             */
22520 #ifdef DEBUG_IDC
22521             xmlGenericError(xmlGenericErrorContext, "IDC:     "
22522                 "activating field states\n");
22523 #endif
22524             sel = sto->matcher->aidc->def->fields;
22525             while (sel != NULL) {
22526                 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22527                     sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22528                     return (-1);
22529                 sel = sel->next;
22530             }
22531         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22532             /*
22533             * An IDC key node was found by the IDC field.
22534             */
22535 #ifdef DEBUG_IDC
22536             xmlGenericError(xmlGenericErrorContext,
22537                 "IDC:     key found\n");
22538 #endif
22539             /*
22540             * Notify that the character value of this node is
22541             * needed.
22542             */
22543             if (resolved == 0) {
22544                 if ((vctxt->inode->flags &
22545                     XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22546                 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22547             }
22548             resolved++;
22549         }
22550 next_sto:
22551         if (sto->next == NULL) {
22552             /*
22553             * Evaluate field state objects created on this node as well.
22554             */
22555             head = first;
22556             sto = vctxt->xpathStates;
22557         } else
22558             sto = sto->next;
22559     }
22560     return (resolved);
22561 }
22562
22563 static const xmlChar *
22564 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22565                               xmlChar **buf,
22566                               xmlSchemaPSVIIDCKeyPtr *seq,
22567                               int count)
22568 {
22569     int i, res;
22570     xmlChar *value = NULL;
22571
22572     *buf = xmlStrdup(BAD_CAST "[");
22573     for (i = 0; i < count; i++) {
22574         *buf = xmlStrcat(*buf, BAD_CAST "'");
22575         res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22576             xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22577             &value);
22578         if (res == 0)
22579             *buf = xmlStrcat(*buf, BAD_CAST value);
22580         else {
22581             VERROR_INT("xmlSchemaFormatIDCKeySequence",
22582                 "failed to compute a canonical value");
22583             *buf = xmlStrcat(*buf, BAD_CAST "???");
22584         }
22585         if (i < count -1)
22586             *buf = xmlStrcat(*buf, BAD_CAST "', ");
22587         else
22588             *buf = xmlStrcat(*buf, BAD_CAST "'");
22589         if (value != NULL) {
22590             xmlFree(value);
22591             value = NULL;
22592         }
22593     }
22594     *buf = xmlStrcat(*buf, BAD_CAST "]");
22595
22596     return (BAD_CAST *buf);
22597 }
22598
22599 /**
22600  * xmlSchemaXPathPop:
22601  * @vctxt: the WXS validation context
22602  *
22603  * Pops all XPath states.
22604  *
22605  * Returns 0 on success and -1 on internal errors.
22606  */
22607 static int
22608 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22609 {
22610     xmlSchemaIDCStateObjPtr sto;
22611     int res;
22612
22613     if (vctxt->xpathStates == NULL)
22614         return(0);
22615     sto = vctxt->xpathStates;
22616     do {
22617         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22618         if (res == -1)
22619             return (-1);
22620         sto = sto->next;
22621     } while (sto != NULL);
22622     return(0);
22623 }
22624
22625 /**
22626  * xmlSchemaXPathProcessHistory:
22627  * @vctxt: the WXS validation context
22628  * @type: the simple/complex type of the current node if any at all
22629  * @val: the precompiled value
22630  *
22631  * Processes and pops the history items of the IDC state objects.
22632  * IDC key-sequences are validated/created on IDC bindings.
22633  *
22634  * Returns 0 on success and -1 on internal errors.
22635  */
22636 static int
22637 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22638                              int depth)
22639 {
22640     xmlSchemaIDCStateObjPtr sto, nextsto;
22641     int res, matchDepth;
22642     xmlSchemaPSVIIDCKeyPtr key = NULL;
22643     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22644
22645     if (vctxt->xpathStates == NULL)
22646         return (0);
22647     sto = vctxt->xpathStates;
22648
22649 #ifdef DEBUG_IDC
22650     {
22651         xmlChar *str = NULL;
22652         xmlGenericError(xmlGenericErrorContext,
22653             "IDC: BACK on %s, depth %d\n",
22654             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22655                 vctxt->inode->localName), vctxt->depth);
22656         FREE_AND_NULL(str)
22657     }
22658 #endif
22659     /*
22660     * Evaluate the state objects.
22661     */
22662     while (sto != NULL) {
22663         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22664         if (res == -1) {
22665             VERROR_INT("xmlSchemaXPathProcessHistory",
22666                 "calling xmlStreamPop()");
22667             return (-1);
22668         }
22669 #ifdef DEBUG_IDC
22670         xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22671             sto->sel->xpath);
22672 #endif
22673         if (sto->nbHistory == 0)
22674             goto deregister_check;
22675
22676         matchDepth = sto->history[sto->nbHistory -1];
22677
22678         /*
22679         * Only matches at the current depth are of interest.
22680         */
22681         if (matchDepth != depth) {
22682             sto = sto->next;
22683             continue;
22684         }
22685         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22686             /*
22687             * NOTE: According to
22688             *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22689             *   ... the simple-content of complex types is also allowed.
22690             */
22691
22692             if (WXS_IS_COMPLEX(type)) {
22693                 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22694                     /*
22695                     * Sanity check for complex types with simple content.
22696                     */
22697                     simpleType = type->contentTypeDef;
22698                     if (simpleType == NULL) {
22699                         VERROR_INT("xmlSchemaXPathProcessHistory",
22700                             "field resolves to a CT with simple content "
22701                             "but the CT is missing the ST definition");
22702                         return (-1);
22703                     }
22704                 } else
22705                     simpleType = NULL;
22706             } else
22707                 simpleType = type;
22708             if (simpleType == NULL) {
22709                 xmlChar *str = NULL;
22710
22711                 /*
22712                 * Not qualified if the field resolves to a node of non
22713                 * simple type.
22714                 */
22715                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22716                     XML_SCHEMAV_CVC_IDC, NULL,
22717                     WXS_BASIC_CAST sto->matcher->aidc->def,
22718                     "The XPath '%s' of a field of %s does evaluate to a node of "
22719                     "non-simple type",
22720                     sto->sel->xpath,
22721                     xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22722                 FREE_AND_NULL(str);
22723                 sto->nbHistory--;
22724                 goto deregister_check;
22725             }
22726
22727             if ((key == NULL) && (vctxt->inode->val == NULL)) {
22728                 /*
22729                 * Failed to provide the normalized value; maybe
22730                 * the value was invalid.
22731                 */
22732                 VERROR(XML_SCHEMAV_CVC_IDC,
22733                     WXS_BASIC_CAST sto->matcher->aidc->def,
22734                     "Warning: No precomputed value available, the value "
22735                     "was either invalid or something strange happend");
22736                 sto->nbHistory--;
22737                 goto deregister_check;
22738             } else {
22739                 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22740                 xmlSchemaPSVIIDCKeyPtr *keySeq;
22741                 int pos, idx;
22742
22743                 /*
22744                 * The key will be anchored on the matcher's list of
22745                 * key-sequences. The position in this list is determined
22746                 * by the target node's depth relative to the matcher's
22747                 * depth of creation (i.e. the depth of the scope element).
22748                 *
22749                 * Element        Depth    Pos   List-entries
22750                 * <scope>          0              NULL
22751                 *   <bar>          1              NULL
22752                 *     <target/>    2       2      target
22753                 *   <bar>
22754                 * </scope>
22755                 *
22756                 * The size of the list is only dependant on the depth of
22757                 * the tree.
22758                 * An entry will be NULLed in selector_leave, i.e. when
22759                 * we hit the target's
22760                 */
22761                 pos = sto->depth - matcher->depth;
22762                 idx = sto->sel->index;
22763
22764                 /*
22765                 * Create/grow the array of key-sequences.
22766                 */
22767                 if (matcher->keySeqs == NULL) {
22768                     if (pos > 9)
22769                         matcher->sizeKeySeqs = pos * 2;
22770                     else
22771                         matcher->sizeKeySeqs = 10;
22772                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22773                         xmlMalloc(matcher->sizeKeySeqs *
22774                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22775                     if (matcher->keySeqs == NULL) {
22776                         xmlSchemaVErrMemory(NULL,
22777                             "allocating an array of key-sequences",
22778                             NULL);
22779                         return(-1);
22780                     }
22781                     memset(matcher->keySeqs, 0,
22782                         matcher->sizeKeySeqs *
22783                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22784                 } else if (pos >= matcher->sizeKeySeqs) {
22785                     int i = matcher->sizeKeySeqs;
22786
22787                     matcher->sizeKeySeqs *= 2;
22788                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22789                         xmlRealloc(matcher->keySeqs,
22790                         matcher->sizeKeySeqs *
22791                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22792                     if (matcher->keySeqs == NULL) {
22793                         xmlSchemaVErrMemory(NULL,
22794                             "reallocating an array of key-sequences",
22795                             NULL);
22796                         return (-1);
22797                     }
22798                     /*
22799                     * The array needs to be NULLed.
22800                     * TODO: Use memset?
22801                     */
22802                     for (; i < matcher->sizeKeySeqs; i++)
22803                         matcher->keySeqs[i] = NULL;
22804                 }
22805
22806                 /*
22807                 * Get/create the key-sequence.
22808                 */
22809                 keySeq = matcher->keySeqs[pos];
22810                 if (keySeq == NULL) {
22811                     goto create_sequence;
22812                 } else if (keySeq[idx] != NULL) {
22813                     xmlChar *str = NULL;
22814                     /*
22815                     * cvc-identity-constraint:
22816                     * 3 For each node in the ï¿½target node set� all
22817                     * of the {fields}, with that node as the context
22818                     * node, evaluate to either an empty node-set or
22819                     * a node-set with exactly one member, which must
22820                     * have a simple type.
22821                     *
22822                     * The key was already set; report an error.
22823                     */
22824                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
22825                         XML_SCHEMAV_CVC_IDC, NULL,
22826                         WXS_BASIC_CAST matcher->aidc->def,
22827                         "The XPath '%s' of a field of %s evaluates to a "
22828                         "node-set with more than one member",
22829                         sto->sel->xpath,
22830                         xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22831                     FREE_AND_NULL(str);
22832                     sto->nbHistory--;
22833                     goto deregister_check;
22834                 } else
22835                     goto create_key;
22836
22837 create_sequence:
22838                 /*
22839                 * Create a key-sequence.
22840                 */
22841                 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22842                     matcher->aidc->def->nbFields *
22843                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22844                 if (keySeq == NULL) {
22845                     xmlSchemaVErrMemory(NULL,
22846                         "allocating an IDC key-sequence", NULL);
22847                     return(-1);
22848                 }
22849                 memset(keySeq, 0, matcher->aidc->def->nbFields *
22850                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22851                 matcher->keySeqs[pos] = keySeq;
22852 create_key:
22853                 /*
22854                 * Create a key once per node only.
22855                 */
22856                 if (key == NULL) {
22857                     key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22858                         sizeof(xmlSchemaPSVIIDCKey));
22859                     if (key == NULL) {
22860                         xmlSchemaVErrMemory(NULL,
22861                             "allocating a IDC key", NULL);
22862                         xmlFree(keySeq);
22863                         matcher->keySeqs[pos] = NULL;
22864                         return(-1);
22865                     }
22866                     /*
22867                     * Consume the compiled value.
22868                     */
22869                     key->type = simpleType;
22870                     key->val = vctxt->inode->val;
22871                     vctxt->inode->val = NULL;
22872                     /*
22873                     * Store the key in a global list.
22874                     */
22875                     if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22876                         xmlSchemaIDCFreeKey(key);
22877                         return (-1);
22878                     }
22879                 }
22880                 keySeq[idx] = key;
22881             }
22882         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22883
22884             xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22885             /* xmlSchemaPSVIIDCBindingPtr bind; */
22886             xmlSchemaPSVIIDCNodePtr ntItem;
22887             xmlSchemaIDCMatcherPtr matcher;
22888             xmlSchemaIDCPtr idc;
22889             xmlSchemaItemListPtr targets;
22890             int pos, i, j, nbKeys;
22891             /*
22892             * Here we have the following scenario:
22893             * An IDC 'selector' state object resolved to a target node,
22894             * during the time this target node was in the
22895             * ancestor-or-self axis, the 'field' state object(s) looked
22896             * out for matching nodes to create a key-sequence for this
22897             * target node. Now we are back to this target node and need
22898             * to put the key-sequence, together with the target node
22899             * itself, into the node-table of the corresponding IDC
22900             * binding.
22901             */
22902             matcher = sto->matcher;
22903             idc = matcher->aidc->def;
22904             nbKeys = idc->nbFields;
22905             pos = depth - matcher->depth;
22906             /*
22907             * Check if the matcher has any key-sequences at all, plus
22908             * if it has a key-sequence for the current target node.
22909             */
22910             if ((matcher->keySeqs == NULL) ||
22911                 (matcher->sizeKeySeqs <= pos)) {
22912                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22913                     goto selector_key_error;
22914                 else
22915                     goto selector_leave;
22916             }
22917
22918             keySeq = &(matcher->keySeqs[pos]);
22919             if (*keySeq == NULL) {
22920                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22921                     goto selector_key_error;
22922                 else
22923                     goto selector_leave;
22924             }
22925
22926             for (i = 0; i < nbKeys; i++) {
22927                 if ((*keySeq)[i] == NULL) {
22928                     /*
22929                     * Not qualified, if not all fields did resolve.
22930                     */
22931                     if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22932                         /*
22933                         * All fields of a "key" IDC must resolve.
22934                         */
22935                         goto selector_key_error;
22936                     }
22937                     goto selector_leave;
22938                 }
22939             }
22940             /*
22941             * All fields did resolve.
22942             */
22943
22944             /*
22945             * 4.1 If the {identity-constraint category} is unique(/key),
22946             * then no two members of the ï¿½qualified node set� have
22947             * ï¿½key-sequences� whose members are pairwise equal, as
22948             * defined by Equal in [XML Schemas: Datatypes].
22949             *
22950             * Get the IDC binding from the matcher and check for
22951             * duplicate key-sequences.
22952             */
22953 #if 0
22954             bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22955 #endif
22956             targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22957             if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22958                 (targets->nbItems != 0)) {
22959                 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22960
22961                 i = 0;
22962                 res = 0;
22963                 /*
22964                 * Compare the key-sequences, key by key.
22965                 */
22966                 do {
22967                     bkeySeq =
22968                         ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22969                     for (j = 0; j < nbKeys; j++) {
22970                         ckey = (*keySeq)[j];
22971                         bkey = bkeySeq[j];
22972                         res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22973                         if (res == -1) {
22974                             return (-1);
22975                         } else if (res == 0) {
22976                             /*
22977                             * One of the keys differs, so the key-sequence
22978                             * won't be equal; get out.
22979                             */
22980                             break;
22981                         }
22982                     }
22983                     if (res == 1) {
22984                         /*
22985                         * Duplicate key-sequence found.
22986                         */
22987                         break;
22988                     }
22989                     i++;
22990                 } while (i < targets->nbItems);
22991                 if (i != targets->nbItems) {
22992                     xmlChar *str = NULL, *strB = NULL;
22993                     /*
22994                     * TODO: Try to report the key-sequence.
22995                     */
22996                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
22997                         XML_SCHEMAV_CVC_IDC, NULL,
22998                         WXS_BASIC_CAST idc,
22999                         "Duplicate key-sequence %s in %s",
23000                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23001                             (*keySeq), nbKeys),
23002                         xmlSchemaGetIDCDesignation(&strB, idc));
23003                     FREE_AND_NULL(str);
23004                     FREE_AND_NULL(strB);
23005                     goto selector_leave;
23006                 }
23007             }
23008             /*
23009             * Add a node-table item to the IDC binding.
23010             */
23011             ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23012                 sizeof(xmlSchemaPSVIIDCNode));
23013             if (ntItem == NULL) {
23014                 xmlSchemaVErrMemory(NULL,
23015                     "allocating an IDC node-table item", NULL);
23016                 xmlFree(*keySeq);
23017                 *keySeq = NULL;
23018                 return(-1);
23019             }
23020             memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23021
23022             /*
23023             * Store the node-table item in a global list.
23024             */
23025             if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23026                 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23027                     xmlFree(ntItem);
23028                     xmlFree(*keySeq);
23029                     *keySeq = NULL;
23030                     return (-1);
23031                 }
23032                 ntItem->nodeQNameID = -1;
23033             } else {
23034                 /*
23035                 * Save a cached QName for this node on the IDC node, to be
23036                 * able to report it, even if the node is not saved.
23037                 */
23038                 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23039                     vctxt->inode->localName, vctxt->inode->nsName);
23040                 if (ntItem->nodeQNameID == -1) {
23041                     xmlFree(ntItem);
23042                     xmlFree(*keySeq);
23043                     *keySeq = NULL;
23044                     return (-1);
23045                 }
23046             }
23047             /*
23048             * Init the node-table item: Save the node, position and
23049             * consume the key-sequence.
23050             */
23051             ntItem->node = vctxt->node;
23052             ntItem->nodeLine = vctxt->inode->nodeLine;
23053             ntItem->keys = *keySeq;
23054             *keySeq = NULL;
23055 #if 0
23056             if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23057 #endif
23058             if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23059                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23060                     /*
23061                     * Free the item, since keyref items won't be
23062                     * put on a global list.
23063                     */
23064                     xmlFree(ntItem->keys);
23065                     xmlFree(ntItem);
23066                 }
23067                 return (-1);
23068             }
23069
23070             goto selector_leave;
23071 selector_key_error:
23072             {
23073                 xmlChar *str = NULL;
23074                 /*
23075                 * 4.2.1 (KEY) The ï¿½target node set� and the
23076                 * ï¿½qualified node set� are equal, that is, every
23077                 * member of the ï¿½target node set� is also a member
23078                 * of the ï¿½qualified node set� and vice versa.
23079                 */
23080                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23081                     XML_SCHEMAV_CVC_IDC, NULL,
23082                     WXS_BASIC_CAST idc,
23083                     "Not all fields of %s evaluate to a node",
23084                     xmlSchemaGetIDCDesignation(&str, idc), NULL);
23085                 FREE_AND_NULL(str);
23086             }
23087 selector_leave:
23088             /*
23089             * Free the key-sequence if not added to the IDC table.
23090             */
23091             if ((keySeq != NULL) && (*keySeq != NULL)) {
23092                 xmlFree(*keySeq);
23093                 *keySeq = NULL;
23094             }
23095         } /* if selector */
23096
23097         sto->nbHistory--;
23098
23099 deregister_check:
23100         /*
23101         * Deregister state objects if they reach the depth of creation.
23102         */
23103         if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23104 #ifdef DEBUG_IDC
23105             xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23106                 sto->sel->xpath);
23107 #endif
23108             if (vctxt->xpathStates != sto) {
23109                 VERROR_INT("xmlSchemaXPathProcessHistory",
23110                     "The state object to be removed is not the first "
23111                     "in the list");
23112             }
23113             nextsto = sto->next;
23114             /*
23115             * Unlink from the list of active XPath state objects.
23116             */
23117             vctxt->xpathStates = sto->next;
23118             sto->next = vctxt->xpathStatePool;
23119             /*
23120             * Link it to the pool of reusable state objects.
23121             */
23122             vctxt->xpathStatePool = sto;
23123             sto = nextsto;
23124         } else
23125             sto = sto->next;
23126     } /* while (sto != NULL) */
23127     return (0);
23128 }
23129
23130 /**
23131  * xmlSchemaIDCRegisterMatchers:
23132  * @vctxt: the WXS validation context
23133  * @elemDecl: the element declaration
23134  *
23135  * Creates helper objects to evaluate IDC selectors/fields
23136  * successively.
23137  *
23138  * Returns 0 if OK and -1 on internal errors.
23139  */
23140 static int
23141 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23142                              xmlSchemaElementPtr elemDecl)
23143 {
23144     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23145     xmlSchemaIDCPtr idc, refIdc;
23146     xmlSchemaIDCAugPtr aidc;
23147
23148     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23149     if (idc == NULL)
23150         return (0);
23151
23152 #ifdef DEBUG_IDC
23153     {
23154         xmlChar *str = NULL;
23155         xmlGenericError(xmlGenericErrorContext,
23156             "IDC: REGISTER on %s, depth %d\n",
23157             (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23158                 vctxt->inode->localName), vctxt->depth);
23159         FREE_AND_NULL(str)
23160     }
23161 #endif
23162     if (vctxt->inode->idcMatchers != NULL) {
23163         VERROR_INT("xmlSchemaIDCRegisterMatchers",
23164             "The chain of IDC matchers is expected to be empty");
23165         return (-1);
23166     }
23167     do {
23168         if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23169             /*
23170             * Since IDCs bubbles are expensive we need to know the
23171             * depth at which the bubbles should stop; this will be
23172             * the depth of the top-most keyref IDC. If no keyref
23173             * references a key/unique IDC, the keyrefDepth will
23174             * be -1, indicating that no bubbles are needed.
23175             */
23176             refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23177             if (refIdc != NULL) {
23178                 /*
23179                 * Remember that we have keyrefs on this node.
23180                 */
23181                 vctxt->inode->hasKeyrefs = 1;
23182                 /*
23183                 * Lookup the referenced augmented IDC info.
23184                 */
23185                 aidc = vctxt->aidcs;
23186                 while (aidc != NULL) {
23187                     if (aidc->def == refIdc)
23188                         break;
23189                     aidc = aidc->next;
23190                 }
23191                 if (aidc == NULL) {
23192                     VERROR_INT("xmlSchemaIDCRegisterMatchers",
23193                         "Could not find an augmented IDC item for an IDC "
23194                         "definition");
23195                     return (-1);
23196                 }
23197                 if ((aidc->keyrefDepth == -1) ||
23198                     (vctxt->depth < aidc->keyrefDepth))
23199                     aidc->keyrefDepth = vctxt->depth;
23200             }
23201         }
23202         /*
23203         * Lookup the augmented IDC item for the IDC definition.
23204         */
23205         aidc = vctxt->aidcs;
23206         while (aidc != NULL) {
23207             if (aidc->def == idc)
23208                 break;
23209             aidc = aidc->next;
23210         }
23211         if (aidc == NULL) {
23212             VERROR_INT("xmlSchemaIDCRegisterMatchers",
23213                 "Could not find an augmented IDC item for an IDC definition");
23214             return (-1);
23215         }
23216         /*
23217         * Create an IDC matcher for every IDC definition.
23218         */
23219         if (vctxt->idcMatcherCache != NULL) {
23220             /*
23221             * Reuse a cached matcher.
23222             */
23223             matcher = vctxt->idcMatcherCache;
23224             vctxt->idcMatcherCache = matcher->nextCached;
23225             matcher->nextCached = NULL;
23226         } else {
23227             matcher = (xmlSchemaIDCMatcherPtr)
23228                 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23229             if (matcher == NULL) {
23230                 xmlSchemaVErrMemory(vctxt,
23231                     "allocating an IDC matcher", NULL);
23232                 return (-1);
23233             }
23234             memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23235         }
23236         if (last == NULL)
23237             vctxt->inode->idcMatchers = matcher;
23238         else
23239             last->next = matcher;
23240         last = matcher;
23241
23242         matcher->type = IDC_MATCHER;
23243         matcher->depth = vctxt->depth;
23244         matcher->aidc = aidc;
23245         matcher->idcType = aidc->def->type;
23246 #ifdef DEBUG_IDC
23247         xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23248 #endif
23249         /*
23250         * Init the automaton state object.
23251         */
23252         if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23253             idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23254             return (-1);
23255
23256         idc = idc->next;
23257     } while (idc != NULL);
23258     return (0);
23259 }
23260
23261 static int
23262 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23263                            xmlSchemaNodeInfoPtr ielem)
23264 {
23265     xmlSchemaPSVIIDCBindingPtr bind;
23266     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23267     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23268     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23269
23270     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23271     /* vctxt->createIDCNodeTables */
23272     while (matcher != NULL) {
23273         /*
23274         * Skip keyref IDCs and empty IDC target-lists.
23275         */
23276         if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23277             WXS_ILIST_IS_EMPTY(matcher->targets))
23278         {
23279             matcher = matcher->next;
23280             continue;
23281         }
23282         /*
23283         * If we _want_ the IDC node-table to be created in any case
23284         * then do so. Otherwise create them only if keyrefs need them.
23285         */
23286         if ((! vctxt->createIDCNodeTables) &&
23287             ((matcher->aidc->keyrefDepth == -1) ||
23288              (matcher->aidc->keyrefDepth > vctxt->depth)))
23289         {
23290             matcher = matcher->next;
23291             continue;
23292         }
23293         /*
23294         * Get/create the IDC binding on this element for the IDC definition.
23295         */
23296         bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23297
23298         if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23299             dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23300             nbDupls = bind->dupls->nbItems;
23301         } else {
23302             dupls = NULL;
23303             nbDupls = 0;
23304         }
23305         if (bind->nodeTable != NULL) {
23306             nbNodeTable = bind->nbNodes;
23307         } else {
23308             nbNodeTable = 0;
23309         }
23310
23311         if ((nbNodeTable == 0) && (nbDupls == 0)) {
23312             /*
23313             * Transfer all IDC target-nodes to the IDC node-table.
23314             */
23315             bind->nodeTable =
23316                 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23317             bind->sizeNodes = matcher->targets->sizeItems;
23318             bind->nbNodes = matcher->targets->nbItems;
23319
23320             matcher->targets->items = NULL;
23321             matcher->targets->sizeItems = 0;
23322             matcher->targets->nbItems = 0;
23323         } else {
23324             /*
23325             * Compare the key-sequences and add to the IDC node-table.
23326             */
23327             nbTargets = matcher->targets->nbItems;
23328             targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23329             nbFields = matcher->aidc->def->nbFields;
23330             i = 0;
23331             do {
23332                 keys = targets[i]->keys;
23333                 if (nbDupls) {
23334                     /*
23335                     * Search in already found duplicates first.
23336                     */
23337                     j = 0;
23338                     do {
23339                         if (nbFields == 1) {
23340                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23341                                 dupls[j]->keys[0]->val);
23342                             if (res == -1)
23343                                 goto internal_error;
23344                             if (res == 1) {
23345                                 /*
23346                                 * Equal key-sequence.
23347                                 */
23348                                 goto next_target;
23349                             }
23350                         } else {
23351                             res = 0;
23352                             ntkeys = dupls[j]->keys;
23353                             for (k = 0; k < nbFields; k++) {
23354                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23355                                     ntkeys[k]->val);
23356                                 if (res == -1)
23357                                     goto internal_error;
23358                                 if (res == 0) {
23359                                     /*
23360                                     * One of the keys differs.
23361                                     */
23362                                     break;
23363                                 }
23364                             }
23365                             if (res == 1) {
23366                                 /*
23367                                 * Equal key-sequence found.
23368                                 */
23369                                 goto next_target;
23370                             }
23371                         }
23372                         j++;
23373                     } while (j < nbDupls);
23374                 }
23375                 if (nbNodeTable) {
23376                     j = 0;
23377                     do {
23378                         if (nbFields == 1) {
23379                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23380                                 bind->nodeTable[j]->keys[0]->val);
23381                             if (res == -1)
23382                                 goto internal_error;
23383                             if (res == 0) {
23384                                 /*
23385                                 * The key-sequence differs.
23386                                 */
23387                                 goto next_node_table_entry;
23388                             }
23389                         } else {
23390                             res = 0;
23391                             ntkeys = bind->nodeTable[j]->keys;
23392                             for (k = 0; k < nbFields; k++) {
23393                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23394                                     ntkeys[k]->val);
23395                                 if (res == -1)
23396                                     goto internal_error;
23397                                 if (res == 0) {
23398                                     /*
23399                                     * One of the keys differs.
23400                                     */
23401                                     goto next_node_table_entry;
23402                                 }
23403                             }
23404                         }
23405                         /*
23406                         * Add the duplicate to the list of duplicates.
23407                         */
23408                         if (bind->dupls == NULL) {
23409                             bind->dupls = xmlSchemaItemListCreate();
23410                             if (bind->dupls == NULL)
23411                                 goto internal_error;
23412                         }
23413                         if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23414                             goto internal_error;
23415                         /*
23416                         * Remove the duplicate entry from the IDC node-table.
23417                         */
23418                         bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23419                         bind->nbNodes--;
23420
23421                         goto next_target;
23422
23423 next_node_table_entry:
23424                         j++;
23425                     } while (j < nbNodeTable);
23426                 }
23427                 /*
23428                 * If everything is fine, then add the IDC target-node to
23429                 * the IDC node-table.
23430                 */
23431                 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23432                     goto internal_error;
23433
23434 next_target:
23435                 i++;
23436             } while (i < nbTargets);
23437         }
23438         matcher = matcher->next;
23439     }
23440     return(0);
23441
23442 internal_error:
23443     return(-1);
23444 }
23445
23446 /**
23447  * xmlSchemaBubbleIDCNodeTables:
23448  * @depth: the current tree depth
23449  *
23450  * Merges IDC bindings of an element at @depth into the corresponding IDC
23451  * bindings of its parent element. If a duplicate note-table entry is found,
23452  * both, the parent node-table entry and child entry are discarded from the
23453  * node-table of the parent.
23454  *
23455  * Returns 0 if OK and -1 on internal errors.
23456  */
23457 static int
23458 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23459 {
23460     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23461     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23462     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23463     xmlSchemaIDCAugPtr aidc;
23464     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23465
23466     bind = vctxt->inode->idcTable;
23467     if (bind == NULL) {
23468         /* Fine, no table, no bubbles. */
23469         return (0);
23470     }
23471
23472     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23473     /*
23474     * Walk all bindings; create new or add to existing bindings.
23475     * Remove duplicate key-sequences.
23476     */
23477     while (bind != NULL) {
23478
23479         if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23480             goto next_binding;
23481         /*
23482         * Check if the key/unique IDC table needs to be bubbled.
23483         */
23484         if (! vctxt->createIDCNodeTables) {
23485             aidc = vctxt->aidcs;
23486             do {
23487                 if (aidc->def == bind->definition) {
23488                     if ((aidc->keyrefDepth == -1) ||
23489                         (aidc->keyrefDepth >= vctxt->depth)) {
23490                         goto next_binding;
23491                     }
23492                     break;
23493                 }
23494                 aidc = aidc->next;
23495             } while (aidc != NULL);
23496         }
23497
23498         if (parTable != NULL)
23499             parBind = *parTable;
23500         /*
23501         * Search a matching parent binding for the
23502         * IDC definition.
23503         */
23504         while (parBind != NULL) {
23505             if (parBind->definition == bind->definition)
23506                 break;
23507             parBind = parBind->next;
23508         }
23509
23510         if (parBind != NULL) {
23511             /*
23512             * Compare every node-table entry of the child node,
23513             * i.e. the key-sequence within, ...
23514             */
23515             oldNum = parBind->nbNodes; /* Skip newly added items. */
23516
23517             if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23518                 oldDupls = parBind->dupls->nbItems;
23519                 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23520             } else {
23521                 dupls = NULL;
23522                 oldDupls = 0;
23523             }
23524
23525             parNodes = parBind->nodeTable;
23526             nbFields = bind->definition->nbFields;
23527
23528             for (i = 0; i < bind->nbNodes; i++) {
23529                 node = bind->nodeTable[i];
23530                 if (node == NULL)
23531                     continue;
23532                 /*
23533                 * ...with every key-sequence of the parent node, already
23534                 * evaluated to be a duplicate key-sequence.
23535                 */
23536                 if (oldDupls) {
23537                     j = 0;
23538                     while (j < oldDupls) {
23539                         if (nbFields == 1) {
23540                             ret = xmlSchemaAreValuesEqual(
23541                                 node->keys[0]->val,
23542                                 dupls[j]->keys[0]->val);
23543                             if (ret == -1)
23544                                 goto internal_error;
23545                             if (ret == 0) {
23546                                 j++;
23547                                 continue;
23548                             }
23549                         } else {
23550                             parNode = dupls[j];
23551                             for (k = 0; k < nbFields; k++) {
23552                                 ret = xmlSchemaAreValuesEqual(
23553                                     node->keys[k]->val,
23554                                     parNode->keys[k]->val);
23555                                 if (ret == -1)
23556                                     goto internal_error;
23557                                 if (ret == 0)
23558                                     break;
23559                             }
23560                         }
23561                         if (ret == 1)
23562                             /* Duplicate found. */
23563                             break;
23564                         j++;
23565                     }
23566                     if (j != oldDupls) {
23567                         /* Duplicate found. Skip this entry. */
23568                         continue;
23569                     }
23570                 }
23571                 /*
23572                 * ... and with every key-sequence of the parent node.
23573                 */
23574                 if (oldNum) {
23575                     j = 0;
23576                     while (j < oldNum) {
23577                         parNode = parNodes[j];
23578                         if (nbFields == 1) {
23579                             ret = xmlSchemaAreValuesEqual(
23580                                 node->keys[0]->val,
23581                                 parNode->keys[0]->val);
23582                             if (ret == -1)
23583                                 goto internal_error;
23584                             if (ret == 0) {
23585                                 j++;
23586                                 continue;
23587                             }
23588                         } else {
23589                             for (k = 0; k < nbFields; k++) {
23590                                 ret = xmlSchemaAreValuesEqual(
23591                                     node->keys[k]->val,
23592                                     parNode->keys[k]->val);
23593                                 if (ret == -1)
23594                                     goto internal_error;
23595                                 if (ret == 0)
23596                                     break;
23597                             }
23598                         }
23599                         if (ret == 1)
23600                             /* Duplicate found. */
23601                             break;
23602                         j++;
23603                     }
23604                     if (j != oldNum) {
23605                         /*
23606                         * Handle duplicates. Move the duplicate in
23607                         * the parent's node-table to the list of
23608                         * duplicates.
23609                         */
23610                         oldNum--;
23611                         parBind->nbNodes--;
23612                         /*
23613                         * Move last old item to pos of duplicate.
23614                         */
23615                         parNodes[j] = parNodes[oldNum];
23616
23617                         if (parBind->nbNodes != oldNum) {
23618                             /*
23619                             * If new items exist, move last new item to
23620                             * last of old items.
23621                             */
23622                             parNodes[oldNum] =
23623                                 parNodes[parBind->nbNodes];
23624                         }
23625                         if (parBind->dupls == NULL) {
23626                             parBind->dupls = xmlSchemaItemListCreate();
23627                             if (parBind->dupls == NULL)
23628                                 goto internal_error;
23629                         }
23630                         xmlSchemaItemListAdd(parBind->dupls, parNode);
23631                     } else {
23632                         /*
23633                         * Add the node-table entry (node and key-sequence) of
23634                         * the child node to the node table of the parent node.
23635                         */
23636                         if (parBind->nodeTable == NULL) {
23637                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23638                                 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23639                             if (parBind->nodeTable == NULL) {
23640                                 xmlSchemaVErrMemory(NULL,
23641                                     "allocating IDC list of node-table items", NULL);
23642                                 goto internal_error;
23643                             }
23644                             parBind->sizeNodes = 1;
23645                         } else if (parBind->nbNodes >= parBind->sizeNodes) {
23646                             parBind->sizeNodes *= 2;
23647                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23648                                 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23649                                 sizeof(xmlSchemaPSVIIDCNodePtr));
23650                             if (parBind->nodeTable == NULL) {
23651                                 xmlSchemaVErrMemory(NULL,
23652                                     "re-allocating IDC list of node-table items", NULL);
23653                                 goto internal_error;
23654                             }
23655                         }
23656                         parNodes = parBind->nodeTable;
23657                         /*
23658                         * Append the new node-table entry to the 'new node-table
23659                         * entries' section.
23660                         */
23661                         parNodes[parBind->nbNodes++] = node;
23662                     }
23663
23664                 }
23665
23666             }
23667         } else {
23668             /*
23669             * No binding for the IDC was found: create a new one and
23670             * copy all node-tables.
23671             */
23672             parBind = xmlSchemaIDCNewBinding(bind->definition);
23673             if (parBind == NULL)
23674                 goto internal_error;
23675
23676             /*
23677             * TODO: Hmm, how to optimize the initial number of
23678             * allocated entries?
23679             */
23680             if (bind->nbNodes != 0) {
23681                 /*
23682                 * Add all IDC node-table entries.
23683                 */
23684                 if (! vctxt->psviExposeIDCNodeTables) {
23685                     /*
23686                     * Just move the entries.
23687                     * NOTE: this is quite save here, since
23688                     * all the keyref lookups have already been
23689                     * performed.
23690                     */
23691                     parBind->nodeTable = bind->nodeTable;
23692                     bind->nodeTable = NULL;
23693                     parBind->sizeNodes = bind->sizeNodes;
23694                     bind->sizeNodes = 0;
23695                     parBind->nbNodes = bind->nbNodes;
23696                     bind->nbNodes = 0;
23697                 } else {
23698                     /*
23699                     * Copy the entries.
23700                     */
23701                     parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23702                         xmlMalloc(bind->nbNodes *
23703                         sizeof(xmlSchemaPSVIIDCNodePtr));
23704                     if (parBind->nodeTable == NULL) {
23705                         xmlSchemaVErrMemory(NULL,
23706                             "allocating an array of IDC node-table "
23707                             "items", NULL);
23708                         xmlSchemaIDCFreeBinding(parBind);
23709                         goto internal_error;
23710                     }
23711                     parBind->sizeNodes = bind->nbNodes;
23712                     parBind->nbNodes = bind->nbNodes;
23713                     memcpy(parBind->nodeTable, bind->nodeTable,
23714                         bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23715                 }
23716             }
23717             if (bind->dupls) {
23718                 /*
23719                 * Move the duplicates.
23720                 */
23721                 if (parBind->dupls != NULL)
23722                     xmlSchemaItemListFree(parBind->dupls);
23723                 parBind->dupls = bind->dupls;
23724                 bind->dupls = NULL;
23725             }
23726             if (parTable != NULL) {
23727                 if (*parTable == NULL)
23728                     *parTable = parBind;
23729                 else {
23730                     parBind->next = *parTable;
23731                     *parTable = parBind;
23732                 }
23733             }
23734         }
23735
23736 next_binding:
23737         bind = bind->next;
23738     }
23739     return (0);
23740
23741 internal_error:
23742     return(-1);
23743 }
23744
23745 /**
23746  * xmlSchemaCheckCVCIDCKeyRef:
23747  * @vctxt: the WXS validation context
23748  * @elemDecl: the element declaration
23749  *
23750  * Check the cvc-idc-keyref constraints.
23751  */
23752 static int
23753 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23754 {
23755     xmlSchemaIDCMatcherPtr matcher;
23756     xmlSchemaPSVIIDCBindingPtr bind;
23757
23758     matcher = vctxt->inode->idcMatchers;
23759     /*
23760     * Find a keyref.
23761     */
23762     while (matcher != NULL) {
23763         if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23764             matcher->targets &&
23765             matcher->targets->nbItems)
23766         {
23767             int i, j, k, res, nbFields, hasDupls;
23768             xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23769             xmlSchemaPSVIIDCNodePtr refNode = NULL;
23770
23771             nbFields = matcher->aidc->def->nbFields;
23772
23773             /*
23774             * Find the IDC node-table for the referenced IDC key/unique.
23775             */
23776             bind = vctxt->inode->idcTable;
23777             while (bind != NULL) {
23778                 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23779                     bind->definition)
23780                     break;
23781                 bind = bind->next;
23782             }
23783             hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23784             /*
23785             * Search for a matching key-sequences.
23786             */
23787             for (i = 0; i < matcher->targets->nbItems; i++) {
23788                 res = 0;
23789                 refNode = matcher->targets->items[i];
23790                 if (bind != NULL) {
23791                     refKeys = refNode->keys;
23792                     for (j = 0; j < bind->nbNodes; j++) {
23793                         keys = bind->nodeTable[j]->keys;
23794                         for (k = 0; k < nbFields; k++) {
23795                             res = xmlSchemaAreValuesEqual(keys[k]->val,
23796                                 refKeys[k]->val);
23797                             if (res == 0)
23798                                 break;
23799                             else if (res == -1) {
23800                                 return (-1);
23801                             }
23802                         }
23803                         if (res == 1) {
23804                             /*
23805                             * Match found.
23806                             */
23807                             break;
23808                         }
23809                     }
23810                     if ((res == 0) && hasDupls) {
23811                         /*
23812                         * Search in duplicates
23813                         */
23814                         for (j = 0; j < bind->dupls->nbItems; j++) {
23815                             keys = ((xmlSchemaPSVIIDCNodePtr)
23816                                 bind->dupls->items[j])->keys;
23817                             for (k = 0; k < nbFields; k++) {
23818                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23819                                     refKeys[k]->val);
23820                                 if (res == 0)
23821                                     break;
23822                                 else if (res == -1) {
23823                                     return (-1);
23824                                 }
23825                             }
23826                             if (res == 1) {
23827                                 /*
23828                                 * Match in duplicates found.
23829                                 */
23830                                 xmlChar *str = NULL, *strB = NULL;
23831                                 xmlSchemaKeyrefErr(vctxt,
23832                                     XML_SCHEMAV_CVC_IDC, refNode,
23833                                     (xmlSchemaTypePtr) matcher->aidc->def,
23834                                     "More than one match found for "
23835                                     "key-sequence %s of keyref '%s'",
23836                                     xmlSchemaFormatIDCKeySequence(vctxt, &str,
23837                                         refNode->keys, nbFields),
23838                                     xmlSchemaGetComponentQName(&strB,
23839                                         matcher->aidc->def));
23840                                 FREE_AND_NULL(str);
23841                                 FREE_AND_NULL(strB);
23842                                 break;
23843                             }
23844                         }
23845                     }
23846                 }
23847
23848                 if (res == 0) {
23849                     xmlChar *str = NULL, *strB = NULL;
23850                     xmlSchemaKeyrefErr(vctxt,
23851                         XML_SCHEMAV_CVC_IDC, refNode,
23852                         (xmlSchemaTypePtr) matcher->aidc->def,
23853                         "No match found for key-sequence %s of keyref '%s'",
23854                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23855                             refNode->keys, nbFields),
23856                         xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23857                     FREE_AND_NULL(str);
23858                     FREE_AND_NULL(strB);
23859                 }
23860             }
23861         }
23862         matcher = matcher->next;
23863     }
23864     /* TODO: Return an error if any error encountered. */
23865     return (0);
23866 }
23867
23868 /************************************************************************
23869  *                                                                      *
23870  *                      XML Reader validation code                      *
23871  *                                                                      *
23872  ************************************************************************/
23873
23874 static xmlSchemaAttrInfoPtr
23875 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23876 {
23877     xmlSchemaAttrInfoPtr iattr;
23878     /*
23879     * Grow/create list of attribute infos.
23880     */
23881     if (vctxt->attrInfos == NULL) {
23882         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23883             xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23884         vctxt->sizeAttrInfos = 1;
23885         if (vctxt->attrInfos == NULL) {
23886             xmlSchemaVErrMemory(vctxt,
23887                 "allocating attribute info list", NULL);
23888             return (NULL);
23889         }
23890     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23891         vctxt->sizeAttrInfos++;
23892         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23893             xmlRealloc(vctxt->attrInfos,
23894                 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23895         if (vctxt->attrInfos == NULL) {
23896             xmlSchemaVErrMemory(vctxt,
23897                 "re-allocating attribute info list", NULL);
23898             return (NULL);
23899         }
23900     } else {
23901         iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23902         if (iattr->localName != NULL) {
23903             VERROR_INT("xmlSchemaGetFreshAttrInfo",
23904                 "attr info not cleared");
23905             return (NULL);
23906         }
23907         iattr->nodeType = XML_ATTRIBUTE_NODE;
23908         return (iattr);
23909     }
23910     /*
23911     * Create an attribute info.
23912     */
23913     iattr = (xmlSchemaAttrInfoPtr)
23914         xmlMalloc(sizeof(xmlSchemaAttrInfo));
23915     if (iattr == NULL) {
23916         xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23917         return (NULL);
23918     }
23919     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23920     iattr->nodeType = XML_ATTRIBUTE_NODE;
23921     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23922
23923     return (iattr);
23924 }
23925
23926 static int
23927 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23928                         xmlNodePtr attrNode,
23929                         int nodeLine,
23930                         const xmlChar *localName,
23931                         const xmlChar *nsName,
23932                         int ownedNames,
23933                         xmlChar *value,
23934                         int ownedValue)
23935 {
23936     xmlSchemaAttrInfoPtr attr;
23937
23938     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23939     if (attr == NULL) {
23940         VERROR_INT("xmlSchemaPushAttribute",
23941             "calling xmlSchemaGetFreshAttrInfo()");
23942         return (-1);
23943     }
23944     attr->node = attrNode;
23945     attr->nodeLine = nodeLine;
23946     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23947     attr->localName = localName;
23948     attr->nsName = nsName;
23949     if (ownedNames)
23950         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23951     /*
23952     * Evaluate if it's an XSI attribute.
23953     */
23954     if (nsName != NULL) {
23955         if (xmlStrEqual(localName, BAD_CAST "nil")) {
23956             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23957                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23958             }
23959         } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23960             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23961                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23962             }
23963         } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23964             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23965                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23966             }
23967         } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23968             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23969                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23970             }
23971         } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23972             attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23973         }
23974     }
23975     attr->value = value;
23976     if (ownedValue)
23977         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23978     if (attr->metaType != 0)
23979         attr->state = XML_SCHEMAS_ATTR_META;
23980     return (0);
23981 }
23982
23983 /**
23984  * xmlSchemaClearElemInfo:
23985  * @vctxt: the WXS validation context
23986  * @ielem: the element information item
23987  */
23988 static void
23989 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23990                        xmlSchemaNodeInfoPtr ielem)
23991 {
23992     ielem->hasKeyrefs = 0;
23993     ielem->appliedXPath = 0;
23994     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23995         FREE_AND_NULL(ielem->localName);
23996         FREE_AND_NULL(ielem->nsName);
23997     } else {
23998         ielem->localName = NULL;
23999         ielem->nsName = NULL;
24000     }
24001     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24002         FREE_AND_NULL(ielem->value);
24003     } else {
24004         ielem->value = NULL;
24005     }
24006     if (ielem->val != NULL) {
24007         /*
24008         * PSVI TODO: Be careful not to free it when the value is
24009         * exposed via PSVI.
24010         */
24011         xmlSchemaFreeValue(ielem->val);
24012         ielem->val = NULL;
24013     }
24014     if (ielem->idcMatchers != NULL) {
24015         /*
24016         * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24017         *   Does it work?
24018         */
24019         xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24020 #if 0
24021         xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24022 #endif
24023         ielem->idcMatchers = NULL;
24024     }
24025     if (ielem->idcTable != NULL) {
24026         /*
24027         * OPTIMIZE TODO: Use a pool of IDC tables??.
24028         */
24029         xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24030         ielem->idcTable = NULL;
24031     }
24032     if (ielem->regexCtxt != NULL) {
24033         xmlRegFreeExecCtxt(ielem->regexCtxt);
24034         ielem->regexCtxt = NULL;
24035     }
24036     if (ielem->nsBindings != NULL) {
24037         xmlFree((xmlChar **)ielem->nsBindings);
24038         ielem->nsBindings = NULL;
24039         ielem->nbNsBindings = 0;
24040         ielem->sizeNsBindings = 0;
24041     }
24042 }
24043
24044 /**
24045  * xmlSchemaGetFreshElemInfo:
24046  * @vctxt: the schema validation context
24047  *
24048  * Creates/reuses and initializes the element info item for
24049  * the currect tree depth.
24050  *
24051  * Returns the element info item or NULL on API or internal errors.
24052  */
24053 static xmlSchemaNodeInfoPtr
24054 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24055 {
24056     xmlSchemaNodeInfoPtr info = NULL;
24057
24058     if (vctxt->depth > vctxt->sizeElemInfos) {
24059         VERROR_INT("xmlSchemaGetFreshElemInfo",
24060             "inconsistent depth encountered");
24061         return (NULL);
24062     }
24063     if (vctxt->elemInfos == NULL) {
24064         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24065             xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24066         if (vctxt->elemInfos == NULL) {
24067             xmlSchemaVErrMemory(vctxt,
24068                 "allocating the element info array", NULL);
24069             return (NULL);
24070         }
24071         memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24072         vctxt->sizeElemInfos = 10;
24073     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24074         int i = vctxt->sizeElemInfos;
24075
24076         vctxt->sizeElemInfos *= 2;
24077         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24078             xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24079             sizeof(xmlSchemaNodeInfoPtr));
24080         if (vctxt->elemInfos == NULL) {
24081             xmlSchemaVErrMemory(vctxt,
24082                 "re-allocating the element info array", NULL);
24083             return (NULL);
24084         }
24085         /*
24086         * We need the new memory to be NULLed.
24087         * TODO: Use memset instead?
24088         */
24089         for (; i < vctxt->sizeElemInfos; i++)
24090             vctxt->elemInfos[i] = NULL;
24091     } else
24092         info = vctxt->elemInfos[vctxt->depth];
24093
24094     if (info == NULL) {
24095         info = (xmlSchemaNodeInfoPtr)
24096             xmlMalloc(sizeof(xmlSchemaNodeInfo));
24097         if (info == NULL) {
24098             xmlSchemaVErrMemory(vctxt,
24099                 "allocating an element info", NULL);
24100             return (NULL);
24101         }
24102         vctxt->elemInfos[vctxt->depth] = info;
24103     } else {
24104         if (info->localName != NULL) {
24105             VERROR_INT("xmlSchemaGetFreshElemInfo",
24106                 "elem info has not been cleared");
24107             return (NULL);
24108         }
24109     }
24110     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24111     info->nodeType = XML_ELEMENT_NODE;
24112     info->depth = vctxt->depth;
24113
24114     return (info);
24115 }
24116
24117 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24118 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24119 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24120
24121 static int
24122 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24123                         xmlNodePtr node,
24124                         xmlSchemaTypePtr type,
24125                         xmlSchemaValType valType,
24126                         const xmlChar * value,
24127                         xmlSchemaValPtr val,
24128                         unsigned long length,
24129                         int fireErrors)
24130 {
24131     int ret, error = 0;
24132
24133     xmlSchemaTypePtr tmpType;
24134     xmlSchemaFacetLinkPtr facetLink;
24135     xmlSchemaFacetPtr facet;
24136     unsigned long len = 0;
24137     xmlSchemaWhitespaceValueType ws;
24138
24139     /*
24140     * In Libxml2, derived built-in types have currently no explicit facets.
24141     */
24142     if (type->type == XML_SCHEMA_TYPE_BASIC)
24143         return (0);
24144
24145     /*
24146     * NOTE: Do not jump away, if the facetSet of the given type is
24147     * empty: until now, "pattern" and "enumeration" facets of the
24148     * *base types* need to be checked as well.
24149     */
24150     if (type->facetSet == NULL)
24151         goto pattern_and_enum;
24152
24153     if (! WXS_IS_ATOMIC(type)) {
24154         if (WXS_IS_LIST(type))
24155             goto WXS_IS_LIST;
24156         else
24157             goto pattern_and_enum;
24158     }
24159     /*
24160     * Whitespace handling is only of importance for string-based
24161     * types.
24162     */
24163     tmpType = xmlSchemaGetPrimitiveType(type);
24164     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24165         WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24166         ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24167     } else
24168         ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24169     /*
24170     * If the value was not computed (for string or
24171     * anySimpleType based types), then use the provided
24172     * type.
24173     */
24174     if (val == NULL)
24175         valType = valType;
24176     else
24177         valType = xmlSchemaGetValType(val);
24178
24179     ret = 0;
24180     for (facetLink = type->facetSet; facetLink != NULL;
24181         facetLink = facetLink->next) {
24182         /*
24183         * Skip the pattern "whiteSpace": it is used to
24184         * format the character content beforehand.
24185         */
24186         switch (facetLink->facet->type) {
24187             case XML_SCHEMA_FACET_WHITESPACE:
24188             case XML_SCHEMA_FACET_PATTERN:
24189             case XML_SCHEMA_FACET_ENUMERATION:
24190                 continue;
24191             case XML_SCHEMA_FACET_LENGTH:
24192             case XML_SCHEMA_FACET_MINLENGTH:
24193             case XML_SCHEMA_FACET_MAXLENGTH:
24194                 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24195                     valType, value, val, &len, ws);
24196                 break;
24197             default:
24198                 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24199                     valType, value, val, ws);
24200                 break;
24201         }
24202         if (ret < 0) {
24203             AERROR_INT("xmlSchemaValidateFacets",
24204                 "validating against a atomic type facet");
24205             return (-1);
24206         } else if (ret > 0) {
24207             if (fireErrors)
24208                 xmlSchemaFacetErr(actxt, ret, node,
24209                 value, len, type, facetLink->facet, NULL, NULL, NULL);
24210             else
24211                 return (ret);
24212             if (error == 0)
24213                 error = ret;
24214         }
24215         ret = 0;
24216     }
24217
24218 WXS_IS_LIST:
24219     if (! WXS_IS_LIST(type))
24220         goto pattern_and_enum;
24221     /*
24222     * "length", "minLength" and "maxLength" of list types.
24223     */
24224     ret = 0;
24225     for (facetLink = type->facetSet; facetLink != NULL;
24226         facetLink = facetLink->next) {
24227
24228         switch (facetLink->facet->type) {
24229             case XML_SCHEMA_FACET_LENGTH:
24230             case XML_SCHEMA_FACET_MINLENGTH:
24231             case XML_SCHEMA_FACET_MAXLENGTH:
24232                 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24233                     value, length, NULL);
24234                 break;
24235             default:
24236                 continue;
24237         }
24238         if (ret < 0) {
24239             AERROR_INT("xmlSchemaValidateFacets",
24240                 "validating against a list type facet");
24241             return (-1);
24242         } else if (ret > 0) {
24243             if (fireErrors)
24244                 xmlSchemaFacetErr(actxt, ret, node,
24245                 value, length, type, facetLink->facet, NULL, NULL, NULL);
24246             else
24247                 return (ret);
24248             if (error == 0)
24249                 error = ret;
24250         }
24251         ret = 0;
24252     }
24253
24254 pattern_and_enum:
24255     if (error >= 0) {
24256         int found = 0;
24257         /*
24258         * Process enumerations. Facet values are in the value space
24259         * of the defining type's base type. This seems to be a bug in the
24260         * XML Schema 1.0 spec. Use the whitespace type of the base type.
24261         * Only the first set of enumerations in the ancestor-or-self axis
24262         * is used for validation.
24263         */
24264         ret = 0;
24265         tmpType = type;
24266         do {
24267             for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24268                 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24269                     continue;
24270                 found = 1;
24271                 ret = xmlSchemaAreValuesEqual(facet->val, val);
24272                 if (ret == 1)
24273                     break;
24274                 else if (ret < 0) {
24275                     AERROR_INT("xmlSchemaValidateFacets",
24276                         "validating against an enumeration facet");
24277                     return (-1);
24278                 }
24279             }
24280             if (ret != 0)
24281                 break;
24282             /*
24283             * Break on the first set of enumerations. Any additional
24284             *  enumerations which might be existent on the ancestors
24285             *  of the current type are restricted by this set; thus
24286             *  *must* *not* be taken into account.
24287             */
24288             if (found)
24289                 break;
24290             tmpType = tmpType->baseType;
24291         } while ((tmpType != NULL) &&
24292             (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24293         if (found && (ret == 0)) {
24294             ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24295             if (fireErrors) {
24296                 xmlSchemaFacetErr(actxt, ret, node,
24297                     value, 0, type, NULL, NULL, NULL, NULL);
24298             } else
24299                 return (ret);
24300             if (error == 0)
24301                 error = ret;
24302         }
24303     }
24304
24305     if (error >= 0) {
24306         int found;
24307         /*
24308         * Process patters. Pattern facets are ORed at type level
24309         * and ANDed if derived. Walk the base type axis.
24310         */
24311         tmpType = type;
24312         facet = NULL;
24313         do {
24314             found = 0;
24315             for (facetLink = tmpType->facetSet; facetLink != NULL;
24316                 facetLink = facetLink->next) {
24317                 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24318                     continue;
24319                 found = 1;
24320                 /*
24321                 * NOTE that for patterns, @value needs to be the
24322                 * normalized vaule.
24323                 */
24324                 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24325                 if (ret == 1)
24326                     break;
24327                 else if (ret < 0) {
24328                     AERROR_INT("xmlSchemaValidateFacets",
24329                         "validating against a pattern facet");
24330                     return (-1);
24331                 } else {
24332                     /*
24333                     * Save the last non-validating facet.
24334                     */
24335                     facet = facetLink->facet;
24336                 }
24337             }
24338             if (found && (ret != 1)) {
24339                 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24340                 if (fireErrors) {
24341                     xmlSchemaFacetErr(actxt, ret, node,
24342                         value, 0, type, facet, NULL, NULL, NULL);
24343                 } else
24344                     return (ret);
24345                 if (error == 0)
24346                     error = ret;
24347                 break;
24348             }
24349             tmpType = tmpType->baseType;
24350         } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24351     }
24352
24353     return (error);
24354 }
24355
24356 static xmlChar *
24357 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24358                         const xmlChar *value)
24359 {
24360     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24361         case XML_SCHEMA_WHITESPACE_COLLAPSE:
24362             return (xmlSchemaCollapseString(value));
24363         case XML_SCHEMA_WHITESPACE_REPLACE:
24364             return (xmlSchemaWhiteSpaceReplace(value));
24365         default:
24366             return (NULL);
24367     }
24368 }
24369
24370 static int
24371 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24372                        const xmlChar *value,
24373                        xmlSchemaValPtr *val,
24374                        int valNeeded)
24375 {
24376     int ret;
24377     const xmlChar *nsName;
24378     xmlChar *local, *prefix = NULL;
24379
24380     ret = xmlValidateQName(value, 1);
24381     if (ret != 0) {
24382         if (ret == -1) {
24383             VERROR_INT("xmlSchemaValidateQName",
24384                 "calling xmlValidateQName()");
24385             return (-1);
24386         }
24387         return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24388     }
24389     /*
24390     * NOTE: xmlSplitQName2 will always return a duplicated
24391     * strings.
24392     */
24393     local = xmlSplitQName2(value, &prefix);
24394     if (local == NULL)
24395         local = xmlStrdup(value);
24396     /*
24397     * OPTIMIZE TODO: Use flags for:
24398     *  - is there any namespace binding?
24399     *  - is there a default namespace?
24400     */
24401     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24402
24403     if (prefix != NULL) {
24404         xmlFree(prefix);
24405         /*
24406         * A namespace must be found if the prefix is
24407         * NOT NULL.
24408         */
24409         if (nsName == NULL) {
24410             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24411             xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24412                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24413                 "The QName value '%s' has no "
24414                 "corresponding namespace declaration in "
24415                 "scope", value, NULL);
24416             if (local != NULL)
24417                 xmlFree(local);
24418             return (ret);
24419         }
24420     }
24421     if (valNeeded && val) {
24422         if (nsName != NULL)
24423             *val = xmlSchemaNewQNameValue(
24424                 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24425         else
24426             *val = xmlSchemaNewQNameValue(NULL,
24427                 BAD_CAST local);
24428     } else
24429         xmlFree(local);
24430     return (0);
24431 }
24432
24433 /*
24434 * cvc-simple-type
24435 */
24436 static int
24437 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24438                              xmlNodePtr node,
24439                              xmlSchemaTypePtr type,
24440                              const xmlChar *value,
24441                              xmlSchemaValPtr *retVal,
24442                              int fireErrors,
24443                              int normalize,
24444                              int isNormalized)
24445 {
24446     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24447     xmlSchemaValPtr val = NULL;
24448     /* xmlSchemaWhitespaceValueType ws; */
24449     xmlChar *normValue = NULL;
24450
24451 #define NORMALIZE(atype) \
24452     if ((! isNormalized) && \
24453     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24454         normValue = xmlSchemaNormalizeValue(atype, value); \
24455         if (normValue != NULL) \
24456             value = normValue; \
24457         isNormalized = 1; \
24458     }
24459
24460     if ((retVal != NULL) && (*retVal != NULL)) {
24461         xmlSchemaFreeValue(*retVal);
24462         *retVal = NULL;
24463     }
24464     /*
24465     * 3.14.4 Simple Type Definition Validation Rules
24466     * Validation Rule: String Valid
24467     */
24468     /*
24469     * 1 It is schema-valid with respect to that definition as defined
24470     * by Datatype Valid in [XML Schemas: Datatypes].
24471     */
24472     /*
24473     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24474     * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24475     * the string must be a ï¿½declared entity name�.
24476     */
24477     /*
24478     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24479     * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24480     * then every whitespace-delimited substring of the string must be a ï¿½declared
24481     * entity name�.
24482     */
24483     /*
24484     * 2.3 otherwise no further condition applies.
24485     */
24486     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24487         valNeeded = 1;
24488     if (value == NULL)
24489         value = BAD_CAST "";
24490     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24491         xmlSchemaTypePtr biType; /* The built-in type. */
24492         /*
24493         * SPEC (1.2.1) "if {variety} is ï¿½atomic� then the string must ï¿½match�
24494         * a literal in the ï¿½lexical space� of {base type definition}"
24495         */
24496         /*
24497         * Whitespace-normalize.
24498         */
24499         NORMALIZE(type);
24500         if (type->type != XML_SCHEMA_TYPE_BASIC) {
24501             /*
24502             * Get the built-in type.
24503             */
24504             biType = type->baseType;
24505             while ((biType != NULL) &&
24506                 (biType->type != XML_SCHEMA_TYPE_BASIC))
24507                 biType = biType->baseType;
24508
24509             if (biType == NULL) {
24510                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24511                     "could not get the built-in type");
24512                 goto internal_error;
24513             }
24514         } else
24515             biType = type;
24516         /*
24517         * NOTATIONs need to be processed here, since they need
24518         * to lookup in the hashtable of NOTATION declarations of the schema.
24519         */
24520         if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24521             switch (biType->builtInType) {
24522                 case XML_SCHEMAS_NOTATION:
24523                     ret = xmlSchemaValidateNotation(
24524                         (xmlSchemaValidCtxtPtr) actxt,
24525                         ((xmlSchemaValidCtxtPtr) actxt)->schema,
24526                         NULL, value, &val, valNeeded);
24527                     break;
24528                 case XML_SCHEMAS_QNAME:
24529                     ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24530                         value, &val, valNeeded);
24531                     break;
24532                 default:
24533                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24534                     if (valNeeded)
24535                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24536                             value, &val, node);
24537                     else
24538                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24539                             value, NULL, node);
24540                     break;
24541             }
24542         } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24543             switch (biType->builtInType) {
24544                 case XML_SCHEMAS_NOTATION:
24545                     ret = xmlSchemaValidateNotation(NULL,
24546                         ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24547                         value, &val, valNeeded);
24548                     break;
24549                 default:
24550                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24551                     if (valNeeded)
24552                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24553                             value, &val, node);
24554                     else
24555                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24556                             value, NULL, node);
24557                     break;
24558             }
24559         } else {
24560             /*
24561             * Validation via a public API is not implemented yet.
24562             */
24563             TODO
24564             goto internal_error;
24565         }
24566         if (ret != 0) {
24567             if (ret < 0) {
24568                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24569                     "validating against a built-in type");
24570                 goto internal_error;
24571             }
24572             if (WXS_IS_LIST(type))
24573                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24574             else
24575                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24576         }
24577         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24578             /*
24579             * Check facets.
24580             */
24581             ret = xmlSchemaValidateFacets(actxt, node, type,
24582                 (xmlSchemaValType) biType->builtInType, value, val,
24583                 0, fireErrors);
24584             if (ret != 0) {
24585                 if (ret < 0) {
24586                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24587                         "validating facets of atomic simple type");
24588                     goto internal_error;
24589                 }
24590                 if (WXS_IS_LIST(type))
24591                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24592                 else
24593                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24594             }
24595         }
24596         if (fireErrors && (ret > 0))
24597             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24598     } else if (WXS_IS_LIST(type)) {
24599
24600         xmlSchemaTypePtr itemType;
24601         const xmlChar *cur, *end;
24602         xmlChar *tmpValue = NULL;
24603         unsigned long len = 0;
24604         xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24605         /* 1.2.2 if {variety} is ï¿½list� then the string must be a sequence
24606         * of white space separated tokens, each of which ï¿½match�es a literal
24607         * in the ï¿½lexical space� of {item type definition}
24608         */
24609         /*
24610         * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24611         * the list type has an enum or pattern facet.
24612         */
24613         NORMALIZE(type);
24614         /*
24615         * VAL TODO: Optimize validation of empty values.
24616         * VAL TODO: We do not have computed values for lists.
24617         */
24618         itemType = WXS_LIST_ITEMTYPE(type);
24619         cur = value;
24620         do {
24621             while (IS_BLANK_CH(*cur))
24622                 cur++;
24623             end = cur;
24624             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24625                 end++;
24626             if (end == cur)
24627                 break;
24628             tmpValue = xmlStrndup(cur, end - cur);
24629             len++;
24630
24631             if (valNeeded)
24632                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24633                     tmpValue, &curVal, fireErrors, 0, 1);
24634             else
24635                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24636                     tmpValue, NULL, fireErrors, 0, 1);
24637             FREE_AND_NULL(tmpValue);
24638             if (curVal != NULL) {
24639                 /*
24640                 * Add to list of computed values.
24641                 */
24642                 if (val == NULL)
24643                     val = curVal;
24644                 else
24645                     xmlSchemaValueAppend(prevVal, curVal);
24646                 prevVal = curVal;
24647                 curVal = NULL;
24648             }
24649             if (ret != 0) {
24650                 if (ret < 0) {
24651                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24652                         "validating an item of list simple type");
24653                     goto internal_error;
24654                 }
24655                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24656                 break;
24657             }
24658             cur = end;
24659         } while (*cur != 0);
24660         FREE_AND_NULL(tmpValue);
24661         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24662             /*
24663             * Apply facets (pattern, enumeration).
24664             */
24665             ret = xmlSchemaValidateFacets(actxt, node, type,
24666                 XML_SCHEMAS_UNKNOWN, value, val,
24667                 len, fireErrors);
24668             if (ret != 0) {
24669                 if (ret < 0) {
24670                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24671                         "validating facets of list simple type");
24672                     goto internal_error;
24673                 }
24674                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24675             }
24676         }
24677         if (fireErrors && (ret > 0)) {
24678             /*
24679             * Report the normalized value.
24680             */
24681             normalize = 1;
24682             NORMALIZE(type);
24683             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24684         }
24685     } else if (WXS_IS_UNION(type)) {
24686         xmlSchemaTypeLinkPtr memberLink;
24687         /*
24688         * TODO: For all datatypes ï¿½derived� by ï¿½union�  whiteSpace does
24689         * not apply directly; however, the normalization behavior of ï¿½union�
24690         * types is controlled by the value of whiteSpace on that one of the
24691         * ï¿½memberTypes� against which the ï¿½union� is successfully validated.
24692         *
24693         * This means that the value is normalized by the first validating
24694         * member type, then the facets of the union type are applied. This
24695         * needs changing of the value!
24696         */
24697
24698         /*
24699         * 1.2.3 if {variety} is ï¿½union� then the string must ï¿½match� a
24700         * literal in the ï¿½lexical space� of at least one member of
24701         * {member type definitions}
24702         */
24703         memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24704         if (memberLink == NULL) {
24705             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24706                 "union simple type has no member types");
24707             goto internal_error;
24708         }
24709         /*
24710         * Always normalize union type values, since we currently
24711         * cannot store the whitespace information with the value
24712         * itself; otherwise a later value-comparison would be
24713         * not possible.
24714         */
24715         while (memberLink != NULL) {
24716             if (valNeeded)
24717                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24718                     memberLink->type, value, &val, 0, 1, 0);
24719             else
24720                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24721                     memberLink->type, value, NULL, 0, 1, 0);
24722             if (ret <= 0)
24723                 break;
24724             memberLink = memberLink->next;
24725         }
24726         if (ret != 0) {
24727             if (ret < 0) {
24728                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24729                     "validating members of union simple type");
24730                 goto internal_error;
24731             }
24732             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24733         }
24734         /*
24735         * Apply facets (pattern, enumeration).
24736         */
24737         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24738             /*
24739             * The normalization behavior of ï¿½union� types is controlled by
24740             * the value of whiteSpace on that one of the ï¿½memberTypes�
24741             * against which the ï¿½union� is successfully validated.
24742             */
24743             NORMALIZE(memberLink->type);
24744             ret = xmlSchemaValidateFacets(actxt, node, type,
24745                 XML_SCHEMAS_UNKNOWN, value, val,
24746                 0, fireErrors);
24747             if (ret != 0) {
24748                 if (ret < 0) {
24749                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24750                         "validating facets of union simple type");
24751                     goto internal_error;
24752                 }
24753                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24754             }
24755         }
24756         if (fireErrors && (ret > 0))
24757             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24758     }
24759
24760     if (normValue != NULL)
24761         xmlFree(normValue);
24762     if (ret == 0) {
24763         if (retVal != NULL)
24764             *retVal = val;
24765         else if (val != NULL)
24766             xmlSchemaFreeValue(val);
24767     } else if (val != NULL)
24768         xmlSchemaFreeValue(val);
24769     return (ret);
24770 internal_error:
24771     if (normValue != NULL)
24772         xmlFree(normValue);
24773     if (val != NULL)
24774         xmlSchemaFreeValue(val);
24775     return (-1);
24776 }
24777
24778 static int
24779 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24780                            const xmlChar *value,
24781                            const xmlChar **nsName,
24782                            const xmlChar **localName)
24783 {
24784     int ret = 0;
24785
24786     if ((nsName == NULL) || (localName == NULL))
24787         return (-1);
24788     *nsName = NULL;
24789     *localName = NULL;
24790
24791     ret = xmlValidateQName(value, 1);
24792     if (ret == -1)
24793         return (-1);
24794     if (ret > 0) {
24795         xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24796             XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24797             value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24798         return (1);
24799     }
24800     {
24801         xmlChar *local = NULL;
24802         xmlChar *prefix;
24803
24804         /*
24805         * NOTE: xmlSplitQName2 will return a duplicated
24806         * string.
24807         */
24808         local = xmlSplitQName2(value, &prefix);
24809         if (local == NULL)
24810             *localName = xmlDictLookup(vctxt->dict, value, -1);
24811         else {
24812             *localName = xmlDictLookup(vctxt->dict, local, -1);
24813             xmlFree(local);
24814         }
24815
24816         *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24817
24818         if (prefix != NULL) {
24819             xmlFree(prefix);
24820             /*
24821             * A namespace must be found if the prefix is NOT NULL.
24822             */
24823             if (*nsName == NULL) {
24824                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24825                     XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24826                     WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24827                     "The QName value '%s' has no "
24828                     "corresponding namespace declaration in scope",
24829                     value, NULL);
24830                 return (2);
24831             }
24832         }
24833     }
24834     return (0);
24835 }
24836
24837 static int
24838 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24839                         xmlSchemaAttrInfoPtr iattr,
24840                         xmlSchemaTypePtr *localType,
24841                         xmlSchemaElementPtr elemDecl)
24842 {
24843     int ret = 0;
24844     /*
24845     * cvc-elt (3.3.4) : (4)
24846     * AND
24847     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24848     *   (1.2.1.2.1) - (1.2.1.2.4)
24849     * Handle 'xsi:type'.
24850     */
24851     if (localType == NULL)
24852         return (-1);
24853     *localType = NULL;
24854     if (iattr == NULL)
24855         return (0);
24856     else {
24857         const xmlChar *nsName = NULL, *local = NULL;
24858         /*
24859         * TODO: We should report a *warning* that the type was overriden
24860         * by the instance.
24861         */
24862         ACTIVATE_ATTRIBUTE(iattr);
24863         /*
24864         * (cvc-elt) (3.3.4) : (4.1)
24865         * (cvc-assess-elt) (1.2.1.2.2)
24866         */
24867         ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24868             &nsName, &local);
24869         if (ret != 0) {
24870             if (ret < 0) {
24871                 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24872                     "calling xmlSchemaQNameExpand() to validate the "
24873                     "attribute 'xsi:type'");
24874                 goto internal_error;
24875             }
24876             goto exit;
24877         }
24878         /*
24879         * (cvc-elt) (3.3.4) : (4.2)
24880         * (cvc-assess-elt) (1.2.1.2.3)
24881         */
24882         *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24883         if (*localType == NULL) {
24884             xmlChar *str = NULL;
24885
24886             xmlSchemaCustomErr(ACTXT_CAST vctxt,
24887                 XML_SCHEMAV_CVC_ELT_4_2, NULL,
24888                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24889                 "The QName value '%s' of the xsi:type attribute does not "
24890                 "resolve to a type definition",
24891                 xmlSchemaFormatQName(&str, nsName, local), NULL);
24892             FREE_AND_NULL(str);
24893             ret = vctxt->err;
24894             goto exit;
24895         }
24896         if (elemDecl != NULL) {
24897             int set = 0;
24898
24899             /*
24900             * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24901             * "The ï¿½local type definition� must be validly
24902             * derived from the {type definition} given the union of
24903             * the {disallowed substitutions} and the {type definition}'s
24904             * {prohibited substitutions}, as defined in
24905             * Type Derivation OK (Complex) (�3.4.6)
24906             * (if it is a complex type definition),
24907             * or given {disallowed substitutions} as defined in Type
24908             * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24909             * definition)."
24910             *
24911             * {disallowed substitutions}: the "block" on the element decl.
24912             * {prohibited substitutions}: the "block" on the type def.
24913             */
24914             /*
24915             * OPTIMIZE TODO: We could map types already evaluated
24916             * to be validly derived from other types to avoid checking
24917             * this over and over for the same types.
24918             */
24919             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24920                 (elemDecl->subtypes->flags &
24921                     XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24922                 set |= SUBSET_EXTENSION;
24923
24924             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24925                 (elemDecl->subtypes->flags &
24926                     XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24927                 set |= SUBSET_RESTRICTION;
24928
24929             /*
24930             * REMOVED and CHANGED since this produced a parser context
24931             * which adds to the string dict of the schema. So this would
24932             * change the schema and we don't want this. We don't need
24933             * the parser context anymore.
24934             *
24935             * if ((vctxt->pctxt == NULL) &&
24936             *   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24937             *       return (-1);
24938             */
24939
24940             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24941                 elemDecl->subtypes, set) != 0) {
24942                 xmlChar *str = NULL;
24943
24944                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24945                     XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24946                     "The type definition '%s', specified by xsi:type, is "
24947                     "blocked or not validly derived from the type definition "
24948                     "of the element declaration",
24949                     xmlSchemaFormatQName(&str,
24950                         (*localType)->targetNamespace,
24951                         (*localType)->name),
24952                     NULL);
24953                 FREE_AND_NULL(str);
24954                 ret = vctxt->err;
24955                 *localType = NULL;
24956             }
24957         }
24958     }
24959 exit:
24960     ACTIVATE_ELEM;
24961     return (ret);
24962 internal_error:
24963     ACTIVATE_ELEM;
24964     return (-1);
24965 }
24966
24967 static int
24968 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24969 {
24970     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24971     xmlSchemaTypePtr actualType;
24972
24973     /*
24974     * cvc-elt (3.3.4) : 1
24975     */
24976     if (elemDecl == NULL) {
24977         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24978             "No matching declaration available");
24979         return (vctxt->err);
24980     }
24981     actualType = WXS_ELEM_TYPEDEF(elemDecl);
24982     /*
24983     * cvc-elt (3.3.4) : 2
24984     */
24985     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24986         VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24987             "The element declaration is abstract");
24988         return (vctxt->err);
24989     }
24990     if (actualType == NULL) {
24991         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24992             "The type definition is absent");
24993         return (XML_SCHEMAV_CVC_TYPE_1);
24994     }
24995     if (vctxt->nbAttrInfos != 0) {
24996         int ret;
24997         xmlSchemaAttrInfoPtr iattr;
24998         /*
24999         * cvc-elt (3.3.4) : 3
25000         * Handle 'xsi:nil'.
25001         */
25002         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25003             XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25004         if (iattr) {
25005             ACTIVATE_ATTRIBUTE(iattr);
25006             /*
25007             * Validate the value.
25008             */
25009             ret = xmlSchemaVCheckCVCSimpleType(
25010                 ACTXT_CAST vctxt, NULL,
25011                 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25012                 iattr->value, &(iattr->val), 1, 0, 0);
25013             ACTIVATE_ELEM;
25014             if (ret < 0) {
25015                 VERROR_INT("xmlSchemaValidateElemDecl",
25016                     "calling xmlSchemaVCheckCVCSimpleType() to "
25017                     "validate the attribute 'xsi:nil'");
25018                 return (-1);
25019             }
25020             if (ret == 0) {
25021                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25022                     /*
25023                     * cvc-elt (3.3.4) : 3.1
25024                     */
25025                     VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25026                         "The element is not 'nillable'");
25027                     /* Does not return an error on purpose. */
25028                 } else {
25029                     if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25030                         /*
25031                         * cvc-elt (3.3.4) : 3.2.2
25032                         */
25033                         if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25034                             (elemDecl->value != NULL)) {
25035                             VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25036                                 "The element cannot be 'nilled' because "
25037                                 "there is a fixed value constraint defined "
25038                                 "for it");
25039                              /* Does not return an error on purpose. */
25040                         } else
25041                             vctxt->inode->flags |=
25042                                 XML_SCHEMA_ELEM_INFO_NILLED;
25043                     }
25044                 }
25045             }
25046         }
25047         /*
25048         * cvc-elt (3.3.4) : 4
25049         * Handle 'xsi:type'.
25050         */
25051         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25052             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25053         if (iattr) {
25054             xmlSchemaTypePtr localType = NULL;
25055
25056             ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25057                 elemDecl);
25058             if (ret != 0) {
25059                 if (ret == -1) {
25060                     VERROR_INT("xmlSchemaValidateElemDecl",
25061                         "calling xmlSchemaProcessXSIType() to "
25062                         "process the attribute 'xsi:type'");
25063                     return (-1);
25064                 }
25065                 /* Does not return an error on purpose. */
25066             }
25067             if (localType != NULL) {
25068                 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25069                 actualType = localType;
25070             }
25071         }
25072     }
25073     /*
25074     * IDC: Register identity-constraint XPath matchers.
25075     */
25076     if ((elemDecl->idcs != NULL) &&
25077         (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25078             return (-1);
25079     /*
25080     * No actual type definition.
25081     */
25082     if (actualType == NULL) {
25083         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25084             "The type definition is absent");
25085         return (XML_SCHEMAV_CVC_TYPE_1);
25086     }
25087     /*
25088     * Remember the actual type definition.
25089     */
25090     vctxt->inode->typeDef = actualType;
25091
25092     return (0);
25093 }
25094
25095 static int
25096 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25097 {
25098     xmlSchemaAttrInfoPtr iattr;
25099     int ret = 0, i;
25100
25101     /*
25102     * SPEC cvc-type (3.1.1)
25103     * "The attributes of must be empty, excepting those whose namespace
25104     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25105     * whose local name is one of type, nil, schemaLocation or
25106     * noNamespaceSchemaLocation."
25107     */
25108     if (vctxt->nbAttrInfos == 0)
25109         return (0);
25110     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25111         iattr = vctxt->attrInfos[i];
25112         if (! iattr->metaType) {
25113             ACTIVATE_ATTRIBUTE(iattr)
25114             xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25115                 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25116             ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25117         }
25118     }
25119     ACTIVATE_ELEM
25120     return (ret);
25121 }
25122
25123 /*
25124 * Cleanup currently used attribute infos.
25125 */
25126 static void
25127 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25128 {
25129     int i;
25130     xmlSchemaAttrInfoPtr attr;
25131
25132     if (vctxt->nbAttrInfos == 0)
25133         return;
25134     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25135         attr = vctxt->attrInfos[i];
25136         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25137             if (attr->localName != NULL)
25138                 xmlFree((xmlChar *) attr->localName);
25139             if (attr->nsName != NULL)
25140                 xmlFree((xmlChar *) attr->nsName);
25141         }
25142         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25143             if (attr->value != NULL)
25144                 xmlFree((xmlChar *) attr->value);
25145         }
25146         if (attr->val != NULL) {
25147             xmlSchemaFreeValue(attr->val);
25148             attr->val = NULL;
25149         }
25150         memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25151     }
25152     vctxt->nbAttrInfos = 0;
25153 }
25154
25155 /*
25156 * 3.4.4 Complex Type Definition Validation Rules
25157 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25158 * 3.2.4 Attribute Declaration Validation Rules
25159 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25160 *   Attribute Locally Valid (Use) (cvc-au)
25161 *
25162 * Only "assessed" attribute information items will be visible to
25163 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25164 */
25165 static int
25166 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25167 {
25168     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25169     xmlSchemaItemListPtr attrUseList;
25170     xmlSchemaAttributeUsePtr attrUse = NULL;
25171     xmlSchemaAttributePtr attrDecl = NULL;
25172     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25173     int i, j, found, nbAttrs, nbUses;
25174     int xpathRes = 0, res, wildIDs = 0, fixed;
25175     xmlNodePtr defAttrOwnerElem = NULL;
25176
25177     /*
25178     * SPEC (cvc-attribute)
25179     * (1) "The declaration must not be ï¿½absent� (see Missing
25180     * Sub-components (�5.3) for how this can fail to be
25181     * the case)."
25182     * (2) "Its {type definition} must not be absent."
25183     *
25184     * NOTE (1) + (2): This is not handled here, since we currently do not
25185     * allow validation against schemas which have missing sub-components.
25186     *
25187     * SPEC (cvc-complex-type)
25188     * (3) "For each attribute information item in the element information
25189     * item's [attributes] excepting those whose [namespace name] is
25190     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25191     * [local name] is one of type, nil, schemaLocation or
25192     * noNamespaceSchemaLocation, the appropriate case among the following
25193     * must be true:
25194     *
25195     */
25196     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25197     /*
25198     * @nbAttrs is the number of attributes present in the instance.
25199     */
25200     nbAttrs = vctxt->nbAttrInfos;
25201     if (attrUseList != NULL)
25202         nbUses = attrUseList->nbItems;
25203     else
25204         nbUses = 0;
25205     for (i = 0; i < nbUses; i++) {
25206         found = 0;
25207         attrUse = attrUseList->items[i];
25208         attrDecl = WXS_ATTRUSE_DECL(attrUse);
25209         for (j = 0; j < nbAttrs; j++) {
25210             iattr = vctxt->attrInfos[j];
25211             /*
25212             * SPEC (cvc-complex-type) (3)
25213             * Skip meta attributes.
25214             */
25215             if (iattr->metaType)
25216                 continue;
25217             if (iattr->localName[0] != attrDecl->name[0])
25218                 continue;
25219             if (!xmlStrEqual(iattr->localName, attrDecl->name))
25220                 continue;
25221             if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25222                 continue;
25223             found = 1;
25224             /*
25225             * SPEC (cvc-complex-type)
25226             * (3.1) "If there is among the {attribute uses} an attribute
25227             * use with an {attribute declaration} whose {name} matches
25228             * the attribute information item's [local name] and whose
25229             * {target namespace} is identical to the attribute information
25230             * item's [namespace name] (where an ï¿½absent� {target namespace}
25231             * is taken to be identical to a [namespace name] with no value),
25232             * then the attribute information must be ï¿½valid� with respect
25233             * to that attribute use as per Attribute Locally Valid (Use)
25234             * (�3.5.4). In this case the {attribute declaration} of that
25235             * attribute use is the ï¿½context-determined declaration� for the
25236             * attribute information item with respect to Schema-Validity
25237             * Assessment (Attribute) (�3.2.4) and
25238             * Assessment Outcome (Attribute) (�3.2.5).
25239             */
25240             iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25241             iattr->use = attrUse;
25242             /*
25243             * Context-determined declaration.
25244             */
25245             iattr->decl = attrDecl;
25246             iattr->typeDef = attrDecl->subtypes;
25247             break;
25248         }
25249
25250         if (found)
25251             continue;
25252
25253         if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25254             /*
25255             * Handle non-existent, required attributes.
25256             *
25257             * SPEC (cvc-complex-type)
25258             * (4) "The {attribute declaration} of each attribute use in
25259             * the {attribute uses} whose {required} is true matches one
25260             * of the attribute information items in the element information
25261             * item's [attributes] as per clause 3.1 above."
25262             */
25263             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25264             if (tmpiattr == NULL) {
25265                 VERROR_INT(
25266                     "xmlSchemaVAttributesComplex",
25267                     "calling xmlSchemaGetFreshAttrInfo()");
25268                 return (-1);
25269             }
25270             tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25271             tmpiattr->use = attrUse;
25272             tmpiattr->decl = attrDecl;
25273         } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25274             ((attrUse->defValue != NULL) ||
25275              (attrDecl->defValue != NULL))) {
25276             /*
25277             * Handle non-existent, optional, default/fixed attributes.
25278             */
25279             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25280             if (tmpiattr == NULL) {
25281                 VERROR_INT(
25282                     "xmlSchemaVAttributesComplex",
25283                     "calling xmlSchemaGetFreshAttrInfo()");
25284                 return (-1);
25285             }
25286             tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25287             tmpiattr->use = attrUse;
25288             tmpiattr->decl = attrDecl;
25289             tmpiattr->typeDef = attrDecl->subtypes;
25290             tmpiattr->localName = attrDecl->name;
25291             tmpiattr->nsName = attrDecl->targetNamespace;
25292         }
25293     }
25294
25295     if (vctxt->nbAttrInfos == 0)
25296         return (0);
25297     /*
25298     * Validate against the wildcard.
25299     */
25300     if (type->attributeWildcard != NULL) {
25301         /*
25302         * SPEC (cvc-complex-type)
25303         * (3.2.1) "There must be an {attribute wildcard}."
25304         */
25305         for (i = 0; i < nbAttrs; i++) {
25306             iattr = vctxt->attrInfos[i];
25307             /*
25308             * SPEC (cvc-complex-type) (3)
25309             * Skip meta attributes.
25310             */
25311             if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25312                 continue;
25313             /*
25314             * SPEC (cvc-complex-type)
25315             * (3.2.2) "The attribute information item must be ï¿½valid� with
25316             * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25317             *
25318             * SPEC Item Valid (Wildcard) (cvc-wildcard)
25319             * "... its [namespace name] must be ï¿½valid� with respect to
25320             * the wildcard constraint, as defined in Wildcard allows
25321             * Namespace Name (�3.10.4)."
25322             */
25323             if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25324                     iattr->nsName) == 0) {
25325                 /*
25326                 * Handle processContents.
25327                 *
25328                 * SPEC (cvc-wildcard):
25329                 * processContents | context-determined declaration:
25330                 * "strict"          "mustFind"
25331                 * "lax"             "none"
25332                 * "skip"            "skip"
25333                 */
25334                 if (type->attributeWildcard->processContents ==
25335                     XML_SCHEMAS_ANY_SKIP) {
25336                      /*
25337                     * context-determined declaration = "skip"
25338                     *
25339                     * SPEC PSVI Assessment Outcome (Attribute)
25340                     * [validity] = "notKnown"
25341                     * [validation attempted] = "none"
25342                     */
25343                     iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25344                     continue;
25345                 }
25346                 /*
25347                 * Find an attribute declaration.
25348                 */
25349                 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25350                     iattr->localName, iattr->nsName);
25351                 if (iattr->decl != NULL) {
25352                     iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25353                     /*
25354                     * SPEC (cvc-complex-type)
25355                     * (5) "Let [Definition:]  the wild IDs be the set of
25356                     * all attribute information item to which clause 3.2
25357                     * applied and whose ï¿½validation� resulted in a
25358                     * ï¿½context-determined declaration� of mustFind or no
25359                     * ï¿½context-determined declaration� at all, and whose
25360                     * [local name] and [namespace name] resolve (as
25361                     * defined by QName resolution (Instance) (�3.15.4)) to
25362                     * an attribute declaration whose {type definition} is
25363                     * or is derived from ID. Then all of the following
25364                     * must be true:"
25365                     */
25366                     iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25367                     if (xmlSchemaIsDerivedFromBuiltInType(
25368                         iattr->typeDef, XML_SCHEMAS_ID)) {
25369                         /*
25370                         * SPEC (5.1) "There must be no more than one
25371                         * item in ï¿½wild IDs�."
25372                         */
25373                         if (wildIDs != 0) {
25374                             /* VAL TODO */
25375                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25376                             TODO
25377                             continue;
25378                         }
25379                         wildIDs++;
25380                         /*
25381                         * SPEC (cvc-complex-type)
25382                         * (5.2) "If ï¿½wild IDs� is non-empty, there must not
25383                         * be any attribute uses among the {attribute uses}
25384                         * whose {attribute declaration}'s {type definition}
25385                         * is or is derived from ID."
25386                         */
25387                         if (attrUseList != NULL) {
25388                             for (j = 0; j < attrUseList->nbItems; j++) {
25389                                 if (xmlSchemaIsDerivedFromBuiltInType(
25390                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25391                                     XML_SCHEMAS_ID)) {
25392                                     /* URGENT VAL TODO: implement */
25393                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25394                                     TODO
25395                                     break;
25396                                 }
25397                             }
25398                         }
25399                     }
25400                 } else if (type->attributeWildcard->processContents ==
25401                     XML_SCHEMAS_ANY_LAX) {
25402                     iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25403                     /*
25404                     * SPEC PSVI Assessment Outcome (Attribute)
25405                     * [validity] = "notKnown"
25406                     * [validation attempted] = "none"
25407                     */
25408                 } else {
25409                     iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25410                 }
25411             }
25412         }
25413     }
25414
25415     if (vctxt->nbAttrInfos == 0)
25416         return (0);
25417
25418     /*
25419     * Get the owner element; needed for creation of default attributes.
25420     * This fixes bug #341337, reported by David Grohmann.
25421     */
25422     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25423         xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25424         if (ielem && ielem->node && ielem->node->doc)
25425             defAttrOwnerElem = ielem->node;
25426     }
25427     /*
25428     * Validate values, create default attributes, evaluate IDCs.
25429     */
25430     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25431         iattr = vctxt->attrInfos[i];
25432         /*
25433         * VAL TODO: Note that we won't try to resolve IDCs to
25434         * "lax" and "skip" validated attributes. Check what to
25435         * do in this case.
25436         */
25437         if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25438             (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25439             continue;
25440         /*
25441         * VAL TODO: What to do if the type definition is missing?
25442         */
25443         if (iattr->typeDef == NULL) {
25444             iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25445             continue;
25446         }
25447
25448         ACTIVATE_ATTRIBUTE(iattr);
25449         fixed = 0;
25450         xpathRes = 0;
25451
25452         if (vctxt->xpathStates != NULL) {
25453             /*
25454             * Evaluate IDCs.
25455             */
25456             xpathRes = xmlSchemaXPathEvaluate(vctxt,
25457                 XML_ATTRIBUTE_NODE);
25458             if (xpathRes == -1) {
25459                 VERROR_INT("xmlSchemaVAttributesComplex",
25460                     "calling xmlSchemaXPathEvaluate()");
25461                 goto internal_error;
25462             }
25463         }
25464
25465         if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25466             /*
25467             * Default/fixed attributes.
25468             * We need the value only if we need to resolve IDCs or
25469             * will create default attributes.
25470             */
25471             if ((xpathRes) || (defAttrOwnerElem)) {
25472                 if (iattr->use->defValue != NULL) {
25473                     iattr->value = (xmlChar *) iattr->use->defValue;
25474                     iattr->val = iattr->use->defVal;
25475                 } else {
25476                     iattr->value = (xmlChar *) iattr->decl->defValue;
25477                     iattr->val = iattr->decl->defVal;
25478                 }
25479                 /*
25480                 * IDCs will consume the precomputed default value,
25481                 * so we need to clone it.
25482                 */
25483                 if (iattr->val == NULL) {
25484                     VERROR_INT("xmlSchemaVAttributesComplex",
25485                         "default/fixed value on an attribute use was "
25486                         "not precomputed");
25487                     goto internal_error;
25488                 }
25489                 iattr->val = xmlSchemaCopyValue(iattr->val);
25490                 if (iattr->val == NULL) {
25491                     VERROR_INT("xmlSchemaVAttributesComplex",
25492                         "calling xmlSchemaCopyValue()");
25493                     goto internal_error;
25494                 }
25495             }
25496             /*
25497             * PSVI: Add the default attribute to the current element.
25498             * VAL TODO: Should we use the *normalized* value? This currently
25499             *   uses the *initial* value.
25500             */
25501
25502             if (defAttrOwnerElem) {
25503                 xmlChar *normValue;
25504                 const xmlChar *value;
25505
25506                 value = iattr->value;
25507                 /*
25508                 * Normalize the value.
25509                 */
25510                 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25511                     iattr->value);
25512                 if (normValue != NULL)
25513                     value = BAD_CAST normValue;
25514
25515                 if (iattr->nsName == NULL) {
25516                     if (xmlNewProp(defAttrOwnerElem,
25517                         iattr->localName, value) == NULL) {
25518                         VERROR_INT("xmlSchemaVAttributesComplex",
25519                             "callling xmlNewProp()");
25520                         if (normValue != NULL)
25521                             xmlFree(normValue);
25522                         goto internal_error;
25523                     }
25524                 } else {
25525                     xmlNsPtr ns;
25526
25527                     ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25528                         defAttrOwnerElem, iattr->nsName);
25529                     if (ns == NULL) {
25530                         xmlChar prefix[12];
25531                         int counter = 0;
25532
25533                         /*
25534                         * Create a namespace declaration on the validation
25535                         * root node if no namespace declaration is in scope.
25536                         */
25537                         do {
25538                             snprintf((char *) prefix, 12, "p%d", counter++);
25539                             ns = xmlSearchNs(defAttrOwnerElem->doc,
25540                                 defAttrOwnerElem, BAD_CAST prefix);
25541                             if (counter > 1000) {
25542                                 VERROR_INT(
25543                                     "xmlSchemaVAttributesComplex",
25544                                     "could not compute a ns prefix for a "
25545                                     "default/fixed attribute");
25546                                 if (normValue != NULL)
25547                                     xmlFree(normValue);
25548                                 goto internal_error;
25549                             }
25550                         } while (ns != NULL);
25551                         ns = xmlNewNs(vctxt->validationRoot,
25552                             iattr->nsName, BAD_CAST prefix);
25553                     }
25554                     /*
25555                     * TODO:
25556                     * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25557                     * If we have QNames: do we need to ensure there's a
25558                     * prefix defined for the QName?
25559                     */
25560                     xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25561                 }
25562                 if (normValue != NULL)
25563                     xmlFree(normValue);
25564             }
25565             /*
25566             * Go directly to IDC evaluation.
25567             */
25568             goto eval_idcs;
25569         }
25570         /*
25571         * Validate the value.
25572         */
25573         if (vctxt->value != NULL) {
25574             /*
25575             * Free last computed value; just for safety reasons.
25576             */
25577             xmlSchemaFreeValue(vctxt->value);
25578             vctxt->value = NULL;
25579         }
25580         /*
25581         * Note that the attribute *use* can be unavailable, if
25582         * the attribute was a wild attribute.
25583         */
25584         if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25585             ((iattr->use != NULL) &&
25586              (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25587             fixed = 1;
25588         else
25589             fixed = 0;
25590         /*
25591         * SPEC (cvc-attribute)
25592         * (3) "The item's ï¿½normalized value� must be locally ï¿½valid�
25593         * with respect to that {type definition} as per
25594         * String Valid (�3.14.4)."
25595         *
25596         * VAL TODO: Do we already have the
25597         * "normalized attribute value" here?
25598         */
25599         if (xpathRes || fixed) {
25600             iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25601             /*
25602             * Request a computed value.
25603             */
25604             res = xmlSchemaVCheckCVCSimpleType(
25605                 ACTXT_CAST vctxt,
25606                 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25607                 1, 1, 0);
25608         } else {
25609             res = xmlSchemaVCheckCVCSimpleType(
25610                 ACTXT_CAST vctxt,
25611                 iattr->node, iattr->typeDef, iattr->value, NULL,
25612                 1, 0, 0);
25613         }
25614
25615         if (res != 0) {
25616             if (res == -1) {
25617                 VERROR_INT("xmlSchemaVAttributesComplex",
25618                     "calling xmlSchemaStreamValidateSimpleTypeValue()");
25619                 goto internal_error;
25620             }
25621             iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25622             /*
25623             * SPEC PSVI Assessment Outcome (Attribute)
25624             * [validity] = "invalid"
25625             */
25626             goto eval_idcs;
25627         }
25628
25629         if (fixed) {
25630             /*
25631             * SPEC Attribute Locally Valid (Use) (cvc-au)
25632             * "For an attribute information item to be�valid�
25633             * with respect to an attribute use its *normalized*
25634             * value� must match the *canonical* lexical
25635             * representation of the attribute use's {value
25636             * constraint}value, if it is present and fixed."
25637             *
25638             * VAL TODO: The requirement for the *canonical* value
25639             * will be removed in XML Schema 1.1.
25640             */
25641             /*
25642             * SPEC Attribute Locally Valid (cvc-attribute)
25643             * (4) "The item's *actual* value� must match the *value* of
25644             * the {value constraint}, if it is present and fixed."
25645             */
25646             if (iattr->val == NULL) {
25647                 /* VAL TODO: A value was not precomputed. */
25648                 TODO
25649                 goto eval_idcs;
25650             }
25651             if ((iattr->use != NULL) &&
25652                 (iattr->use->defValue != NULL)) {
25653                 if (iattr->use->defVal == NULL) {
25654                     /* VAL TODO: A default value was not precomputed. */
25655                     TODO
25656                     goto eval_idcs;
25657                 }
25658                 iattr->vcValue = iattr->use->defValue;
25659                 /*
25660                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25661                     (xmlSchemaWhitespaceValueType) ws,
25662                     attr->use->defVal,
25663                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25664                 */
25665                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25666                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25667             } else {
25668                 if (iattr->decl->defVal == NULL) {
25669                     /* VAL TODO: A default value was not precomputed. */
25670                     TODO
25671                     goto eval_idcs;
25672                 }
25673                 iattr->vcValue = iattr->decl->defValue;
25674                 /*
25675                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25676                     (xmlSchemaWhitespaceValueType) ws,
25677                     attrDecl->defVal,
25678                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25679                 */
25680                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25681                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25682             }
25683             /*
25684             * [validity] = "valid"
25685             */
25686         }
25687 eval_idcs:
25688         /*
25689         * Evaluate IDCs.
25690         */
25691         if (xpathRes) {
25692             if (xmlSchemaXPathProcessHistory(vctxt,
25693                 vctxt->depth +1) == -1) {
25694                 VERROR_INT("xmlSchemaVAttributesComplex",
25695                     "calling xmlSchemaXPathEvaluate()");
25696                 goto internal_error;
25697             }
25698         } else if (vctxt->xpathStates != NULL)
25699             xmlSchemaXPathPop(vctxt);
25700     }
25701
25702     /*
25703     * Report errors.
25704     */
25705     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25706         iattr = vctxt->attrInfos[i];
25707         if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25708             (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25709             (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25710             (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25711             continue;
25712         ACTIVATE_ATTRIBUTE(iattr);
25713         switch (iattr->state) {
25714             case XML_SCHEMAS_ATTR_ERR_MISSING: {
25715                     xmlChar *str = NULL;
25716                     ACTIVATE_ELEM;
25717                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
25718                         XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25719                         "The attribute '%s' is required but missing",
25720                         xmlSchemaFormatQName(&str,
25721                             iattr->decl->targetNamespace,
25722                             iattr->decl->name),
25723                         NULL);
25724                     FREE_AND_NULL(str)
25725                     break;
25726                 }
25727             case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25728                 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25729                     "The type definition is absent");
25730                 break;
25731             case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25732                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25733                     XML_SCHEMAV_CVC_AU, NULL, NULL,
25734                     "The value '%s' does not match the fixed "
25735                     "value constraint '%s'",
25736                     iattr->value, iattr->vcValue);
25737                 break;
25738             case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25739                 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25740                     "No matching global attribute declaration available, but "
25741                     "demanded by the strict wildcard");
25742                 break;
25743             case XML_SCHEMAS_ATTR_UNKNOWN:
25744                 if (iattr->metaType)
25745                     break;
25746                 /*
25747                 * MAYBE VAL TODO: One might report different error messages
25748                 * for the following errors.
25749                 */
25750                 if (type->attributeWildcard == NULL) {
25751                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25752                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25753                 } else {
25754                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25755                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25756                 }
25757                 break;
25758             default:
25759                 break;
25760         }
25761     }
25762
25763     ACTIVATE_ELEM;
25764     return (0);
25765 internal_error:
25766     ACTIVATE_ELEM;
25767     return (-1);
25768 }
25769
25770 static int
25771 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25772                               int *skip)
25773 {
25774     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25775     /*
25776     * The namespace of the element was already identified to be
25777     * matching the wildcard.
25778     */
25779     if ((skip == NULL) || (wild == NULL) ||
25780         (wild->type != XML_SCHEMA_TYPE_ANY)) {
25781         VERROR_INT("xmlSchemaValidateElemWildcard",
25782             "bad arguments");
25783         return (-1);
25784     }
25785     *skip = 0;
25786     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25787         /*
25788         * URGENT VAL TODO: Either we need to position the stream to the
25789         * next sibling, or walk the whole subtree.
25790         */
25791         *skip = 1;
25792         return (0);
25793     }
25794     {
25795         xmlSchemaElementPtr decl = NULL;
25796
25797         decl = xmlSchemaGetElem(vctxt->schema,
25798             vctxt->inode->localName, vctxt->inode->nsName);
25799         if (decl != NULL) {
25800             vctxt->inode->decl = decl;
25801             return (0);
25802         }
25803     }
25804     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25805         /* VAL TODO: Change to proper error code. */
25806         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25807             "No matching global element declaration available, but "
25808             "demanded by the strict wildcard");
25809         return (vctxt->err);
25810     }
25811     if (vctxt->nbAttrInfos != 0) {
25812         xmlSchemaAttrInfoPtr iattr;
25813         /*
25814         * SPEC Validation Rule: Schema-Validity Assessment (Element)
25815         * (1.2.1.2.1) - (1.2.1.2.3 )
25816         *
25817         * Use the xsi:type attribute for the type definition.
25818         */
25819         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25820             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25821         if (iattr != NULL) {
25822             if (xmlSchemaProcessXSIType(vctxt, iattr,
25823                 &(vctxt->inode->typeDef), NULL) == -1) {
25824                 VERROR_INT("xmlSchemaValidateElemWildcard",
25825                     "calling xmlSchemaProcessXSIType() to "
25826                     "process the attribute 'xsi:nil'");
25827                 return (-1);
25828             }
25829             /*
25830             * Don't return an error on purpose.
25831             */
25832             return (0);
25833         }
25834     }
25835     /*
25836     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25837     *
25838     * Fallback to "anyType".
25839     */
25840     vctxt->inode->typeDef =
25841         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25842     return (0);
25843 }
25844
25845 /*
25846 * xmlSchemaCheckCOSValidDefault:
25847 *
25848 * This will be called if: not nilled, no content and a default/fixed
25849 * value is provided.
25850 */
25851
25852 static int
25853 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25854                               const xmlChar *value,
25855                               xmlSchemaValPtr *val)
25856 {
25857     int ret = 0;
25858     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25859
25860     /*
25861     * cos-valid-default:
25862     * Schema Component Constraint: Element Default Valid (Immediate)
25863     * For a string to be a valid default with respect to a type
25864     * definition the appropriate case among the following must be true:
25865     */
25866     if WXS_IS_COMPLEX(inode->typeDef) {
25867         /*
25868         * Complex type.
25869         *
25870         * SPEC (2.1) "its {content type} must be a simple type definition
25871         * or mixed."
25872         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25873         * type}'s particle must be ï¿½emptiable� as defined by
25874         * Particle Emptiable (�3.9.6)."
25875         */
25876         if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25877             ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25878              (! WXS_EMPTIABLE(inode->typeDef)))) {
25879             ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25880             /* NOTE that this covers (2.2.2) as well. */
25881             VERROR(ret, NULL,
25882                 "For a string to be a valid default, the type definition "
25883                 "must be a simple type or a complex type with simple content "
25884                 "or mixed content and a particle emptiable");
25885             return(ret);
25886         }
25887     }
25888     /*
25889     * 1 If the type definition is a simple type definition, then the string
25890     * must be ï¿½valid� with respect to that definition as defined by String
25891     * Valid (�3.14.4).
25892     *
25893     * AND
25894     *
25895     * 2.2.1 If the {content type} is a simple type definition, then the
25896     * string must be ï¿½valid� with respect to that simple type definition
25897     * as defined by String Valid (�3.14.4).
25898     */
25899     if (WXS_IS_SIMPLE(inode->typeDef)) {
25900
25901         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25902             NULL, inode->typeDef, value, val, 1, 1, 0);
25903
25904     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25905
25906         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25907             NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25908     }
25909     if (ret < 0) {
25910         VERROR_INT("xmlSchemaCheckCOSValidDefault",
25911             "calling xmlSchemaVCheckCVCSimpleType()");
25912     }
25913     return (ret);
25914 }
25915
25916 static void
25917 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25918                                const xmlChar * name ATTRIBUTE_UNUSED,
25919                                xmlSchemaElementPtr item,
25920                                xmlSchemaNodeInfoPtr inode)
25921 {
25922     inode->decl = item;
25923 #ifdef DEBUG_CONTENT
25924     {
25925         xmlChar *str = NULL;
25926
25927         if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25928             xmlGenericError(xmlGenericErrorContext,
25929                 "AUTOMATON callback for '%s' [declaration]\n",
25930                 xmlSchemaFormatQName(&str,
25931                 inode->localName, inode->nsName));
25932         } else {
25933             xmlGenericError(xmlGenericErrorContext,
25934                     "AUTOMATON callback for '%s' [wildcard]\n",
25935                     xmlSchemaFormatQName(&str,
25936                     inode->localName, inode->nsName));
25937
25938         }
25939         FREE_AND_NULL(str)
25940     }
25941 #endif
25942 }
25943
25944 static int
25945 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25946 {
25947     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25948     if (vctxt->inode == NULL) {
25949         VERROR_INT("xmlSchemaValidatorPushElem",
25950             "calling xmlSchemaGetFreshElemInfo()");
25951         return (-1);
25952     }
25953     vctxt->nbAttrInfos = 0;
25954     return (0);
25955 }
25956
25957 static int
25958 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25959                              xmlSchemaNodeInfoPtr inode,
25960                              xmlSchemaTypePtr type,
25961                              const xmlChar *value)
25962 {
25963     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25964         return (xmlSchemaVCheckCVCSimpleType(
25965             ACTXT_CAST vctxt, NULL,
25966             type, value, &(inode->val), 1, 1, 0));
25967     else
25968         return (xmlSchemaVCheckCVCSimpleType(
25969             ACTXT_CAST vctxt, NULL,
25970             type, value, NULL, 1, 0, 0));
25971 }
25972
25973
25974
25975 /*
25976 * Process END of element.
25977 */
25978 static int
25979 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25980 {
25981     int ret = 0;
25982     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25983
25984     if (vctxt->nbAttrInfos != 0)
25985         xmlSchemaClearAttrInfos(vctxt);
25986     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25987         /*
25988         * This element was not expected;
25989         * we will not validate child elements of broken parents.
25990         * Skip validation of all content of the parent.
25991         */
25992         vctxt->skipDepth = vctxt->depth -1;
25993         goto end_elem;
25994     }
25995     if ((inode->typeDef == NULL) ||
25996         (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25997         /*
25998         * 1. the type definition might be missing if the element was
25999         *    error prone
26000         * 2. it might be abstract.
26001         */
26002         goto end_elem;
26003     }
26004     /*
26005     * Check the content model.
26006     */
26007     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26008         (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26009
26010         /*
26011         * Workaround for "anyType".
26012         */
26013         if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26014             goto character_content;
26015
26016         if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26017             xmlChar *values[10];
26018             int terminal, nbval = 10, nbneg;
26019
26020             if (inode->regexCtxt == NULL) {
26021                 /*
26022                 * Create the regex context.
26023                 */
26024                 inode->regexCtxt =
26025                     xmlRegNewExecCtxt(inode->typeDef->contModel,
26026                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26027                     vctxt);
26028                 if (inode->regexCtxt == NULL) {
26029                     VERROR_INT("xmlSchemaValidatorPopElem",
26030                         "failed to create a regex context");
26031                     goto internal_error;
26032                 }
26033 #ifdef DEBUG_AUTOMATA
26034                 xmlGenericError(xmlGenericErrorContext,
26035                     "AUTOMATON create on '%s'\n", inode->localName);
26036 #endif
26037             }
26038             /*
26039             * Get hold of the still expected content, since a further
26040             * call to xmlRegExecPushString() will loose this information.
26041             */
26042             xmlRegExecNextValues(inode->regexCtxt,
26043                 &nbval, &nbneg, &values[0], &terminal);
26044             ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26045             if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26046                 /*
26047                 * Still missing something.
26048                 */
26049                 ret = 1;
26050                 inode->flags |=
26051                     XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26052                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26053                     XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26054                     "Missing child element(s)",
26055                     nbval, nbneg, values);
26056 #ifdef DEBUG_AUTOMATA
26057                 xmlGenericError(xmlGenericErrorContext,
26058                     "AUTOMATON missing ERROR on '%s'\n",
26059                     inode->localName);
26060 #endif
26061             } else {
26062                 /*
26063                 * Content model is satisfied.
26064                 */
26065                 ret = 0;
26066 #ifdef DEBUG_AUTOMATA
26067                 xmlGenericError(xmlGenericErrorContext,
26068                     "AUTOMATON succeeded on '%s'\n",
26069                     inode->localName);
26070 #endif
26071             }
26072
26073         }
26074     }
26075     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26076         goto end_elem;
26077
26078 character_content:
26079
26080     if (vctxt->value != NULL) {
26081         xmlSchemaFreeValue(vctxt->value);
26082         vctxt->value = NULL;
26083     }
26084     /*
26085     * Check character content.
26086     */
26087     if (inode->decl == NULL) {
26088         /*
26089         * Speedup if no declaration exists.
26090         */
26091         if (WXS_IS_SIMPLE(inode->typeDef)) {
26092             ret = xmlSchemaVCheckINodeDataType(vctxt,
26093                 inode, inode->typeDef, inode->value);
26094         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26095             ret = xmlSchemaVCheckINodeDataType(vctxt,
26096                 inode, inode->typeDef->contentTypeDef,
26097                 inode->value);
26098         }
26099         if (ret < 0) {
26100             VERROR_INT("xmlSchemaValidatorPopElem",
26101                 "calling xmlSchemaVCheckCVCSimpleType()");
26102             goto internal_error;
26103         }
26104         goto end_elem;
26105     }
26106     /*
26107     * cvc-elt (3.3.4) : 5
26108     * The appropriate case among the following must be true:
26109     */
26110     /*
26111     * cvc-elt (3.3.4) : 5.1
26112     * If the declaration has a {value constraint},
26113     * the item has neither element nor character [children] and
26114     * clause 3.2 has not applied, then all of the following must be true:
26115     */
26116     if ((inode->decl->value != NULL) &&
26117         (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26118         (! INODE_NILLED(inode))) {
26119         /*
26120         * cvc-elt (3.3.4) : 5.1.1
26121         * If the ï¿½actual type definition� is a ï¿½local type definition�
26122         * then the canonical lexical representation of the {value constraint}
26123         * value must be a valid default for the ï¿½actual type definition� as
26124         * defined in Element Default Valid (Immediate) (�3.3.6).
26125         */
26126         /*
26127         * NOTE: 'local' above means types acquired by xsi:type.
26128         * NOTE: Although the *canonical* value is stated, it is not
26129         * relevant if canonical or not. Additionally XML Schema 1.1
26130         * will removed this requirement as well.
26131         */
26132         if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26133
26134             ret = xmlSchemaCheckCOSValidDefault(vctxt,
26135                 inode->decl->value, &(inode->val));
26136             if (ret != 0) {
26137                 if (ret < 0) {
26138                     VERROR_INT("xmlSchemaValidatorPopElem",
26139                         "calling xmlSchemaCheckCOSValidDefault()");
26140                     goto internal_error;
26141                 }
26142                 goto end_elem;
26143             }
26144             /*
26145             * Stop here, to avoid redundant validation of the value
26146             * (see following).
26147             */
26148             goto default_psvi;
26149         }
26150         /*
26151         * cvc-elt (3.3.4) : 5.1.2
26152         * The element information item with the canonical lexical
26153         * representation of the {value constraint} value used as its
26154         * ï¿½normalized value� must be ï¿½valid� with respect to the
26155         * ï¿½actual type definition� as defined by Element Locally Valid (Type)
26156         * (�3.3.4).
26157         */
26158         if (WXS_IS_SIMPLE(inode->typeDef)) {
26159             ret = xmlSchemaVCheckINodeDataType(vctxt,
26160                 inode, inode->typeDef, inode->decl->value);
26161         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26162             ret = xmlSchemaVCheckINodeDataType(vctxt,
26163                 inode, inode->typeDef->contentTypeDef,
26164                 inode->decl->value);
26165         }
26166         if (ret != 0) {
26167             if (ret < 0) {
26168                 VERROR_INT("xmlSchemaValidatorPopElem",
26169                     "calling xmlSchemaVCheckCVCSimpleType()");
26170                 goto internal_error;
26171             }
26172             goto end_elem;
26173         }
26174
26175 default_psvi:
26176         /*
26177         * PSVI: Create a text node on the instance element.
26178         */
26179         if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26180             (inode->node != NULL)) {
26181             xmlNodePtr textChild;
26182             xmlChar *normValue;
26183             /*
26184             * VAL TODO: Normalize the value.
26185             */
26186             normValue = xmlSchemaNormalizeValue(inode->typeDef,
26187                 inode->decl->value);
26188             if (normValue != NULL) {
26189                 textChild = xmlNewText(BAD_CAST normValue);
26190                 xmlFree(normValue);
26191             } else
26192                 textChild = xmlNewText(inode->decl->value);
26193             if (textChild == NULL) {
26194                 VERROR_INT("xmlSchemaValidatorPopElem",
26195                     "calling xmlNewText()");
26196                 goto internal_error;
26197             } else
26198                 xmlAddChild(inode->node, textChild);
26199         }
26200
26201     } else if (! INODE_NILLED(inode)) {
26202         /*
26203         * 5.2.1 The element information item must be ï¿½valid� with respect
26204         * to the ï¿½actual type definition� as defined by Element Locally
26205         * Valid (Type) (�3.3.4).
26206         */
26207         if (WXS_IS_SIMPLE(inode->typeDef)) {
26208              /*
26209             * SPEC (cvc-type) (3.1)
26210             * "If the type definition is a simple type definition, ..."
26211             * (3.1.3) "If clause 3.2 of Element Locally Valid
26212             * (Element) (�3.3.4) did not apply, then the ï¿½normalized value�
26213             * must be ï¿½valid� with respect to the type definition as defined
26214             * by String Valid (�3.14.4).
26215             */
26216             ret = xmlSchemaVCheckINodeDataType(vctxt,
26217                     inode, inode->typeDef, inode->value);
26218         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26219             /*
26220             * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26221             * definition, then the element information item must be
26222             * ï¿½valid� with respect to the type definition as per
26223             * Element Locally Valid (Complex Type) (�3.4.4);"
26224             *
26225             * SPEC (cvc-complex-type) (2.2)
26226             * "If the {content type} is a simple type definition, ...
26227             * the ï¿½normalized value� of the element information item is
26228             * ï¿½valid� with respect to that simple type definition as
26229             * defined by String Valid (�3.14.4)."
26230             */
26231             ret = xmlSchemaVCheckINodeDataType(vctxt,
26232                 inode, inode->typeDef->contentTypeDef, inode->value);
26233         }
26234         if (ret != 0) {
26235             if (ret < 0) {
26236                 VERROR_INT("xmlSchemaValidatorPopElem",
26237                     "calling xmlSchemaVCheckCVCSimpleType()");
26238                 goto internal_error;
26239             }
26240             goto end_elem;
26241         }
26242         /*
26243         * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26244         * not applied, all of the following must be true:
26245         */
26246         if ((inode->decl->value != NULL) &&
26247             (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26248
26249             /*
26250             * TODO: We will need a computed value, when comparison is
26251             * done on computed values.
26252             */
26253             /*
26254             * 5.2.2.1 The element information item must have no element
26255             * information item [children].
26256             */
26257             if (inode->flags &
26258                     XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26259                 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26260                 VERROR(ret, NULL,
26261                     "The content must not containt element nodes since "
26262                     "there is a fixed value constraint");
26263                 goto end_elem;
26264             } else {
26265                 /*
26266                 * 5.2.2.2 The appropriate case among the following must
26267                 * be true:
26268                 */
26269                 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26270                     /*
26271                     * 5.2.2.2.1 If the {content type} of the ï¿½actual type
26272                     * definition� is mixed, then the *initial value* of the
26273                     * item must match the canonical lexical representation
26274                     * of the {value constraint} value.
26275                     *
26276                     * ... the *initial value* of an element information
26277                     * item is the string composed of, in order, the
26278                     * [character code] of each character information item in
26279                     * the [children] of that element information item.
26280                     */
26281                     if (! xmlStrEqual(inode->value, inode->decl->value)){
26282                         /*
26283                         * VAL TODO: Report invalid & expected values as well.
26284                         * VAL TODO: Implement the canonical stuff.
26285                         */
26286                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26287                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26288                             ret, NULL, NULL,
26289                             "The initial value '%s' does not match the fixed "
26290                             "value constraint '%s'",
26291                             inode->value, inode->decl->value);
26292                         goto end_elem;
26293                     }
26294                 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26295                     /*
26296                     * 5.2.2.2.2 If the {content type} of the ï¿½actual type
26297                     * definition� is a simple type definition, then the
26298                     * *actual value* of the item must match the canonical
26299                     * lexical representation of the {value constraint} value.
26300                     */
26301                     /*
26302                     * VAL TODO: *actual value* is the normalized value, impl.
26303                     *           this.
26304                     * VAL TODO: Report invalid & expected values as well.
26305                     * VAL TODO: Implement a comparison with the computed values.
26306                     */
26307                     if (! xmlStrEqual(inode->value,
26308                             inode->decl->value)) {
26309                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26310                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26311                             ret, NULL, NULL,
26312                             "The actual value '%s' does not match the fixed "
26313                             "value constraint '%s'",
26314                             inode->value,
26315                             inode->decl->value);
26316                         goto end_elem;
26317                     }
26318                 }
26319             }
26320         }
26321     }
26322
26323 end_elem:
26324     if (vctxt->depth < 0) {
26325         /* TODO: raise error? */
26326         return (0);
26327     }
26328     if (vctxt->depth == vctxt->skipDepth)
26329         vctxt->skipDepth = -1;
26330     /*
26331     * Evaluate the history of XPath state objects.
26332     */
26333     if (inode->appliedXPath &&
26334         (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26335         goto internal_error;
26336     /*
26337     * MAYBE TODO:
26338     * SPEC (6) "The element information item must be ï¿½valid� with
26339     * respect to each of the {identity-constraint definitions} as per
26340     * Identity-constraint Satisfied (�3.11.4)."
26341     */
26342     /*
26343     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26344     *   need to be built in any case.
26345     *   We will currently build IDC node-tables and bubble them only if
26346     *   keyrefs do exist.
26347     */
26348
26349     /*
26350     * Add the current IDC target-nodes to the IDC node-tables.
26351     */
26352     if ((inode->idcMatchers != NULL) &&
26353         (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26354     {
26355         if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26356             goto internal_error;
26357     }
26358     /*
26359     * Validate IDC keyrefs.
26360     */
26361     if (vctxt->inode->hasKeyrefs)
26362         if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26363             goto internal_error;
26364     /*
26365     * Merge/free the IDC table.
26366     */
26367     if (inode->idcTable != NULL) {
26368 #ifdef DEBUG_IDC_NODE_TABLE
26369         xmlSchemaDebugDumpIDCTable(stdout,
26370             inode->nsName,
26371             inode->localName,
26372             inode->idcTable);
26373 #endif
26374         if ((vctxt->depth > 0) &&
26375             (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26376         {
26377             /*
26378             * Merge the IDC node table with the table of the parent node.
26379             */
26380             if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26381                 goto internal_error;
26382         }
26383     }
26384     /*
26385     * Clear the current ielem.
26386     * VAL TODO: Don't free the PSVI IDC tables if they are
26387     * requested for the PSVI.
26388     */
26389     xmlSchemaClearElemInfo(vctxt, inode);
26390     /*
26391     * Skip further processing if we are on the validation root.
26392     */
26393     if (vctxt->depth == 0) {
26394         vctxt->depth--;
26395         vctxt->inode = NULL;
26396         return (0);
26397     }
26398     /*
26399     * Reset the keyrefDepth if needed.
26400     */
26401     if (vctxt->aidcs != NULL) {
26402         xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26403         do {
26404             if (aidc->keyrefDepth == vctxt->depth) {
26405                 /*
26406                 * A 'keyrefDepth' of a key/unique IDC matches the current
26407                 * depth, this means that we are leaving the scope of the
26408                 * top-most keyref IDC which refers to this IDC.
26409                 */
26410                 aidc->keyrefDepth = -1;
26411             }
26412             aidc = aidc->next;
26413         } while (aidc != NULL);
26414     }
26415     vctxt->depth--;
26416     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26417     /*
26418     * VAL TODO: 7 If the element information item is the ï¿½validation root�, it must be
26419     * ï¿½valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26420     */
26421     return (ret);
26422
26423 internal_error:
26424     vctxt->err = -1;
26425     return (-1);
26426 }
26427
26428 /*
26429 * 3.4.4 Complex Type Definition Validation Rules
26430 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26431 */
26432 static int
26433 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26434 {
26435     xmlSchemaNodeInfoPtr pielem;
26436     xmlSchemaTypePtr ptype;
26437     int ret = 0;
26438
26439     if (vctxt->depth <= 0) {
26440         VERROR_INT("xmlSchemaValidateChildElem",
26441             "not intended for the validation root");
26442         return (-1);
26443     }
26444     pielem = vctxt->elemInfos[vctxt->depth -1];
26445     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26446         pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26447     /*
26448     * Handle 'nilled' elements.
26449     */
26450     if (INODE_NILLED(pielem)) {
26451         /*
26452         * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26453         */
26454         ACTIVATE_PARENT_ELEM;
26455         ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26456         VERROR(ret, NULL,
26457             "Neither character nor element content is allowed, "
26458             "because the element was 'nilled'");
26459         ACTIVATE_ELEM;
26460         goto unexpected_elem;
26461     }
26462
26463     ptype = pielem->typeDef;
26464
26465     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26466         /*
26467         * Workaround for "anyType": we have currently no content model
26468         * assigned for "anyType", so handle it explicitely.
26469         * "anyType" has an unbounded, lax "any" wildcard.
26470         */
26471         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26472             vctxt->inode->localName,
26473             vctxt->inode->nsName);
26474
26475         if (vctxt->inode->decl == NULL) {
26476             xmlSchemaAttrInfoPtr iattr;
26477             /*
26478             * Process "xsi:type".
26479             * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26480             */
26481             iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26482                 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26483             if (iattr != NULL) {
26484                 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26485                     &(vctxt->inode->typeDef), NULL);
26486                 if (ret != 0) {
26487                     if (ret == -1) {
26488                         VERROR_INT("xmlSchemaValidateChildElem",
26489                             "calling xmlSchemaProcessXSIType() to "
26490                             "process the attribute 'xsi:nil'");
26491                         return (-1);
26492                     }
26493                     return (ret);
26494                 }
26495             } else {
26496                  /*
26497                  * Fallback to "anyType".
26498                  *
26499                  * SPEC (cvc-assess-elt)
26500                  * "If the item cannot be ï¿½strictly assessed�, [...]
26501                  * an element information item's schema validity may be laxly
26502                  * assessed if its ï¿½context-determined declaration� is not
26503                  * skip by ï¿½validating� with respect to the ï¿½ur-type
26504                  * definition� as per Element Locally Valid (Type) (�3.3.4)."
26505                 */
26506                 vctxt->inode->typeDef =
26507                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26508             }
26509         }
26510         return (0);
26511     }
26512
26513     switch (ptype->contentType) {
26514         case XML_SCHEMA_CONTENT_EMPTY:
26515             /*
26516             * SPEC (2.1) "If the {content type} is empty, then the
26517             * element information item has no character or element
26518             * information item [children]."
26519             */
26520             ACTIVATE_PARENT_ELEM
26521             ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26522             VERROR(ret, NULL,
26523                 "Element content is not allowed, "
26524                 "because the content type is empty");
26525             ACTIVATE_ELEM
26526             goto unexpected_elem;
26527             break;
26528
26529         case XML_SCHEMA_CONTENT_MIXED:
26530         case XML_SCHEMA_CONTENT_ELEMENTS: {
26531             xmlRegExecCtxtPtr regexCtxt;
26532             xmlChar *values[10];
26533             int terminal, nbval = 10, nbneg;
26534
26535             /* VAL TODO: Optimized "anyType" validation.*/
26536
26537             if (ptype->contModel == NULL) {
26538                 VERROR_INT("xmlSchemaValidateChildElem",
26539                     "type has elem content but no content model");
26540                 return (-1);
26541             }
26542             /*
26543             * Safety belf for evaluation if the cont. model was already
26544             * examined to be invalid.
26545             */
26546             if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26547                 VERROR_INT("xmlSchemaValidateChildElem",
26548                     "validating elem, but elem content is already invalid");
26549                 return (-1);
26550             }
26551
26552             regexCtxt = pielem->regexCtxt;
26553             if (regexCtxt == NULL) {
26554                 /*
26555                 * Create the regex context.
26556                 */
26557                 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26558                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26559                     vctxt);
26560                 if (regexCtxt == NULL) {
26561                     VERROR_INT("xmlSchemaValidateChildElem",
26562                         "failed to create a regex context");
26563                     return (-1);
26564                 }
26565                 pielem->regexCtxt = regexCtxt;
26566 #ifdef DEBUG_AUTOMATA
26567                 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26568                     pielem->localName);
26569 #endif
26570             }
26571
26572             /*
26573             * SPEC (2.4) "If the {content type} is element-only or mixed,
26574             * then the sequence of the element information item's
26575             * element information item [children], if any, taken in
26576             * order, is ï¿½valid� with respect to the {content type}'s
26577             * particle, as defined in Element Sequence Locally Valid
26578             * (Particle) (�3.9.4)."
26579             */
26580             ret = xmlRegExecPushString2(regexCtxt,
26581                 vctxt->inode->localName,
26582                 vctxt->inode->nsName,
26583                 vctxt->inode);
26584 #ifdef DEBUG_AUTOMATA
26585             if (ret < 0)
26586                 xmlGenericError(xmlGenericErrorContext,
26587                 "AUTOMATON push ERROR for '%s' on '%s'\n",
26588                 vctxt->inode->localName, pielem->localName);
26589             else
26590                 xmlGenericError(xmlGenericErrorContext,
26591                 "AUTOMATON push OK for '%s' on '%s'\n",
26592                 vctxt->inode->localName, pielem->localName);
26593 #endif
26594             if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26595                 VERROR_INT("xmlSchemaValidateChildElem",
26596                     "calling xmlRegExecPushString2()");
26597                 return (-1);
26598             }
26599             if (ret < 0) {
26600                 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26601                     &values[0], &terminal);
26602                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26603                     XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26604                     "This element is not expected",
26605                     nbval, nbneg, values);
26606                 ret = vctxt->err;
26607                 goto unexpected_elem;
26608             } else
26609                 ret = 0;
26610         }
26611             break;
26612         case XML_SCHEMA_CONTENT_SIMPLE:
26613         case XML_SCHEMA_CONTENT_BASIC:
26614             ACTIVATE_PARENT_ELEM
26615             if (WXS_IS_COMPLEX(ptype)) {
26616                 /*
26617                 * SPEC (cvc-complex-type) (2.2)
26618                 * "If the {content type} is a simple type definition, then
26619                 * the element information item has no element information
26620                 * item [children], ..."
26621                 */
26622                 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26623                 VERROR(ret, NULL, "Element content is not allowed, "
26624                     "because the content type is a simple type definition");
26625             } else {
26626                 /*
26627                 * SPEC (cvc-type) (3.1.2) "The element information item must
26628                 * have no element information item [children]."
26629                 */
26630                 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26631                 VERROR(ret, NULL, "Element content is not allowed, "
26632                     "because the type definition is simple");
26633             }
26634             ACTIVATE_ELEM
26635             ret = vctxt->err;
26636             goto unexpected_elem;
26637             break;
26638
26639         default:
26640             break;
26641     }
26642     return (ret);
26643 unexpected_elem:
26644     /*
26645     * Pop this element and set the skipDepth to skip
26646     * all further content of the parent element.
26647     */
26648     vctxt->skipDepth = vctxt->depth;
26649     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26650     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26651     return (ret);
26652 }
26653
26654 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26655 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26656 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26657
26658 static int
26659 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26660                   int nodeType, const xmlChar *value, int len,
26661                   int mode, int *consumed)
26662 {
26663     /*
26664     * Unfortunately we have to duplicate the text sometimes.
26665     * OPTIMIZE: Maybe we could skip it, if:
26666     *   1. content type is simple
26667     *   2. whitespace is "collapse"
26668     *   3. it consists of whitespace only
26669     *
26670     * Process character content.
26671     */
26672     if (consumed != NULL)
26673         *consumed = 0;
26674     if (INODE_NILLED(vctxt->inode)) {
26675         /*
26676         * SPEC cvc-elt (3.3.4 - 3.2.1)
26677         * "The element information item must have no character or
26678         * element information item [children]."
26679         */
26680         VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26681             "Neither character nor element content is allowed "
26682             "because the element is 'nilled'");
26683         return (vctxt->err);
26684     }
26685     /*
26686     * SPEC (2.1) "If the {content type} is empty, then the
26687     * element information item has no character or element
26688     * information item [children]."
26689     */
26690     if (vctxt->inode->typeDef->contentType ==
26691             XML_SCHEMA_CONTENT_EMPTY) {
26692         VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26693             "Character content is not allowed, "
26694             "because the content type is empty");
26695         return (vctxt->err);
26696     }
26697
26698     if (vctxt->inode->typeDef->contentType ==
26699             XML_SCHEMA_CONTENT_ELEMENTS) {
26700         if ((nodeType != XML_TEXT_NODE) ||
26701             (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26702             /*
26703             * SPEC cvc-complex-type (2.3)
26704             * "If the {content type} is element-only, then the
26705             * element information item has no character information
26706             * item [children] other than those whose [character
26707             * code] is defined as a white space in [XML 1.0 (Second
26708             * Edition)]."
26709             */
26710             VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26711                 "Character content other than whitespace is not allowed "
26712                 "because the content type is 'element-only'");
26713             return (vctxt->err);
26714         }
26715         return (0);
26716     }
26717
26718     if ((value == NULL) || (value[0] == 0))
26719         return (0);
26720     /*
26721     * Save the value.
26722     * NOTE that even if the content type is *mixed*, we need the
26723     * *initial value* for default/fixed value constraints.
26724     */
26725     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26726         ((vctxt->inode->decl == NULL) ||
26727         (vctxt->inode->decl->value == NULL)))
26728         return (0);
26729
26730     if (vctxt->inode->value == NULL) {
26731         /*
26732         * Set the value.
26733         */
26734         switch (mode) {
26735             case XML_SCHEMA_PUSH_TEXT_PERSIST:
26736                 /*
26737                 * When working on a tree.
26738                 */
26739                 vctxt->inode->value = value;
26740                 break;
26741             case XML_SCHEMA_PUSH_TEXT_CREATED:
26742                 /*
26743                 * When working with the reader.
26744                 * The value will be freed by the element info.
26745                 */
26746                 vctxt->inode->value = value;
26747                 if (consumed != NULL)
26748                     *consumed = 1;
26749                 vctxt->inode->flags |=
26750                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26751                 break;
26752             case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26753                 /*
26754                 * When working with SAX.
26755                 * The value will be freed by the element info.
26756                 */
26757                 if (len != -1)
26758                     vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26759                 else
26760                     vctxt->inode->value = BAD_CAST xmlStrdup(value);
26761                 vctxt->inode->flags |=
26762                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26763                 break;
26764             default:
26765                 break;
26766         }
26767     } else {
26768         if (len < 0)
26769             len = xmlStrlen(value);
26770         /*
26771         * Concat the value.
26772         */
26773         if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26774             vctxt->inode->value = BAD_CAST xmlStrncat(
26775                 (xmlChar *) vctxt->inode->value, value, len);
26776         } else {
26777             vctxt->inode->value =
26778                 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26779             vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26780         }
26781     }
26782
26783     return (0);
26784 }
26785
26786 static int
26787 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26788 {
26789     int ret = 0;
26790
26791     if ((vctxt->skipDepth != -1) &&
26792         (vctxt->depth >= vctxt->skipDepth)) {
26793         VERROR_INT("xmlSchemaValidateElem",
26794             "in skip-state");
26795         goto internal_error;
26796     }
26797     if (vctxt->xsiAssemble) {
26798         /*
26799         * We will stop validation if there was an error during
26800         * dynamic schema construction.
26801         * Note that we simply set @skipDepth to 0, this could
26802         * mean that a streaming document via SAX would be
26803         * still read to the end but it won't be validated any more.
26804         * TODO: If we are sure how to stop the validation at once
26805         *   for all input scenarios, then this should be changed to
26806         *   instantly stop the validation.
26807         */
26808         ret = xmlSchemaAssembleByXSI(vctxt);
26809         if (ret != 0) {
26810             if (ret == -1)
26811                 goto internal_error;
26812             vctxt->skipDepth = 0;
26813             return(ret);
26814         }
26815         /*
26816          * Augment the IDC definitions for the main schema and all imported ones
26817          * NOTE: main schema is the first in the imported list
26818          */
26819         xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26820     }
26821     if (vctxt->depth > 0) {
26822         /*
26823         * Validate this element against the content model
26824         * of the parent.
26825         */
26826         ret = xmlSchemaValidateChildElem(vctxt);
26827         if (ret != 0) {
26828             if (ret < 0) {
26829                 VERROR_INT("xmlSchemaValidateElem",
26830                     "calling xmlSchemaStreamValidateChildElement()");
26831                 goto internal_error;
26832             }
26833             goto exit;
26834         }
26835         if (vctxt->depth == vctxt->skipDepth)
26836             goto exit;
26837         if ((vctxt->inode->decl == NULL) &&
26838             (vctxt->inode->typeDef == NULL)) {
26839             VERROR_INT("xmlSchemaValidateElem",
26840                 "the child element was valid but neither the "
26841                 "declaration nor the type was set");
26842             goto internal_error;
26843         }
26844     } else {
26845         /*
26846         * Get the declaration of the validation root.
26847         */
26848         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26849             vctxt->inode->localName,
26850             vctxt->inode->nsName);
26851         if (vctxt->inode->decl == NULL) {
26852             ret = XML_SCHEMAV_CVC_ELT_1;
26853             VERROR(ret, NULL,
26854                 "No matching global declaration available "
26855                 "for the validation root");
26856             goto exit;
26857         }
26858     }
26859
26860     if (vctxt->inode->decl == NULL)
26861         goto type_validation;
26862
26863     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26864         int skip;
26865         /*
26866         * Wildcards.
26867         */
26868         ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26869         if (ret != 0) {
26870             if (ret < 0) {
26871                 VERROR_INT("xmlSchemaValidateElem",
26872                     "calling xmlSchemaValidateElemWildcard()");
26873                 goto internal_error;
26874             }
26875             goto exit;
26876         }
26877         if (skip) {
26878             vctxt->skipDepth = vctxt->depth;
26879             goto exit;
26880         }
26881         /*
26882         * The declaration might be set by the wildcard validation,
26883         * when the processContents is "lax" or "strict".
26884         */
26885         if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26886             /*
26887             * Clear the "decl" field to not confuse further processing.
26888             */
26889             vctxt->inode->decl = NULL;
26890             goto type_validation;
26891         }
26892     }
26893     /*
26894     * Validate against the declaration.
26895     */
26896     ret = xmlSchemaValidateElemDecl(vctxt);
26897     if (ret != 0) {
26898         if (ret < 0) {
26899             VERROR_INT("xmlSchemaValidateElem",
26900                 "calling xmlSchemaValidateElemDecl()");
26901             goto internal_error;
26902         }
26903         goto exit;
26904     }
26905     /*
26906     * Validate against the type definition.
26907     */
26908 type_validation:
26909
26910     if (vctxt->inode->typeDef == NULL) {
26911         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26912         ret = XML_SCHEMAV_CVC_TYPE_1;
26913         VERROR(ret, NULL,
26914             "The type definition is absent");
26915         goto exit;
26916     }
26917     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26918         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26919         ret = XML_SCHEMAV_CVC_TYPE_2;
26920             VERROR(ret, NULL,
26921             "The type definition is abstract");
26922         goto exit;
26923     }
26924     /*
26925     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26926     * during validation against the declaration. This must be done
26927     * _before_ attribute validation.
26928     */
26929     if (vctxt->xpathStates != NULL) {
26930         ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26931         vctxt->inode->appliedXPath = 1;
26932         if (ret == -1) {
26933             VERROR_INT("xmlSchemaValidateElem",
26934                 "calling xmlSchemaXPathEvaluate()");
26935             goto internal_error;
26936         }
26937     }
26938     /*
26939     * Validate attributes.
26940     */
26941     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26942         if ((vctxt->nbAttrInfos != 0) ||
26943             (vctxt->inode->typeDef->attrUses != NULL)) {
26944
26945             ret = xmlSchemaVAttributesComplex(vctxt);
26946         }
26947     } else if (vctxt->nbAttrInfos != 0) {
26948
26949         ret = xmlSchemaVAttributesSimple(vctxt);
26950     }
26951     /*
26952     * Clear registered attributes.
26953     */
26954     if (vctxt->nbAttrInfos != 0)
26955         xmlSchemaClearAttrInfos(vctxt);
26956     if (ret == -1) {
26957         VERROR_INT("xmlSchemaValidateElem",
26958             "calling attributes validation");
26959         goto internal_error;
26960     }
26961     /*
26962     * Don't return an error if attributes are invalid on purpose.
26963     */
26964     ret = 0;
26965
26966 exit:
26967     if (ret != 0)
26968         vctxt->skipDepth = vctxt->depth;
26969     return (ret);
26970 internal_error:
26971     return (-1);
26972 }
26973
26974 #ifdef XML_SCHEMA_READER_ENABLED
26975 static int
26976 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26977 {
26978     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26979     int depth, nodeType, ret = 0, consumed;
26980     xmlSchemaNodeInfoPtr ielem;
26981
26982     vctxt->depth = -1;
26983     ret = xmlTextReaderRead(vctxt->reader);
26984     /*
26985     * Move to the document element.
26986     */
26987     while (ret == 1) {
26988         nodeType = xmlTextReaderNodeType(vctxt->reader);
26989         if (nodeType == XML_ELEMENT_NODE)
26990             goto root_found;
26991         ret = xmlTextReaderRead(vctxt->reader);
26992     }
26993     goto exit;
26994
26995 root_found:
26996
26997     do {
26998         depth = xmlTextReaderDepth(vctxt->reader);
26999         nodeType = xmlTextReaderNodeType(vctxt->reader);
27000
27001         if (nodeType == XML_ELEMENT_NODE) {
27002
27003             vctxt->depth++;
27004             if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27005                 VERROR_INT("xmlSchemaVReaderWalk",
27006                     "calling xmlSchemaValidatorPushElem()");
27007                 goto internal_error;
27008             }
27009             ielem = vctxt->inode;
27010             ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27011             ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27012             ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27013             /*
27014             * Is the element empty?
27015             */
27016             ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27017             if (ret == -1) {
27018                 VERROR_INT("xmlSchemaVReaderWalk",
27019                     "calling xmlTextReaderIsEmptyElement()");
27020                 goto internal_error;
27021             }
27022             if (ret) {
27023                 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27024             }
27025             /*
27026             * Register attributes.
27027             */
27028             vctxt->nbAttrInfos = 0;
27029             ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27030             if (ret == -1) {
27031                 VERROR_INT("xmlSchemaVReaderWalk",
27032                     "calling xmlTextReaderMoveToFirstAttribute()");
27033                 goto internal_error;
27034             }
27035             if (ret == 1) {
27036                 do {
27037                     /*
27038                     * VAL TODO: How do we know that the reader works on a
27039                     * node tree, to be able to pass a node here?
27040                     */
27041                     if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27042                         (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27043                         xmlTextReaderNamespaceUri(vctxt->reader), 1,
27044                         xmlTextReaderValue(vctxt->reader), 1) == -1) {
27045
27046                         VERROR_INT("xmlSchemaVReaderWalk",
27047                             "calling xmlSchemaValidatorPushAttribute()");
27048                         goto internal_error;
27049                     }
27050                     ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27051                     if (ret == -1) {
27052                         VERROR_INT("xmlSchemaVReaderWalk",
27053                             "calling xmlTextReaderMoveToFirstAttribute()");
27054                         goto internal_error;
27055                     }
27056                 } while (ret == 1);
27057                 /*
27058                 * Back to element position.
27059                 */
27060                 ret = xmlTextReaderMoveToElement(vctxt->reader);
27061                 if (ret == -1) {
27062                     VERROR_INT("xmlSchemaVReaderWalk",
27063                         "calling xmlTextReaderMoveToElement()");
27064                     goto internal_error;
27065                 }
27066             }
27067             /*
27068             * Validate the element.
27069             */
27070             ret= xmlSchemaValidateElem(vctxt);
27071             if (ret != 0) {
27072                 if (ret == -1) {
27073                     VERROR_INT("xmlSchemaVReaderWalk",
27074                         "calling xmlSchemaValidateElem()");
27075                     goto internal_error;
27076                 }
27077                 goto exit;
27078             }
27079             if (vctxt->depth == vctxt->skipDepth) {
27080                 int curDepth;
27081                 /*
27082                 * Skip all content.
27083                 */
27084                 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27085                     ret = xmlTextReaderRead(vctxt->reader);
27086                     curDepth = xmlTextReaderDepth(vctxt->reader);
27087                     while ((ret == 1) && (curDepth != depth)) {
27088                         ret = xmlTextReaderRead(vctxt->reader);
27089                         curDepth = xmlTextReaderDepth(vctxt->reader);
27090                     }
27091                     if (ret < 0) {
27092                         /*
27093                         * VAL TODO: A reader error occured; what to do here?
27094                         */
27095                         ret = 1;
27096                         goto exit;
27097                     }
27098                 }
27099                 goto leave_elem;
27100             }
27101             /*
27102             * READER VAL TODO: Is an END_ELEM really never called
27103             * if the elem is empty?
27104             */
27105             if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27106                 goto leave_elem;
27107         } else if (nodeType == END_ELEM) {
27108             /*
27109             * Process END of element.
27110             */
27111 leave_elem:
27112             ret = xmlSchemaValidatorPopElem(vctxt);
27113             if (ret != 0) {
27114                 if (ret < 0) {
27115                     VERROR_INT("xmlSchemaVReaderWalk",
27116                         "calling xmlSchemaValidatorPopElem()");
27117                     goto internal_error;
27118                 }
27119                 goto exit;
27120             }
27121             if (vctxt->depth >= 0)
27122                 ielem = vctxt->inode;
27123             else
27124                 ielem = NULL;
27125         } else if ((nodeType == XML_TEXT_NODE) ||
27126             (nodeType == XML_CDATA_SECTION_NODE) ||
27127             (nodeType == WHTSP) ||
27128             (nodeType == SIGN_WHTSP)) {
27129             /*
27130             * Process character content.
27131             */
27132             xmlChar *value;
27133
27134             if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27135                 nodeType = XML_TEXT_NODE;
27136
27137             value = xmlTextReaderValue(vctxt->reader);
27138             ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27139                 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27140             if (! consumed)
27141                 xmlFree(value);
27142             if (ret == -1) {
27143                 VERROR_INT("xmlSchemaVReaderWalk",
27144                     "calling xmlSchemaVPushText()");
27145                 goto internal_error;
27146             }
27147         } else if ((nodeType == XML_ENTITY_NODE) ||
27148             (nodeType == XML_ENTITY_REF_NODE)) {
27149             /*
27150             * VAL TODO: What to do with entities?
27151             */
27152             TODO
27153         }
27154         /*
27155         * Read next node.
27156         */
27157         ret = xmlTextReaderRead(vctxt->reader);
27158     } while (ret == 1);
27159
27160 exit:
27161     return (ret);
27162 internal_error:
27163     return (-1);
27164 }
27165 #endif
27166
27167 /************************************************************************
27168  *                                                                      *
27169  *                      SAX validation handlers                         *
27170  *                                                                      *
27171  ************************************************************************/
27172
27173 /*
27174 * Process text content.
27175 */
27176 static void
27177 xmlSchemaSAXHandleText(void *ctx,
27178                        const xmlChar * ch,
27179                        int len)
27180 {
27181     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27182
27183     if (vctxt->depth < 0)
27184         return;
27185     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27186         return;
27187     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27188         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27189     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27190         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27191         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27192             "calling xmlSchemaVPushText()");
27193         vctxt->err = -1;
27194         xmlStopParser(vctxt->parserCtxt);
27195     }
27196 }
27197
27198 /*
27199 * Process CDATA content.
27200 */
27201 static void
27202 xmlSchemaSAXHandleCDataSection(void *ctx,
27203                              const xmlChar * ch,
27204                              int len)
27205 {
27206     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27207
27208     if (vctxt->depth < 0)
27209         return;
27210     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27211         return;
27212     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27213         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27214     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27215         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27216         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27217             "calling xmlSchemaVPushText()");
27218         vctxt->err = -1;
27219         xmlStopParser(vctxt->parserCtxt);
27220     }
27221 }
27222
27223 static void
27224 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27225                             const xmlChar * name ATTRIBUTE_UNUSED)
27226 {
27227     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27228
27229     if (vctxt->depth < 0)
27230         return;
27231     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27232         return;
27233     /* SAX VAL TODO: What to do here? */
27234     TODO
27235 }
27236
27237 static void
27238 xmlSchemaSAXHandleStartElementNs(void *ctx,
27239                                  const xmlChar * localname,
27240                                  const xmlChar * prefix ATTRIBUTE_UNUSED,
27241                                  const xmlChar * URI,
27242                                  int nb_namespaces,
27243                                  const xmlChar ** namespaces,
27244                                  int nb_attributes,
27245                                  int nb_defaulted ATTRIBUTE_UNUSED,
27246                                  const xmlChar ** attributes)
27247 {
27248     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27249     int ret;
27250     xmlSchemaNodeInfoPtr ielem;
27251     int i, j;
27252
27253     /*
27254     * SAX VAL TODO: What to do with nb_defaulted?
27255     */
27256     /*
27257     * Skip elements if inside a "skip" wildcard or invalid.
27258     */
27259     vctxt->depth++;
27260     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27261         return;
27262     /*
27263     * Push the element.
27264     */
27265     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27266         VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27267             "calling xmlSchemaValidatorPushElem()");
27268         goto internal_error;
27269     }
27270     ielem = vctxt->inode;
27271     /*
27272     * TODO: Is this OK?
27273     */
27274     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27275     ielem->localName = localname;
27276     ielem->nsName = URI;
27277     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27278     /*
27279     * Register namespaces on the elem info.
27280     */
27281     if (nb_namespaces != 0) {
27282         /*
27283         * Although the parser builds its own namespace list,
27284         * we have no access to it, so we'll use an own one.
27285         */
27286         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27287             /*
27288             * Store prefix and namespace name.
27289             */
27290             if (ielem->nsBindings == NULL) {
27291                 ielem->nsBindings =
27292                     (const xmlChar **) xmlMalloc(10 *
27293                         sizeof(const xmlChar *));
27294                 if (ielem->nsBindings == NULL) {
27295                     xmlSchemaVErrMemory(vctxt,
27296                         "allocating namespace bindings for SAX validation",
27297                         NULL);
27298                     goto internal_error;
27299                 }
27300                 ielem->nbNsBindings = 0;
27301                 ielem->sizeNsBindings = 5;
27302             } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27303                 ielem->sizeNsBindings *= 2;
27304                 ielem->nsBindings =
27305                     (const xmlChar **) xmlRealloc(
27306                         (void *) ielem->nsBindings,
27307                         ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27308                 if (ielem->nsBindings == NULL) {
27309                     xmlSchemaVErrMemory(vctxt,
27310                         "re-allocating namespace bindings for SAX validation",
27311                         NULL);
27312                     goto internal_error;
27313                 }
27314             }
27315
27316             ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27317             if (namespaces[j+1][0] == 0) {
27318                 /*
27319                 * Handle xmlns="".
27320                 */
27321                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27322             } else
27323                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27324                     namespaces[j+1];
27325             ielem->nbNsBindings++;
27326         }
27327     }
27328     /*
27329     * Register attributes.
27330     * SAX VAL TODO: We are not adding namespace declaration
27331     * attributes yet.
27332     */
27333     if (nb_attributes != 0) {
27334         xmlChar *value;
27335
27336         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27337             /*
27338             * Duplicate the value.
27339             */
27340             value = xmlStrndup(attributes[j+3],
27341                 attributes[j+4] - attributes[j+3]);
27342             /*
27343             * TODO: Set the node line.
27344             */
27345             ret = xmlSchemaValidatorPushAttribute(vctxt,
27346                 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27347                 value, 1);
27348             if (ret == -1) {
27349                 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27350                     "calling xmlSchemaValidatorPushAttribute()");
27351                 goto internal_error;
27352             }
27353         }
27354     }
27355     /*
27356     * Validate the element.
27357     */
27358     ret = xmlSchemaValidateElem(vctxt);
27359     if (ret != 0) {
27360         if (ret == -1) {
27361             VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27362                 "calling xmlSchemaValidateElem()");
27363             goto internal_error;
27364         }
27365         goto exit;
27366     }
27367
27368 exit:
27369     return;
27370 internal_error:
27371     vctxt->err = -1;
27372     xmlStopParser(vctxt->parserCtxt);
27373     return;
27374 }
27375
27376 static void
27377 xmlSchemaSAXHandleEndElementNs(void *ctx,
27378                                const xmlChar * localname ATTRIBUTE_UNUSED,
27379                                const xmlChar * prefix ATTRIBUTE_UNUSED,
27380                                const xmlChar * URI ATTRIBUTE_UNUSED)
27381 {
27382     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27383     int res;
27384
27385     /*
27386     * Skip elements if inside a "skip" wildcard or if invalid.
27387     */
27388     if (vctxt->skipDepth != -1) {
27389         if (vctxt->depth > vctxt->skipDepth) {
27390             vctxt->depth--;
27391             return;
27392         } else
27393             vctxt->skipDepth = -1;
27394     }
27395     /*
27396     * SAX VAL TODO: Just a temporary check.
27397     */
27398     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27399         (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27400         VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27401             "elem pop mismatch");
27402     }
27403     res = xmlSchemaValidatorPopElem(vctxt);
27404     if (res != 0) {
27405         if (res < 0) {
27406             VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27407                 "calling xmlSchemaValidatorPopElem()");
27408             goto internal_error;
27409         }
27410         goto exit;
27411     }
27412 exit:
27413     return;
27414 internal_error:
27415     vctxt->err = -1;
27416     xmlStopParser(vctxt->parserCtxt);
27417     return;
27418 }
27419
27420 /************************************************************************
27421  *                                                                      *
27422  *                      Validation interfaces                           *
27423  *                                                                      *
27424  ************************************************************************/
27425
27426 /**
27427  * xmlSchemaNewValidCtxt:
27428  * @schema:  a precompiled XML Schemas
27429  *
27430  * Create an XML Schemas validation context based on the given schema.
27431  *
27432  * Returns the validation context or NULL in case of error
27433  */
27434 xmlSchemaValidCtxtPtr
27435 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27436 {
27437     xmlSchemaValidCtxtPtr ret;
27438
27439     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27440     if (ret == NULL) {
27441         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27442         return (NULL);
27443     }
27444     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27445     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27446     ret->dict = xmlDictCreate();
27447     ret->nodeQNames = xmlSchemaItemListCreate();
27448     ret->schema = schema;
27449     return (ret);
27450 }
27451
27452 /**
27453  * xmlSchemaClearValidCtxt:
27454  * @ctxt: the schema validation context
27455  *
27456  * Free the resources associated to the schema validation context;
27457  * leaves some fields alive intended for reuse of the context.
27458  */
27459 static void
27460 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27461 {
27462     if (vctxt == NULL)
27463         return;
27464
27465     /*
27466     * TODO: Should we clear the flags?
27467     *   Might be problematic if one reuses the context
27468     *   and assumes that the options remain the same.
27469     */
27470     vctxt->flags = 0;
27471     vctxt->validationRoot = NULL;
27472     vctxt->doc = NULL;
27473 #ifdef LIBXML_READER_ENABLED
27474     vctxt->reader = NULL;
27475 #endif
27476     vctxt->hasKeyrefs = 0;
27477
27478     if (vctxt->value != NULL) {
27479         xmlSchemaFreeValue(vctxt->value);
27480         vctxt->value = NULL;
27481     }
27482     /*
27483     * Augmented IDC information.
27484     */
27485     if (vctxt->aidcs != NULL) {
27486         xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27487         do {
27488             next = cur->next;
27489             xmlFree(cur);
27490             cur = next;
27491         } while (cur != NULL);
27492         vctxt->aidcs = NULL;
27493     }
27494     if (vctxt->idcMatcherCache != NULL) {
27495         xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27496
27497         while (matcher) {
27498             tmp = matcher;
27499             matcher = matcher->nextCached;
27500             xmlSchemaIDCFreeMatcherList(tmp);
27501         }
27502         vctxt->idcMatcherCache = NULL;
27503     }
27504
27505
27506     if (vctxt->idcNodes != NULL) {
27507         int i;
27508         xmlSchemaPSVIIDCNodePtr item;
27509
27510         for (i = 0; i < vctxt->nbIdcNodes; i++) {
27511             item = vctxt->idcNodes[i];
27512             xmlFree(item->keys);
27513             xmlFree(item);
27514         }
27515         xmlFree(vctxt->idcNodes);
27516         vctxt->idcNodes = NULL;
27517         vctxt->nbIdcNodes = 0;
27518         vctxt->sizeIdcNodes = 0;
27519     }
27520     /*
27521     * Note that we won't delete the XPath state pool here.
27522     */
27523     if (vctxt->xpathStates != NULL) {
27524         xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27525         vctxt->xpathStates = NULL;
27526     }
27527     /*
27528     * Attribute info.
27529     */
27530     if (vctxt->nbAttrInfos != 0) {
27531         xmlSchemaClearAttrInfos(vctxt);
27532     }
27533     /*
27534     * Element info.
27535     */
27536     if (vctxt->elemInfos != NULL) {
27537         int i;
27538         xmlSchemaNodeInfoPtr ei;
27539
27540         for (i = 0; i < vctxt->sizeElemInfos; i++) {
27541             ei = vctxt->elemInfos[i];
27542             if (ei == NULL)
27543                 break;
27544             xmlSchemaClearElemInfo(vctxt, ei);
27545         }
27546     }
27547     xmlSchemaItemListClear(vctxt->nodeQNames);
27548     /* Recreate the dict. */
27549     xmlDictFree(vctxt->dict);
27550     /*
27551     * TODO: Is is save to recreate it? Do we have a scenario
27552     * where the user provides the dict?
27553     */
27554     vctxt->dict = xmlDictCreate();
27555 }
27556
27557 /**
27558  * xmlSchemaFreeValidCtxt:
27559  * @ctxt:  the schema validation context
27560  *
27561  * Free the resources associated to the schema validation context
27562  */
27563 void
27564 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27565 {
27566     if (ctxt == NULL)
27567         return;
27568     if (ctxt->value != NULL)
27569         xmlSchemaFreeValue(ctxt->value);
27570     if (ctxt->pctxt != NULL)
27571         xmlSchemaFreeParserCtxt(ctxt->pctxt);
27572     if (ctxt->idcNodes != NULL) {
27573         int i;
27574         xmlSchemaPSVIIDCNodePtr item;
27575
27576         for (i = 0; i < ctxt->nbIdcNodes; i++) {
27577             item = ctxt->idcNodes[i];
27578             xmlFree(item->keys);
27579             xmlFree(item);
27580         }
27581         xmlFree(ctxt->idcNodes);
27582     }
27583     if (ctxt->idcKeys != NULL) {
27584         int i;
27585         for (i = 0; i < ctxt->nbIdcKeys; i++)
27586             xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27587         xmlFree(ctxt->idcKeys);
27588     }
27589
27590     if (ctxt->xpathStates != NULL) {
27591         xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27592         ctxt->xpathStates = NULL;
27593     }
27594     if (ctxt->xpathStatePool != NULL) {
27595         xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27596         ctxt->xpathStatePool = NULL;
27597     }
27598
27599     /*
27600     * Augmented IDC information.
27601     */
27602     if (ctxt->aidcs != NULL) {
27603         xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27604         do {
27605             next = cur->next;
27606             xmlFree(cur);
27607             cur = next;
27608         } while (cur != NULL);
27609     }
27610     if (ctxt->attrInfos != NULL) {
27611         int i;
27612         xmlSchemaAttrInfoPtr attr;
27613
27614         /* Just a paranoid call to the cleanup. */
27615         if (ctxt->nbAttrInfos != 0)
27616             xmlSchemaClearAttrInfos(ctxt);
27617         for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27618             attr = ctxt->attrInfos[i];
27619             xmlFree(attr);
27620         }
27621         xmlFree(ctxt->attrInfos);
27622     }
27623     if (ctxt->elemInfos != NULL) {
27624         int i;
27625         xmlSchemaNodeInfoPtr ei;
27626
27627         for (i = 0; i < ctxt->sizeElemInfos; i++) {
27628             ei = ctxt->elemInfos[i];
27629             if (ei == NULL)
27630                 break;
27631             xmlSchemaClearElemInfo(ctxt, ei);
27632             xmlFree(ei);
27633         }
27634         xmlFree(ctxt->elemInfos);
27635     }
27636     if (ctxt->nodeQNames != NULL)
27637         xmlSchemaItemListFree(ctxt->nodeQNames);
27638     if (ctxt->dict != NULL)
27639         xmlDictFree(ctxt->dict);
27640     xmlFree(ctxt);
27641 }
27642
27643 /**
27644  * xmlSchemaIsValid:
27645  * @ctxt: the schema validation context
27646  *
27647  * Check if any error was detected during validation.
27648  *
27649  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27650  *         of internal error.
27651  */
27652 int
27653 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27654 {
27655     if (ctxt == NULL)
27656         return(-1);
27657     return(ctxt->err == 0);
27658 }
27659
27660 /**
27661  * xmlSchemaSetValidErrors:
27662  * @ctxt:  a schema validation context
27663  * @err:  the error function
27664  * @warn: the warning function
27665  * @ctx: the functions context
27666  *
27667  * Set the error and warning callback informations
27668  */
27669 void
27670 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27671                         xmlSchemaValidityErrorFunc err,
27672                         xmlSchemaValidityWarningFunc warn, void *ctx)
27673 {
27674     if (ctxt == NULL)
27675         return;
27676     ctxt->error = err;
27677     ctxt->warning = warn;
27678     ctxt->errCtxt = ctx;
27679     if (ctxt->pctxt != NULL)
27680         xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27681 }
27682
27683 /**
27684  * xmlSchemaSetValidStructuredErrors:
27685  * @ctxt:  a schema validation context
27686  * @serror:  the structured error function
27687  * @ctx: the functions context
27688  *
27689  * Set the structured error callback
27690  */
27691 void
27692 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27693                                   xmlStructuredErrorFunc serror, void *ctx)
27694 {
27695     if (ctxt == NULL)
27696         return;
27697         ctxt->serror = serror;
27698     ctxt->error = NULL;
27699     ctxt->warning = NULL;
27700     ctxt->errCtxt = ctx;
27701     if (ctxt->pctxt != NULL)
27702         xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27703 }
27704
27705 /**
27706  * xmlSchemaGetValidErrors:
27707  * @ctxt: a XML-Schema validation context
27708  * @err: the error function result
27709  * @warn: the warning function result
27710  * @ctx: the functions context result
27711  *
27712  * Get the error and warning callback informations
27713  *
27714  * Returns -1 in case of error and 0 otherwise
27715  */
27716 int
27717 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27718                         xmlSchemaValidityErrorFunc * err,
27719                         xmlSchemaValidityWarningFunc * warn, void **ctx)
27720 {
27721         if (ctxt == NULL)
27722                 return (-1);
27723         if (err != NULL)
27724                 *err = ctxt->error;
27725         if (warn != NULL)
27726                 *warn = ctxt->warning;
27727         if (ctx != NULL)
27728                 *ctx = ctxt->errCtxt;
27729         return (0);
27730 }
27731
27732
27733 /**
27734  * xmlSchemaSetValidOptions:
27735  * @ctxt:       a schema validation context
27736  * @options: a combination of xmlSchemaValidOption
27737  *
27738  * Sets the options to be used during the validation.
27739  *
27740  * Returns 0 in case of success, -1 in case of an
27741  * API error.
27742  */
27743 int
27744 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27745                          int options)
27746
27747 {
27748     int i;
27749
27750     if (ctxt == NULL)
27751         return (-1);
27752     /*
27753     * WARNING: Change the start value if adding to the
27754     * xmlSchemaValidOption.
27755     * TODO: Is there an other, more easy to maintain,
27756     * way?
27757     */
27758     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27759         if (options & 1<<i)
27760             return (-1);
27761     }
27762     ctxt->options = options;
27763     return (0);
27764 }
27765
27766 /**
27767  * xmlSchemaValidCtxtGetOptions:
27768  * @ctxt: a schema validation context
27769  *
27770  * Get the validation context options.
27771  *
27772  * Returns the option combination or -1 on error.
27773  */
27774 int
27775 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27776
27777 {
27778     if (ctxt == NULL)
27779         return (-1);
27780     else
27781         return (ctxt->options);
27782 }
27783
27784 static int
27785 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27786 {
27787     xmlAttrPtr attr;
27788     int ret = 0;
27789     xmlSchemaNodeInfoPtr ielem = NULL;
27790     xmlNodePtr node, valRoot;
27791     const xmlChar *nsName;
27792
27793     /* DOC VAL TODO: Move this to the start function. */
27794     valRoot = xmlDocGetRootElement(vctxt->doc);
27795     if (valRoot == NULL) {
27796         /* VAL TODO: Error code? */
27797         VERROR(1, NULL, "The document has no document element");
27798         return (1);
27799     }
27800     vctxt->depth = -1;
27801     vctxt->validationRoot = valRoot;
27802     node = valRoot;
27803     while (node != NULL) {
27804         if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27805             goto next_sibling;
27806         if (node->type == XML_ELEMENT_NODE) {
27807
27808             /*
27809             * Init the node-info.
27810             */
27811             vctxt->depth++;
27812             if (xmlSchemaValidatorPushElem(vctxt) == -1)
27813                 goto internal_error;
27814             ielem = vctxt->inode;
27815             ielem->node = node;
27816             ielem->nodeLine = node->line;
27817             ielem->localName = node->name;
27818             if (node->ns != NULL)
27819                 ielem->nsName = node->ns->href;
27820             ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27821             /*
27822             * Register attributes.
27823             * DOC VAL TODO: We do not register namespace declaration
27824             * attributes yet.
27825             */
27826             vctxt->nbAttrInfos = 0;
27827             if (node->properties != NULL) {
27828                 attr = node->properties;
27829                 do {
27830                     if (attr->ns != NULL)
27831                         nsName = attr->ns->href;
27832                     else
27833                         nsName = NULL;
27834                     ret = xmlSchemaValidatorPushAttribute(vctxt,
27835                         (xmlNodePtr) attr,
27836                         /*
27837                         * Note that we give it the line number of the
27838                         * parent element.
27839                         */
27840                         ielem->nodeLine,
27841                         attr->name, nsName, 0,
27842                         xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27843                     if (ret == -1) {
27844                         VERROR_INT("xmlSchemaDocWalk",
27845                             "calling xmlSchemaValidatorPushAttribute()");
27846                         goto internal_error;
27847                     }
27848                     attr = attr->next;
27849                 } while (attr);
27850             }
27851             /*
27852             * Validate the element.
27853             */
27854             ret = xmlSchemaValidateElem(vctxt);
27855             if (ret != 0) {
27856                 if (ret == -1) {
27857                     VERROR_INT("xmlSchemaDocWalk",
27858                         "calling xmlSchemaValidateElem()");
27859                     goto internal_error;
27860                 }
27861                 /*
27862                 * Don't stop validation; just skip the content
27863                 * of this element.
27864                 */
27865                 goto leave_node;
27866             }
27867             if ((vctxt->skipDepth != -1) &&
27868                 (vctxt->depth >= vctxt->skipDepth))
27869                 goto leave_node;
27870         } else if ((node->type == XML_TEXT_NODE) ||
27871             (node->type == XML_CDATA_SECTION_NODE)) {
27872             /*
27873             * Process character content.
27874             */
27875             if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27876                 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27877             ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27878                 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27879             if (ret < 0) {
27880                 VERROR_INT("xmlSchemaVDocWalk",
27881                     "calling xmlSchemaVPushText()");
27882                 goto internal_error;
27883             }
27884             /*
27885             * DOC VAL TODO: Should we skip further validation of the
27886             * element content here?
27887             */
27888         } else if ((node->type == XML_ENTITY_NODE) ||
27889             (node->type == XML_ENTITY_REF_NODE)) {
27890             /*
27891             * DOC VAL TODO: What to do with entities?
27892             */
27893             VERROR_INT("xmlSchemaVDocWalk",
27894                 "there is at least one entity reference in the node-tree "
27895                 "currently being validated. Processing of entities with "
27896                 "this XML Schema processor is not supported (yet). Please "
27897                 "substitute entities before validation.");
27898             goto internal_error;
27899         } else {
27900             goto leave_node;
27901             /*
27902             * DOC VAL TODO: XInclude nodes, etc.
27903             */
27904         }
27905         /*
27906         * Walk the doc.
27907         */
27908         if (node->children != NULL) {
27909             node = node->children;
27910             continue;
27911         }
27912 leave_node:
27913         if (node->type == XML_ELEMENT_NODE) {
27914             /*
27915             * Leaving the scope of an element.
27916             */
27917             if (node != vctxt->inode->node) {
27918                 VERROR_INT("xmlSchemaVDocWalk",
27919                     "element position mismatch");
27920                 goto internal_error;
27921             }
27922             ret = xmlSchemaValidatorPopElem(vctxt);
27923             if (ret != 0) {
27924                 if (ret < 0) {
27925                     VERROR_INT("xmlSchemaVDocWalk",
27926                         "calling xmlSchemaValidatorPopElem()");
27927                     goto internal_error;
27928                 }
27929             }
27930             if (node == valRoot)
27931                 goto exit;
27932         }
27933 next_sibling:
27934         if (node->next != NULL)
27935             node = node->next;
27936         else {
27937             node = node->parent;
27938             goto leave_node;
27939         }
27940     }
27941
27942 exit:
27943     return (ret);
27944 internal_error:
27945     return (-1);
27946 }
27947
27948 static int
27949 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27950     /*
27951     * Some initialization.
27952     */
27953     vctxt->err = 0;
27954     vctxt->nberrors = 0;
27955     vctxt->depth = -1;
27956     vctxt->skipDepth = -1;
27957     vctxt->xsiAssemble = 0;
27958     vctxt->hasKeyrefs = 0;
27959 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27960     vctxt->createIDCNodeTables = 1;
27961 #else
27962     vctxt->createIDCNodeTables = 0;
27963 #endif
27964     /*
27965     * Create a schema + parser if necessary.
27966     */
27967     if (vctxt->schema == NULL) {
27968         xmlSchemaParserCtxtPtr pctxt;
27969
27970         vctxt->xsiAssemble = 1;
27971         /*
27972         * If not schema was given then we will create a schema
27973         * dynamically using XSI schema locations.
27974         *
27975         * Create the schema parser context.
27976         */
27977         if ((vctxt->pctxt == NULL) &&
27978            (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27979            return (-1);
27980         pctxt = vctxt->pctxt;
27981         pctxt->xsiAssemble = 1;
27982         /*
27983         * Create the schema.
27984         */
27985         vctxt->schema = xmlSchemaNewSchema(pctxt);
27986         if (vctxt->schema == NULL)
27987             return (-1);
27988         /*
27989         * Create the schema construction context.
27990         */
27991         pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27992         if (pctxt->constructor == NULL)
27993             return(-1);
27994         pctxt->constructor->mainSchema = vctxt->schema;
27995         /*
27996         * Take ownership of the constructor to be able to free it.
27997         */
27998         pctxt->ownsConstructor = 1;
27999     }
28000     /*
28001     * Augment the IDC definitions for the main schema and all imported ones
28002     * NOTE: main schema if the first in the imported list
28003     */
28004     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28005
28006     return(0);
28007 }
28008
28009 static void
28010 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28011     if (vctxt->xsiAssemble) {
28012         if (vctxt->schema != NULL) {
28013             xmlSchemaFree(vctxt->schema);
28014             vctxt->schema = NULL;
28015         }
28016     }
28017     xmlSchemaClearValidCtxt(vctxt);
28018 }
28019
28020 static int
28021 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28022 {
28023     int ret = 0;
28024
28025     if (xmlSchemaPreRun(vctxt) < 0)
28026         return(-1);
28027
28028     if (vctxt->doc != NULL) {
28029         /*
28030          * Tree validation.
28031          */
28032         ret = xmlSchemaVDocWalk(vctxt);
28033 #ifdef LIBXML_READER_ENABLED
28034     } else if (vctxt->reader != NULL) {
28035         /*
28036          * XML Reader validation.
28037          */
28038 #ifdef XML_SCHEMA_READER_ENABLED
28039         ret = xmlSchemaVReaderWalk(vctxt);
28040 #endif
28041 #endif
28042     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28043         /*
28044          * SAX validation.
28045          */
28046         ret = xmlParseDocument(vctxt->parserCtxt);
28047     } else {
28048         VERROR_INT("xmlSchemaVStart",
28049             "no instance to validate");
28050         ret = -1;
28051     }
28052
28053     xmlSchemaPostRun(vctxt);
28054     if (ret == 0)
28055         ret = vctxt->err;
28056     return (ret);
28057 }
28058
28059 /**
28060  * xmlSchemaValidateOneElement:
28061  * @ctxt:  a schema validation context
28062  * @elem:  an element node
28063  *
28064  * Validate a branch of a tree, starting with the given @elem.
28065  *
28066  * Returns 0 if the element and its subtree is valid, a positive error
28067  * code number otherwise and -1 in case of an internal or API error.
28068  */
28069 int
28070 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28071 {
28072     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28073         return (-1);
28074
28075     if (ctxt->schema == NULL)
28076         return (-1);
28077
28078     ctxt->doc = elem->doc;
28079     ctxt->node = elem;
28080     ctxt->validationRoot = elem;
28081     return(xmlSchemaVStart(ctxt));
28082 }
28083
28084 /**
28085  * xmlSchemaValidateDoc:
28086  * @ctxt:  a schema validation context
28087  * @doc:  a parsed document tree
28088  *
28089  * Validate a document tree in memory.
28090  *
28091  * Returns 0 if the document is schemas valid, a positive error code
28092  *     number otherwise and -1 in case of internal or API error.
28093  */
28094 int
28095 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28096 {
28097     if ((ctxt == NULL) || (doc == NULL))
28098         return (-1);
28099
28100     ctxt->doc = doc;
28101     ctxt->node = xmlDocGetRootElement(doc);
28102     if (ctxt->node == NULL) {
28103         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28104             XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28105             (xmlNodePtr) doc, NULL,
28106             "The document has no document element", NULL, NULL);
28107         return (ctxt->err);
28108     }
28109     ctxt->validationRoot = ctxt->node;
28110     return (xmlSchemaVStart(ctxt));
28111 }
28112
28113
28114 /************************************************************************
28115  *                                                                      *
28116  *              Function and data for SAX streaming API                 *
28117  *                                                                      *
28118  ************************************************************************/
28119 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28120 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28121
28122 struct _xmlSchemaSplitSAXData {
28123     xmlSAXHandlerPtr      user_sax;
28124     void                 *user_data;
28125     xmlSchemaValidCtxtPtr ctxt;
28126     xmlSAXHandlerPtr      schemas_sax;
28127 };
28128
28129 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28130
28131 struct _xmlSchemaSAXPlug {
28132     unsigned int magic;
28133
28134     /* the original callbacks informations */
28135     xmlSAXHandlerPtr     *user_sax_ptr;
28136     xmlSAXHandlerPtr      user_sax;
28137     void                **user_data_ptr;
28138     void                 *user_data;
28139
28140     /* the block plugged back and validation informations */
28141     xmlSAXHandler         schemas_sax;
28142     xmlSchemaValidCtxtPtr ctxt;
28143 };
28144
28145 /* All those functions just bounces to the user provided SAX handlers */
28146 static void
28147 internalSubsetSplit(void *ctx, const xmlChar *name,
28148                const xmlChar *ExternalID, const xmlChar *SystemID)
28149 {
28150     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28151     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28152         (ctxt->user_sax->internalSubset != NULL))
28153         ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28154                                        SystemID);
28155 }
28156
28157 static int
28158 isStandaloneSplit(void *ctx)
28159 {
28160     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28161     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28162         (ctxt->user_sax->isStandalone != NULL))
28163         return(ctxt->user_sax->isStandalone(ctxt->user_data));
28164     return(0);
28165 }
28166
28167 static int
28168 hasInternalSubsetSplit(void *ctx)
28169 {
28170     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28171     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28172         (ctxt->user_sax->hasInternalSubset != NULL))
28173         return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28174     return(0);
28175 }
28176
28177 static int
28178 hasExternalSubsetSplit(void *ctx)
28179 {
28180     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28181     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28182         (ctxt->user_sax->hasExternalSubset != NULL))
28183         return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28184     return(0);
28185 }
28186
28187 static void
28188 externalSubsetSplit(void *ctx, const xmlChar *name,
28189                const xmlChar *ExternalID, const xmlChar *SystemID)
28190 {
28191     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28192     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28193         (ctxt->user_sax->externalSubset != NULL))
28194         ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28195                                        SystemID);
28196 }
28197
28198 static xmlParserInputPtr
28199 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28200 {
28201     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28202     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28203         (ctxt->user_sax->resolveEntity != NULL))
28204         return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28205                                              systemId));
28206     return(NULL);
28207 }
28208
28209 static xmlEntityPtr
28210 getEntitySplit(void *ctx, const xmlChar *name)
28211 {
28212     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28213     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28214         (ctxt->user_sax->getEntity != NULL))
28215         return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28216     return(NULL);
28217 }
28218
28219 static xmlEntityPtr
28220 getParameterEntitySplit(void *ctx, const xmlChar *name)
28221 {
28222     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28223     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28224         (ctxt->user_sax->getParameterEntity != NULL))
28225         return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28226     return(NULL);
28227 }
28228
28229
28230 static void
28231 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28232           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28233 {
28234     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28235     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28236         (ctxt->user_sax->entityDecl != NULL))
28237         ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28238                                    systemId, content);
28239 }
28240
28241 static void
28242 attributeDeclSplit(void *ctx, const xmlChar * elem,
28243                    const xmlChar * name, int type, int def,
28244                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28245 {
28246     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28247     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28248         (ctxt->user_sax->attributeDecl != NULL)) {
28249         ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28250                                       def, defaultValue, tree);
28251     } else {
28252         xmlFreeEnumeration(tree);
28253     }
28254 }
28255
28256 static void
28257 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28258             xmlElementContentPtr content)
28259 {
28260     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28261     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28262         (ctxt->user_sax->elementDecl != NULL))
28263         ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28264 }
28265
28266 static void
28267 notationDeclSplit(void *ctx, const xmlChar *name,
28268              const xmlChar *publicId, const xmlChar *systemId)
28269 {
28270     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28271     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28272         (ctxt->user_sax->notationDecl != NULL))
28273         ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28274                                      systemId);
28275 }
28276
28277 static void
28278 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28279                    const xmlChar *publicId, const xmlChar *systemId,
28280                    const xmlChar *notationName)
28281 {
28282     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28283     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28284         (ctxt->user_sax->unparsedEntityDecl != NULL))
28285         ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28286                                            systemId, notationName);
28287 }
28288
28289 static void
28290 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28291 {
28292     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28293     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28294         (ctxt->user_sax->setDocumentLocator != NULL))
28295         ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28296 }
28297
28298 static void
28299 startDocumentSplit(void *ctx)
28300 {
28301     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28302     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28303         (ctxt->user_sax->startDocument != NULL))
28304         ctxt->user_sax->startDocument(ctxt->user_data);
28305 }
28306
28307 static void
28308 endDocumentSplit(void *ctx)
28309 {
28310     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28311     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28312         (ctxt->user_sax->endDocument != NULL))
28313         ctxt->user_sax->endDocument(ctxt->user_data);
28314 }
28315
28316 static void
28317 processingInstructionSplit(void *ctx, const xmlChar *target,
28318                       const xmlChar *data)
28319 {
28320     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28321     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28322         (ctxt->user_sax->processingInstruction != NULL))
28323         ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28324 }
28325
28326 static void
28327 commentSplit(void *ctx, const xmlChar *value)
28328 {
28329     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28330     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28331         (ctxt->user_sax->comment != NULL))
28332         ctxt->user_sax->comment(ctxt->user_data, value);
28333 }
28334
28335 /*
28336  * Varargs error callbacks to the user application, harder ...
28337  */
28338
28339 static void XMLCDECL
28340 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28341     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28342     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28343         (ctxt->user_sax->warning != NULL)) {
28344         TODO
28345     }
28346 }
28347 static void XMLCDECL
28348 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28349     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28350     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28351         (ctxt->user_sax->error != NULL)) {
28352         TODO
28353     }
28354 }
28355 static void XMLCDECL
28356 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28357     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28358     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28359         (ctxt->user_sax->fatalError != NULL)) {
28360         TODO
28361     }
28362 }
28363
28364 /*
28365  * Those are function where both the user handler and the schemas handler
28366  * need to be called.
28367  */
28368 static void
28369 charactersSplit(void *ctx, const xmlChar *ch, int len)
28370 {
28371     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28372     if (ctxt == NULL)
28373         return;
28374     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28375         ctxt->user_sax->characters(ctxt->user_data, ch, len);
28376     if (ctxt->ctxt != NULL)
28377         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28378 }
28379
28380 static void
28381 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28382 {
28383     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28384     if (ctxt == NULL)
28385         return;
28386     if ((ctxt->user_sax != NULL) &&
28387         (ctxt->user_sax->ignorableWhitespace != NULL))
28388         ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28389     if (ctxt->ctxt != NULL)
28390         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28391 }
28392
28393 static void
28394 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28395 {
28396     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28397     if (ctxt == NULL)
28398         return;
28399     if ((ctxt->user_sax != NULL) &&
28400         (ctxt->user_sax->cdataBlock != NULL))
28401         ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28402     if (ctxt->ctxt != NULL)
28403         xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28404 }
28405
28406 static void
28407 referenceSplit(void *ctx, const xmlChar *name)
28408 {
28409     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28410     if (ctxt == NULL)
28411         return;
28412     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28413         (ctxt->user_sax->reference != NULL))
28414         ctxt->user_sax->reference(ctxt->user_data, name);
28415     if (ctxt->ctxt != NULL)
28416         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28417 }
28418
28419 static void
28420 startElementNsSplit(void *ctx, const xmlChar * localname,
28421                     const xmlChar * prefix, const xmlChar * URI,
28422                     int nb_namespaces, const xmlChar ** namespaces,
28423                     int nb_attributes, int nb_defaulted,
28424                     const xmlChar ** attributes) {
28425     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28426     if (ctxt == NULL)
28427         return;
28428     if ((ctxt->user_sax != NULL) &&
28429         (ctxt->user_sax->startElementNs != NULL))
28430         ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28431                                        URI, nb_namespaces, namespaces,
28432                                        nb_attributes, nb_defaulted,
28433                                        attributes);
28434     if (ctxt->ctxt != NULL)
28435         xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28436                                          URI, nb_namespaces, namespaces,
28437                                          nb_attributes, nb_defaulted,
28438                                          attributes);
28439 }
28440
28441 static void
28442 endElementNsSplit(void *ctx, const xmlChar * localname,
28443                     const xmlChar * prefix, const xmlChar * URI) {
28444     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28445     if (ctxt == NULL)
28446         return;
28447     if ((ctxt->user_sax != NULL) &&
28448         (ctxt->user_sax->endElementNs != NULL))
28449         ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28450     if (ctxt->ctxt != NULL)
28451         xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28452 }
28453
28454 /**
28455  * xmlSchemaSAXPlug:
28456  * @ctxt:  a schema validation context
28457  * @sax:  a pointer to the original xmlSAXHandlerPtr
28458  * @user_data:  a pointer to the original SAX user data pointer
28459  *
28460  * Plug a SAX based validation layer in a SAX parsing event flow.
28461  * The original @saxptr and @dataptr data are replaced by new pointers
28462  * but the calls to the original will be maintained.
28463  *
28464  * Returns a pointer to a data structure needed to unplug the validation layer
28465  *         or NULL in case of errors.
28466  */
28467 xmlSchemaSAXPlugPtr
28468 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28469                  xmlSAXHandlerPtr *sax, void **user_data)
28470 {
28471     xmlSchemaSAXPlugPtr ret;
28472     xmlSAXHandlerPtr old_sax;
28473
28474     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28475         return(NULL);
28476
28477     /*
28478      * We only allow to plug into SAX2 event streams
28479      */
28480     old_sax = *sax;
28481     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28482         return(NULL);
28483     if ((old_sax != NULL) &&
28484         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28485         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28486         return(NULL);
28487
28488     /*
28489      * everything seems right allocate the local data needed for that layer
28490      */
28491     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28492     if (ret == NULL) {
28493         return(NULL);
28494     }
28495     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28496     ret->magic = XML_SAX_PLUG_MAGIC;
28497     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28498     ret->ctxt = ctxt;
28499     ret->user_sax_ptr = sax;
28500     ret->user_sax = old_sax;
28501     if (old_sax == NULL) {
28502         /*
28503          * go direct, no need for the split block and functions.
28504          */
28505         ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28506         ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28507         /*
28508          * Note that we use the same text-function for both, to prevent
28509          * the parser from testing for ignorable whitespace.
28510          */
28511         ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28512         ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28513
28514         ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28515         ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28516
28517         ret->user_data = ctxt;
28518         *user_data = ctxt;
28519     } else {
28520        /*
28521         * for each callback unused by Schemas initialize it to the Split
28522         * routine only if non NULL in the user block, this can speed up
28523         * things at the SAX level.
28524         */
28525         if (old_sax->internalSubset != NULL)
28526             ret->schemas_sax.internalSubset = internalSubsetSplit;
28527         if (old_sax->isStandalone != NULL)
28528             ret->schemas_sax.isStandalone = isStandaloneSplit;
28529         if (old_sax->hasInternalSubset != NULL)
28530             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28531         if (old_sax->hasExternalSubset != NULL)
28532             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28533         if (old_sax->resolveEntity != NULL)
28534             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28535         if (old_sax->getEntity != NULL)
28536             ret->schemas_sax.getEntity = getEntitySplit;
28537         if (old_sax->entityDecl != NULL)
28538             ret->schemas_sax.entityDecl = entityDeclSplit;
28539         if (old_sax->notationDecl != NULL)
28540             ret->schemas_sax.notationDecl = notationDeclSplit;
28541         if (old_sax->attributeDecl != NULL)
28542             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28543         if (old_sax->elementDecl != NULL)
28544             ret->schemas_sax.elementDecl = elementDeclSplit;
28545         if (old_sax->unparsedEntityDecl != NULL)
28546             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28547         if (old_sax->setDocumentLocator != NULL)
28548             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28549         if (old_sax->startDocument != NULL)
28550             ret->schemas_sax.startDocument = startDocumentSplit;
28551         if (old_sax->endDocument != NULL)
28552             ret->schemas_sax.endDocument = endDocumentSplit;
28553         if (old_sax->processingInstruction != NULL)
28554             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28555         if (old_sax->comment != NULL)
28556             ret->schemas_sax.comment = commentSplit;
28557         if (old_sax->warning != NULL)
28558             ret->schemas_sax.warning = warningSplit;
28559         if (old_sax->error != NULL)
28560             ret->schemas_sax.error = errorSplit;
28561         if (old_sax->fatalError != NULL)
28562             ret->schemas_sax.fatalError = fatalErrorSplit;
28563         if (old_sax->getParameterEntity != NULL)
28564             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28565         if (old_sax->externalSubset != NULL)
28566             ret->schemas_sax.externalSubset = externalSubsetSplit;
28567
28568         /*
28569          * the 6 schemas callback have to go to the splitter functions
28570          * Note that we use the same text-function for ignorableWhitespace
28571          * if possible, to prevent the parser from testing for ignorable
28572          * whitespace.
28573          */
28574         ret->schemas_sax.characters = charactersSplit;
28575         if ((old_sax->ignorableWhitespace != NULL) &&
28576             (old_sax->ignorableWhitespace != old_sax->characters))
28577             ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28578         else
28579             ret->schemas_sax.ignorableWhitespace = charactersSplit;
28580         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28581         ret->schemas_sax.reference = referenceSplit;
28582         ret->schemas_sax.startElementNs = startElementNsSplit;
28583         ret->schemas_sax.endElementNs = endElementNsSplit;
28584
28585         ret->user_data_ptr = user_data;
28586         ret->user_data = *user_data;
28587         *user_data = ret;
28588     }
28589
28590     /*
28591      * plug the pointers back.
28592      */
28593     *sax = &(ret->schemas_sax);
28594     ctxt->sax = *sax;
28595     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28596     xmlSchemaPreRun(ctxt);
28597     return(ret);
28598 }
28599
28600 /**
28601  * xmlSchemaSAXUnplug:
28602  * @plug:  a data structure returned by xmlSchemaSAXPlug
28603  *
28604  * Unplug a SAX based validation layer in a SAX parsing event flow.
28605  * The original pointers used in the call are restored.
28606  *
28607  * Returns 0 in case of success and -1 in case of failure.
28608  */
28609 int
28610 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28611 {
28612     xmlSAXHandlerPtr *sax;
28613     void **user_data;
28614
28615     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28616         return(-1);
28617     plug->magic = 0;
28618
28619     xmlSchemaPostRun(plug->ctxt);
28620     /* restore the data */
28621     sax = plug->user_sax_ptr;
28622     *sax = plug->user_sax;
28623     if (plug->user_sax != NULL) {
28624         user_data = plug->user_data_ptr;
28625         *user_data = plug->user_data;
28626     }
28627
28628     /* free and return */
28629     xmlFree(plug);
28630     return(0);
28631 }
28632
28633 /**
28634  * xmlSchemaValidateStream:
28635  * @ctxt:  a schema validation context
28636  * @input:  the input to use for reading the data
28637  * @enc:  an optional encoding information
28638  * @sax:  a SAX handler for the resulting events
28639  * @user_data:  the context to provide to the SAX handler.
28640  *
28641  * Validate an input based on a flow of SAX event from the parser
28642  * and forward the events to the @sax handler with the provided @user_data
28643  * the user provided @sax handler must be a SAX2 one.
28644  *
28645  * Returns 0 if the document is schemas valid, a positive error code
28646  *     number otherwise and -1 in case of internal or API error.
28647  */
28648 int
28649 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28650                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28651                         xmlSAXHandlerPtr sax, void *user_data)
28652 {
28653     xmlSchemaSAXPlugPtr plug = NULL;
28654     xmlSAXHandlerPtr old_sax = NULL;
28655     xmlParserCtxtPtr pctxt = NULL;
28656     xmlParserInputPtr inputStream = NULL;
28657     int ret;
28658
28659     if ((ctxt == NULL) || (input == NULL))
28660         return (-1);
28661
28662     /*
28663      * prepare the parser
28664      */
28665     pctxt = xmlNewParserCtxt();
28666     if (pctxt == NULL)
28667         return (-1);
28668     old_sax = pctxt->sax;
28669     pctxt->sax = sax;
28670     pctxt->userData = user_data;
28671 #if 0
28672     if (options)
28673         xmlCtxtUseOptions(pctxt, options);
28674 #endif
28675     pctxt->linenumbers = 1;
28676
28677     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28678     if (inputStream == NULL) {
28679         ret = -1;
28680         goto done;
28681     }
28682     inputPush(pctxt, inputStream);
28683     ctxt->parserCtxt = pctxt;
28684     ctxt->input = input;
28685
28686     /*
28687      * Plug the validation and launch the parsing
28688      */
28689     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28690     if (plug == NULL) {
28691         ret = -1;
28692         goto done;
28693     }
28694     ctxt->input = input;
28695     ctxt->enc = enc;
28696     ctxt->sax = pctxt->sax;
28697     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28698     ret = xmlSchemaVStart(ctxt);
28699
28700     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28701         ret = ctxt->parserCtxt->errNo;
28702         if (ret == 0)
28703             ret = 1;
28704     }
28705
28706 done:
28707     ctxt->parserCtxt = NULL;
28708     ctxt->sax = NULL;
28709     ctxt->input = NULL;
28710     if (plug != NULL) {
28711         xmlSchemaSAXUnplug(plug);
28712     }
28713     /* cleanup */
28714     if (pctxt != NULL) {
28715         pctxt->sax = old_sax;
28716         xmlFreeParserCtxt(pctxt);
28717     }
28718     return (ret);
28719 }
28720
28721 /**
28722  * xmlSchemaValidateFile:
28723  * @ctxt: a schema validation context
28724  * @filename: the URI of the instance
28725  * @options: a future set of options, currently unused
28726  *
28727  * Do a schemas validation of the given resource, it will use the
28728  * SAX streamable validation internally.
28729  *
28730  * Returns 0 if the document is valid, a positive error code
28731  *     number otherwise and -1 in case of an internal or API error.
28732  */
28733 int
28734 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28735                       const char * filename,
28736                       int options ATTRIBUTE_UNUSED)
28737 {
28738     int ret;
28739     xmlParserInputBufferPtr input;
28740
28741     if ((ctxt == NULL) || (filename == NULL))
28742         return (-1);
28743
28744     input = xmlParserInputBufferCreateFilename(filename,
28745         XML_CHAR_ENCODING_NONE);
28746     if (input == NULL)
28747         return (-1);
28748     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28749         NULL, NULL);
28750     return (ret);
28751 }
28752
28753 /**
28754  * xmlSchemaValidCtxtGetParserCtxt:
28755  * @ctxt: a schema validation context
28756  *
28757  * allow access to the parser context of the schema validation context
28758  *
28759  * Returns the parser context of the schema validation context or NULL
28760  *         in case of error.
28761  */
28762 xmlParserCtxtPtr
28763 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28764 {
28765     if (ctxt == NULL)
28766         return(NULL);
28767     return (ctxt->parserCtxt);
28768 }
28769
28770 #define bottom_xmlschemas
28771 #include "elfgcchack.h"
28772 #endif /* LIBXML_SCHEMAS_ENABLED */