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 */
120static const xmlChar *xmlSchemaNs = (const xmlChar *)
121    "http://www.w3.org/2001/XMLSchema";
122
123static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124    "http://www.w3.org/2001/XMLSchema-instance";
125
126static 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
348typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
350
351typedef struct _xmlSchemaItemList xmlSchemaItemList;
352typedef xmlSchemaItemList *xmlSchemaItemListPtr;
353struct _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
362typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364struct _xmlSchemaAbstractCtxt {
365    int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
366};
367
368typedef struct _xmlSchemaBucket xmlSchemaBucket;
369typedef 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 */
381typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383struct _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
393struct _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 */
417typedef struct _xmlSchemaImport xmlSchemaImport;
418typedef xmlSchemaImport *xmlSchemaImportPtr;
419struct _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*/
446typedef struct _xmlSchemaInclude xmlSchemaInclude;
447typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448struct _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 */
472typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474struct _xmlSchemaBasicItem {
475    xmlSchemaTypeType type;
476};
477
478/**
479 * xmlSchemaAnnotItem:
480 *
481 * The abstract base type for annotated schema components.
482 * (Extends xmlSchemaBasicItem)
483 */
484typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486struct _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 */
497typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499struct _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 */
514typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516struct _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 */
539typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541struct _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 */
552typedef struct _xmlSchemaRedef xmlSchemaRedef;
553typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554struct _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 */
568typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570struct _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
587struct _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 */
642typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644struct _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 */
659typedef struct _xmlSchemaParticle xmlSchemaParticle;
660typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661struct _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 */
679typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681struct _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 */
697typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699struct _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
710typedef struct _xmlSchemaIDC xmlSchemaIDC;
711typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712
713/**
714 * xmlSchemaIDCSelect:
715 *
716 * The identity-constraint "field" and "selector" item, holding the
717 * XPath expression.
718 */
719typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721struct _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
736struct _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 */
754typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756struct _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 */
768typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770struct _xmlSchemaPSVIIDCKey {
771    xmlSchemaTypePtr type;
772    xmlSchemaValPtr val;
773};
774
775/**
776 * xmlSchemaPSVIIDCNode:
777 *
778 * The node table item of a node table.
779 */
780typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782struct _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 */
795typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797struct _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
813typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815
816/**
817 * xmlSchemaIDCStateObj:
818 *
819 * The state object used to evaluate XPath expressions.
820 */
821typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823struct _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 */
843struct _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 */
879struct _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
936typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938struct _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 */
964struct _xmlSchemaValidCtxt {
965    int type;
966    void *errCtxt;             /* user specific data block */
967    xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
968    xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
969    xmlStructuredErrorFunc serror;
970
971    xmlSchemaPtr schema;        /* The schema in use */
972    xmlDocPtr doc;
973    xmlParserInputBufferPtr input;
974    xmlCharEncoding enc;
975    xmlSAXHandlerPtr sax;
976    xmlParserCtxtPtr parserCtxt;
977    void *user_data; /* TODO: What is this for? */
978    char *filename;
979
980    int err;
981    int nberrors;
982
983    xmlNodePtr node;
984    xmlNodePtr cur;
985    /* xmlSchemaTypePtr type; */
986
987    xmlRegExecCtxtPtr regexp;
988    xmlSchemaValPtr value;
989
990    int valueWS;
991    int options;
992    xmlNodePtr validationRoot;
993    xmlSchemaParserCtxtPtr pctxt;
994    int xsiAssemble;
995
996    int depth;
997    xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
998    int sizeElemInfos;
999    xmlSchemaNodeInfoPtr inode; /* the current element information */
1000
1001    xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1002
1003    xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1004    xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1005    xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1006
1007    xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1008    int nbIdcNodes;
1009    int sizeIdcNodes;
1010
1011    xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1012    int nbIdcKeys;
1013    int sizeIdcKeys;
1014
1015    int flags;
1016
1017    xmlDictPtr dict;
1018
1019#ifdef LIBXML_READER_ENABLED
1020    xmlTextReaderPtr reader;
1021#endif
1022
1023    xmlSchemaAttrInfoPtr *attrInfos;
1024    int nbAttrInfos;
1025    int sizeAttrInfos;
1026
1027    int skipDepth;
1028    xmlSchemaItemListPtr nodeQNames;
1029    int hasKeyrefs;
1030    int createIDCNodeTables;
1031    int psviExposeIDCNodeTables;
1032
1033    /* Locator for error reporting in streaming mode */
1034    xmlSchemaValidityLocatorFunc locFunc;
1035    void *locCtxt;
1036};
1037
1038/**
1039 * xmlSchemaSubstGroup:
1040 *
1041 *
1042 */
1043typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1044typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1045struct _xmlSchemaSubstGroup {
1046    xmlSchemaElementPtr head;
1047    xmlSchemaItemListPtr members;
1048};
1049
1050/************************************************************************
1051 *									*
1052 *			Some predeclarations				*
1053 *									*
1054 ************************************************************************/
1055
1056static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1057                                 xmlSchemaPtr schema,
1058                                 xmlNodePtr node);
1059static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1060                                 xmlSchemaPtr schema,
1061                                 xmlNodePtr node);
1062static int
1063xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1064                   xmlSchemaAbstractCtxtPtr ctxt);
1065static const xmlChar *
1066xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1067static int
1068xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1069                     xmlNodePtr node);
1070static int
1071xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1072                       xmlSchemaParserCtxtPtr ctxt);
1073static void
1074xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1075static xmlSchemaWhitespaceValueType
1076xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1077static xmlSchemaTreeItemPtr
1078xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1079			 xmlNodePtr node, xmlSchemaTypeType type,
1080			 int withParticle);
1081static const xmlChar *
1082xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1083static xmlSchemaTypeLinkPtr
1084xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1085static void
1086xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1087		     const char *funcName,
1088		     const char *message);
1089static int
1090xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1091			     xmlSchemaTypePtr type,
1092			     xmlSchemaTypePtr baseType,
1093			     int subset);
1094static void
1095xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1096				   xmlSchemaParserCtxtPtr ctxt);
1097static void
1098xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1099static xmlSchemaQNameRefPtr
1100xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1101				xmlSchemaPtr schema,
1102				xmlNodePtr node);
1103
1104/************************************************************************
1105 *									*
1106 *			Helper functions			        *
1107 *									*
1108 ************************************************************************/
1109
1110/**
1111 * xmlSchemaItemTypeToStr:
1112 * @type: the type of the schema item
1113 *
1114 * Returns the component name of a schema item.
1115 */
1116static const xmlChar *
1117xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1118{
1119    switch (type) {
1120	case XML_SCHEMA_TYPE_BASIC:
1121	    return(BAD_CAST "simple type definition");
1122	case XML_SCHEMA_TYPE_SIMPLE:
1123	    return(BAD_CAST "simple type definition");
1124	case XML_SCHEMA_TYPE_COMPLEX:
1125	    return(BAD_CAST "complex type definition");
1126	case XML_SCHEMA_TYPE_ELEMENT:
1127	    return(BAD_CAST "element declaration");
1128	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1129	    return(BAD_CAST "attribute use");
1130	case XML_SCHEMA_TYPE_ATTRIBUTE:
1131	    return(BAD_CAST "attribute declaration");
1132	case XML_SCHEMA_TYPE_GROUP:
1133	    return(BAD_CAST "model group definition");
1134	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1135	    return(BAD_CAST "attribute group definition");
1136	case XML_SCHEMA_TYPE_NOTATION:
1137	    return(BAD_CAST "notation declaration");
1138	case XML_SCHEMA_TYPE_SEQUENCE:
1139	    return(BAD_CAST "model group (sequence)");
1140	case XML_SCHEMA_TYPE_CHOICE:
1141	    return(BAD_CAST "model group (choice)");
1142	case XML_SCHEMA_TYPE_ALL:
1143	    return(BAD_CAST "model group (all)");
1144	case XML_SCHEMA_TYPE_PARTICLE:
1145	    return(BAD_CAST "particle");
1146	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1147	    return(BAD_CAST "unique identity-constraint");
1148	    /* return(BAD_CAST "IDC (unique)"); */
1149	case XML_SCHEMA_TYPE_IDC_KEY:
1150	    return(BAD_CAST "key identity-constraint");
1151	    /* return(BAD_CAST "IDC (key)"); */
1152	case XML_SCHEMA_TYPE_IDC_KEYREF:
1153	    return(BAD_CAST "keyref identity-constraint");
1154	    /* return(BAD_CAST "IDC (keyref)"); */
1155	case XML_SCHEMA_TYPE_ANY:
1156	    return(BAD_CAST "wildcard (any)");
1157	case XML_SCHEMA_EXTRA_QNAMEREF:
1158	    return(BAD_CAST "[helper component] QName reference");
1159	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1160	    return(BAD_CAST "[helper component] attribute use prohibition");
1161	default:
1162	    return(BAD_CAST "Not a schema component");
1163    }
1164}
1165
1166/**
1167 * xmlSchemaGetComponentTypeStr:
1168 * @type: the type of the schema item
1169 *
1170 * Returns the component name of a schema item.
1171 */
1172static const xmlChar *
1173xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1174{
1175    switch (item->type) {
1176	case XML_SCHEMA_TYPE_BASIC:
1177	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1178		return(BAD_CAST "complex type definition");
1179	    else
1180		return(BAD_CAST "simple type definition");
1181	default:
1182	    return(xmlSchemaItemTypeToStr(item->type));
1183    }
1184}
1185
1186/**
1187 * xmlSchemaGetComponentNode:
1188 * @item: a schema component
1189 *
1190 * Returns node associated with the schema component.
1191 * NOTE that such a node need not be available; plus, a component's
1192 * node need not to reflect the component directly, since there is no
1193 * one-to-one relationship between the XML Schema representation and
1194 * the component representation.
1195 */
1196static xmlNodePtr
1197xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1198{
1199    switch (item->type) {
1200	case XML_SCHEMA_TYPE_ELEMENT:
1201	    return (((xmlSchemaElementPtr) item)->node);
1202	case XML_SCHEMA_TYPE_ATTRIBUTE:
1203	    return (((xmlSchemaAttributePtr) item)->node);
1204	case XML_SCHEMA_TYPE_COMPLEX:
1205	case XML_SCHEMA_TYPE_SIMPLE:
1206	    return (((xmlSchemaTypePtr) item)->node);
1207	case XML_SCHEMA_TYPE_ANY:
1208	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1209	    return (((xmlSchemaWildcardPtr) item)->node);
1210	case XML_SCHEMA_TYPE_PARTICLE:
1211	    return (((xmlSchemaParticlePtr) item)->node);
1212	case XML_SCHEMA_TYPE_SEQUENCE:
1213	case XML_SCHEMA_TYPE_CHOICE:
1214	case XML_SCHEMA_TYPE_ALL:
1215	    return (((xmlSchemaModelGroupPtr) item)->node);
1216	case XML_SCHEMA_TYPE_GROUP:
1217	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1218	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1219	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1220	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1221	case XML_SCHEMA_TYPE_IDC_KEY:
1222	case XML_SCHEMA_TYPE_IDC_KEYREF:
1223	    return (((xmlSchemaIDCPtr) item)->node);
1224	case XML_SCHEMA_EXTRA_QNAMEREF:
1225	    return(((xmlSchemaQNameRefPtr) item)->node);
1226	/* TODO: What to do with NOTATIONs?
1227	case XML_SCHEMA_TYPE_NOTATION:
1228	    return (((xmlSchemaNotationPtr) item)->node);
1229	*/
1230	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1231	    return (((xmlSchemaAttributeUsePtr) item)->node);
1232	default:
1233	    return (NULL);
1234    }
1235}
1236
1237#if 0
1238/**
1239 * xmlSchemaGetNextComponent:
1240 * @item: a schema component
1241 *
1242 * Returns the next sibling of the schema component.
1243 */
1244static xmlSchemaBasicItemPtr
1245xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1246{
1247    switch (item->type) {
1248	case XML_SCHEMA_TYPE_ELEMENT:
1249	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1250	case XML_SCHEMA_TYPE_ATTRIBUTE:
1251	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1252	case XML_SCHEMA_TYPE_COMPLEX:
1253	case XML_SCHEMA_TYPE_SIMPLE:
1254	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1255	case XML_SCHEMA_TYPE_ANY:
1256	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1257	    return (NULL);
1258	case XML_SCHEMA_TYPE_PARTICLE:
1259	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1260	case XML_SCHEMA_TYPE_SEQUENCE:
1261	case XML_SCHEMA_TYPE_CHOICE:
1262	case XML_SCHEMA_TYPE_ALL:
1263	    return (NULL);
1264	case XML_SCHEMA_TYPE_GROUP:
1265	    return (NULL);
1266	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1267	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1268	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1269	case XML_SCHEMA_TYPE_IDC_KEY:
1270	case XML_SCHEMA_TYPE_IDC_KEYREF:
1271	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1272	default:
1273	    return (NULL);
1274    }
1275}
1276#endif
1277
1278
1279/**
1280 * xmlSchemaFormatQName:
1281 * @buf: the string buffer
1282 * @namespaceName:  the namespace name
1283 * @localName: the local name
1284 *
1285 * Returns the given QName in the format "{namespaceName}localName" or
1286 * just "localName" if @namespaceName is NULL.
1287 *
1288 * Returns the localName if @namespaceName is NULL, a formatted
1289 * string otherwise.
1290 */
1291static const xmlChar*
1292xmlSchemaFormatQName(xmlChar **buf,
1293		     const xmlChar *namespaceName,
1294		     const xmlChar *localName)
1295{
1296    FREE_AND_NULL(*buf)
1297    if (namespaceName != NULL) {
1298	*buf = xmlStrdup(BAD_CAST "{");
1299	*buf = xmlStrcat(*buf, namespaceName);
1300	*buf = xmlStrcat(*buf, BAD_CAST "}");
1301    }
1302    if (localName != NULL) {
1303	if (namespaceName == NULL)
1304	    return(localName);
1305	*buf = xmlStrcat(*buf, localName);
1306    } else {
1307	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1308    }
1309    return ((const xmlChar *) *buf);
1310}
1311
1312static const xmlChar*
1313xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1314{
1315    if (ns != NULL)
1316	return (xmlSchemaFormatQName(buf, ns->href, localName));
1317    else
1318	return (xmlSchemaFormatQName(buf, NULL, localName));
1319}
1320
1321static const xmlChar *
1322xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1323{
1324    switch (item->type) {
1325	case XML_SCHEMA_TYPE_ELEMENT:
1326	    return (((xmlSchemaElementPtr) item)->name);
1327	case XML_SCHEMA_TYPE_ATTRIBUTE:
1328	    return (((xmlSchemaAttributePtr) item)->name);
1329	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1330	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1331	case XML_SCHEMA_TYPE_BASIC:
1332	case XML_SCHEMA_TYPE_SIMPLE:
1333	case XML_SCHEMA_TYPE_COMPLEX:
1334	    return (((xmlSchemaTypePtr) item)->name);
1335	case XML_SCHEMA_TYPE_GROUP:
1336	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1337	case XML_SCHEMA_TYPE_IDC_KEY:
1338	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1339	case XML_SCHEMA_TYPE_IDC_KEYREF:
1340	    return (((xmlSchemaIDCPtr) item)->name);
1341	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1342	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1343		return(xmlSchemaGetComponentName(
1344		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1345	    } else
1346		return(NULL);
1347	case XML_SCHEMA_EXTRA_QNAMEREF:
1348	    return (((xmlSchemaQNameRefPtr) item)->name);
1349	case XML_SCHEMA_TYPE_NOTATION:
1350	    return (((xmlSchemaNotationPtr) item)->name);
1351	default:
1352	    /*
1353	    * Other components cannot have names.
1354	    */
1355	    break;
1356    }
1357    return (NULL);
1358}
1359
1360#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1361#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1362/*
1363static const xmlChar *
1364xmlSchemaGetQNameRefName(void *ref)
1365{
1366    return(((xmlSchemaQNameRefPtr) ref)->name);
1367}
1368
1369static const xmlChar *
1370xmlSchemaGetQNameRefTargetNs(void *ref)
1371{
1372    return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1373}
1374*/
1375
1376static const xmlChar *
1377xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1378{
1379    switch (item->type) {
1380	case XML_SCHEMA_TYPE_ELEMENT:
1381	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1382	case XML_SCHEMA_TYPE_ATTRIBUTE:
1383	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1384	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1385	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1386	case XML_SCHEMA_TYPE_BASIC:
1387	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1388	case XML_SCHEMA_TYPE_SIMPLE:
1389	case XML_SCHEMA_TYPE_COMPLEX:
1390	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1391	case XML_SCHEMA_TYPE_GROUP:
1392	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1393	case XML_SCHEMA_TYPE_IDC_KEY:
1394	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1395	case XML_SCHEMA_TYPE_IDC_KEYREF:
1396	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1397	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1398	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1399		return(xmlSchemaGetComponentTargetNs(
1400		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1401	    }
1402	    /* TODO: Will returning NULL break something? */
1403	    break;
1404	case XML_SCHEMA_EXTRA_QNAMEREF:
1405	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1406	case XML_SCHEMA_TYPE_NOTATION:
1407	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1408	default:
1409	    /*
1410	    * Other components cannot have names.
1411	    */
1412	    break;
1413    }
1414    return (NULL);
1415}
1416
1417static const xmlChar*
1418xmlSchemaGetComponentQName(xmlChar **buf,
1419			   void *item)
1420{
1421    return (xmlSchemaFormatQName(buf,
1422	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1423	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1424}
1425
1426static const xmlChar*
1427xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1428{
1429    xmlChar *str = NULL;
1430
1431    *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1432    *buf = xmlStrcat(*buf, BAD_CAST " '");
1433    *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1434	(xmlSchemaBasicItemPtr) item));
1435    *buf = xmlStrcat(*buf, BAD_CAST "'");
1436    FREE_AND_NULL(str);
1437    return(*buf);
1438}
1439
1440static const xmlChar*
1441xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1442{
1443    return(xmlSchemaGetComponentDesignation(buf, idc));
1444}
1445
1446/**
1447 * xmlSchemaWildcardPCToString:
1448 * @pc: the type of processContents
1449 *
1450 * Returns a string representation of the type of
1451 * processContents.
1452 */
1453static const xmlChar *
1454xmlSchemaWildcardPCToString(int pc)
1455{
1456    switch (pc) {
1457	case XML_SCHEMAS_ANY_SKIP:
1458	    return (BAD_CAST "skip");
1459	case XML_SCHEMAS_ANY_LAX:
1460	    return (BAD_CAST "lax");
1461	case XML_SCHEMAS_ANY_STRICT:
1462	    return (BAD_CAST "strict");
1463	default:
1464	    return (BAD_CAST "invalid process contents");
1465    }
1466}
1467
1468/**
1469 * xmlSchemaGetCanonValueWhtspExt:
1470 * @val: the precomputed value
1471 * @retValue: the returned value
1472 * @ws: the whitespace type of the value
1473 *
1474 * Get a the canonical representation of the value.
1475 * The caller has to free the returned retValue.
1476 *
1477 * Returns 0 if the value could be built and -1 in case of
1478 *         API errors or if the value type is not supported yet.
1479 */
1480static int
1481xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1482			       xmlSchemaWhitespaceValueType ws,
1483			       xmlChar **retValue)
1484{
1485    int list;
1486    xmlSchemaValType valType;
1487    const xmlChar *value, *value2 = NULL;
1488
1489
1490    if ((retValue == NULL) || (val == NULL))
1491	return (-1);
1492    list = xmlSchemaValueGetNext(val) ? 1 : 0;
1493    *retValue = NULL;
1494    do {
1495	value = NULL;
1496	valType = xmlSchemaGetValType(val);
1497	switch (valType) {
1498	    case XML_SCHEMAS_STRING:
1499	    case XML_SCHEMAS_NORMSTRING:
1500	    case XML_SCHEMAS_ANYSIMPLETYPE:
1501		value = xmlSchemaValueGetAsString(val);
1502		if (value != NULL) {
1503		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1504			value2 = xmlSchemaCollapseString(value);
1505		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1506			value2 = xmlSchemaWhiteSpaceReplace(value);
1507		    if (value2 != NULL)
1508			value = value2;
1509		}
1510		break;
1511	    default:
1512		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1513		    if (value2 != NULL)
1514			xmlFree((xmlChar *) value2);
1515		    goto internal_error;
1516		}
1517		value = value2;
1518	}
1519	if (*retValue == NULL)
1520	    if (value == NULL) {
1521		if (! list)
1522		    *retValue = xmlStrdup(BAD_CAST "");
1523	    } else
1524		*retValue = xmlStrdup(value);
1525	else if (value != NULL) {
1526	    /* List. */
1527	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1528	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1529	}
1530	FREE_AND_NULL(value2)
1531	val = xmlSchemaValueGetNext(val);
1532    } while (val != NULL);
1533
1534    return (0);
1535internal_error:
1536    if (*retValue != NULL)
1537	xmlFree((xmlChar *) (*retValue));
1538    if (value2 != NULL)
1539	xmlFree((xmlChar *) value2);
1540    return (-1);
1541}
1542
1543/**
1544 * xmlSchemaFormatItemForReport:
1545 * @buf: the string buffer
1546 * @itemDes: the designation of the item
1547 * @itemName: the name of the item
1548 * @item: the item as an object
1549 * @itemNode: the node of the item
1550 * @local: the local name
1551 * @parsing: if the function is used during the parse
1552 *
1553 * Returns a representation of the given item used
1554 * for error reports.
1555 *
1556 * The following order is used to build the resulting
1557 * designation if the arguments are not NULL:
1558 * 1a. If itemDes not NULL -> itemDes
1559 * 1b. If (itemDes not NULL) and (itemName not NULL)
1560 *     -> itemDes + itemName
1561 * 2. If the preceding was NULL and (item not NULL) -> item
1562 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1563 *
1564 * If the itemNode is an attribute node, the name of the attribute
1565 * will be appended to the result.
1566 *
1567 * Returns the formatted string and sets @buf to the resulting value.
1568 */
1569static xmlChar*
1570xmlSchemaFormatItemForReport(xmlChar **buf,
1571		     const xmlChar *itemDes,
1572		     xmlSchemaBasicItemPtr item,
1573		     xmlNodePtr itemNode)
1574{
1575    xmlChar *str = NULL;
1576    int named = 1;
1577
1578    if (*buf != NULL) {
1579	xmlFree(*buf);
1580	*buf = NULL;
1581    }
1582
1583    if (itemDes != NULL) {
1584	*buf = xmlStrdup(itemDes);
1585    } else if (item != NULL) {
1586	switch (item->type) {
1587	case XML_SCHEMA_TYPE_BASIC: {
1588	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1589
1590	    if (WXS_IS_ATOMIC(type))
1591		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1592	    else if (WXS_IS_LIST(type))
1593		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1594	    else if (WXS_IS_UNION(type))
1595		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1596	    else
1597		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1598	    *buf = xmlStrcat(*buf, type->name);
1599	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1600	    }
1601	    break;
1602	case XML_SCHEMA_TYPE_SIMPLE: {
1603	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1604
1605	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1606		*buf = xmlStrdup(BAD_CAST"");
1607	    } else {
1608		*buf = xmlStrdup(BAD_CAST "local ");
1609	    }
1610	    if (WXS_IS_ATOMIC(type))
1611		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1612	    else if (WXS_IS_LIST(type))
1613		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1614	    else if (WXS_IS_UNION(type))
1615		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1616	    else
1617		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1618	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1619		*buf = xmlStrcat(*buf, BAD_CAST " '");
1620		*buf = xmlStrcat(*buf, type->name);
1621		*buf = xmlStrcat(*buf, BAD_CAST "'");
1622	    }
1623	    }
1624	    break;
1625	case XML_SCHEMA_TYPE_COMPLEX: {
1626	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1627
1628	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1629		*buf = xmlStrdup(BAD_CAST "");
1630	    else
1631		*buf = xmlStrdup(BAD_CAST "local ");
1632	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1633	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1634		*buf = xmlStrcat(*buf, BAD_CAST " '");
1635		*buf = xmlStrcat(*buf, type->name);
1636		*buf = xmlStrcat(*buf, BAD_CAST "'");
1637	    }
1638	    }
1639	    break;
1640	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1641		xmlSchemaAttributeUsePtr ause;
1642
1643		ause = WXS_ATTR_USE_CAST item;
1644		*buf = xmlStrdup(BAD_CAST "attribute use ");
1645		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1646		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1647		    *buf = xmlStrcat(*buf,
1648			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1649		    FREE_AND_NULL(str)
1650			*buf = xmlStrcat(*buf, BAD_CAST "'");
1651		} else {
1652		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1653		}
1654	    }
1655	    break;
1656	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1657		xmlSchemaAttributePtr attr;
1658
1659		attr = (xmlSchemaAttributePtr) item;
1660		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1661		*buf = xmlStrcat(*buf, BAD_CAST " '");
1662		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1663		    attr->targetNamespace, attr->name));
1664		FREE_AND_NULL(str)
1665		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1666	    }
1667	    break;
1668	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1669	    xmlSchemaGetComponentDesignation(buf, item);
1670	    break;
1671	case XML_SCHEMA_TYPE_ELEMENT: {
1672		xmlSchemaElementPtr elem;
1673
1674		elem = (xmlSchemaElementPtr) item;
1675		*buf = xmlStrdup(BAD_CAST "element decl.");
1676		*buf = xmlStrcat(*buf, BAD_CAST " '");
1677		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1678		    elem->targetNamespace, elem->name));
1679		*buf = xmlStrcat(*buf, BAD_CAST "'");
1680	    }
1681	    break;
1682	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1683	case XML_SCHEMA_TYPE_IDC_KEY:
1684	case XML_SCHEMA_TYPE_IDC_KEYREF:
1685	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1686		*buf = xmlStrdup(BAD_CAST "unique '");
1687	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1688		*buf = xmlStrdup(BAD_CAST "key '");
1689	    else
1690		*buf = xmlStrdup(BAD_CAST "keyRef '");
1691	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1692	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1693	    break;
1694	case XML_SCHEMA_TYPE_ANY:
1695	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1696	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1697		    ((xmlSchemaWildcardPtr) item)->processContents));
1698	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1699	    break;
1700	case XML_SCHEMA_FACET_MININCLUSIVE:
1701	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1702	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1703	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1704	case XML_SCHEMA_FACET_TOTALDIGITS:
1705	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1706	case XML_SCHEMA_FACET_PATTERN:
1707	case XML_SCHEMA_FACET_ENUMERATION:
1708	case XML_SCHEMA_FACET_WHITESPACE:
1709	case XML_SCHEMA_FACET_LENGTH:
1710	case XML_SCHEMA_FACET_MAXLENGTH:
1711	case XML_SCHEMA_FACET_MINLENGTH:
1712	    *buf = xmlStrdup(BAD_CAST "facet '");
1713	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1714	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1715	    break;
1716	case XML_SCHEMA_TYPE_GROUP: {
1717		*buf = xmlStrdup(BAD_CAST "model group def.");
1718		*buf = xmlStrcat(*buf, BAD_CAST " '");
1719		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1720		*buf = xmlStrcat(*buf, BAD_CAST "'");
1721		FREE_AND_NULL(str)
1722	    }
1723	    break;
1724	case XML_SCHEMA_TYPE_SEQUENCE:
1725	case XML_SCHEMA_TYPE_CHOICE:
1726	case XML_SCHEMA_TYPE_ALL:
1727	case XML_SCHEMA_TYPE_PARTICLE:
1728	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1729	    break;
1730	case XML_SCHEMA_TYPE_NOTATION: {
1731		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1732		*buf = xmlStrcat(*buf, BAD_CAST " '");
1733		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1734		*buf = xmlStrcat(*buf, BAD_CAST "'");
1735		FREE_AND_NULL(str);
1736	    }
1737	default:
1738	    named = 0;
1739	}
1740    } else
1741	named = 0;
1742
1743    if ((named == 0) && (itemNode != NULL)) {
1744	xmlNodePtr elem;
1745
1746	if (itemNode->type == XML_ATTRIBUTE_NODE)
1747	    elem = itemNode->parent;
1748	else
1749	    elem = itemNode;
1750	*buf = xmlStrdup(BAD_CAST "Element '");
1751	if (elem->ns != NULL) {
1752	    *buf = xmlStrcat(*buf,
1753		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1754	    FREE_AND_NULL(str)
1755	} else
1756	    *buf = xmlStrcat(*buf, elem->name);
1757	*buf = xmlStrcat(*buf, BAD_CAST "'");
1758
1759    }
1760    if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1761	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1762	if (itemNode->ns != NULL) {
1763	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1764		itemNode->ns->href, itemNode->name));
1765	    FREE_AND_NULL(str)
1766	} else
1767	    *buf = xmlStrcat(*buf, itemNode->name);
1768	*buf = xmlStrcat(*buf, BAD_CAST "'");
1769    }
1770    FREE_AND_NULL(str)
1771
1772    return (*buf);
1773}
1774
1775/**
1776 * xmlSchemaFormatFacetEnumSet:
1777 * @buf: the string buffer
1778 * @type: the type holding the enumeration facets
1779 *
1780 * Builds a string consisting of all enumeration elements.
1781 *
1782 * Returns a string of all enumeration elements.
1783 */
1784static const xmlChar *
1785xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1786			    xmlChar **buf, xmlSchemaTypePtr type)
1787{
1788    xmlSchemaFacetPtr facet;
1789    xmlSchemaWhitespaceValueType ws;
1790    xmlChar *value = NULL;
1791    int res, found = 0;
1792
1793    if (*buf != NULL)
1794	xmlFree(*buf);
1795    *buf = NULL;
1796
1797    do {
1798	/*
1799	* Use the whitespace type of the base type.
1800	*/
1801	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1802	for (facet = type->facets; facet != NULL; facet = facet->next) {
1803	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1804		continue;
1805	    found = 1;
1806	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1807		ws, &value);
1808	    if (res == -1) {
1809		xmlSchemaInternalErr(actxt,
1810		    "xmlSchemaFormatFacetEnumSet",
1811		    "compute the canonical lexical representation");
1812		if (*buf != NULL)
1813		    xmlFree(*buf);
1814		*buf = NULL;
1815		return (NULL);
1816	    }
1817	    if (*buf == NULL)
1818		*buf = xmlStrdup(BAD_CAST "'");
1819	    else
1820		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1821	    *buf = xmlStrcat(*buf, BAD_CAST value);
1822	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1823	    if (value != NULL) {
1824		xmlFree((xmlChar *)value);
1825		value = NULL;
1826	    }
1827	}
1828	/*
1829	* The enumeration facet of a type restricts the enumeration
1830	* facet of the ancestor type; i.e., such restricted enumerations
1831	* do not belong to the set of the given type. Thus we break
1832	* on the first found enumeration.
1833	*/
1834	if (found)
1835	    break;
1836	type = type->baseType;
1837    } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1838
1839    return ((const xmlChar *) *buf);
1840}
1841
1842/************************************************************************
1843 *									*
1844 *			Error functions				        *
1845 *									*
1846 ************************************************************************/
1847
1848#if 0
1849static void
1850xmlSchemaErrMemory(const char *msg)
1851{
1852    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1853                     msg);
1854}
1855#endif
1856
1857static void
1858xmlSchemaPSimpleErr(const char *msg)
1859{
1860    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1861                     msg);
1862}
1863
1864/**
1865 * xmlSchemaPErrMemory:
1866 * @node: a context node
1867 * @extra:  extra informations
1868 *
1869 * Handle an out of memory condition
1870 */
1871static void
1872xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1873                    const char *extra, xmlNodePtr node)
1874{
1875    if (ctxt != NULL)
1876        ctxt->nberrors++;
1877    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1878                     extra);
1879}
1880
1881/**
1882 * xmlSchemaPErr:
1883 * @ctxt: the parsing context
1884 * @node: the context node
1885 * @error: the error code
1886 * @msg: the error message
1887 * @str1: extra data
1888 * @str2: extra data
1889 *
1890 * Handle a parser error
1891 */
1892static void
1893xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1894              const char *msg, const xmlChar * str1, const xmlChar * str2)
1895{
1896    xmlGenericErrorFunc channel = NULL;
1897    xmlStructuredErrorFunc schannel = NULL;
1898    void *data = NULL;
1899
1900    if (ctxt != NULL) {
1901        ctxt->nberrors++;
1902	ctxt->err = error;
1903        channel = ctxt->error;
1904        data = ctxt->errCtxt;
1905	schannel = ctxt->serror;
1906    }
1907    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1908                    error, XML_ERR_ERROR, NULL, 0,
1909                    (const char *) str1, (const char *) str2, NULL, 0, 0,
1910                    msg, str1, str2);
1911}
1912
1913/**
1914 * xmlSchemaPErr2:
1915 * @ctxt: the parsing context
1916 * @node: the context node
1917 * @node: the current child
1918 * @error: the error code
1919 * @msg: the error message
1920 * @str1: extra data
1921 * @str2: extra data
1922 *
1923 * Handle a parser error
1924 */
1925static void
1926xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1927               xmlNodePtr child, int error,
1928               const char *msg, const xmlChar * str1, const xmlChar * str2)
1929{
1930    if (child != NULL)
1931        xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1932    else
1933        xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1934}
1935
1936
1937/**
1938 * xmlSchemaPErrExt:
1939 * @ctxt: the parsing context
1940 * @node: the context node
1941 * @error: the error code
1942 * @strData1: extra data
1943 * @strData2: extra data
1944 * @strData3: extra data
1945 * @msg: the message
1946 * @str1:  extra parameter for the message display
1947 * @str2:  extra parameter for the message display
1948 * @str3:  extra parameter for the message display
1949 * @str4:  extra parameter for the message display
1950 * @str5:  extra parameter for the message display
1951 *
1952 * Handle a parser error
1953 */
1954static void
1955xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1956		const xmlChar * strData1, const xmlChar * strData2,
1957		const xmlChar * strData3, const char *msg, const xmlChar * str1,
1958		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1959		const xmlChar * str5)
1960{
1961
1962    xmlGenericErrorFunc channel = NULL;
1963    xmlStructuredErrorFunc schannel = NULL;
1964    void *data = NULL;
1965
1966    if (ctxt != NULL) {
1967        ctxt->nberrors++;
1968	ctxt->err = error;
1969        channel = ctxt->error;
1970        data = ctxt->errCtxt;
1971	schannel = ctxt->serror;
1972    }
1973    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1974                    error, XML_ERR_ERROR, NULL, 0,
1975                    (const char *) strData1, (const char *) strData2,
1976		    (const char *) strData3, 0, 0, msg, str1, str2,
1977		    str3, str4, str5);
1978}
1979
1980/************************************************************************
1981 *									*
1982 *			Allround error functions			*
1983 *									*
1984 ************************************************************************/
1985
1986/**
1987 * xmlSchemaVTypeErrMemory:
1988 * @node: a context node
1989 * @extra:  extra informations
1990 *
1991 * Handle an out of memory condition
1992 */
1993static void
1994xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1995                    const char *extra, xmlNodePtr node)
1996{
1997    if (ctxt != NULL) {
1998        ctxt->nberrors++;
1999        ctxt->err = XML_SCHEMAV_INTERNAL;
2000    }
2001    __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2002                     extra);
2003}
2004
2005static void
2006xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2007			    const char *msg, const xmlChar *str)
2008{
2009     __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2010	 msg, (const char *) str);
2011}
2012
2013#define WXS_ERROR_TYPE_ERROR 1
2014#define WXS_ERROR_TYPE_WARNING 2
2015/**
2016 * xmlSchemaErr3:
2017 * @ctxt: the validation context
2018 * @node: the context node
2019 * @error: the error code
2020 * @msg: the error message
2021 * @str1: extra data
2022 * @str2: extra data
2023 * @str3: extra data
2024 *
2025 * Handle a validation error
2026 */
2027static void
2028xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2029		  xmlErrorLevel errorLevel,
2030		  int error, xmlNodePtr node, int line, const char *msg,
2031		  const xmlChar *str1, const xmlChar *str2,
2032		  const xmlChar *str3, const xmlChar *str4)
2033{
2034    xmlStructuredErrorFunc schannel = NULL;
2035    xmlGenericErrorFunc channel = NULL;
2036    void *data = NULL;
2037
2038    if (ctxt != NULL) {
2039	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2040	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2041	    const char *file = NULL;
2042	    int col = 0;
2043	    if (errorLevel != XML_ERR_WARNING) {
2044		vctxt->nberrors++;
2045		vctxt->err = error;
2046		channel = vctxt->error;
2047	    } else {
2048		channel = vctxt->warning;
2049	    }
2050	    schannel = vctxt->serror;
2051	    data = vctxt->errCtxt;
2052
2053	    /*
2054	    * Error node. If we specify a line number, then
2055	    * do not channel any node to the error function.
2056	    */
2057	    if (line == 0) {
2058		if ((node == NULL) &&
2059		    (vctxt->depth >= 0) &&
2060		    (vctxt->inode != NULL)) {
2061		    node = vctxt->inode->node;
2062		}
2063		/*
2064		* Get filename and line if no node-tree.
2065		*/
2066		if ((node == NULL) &&
2067		    (vctxt->parserCtxt != NULL) &&
2068		    (vctxt->parserCtxt->input != NULL)) {
2069		    file = vctxt->parserCtxt->input->filename;
2070		    line = vctxt->parserCtxt->input->line;
2071		    col = vctxt->parserCtxt->input->col;
2072		}
2073	    } else {
2074		/*
2075		* Override the given node's (if any) position
2076		* and channel only the given line number.
2077		*/
2078		node = NULL;
2079		/*
2080		* Get filename.
2081		*/
2082		if (vctxt->doc != NULL)
2083		    file = (const char *) vctxt->doc->URL;
2084		else if ((vctxt->parserCtxt != NULL) &&
2085		    (vctxt->parserCtxt->input != NULL))
2086		    file = vctxt->parserCtxt->input->filename;
2087	    }
2088	    if (vctxt->locFunc != NULL) {
2089	        if ((file == NULL) || (line == 0)) {
2090		    unsigned long l;
2091		    const char *f;
2092		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2093		    if (file == NULL)
2094		        file = f;
2095		    if (line == 0)
2096		        line = (int) l;
2097		}
2098	    }
2099	    if ((file == NULL) && (vctxt->filename != NULL))
2100	        file = vctxt->filename;
2101
2102	    __xmlRaiseError(schannel, channel, data, ctxt,
2103		node, XML_FROM_SCHEMASV,
2104		error, errorLevel, file, line,
2105		(const char *) str1, (const char *) str2,
2106		(const char *) str3, 0, col, msg, str1, str2, str3, str4);
2107
2108	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2109	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2110	    if (errorLevel != XML_ERR_WARNING) {
2111		pctxt->nberrors++;
2112		pctxt->err = error;
2113		channel = pctxt->error;
2114	    } else {
2115		channel = pctxt->warning;
2116	    }
2117	    schannel = pctxt->serror;
2118	    data = pctxt->errCtxt;
2119	    __xmlRaiseError(schannel, channel, data, ctxt,
2120		node, XML_FROM_SCHEMASP, error,
2121		errorLevel, NULL, 0,
2122		(const char *) str1, (const char *) str2,
2123		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2124	} else {
2125	    TODO
2126	}
2127    }
2128}
2129
2130/**
2131 * xmlSchemaErr3:
2132 * @ctxt: the validation context
2133 * @node: the context node
2134 * @error: the error code
2135 * @msg: the error message
2136 * @str1: extra data
2137 * @str2: extra data
2138 * @str3: extra data
2139 *
2140 * Handle a validation error
2141 */
2142static void
2143xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2144	      int error, xmlNodePtr node, const char *msg,
2145	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2146{
2147    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2148	msg, str1, str2, str3, NULL);
2149}
2150
2151static void
2152xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2153	      int error, xmlNodePtr node, const char *msg,
2154	      const xmlChar *str1, const xmlChar *str2,
2155	      const xmlChar *str3, const xmlChar *str4)
2156{
2157    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2158	msg, str1, str2, str3, str4);
2159}
2160
2161static void
2162xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2163	     int error, xmlNodePtr node, const char *msg,
2164	     const xmlChar *str1, const xmlChar *str2)
2165{
2166    xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2167}
2168
2169static xmlChar *
2170xmlSchemaFormatNodeForError(xmlChar ** msg,
2171			    xmlSchemaAbstractCtxtPtr actxt,
2172			    xmlNodePtr node)
2173{
2174    xmlChar *str = NULL;
2175
2176    *msg = NULL;
2177    if ((node != NULL) &&
2178	(node->type != XML_ELEMENT_NODE) &&
2179	(node->type != XML_ATTRIBUTE_NODE))
2180    {
2181	/*
2182	* Don't try to format other nodes than element and
2183	* attribute nodes.
2184	* Play save and return an empty string.
2185	*/
2186	*msg = xmlStrdup(BAD_CAST "");
2187	return(*msg);
2188    }
2189    if (node != NULL) {
2190	/*
2191	* Work on tree nodes.
2192	*/
2193	if (node->type == XML_ATTRIBUTE_NODE) {
2194	    xmlNodePtr elem = node->parent;
2195
2196	    *msg = xmlStrdup(BAD_CAST "Element '");
2197	    if (elem->ns != NULL)
2198		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2199		    elem->ns->href, elem->name));
2200	    else
2201		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2202		    NULL, elem->name));
2203	    FREE_AND_NULL(str);
2204	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2205	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2206	} else {
2207	    *msg = xmlStrdup(BAD_CAST "Element '");
2208	}
2209	if (node->ns != NULL)
2210	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2211	    node->ns->href, node->name));
2212	else
2213	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2214	    NULL, node->name));
2215	FREE_AND_NULL(str);
2216	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2217    } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2218	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2219	/*
2220	* Work on node infos.
2221	*/
2222	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2223	    xmlSchemaNodeInfoPtr ielem =
2224		vctxt->elemInfos[vctxt->depth];
2225
2226	    *msg = xmlStrdup(BAD_CAST "Element '");
2227	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2228		ielem->nsName, ielem->localName));
2229	    FREE_AND_NULL(str);
2230	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2231	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2232	} else {
2233	    *msg = xmlStrdup(BAD_CAST "Element '");
2234	}
2235	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2236	    vctxt->inode->nsName, vctxt->inode->localName));
2237	FREE_AND_NULL(str);
2238	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2239    } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2240	/*
2241	* Hmm, no node while parsing?
2242	* Return an empty string, in case NULL will break something.
2243	*/
2244	*msg = xmlStrdup(BAD_CAST "");
2245    } else {
2246	TODO
2247	return (NULL);
2248    }
2249    /*
2250    * VAL TODO: The output of the given schema component is currently
2251    * disabled.
2252    */
2253#if 0
2254    if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2255	*msg = xmlStrcat(*msg, BAD_CAST " [");
2256	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2257	    NULL, type, NULL, 0));
2258	FREE_AND_NULL(str)
2259	*msg = xmlStrcat(*msg, BAD_CAST "]");
2260    }
2261#endif
2262    return (*msg);
2263}
2264
2265static void
2266xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2267		     const char *funcName,
2268		     const char *message,
2269		     const xmlChar *str1,
2270		     const xmlChar *str2)
2271{
2272    xmlChar *msg = NULL;
2273
2274    if (actxt == NULL)
2275        return;
2276    msg = xmlStrdup(BAD_CAST "Internal error: ");
2277    msg = xmlStrcat(msg, BAD_CAST funcName);
2278    msg = xmlStrcat(msg, BAD_CAST ", ");
2279    msg = xmlStrcat(msg, BAD_CAST message);
2280    msg = xmlStrcat(msg, BAD_CAST ".\n");
2281
2282    if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2283	xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2284	    (const char *) msg, str1, str2);
2285
2286    else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2287	xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2288	    (const char *) msg, str1, str2);
2289
2290    FREE_AND_NULL(msg)
2291}
2292
2293static void
2294xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2295		     const char *funcName,
2296		     const char *message)
2297{
2298    xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2299}
2300
2301#if 0
2302static void
2303xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2304		     const char *funcName,
2305		     const char *message,
2306		     const xmlChar *str1,
2307		     const xmlChar *str2)
2308{
2309    xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2310	str1, str2);
2311}
2312#endif
2313
2314static void
2315xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2316		   xmlParserErrors error,
2317		   xmlNodePtr node,
2318		   xmlSchemaBasicItemPtr item,
2319		   const char *message,
2320		   const xmlChar *str1, const xmlChar *str2,
2321		   const xmlChar *str3, const xmlChar *str4)
2322{
2323    xmlChar *msg = NULL;
2324
2325    if ((node == NULL) && (item != NULL) &&
2326	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2327	node = WXS_ITEM_NODE(item);
2328	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2329	msg = xmlStrcat(msg, BAD_CAST ": ");
2330    } else
2331	xmlSchemaFormatNodeForError(&msg, actxt, node);
2332    msg = xmlStrcat(msg, (const xmlChar *) message);
2333    msg = xmlStrcat(msg, BAD_CAST ".\n");
2334    xmlSchemaErr4(actxt, error, node,
2335	(const char *) msg, str1, str2, str3, str4);
2336    FREE_AND_NULL(msg)
2337}
2338
2339static void
2340xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2341		   xmlParserErrors error,
2342		   xmlNodePtr node,
2343		   xmlSchemaBasicItemPtr item,
2344		   const char *message,
2345		   const xmlChar *str1,
2346		   const xmlChar *str2)
2347{
2348    xmlSchemaCustomErr4(actxt, error, node, item,
2349	message, str1, str2, NULL, NULL);
2350}
2351
2352
2353
2354static void
2355xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2356		   xmlParserErrors error,
2357		   xmlNodePtr node,
2358		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2359		   const char *message,
2360		   const xmlChar *str1,
2361		   const xmlChar *str2,
2362		   const xmlChar *str3)
2363{
2364    xmlChar *msg = NULL;
2365
2366    xmlSchemaFormatNodeForError(&msg, actxt, node);
2367    msg = xmlStrcat(msg, (const xmlChar *) message);
2368    msg = xmlStrcat(msg, BAD_CAST ".\n");
2369
2370    /* URGENT TODO: Set the error code to something sane. */
2371    xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2372	(const char *) msg, str1, str2, str3, NULL);
2373
2374    FREE_AND_NULL(msg)
2375}
2376
2377
2378
2379static void
2380xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2381		   xmlParserErrors error,
2382		   xmlSchemaPSVIIDCNodePtr idcNode,
2383		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2384		   const char *message,
2385		   const xmlChar *str1,
2386		   const xmlChar *str2)
2387{
2388    xmlChar *msg = NULL, *qname = NULL;
2389
2390    msg = xmlStrdup(BAD_CAST "Element '%s': ");
2391    msg = xmlStrcat(msg, (const xmlChar *) message);
2392    msg = xmlStrcat(msg, BAD_CAST ".\n");
2393    xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2394	error, NULL, idcNode->nodeLine, (const char *) msg,
2395	xmlSchemaFormatQName(&qname,
2396	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2397	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2398	str1, str2, NULL);
2399    FREE_AND_NULL(qname);
2400    FREE_AND_NULL(msg);
2401}
2402
2403static int
2404xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2405			   xmlNodePtr node)
2406{
2407    if (node != NULL)
2408	return (node->type);
2409    if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2410	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2411	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2412    return (-1);
2413}
2414
2415static int
2416xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2417{
2418    switch (item->type) {
2419	case XML_SCHEMA_TYPE_COMPLEX:
2420	case XML_SCHEMA_TYPE_SIMPLE:
2421	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2422		return(1);
2423	    break;
2424	case XML_SCHEMA_TYPE_GROUP:
2425	    return (1);
2426	case XML_SCHEMA_TYPE_ELEMENT:
2427	    if ( ((xmlSchemaElementPtr) item)->flags &
2428		XML_SCHEMAS_ELEM_GLOBAL)
2429		return(1);
2430	    break;
2431	case XML_SCHEMA_TYPE_ATTRIBUTE:
2432	    if ( ((xmlSchemaAttributePtr) item)->flags &
2433		XML_SCHEMAS_ATTR_GLOBAL)
2434		return(1);
2435	    break;
2436	/* Note that attribute groups are always global. */
2437	default:
2438	    return(1);
2439    }
2440    return (0);
2441}
2442
2443static void
2444xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2445		       xmlParserErrors error,
2446		       xmlNodePtr node,
2447		       const xmlChar *value,
2448		       xmlSchemaTypePtr type,
2449		       int displayValue)
2450{
2451    xmlChar *msg = NULL;
2452
2453    xmlSchemaFormatNodeForError(&msg, actxt, node);
2454
2455    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2456	    XML_ATTRIBUTE_NODE))
2457	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2458    else
2459	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2460	    "value of ");
2461
2462    if (! xmlSchemaIsGlobalItem(type))
2463	msg = xmlStrcat(msg, BAD_CAST "the local ");
2464    else
2465	msg = xmlStrcat(msg, BAD_CAST "the ");
2466
2467    if (WXS_IS_ATOMIC(type))
2468	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2469    else if (WXS_IS_LIST(type))
2470	msg = xmlStrcat(msg, BAD_CAST "list type");
2471    else if (WXS_IS_UNION(type))
2472	msg = xmlStrcat(msg, BAD_CAST "union type");
2473
2474    if (xmlSchemaIsGlobalItem(type)) {
2475	xmlChar *str = NULL;
2476	msg = xmlStrcat(msg, BAD_CAST " '");
2477	if (type->builtInType != 0) {
2478	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2479	    msg = xmlStrcat(msg, type->name);
2480	} else
2481	    msg = xmlStrcat(msg,
2482		xmlSchemaFormatQName(&str,
2483		    type->targetNamespace, type->name));
2484	msg = xmlStrcat(msg, BAD_CAST "'");
2485	FREE_AND_NULL(str);
2486    }
2487    msg = xmlStrcat(msg, BAD_CAST ".\n");
2488    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2489	    XML_ATTRIBUTE_NODE))
2490	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2491    else
2492	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2493    FREE_AND_NULL(msg)
2494}
2495
2496static const xmlChar *
2497xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2498			      xmlSchemaNodeInfoPtr ni,
2499			      xmlNodePtr node)
2500{
2501    if (node != NULL) {
2502	if (node->ns != NULL)
2503	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2504	else
2505	    return (xmlSchemaFormatQName(str, NULL, node->name));
2506    } else if (ni != NULL)
2507	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2508    return (NULL);
2509}
2510
2511static void
2512xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2513			xmlParserErrors error,
2514			xmlSchemaAttrInfoPtr ni,
2515			xmlNodePtr node)
2516{
2517    xmlChar *msg = NULL, *str = NULL;
2518
2519    xmlSchemaFormatNodeForError(&msg, actxt, node);
2520    msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2521    xmlSchemaErr(actxt, error, node, (const char *) msg,
2522	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2523	NULL);
2524    FREE_AND_NULL(str)
2525    FREE_AND_NULL(msg)
2526}
2527
2528static void
2529xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2530		        xmlParserErrors error,
2531		        xmlNodePtr node,
2532			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2533			const char *message,
2534			int nbval,
2535			int nbneg,
2536			xmlChar **values)
2537{
2538    xmlChar *str = NULL, *msg = NULL;
2539    xmlChar *localName, *nsName;
2540    const xmlChar *cur, *end;
2541    int i;
2542
2543    xmlSchemaFormatNodeForError(&msg, actxt, node);
2544    msg = xmlStrcat(msg, (const xmlChar *) message);
2545    msg = xmlStrcat(msg, BAD_CAST ".");
2546    /*
2547    * Note that is does not make sense to report that we have a
2548    * wildcard here, since the wildcard might be unfolded into
2549    * multiple transitions.
2550    */
2551    if (nbval + nbneg > 0) {
2552	if (nbval + nbneg > 1) {
2553	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2554	} else
2555	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2556	nsName = NULL;
2557
2558	for (i = 0; i < nbval + nbneg; i++) {
2559	    cur = values[i];
2560	    if (cur == NULL)
2561	        continue;
2562	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2563	        (cur[3] == ' ')) {
2564		cur += 4;
2565		str = xmlStrcat(str, BAD_CAST "##other");
2566	    }
2567	    /*
2568	    * Get the local name.
2569	    */
2570	    localName = NULL;
2571
2572	    end = cur;
2573	    if (*end == '*') {
2574		localName = xmlStrdup(BAD_CAST "*");
2575		end++;
2576	    } else {
2577		while ((*end != 0) && (*end != '|'))
2578		    end++;
2579		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2580	    }
2581	    if (*end != 0) {
2582		end++;
2583		/*
2584		* Skip "*|*" if they come with negated expressions, since
2585		* they represent the same negated wildcard.
2586		*/
2587		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2588		    /*
2589		    * Get the namespace name.
2590		    */
2591		    cur = end;
2592		    if (*end == '*') {
2593			nsName = xmlStrdup(BAD_CAST "{*}");
2594		    } else {
2595			while (*end != 0)
2596			    end++;
2597
2598			if (i >= nbval)
2599			    nsName = xmlStrdup(BAD_CAST "{##other:");
2600			else
2601			    nsName = xmlStrdup(BAD_CAST "{");
2602
2603			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2604			nsName = xmlStrcat(nsName, BAD_CAST "}");
2605		    }
2606		    str = xmlStrcat(str, BAD_CAST nsName);
2607		    FREE_AND_NULL(nsName)
2608		} else {
2609		    FREE_AND_NULL(localName);
2610		    continue;
2611		}
2612	    }
2613	    str = xmlStrcat(str, BAD_CAST localName);
2614	    FREE_AND_NULL(localName);
2615
2616	    if (i < nbval + nbneg -1)
2617		str = xmlStrcat(str, BAD_CAST ", ");
2618	}
2619	str = xmlStrcat(str, BAD_CAST " ).\n");
2620	msg = xmlStrcat(msg, BAD_CAST str);
2621	FREE_AND_NULL(str)
2622    } else
2623      msg = xmlStrcat(msg, BAD_CAST "\n");
2624    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2625    xmlFree(msg);
2626}
2627
2628static void
2629xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2630		  xmlParserErrors error,
2631		  xmlNodePtr node,
2632		  const xmlChar *value,
2633		  unsigned long length,
2634		  xmlSchemaTypePtr type,
2635		  xmlSchemaFacetPtr facet,
2636		  const char *message,
2637		  const xmlChar *str1,
2638		  const xmlChar *str2)
2639{
2640    xmlChar *str = NULL, *msg = NULL;
2641    xmlSchemaTypeType facetType;
2642    int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2643
2644    xmlSchemaFormatNodeForError(&msg, actxt, node);
2645    if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2646	facetType = XML_SCHEMA_FACET_ENUMERATION;
2647	/*
2648	* If enumerations are validated, one must not expect the
2649	* facet to be given.
2650	*/
2651    } else
2652	facetType = facet->type;
2653    msg = xmlStrcat(msg, BAD_CAST "[");
2654    msg = xmlStrcat(msg, BAD_CAST "facet '");
2655    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2656    msg = xmlStrcat(msg, BAD_CAST "'] ");
2657    if (message == NULL) {
2658	/*
2659	* Use a default message.
2660	*/
2661	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2662	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2663	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2664
2665	    char len[25], actLen[25];
2666
2667	    /* FIXME, TODO: What is the max expected string length of the
2668	    * this value?
2669	    */
2670	    if (nodeType == XML_ATTRIBUTE_NODE)
2671		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2672	    else
2673		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2674
2675	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2676	    snprintf(actLen, 24, "%lu", length);
2677
2678	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2679		msg = xmlStrcat(msg,
2680		BAD_CAST "this differs from the allowed length of '%s'.\n");
2681	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2682		msg = xmlStrcat(msg,
2683		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2684	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2685		msg = xmlStrcat(msg,
2686		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2687
2688	    if (nodeType == XML_ATTRIBUTE_NODE)
2689		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2690		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2691	    else
2692		xmlSchemaErr(actxt, error, node, (const char *) msg,
2693		    (const xmlChar *) actLen, (const xmlChar *) len);
2694
2695	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2696	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2697		"of the set {%s}.\n");
2698	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2699		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2700	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2701	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2702		"by the pattern '%s'.\n");
2703	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2704		facet->value);
2705	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2706	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2707		"minimum value allowed ('%s').\n");
2708	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2709		facet->value);
2710	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2711	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2712		"maximum value allowed ('%s').\n");
2713	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2714		facet->value);
2715	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2716	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2717		"'%s'.\n");
2718	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2719		facet->value);
2720	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2721	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2722		"'%s'.\n");
2723	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2724		facet->value);
2725	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2726	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2727		"digits than are allowed ('%s').\n");
2728	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2729		facet->value);
2730	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2731	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2732		"digits than are allowed ('%s').\n");
2733	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2734		facet->value);
2735	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2736	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2737	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2738	} else {
2739	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2740	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2741	}
2742    } else {
2743	msg = xmlStrcat(msg, (const xmlChar *) message);
2744	msg = xmlStrcat(msg, BAD_CAST ".\n");
2745	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2746    }
2747    FREE_AND_NULL(str)
2748    xmlFree(msg);
2749}
2750
2751#define VERROR(err, type, msg) \
2752    xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2753
2754#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2755
2756#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2757#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2758
2759#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2760
2761
2762/**
2763 * xmlSchemaPMissingAttrErr:
2764 * @ctxt: the schema validation context
2765 * @ownerDes: the designation of  the owner
2766 * @ownerName: the name of the owner
2767 * @ownerItem: the owner as a schema object
2768 * @ownerElem: the owner as an element node
2769 * @node: the parent element node of the missing attribute node
2770 * @type: the corresponding type of the attribute node
2771 *
2772 * Reports an illegal attribute.
2773 */
2774static void
2775xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2776			 xmlParserErrors error,
2777			 xmlSchemaBasicItemPtr ownerItem,
2778			 xmlNodePtr ownerElem,
2779			 const char *name,
2780			 const char *message)
2781{
2782    xmlChar *des = NULL;
2783
2784    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2785
2786    if (message != NULL)
2787	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2788    else
2789	xmlSchemaPErr(ctxt, ownerElem, error,
2790	    "%s: The attribute '%s' is required but missing.\n",
2791	    BAD_CAST des, BAD_CAST name);
2792    FREE_AND_NULL(des);
2793}
2794
2795
2796/**
2797 * xmlSchemaPResCompAttrErr:
2798 * @ctxt: the schema validation context
2799 * @error: the error code
2800 * @ownerDes: the designation of  the owner
2801 * @ownerItem: the owner as a schema object
2802 * @ownerElem: the owner as an element node
2803 * @name: the name of the attribute holding the QName
2804 * @refName: the referenced local name
2805 * @refURI: the referenced namespace URI
2806 * @message: optional message
2807 *
2808 * Used to report QName attribute values that failed to resolve
2809 * to schema components.
2810 */
2811static void
2812xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2813			 xmlParserErrors error,
2814			 xmlSchemaBasicItemPtr ownerItem,
2815			 xmlNodePtr ownerElem,
2816			 const char *name,
2817			 const xmlChar *refName,
2818			 const xmlChar *refURI,
2819			 xmlSchemaTypeType refType,
2820			 const char *refTypeStr)
2821{
2822    xmlChar *des = NULL, *strA = NULL;
2823
2824    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2825    if (refTypeStr == NULL)
2826	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2827	xmlSchemaPErrExt(ctxt, ownerElem, error,
2828	    NULL, NULL, NULL,
2829	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2830	    "%s.\n", BAD_CAST des, BAD_CAST name,
2831	    xmlSchemaFormatQName(&strA, refURI, refName),
2832	    BAD_CAST refTypeStr, NULL);
2833    FREE_AND_NULL(des)
2834    FREE_AND_NULL(strA)
2835}
2836
2837/**
2838 * xmlSchemaPCustomAttrErr:
2839 * @ctxt: the schema parser context
2840 * @error: the error code
2841 * @ownerDes: the designation of the owner
2842 * @ownerItem: the owner as a schema object
2843 * @attr: the illegal attribute node
2844 *
2845 * Reports an illegal attribute during the parse.
2846 */
2847static void
2848xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2849			xmlParserErrors error,
2850			xmlChar **ownerDes,
2851			xmlSchemaBasicItemPtr ownerItem,
2852			xmlAttrPtr attr,
2853			const char *msg)
2854{
2855    xmlChar *des = NULL;
2856
2857    if (ownerDes == NULL)
2858	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2859    else if (*ownerDes == NULL) {
2860	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2861	des = *ownerDes;
2862    } else
2863	des = *ownerDes;
2864    if (attr == NULL) {
2865	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2866	    "%s, attribute '%s': %s.\n",
2867	    BAD_CAST des, (const xmlChar *) "Unknown",
2868	    (const xmlChar *) msg, NULL, NULL);
2869    } else {
2870	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2871	    "%s, attribute '%s': %s.\n",
2872	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2873    }
2874    if (ownerDes == NULL)
2875	FREE_AND_NULL(des);
2876}
2877
2878/**
2879 * xmlSchemaPIllegalAttrErr:
2880 * @ctxt: the schema parser context
2881 * @error: the error code
2882 * @ownerDes: the designation of the attribute's owner
2883 * @ownerItem: the attribute's owner item
2884 * @attr: the illegal attribute node
2885 *
2886 * Reports an illegal attribute during the parse.
2887 */
2888static void
2889xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2890			 xmlParserErrors error,
2891			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2892			 xmlAttrPtr attr)
2893{
2894    xmlChar *strA = NULL, *strB = NULL;
2895
2896    xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2897    xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2898	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2899	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2900	NULL, NULL);
2901    FREE_AND_NULL(strA);
2902    FREE_AND_NULL(strB);
2903}
2904
2905/**
2906 * xmlSchemaPCustomErr:
2907 * @ctxt: the schema parser context
2908 * @error: the error code
2909 * @itemDes: the designation of the schema item
2910 * @item: the schema item
2911 * @itemElem: the node of the schema item
2912 * @message: the error message
2913 * @str1: an optional param for the error message
2914 * @str2: an optional param for the error message
2915 * @str3: an optional param for the error message
2916 *
2917 * Reports an error during parsing.
2918 */
2919static void
2920xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2921		    xmlParserErrors error,
2922		    xmlSchemaBasicItemPtr item,
2923		    xmlNodePtr itemElem,
2924		    const char *message,
2925		    const xmlChar *str1,
2926		    const xmlChar *str2,
2927		    const xmlChar *str3)
2928{
2929    xmlChar *des = NULL, *msg = NULL;
2930
2931    xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2932    msg = xmlStrdup(BAD_CAST "%s: ");
2933    msg = xmlStrcat(msg, (const xmlChar *) message);
2934    msg = xmlStrcat(msg, BAD_CAST ".\n");
2935    if ((itemElem == NULL) && (item != NULL))
2936	itemElem = WXS_ITEM_NODE(item);
2937    xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2938	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2939    FREE_AND_NULL(des);
2940    FREE_AND_NULL(msg);
2941}
2942
2943/**
2944 * xmlSchemaPCustomErr:
2945 * @ctxt: the schema parser context
2946 * @error: the error code
2947 * @itemDes: the designation of the schema item
2948 * @item: the schema item
2949 * @itemElem: the node of the schema item
2950 * @message: the error message
2951 * @str1: the optional param for the error message
2952 *
2953 * Reports an error during parsing.
2954 */
2955static void
2956xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2957		    xmlParserErrors error,
2958		    xmlSchemaBasicItemPtr item,
2959		    xmlNodePtr itemElem,
2960		    const char *message,
2961		    const xmlChar *str1)
2962{
2963    xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2964	str1, NULL, NULL);
2965}
2966
2967/**
2968 * xmlSchemaPAttrUseErr:
2969 * @ctxt: the schema parser context
2970 * @error: the error code
2971 * @itemDes: the designation of the schema type
2972 * @item: the schema type
2973 * @itemElem: the node of the schema type
2974 * @attr: the invalid schema attribute
2975 * @message: the error message
2976 * @str1: the optional param for the error message
2977 *
2978 * Reports an attribute use error during parsing.
2979 */
2980static void
2981xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2982		    xmlParserErrors error,
2983		    xmlNodePtr node,
2984		    xmlSchemaBasicItemPtr ownerItem,
2985		    const xmlSchemaAttributeUsePtr attruse,
2986		    const char *message,
2987		    const xmlChar *str1, const xmlChar *str2,
2988		    const xmlChar *str3,const xmlChar *str4)
2989{
2990    xmlChar *str = NULL, *msg = NULL;
2991
2992    xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2993    msg = xmlStrcat(msg, BAD_CAST ", ");
2994    msg = xmlStrcat(msg,
2995	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2996	WXS_BASIC_CAST attruse, NULL));
2997    FREE_AND_NULL(str);
2998    msg = xmlStrcat(msg, BAD_CAST ": ");
2999    msg = xmlStrcat(msg, (const xmlChar *) message);
3000    msg = xmlStrcat(msg, BAD_CAST ".\n");
3001    xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3002	(const char *) msg, str1, str2, str3, str4);
3003    xmlFree(msg);
3004}
3005
3006/**
3007 * xmlSchemaPIllegalFacetAtomicErr:
3008 * @ctxt: the schema parser context
3009 * @error: the error code
3010 * @type: the schema type
3011 * @baseType: the base type of type
3012 * @facet: the illegal facet
3013 *
3014 * Reports an illegal facet for atomic simple types.
3015 */
3016static void
3017xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3018			  xmlParserErrors error,
3019			  xmlSchemaTypePtr type,
3020			  xmlSchemaTypePtr baseType,
3021			  xmlSchemaFacetPtr facet)
3022{
3023    xmlChar *des = NULL, *strT = NULL;
3024
3025    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3026    xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3027	"%s: The facet '%s' is not allowed on types derived from the "
3028	"type %s.\n",
3029	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3030	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3031	NULL, NULL);
3032    FREE_AND_NULL(des);
3033    FREE_AND_NULL(strT);
3034}
3035
3036/**
3037 * xmlSchemaPIllegalFacetListUnionErr:
3038 * @ctxt: the schema parser context
3039 * @error: the error code
3040 * @itemDes: the designation of the schema item involved
3041 * @item: the schema item involved
3042 * @facet: the illegal facet
3043 *
3044 * Reports an illegal facet for <list> and <union>.
3045 */
3046static void
3047xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3048			  xmlParserErrors error,
3049			  xmlSchemaTypePtr type,
3050			  xmlSchemaFacetPtr facet)
3051{
3052    xmlChar *des = NULL;
3053
3054    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3055	type->node);
3056    xmlSchemaPErr(ctxt, type->node, error,
3057	"%s: The facet '%s' is not allowed.\n",
3058	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3059    FREE_AND_NULL(des);
3060}
3061
3062/**
3063 * xmlSchemaPMutualExclAttrErr:
3064 * @ctxt: the schema validation context
3065 * @error: the error code
3066 * @elemDes: the designation of the parent element node
3067 * @attr: the bad attribute node
3068 * @type: the corresponding type of the attribute node
3069 *
3070 * Reports an illegal attribute.
3071 */
3072static void
3073xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3074			 xmlParserErrors error,
3075			 xmlSchemaBasicItemPtr ownerItem,
3076			 xmlAttrPtr attr,
3077			 const char *name1,
3078			 const char *name2)
3079{
3080    xmlChar *des = NULL;
3081
3082    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3083    xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3084	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3085	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3086    FREE_AND_NULL(des);
3087}
3088
3089/**
3090 * xmlSchemaPSimpleTypeErr:
3091 * @ctxt:  the schema validation context
3092 * @error: the error code
3093 * @type: the type specifier
3094 * @ownerDes: the designation of the owner
3095 * @ownerItem: the schema object if existent
3096 * @node: the validated node
3097 * @value: the validated value
3098 *
3099 * Reports a simple type validation error.
3100 * TODO: Should this report the value of an element as well?
3101 */
3102static void
3103xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3104			xmlParserErrors error,
3105			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3106			xmlNodePtr node,
3107			xmlSchemaTypePtr type,
3108			const char *expected,
3109			const xmlChar *value,
3110			const char *message,
3111			const xmlChar *str1,
3112			const xmlChar *str2)
3113{
3114    xmlChar *msg = NULL;
3115
3116    xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3117    if (message == NULL) {
3118	/*
3119	* Use default messages.
3120	*/
3121	if (type != NULL) {
3122	    if (node->type == XML_ATTRIBUTE_NODE)
3123		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3124	    else
3125		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3126		"valid value of ");
3127	    if (! xmlSchemaIsGlobalItem(type))
3128		msg = xmlStrcat(msg, BAD_CAST "the local ");
3129	    else
3130		msg = xmlStrcat(msg, BAD_CAST "the ");
3131
3132	    if (WXS_IS_ATOMIC(type))
3133		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3134	    else if (WXS_IS_LIST(type))
3135		msg = xmlStrcat(msg, BAD_CAST "list type");
3136	    else if (WXS_IS_UNION(type))
3137		msg = xmlStrcat(msg, BAD_CAST "union type");
3138
3139	    if (xmlSchemaIsGlobalItem(type)) {
3140		xmlChar *str = NULL;
3141		msg = xmlStrcat(msg, BAD_CAST " '");
3142		if (type->builtInType != 0) {
3143		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3144		    msg = xmlStrcat(msg, type->name);
3145		} else
3146		    msg = xmlStrcat(msg,
3147			xmlSchemaFormatQName(&str,
3148			    type->targetNamespace, type->name));
3149		msg = xmlStrcat(msg, BAD_CAST "'.");
3150		FREE_AND_NULL(str);
3151	    }
3152	} else {
3153	    if (node->type == XML_ATTRIBUTE_NODE)
3154		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3155	    else
3156		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3157		"valid.");
3158	}
3159	if (expected) {
3160	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3161	    msg = xmlStrcat(msg, BAD_CAST expected);
3162	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3163	} else
3164	    msg = xmlStrcat(msg, BAD_CAST "\n");
3165	if (node->type == XML_ATTRIBUTE_NODE)
3166	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3167	else
3168	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3169    } else {
3170	msg = xmlStrcat(msg, BAD_CAST message);
3171	msg = xmlStrcat(msg, BAD_CAST ".\n");
3172	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3173	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3174    }
3175    /* Cleanup. */
3176    FREE_AND_NULL(msg)
3177}
3178
3179/**
3180 * xmlSchemaPContentErr:
3181 * @ctxt: the schema parser context
3182 * @error: the error code
3183 * @onwerDes: the designation of the holder of the content
3184 * @ownerItem: the owner item of the holder of the content
3185 * @ownerElem: the node of the holder of the content
3186 * @child: the invalid child node
3187 * @message: the optional error message
3188 * @content: the optional string describing the correct content
3189 *
3190 * Reports an error concerning the content of a schema element.
3191 */
3192static void
3193xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3194		     xmlParserErrors error,
3195		     xmlSchemaBasicItemPtr ownerItem,
3196		     xmlNodePtr ownerElem,
3197		     xmlNodePtr child,
3198		     const char *message,
3199		     const char *content)
3200{
3201    xmlChar *des = NULL;
3202
3203    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3204    if (message != NULL)
3205	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3206	    "%s: %s.\n",
3207	    BAD_CAST des, BAD_CAST message);
3208    else {
3209	if (content != NULL) {
3210	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3211		"%s: The content is not valid. Expected is %s.\n",
3212		BAD_CAST des, BAD_CAST content);
3213	} else {
3214	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3215		"%s: The content is not valid.\n",
3216		BAD_CAST des, NULL);
3217	}
3218    }
3219    FREE_AND_NULL(des)
3220}
3221
3222/************************************************************************
3223 *									*
3224 *			Streamable error functions                      *
3225 *									*
3226 ************************************************************************/
3227
3228
3229
3230
3231/************************************************************************
3232 *									*
3233 *			Validation helper functions			*
3234 *									*
3235 ************************************************************************/
3236
3237
3238/************************************************************************
3239 *									*
3240 *			Allocation functions				*
3241 *									*
3242 ************************************************************************/
3243
3244/**
3245 * xmlSchemaNewSchemaForParserCtxt:
3246 * @ctxt:  a schema validation context
3247 *
3248 * Allocate a new Schema structure.
3249 *
3250 * Returns the newly allocated structure or NULL in case or error
3251 */
3252static xmlSchemaPtr
3253xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3254{
3255    xmlSchemaPtr ret;
3256
3257    ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3258    if (ret == NULL) {
3259        xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3260        return (NULL);
3261    }
3262    memset(ret, 0, sizeof(xmlSchema));
3263    ret->dict = ctxt->dict;
3264    xmlDictReference(ret->dict);
3265
3266    return (ret);
3267}
3268
3269/**
3270 * xmlSchemaNewFacet:
3271 *
3272 * Allocate a new Facet structure.
3273 *
3274 * Returns the newly allocated structure or NULL in case or error
3275 */
3276xmlSchemaFacetPtr
3277xmlSchemaNewFacet(void)
3278{
3279    xmlSchemaFacetPtr ret;
3280
3281    ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3282    if (ret == NULL) {
3283        return (NULL);
3284    }
3285    memset(ret, 0, sizeof(xmlSchemaFacet));
3286
3287    return (ret);
3288}
3289
3290/**
3291 * xmlSchemaNewAnnot:
3292 * @ctxt:  a schema validation context
3293 * @node:  a node
3294 *
3295 * Allocate a new annotation structure.
3296 *
3297 * Returns the newly allocated structure or NULL in case or error
3298 */
3299static xmlSchemaAnnotPtr
3300xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3301{
3302    xmlSchemaAnnotPtr ret;
3303
3304    ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3305    if (ret == NULL) {
3306        xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3307        return (NULL);
3308    }
3309    memset(ret, 0, sizeof(xmlSchemaAnnot));
3310    ret->content = node;
3311    return (ret);
3312}
3313
3314static xmlSchemaItemListPtr
3315xmlSchemaItemListCreate(void)
3316{
3317    xmlSchemaItemListPtr ret;
3318
3319    ret = xmlMalloc(sizeof(xmlSchemaItemList));
3320    if (ret == NULL) {
3321	xmlSchemaPErrMemory(NULL,
3322	    "allocating an item list structure", NULL);
3323	return (NULL);
3324    }
3325    memset(ret, 0, sizeof(xmlSchemaItemList));
3326    return (ret);
3327}
3328
3329static void
3330xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3331{
3332    if (list->items != NULL) {
3333	xmlFree(list->items);
3334	list->items = NULL;
3335    }
3336    list->nbItems = 0;
3337    list->sizeItems = 0;
3338}
3339
3340static int
3341xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3342{
3343    if (list->items == NULL) {
3344	list->items = (void **) xmlMalloc(
3345	    20 * sizeof(void *));
3346	if (list->items == NULL) {
3347	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3348	    return(-1);
3349	}
3350	list->sizeItems = 20;
3351    } else if (list->sizeItems <= list->nbItems) {
3352	list->sizeItems *= 2;
3353	list->items = (void **) xmlRealloc(list->items,
3354	    list->sizeItems * sizeof(void *));
3355	if (list->items == NULL) {
3356	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3357	    list->sizeItems = 0;
3358	    return(-1);
3359	}
3360    }
3361    list->items[list->nbItems++] = item;
3362    return(0);
3363}
3364
3365static int
3366xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3367			 int initialSize,
3368			 void *item)
3369{
3370    if (list->items == NULL) {
3371	if (initialSize <= 0)
3372	    initialSize = 1;
3373	list->items = (void **) xmlMalloc(
3374	    initialSize * sizeof(void *));
3375	if (list->items == NULL) {
3376	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3377	    return(-1);
3378	}
3379	list->sizeItems = initialSize;
3380    } else if (list->sizeItems <= list->nbItems) {
3381	list->sizeItems *= 2;
3382	list->items = (void **) xmlRealloc(list->items,
3383	    list->sizeItems * sizeof(void *));
3384	if (list->items == NULL) {
3385	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3386	    list->sizeItems = 0;
3387	    return(-1);
3388	}
3389    }
3390    list->items[list->nbItems++] = item;
3391    return(0);
3392}
3393
3394static int
3395xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3396{
3397    if (list->items == NULL) {
3398	list->items = (void **) xmlMalloc(
3399	    20 * sizeof(void *));
3400	if (list->items == NULL) {
3401	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3402	    return(-1);
3403	}
3404	list->sizeItems = 20;
3405    } else if (list->sizeItems <= list->nbItems) {
3406	list->sizeItems *= 2;
3407	list->items = (void **) xmlRealloc(list->items,
3408	    list->sizeItems * sizeof(void *));
3409	if (list->items == NULL) {
3410	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3411	    list->sizeItems = 0;
3412	    return(-1);
3413	}
3414    }
3415    /*
3416    * Just append if the index is greater/equal than the item count.
3417    */
3418    if (idx >= list->nbItems) {
3419	list->items[list->nbItems++] = item;
3420    } else {
3421	int i;
3422	for (i = list->nbItems; i > idx; i--)
3423	    list->items[i] = list->items[i-1];
3424	list->items[idx] = item;
3425	list->nbItems++;
3426    }
3427    return(0);
3428}
3429
3430#if 0 /* enable if ever needed */
3431static int
3432xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3433			    int initialSize,
3434			    void *item,
3435			    int idx)
3436{
3437    if (list->items == NULL) {
3438	if (initialSize <= 0)
3439	    initialSize = 1;
3440	list->items = (void **) xmlMalloc(
3441	    initialSize * sizeof(void *));
3442	if (list->items == NULL) {
3443	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3444	    return(-1);
3445	}
3446	list->sizeItems = initialSize;
3447    } else if (list->sizeItems <= list->nbItems) {
3448	list->sizeItems *= 2;
3449	list->items = (void **) xmlRealloc(list->items,
3450	    list->sizeItems * sizeof(void *));
3451	if (list->items == NULL) {
3452	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3453	    list->sizeItems = 0;
3454	    return(-1);
3455	}
3456    }
3457    /*
3458    * Just append if the index is greater/equal than the item count.
3459    */
3460    if (idx >= list->nbItems) {
3461	list->items[list->nbItems++] = item;
3462    } else {
3463	int i;
3464	for (i = list->nbItems; i > idx; i--)
3465	    list->items[i] = list->items[i-1];
3466	list->items[idx] = item;
3467	list->nbItems++;
3468    }
3469    return(0);
3470}
3471#endif
3472
3473static int
3474xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3475{
3476    int i;
3477    if ((list->items == NULL) || (idx >= list->nbItems)) {
3478	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3479	    "index error.\n");
3480	return(-1);
3481    }
3482
3483    if (list->nbItems == 1) {
3484	/* TODO: Really free the list? */
3485	xmlFree(list->items);
3486	list->items = NULL;
3487	list->nbItems = 0;
3488	list->sizeItems = 0;
3489    } else if (list->nbItems -1 == idx) {
3490	list->nbItems--;
3491    } else {
3492	for (i = idx; i < list->nbItems -1; i++)
3493	    list->items[i] = list->items[i+1];
3494	list->nbItems--;
3495    }
3496    return(0);
3497}
3498
3499/**
3500 * xmlSchemaItemListFree:
3501 * @annot:  a schema type structure
3502 *
3503 * Deallocate a annotation structure
3504 */
3505static void
3506xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3507{
3508    if (list == NULL)
3509	return;
3510    if (list->items != NULL)
3511	xmlFree(list->items);
3512    xmlFree(list);
3513}
3514
3515static void
3516xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3517{
3518    if (bucket == NULL)
3519	return;
3520    if (bucket->globals != NULL) {
3521	xmlSchemaComponentListFree(bucket->globals);
3522	xmlSchemaItemListFree(bucket->globals);
3523    }
3524    if (bucket->locals != NULL) {
3525	xmlSchemaComponentListFree(bucket->locals);
3526	xmlSchemaItemListFree(bucket->locals);
3527    }
3528    if (bucket->relations != NULL) {
3529	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3530	do {
3531	    prev = cur;
3532	    cur = cur->next;
3533	    xmlFree(prev);
3534	} while (cur != NULL);
3535    }
3536    if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3537	xmlFreeDoc(bucket->doc);
3538    }
3539    if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3540	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3541	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3542    }
3543    xmlFree(bucket);
3544}
3545
3546static xmlSchemaBucketPtr
3547xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3548			 int type, const xmlChar *targetNamespace)
3549{
3550    xmlSchemaBucketPtr ret;
3551    int size;
3552    xmlSchemaPtr mainSchema;
3553
3554    if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3555	PERROR_INT("xmlSchemaBucketCreate",
3556	    "no main schema on constructor");
3557	return(NULL);
3558    }
3559    mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3560    /* Create the schema bucket. */
3561    if (WXS_IS_BUCKET_INCREDEF(type))
3562	size = sizeof(xmlSchemaInclude);
3563    else
3564	size = sizeof(xmlSchemaImport);
3565    ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3566    if (ret == NULL) {
3567	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3568	return(NULL);
3569    }
3570    memset(ret, 0, size);
3571    ret->targetNamespace = targetNamespace;
3572    ret->type = type;
3573    ret->globals = xmlSchemaItemListCreate();
3574    if (ret->globals == NULL) {
3575	xmlFree(ret);
3576	return(NULL);
3577    }
3578    ret->locals = xmlSchemaItemListCreate();
3579    if (ret->locals == NULL) {
3580	xmlFree(ret);
3581	return(NULL);
3582    }
3583    /*
3584    * The following will assure that only the first bucket is marked as
3585    * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3586    * For each following import buckets an xmlSchema will be created.
3587    * An xmlSchema will be created for every distinct targetNamespace.
3588    * We assign the targetNamespace to the schemata here.
3589    */
3590    if (! WXS_HAS_BUCKETS(pctxt)) {
3591	if (WXS_IS_BUCKET_INCREDEF(type)) {
3592	    PERROR_INT("xmlSchemaBucketCreate",
3593		"first bucket but it's an include or redefine");
3594	    xmlSchemaBucketFree(ret);
3595	    return(NULL);
3596	}
3597	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3598	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3599	/* Point to the *main* schema. */
3600	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3601	WXS_IMPBUCKET(ret)->schema = mainSchema;
3602	/*
3603	* Ensure that the main schema gets a targetNamespace.
3604	*/
3605	mainSchema->targetNamespace = targetNamespace;
3606    } else {
3607	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3608	    PERROR_INT("xmlSchemaBucketCreate",
3609		"main bucket but it's not the first one");
3610	    xmlSchemaBucketFree(ret);
3611	    return(NULL);
3612	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3613	    /*
3614	    * Create a schema for imports and assign the
3615	    * targetNamespace.
3616	    */
3617	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3618	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3619		xmlSchemaBucketFree(ret);
3620		return(NULL);
3621	    }
3622	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3623	}
3624    }
3625    if (WXS_IS_BUCKET_IMPMAIN(type)) {
3626	int res;
3627	/*
3628	* Imports go into the "schemasImports" slot of the main *schema*.
3629	* Note that we create an import entry for the main schema as well; i.e.,
3630	* even if there's only one schema, we'll get an import.
3631	*/
3632	if (mainSchema->schemasImports == NULL) {
3633	    mainSchema->schemasImports = xmlHashCreateDict(5,
3634		WXS_CONSTRUCTOR(pctxt)->dict);
3635	    if (mainSchema->schemasImports == NULL) {
3636		xmlSchemaBucketFree(ret);
3637		return(NULL);
3638	    }
3639	}
3640	if (targetNamespace == NULL)
3641	    res = xmlHashAddEntry(mainSchema->schemasImports,
3642		XML_SCHEMAS_NO_NAMESPACE, ret);
3643	else
3644	    res = xmlHashAddEntry(mainSchema->schemasImports,
3645		targetNamespace, ret);
3646	if (res != 0) {
3647	    PERROR_INT("xmlSchemaBucketCreate",
3648		"failed to add the schema bucket to the hash");
3649	    xmlSchemaBucketFree(ret);
3650	    return(NULL);
3651	}
3652    } else {
3653	/* Set the @ownerImport of an include bucket. */
3654	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3655	    WXS_INCBUCKET(ret)->ownerImport =
3656		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3657	else
3658	    WXS_INCBUCKET(ret)->ownerImport =
3659		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3660
3661	/* Includes got into the "includes" slot of the *main* schema. */
3662	if (mainSchema->includes == NULL) {
3663	    mainSchema->includes = xmlSchemaItemListCreate();
3664	    if (mainSchema->includes == NULL) {
3665		xmlSchemaBucketFree(ret);
3666		return(NULL);
3667	    }
3668	}
3669	xmlSchemaItemListAdd(mainSchema->includes, ret);
3670    }
3671    /*
3672    * Add to list of all buckets; this is used for lookup
3673    * during schema construction time only.
3674    */
3675    if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3676	return(NULL);
3677    return(ret);
3678}
3679
3680static int
3681xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3682{
3683    if (*list == NULL) {
3684	*list = xmlSchemaItemListCreate();
3685	if (*list == NULL)
3686	    return(-1);
3687    }
3688    xmlSchemaItemListAddSize(*list, initialSize, item);
3689    return(0);
3690}
3691
3692/**
3693 * xmlSchemaFreeAnnot:
3694 * @annot:  a schema type structure
3695 *
3696 * Deallocate a annotation structure
3697 */
3698static void
3699xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3700{
3701    if (annot == NULL)
3702        return;
3703    if (annot->next == NULL) {
3704	xmlFree(annot);
3705    } else {
3706	xmlSchemaAnnotPtr prev;
3707
3708	do {
3709	    prev = annot;
3710	    annot = annot->next;
3711	    xmlFree(prev);
3712	} while (annot != NULL);
3713    }
3714}
3715
3716/**
3717 * xmlSchemaFreeNotation:
3718 * @schema:  a schema notation structure
3719 *
3720 * Deallocate a Schema Notation structure.
3721 */
3722static void
3723xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3724{
3725    if (nota == NULL)
3726        return;
3727    xmlFree(nota);
3728}
3729
3730/**
3731 * xmlSchemaFreeAttribute:
3732 * @attr:  an attribute declaration
3733 *
3734 * Deallocates an attribute declaration structure.
3735 */
3736static void
3737xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3738{
3739    if (attr == NULL)
3740        return;
3741    if (attr->annot != NULL)
3742	xmlSchemaFreeAnnot(attr->annot);
3743    if (attr->defVal != NULL)
3744	xmlSchemaFreeValue(attr->defVal);
3745    xmlFree(attr);
3746}
3747
3748/**
3749 * xmlSchemaFreeAttributeUse:
3750 * @use:  an attribute use
3751 *
3752 * Deallocates an attribute use structure.
3753 */
3754static void
3755xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3756{
3757    if (use == NULL)
3758        return;
3759    if (use->annot != NULL)
3760	xmlSchemaFreeAnnot(use->annot);
3761    if (use->defVal != NULL)
3762	xmlSchemaFreeValue(use->defVal);
3763    xmlFree(use);
3764}
3765
3766/**
3767 * xmlSchemaFreeAttributeUseProhib:
3768 * @prohib:  an attribute use prohibition
3769 *
3770 * Deallocates an attribute use structure.
3771 */
3772static void
3773xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3774{
3775    if (prohib == NULL)
3776        return;
3777    xmlFree(prohib);
3778}
3779
3780/**
3781 * xmlSchemaFreeWildcardNsSet:
3782 * set:  a schema wildcard namespace
3783 *
3784 * Deallocates a list of wildcard constraint structures.
3785 */
3786static void
3787xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3788{
3789    xmlSchemaWildcardNsPtr next;
3790
3791    while (set != NULL) {
3792	next = set->next;
3793	xmlFree(set);
3794	set = next;
3795    }
3796}
3797
3798/**
3799 * xmlSchemaFreeWildcard:
3800 * @wildcard:  a wildcard structure
3801 *
3802 * Deallocates a wildcard structure.
3803 */
3804void
3805xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3806{
3807    if (wildcard == NULL)
3808        return;
3809    if (wildcard->annot != NULL)
3810        xmlSchemaFreeAnnot(wildcard->annot);
3811    if (wildcard->nsSet != NULL)
3812	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3813    if (wildcard->negNsSet != NULL)
3814	xmlFree(wildcard->negNsSet);
3815    xmlFree(wildcard);
3816}
3817
3818/**
3819 * xmlSchemaFreeAttributeGroup:
3820 * @schema:  a schema attribute group structure
3821 *
3822 * Deallocate a Schema Attribute Group structure.
3823 */
3824static void
3825xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3826{
3827    if (attrGr == NULL)
3828        return;
3829    if (attrGr->annot != NULL)
3830        xmlSchemaFreeAnnot(attrGr->annot);
3831    if (attrGr->attrUses != NULL)
3832	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3833    xmlFree(attrGr);
3834}
3835
3836/**
3837 * xmlSchemaFreeQNameRef:
3838 * @item: a QName reference structure
3839 *
3840 * Deallocatea a QName reference structure.
3841 */
3842static void
3843xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3844{
3845    xmlFree(item);
3846}
3847
3848/**
3849 * xmlSchemaFreeTypeLinkList:
3850 * @alink: a type link
3851 *
3852 * Deallocate a list of types.
3853 */
3854static void
3855xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3856{
3857    xmlSchemaTypeLinkPtr next;
3858
3859    while (link != NULL) {
3860	next = link->next;
3861	xmlFree(link);
3862	link = next;
3863    }
3864}
3865
3866static void
3867xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3868{
3869    xmlSchemaIDCStateObjPtr next;
3870    while (sto != NULL) {
3871	next = sto->next;
3872	if (sto->history != NULL)
3873	    xmlFree(sto->history);
3874	if (sto->xpathCtxt != NULL)
3875	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3876	xmlFree(sto);
3877	sto = next;
3878    }
3879}
3880
3881/**
3882 * xmlSchemaFreeIDC:
3883 * @idc: a identity-constraint definition
3884 *
3885 * Deallocates an identity-constraint definition.
3886 */
3887static void
3888xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3889{
3890    xmlSchemaIDCSelectPtr cur, prev;
3891
3892    if (idcDef == NULL)
3893	return;
3894    if (idcDef->annot != NULL)
3895        xmlSchemaFreeAnnot(idcDef->annot);
3896    /* Selector */
3897    if (idcDef->selector != NULL) {
3898	if (idcDef->selector->xpathComp != NULL)
3899	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3900	xmlFree(idcDef->selector);
3901    }
3902    /* Fields */
3903    if (idcDef->fields != NULL) {
3904	cur = idcDef->fields;
3905	do {
3906	    prev = cur;
3907	    cur = cur->next;
3908	    if (prev->xpathComp != NULL)
3909		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3910	    xmlFree(prev);
3911	} while (cur != NULL);
3912    }
3913    xmlFree(idcDef);
3914}
3915
3916/**
3917 * xmlSchemaFreeElement:
3918 * @schema:  a schema element structure
3919 *
3920 * Deallocate a Schema Element structure.
3921 */
3922static void
3923xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3924{
3925    if (elem == NULL)
3926        return;
3927    if (elem->annot != NULL)
3928        xmlSchemaFreeAnnot(elem->annot);
3929    if (elem->contModel != NULL)
3930        xmlRegFreeRegexp(elem->contModel);
3931    if (elem->defVal != NULL)
3932	xmlSchemaFreeValue(elem->defVal);
3933    xmlFree(elem);
3934}
3935
3936/**
3937 * xmlSchemaFreeFacet:
3938 * @facet:  a schema facet structure
3939 *
3940 * Deallocate a Schema Facet structure.
3941 */
3942void
3943xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3944{
3945    if (facet == NULL)
3946        return;
3947    if (facet->val != NULL)
3948        xmlSchemaFreeValue(facet->val);
3949    if (facet->regexp != NULL)
3950        xmlRegFreeRegexp(facet->regexp);
3951    if (facet->annot != NULL)
3952        xmlSchemaFreeAnnot(facet->annot);
3953    xmlFree(facet);
3954}
3955
3956/**
3957 * xmlSchemaFreeType:
3958 * @type:  a schema type structure
3959 *
3960 * Deallocate a Schema Type structure.
3961 */
3962void
3963xmlSchemaFreeType(xmlSchemaTypePtr type)
3964{
3965    if (type == NULL)
3966        return;
3967    if (type->annot != NULL)
3968        xmlSchemaFreeAnnot(type->annot);
3969    if (type->facets != NULL) {
3970        xmlSchemaFacetPtr facet, next;
3971
3972        facet = type->facets;
3973        while (facet != NULL) {
3974            next = facet->next;
3975            xmlSchemaFreeFacet(facet);
3976            facet = next;
3977        }
3978    }
3979    if (type->attrUses != NULL)
3980	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3981    if (type->memberTypes != NULL)
3982	xmlSchemaFreeTypeLinkList(type->memberTypes);
3983    if (type->facetSet != NULL) {
3984	xmlSchemaFacetLinkPtr next, link;
3985
3986	link = type->facetSet;
3987	do {
3988	    next = link->next;
3989	    xmlFree(link);
3990	    link = next;
3991	} while (link != NULL);
3992    }
3993    if (type->contModel != NULL)
3994        xmlRegFreeRegexp(type->contModel);
3995    xmlFree(type);
3996}
3997
3998/**
3999 * xmlSchemaFreeModelGroupDef:
4000 * @item:  a schema model group definition
4001 *
4002 * Deallocates a schema model group definition.
4003 */
4004static void
4005xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4006{
4007    if (item->annot != NULL)
4008	xmlSchemaFreeAnnot(item->annot);
4009    xmlFree(item);
4010}
4011
4012/**
4013 * xmlSchemaFreeModelGroup:
4014 * @item:  a schema model group
4015 *
4016 * Deallocates a schema model group structure.
4017 */
4018static void
4019xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4020{
4021    if (item->annot != NULL)
4022	xmlSchemaFreeAnnot(item->annot);
4023    xmlFree(item);
4024}
4025
4026static void
4027xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4028{
4029    if ((list == NULL) || (list->nbItems == 0))
4030	return;
4031    {
4032	xmlSchemaTreeItemPtr item;
4033	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4034	int i;
4035
4036	for (i = 0; i < list->nbItems; i++) {
4037	    item = items[i];
4038	    if (item == NULL)
4039		continue;
4040	    switch (item->type) {
4041		case XML_SCHEMA_TYPE_SIMPLE:
4042		case XML_SCHEMA_TYPE_COMPLEX:
4043		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4044		    break;
4045		case XML_SCHEMA_TYPE_ATTRIBUTE:
4046		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4047		    break;
4048		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4049		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4050		    break;
4051		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4052		    xmlSchemaFreeAttributeUseProhib(
4053			(xmlSchemaAttributeUseProhibPtr) item);
4054		    break;
4055		case XML_SCHEMA_TYPE_ELEMENT:
4056		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4057		    break;
4058		case XML_SCHEMA_TYPE_PARTICLE:
4059		    if (item->annot != NULL)
4060			xmlSchemaFreeAnnot(item->annot);
4061		    xmlFree(item);
4062		    break;
4063		case XML_SCHEMA_TYPE_SEQUENCE:
4064		case XML_SCHEMA_TYPE_CHOICE:
4065		case XML_SCHEMA_TYPE_ALL:
4066		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4067		    break;
4068		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4069		    xmlSchemaFreeAttributeGroup(
4070			(xmlSchemaAttributeGroupPtr) item);
4071		    break;
4072		case XML_SCHEMA_TYPE_GROUP:
4073		    xmlSchemaFreeModelGroupDef(
4074			(xmlSchemaModelGroupDefPtr) item);
4075		    break;
4076		case XML_SCHEMA_TYPE_ANY:
4077		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4078		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4079		    break;
4080		case XML_SCHEMA_TYPE_IDC_KEY:
4081		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4082		case XML_SCHEMA_TYPE_IDC_KEYREF:
4083		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4084		    break;
4085		case XML_SCHEMA_TYPE_NOTATION:
4086		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4087		    break;
4088		case XML_SCHEMA_EXTRA_QNAMEREF:
4089		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4090		    break;
4091		default: {
4092		    /* TODO: This should never be hit. */
4093		    xmlSchemaPSimpleInternalErr(NULL,
4094			"Internal error: xmlSchemaComponentListFree, "
4095			"unexpected component type '%s'\n",
4096			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4097			 }
4098		    break;
4099	    }
4100	}
4101	list->nbItems = 0;
4102    }
4103}
4104
4105/**
4106 * xmlSchemaFree:
4107 * @schema:  a schema structure
4108 *
4109 * Deallocate a Schema structure.
4110 */
4111void
4112xmlSchemaFree(xmlSchemaPtr schema)
4113{
4114    if (schema == NULL)
4115        return;
4116    /* @volatiles is not used anymore :-/ */
4117    if (schema->volatiles != NULL)
4118	TODO
4119    /*
4120    * Note that those slots are not responsible for freeing
4121    * schema components anymore; this will now be done by
4122    * the schema buckets.
4123    */
4124    if (schema->notaDecl != NULL)
4125        xmlHashFree(schema->notaDecl, NULL);
4126    if (schema->attrDecl != NULL)
4127        xmlHashFree(schema->attrDecl, NULL);
4128    if (schema->attrgrpDecl != NULL)
4129        xmlHashFree(schema->attrgrpDecl, NULL);
4130    if (schema->elemDecl != NULL)
4131        xmlHashFree(schema->elemDecl, NULL);
4132    if (schema->typeDecl != NULL)
4133        xmlHashFree(schema->typeDecl, NULL);
4134    if (schema->groupDecl != NULL)
4135        xmlHashFree(schema->groupDecl, NULL);
4136    if (schema->idcDef != NULL)
4137        xmlHashFree(schema->idcDef, NULL);
4138
4139    if (schema->schemasImports != NULL)
4140	xmlHashFree(schema->schemasImports,
4141		    (xmlHashDeallocator) xmlSchemaBucketFree);
4142    if (schema->includes != NULL) {
4143	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4144	int i;
4145	for (i = 0; i < list->nbItems; i++) {
4146	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4147	}
4148	xmlSchemaItemListFree(list);
4149    }
4150    if (schema->annot != NULL)
4151        xmlSchemaFreeAnnot(schema->annot);
4152    /* Never free the doc here, since this will be done by the buckets. */
4153
4154    xmlDictFree(schema->dict);
4155    xmlFree(schema);
4156}
4157
4158/************************************************************************
4159 *									*
4160 *			Debug functions					*
4161 *									*
4162 ************************************************************************/
4163
4164#ifdef LIBXML_OUTPUT_ENABLED
4165
4166static void
4167xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4168
4169/**
4170 * xmlSchemaElementDump:
4171 * @elem:  an element
4172 * @output:  the file output
4173 *
4174 * Dump the element
4175 */
4176static void
4177xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4178                     const xmlChar * name ATTRIBUTE_UNUSED,
4179		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4180                     const xmlChar * context ATTRIBUTE_UNUSED)
4181{
4182    if (elem == NULL)
4183        return;
4184
4185
4186    fprintf(output, "Element");
4187    if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4188	fprintf(output, " (global)");
4189    fprintf(output, ": '%s' ", elem->name);
4190    if (namespace != NULL)
4191	fprintf(output, "ns '%s'", namespace);
4192    fprintf(output, "\n");
4193#if 0
4194    if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4195	fprintf(output, "  min %d ", elem->minOccurs);
4196        if (elem->maxOccurs >= UNBOUNDED)
4197            fprintf(output, "max: unbounded\n");
4198        else if (elem->maxOccurs != 1)
4199            fprintf(output, "max: %d\n", elem->maxOccurs);
4200        else
4201            fprintf(output, "\n");
4202    }
4203#endif
4204    /*
4205    * Misc other properties.
4206    */
4207    if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4208	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4209	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4210	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4211	fprintf(output, "  props: ");
4212	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4213	    fprintf(output, "[fixed] ");
4214	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4215	    fprintf(output, "[default] ");
4216	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4217	    fprintf(output, "[abstract] ");
4218	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4219	    fprintf(output, "[nillable] ");
4220	fprintf(output, "\n");
4221    }
4222    /*
4223    * Default/fixed value.
4224    */
4225    if (elem->value != NULL)
4226	fprintf(output, "  value: '%s'\n", elem->value);
4227    /*
4228    * Type.
4229    */
4230    if (elem->namedType != NULL) {
4231	fprintf(output, "  type: '%s' ", elem->namedType);
4232	if (elem->namedTypeNs != NULL)
4233	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4234	else
4235	    fprintf(output, "\n");
4236    } else if (elem->subtypes != NULL) {
4237	/*
4238	* Dump local types.
4239	*/
4240	xmlSchemaTypeDump(elem->subtypes, output);
4241    }
4242    /*
4243    * Substitution group.
4244    */
4245    if (elem->substGroup != NULL) {
4246	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4247	if (elem->substGroupNs != NULL)
4248	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4249	else
4250	    fprintf(output, "\n");
4251    }
4252}
4253
4254/**
4255 * xmlSchemaAnnotDump:
4256 * @output:  the file output
4257 * @annot:  a annotation
4258 *
4259 * Dump the annotation
4260 */
4261static void
4262xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4263{
4264    xmlChar *content;
4265
4266    if (annot == NULL)
4267        return;
4268
4269    content = xmlNodeGetContent(annot->content);
4270    if (content != NULL) {
4271        fprintf(output, "  Annot: %s\n", content);
4272        xmlFree(content);
4273    } else
4274        fprintf(output, "  Annot: empty\n");
4275}
4276
4277/**
4278 * xmlSchemaContentModelDump:
4279 * @particle: the schema particle
4280 * @output: the file output
4281 * @depth: the depth used for intentation
4282 *
4283 * Dump a SchemaType structure
4284 */
4285static void
4286xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4287{
4288    xmlChar *str = NULL;
4289    xmlSchemaTreeItemPtr term;
4290    char shift[100];
4291    int i;
4292
4293    if (particle == NULL)
4294	return;
4295    for (i = 0;((i < depth) && (i < 25));i++)
4296        shift[2 * i] = shift[2 * i + 1] = ' ';
4297    shift[2 * i] = shift[2 * i + 1] = 0;
4298    fprintf(output, "%s", shift);
4299    if (particle->children == NULL) {
4300	fprintf(output, "MISSING particle term\n");
4301	return;
4302    }
4303    term = particle->children;
4304    if (term == NULL) {
4305	fprintf(output, "(NULL)");
4306    } else {
4307	switch (term->type) {
4308	    case XML_SCHEMA_TYPE_ELEMENT:
4309		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4310		    ((xmlSchemaElementPtr)term)->targetNamespace,
4311		    ((xmlSchemaElementPtr)term)->name));
4312		FREE_AND_NULL(str);
4313		break;
4314	    case XML_SCHEMA_TYPE_SEQUENCE:
4315		fprintf(output, "SEQUENCE");
4316		break;
4317	    case XML_SCHEMA_TYPE_CHOICE:
4318		fprintf(output, "CHOICE");
4319		break;
4320	    case XML_SCHEMA_TYPE_ALL:
4321		fprintf(output, "ALL");
4322		break;
4323	    case XML_SCHEMA_TYPE_ANY:
4324		fprintf(output, "ANY");
4325		break;
4326	    default:
4327		fprintf(output, "UNKNOWN\n");
4328		return;
4329	}
4330    }
4331    if (particle->minOccurs != 1)
4332	fprintf(output, " min: %d", particle->minOccurs);
4333    if (particle->maxOccurs >= UNBOUNDED)
4334	fprintf(output, " max: unbounded");
4335    else if (particle->maxOccurs != 1)
4336	fprintf(output, " max: %d", particle->maxOccurs);
4337    fprintf(output, "\n");
4338    if (term &&
4339	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4340	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4341	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4342	 (term->children != NULL)) {
4343	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4344	    output, depth +1);
4345    }
4346    if (particle->next != NULL)
4347	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4348		output, depth);
4349}
4350
4351/**
4352 * xmlSchemaAttrUsesDump:
4353 * @uses:  attribute uses list
4354 * @output:  the file output
4355 *
4356 * Dumps a list of attribute use components.
4357 */
4358static void
4359xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4360{
4361    xmlSchemaAttributeUsePtr use;
4362    xmlSchemaAttributeUseProhibPtr prohib;
4363    xmlSchemaQNameRefPtr ref;
4364    const xmlChar *name, *tns;
4365    xmlChar *str = NULL;
4366    int i;
4367
4368    if ((uses == NULL) || (uses->nbItems == 0))
4369        return;
4370
4371    fprintf(output, "  attributes:\n");
4372    for (i = 0; i < uses->nbItems; i++) {
4373	use = uses->items[i];
4374	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4375	    fprintf(output, "  [prohibition] ");
4376	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4377	    name = prohib->name;
4378	    tns = prohib->targetNamespace;
4379	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4380	    fprintf(output, "  [reference] ");
4381	    ref = (xmlSchemaQNameRefPtr) use;
4382	    name = ref->name;
4383	    tns = ref->targetNamespace;
4384	} else {
4385	    fprintf(output, "  [use] ");
4386	    name = WXS_ATTRUSE_DECL_NAME(use);
4387	    tns = WXS_ATTRUSE_DECL_TNS(use);
4388	}
4389	fprintf(output, "'%s'\n",
4390	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4391	FREE_AND_NULL(str);
4392    }
4393}
4394
4395/**
4396 * xmlSchemaTypeDump:
4397 * @output:  the file output
4398 * @type:  a type structure
4399 *
4400 * Dump a SchemaType structure
4401 */
4402static void
4403xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4404{
4405    if (type == NULL) {
4406        fprintf(output, "Type: NULL\n");
4407        return;
4408    }
4409    fprintf(output, "Type: ");
4410    if (type->name != NULL)
4411        fprintf(output, "'%s' ", type->name);
4412    else
4413        fprintf(output, "(no name) ");
4414    if (type->targetNamespace != NULL)
4415	fprintf(output, "ns '%s' ", type->targetNamespace);
4416    switch (type->type) {
4417        case XML_SCHEMA_TYPE_BASIC:
4418            fprintf(output, "[basic] ");
4419            break;
4420        case XML_SCHEMA_TYPE_SIMPLE:
4421            fprintf(output, "[simple] ");
4422            break;
4423        case XML_SCHEMA_TYPE_COMPLEX:
4424            fprintf(output, "[complex] ");
4425            break;
4426        case XML_SCHEMA_TYPE_SEQUENCE:
4427            fprintf(output, "[sequence] ");
4428            break;
4429        case XML_SCHEMA_TYPE_CHOICE:
4430            fprintf(output, "[choice] ");
4431            break;
4432        case XML_SCHEMA_TYPE_ALL:
4433            fprintf(output, "[all] ");
4434            break;
4435        case XML_SCHEMA_TYPE_UR:
4436            fprintf(output, "[ur] ");
4437            break;
4438        case XML_SCHEMA_TYPE_RESTRICTION:
4439            fprintf(output, "[restriction] ");
4440            break;
4441        case XML_SCHEMA_TYPE_EXTENSION:
4442            fprintf(output, "[extension] ");
4443            break;
4444        default:
4445            fprintf(output, "[unknown type %d] ", type->type);
4446            break;
4447    }
4448    fprintf(output, "content: ");
4449    switch (type->contentType) {
4450        case XML_SCHEMA_CONTENT_UNKNOWN:
4451            fprintf(output, "[unknown] ");
4452            break;
4453        case XML_SCHEMA_CONTENT_EMPTY:
4454            fprintf(output, "[empty] ");
4455            break;
4456        case XML_SCHEMA_CONTENT_ELEMENTS:
4457            fprintf(output, "[element] ");
4458            break;
4459        case XML_SCHEMA_CONTENT_MIXED:
4460            fprintf(output, "[mixed] ");
4461            break;
4462        case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4463	/* not used. */
4464            break;
4465        case XML_SCHEMA_CONTENT_BASIC:
4466            fprintf(output, "[basic] ");
4467            break;
4468        case XML_SCHEMA_CONTENT_SIMPLE:
4469            fprintf(output, "[simple] ");
4470            break;
4471        case XML_SCHEMA_CONTENT_ANY:
4472            fprintf(output, "[any] ");
4473            break;
4474    }
4475    fprintf(output, "\n");
4476    if (type->base != NULL) {
4477        fprintf(output, "  base type: '%s'", type->base);
4478	if (type->baseNs != NULL)
4479	    fprintf(output, " ns '%s'\n", type->baseNs);
4480	else
4481	    fprintf(output, "\n");
4482    }
4483    if (type->attrUses != NULL)
4484	xmlSchemaAttrUsesDump(type->attrUses, output);
4485    if (type->annot != NULL)
4486        xmlSchemaAnnotDump(output, type->annot);
4487#ifdef DUMP_CONTENT_MODEL
4488    if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4489	(type->subtypes != NULL)) {
4490	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4491	    output, 1);
4492    }
4493#endif
4494}
4495
4496/**
4497 * xmlSchemaDump:
4498 * @output:  the file output
4499 * @schema:  a schema structure
4500 *
4501 * Dump a Schema structure.
4502 */
4503void
4504xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4505{
4506    if (output == NULL)
4507        return;
4508    if (schema == NULL) {
4509        fprintf(output, "Schemas: NULL\n");
4510        return;
4511    }
4512    fprintf(output, "Schemas: ");
4513    if (schema->name != NULL)
4514        fprintf(output, "%s, ", schema->name);
4515    else
4516        fprintf(output, "no name, ");
4517    if (schema->targetNamespace != NULL)
4518        fprintf(output, "%s", (const char *) schema->targetNamespace);
4519    else
4520        fprintf(output, "no target namespace");
4521    fprintf(output, "\n");
4522    if (schema->annot != NULL)
4523        xmlSchemaAnnotDump(output, schema->annot);
4524    xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4525                output);
4526    xmlHashScanFull(schema->elemDecl,
4527                    (xmlHashScannerFull) xmlSchemaElementDump, output);
4528}
4529
4530#ifdef DEBUG_IDC_NODE_TABLE
4531/**
4532 * xmlSchemaDebugDumpIDCTable:
4533 * @vctxt: the WXS validation context
4534 *
4535 * Displays the current IDC table for debug purposes.
4536 */
4537static void
4538xmlSchemaDebugDumpIDCTable(FILE * output,
4539			   const xmlChar *namespaceName,
4540			   const xmlChar *localName,
4541			   xmlSchemaPSVIIDCBindingPtr bind)
4542{
4543    xmlChar *str = NULL;
4544    const xmlChar *value;
4545    xmlSchemaPSVIIDCNodePtr tab;
4546    xmlSchemaPSVIIDCKeyPtr key;
4547    int i, j, res;
4548
4549    fprintf(output, "IDC: TABLES on '%s'\n",
4550	xmlSchemaFormatQName(&str, namespaceName, localName));
4551    FREE_AND_NULL(str)
4552
4553    if (bind == NULL)
4554	return;
4555    do {
4556	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4557	    xmlSchemaGetComponentQName(&str,
4558		bind->definition), bind->nbNodes);
4559	FREE_AND_NULL(str)
4560	for (i = 0; i < bind->nbNodes; i++) {
4561	    tab = bind->nodeTable[i];
4562	    fprintf(output, "         ( ");
4563	    for (j = 0; j < bind->definition->nbFields; j++) {
4564		key = tab->keys[j];
4565		if ((key != NULL) && (key->val != NULL)) {
4566		    res = xmlSchemaGetCanonValue(key->val, &value);
4567		    if (res >= 0)
4568			fprintf(output, "'%s' ", value);
4569		    else
4570			fprintf(output, "CANON-VALUE-FAILED ");
4571		    if (res == 0)
4572			FREE_AND_NULL(value)
4573		} else if (key != NULL)
4574		    fprintf(output, "(no val), ");
4575		else
4576		    fprintf(output, "(key missing), ");
4577	    }
4578	    fprintf(output, ")\n");
4579	}
4580	if (bind->dupls && bind->dupls->nbItems) {
4581	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4582	    for (i = 0; i < bind->dupls->nbItems; i++) {
4583		tab = bind->dupls->items[i];
4584		fprintf(output, "         ( ");
4585		for (j = 0; j < bind->definition->nbFields; j++) {
4586		    key = tab->keys[j];
4587		    if ((key != NULL) && (key->val != NULL)) {
4588			res = xmlSchemaGetCanonValue(key->val, &value);
4589			if (res >= 0)
4590			    fprintf(output, "'%s' ", value);
4591			else
4592			    fprintf(output, "CANON-VALUE-FAILED ");
4593			if (res == 0)
4594			    FREE_AND_NULL(value)
4595		    } else if (key != NULL)
4596		    fprintf(output, "(no val), ");
4597			else
4598			    fprintf(output, "(key missing), ");
4599		}
4600		fprintf(output, ")\n");
4601	    }
4602	}
4603	bind = bind->next;
4604    } while (bind != NULL);
4605}
4606#endif /* DEBUG_IDC */
4607#endif /* LIBXML_OUTPUT_ENABLED */
4608
4609/************************************************************************
4610 *									*
4611 *			Utilities					*
4612 *									*
4613 ************************************************************************/
4614
4615/**
4616 * xmlSchemaGetPropNode:
4617 * @node: the element node
4618 * @name: the name of the attribute
4619 *
4620 * Seeks an attribute with a name of @name in
4621 * no namespace.
4622 *
4623 * Returns the attribute or NULL if not present.
4624 */
4625static xmlAttrPtr
4626xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4627{
4628    xmlAttrPtr prop;
4629
4630    if ((node == NULL) || (name == NULL))
4631	return(NULL);
4632    prop = node->properties;
4633    while (prop != NULL) {
4634        if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4635	    return(prop);
4636	prop = prop->next;
4637    }
4638    return (NULL);
4639}
4640
4641/**
4642 * xmlSchemaGetPropNodeNs:
4643 * @node: the element node
4644 * @uri: the uri
4645 * @name: the name of the attribute
4646 *
4647 * Seeks an attribute with a local name of @name and
4648 * a namespace URI of @uri.
4649 *
4650 * Returns the attribute or NULL if not present.
4651 */
4652static xmlAttrPtr
4653xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4654{
4655    xmlAttrPtr prop;
4656
4657    if ((node == NULL) || (name == NULL))
4658	return(NULL);
4659    prop = node->properties;
4660    while (prop != NULL) {
4661	if ((prop->ns != NULL) &&
4662	    xmlStrEqual(prop->name, BAD_CAST name) &&
4663	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4664	    return(prop);
4665	prop = prop->next;
4666    }
4667    return (NULL);
4668}
4669
4670static const xmlChar *
4671xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4672{
4673    xmlChar *val;
4674    const xmlChar *ret;
4675
4676    val = xmlNodeGetContent(node);
4677    if (val == NULL)
4678	val = xmlStrdup((xmlChar *)"");
4679    ret = xmlDictLookup(ctxt->dict, val, -1);
4680    xmlFree(val);
4681    return(ret);
4682}
4683
4684static const xmlChar *
4685xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4686{
4687    return((const xmlChar*) xmlNodeGetContent(node));
4688}
4689
4690/**
4691 * xmlSchemaGetProp:
4692 * @ctxt: the parser context
4693 * @node: the node
4694 * @name: the property name
4695 *
4696 * Read a attribute value and internalize the string
4697 *
4698 * Returns the string or NULL if not present.
4699 */
4700static const xmlChar *
4701xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4702                 const char *name)
4703{
4704    xmlChar *val;
4705    const xmlChar *ret;
4706
4707    val = xmlGetNoNsProp(node, BAD_CAST name);
4708    if (val == NULL)
4709        return(NULL);
4710    ret = xmlDictLookup(ctxt->dict, val, -1);
4711    xmlFree(val);
4712    return(ret);
4713}
4714
4715/************************************************************************
4716 *									*
4717 *			Parsing functions				*
4718 *									*
4719 ************************************************************************/
4720
4721#define WXS_FIND_GLOBAL_ITEM(slot)			\
4722    if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4723	ret = xmlHashLookup(schema->slot, name); \
4724	if (ret != NULL) goto exit; \
4725    } \
4726    if (xmlHashSize(schema->schemasImports) > 1) { \
4727	xmlSchemaImportPtr import; \
4728	if (nsName == NULL) \
4729	    import = xmlHashLookup(schema->schemasImports, \
4730		XML_SCHEMAS_NO_NAMESPACE); \
4731	else \
4732	    import = xmlHashLookup(schema->schemasImports, nsName); \
4733	if (import == NULL) \
4734	    goto exit; \
4735	ret = xmlHashLookup(import->schema->slot, name); \
4736    }
4737
4738/**
4739 * xmlSchemaGetElem:
4740 * @schema:  the schema context
4741 * @name:  the element name
4742 * @ns:  the element namespace
4743 *
4744 * Lookup a global element declaration in the schema.
4745 *
4746 * Returns the element declaration or NULL if not found.
4747 */
4748static xmlSchemaElementPtr
4749xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4750                 const xmlChar * nsName)
4751{
4752    xmlSchemaElementPtr ret = NULL;
4753
4754    if ((name == NULL) || (schema == NULL))
4755        return(NULL);
4756    if (schema != NULL) {
4757	WXS_FIND_GLOBAL_ITEM(elemDecl)
4758    }
4759exit:
4760#ifdef DEBUG
4761    if (ret == NULL) {
4762        if (nsName == NULL)
4763            fprintf(stderr, "Unable to lookup element decl. %s", name);
4764        else
4765            fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4766                    nsName);
4767    }
4768#endif
4769    return (ret);
4770}
4771
4772/**
4773 * xmlSchemaGetType:
4774 * @schema:  the main schema
4775 * @name:  the type's name
4776 * nsName:  the type's namespace
4777 *
4778 * Lookup a type in the schemas or the predefined types
4779 *
4780 * Returns the group definition or NULL if not found.
4781 */
4782static xmlSchemaTypePtr
4783xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4784                 const xmlChar * nsName)
4785{
4786    xmlSchemaTypePtr ret = NULL;
4787
4788    if (name == NULL)
4789        return (NULL);
4790    /* First try the built-in types. */
4791    if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4792	ret = xmlSchemaGetPredefinedType(name, nsName);
4793	if (ret != NULL)
4794	    goto exit;
4795	/*
4796	* Note that we try the parsed schemas as well here
4797	* since one might have parsed the S4S, which contain more
4798	* than the built-in types.
4799	* TODO: Can we optimize this?
4800	*/
4801    }
4802    if (schema != NULL) {
4803	WXS_FIND_GLOBAL_ITEM(typeDecl)
4804    }
4805exit:
4806
4807#ifdef DEBUG
4808    if (ret == NULL) {
4809        if (nsName == NULL)
4810            fprintf(stderr, "Unable to lookup type %s", name);
4811        else
4812            fprintf(stderr, "Unable to lookup type %s:%s", name,
4813                    nsName);
4814    }
4815#endif
4816    return (ret);
4817}
4818
4819/**
4820 * xmlSchemaGetAttributeDecl:
4821 * @schema:  the context of the schema
4822 * @name:  the name of the attribute
4823 * @ns:  the target namespace of the attribute
4824 *
4825 * Lookup a an attribute in the schema or imported schemas
4826 *
4827 * Returns the attribute declaration or NULL if not found.
4828 */
4829static xmlSchemaAttributePtr
4830xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4831                 const xmlChar * nsName)
4832{
4833    xmlSchemaAttributePtr ret = NULL;
4834
4835    if ((name == NULL) || (schema == NULL))
4836        return (NULL);
4837    if (schema != NULL) {
4838	WXS_FIND_GLOBAL_ITEM(attrDecl)
4839    }
4840exit:
4841#ifdef DEBUG
4842    if (ret == NULL) {
4843        if (nsName == NULL)
4844            fprintf(stderr, "Unable to lookup attribute %s", name);
4845        else
4846            fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4847                    nsName);
4848    }
4849#endif
4850    return (ret);
4851}
4852
4853/**
4854 * xmlSchemaGetAttributeGroup:
4855 * @schema:  the context of the schema
4856 * @name:  the name of the attribute group
4857 * @ns:  the target namespace of the attribute group
4858 *
4859 * Lookup a an attribute group in the schema or imported schemas
4860 *
4861 * Returns the attribute group definition or NULL if not found.
4862 */
4863static xmlSchemaAttributeGroupPtr
4864xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4865                 const xmlChar * nsName)
4866{
4867    xmlSchemaAttributeGroupPtr ret = NULL;
4868
4869    if ((name == NULL) || (schema == NULL))
4870        return (NULL);
4871    if (schema != NULL) {
4872	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4873    }
4874exit:
4875    /* TODO:
4876    if ((ret != NULL) && (ret->redef != NULL)) {
4877	* Return the last redefinition. *
4878	ret = ret->redef;
4879    }
4880    */
4881#ifdef DEBUG
4882    if (ret == NULL) {
4883        if (nsName == NULL)
4884            fprintf(stderr, "Unable to lookup attribute group %s", name);
4885        else
4886            fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4887                    nsName);
4888    }
4889#endif
4890    return (ret);
4891}
4892
4893/**
4894 * xmlSchemaGetGroup:
4895 * @schema:  the context of the schema
4896 * @name:  the name of the group
4897 * @ns:  the target namespace of the group
4898 *
4899 * Lookup a group in the schema or imported schemas
4900 *
4901 * Returns the group definition or NULL if not found.
4902 */
4903static xmlSchemaModelGroupDefPtr
4904xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4905                 const xmlChar * nsName)
4906{
4907    xmlSchemaModelGroupDefPtr ret = NULL;
4908
4909    if ((name == NULL) || (schema == NULL))
4910        return (NULL);
4911    if (schema != NULL) {
4912	WXS_FIND_GLOBAL_ITEM(groupDecl)
4913    }
4914exit:
4915
4916#ifdef DEBUG
4917    if (ret == NULL) {
4918        if (nsName == NULL)
4919            fprintf(stderr, "Unable to lookup group %s", name);
4920        else
4921            fprintf(stderr, "Unable to lookup group %s:%s", name,
4922                    nsName);
4923    }
4924#endif
4925    return (ret);
4926}
4927
4928static xmlSchemaNotationPtr
4929xmlSchemaGetNotation(xmlSchemaPtr schema,
4930		     const xmlChar *name,
4931		     const xmlChar *nsName)
4932{
4933    xmlSchemaNotationPtr ret = NULL;
4934
4935    if ((name == NULL) || (schema == NULL))
4936        return (NULL);
4937    if (schema != NULL) {
4938	WXS_FIND_GLOBAL_ITEM(notaDecl)
4939    }
4940exit:
4941    return (ret);
4942}
4943
4944static xmlSchemaIDCPtr
4945xmlSchemaGetIDC(xmlSchemaPtr schema,
4946		const xmlChar *name,
4947		const xmlChar *nsName)
4948{
4949    xmlSchemaIDCPtr ret = NULL;
4950
4951    if ((name == NULL) || (schema == NULL))
4952        return (NULL);
4953    if (schema != NULL) {
4954	WXS_FIND_GLOBAL_ITEM(idcDef)
4955    }
4956exit:
4957    return (ret);
4958}
4959
4960/**
4961 * xmlSchemaGetNamedComponent:
4962 * @schema:  the schema
4963 * @name:  the name of the group
4964 * @ns:  the target namespace of the group
4965 *
4966 * Lookup a group in the schema or imported schemas
4967 *
4968 * Returns the group definition or NULL if not found.
4969 */
4970static xmlSchemaBasicItemPtr
4971xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4972			   xmlSchemaTypeType itemType,
4973			   const xmlChar *name,
4974			   const xmlChar *targetNs)
4975{
4976    switch (itemType) {
4977	case XML_SCHEMA_TYPE_GROUP:
4978	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4979		name, targetNs));
4980	case XML_SCHEMA_TYPE_ELEMENT:
4981	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4982		name, targetNs));
4983	default:
4984	    TODO
4985	    return (NULL);
4986    }
4987}
4988
4989/************************************************************************
4990 *									*
4991 *			Parsing functions				*
4992 *									*
4993 ************************************************************************/
4994
4995#define IS_BLANK_NODE(n)						\
4996    (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4997
4998/**
4999 * xmlSchemaIsBlank:
5000 * @str:  a string
5001 * @len: the length of the string or -1
5002 *
5003 * Check if a string is ignorable
5004 *
5005 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5006 */
5007static int
5008xmlSchemaIsBlank(xmlChar * str, int len)
5009{
5010    if (str == NULL)
5011        return (1);
5012    if (len < 0) {
5013	while (*str != 0) {
5014	    if (!(IS_BLANK_CH(*str)))
5015		return (0);
5016	    str++;
5017	}
5018    } else while ((*str != 0) && (len != 0)) {
5019	if (!(IS_BLANK_CH(*str)))
5020	    return (0);
5021	str++;
5022	len--;
5023    }
5024
5025    return (1);
5026}
5027
5028#define WXS_COMP_NAME(c, t) ((t) (c))->name
5029#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5030/*
5031* xmlSchemaFindRedefCompInGraph:
5032* ATTENTION TODO: This uses pointer comp. for strings.
5033*/
5034static xmlSchemaBasicItemPtr
5035xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5036			      xmlSchemaTypeType type,
5037			      const xmlChar *name,
5038			      const xmlChar *nsName)
5039{
5040    xmlSchemaBasicItemPtr ret;
5041    int i;
5042
5043    if ((bucket == NULL) || (name == NULL))
5044	return(NULL);
5045    if ((bucket->globals == NULL) ||
5046	(bucket->globals->nbItems == 0))
5047	goto subschemas;
5048    /*
5049    * Search in global components.
5050    */
5051    for (i = 0; i < bucket->globals->nbItems; i++) {
5052	ret = bucket->globals->items[i];
5053	if (ret->type == type) {
5054	    switch (type) {
5055		case XML_SCHEMA_TYPE_COMPLEX:
5056		case XML_SCHEMA_TYPE_SIMPLE:
5057		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5058			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5059			nsName))
5060		    {
5061			return(ret);
5062		    }
5063		    break;
5064		case XML_SCHEMA_TYPE_GROUP:
5065		    if ((WXS_COMP_NAME(ret,
5066			    xmlSchemaModelGroupDefPtr) == name) &&
5067			(WXS_COMP_TNS(ret,
5068			    xmlSchemaModelGroupDefPtr) == nsName))
5069		    {
5070			return(ret);
5071		    }
5072		    break;
5073		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5074		    if ((WXS_COMP_NAME(ret,
5075			    xmlSchemaAttributeGroupPtr) == name) &&
5076			(WXS_COMP_TNS(ret,
5077			    xmlSchemaAttributeGroupPtr) == nsName))
5078		    {
5079			return(ret);
5080		    }
5081		    break;
5082		default:
5083		    /* Should not be hit. */
5084		    return(NULL);
5085	    }
5086	}
5087    }
5088subschemas:
5089    /*
5090    * Process imported/included schemas.
5091    */
5092    if (bucket->relations != NULL) {
5093	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5094
5095	/*
5096	* TODO: Marking the bucket will not avoid multiple searches
5097	* in the same schema, but avoids at least circularity.
5098	*/
5099	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5100	do {
5101	    if ((rel->bucket != NULL) &&
5102		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5103		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5104		    type, name, nsName);
5105		if (ret != NULL)
5106		    return(ret);
5107	    }
5108	    rel = rel->next;
5109	} while (rel != NULL);
5110	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5111    }
5112    return(NULL);
5113}
5114
5115/**
5116 * xmlSchemaAddNotation:
5117 * @ctxt:  a schema parser context
5118 * @schema:  the schema being built
5119 * @name:  the item name
5120 *
5121 * Add an XML schema annotation declaration
5122 * *WARNING* this interface is highly subject to change
5123 *
5124 * Returns the new struture or NULL in case of error
5125 */
5126static xmlSchemaNotationPtr
5127xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5128                     const xmlChar *name, const xmlChar *nsName,
5129		     xmlNodePtr node ATTRIBUTE_UNUSED)
5130{
5131    xmlSchemaNotationPtr ret = NULL;
5132
5133    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5134        return (NULL);
5135
5136    ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5137    if (ret == NULL) {
5138        xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5139        return (NULL);
5140    }
5141    memset(ret, 0, sizeof(xmlSchemaNotation));
5142    ret->type = XML_SCHEMA_TYPE_NOTATION;
5143    ret->name = name;
5144    ret->targetNamespace = nsName;
5145    /* TODO: do we need the node to be set?
5146    * ret->node = node;*/
5147    WXS_ADD_GLOBAL(ctxt, ret);
5148    return (ret);
5149}
5150
5151/**
5152 * xmlSchemaAddAttribute:
5153 * @ctxt:  a schema parser context
5154 * @schema:  the schema being built
5155 * @name:  the item name
5156 * @namespace:  the namespace
5157 *
5158 * Add an XML schema Attrribute declaration
5159 * *WARNING* this interface is highly subject to change
5160 *
5161 * Returns the new struture or NULL in case of error
5162 */
5163static xmlSchemaAttributePtr
5164xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5165                      const xmlChar * name, const xmlChar * nsName,
5166		      xmlNodePtr node, int topLevel)
5167{
5168    xmlSchemaAttributePtr ret = NULL;
5169
5170    if ((ctxt == NULL) || (schema == NULL))
5171        return (NULL);
5172
5173    ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5174    if (ret == NULL) {
5175        xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5176        return (NULL);
5177    }
5178    memset(ret, 0, sizeof(xmlSchemaAttribute));
5179    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5180    ret->node = node;
5181    ret->name = name;
5182    ret->targetNamespace = nsName;
5183
5184    if (topLevel)
5185	WXS_ADD_GLOBAL(ctxt, ret);
5186    else
5187	WXS_ADD_LOCAL(ctxt, ret);
5188    WXS_ADD_PENDING(ctxt, ret);
5189    return (ret);
5190}
5191
5192/**
5193 * xmlSchemaAddAttributeUse:
5194 * @ctxt:  a schema parser context
5195 * @schema:  the schema being built
5196 * @name:  the item name
5197 * @namespace:  the namespace
5198 *
5199 * Add an XML schema Attrribute declaration
5200 * *WARNING* this interface is highly subject to change
5201 *
5202 * Returns the new struture or NULL in case of error
5203 */
5204static xmlSchemaAttributeUsePtr
5205xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5206			 xmlNodePtr node)
5207{
5208    xmlSchemaAttributeUsePtr ret = NULL;
5209
5210    if (pctxt == NULL)
5211        return (NULL);
5212
5213    ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5214    if (ret == NULL) {
5215        xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5216        return (NULL);
5217    }
5218    memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5219    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5220    ret->node = node;
5221
5222    WXS_ADD_LOCAL(pctxt, ret);
5223    return (ret);
5224}
5225
5226/*
5227* xmlSchemaAddRedef:
5228*
5229* Adds a redefinition information. This is used at a later stage to:
5230* resolve references to the redefined components and to check constraints.
5231*/
5232static xmlSchemaRedefPtr
5233xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5234		  xmlSchemaBucketPtr targetBucket,
5235		  void *item,
5236		  const xmlChar *refName,
5237		  const xmlChar *refTargetNs)
5238{
5239    xmlSchemaRedefPtr ret;
5240
5241    ret = (xmlSchemaRedefPtr)
5242	xmlMalloc(sizeof(xmlSchemaRedef));
5243    if (ret == NULL) {
5244	xmlSchemaPErrMemory(pctxt,
5245	    "allocating redefinition info", NULL);
5246	return (NULL);
5247    }
5248    memset(ret, 0, sizeof(xmlSchemaRedef));
5249    ret->item = item;
5250    ret->targetBucket = targetBucket;
5251    ret->refName = refName;
5252    ret->refTargetNs = refTargetNs;
5253    if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5254	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5255    else
5256	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5257    WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5258
5259    return (ret);
5260}
5261
5262/**
5263 * xmlSchemaAddAttributeGroupDefinition:
5264 * @ctxt:  a schema parser context
5265 * @schema:  the schema being built
5266 * @name:  the item name
5267 * @nsName:  the target namespace
5268 * @node: the corresponding node
5269 *
5270 * Add an XML schema Attrribute Group definition.
5271 *
5272 * Returns the new struture or NULL in case of error
5273 */
5274static xmlSchemaAttributeGroupPtr
5275xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5276                           xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5277			   const xmlChar *name,
5278			   const xmlChar *nsName,
5279			   xmlNodePtr node)
5280{
5281    xmlSchemaAttributeGroupPtr ret = NULL;
5282
5283    if ((pctxt == NULL) || (name == NULL))
5284        return (NULL);
5285
5286    ret = (xmlSchemaAttributeGroupPtr)
5287        xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5288    if (ret == NULL) {
5289	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5290	return (NULL);
5291    }
5292    memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5293    ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5294    ret->name = name;
5295    ret->targetNamespace = nsName;
5296    ret->node = node;
5297
5298    /* TODO: Remove the flag. */
5299    ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5300    if (pctxt->isRedefine) {
5301	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5302	    ret, name, nsName);
5303	if (pctxt->redef == NULL) {
5304	    xmlFree(ret);
5305	    return(NULL);
5306	}
5307	pctxt->redefCounter = 0;
5308    }
5309    WXS_ADD_GLOBAL(pctxt, ret);
5310    WXS_ADD_PENDING(pctxt, ret);
5311    return (ret);
5312}
5313
5314/**
5315 * xmlSchemaAddElement:
5316 * @ctxt:  a schema parser context
5317 * @schema:  the schema being built
5318 * @name:  the type name
5319 * @namespace:  the type namespace
5320 *
5321 * Add an XML schema Element declaration
5322 * *WARNING* this interface is highly subject to change
5323 *
5324 * Returns the new struture or NULL in case of error
5325 */
5326static xmlSchemaElementPtr
5327xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5328                    const xmlChar * name, const xmlChar * nsName,
5329		    xmlNodePtr node, int topLevel)
5330{
5331    xmlSchemaElementPtr ret = NULL;
5332
5333    if ((ctxt == NULL) || (name == NULL))
5334        return (NULL);
5335
5336    ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5337    if (ret == NULL) {
5338        xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5339        return (NULL);
5340    }
5341    memset(ret, 0, sizeof(xmlSchemaElement));
5342    ret->type = XML_SCHEMA_TYPE_ELEMENT;
5343    ret->name = name;
5344    ret->targetNamespace = nsName;
5345    ret->node = node;
5346
5347    if (topLevel)
5348	WXS_ADD_GLOBAL(ctxt, ret);
5349    else
5350	WXS_ADD_LOCAL(ctxt, ret);
5351    WXS_ADD_PENDING(ctxt, ret);
5352    return (ret);
5353}
5354
5355/**
5356 * xmlSchemaAddType:
5357 * @ctxt:  a schema parser context
5358 * @schema:  the schema being built
5359 * @name:  the item name
5360 * @namespace:  the namespace
5361 *
5362 * Add an XML schema item
5363 * *WARNING* this interface is highly subject to change
5364 *
5365 * Returns the new struture or NULL in case of error
5366 */
5367static xmlSchemaTypePtr
5368xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5369		 xmlSchemaTypeType type,
5370                 const xmlChar * name, const xmlChar * nsName,
5371		 xmlNodePtr node, int topLevel)
5372{
5373    xmlSchemaTypePtr ret = NULL;
5374
5375    if ((ctxt == NULL) || (schema == NULL))
5376        return (NULL);
5377
5378    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5379    if (ret == NULL) {
5380        xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5381        return (NULL);
5382    }
5383    memset(ret, 0, sizeof(xmlSchemaType));
5384    ret->type = type;
5385    ret->name = name;
5386    ret->targetNamespace = nsName;
5387    ret->node = node;
5388    if (topLevel) {
5389	if (ctxt->isRedefine) {
5390	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5391		ret, name, nsName);
5392	    if (ctxt->redef == NULL) {
5393		xmlFree(ret);
5394		return(NULL);
5395	    }
5396	    ctxt->redefCounter = 0;
5397	}
5398	WXS_ADD_GLOBAL(ctxt, ret);
5399    } else
5400	WXS_ADD_LOCAL(ctxt, ret);
5401    WXS_ADD_PENDING(ctxt, ret);
5402    return (ret);
5403}
5404
5405static xmlSchemaQNameRefPtr
5406xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5407		     xmlSchemaTypeType refType,
5408		     const xmlChar *refName,
5409		     const xmlChar *refNs)
5410{
5411    xmlSchemaQNameRefPtr ret;
5412
5413    ret = (xmlSchemaQNameRefPtr)
5414	xmlMalloc(sizeof(xmlSchemaQNameRef));
5415    if (ret == NULL) {
5416	xmlSchemaPErrMemory(pctxt,
5417	    "allocating QName reference item", NULL);
5418	return (NULL);
5419    }
5420    ret->node = NULL;
5421    ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5422    ret->name = refName;
5423    ret->targetNamespace = refNs;
5424    ret->item = NULL;
5425    ret->itemType = refType;
5426    /*
5427    * Store the reference item in the schema.
5428    */
5429    WXS_ADD_LOCAL(pctxt, ret);
5430    return (ret);
5431}
5432
5433static xmlSchemaAttributeUseProhibPtr
5434xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5435{
5436    xmlSchemaAttributeUseProhibPtr ret;
5437
5438    ret = (xmlSchemaAttributeUseProhibPtr)
5439	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5440    if (ret == NULL) {
5441	xmlSchemaPErrMemory(pctxt,
5442	    "allocating attribute use prohibition", NULL);
5443	return (NULL);
5444    }
5445    memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5446    ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5447    WXS_ADD_LOCAL(pctxt, ret);
5448    return (ret);
5449}
5450
5451
5452/**
5453 * xmlSchemaAddModelGroup:
5454 * @ctxt:  a schema parser context
5455 * @schema:  the schema being built
5456 * @type: the "compositor" type of the model group
5457 * @node: the node in the schema doc
5458 *
5459 * Adds a schema model group
5460 * *WARNING* this interface is highly subject to change
5461 *
5462 * Returns the new struture or NULL in case of error
5463 */
5464static xmlSchemaModelGroupPtr
5465xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5466		       xmlSchemaPtr schema,
5467		       xmlSchemaTypeType type,
5468		       xmlNodePtr node)
5469{
5470    xmlSchemaModelGroupPtr ret = NULL;
5471
5472    if ((ctxt == NULL) || (schema == NULL))
5473        return (NULL);
5474
5475    ret = (xmlSchemaModelGroupPtr)
5476	xmlMalloc(sizeof(xmlSchemaModelGroup));
5477    if (ret == NULL) {
5478	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5479	    NULL);
5480	return (NULL);
5481    }
5482    memset(ret, 0, sizeof(xmlSchemaModelGroup));
5483    ret->type = type;
5484    ret->node = node;
5485    WXS_ADD_LOCAL(ctxt, ret);
5486    if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5487	(type == XML_SCHEMA_TYPE_CHOICE))
5488	WXS_ADD_PENDING(ctxt, ret);
5489    return (ret);
5490}
5491
5492
5493/**
5494 * xmlSchemaAddParticle:
5495 * @ctxt:  a schema parser context
5496 * @schema:  the schema being built
5497 * @node: the corresponding node in the schema doc
5498 * @min: the minOccurs
5499 * @max: the maxOccurs
5500 *
5501 * Adds an XML schema particle component.
5502 * *WARNING* this interface is highly subject to change
5503 *
5504 * Returns the new struture or NULL in case of error
5505 */
5506static xmlSchemaParticlePtr
5507xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5508		     xmlNodePtr node, int min, int max)
5509{
5510    xmlSchemaParticlePtr ret = NULL;
5511    if (ctxt == NULL)
5512        return (NULL);
5513
5514#ifdef DEBUG
5515    fprintf(stderr, "Adding particle component\n");
5516#endif
5517    ret = (xmlSchemaParticlePtr)
5518	xmlMalloc(sizeof(xmlSchemaParticle));
5519    if (ret == NULL) {
5520	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5521	    NULL);
5522	return (NULL);
5523    }
5524    ret->type = XML_SCHEMA_TYPE_PARTICLE;
5525    ret->annot = NULL;
5526    ret->node = node;
5527    ret->minOccurs = min;
5528    ret->maxOccurs = max;
5529    ret->next = NULL;
5530    ret->children = NULL;
5531
5532    WXS_ADD_LOCAL(ctxt, ret);
5533    /*
5534    * Note that addition to pending components will be done locally
5535    * to the specific parsing function, since the most particles
5536    * need not to be fixed up (i.e. the reference to be resolved).
5537    * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5538    */
5539    return (ret);
5540}
5541
5542/**
5543 * xmlSchemaAddModelGroupDefinition:
5544 * @ctxt:  a schema validation context
5545 * @schema:  the schema being built
5546 * @name:  the group name
5547 *
5548 * Add an XML schema Group definition
5549 *
5550 * Returns the new struture or NULL in case of error
5551 */
5552static xmlSchemaModelGroupDefPtr
5553xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5554				 xmlSchemaPtr schema,
5555				 const xmlChar *name,
5556				 const xmlChar *nsName,
5557				 xmlNodePtr node)
5558{
5559    xmlSchemaModelGroupDefPtr ret = NULL;
5560
5561    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5562        return (NULL);
5563
5564    ret = (xmlSchemaModelGroupDefPtr)
5565	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5566    if (ret == NULL) {
5567        xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5568        return (NULL);
5569    }
5570    memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5571    ret->name = name;
5572    ret->type = XML_SCHEMA_TYPE_GROUP;
5573    ret->node = node;
5574    ret->targetNamespace = nsName;
5575
5576    if (ctxt->isRedefine) {
5577	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5578	    ret, name, nsName);
5579	if (ctxt->redef == NULL) {
5580	    xmlFree(ret);
5581	    return(NULL);
5582	}
5583	ctxt->redefCounter = 0;
5584    }
5585    WXS_ADD_GLOBAL(ctxt, ret);
5586    WXS_ADD_PENDING(ctxt, ret);
5587    return (ret);
5588}
5589
5590/**
5591 * xmlSchemaNewWildcardNs:
5592 * @ctxt:  a schema validation context
5593 *
5594 * Creates a new wildcard namespace constraint.
5595 *
5596 * Returns the new struture or NULL in case of error
5597 */
5598static xmlSchemaWildcardNsPtr
5599xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5600{
5601    xmlSchemaWildcardNsPtr ret;
5602
5603    ret = (xmlSchemaWildcardNsPtr)
5604	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5605    if (ret == NULL) {
5606	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5607	return (NULL);
5608    }
5609    ret->value = NULL;
5610    ret->next = NULL;
5611    return (ret);
5612}
5613
5614static xmlSchemaIDCPtr
5615xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5616                  const xmlChar *name, const xmlChar *nsName,
5617		  int category, xmlNodePtr node)
5618{
5619    xmlSchemaIDCPtr ret = NULL;
5620
5621    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5622        return (NULL);
5623
5624    ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5625    if (ret == NULL) {
5626        xmlSchemaPErrMemory(ctxt,
5627	    "allocating an identity-constraint definition", NULL);
5628        return (NULL);
5629    }
5630    memset(ret, 0, sizeof(xmlSchemaIDC));
5631    /* The target namespace of the parent element declaration. */
5632    ret->targetNamespace = nsName;
5633    ret->name = name;
5634    ret->type = category;
5635    ret->node = node;
5636
5637    WXS_ADD_GLOBAL(ctxt, ret);
5638    /*
5639    * Only keyrefs need to be fixup up.
5640    */
5641    if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5642	WXS_ADD_PENDING(ctxt, ret);
5643    return (ret);
5644}
5645
5646/**
5647 * xmlSchemaAddWildcard:
5648 * @ctxt:  a schema validation context
5649 * @schema: a schema
5650 *
5651 * Adds a wildcard.
5652 * It corresponds to a xsd:anyAttribute and xsd:any.
5653 *
5654 * Returns the new struture or NULL in case of error
5655 */
5656static xmlSchemaWildcardPtr
5657xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5658		     xmlSchemaTypeType type, xmlNodePtr node)
5659{
5660    xmlSchemaWildcardPtr ret = NULL;
5661
5662    if ((ctxt == NULL) || (schema == NULL))
5663        return (NULL);
5664
5665    ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5666    if (ret == NULL) {
5667        xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5668        return (NULL);
5669    }
5670    memset(ret, 0, sizeof(xmlSchemaWildcard));
5671    ret->type = type;
5672    ret->node = node;
5673    WXS_ADD_LOCAL(ctxt, ret);
5674    return (ret);
5675}
5676
5677static void
5678xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5679{
5680    if (group == NULL)
5681	return;
5682    if (group->members != NULL)
5683	xmlSchemaItemListFree(group->members);
5684    xmlFree(group);
5685}
5686
5687static xmlSchemaSubstGroupPtr
5688xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5689		       xmlSchemaElementPtr head)
5690{
5691    xmlSchemaSubstGroupPtr ret;
5692
5693    /* Init subst group hash. */
5694    if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5695	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5696	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5697	    return(NULL);
5698    }
5699    /* Create a new substitution group. */
5700    ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5701    if (ret == NULL) {
5702	xmlSchemaPErrMemory(NULL,
5703	    "allocating a substitution group container", NULL);
5704	return(NULL);
5705    }
5706    memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5707    ret->head = head;
5708    /* Create list of members. */
5709    ret->members = xmlSchemaItemListCreate();
5710    if (ret->members == NULL) {
5711	xmlSchemaSubstGroupFree(ret);
5712	return(NULL);
5713    }
5714    /* Add subst group to hash. */
5715    if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5716	head->name, head->targetNamespace, ret) != 0) {
5717	PERROR_INT("xmlSchemaSubstGroupAdd",
5718	    "failed to add a new substitution container");
5719	xmlSchemaSubstGroupFree(ret);
5720	return(NULL);
5721    }
5722    return(ret);
5723}
5724
5725static xmlSchemaSubstGroupPtr
5726xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5727		       xmlSchemaElementPtr head)
5728{
5729    if (WXS_SUBST_GROUPS(pctxt) == NULL)
5730	return(NULL);
5731    return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5732	head->name, head->targetNamespace));
5733
5734}
5735
5736/**
5737 * xmlSchemaAddElementSubstitutionMember:
5738 * @pctxt:  a schema parser context
5739 * @head:  the head of the substitution group
5740 * @member: the new member of the substitution group
5741 *
5742 * Allocate a new annotation structure.
5743 *
5744 * Returns the newly allocated structure or NULL in case or error
5745 */
5746static int
5747xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5748				      xmlSchemaElementPtr head,
5749				      xmlSchemaElementPtr member)
5750{
5751    xmlSchemaSubstGroupPtr substGroup = NULL;
5752
5753    if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5754	return (-1);
5755
5756    substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5757    if (substGroup == NULL)
5758	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5759    if (substGroup == NULL)
5760	return(-1);
5761    if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5762	return(-1);
5763    return(0);
5764}
5765
5766/************************************************************************
5767 *									*
5768 *		Utilities for parsing					*
5769 *									*
5770 ************************************************************************/
5771
5772/**
5773 * xmlSchemaPValAttrNodeQNameValue:
5774 * @ctxt:  a schema parser context
5775 * @schema: the schema context
5776 * @ownerDes: the designation of the parent element
5777 * @ownerItem: the parent as a schema object
5778 * @value:  the QName value
5779 * @local: the resulting local part if found, the attribute value otherwise
5780 * @uri:  the resulting namespace URI if found
5781 *
5782 * Extracts the local name and the URI of a QName value and validates it.
5783 * This one is intended to be used on attribute values that
5784 * should resolve to schema components.
5785 *
5786 * Returns 0, in case the QName is valid, a positive error code
5787 * if not valid and -1 if an internal error occurs.
5788 */
5789static int
5790xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5791				       xmlSchemaPtr schema,
5792				       xmlSchemaBasicItemPtr ownerItem,
5793				       xmlAttrPtr attr,
5794				       const xmlChar *value,
5795				       const xmlChar **uri,
5796				       const xmlChar **local)
5797{
5798    const xmlChar *pref;
5799    xmlNsPtr ns;
5800    int len, ret;
5801
5802    *uri = NULL;
5803    *local = NULL;
5804    ret = xmlValidateQName(value, 1);
5805    if (ret > 0) {
5806	xmlSchemaPSimpleTypeErr(ctxt,
5807	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5808	    ownerItem, (xmlNodePtr) attr,
5809	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5810	    NULL, value, NULL, NULL, NULL);
5811	*local = value;
5812	return (ctxt->err);
5813    } else if (ret < 0)
5814	return (-1);
5815
5816    if (!strchr((char *) value, ':')) {
5817	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5818	if (ns)
5819	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5820	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5821	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5822	    * parser context. */
5823	    /*
5824	    * This one takes care of included schemas with no
5825	    * target namespace.
5826	    */
5827	    *uri = ctxt->targetNamespace;
5828	}
5829	*local = xmlDictLookup(ctxt->dict, value, -1);
5830	return (0);
5831    }
5832    /*
5833    * At this point xmlSplitQName3 has to return a local name.
5834    */
5835    *local = xmlSplitQName3(value, &len);
5836    *local = xmlDictLookup(ctxt->dict, *local, -1);
5837    pref = xmlDictLookup(ctxt->dict, value, len);
5838    ns = xmlSearchNs(attr->doc, attr->parent, pref);
5839    if (ns == NULL) {
5840	xmlSchemaPSimpleTypeErr(ctxt,
5841	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5842	    ownerItem, (xmlNodePtr) attr,
5843	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5844	    "The value '%s' of simple type 'xs:QName' has no "
5845	    "corresponding namespace declaration in scope", value, NULL);
5846	return (ctxt->err);
5847    } else {
5848        *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5849    }
5850    return (0);
5851}
5852
5853/**
5854 * xmlSchemaPValAttrNodeQName:
5855 * @ctxt:  a schema parser context
5856 * @schema: the schema context
5857 * @ownerDes: the designation of the owner element
5858 * @ownerItem: the owner as a schema object
5859 * @attr:  the attribute node
5860 * @local: the resulting local part if found, the attribute value otherwise
5861 * @uri:  the resulting namespace URI if found
5862 *
5863 * Extracts and validates the QName of an attribute value.
5864 * This one is intended to be used on attribute values that
5865 * should resolve to schema components.
5866 *
5867 * Returns 0, in case the QName is valid, a positive error code
5868 * if not valid and -1 if an internal error occurs.
5869 */
5870static int
5871xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5872				       xmlSchemaPtr schema,
5873				       xmlSchemaBasicItemPtr ownerItem,
5874				       xmlAttrPtr attr,
5875				       const xmlChar **uri,
5876				       const xmlChar **local)
5877{
5878    const xmlChar *value;
5879
5880    value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5881    return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5882	ownerItem, attr, value, uri, local));
5883}
5884
5885/**
5886 * xmlSchemaPValAttrQName:
5887 * @ctxt:  a schema parser context
5888 * @schema: the schema context
5889 * @ownerDes: the designation of the parent element
5890 * @ownerItem: the owner as a schema object
5891 * @ownerElem:  the parent node of the attribute
5892 * @name:  the name of the attribute
5893 * @local: the resulting local part if found, the attribute value otherwise
5894 * @uri:  the resulting namespace URI if found
5895 *
5896 * Extracts and validates the QName of an attribute value.
5897 *
5898 * Returns 0, in case the QName is valid, a positive error code
5899 * if not valid and -1 if an internal error occurs.
5900 */
5901static int
5902xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5903				   xmlSchemaPtr schema,
5904				   xmlSchemaBasicItemPtr ownerItem,
5905				   xmlNodePtr ownerElem,
5906				   const char *name,
5907				   const xmlChar **uri,
5908				   const xmlChar **local)
5909{
5910    xmlAttrPtr attr;
5911
5912    attr = xmlSchemaGetPropNode(ownerElem, name);
5913    if (attr == NULL) {
5914	*local = NULL;
5915	*uri = NULL;
5916	return (0);
5917    }
5918    return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5919	ownerItem, attr, uri, local));
5920}
5921
5922/**
5923 * xmlSchemaPValAttrID:
5924 * @ctxt:  a schema parser context
5925 * @schema: the schema context
5926 * @ownerDes: the designation of the parent element
5927 * @ownerItem: the owner as a schema object
5928 * @ownerElem:  the parent node of the attribute
5929 * @name:  the name of the attribute
5930 *
5931 * Extracts and validates the ID of an attribute value.
5932 *
5933 * Returns 0, in case the ID is valid, a positive error code
5934 * if not valid and -1 if an internal error occurs.
5935 */
5936static int
5937xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5938{
5939    int ret;
5940    const xmlChar *value;
5941
5942    if (attr == NULL)
5943	return(0);
5944    value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5945    ret = xmlValidateNCName(value, 1);
5946    if (ret == 0) {
5947	/*
5948	* NOTE: the IDness might have already be declared in the DTD
5949	*/
5950	if (attr->atype != XML_ATTRIBUTE_ID) {
5951	    xmlIDPtr res;
5952	    xmlChar *strip;
5953
5954	    /*
5955	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5956	    * moment.
5957	    */
5958	    strip = xmlSchemaCollapseString(value);
5959	    if (strip != NULL) {
5960		xmlFree((xmlChar *) value);
5961		value = strip;
5962	    }
5963	    res = xmlAddID(NULL, attr->doc, value, attr);
5964	    if (res == NULL) {
5965		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5966		xmlSchemaPSimpleTypeErr(ctxt,
5967		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5968		    NULL, (xmlNodePtr) attr,
5969		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5970		    NULL, NULL, "Duplicate value '%s' of simple "
5971		    "type 'xs:ID'", value, NULL);
5972	    } else
5973		attr->atype = XML_ATTRIBUTE_ID;
5974	}
5975    } else if (ret > 0) {
5976	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5977	xmlSchemaPSimpleTypeErr(ctxt,
5978	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5979	    NULL, (xmlNodePtr) attr,
5980	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5981	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5982	    "not a valid 'xs:NCName'",
5983	    value, NULL);
5984    }
5985    if (value != NULL)
5986	xmlFree((xmlChar *)value);
5987
5988    return (ret);
5989}
5990
5991static int
5992xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5993		    xmlNodePtr ownerElem,
5994		    const xmlChar *name)
5995{
5996    xmlAttrPtr attr;
5997
5998    attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5999    if (attr == NULL)
6000	return(0);
6001    return(xmlSchemaPValAttrNodeID(ctxt, attr));
6002
6003}
6004
6005/**
6006 * xmlGetMaxOccurs:
6007 * @ctxt:  a schema validation context
6008 * @node:  a subtree containing XML Schema informations
6009 *
6010 * Get the maxOccurs property
6011 *
6012 * Returns the default if not found, or the value
6013 */
6014static int
6015xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6016		int min, int max, int def, const char *expected)
6017{
6018    const xmlChar *val, *cur;
6019    int ret = 0;
6020    xmlAttrPtr attr;
6021
6022    attr = xmlSchemaGetPropNode(node, "maxOccurs");
6023    if (attr == NULL)
6024	return (def);
6025    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6026
6027    if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6028	if (max != UNBOUNDED) {
6029	    xmlSchemaPSimpleTypeErr(ctxt,
6030		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6031		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6032		NULL, (xmlNodePtr) attr, NULL, expected,
6033		val, NULL, NULL, NULL);
6034	    return (def);
6035	} else
6036	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6037    }
6038
6039    cur = val;
6040    while (IS_BLANK_CH(*cur))
6041        cur++;
6042    if (*cur == 0) {
6043        xmlSchemaPSimpleTypeErr(ctxt,
6044	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6045	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6046	    NULL, (xmlNodePtr) attr, NULL, expected,
6047	    val, NULL, NULL, NULL);
6048	return (def);
6049    }
6050    while ((*cur >= '0') && (*cur <= '9')) {
6051        ret = ret * 10 + (*cur - '0');
6052        cur++;
6053    }
6054    while (IS_BLANK_CH(*cur))
6055        cur++;
6056    /*
6057    * TODO: Restrict the maximal value to Integer.
6058    */
6059    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6060	xmlSchemaPSimpleTypeErr(ctxt,
6061	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6062	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6063	    NULL, (xmlNodePtr) attr, NULL, expected,
6064	    val, NULL, NULL, NULL);
6065        return (def);
6066    }
6067    return (ret);
6068}
6069
6070/**
6071 * xmlGetMinOccurs:
6072 * @ctxt:  a schema validation context
6073 * @node:  a subtree containing XML Schema informations
6074 *
6075 * Get the minOccurs property
6076 *
6077 * Returns the default if not found, or the value
6078 */
6079static int
6080xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6081		int min, int max, int def, const char *expected)
6082{
6083    const xmlChar *val, *cur;
6084    int ret = 0;
6085    xmlAttrPtr attr;
6086
6087    attr = xmlSchemaGetPropNode(node, "minOccurs");
6088    if (attr == NULL)
6089	return (def);
6090    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6091    cur = val;
6092    while (IS_BLANK_CH(*cur))
6093        cur++;
6094    if (*cur == 0) {
6095        xmlSchemaPSimpleTypeErr(ctxt,
6096	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6097	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6098	    NULL, (xmlNodePtr) attr, NULL, expected,
6099	    val, NULL, NULL, NULL);
6100        return (def);
6101    }
6102    while ((*cur >= '0') && (*cur <= '9')) {
6103        ret = ret * 10 + (*cur - '0');
6104        cur++;
6105    }
6106    while (IS_BLANK_CH(*cur))
6107        cur++;
6108    /*
6109    * TODO: Restrict the maximal value to Integer.
6110    */
6111    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6112	xmlSchemaPSimpleTypeErr(ctxt,
6113	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6114	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6115	    NULL, (xmlNodePtr) attr, NULL, expected,
6116	    val, NULL, NULL, NULL);
6117        return (def);
6118    }
6119    return (ret);
6120}
6121
6122/**
6123 * xmlSchemaPGetBoolNodeValue:
6124 * @ctxt:  a schema validation context
6125 * @ownerDes:  owner designation
6126 * @ownerItem:  the owner as a schema item
6127 * @node: the node holding the value
6128 *
6129 * Converts a boolean string value into 1 or 0.
6130 *
6131 * Returns 0 or 1.
6132 */
6133static int
6134xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6135			   xmlSchemaBasicItemPtr ownerItem,
6136			   xmlNodePtr node)
6137{
6138    xmlChar *value = NULL;
6139    int res = 0;
6140
6141    value = xmlNodeGetContent(node);
6142    /*
6143    * 3.2.2.1 Lexical representation
6144    * An instance of a datatype that is defined as `boolean`
6145    * can have the following legal literals {true, false, 1, 0}.
6146    */
6147    if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6148        res = 1;
6149    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6150        res = 0;
6151    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6152	res = 1;
6153    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6154        res = 0;
6155    else {
6156        xmlSchemaPSimpleTypeErr(ctxt,
6157	    XML_SCHEMAP_INVALID_BOOLEAN,
6158	    ownerItem, node,
6159	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6160	    NULL, BAD_CAST value,
6161	    NULL, NULL, NULL);
6162    }
6163    if (value != NULL)
6164	xmlFree(value);
6165    return (res);
6166}
6167
6168/**
6169 * xmlGetBooleanProp:
6170 * @ctxt:  a schema validation context
6171 * @node:  a subtree containing XML Schema informations
6172 * @name:  the attribute name
6173 * @def:  the default value
6174 *
6175 * Evaluate if a boolean property is set
6176 *
6177 * Returns the default if not found, 0 if found to be false,
6178 * 1 if found to be true
6179 */
6180static int
6181xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6182		  xmlNodePtr node,
6183                  const char *name, int def)
6184{
6185    const xmlChar *val;
6186
6187    val = xmlSchemaGetProp(ctxt, node, name);
6188    if (val == NULL)
6189        return (def);
6190    /*
6191    * 3.2.2.1 Lexical representation
6192    * An instance of a datatype that is defined as `boolean`
6193    * can have the following legal literals {true, false, 1, 0}.
6194    */
6195    if (xmlStrEqual(val, BAD_CAST "true"))
6196        def = 1;
6197    else if (xmlStrEqual(val, BAD_CAST "false"))
6198        def = 0;
6199    else if (xmlStrEqual(val, BAD_CAST "1"))
6200	def = 1;
6201    else if (xmlStrEqual(val, BAD_CAST "0"))
6202        def = 0;
6203    else {
6204        xmlSchemaPSimpleTypeErr(ctxt,
6205	    XML_SCHEMAP_INVALID_BOOLEAN,
6206	    NULL,
6207	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6208	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6209	    NULL, val, NULL, NULL, NULL);
6210    }
6211    return (def);
6212}
6213
6214/************************************************************************
6215 *									*
6216 *		Shema extraction from an Infoset			*
6217 *									*
6218 ************************************************************************/
6219static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6220                                                 ctxt, xmlSchemaPtr schema,
6221                                                 xmlNodePtr node,
6222						 int topLevel);
6223static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6224                                                  ctxt,
6225                                                  xmlSchemaPtr schema,
6226                                                  xmlNodePtr node,
6227						  int topLevel);
6228static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6229                                                  ctxt,
6230                                                  xmlSchemaPtr schema,
6231                                                  xmlNodePtr node,
6232						  xmlSchemaTypeType parentType);
6233static xmlSchemaBasicItemPtr
6234xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6235			     xmlSchemaPtr schema,
6236			     xmlNodePtr node,
6237			     xmlSchemaItemListPtr uses,
6238			     int parentType);
6239static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6240                                           xmlSchemaPtr schema,
6241                                           xmlNodePtr node);
6242static xmlSchemaWildcardPtr
6243xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6244                           xmlSchemaPtr schema, xmlNodePtr node);
6245
6246/**
6247 * xmlSchemaPValAttrNodeValue:
6248 *
6249 * @ctxt:  a schema parser context
6250 * @ownerDes: the designation of the parent element
6251 * @ownerItem: the schema object owner if existent
6252 * @attr:  the schema attribute node being validated
6253 * @value: the value
6254 * @type: the built-in type to be validated against
6255 *
6256 * Validates a value against the given built-in type.
6257 * This one is intended to be used internally for validation
6258 * of schema attribute values during parsing of the schema.
6259 *
6260 * Returns 0 if the value is valid, a positive error code
6261 * number otherwise and -1 in case of an internal or API error.
6262 */
6263static int
6264xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6265			   xmlSchemaBasicItemPtr ownerItem,
6266			   xmlAttrPtr attr,
6267			   const xmlChar *value,
6268			   xmlSchemaTypePtr type)
6269{
6270
6271    int ret = 0;
6272
6273    /*
6274    * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6275    * one is really meant to be used internally, so better not.
6276    */
6277    if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6278	return (-1);
6279    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6280	PERROR_INT("xmlSchemaPValAttrNodeValue",
6281	    "the given type is not a built-in type");
6282	return (-1);
6283    }
6284    switch (type->builtInType) {
6285	case XML_SCHEMAS_NCNAME:
6286	case XML_SCHEMAS_QNAME:
6287	case XML_SCHEMAS_ANYURI:
6288	case XML_SCHEMAS_TOKEN:
6289	case XML_SCHEMAS_LANGUAGE:
6290	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6291		(xmlNodePtr) attr);
6292	    break;
6293	default: {
6294	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6295		"validation using the given type is not supported while "
6296		"parsing a schema");
6297	    return (-1);
6298	}
6299    }
6300    /*
6301    * TODO: Should we use the S4S error codes instead?
6302    */
6303    if (ret < 0) {
6304	PERROR_INT("xmlSchemaPValAttrNodeValue",
6305	    "failed to validate a schema attribute value");
6306	return (-1);
6307    } else if (ret > 0) {
6308	if (WXS_IS_LIST(type))
6309	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6310	else
6311	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6312	xmlSchemaPSimpleTypeErr(pctxt,
6313	    ret, ownerItem, (xmlNodePtr) attr,
6314	    type, NULL, value, NULL, NULL, NULL);
6315    }
6316    return (ret);
6317}
6318
6319/**
6320 * xmlSchemaPValAttrNode:
6321 *
6322 * @ctxt:  a schema parser context
6323 * @ownerDes: the designation of the parent element
6324 * @ownerItem: the schema object owner if existent
6325 * @attr:  the schema attribute node being validated
6326 * @type: the built-in type to be validated against
6327 * @value: the resulting value if any
6328 *
6329 * Extracts and validates a value against the given built-in type.
6330 * This one is intended to be used internally for validation
6331 * of schema attribute values during parsing of the schema.
6332 *
6333 * Returns 0 if the value is valid, a positive error code
6334 * number otherwise and -1 in case of an internal or API error.
6335 */
6336static int
6337xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6338			   xmlSchemaBasicItemPtr ownerItem,
6339			   xmlAttrPtr attr,
6340			   xmlSchemaTypePtr type,
6341			   const xmlChar **value)
6342{
6343    const xmlChar *val;
6344
6345    if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6346	return (-1);
6347
6348    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6349    if (value != NULL)
6350	*value = val;
6351
6352    return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6353	val, type));
6354}
6355
6356/**
6357 * xmlSchemaPValAttr:
6358 *
6359 * @ctxt:  a schema parser context
6360 * @node: the element node of the attribute
6361 * @ownerDes: the designation of the parent element
6362 * @ownerItem: the schema object owner if existent
6363 * @ownerElem: the owner element node
6364 * @name:  the name of the schema attribute node
6365 * @type: the built-in type to be validated against
6366 * @value: the resulting value if any
6367 *
6368 * Extracts and validates a value against the given built-in type.
6369 * This one is intended to be used internally for validation
6370 * of schema attribute values during parsing of the schema.
6371 *
6372 * Returns 0 if the value is valid, a positive error code
6373 * number otherwise and -1 in case of an internal or API error.
6374 */
6375static int
6376xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6377		       xmlSchemaBasicItemPtr ownerItem,
6378		       xmlNodePtr ownerElem,
6379		       const char *name,
6380		       xmlSchemaTypePtr type,
6381		       const xmlChar **value)
6382{
6383    xmlAttrPtr attr;
6384
6385    if ((ctxt == NULL) || (type == NULL)) {
6386	if (value != NULL)
6387	    *value = NULL;
6388	return (-1);
6389    }
6390    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6391	if (value != NULL)
6392	    *value = NULL;
6393	xmlSchemaPErr(ctxt, ownerElem,
6394	    XML_SCHEMAP_INTERNAL,
6395	    "Internal error: xmlSchemaPValAttr, the given "
6396	    "type '%s' is not a built-in type.\n",
6397	    type->name, NULL);
6398	return (-1);
6399    }
6400    attr = xmlSchemaGetPropNode(ownerElem, name);
6401    if (attr == NULL) {
6402	if (value != NULL)
6403	    *value = NULL;
6404	return (0);
6405    }
6406    return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6407	type, value));
6408}
6409
6410static int
6411xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6412		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6413		  xmlNodePtr node,
6414		  xmlAttrPtr attr,
6415		  const xmlChar *namespaceName)
6416{
6417    /* TODO: Pointer comparison instead? */
6418    if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6419	return (0);
6420    if (xmlStrEqual(xmlSchemaNs, namespaceName))
6421	return (0);
6422    /*
6423    * Check if the referenced namespace was <import>ed.
6424    */
6425    if (WXS_BUCKET(pctxt)->relations != NULL) {
6426	xmlSchemaSchemaRelationPtr rel;
6427
6428	rel = WXS_BUCKET(pctxt)->relations;
6429	do {
6430	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6431		xmlStrEqual(namespaceName, rel->importNamespace))
6432		return (0);
6433	    rel = rel->next;
6434	} while (rel != NULL);
6435    }
6436    /*
6437    * No matching <import>ed namespace found.
6438    */
6439    {
6440	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6441
6442	if (namespaceName == NULL)
6443	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6444		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6445		"References from this schema to components in no "
6446		"namespace are not allowed, since not indicated by an "
6447		"import statement", NULL, NULL);
6448	else
6449	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6450		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6451		"References from this schema to components in the "
6452		"namespace '%s' are not allowed, since not indicated by an "
6453		"import statement", namespaceName, NULL);
6454    }
6455    return (XML_SCHEMAP_SRC_RESOLVE);
6456}
6457
6458/**
6459 * xmlSchemaParseLocalAttributes:
6460 * @ctxt:  a schema validation context
6461 * @schema:  the schema being built
6462 * @node:  a subtree containing XML Schema informations
6463 * @type:  the hosting type where the attributes will be anchored
6464 *
6465 * Parses attribute uses and attribute declarations and
6466 * attribute group references.
6467 */
6468static int
6469xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6470                        xmlNodePtr *child, xmlSchemaItemListPtr *list,
6471			int parentType, int *hasRefs)
6472{
6473    void *item;
6474
6475    while ((IS_SCHEMA((*child), "attribute")) ||
6476           (IS_SCHEMA((*child), "attributeGroup"))) {
6477        if (IS_SCHEMA((*child), "attribute")) {
6478	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6479		*list, parentType);
6480        } else {
6481            item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6482	    if ((item != NULL) && (hasRefs != NULL))
6483		*hasRefs = 1;
6484        }
6485	if (item != NULL) {
6486	    if (*list == NULL) {
6487		/* TODO: Customize grow factor. */
6488		*list = xmlSchemaItemListCreate();
6489		if (*list == NULL)
6490		    return(-1);
6491	    }
6492	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6493		return(-1);
6494	}
6495        *child = (*child)->next;
6496    }
6497    return (0);
6498}
6499
6500/**
6501 * xmlSchemaParseAnnotation:
6502 * @ctxt:  a schema validation context
6503 * @schema:  the schema being built
6504 * @node:  a subtree containing XML Schema informations
6505 *
6506 * parse a XML schema Attrribute declaration
6507 * *WARNING* this interface is highly subject to change
6508 *
6509 * Returns -1 in case of error, 0 if the declaration is improper and
6510 *         1 in case of success.
6511 */
6512static xmlSchemaAnnotPtr
6513xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6514{
6515    xmlSchemaAnnotPtr ret;
6516    xmlNodePtr child = NULL;
6517    xmlAttrPtr attr;
6518    int barked = 0;
6519
6520    /*
6521    * INFO: S4S completed.
6522    */
6523    /*
6524    * id = ID
6525    * {any attributes with non-schema namespace . . .}>
6526    * Content: (appinfo | documentation)*
6527    */
6528    if ((ctxt == NULL) || (node == NULL))
6529        return (NULL);
6530    if (needed)
6531	ret = xmlSchemaNewAnnot(ctxt, node);
6532    else
6533	ret = NULL;
6534    attr = node->properties;
6535    while (attr != NULL) {
6536	if (((attr->ns == NULL) &&
6537	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6538	    ((attr->ns != NULL) &&
6539	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6540
6541	    xmlSchemaPIllegalAttrErr(ctxt,
6542		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6543	}
6544	attr = attr->next;
6545    }
6546    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6547    /*
6548    * And now for the children...
6549    */
6550    child = node->children;
6551    while (child != NULL) {
6552	if (IS_SCHEMA(child, "appinfo")) {
6553	    /* TODO: make available the content of "appinfo". */
6554	    /*
6555	    * source = anyURI
6556	    * {any attributes with non-schema namespace . . .}>
6557	    * Content: ({any})*
6558	    */
6559	    attr = child->properties;
6560	    while (attr != NULL) {
6561		if (((attr->ns == NULL) &&
6562		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6563		     ((attr->ns != NULL) &&
6564		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6565
6566		    xmlSchemaPIllegalAttrErr(ctxt,
6567			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6568		}
6569		attr = attr->next;
6570	    }
6571	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6572		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6573	    child = child->next;
6574	} else if (IS_SCHEMA(child, "documentation")) {
6575	    /* TODO: make available the content of "documentation". */
6576	    /*
6577	    * source = anyURI
6578	    * {any attributes with non-schema namespace . . .}>
6579	    * Content: ({any})*
6580	    */
6581	    attr = child->properties;
6582	    while (attr != NULL) {
6583		if (attr->ns == NULL) {
6584		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6585			xmlSchemaPIllegalAttrErr(ctxt,
6586			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6587		    }
6588		} else {
6589		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6590			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6591			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6592
6593			xmlSchemaPIllegalAttrErr(ctxt,
6594			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6595		    }
6596		}
6597		attr = attr->next;
6598	    }
6599	    /*
6600	    * Attribute "xml:lang".
6601	    */
6602	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6603	    if (attr != NULL)
6604		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6605		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6606	    child = child->next;
6607	} else {
6608	    if (!barked)
6609		xmlSchemaPContentErr(ctxt,
6610		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6611		    NULL, node, child, NULL, "(appinfo | documentation)*");
6612	    barked = 1;
6613	    child = child->next;
6614	}
6615    }
6616
6617    return (ret);
6618}
6619
6620/**
6621 * xmlSchemaParseFacet:
6622 * @ctxt:  a schema validation context
6623 * @schema:  the schema being built
6624 * @node:  a subtree containing XML Schema informations
6625 *
6626 * parse a XML schema Facet declaration
6627 * *WARNING* this interface is highly subject to change
6628 *
6629 * Returns the new type structure or NULL in case of error
6630 */
6631static xmlSchemaFacetPtr
6632xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6633                    xmlNodePtr node)
6634{
6635    xmlSchemaFacetPtr facet;
6636    xmlNodePtr child = NULL;
6637    const xmlChar *value;
6638
6639    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6640        return (NULL);
6641
6642    facet = xmlSchemaNewFacet();
6643    if (facet == NULL) {
6644        xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6645        return (NULL);
6646    }
6647    facet->node = node;
6648    value = xmlSchemaGetProp(ctxt, node, "value");
6649    if (value == NULL) {
6650        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6651                       "Facet %s has no value\n", node->name, NULL);
6652        xmlSchemaFreeFacet(facet);
6653        return (NULL);
6654    }
6655    if (IS_SCHEMA(node, "minInclusive")) {
6656        facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6657    } else if (IS_SCHEMA(node, "minExclusive")) {
6658        facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6659    } else if (IS_SCHEMA(node, "maxInclusive")) {
6660        facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6661    } else if (IS_SCHEMA(node, "maxExclusive")) {
6662        facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6663    } else if (IS_SCHEMA(node, "totalDigits")) {
6664        facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6665    } else if (IS_SCHEMA(node, "fractionDigits")) {
6666        facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6667    } else if (IS_SCHEMA(node, "pattern")) {
6668        facet->type = XML_SCHEMA_FACET_PATTERN;
6669    } else if (IS_SCHEMA(node, "enumeration")) {
6670        facet->type = XML_SCHEMA_FACET_ENUMERATION;
6671    } else if (IS_SCHEMA(node, "whiteSpace")) {
6672        facet->type = XML_SCHEMA_FACET_WHITESPACE;
6673    } else if (IS_SCHEMA(node, "length")) {
6674        facet->type = XML_SCHEMA_FACET_LENGTH;
6675    } else if (IS_SCHEMA(node, "maxLength")) {
6676        facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6677    } else if (IS_SCHEMA(node, "minLength")) {
6678        facet->type = XML_SCHEMA_FACET_MINLENGTH;
6679    } else {
6680        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6681                       "Unknown facet type %s\n", node->name, NULL);
6682        xmlSchemaFreeFacet(facet);
6683        return (NULL);
6684    }
6685    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6686    facet->value = value;
6687    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6688	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6689	const xmlChar *fixed;
6690
6691	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6692	if (fixed != NULL) {
6693	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6694		facet->fixed = 1;
6695	}
6696    }
6697    child = node->children;
6698
6699    if (IS_SCHEMA(child, "annotation")) {
6700        facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6701        child = child->next;
6702    }
6703    if (child != NULL) {
6704        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6705                       "Facet %s has unexpected child content\n",
6706                       node->name, NULL);
6707    }
6708    return (facet);
6709}
6710
6711/**
6712 * xmlSchemaParseWildcardNs:
6713 * @ctxt:  a schema parser context
6714 * @wildc:  the wildcard, already created
6715 * @node:  a subtree containing XML Schema informations
6716 *
6717 * Parses the attribute "processContents" and "namespace"
6718 * of a xsd:anyAttribute and xsd:any.
6719 * *WARNING* this interface is highly subject to change
6720 *
6721 * Returns 0 if everything goes fine, a positive error code
6722 * if something is not valid and -1 if an internal error occurs.
6723 */
6724static int
6725xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6726			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6727			 xmlSchemaWildcardPtr wildc,
6728			 xmlNodePtr node)
6729{
6730    const xmlChar *pc, *ns, *dictnsItem;
6731    int ret = 0;
6732    xmlChar *nsItem;
6733    xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6734    xmlAttrPtr attr;
6735
6736    pc = xmlSchemaGetProp(ctxt, node, "processContents");
6737    if ((pc == NULL)
6738        || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6739        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6740    } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6741        wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6742    } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6743        wildc->processContents = XML_SCHEMAS_ANY_LAX;
6744    } else {
6745        xmlSchemaPSimpleTypeErr(ctxt,
6746	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6747	    NULL, node,
6748	    NULL, "(strict | skip | lax)", pc,
6749	    NULL, NULL, NULL);
6750        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6751	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6752    }
6753    /*
6754     * Build the namespace constraints.
6755     */
6756    attr = xmlSchemaGetPropNode(node, "namespace");
6757    ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6758    if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6759	wildc->any = 1;
6760    else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6761	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6762	if (wildc->negNsSet == NULL) {
6763	    return (-1);
6764	}
6765	wildc->negNsSet->value = ctxt->targetNamespace;
6766    } else {
6767	const xmlChar *end, *cur;
6768
6769	cur = ns;
6770	do {
6771	    while (IS_BLANK_CH(*cur))
6772		cur++;
6773	    end = cur;
6774	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6775		end++;
6776	    if (end == cur)
6777		break;
6778	    nsItem = xmlStrndup(cur, end - cur);
6779	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6780		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6781		xmlSchemaPSimpleTypeErr(ctxt,
6782		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6783		    NULL, (xmlNodePtr) attr,
6784		    NULL,
6785		    "((##any | ##other) | List of (xs:anyURI | "
6786		    "(##targetNamespace | ##local)))",
6787		    nsItem, NULL, NULL, NULL);
6788		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6789	    } else {
6790		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6791		    dictnsItem = ctxt->targetNamespace;
6792		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6793		    dictnsItem = NULL;
6794		} else {
6795		    /*
6796		    * Validate the item (anyURI).
6797		    */
6798		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6799			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6800		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6801		}
6802		/*
6803		* Avoid dublicate namespaces.
6804		*/
6805		tmp = wildc->nsSet;
6806		while (tmp != NULL) {
6807		    if (dictnsItem == tmp->value)
6808			break;
6809		    tmp = tmp->next;
6810		}
6811		if (tmp == NULL) {
6812		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6813		    if (tmp == NULL) {
6814			xmlFree(nsItem);
6815			return (-1);
6816		    }
6817		    tmp->value = dictnsItem;
6818		    tmp->next = NULL;
6819		    if (wildc->nsSet == NULL)
6820			wildc->nsSet = tmp;
6821		    else if (lastNs != NULL)
6822			lastNs->next = tmp;
6823		    lastNs = tmp;
6824		}
6825
6826	    }
6827	    xmlFree(nsItem);
6828	    cur = end;
6829	} while (*cur != 0);
6830    }
6831    return (ret);
6832}
6833
6834static int
6835xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6836				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6837				 xmlNodePtr node,
6838				 int minOccurs,
6839				 int maxOccurs) {
6840
6841    if ((maxOccurs == 0) && ( minOccurs == 0))
6842	return (0);
6843    if (maxOccurs != UNBOUNDED) {
6844	/*
6845	* TODO: Maybe we should better not create the particle,
6846	* if min/max is invalid, since it could confuse the build of the
6847	* content model.
6848	*/
6849	/*
6850	* 3.9.6 Schema Component Constraint: Particle Correct
6851	*
6852	*/
6853	if (maxOccurs < 1) {
6854	    /*
6855	    * 2.2 {max occurs} must be greater than or equal to 1.
6856	    */
6857	    xmlSchemaPCustomAttrErr(ctxt,
6858		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6859		NULL, NULL,
6860		xmlSchemaGetPropNode(node, "maxOccurs"),
6861		"The value must be greater than or equal to 1");
6862	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6863	} else if (minOccurs > maxOccurs) {
6864	    /*
6865	    * 2.1 {min occurs} must not be greater than {max occurs}.
6866	    */
6867	    xmlSchemaPCustomAttrErr(ctxt,
6868		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6869		NULL, NULL,
6870		xmlSchemaGetPropNode(node, "minOccurs"),
6871		"The value must not be greater than the value of 'maxOccurs'");
6872	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6873	}
6874    }
6875    return (0);
6876}
6877
6878/**
6879 * xmlSchemaParseAny:
6880 * @ctxt:  a schema validation context
6881 * @schema:  the schema being built
6882 * @node:  a subtree containing XML Schema informations
6883 *
6884 * Parsea a XML schema <any> element. A particle and wildcard
6885 * will be created (except if minOccurs==maxOccurs==0, in this case
6886 * nothing will be created).
6887 * *WARNING* this interface is highly subject to change
6888 *
6889 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6890 */
6891static xmlSchemaParticlePtr
6892xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6893                  xmlNodePtr node)
6894{
6895    xmlSchemaParticlePtr particle;
6896    xmlNodePtr child = NULL;
6897    xmlSchemaWildcardPtr wild;
6898    int min, max;
6899    xmlAttrPtr attr;
6900    xmlSchemaAnnotPtr annot = NULL;
6901
6902    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6903        return (NULL);
6904    /*
6905    * Check for illegal attributes.
6906    */
6907    attr = node->properties;
6908    while (attr != NULL) {
6909	if (attr->ns == NULL) {
6910	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6911		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6912		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6913	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6914		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6915		xmlSchemaPIllegalAttrErr(ctxt,
6916		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6917	    }
6918	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6919	    xmlSchemaPIllegalAttrErr(ctxt,
6920		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6921	}
6922	attr = attr->next;
6923    }
6924    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6925    /*
6926    * minOccurs/maxOccurs.
6927    */
6928    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6929	"(xs:nonNegativeInteger | unbounded)");
6930    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6931	"xs:nonNegativeInteger");
6932    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6933    /*
6934    * Create & parse the wildcard.
6935    */
6936    wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6937    if (wild == NULL)
6938	return (NULL);
6939    xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6940    /*
6941    * And now for the children...
6942    */
6943    child = node->children;
6944    if (IS_SCHEMA(child, "annotation")) {
6945        annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6946        child = child->next;
6947    }
6948    if (child != NULL) {
6949	xmlSchemaPContentErr(ctxt,
6950	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6951	    NULL, node, child,
6952	    NULL, "(annotation?)");
6953    }
6954    /*
6955    * No component if minOccurs==maxOccurs==0.
6956    */
6957    if ((min == 0) && (max == 0)) {
6958	/* Don't free the wildcard, since it's already on the list. */
6959	return (NULL);
6960    }
6961    /*
6962    * Create the particle.
6963    */
6964    particle = xmlSchemaAddParticle(ctxt, node, min, max);
6965    if (particle == NULL)
6966        return (NULL);
6967    particle->annot = annot;
6968    particle->children = (xmlSchemaTreeItemPtr) wild;
6969
6970    return (particle);
6971}
6972
6973/**
6974 * xmlSchemaParseNotation:
6975 * @ctxt:  a schema validation context
6976 * @schema:  the schema being built
6977 * @node:  a subtree containing XML Schema informations
6978 *
6979 * parse a XML schema Notation declaration
6980 *
6981 * Returns the new structure or NULL in case of error
6982 */
6983static xmlSchemaNotationPtr
6984xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6985                       xmlNodePtr node)
6986{
6987    const xmlChar *name;
6988    xmlSchemaNotationPtr ret;
6989    xmlNodePtr child = NULL;
6990
6991    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6992        return (NULL);
6993    name = xmlSchemaGetProp(ctxt, node, "name");
6994    if (name == NULL) {
6995        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6996                       "Notation has no name\n", NULL, NULL);
6997        return (NULL);
6998    }
6999    ret = xmlSchemaAddNotation(ctxt, schema, name,
7000	ctxt->targetNamespace, node);
7001    if (ret == NULL)
7002        return (NULL);
7003    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7004
7005    child = node->children;
7006    if (IS_SCHEMA(child, "annotation")) {
7007        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7008        child = child->next;
7009    }
7010    if (child != NULL) {
7011	xmlSchemaPContentErr(ctxt,
7012	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7013	    NULL, node, child,
7014	    NULL, "(annotation?)");
7015    }
7016
7017    return (ret);
7018}
7019
7020/**
7021 * xmlSchemaParseAnyAttribute:
7022 * @ctxt:  a schema validation context
7023 * @schema:  the schema being built
7024 * @node:  a subtree containing XML Schema informations
7025 *
7026 * parse a XML schema AnyAttrribute declaration
7027 * *WARNING* this interface is highly subject to change
7028 *
7029 * Returns a wildcard or NULL.
7030 */
7031static xmlSchemaWildcardPtr
7032xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7033                           xmlSchemaPtr schema, xmlNodePtr node)
7034{
7035    xmlSchemaWildcardPtr ret;
7036    xmlNodePtr child = NULL;
7037    xmlAttrPtr attr;
7038
7039    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7040        return (NULL);
7041
7042    ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7043	node);
7044    if (ret == NULL) {
7045        return (NULL);
7046    }
7047    /*
7048    * Check for illegal attributes.
7049    */
7050    attr = node->properties;
7051    while (attr != NULL) {
7052	if (attr->ns == NULL) {
7053	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7054	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7055		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7056		xmlSchemaPIllegalAttrErr(ctxt,
7057		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7058	    }
7059	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7060	    xmlSchemaPIllegalAttrErr(ctxt,
7061		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7062	}
7063	attr = attr->next;
7064    }
7065    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7066    /*
7067    * Parse the namespace list.
7068    */
7069    if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7070	return (NULL);
7071    /*
7072    * And now for the children...
7073    */
7074    child = node->children;
7075    if (IS_SCHEMA(child, "annotation")) {
7076        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7077        child = child->next;
7078    }
7079    if (child != NULL) {
7080	xmlSchemaPContentErr(ctxt,
7081	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7082	    NULL, node, child,
7083	    NULL, "(annotation?)");
7084    }
7085
7086    return (ret);
7087}
7088
7089
7090/**
7091 * xmlSchemaParseAttribute:
7092 * @ctxt:  a schema validation context
7093 * @schema:  the schema being built
7094 * @node:  a subtree containing XML Schema informations
7095 *
7096 * parse a XML schema Attrribute declaration
7097 * *WARNING* this interface is highly subject to change
7098 *
7099 * Returns the attribute declaration.
7100 */
7101static xmlSchemaBasicItemPtr
7102xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7103			     xmlSchemaPtr schema,
7104			     xmlNodePtr node,
7105			     xmlSchemaItemListPtr uses,
7106			     int parentType)
7107{
7108    const xmlChar *attrValue, *name = NULL, *ns = NULL;
7109    xmlSchemaAttributeUsePtr use = NULL;
7110    xmlNodePtr child = NULL;
7111    xmlAttrPtr attr;
7112    const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7113    int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7114    int	nberrors, hasForm = 0, defValueType = 0;
7115
7116#define WXS_ATTR_DEF_VAL_DEFAULT 1
7117#define WXS_ATTR_DEF_VAL_FIXED 2
7118
7119    /*
7120     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7121     */
7122
7123    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7124        return (NULL);
7125    attr = xmlSchemaGetPropNode(node, "ref");
7126    if (attr != NULL) {
7127	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7128	    NULL, attr, &tmpNs, &tmpName) != 0) {
7129	    return (NULL);
7130	}
7131	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7132	    return(NULL);
7133	isRef = 1;
7134    }
7135    nberrors = pctxt->nberrors;
7136    /*
7137    * Check for illegal attributes.
7138    */
7139    attr = node->properties;
7140    while (attr != NULL) {
7141	if (attr->ns == NULL) {
7142	    if (isRef) {
7143		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7144		    xmlSchemaPValAttrNodeID(pctxt, attr);
7145		    goto attr_next;
7146		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7147		    goto attr_next;
7148		}
7149	    } else {
7150		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7151		    goto attr_next;
7152		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7153		    xmlSchemaPValAttrNodeID(pctxt, attr);
7154		    goto attr_next;
7155		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7156		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7157			attr, &tmpNs, &tmpName);
7158		    goto attr_next;
7159		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7160		    /*
7161		    * Evaluate the target namespace
7162		    */
7163		    hasForm = 1;
7164		    attrValue = xmlSchemaGetNodeContent(pctxt,
7165			(xmlNodePtr) attr);
7166		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7167			ns = pctxt->targetNamespace;
7168		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7169		    {
7170			xmlSchemaPSimpleTypeErr(pctxt,
7171			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7172			    NULL, (xmlNodePtr) attr,
7173			    NULL, "(qualified | unqualified)",
7174			    attrValue, NULL, NULL, NULL);
7175		    }
7176		    goto attr_next;
7177		}
7178	    }
7179	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7180
7181		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7182		/* TODO: Maybe we need to normalize the value beforehand. */
7183		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7184		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7185		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7186		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7187		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7188		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7189		else {
7190		    xmlSchemaPSimpleTypeErr(pctxt,
7191			XML_SCHEMAP_INVALID_ATTR_USE,
7192			NULL, (xmlNodePtr) attr,
7193			NULL, "(optional | prohibited | required)",
7194			attrValue, NULL, NULL, NULL);
7195		}
7196		goto attr_next;
7197	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7198		/*
7199		* 3.2.3 : 1
7200		* default and fixed must not both be present.
7201		*/
7202		if (defValue) {
7203		    xmlSchemaPMutualExclAttrErr(pctxt,
7204			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7205			NULL, attr, "default", "fixed");
7206		} else {
7207		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7208		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7209		}
7210		goto attr_next;
7211	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7212		/*
7213		* 3.2.3 : 1
7214		* default and fixed must not both be present.
7215		*/
7216		if (defValue) {
7217		    xmlSchemaPMutualExclAttrErr(pctxt,
7218			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7219			NULL, attr, "default", "fixed");
7220		} else {
7221		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7222		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7223		}
7224		goto attr_next;
7225	    }
7226	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7227	    goto attr_next;
7228
7229	xmlSchemaPIllegalAttrErr(pctxt,
7230	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7231
7232attr_next:
7233	attr = attr->next;
7234    }
7235    /*
7236    * 3.2.3 : 2
7237    * If default and use are both present, use must have
7238    * the actual value optional.
7239    */
7240    if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7241	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7242	xmlSchemaPSimpleTypeErr(pctxt,
7243	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7244	    NULL, node, NULL,
7245	    "(optional | prohibited | required)", NULL,
7246	    "The value of the attribute 'use' must be 'optional' "
7247	    "if the attribute 'default' is present",
7248	    NULL, NULL);
7249    }
7250    /*
7251    * We want correct attributes.
7252    */
7253    if (nberrors != pctxt->nberrors)
7254	return(NULL);
7255    if (! isRef) {
7256	xmlSchemaAttributePtr attrDecl;
7257
7258	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7259	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7260	    ns = pctxt->targetNamespace;
7261	/*
7262	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7263	* TODO: Move this to the component layer.
7264	*/
7265	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7266	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7267		XML_SCHEMAP_NO_XSI,
7268		node, NULL,
7269		"The target namespace must not match '%s'",
7270		xmlSchemaInstanceNs, NULL);
7271	}
7272	attr = xmlSchemaGetPropNode(node, "name");
7273	if (attr == NULL) {
7274	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7275		NULL, node, "name", NULL);
7276	    return (NULL);
7277	}
7278	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7279	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7280	    return (NULL);
7281	}
7282	/*
7283	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7284	* TODO: Move this to the component layer.
7285	*/
7286	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7287	    xmlSchemaPSimpleTypeErr(pctxt,
7288		XML_SCHEMAP_NO_XMLNS,
7289		NULL, (xmlNodePtr) attr,
7290		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7291		"The value of the attribute must not match 'xmlns'",
7292		NULL, NULL);
7293	    return (NULL);
7294	}
7295	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7296	    goto check_children;
7297	/*
7298	* Create the attribute use component.
7299	*/
7300	use = xmlSchemaAddAttributeUse(pctxt, node);
7301	if (use == NULL)
7302	    return(NULL);
7303	use->occurs = occurs;
7304	/*
7305	* Create the attribute declaration.
7306	*/
7307	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7308	if (attrDecl == NULL)
7309	    return (NULL);
7310	if (tmpName != NULL) {
7311	    attrDecl->typeName = tmpName;
7312	    attrDecl->typeNs = tmpNs;
7313	}
7314	use->attrDecl = attrDecl;
7315	/*
7316	* Value constraint.
7317	*/
7318	if (defValue != NULL) {
7319	    attrDecl->defValue = defValue;
7320	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7321		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7322	}
7323    } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7324	xmlSchemaQNameRefPtr ref;
7325
7326	/*
7327	* Create the attribute use component.
7328	*/
7329	use = xmlSchemaAddAttributeUse(pctxt, node);
7330	if (use == NULL)
7331	    return(NULL);
7332	/*
7333	* We need to resolve the reference at later stage.
7334	*/
7335	WXS_ADD_PENDING(pctxt, use);
7336	use->occurs = occurs;
7337	/*
7338	* Create a QName reference to the attribute declaration.
7339	*/
7340	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7341	    tmpName, tmpNs);
7342	if (ref == NULL)
7343	    return(NULL);
7344	/*
7345	* Assign the reference. This will be substituted for the
7346	* referenced attribute declaration when the QName is resolved.
7347	*/
7348	use->attrDecl = WXS_ATTR_CAST ref;
7349	/*
7350	* Value constraint.
7351	*/
7352	if (defValue != NULL)
7353	    use->defValue = defValue;
7354	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7355		use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7356    }
7357
7358check_children:
7359    /*
7360    * And now for the children...
7361    */
7362    child = node->children;
7363    if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7364	xmlSchemaAttributeUseProhibPtr prohib;
7365
7366	if (IS_SCHEMA(child, "annotation")) {
7367	    xmlSchemaParseAnnotation(pctxt, child, 0);
7368	    child = child->next;
7369	}
7370	if (child != NULL) {
7371	    xmlSchemaPContentErr(pctxt,
7372		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7373		NULL, node, child, NULL,
7374		"(annotation?)");
7375	}
7376	/*
7377	* Check for pointlessness of attribute prohibitions.
7378	*/
7379	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7380	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7381		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7382		node, NULL,
7383		"Skipping attribute use prohibition, since it is "
7384		"pointless inside an <attributeGroup>",
7385		NULL, NULL, NULL);
7386	    return(NULL);
7387	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7388	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7389		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7390		node, NULL,
7391		"Skipping attribute use prohibition, since it is "
7392		"pointless when extending a type",
7393		NULL, NULL, NULL);
7394	    return(NULL);
7395	}
7396	if (! isRef) {
7397	    tmpName = name;
7398	    tmpNs = ns;
7399	}
7400	/*
7401	* Check for duplicate attribute prohibitions.
7402	*/
7403	if (uses) {
7404	    int i;
7405
7406	    for (i = 0; i < uses->nbItems; i++) {
7407		use = uses->items[i];
7408		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7409		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7410		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7411		{
7412		    xmlChar *str = NULL;
7413
7414		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7415			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7416			node, NULL,
7417			"Skipping duplicate attribute use prohibition '%s'",
7418			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7419			NULL, NULL);
7420		    FREE_AND_NULL(str)
7421		    return(NULL);
7422		}
7423	    }
7424	}
7425	/*
7426	* Create the attribute prohibition helper component.
7427	*/
7428	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7429	if (prohib == NULL)
7430	    return(NULL);
7431	prohib->node = node;
7432	prohib->name = tmpName;
7433	prohib->targetNamespace = tmpNs;
7434	if (isRef) {
7435	    /*
7436	    * We need at least to resolve to the attribute declaration.
7437	    */
7438	    WXS_ADD_PENDING(pctxt, prohib);
7439	}
7440	return(WXS_BASIC_CAST prohib);
7441    } else {
7442	if (IS_SCHEMA(child, "annotation")) {
7443	    /*
7444	    * TODO: Should this go into the attr decl?
7445	    */
7446	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7447	    child = child->next;
7448	}
7449	if (isRef) {
7450	    if (child != NULL) {
7451		if (IS_SCHEMA(child, "simpleType"))
7452		    /*
7453		    * 3.2.3 : 3.2
7454		    * If ref is present, then all of <simpleType>,
7455		    * form and type must be absent.
7456		    */
7457		    xmlSchemaPContentErr(pctxt,
7458			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7459			NULL, node, child, NULL,
7460			"(annotation?)");
7461		else
7462		    xmlSchemaPContentErr(pctxt,
7463			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464			NULL, node, child, NULL,
7465			"(annotation?)");
7466	    }
7467	} else {
7468	    if (IS_SCHEMA(child, "simpleType")) {
7469		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7470		    /*
7471		    * 3.2.3 : 4
7472		    * type and <simpleType> must not both be present.
7473		    */
7474		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7475			NULL, node, child,
7476			"The attribute 'type' and the <simpleType> child "
7477			"are mutually exclusive", NULL);
7478		} else
7479		    WXS_ATTRUSE_TYPEDEF(use) =
7480			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7481		child = child->next;
7482	    }
7483	    if (child != NULL)
7484		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7485		NULL, node, child, NULL,
7486		"(annotation?, simpleType?)");
7487	}
7488    }
7489    return (WXS_BASIC_CAST use);
7490}
7491
7492
7493static xmlSchemaAttributePtr
7494xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7495			      xmlSchemaPtr schema,
7496			      xmlNodePtr node)
7497{
7498    const xmlChar *attrValue;
7499    xmlSchemaAttributePtr ret;
7500    xmlNodePtr child = NULL;
7501    xmlAttrPtr attr;
7502
7503    /*
7504     * Note that the w3c spec assumes the schema to be validated with schema
7505     * for schemas beforehand.
7506     *
7507     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7508     */
7509    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7510        return (NULL);
7511    /*
7512    * 3.2.3 : 3.1
7513    * One of ref or name must be present, but not both
7514    */
7515    attr = xmlSchemaGetPropNode(node, "name");
7516    if (attr == NULL) {
7517	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7518	    NULL, node, "name", NULL);
7519	return (NULL);
7520    }
7521    if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7522	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7523	return (NULL);
7524    }
7525    /*
7526    * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7527    * TODO: Move this to the component layer.
7528    */
7529    if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7530	xmlSchemaPSimpleTypeErr(pctxt,
7531	    XML_SCHEMAP_NO_XMLNS,
7532	    NULL, (xmlNodePtr) attr,
7533	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7534	    "The value of the attribute must not match 'xmlns'",
7535	    NULL, NULL);
7536	return (NULL);
7537    }
7538    /*
7539    * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7540    * TODO: Move this to the component layer.
7541    *       Or better leave it here and add it to the component layer
7542    *       if we have a schema construction API.
7543    */
7544    if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7545	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7546	    XML_SCHEMAP_NO_XSI, node, NULL,
7547	    "The target namespace must not match '%s'",
7548	    xmlSchemaInstanceNs, NULL);
7549    }
7550
7551    ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7552	pctxt->targetNamespace, node, 1);
7553    if (ret == NULL)
7554	return (NULL);
7555    ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7556
7557    /*
7558    * Check for illegal attributes.
7559    */
7560    attr = node->properties;
7561    while (attr != NULL) {
7562	if (attr->ns == NULL) {
7563	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7564		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7565		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7566		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7567		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7568	    {
7569		xmlSchemaPIllegalAttrErr(pctxt,
7570		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7571	    }
7572	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7573	    xmlSchemaPIllegalAttrErr(pctxt,
7574		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7575	}
7576	attr = attr->next;
7577    }
7578    xmlSchemaPValAttrQName(pctxt, schema, NULL,
7579	node, "type", &ret->typeNs, &ret->typeName);
7580
7581    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7582    /*
7583    * Attribute "fixed".
7584    */
7585    ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7586    if (ret->defValue != NULL)
7587	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7588    /*
7589    * Attribute "default".
7590    */
7591    attr = xmlSchemaGetPropNode(node, "default");
7592    if (attr != NULL) {
7593	/*
7594	* 3.2.3 : 1
7595	* default and fixed must not both be present.
7596	*/
7597	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7598	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7599		WXS_BASIC_CAST ret, attr, "default", "fixed");
7600	} else
7601	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7602    }
7603    /*
7604    * And now for the children...
7605    */
7606    child = node->children;
7607    if (IS_SCHEMA(child, "annotation")) {
7608        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7609        child = child->next;
7610    }
7611    if (IS_SCHEMA(child, "simpleType")) {
7612	if (ret->typeName != NULL) {
7613	    /*
7614	    * 3.2.3 : 4
7615	    * type and <simpleType> must not both be present.
7616	    */
7617	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7618		NULL, node, child,
7619		"The attribute 'type' and the <simpleType> child "
7620		"are mutually exclusive", NULL);
7621	} else
7622	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7623	child = child->next;
7624    }
7625    if (child != NULL)
7626	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7627	    NULL, node, child, NULL,
7628	    "(annotation?, simpleType?)");
7629
7630    return (ret);
7631}
7632
7633/**
7634 * xmlSchemaParseAttributeGroupRef:
7635 * @ctxt:  a schema validation context
7636 * @schema:  the schema being built
7637 * @node:  a subtree containing XML Schema informations
7638 *
7639 * Parse an attribute group definition reference.
7640 * Note that a reference to an attribute group does not
7641 * correspond to any component at all.
7642 * *WARNING* this interface is highly subject to change
7643 *
7644 * Returns the attribute group or NULL in case of error.
7645 */
7646static xmlSchemaQNameRefPtr
7647xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7648				xmlSchemaPtr schema,
7649				xmlNodePtr node)
7650{
7651    xmlSchemaQNameRefPtr ret;
7652    xmlNodePtr child = NULL;
7653    xmlAttrPtr attr;
7654    const xmlChar *refNs = NULL, *ref = NULL;
7655
7656    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7657        return (NULL);
7658
7659    attr = xmlSchemaGetPropNode(node, "ref");
7660    if (attr == NULL) {
7661	xmlSchemaPMissingAttrErr(pctxt,
7662	    XML_SCHEMAP_S4S_ATTR_MISSING,
7663	    NULL, node, "ref", NULL);
7664	return (NULL);
7665    }
7666    xmlSchemaPValAttrNodeQName(pctxt, schema,
7667	NULL, attr, &refNs, &ref);
7668    if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7669	return(NULL);
7670
7671    /*
7672    * Check for illegal attributes.
7673    */
7674    attr = node->properties;
7675    while (attr != NULL) {
7676	if (attr->ns == NULL) {
7677	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7678		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7679	    {
7680		xmlSchemaPIllegalAttrErr(pctxt,
7681		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7682	    }
7683	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7684	    xmlSchemaPIllegalAttrErr(pctxt,
7685		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7686	}
7687	attr = attr->next;
7688    }
7689    /* Attribute ID */
7690    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7691
7692    /*
7693    * And now for the children...
7694    */
7695    child = node->children;
7696    if (IS_SCHEMA(child, "annotation")) {
7697	/*
7698	* TODO: We do not have a place to store the annotation, do we?
7699	*/
7700        xmlSchemaParseAnnotation(pctxt, child, 0);
7701        child = child->next;
7702    }
7703    if (child != NULL) {
7704	xmlSchemaPContentErr(pctxt,
7705	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7706	    NULL, node, child, NULL,
7707	    "(annotation?)");
7708    }
7709
7710    /*
7711    * Handle attribute group redefinitions.
7712    */
7713    if (pctxt->isRedefine && pctxt->redef &&
7714	(pctxt->redef->item->type ==
7715	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7716	(ref == pctxt->redef->refName) &&
7717	(refNs == pctxt->redef->refTargetNs))
7718    {
7719	/*
7720	* SPEC src-redefine:
7721	* (7.1) "If it has an <attributeGroup> among its contents
7722	* the `actual value` of whose ref [attribute] is the same
7723	* as the `actual value` of its own name attribute plus
7724	* target namespace, then it must have exactly one such group."
7725	*/
7726	if (pctxt->redefCounter != 0) {
7727	    xmlChar *str = NULL;
7728
7729	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7730		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7731		"The redefining attribute group definition "
7732		"'%s' must not contain more than one "
7733		"reference to the redefined definition",
7734		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7735	    FREE_AND_NULL(str);
7736	    return(NULL);
7737	}
7738	pctxt->redefCounter++;
7739	/*
7740	* URGENT TODO: How to ensure that the reference will not be
7741	* handled by the normal component resolution mechanism?
7742	*/
7743	ret = xmlSchemaNewQNameRef(pctxt,
7744	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7745	if (ret == NULL)
7746	    return(NULL);
7747	ret->node = node;
7748	pctxt->redef->reference = WXS_BASIC_CAST ret;
7749    } else {
7750	/*
7751	* Create a QName-reference helper component. We will substitute this
7752	* component for the attribute uses of the referenced attribute group
7753	* definition.
7754	*/
7755	ret = xmlSchemaNewQNameRef(pctxt,
7756	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7757	if (ret == NULL)
7758	    return(NULL);
7759	ret->node = node;
7760	/* Add to pending items, to be able to resolve the reference. */
7761	WXS_ADD_PENDING(pctxt, ret);
7762    }
7763    return (ret);
7764}
7765
7766/**
7767 * xmlSchemaParseAttributeGroupDefinition:
7768 * @pctxt:  a schema validation context
7769 * @schema:  the schema being built
7770 * @node:  a subtree containing XML Schema informations
7771 *
7772 * parse a XML schema Attribute Group declaration
7773 * *WARNING* this interface is highly subject to change
7774 *
7775 * Returns the attribute group definition or NULL in case of error.
7776 */
7777static xmlSchemaAttributeGroupPtr
7778xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7779				       xmlSchemaPtr schema,
7780				       xmlNodePtr node)
7781{
7782    const xmlChar *name;
7783    xmlSchemaAttributeGroupPtr ret;
7784    xmlNodePtr child = NULL;
7785    xmlAttrPtr attr;
7786    int hasRefs = 0;
7787
7788    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7789        return (NULL);
7790
7791    attr = xmlSchemaGetPropNode(node, "name");
7792    if (attr == NULL) {
7793	xmlSchemaPMissingAttrErr(pctxt,
7794	    XML_SCHEMAP_S4S_ATTR_MISSING,
7795	    NULL, node, "name", NULL);
7796	return (NULL);
7797    }
7798    /*
7799    * The name is crucial, exit if invalid.
7800    */
7801    if (xmlSchemaPValAttrNode(pctxt,
7802	NULL, attr,
7803	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7804	return (NULL);
7805    }
7806    ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7807	name, pctxt->targetNamespace, node);
7808    if (ret == NULL)
7809	return (NULL);
7810    /*
7811    * Check for illegal attributes.
7812    */
7813    attr = node->properties;
7814    while (attr != NULL) {
7815	if (attr->ns == NULL) {
7816	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7817		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7818	    {
7819		xmlSchemaPIllegalAttrErr(pctxt,
7820		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7821	    }
7822	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7823	    xmlSchemaPIllegalAttrErr(pctxt,
7824		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7825	}
7826	attr = attr->next;
7827    }
7828    /* Attribute ID */
7829    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7830    /*
7831    * And now for the children...
7832    */
7833    child = node->children;
7834    if (IS_SCHEMA(child, "annotation")) {
7835        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7836        child = child->next;
7837    }
7838    /*
7839    * Parse contained attribute decls/refs.
7840    */
7841    if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7842	(xmlSchemaItemListPtr *) &(ret->attrUses),
7843	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7844	return(NULL);
7845    if (hasRefs)
7846	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7847    /*
7848    * Parse the attribute wildcard.
7849    */
7850    if (IS_SCHEMA(child, "anyAttribute")) {
7851	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7852	    schema, child);
7853	child = child->next;
7854    }
7855    if (child != NULL) {
7856	xmlSchemaPContentErr(pctxt,
7857	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7858	    NULL, node, child, NULL,
7859	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7860    }
7861    return (ret);
7862}
7863
7864/**
7865 * xmlSchemaPValAttrFormDefault:
7866 * @value:  the value
7867 * @flags: the flags to be modified
7868 * @flagQualified: the specific flag for "qualified"
7869 *
7870 * Returns 0 if the value is valid, 1 otherwise.
7871 */
7872static int
7873xmlSchemaPValAttrFormDefault(const xmlChar *value,
7874			     int *flags,
7875			     int flagQualified)
7876{
7877    if (xmlStrEqual(value, BAD_CAST "qualified")) {
7878	if  ((*flags & flagQualified) == 0)
7879	    *flags |= flagQualified;
7880    } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7881	return (1);
7882
7883    return (0);
7884}
7885
7886/**
7887 * xmlSchemaPValAttrBlockFinal:
7888 * @value:  the value
7889 * @flags: the flags to be modified
7890 * @flagAll: the specific flag for "#all"
7891 * @flagExtension: the specific flag for "extension"
7892 * @flagRestriction: the specific flag for "restriction"
7893 * @flagSubstitution: the specific flag for "substitution"
7894 * @flagList: the specific flag for "list"
7895 * @flagUnion: the specific flag for "union"
7896 *
7897 * Validates the value of the attribute "final" and "block". The value
7898 * is converted into the specified flag values and returned in @flags.
7899 *
7900 * Returns 0 if the value is valid, 1 otherwise.
7901 */
7902
7903static int
7904xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7905			    int *flags,
7906			    int flagAll,
7907			    int flagExtension,
7908			    int flagRestriction,
7909			    int flagSubstitution,
7910			    int flagList,
7911			    int flagUnion)
7912{
7913    int ret = 0;
7914
7915    /*
7916    * TODO: This does not check for dublicate entries.
7917    */
7918    if ((flags == NULL) || (value == NULL))
7919	return (-1);
7920    if (value[0] == 0)
7921	return (0);
7922    if (xmlStrEqual(value, BAD_CAST "#all")) {
7923	if (flagAll != -1)
7924	    *flags |= flagAll;
7925	else {
7926	    if (flagExtension != -1)
7927		*flags |= flagExtension;
7928	    if (flagRestriction != -1)
7929		*flags |= flagRestriction;
7930	    if (flagSubstitution != -1)
7931		*flags |= flagSubstitution;
7932	    if (flagList != -1)
7933		*flags |= flagList;
7934	    if (flagUnion != -1)
7935		*flags |= flagUnion;
7936	}
7937    } else {
7938	const xmlChar *end, *cur = value;
7939	xmlChar *item;
7940
7941	do {
7942	    while (IS_BLANK_CH(*cur))
7943		cur++;
7944	    end = cur;
7945	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7946		end++;
7947	    if (end == cur)
7948		break;
7949	    item = xmlStrndup(cur, end - cur);
7950	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7951		if (flagExtension != -1) {
7952		    if ((*flags & flagExtension) == 0)
7953			*flags |= flagExtension;
7954		} else
7955		    ret = 1;
7956	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7957		if (flagRestriction != -1) {
7958		    if ((*flags & flagRestriction) == 0)
7959			*flags |= flagRestriction;
7960		} else
7961		    ret = 1;
7962	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7963		if (flagSubstitution != -1) {
7964		    if ((*flags & flagSubstitution) == 0)
7965			*flags |= flagSubstitution;
7966		} else
7967		    ret = 1;
7968	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
7969		if (flagList != -1) {
7970		    if ((*flags & flagList) == 0)
7971			*flags |= flagList;
7972		} else
7973		    ret = 1;
7974	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
7975		if (flagUnion != -1) {
7976		    if ((*flags & flagUnion) == 0)
7977			*flags |= flagUnion;
7978		} else
7979		    ret = 1;
7980	    } else
7981		ret = 1;
7982	    if (item != NULL)
7983		xmlFree(item);
7984	    cur = end;
7985	} while ((ret == 0) && (*cur != 0));
7986    }
7987
7988    return (ret);
7989}
7990
7991static int
7992xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7993			     xmlSchemaIDCPtr idc,
7994			     xmlSchemaIDCSelectPtr selector,
7995			     xmlAttrPtr attr,
7996			     int isField)
7997{
7998    xmlNodePtr node;
7999
8000    /*
8001    * c-selector-xpath:
8002    * Schema Component Constraint: Selector Value OK
8003    *
8004    * TODO: 1 The {selector} must be a valid XPath expression, as defined
8005    * in [XPath].
8006    */
8007    if (selector == NULL) {
8008	xmlSchemaPErr(ctxt, idc->node,
8009	    XML_SCHEMAP_INTERNAL,
8010	    "Internal error: xmlSchemaCheckCSelectorXPath, "
8011	    "the selector is not specified.\n", NULL, NULL);
8012	return (-1);
8013    }
8014    if (attr == NULL)
8015	node = idc->node;
8016    else
8017	node = (xmlNodePtr) attr;
8018    if (selector->xpath == NULL) {
8019	xmlSchemaPCustomErr(ctxt,
8020	    /* TODO: Adjust error code. */
8021	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8022	    NULL, node,
8023	    "The XPath expression of the selector is not valid", NULL);
8024	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8025    } else {
8026	const xmlChar **nsArray = NULL;
8027	xmlNsPtr *nsList = NULL;
8028	/*
8029	* Compile the XPath expression.
8030	*/
8031	/*
8032	* TODO: We need the array of in-scope namespaces for compilation.
8033	* TODO: Call xmlPatterncompile with different options for selector/
8034	* field.
8035	*/
8036	if (attr == NULL)
8037	    nsList = NULL;
8038	else
8039	    nsList = xmlGetNsList(attr->doc, attr->parent);
8040	/*
8041	* Build an array of prefixes and namespaces.
8042	*/
8043	if (nsList != NULL) {
8044	    int i, count = 0;
8045
8046	    for (i = 0; nsList[i] != NULL; i++)
8047		count++;
8048
8049	    nsArray = (const xmlChar **) xmlMalloc(
8050		(count * 2 + 1) * sizeof(const xmlChar *));
8051	    if (nsArray == NULL) {
8052		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8053		    NULL);
8054		xmlFree(nsList);
8055		return (-1);
8056	    }
8057	    for (i = 0; i < count; i++) {
8058		nsArray[2 * i] = nsList[i]->href;
8059		nsArray[2 * i + 1] = nsList[i]->prefix;
8060	    }
8061	    nsArray[count * 2] = NULL;
8062	    xmlFree(nsList);
8063	}
8064	/*
8065	* TODO: Differentiate between "selector" and "field".
8066	*/
8067	if (isField)
8068	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8069		NULL, XML_PATTERN_XSFIELD, nsArray);
8070	else
8071	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8072		NULL, XML_PATTERN_XSSEL, nsArray);
8073	if (nsArray != NULL)
8074	    xmlFree((xmlChar **) nsArray);
8075
8076	if (selector->xpathComp == NULL) {
8077	    xmlSchemaPCustomErr(ctxt,
8078		/* TODO: Adjust error code? */
8079		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8080		NULL, node,
8081		"The XPath expression '%s' could not be "
8082		"compiled", selector->xpath);
8083	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8084	}
8085    }
8086    return (0);
8087}
8088
8089#define ADD_ANNOTATION(annot)   \
8090    xmlSchemaAnnotPtr cur = item->annot; \
8091    if (item->annot == NULL) {  \
8092	item->annot = annot;    \
8093	return (annot);         \
8094    }                           \
8095    cur = item->annot;          \
8096    if (cur->next != NULL) {    \
8097	cur = cur->next;	\
8098    }                           \
8099    cur->next = annot;
8100
8101/**
8102 * xmlSchemaAssignAnnotation:
8103 * @item: the schema component
8104 * @annot: the annotation
8105 *
8106 * Adds the annotation to the given schema component.
8107 *
8108 * Returns the given annotaion.
8109 */
8110static xmlSchemaAnnotPtr
8111xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8112		       xmlSchemaAnnotPtr annot)
8113{
8114    if ((annItem == NULL) || (annot == NULL))
8115	return (NULL);
8116    switch (annItem->type) {
8117	case XML_SCHEMA_TYPE_ELEMENT: {
8118		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8119		ADD_ANNOTATION(annot)
8120	    }
8121	    break;
8122	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8123		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8124		ADD_ANNOTATION(annot)
8125	    }
8126	    break;
8127	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8128	case XML_SCHEMA_TYPE_ANY: {
8129		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8130		ADD_ANNOTATION(annot)
8131	    }
8132	    break;
8133	case XML_SCHEMA_TYPE_PARTICLE:
8134	case XML_SCHEMA_TYPE_IDC_KEY:
8135	case XML_SCHEMA_TYPE_IDC_KEYREF:
8136	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8137		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8138		ADD_ANNOTATION(annot)
8139	    }
8140	    break;
8141	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8142		xmlSchemaAttributeGroupPtr item =
8143		    (xmlSchemaAttributeGroupPtr) annItem;
8144		ADD_ANNOTATION(annot)
8145	    }
8146	    break;
8147	case XML_SCHEMA_TYPE_NOTATION: {
8148		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8149		ADD_ANNOTATION(annot)
8150	    }
8151	    break;
8152	case XML_SCHEMA_FACET_MININCLUSIVE:
8153	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8154	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8155	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8156	case XML_SCHEMA_FACET_TOTALDIGITS:
8157	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8158	case XML_SCHEMA_FACET_PATTERN:
8159	case XML_SCHEMA_FACET_ENUMERATION:
8160	case XML_SCHEMA_FACET_WHITESPACE:
8161	case XML_SCHEMA_FACET_LENGTH:
8162	case XML_SCHEMA_FACET_MAXLENGTH:
8163	case XML_SCHEMA_FACET_MINLENGTH: {
8164		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8165		ADD_ANNOTATION(annot)
8166	    }
8167	    break;
8168	case XML_SCHEMA_TYPE_SIMPLE:
8169	case XML_SCHEMA_TYPE_COMPLEX: {
8170		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8171		ADD_ANNOTATION(annot)
8172	    }
8173	    break;
8174	case XML_SCHEMA_TYPE_GROUP: {
8175		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8176		ADD_ANNOTATION(annot)
8177	    }
8178	    break;
8179	case XML_SCHEMA_TYPE_SEQUENCE:
8180	case XML_SCHEMA_TYPE_CHOICE:
8181	case XML_SCHEMA_TYPE_ALL: {
8182		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8183		ADD_ANNOTATION(annot)
8184	    }
8185	    break;
8186	default:
8187	     xmlSchemaPCustomErr(NULL,
8188		XML_SCHEMAP_INTERNAL,
8189		NULL, NULL,
8190		"Internal error: xmlSchemaAddAnnotation, "
8191		"The item is not a annotated schema component", NULL);
8192	     break;
8193    }
8194    return (annot);
8195}
8196
8197/**
8198 * xmlSchemaParseIDCSelectorAndField:
8199 * @ctxt:  a schema validation context
8200 * @schema:  the schema being built
8201 * @node:  a subtree containing XML Schema informations
8202 *
8203 * Parses a XML Schema identity-contraint definition's
8204 * <selector> and <field> elements.
8205 *
8206 * Returns the parsed identity-constraint definition.
8207 */
8208static xmlSchemaIDCSelectPtr
8209xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8210			  xmlSchemaIDCPtr idc,
8211			  xmlNodePtr node,
8212			  int isField)
8213{
8214    xmlSchemaIDCSelectPtr item;
8215    xmlNodePtr child = NULL;
8216    xmlAttrPtr attr;
8217
8218    /*
8219    * Check for illegal attributes.
8220    */
8221    attr = node->properties;
8222    while (attr != NULL) {
8223	if (attr->ns == NULL) {
8224	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8225		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8226		xmlSchemaPIllegalAttrErr(ctxt,
8227		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8228	    }
8229	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8230	    xmlSchemaPIllegalAttrErr(ctxt,
8231		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8232	}
8233	attr = attr->next;
8234    }
8235    /*
8236    * Create the item.
8237    */
8238    item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8239    if (item == NULL) {
8240        xmlSchemaPErrMemory(ctxt,
8241	    "allocating a 'selector' of an identity-constraint definition",
8242	    NULL);
8243        return (NULL);
8244    }
8245    memset(item, 0, sizeof(xmlSchemaIDCSelect));
8246    /*
8247    * Attribute "xpath" (mandatory).
8248    */
8249    attr = xmlSchemaGetPropNode(node, "xpath");
8250    if (attr == NULL) {
8251	xmlSchemaPMissingAttrErr(ctxt,
8252	    XML_SCHEMAP_S4S_ATTR_MISSING,
8253	    NULL, node,
8254	    "name", NULL);
8255    } else {
8256	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8257	/*
8258	* URGENT TODO: "field"s have an other syntax than "selector"s.
8259	*/
8260
8261	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8262	    isField) == -1) {
8263	    xmlSchemaPErr(ctxt,
8264		(xmlNodePtr) attr,
8265		XML_SCHEMAP_INTERNAL,
8266		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8267		"validating the XPath expression of a IDC selector.\n",
8268		NULL, NULL);
8269	}
8270
8271    }
8272    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8273    /*
8274    * And now for the children...
8275    */
8276    child = node->children;
8277    if (IS_SCHEMA(child, "annotation")) {
8278	/*
8279	* Add the annotation to the parent IDC.
8280	*/
8281	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8282	    xmlSchemaParseAnnotation(ctxt, child, 1));
8283	child = child->next;
8284    }
8285    if (child != NULL) {
8286	xmlSchemaPContentErr(ctxt,
8287	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8288	    NULL, node, child,
8289	    NULL, "(annotation?)");
8290    }
8291
8292    return (item);
8293}
8294
8295/**
8296 * xmlSchemaParseIDC:
8297 * @ctxt:  a schema validation context
8298 * @schema:  the schema being built
8299 * @node:  a subtree containing XML Schema informations
8300 *
8301 * Parses a XML Schema identity-contraint definition.
8302 *
8303 * Returns the parsed identity-constraint definition.
8304 */
8305static xmlSchemaIDCPtr
8306xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8307		  xmlSchemaPtr schema,
8308		  xmlNodePtr node,
8309		  xmlSchemaTypeType idcCategory,
8310		  const xmlChar *targetNamespace)
8311{
8312    xmlSchemaIDCPtr item = NULL;
8313    xmlNodePtr child = NULL;
8314    xmlAttrPtr attr;
8315    const xmlChar *name = NULL;
8316    xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8317
8318    /*
8319    * Check for illegal attributes.
8320    */
8321    attr = node->properties;
8322    while (attr != NULL) {
8323	if (attr->ns == NULL) {
8324	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8325		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8326		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8327		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8328		xmlSchemaPIllegalAttrErr(ctxt,
8329		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8330	    }
8331	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8332	    xmlSchemaPIllegalAttrErr(ctxt,
8333		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8334	}
8335	attr = attr->next;
8336    }
8337    /*
8338    * Attribute "name" (mandatory).
8339    */
8340    attr = xmlSchemaGetPropNode(node, "name");
8341    if (attr == NULL) {
8342	xmlSchemaPMissingAttrErr(ctxt,
8343	    XML_SCHEMAP_S4S_ATTR_MISSING,
8344	    NULL, node,
8345	    "name", NULL);
8346	return (NULL);
8347    } else if (xmlSchemaPValAttrNode(ctxt,
8348	NULL, attr,
8349	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8350	return (NULL);
8351    }
8352    /* Create the component. */
8353    item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8354	idcCategory, node);
8355    if (item == NULL)
8356	return(NULL);
8357
8358    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8359    if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8360	/*
8361	* Attribute "refer" (mandatory).
8362	*/
8363	attr = xmlSchemaGetPropNode(node, "refer");
8364	if (attr == NULL) {
8365	    xmlSchemaPMissingAttrErr(ctxt,
8366		XML_SCHEMAP_S4S_ATTR_MISSING,
8367		NULL, node,
8368		"refer", NULL);
8369	} else {
8370	    /*
8371	    * Create a reference item.
8372	    */
8373	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8374		NULL, NULL);
8375	    if (item->ref == NULL)
8376		return (NULL);
8377	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8378		NULL, attr,
8379		&(item->ref->targetNamespace),
8380		&(item->ref->name));
8381	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8382		item->ref->targetNamespace);
8383	}
8384    }
8385    /*
8386    * And now for the children...
8387    */
8388    child = node->children;
8389    if (IS_SCHEMA(child, "annotation")) {
8390	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8391	child = child->next;
8392    }
8393    if (child == NULL) {
8394	xmlSchemaPContentErr(ctxt,
8395		XML_SCHEMAP_S4S_ELEM_MISSING,
8396		NULL, node, child,
8397		"A child element is missing",
8398		"(annotation?, (selector, field+))");
8399    }
8400    /*
8401    * Child element <selector>.
8402    */
8403    if (IS_SCHEMA(child, "selector")) {
8404	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8405	    item, child, 0);
8406	child = child->next;
8407	/*
8408	* Child elements <field>.
8409	*/
8410	if (IS_SCHEMA(child, "field")) {
8411	    do {
8412		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8413		    item, child, 1);
8414		if (field != NULL) {
8415		    field->index = item->nbFields;
8416		    item->nbFields++;
8417		    if (lastField != NULL)
8418			lastField->next = field;
8419		    else
8420			item->fields = field;
8421		    lastField = field;
8422		}
8423		child = child->next;
8424	    } while (IS_SCHEMA(child, "field"));
8425	} else {
8426	    xmlSchemaPContentErr(ctxt,
8427		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8428		NULL, node, child,
8429		NULL, "(annotation?, (selector, field+))");
8430	}
8431    }
8432    if (child != NULL) {
8433	xmlSchemaPContentErr(ctxt,
8434	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8435	    NULL, node, child,
8436	    NULL, "(annotation?, (selector, field+))");
8437    }
8438
8439    return (item);
8440}
8441
8442/**
8443 * xmlSchemaParseElement:
8444 * @ctxt:  a schema validation context
8445 * @schema:  the schema being built
8446 * @node:  a subtree containing XML Schema informations
8447 * @topLevel: indicates if this is global declaration
8448 *
8449 * Parses a XML schema element declaration.
8450 * *WARNING* this interface is highly subject to change
8451 *
8452 * Returns the element declaration or a particle; NULL in case
8453 * of an error or if the particle has minOccurs==maxOccurs==0.
8454 */
8455static xmlSchemaBasicItemPtr
8456xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8457                      xmlNodePtr node, int *isElemRef, int topLevel)
8458{
8459    xmlSchemaElementPtr decl = NULL;
8460    xmlSchemaParticlePtr particle = NULL;
8461    xmlSchemaAnnotPtr annot = NULL;
8462    xmlNodePtr child = NULL;
8463    xmlAttrPtr attr, nameAttr;
8464    int min, max, isRef = 0;
8465    xmlChar *des = NULL;
8466
8467    /* 3.3.3 Constraints on XML Representations of Element Declarations */
8468    /* TODO: Complete implementation of 3.3.6 */
8469
8470    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8471        return (NULL);
8472
8473    if (isElemRef != NULL)
8474	*isElemRef = 0;
8475    /*
8476    * If we get a "ref" attribute on a local <element> we will assume it's
8477    * a reference - even if there's a "name" attribute; this seems to be more
8478    * robust.
8479    */
8480    nameAttr = xmlSchemaGetPropNode(node, "name");
8481    attr = xmlSchemaGetPropNode(node, "ref");
8482    if ((topLevel) || (attr == NULL)) {
8483	if (nameAttr == NULL) {
8484	    xmlSchemaPMissingAttrErr(ctxt,
8485		XML_SCHEMAP_S4S_ATTR_MISSING,
8486		NULL, node, "name", NULL);
8487	    return (NULL);
8488	}
8489    } else
8490	isRef = 1;
8491
8492    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8493    child = node->children;
8494    if (IS_SCHEMA(child, "annotation")) {
8495	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8496	child = child->next;
8497    }
8498    /*
8499    * Skip particle part if a global declaration.
8500    */
8501    if (topLevel)
8502	goto declaration_part;
8503    /*
8504    * The particle part ==================================================
8505    */
8506    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8507    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8508    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8509    particle = xmlSchemaAddParticle(ctxt, node, min, max);
8510    if (particle == NULL)
8511	goto return_null;
8512
8513    /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8514
8515    if (isRef) {
8516	const xmlChar *refNs = NULL, *ref = NULL;
8517	xmlSchemaQNameRefPtr refer = NULL;
8518	/*
8519	* The reference part =============================================
8520	*/
8521	if (isElemRef != NULL)
8522	    *isElemRef = 1;
8523
8524	xmlSchemaPValAttrNodeQName(ctxt, schema,
8525	    NULL, attr, &refNs, &ref);
8526	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8527	/*
8528	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8529	*/
8530	if (nameAttr != NULL) {
8531	    xmlSchemaPMutualExclAttrErr(ctxt,
8532		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8533	}
8534	/*
8535	* Check for illegal attributes.
8536	*/
8537	attr = node->properties;
8538	while (attr != NULL) {
8539	    if (attr->ns == NULL) {
8540		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8541		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8542		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8543		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8544		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8545		{
8546		    attr = attr->next;
8547		    continue;
8548		} else {
8549		    /* SPEC (3.3.3 : 2.2) */
8550		    xmlSchemaPCustomAttrErr(ctxt,
8551			XML_SCHEMAP_SRC_ELEMENT_2_2,
8552			NULL, NULL, attr,
8553			"Only the attributes 'minOccurs', 'maxOccurs' and "
8554			"'id' are allowed in addition to 'ref'");
8555		    break;
8556		}
8557	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8558		xmlSchemaPIllegalAttrErr(ctxt,
8559		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8560	    }
8561	    attr = attr->next;
8562	}
8563	/*
8564	* No children except <annotation> expected.
8565	*/
8566	if (child != NULL) {
8567	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8568		NULL, node, child, NULL, "(annotation?)");
8569	}
8570	if ((min == 0) && (max == 0))
8571	    goto return_null;
8572	/*
8573	* Create the reference item and attach it to the particle.
8574	*/
8575	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8576	    ref, refNs);
8577	if (refer == NULL)
8578	    goto return_null;
8579	particle->children = (xmlSchemaTreeItemPtr) refer;
8580	particle->annot = annot;
8581	/*
8582	* Add the particle to pending components, since the reference
8583	* need to be resolved.
8584	*/
8585	WXS_ADD_PENDING(ctxt, particle);
8586	return ((xmlSchemaBasicItemPtr) particle);
8587    }
8588    /*
8589    * The declaration part ===============================================
8590    */
8591declaration_part:
8592    {
8593	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8594	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8595
8596	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8597	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8598	    goto return_null;
8599	/*
8600	* Evaluate the target namespace.
8601	*/
8602	if (topLevel) {
8603	    ns = ctxt->targetNamespace;
8604	} else {
8605	    attr = xmlSchemaGetPropNode(node, "form");
8606	    if (attr != NULL) {
8607		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8608		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8609		    ns = ctxt->targetNamespace;
8610		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8611		    xmlSchemaPSimpleTypeErr(ctxt,
8612			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8613			NULL, (xmlNodePtr) attr,
8614			NULL, "(qualified | unqualified)",
8615			attrValue, NULL, NULL, NULL);
8616		}
8617	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8618		ns = ctxt->targetNamespace;
8619	}
8620	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8621	if (decl == NULL) {
8622	    goto return_null;
8623	}
8624	/*
8625	* Check for illegal attributes.
8626	*/
8627	attr = node->properties;
8628	while (attr != NULL) {
8629	    if (attr->ns == NULL) {
8630		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8631		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8632		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8633		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8634		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8635		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8636		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8637		{
8638		    if (topLevel == 0) {
8639			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8640			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8641			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8642			{
8643			    xmlSchemaPIllegalAttrErr(ctxt,
8644				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8645			}
8646		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8647			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8648			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8649
8650			xmlSchemaPIllegalAttrErr(ctxt,
8651			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8652		    }
8653		}
8654	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8655
8656		xmlSchemaPIllegalAttrErr(ctxt,
8657		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8658	    }
8659	    attr = attr->next;
8660	}
8661	/*
8662	* Extract/validate attributes.
8663	*/
8664	if (topLevel) {
8665	    /*
8666	    * Process top attributes of global element declarations here.
8667	    */
8668	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8669	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8670	    xmlSchemaPValAttrQName(ctxt, schema,
8671		NULL, node, "substitutionGroup",
8672		&(decl->substGroupNs), &(decl->substGroup));
8673	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8674		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8675	    /*
8676	    * Attribute "final".
8677	    */
8678	    attr = xmlSchemaGetPropNode(node, "final");
8679	    if (attr == NULL) {
8680		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8681		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8682		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8683		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8684	    } else {
8685		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8686		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8687		    -1,
8688		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8689		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8690		    xmlSchemaPSimpleTypeErr(ctxt,
8691			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8692			NULL, (xmlNodePtr) attr,
8693			NULL, "(#all | List of (extension | restriction))",
8694			attrValue, NULL, NULL, NULL);
8695		}
8696	    }
8697	}
8698	/*
8699	* Attribute "block".
8700	*/
8701	attr = xmlSchemaGetPropNode(node, "block");
8702	if (attr == NULL) {
8703	    /*
8704	    * Apply default "block" values.
8705	    */
8706	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8707		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8708	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8709		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8710	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8711		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8712	} else {
8713	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8714	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8715		-1,
8716		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8717		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8718		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8719		xmlSchemaPSimpleTypeErr(ctxt,
8720		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8721		    NULL, (xmlNodePtr) attr,
8722		    NULL, "(#all | List of (extension | "
8723		    "restriction | substitution))", attrValue,
8724		    NULL, NULL, NULL);
8725	    }
8726	}
8727	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8728	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8729
8730	attr = xmlSchemaGetPropNode(node, "type");
8731	if (attr != NULL) {
8732	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8733		NULL, attr,
8734		&(decl->namedTypeNs), &(decl->namedType));
8735	    xmlSchemaCheckReference(ctxt, schema, node,
8736		attr, decl->namedTypeNs);
8737	}
8738	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8739	attr = xmlSchemaGetPropNode(node, "fixed");
8740	if (attr != NULL) {
8741	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8742	    if (decl->value != NULL) {
8743		/*
8744		* 3.3.3 : 1
8745		* default and fixed must not both be present.
8746		*/
8747		xmlSchemaPMutualExclAttrErr(ctxt,
8748		    XML_SCHEMAP_SRC_ELEMENT_1,
8749		    NULL, attr, "default", "fixed");
8750	    } else {
8751		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8752		decl->value = fixed;
8753	    }
8754	}
8755	/*
8756	* And now for the children...
8757	*/
8758	if (IS_SCHEMA(child, "complexType")) {
8759	    /*
8760	    * 3.3.3 : 3
8761	    * "type" and either <simpleType> or <complexType> are mutually
8762	    * exclusive
8763	    */
8764	    if (decl->namedType != NULL) {
8765		xmlSchemaPContentErr(ctxt,
8766		    XML_SCHEMAP_SRC_ELEMENT_3,
8767		    NULL, node, child,
8768		    "The attribute 'type' and the <complexType> child are "
8769		    "mutually exclusive", NULL);
8770	    } else
8771		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8772	    child = child->next;
8773	} else if (IS_SCHEMA(child, "simpleType")) {
8774	    /*
8775	    * 3.3.3 : 3
8776	    * "type" and either <simpleType> or <complexType> are
8777	    * mutually exclusive
8778	    */
8779	    if (decl->namedType != NULL) {
8780		xmlSchemaPContentErr(ctxt,
8781		    XML_SCHEMAP_SRC_ELEMENT_3,
8782		    NULL, node, child,
8783		    "The attribute 'type' and the <simpleType> child are "
8784		    "mutually exclusive", NULL);
8785	    } else
8786		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8787	    child = child->next;
8788	}
8789	while ((IS_SCHEMA(child, "unique")) ||
8790	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8791	    if (IS_SCHEMA(child, "unique")) {
8792		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8793		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8794	    } else if (IS_SCHEMA(child, "key")) {
8795		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8796		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8797	    } else if (IS_SCHEMA(child, "keyref")) {
8798		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8799		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8800	    }
8801	    if (lastIDC != NULL)
8802		lastIDC->next = curIDC;
8803	    else
8804		decl->idcs = (void *) curIDC;
8805	    lastIDC = curIDC;
8806	    child = child->next;
8807	}
8808	if (child != NULL) {
8809	    xmlSchemaPContentErr(ctxt,
8810		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8811		NULL, node, child,
8812		NULL, "(annotation?, ((simpleType | complexType)?, "
8813		"(unique | key | keyref)*))");
8814	}
8815	decl->annot = annot;
8816    }
8817    /*
8818    * NOTE: Element Declaration Representation OK 4. will be checked at a
8819    * different layer.
8820    */
8821    FREE_AND_NULL(des)
8822    if (topLevel)
8823	return ((xmlSchemaBasicItemPtr) decl);
8824    else {
8825	particle->children = (xmlSchemaTreeItemPtr) decl;
8826	return ((xmlSchemaBasicItemPtr) particle);
8827    }
8828
8829return_null:
8830    FREE_AND_NULL(des);
8831    if (annot != NULL) {
8832	if (particle != NULL)
8833	    particle->annot = NULL;
8834	if (decl != NULL)
8835	    decl->annot = NULL;
8836	xmlSchemaFreeAnnot(annot);
8837    }
8838    return (NULL);
8839}
8840
8841/**
8842 * xmlSchemaParseUnion:
8843 * @ctxt:  a schema validation context
8844 * @schema:  the schema being built
8845 * @node:  a subtree containing XML Schema informations
8846 *
8847 * parse a XML schema Union definition
8848 * *WARNING* this interface is highly subject to change
8849 *
8850 * Returns -1 in case of internal error, 0 in case of success and a positive
8851 * error code otherwise.
8852 */
8853static int
8854xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8855                    xmlNodePtr node)
8856{
8857    xmlSchemaTypePtr type;
8858    xmlNodePtr child = NULL;
8859    xmlAttrPtr attr;
8860    const xmlChar *cur = NULL;
8861
8862    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8863        return (-1);
8864    /* Not a component, don't create it. */
8865    type = ctxt->ctxtType;
8866    /*
8867    * Mark the simple type as being of variety "union".
8868    */
8869    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8870    /*
8871    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8872    * then the `simple ur-type definition`."
8873    */
8874    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8875    /*
8876    * Check for illegal attributes.
8877    */
8878    attr = node->properties;
8879    while (attr != NULL) {
8880	if (attr->ns == NULL) {
8881	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8882		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8883		xmlSchemaPIllegalAttrErr(ctxt,
8884		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8885	    }
8886	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8887	    xmlSchemaPIllegalAttrErr(ctxt,
8888		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8889	}
8890	attr = attr->next;
8891    }
8892    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8893    /*
8894    * Attribute "memberTypes". This is a list of QNames.
8895    * TODO: Check the value to contain anything.
8896    */
8897    attr = xmlSchemaGetPropNode(node, "memberTypes");
8898    if (attr != NULL) {
8899	const xmlChar *end;
8900	xmlChar *tmp;
8901	const xmlChar *localName, *nsName;
8902	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8903	xmlSchemaQNameRefPtr ref;
8904
8905	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8906	type->base = cur;
8907	do {
8908	    while (IS_BLANK_CH(*cur))
8909		cur++;
8910	    end = cur;
8911	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8912		end++;
8913	    if (end == cur)
8914		break;
8915	    tmp = xmlStrndup(cur, end - cur);
8916	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8917		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8918		/*
8919		* Create the member type link.
8920		*/
8921		link = (xmlSchemaTypeLinkPtr)
8922		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8923		if (link == NULL) {
8924		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8925			"allocating a type link", NULL);
8926		    return (-1);
8927		}
8928		link->type = NULL;
8929		link->next = NULL;
8930		if (lastLink == NULL)
8931		    type->memberTypes = link;
8932		else
8933		    lastLink->next = link;
8934		lastLink = link;
8935		/*
8936		* Create a reference item.
8937		*/
8938		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8939		    localName, nsName);
8940		if (ref == NULL) {
8941		    FREE_AND_NULL(tmp)
8942		    return (-1);
8943		}
8944		/*
8945		* Assign the reference to the link, it will be resolved
8946		* later during fixup of the union simple type.
8947		*/
8948		link->type = (xmlSchemaTypePtr) ref;
8949	    }
8950	    FREE_AND_NULL(tmp)
8951	    cur = end;
8952	} while (*cur != 0);
8953
8954    }
8955    /*
8956    * And now for the children...
8957    */
8958    child = node->children;
8959    if (IS_SCHEMA(child, "annotation")) {
8960	/*
8961	* Add the annotation to the simple type ancestor.
8962	*/
8963	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8964	    xmlSchemaParseAnnotation(ctxt, child, 1));
8965        child = child->next;
8966    }
8967    if (IS_SCHEMA(child, "simpleType")) {
8968	xmlSchemaTypePtr subtype, last = NULL;
8969
8970	/*
8971	* Anchor the member types in the "subtypes" field of the
8972	* simple type.
8973	*/
8974	while (IS_SCHEMA(child, "simpleType")) {
8975	    subtype = (xmlSchemaTypePtr)
8976		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8977	    if (subtype != NULL) {
8978		if (last == NULL) {
8979		    type->subtypes = subtype;
8980		    last = subtype;
8981		} else {
8982		    last->next = subtype;
8983		    last = subtype;
8984		}
8985		last->next = NULL;
8986	    }
8987	    child = child->next;
8988	}
8989    }
8990    if (child != NULL) {
8991	xmlSchemaPContentErr(ctxt,
8992	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8993	    NULL, node, child, NULL, "(annotation?, simpleType*)");
8994    }
8995    if ((attr == NULL) && (type->subtypes == NULL)) {
8996	 /*
8997	* src-union-memberTypes-or-simpleTypes
8998	* Either the memberTypes [attribute] of the <union> element must
8999	* be non-empty or there must be at least one simpleType [child].
9000	*/
9001	xmlSchemaPCustomErr(ctxt,
9002	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9003	    NULL, node,
9004	    "Either the attribute 'memberTypes' or "
9005	    "at least one <simpleType> child must be present", NULL);
9006    }
9007    return (0);
9008}
9009
9010/**
9011 * xmlSchemaParseList:
9012 * @ctxt:  a schema validation context
9013 * @schema:  the schema being built
9014 * @node:  a subtree containing XML Schema informations
9015 *
9016 * parse a XML schema List definition
9017 * *WARNING* this interface is highly subject to change
9018 *
9019 * Returns -1 in case of error, 0 if the declaration is improper and
9020 *         1 in case of success.
9021 */
9022static xmlSchemaTypePtr
9023xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9024                   xmlNodePtr node)
9025{
9026    xmlSchemaTypePtr type;
9027    xmlNodePtr child = NULL;
9028    xmlAttrPtr attr;
9029
9030    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9031        return (NULL);
9032    /* Not a component, don't create it. */
9033    type = ctxt->ctxtType;
9034    /*
9035    * Mark the type as being of variety "list".
9036    */
9037    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9038    /*
9039    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9040    * then the `simple ur-type definition`."
9041    */
9042    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9043    /*
9044    * Check for illegal attributes.
9045    */
9046    attr = node->properties;
9047    while (attr != NULL) {
9048	if (attr->ns == NULL) {
9049	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9050		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9051		xmlSchemaPIllegalAttrErr(ctxt,
9052		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9053	    }
9054	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9055	    xmlSchemaPIllegalAttrErr(ctxt,
9056		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9057	}
9058	attr = attr->next;
9059    }
9060
9061    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9062
9063    /*
9064    * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9065    * fields for holding the reference to the itemType.
9066    *
9067    * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9068    * the "ref" fields.
9069    */
9070    xmlSchemaPValAttrQName(ctxt, schema, NULL,
9071	node, "itemType", &(type->baseNs), &(type->base));
9072    /*
9073    * And now for the children...
9074    */
9075    child = node->children;
9076    if (IS_SCHEMA(child, "annotation")) {
9077	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9078	    xmlSchemaParseAnnotation(ctxt, child, 1));
9079        child = child->next;
9080    }
9081    if (IS_SCHEMA(child, "simpleType")) {
9082	/*
9083	* src-list-itemType-or-simpleType
9084	* Either the itemType [attribute] or the <simpleType> [child] of
9085	* the <list> element must be present, but not both.
9086	*/
9087	if (type->base != NULL) {
9088	    xmlSchemaPCustomErr(ctxt,
9089		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9090		NULL, node,
9091		"The attribute 'itemType' and the <simpleType> child "
9092		"are mutually exclusive", NULL);
9093	} else {
9094	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9095	}
9096        child = child->next;
9097    } else if (type->base == NULL) {
9098	xmlSchemaPCustomErr(ctxt,
9099	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9100	    NULL, node,
9101	    "Either the attribute 'itemType' or the <simpleType> child "
9102	    "must be present", NULL);
9103    }
9104    if (child != NULL) {
9105	xmlSchemaPContentErr(ctxt,
9106	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9107	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9108    }
9109    if ((type->base == NULL) &&
9110	(type->subtypes == NULL) &&
9111	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9112	xmlSchemaPCustomErr(ctxt,
9113	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9114	    NULL, node,
9115	    "Either the attribute 'itemType' or the <simpleType> child "
9116	    "must be present", NULL);
9117    }
9118    return (NULL);
9119}
9120
9121/**
9122 * xmlSchemaParseSimpleType:
9123 * @ctxt:  a schema validation context
9124 * @schema:  the schema being built
9125 * @node:  a subtree containing XML Schema informations
9126 *
9127 * parse a XML schema Simple Type definition
9128 * *WARNING* this interface is highly subject to change
9129 *
9130 * Returns -1 in case of error, 0 if the declaration is improper and
9131 * 1 in case of success.
9132 */
9133static xmlSchemaTypePtr
9134xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9135                         xmlNodePtr node, int topLevel)
9136{
9137    xmlSchemaTypePtr type, oldCtxtType;
9138    xmlNodePtr child = NULL;
9139    const xmlChar *attrValue = NULL;
9140    xmlAttrPtr attr;
9141    int hasRestriction = 0;
9142
9143    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9144        return (NULL);
9145
9146    if (topLevel) {
9147	attr = xmlSchemaGetPropNode(node, "name");
9148	if (attr == NULL) {
9149	    xmlSchemaPMissingAttrErr(ctxt,
9150		XML_SCHEMAP_S4S_ATTR_MISSING,
9151		NULL, node,
9152		"name", NULL);
9153	    return (NULL);
9154	} else {
9155	    if (xmlSchemaPValAttrNode(ctxt,
9156		NULL, attr,
9157		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9158		return (NULL);
9159	    /*
9160	    * Skip built-in types.
9161	    */
9162	    if (ctxt->isS4S) {
9163		xmlSchemaTypePtr biType;
9164
9165		if (ctxt->isRedefine) {
9166		    /*
9167		    * REDEFINE: Disallow redefinition of built-in-types.
9168		    * TODO: It seems that the spec does not say anything
9169		    * about this case.
9170		    */
9171		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9172			NULL, node,
9173			"Redefinition of built-in simple types is not "
9174			"supported", NULL);
9175		    return(NULL);
9176		}
9177		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9178		if (biType != NULL)
9179		    return (biType);
9180	    }
9181	}
9182    }
9183    /*
9184    * TargetNamespace:
9185    * SPEC "The `actual value` of the targetNamespace [attribute]
9186    * of the <schema> ancestor element information item if present,
9187    * otherwise `absent`.
9188    */
9189    if (topLevel == 0) {
9190#ifdef ENABLE_NAMED_LOCALS
9191        char buf[40];
9192#endif
9193	/*
9194	* Parse as local simple type definition.
9195	*/
9196#ifdef ENABLE_NAMED_LOCALS
9197        snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9198	type = xmlSchemaAddType(ctxt, schema,
9199	    XML_SCHEMA_TYPE_SIMPLE,
9200	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9201	    ctxt->targetNamespace, node, 0);
9202#else
9203	type = xmlSchemaAddType(ctxt, schema,
9204	    XML_SCHEMA_TYPE_SIMPLE,
9205	    NULL, ctxt->targetNamespace, node, 0);
9206#endif
9207	if (type == NULL)
9208	    return (NULL);
9209	type->type = XML_SCHEMA_TYPE_SIMPLE;
9210	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9211	/*
9212	* Check for illegal attributes.
9213	*/
9214	attr = node->properties;
9215	while (attr != NULL) {
9216	    if (attr->ns == NULL) {
9217		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9218		    xmlSchemaPIllegalAttrErr(ctxt,
9219			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9220		}
9221	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9222		    xmlSchemaPIllegalAttrErr(ctxt,
9223			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9224	    }
9225	    attr = attr->next;
9226	}
9227    } else {
9228	/*
9229	* Parse as global simple type definition.
9230	*
9231	* Note that attrValue is the value of the attribute "name" here.
9232	*/
9233	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9234	    attrValue, ctxt->targetNamespace, node, 1);
9235	if (type == NULL)
9236	    return (NULL);
9237	type->type = XML_SCHEMA_TYPE_SIMPLE;
9238	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9239	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9240	/*
9241	* Check for illegal attributes.
9242	*/
9243	attr = node->properties;
9244	while (attr != NULL) {
9245	    if (attr->ns == NULL) {
9246		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9247		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9248		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9249		    xmlSchemaPIllegalAttrErr(ctxt,
9250			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9251		}
9252	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9253		xmlSchemaPIllegalAttrErr(ctxt,
9254		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9255	    }
9256	    attr = attr->next;
9257	}
9258	/*
9259	* Attribute "final".
9260	*/
9261	attr = xmlSchemaGetPropNode(node, "final");
9262	if (attr == NULL) {
9263	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9264		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9265	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9266		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9267	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9268		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9269	} else {
9270	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9271	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9272		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9273		XML_SCHEMAS_TYPE_FINAL_LIST,
9274		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9275
9276		xmlSchemaPSimpleTypeErr(ctxt,
9277		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9278		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9279		    NULL, "(#all | List of (list | union | restriction)",
9280		    attrValue, NULL, NULL, NULL);
9281	    }
9282	}
9283    }
9284    type->targetNamespace = ctxt->targetNamespace;
9285    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9286    /*
9287    * And now for the children...
9288    */
9289    oldCtxtType = ctxt->ctxtType;
9290
9291    ctxt->ctxtType = type;
9292
9293    child = node->children;
9294    if (IS_SCHEMA(child, "annotation")) {
9295        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9296        child = child->next;
9297    }
9298    if (child == NULL) {
9299	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9300	    NULL, node, child, NULL,
9301	    "(annotation?, (restriction | list | union))");
9302    } else if (IS_SCHEMA(child, "restriction")) {
9303        xmlSchemaParseRestriction(ctxt, schema, child,
9304	    XML_SCHEMA_TYPE_SIMPLE);
9305	hasRestriction = 1;
9306        child = child->next;
9307    } else if (IS_SCHEMA(child, "list")) {
9308        xmlSchemaParseList(ctxt, schema, child);
9309        child = child->next;
9310    } else if (IS_SCHEMA(child, "union")) {
9311        xmlSchemaParseUnion(ctxt, schema, child);
9312        child = child->next;
9313    }
9314    if (child != NULL) {
9315	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9316	    NULL, node, child, NULL,
9317	    "(annotation?, (restriction | list | union))");
9318    }
9319    /*
9320    * REDEFINE: SPEC src-redefine (5)
9321    * "Within the [children], each <simpleType> must have a
9322    * <restriction> among its [children] ... the `actual value` of whose
9323    * base [attribute] must be the same as the `actual value` of its own
9324    * name attribute plus target namespace;"
9325    */
9326    if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9327	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9328	    NULL, node, "This is a redefinition, thus the "
9329	    "<simpleType> must have a <restriction> child", NULL);
9330    }
9331
9332    ctxt->ctxtType = oldCtxtType;
9333    return (type);
9334}
9335
9336/**
9337 * xmlSchemaParseModelGroupDefRef:
9338 * @ctxt:  the parser context
9339 * @schema: the schema being built
9340 * @node:  the node
9341 *
9342 * Parses a reference to a model group definition.
9343 *
9344 * We will return a particle component with a qname-component or
9345 * NULL in case of an error.
9346 */
9347static xmlSchemaTreeItemPtr
9348xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9349			       xmlSchemaPtr schema,
9350			       xmlNodePtr node)
9351{
9352    xmlSchemaParticlePtr item;
9353    xmlNodePtr child = NULL;
9354    xmlAttrPtr attr;
9355    const xmlChar *ref = NULL, *refNs = NULL;
9356    int min, max;
9357
9358    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9359        return (NULL);
9360
9361    attr = xmlSchemaGetPropNode(node, "ref");
9362    if (attr == NULL) {
9363	xmlSchemaPMissingAttrErr(ctxt,
9364	    XML_SCHEMAP_S4S_ATTR_MISSING,
9365	    NULL, node, "ref", NULL);
9366	return (NULL);
9367    } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9368	attr, &refNs, &ref) != 0) {
9369	return (NULL);
9370    }
9371    xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9372    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9373    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9374	"(xs:nonNegativeInteger | unbounded)");
9375    /*
9376    * Check for illegal attributes.
9377    */
9378    attr = node->properties;
9379    while (attr != NULL) {
9380	if (attr->ns == NULL) {
9381	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9382		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9383		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9384		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9385		xmlSchemaPIllegalAttrErr(ctxt,
9386		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9387	    }
9388	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9389	    xmlSchemaPIllegalAttrErr(ctxt,
9390		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9391	}
9392	attr = attr->next;
9393    }
9394    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9395    item = xmlSchemaAddParticle(ctxt, node, min, max);
9396    if (item == NULL)
9397	return (NULL);
9398    /*
9399    * Create a qname-reference and set as the term; it will be substituted
9400    * for the model group after the reference has been resolved.
9401    */
9402    item->children = (xmlSchemaTreeItemPtr)
9403	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9404    xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9405    /*
9406    * And now for the children...
9407    */
9408    child = node->children;
9409    /* TODO: Is annotation even allowed for a model group reference? */
9410    if (IS_SCHEMA(child, "annotation")) {
9411	/*
9412	* TODO: What to do exactly with the annotation?
9413	*/
9414	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9415	child = child->next;
9416    }
9417    if (child != NULL) {
9418	xmlSchemaPContentErr(ctxt,
9419	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9420	    NULL, node, child, NULL,
9421	    "(annotation?)");
9422    }
9423    /*
9424    * Corresponds to no component at all if minOccurs==maxOccurs==0.
9425    */
9426    if ((min == 0) && (max == 0))
9427	return (NULL);
9428
9429    return ((xmlSchemaTreeItemPtr) item);
9430}
9431
9432/**
9433 * xmlSchemaParseModelGroupDefinition:
9434 * @ctxt:  a schema validation context
9435 * @schema:  the schema being built
9436 * @node:  a subtree containing XML Schema informations
9437 *
9438 * Parses a XML schema model group definition.
9439 *
9440 * Note that the contraint src-redefine (6.2) can't be applied until
9441 * references have been resolved. So we will do this at the
9442 * component fixup level.
9443 *
9444 * *WARNING* this interface is highly subject to change
9445 *
9446 * Returns -1 in case of error, 0 if the declaration is improper and
9447 *         1 in case of success.
9448 */
9449static xmlSchemaModelGroupDefPtr
9450xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9451				   xmlSchemaPtr schema,
9452				   xmlNodePtr node)
9453{
9454    xmlSchemaModelGroupDefPtr item;
9455    xmlNodePtr child = NULL;
9456    xmlAttrPtr attr;
9457    const xmlChar *name;
9458
9459    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9460        return (NULL);
9461
9462    attr = xmlSchemaGetPropNode(node, "name");
9463    if (attr == NULL) {
9464	xmlSchemaPMissingAttrErr(ctxt,
9465	    XML_SCHEMAP_S4S_ATTR_MISSING,
9466	    NULL, node,
9467	    "name", NULL);
9468	return (NULL);
9469    } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9470	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9471	return (NULL);
9472    }
9473    item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9474	ctxt->targetNamespace, node);
9475    if (item == NULL)
9476	return (NULL);
9477    /*
9478    * Check for illegal attributes.
9479    */
9480    attr = node->properties;
9481    while (attr != NULL) {
9482	if (attr->ns == NULL) {
9483	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9484		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9485		xmlSchemaPIllegalAttrErr(ctxt,
9486		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9487	    }
9488	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9489	    xmlSchemaPIllegalAttrErr(ctxt,
9490		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9491	}
9492	attr = attr->next;
9493    }
9494    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9495    /*
9496    * And now for the children...
9497    */
9498    child = node->children;
9499    if (IS_SCHEMA(child, "annotation")) {
9500	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9501	child = child->next;
9502    }
9503    if (IS_SCHEMA(child, "all")) {
9504	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9505	    XML_SCHEMA_TYPE_ALL, 0);
9506	child = child->next;
9507    } else if (IS_SCHEMA(child, "choice")) {
9508	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9509	    XML_SCHEMA_TYPE_CHOICE, 0);
9510	child = child->next;
9511    } else if (IS_SCHEMA(child, "sequence")) {
9512	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9513	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9514	child = child->next;
9515    }
9516
9517
9518
9519    if (child != NULL) {
9520	xmlSchemaPContentErr(ctxt,
9521	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9522	    NULL, node, child, NULL,
9523	    "(annotation?, (all | choice | sequence)?)");
9524    }
9525    return (item);
9526}
9527
9528/**
9529 * xmlSchemaCleanupDoc:
9530 * @ctxt:  a schema validation context
9531 * @node:  the root of the document.
9532 *
9533 * removes unwanted nodes in a schemas document tree
9534 */
9535static void
9536xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9537{
9538    xmlNodePtr delete, cur;
9539
9540    if ((ctxt == NULL) || (root == NULL)) return;
9541
9542    /*
9543     * Remove all the blank text nodes
9544     */
9545    delete = NULL;
9546    cur = root;
9547    while (cur != NULL) {
9548        if (delete != NULL) {
9549            xmlUnlinkNode(delete);
9550            xmlFreeNode(delete);
9551            delete = NULL;
9552        }
9553        if (cur->type == XML_TEXT_NODE) {
9554            if (IS_BLANK_NODE(cur)) {
9555                if (xmlNodeGetSpacePreserve(cur) != 1) {
9556                    delete = cur;
9557                }
9558            }
9559        } else if ((cur->type != XML_ELEMENT_NODE) &&
9560                   (cur->type != XML_CDATA_SECTION_NODE)) {
9561            delete = cur;
9562            goto skip_children;
9563        }
9564
9565        /*
9566         * Skip to next node
9567         */
9568        if (cur->children != NULL) {
9569            if ((cur->children->type != XML_ENTITY_DECL) &&
9570                (cur->children->type != XML_ENTITY_REF_NODE) &&
9571                (cur->children->type != XML_ENTITY_NODE)) {
9572                cur = cur->children;
9573                continue;
9574            }
9575        }
9576      skip_children:
9577        if (cur->next != NULL) {
9578            cur = cur->next;
9579            continue;
9580        }
9581
9582        do {
9583            cur = cur->parent;
9584            if (cur == NULL)
9585                break;
9586            if (cur == root) {
9587                cur = NULL;
9588                break;
9589            }
9590            if (cur->next != NULL) {
9591                cur = cur->next;
9592                break;
9593            }
9594        } while (cur != NULL);
9595    }
9596    if (delete != NULL) {
9597        xmlUnlinkNode(delete);
9598        xmlFreeNode(delete);
9599        delete = NULL;
9600    }
9601}
9602
9603
9604static void
9605xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9606{
9607    if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9608	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9609
9610    if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9611	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9612
9613    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9614	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9615    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9616	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9617    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9618	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9619    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9620	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9621
9622    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9623	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9624    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9625	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9626    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9627	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9628}
9629
9630static int
9631xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9632			     xmlSchemaPtr schema,
9633			     xmlNodePtr node)
9634{
9635    xmlAttrPtr attr;
9636    const xmlChar *val;
9637    int res = 0, oldErrs = ctxt->nberrors;
9638
9639    /*
9640    * Those flags should be moved to the parser context flags,
9641    * since they are not visible at the component level. I.e.
9642    * they are used if processing schema *documents* only.
9643    */
9644    res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9645    HFAILURE;
9646
9647    /*
9648    * Since the version is of type xs:token, we won't bother to
9649    * check it.
9650    */
9651    /* REMOVED:
9652    attr = xmlSchemaGetPropNode(node, "version");
9653    if (attr != NULL) {
9654	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9655	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9656	HFAILURE;
9657    }
9658    */
9659    attr = xmlSchemaGetPropNode(node, "targetNamespace");
9660    if (attr != NULL) {
9661	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9662	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9663	HFAILURE;
9664	if (res != 0) {
9665	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9666	    goto exit;
9667	}
9668    }
9669    attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9670    if (attr != NULL) {
9671	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9672	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9673	    XML_SCHEMAS_QUALIF_ELEM);
9674	HFAILURE;
9675	if (res != 0) {
9676	    xmlSchemaPSimpleTypeErr(ctxt,
9677		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9678		NULL, (xmlNodePtr) attr, NULL,
9679		"(qualified | unqualified)", val, NULL, NULL, NULL);
9680	}
9681    }
9682    attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9683    if (attr != NULL) {
9684	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9685	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9686	    XML_SCHEMAS_QUALIF_ATTR);
9687	HFAILURE;
9688	if (res != 0) {
9689	    xmlSchemaPSimpleTypeErr(ctxt,
9690		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9691		NULL, (xmlNodePtr) attr, NULL,
9692		"(qualified | unqualified)", val, NULL, NULL, NULL);
9693	}
9694    }
9695    attr = xmlSchemaGetPropNode(node, "finalDefault");
9696    if (attr != NULL) {
9697	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9698	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9699	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9700	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9701	    -1,
9702	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9703	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9704	HFAILURE;
9705	if (res != 0) {
9706	    xmlSchemaPSimpleTypeErr(ctxt,
9707		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9708		NULL, (xmlNodePtr) attr, NULL,
9709		"(#all | List of (extension | restriction | list | union))",
9710		val, NULL, NULL, NULL);
9711	}
9712    }
9713    attr = xmlSchemaGetPropNode(node, "blockDefault");
9714    if (attr != NULL) {
9715	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9716	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9717	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9718	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9719	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9720	HFAILURE;
9721	if (res != 0) {
9722	    xmlSchemaPSimpleTypeErr(ctxt,
9723		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9724		NULL, (xmlNodePtr) attr, NULL,
9725		"(#all | List of (extension | restriction | substitution))",
9726		val, NULL, NULL, NULL);
9727	}
9728    }
9729
9730exit:
9731    if (oldErrs != ctxt->nberrors)
9732	res = ctxt->err;
9733    return(res);
9734exit_failure:
9735    return(-1);
9736}
9737
9738/**
9739 * xmlSchemaParseSchemaTopLevel:
9740 * @ctxt:  a schema validation context
9741 * @schema:  the schemas
9742 * @nodes:  the list of top level nodes
9743 *
9744 * Returns the internal XML Schema structure built from the resource or
9745 *         NULL in case of error
9746 */
9747static int
9748xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9749                             xmlSchemaPtr schema, xmlNodePtr nodes)
9750{
9751    xmlNodePtr child;
9752    xmlSchemaAnnotPtr annot;
9753    int res = 0, oldErrs, tmpOldErrs;
9754
9755    if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9756        return(-1);
9757
9758    oldErrs = ctxt->nberrors;
9759    child = nodes;
9760    while ((IS_SCHEMA(child, "include")) ||
9761	   (IS_SCHEMA(child, "import")) ||
9762	   (IS_SCHEMA(child, "redefine")) ||
9763	   (IS_SCHEMA(child, "annotation"))) {
9764	if (IS_SCHEMA(child, "annotation")) {
9765	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9766	    if (schema->annot == NULL)
9767		schema->annot = annot;
9768	    else
9769		xmlSchemaFreeAnnot(annot);
9770	} else if (IS_SCHEMA(child, "import")) {
9771	    tmpOldErrs = ctxt->nberrors;
9772	    res = xmlSchemaParseImport(ctxt, schema, child);
9773	    HFAILURE;
9774	    HSTOP(ctxt);
9775	    if (tmpOldErrs != ctxt->nberrors)
9776		goto exit;
9777	} else if (IS_SCHEMA(child, "include")) {
9778	    tmpOldErrs = ctxt->nberrors;
9779	    res = xmlSchemaParseInclude(ctxt, schema, child);
9780	    HFAILURE;
9781	    HSTOP(ctxt);
9782	    if (tmpOldErrs != ctxt->nberrors)
9783		goto exit;
9784	} else if (IS_SCHEMA(child, "redefine")) {
9785	    tmpOldErrs = ctxt->nberrors;
9786	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9787	    HFAILURE;
9788	    HSTOP(ctxt);
9789	    if (tmpOldErrs != ctxt->nberrors)
9790		goto exit;
9791	}
9792	child = child->next;
9793    }
9794    /*
9795    * URGENT TODO: Change the functions to return int results.
9796    * We need especially to catch internal errors.
9797    */
9798    while (child != NULL) {
9799	if (IS_SCHEMA(child, "complexType")) {
9800	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9801	    child = child->next;
9802	} else if (IS_SCHEMA(child, "simpleType")) {
9803	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9804	    child = child->next;
9805	} else if (IS_SCHEMA(child, "element")) {
9806	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9807	    child = child->next;
9808	} else if (IS_SCHEMA(child, "attribute")) {
9809	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9810	    child = child->next;
9811	} else if (IS_SCHEMA(child, "attributeGroup")) {
9812	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9813	    child = child->next;
9814	} else if (IS_SCHEMA(child, "group")) {
9815	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9816	    child = child->next;
9817	} else if (IS_SCHEMA(child, "notation")) {
9818	    xmlSchemaParseNotation(ctxt, schema, child);
9819	    child = child->next;
9820	} else {
9821	    xmlSchemaPContentErr(ctxt,
9822		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9823		NULL, child->parent, child,
9824		NULL, "((include | import | redefine | annotation)*, "
9825		"(((simpleType | complexType | group | attributeGroup) "
9826		"| element | attribute | notation), annotation*)*)");
9827	    child = child->next;
9828	}
9829	while (IS_SCHEMA(child, "annotation")) {
9830	    /*
9831	    * TODO: We should add all annotations.
9832	    */
9833	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9834	    if (schema->annot == NULL)
9835		schema->annot = annot;
9836	    else
9837		xmlSchemaFreeAnnot(annot);
9838	    child = child->next;
9839	}
9840    }
9841exit:
9842    ctxt->ctxtType = NULL;
9843    if (oldErrs != ctxt->nberrors)
9844	res = ctxt->err;
9845    return(res);
9846exit_failure:
9847    return(-1);
9848}
9849
9850static xmlSchemaSchemaRelationPtr
9851xmlSchemaSchemaRelationCreate(void)
9852{
9853    xmlSchemaSchemaRelationPtr ret;
9854
9855    ret = (xmlSchemaSchemaRelationPtr)
9856	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9857    if (ret == NULL) {
9858	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9859	return(NULL);
9860    }
9861    memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9862    return(ret);
9863}
9864
9865#if 0
9866static void
9867xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9868{
9869    xmlFree(rel);
9870}
9871#endif
9872
9873static void
9874xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9875{
9876    xmlSchemaRedefPtr prev;
9877
9878    while (redef != NULL) {
9879	prev = redef;
9880	redef = redef->next;
9881	xmlFree(prev);
9882    }
9883}
9884
9885static void
9886xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9887{
9888    /*
9889    * After the construction context has been freed, there will be
9890    * no schema graph available any more. Only the schema buckets
9891    * will stay alive, which are put into the "schemasImports" and
9892    * "includes" slots of the xmlSchema.
9893    */
9894    if (con->buckets != NULL)
9895	xmlSchemaItemListFree(con->buckets);
9896    if (con->pending != NULL)
9897	xmlSchemaItemListFree(con->pending);
9898    if (con->substGroups != NULL)
9899	xmlHashFree(con->substGroups,
9900	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9901    if (con->redefs != NULL)
9902	xmlSchemaRedefListFree(con->redefs);
9903    if (con->dict != NULL)
9904	xmlDictFree(con->dict);
9905    xmlFree(con);
9906}
9907
9908static xmlSchemaConstructionCtxtPtr
9909xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9910{
9911    xmlSchemaConstructionCtxtPtr ret;
9912
9913    ret = (xmlSchemaConstructionCtxtPtr)
9914	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9915    if (ret == NULL) {
9916        xmlSchemaPErrMemory(NULL,
9917	    "allocating schema construction context", NULL);
9918        return (NULL);
9919    }
9920    memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9921
9922    ret->buckets = xmlSchemaItemListCreate();
9923    if (ret->buckets == NULL) {
9924	xmlSchemaPErrMemory(NULL,
9925	    "allocating list of schema buckets", NULL);
9926	xmlFree(ret);
9927        return (NULL);
9928    }
9929    ret->pending = xmlSchemaItemListCreate();
9930    if (ret->pending == NULL) {
9931	xmlSchemaPErrMemory(NULL,
9932	    "allocating list of pending global components", NULL);
9933	xmlSchemaConstructionCtxtFree(ret);
9934        return (NULL);
9935    }
9936    ret->dict = dict;
9937    xmlDictReference(dict);
9938    return(ret);
9939}
9940
9941static xmlSchemaParserCtxtPtr
9942xmlSchemaParserCtxtCreate(void)
9943{
9944    xmlSchemaParserCtxtPtr ret;
9945
9946    ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9947    if (ret == NULL) {
9948        xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9949                            NULL);
9950        return (NULL);
9951    }
9952    memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9953    ret->type = XML_SCHEMA_CTXT_PARSER;
9954    ret->attrProhibs = xmlSchemaItemListCreate();
9955    if (ret->attrProhibs == NULL) {
9956	xmlFree(ret);
9957	return(NULL);
9958    }
9959    return(ret);
9960}
9961
9962/**
9963 * xmlSchemaNewParserCtxtUseDict:
9964 * @URL:  the location of the schema
9965 * @dict: the dictionary to be used
9966 *
9967 * Create an XML Schemas parse context for that file/resource expected
9968 * to contain an XML Schemas file.
9969 *
9970 * Returns the parser context or NULL in case of error
9971 */
9972static xmlSchemaParserCtxtPtr
9973xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9974{
9975    xmlSchemaParserCtxtPtr ret;
9976
9977    ret = xmlSchemaParserCtxtCreate();
9978    if (ret == NULL)
9979        return (NULL);
9980    ret->dict = dict;
9981    xmlDictReference(dict);
9982    if (URL != NULL)
9983	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9984    return (ret);
9985}
9986
9987static int
9988xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9989{
9990    if (vctxt->pctxt == NULL) {
9991        if (vctxt->schema != NULL)
9992	    vctxt->pctxt =
9993		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9994	else
9995	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9996	if (vctxt->pctxt == NULL) {
9997	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9998		"failed to create a temp. parser context");
9999	    return (-1);
10000	}
10001	/* TODO: Pass user data. */
10002	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10003	    vctxt->warning, vctxt->errCtxt);
10004	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10005	    vctxt->errCtxt);
10006    }
10007    return (0);
10008}
10009
10010/**
10011 * xmlSchemaGetSchemaBucket:
10012 * @pctxt: the schema parser context
10013 * @schemaLocation: the URI of the schema document
10014 *
10015 * Returns a schema bucket if it was already parsed.
10016 *
10017 * Returns a schema bucket if it was already parsed from
10018 *         @schemaLocation, NULL otherwise.
10019 */
10020static xmlSchemaBucketPtr
10021xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10022			    const xmlChar *schemaLocation)
10023{
10024    xmlSchemaBucketPtr cur;
10025    xmlSchemaItemListPtr list;
10026
10027    list = pctxt->constructor->buckets;
10028    if (list->nbItems == 0)
10029	return(NULL);
10030    else {
10031	int i;
10032	for (i = 0; i < list->nbItems; i++) {
10033	    cur = (xmlSchemaBucketPtr) list->items[i];
10034	    /* Pointer comparison! */
10035	    if (cur->schemaLocation == schemaLocation)
10036		return(cur);
10037	}
10038    }
10039    return(NULL);
10040}
10041
10042static xmlSchemaBucketPtr
10043xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10044				     const xmlChar *schemaLocation,
10045				     const xmlChar *targetNamespace)
10046{
10047    xmlSchemaBucketPtr cur;
10048    xmlSchemaItemListPtr list;
10049
10050    list = pctxt->constructor->buckets;
10051    if (list->nbItems == 0)
10052	return(NULL);
10053    else {
10054	int i;
10055	for (i = 0; i < list->nbItems; i++) {
10056	    cur = (xmlSchemaBucketPtr) list->items[i];
10057	    /* Pointer comparison! */
10058	    if ((cur->origTargetNamespace == NULL) &&
10059		(cur->schemaLocation == schemaLocation) &&
10060		(cur->targetNamespace == targetNamespace))
10061		return(cur);
10062	}
10063    }
10064    return(NULL);
10065}
10066
10067
10068#define IS_BAD_SCHEMA_DOC(b) \
10069    (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10070
10071static xmlSchemaBucketPtr
10072xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10073				 const xmlChar *targetNamespace,
10074				 int imported)
10075{
10076    xmlSchemaBucketPtr cur;
10077    xmlSchemaItemListPtr list;
10078
10079    list = pctxt->constructor->buckets;
10080    if (list->nbItems == 0)
10081	return(NULL);
10082    else {
10083	int i;
10084	for (i = 0; i < list->nbItems; i++) {
10085	    cur = (xmlSchemaBucketPtr) list->items[i];
10086	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10087		(cur->origTargetNamespace == targetNamespace) &&
10088		((imported && cur->imported) ||
10089		 ((!imported) && (!cur->imported))))
10090		return(cur);
10091	}
10092    }
10093    return(NULL);
10094}
10095
10096static int
10097xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10098		     xmlSchemaPtr schema,
10099		     xmlSchemaBucketPtr bucket)
10100{
10101    int oldFlags;
10102    xmlDocPtr oldDoc;
10103    xmlNodePtr node;
10104    int ret, oldErrs;
10105    xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10106
10107    /*
10108    * Save old values; reset the *main* schema.
10109    * URGENT TODO: This is not good; move the per-document information
10110    * to the parser. Get rid of passing the main schema to the
10111    * parsing functions.
10112    */
10113    oldFlags = schema->flags;
10114    oldDoc = schema->doc;
10115    if (schema->flags != 0)
10116	xmlSchemaClearSchemaDefaults(schema);
10117    schema->doc = bucket->doc;
10118    pctxt->schema = schema;
10119    /*
10120    * Keep the current target namespace on the parser *not* on the
10121    * main schema.
10122    */
10123    pctxt->targetNamespace = bucket->targetNamespace;
10124    WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10125
10126    if ((bucket->targetNamespace != NULL) &&
10127	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10128	/*
10129	* We are parsing the schema for schemas!
10130	*/
10131	pctxt->isS4S = 1;
10132    }
10133    /* Mark it as parsed, even if parsing fails. */
10134    bucket->parsed++;
10135    /* Compile the schema doc. */
10136    node = xmlDocGetRootElement(bucket->doc);
10137    ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10138    if (ret != 0)
10139	goto exit;
10140    /* An empty schema; just get out. */
10141    if (node->children == NULL)
10142	goto exit;
10143    oldErrs = pctxt->nberrors;
10144    ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10145    if (ret != 0)
10146	goto exit;
10147    /*
10148    * TODO: Not nice, but I'm not 100% sure we will get always an error
10149    * as a result of the obove functions; so better rely on pctxt->err
10150    * as well.
10151    */
10152    if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10153	ret = pctxt->err;
10154	goto exit;
10155    }
10156
10157exit:
10158    WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10159    /* Restore schema values. */
10160    schema->doc = oldDoc;
10161    schema->flags = oldFlags;
10162    return(ret);
10163}
10164
10165static int
10166xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10167		     xmlSchemaPtr schema,
10168		     xmlSchemaBucketPtr bucket)
10169{
10170    xmlSchemaParserCtxtPtr newpctxt;
10171    int res = 0;
10172
10173    if (bucket == NULL)
10174	return(0);
10175    if (bucket->parsed) {
10176	PERROR_INT("xmlSchemaParseNewDoc",
10177	    "reparsing a schema doc");
10178	return(-1);
10179    }
10180    if (bucket->doc == NULL) {
10181	PERROR_INT("xmlSchemaParseNewDoc",
10182	    "parsing a schema doc, but there's no doc");
10183	return(-1);
10184    }
10185    if (pctxt->constructor == NULL) {
10186	PERROR_INT("xmlSchemaParseNewDoc",
10187	    "no constructor");
10188	return(-1);
10189    }
10190    /* Create and init the temporary parser context. */
10191    newpctxt = xmlSchemaNewParserCtxtUseDict(
10192	(const char *) bucket->schemaLocation, pctxt->dict);
10193    if (newpctxt == NULL)
10194	return(-1);
10195    newpctxt->constructor = pctxt->constructor;
10196    /*
10197    * TODO: Can we avoid that the parser knows about the main schema?
10198    * It would be better if he knows about the current schema bucket
10199    * only.
10200    */
10201    newpctxt->schema = schema;
10202    xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10203	pctxt->errCtxt);
10204    xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10205	pctxt->errCtxt);
10206    newpctxt->counter = pctxt->counter;
10207
10208
10209    res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10210
10211    /* Channel back errors and cleanup the temporary parser context. */
10212    if (res != 0)
10213	pctxt->err = res;
10214    pctxt->nberrors += newpctxt->nberrors;
10215    pctxt->counter = newpctxt->counter;
10216    newpctxt->constructor = NULL;
10217    /* Free the parser context. */
10218    xmlSchemaFreeParserCtxt(newpctxt);
10219    return(res);
10220}
10221
10222static void
10223xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10224				xmlSchemaSchemaRelationPtr rel)
10225{
10226    xmlSchemaSchemaRelationPtr cur = bucket->relations;
10227
10228    if (cur == NULL) {
10229	bucket->relations = rel;
10230	return;
10231    }
10232    while (cur->next != NULL)
10233	cur = cur->next;
10234    cur->next = rel;
10235}
10236
10237
10238static const xmlChar *
10239xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10240			  xmlNodePtr ctxtNode)
10241{
10242    /*
10243    * Build an absolue location URI.
10244    */
10245    if (location != NULL) {
10246	if (ctxtNode == NULL)
10247	    return(location);
10248	else {
10249	    xmlChar *base, *URI;
10250	    const xmlChar *ret = NULL;
10251
10252	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10253	    if (base == NULL) {
10254		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10255	    } else {
10256		URI = xmlBuildURI(location, base);
10257		xmlFree(base);
10258	    }
10259	    if (URI != NULL) {
10260		ret = xmlDictLookup(dict, URI, -1);
10261		xmlFree(URI);
10262		return(ret);
10263	    }
10264	}
10265    }
10266    return(NULL);
10267}
10268
10269
10270
10271/**
10272 * xmlSchemaAddSchemaDoc:
10273 * @pctxt:  a schema validation context
10274 * @schema:  the schema being built
10275 * @node:  a subtree containing XML Schema informations
10276 *
10277 * Parse an included (and to-be-redefined) XML schema document.
10278 *
10279 * Returns 0 on success, a positive error code on errors and
10280 *         -1 in case of an internal or API error.
10281 */
10282
10283static int
10284xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10285		int type, /* import or include or redefine */
10286		const xmlChar *schemaLocation,
10287		xmlDocPtr schemaDoc,
10288		const char *schemaBuffer,
10289		int schemaBufferLen,
10290		xmlNodePtr invokingNode,
10291		const xmlChar *sourceTargetNamespace,
10292		const xmlChar *importNamespace,
10293		xmlSchemaBucketPtr *bucket)
10294{
10295    const xmlChar *targetNamespace = NULL;
10296    xmlSchemaSchemaRelationPtr relation = NULL;
10297    xmlDocPtr doc = NULL;
10298    int res = 0, err = 0, located = 0, preserveDoc = 0;
10299    xmlSchemaBucketPtr bkt = NULL;
10300
10301    if (bucket != NULL)
10302	*bucket = NULL;
10303
10304    switch (type) {
10305	case XML_SCHEMA_SCHEMA_IMPORT:
10306	case XML_SCHEMA_SCHEMA_MAIN:
10307	    err = XML_SCHEMAP_SRC_IMPORT;
10308	    break;
10309	case XML_SCHEMA_SCHEMA_INCLUDE:
10310	    err = XML_SCHEMAP_SRC_INCLUDE;
10311	    break;
10312	case XML_SCHEMA_SCHEMA_REDEFINE:
10313	    err = XML_SCHEMAP_SRC_REDEFINE;
10314	    break;
10315    }
10316
10317
10318    /* Special handling for the main schema:
10319    * skip the location and relation logic and just parse the doc.
10320    * We need just a bucket to be returned in this case.
10321    */
10322    if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10323	goto doc_load;
10324
10325    /* Note that we expect the location to be an absulute URI. */
10326    if (schemaLocation != NULL) {
10327	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10328	if ((bkt != NULL) &&
10329	    (pctxt->constructor->bucket == bkt)) {
10330	    /* Report self-imports/inclusions/redefinitions. */
10331
10332	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10333		invokingNode, NULL,
10334		"The schema must not import/include/redefine itself",
10335		NULL, NULL);
10336	    goto exit;
10337	}
10338    }
10339    /*
10340    * Create a relation for the graph of schemas.
10341    */
10342    relation = xmlSchemaSchemaRelationCreate();
10343    if (relation == NULL)
10344	return(-1);
10345    xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10346	relation);
10347    relation->type = type;
10348
10349    /*
10350    * Save the namespace import information.
10351    */
10352    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10353	relation->importNamespace = importNamespace;
10354	if (schemaLocation == NULL) {
10355	    /*
10356	    * No location; this is just an import of the namespace.
10357	    * Note that we don't assign a bucket to the relation
10358	    * in this case.
10359	    */
10360	    goto exit;
10361	}
10362	targetNamespace = importNamespace;
10363    }
10364
10365    /* Did we already fetch the doc? */
10366    if (bkt != NULL) {
10367	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10368	    /*
10369	    * We included/redefined and then try to import a schema,
10370	    * but the new location provided for import was different.
10371	    */
10372	    if (schemaLocation == NULL)
10373		schemaLocation = BAD_CAST "in_memory_buffer";
10374	    if (!xmlStrEqual(schemaLocation,
10375		bkt->schemaLocation)) {
10376		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10377		    invokingNode, NULL,
10378		    "The schema document '%s' cannot be imported, since "
10379		    "it was already included or redefined",
10380		    schemaLocation, NULL);
10381		goto exit;
10382	    }
10383	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10384	    /*
10385	    * We imported and then try to include/redefine a schema,
10386	    * but the new location provided for the include/redefine
10387	    * was different.
10388	    */
10389	    if (schemaLocation == NULL)
10390		schemaLocation = BAD_CAST "in_memory_buffer";
10391	    if (!xmlStrEqual(schemaLocation,
10392		bkt->schemaLocation)) {
10393		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10394		    invokingNode, NULL,
10395		    "The schema document '%s' cannot be included or "
10396		    "redefined, since it was already imported",
10397		    schemaLocation, NULL);
10398		goto exit;
10399	    }
10400	}
10401    }
10402
10403    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10404	/*
10405	* Given that the schemaLocation [attribute] is only a hint, it is open
10406	* to applications to ignore all but the first <import> for a given
10407	* namespace, regardless of the `actual value` of schemaLocation, but
10408	* such a strategy risks missing useful information when new
10409	* schemaLocations are offered.
10410	*
10411	* We will use the first <import> that comes with a location.
10412	* Further <import>s *with* a location, will result in an error.
10413	* TODO: Better would be to just report a warning here, but
10414	* we'll try it this way until someone complains.
10415	*
10416	* Schema Document Location Strategy:
10417	* 3 Based on the namespace name, identify an existing schema document,
10418	* either as a resource which is an XML document or a <schema> element
10419	* information item, in some local schema repository;
10420	* 5 Attempt to resolve the namespace name to locate such a resource.
10421	*
10422	* NOTE: (3) and (5) are not supported.
10423	*/
10424	if (bkt != NULL) {
10425	    relation->bucket = bkt;
10426	    goto exit;
10427	}
10428	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10429	    importNamespace, 1);
10430
10431	if (bkt != NULL) {
10432	    relation->bucket = bkt;
10433	    if (bkt->schemaLocation == NULL) {
10434		/* First given location of the schema; load the doc. */
10435		bkt->schemaLocation = schemaLocation;
10436	    } else {
10437		if (!xmlStrEqual(schemaLocation,
10438		    bkt->schemaLocation)) {
10439		    /*
10440		    * Additional location given; just skip it.
10441		    * URGENT TODO: We should report a warning here.
10442		    * res = XML_SCHEMAP_SRC_IMPORT;
10443		    */
10444		    if (schemaLocation == NULL)
10445			schemaLocation = BAD_CAST "in_memory_buffer";
10446
10447		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10448			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10449			invokingNode, NULL,
10450			"Skipping import of schema located at '%s' for the "
10451			"namespace '%s', since this namespace was already "
10452			"imported with the schema located at '%s'",
10453			schemaLocation, importNamespace, bkt->schemaLocation);
10454		}
10455		goto exit;
10456	    }
10457	}
10458	/*
10459	* No bucket + first location: load the doc and create a
10460	* bucket.
10461	*/
10462    } else {
10463	/* <include> and <redefine> */
10464	if (bkt != NULL) {
10465
10466	    if ((bkt->origTargetNamespace == NULL) &&
10467		(bkt->targetNamespace != sourceTargetNamespace)) {
10468		xmlSchemaBucketPtr chamel;
10469
10470		/*
10471		* Chameleon include/redefine: skip loading only if it was
10472		* aleady build for the targetNamespace of the including
10473		* schema.
10474		*/
10475		/*
10476		* URGENT TODO: If the schema is a chameleon-include then copy
10477		* the components into the including schema and modify the
10478		* targetNamespace of those components, do nothing otherwise.
10479		* NOTE: This is currently worked-around by compiling the
10480		* chameleon for every destinct including targetNamespace; thus
10481		* not performant at the moment.
10482		* TODO: Check when the namespace in wildcards for chameleons
10483		* needs to be converted: before we built wildcard intersections
10484		* or after.
10485		*   Answer: after!
10486		*/
10487		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10488		    schemaLocation, sourceTargetNamespace);
10489		if (chamel != NULL) {
10490		    /* A fitting chameleon was already parsed; NOP. */
10491		    relation->bucket = chamel;
10492		    goto exit;
10493		}
10494		/*
10495		* We need to parse the chameleon again for a different
10496		* targetNamespace.
10497		* CHAMELEON TODO: Optimize this by only parsing the
10498		* chameleon once, and then copying the components to
10499		* the new targetNamespace.
10500		*/
10501		bkt = NULL;
10502	    } else {
10503		relation->bucket = bkt;
10504		goto exit;
10505	    }
10506	}
10507    }
10508    if ((bkt != NULL) && (bkt->doc != NULL)) {
10509	PERROR_INT("xmlSchemaAddSchemaDoc",
10510	    "trying to load a schema doc, but a doc is already "
10511	    "assigned to the schema bucket");
10512	goto exit_failure;
10513    }
10514
10515doc_load:
10516    /*
10517    * Load the document.
10518    */
10519    if (schemaDoc != NULL) {
10520	doc = schemaDoc;
10521	/* Don' free this one, since it was provided by the caller. */
10522	preserveDoc = 1;
10523	/* TODO: Does the context or the doc hold the location? */
10524	if (schemaDoc->URL != NULL)
10525	    schemaLocation = xmlDictLookup(pctxt->dict,
10526		schemaDoc->URL, -1);
10527        else
10528	    schemaLocation = BAD_CAST "in_memory_buffer";
10529    } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10530	xmlParserCtxtPtr parserCtxt;
10531
10532	parserCtxt = xmlNewParserCtxt();
10533	if (parserCtxt == NULL) {
10534	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10535		"allocating a parser context", NULL);
10536	    goto exit_failure;
10537	}
10538	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10539	    /*
10540	    * TODO: Do we have to burden the schema parser dict with all
10541	    * the content of the schema doc?
10542	    */
10543	    xmlDictFree(parserCtxt->dict);
10544	    parserCtxt->dict = pctxt->dict;
10545	    xmlDictReference(parserCtxt->dict);
10546	}
10547	if (schemaLocation != NULL) {
10548	    /* Parse from file. */
10549	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10550		NULL, SCHEMAS_PARSE_OPTIONS);
10551	} else if (schemaBuffer != NULL) {
10552	    /* Parse from memory buffer. */
10553	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10554		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10555	    schemaLocation = BAD_CAST "in_memory_buffer";
10556	    if (doc != NULL)
10557		doc->URL = xmlStrdup(schemaLocation);
10558	}
10559	/*
10560	* For <import>:
10561	* 2.1 The referent is (a fragment of) a resource which is an
10562	* XML document (see clause 1.1), which in turn corresponds to
10563	* a <schema> element information item in a well-formed information
10564	* set, which in turn corresponds to a valid schema.
10565	* TODO: (2.1) fragments of XML documents are not supported.
10566	*
10567	* 2.2 The referent is a <schema> element information item in
10568	* a well-formed information set, which in turn corresponds
10569	* to a valid schema.
10570	* TODO: (2.2) is not supported.
10571	*/
10572	if (doc == NULL) {
10573	    xmlErrorPtr lerr;
10574	    lerr = xmlGetLastError();
10575	    /*
10576	    * Check if this a parser error, or if the document could
10577	    * just not be located.
10578	    * TODO: Try to find specific error codes to react only on
10579	    * localisation failures.
10580	    */
10581	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10582		/*
10583		* We assume a parser error here.
10584		*/
10585		located = 1;
10586		/* TODO: Error code ?? */
10587		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10588		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10589		    invokingNode, NULL,
10590		    "Failed to parse the XML resource '%s'",
10591		    schemaLocation, NULL);
10592	    }
10593	}
10594	xmlFreeParserCtxt(parserCtxt);
10595	if ((doc == NULL) && located)
10596	    goto exit_error;
10597    } else {
10598	xmlSchemaPErr(pctxt, NULL,
10599	    XML_SCHEMAP_NOTHING_TO_PARSE,
10600	    "No information for parsing was provided with the "
10601	    "given schema parser context.\n",
10602	    NULL, NULL);
10603	goto exit_failure;
10604    }
10605    /*
10606    * Preprocess the document.
10607    */
10608    if (doc != NULL) {
10609	xmlNodePtr docElem = NULL;
10610
10611	located = 1;
10612	docElem = xmlDocGetRootElement(doc);
10613	if (docElem == NULL) {
10614	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10615		invokingNode, NULL,
10616		"The document '%s' has no document element",
10617		schemaLocation, NULL);
10618	    goto exit_error;
10619	}
10620	/*
10621	* Remove all the blank text nodes.
10622	*/
10623	xmlSchemaCleanupDoc(pctxt, docElem);
10624	/*
10625	* Check the schema's top level element.
10626	*/
10627	if (!IS_SCHEMA(docElem, "schema")) {
10628	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10629		invokingNode, NULL,
10630		"The XML document '%s' is not a schema document",
10631		schemaLocation, NULL);
10632	    goto exit_error;
10633	}
10634	/*
10635	* Note that we don't apply a type check for the
10636	* targetNamespace value here.
10637	*/
10638	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10639	    "targetNamespace");
10640    }
10641
10642/* after_doc_loading: */
10643    if ((bkt == NULL) && located) {
10644	/* Only create a bucket if the schema was located. */
10645        bkt = xmlSchemaBucketCreate(pctxt, type,
10646	    targetNamespace);
10647	if (bkt == NULL)
10648	    goto exit_failure;
10649    }
10650    if (bkt != NULL) {
10651	bkt->schemaLocation = schemaLocation;
10652	bkt->located = located;
10653	if (doc != NULL) {
10654	    bkt->doc = doc;
10655	    bkt->targetNamespace = targetNamespace;
10656	    bkt->origTargetNamespace = targetNamespace;
10657	    if (preserveDoc)
10658		bkt->preserveDoc = 1;
10659	}
10660	if (WXS_IS_BUCKET_IMPMAIN(type))
10661	    bkt->imported++;
10662	    /*
10663	    * Add it to the graph of schemas.
10664	    */
10665	if (relation != NULL)
10666	    relation->bucket = bkt;
10667    }
10668
10669exit:
10670    /*
10671    * Return the bucket explicitely; this is needed for the
10672    * main schema.
10673    */
10674    if (bucket != NULL)
10675	*bucket = bkt;
10676    return (0);
10677
10678exit_error:
10679    if ((doc != NULL) && (! preserveDoc)) {
10680	xmlFreeDoc(doc);
10681	if (bkt != NULL)
10682	    bkt->doc = NULL;
10683    }
10684    return(pctxt->err);
10685
10686exit_failure:
10687    if ((doc != NULL) && (! preserveDoc)) {
10688	xmlFreeDoc(doc);
10689	if (bkt != NULL)
10690	    bkt->doc = NULL;
10691    }
10692    return (-1);
10693}
10694
10695/**
10696 * xmlSchemaParseImport:
10697 * @ctxt:  a schema validation context
10698 * @schema:  the schema being built
10699 * @node:  a subtree containing XML Schema informations
10700 *
10701 * parse a XML schema Import definition
10702 * *WARNING* this interface is highly subject to change
10703 *
10704 * Returns 0 in case of success, a positive error code if
10705 * not valid and -1 in case of an internal error.
10706 */
10707static int
10708xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10709                     xmlNodePtr node)
10710{
10711    xmlNodePtr child;
10712    const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10713    const xmlChar *thisTargetNamespace;
10714    xmlAttrPtr attr;
10715    int ret = 0;
10716    xmlSchemaBucketPtr bucket = NULL;
10717
10718    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10719        return (-1);
10720
10721    /*
10722    * Check for illegal attributes.
10723    */
10724    attr = node->properties;
10725    while (attr != NULL) {
10726	if (attr->ns == NULL) {
10727	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10728		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10729		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10730		xmlSchemaPIllegalAttrErr(pctxt,
10731		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10732	    }
10733	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10734	    xmlSchemaPIllegalAttrErr(pctxt,
10735		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10736	}
10737	attr = attr->next;
10738    }
10739    /*
10740    * Extract and validate attributes.
10741    */
10742    if (xmlSchemaPValAttr(pctxt, NULL, node,
10743	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10744	&namespaceName) != 0) {
10745	xmlSchemaPSimpleTypeErr(pctxt,
10746	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10747	    NULL, node,
10748	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10749	    NULL, namespaceName, NULL, NULL, NULL);
10750	return (pctxt->err);
10751    }
10752
10753    if (xmlSchemaPValAttr(pctxt, NULL, node,
10754	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10755	&schemaLocation) != 0) {
10756	xmlSchemaPSimpleTypeErr(pctxt,
10757	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10758	    NULL, node,
10759	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10760	    NULL, schemaLocation, NULL, NULL, NULL);
10761	return (pctxt->err);
10762    }
10763    /*
10764    * And now for the children...
10765    */
10766    child = node->children;
10767    if (IS_SCHEMA(child, "annotation")) {
10768        /*
10769         * the annotation here is simply discarded ...
10770	 * TODO: really?
10771         */
10772        child = child->next;
10773    }
10774    if (child != NULL) {
10775	xmlSchemaPContentErr(pctxt,
10776	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10777	    NULL, node, child, NULL,
10778	    "(annotation?)");
10779    }
10780    /*
10781    * Apply additional constraints.
10782    *
10783    * Note that it is important to use the original @targetNamespace
10784    * (or none at all), to rule out imports of schemas _with_ a
10785    * @targetNamespace if the importing schema is a chameleon schema
10786    * (with no @targetNamespace).
10787    */
10788    thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10789    if (namespaceName != NULL) {
10790	/*
10791	* 1.1 If the namespace [attribute] is present, then its `actual value`
10792	* must not match the `actual value` of the enclosing <schema>'s
10793	* targetNamespace [attribute].
10794	*/
10795	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10796	    xmlSchemaPCustomErr(pctxt,
10797		XML_SCHEMAP_SRC_IMPORT_1_1,
10798		NULL, node,
10799		"The value of the attribute 'namespace' must not match "
10800		"the target namespace '%s' of the importing schema",
10801		thisTargetNamespace);
10802	    return (pctxt->err);
10803	}
10804    } else {
10805	/*
10806	* 1.2 If the namespace [attribute] is not present, then the enclosing
10807	* <schema> must have a targetNamespace [attribute].
10808	*/
10809	if (thisTargetNamespace == NULL) {
10810	    xmlSchemaPCustomErr(pctxt,
10811		XML_SCHEMAP_SRC_IMPORT_1_2,
10812		NULL, node,
10813		"The attribute 'namespace' must be existent if "
10814		"the importing schema has no target namespace",
10815		NULL);
10816	    return (pctxt->err);
10817	}
10818    }
10819    /*
10820    * Locate and acquire the schema document.
10821    */
10822    if (schemaLocation != NULL)
10823	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10824	    schemaLocation, node);
10825    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10826	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10827	namespaceName, &bucket);
10828
10829    if (ret != 0)
10830	return(ret);
10831
10832    /*
10833    * For <import>: "It is *not* an error for the application
10834    * schema reference strategy to fail."
10835    * So just don't parse if no schema document was found.
10836    * Note that we will get no bucket if the schema could not be
10837    * located or if there was no schemaLocation.
10838    */
10839    if ((bucket == NULL) && (schemaLocation != NULL)) {
10840	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10841	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10842	    node, NULL,
10843	    "Failed to locate a schema at location '%s'. "
10844	    "Skipping the import", schemaLocation, NULL, NULL);
10845    }
10846
10847    if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10848	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10849    }
10850
10851    return (ret);
10852}
10853
10854static int
10855xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10856				     xmlSchemaPtr schema,
10857				     xmlNodePtr node,
10858				     xmlChar **schemaLocation,
10859				     int type)
10860{
10861    xmlAttrPtr attr;
10862
10863    if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10864	(schemaLocation == NULL))
10865        return (-1);
10866
10867    *schemaLocation = NULL;
10868    /*
10869    * Check for illegal attributes.
10870    * Applies for both <include> and <redefine>.
10871    */
10872    attr = node->properties;
10873    while (attr != NULL) {
10874	if (attr->ns == NULL) {
10875	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10876		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10877		xmlSchemaPIllegalAttrErr(pctxt,
10878		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10879	    }
10880	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10881	    xmlSchemaPIllegalAttrErr(pctxt,
10882		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10883	}
10884	attr = attr->next;
10885    }
10886    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10887    /*
10888    * Preliminary step, extract the URI-Reference and make an URI
10889    * from the base.
10890    */
10891    /*
10892    * Attribute "schemaLocation" is mandatory.
10893    */
10894    attr = xmlSchemaGetPropNode(node, "schemaLocation");
10895    if (attr != NULL) {
10896        xmlChar *base = NULL;
10897        xmlChar *uri = NULL;
10898
10899	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10900	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10901	    (const xmlChar **) schemaLocation) != 0)
10902	    goto exit_error;
10903	base = xmlNodeGetBase(node->doc, node);
10904	if (base == NULL) {
10905	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10906	} else {
10907	    uri = xmlBuildURI(*schemaLocation, base);
10908	    xmlFree(base);
10909	}
10910	if (uri == NULL) {
10911	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10912		"could not build an URI from the schemaLocation")
10913	    goto exit_failure;
10914	}
10915	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10916	xmlFree(uri);
10917    } else {
10918	xmlSchemaPMissingAttrErr(pctxt,
10919	    XML_SCHEMAP_S4S_ATTR_MISSING,
10920	    NULL, node, "schemaLocation", NULL);
10921	goto exit_error;
10922    }
10923    /*
10924    * Report self-inclusion and self-redefinition.
10925    */
10926    if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10927	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10928	    xmlSchemaPCustomErr(pctxt,
10929		XML_SCHEMAP_SRC_REDEFINE,
10930		NULL, node,
10931		"The schema document '%s' cannot redefine itself.",
10932		*schemaLocation);
10933	} else {
10934	    xmlSchemaPCustomErr(pctxt,
10935		XML_SCHEMAP_SRC_INCLUDE,
10936		NULL, node,
10937		"The schema document '%s' cannot include itself.",
10938		*schemaLocation);
10939	}
10940	goto exit_error;
10941    }
10942
10943    return(0);
10944exit_error:
10945    return(pctxt->err);
10946exit_failure:
10947    return(-1);
10948}
10949
10950static int
10951xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10952				xmlSchemaPtr schema,
10953				xmlNodePtr node,
10954				int type)
10955{
10956    xmlNodePtr child = NULL;
10957    const xmlChar *schemaLocation = NULL;
10958    int res = 0; /* hasRedefinitions = 0 */
10959    int isChameleon = 0, wasChameleon = 0;
10960    xmlSchemaBucketPtr bucket = NULL;
10961
10962    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10963        return (-1);
10964
10965    /*
10966    * Parse attributes. Note that the returned schemaLocation will
10967    * be already converted to an absolute URI.
10968    */
10969    res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10970	node, (xmlChar **) (&schemaLocation), type);
10971    if (res != 0)
10972	return(res);
10973    /*
10974    * Load and add the schema document.
10975    */
10976    res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10977	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10978    if (res != 0)
10979	return(res);
10980    /*
10981    * If we get no schema bucket back, then this means that the schema
10982    * document could not be located or was broken XML or was not
10983    * a schema document.
10984    */
10985    if ((bucket == NULL) || (bucket->doc == NULL)) {
10986	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10987	    /*
10988	    * WARNING for <include>:
10989	    * We will raise an error if the schema cannot be located
10990	    * for inclusions, since the that was the feedback from the
10991	    * schema people. I.e. the following spec piece will *not* be
10992	    * satisfied:
10993	    * SPEC src-include: "It is not an error for the `actual value` of the
10994	    * schemaLocation [attribute] to fail to resolve it all, in which
10995	    * case no corresponding inclusion is performed.
10996	    * So do we need a warning report here?"
10997	    */
10998	    res = XML_SCHEMAP_SRC_INCLUDE;
10999	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11000		node, NULL,
11001		"Failed to load the document '%s' for inclusion",
11002		schemaLocation, NULL);
11003	} else {
11004	    /*
11005	    * NOTE: This was changed to raise an error even if no redefinitions
11006	    * are specified.
11007	    *
11008	    * SPEC src-redefine (1)
11009	    * "If there are any element information items among the [children]
11010	    * other than <annotation> then the `actual value` of the
11011	    * schemaLocation [attribute] must successfully resolve."
11012	    * TODO: Ask the WG if a the location has always to resolve
11013	    * here as well!
11014	    */
11015	    res = XML_SCHEMAP_SRC_REDEFINE;
11016	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11017		node, NULL,
11018		"Failed to load the document '%s' for redefinition",
11019		schemaLocation, NULL);
11020	}
11021    } else {
11022	/*
11023	* Check targetNamespace sanity before parsing the new schema.
11024	* TODO: Note that we won't check further content if the
11025	* targetNamespace was bad.
11026	*/
11027	if (bucket->origTargetNamespace != NULL) {
11028	    /*
11029	    * SPEC src-include (2.1)
11030	    * "SII has a targetNamespace [attribute], and its `actual
11031	    * value` is identical to the `actual value` of the targetNamespace
11032	    * [attribute] of SII' (which must have such an [attribute])."
11033	    */
11034	    if (pctxt->targetNamespace == NULL) {
11035		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11036		    XML_SCHEMAP_SRC_INCLUDE,
11037		    node, NULL,
11038		    "The target namespace of the included/redefined schema "
11039		    "'%s' has to be absent, since the including/redefining "
11040		    "schema has no target namespace",
11041		    schemaLocation, NULL);
11042		goto exit_error;
11043	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11044		pctxt->targetNamespace)) {
11045		/* TODO: Change error function. */
11046		xmlSchemaPCustomErrExt(pctxt,
11047		    XML_SCHEMAP_SRC_INCLUDE,
11048		    NULL, node,
11049		    "The target namespace '%s' of the included/redefined "
11050		    "schema '%s' differs from '%s' of the "
11051		    "including/redefining schema",
11052		    bucket->origTargetNamespace, schemaLocation,
11053		    pctxt->targetNamespace);
11054		goto exit_error;
11055	    }
11056	} else if (pctxt->targetNamespace != NULL) {
11057	    /*
11058	    * Chameleons: the original target namespace will
11059	    * differ from the resulting namespace.
11060	    */
11061	    isChameleon = 1;
11062	    if (bucket->parsed &&
11063		bucket->origTargetNamespace != NULL) {
11064		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11065		    XML_SCHEMAP_SRC_INCLUDE,
11066		    node, NULL,
11067		    "The target namespace of the included/redefined schema "
11068		    "'%s' has to be absent or the same as the "
11069		    "including/redefining schema's target namespace",
11070		    schemaLocation, NULL);
11071		goto exit_error;
11072	    }
11073	    bucket->targetNamespace = pctxt->targetNamespace;
11074	}
11075    }
11076    /*
11077    * Parse the schema.
11078    */
11079    if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11080	if (isChameleon) {
11081	    /* TODO: Get rid of this flag on the schema itself. */
11082	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11083		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11084	    } else
11085		wasChameleon = 1;
11086	}
11087	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11088	/* Restore chameleon flag. */
11089	if (isChameleon && (!wasChameleon))
11090	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11091    }
11092    /*
11093    * And now for the children...
11094    */
11095    child = node->children;
11096    if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11097	/*
11098	* Parse (simpleType | complexType | group | attributeGroup))*
11099	*/
11100	pctxt->redefined = bucket;
11101	/*
11102	* How to proceed if the redefined schema was not located?
11103	*/
11104	pctxt->isRedefine = 1;
11105	while (IS_SCHEMA(child, "annotation") ||
11106	    IS_SCHEMA(child, "simpleType") ||
11107	    IS_SCHEMA(child, "complexType") ||
11108	    IS_SCHEMA(child, "group") ||
11109	    IS_SCHEMA(child, "attributeGroup")) {
11110	    if (IS_SCHEMA(child, "annotation")) {
11111		/*
11112		* TODO: discard or not?
11113		*/
11114	    } else if (IS_SCHEMA(child, "simpleType")) {
11115		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11116	    } else if (IS_SCHEMA(child, "complexType")) {
11117		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11118		/* hasRedefinitions = 1; */
11119	    } else if (IS_SCHEMA(child, "group")) {
11120		/* hasRedefinitions = 1; */
11121		xmlSchemaParseModelGroupDefinition(pctxt,
11122		    schema, child);
11123	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11124		/* hasRedefinitions = 1; */
11125		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11126		    child);
11127	    }
11128	    child = child->next;
11129	}
11130	pctxt->redefined = NULL;
11131	pctxt->isRedefine = 0;
11132    } else {
11133	if (IS_SCHEMA(child, "annotation")) {
11134	    /*
11135	    * TODO: discard or not?
11136	    */
11137	    child = child->next;
11138	}
11139    }
11140    if (child != NULL) {
11141	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11142	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11143	    xmlSchemaPContentErr(pctxt, res,
11144		NULL, node, child, NULL,
11145		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11146	} else {
11147	     xmlSchemaPContentErr(pctxt, res,
11148		NULL, node, child, NULL,
11149		"(annotation?)");
11150	}
11151    }
11152    return(res);
11153
11154exit_error:
11155    return(pctxt->err);
11156}
11157
11158static int
11159xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11160                       xmlNodePtr node)
11161{
11162    int res;
11163#ifndef ENABLE_REDEFINE
11164    TODO
11165    return(0);
11166#endif
11167    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11168	XML_SCHEMA_SCHEMA_REDEFINE);
11169    if (res != 0)
11170	return(res);
11171    return(0);
11172}
11173
11174static int
11175xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11176                       xmlNodePtr node)
11177{
11178    int res;
11179
11180    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11181	XML_SCHEMA_SCHEMA_INCLUDE);
11182    if (res != 0)
11183	return(res);
11184    return(0);
11185}
11186
11187/**
11188 * xmlSchemaParseModelGroup:
11189 * @ctxt:  a schema validation context
11190 * @schema:  the schema being built
11191 * @node:  a subtree containing XML Schema informations
11192 * @type: the "compositor" type
11193 * @particleNeeded: if a a model group with a particle
11194 *
11195 * parse a XML schema Sequence definition.
11196 * Applies parts of:
11197 *   Schema Representation Constraint:
11198 *     Redefinition Constraints and Semantics (src-redefine)
11199 *     (6.1), (6.1.1), (6.1.2)
11200 *
11201 *   Schema Component Constraint:
11202 *     All Group Limited (cos-all-limited) (2)
11203 *     TODO: Actually this should go to component-level checks,
11204 *     but is done here due to performance. Move it to an other layer
11205 *     is schema construction via an API is implemented.
11206 *
11207 * *WARNING* this interface is highly subject to change
11208 *
11209 * Returns -1 in case of error, 0 if the declaration is improper and
11210 *         1 in case of success.
11211 */
11212static xmlSchemaTreeItemPtr
11213xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11214			 xmlNodePtr node, xmlSchemaTypeType type,
11215			 int withParticle)
11216{
11217    xmlSchemaModelGroupPtr item;
11218    xmlSchemaParticlePtr particle = NULL;
11219    xmlNodePtr child = NULL;
11220    xmlAttrPtr attr;
11221    int min = 1, max = 1, isElemRef, hasRefs = 0;
11222
11223    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11224        return (NULL);
11225    /*
11226    * Create a model group with the given compositor.
11227    */
11228    item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11229    if (item == NULL)
11230	return (NULL);
11231
11232    if (withParticle) {
11233	if (type == XML_SCHEMA_TYPE_ALL) {
11234	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11235	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11236	} else {
11237	    /* choice + sequence */
11238	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11239	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11240		"(xs:nonNegativeInteger | unbounded)");
11241	}
11242	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11243	/*
11244	* Create a particle
11245	*/
11246	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11247	if (particle == NULL)
11248	    return (NULL);
11249	particle->children = (xmlSchemaTreeItemPtr) item;
11250	/*
11251	* Check for illegal attributes.
11252	*/
11253	attr = node->properties;
11254	while (attr != NULL) {
11255	    if (attr->ns == NULL) {
11256		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11257		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11258		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11259		    xmlSchemaPIllegalAttrErr(ctxt,
11260			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11261		}
11262	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11263		xmlSchemaPIllegalAttrErr(ctxt,
11264		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11265	    }
11266	    attr = attr->next;
11267	}
11268    } else {
11269	/*
11270	* Check for illegal attributes.
11271	*/
11272	attr = node->properties;
11273	while (attr != NULL) {
11274	    if (attr->ns == NULL) {
11275		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11276		    xmlSchemaPIllegalAttrErr(ctxt,
11277			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11278		}
11279	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11280		xmlSchemaPIllegalAttrErr(ctxt,
11281		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11282	    }
11283	    attr = attr->next;
11284	}
11285    }
11286
11287    /*
11288    * Extract and validate attributes.
11289    */
11290    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11291    /*
11292    * And now for the children...
11293    */
11294    child = node->children;
11295    if (IS_SCHEMA(child, "annotation")) {
11296        item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11297        child = child->next;
11298    }
11299    if (type == XML_SCHEMA_TYPE_ALL) {
11300	xmlSchemaParticlePtr part, last = NULL;
11301
11302	while (IS_SCHEMA(child, "element")) {
11303	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11304		schema, child, &isElemRef, 0);
11305	    /*
11306	    * SPEC cos-all-limited (2)
11307	    * "The {max occurs} of all the particles in the {particles}
11308	    * of the ('all') group must be 0 or 1.
11309	    */
11310	    if (part != NULL) {
11311		if (isElemRef)
11312		    hasRefs++;
11313		if (part->minOccurs > 1) {
11314		    xmlSchemaPCustomErr(ctxt,
11315			XML_SCHEMAP_COS_ALL_LIMITED,
11316			NULL, child,
11317			"Invalid value for minOccurs (must be 0 or 1)",
11318			NULL);
11319		    /* Reset to 1. */
11320		    part->minOccurs = 1;
11321		}
11322		if (part->maxOccurs > 1) {
11323		    xmlSchemaPCustomErr(ctxt,
11324			XML_SCHEMAP_COS_ALL_LIMITED,
11325			NULL, child,
11326			"Invalid value for maxOccurs (must be 0 or 1)",
11327			NULL);
11328		    /* Reset to 1. */
11329		    part->maxOccurs = 1;
11330		}
11331		if (last == NULL)
11332		    item->children = (xmlSchemaTreeItemPtr) part;
11333		else
11334		    last->next = (xmlSchemaTreeItemPtr) part;
11335		last = part;
11336	    }
11337	    child = child->next;
11338	}
11339	if (child != NULL) {
11340	    xmlSchemaPContentErr(ctxt,
11341		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11342		NULL, node, child, NULL,
11343		"(annotation?, (annotation?, element*)");
11344	}
11345    } else {
11346	/* choice + sequence */
11347	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11348
11349	while ((IS_SCHEMA(child, "element")) ||
11350	    (IS_SCHEMA(child, "group")) ||
11351	    (IS_SCHEMA(child, "any")) ||
11352	    (IS_SCHEMA(child, "choice")) ||
11353	    (IS_SCHEMA(child, "sequence"))) {
11354
11355	    if (IS_SCHEMA(child, "element")) {
11356		part = (xmlSchemaTreeItemPtr)
11357		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11358		if (part && isElemRef)
11359		    hasRefs++;
11360	    } else if (IS_SCHEMA(child, "group")) {
11361		part =
11362		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11363		if (part != NULL)
11364		    hasRefs++;
11365		/*
11366		* Handle redefinitions.
11367		*/
11368		if (ctxt->isRedefine && ctxt->redef &&
11369		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11370		    part && part->children)
11371		{
11372		    if ((xmlSchemaGetQNameRefName(part->children) ==
11373			    ctxt->redef->refName) &&
11374			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11375			    ctxt->redef->refTargetNs))
11376		    {
11377			/*
11378			* SPEC src-redefine:
11379			* (6.1) "If it has a <group> among its contents at
11380			* some level the `actual value` of whose ref
11381			* [attribute] is the same as the `actual value` of
11382			* its own name attribute plus target namespace, then
11383			* all of the following must be true:"
11384			* (6.1.1) "It must have exactly one such group."
11385			*/
11386			if (ctxt->redefCounter != 0) {
11387			    xmlChar *str = NULL;
11388
11389			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391				"The redefining model group definition "
11392				"'%s' must not contain more than one "
11393				"reference to the redefined definition",
11394				xmlSchemaFormatQName(&str,
11395				    ctxt->redef->refTargetNs,
11396				    ctxt->redef->refName),
11397				NULL);
11398			    FREE_AND_NULL(str)
11399			    part = NULL;
11400			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11401			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11402			{
11403			    xmlChar *str = NULL;
11404			    /*
11405			    * SPEC src-redefine:
11406			    * (6.1.2) "The `actual value` of both that
11407			    * group's minOccurs and maxOccurs [attribute]
11408			    * must be 1 (or `absent`).
11409			    */
11410			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11411				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11412				"The redefining model group definition "
11413				"'%s' must not contain a reference to the "
11414				"redefined definition with a "
11415				"maxOccurs/minOccurs other than 1",
11416				xmlSchemaFormatQName(&str,
11417				    ctxt->redef->refTargetNs,
11418				    ctxt->redef->refName),
11419				NULL);
11420			    FREE_AND_NULL(str)
11421			    part = NULL;
11422			}
11423			ctxt->redef->reference = WXS_BASIC_CAST part;
11424			ctxt->redefCounter++;
11425		    }
11426		}
11427	    } else if (IS_SCHEMA(child, "any")) {
11428		part = (xmlSchemaTreeItemPtr)
11429		    xmlSchemaParseAny(ctxt, schema, child);
11430	    } else if (IS_SCHEMA(child, "choice")) {
11431		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11432		    XML_SCHEMA_TYPE_CHOICE, 1);
11433	    } else if (IS_SCHEMA(child, "sequence")) {
11434		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11435		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11436	    }
11437	    if (part != NULL) {
11438		if (last == NULL)
11439		    item->children = part;
11440		else
11441		    last->next = part;
11442		last = part;
11443	    }
11444	    child = child->next;
11445	}
11446	if (child != NULL) {
11447	    xmlSchemaPContentErr(ctxt,
11448		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11449		NULL, node, child, NULL,
11450		"(annotation?, (element | group | choice | sequence | any)*)");
11451	}
11452    }
11453    if ((max == 0) && (min == 0))
11454	return (NULL);
11455    if (hasRefs) {
11456	/*
11457	* We need to resolve references.
11458	*/
11459	WXS_ADD_PENDING(ctxt, item);
11460    }
11461    if (withParticle)
11462	return ((xmlSchemaTreeItemPtr) particle);
11463    else
11464	return ((xmlSchemaTreeItemPtr) item);
11465}
11466
11467/**
11468 * xmlSchemaParseRestriction:
11469 * @ctxt:  a schema validation context
11470 * @schema:  the schema being built
11471 * @node:  a subtree containing XML Schema informations
11472 *
11473 * parse a XML schema Restriction definition
11474 * *WARNING* this interface is highly subject to change
11475 *
11476 * Returns the type definition or NULL in case of error
11477 */
11478static xmlSchemaTypePtr
11479xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11480                          xmlNodePtr node, xmlSchemaTypeType parentType)
11481{
11482    xmlSchemaTypePtr type;
11483    xmlNodePtr child = NULL;
11484    xmlAttrPtr attr;
11485
11486    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11487        return (NULL);
11488    /* Not a component, don't create it. */
11489    type = ctxt->ctxtType;
11490    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11491
11492    /*
11493    * Check for illegal attributes.
11494    */
11495    attr = node->properties;
11496    while (attr != NULL) {
11497	if (attr->ns == NULL) {
11498	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11499		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11500		xmlSchemaPIllegalAttrErr(ctxt,
11501		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11502	    }
11503	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11504	    xmlSchemaPIllegalAttrErr(ctxt,
11505		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11506	}
11507	attr = attr->next;
11508    }
11509    /*
11510    * Extract and validate attributes.
11511    */
11512    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11513    /*
11514    * Attribute
11515    */
11516    /*
11517    * Extract the base type. The "base" attribute is mandatory if inside
11518    * a complex type or if redefining.
11519    *
11520    * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11521    * among its [children]), the simple type definition which is
11522    * the {content type} of the type definition `resolved` to by
11523    * the `actual value` of the base [attribute]"
11524    */
11525    if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11526	&(type->baseNs), &(type->base)) == 0)
11527    {
11528	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11529	    xmlSchemaPMissingAttrErr(ctxt,
11530		XML_SCHEMAP_S4S_ATTR_MISSING,
11531		NULL, node, "base", NULL);
11532	} else if ((ctxt->isRedefine) &&
11533	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11534	{
11535	    if (type->base == NULL) {
11536		xmlSchemaPMissingAttrErr(ctxt,
11537		    XML_SCHEMAP_S4S_ATTR_MISSING,
11538		    NULL, node, "base", NULL);
11539	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11540		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11541	    {
11542		xmlChar *str1 = NULL, *str2 = NULL;
11543		/*
11544		* REDEFINE: SPEC src-redefine (5)
11545		* "Within the [children], each <simpleType> must have a
11546		* <restriction> among its [children] ... the `actual value` of
11547		* whose base [attribute] must be the same as the `actual value`
11548		* of its own name attribute plus target namespace;"
11549		*/
11550		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11551		    NULL, node, "This is a redefinition, but the QName "
11552		    "value '%s' of the 'base' attribute does not match the "
11553		    "type's designation '%s'",
11554		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11555		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11556			type->name), NULL);
11557		FREE_AND_NULL(str1);
11558		FREE_AND_NULL(str2);
11559		/* Avoid confusion and erase the values. */
11560		type->base = NULL;
11561		type->baseNs = NULL;
11562	    }
11563	}
11564    }
11565    /*
11566    * And now for the children...
11567    */
11568    child = node->children;
11569    if (IS_SCHEMA(child, "annotation")) {
11570	/*
11571	* Add the annotation to the simple type ancestor.
11572	*/
11573	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11574	    xmlSchemaParseAnnotation(ctxt, child, 1));
11575        child = child->next;
11576    }
11577    if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11578	/*
11579	* Corresponds to <simpleType><restriction><simpleType>.
11580	*/
11581	if (IS_SCHEMA(child, "simpleType")) {
11582	    if (type->base != NULL) {
11583		/*
11584		* src-restriction-base-or-simpleType
11585		* Either the base [attribute] or the simpleType [child] of the
11586		* <restriction> element must be present, but not both.
11587		*/
11588		xmlSchemaPContentErr(ctxt,
11589		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11590		    NULL, node, child,
11591		    "The attribute 'base' and the <simpleType> child are "
11592		    "mutually exclusive", NULL);
11593	    } else {
11594		type->baseType = (xmlSchemaTypePtr)
11595		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11596	    }
11597	    child = child->next;
11598	} else if (type->base == NULL) {
11599	    xmlSchemaPContentErr(ctxt,
11600		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11601		NULL, node, child,
11602		"Either the attribute 'base' or a <simpleType> child "
11603		"must be present", NULL);
11604	}
11605    } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11606	/*
11607	* Corresponds to <complexType><complexContent><restriction>...
11608	* followed by:
11609	*
11610	* Model groups <all>, <choice> and <sequence>.
11611	*/
11612	if (IS_SCHEMA(child, "all")) {
11613	    type->subtypes = (xmlSchemaTypePtr)
11614		xmlSchemaParseModelGroup(ctxt, schema, child,
11615		    XML_SCHEMA_TYPE_ALL, 1);
11616	    child = child->next;
11617	} else if (IS_SCHEMA(child, "choice")) {
11618	    type->subtypes = (xmlSchemaTypePtr)
11619		xmlSchemaParseModelGroup(ctxt,
11620		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11621	    child = child->next;
11622	} else if (IS_SCHEMA(child, "sequence")) {
11623	    type->subtypes = (xmlSchemaTypePtr)
11624		xmlSchemaParseModelGroup(ctxt, schema, child,
11625		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11626	    child = child->next;
11627	/*
11628	* Model group reference <group>.
11629	*/
11630	} else if (IS_SCHEMA(child, "group")) {
11631	    type->subtypes = (xmlSchemaTypePtr)
11632		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11633	    /*
11634	    * Note that the reference will be resolved in
11635	    * xmlSchemaResolveTypeReferences();
11636	    */
11637	    child = child->next;
11638	}
11639    } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11640	/*
11641	* Corresponds to <complexType><simpleContent><restriction>...
11642	*
11643	* "1.1 the simple type definition corresponding to the <simpleType>
11644	* among the [children] of <restriction> if there is one;"
11645	*/
11646	if (IS_SCHEMA(child, "simpleType")) {
11647	    /*
11648	    * We will store the to-be-restricted simple type in
11649	    * type->contentTypeDef *temporarily*.
11650	    */
11651	    type->contentTypeDef = (xmlSchemaTypePtr)
11652		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11653	    if ( type->contentTypeDef == NULL)
11654		return (NULL);
11655	    child = child->next;
11656	}
11657    }
11658
11659    if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11660	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11661	xmlSchemaFacetPtr facet, lastfacet = NULL;
11662	/*
11663	* Corresponds to <complexType><simpleContent><restriction>...
11664	* <simpleType><restriction>...
11665	*/
11666
11667	/*
11668	* Add the facets to the simple type ancestor.
11669	*/
11670	/*
11671	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11672	* Simple Type Definition Schema Representation Constraint:
11673	* *Single Facet Value*
11674	*/
11675	while ((IS_SCHEMA(child, "minInclusive")) ||
11676	    (IS_SCHEMA(child, "minExclusive")) ||
11677	    (IS_SCHEMA(child, "maxInclusive")) ||
11678	    (IS_SCHEMA(child, "maxExclusive")) ||
11679	    (IS_SCHEMA(child, "totalDigits")) ||
11680	    (IS_SCHEMA(child, "fractionDigits")) ||
11681	    (IS_SCHEMA(child, "pattern")) ||
11682	    (IS_SCHEMA(child, "enumeration")) ||
11683	    (IS_SCHEMA(child, "whiteSpace")) ||
11684	    (IS_SCHEMA(child, "length")) ||
11685	    (IS_SCHEMA(child, "maxLength")) ||
11686	    (IS_SCHEMA(child, "minLength"))) {
11687	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11688	    if (facet != NULL) {
11689		if (lastfacet == NULL)
11690		    type->facets = facet;
11691		else
11692		    lastfacet->next = facet;
11693		lastfacet = facet;
11694		lastfacet->next = NULL;
11695	    }
11696	    child = child->next;
11697	}
11698	/*
11699	* Create links for derivation and validation.
11700	*/
11701	if (type->facets != NULL) {
11702	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11703
11704	    facet = type->facets;
11705	    do {
11706		facetLink = (xmlSchemaFacetLinkPtr)
11707		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11708		if (facetLink == NULL) {
11709		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11710		    xmlFree(facetLink);
11711		    return (NULL);
11712		}
11713		facetLink->facet = facet;
11714		facetLink->next = NULL;
11715		if (lastFacetLink == NULL)
11716		    type->facetSet = facetLink;
11717		else
11718		    lastFacetLink->next = facetLink;
11719		lastFacetLink = facetLink;
11720		facet = facet->next;
11721	    } while (facet != NULL);
11722	}
11723    }
11724    if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11725	/*
11726	* Attribute uses/declarations.
11727	*/
11728	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11729	    (xmlSchemaItemListPtr *) &(type->attrUses),
11730	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11731	    return(NULL);
11732	/*
11733	* Attribute wildcard.
11734	*/
11735	if (IS_SCHEMA(child, "anyAttribute")) {
11736	    type->attributeWildcard =
11737		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11738	    child = child->next;
11739	}
11740    }
11741    if (child != NULL) {
11742	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11743	    xmlSchemaPContentErr(ctxt,
11744		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11745		NULL, node, child, NULL,
11746		"annotation?, (group | all | choice | sequence)?, "
11747		"((attribute | attributeGroup)*, anyAttribute?))");
11748	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11749	     xmlSchemaPContentErr(ctxt,
11750		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11751		NULL, node, child, NULL,
11752		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11753		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11754		"length | minLength | maxLength | enumeration | whiteSpace | "
11755		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11756	} else {
11757	    /* Simple type */
11758	    xmlSchemaPContentErr(ctxt,
11759		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11760		NULL, node, child, NULL,
11761		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11762		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11763		"length | minLength | maxLength | enumeration | whiteSpace | "
11764		"pattern)*))");
11765	}
11766    }
11767    return (NULL);
11768}
11769
11770/**
11771 * xmlSchemaParseExtension:
11772 * @ctxt:  a schema validation context
11773 * @schema:  the schema being built
11774 * @node:  a subtree containing XML Schema informations
11775 *
11776 * Parses an <extension>, which is found inside a
11777 * <simpleContent> or <complexContent>.
11778 * *WARNING* this interface is highly subject to change.
11779 *
11780 * TODO: Returns the type definition or NULL in case of error
11781 */
11782static xmlSchemaTypePtr
11783xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11784                        xmlNodePtr node, xmlSchemaTypeType parentType)
11785{
11786    xmlSchemaTypePtr type;
11787    xmlNodePtr child = NULL;
11788    xmlAttrPtr attr;
11789
11790    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11791        return (NULL);
11792    /* Not a component, don't create it. */
11793    type = ctxt->ctxtType;
11794    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11795
11796    /*
11797    * Check for illegal attributes.
11798    */
11799    attr = node->properties;
11800    while (attr != NULL) {
11801	if (attr->ns == NULL) {
11802	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11803		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11804		xmlSchemaPIllegalAttrErr(ctxt,
11805		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11806	    }
11807	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11808	    xmlSchemaPIllegalAttrErr(ctxt,
11809		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11810	}
11811	attr = attr->next;
11812    }
11813
11814    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11815
11816    /*
11817    * Attribute "base" - mandatory.
11818    */
11819    if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11820	"base", &(type->baseNs), &(type->base)) == 0) &&
11821	(type->base == NULL)) {
11822	xmlSchemaPMissingAttrErr(ctxt,
11823	    XML_SCHEMAP_S4S_ATTR_MISSING,
11824	    NULL, node, "base", NULL);
11825    }
11826    /*
11827    * And now for the children...
11828    */
11829    child = node->children;
11830    if (IS_SCHEMA(child, "annotation")) {
11831	/*
11832	* Add the annotation to the type ancestor.
11833	*/
11834	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11835	    xmlSchemaParseAnnotation(ctxt, child, 1));
11836        child = child->next;
11837    }
11838    if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11839	/*
11840	* Corresponds to <complexType><complexContent><extension>... and:
11841	*
11842	* Model groups <all>, <choice>, <sequence> and <group>.
11843	*/
11844	if (IS_SCHEMA(child, "all")) {
11845	    type->subtypes = (xmlSchemaTypePtr)
11846		xmlSchemaParseModelGroup(ctxt, schema,
11847		    child, XML_SCHEMA_TYPE_ALL, 1);
11848	    child = child->next;
11849	} else if (IS_SCHEMA(child, "choice")) {
11850	    type->subtypes = (xmlSchemaTypePtr)
11851		xmlSchemaParseModelGroup(ctxt, schema,
11852		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11853	    child = child->next;
11854	} else if (IS_SCHEMA(child, "sequence")) {
11855	    type->subtypes = (xmlSchemaTypePtr)
11856		xmlSchemaParseModelGroup(ctxt, schema,
11857		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11858	    child = child->next;
11859	} else if (IS_SCHEMA(child, "group")) {
11860	    type->subtypes = (xmlSchemaTypePtr)
11861		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11862	    /*
11863	    * Note that the reference will be resolved in
11864	    * xmlSchemaResolveTypeReferences();
11865	    */
11866	    child = child->next;
11867	}
11868    }
11869    if (child != NULL) {
11870	/*
11871	* Attribute uses/declarations.
11872	*/
11873	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11874	    (xmlSchemaItemListPtr *) &(type->attrUses),
11875	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11876	    return(NULL);
11877	/*
11878	* Attribute wildcard.
11879	*/
11880	if (IS_SCHEMA(child, "anyAttribute")) {
11881	    ctxt->ctxtType->attributeWildcard =
11882		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11883	    child = child->next;
11884	}
11885    }
11886    if (child != NULL) {
11887	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11888	    /* Complex content extension. */
11889	    xmlSchemaPContentErr(ctxt,
11890		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11891		NULL, node, child, NULL,
11892		"(annotation?, ((group | all | choice | sequence)?, "
11893		"((attribute | attributeGroup)*, anyAttribute?)))");
11894	} else {
11895	    /* Simple content extension. */
11896	    xmlSchemaPContentErr(ctxt,
11897		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11898		NULL, node, child, NULL,
11899		"(annotation?, ((attribute | attributeGroup)*, "
11900		"anyAttribute?))");
11901	}
11902    }
11903    return (NULL);
11904}
11905
11906/**
11907 * xmlSchemaParseSimpleContent:
11908 * @ctxt:  a schema validation context
11909 * @schema:  the schema being built
11910 * @node:  a subtree containing XML Schema informations
11911 *
11912 * parse a XML schema SimpleContent definition
11913 * *WARNING* this interface is highly subject to change
11914 *
11915 * Returns the type definition or NULL in case of error
11916 */
11917static int
11918xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11919                            xmlSchemaPtr schema, xmlNodePtr node,
11920			    int *hasRestrictionOrExtension)
11921{
11922    xmlSchemaTypePtr type;
11923    xmlNodePtr child = NULL;
11924    xmlAttrPtr attr;
11925
11926    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11927	(hasRestrictionOrExtension == NULL))
11928        return (-1);
11929    *hasRestrictionOrExtension = 0;
11930    /* Not a component, don't create it. */
11931    type = ctxt->ctxtType;
11932    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11933    /*
11934    * Check for illegal attributes.
11935    */
11936    attr = node->properties;
11937    while (attr != NULL) {
11938	if (attr->ns == NULL) {
11939	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11940		xmlSchemaPIllegalAttrErr(ctxt,
11941		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11942	    }
11943	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11944	    xmlSchemaPIllegalAttrErr(ctxt,
11945		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11946	}
11947	attr = attr->next;
11948    }
11949
11950    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11951
11952    /*
11953    * And now for the children...
11954    */
11955    child = node->children;
11956    if (IS_SCHEMA(child, "annotation")) {
11957	/*
11958	* Add the annotation to the complex type ancestor.
11959	*/
11960	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11961	    xmlSchemaParseAnnotation(ctxt, child, 1));
11962        child = child->next;
11963    }
11964    if (child == NULL) {
11965	xmlSchemaPContentErr(ctxt,
11966	    XML_SCHEMAP_S4S_ELEM_MISSING,
11967	    NULL, node, NULL, NULL,
11968	    "(annotation?, (restriction | extension))");
11969    }
11970    if (child == NULL) {
11971	xmlSchemaPContentErr(ctxt,
11972	    XML_SCHEMAP_S4S_ELEM_MISSING,
11973	    NULL, node, NULL, NULL,
11974	    "(annotation?, (restriction | extension))");
11975    }
11976    if (IS_SCHEMA(child, "restriction")) {
11977        xmlSchemaParseRestriction(ctxt, schema, child,
11978	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11979	(*hasRestrictionOrExtension) = 1;
11980        child = child->next;
11981    } else if (IS_SCHEMA(child, "extension")) {
11982        xmlSchemaParseExtension(ctxt, schema, child,
11983	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11984	(*hasRestrictionOrExtension) = 1;
11985        child = child->next;
11986    }
11987    if (child != NULL) {
11988	xmlSchemaPContentErr(ctxt,
11989	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11990	    NULL, node, child, NULL,
11991	    "(annotation?, (restriction | extension))");
11992    }
11993    return (0);
11994}
11995
11996/**
11997 * xmlSchemaParseComplexContent:
11998 * @ctxt:  a schema validation context
11999 * @schema:  the schema being built
12000 * @node:  a subtree containing XML Schema informations
12001 *
12002 * parse a XML schema ComplexContent definition
12003 * *WARNING* this interface is highly subject to change
12004 *
12005 * Returns the type definition or NULL in case of error
12006 */
12007static int
12008xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12009                             xmlSchemaPtr schema, xmlNodePtr node,
12010			     int *hasRestrictionOrExtension)
12011{
12012    xmlSchemaTypePtr type;
12013    xmlNodePtr child = NULL;
12014    xmlAttrPtr attr;
12015
12016    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12017	(hasRestrictionOrExtension == NULL))
12018        return (-1);
12019    *hasRestrictionOrExtension = 0;
12020    /* Not a component, don't create it. */
12021    type = ctxt->ctxtType;
12022    /*
12023    * Check for illegal attributes.
12024    */
12025    attr = node->properties;
12026    while (attr != NULL) {
12027	if (attr->ns == NULL) {
12028	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12029		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12030	    {
12031		xmlSchemaPIllegalAttrErr(ctxt,
12032		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12033	    }
12034	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12035	    xmlSchemaPIllegalAttrErr(ctxt,
12036		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12037	}
12038	attr = attr->next;
12039    }
12040
12041    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12042
12043    /*
12044    * Set the 'mixed' on the complex type ancestor.
12045    */
12046    if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12047	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12048	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12049    }
12050    child = node->children;
12051    if (IS_SCHEMA(child, "annotation")) {
12052	/*
12053	* Add the annotation to the complex type ancestor.
12054	*/
12055	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12056	    xmlSchemaParseAnnotation(ctxt, child, 1));
12057        child = child->next;
12058    }
12059    if (child == NULL) {
12060	xmlSchemaPContentErr(ctxt,
12061	    XML_SCHEMAP_S4S_ELEM_MISSING,
12062	    NULL, node, NULL,
12063	    NULL, "(annotation?, (restriction | extension))");
12064    }
12065    if (child == NULL) {
12066	xmlSchemaPContentErr(ctxt,
12067	    XML_SCHEMAP_S4S_ELEM_MISSING,
12068	    NULL, node, NULL,
12069	    NULL, "(annotation?, (restriction | extension))");
12070    }
12071    if (IS_SCHEMA(child, "restriction")) {
12072        xmlSchemaParseRestriction(ctxt, schema, child,
12073	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12074	(*hasRestrictionOrExtension) = 1;
12075        child = child->next;
12076    } else if (IS_SCHEMA(child, "extension")) {
12077        xmlSchemaParseExtension(ctxt, schema, child,
12078	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12079	(*hasRestrictionOrExtension) = 1;
12080        child = child->next;
12081    }
12082    if (child != NULL) {
12083	xmlSchemaPContentErr(ctxt,
12084	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12085	    NULL, node, child,
12086	    NULL, "(annotation?, (restriction | extension))");
12087    }
12088    return (0);
12089}
12090
12091/**
12092 * xmlSchemaParseComplexType:
12093 * @ctxt:  a schema validation context
12094 * @schema:  the schema being built
12095 * @node:  a subtree containing XML Schema informations
12096 *
12097 * parse a XML schema Complex Type definition
12098 * *WARNING* this interface is highly subject to change
12099 *
12100 * Returns the type definition or NULL in case of error
12101 */
12102static xmlSchemaTypePtr
12103xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12104                          xmlNodePtr node, int topLevel)
12105{
12106    xmlSchemaTypePtr type, ctxtType;
12107    xmlNodePtr child = NULL;
12108    const xmlChar *name = NULL;
12109    xmlAttrPtr attr;
12110    const xmlChar *attrValue;
12111#ifdef ENABLE_NAMED_LOCALS
12112    char buf[40];
12113#endif
12114    int final = 0, block = 0, hasRestrictionOrExtension = 0;
12115
12116
12117    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12118        return (NULL);
12119
12120    ctxtType = ctxt->ctxtType;
12121
12122    if (topLevel) {
12123	attr = xmlSchemaGetPropNode(node, "name");
12124	if (attr == NULL) {
12125	    xmlSchemaPMissingAttrErr(ctxt,
12126		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12127	    return (NULL);
12128	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12129	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12130	    return (NULL);
12131	}
12132    }
12133
12134    if (topLevel == 0) {
12135	/*
12136	* Parse as local complex type definition.
12137	*/
12138#ifdef ENABLE_NAMED_LOCALS
12139        snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12140	type = xmlSchemaAddType(ctxt, schema,
12141	    XML_SCHEMA_TYPE_COMPLEX,
12142	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12143	    ctxt->targetNamespace, node, 0);
12144#else
12145	type = xmlSchemaAddType(ctxt, schema,
12146	    XML_SCHEMA_TYPE_COMPLEX,
12147	    NULL, ctxt->targetNamespace, node, 0);
12148#endif
12149	if (type == NULL)
12150	    return (NULL);
12151	name = type->name;
12152	type->node = node;
12153	type->type = XML_SCHEMA_TYPE_COMPLEX;
12154	/*
12155	* TODO: We need the target namespace.
12156	*/
12157    } else {
12158	/*
12159	* Parse as global complex type definition.
12160	*/
12161	type = xmlSchemaAddType(ctxt, schema,
12162	    XML_SCHEMA_TYPE_COMPLEX,
12163	    name, ctxt->targetNamespace, node, 1);
12164	if (type == NULL)
12165	    return (NULL);
12166	type->node = node;
12167	type->type = XML_SCHEMA_TYPE_COMPLEX;
12168	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12169    }
12170    type->targetNamespace = ctxt->targetNamespace;
12171    /*
12172    * Handle attributes.
12173    */
12174    attr = node->properties;
12175    while (attr != NULL) {
12176	if (attr->ns == NULL) {
12177	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12178		/*
12179		* Attribute "id".
12180		*/
12181		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12182	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12183		/*
12184		* Attribute "mixed".
12185		*/
12186		if (xmlSchemaPGetBoolNodeValue(ctxt,
12187			NULL, (xmlNodePtr) attr))
12188		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12189	    } else if (topLevel) {
12190		/*
12191		* Attributes of global complex type definitions.
12192		*/
12193		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12194		    /* Pass. */
12195		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12196		    /*
12197		    * Attribute "abstract".
12198		    */
12199		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12200			    NULL, (xmlNodePtr) attr))
12201			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12202		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12203		    /*
12204		    * Attribute "final".
12205		    */
12206		    attrValue = xmlSchemaGetNodeContent(ctxt,
12207			(xmlNodePtr) attr);
12208		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12209			&(type->flags),
12210			-1,
12211			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12212			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12213			-1, -1, -1) != 0)
12214		    {
12215			xmlSchemaPSimpleTypeErr(ctxt,
12216			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12217			    NULL, (xmlNodePtr) attr, NULL,
12218			    "(#all | List of (extension | restriction))",
12219			    attrValue, NULL, NULL, NULL);
12220		    } else
12221			final = 1;
12222		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12223		    /*
12224		    * Attribute "block".
12225		    */
12226		    attrValue = xmlSchemaGetNodeContent(ctxt,
12227			(xmlNodePtr) attr);
12228		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12229			-1,
12230			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12231			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12232			-1, -1, -1) != 0) {
12233			xmlSchemaPSimpleTypeErr(ctxt,
12234			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12235			    NULL, (xmlNodePtr) attr, NULL,
12236			    "(#all | List of (extension | restriction)) ",
12237			    attrValue, NULL, NULL, NULL);
12238		    } else
12239			block = 1;
12240		} else {
12241			xmlSchemaPIllegalAttrErr(ctxt,
12242			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12243		}
12244	    } else {
12245		xmlSchemaPIllegalAttrErr(ctxt,
12246		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12247	    }
12248	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12249	    xmlSchemaPIllegalAttrErr(ctxt,
12250		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12251	}
12252	attr = attr->next;
12253    }
12254    if (! block) {
12255	/*
12256	* Apply default "block" values.
12257	*/
12258	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12259	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12260	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12261	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12262    }
12263    if (! final) {
12264	/*
12265	* Apply default "block" values.
12266	*/
12267	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12268	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12269	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12270	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12271    }
12272    /*
12273    * And now for the children...
12274    */
12275    child = node->children;
12276    if (IS_SCHEMA(child, "annotation")) {
12277        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12278        child = child->next;
12279    }
12280    ctxt->ctxtType = type;
12281    if (IS_SCHEMA(child, "simpleContent")) {
12282	/*
12283	* <complexType><simpleContent>...
12284	* 3.4.3 : 2.2
12285	* Specifying mixed='true' when the <simpleContent>
12286	* alternative is chosen has no effect
12287	*/
12288	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12289	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12290        xmlSchemaParseSimpleContent(ctxt, schema, child,
12291	    &hasRestrictionOrExtension);
12292        child = child->next;
12293    } else if (IS_SCHEMA(child, "complexContent")) {
12294	/*
12295	* <complexType><complexContent>...
12296	*/
12297	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12298        xmlSchemaParseComplexContent(ctxt, schema, child,
12299	    &hasRestrictionOrExtension);
12300        child = child->next;
12301    } else {
12302	/*
12303	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12304	*
12305	* SPEC
12306	* "...the third alternative (neither <simpleContent> nor
12307	* <complexContent>) is chosen. This case is understood as shorthand
12308	* for complex content restricting the `ur-type definition`, and the
12309	* details of the mappings should be modified as necessary.
12310	*/
12311	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12312	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12313	/*
12314	* Parse model groups.
12315	*/
12316        if (IS_SCHEMA(child, "all")) {
12317            type->subtypes = (xmlSchemaTypePtr)
12318		xmlSchemaParseModelGroup(ctxt, schema, child,
12319		    XML_SCHEMA_TYPE_ALL, 1);
12320            child = child->next;
12321        } else if (IS_SCHEMA(child, "choice")) {
12322            type->subtypes = (xmlSchemaTypePtr)
12323		xmlSchemaParseModelGroup(ctxt, schema, child,
12324		    XML_SCHEMA_TYPE_CHOICE, 1);
12325            child = child->next;
12326        } else if (IS_SCHEMA(child, "sequence")) {
12327            type->subtypes = (xmlSchemaTypePtr)
12328		xmlSchemaParseModelGroup(ctxt, schema, child,
12329		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12330            child = child->next;
12331        } else if (IS_SCHEMA(child, "group")) {
12332            type->subtypes = (xmlSchemaTypePtr)
12333		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12334	    /*
12335	    * Note that the reference will be resolved in
12336	    * xmlSchemaResolveTypeReferences();
12337	    */
12338            child = child->next;
12339        }
12340	/*
12341	* Parse attribute decls/refs.
12342	*/
12343        if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12344	    (xmlSchemaItemListPtr *) &(type->attrUses),
12345	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12346	    return(NULL);
12347	/*
12348	* Parse attribute wildcard.
12349	*/
12350	if (IS_SCHEMA(child, "anyAttribute")) {
12351	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12352	    child = child->next;
12353	}
12354    }
12355    if (child != NULL) {
12356	xmlSchemaPContentErr(ctxt,
12357	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12358	    NULL, node, child,
12359	    NULL, "(annotation?, (simpleContent | complexContent | "
12360	    "((group | all | choice | sequence)?, ((attribute | "
12361	    "attributeGroup)*, anyAttribute?))))");
12362    }
12363    /*
12364    * REDEFINE: SPEC src-redefine (5)
12365    */
12366    if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12367	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12368	    NULL, node, "This is a redefinition, thus the "
12369	    "<complexType> must have a <restriction> or <extension> "
12370	    "grand-child", NULL);
12371    }
12372    ctxt->ctxtType = ctxtType;
12373    return (type);
12374}
12375
12376/************************************************************************
12377 *									*
12378 *			Validating using Schemas			*
12379 *									*
12380 ************************************************************************/
12381
12382/************************************************************************
12383 *									*
12384 *			Reading/Writing Schemas				*
12385 *									*
12386 ************************************************************************/
12387
12388#if 0 /* Will be enabled if it is clear what options are needed. */
12389/**
12390 * xmlSchemaParserCtxtSetOptions:
12391 * @ctxt:	a schema parser context
12392 * @options: a combination of xmlSchemaParserOption
12393 *
12394 * Sets the options to be used during the parse.
12395 *
12396 * Returns 0 in case of success, -1 in case of an
12397 * API error.
12398 */
12399static int
12400xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12401			      int options)
12402
12403{
12404    int i;
12405
12406    if (ctxt == NULL)
12407	return (-1);
12408    /*
12409    * WARNING: Change the start value if adding to the
12410    * xmlSchemaParseOption.
12411    */
12412    for (i = 1; i < (int) sizeof(int) * 8; i++) {
12413        if (options & 1<<i) {
12414	    return (-1);
12415        }
12416    }
12417    ctxt->options = options;
12418    return (0);
12419}
12420
12421/**
12422 * xmlSchemaValidCtxtGetOptions:
12423 * @ctxt: a schema parser context
12424 *
12425 * Returns the option combination of the parser context.
12426 */
12427static int
12428xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12429
12430{
12431    if (ctxt == NULL)
12432	return (-1);
12433    else
12434	return (ctxt->options);
12435}
12436#endif
12437
12438/**
12439 * xmlSchemaNewParserCtxt:
12440 * @URL:  the location of the schema
12441 *
12442 * Create an XML Schemas parse context for that file/resource expected
12443 * to contain an XML Schemas file.
12444 *
12445 * Returns the parser context or NULL in case of error
12446 */
12447xmlSchemaParserCtxtPtr
12448xmlSchemaNewParserCtxt(const char *URL)
12449{
12450    xmlSchemaParserCtxtPtr ret;
12451
12452    if (URL == NULL)
12453        return (NULL);
12454
12455    ret = xmlSchemaParserCtxtCreate();
12456    if (ret == NULL)
12457	return(NULL);
12458    ret->dict = xmlDictCreate();
12459    ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12460    return (ret);
12461}
12462
12463/**
12464 * xmlSchemaNewMemParserCtxt:
12465 * @buffer:  a pointer to a char array containing the schemas
12466 * @size:  the size of the array
12467 *
12468 * Create an XML Schemas parse context for that memory buffer expected
12469 * to contain an XML Schemas file.
12470 *
12471 * Returns the parser context or NULL in case of error
12472 */
12473xmlSchemaParserCtxtPtr
12474xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12475{
12476    xmlSchemaParserCtxtPtr ret;
12477
12478    if ((buffer == NULL) || (size <= 0))
12479        return (NULL);
12480    ret = xmlSchemaParserCtxtCreate();
12481    if (ret == NULL)
12482	return(NULL);
12483    ret->buffer = buffer;
12484    ret->size = size;
12485    ret->dict = xmlDictCreate();
12486    return (ret);
12487}
12488
12489/**
12490 * xmlSchemaNewDocParserCtxt:
12491 * @doc:  a preparsed document tree
12492 *
12493 * Create an XML Schemas parse context for that document.
12494 * NB. The document may be modified during the parsing process.
12495 *
12496 * Returns the parser context or NULL in case of error
12497 */
12498xmlSchemaParserCtxtPtr
12499xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12500{
12501    xmlSchemaParserCtxtPtr ret;
12502
12503    if (doc == NULL)
12504      return (NULL);
12505    ret = xmlSchemaParserCtxtCreate();
12506    if (ret == NULL)
12507	return(NULL);
12508    ret->doc = doc;
12509    ret->dict = xmlDictCreate();
12510    /* The application has responsibility for the document */
12511    ret->preserve = 1;
12512
12513    return (ret);
12514}
12515
12516/**
12517 * xmlSchemaFreeParserCtxt:
12518 * @ctxt:  the schema parser context
12519 *
12520 * Free the resources associated to the schema parser context
12521 */
12522void
12523xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12524{
12525    if (ctxt == NULL)
12526        return;
12527    if (ctxt->doc != NULL && !ctxt->preserve)
12528        xmlFreeDoc(ctxt->doc);
12529    if (ctxt->vctxt != NULL) {
12530	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12531    }
12532    if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12533	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12534	ctxt->constructor = NULL;
12535	ctxt->ownsConstructor = 0;
12536    }
12537    if (ctxt->attrProhibs != NULL)
12538	xmlSchemaItemListFree(ctxt->attrProhibs);
12539    xmlDictFree(ctxt->dict);
12540    xmlFree(ctxt);
12541}
12542
12543/************************************************************************
12544 *									*
12545 *			Building the content models			*
12546 *									*
12547 ************************************************************************/
12548
12549/**
12550 * xmlSchemaBuildContentModelForSubstGroup:
12551 *
12552 * Returns 1 if nillable, 0 otherwise
12553 */
12554static int
12555xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12556	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12557{
12558    xmlAutomataStatePtr start, tmp;
12559    xmlSchemaElementPtr elemDecl, member;
12560    xmlSchemaSubstGroupPtr substGroup;
12561    int i;
12562    int ret = 0;
12563
12564    elemDecl = (xmlSchemaElementPtr) particle->children;
12565    /*
12566    * Wrap the substitution group with a CHOICE.
12567    */
12568    start = pctxt->state;
12569    if (end == NULL)
12570	end = xmlAutomataNewState(pctxt->am);
12571    substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12572    if (substGroup == NULL) {
12573	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12574	    XML_SCHEMAP_INTERNAL,
12575	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12576	    "declaration is marked having a subst. group but none "
12577	    "available.\n", elemDecl->name, NULL);
12578	return(0);
12579    }
12580    if (counter >= 0) {
12581	/*
12582	* NOTE that we put the declaration in, even if it's abstract.
12583	* However, an error will be raised during *validation* if an element
12584	* information item shall be validated against an abstract element
12585	* declaration.
12586	*/
12587	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12588        xmlAutomataNewTransition2(pctxt->am, tmp, end,
12589	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12590	/*
12591	* Add subst. group members.
12592	*/
12593	for (i = 0; i < substGroup->members->nbItems; i++) {
12594	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12595            xmlAutomataNewTransition2(pctxt->am, tmp, end,
12596		               member->name, member->targetNamespace, member);
12597	}
12598    } else if (particle->maxOccurs == 1) {
12599	/*
12600	* NOTE that we put the declaration in, even if it's abstract,
12601	*/
12602	xmlAutomataNewEpsilon(pctxt->am,
12603	    xmlAutomataNewTransition2(pctxt->am,
12604	    start, NULL,
12605	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12606	/*
12607	* Add subst. group members.
12608	*/
12609	for (i = 0; i < substGroup->members->nbItems; i++) {
12610	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12611	    /*
12612	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12613	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12614	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12615	    *  section in xmlSchemaBuildAContentModel() ).
12616	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12617	    *  intended for the above "counter" section originally. I.e.,
12618	    *  check xs:all with subst-groups.
12619	    *
12620	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12621	    *	               member->name, member->targetNamespace,
12622	    *		       1, 1, member);
12623	    */
12624	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12625		member->name, member->targetNamespace, member);
12626	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12627	}
12628    } else {
12629	xmlAutomataStatePtr hop;
12630	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12631	    UNBOUNDED : particle->maxOccurs - 1;
12632	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12633
12634	counter =
12635	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12636	    maxOccurs);
12637	hop = xmlAutomataNewState(pctxt->am);
12638
12639	xmlAutomataNewEpsilon(pctxt->am,
12640	    xmlAutomataNewTransition2(pctxt->am,
12641	    start, NULL,
12642	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12643	    hop);
12644	/*
12645	 * Add subst. group members.
12646	 */
12647	for (i = 0; i < substGroup->members->nbItems; i++) {
12648	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12649	    xmlAutomataNewEpsilon(pctxt->am,
12650		xmlAutomataNewTransition2(pctxt->am,
12651		start, NULL,
12652		member->name, member->targetNamespace, member),
12653		hop);
12654	}
12655	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12656	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12657    }
12658    if (particle->minOccurs == 0) {
12659	xmlAutomataNewEpsilon(pctxt->am, start, end);
12660        ret = 1;
12661    }
12662    pctxt->state = end;
12663    return(ret);
12664}
12665
12666/**
12667 * xmlSchemaBuildContentModelForElement:
12668 *
12669 * Returns 1 if nillable, 0 otherwise
12670 */
12671static int
12672xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12673				     xmlSchemaParticlePtr particle)
12674{
12675    int ret = 0;
12676
12677    if (((xmlSchemaElementPtr) particle->children)->flags &
12678	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12679	/*
12680	* Substitution groups.
12681	*/
12682	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12683    } else {
12684	xmlSchemaElementPtr elemDecl;
12685	xmlAutomataStatePtr start;
12686
12687	elemDecl = (xmlSchemaElementPtr) particle->children;
12688
12689	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12690	    return(0);
12691	if (particle->maxOccurs == 1) {
12692	    start = ctxt->state;
12693	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12694		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12695	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12696	           (particle->minOccurs < 2)) {
12697	    /* Special case. */
12698	    start = ctxt->state;
12699	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12700		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12701	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12702		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12703	} else {
12704	    int counter;
12705	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12706			    UNBOUNDED : particle->maxOccurs - 1;
12707	    int minOccurs = particle->minOccurs < 1 ?
12708			    0 : particle->minOccurs - 1;
12709
12710	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12711	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12712	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12713		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12714	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12715	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12716		NULL, counter);
12717	}
12718	if (particle->minOccurs == 0) {
12719	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12720            ret = 1;
12721        }
12722    }
12723    return(ret);
12724}
12725
12726/**
12727 * xmlSchemaBuildAContentModel:
12728 * @ctxt:  the schema parser context
12729 * @particle:  the particle component
12730 * @name:  the complex type's name whose content is being built
12731 *
12732 * Create the automaton for the {content type} of a complex type.
12733 *
12734 * Returns 1 if the content is nillable, 0 otherwise
12735 */
12736static int
12737xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12738			    xmlSchemaParticlePtr particle)
12739{
12740    int ret = 0, tmp2;
12741
12742    if (particle == NULL) {
12743	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12744	return(1);
12745    }
12746    if (particle->children == NULL) {
12747	/*
12748	* Just return in this case. A missing "term" of the particle
12749	* might arise due to an invalid "term" component.
12750	*/
12751	return(1);
12752    }
12753
12754    switch (particle->children->type) {
12755	case XML_SCHEMA_TYPE_ANY: {
12756	    xmlAutomataStatePtr start, end;
12757	    xmlSchemaWildcardPtr wild;
12758	    xmlSchemaWildcardNsPtr ns;
12759
12760	    wild = (xmlSchemaWildcardPtr) particle->children;
12761
12762	    start = pctxt->state;
12763	    end = xmlAutomataNewState(pctxt->am);
12764
12765	    if (particle->maxOccurs == 1) {
12766		if (wild->any == 1) {
12767		    /*
12768		    * We need to add both transitions:
12769		    *
12770		    * 1. the {"*", "*"} for elements in a namespace.
12771		    */
12772		    pctxt->state =
12773			xmlAutomataNewTransition2(pctxt->am,
12774			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12775		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12776		    /*
12777		    * 2. the {"*"} for elements in no namespace.
12778		    */
12779		    pctxt->state =
12780			xmlAutomataNewTransition2(pctxt->am,
12781			start, NULL, BAD_CAST "*", NULL, wild);
12782		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12783
12784		} else if (wild->nsSet != NULL) {
12785		    ns = wild->nsSet;
12786		    do {
12787			pctxt->state = start;
12788			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12789			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12790			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12791			ns = ns->next;
12792		    } while (ns != NULL);
12793
12794		} else if (wild->negNsSet != NULL) {
12795		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12796			start, end, BAD_CAST "*", wild->negNsSet->value,
12797			wild);
12798		}
12799	    } else {
12800		int counter;
12801		xmlAutomataStatePtr hop;
12802		int maxOccurs =
12803		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12804                                           particle->maxOccurs - 1;
12805		int minOccurs =
12806		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12807
12808		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12809		hop = xmlAutomataNewState(pctxt->am);
12810		if (wild->any == 1) {
12811		    pctxt->state =
12812			xmlAutomataNewTransition2(pctxt->am,
12813			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12814		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12815		    pctxt->state =
12816			xmlAutomataNewTransition2(pctxt->am,
12817			start, NULL, BAD_CAST "*", NULL, wild);
12818		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12819		} else if (wild->nsSet != NULL) {
12820		    ns = wild->nsSet;
12821		    do {
12822			pctxt->state =
12823			    xmlAutomataNewTransition2(pctxt->am,
12824				start, NULL, BAD_CAST "*", ns->value, wild);
12825			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12826			ns = ns->next;
12827		    } while (ns != NULL);
12828
12829		} else if (wild->negNsSet != NULL) {
12830		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12831			start, hop, BAD_CAST "*", wild->negNsSet->value,
12832			wild);
12833		}
12834		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12835		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12836	    }
12837	    if (particle->minOccurs == 0) {
12838		xmlAutomataNewEpsilon(pctxt->am, start, end);
12839                ret = 1;
12840	    }
12841	    pctxt->state = end;
12842            break;
12843	}
12844        case XML_SCHEMA_TYPE_ELEMENT:
12845	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12846	    break;
12847        case XML_SCHEMA_TYPE_SEQUENCE:{
12848            xmlSchemaTreeItemPtr sub;
12849
12850            ret = 1;
12851            /*
12852             * If max and min occurances are default (1) then
12853             * simply iterate over the particles of the <sequence>.
12854             */
12855            if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12856                sub = particle->children->children;
12857
12858                while (sub != NULL) {
12859                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
12860                                        (xmlSchemaParticlePtr) sub);
12861                    if (tmp2 != 1) ret = 0;
12862                    sub = sub->next;
12863                }
12864            } else {
12865                xmlAutomataStatePtr oldstate = pctxt->state;
12866
12867                if (particle->maxOccurs >= UNBOUNDED) {
12868                    if (particle->minOccurs > 1) {
12869                        xmlAutomataStatePtr tmp;
12870                        int counter;
12871
12872                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12873                            oldstate, NULL);
12874                        oldstate = pctxt->state;
12875
12876                        counter = xmlAutomataNewCounter(pctxt->am,
12877                            particle->minOccurs - 1, UNBOUNDED);
12878
12879                        sub = particle->children->children;
12880                        while (sub != NULL) {
12881                            tmp2 = xmlSchemaBuildAContentModel(pctxt,
12882                                            (xmlSchemaParticlePtr) sub);
12883                            if (tmp2 != 1) ret = 0;
12884                            sub = sub->next;
12885                        }
12886                        tmp = pctxt->state;
12887                        xmlAutomataNewCountedTrans(pctxt->am, tmp,
12888                                                   oldstate, counter);
12889                        pctxt->state =
12890                            xmlAutomataNewCounterTrans(pctxt->am, tmp,
12891                                                       NULL, counter);
12892                        if (ret == 1)
12893                            xmlAutomataNewEpsilon(pctxt->am,
12894                                                oldstate, pctxt->state);
12895
12896                    } else {
12897                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12898                            oldstate, NULL);
12899                        oldstate = pctxt->state;
12900
12901                        sub = particle->children->children;
12902                        while (sub != NULL) {
12903                            tmp2 = xmlSchemaBuildAContentModel(pctxt,
12904                                        (xmlSchemaParticlePtr) sub);
12905                            if (tmp2 != 1) ret = 0;
12906                            sub = sub->next;
12907                        }
12908                        xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12909                                              oldstate);
12910                        /*
12911                         * epsilon needed to block previous trans from
12912                         * being allowed to enter back from another
12913                         * construct
12914                         */
12915                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12916                                            pctxt->state, NULL);
12917                        if (particle->minOccurs == 0) {
12918                            xmlAutomataNewEpsilon(pctxt->am,
12919                                oldstate, pctxt->state);
12920                            ret = 1;
12921                        }
12922                    }
12923                } else if ((particle->maxOccurs > 1)
12924                           || (particle->minOccurs > 1)) {
12925                    xmlAutomataStatePtr tmp;
12926                    int counter;
12927
12928                    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12929                        oldstate, NULL);
12930                    oldstate = pctxt->state;
12931
12932                    counter = xmlAutomataNewCounter(pctxt->am,
12933                        particle->minOccurs - 1,
12934                        particle->maxOccurs - 1);
12935
12936                    sub = particle->children->children;
12937                    while (sub != NULL) {
12938                        tmp2 = xmlSchemaBuildAContentModel(pctxt,
12939                                        (xmlSchemaParticlePtr) sub);
12940                        if (tmp2 != 1) ret = 0;
12941                        sub = sub->next;
12942                    }
12943                    tmp = pctxt->state;
12944                    xmlAutomataNewCountedTrans(pctxt->am,
12945                        tmp, oldstate, counter);
12946                    pctxt->state =
12947                        xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12948                                                   counter);
12949                    if ((particle->minOccurs == 0) || (ret == 1)) {
12950                        xmlAutomataNewEpsilon(pctxt->am,
12951                                            oldstate, pctxt->state);
12952                        ret = 1;
12953                    }
12954                } else {
12955                    sub = particle->children->children;
12956                    while (sub != NULL) {
12957                        tmp2 = xmlSchemaBuildAContentModel(pctxt,
12958                                        (xmlSchemaParticlePtr) sub);
12959                        if (tmp2 != 1) ret = 0;
12960                        sub = sub->next;
12961                    }
12962
12963		    /*
12964		     * epsilon needed to block previous trans from
12965		     * being allowed to enter back from another
12966		     * construct
12967		     */
12968		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12969					pctxt->state, NULL);
12970
12971                    if (particle->minOccurs == 0) {
12972                        xmlAutomataNewEpsilon(pctxt->am, oldstate,
12973                                              pctxt->state);
12974                        ret = 1;
12975                    }
12976                }
12977            }
12978            break;
12979        }
12980        case XML_SCHEMA_TYPE_CHOICE:{
12981            xmlSchemaTreeItemPtr sub;
12982            xmlAutomataStatePtr start, end;
12983
12984            ret = 0;
12985            start = pctxt->state;
12986            end = xmlAutomataNewState(pctxt->am);
12987
12988            /*
12989             * iterate over the subtypes and remerge the end with an
12990             * epsilon transition
12991             */
12992            if (particle->maxOccurs == 1) {
12993                sub = particle->children->children;
12994                while (sub != NULL) {
12995                    pctxt->state = start;
12996                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
12997                                        (xmlSchemaParticlePtr) sub);
12998                    if (tmp2 == 1) ret = 1;
12999                    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13000                    sub = sub->next;
13001                }
13002            } else {
13003                int counter;
13004                xmlAutomataStatePtr hop, base;
13005                int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13006                    UNBOUNDED : particle->maxOccurs - 1;
13007                int minOccurs =
13008                    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13009
13010                /*
13011                 * use a counter to keep track of the number of transtions
13012                 * which went through the choice.
13013                 */
13014                counter =
13015                    xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13016                hop = xmlAutomataNewState(pctxt->am);
13017                base = xmlAutomataNewState(pctxt->am);
13018
13019                sub = particle->children->children;
13020                while (sub != NULL) {
13021                    pctxt->state = base;
13022                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
13023                                        (xmlSchemaParticlePtr) sub);
13024                    if (tmp2 == 1) ret = 1;
13025                    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13026                    sub = sub->next;
13027                }
13028                xmlAutomataNewEpsilon(pctxt->am, start, base);
13029                xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13030                xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13031                if (ret == 1)
13032                    xmlAutomataNewEpsilon(pctxt->am, base, end);
13033            }
13034            if (particle->minOccurs == 0) {
13035                xmlAutomataNewEpsilon(pctxt->am, start, end);
13036                ret = 1;
13037            }
13038            pctxt->state = end;
13039            break;
13040        }
13041        case XML_SCHEMA_TYPE_ALL:{
13042            xmlAutomataStatePtr start, tmp;
13043            xmlSchemaParticlePtr sub;
13044            xmlSchemaElementPtr elemDecl;
13045
13046            ret = 1;
13047
13048            sub = (xmlSchemaParticlePtr) particle->children->children;
13049            if (sub == NULL)
13050                break;
13051
13052            ret = 0;
13053
13054            start = pctxt->state;
13055            tmp = xmlAutomataNewState(pctxt->am);
13056            xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13057            pctxt->state = tmp;
13058            while (sub != NULL) {
13059                pctxt->state = tmp;
13060
13061                elemDecl = (xmlSchemaElementPtr) sub->children;
13062                if (elemDecl == NULL) {
13063                    PERROR_INT("xmlSchemaBuildAContentModel",
13064                        "<element> particle has no term");
13065                    return(ret);
13066                };
13067                /*
13068                * NOTE: The {max occurs} of all the particles in the
13069                * {particles} of the group must be 0 or 1; this is
13070                * already ensured during the parse of the content of
13071                * <all>.
13072                */
13073                if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13074                    int counter;
13075
13076                    /*
13077                     * This is an abstract group, we need to share
13078                     * the same counter for all the element transitions
13079                     * derived from the group
13080                     */
13081                    counter = xmlAutomataNewCounter(pctxt->am,
13082                                       sub->minOccurs, sub->maxOccurs);
13083                    xmlSchemaBuildContentModelForSubstGroup(pctxt,
13084                                       sub, counter, pctxt->state);
13085                } else {
13086                    if ((sub->minOccurs == 1) &&
13087                        (sub->maxOccurs == 1)) {
13088                        xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13089                                                pctxt->state,
13090                                                elemDecl->name,
13091                                                elemDecl->targetNamespace,
13092                                                1, 1, elemDecl);
13093                    } else if ((sub->minOccurs == 0) &&
13094                        (sub->maxOccurs == 1)) {
13095
13096                        xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13097                                                 pctxt->state,
13098                                                 elemDecl->name,
13099                                                 elemDecl->targetNamespace,
13100                                                 0,
13101                                                 1,
13102                                                 elemDecl);
13103                    }
13104                }
13105                sub = (xmlSchemaParticlePtr) sub->next;
13106            }
13107            pctxt->state =
13108                xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13109            if (particle->minOccurs == 0) {
13110                xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13111                ret = 1;
13112            }
13113            break;
13114        }
13115	case XML_SCHEMA_TYPE_GROUP:
13116	    /*
13117	    * If we hit a model group definition, then this means that
13118	    * it was empty, thus was not substituted for the containing
13119	    * model group. Just do nothing in this case.
13120	    * TODO: But the group should be substituted and not occur at
13121	    * all in the content model at this point. Fix this.
13122	    */
13123            ret = 1;
13124	    break;
13125        default:
13126	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13127		"xmlSchemaBuildAContentModel",
13128		"found unexpected term of type '%s' in content model",
13129		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13130            return(ret);
13131    }
13132    return(ret);
13133}
13134
13135/**
13136 * xmlSchemaBuildContentModel:
13137 * @ctxt:  the schema parser context
13138 * @type:  the complex type definition
13139 * @name:  the element name
13140 *
13141 * Builds the content model of the complex type.
13142 */
13143static void
13144xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13145			   xmlSchemaParserCtxtPtr ctxt)
13146{
13147    if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13148	(type->contModel != NULL) ||
13149	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13150	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13151	return;
13152
13153#ifdef DEBUG_CONTENT
13154    xmlGenericError(xmlGenericErrorContext,
13155                    "Building content model for %s\n", name);
13156#endif
13157    ctxt->am = NULL;
13158    ctxt->am = xmlNewAutomata();
13159    if (ctxt->am == NULL) {
13160        xmlGenericError(xmlGenericErrorContext,
13161	    "Cannot create automata for complex type %s\n", type->name);
13162        return;
13163    }
13164    ctxt->state = xmlAutomataGetInitState(ctxt->am);
13165    /*
13166    * Build the automaton.
13167    */
13168    xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13169    xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13170    type->contModel = xmlAutomataCompile(ctxt->am);
13171    if (type->contModel == NULL) {
13172        xmlSchemaPCustomErr(ctxt,
13173	    XML_SCHEMAP_INTERNAL,
13174	    WXS_BASIC_CAST type, type->node,
13175	    "Failed to compile the content model", NULL);
13176    } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13177        xmlSchemaPCustomErr(ctxt,
13178	    XML_SCHEMAP_NOT_DETERMINISTIC,
13179	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13180	    WXS_BASIC_CAST type, type->node,
13181	    "The content model is not determinist", NULL);
13182    } else {
13183#ifdef DEBUG_CONTENT_REGEXP
13184        xmlGenericError(xmlGenericErrorContext,
13185                        "Content model of %s:\n", type->name);
13186        xmlRegexpPrint(stderr, type->contModel);
13187#endif
13188    }
13189    ctxt->state = NULL;
13190    xmlFreeAutomata(ctxt->am);
13191    ctxt->am = NULL;
13192}
13193
13194/**
13195 * xmlSchemaResolveElementReferences:
13196 * @elem:  the schema element context
13197 * @ctxt:  the schema parser context
13198 *
13199 * Resolves the references of an element declaration
13200 * or particle, which has an element declaration as it's
13201 * term.
13202 */
13203static void
13204xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13205				  xmlSchemaParserCtxtPtr ctxt)
13206{
13207    if ((ctxt == NULL) || (elemDecl == NULL) ||
13208	((elemDecl != NULL) &&
13209	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13210        return;
13211    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13212
13213    if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13214	xmlSchemaTypePtr type;
13215
13216	/* (type definition) ... otherwise the type definition `resolved`
13217	* to by the `actual value` of the type [attribute] ...
13218	*/
13219	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13220	    elemDecl->namedTypeNs);
13221	if (type == NULL) {
13222	    xmlSchemaPResCompAttrErr(ctxt,
13223		XML_SCHEMAP_SRC_RESOLVE,
13224		WXS_BASIC_CAST elemDecl, elemDecl->node,
13225		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13226		XML_SCHEMA_TYPE_BASIC, "type definition");
13227	} else
13228	    elemDecl->subtypes = type;
13229    }
13230    if (elemDecl->substGroup != NULL) {
13231	xmlSchemaElementPtr substHead;
13232
13233	/*
13234	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13235	* substitutionGroup?
13236	*/
13237	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13238	    elemDecl->substGroupNs);
13239	if (substHead == NULL) {
13240	    xmlSchemaPResCompAttrErr(ctxt,
13241		XML_SCHEMAP_SRC_RESOLVE,
13242		WXS_BASIC_CAST elemDecl, NULL,
13243		"substitutionGroup", elemDecl->substGroup,
13244		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13245	} else {
13246	    xmlSchemaResolveElementReferences(substHead, ctxt);
13247	    /*
13248	    * Set the "substitution group affiliation".
13249	    * NOTE that now we use the "refDecl" field for this.
13250	    */
13251	    WXS_SUBST_HEAD(elemDecl) = substHead;
13252	    /*
13253	    * The type definitions is set to:
13254	    * SPEC "...the {type definition} of the element
13255	    * declaration `resolved` to by the `actual value`
13256	    * of the substitutionGroup [attribute], if present"
13257	    */
13258	    if (elemDecl->subtypes == NULL)
13259		elemDecl->subtypes = substHead->subtypes;
13260	}
13261    }
13262    /*
13263    * SPEC "The definition of anyType serves as the default type definition
13264    * for element declarations whose XML representation does not specify one."
13265    */
13266    if ((elemDecl->subtypes == NULL) &&
13267	(elemDecl->namedType == NULL) &&
13268	(elemDecl->substGroup == NULL))
13269	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13270}
13271
13272/**
13273 * xmlSchemaResolveUnionMemberTypes:
13274 * @ctxt:  the schema parser context
13275 * @type:  the schema simple type definition
13276 *
13277 * Checks and builds the "member type definitions" property of the union
13278 * simple type. This handles part (1), part (2) is done in
13279 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13280 *
13281 * Returns -1 in case of an internal error, 0 otherwise.
13282 */
13283static int
13284xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13285				 xmlSchemaTypePtr type)
13286{
13287
13288    xmlSchemaTypeLinkPtr link, lastLink, newLink;
13289    xmlSchemaTypePtr memberType;
13290
13291    /*
13292    * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13293    * define the explicit members as the type definitions `resolved`
13294    * to by the items in the `actual value` of the memberTypes [attribute],
13295    * if any, followed by the type definitions corresponding to the
13296    * <simpleType>s among the [children] of <union>, if any."
13297    */
13298    /*
13299    * Resolve references.
13300    */
13301    link = type->memberTypes;
13302    lastLink = NULL;
13303    while (link != NULL) {
13304	const xmlChar *name, *nsName;
13305
13306	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13307	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13308
13309	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13310	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13311	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13312		WXS_BASIC_CAST type, type->node, "memberTypes",
13313		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13314	    /*
13315	    * Remove the member type link.
13316	    */
13317	    if (lastLink == NULL)
13318		type->memberTypes = link->next;
13319	    else
13320		lastLink->next = link->next;
13321	    newLink = link;
13322	    link = link->next;
13323	    xmlFree(newLink);
13324	} else {
13325	    link->type = memberType;
13326	    lastLink = link;
13327	    link = link->next;
13328	}
13329    }
13330    /*
13331    * Add local simple types,
13332    */
13333    memberType = type->subtypes;
13334    while (memberType != NULL) {
13335	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13336	if (link == NULL) {
13337	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13338	    return (-1);
13339	}
13340	link->type = memberType;
13341	link->next = NULL;
13342	if (lastLink == NULL)
13343	    type->memberTypes = link;
13344	else
13345	    lastLink->next = link;
13346	lastLink = link;
13347	memberType = memberType->next;
13348    }
13349    return (0);
13350}
13351
13352/**
13353 * xmlSchemaIsDerivedFromBuiltInType:
13354 * @ctxt:  the schema parser context
13355 * @type:  the type definition
13356 * @valType: the value type
13357 *
13358 *
13359 * Returns 1 if the type has the given value type, or
13360 * is derived from such a type.
13361 */
13362static int
13363xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13364{
13365    if (type == NULL)
13366	return (0);
13367    if (WXS_IS_COMPLEX(type))
13368	return (0);
13369    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13370	if (type->builtInType == valType)
13371	    return(1);
13372	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13373	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13374	    return (0);
13375	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13376    }
13377    return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13378}
13379
13380#if 0
13381/**
13382 * xmlSchemaIsDerivedFromBuiltInType:
13383 * @ctxt:  the schema parser context
13384 * @type:  the type definition
13385 * @valType: the value type
13386 *
13387 *
13388 * Returns 1 if the type has the given value type, or
13389 * is derived from such a type.
13390 */
13391static int
13392xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13393{
13394    if (type == NULL)
13395	return (0);
13396    if (WXS_IS_COMPLEX(type))
13397	return (0);
13398    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13399	if (type->builtInType == valType)
13400	    return(1);
13401	return (0);
13402    } else
13403	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13404
13405    return (0);
13406}
13407
13408static xmlSchemaTypePtr
13409xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13410{
13411    if (type == NULL)
13412	return (NULL);
13413    if (WXS_IS_COMPLEX(type))
13414	return (NULL);
13415    if (type->type == XML_SCHEMA_TYPE_BASIC)
13416	return(type);
13417    return(xmlSchemaQueryBuiltInType(type->subtypes));
13418}
13419#endif
13420
13421/**
13422 * xmlSchemaGetPrimitiveType:
13423 * @type:  the simpleType definition
13424 *
13425 * Returns the primitive type of the given type or
13426 * NULL in case of error.
13427 */
13428static xmlSchemaTypePtr
13429xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13430{
13431
13432    while (type != NULL) {
13433	/*
13434	* Note that anySimpleType is actually not a primitive type
13435	* but we need that here.
13436	*/
13437	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13438	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13439	    return (type);
13440	type = type->baseType;
13441    }
13442
13443    return (NULL);
13444}
13445
13446#if 0
13447/**
13448 * xmlSchemaGetBuiltInTypeAncestor:
13449 * @type:  the simpleType definition
13450 *
13451 * Returns the primitive type of the given type or
13452 * NULL in case of error.
13453 */
13454static xmlSchemaTypePtr
13455xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13456{
13457    if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13458	return (0);
13459    while (type != NULL) {
13460	if (type->type == XML_SCHEMA_TYPE_BASIC)
13461	    return (type);
13462	type = type->baseType;
13463    }
13464
13465    return (NULL);
13466}
13467#endif
13468
13469/**
13470 * xmlSchemaCloneWildcardNsConstraints:
13471 * @ctxt:  the schema parser context
13472 * @dest:  the destination wildcard
13473 * @source: the source wildcard
13474 *
13475 * Clones the namespace constraints of source
13476 * and assignes them to dest.
13477 * Returns -1 on internal error, 0 otherwise.
13478 */
13479static int
13480xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13481				    xmlSchemaWildcardPtr dest,
13482				    xmlSchemaWildcardPtr source)
13483{
13484    xmlSchemaWildcardNsPtr cur, tmp, last;
13485
13486    if ((source == NULL) || (dest == NULL))
13487	return(-1);
13488    dest->any = source->any;
13489    cur = source->nsSet;
13490    last = NULL;
13491    while (cur != NULL) {
13492	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13493	if (tmp == NULL)
13494	    return(-1);
13495	tmp->value = cur->value;
13496	if (last == NULL)
13497	    dest->nsSet = tmp;
13498	else
13499	    last->next = tmp;
13500	last = tmp;
13501	cur = cur->next;
13502    }
13503    if (dest->negNsSet != NULL)
13504	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13505    if (source->negNsSet != NULL) {
13506	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13507	if (dest->negNsSet == NULL)
13508	    return(-1);
13509	dest->negNsSet->value = source->negNsSet->value;
13510    } else
13511	dest->negNsSet = NULL;
13512    return(0);
13513}
13514
13515/**
13516 * xmlSchemaUnionWildcards:
13517 * @ctxt:  the schema parser context
13518 * @completeWild:  the first wildcard
13519 * @curWild: the second wildcard
13520 *
13521 * Unions the namespace constraints of the given wildcards.
13522 * @completeWild will hold the resulting union.
13523 * Returns a positive error code on failure, -1 in case of an
13524 * internal error, 0 otherwise.
13525 */
13526static int
13527xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13528			    xmlSchemaWildcardPtr completeWild,
13529			    xmlSchemaWildcardPtr curWild)
13530{
13531    xmlSchemaWildcardNsPtr cur, curB, tmp;
13532
13533    /*
13534    * 1 If O1 and O2 are the same value, then that value must be the
13535    * value.
13536    */
13537    if ((completeWild->any == curWild->any) &&
13538	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13539	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13540
13541	if ((completeWild->negNsSet == NULL) ||
13542	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13543
13544	    if (completeWild->nsSet != NULL) {
13545		int found = 0;
13546
13547		/*
13548		* Check equality of sets.
13549		*/
13550		cur = completeWild->nsSet;
13551		while (cur != NULL) {
13552		    found = 0;
13553		    curB = curWild->nsSet;
13554		    while (curB != NULL) {
13555			if (cur->value == curB->value) {
13556			    found = 1;
13557			    break;
13558			}
13559			curB = curB->next;
13560		    }
13561		    if (!found)
13562			break;
13563		    cur = cur->next;
13564		}
13565		if (found)
13566		    return(0);
13567	    } else
13568		return(0);
13569	}
13570    }
13571    /*
13572    * 2 If either O1 or O2 is any, then any must be the value
13573    */
13574    if (completeWild->any != curWild->any) {
13575	if (completeWild->any == 0) {
13576	    completeWild->any = 1;
13577	    if (completeWild->nsSet != NULL) {
13578		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13579		completeWild->nsSet = NULL;
13580	    }
13581	    if (completeWild->negNsSet != NULL) {
13582		xmlFree(completeWild->negNsSet);
13583		completeWild->negNsSet = NULL;
13584	    }
13585	}
13586	return (0);
13587    }
13588    /*
13589    * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13590    * then the union of those sets must be the value.
13591    */
13592    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13593	int found;
13594	xmlSchemaWildcardNsPtr start;
13595
13596	cur = curWild->nsSet;
13597	start = completeWild->nsSet;
13598	while (cur != NULL) {
13599	    found = 0;
13600	    curB = start;
13601	    while (curB != NULL) {
13602		if (cur->value == curB->value) {
13603		    found = 1;
13604		    break;
13605		}
13606		curB = curB->next;
13607	    }
13608	    if (!found) {
13609		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13610		if (tmp == NULL)
13611		    return (-1);
13612		tmp->value = cur->value;
13613		tmp->next = completeWild->nsSet;
13614		completeWild->nsSet = tmp;
13615	    }
13616	    cur = cur->next;
13617	}
13618
13619	return(0);
13620    }
13621    /*
13622    * 4 If the two are negations of different values (namespace names
13623    * or `absent`), then a pair of not and `absent` must be the value.
13624    */
13625    if ((completeWild->negNsSet != NULL) &&
13626	(curWild->negNsSet != NULL) &&
13627	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13628	completeWild->negNsSet->value = NULL;
13629
13630	return(0);
13631    }
13632    /*
13633     * 5.
13634     */
13635    if (((completeWild->negNsSet != NULL) &&
13636	(completeWild->negNsSet->value != NULL) &&
13637	(curWild->nsSet != NULL)) ||
13638	((curWild->negNsSet != NULL) &&
13639	(curWild->negNsSet->value != NULL) &&
13640	(completeWild->nsSet != NULL))) {
13641
13642	int nsFound, absentFound = 0;
13643
13644	if (completeWild->nsSet != NULL) {
13645	    cur = completeWild->nsSet;
13646	    curB = curWild->negNsSet;
13647	} else {
13648	    cur = curWild->nsSet;
13649	    curB = completeWild->negNsSet;
13650	}
13651	nsFound = 0;
13652	while (cur != NULL) {
13653	    if (cur->value == NULL)
13654		absentFound = 1;
13655	    else if (cur->value == curB->value)
13656		nsFound = 1;
13657	    if (nsFound && absentFound)
13658		break;
13659	    cur = cur->next;
13660	}
13661
13662	if (nsFound && absentFound) {
13663	    /*
13664	    * 5.1 If the set S includes both the negated namespace
13665	    * name and `absent`, then any must be the value.
13666	    */
13667	    completeWild->any = 1;
13668	    if (completeWild->nsSet != NULL) {
13669		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13670		completeWild->nsSet = NULL;
13671	    }
13672	    if (completeWild->negNsSet != NULL) {
13673		xmlFree(completeWild->negNsSet);
13674		completeWild->negNsSet = NULL;
13675	    }
13676	} else if (nsFound && (!absentFound)) {
13677	    /*
13678	    * 5.2 If the set S includes the negated namespace name
13679	    * but not `absent`, then a pair of not and `absent` must
13680	    * be the value.
13681	    */
13682	    if (completeWild->nsSet != NULL) {
13683		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13684		completeWild->nsSet = NULL;
13685	    }
13686	    if (completeWild->negNsSet == NULL) {
13687		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13688		if (completeWild->negNsSet == NULL)
13689		    return (-1);
13690	    }
13691	    completeWild->negNsSet->value = NULL;
13692	} else if ((!nsFound) && absentFound) {
13693	    /*
13694	    * 5.3 If the set S includes `absent` but not the negated
13695	    * namespace name, then the union is not expressible.
13696	    */
13697	    xmlSchemaPErr(ctxt, completeWild->node,
13698		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13699		"The union of the wilcard is not expressible.\n",
13700		NULL, NULL);
13701	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13702	} else if ((!nsFound) && (!absentFound)) {
13703	    /*
13704	    * 5.4 If the set S does not include either the negated namespace
13705	    * name or `absent`, then whichever of O1 or O2 is a pair of not
13706	    * and a namespace name must be the value.
13707	    */
13708	    if (completeWild->negNsSet == NULL) {
13709		if (completeWild->nsSet != NULL) {
13710		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13711		    completeWild->nsSet = NULL;
13712		}
13713		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13714		if (completeWild->negNsSet == NULL)
13715		    return (-1);
13716		completeWild->negNsSet->value = curWild->negNsSet->value;
13717	    }
13718	}
13719	return (0);
13720    }
13721    /*
13722     * 6.
13723     */
13724    if (((completeWild->negNsSet != NULL) &&
13725	(completeWild->negNsSet->value == NULL) &&
13726	(curWild->nsSet != NULL)) ||
13727	((curWild->negNsSet != NULL) &&
13728	(curWild->negNsSet->value == NULL) &&
13729	(completeWild->nsSet != NULL))) {
13730
13731	if (completeWild->nsSet != NULL) {
13732	    cur = completeWild->nsSet;
13733	} else {
13734	    cur = curWild->nsSet;
13735	}
13736	while (cur != NULL) {
13737	    if (cur->value == NULL) {
13738		/*
13739		* 6.1 If the set S includes `absent`, then any must be the
13740		* value.
13741		*/
13742		completeWild->any = 1;
13743		if (completeWild->nsSet != NULL) {
13744		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13745		    completeWild->nsSet = NULL;
13746		}
13747		if (completeWild->negNsSet != NULL) {
13748		    xmlFree(completeWild->negNsSet);
13749		    completeWild->negNsSet = NULL;
13750		}
13751		return (0);
13752	    }
13753	    cur = cur->next;
13754	}
13755	if (completeWild->negNsSet == NULL) {
13756	    /*
13757	    * 6.2 If the set S does not include `absent`, then a pair of not
13758	    * and `absent` must be the value.
13759	    */
13760	    if (completeWild->nsSet != NULL) {
13761		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13762		completeWild->nsSet = NULL;
13763	    }
13764	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13765	    if (completeWild->negNsSet == NULL)
13766		return (-1);
13767	    completeWild->negNsSet->value = NULL;
13768	}
13769	return (0);
13770    }
13771    return (0);
13772
13773}
13774
13775/**
13776 * xmlSchemaIntersectWildcards:
13777 * @ctxt:  the schema parser context
13778 * @completeWild:  the first wildcard
13779 * @curWild: the second wildcard
13780 *
13781 * Intersects the namespace constraints of the given wildcards.
13782 * @completeWild will hold the resulting intersection.
13783 * Returns a positive error code on failure, -1 in case of an
13784 * internal error, 0 otherwise.
13785 */
13786static int
13787xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13788			    xmlSchemaWildcardPtr completeWild,
13789			    xmlSchemaWildcardPtr curWild)
13790{
13791    xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13792
13793    /*
13794    * 1 If O1 and O2 are the same value, then that value must be the
13795    * value.
13796    */
13797    if ((completeWild->any == curWild->any) &&
13798	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13799	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13800
13801	if ((completeWild->negNsSet == NULL) ||
13802	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13803
13804	    if (completeWild->nsSet != NULL) {
13805		int found = 0;
13806
13807		/*
13808		* Check equality of sets.
13809		*/
13810		cur = completeWild->nsSet;
13811		while (cur != NULL) {
13812		    found = 0;
13813		    curB = curWild->nsSet;
13814		    while (curB != NULL) {
13815			if (cur->value == curB->value) {
13816			    found = 1;
13817			    break;
13818			}
13819			curB = curB->next;
13820		    }
13821		    if (!found)
13822			break;
13823		    cur = cur->next;
13824		}
13825		if (found)
13826		    return(0);
13827	    } else
13828		return(0);
13829	}
13830    }
13831    /*
13832    * 2 If either O1 or O2 is any, then the other must be the value.
13833    */
13834    if ((completeWild->any != curWild->any) && (completeWild->any)) {
13835	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13836	    return(-1);
13837	return(0);
13838    }
13839    /*
13840    * 3 If either O1 or O2 is a pair of not and a value (a namespace
13841    * name or `absent`) and the other is a set of (namespace names or
13842    * `absent`), then that set, minus the negated value if it was in
13843    * the set, minus `absent` if it was in the set, must be the value.
13844    */
13845    if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13846	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13847	const xmlChar *neg;
13848
13849	if (completeWild->nsSet == NULL) {
13850	    neg = completeWild->negNsSet->value;
13851	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13852		return(-1);
13853	} else
13854	    neg = curWild->negNsSet->value;
13855	/*
13856	* Remove absent and negated.
13857	*/
13858	prev = NULL;
13859	cur = completeWild->nsSet;
13860	while (cur != NULL) {
13861	    if (cur->value == NULL) {
13862		if (prev == NULL)
13863		    completeWild->nsSet = cur->next;
13864		else
13865		    prev->next = cur->next;
13866		xmlFree(cur);
13867		break;
13868	    }
13869	    prev = cur;
13870	    cur = cur->next;
13871	}
13872	if (neg != NULL) {
13873	    prev = NULL;
13874	    cur = completeWild->nsSet;
13875	    while (cur != NULL) {
13876		if (cur->value == neg) {
13877		    if (prev == NULL)
13878			completeWild->nsSet = cur->next;
13879		    else
13880			prev->next = cur->next;
13881		    xmlFree(cur);
13882		    break;
13883		}
13884		prev = cur;
13885		cur = cur->next;
13886	    }
13887	}
13888
13889	return(0);
13890    }
13891    /*
13892    * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13893    * then the intersection of those sets must be the value.
13894    */
13895    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13896	int found;
13897
13898	cur = completeWild->nsSet;
13899	prev = NULL;
13900	while (cur != NULL) {
13901	    found = 0;
13902	    curB = curWild->nsSet;
13903	    while (curB != NULL) {
13904		if (cur->value == curB->value) {
13905		    found = 1;
13906		    break;
13907		}
13908		curB = curB->next;
13909	    }
13910	    if (!found) {
13911		if (prev == NULL)
13912		    completeWild->nsSet = cur->next;
13913		else
13914		    prev->next = cur->next;
13915		tmp = cur->next;
13916		xmlFree(cur);
13917		cur = tmp;
13918		continue;
13919	    }
13920	    prev = cur;
13921	    cur = cur->next;
13922	}
13923
13924	return(0);
13925    }
13926    /* 5 If the two are negations of different namespace names,
13927    * then the intersection is not expressible
13928    */
13929    if ((completeWild->negNsSet != NULL) &&
13930	(curWild->negNsSet != NULL) &&
13931	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13932	(completeWild->negNsSet->value != NULL) &&
13933	(curWild->negNsSet->value != NULL)) {
13934
13935	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13936	    "The intersection of the wilcard is not expressible.\n",
13937	    NULL, NULL);
13938	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13939    }
13940    /*
13941    * 6 If the one is a negation of a namespace name and the other
13942    * is a negation of `absent`, then the one which is the negation
13943    * of a namespace name must be the value.
13944    */
13945    if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13946	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13947	(completeWild->negNsSet->value == NULL)) {
13948	completeWild->negNsSet->value =  curWild->negNsSet->value;
13949    }
13950    return(0);
13951}
13952
13953/**
13954 * xmlSchemaIsWildcardNsConstraintSubset:
13955 * @ctxt:  the schema parser context
13956 * @sub:  the first wildcard
13957 * @super: the second wildcard
13958 *
13959 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13960 *
13961 * Returns 0 if the namespace constraint of @sub is an intensional
13962 * subset of @super, 1 otherwise.
13963 */
13964static int
13965xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13966			  xmlSchemaWildcardPtr super)
13967{
13968    /*
13969    * 1 super must be any.
13970    */
13971    if (super->any)
13972	return (0);
13973    /*
13974    * 2.1 sub must be a pair of not and a namespace name or `absent`.
13975    * 2.2 super must be a pair of not and the same value.
13976    */
13977    if ((sub->negNsSet != NULL) &&
13978	(super->negNsSet != NULL) &&
13979	(sub->negNsSet->value == super->negNsSet->value))
13980	return (0);
13981    /*
13982    * 3.1 sub must be a set whose members are either namespace names or `absent`.
13983    */
13984    if (sub->nsSet != NULL) {
13985	/*
13986	* 3.2.1 super must be the same set or a superset thereof.
13987	*/
13988	if (super->nsSet != NULL) {
13989	    xmlSchemaWildcardNsPtr cur, curB;
13990	    int found = 0;
13991
13992	    cur = sub->nsSet;
13993	    while (cur != NULL) {
13994		found = 0;
13995		curB = super->nsSet;
13996		while (curB != NULL) {
13997		    if (cur->value == curB->value) {
13998			found = 1;
13999			break;
14000		    }
14001		    curB = curB->next;
14002		}
14003		if (!found)
14004		    return (1);
14005		cur = cur->next;
14006	    }
14007	    if (found)
14008		return (0);
14009	} else if (super->negNsSet != NULL) {
14010	    xmlSchemaWildcardNsPtr cur;
14011	    /*
14012	    * 3.2.2 super must be a pair of not and a namespace name or
14013	    * `absent` and that value must not be in sub's set.
14014	    */
14015	    cur = sub->nsSet;
14016	    while (cur != NULL) {
14017		if (cur->value == super->negNsSet->value)
14018		    return (1);
14019		cur = cur->next;
14020	    }
14021	    return (0);
14022	}
14023    }
14024    return (1);
14025}
14026
14027static int
14028xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14029				     int *fixed,
14030				     const xmlChar **value,
14031				     xmlSchemaValPtr *val)
14032{
14033    *fixed = 0;
14034    *value = NULL;
14035    if (val != 0)
14036	*val = NULL;
14037
14038    if (attruse->defValue != NULL) {
14039	*value = attruse->defValue;
14040	if (val != NULL)
14041	    *val = attruse->defVal;
14042	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14043	    *fixed = 1;
14044	return(1);
14045    } else if ((attruse->attrDecl != NULL) &&
14046	(attruse->attrDecl->defValue != NULL)) {
14047	*value = attruse->attrDecl->defValue;
14048	if (val != NULL)
14049	    *val = attruse->attrDecl->defVal;
14050	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14051	    *fixed = 1;
14052	return(1);
14053    }
14054    return(0);
14055}
14056/**
14057 * xmlSchemaCheckCVCWildcardNamespace:
14058 * @wild:  the wildcard
14059 * @ns:  the namespace
14060 *
14061 * Validation Rule: Wildcard allows Namespace Name
14062 * (cvc-wildcard-namespace)
14063 *
14064 * Returns 0 if the given namespace matches the wildcard,
14065 * 1 otherwise and -1 on API errors.
14066 */
14067static int
14068xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14069				   const xmlChar* ns)
14070{
14071    if (wild == NULL)
14072	return(-1);
14073
14074    if (wild->any)
14075	return(0);
14076    else if (wild->nsSet != NULL) {
14077	xmlSchemaWildcardNsPtr cur;
14078
14079	cur = wild->nsSet;
14080	while (cur != NULL) {
14081	    if (xmlStrEqual(cur->value, ns))
14082		return(0);
14083	    cur = cur->next;
14084	}
14085    } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14086	(!xmlStrEqual(wild->negNsSet->value, ns)))
14087	return(0);
14088
14089    return(1);
14090}
14091
14092#define XML_SCHEMA_ACTION_DERIVE 0
14093#define XML_SCHEMA_ACTION_REDEFINE 1
14094
14095#define WXS_ACTION_STR(a) \
14096((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14097
14098/*
14099* Schema Component Constraint:
14100*   Derivation Valid (Restriction, Complex)
14101*   derivation-ok-restriction (2) - (4)
14102*
14103* ATTENTION:
14104* In XML Schema 1.1 this will be:
14105* Validation Rule:
14106*     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14107*
14108*/
14109static int
14110xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14111				       int action,
14112				       xmlSchemaBasicItemPtr item,
14113				       xmlSchemaBasicItemPtr baseItem,
14114				       xmlSchemaItemListPtr uses,
14115				       xmlSchemaItemListPtr baseUses,
14116				       xmlSchemaWildcardPtr wild,
14117				       xmlSchemaWildcardPtr baseWild)
14118{
14119    xmlSchemaAttributeUsePtr cur = NULL, bcur;
14120    int i, j, found; /* err = 0; */
14121    const xmlChar *bEffValue;
14122    int effFixed;
14123
14124    if (uses != NULL) {
14125	for (i = 0; i < uses->nbItems; i++) {
14126	    cur = uses->items[i];
14127	    found = 0;
14128	    if (baseUses == NULL)
14129		goto not_found;
14130	    for (j = 0; j < baseUses->nbItems; j++) {
14131		bcur = baseUses->items[j];
14132		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14133			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14134		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14135			WXS_ATTRUSE_DECL_TNS(bcur)))
14136		{
14137		    /*
14138		    * (2.1) "If there is an attribute use in the {attribute
14139		    * uses} of the {base type definition} (call this B) whose
14140		    * {attribute declaration} has the same {name} and {target
14141		    * namespace}, then  all of the following must be true:"
14142		    */
14143		    found = 1;
14144
14145		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14146			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14147		    {
14148			xmlChar *str = NULL;
14149			/*
14150			* (2.1.1) "one of the following must be true:"
14151			* (2.1.1.1) "B's {required} is false."
14152			* (2.1.1.2) "R's {required} is true."
14153			*/
14154			xmlSchemaPAttrUseErr4(pctxt,
14155			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14156			    WXS_ITEM_NODE(item), item, cur,
14157			    "The 'optional' attribute use is inconsistent "
14158			    "with the corresponding 'required' attribute use of "
14159			    "the %s %s",
14160			    WXS_ACTION_STR(action),
14161			    xmlSchemaGetComponentDesignation(&str, baseItem),
14162			    NULL, NULL);
14163			FREE_AND_NULL(str);
14164			/* err = pctxt->err; */
14165		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14166			WXS_ATTRUSE_TYPEDEF(cur),
14167			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14168		    {
14169			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14170
14171			/*
14172			* SPEC (2.1.2) "R's {attribute declaration}'s
14173			* {type definition} must be validly derived from
14174			* B's {type definition} given the empty set as
14175			* defined in Type Derivation OK (Simple) ($3.14.6)."
14176			*/
14177			xmlSchemaPAttrUseErr4(pctxt,
14178			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14179			    WXS_ITEM_NODE(item), item, cur,
14180			    "The attribute declaration's %s "
14181			    "is not validly derived from "
14182			    "the corresponding %s of the "
14183			    "attribute declaration in the %s %s",
14184			    xmlSchemaGetComponentDesignation(&strA,
14185				WXS_ATTRUSE_TYPEDEF(cur)),
14186			    xmlSchemaGetComponentDesignation(&strB,
14187				WXS_ATTRUSE_TYPEDEF(bcur)),
14188			    WXS_ACTION_STR(action),
14189			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14190			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14191			FREE_AND_NULL(strA);
14192			FREE_AND_NULL(strB);
14193			FREE_AND_NULL(strC);
14194			/* err = pctxt->err; */
14195		    } else {
14196			/*
14197			* 2.1.3 [Definition:]  Let the effective value
14198			* constraint of an attribute use be its {value
14199			* constraint}, if present, otherwise its {attribute
14200			* declaration}'s {value constraint} .
14201			*/
14202			xmlSchemaGetEffectiveValueConstraint(bcur,
14203			    &effFixed, &bEffValue, NULL);
14204			/*
14205			* 2.1.3 ... one of the following must be true
14206			*
14207			* 2.1.3.1 B's `effective value constraint` is
14208			* `absent` or default.
14209			*/
14210			if ((bEffValue != NULL) &&
14211			    (effFixed == 1)) {
14212			    const xmlChar *rEffValue = NULL;
14213
14214			    xmlSchemaGetEffectiveValueConstraint(bcur,
14215				&effFixed, &rEffValue, NULL);
14216			    /*
14217			    * 2.1.3.2 R's `effective value constraint` is
14218			    * fixed with the same string as B's.
14219			    * MAYBE TODO: Compare the computed values.
14220			    *       Hmm, it says "same string" so
14221			    *       string-equality might really be sufficient.
14222			    */
14223			    if ((effFixed == 0) ||
14224				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14225			    {
14226				xmlChar *str = NULL;
14227
14228				xmlSchemaPAttrUseErr4(pctxt,
14229				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14230				    WXS_ITEM_NODE(item), item, cur,
14231				    "The effective value constraint of the "
14232				    "attribute use is inconsistent with "
14233				    "its correspondent in the %s %s",
14234				    WXS_ACTION_STR(action),
14235				    xmlSchemaGetComponentDesignation(&str,
14236					baseItem),
14237				    NULL, NULL);
14238				FREE_AND_NULL(str);
14239				/* err = pctxt->err; */
14240			    }
14241			}
14242		    }
14243		    break;
14244		}
14245	    }
14246not_found:
14247	    if (!found) {
14248		/*
14249		* (2.2) "otherwise the {base type definition} must have an
14250		* {attribute wildcard} and the {target namespace} of the
14251		* R's {attribute declaration} must be `valid` with respect
14252		* to that wildcard, as defined in Wildcard allows Namespace
14253		* Name ($3.10.4)."
14254		*/
14255		if ((baseWild == NULL) ||
14256		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14257		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14258		{
14259		    xmlChar *str = NULL;
14260
14261		    xmlSchemaPAttrUseErr4(pctxt,
14262			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14263			WXS_ITEM_NODE(item), item, cur,
14264			"Neither a matching attribute use, "
14265			"nor a matching wildcard exists in the %s %s",
14266			WXS_ACTION_STR(action),
14267			xmlSchemaGetComponentDesignation(&str, baseItem),
14268			NULL, NULL);
14269		    FREE_AND_NULL(str);
14270		    /* err = pctxt->err; */
14271		}
14272	    }
14273	}
14274    }
14275    /*
14276    * SPEC derivation-ok-restriction (3):
14277    * (3) "For each attribute use in the {attribute uses} of the {base type
14278    * definition} whose {required} is true, there must be an attribute
14279    * use with an {attribute declaration} with the same {name} and
14280    * {target namespace} as its {attribute declaration} in the {attribute
14281    * uses} of the complex type definition itself whose {required} is true.
14282    */
14283    if (baseUses != NULL) {
14284	for (j = 0; j < baseUses->nbItems; j++) {
14285	    bcur = baseUses->items[j];
14286	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14287		continue;
14288	    found = 0;
14289	    if (uses != NULL) {
14290		for (i = 0; i < uses->nbItems; i++) {
14291		    cur = uses->items[i];
14292		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14293			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14294			(WXS_ATTRUSE_DECL_TNS(cur) ==
14295			WXS_ATTRUSE_DECL_TNS(bcur))) {
14296			found = 1;
14297			break;
14298		    }
14299		}
14300	    }
14301	    if (!found) {
14302		xmlChar *strA = NULL, *strB = NULL;
14303
14304		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14305		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14306		    NULL, item,
14307		    "A matching attribute use for the "
14308		    "'required' %s of the %s %s is missing",
14309		    xmlSchemaGetComponentDesignation(&strA, bcur),
14310		    WXS_ACTION_STR(action),
14311		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14312		    NULL);
14313		FREE_AND_NULL(strA);
14314		FREE_AND_NULL(strB);
14315	    }
14316	}
14317    }
14318    /*
14319    * derivation-ok-restriction (4)
14320    */
14321    if (wild != NULL) {
14322	/*
14323	* (4) "If there is an {attribute wildcard}, all of the
14324	* following must be true:"
14325	*/
14326	if (baseWild == NULL) {
14327	    xmlChar *str = NULL;
14328
14329	    /*
14330	    * (4.1) "The {base type definition} must also have one."
14331	    */
14332	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14333		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14334		NULL, item,
14335		"The %s has an attribute wildcard, "
14336		"but the %s %s '%s' does not have one",
14337		WXS_ITEM_TYPE_NAME(item),
14338		WXS_ACTION_STR(action),
14339		WXS_ITEM_TYPE_NAME(baseItem),
14340		xmlSchemaGetComponentQName(&str, baseItem));
14341	    FREE_AND_NULL(str);
14342	    return(pctxt->err);
14343	} else if ((baseWild->any == 0) &&
14344		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14345	{
14346	    xmlChar *str = NULL;
14347	    /*
14348	    * (4.2) "The complex type definition's {attribute wildcard}'s
14349	    * {namespace constraint} must be a subset of the {base type
14350	    * definition}'s {attribute wildcard}'s {namespace constraint},
14351	    * as defined by Wildcard Subset ($3.10.6)."
14352	    */
14353	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14354		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14355		NULL, item,
14356		"The attribute wildcard is not a valid "
14357		"subset of the wildcard in the %s %s '%s'",
14358		WXS_ACTION_STR(action),
14359		WXS_ITEM_TYPE_NAME(baseItem),
14360		xmlSchemaGetComponentQName(&str, baseItem),
14361		NULL);
14362	    FREE_AND_NULL(str);
14363	    return(pctxt->err);
14364	}
14365	/* 4.3 Unless the {base type definition} is the `ur-type
14366	* definition`, the complex type definition's {attribute
14367	* wildcard}'s {process contents} must be identical to or
14368	* stronger than the {base type definition}'s {attribute
14369	* wildcard}'s {process contents}, where strict is stronger
14370	* than lax is stronger than skip.
14371	*/
14372	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14373	    (wild->processContents < baseWild->processContents)) {
14374	    xmlChar *str = NULL;
14375	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14376		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14377		NULL, baseItem,
14378		"The {process contents} of the attribute wildcard is "
14379		"weaker than the one in the %s %s '%s'",
14380		WXS_ACTION_STR(action),
14381		WXS_ITEM_TYPE_NAME(baseItem),
14382		xmlSchemaGetComponentQName(&str, baseItem),
14383		NULL);
14384	    FREE_AND_NULL(str)
14385		return(pctxt->err);
14386	}
14387    }
14388    return(0);
14389}
14390
14391
14392static int
14393xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14394				  xmlSchemaBasicItemPtr item,
14395				  xmlSchemaWildcardPtr *completeWild,
14396				  xmlSchemaItemListPtr list,
14397				  xmlSchemaItemListPtr prohibs);
14398/**
14399 * xmlSchemaFixupTypeAttributeUses:
14400 * @ctxt:  the schema parser context
14401 * @type:  the complex type definition
14402 *
14403 *
14404 * Builds the wildcard and the attribute uses on the given complex type.
14405 * Returns -1 if an internal error occurs, 0 otherwise.
14406 *
14407 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14408 * strings, so recheck this if we start to hardcode some schemata, since
14409 * they might not be in the same dict.
14410 * NOTE: It is allowed to "extend" the xs:anyType type.
14411 */
14412static int
14413xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14414				  xmlSchemaTypePtr type)
14415{
14416    xmlSchemaTypePtr baseType = NULL;
14417    xmlSchemaAttributeUsePtr use;
14418    xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14419
14420    if (type->baseType == NULL) {
14421	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14422	    "no base type");
14423        return (-1);
14424    }
14425    baseType = type->baseType;
14426    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14427	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14428	    return(-1);
14429
14430    uses = type->attrUses;
14431    baseUses = baseType->attrUses;
14432    /*
14433    * Expand attribute group references. And build the 'complete'
14434    * wildcard, i.e. intersect multiple wildcards.
14435    * Move attribute prohibitions into a separate list.
14436    */
14437    if (uses != NULL) {
14438	if (WXS_IS_RESTRICTION(type)) {
14439	    /*
14440	    * This one will transfer all attr. prohibitions
14441	    * into pctxt->attrProhibs.
14442	    */
14443	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14444		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14445		pctxt->attrProhibs) == -1)
14446	    {
14447		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14448		"failed to expand attributes");
14449	    }
14450	    if (pctxt->attrProhibs->nbItems != 0)
14451		prohibs = pctxt->attrProhibs;
14452	} else {
14453	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14454		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14455		NULL) == -1)
14456	    {
14457		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14458		"failed to expand attributes");
14459	    }
14460	}
14461    }
14462    /*
14463    * Inherit the attribute uses of the base type.
14464    */
14465    if (baseUses != NULL) {
14466	int i, j;
14467	xmlSchemaAttributeUseProhibPtr pro;
14468
14469	if (WXS_IS_RESTRICTION(type)) {
14470	    int usesCount;
14471	    xmlSchemaAttributeUsePtr tmp;
14472
14473	    if (uses != NULL)
14474		usesCount = uses->nbItems;
14475	    else
14476		usesCount = 0;
14477
14478	    /* Restriction. */
14479	    for (i = 0; i < baseUses->nbItems; i++) {
14480		use = baseUses->items[i];
14481		if (prohibs) {
14482		    /*
14483		    * Filter out prohibited uses.
14484		    */
14485		    for (j = 0; j < prohibs->nbItems; j++) {
14486			pro = prohibs->items[j];
14487			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14488			    (WXS_ATTRUSE_DECL_TNS(use) ==
14489				pro->targetNamespace))
14490			{
14491			    goto inherit_next;
14492			}
14493		    }
14494		}
14495		if (usesCount) {
14496		    /*
14497		    * Filter out existing uses.
14498		    */
14499		    for (j = 0; j < usesCount; j++) {
14500			tmp = uses->items[j];
14501			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14502				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14503			    (WXS_ATTRUSE_DECL_TNS(use) ==
14504				WXS_ATTRUSE_DECL_TNS(tmp)))
14505			{
14506			    goto inherit_next;
14507			}
14508		    }
14509		}
14510		if (uses == NULL) {
14511		    type->attrUses = xmlSchemaItemListCreate();
14512		    if (type->attrUses == NULL)
14513			goto exit_failure;
14514		    uses = type->attrUses;
14515		}
14516		xmlSchemaItemListAddSize(uses, 2, use);
14517inherit_next: {}
14518	    }
14519	} else {
14520	    /* Extension. */
14521	    for (i = 0; i < baseUses->nbItems; i++) {
14522		use = baseUses->items[i];
14523		if (uses == NULL) {
14524		    type->attrUses = xmlSchemaItemListCreate();
14525		    if (type->attrUses == NULL)
14526			goto exit_failure;
14527		    uses = type->attrUses;
14528		}
14529		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14530	    }
14531	}
14532    }
14533    /*
14534    * Shrink attr. uses.
14535    */
14536    if (uses) {
14537	if (uses->nbItems == 0) {
14538	    xmlSchemaItemListFree(uses);
14539	    type->attrUses = NULL;
14540	}
14541	/*
14542	* TODO: We could shrink the size of the array
14543	* to fit the actual number of items.
14544	*/
14545    }
14546    /*
14547    * Compute the complete wildcard.
14548    */
14549    if (WXS_IS_EXTENSION(type)) {
14550	if (baseType->attributeWildcard != NULL) {
14551	    /*
14552	    * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14553	    * the appropriate case among the following:"
14554	    */
14555	    if (type->attributeWildcard != NULL) {
14556		/*
14557		* Union the complete wildcard with the base wildcard.
14558		* SPEC {attribute wildcard}
14559		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14560		* and {annotation} are those of the `complete wildcard`,
14561		* and whose {namespace constraint} is the intensional union
14562		* of the {namespace constraint} of the `complete wildcard`
14563		* and of the `base wildcard`, as defined in Attribute
14564		* Wildcard Union ($3.10.6)."
14565		*/
14566		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14567		    baseType->attributeWildcard) == -1)
14568		    goto exit_failure;
14569	    } else {
14570		/*
14571		* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14572		* then the `base wildcard`."
14573		*/
14574		type->attributeWildcard = baseType->attributeWildcard;
14575	    }
14576	} else {
14577	    /*
14578	    * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14579	    * `complete wildcard`"
14580	    * NOOP
14581	    */
14582	}
14583    } else {
14584	/*
14585	* SPEC {attribute wildcard}
14586	* (3.1) "If the <restriction> alternative is chosen, then the
14587	* `complete wildcard`;"
14588	* NOOP
14589	*/
14590    }
14591
14592    return (0);
14593
14594exit_failure:
14595    return(-1);
14596}
14597
14598/**
14599 * xmlSchemaTypeFinalContains:
14600 * @schema:  the schema
14601 * @type:  the type definition
14602 * @final: the final
14603 *
14604 * Evaluates if a type definition contains the given "final".
14605 * This does take "finalDefault" into account as well.
14606 *
14607 * Returns 1 if the type does containt the given "final",
14608 * 0 otherwise.
14609 */
14610static int
14611xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14612{
14613    if (type == NULL)
14614	return (0);
14615    if (type->flags & final)
14616	return (1);
14617    else
14618	return (0);
14619}
14620
14621/**
14622 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14623 * @type:  the Union Simple Type
14624 *
14625 * Returns a list of member types of @type if existing,
14626 * returns NULL otherwise.
14627 */
14628static xmlSchemaTypeLinkPtr
14629xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14630{
14631    while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14632	if (type->memberTypes != NULL)
14633	    return (type->memberTypes);
14634	else
14635	    type = type->baseType;
14636    }
14637    return (NULL);
14638}
14639
14640/**
14641 * xmlSchemaGetParticleTotalRangeMin:
14642 * @particle: the particle
14643 *
14644 * Schema Component Constraint: Effective Total Range
14645 * (all and sequence) + (choice)
14646 *
14647 * Returns the minimun Effective Total Range.
14648 */
14649static int
14650xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14651{
14652    if ((particle->children == NULL) ||
14653	(particle->minOccurs == 0))
14654	return (0);
14655    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14656	int min = -1, cur;
14657	xmlSchemaParticlePtr part =
14658	    (xmlSchemaParticlePtr) particle->children->children;
14659
14660	if (part == NULL)
14661	    return (0);
14662	while (part != NULL) {
14663	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14664		(part->children->type == XML_SCHEMA_TYPE_ANY))
14665		cur = part->minOccurs;
14666	    else
14667		cur = xmlSchemaGetParticleTotalRangeMin(part);
14668	    if (cur == 0)
14669		return (0);
14670	    if ((min > cur) || (min == -1))
14671		min = cur;
14672	    part = (xmlSchemaParticlePtr) part->next;
14673	}
14674	return (particle->minOccurs * min);
14675    } else {
14676	/* <all> and <sequence> */
14677	int sum = 0;
14678	xmlSchemaParticlePtr part =
14679	    (xmlSchemaParticlePtr) particle->children->children;
14680
14681	if (part == NULL)
14682	    return (0);
14683	do {
14684	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14685		(part->children->type == XML_SCHEMA_TYPE_ANY))
14686		sum += part->minOccurs;
14687	    else
14688		sum += xmlSchemaGetParticleTotalRangeMin(part);
14689	    part = (xmlSchemaParticlePtr) part->next;
14690	} while (part != NULL);
14691	return (particle->minOccurs * sum);
14692    }
14693}
14694
14695#if 0
14696/**
14697 * xmlSchemaGetParticleTotalRangeMax:
14698 * @particle: the particle
14699 *
14700 * Schema Component Constraint: Effective Total Range
14701 * (all and sequence) + (choice)
14702 *
14703 * Returns the maximum Effective Total Range.
14704 */
14705static int
14706xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14707{
14708    if ((particle->children == NULL) ||
14709	(particle->children->children == NULL))
14710	return (0);
14711    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14712	int max = -1, cur;
14713	xmlSchemaParticlePtr part =
14714	    (xmlSchemaParticlePtr) particle->children->children;
14715
14716	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14717	    if (part->children == NULL)
14718		continue;
14719	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14720		(part->children->type == XML_SCHEMA_TYPE_ANY))
14721		cur = part->maxOccurs;
14722	    else
14723		cur = xmlSchemaGetParticleTotalRangeMax(part);
14724	    if (cur == UNBOUNDED)
14725		return (UNBOUNDED);
14726	    if ((max < cur) || (max == -1))
14727		max = cur;
14728	}
14729	/* TODO: Handle overflows? */
14730	return (particle->maxOccurs * max);
14731    } else {
14732	/* <all> and <sequence> */
14733	int sum = 0, cur;
14734	xmlSchemaParticlePtr part =
14735	    (xmlSchemaParticlePtr) particle->children->children;
14736
14737	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14738	    if (part->children == NULL)
14739		continue;
14740	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14741		(part->children->type == XML_SCHEMA_TYPE_ANY))
14742		cur = part->maxOccurs;
14743	    else
14744		cur = xmlSchemaGetParticleTotalRangeMax(part);
14745	    if (cur == UNBOUNDED)
14746		return (UNBOUNDED);
14747	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14748		return (UNBOUNDED);
14749	    sum += cur;
14750	}
14751	/* TODO: Handle overflows? */
14752	return (particle->maxOccurs * sum);
14753    }
14754}
14755#endif
14756
14757/**
14758 * xmlSchemaIsParticleEmptiable:
14759 * @particle: the particle
14760 *
14761 * Schema Component Constraint: Particle Emptiable
14762 * Checks whether the given particle is emptiable.
14763 *
14764 * Returns 1 if emptiable, 0 otherwise.
14765 */
14766static int
14767xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14768{
14769    /*
14770    * SPEC (1) "Its {min occurs} is 0."
14771    */
14772    if ((particle == NULL) || (particle->minOccurs == 0) ||
14773	(particle->children == NULL))
14774	return (1);
14775    /*
14776    * SPEC (2) "Its {term} is a group and the minimum part of the
14777    * effective total range of that group, [...] is 0."
14778    */
14779    if (WXS_IS_MODEL_GROUP(particle->children)) {
14780	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14781	    return (1);
14782    }
14783    return (0);
14784}
14785
14786/**
14787 * xmlSchemaCheckCOSSTDerivedOK:
14788 * @actxt: a context
14789 * @type:  the derived simple type definition
14790 * @baseType:  the base type definition
14791 * @subset: the subset of ('restriction', ect.)
14792 *
14793 * Schema Component Constraint:
14794 * Type Derivation OK (Simple) (cos-st-derived-OK)
14795 *
14796 * Checks wheter @type can be validly
14797 * derived from @baseType.
14798 *
14799 * Returns 0 on success, an positive error code otherwise.
14800 */
14801static int
14802xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14803			     xmlSchemaTypePtr type,
14804			     xmlSchemaTypePtr baseType,
14805			     int subset)
14806{
14807    /*
14808    * 1 They are the same type definition.
14809    * TODO: The identy check might have to be more complex than this.
14810    */
14811    if (type == baseType)
14812	return (0);
14813    /*
14814    * 2.1 restriction is not in the subset, or in the {final}
14815    * of its own {base type definition};
14816    *
14817    * NOTE that this will be used also via "xsi:type".
14818    *
14819    * TODO: Revise this, it looks strange. How can the "type"
14820    * not be fixed or *in* fixing?
14821    */
14822    if (WXS_IS_TYPE_NOT_FIXED(type))
14823	if (xmlSchemaTypeFixup(type, actxt) == -1)
14824	    return(-1);
14825    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14826	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14827	    return(-1);
14828    if ((subset & SUBSET_RESTRICTION) ||
14829	(xmlSchemaTypeFinalContains(type->baseType,
14830	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14831	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14832    }
14833    /* 2.2 */
14834    if (type->baseType == baseType) {
14835	/*
14836	* 2.2.1 D's `base type definition` is B.
14837	*/
14838	return (0);
14839    }
14840    /*
14841    * 2.2.2 D's `base type definition` is not the `ur-type definition`
14842    * and is validly derived from B given the subset, as defined by this
14843    * constraint.
14844    */
14845    if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14846	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14847	    baseType, subset) == 0)) {
14848	return (0);
14849    }
14850    /*
14851    * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14852    * definition`.
14853    */
14854    if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14855	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14856	return (0);
14857    }
14858    /*
14859    * 2.2.4 B's {variety} is union and D is validly derived from a type
14860    * definition in B's {member type definitions} given the subset, as
14861    * defined by this constraint.
14862    *
14863    * NOTE: This seems not to involve built-in types, since there is no
14864    * built-in Union Simple Type.
14865    */
14866    if (WXS_IS_UNION(baseType)) {
14867	xmlSchemaTypeLinkPtr cur;
14868
14869	cur = baseType->memberTypes;
14870	while (cur != NULL) {
14871	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14872		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14873		    return(-1);
14874	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14875		    type, cur->type, subset) == 0)
14876	    {
14877		/*
14878		* It just has to be validly derived from at least one
14879		* member-type.
14880		*/
14881		return (0);
14882	    }
14883	    cur = cur->next;
14884	}
14885    }
14886    return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14887}
14888
14889/**
14890 * xmlSchemaCheckTypeDefCircularInternal:
14891 * @pctxt:  the schema parser context
14892 * @ctxtType:  the type definition
14893 * @ancestor: an ancestor of @ctxtType
14894 *
14895 * Checks st-props-correct (2) + ct-props-correct (3).
14896 * Circular type definitions are not allowed.
14897 *
14898 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14899 * circular, 0 otherwise.
14900 */
14901static int
14902xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14903			   xmlSchemaTypePtr ctxtType,
14904			   xmlSchemaTypePtr ancestor)
14905{
14906    int ret;
14907
14908    if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14909	return (0);
14910
14911    if (ctxtType == ancestor) {
14912	xmlSchemaPCustomErr(pctxt,
14913	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14914	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14915	    "The definition is circular", NULL);
14916	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14917    }
14918    if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14919	/*
14920	* Avoid inifinite recursion on circular types not yet checked.
14921	*/
14922	return (0);
14923    }
14924    ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14925    ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14926	ancestor->baseType);
14927    ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14928    return (ret);
14929}
14930
14931/**
14932 * xmlSchemaCheckTypeDefCircular:
14933 * @item:  the complex/simple type definition
14934 * @ctxt:  the parser context
14935 * @name:  the name
14936 *
14937 * Checks for circular type definitions.
14938 */
14939static void
14940xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14941			      xmlSchemaParserCtxtPtr ctxt)
14942{
14943    if ((item == NULL) ||
14944	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14945	(item->baseType == NULL))
14946	return;
14947    xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14948	item->baseType);
14949}
14950
14951/*
14952* Simple Type Definition Representation OK (src-simple-type) 4
14953*
14954* "4 Circular union type definition is disallowed. That is, if the
14955* <union> alternative is chosen, there must not be any entries in the
14956* memberTypes [attribute] at any depth which resolve to the component
14957* corresponding to the <simpleType>."
14958*
14959* Note that this should work on the *representation* of a component,
14960* thus assumes any union types in the member types not being yet
14961* substituted. At this stage we need the variety of the types
14962* to be already computed.
14963*/
14964static int
14965xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14966					xmlSchemaTypePtr ctxType,
14967					xmlSchemaTypeLinkPtr members)
14968{
14969    xmlSchemaTypeLinkPtr member;
14970    xmlSchemaTypePtr memberType;
14971
14972    member = members;
14973    while (member != NULL) {
14974	memberType = member->type;
14975	while ((memberType != NULL) &&
14976	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14977	    if (memberType == ctxType) {
14978		xmlSchemaPCustomErr(pctxt,
14979		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14980		    WXS_BASIC_CAST ctxType, NULL,
14981		    "The union type definition is circular", NULL);
14982		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14983	    }
14984	    if ((WXS_IS_UNION(memberType)) &&
14985		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14986	    {
14987		int res;
14988		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14989		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14990		    ctxType,
14991		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14992		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14993		if (res != 0)
14994		    return(res);
14995	    }
14996	    memberType = memberType->baseType;
14997	}
14998	member = member->next;
14999    }
15000    return(0);
15001}
15002
15003static int
15004xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15005				   xmlSchemaTypePtr type)
15006{
15007    if (! WXS_IS_UNION(type))
15008	return(0);
15009    return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15010	type->memberTypes));
15011}
15012
15013/**
15014 * xmlSchemaResolveTypeReferences:
15015 * @item:  the complex/simple type definition
15016 * @ctxt:  the parser context
15017 * @name:  the name
15018 *
15019 * Resolvese type definition references
15020 */
15021static void
15022xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15023			 xmlSchemaParserCtxtPtr ctxt)
15024{
15025    if (typeDef == NULL)
15026	return;
15027
15028    /*
15029    * Resolve the base type.
15030    */
15031    if (typeDef->baseType == NULL) {
15032	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15033	    typeDef->base, typeDef->baseNs);
15034	if (typeDef->baseType == NULL) {
15035	    xmlSchemaPResCompAttrErr(ctxt,
15036		XML_SCHEMAP_SRC_RESOLVE,
15037		WXS_BASIC_CAST typeDef, typeDef->node,
15038		"base", typeDef->base, typeDef->baseNs,
15039		XML_SCHEMA_TYPE_SIMPLE, NULL);
15040	    return;
15041	}
15042    }
15043    if (WXS_IS_SIMPLE(typeDef)) {
15044	if (WXS_IS_UNION(typeDef)) {
15045	    /*
15046	    * Resolve the memberTypes.
15047	    */
15048	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15049	    return;
15050	} else if (WXS_IS_LIST(typeDef)) {
15051	    /*
15052	    * Resolve the itemType.
15053	    */
15054	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15055
15056		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15057		    typeDef->base, typeDef->baseNs);
15058
15059		if ((typeDef->subtypes == NULL) ||
15060		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15061		{
15062		    typeDef->subtypes = NULL;
15063		    xmlSchemaPResCompAttrErr(ctxt,
15064			XML_SCHEMAP_SRC_RESOLVE,
15065			WXS_BASIC_CAST typeDef, typeDef->node,
15066			"itemType", typeDef->base, typeDef->baseNs,
15067			XML_SCHEMA_TYPE_SIMPLE, NULL);
15068		}
15069	    }
15070	    return;
15071	}
15072    }
15073    /*
15074    * The ball of letters below means, that if we have a particle
15075    * which has a QName-helper component as its {term}, we want
15076    * to resolve it...
15077    */
15078    else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15079	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15080	    XML_SCHEMA_TYPE_PARTICLE) &&
15081	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15082	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15083	    XML_SCHEMA_EXTRA_QNAMEREF))
15084    {
15085	xmlSchemaQNameRefPtr ref =
15086	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15087	xmlSchemaModelGroupDefPtr groupDef;
15088
15089	/*
15090	* URGENT TODO: Test this.
15091	*/
15092	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15093	/*
15094	* Resolve the MG definition reference.
15095	*/
15096	groupDef =
15097	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15098		ref->itemType, ref->name, ref->targetNamespace);
15099	if (groupDef == NULL) {
15100	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15101		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15102		"ref", ref->name, ref->targetNamespace, ref->itemType,
15103		NULL);
15104	    /* Remove the particle. */
15105	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15106	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15107	    /* Remove the particle. */
15108	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15109	else {
15110	    /*
15111	    * Assign the MG definition's {model group} to the
15112	    * particle's {term}.
15113	    */
15114	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15115
15116	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15117		/*
15118		* SPEC cos-all-limited (1.2)
15119		* "1.2 the {term} property of a particle with
15120		* {max occurs}=1 which is part of a pair which constitutes
15121		* the {content type} of a complex type definition."
15122		*/
15123		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15124		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15125			/* TODO: error code */
15126			XML_SCHEMAP_COS_ALL_LIMITED,
15127			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15128			"The particle's {max occurs} must be 1, since the "
15129			"reference resolves to an 'all' model group",
15130			NULL, NULL);
15131		}
15132	    }
15133	}
15134    }
15135}
15136
15137
15138
15139/**
15140 * xmlSchemaCheckSTPropsCorrect:
15141 * @ctxt:  the schema parser context
15142 * @type:  the simple type definition
15143 *
15144 * Checks st-props-correct.
15145 *
15146 * Returns 0 if the properties are correct,
15147 * if not, a positive error code and -1 on internal
15148 * errors.
15149 */
15150static int
15151xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15152			     xmlSchemaTypePtr type)
15153{
15154    xmlSchemaTypePtr baseType = type->baseType;
15155    xmlChar *str = NULL;
15156
15157    /* STATE: error funcs converted. */
15158    /*
15159    * Schema Component Constraint: Simple Type Definition Properties Correct
15160    *
15161    * NOTE: This is somehow redundant, since we actually built a simple type
15162    * to have all the needed information; this acts as an self test.
15163    */
15164    /* Base type: If the datatype has been `derived` by `restriction`
15165    * then the Simple Type Definition component from which it is `derived`,
15166    * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15167    */
15168    if (baseType == NULL) {
15169	/*
15170	* TODO: Think about: "modulo the impact of Missing
15171	* Sub-components ($5.3)."
15172	*/
15173	xmlSchemaPCustomErr(ctxt,
15174	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15175	    WXS_BASIC_CAST type, NULL,
15176	    "No base type existent", NULL);
15177	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15178
15179    }
15180    if (! WXS_IS_SIMPLE(baseType)) {
15181	xmlSchemaPCustomErr(ctxt,
15182	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15183	    WXS_BASIC_CAST type, NULL,
15184	    "The base type '%s' is not a simple type",
15185	    xmlSchemaGetComponentQName(&str, baseType));
15186	FREE_AND_NULL(str)
15187	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15188    }
15189    if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15190	(WXS_IS_RESTRICTION(type) == 0) &&
15191	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15192         (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15193	xmlSchemaPCustomErr(ctxt,
15194	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15195	    WXS_BASIC_CAST type, NULL,
15196	    "A type, derived by list or union, must have "
15197	    "the simple ur-type definition as base type, not '%s'",
15198	    xmlSchemaGetComponentQName(&str, baseType));
15199	FREE_AND_NULL(str)
15200	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15201    }
15202    /*
15203    * Variety: One of {atomic, list, union}.
15204    */
15205    if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15206	(! WXS_IS_LIST(type))) {
15207	xmlSchemaPCustomErr(ctxt,
15208	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15209	    WXS_BASIC_CAST type, NULL,
15210	    "The variety is absent", NULL);
15211	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15212    }
15213    /* TODO: Finish this. Hmm, is this finished? */
15214
15215    /*
15216    * 3 The {final} of the {base type definition} must not contain restriction.
15217    */
15218    if (xmlSchemaTypeFinalContains(baseType,
15219	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15220	xmlSchemaPCustomErr(ctxt,
15221	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15222	    WXS_BASIC_CAST type, NULL,
15223	    "The 'final' of its base type '%s' must not contain "
15224	    "'restriction'",
15225	    xmlSchemaGetComponentQName(&str, baseType));
15226	FREE_AND_NULL(str)
15227	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15228    }
15229
15230    /*
15231    * 2 All simple type definitions must be derived ultimately from the `simple
15232    * ur-type definition` (so circular definitions are disallowed). That is, it
15233    * must be possible to reach a built-in primitive datatype or the `simple
15234    * ur-type definition` by repeatedly following the {base type definition}.
15235    *
15236    * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15237    */
15238    return (0);
15239}
15240
15241/**
15242 * xmlSchemaCheckCOSSTRestricts:
15243 * @ctxt:  the schema parser context
15244 * @type:  the simple type definition
15245 *
15246 * Schema Component Constraint:
15247 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15248
15249 * Checks if the given @type (simpleType) is derived validly by restriction.
15250 * STATUS:
15251 *
15252 * Returns -1 on internal errors, 0 if the type is validly derived,
15253 * a positive error code otherwise.
15254 */
15255static int
15256xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15257			     xmlSchemaTypePtr type)
15258{
15259    xmlChar *str = NULL;
15260
15261    if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15262	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15263	    "given type is not a user-derived simpleType");
15264	return (-1);
15265    }
15266
15267    if (WXS_IS_ATOMIC(type)) {
15268	xmlSchemaTypePtr primitive;
15269	/*
15270	* 1.1 The {base type definition} must be an atomic simple
15271	* type definition or a built-in primitive datatype.
15272	*/
15273	if (! WXS_IS_ATOMIC(type->baseType)) {
15274	    xmlSchemaPCustomErr(pctxt,
15275		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15276		WXS_BASIC_CAST type, NULL,
15277		"The base type '%s' is not an atomic simple type",
15278		xmlSchemaGetComponentQName(&str, type->baseType));
15279	    FREE_AND_NULL(str)
15280	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15281	}
15282	/* 1.2 The {final} of the {base type definition} must not contain
15283	* restriction.
15284	*/
15285	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15286	if (xmlSchemaTypeFinalContains(type->baseType,
15287	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15288	    xmlSchemaPCustomErr(pctxt,
15289		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15290		WXS_BASIC_CAST type, NULL,
15291		"The final of its base type '%s' must not contain 'restriction'",
15292		xmlSchemaGetComponentQName(&str, type->baseType));
15293	    FREE_AND_NULL(str)
15294	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15295	}
15296
15297	/*
15298	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15299	* type definition}, as specified in the appropriate subsection of 3.2
15300	* Primitive datatypes.
15301	*/
15302	if (type->facets != NULL) {
15303	    xmlSchemaFacetPtr facet;
15304	    int ok = 1;
15305
15306	    primitive = xmlSchemaGetPrimitiveType(type);
15307	    if (primitive == NULL) {
15308		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309		    "failed to get primitive type");
15310		return (-1);
15311	    }
15312	    facet = type->facets;
15313	    do {
15314		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15315		    ok = 0;
15316		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15317			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15318			type, primitive, facet);
15319		}
15320		facet = facet->next;
15321	    } while (facet != NULL);
15322	    if (ok == 0)
15323		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15324	}
15325	/*
15326	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15327	* of the {base type definition} (call this BF),then the DF's {value}
15328	* must be a valid restriction of BF's {value} as defined in
15329	* [XML Schemas: Datatypes]."
15330	*
15331	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15332	* xmlSchemaDeriveAndValidateFacets()
15333	*/
15334    } else if (WXS_IS_LIST(type)) {
15335	xmlSchemaTypePtr itemType = NULL;
15336
15337	itemType = type->subtypes;
15338	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15339	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15340		"failed to evaluate the item type");
15341	    return (-1);
15342	}
15343	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15344	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15345	/*
15346	* 2.1 The {item type definition} must have a {variety} of atomic or
15347	* union (in which case all the {member type definitions}
15348	* must be atomic).
15349	*/
15350	if ((! WXS_IS_ATOMIC(itemType)) &&
15351	    (! WXS_IS_UNION(itemType))) {
15352	    xmlSchemaPCustomErr(pctxt,
15353		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15354		WXS_BASIC_CAST type, NULL,
15355		"The item type '%s' does not have a variety of atomic or union",
15356		xmlSchemaGetComponentQName(&str, itemType));
15357	    FREE_AND_NULL(str)
15358	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15359	} else if (WXS_IS_UNION(itemType)) {
15360	    xmlSchemaTypeLinkPtr member;
15361
15362	    member = itemType->memberTypes;
15363	    while (member != NULL) {
15364		if (! WXS_IS_ATOMIC(member->type)) {
15365		    xmlSchemaPCustomErr(pctxt,
15366			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15367			WXS_BASIC_CAST type, NULL,
15368			"The item type is a union type, but the "
15369			"member type '%s' of this item type is not atomic",
15370			xmlSchemaGetComponentQName(&str, member->type));
15371		    FREE_AND_NULL(str)
15372		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15373		}
15374		member = member->next;
15375	    }
15376	}
15377
15378	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15379	    xmlSchemaFacetPtr facet;
15380	    /*
15381	    * This is the case if we have: <simpleType><list ..
15382	    */
15383	    /*
15384	    * 2.3.1
15385	    * 2.3.1.1 The {final} of the {item type definition} must not
15386	    * contain list.
15387	    */
15388	    if (xmlSchemaTypeFinalContains(itemType,
15389		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15390		xmlSchemaPCustomErr(pctxt,
15391		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15392		    WXS_BASIC_CAST type, NULL,
15393		    "The final of its item type '%s' must not contain 'list'",
15394		    xmlSchemaGetComponentQName(&str, itemType));
15395		FREE_AND_NULL(str)
15396		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15397	    }
15398	    /*
15399	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15400	    * facet component.
15401	    * OPTIMIZE TODO: the S4S already disallows any facet
15402	    * to be specified.
15403	    */
15404	    if (type->facets != NULL) {
15405		facet = type->facets;
15406		do {
15407		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15408			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15409			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15410			    type, facet);
15411			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15412		    }
15413		    facet = facet->next;
15414		} while (facet != NULL);
15415	    }
15416	    /*
15417	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15418	    * A `list` datatype can be `derived` from an `atomic` datatype
15419	    * whose `lexical space` allows space (such as string or anyURI)or
15420	    * a `union` datatype any of whose {member type definitions}'s
15421	    * `lexical space` allows space.
15422	    */
15423	} else {
15424	    /*
15425	    * This is the case if we have: <simpleType><restriction ...
15426	    * I.e. the variety of "list" is inherited.
15427	    */
15428	    /*
15429	    * 2.3.2
15430	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15431	    */
15432	    if (! WXS_IS_LIST(type->baseType)) {
15433		xmlSchemaPCustomErr(pctxt,
15434		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15435		    WXS_BASIC_CAST type, NULL,
15436		    "The base type '%s' must be a list type",
15437		    xmlSchemaGetComponentQName(&str, type->baseType));
15438		FREE_AND_NULL(str)
15439		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15440	    }
15441	    /*
15442	    * 2.3.2.2 The {final} of the {base type definition} must not
15443	    * contain restriction.
15444	    */
15445	    if (xmlSchemaTypeFinalContains(type->baseType,
15446		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15447		xmlSchemaPCustomErr(pctxt,
15448		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15449		    WXS_BASIC_CAST type, NULL,
15450		    "The 'final' of the base type '%s' must not contain 'restriction'",
15451		    xmlSchemaGetComponentQName(&str, type->baseType));
15452		FREE_AND_NULL(str)
15453		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15454	    }
15455	    /*
15456	    * 2.3.2.3 The {item type definition} must be validly derived
15457	    * from the {base type definition}'s {item type definition} given
15458	    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15459	    */
15460	    {
15461		xmlSchemaTypePtr baseItemType;
15462
15463		baseItemType = type->baseType->subtypes;
15464		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15465		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15466			"failed to eval the item type of a base type");
15467		    return (-1);
15468		}
15469		if ((itemType != baseItemType) &&
15470		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15471			baseItemType, 0) != 0)) {
15472		    xmlChar *strBIT = NULL, *strBT = NULL;
15473		    xmlSchemaPCustomErrExt(pctxt,
15474			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15475			WXS_BASIC_CAST type, NULL,
15476			"The item type '%s' is not validly derived from "
15477			"the item type '%s' of the base type '%s'",
15478			xmlSchemaGetComponentQName(&str, itemType),
15479			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15480			xmlSchemaGetComponentQName(&strBT, type->baseType));
15481
15482		    FREE_AND_NULL(str)
15483		    FREE_AND_NULL(strBIT)
15484		    FREE_AND_NULL(strBT)
15485		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15486		}
15487	    }
15488
15489	    if (type->facets != NULL) {
15490		xmlSchemaFacetPtr facet;
15491		int ok = 1;
15492		/*
15493		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15494		* and enumeration facet components are allowed among the {facets}.
15495		*/
15496		facet = type->facets;
15497		do {
15498		    switch (facet->type) {
15499			case XML_SCHEMA_FACET_LENGTH:
15500			case XML_SCHEMA_FACET_MINLENGTH:
15501			case XML_SCHEMA_FACET_MAXLENGTH:
15502			case XML_SCHEMA_FACET_WHITESPACE:
15503			    /*
15504			    * TODO: 2.5.1.2 List datatypes
15505			    * The value of `whiteSpace` is fixed to the value collapse.
15506			    */
15507			case XML_SCHEMA_FACET_PATTERN:
15508			case XML_SCHEMA_FACET_ENUMERATION:
15509			    break;
15510			default: {
15511			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15512				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15513				type, facet);
15514			    /*
15515			    * We could return, but it's nicer to report all
15516			    * invalid facets.
15517			    */
15518			    ok = 0;
15519			}
15520		    }
15521		    facet = facet->next;
15522		} while (facet != NULL);
15523		if (ok == 0)
15524		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15525		/*
15526		* SPEC (2.3.2.5) (same as 1.3.2)
15527		*
15528		* NOTE (2.3.2.5) This is currently done in
15529		* xmlSchemaDeriveAndValidateFacets()
15530		*/
15531	    }
15532	}
15533    } else if (WXS_IS_UNION(type)) {
15534	/*
15535	* 3.1 The {member type definitions} must all have {variety} of
15536	* atomic or list.
15537	*/
15538	xmlSchemaTypeLinkPtr member;
15539
15540	member = type->memberTypes;
15541	while (member != NULL) {
15542	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15543		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15544
15545	    if ((! WXS_IS_ATOMIC(member->type)) &&
15546		(! WXS_IS_LIST(member->type))) {
15547		xmlSchemaPCustomErr(pctxt,
15548		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15549		    WXS_BASIC_CAST type, NULL,
15550		    "The member type '%s' is neither an atomic, nor a list type",
15551		    xmlSchemaGetComponentQName(&str, member->type));
15552		FREE_AND_NULL(str)
15553		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15554	    }
15555	    member = member->next;
15556	}
15557	/*
15558	* 3.3.1 If the {base type definition} is the `simple ur-type
15559	* definition`
15560	*/
15561	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15562	    /*
15563	    * 3.3.1.1 All of the {member type definitions} must have a
15564	    * {final} which does not contain union.
15565	    */
15566	    member = type->memberTypes;
15567	    while (member != NULL) {
15568		if (xmlSchemaTypeFinalContains(member->type,
15569		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15570		    xmlSchemaPCustomErr(pctxt,
15571			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15572			WXS_BASIC_CAST type, NULL,
15573			"The 'final' of member type '%s' contains 'union'",
15574			xmlSchemaGetComponentQName(&str, member->type));
15575		    FREE_AND_NULL(str)
15576		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15577		}
15578		member = member->next;
15579	    }
15580	    /*
15581	    * 3.3.1.2 The {facets} must be empty.
15582	    */
15583	    if (type->facetSet != NULL) {
15584		xmlSchemaPCustomErr(pctxt,
15585		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15586		    WXS_BASIC_CAST type, NULL,
15587		    "No facets allowed", NULL);
15588		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15589	    }
15590	} else {
15591	    /*
15592	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15593	    * I.e. the variety of "list" is inherited.
15594	    */
15595	    if (! WXS_IS_UNION(type->baseType)) {
15596		xmlSchemaPCustomErr(pctxt,
15597		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15598		    WXS_BASIC_CAST type, NULL,
15599		    "The base type '%s' is not a union type",
15600		    xmlSchemaGetComponentQName(&str, type->baseType));
15601		FREE_AND_NULL(str)
15602		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15603	    }
15604	    /*
15605	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15606	    */
15607	    if (xmlSchemaTypeFinalContains(type->baseType,
15608		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15609		xmlSchemaPCustomErr(pctxt,
15610		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15611		    WXS_BASIC_CAST type, NULL,
15612		    "The 'final' of its base type '%s' must not contain 'restriction'",
15613		    xmlSchemaGetComponentQName(&str, type->baseType));
15614		FREE_AND_NULL(str)
15615		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15616	    }
15617	    /*
15618	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15619	    * derived from the corresponding type definitions in the {base
15620	    * type definition}'s {member type definitions} given the empty set,
15621	    * as defined in Type Derivation OK (Simple) ($3.14.6).
15622	    */
15623	    {
15624		xmlSchemaTypeLinkPtr baseMember;
15625
15626		/*
15627		* OPTIMIZE: if the type is restricting, it has no local defined
15628		* member types and inherits the member types of the base type;
15629		* thus a check for equality can be skipped.
15630		*/
15631		/*
15632		* Even worse: I cannot see a scenario where a restricting
15633		* union simple type can have other member types as the member
15634		* types of it's base type. This check seems not necessary with
15635		* respect to the derivation process in libxml2.
15636		* But necessary if constructing types with an API.
15637		*/
15638		if (type->memberTypes != NULL) {
15639		    member = type->memberTypes;
15640		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15641		    if ((member == NULL) && (baseMember != NULL)) {
15642			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15643			    "different number of member types in base");
15644		    }
15645		    while (member != NULL) {
15646			if (baseMember == NULL) {
15647			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15648			    "different number of member types in base");
15649			} else if ((member->type != baseMember->type) &&
15650			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15651				member->type, baseMember->type, 0) != 0)) {
15652			    xmlChar *strBMT = NULL, *strBT = NULL;
15653
15654			    xmlSchemaPCustomErrExt(pctxt,
15655				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15656				WXS_BASIC_CAST type, NULL,
15657				"The member type %s is not validly "
15658				"derived from its corresponding member "
15659				"type %s of the base type %s",
15660				xmlSchemaGetComponentQName(&str, member->type),
15661				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15662				xmlSchemaGetComponentQName(&strBT, type->baseType));
15663			    FREE_AND_NULL(str)
15664			    FREE_AND_NULL(strBMT)
15665			    FREE_AND_NULL(strBT)
15666			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15667			}
15668			member = member->next;
15669                        if (baseMember != NULL)
15670                            baseMember = baseMember->next;
15671		    }
15672		}
15673	    }
15674	    /*
15675	    * 3.3.2.4 Only pattern and enumeration facet components are
15676	    * allowed among the {facets}.
15677	    */
15678	    if (type->facets != NULL) {
15679		xmlSchemaFacetPtr facet;
15680		int ok = 1;
15681
15682		facet = type->facets;
15683		do {
15684		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15685			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15686			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15687				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15688				type, facet);
15689			ok = 0;
15690		    }
15691		    facet = facet->next;
15692		} while (facet != NULL);
15693		if (ok == 0)
15694		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15695
15696	    }
15697	    /*
15698	    * SPEC (3.3.2.5) (same as 1.3.2)
15699	    *
15700	    * NOTE (3.3.2.5) This is currently done in
15701	    * xmlSchemaDeriveAndValidateFacets()
15702	    */
15703	}
15704    }
15705
15706    return (0);
15707}
15708
15709/**
15710 * xmlSchemaCheckSRCSimpleType:
15711 * @ctxt:  the schema parser context
15712 * @type:  the simple type definition
15713 *
15714 * Checks crc-simple-type constraints.
15715 *
15716 * Returns 0 if the constraints are satisfied,
15717 * if not a positive error code and -1 on internal
15718 * errors.
15719 */
15720#if 0
15721static int
15722xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15723			    xmlSchemaTypePtr type)
15724{
15725    /*
15726    * src-simple-type.1 The corresponding simple type definition, if any,
15727    * must satisfy the conditions set out in Constraints on Simple Type
15728    * Definition Schema Components ($3.14.6).
15729    */
15730    if (WXS_IS_RESTRICTION(type)) {
15731	/*
15732	* src-simple-type.2 "If the <restriction> alternative is chosen,
15733	* either it must have a base [attribute] or a <simpleType> among its
15734	* [children], but not both."
15735	* NOTE: This is checked in the parse function of <restriction>.
15736	*/
15737	/*
15738	*
15739	*/
15740    } else if (WXS_IS_LIST(type)) {
15741	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15742	* an itemType [attribute] or a <simpleType> among its [children],
15743	* but not both."
15744	*
15745	* NOTE: This is checked in the parse function of <list>.
15746	*/
15747    } else if (WXS_IS_UNION(type)) {
15748	/*
15749	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15750	*/
15751    }
15752    return (0);
15753}
15754#endif
15755
15756static int
15757xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15758{
15759   if (ctxt->vctxt == NULL) {
15760	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15761	if (ctxt->vctxt == NULL) {
15762	    xmlSchemaPErr(ctxt, NULL,
15763		XML_SCHEMAP_INTERNAL,
15764		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15765		"failed to create a temp. validation context.\n",
15766		NULL, NULL);
15767	    return (-1);
15768	}
15769	/* TODO: Pass user data. */
15770	xmlSchemaSetValidErrors(ctxt->vctxt,
15771	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15772	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15773	    ctxt->serror, ctxt->errCtxt);
15774    }
15775    return (0);
15776}
15777
15778static int
15779xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15780			     xmlNodePtr node,
15781			     xmlSchemaTypePtr type,
15782			     const xmlChar *value,
15783			     xmlSchemaValPtr *retVal,
15784			     int fireErrors,
15785			     int normalize,
15786			     int isNormalized);
15787
15788/**
15789 * xmlSchemaParseCheckCOSValidDefault:
15790 * @pctxt:  the schema parser context
15791 * @type:  the simple type definition
15792 * @value: the default value
15793 * @node: an optional node (the holder of the value)
15794 *
15795 * Schema Component Constraint: Element Default Valid (Immediate)
15796 * (cos-valid-default)
15797 * This will be used by the parser only. For the validator there's
15798 * an other version.
15799 *
15800 * Returns 0 if the constraints are satisfied,
15801 * if not, a positive error code and -1 on internal
15802 * errors.
15803 */
15804static int
15805xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15806				   xmlNodePtr node,
15807				   xmlSchemaTypePtr type,
15808				   const xmlChar *value,
15809				   xmlSchemaValPtr *val)
15810{
15811    int ret = 0;
15812
15813    /*
15814    * cos-valid-default:
15815    * Schema Component Constraint: Element Default Valid (Immediate)
15816    * For a string to be a valid default with respect to a type
15817    * definition the appropriate case among the following must be true:
15818    */
15819    if WXS_IS_COMPLEX(type) {
15820	/*
15821	* Complex type.
15822	*
15823	* SPEC (2.1) "its {content type} must be a simple type definition
15824	* or mixed."
15825	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15826	* type}'s particle must be `emptiable` as defined by
15827	* Particle Emptiable ($3.9.6)."
15828	*/
15829	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15830	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15831	    /* NOTE that this covers (2.2.2) as well. */
15832	    xmlSchemaPCustomErr(pctxt,
15833		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15834		WXS_BASIC_CAST type, type->node,
15835		"For a string to be a valid default, the type definition "
15836		"must be a simple type or a complex type with mixed content "
15837		"and a particle emptiable", NULL);
15838	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15839	}
15840    }
15841    /*
15842    * 1 If the type definition is a simple type definition, then the string
15843    * must be `valid` with respect to that definition as defined by String
15844    * Valid ($3.14.4).
15845    *
15846    * AND
15847    *
15848    * 2.2.1 If the {content type} is a simple type definition, then the
15849    * string must be `valid` with respect to that simple type definition
15850    * as defined by String Valid ($3.14.4).
15851    */
15852    if (WXS_IS_SIMPLE(type))
15853	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15854	    type, value, val, 1, 1, 0);
15855    else if (WXS_HAS_SIMPLE_CONTENT(type))
15856	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15857	    type->contentTypeDef, value, val, 1, 1, 0);
15858    else
15859	return (ret);
15860
15861    if (ret < 0) {
15862	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15863	    "calling xmlSchemaVCheckCVCSimpleType()");
15864    }
15865
15866    return (ret);
15867}
15868
15869/**
15870 * xmlSchemaCheckCTPropsCorrect:
15871 * @ctxt:  the schema parser context
15872 * @type:  the complex type definition
15873 *
15874 *.(4.6) Constraints on Complex Type Definition Schema Components
15875 * Schema Component Constraint:
15876 * Complex Type Definition Properties Correct (ct-props-correct)
15877 * STATUS: (seems) complete
15878 *
15879 * Returns 0 if the constraints are satisfied, a positive
15880 * error code if not and -1 if an internal error occured.
15881 */
15882static int
15883xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15884			     xmlSchemaTypePtr type)
15885{
15886    /*
15887    * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15888    *
15889    * SPEC (1) "The values of the properties of a complex type definition must
15890    * be as described in the property tableau in The Complex Type Definition
15891    * Schema Component ($3.4.1), modulo the impact of Missing
15892    * Sub-components ($5.3)."
15893    */
15894    if ((type->baseType != NULL) &&
15895	(WXS_IS_SIMPLE(type->baseType)) &&
15896	(WXS_IS_EXTENSION(type) == 0)) {
15897	/*
15898	* SPEC (2) "If the {base type definition} is a simple type definition,
15899	* the {derivation method} must be extension."
15900	*/
15901	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15902	    XML_SCHEMAP_SRC_CT_1,
15903	    NULL, WXS_BASIC_CAST type,
15904	    "If the base type is a simple type, the derivation method must be "
15905	    "'extension'", NULL, NULL);
15906	return (XML_SCHEMAP_SRC_CT_1);
15907    }
15908    /*
15909    * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15910    * definition`. That is, it must be possible to reach the `ur-type
15911    * definition` by repeatedly following the {base type definition}."
15912    *
15913    * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15914    */
15915    /*
15916    * NOTE that (4) and (5) need the following:
15917    *   - attribute uses need to be already inherited (apply attr. prohibitions)
15918    *   - attribute group references need to be expanded already
15919    *   - simple types need to be typefixed already
15920    */
15921    if (type->attrUses &&
15922	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15923    {
15924	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15925	xmlSchemaAttributeUsePtr use, tmp;
15926	int i, j, hasId = 0;
15927
15928	for (i = uses->nbItems -1; i >= 0; i--) {
15929	    use = uses->items[i];
15930
15931	    /*
15932	    * SPEC ct-props-correct
15933	    * (4) "Two distinct attribute declarations in the
15934	    * {attribute uses} must not have identical {name}s and
15935	    * {target namespace}s."
15936	    */
15937	    if (i > 0) {
15938		for (j = i -1; j >= 0; j--) {
15939		    tmp = uses->items[j];
15940		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15941			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15942			(WXS_ATTRUSE_DECL_TNS(use) ==
15943			WXS_ATTRUSE_DECL_TNS(tmp)))
15944		    {
15945			xmlChar *str = NULL;
15946
15947			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15948			    XML_SCHEMAP_AG_PROPS_CORRECT,
15949			    NULL, WXS_BASIC_CAST type,
15950			    "Duplicate %s",
15951			    xmlSchemaGetComponentDesignation(&str, use),
15952			    NULL);
15953			FREE_AND_NULL(str);
15954			/*
15955			* Remove the duplicate.
15956			*/
15957			if (xmlSchemaItemListRemove(uses, i) == -1)
15958			    goto exit_failure;
15959			goto next_use;
15960		    }
15961		}
15962	    }
15963	    /*
15964	    * SPEC ct-props-correct
15965	    * (5) "Two distinct attribute declarations in the
15966	    * {attribute uses} must not have {type definition}s which
15967	    * are or are derived from ID."
15968	    */
15969	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15970		if (xmlSchemaIsDerivedFromBuiltInType(
15971		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15972		{
15973		    if (hasId) {
15974			xmlChar *str = NULL;
15975
15976			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15977			    XML_SCHEMAP_AG_PROPS_CORRECT,
15978			    NULL, WXS_BASIC_CAST type,
15979			    "There must not exist more than one attribute "
15980			    "declaration of type 'xs:ID' "
15981			    "(or derived from 'xs:ID'). The %s violates this "
15982			    "constraint",
15983			    xmlSchemaGetComponentDesignation(&str, use),
15984			    NULL);
15985			FREE_AND_NULL(str);
15986			if (xmlSchemaItemListRemove(uses, i) == -1)
15987			    goto exit_failure;
15988		    }
15989
15990		    hasId = 1;
15991		}
15992	    }
15993next_use: {}
15994	}
15995    }
15996    return (0);
15997exit_failure:
15998    return(-1);
15999}
16000
16001static int
16002xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16003		       xmlSchemaTypePtr typeB)
16004{
16005    /*
16006    * TODO: This should implement component-identity
16007    * in the future.
16008    */
16009    if ((typeA == NULL) || (typeB == NULL))
16010	return (0);
16011    return (typeA == typeB);
16012}
16013
16014/**
16015 * xmlSchemaCheckCOSCTDerivedOK:
16016 * @ctxt:  the schema parser context
16017 * @type:  the to-be derived complex type definition
16018 * @baseType:  the base complex type definition
16019 * @set: the given set
16020 *
16021 * Schema Component Constraint:
16022 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16023 *
16024 * STATUS: completed
16025 *
16026 * Returns 0 if the constraints are satisfied, or 1
16027 * if not.
16028 */
16029static int
16030xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16031			     xmlSchemaTypePtr type,
16032			     xmlSchemaTypePtr baseType,
16033			     int set)
16034{
16035    int equal = xmlSchemaAreEqualTypes(type, baseType);
16036    /* TODO: Error codes. */
16037    /*
16038    * SPEC "For a complex type definition (call it D, for derived)
16039    * to be validly derived from a type definition (call this
16040    * B, for base) given a subset of {extension, restriction}
16041    * all of the following must be true:"
16042    */
16043    if (! equal) {
16044	/*
16045	* SPEC (1) "If B and D are not the same type definition, then the
16046	* {derivation method} of D must not be in the subset."
16047	*/
16048	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16049	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16050	    return (1);
16051    } else {
16052	/*
16053	* SPEC (2.1) "B and D must be the same type definition."
16054	*/
16055	return (0);
16056    }
16057    /*
16058    * SPEC (2.2) "B must be D's {base type definition}."
16059    */
16060    if (type->baseType == baseType)
16061	return (0);
16062    /*
16063    * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16064    * definition`."
16065    */
16066    if (WXS_IS_ANYTYPE(type->baseType))
16067	return (1);
16068
16069    if (WXS_IS_COMPLEX(type->baseType)) {
16070	/*
16071	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16072	* must be validly derived from B given the subset as defined by this
16073	* constraint."
16074	*/
16075	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16076	    baseType, set));
16077    } else {
16078	/*
16079	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16080	* must be validly derived from B given the subset as defined in Type
16081	* Derivation OK (Simple) ($3.14.6).
16082	*/
16083	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16084	    baseType, set));
16085    }
16086}
16087
16088/**
16089 * xmlSchemaCheckCOSDerivedOK:
16090 * @type:  the derived simple type definition
16091 * @baseType:  the base type definition
16092 *
16093 * Calls:
16094 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16095 *
16096 * Checks wheter @type can be validly derived from @baseType.
16097 *
16098 * Returns 0 on success, an positive error code otherwise.
16099 */
16100static int
16101xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16102			   xmlSchemaTypePtr type,
16103			   xmlSchemaTypePtr baseType,
16104			   int set)
16105{
16106    if (WXS_IS_SIMPLE(type))
16107	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16108    else
16109	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16110}
16111
16112/**
16113 * xmlSchemaCheckCOSCTExtends:
16114 * @ctxt:  the schema parser context
16115 * @type:  the complex type definition
16116 *
16117 * (3.4.6) Constraints on Complex Type Definition Schema Components
16118 * Schema Component Constraint:
16119 * Derivation Valid (Extension) (cos-ct-extends)
16120 *
16121 * STATUS:
16122 *   missing:
16123 *     (1.5)
16124 *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16125 *
16126 * Returns 0 if the constraints are satisfied, a positive
16127 * error code if not and -1 if an internal error occured.
16128 */
16129static int
16130xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16131			   xmlSchemaTypePtr type)
16132{
16133    xmlSchemaTypePtr base = type->baseType;
16134    /*
16135    * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16136    * temporarily only.
16137    */
16138    /*
16139    * SPEC (1) "If the {base type definition} is a complex type definition,
16140    * then all of the following must be true:"
16141    */
16142    if (WXS_IS_COMPLEX(base)) {
16143	/*
16144	* SPEC (1.1) "The {final} of the {base type definition} must not
16145	* contain extension."
16146	*/
16147	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16148	    xmlSchemaPCustomErr(ctxt,
16149		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16150		WXS_BASIC_CAST type, NULL,
16151		"The 'final' of the base type definition "
16152		"contains 'extension'", NULL);
16153	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16154	}
16155
16156	/*
16157	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16158	* since they are automatically satisfied through the
16159	* inheriting mechanism.
16160	* Note that even if redefining components, the inheriting mechanism
16161	* is used.
16162	*/
16163#if 0
16164	/*
16165	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16166	* uses}
16167	* of the complex type definition itself, that is, for every attribute
16168	* use in the {attribute uses} of the {base type definition}, there
16169	* must be an attribute use in the {attribute uses} of the complex
16170	* type definition itself whose {attribute declaration} has the same
16171	* {name}, {target namespace} and {type definition} as its attribute
16172	* declaration"
16173	*/
16174	if (base->attrUses != NULL) {
16175	    int i, j, found;
16176	    xmlSchemaAttributeUsePtr use, buse;
16177
16178	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16179		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16180		found = 0;
16181		if (type->attrUses != NULL) {
16182		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16183		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16184		    {
16185			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16186				WXS_ATTRUSE_DECL_NAME(buse)) &&
16187			    (WXS_ATTRUSE_DECL_TNS(use) ==
16188				WXS_ATTRUSE_DECL_TNS(buse)) &&
16189			    (WXS_ATTRUSE_TYPEDEF(use) ==
16190				WXS_ATTRUSE_TYPEDEF(buse))
16191			{
16192			    found = 1;
16193			    break;
16194			}
16195		    }
16196		}
16197		if (! found) {
16198		    xmlChar *str = NULL;
16199
16200		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16201			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16202			NULL, WXS_BASIC_CAST type,
16203			/*
16204			* TODO: The report does not indicate that also the
16205			* type needs to be the same.
16206			*/
16207			"This type is missing a matching correspondent "
16208			"for its {base type}'s %s in its {attribute uses}",
16209			xmlSchemaGetComponentDesignation(&str,
16210			    buse->children),
16211			NULL);
16212		    FREE_AND_NULL(str)
16213		}
16214	    }
16215	}
16216	/*
16217	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16218	* definition must also have one, and the base type definition's
16219	* {attribute  wildcard}'s {namespace constraint} must be a subset
16220	* of the complex  type definition's {attribute wildcard}'s {namespace
16221	* constraint}, as defined by Wildcard Subset ($3.10.6)."
16222	*/
16223
16224	/*
16225	* MAYBE TODO: Enable if ever needed. But this will be needed only
16226	* if created the type via a schema construction API.
16227	*/
16228	if (base->attributeWildcard != NULL) {
16229	    if (type->attributeWilcard == NULL) {
16230		xmlChar *str = NULL;
16231
16232		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16233		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16234		    NULL, type,
16235		    "The base %s has an attribute wildcard, "
16236		    "but this type is missing an attribute wildcard",
16237		    xmlSchemaGetComponentDesignation(&str, base));
16238		FREE_AND_NULL(str)
16239
16240	    } else if (xmlSchemaCheckCOSNSSubset(
16241		base->attributeWildcard, type->attributeWildcard))
16242	    {
16243		xmlChar *str = NULL;
16244
16245		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16246		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16247		    NULL, type,
16248		    "The attribute wildcard is not a valid "
16249		    "superset of the one in the base %s",
16250		    xmlSchemaGetComponentDesignation(&str, base));
16251		FREE_AND_NULL(str)
16252	    }
16253	}
16254#endif
16255	/*
16256	* SPEC (1.4) "One of the following must be true:"
16257	*/
16258	if ((type->contentTypeDef != NULL) &&
16259	    (type->contentTypeDef == base->contentTypeDef)) {
16260	    /*
16261	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16262	    * and the {content type} of the complex type definition itself
16263	    * must be the same simple type definition"
16264	    * PASS
16265	    */
16266	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16267	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16268	    /*
16269	    * SPEC (1.4.2) "The {content type} of both the {base type
16270	    * definition} and the complex type definition itself must
16271	    * be empty."
16272	    * PASS
16273	    */
16274	} else {
16275	    /*
16276	    * SPEC (1.4.3) "All of the following must be true:"
16277	    */
16278	    if (type->subtypes == NULL) {
16279		/*
16280		* SPEC 1.4.3.1 The {content type} of the complex type
16281		* definition itself must specify a particle.
16282		*/
16283		xmlSchemaPCustomErr(ctxt,
16284		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16285		    WXS_BASIC_CAST type, NULL,
16286		    "The content type must specify a particle", NULL);
16287		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16288	    }
16289	    /*
16290	    * SPEC (1.4.3.2) "One of the following must be true:"
16291	    */
16292	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16293		/*
16294		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16295		* definition} must be empty.
16296		* PASS
16297		*/
16298	    } else {
16299		/*
16300		* SPEC (1.4.3.2.2) "All of the following must be true:"
16301		*/
16302		if ((type->contentType != base->contentType) ||
16303		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16304		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16305		    /*
16306		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16307		    * or both must be element-only."
16308		    */
16309		    xmlSchemaPCustomErr(ctxt,
16310			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16311			WXS_BASIC_CAST type, NULL,
16312			"The content type of both, the type and its base "
16313			"type, must either 'mixed' or 'element-only'", NULL);
16314		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16315		}
16316		/*
16317		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16318		* complex type definition must be a `valid extension`
16319		* of the {base type definition}'s particle, as defined
16320		* in Particle Valid (Extension) ($3.9.6)."
16321		*
16322		* NOTE that we won't check "Particle Valid (Extension)",
16323		* since it is ensured by the derivation process in
16324		* xmlSchemaTypeFixup(). We need to implement this when heading
16325		* for a construction API
16326		* TODO: !! This is needed to be checked if redefining a type !!
16327		*/
16328	    }
16329	    /*
16330	    * URGENT TODO (1.5)
16331	    */
16332	}
16333    } else {
16334	/*
16335	* SPEC (2) "If the {base type definition} is a simple type definition,
16336	* then all of the following must be true:"
16337	*/
16338	if (type->contentTypeDef != base) {
16339	    /*
16340	    * SPEC (2.1) "The {content type} must be the same simple type
16341	    * definition."
16342	    */
16343	    xmlSchemaPCustomErr(ctxt,
16344		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16345		WXS_BASIC_CAST type, NULL,
16346		"The content type must be the simple base type", NULL);
16347	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16348	}
16349	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16350	    /*
16351	    * SPEC (2.2) "The {final} of the {base type definition} must not
16352	    * contain extension"
16353	    * NOTE that this is the same as (1.1).
16354	    */
16355	    xmlSchemaPCustomErr(ctxt,
16356		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16357		WXS_BASIC_CAST type, NULL,
16358		"The 'final' of the base type definition "
16359		"contains 'extension'", NULL);
16360	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16361	}
16362    }
16363    return (0);
16364}
16365
16366/**
16367 * xmlSchemaCheckDerivationOKRestriction:
16368 * @ctxt:  the schema parser context
16369 * @type:  the complex type definition
16370 *
16371 * (3.4.6) Constraints on Complex Type Definition Schema Components
16372 * Schema Component Constraint:
16373 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16374 *
16375 * STATUS:
16376 *   missing:
16377 *     (5.4.2) ???
16378 *
16379 * ATTENTION:
16380 * In XML Schema 1.1 this will be:
16381 * Validation Rule: Checking complex type subsumption
16382 *
16383 * Returns 0 if the constraints are satisfied, a positive
16384 * error code if not and -1 if an internal error occured.
16385 */
16386static int
16387xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16388				      xmlSchemaTypePtr type)
16389{
16390    xmlSchemaTypePtr base;
16391
16392    /*
16393    * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16394    * temporarily only.
16395    */
16396    base = type->baseType;
16397    if (! WXS_IS_COMPLEX(base)) {
16398	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16399	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16400	    type->node, WXS_BASIC_CAST type,
16401	    "The base type must be a complex type", NULL, NULL);
16402	return(ctxt->err);
16403    }
16404    if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16405	/*
16406	* SPEC (1) "The {base type definition} must be a complex type
16407	* definition whose {final} does not contain restriction."
16408	*/
16409	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16410	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16411	    type->node, WXS_BASIC_CAST type,
16412	    "The 'final' of the base type definition "
16413	    "contains 'restriction'", NULL, NULL);
16414	return (ctxt->err);
16415    }
16416    /*
16417    * SPEC (2), (3) and (4)
16418    * Those are handled in a separate function, since the
16419    * same constraints are needed for redefinition of
16420    * attribute groups as well.
16421    */
16422    if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16423	XML_SCHEMA_ACTION_DERIVE,
16424	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16425	type->attrUses, base->attrUses,
16426	type->attributeWildcard,
16427	base->attributeWildcard) == -1)
16428    {
16429	return(-1);
16430    }
16431    /*
16432    * SPEC (5) "One of the following must be true:"
16433    */
16434    if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16435	/*
16436	* SPEC (5.1) "The {base type definition} must be the
16437	* `ur-type definition`."
16438	* PASS
16439	*/
16440    } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16441	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16442	/*
16443	* SPEC (5.2.1) "The {content type} of the complex type definition
16444	* must be a simple type definition"
16445	*
16446	* SPEC (5.2.2) "One of the following must be true:"
16447	*/
16448	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16449	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16450	{
16451	    int err;
16452	    /*
16453	    * SPEC (5.2.2.1) "The {content type} of the {base type
16454	    * definition} must be a simple type definition from which
16455	    * the {content type} is validly derived given the empty
16456	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16457	    *
16458	    * ATTENTION TODO: This seems not needed if the type implicitely
16459	    * derived from the base type.
16460	    *
16461	    */
16462	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16463		type->contentTypeDef, base->contentTypeDef, 0);
16464	    if (err != 0) {
16465		xmlChar *strA = NULL, *strB = NULL;
16466
16467		if (err == -1)
16468		    return(-1);
16469		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16470		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16471		    NULL, WXS_BASIC_CAST type,
16472		    "The {content type} %s is not validly derived from the "
16473		    "base type's {content type} %s",
16474		    xmlSchemaGetComponentDesignation(&strA,
16475			type->contentTypeDef),
16476		    xmlSchemaGetComponentDesignation(&strB,
16477			base->contentTypeDef));
16478		FREE_AND_NULL(strA);
16479		FREE_AND_NULL(strB);
16480		return(ctxt->err);
16481	    }
16482	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16483	    (xmlSchemaIsParticleEmptiable(
16484		(xmlSchemaParticlePtr) base->subtypes))) {
16485	    /*
16486	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16487	    * and have a particle which is `emptiable` as defined in
16488	    * Particle Emptiable ($3.9.6)."
16489	    * PASS
16490	    */
16491	} else {
16492	    xmlSchemaPCustomErr(ctxt,
16493		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16494		WXS_BASIC_CAST type, NULL,
16495		"The content type of the base type must be either "
16496		"a simple type or 'mixed' and an emptiable particle", NULL);
16497	    return (ctxt->err);
16498	}
16499    } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16500	/*
16501	* SPEC (5.3.1) "The {content type} of the complex type itself must
16502	* be empty"
16503	*/
16504	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16505	    /*
16506	    * SPEC (5.3.2.1) "The {content type} of the {base type
16507	    * definition} must also be empty."
16508	    * PASS
16509	    */
16510	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16511	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16512	    xmlSchemaIsParticleEmptiable(
16513		(xmlSchemaParticlePtr) base->subtypes)) {
16514	    /*
16515	    * SPEC (5.3.2.2) "The {content type} of the {base type
16516	    * definition} must be elementOnly or mixed and have a particle
16517	    * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16518	    * PASS
16519	    */
16520	} else {
16521	    xmlSchemaPCustomErr(ctxt,
16522		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16523		WXS_BASIC_CAST type, NULL,
16524		"The content type of the base type must be either "
16525		"empty or 'mixed' (or 'elements-only') and an emptiable "
16526		"particle", NULL);
16527	    return (ctxt->err);
16528	}
16529    } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16530	WXS_HAS_MIXED_CONTENT(type)) {
16531	/*
16532	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16533	* itself must be element-only"
16534	*/
16535	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16536	    /*
16537	    * SPEC (5.4.1.2) "The {content type} of the complex type
16538	    * definition itself and of the {base type definition} must be
16539	    * mixed"
16540	    */
16541	    xmlSchemaPCustomErr(ctxt,
16542		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16543		WXS_BASIC_CAST type, NULL,
16544		"If the content type is 'mixed', then the content type of the "
16545		"base type must also be 'mixed'", NULL);
16546	    return (ctxt->err);
16547	}
16548	/*
16549	* SPEC (5.4.2) "The particle of the complex type definition itself
16550	* must be a `valid restriction` of the particle of the {content
16551	* type} of the {base type definition} as defined in Particle Valid
16552	* (Restriction) ($3.9.6).
16553	*
16554	* URGENT TODO: (5.4.2)
16555	*/
16556    } else {
16557	xmlSchemaPCustomErr(ctxt,
16558	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16559	    WXS_BASIC_CAST type, NULL,
16560	    "The type is not a valid restriction of its base type", NULL);
16561	return (ctxt->err);
16562    }
16563    return (0);
16564}
16565
16566/**
16567 * xmlSchemaCheckCTComponent:
16568 * @ctxt:  the schema parser context
16569 * @type:  the complex type definition
16570 *
16571 * (3.4.6) Constraints on Complex Type Definition Schema Components
16572 *
16573 * Returns 0 if the constraints are satisfied, a positive
16574 * error code if not and -1 if an internal error occured.
16575 */
16576static int
16577xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16578			  xmlSchemaTypePtr type)
16579{
16580    int ret;
16581    /*
16582    * Complex Type Definition Properties Correct
16583    */
16584    ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16585    if (ret != 0)
16586	return (ret);
16587    if (WXS_IS_EXTENSION(type))
16588	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16589    else
16590	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16591    return (ret);
16592}
16593
16594/**
16595 * xmlSchemaCheckSRCCT:
16596 * @ctxt:  the schema parser context
16597 * @type:  the complex type definition
16598 *
16599 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16600 * Schema Representation Constraint:
16601 * Complex Type Definition Representation OK (src-ct)
16602 *
16603 * Returns 0 if the constraints are satisfied, a positive
16604 * error code if not and -1 if an internal error occured.
16605 */
16606static int
16607xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16608		    xmlSchemaTypePtr type)
16609{
16610    xmlSchemaTypePtr base;
16611    int ret = 0;
16612
16613    /*
16614    * TODO: Adjust the error codes here, as I used
16615    * XML_SCHEMAP_SRC_CT_1 only yet.
16616    */
16617    base = type->baseType;
16618    if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16619	/*
16620	* 1 If the <complexContent> alternative is chosen, the type definition
16621	* `resolved` to by the `actual value` of the base [attribute]
16622	* must be a complex type definition;
16623	*/
16624	if (! WXS_IS_COMPLEX(base)) {
16625	    xmlChar *str = NULL;
16626	    xmlSchemaPCustomErr(ctxt,
16627		XML_SCHEMAP_SRC_CT_1,
16628		WXS_BASIC_CAST type, type->node,
16629		"If using <complexContent>, the base type is expected to be "
16630		"a complex type. The base type '%s' is a simple type",
16631		xmlSchemaFormatQName(&str, base->targetNamespace,
16632		base->name));
16633	    FREE_AND_NULL(str)
16634	    return (XML_SCHEMAP_SRC_CT_1);
16635	}
16636    } else {
16637	/*
16638	* SPEC
16639	* 2 If the <simpleContent> alternative is chosen, all of the
16640	* following must be true:
16641	* 2.1 The type definition `resolved` to by the `actual value` of the
16642	* base [attribute] must be one of the following:
16643	*/
16644	if (WXS_IS_SIMPLE(base)) {
16645	    if (WXS_IS_EXTENSION(type) == 0) {
16646		xmlChar *str = NULL;
16647		/*
16648		* 2.1.3 only if the <extension> alternative is also
16649		* chosen, a simple type definition.
16650		*/
16651		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16652		xmlSchemaPCustomErr(ctxt,
16653		    XML_SCHEMAP_SRC_CT_1,
16654		    WXS_BASIC_CAST type, NULL,
16655		    "If using <simpleContent> and <restriction>, the base "
16656		    "type must be a complex type. The base type '%s' is "
16657		    "a simple type",
16658		    xmlSchemaFormatQName(&str, base->targetNamespace,
16659			base->name));
16660		FREE_AND_NULL(str)
16661		return (XML_SCHEMAP_SRC_CT_1);
16662	    }
16663	} else {
16664	    /* Base type is a complex type. */
16665	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16666		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16667		/*
16668		* 2.1.1 a complex type definition whose {content type} is a
16669		* simple type definition;
16670		* PASS
16671		*/
16672		if (base->contentTypeDef == NULL) {
16673		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16674			WXS_BASIC_CAST type, NULL,
16675			"Internal error: xmlSchemaCheckSRCCT, "
16676			"'%s', base type has no content type",
16677			type->name);
16678		    return (-1);
16679		}
16680	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16681		(WXS_IS_RESTRICTION(type))) {
16682
16683		/*
16684		* 2.1.2 only if the <restriction> alternative is also
16685		* chosen, a complex type definition whose {content type}
16686		* is mixed and a particle emptiable.
16687		*/
16688		if (! xmlSchemaIsParticleEmptiable(
16689		    (xmlSchemaParticlePtr) base->subtypes)) {
16690		    ret = XML_SCHEMAP_SRC_CT_1;
16691		} else
16692		    /*
16693		    * Attention: at this point the <simpleType> child is in
16694		    * ->contentTypeDef (put there during parsing).
16695		    */
16696		    if (type->contentTypeDef == NULL) {
16697		    xmlChar *str = NULL;
16698		    /*
16699		    * 2.2 If clause 2.1.2 above is satisfied, then there
16700		    * must be a <simpleType> among the [children] of
16701		    * <restriction>.
16702		    */
16703		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16704		    xmlSchemaPCustomErr(ctxt,
16705			XML_SCHEMAP_SRC_CT_1,
16706			WXS_BASIC_CAST type, NULL,
16707			"A <simpleType> is expected among the children "
16708			"of <restriction>, if <simpleContent> is used and "
16709			"the base type '%s' is a complex type",
16710			xmlSchemaFormatQName(&str, base->targetNamespace,
16711			base->name));
16712		    FREE_AND_NULL(str)
16713		    return (XML_SCHEMAP_SRC_CT_1);
16714		}
16715	    } else {
16716		ret = XML_SCHEMAP_SRC_CT_1;
16717	    }
16718	}
16719	if (ret > 0) {
16720	    xmlChar *str = NULL;
16721	    if (WXS_IS_RESTRICTION(type)) {
16722		xmlSchemaPCustomErr(ctxt,
16723		    XML_SCHEMAP_SRC_CT_1,
16724		    WXS_BASIC_CAST type, NULL,
16725		    "If <simpleContent> and <restriction> is used, the "
16726		    "base type must be a simple type or a complex type with "
16727		    "mixed content and particle emptiable. The base type "
16728		    "'%s' is none of those",
16729		    xmlSchemaFormatQName(&str, base->targetNamespace,
16730		    base->name));
16731	    } else {
16732		xmlSchemaPCustomErr(ctxt,
16733		    XML_SCHEMAP_SRC_CT_1,
16734		    WXS_BASIC_CAST type, NULL,
16735		    "If <simpleContent> and <extension> is used, the "
16736		    "base type must be a simple type. The base type '%s' "
16737		    "is a complex type",
16738		    xmlSchemaFormatQName(&str, base->targetNamespace,
16739		    base->name));
16740	    }
16741	    FREE_AND_NULL(str)
16742	}
16743    }
16744    /*
16745    * SPEC (3) "The corresponding complex type definition component must
16746    * satisfy the conditions set out in Constraints on Complex Type
16747    * Definition Schema Components ($3.4.6);"
16748    * NOTE (3) will be done in xmlSchemaTypeFixup().
16749    */
16750    /*
16751    * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16752    * above for {attribute wildcard} is satisfied, the intensional
16753    * intersection must be expressible, as defined in Attribute Wildcard
16754    * Intersection ($3.10.6).
16755    * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16756    */
16757    return (ret);
16758}
16759
16760#ifdef ENABLE_PARTICLE_RESTRICTION
16761/**
16762 * xmlSchemaCheckParticleRangeOK:
16763 * @ctxt:  the schema parser context
16764 * @type:  the complex type definition
16765 *
16766 * (3.9.6) Constraints on Particle Schema Components
16767 * Schema Component Constraint:
16768 * Occurrence Range OK (range-ok)
16769 *
16770 * STATUS: complete
16771 *
16772 * Returns 0 if the constraints are satisfied, a positive
16773 * error code if not and -1 if an internal error occured.
16774 */
16775static int
16776xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16777			      int bmin, int bmax)
16778{
16779    if (rmin < bmin)
16780	return (1);
16781    if ((bmax != UNBOUNDED) &&
16782	(rmax > bmax))
16783	return (1);
16784    return (0);
16785}
16786
16787/**
16788 * xmlSchemaCheckRCaseNameAndTypeOK:
16789 * @ctxt:  the schema parser context
16790 * @r: the restricting element declaration particle
16791 * @b: the base element declaration particle
16792 *
16793 * (3.9.6) Constraints on Particle Schema Components
16794 * Schema Component Constraint:
16795 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16796 * (rcase-NameAndTypeOK)
16797 *
16798 * STATUS:
16799 *   MISSING (3.2.3)
16800 *   CLARIFY: (3.2.2)
16801 *
16802 * Returns 0 if the constraints are satisfied, a positive
16803 * error code if not and -1 if an internal error occured.
16804 */
16805static int
16806xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16807				 xmlSchemaParticlePtr r,
16808				 xmlSchemaParticlePtr b)
16809{
16810    xmlSchemaElementPtr elemR, elemB;
16811
16812    /* TODO: Error codes (rcase-NameAndTypeOK). */
16813    elemR = (xmlSchemaElementPtr) r->children;
16814    elemB = (xmlSchemaElementPtr) b->children;
16815    /*
16816    * SPEC (1) "The declarations' {name}s and {target namespace}s are
16817    * the same."
16818    */
16819    if ((elemR != elemB) &&
16820	((! xmlStrEqual(elemR->name, elemB->name)) ||
16821	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16822	return (1);
16823    /*
16824    * SPEC (2) "R's occurrence range is a valid restriction of B's
16825    * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16826    */
16827    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16828	    b->minOccurs, b->maxOccurs) != 0)
16829	return (1);
16830    /*
16831    * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16832    * {scope} are global."
16833    */
16834    if (elemR == elemB)
16835	return (0);
16836    /*
16837    * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16838    */
16839    if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16840	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16841	 return (1);
16842    /*
16843    * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16844    * or is not fixed, or R's declaration's {value constraint} is fixed
16845    * with the same value."
16846    */
16847    if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16848	((elemR->value == NULL) ||
16849	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16850	 /* TODO: Equality of the initial value or normalized or canonical? */
16851	 (! xmlStrEqual(elemR->value, elemB->value))))
16852	 return (1);
16853    /*
16854    * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16855    * definitions} is a subset of B's declaration's {identity-constraint
16856    * definitions}, if any."
16857    */
16858    if (elemB->idcs != NULL) {
16859	/* TODO */
16860    }
16861    /*
16862    * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16863    * superset of B's declaration's {disallowed substitutions}."
16864    */
16865    if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16866	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16867	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16868	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16869	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16870	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16871	 return (1);
16872    /*
16873    * SPEC (3.2.5) "R's {type definition} is validly derived given
16874    * {extension, list, union} from B's {type definition}"
16875    *
16876    * BADSPEC TODO: What's the point of adding "list" and "union" to the
16877    * set, if the corresponding constraints handle "restriction" and
16878    * "extension" only?
16879    *
16880    */
16881    {
16882	int set = 0;
16883
16884	set |= SUBSET_EXTENSION;
16885	set |= SUBSET_LIST;
16886	set |= SUBSET_UNION;
16887	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16888	    elemB->subtypes, set) != 0)
16889	    return (1);
16890    }
16891    return (0);
16892}
16893
16894/**
16895 * xmlSchemaCheckRCaseNSCompat:
16896 * @ctxt:  the schema parser context
16897 * @r: the restricting element declaration particle
16898 * @b: the base wildcard particle
16899 *
16900 * (3.9.6) Constraints on Particle Schema Components
16901 * Schema Component Constraint:
16902 * Particle Derivation OK (Elt:Any -- NSCompat)
16903 * (rcase-NSCompat)
16904 *
16905 * STATUS: complete
16906 *
16907 * Returns 0 if the constraints are satisfied, a positive
16908 * error code if not and -1 if an internal error occured.
16909 */
16910static int
16911xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16912			    xmlSchemaParticlePtr r,
16913			    xmlSchemaParticlePtr b)
16914{
16915    /* TODO:Error codes (rcase-NSCompat). */
16916    /*
16917    * SPEC "For an element declaration particle to be a `valid restriction`
16918    * of a wildcard particle all of the following must be true:"
16919    *
16920    * SPEC (1) "The element declaration's {target namespace} is `valid`
16921    * with respect to the wildcard's {namespace constraint} as defined by
16922    * Wildcard allows Namespace Name ($3.10.4)."
16923    */
16924    if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16925	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16926	return (1);
16927    /*
16928    * SPEC (2) "R's occurrence range is a valid restriction of B's
16929    * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16930    */
16931    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16932	    b->minOccurs, b->maxOccurs) != 0)
16933	return (1);
16934
16935    return (0);
16936}
16937
16938/**
16939 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16940 * @ctxt:  the schema parser context
16941 * @r: the restricting element declaration particle
16942 * @b: the base model group particle
16943 *
16944 * (3.9.6) Constraints on Particle Schema Components
16945 * Schema Component Constraint:
16946 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16947 * (rcase-RecurseAsIfGroup)
16948 *
16949 * STATUS: TODO
16950 *
16951 * Returns 0 if the constraints are satisfied, a positive
16952 * error code if not and -1 if an internal error occured.
16953 */
16954static int
16955xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16956				    xmlSchemaParticlePtr r,
16957				    xmlSchemaParticlePtr b)
16958{
16959    /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16960    TODO
16961    return (0);
16962}
16963
16964/**
16965 * xmlSchemaCheckRCaseNSSubset:
16966 * @ctxt:  the schema parser context
16967 * @r: the restricting wildcard particle
16968 * @b: the base wildcard particle
16969 *
16970 * (3.9.6) Constraints on Particle Schema Components
16971 * Schema Component Constraint:
16972 * Particle Derivation OK (Any:Any -- NSSubset)
16973 * (rcase-NSSubset)
16974 *
16975 * STATUS: complete
16976 *
16977 * Returns 0 if the constraints are satisfied, a positive
16978 * error code if not and -1 if an internal error occured.
16979 */
16980static int
16981xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16982				    xmlSchemaParticlePtr r,
16983				    xmlSchemaParticlePtr b,
16984				    int isAnyTypeBase)
16985{
16986    /* TODO: Error codes (rcase-NSSubset). */
16987    /*
16988    * SPEC (1) "R's occurrence range is a valid restriction of B's
16989    * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16990    */
16991    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16992	    b->minOccurs, b->maxOccurs))
16993	return (1);
16994    /*
16995    * SPEC (2) "R's {namespace constraint} must be an intensional subset
16996    * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
16997    */
16998    if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16999	(xmlSchemaWildcardPtr) b->children))
17000	return (1);
17001    /*
17002    * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17003    * definition`, R's {process contents} must be identical to or stronger
17004    * than B's {process contents}, where strict is stronger than lax is
17005    * stronger than skip."
17006    */
17007    if (! isAnyTypeBase) {
17008	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17009	    ((xmlSchemaWildcardPtr) b->children)->processContents)
17010	    return (1);
17011    }
17012
17013    return (0);
17014}
17015
17016/**
17017 * xmlSchemaCheckCOSParticleRestrict:
17018 * @ctxt:  the schema parser context
17019 * @type:  the complex type definition
17020 *
17021 * (3.9.6) Constraints on Particle Schema Components
17022 * Schema Component Constraint:
17023 * Particle Valid (Restriction) (cos-particle-restrict)
17024 *
17025 * STATUS: TODO
17026 *
17027 * Returns 0 if the constraints are satisfied, a positive
17028 * error code if not and -1 if an internal error occured.
17029 */
17030static int
17031xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17032				  xmlSchemaParticlePtr r,
17033				  xmlSchemaParticlePtr b)
17034{
17035    int ret = 0;
17036
17037    /*part = WXS_TYPE_PARTICLE(type);
17038    basePart = WXS_TYPE_PARTICLE(base);
17039    */
17040
17041    TODO
17042
17043    /*
17044    * SPEC (1) "They are the same particle."
17045    */
17046    if (r == b)
17047	return (0);
17048
17049
17050    return (0);
17051}
17052
17053#if 0
17054/**
17055 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17056 * @ctxt:  the schema parser context
17057 * @r: the model group particle
17058 * @b: the base wildcard particle
17059 *
17060 * (3.9.6) Constraints on Particle Schema Components
17061 * Schema Component Constraint:
17062 * Particle Derivation OK (All/Choice/Sequence:Any --
17063 *                         NSRecurseCheckCardinality)
17064 * (rcase-NSRecurseCheckCardinality)
17065 *
17066 * STATUS: TODO: subst-groups
17067 *
17068 * Returns 0 if the constraints are satisfied, a positive
17069 * error code if not and -1 if an internal error occured.
17070 */
17071static int
17072xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17073					     xmlSchemaParticlePtr r,
17074					     xmlSchemaParticlePtr b)
17075{
17076    xmlSchemaParticlePtr part;
17077    /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17078    if ((r->children == NULL) || (r->children->children == NULL))
17079	return (-1);
17080    /*
17081    * SPEC "For a group particle to be a `valid restriction` of a
17082    * wildcard particle..."
17083    *
17084    * SPEC (1) "Every member of the {particles} of the group is a `valid
17085    * restriction` of the wildcard as defined by
17086    * Particle Valid (Restriction) ($3.9.6)."
17087    */
17088    part = (xmlSchemaParticlePtr) r->children->children;
17089    do {
17090	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17091	    return (1);
17092	part = (xmlSchemaParticlePtr) part->next;
17093    } while (part != NULL);
17094    /*
17095    * SPEC (2) "The effective total range of the group [...] is a
17096    * valid restriction of B's occurrence range as defined by
17097    * Occurrence Range OK ($3.9.6)."
17098    */
17099    if (xmlSchemaCheckParticleRangeOK(
17100	    xmlSchemaGetParticleTotalRangeMin(r),
17101	    xmlSchemaGetParticleTotalRangeMax(r),
17102	    b->minOccurs, b->maxOccurs) != 0)
17103	return (1);
17104    return (0);
17105}
17106#endif
17107
17108/**
17109 * xmlSchemaCheckRCaseRecurse:
17110 * @ctxt:  the schema parser context
17111 * @r: the <all> or <sequence> model group particle
17112 * @b: the base <all> or <sequence> model group particle
17113 *
17114 * (3.9.6) Constraints on Particle Schema Components
17115 * Schema Component Constraint:
17116 * Particle Derivation OK (All:All,Sequence:Sequence --
17117                           Recurse)
17118 * (rcase-Recurse)
17119 *
17120 * STATUS:  ?
17121 * TODO: subst-groups
17122 *
17123 * Returns 0 if the constraints are satisfied, a positive
17124 * error code if not and -1 if an internal error occured.
17125 */
17126static int
17127xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17128			   xmlSchemaParticlePtr r,
17129			   xmlSchemaParticlePtr b)
17130{
17131    /* xmlSchemaParticlePtr part; */
17132    /* TODO: Error codes (rcase-Recurse). */
17133    if ((r->children == NULL) || (b->children == NULL) ||
17134	(r->children->type != b->children->type))
17135	return (-1);
17136    /*
17137    * SPEC "For an all or sequence group particle to be a `valid
17138    * restriction` of another group particle with the same {compositor}..."
17139    *
17140    * SPEC (1) "R's occurrence range is a valid restriction of B's
17141    * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17142    */
17143    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17144	    b->minOccurs, b->maxOccurs))
17145	return (1);
17146
17147
17148    return (0);
17149}
17150
17151#endif
17152
17153#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17154    xmlSchemaPCustomErrExt(pctxt,      \
17155	XML_SCHEMAP_INVALID_FACET_VALUE, \
17156	WXS_BASIC_CAST fac1, fac1->node, \
17157	"It is an error for both '%s' and '%s' to be specified on the "\
17158	"same type definition", \
17159	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17160	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17161
17162#define FACET_RESTR_ERR(fac1, msg) \
17163    xmlSchemaPCustomErr(pctxt,      \
17164	XML_SCHEMAP_INVALID_FACET_VALUE, \
17165	WXS_BASIC_CAST fac1, fac1->node, \
17166	msg, NULL);
17167
17168#define FACET_RESTR_FIXED_ERR(fac) \
17169    xmlSchemaPCustomErr(pctxt, \
17170	XML_SCHEMAP_INVALID_FACET_VALUE, \
17171	WXS_BASIC_CAST fac, fac->node, \
17172	"The base type's facet is 'fixed', thus the value must not " \
17173	"differ", NULL);
17174
17175static void
17176xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17177			xmlSchemaFacetPtr facet1,
17178			xmlSchemaFacetPtr facet2,
17179			int lessGreater,
17180			int orEqual,
17181			int ofBase)
17182{
17183    xmlChar *msg = NULL;
17184
17185    msg = xmlStrdup(BAD_CAST "'");
17186    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17187    msg = xmlStrcat(msg, BAD_CAST "' has to be");
17188    if (lessGreater == 0)
17189	msg = xmlStrcat(msg, BAD_CAST " equal to");
17190    if (lessGreater == 1)
17191	msg = xmlStrcat(msg, BAD_CAST " greater than");
17192    else
17193	msg = xmlStrcat(msg, BAD_CAST " less than");
17194
17195    if (orEqual)
17196	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17197    msg = xmlStrcat(msg, BAD_CAST " '");
17198    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17199    if (ofBase)
17200	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17201    else
17202	msg = xmlStrcat(msg, BAD_CAST "'");
17203
17204    xmlSchemaPCustomErr(pctxt,
17205	XML_SCHEMAP_INVALID_FACET_VALUE,
17206	WXS_BASIC_CAST facet1, NULL,
17207	(const char *) msg, NULL);
17208
17209    if (msg != NULL)
17210	xmlFree(msg);
17211}
17212
17213/*
17214* xmlSchemaDeriveAndValidateFacets:
17215*
17216* Schema Component Constraint: Simple Type Restriction (Facets)
17217* (st-restrict-facets)
17218*/
17219static int
17220xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17221				 xmlSchemaTypePtr type)
17222{
17223    xmlSchemaTypePtr base = type->baseType;
17224    xmlSchemaFacetLinkPtr link, cur, last = NULL;
17225    xmlSchemaFacetPtr facet, bfacet,
17226	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17227	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17228	fmininc = NULL, fmaxinc = NULL,
17229	fminexc = NULL, fmaxexc = NULL,
17230	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17231	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17232	bfmininc = NULL, bfmaxinc = NULL,
17233	bfminexc = NULL, bfmaxexc = NULL;
17234    int res; /* err = 0, fixedErr; */
17235
17236    /*
17237    * SPEC st-restrict-facets 1:
17238    * "The {variety} of R is the same as that of B."
17239    */
17240    /*
17241    * SPEC st-restrict-facets 2:
17242    * "If {variety} is atomic, the {primitive type definition}
17243    * of R is the same as that of B."
17244    *
17245    * NOTE: we leave 1 & 2 out for now, since this will be
17246    * satisfied by the derivation process.
17247    * CONSTRUCTION TODO: Maybe needed if using a construction API.
17248    */
17249    /*
17250    * SPEC st-restrict-facets 3:
17251    * "The {facets} of R are the union of S and the {facets}
17252    * of B, eliminating duplicates. To eliminate duplicates,
17253    * when a facet of the same kind occurs in both S and the
17254    * {facets} of B, the one in the {facets} of B is not
17255    * included, with the exception of enumeration and pattern
17256    * facets, for which multiple occurrences with distinct values
17257    * are allowed."
17258    */
17259
17260    if ((type->facetSet == NULL) && (base->facetSet == NULL))
17261	return (0);
17262
17263    last = type->facetSet;
17264    if (last != NULL)
17265	while (last->next != NULL)
17266	    last = last->next;
17267
17268    for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17269	facet = cur->facet;
17270	switch (facet->type) {
17271	    case XML_SCHEMA_FACET_LENGTH:
17272		flength = facet; break;
17273	    case XML_SCHEMA_FACET_MINLENGTH:
17274		fminlen = facet; break;
17275	    case XML_SCHEMA_FACET_MININCLUSIVE:
17276		fmininc = facet; break;
17277	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17278		fminexc = facet; break;
17279	    case XML_SCHEMA_FACET_MAXLENGTH:
17280		fmaxlen = facet; break;
17281	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17282		fmaxinc = facet; break;
17283	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17284		fmaxexc = facet; break;
17285	    case XML_SCHEMA_FACET_TOTALDIGITS:
17286		ftotdig = facet; break;
17287	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17288		ffracdig = facet; break;
17289	    default:
17290		break;
17291	}
17292    }
17293    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17294	facet = cur->facet;
17295	switch (facet->type) {
17296	    case XML_SCHEMA_FACET_LENGTH:
17297		bflength = facet; break;
17298	    case XML_SCHEMA_FACET_MINLENGTH:
17299		bfminlen = facet; break;
17300	    case XML_SCHEMA_FACET_MININCLUSIVE:
17301		bfmininc = facet; break;
17302	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17303		bfminexc = facet; break;
17304	    case XML_SCHEMA_FACET_MAXLENGTH:
17305		bfmaxlen = facet; break;
17306	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17307		bfmaxinc = facet; break;
17308	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17309		bfmaxexc = facet; break;
17310	    case XML_SCHEMA_FACET_TOTALDIGITS:
17311		bftotdig = facet; break;
17312	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17313		bffracdig = facet; break;
17314	    default:
17315		break;
17316	}
17317    }
17318    /*
17319    * length and minLength or maxLength (2.2) + (3.2)
17320    */
17321    if (flength && (fminlen || fmaxlen)) {
17322	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17323	    "either of 'minLength' or 'maxLength' to be specified on "
17324	    "the same type definition")
17325    }
17326    /*
17327    * Mutual exclusions in the same derivation step.
17328    */
17329    if ((fmaxinc) && (fmaxexc)) {
17330	/*
17331	* SCC "maxInclusive and maxExclusive"
17332	*/
17333	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17334    }
17335    if ((fmininc) && (fminexc)) {
17336	/*
17337	* SCC "minInclusive and minExclusive"
17338	*/
17339	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17340    }
17341
17342    if (flength && bflength) {
17343	/*
17344	* SCC "length valid restriction"
17345	* The values have to be equal.
17346	*/
17347	res = xmlSchemaCompareValues(flength->val, bflength->val);
17348	if (res == -2)
17349	    goto internal_error;
17350	if (res != 0)
17351	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17352	if ((res != 0) && (bflength->fixed)) {
17353	    FACET_RESTR_FIXED_ERR(flength)
17354	}
17355
17356    }
17357    if (fminlen && bfminlen) {
17358	/*
17359	* SCC "minLength valid restriction"
17360	* minLength >= BASE minLength
17361	*/
17362	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17363	if (res == -2)
17364	    goto internal_error;
17365	if (res == -1)
17366	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17367	if ((res != 0) && (bfminlen->fixed)) {
17368	    FACET_RESTR_FIXED_ERR(fminlen)
17369	}
17370    }
17371    if (fmaxlen && bfmaxlen) {
17372	/*
17373	* SCC "maxLength valid restriction"
17374	* maxLength <= BASE minLength
17375	*/
17376	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17377	if (res == -2)
17378	    goto internal_error;
17379	if (res == 1)
17380	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17381	if ((res != 0) && (bfmaxlen->fixed)) {
17382	    FACET_RESTR_FIXED_ERR(fmaxlen)
17383	}
17384    }
17385    /*
17386    * SCC "length and minLength or maxLength"
17387    */
17388    if (! flength)
17389	flength = bflength;
17390    if (flength) {
17391	if (! fminlen)
17392	    fminlen = bfminlen;
17393	if (fminlen) {
17394	    /* (1.1) length >= minLength */
17395	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17396	    if (res == -2)
17397		goto internal_error;
17398	    if (res == -1)
17399		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17400	}
17401	if (! fmaxlen)
17402	    fmaxlen = bfmaxlen;
17403	if (fmaxlen) {
17404	    /* (2.1) length <= maxLength */
17405	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17406	    if (res == -2)
17407		goto internal_error;
17408	    if (res == 1)
17409		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17410	}
17411    }
17412    if (fmaxinc) {
17413	/*
17414	* "maxInclusive"
17415	*/
17416	if (fmininc) {
17417	    /* SCC "maxInclusive >= minInclusive" */
17418	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17419	    if (res == -2)
17420		goto internal_error;
17421	    if (res == -1) {
17422		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17423	    }
17424	}
17425	/*
17426	* SCC "maxInclusive valid restriction"
17427	*/
17428	if (bfmaxinc) {
17429	    /* maxInclusive <= BASE maxInclusive */
17430	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17431	    if (res == -2)
17432		goto internal_error;
17433	    if (res == 1)
17434		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17435	    if ((res != 0) && (bfmaxinc->fixed)) {
17436		FACET_RESTR_FIXED_ERR(fmaxinc)
17437	    }
17438	}
17439	if (bfmaxexc) {
17440	    /* maxInclusive < BASE maxExclusive */
17441	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17442	    if (res == -2)
17443		goto internal_error;
17444	    if (res != -1) {
17445		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17446	    }
17447	}
17448	if (bfmininc) {
17449	    /* maxInclusive >= BASE minInclusive */
17450	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17451	    if (res == -2)
17452		goto internal_error;
17453	    if (res == -1) {
17454		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17455	    }
17456	}
17457	if (bfminexc) {
17458	    /* maxInclusive > BASE minExclusive */
17459	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17460	    if (res == -2)
17461		goto internal_error;
17462	    if (res != 1) {
17463		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17464	    }
17465	}
17466    }
17467    if (fmaxexc) {
17468	/*
17469	* "maxExclusive >= minExclusive"
17470	*/
17471	if (fminexc) {
17472	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17473	    if (res == -2)
17474		goto internal_error;
17475	    if (res == -1) {
17476		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17477	    }
17478	}
17479	/*
17480	* "maxExclusive valid restriction"
17481	*/
17482	if (bfmaxexc) {
17483	    /* maxExclusive <= BASE maxExclusive */
17484	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17485	    if (res == -2)
17486		goto internal_error;
17487	    if (res == 1) {
17488		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17489	    }
17490	    if ((res != 0) && (bfmaxexc->fixed)) {
17491		FACET_RESTR_FIXED_ERR(fmaxexc)
17492	    }
17493	}
17494	if (bfmaxinc) {
17495	    /* maxExclusive <= BASE maxInclusive */
17496	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17497	    if (res == -2)
17498		goto internal_error;
17499	    if (res == 1) {
17500		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17501	    }
17502	}
17503	if (bfmininc) {
17504	    /* maxExclusive > BASE minInclusive */
17505	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17506	    if (res == -2)
17507		goto internal_error;
17508	    if (res != 1) {
17509		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17510	    }
17511	}
17512	if (bfminexc) {
17513	    /* maxExclusive > BASE minExclusive */
17514	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17515	    if (res == -2)
17516		goto internal_error;
17517	    if (res != 1) {
17518		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17519	    }
17520	}
17521    }
17522    if (fminexc) {
17523	/*
17524	* "minExclusive < maxInclusive"
17525	*/
17526	if (fmaxinc) {
17527	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17528	    if (res == -2)
17529		goto internal_error;
17530	    if (res != -1) {
17531		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17532	    }
17533	}
17534	/*
17535	* "minExclusive valid restriction"
17536	*/
17537	if (bfminexc) {
17538	    /* minExclusive >= BASE minExclusive */
17539	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17540	    if (res == -2)
17541		goto internal_error;
17542	    if (res == -1) {
17543		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17544	    }
17545	    if ((res != 0) && (bfminexc->fixed)) {
17546		FACET_RESTR_FIXED_ERR(fminexc)
17547	    }
17548	}
17549	if (bfmaxinc) {
17550	    /* minExclusive <= BASE maxInclusive */
17551	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17552	    if (res == -2)
17553		goto internal_error;
17554	    if (res == 1) {
17555		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17556	    }
17557	}
17558	if (bfmininc) {
17559	    /* minExclusive >= BASE minInclusive */
17560	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17561	    if (res == -2)
17562		goto internal_error;
17563	    if (res == -1) {
17564		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17565	    }
17566	}
17567	if (bfmaxexc) {
17568	    /* minExclusive < BASE maxExclusive */
17569	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17570	    if (res == -2)
17571		goto internal_error;
17572	    if (res != -1) {
17573		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17574	    }
17575	}
17576    }
17577    if (fmininc) {
17578	/*
17579	* "minInclusive < maxExclusive"
17580	*/
17581	if (fmaxexc) {
17582	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17583	    if (res == -2)
17584		goto internal_error;
17585	    if (res != -1) {
17586		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17587	    }
17588	}
17589	/*
17590	* "minExclusive valid restriction"
17591	*/
17592	if (bfmininc) {
17593	    /* minInclusive >= BASE minInclusive */
17594	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17595	    if (res == -2)
17596		goto internal_error;
17597	    if (res == -1) {
17598		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17599	    }
17600	    if ((res != 0) && (bfmininc->fixed)) {
17601		FACET_RESTR_FIXED_ERR(fmininc)
17602	    }
17603	}
17604	if (bfmaxinc) {
17605	    /* minInclusive <= BASE maxInclusive */
17606	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17607	    if (res == -2)
17608		goto internal_error;
17609	    if (res == 1) {
17610		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17611	    }
17612	}
17613	if (bfminexc) {
17614	    /* minInclusive > BASE minExclusive */
17615	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17616	    if (res == -2)
17617		goto internal_error;
17618	    if (res != 1)
17619		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17620	}
17621	if (bfmaxexc) {
17622	    /* minInclusive < BASE maxExclusive */
17623	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17624	    if (res == -2)
17625		goto internal_error;
17626	    if (res != -1)
17627		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17628	}
17629    }
17630    if (ftotdig && bftotdig) {
17631	/*
17632	* SCC " totalDigits valid restriction"
17633	* totalDigits <= BASE totalDigits
17634	*/
17635	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17636	if (res == -2)
17637	    goto internal_error;
17638	if (res == 1)
17639	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17640	    -1, 1, 1);
17641	if ((res != 0) && (bftotdig->fixed)) {
17642	    FACET_RESTR_FIXED_ERR(ftotdig)
17643	}
17644    }
17645    if (ffracdig && bffracdig) {
17646	/*
17647	* SCC  "fractionDigits valid restriction"
17648	* fractionDigits <= BASE fractionDigits
17649	*/
17650	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17651	if (res == -2)
17652	    goto internal_error;
17653	if (res == 1)
17654	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17655	    -1, 1, 1);
17656	if ((res != 0) && (bffracdig->fixed)) {
17657	    FACET_RESTR_FIXED_ERR(ffracdig)
17658	}
17659    }
17660    /*
17661    * SCC "fractionDigits less than or equal to totalDigits"
17662    */
17663    if (! ftotdig)
17664	ftotdig = bftotdig;
17665    if (! ffracdig)
17666	ffracdig = bffracdig;
17667    if (ftotdig && ffracdig) {
17668	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17669	if (res == -2)
17670	    goto internal_error;
17671	if (res == 1)
17672	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17673		-1, 1, 0);
17674    }
17675    /*
17676    * *Enumerations* won' be added here, since only the first set
17677    * of enumerations in the ancestor-or-self axis is used
17678    * for validation, plus we need to use the base type of those
17679    * enumerations for whitespace.
17680    *
17681    * *Patterns*: won't be add here, since they are ORed at
17682    * type level and ANDed at ancestor level. This will
17683    * happed during validation by walking the base axis
17684    * of the type.
17685    */
17686    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17687	bfacet = cur->facet;
17688	/*
17689	* Special handling of enumerations and patterns.
17690	* TODO: hmm, they should not appear in the set, so remove this.
17691	*/
17692	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17693	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17694	    continue;
17695	/*
17696	* Search for a duplicate facet in the current type.
17697	*/
17698	link = type->facetSet;
17699	/* err = 0; */
17700	/* fixedErr = 0; */
17701	while (link != NULL) {
17702	    facet = link->facet;
17703	    if (facet->type == bfacet->type) {
17704		switch (facet->type) {
17705		    case XML_SCHEMA_FACET_WHITESPACE:
17706			/*
17707			* The whitespace must be stronger.
17708			*/
17709			if (facet->whitespace < bfacet->whitespace) {
17710			    FACET_RESTR_ERR(facet,
17711				"The 'whitespace' value has to be equal to "
17712				"or stronger than the 'whitespace' value of "
17713				"the base type")
17714			}
17715			if ((bfacet->fixed) &&
17716			    (facet->whitespace != bfacet->whitespace)) {
17717			    FACET_RESTR_FIXED_ERR(facet)
17718			}
17719			break;
17720		    default:
17721			break;
17722		}
17723		/* Duplicate found. */
17724		break;
17725	    }
17726	    link = link->next;
17727	}
17728	/*
17729	* If no duplicate was found: add the base types's facet
17730	* to the set.
17731	*/
17732	if (link == NULL) {
17733	    link = (xmlSchemaFacetLinkPtr)
17734		xmlMalloc(sizeof(xmlSchemaFacetLink));
17735	    if (link == NULL) {
17736		xmlSchemaPErrMemory(pctxt,
17737		    "deriving facets, creating a facet link", NULL);
17738		return (-1);
17739	    }
17740	    link->facet = cur->facet;
17741	    link->next = NULL;
17742	    if (last == NULL)
17743		type->facetSet = link;
17744	    else
17745		last->next = link;
17746	    last = link;
17747	}
17748
17749    }
17750
17751    return (0);
17752internal_error:
17753    PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17754	"an error occured");
17755    return (-1);
17756}
17757
17758static int
17759xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17760					     xmlSchemaTypePtr type)
17761{
17762    xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17763    /*
17764    * The actual value is then formed by replacing any union type
17765    * definition in the `explicit members` with the members of their
17766    * {member type definitions}, in order.
17767    *
17768    * TODO: There's a bug entry at
17769    * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17770    * which indicates that we'll keep the union types the future.
17771    */
17772    link = type->memberTypes;
17773    while (link != NULL) {
17774
17775	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17776	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17777
17778	if (WXS_IS_UNION(link->type)) {
17779	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17780	    if (subLink != NULL) {
17781		link->type = subLink->type;
17782		if (subLink->next != NULL) {
17783		    lastLink = link->next;
17784		    subLink = subLink->next;
17785		    prevLink = link;
17786		    while (subLink != NULL) {
17787			newLink = (xmlSchemaTypeLinkPtr)
17788			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17789			if (newLink == NULL) {
17790			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17791				NULL);
17792			    return (-1);
17793			}
17794			newLink->type = subLink->type;
17795			prevLink->next = newLink;
17796			prevLink = newLink;
17797			newLink->next = lastLink;
17798
17799			subLink = subLink->next;
17800		    }
17801		}
17802	    }
17803	}
17804	link = link->next;
17805    }
17806    return (0);
17807}
17808
17809static void
17810xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17811{
17812    int has = 0, needVal = 0, normVal = 0;
17813
17814    has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17815    if (has) {
17816	needVal = (type->baseType->flags &
17817	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17818	normVal = (type->baseType->flags &
17819	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17820    }
17821    if (type->facets != NULL) {
17822	xmlSchemaFacetPtr fac;
17823
17824	for (fac = type->facets; fac != NULL; fac = fac->next) {
17825	    switch (fac->type) {
17826		case XML_SCHEMA_FACET_WHITESPACE:
17827		    break;
17828		case XML_SCHEMA_FACET_PATTERN:
17829		    normVal = 1;
17830		    has = 1;
17831		    break;
17832		case XML_SCHEMA_FACET_ENUMERATION:
17833		    needVal = 1;
17834		    normVal = 1;
17835		    has = 1;
17836		    break;
17837		default:
17838		    has = 1;
17839		    break;
17840	    }
17841	}
17842    }
17843    if (normVal)
17844	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17845    if (needVal)
17846	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17847    if (has)
17848	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17849
17850    if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17851	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17852	/*
17853	* OPTIMIZE VAL TODO: Some facets need a computed value.
17854	*/
17855	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17856	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17857	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17858	}
17859    }
17860}
17861
17862static int
17863xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17864{
17865
17866
17867    /*
17868    * Evaluate the whitespace-facet value.
17869    */
17870    if (WXS_IS_LIST(type)) {
17871	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17872	return (0);
17873    } else if (WXS_IS_UNION(type))
17874	return (0);
17875
17876    if (type->facetSet != NULL) {
17877	xmlSchemaFacetLinkPtr lin;
17878
17879	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17880	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17881		switch (lin->facet->whitespace) {
17882		case XML_SCHEMAS_FACET_PRESERVE:
17883		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17884		    break;
17885		case XML_SCHEMAS_FACET_REPLACE:
17886		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17887		    break;
17888		case XML_SCHEMAS_FACET_COLLAPSE:
17889		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17890		    break;
17891		default:
17892		    return (-1);
17893		}
17894		return (0);
17895	    }
17896	}
17897    }
17898    /*
17899    * For all `atomic` datatypes other than string (and types `derived`
17900    * by `restriction` from it) the value of whiteSpace is fixed to
17901    * collapse
17902    */
17903    {
17904	xmlSchemaTypePtr anc;
17905
17906	for (anc = type->baseType; anc != NULL &&
17907		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17908		anc = anc->baseType) {
17909
17910	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17911		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17912		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17913
17914		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17915		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17916		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17917
17918		} else
17919		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17920		break;
17921	    }
17922	}
17923    }
17924    return (0);
17925}
17926
17927static int
17928xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17929			  xmlSchemaTypePtr type)
17930{
17931    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17932	return(0);
17933    if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17934	return(0);
17935    type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17936
17937    if (WXS_IS_LIST(type)) {
17938	/*
17939	* Corresponds to <simpleType><list>...
17940	*/
17941	if (type->subtypes == NULL) {
17942	    /*
17943	    * This one is really needed, so get out.
17944	    */
17945	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17946		"list type has no item-type assigned");
17947	    return(-1);
17948	}
17949    } else if (WXS_IS_UNION(type)) {
17950	/*
17951	* Corresponds to <simpleType><union>...
17952	*/
17953	if (type->memberTypes == NULL) {
17954	    /*
17955	    * This one is really needed, so get out.
17956	    */
17957	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17958		"union type has no member-types assigned");
17959	    return(-1);
17960	}
17961    } else {
17962	/*
17963	* Corresponds to <simpleType><restriction>...
17964	*/
17965	if (type->baseType == NULL) {
17966	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17967		"type has no base-type assigned");
17968	    return(-1);
17969	}
17970	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17971	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17972		return(-1);
17973	/*
17974	* Variety
17975	* If the <restriction> alternative is chosen, then the
17976	* {variety} of the {base type definition}.
17977	*/
17978	if (WXS_IS_ATOMIC(type->baseType))
17979	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17980	else if (WXS_IS_LIST(type->baseType)) {
17981	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17982	    /*
17983	    * Inherit the itemType.
17984	    */
17985	    type->subtypes = type->baseType->subtypes;
17986	} else if (WXS_IS_UNION(type->baseType)) {
17987	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17988	    /*
17989	    * NOTE that we won't assign the memberTypes of the base,
17990	    * since this will make trouble when freeing them; we will
17991	    * use a lookup function to access them instead.
17992	    */
17993	}
17994    }
17995    return(0);
17996}
17997
17998#ifdef DEBUG_TYPE
17999static void
18000xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18001		       xmlSchemaTypePtr type)
18002{
18003    if (type->node != NULL) {
18004        xmlGenericError(xmlGenericErrorContext,
18005                        "Type of %s : %s:%d :", name,
18006                        type->node->doc->URL,
18007                        xmlGetLineNo(type->node));
18008    } else {
18009        xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18010    }
18011    if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18012	switch (type->contentType) {
18013	    case XML_SCHEMA_CONTENT_SIMPLE:
18014		xmlGenericError(xmlGenericErrorContext, "simple\n");
18015		break;
18016	    case XML_SCHEMA_CONTENT_ELEMENTS:
18017		xmlGenericError(xmlGenericErrorContext, "elements\n");
18018		break;
18019	    case XML_SCHEMA_CONTENT_UNKNOWN:
18020		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18021		break;
18022	    case XML_SCHEMA_CONTENT_EMPTY:
18023		xmlGenericError(xmlGenericErrorContext, "empty\n");
18024		break;
18025	    case XML_SCHEMA_CONTENT_MIXED:
18026		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18027		    type->subtypes))
18028		    xmlGenericError(xmlGenericErrorContext,
18029			"mixed as emptiable particle\n");
18030		else
18031		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18032		break;
18033		/* Removed, since not used. */
18034		/*
18035		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18036		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18037		break;
18038		*/
18039	    case XML_SCHEMA_CONTENT_BASIC:
18040		xmlGenericError(xmlGenericErrorContext, "basic\n");
18041		break;
18042	    default:
18043		xmlGenericError(xmlGenericErrorContext,
18044		    "not registered !!!\n");
18045		break;
18046	}
18047    }
18048}
18049#endif
18050
18051/*
18052* 3.14.6 Constraints on Simple Type Definition Schema Components
18053*/
18054static int
18055xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18056				 xmlSchemaTypePtr type)
18057{
18058    int res, olderrs = pctxt->nberrors;
18059
18060    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18061	return(-1);
18062
18063    if (! WXS_IS_TYPE_NOT_FIXED(type))
18064	return(0);
18065
18066    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18067    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18068
18069    if (type->baseType == NULL) {
18070	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18071	    "missing baseType");
18072	goto exit_failure;
18073    }
18074    if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18075	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18076    /*
18077    * If a member type of a union is a union itself, we need to substitute
18078    * that member type for its member types.
18079    * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18080    * types in WXS 1.1.
18081    */
18082    if ((type->memberTypes != NULL) &&
18083	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18084	return(-1);
18085    /*
18086    * SPEC src-simple-type 1
18087    * "The corresponding simple type definition, if any, must satisfy
18088    * the conditions set out in Constraints on Simple Type Definition
18089    * Schema Components ($3.14.6)."
18090    */
18091    /*
18092    * Schema Component Constraint: Simple Type Definition Properties Correct
18093    * (st-props-correct)
18094    */
18095    res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18096    HFAILURE HERROR
18097    /*
18098    * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18099    * (cos-st-restricts)
18100    */
18101    res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18102    HFAILURE HERROR
18103    /*
18104    * TODO: Removed the error report, since it got annoying to get an
18105    * extra error report, if anything failed until now.
18106    * Enable this if needed.
18107    *
18108    * xmlSchemaPErr(ctxt, type->node,
18109    *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18110    *    "Simple type '%s' does not satisfy the constraints "
18111    *    "on simple type definitions.\n",
18112    *    type->name, NULL);
18113    */
18114    /*
18115    * Schema Component Constraint: Simple Type Restriction (Facets)
18116    * (st-restrict-facets)
18117    */
18118    res = xmlSchemaCheckFacetValues(type, pctxt);
18119    HFAILURE HERROR
18120    if ((type->facetSet != NULL) ||
18121	(type->baseType->facetSet != NULL)) {
18122	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18123	HFAILURE HERROR
18124    }
18125    /*
18126    * Whitespace value.
18127    */
18128    res = xmlSchemaTypeFixupWhitespace(type);
18129    HFAILURE HERROR
18130    xmlSchemaTypeFixupOptimFacets(type);
18131
18132exit_error:
18133#ifdef DEBUG_TYPE
18134    xmlSchemaDebugFixedType(pctxt, type);
18135#endif
18136    if (olderrs != pctxt->nberrors)
18137	return(pctxt->err);
18138    return(0);
18139
18140exit_failure:
18141#ifdef DEBUG_TYPE
18142    xmlSchemaDebugFixedType(pctxt, type);
18143#endif
18144    return(-1);
18145}
18146
18147static int
18148xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18149			  xmlSchemaTypePtr type)
18150{
18151    int res = 0, olderrs = pctxt->nberrors;
18152    xmlSchemaTypePtr baseType = type->baseType;
18153
18154    if (! WXS_IS_TYPE_NOT_FIXED(type))
18155	return(0);
18156    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18157    if (baseType == NULL) {
18158	PERROR_INT("xmlSchemaFixupComplexType",
18159	    "missing baseType");
18160	goto exit_failure;
18161    }
18162    /*
18163    * Fixup the base type.
18164    */
18165    if (WXS_IS_TYPE_NOT_FIXED(baseType))
18166	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18167    if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18168	/*
18169	* Skip fixup if the base type is invalid.
18170	* TODO: Generate a warning!
18171	*/
18172	return(0);
18173    }
18174    /*
18175    * This basically checks if the base type can be derived.
18176    */
18177    res = xmlSchemaCheckSRCCT(pctxt, type);
18178    HFAILURE HERROR
18179    /*
18180    * Fixup the content type.
18181    */
18182    if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18183	/*
18184	* Corresponds to <complexType><simpleContent>...
18185	*/
18186	if ((WXS_IS_COMPLEX(baseType)) &&
18187	    (baseType->contentTypeDef != NULL) &&
18188	    (WXS_IS_RESTRICTION(type))) {
18189	    xmlSchemaTypePtr contentBase, content;
18190#ifdef ENABLE_NAMED_LOCALS
18191	    char buf[30];
18192	    const xmlChar *tmpname;
18193#endif
18194	    /*
18195	    * SPEC (1) If <restriction> + base type is <complexType>,
18196	    * "whose own {content type} is a simple type..."
18197	    */
18198	    if (type->contentTypeDef != NULL) {
18199		/*
18200		* SPEC (1.1) "the simple type definition corresponding to the
18201		* <simpleType> among the [children] of <restriction> if there
18202		* is one;"
18203		* Note that this "<simpleType> among the [children]" was put
18204		* into ->contentTypeDef during parsing.
18205		*/
18206		contentBase = type->contentTypeDef;
18207		type->contentTypeDef = NULL;
18208	    } else {
18209		/*
18210		* (1.2) "...otherwise (<restriction> has no <simpleType>
18211		* among its [children]), the simple type definition which
18212		* is the {content type} of the ... base type."
18213		*/
18214		contentBase = baseType->contentTypeDef;
18215	    }
18216	    /*
18217	    * SPEC
18218	    * "... a simple type definition which restricts the simple
18219	    * type definition identified in clause 1.1 or clause 1.2
18220	    * with a set of facet components"
18221	    *
18222	    * Create the anonymous simple type, which will be the content
18223	    * type of the complex type.
18224	    */
18225#ifdef ENABLE_NAMED_LOCALS
18226	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18227	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18228	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18229		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18230		type->node, 0);
18231#else
18232	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18233		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18234		type->node, 0);
18235#endif
18236	    if (content == NULL)
18237		goto exit_failure;
18238	    /*
18239	    * We will use the same node as for the <complexType>
18240	    * to have it somehow anchored in the schema doc.
18241	    */
18242	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18243	    content->baseType = contentBase;
18244	    /*
18245	    * Move the facets, previously anchored on the
18246	    * complexType during parsing.
18247	    */
18248	    content->facets = type->facets;
18249	    type->facets = NULL;
18250	    content->facetSet = type->facetSet;
18251	    type->facetSet = NULL;
18252
18253	    type->contentTypeDef = content;
18254	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18255		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18256	    /*
18257	    * Fixup the newly created type. We don't need to check
18258	    * for circularity here.
18259	    */
18260	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18261	    HFAILURE HERROR
18262	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18263	    HFAILURE HERROR
18264
18265	} else if ((WXS_IS_COMPLEX(baseType)) &&
18266	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18267	    (WXS_IS_RESTRICTION(type))) {
18268	    /*
18269	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18270	    * an emptiable particle, then a simple type definition which
18271	    * restricts the <restriction>'s <simpleType> child.
18272	    */
18273	    if ((type->contentTypeDef == NULL) ||
18274		(type->contentTypeDef->baseType == NULL)) {
18275		/*
18276		* TODO: Check if this ever happens.
18277		*/
18278		xmlSchemaPCustomErr(pctxt,
18279		    XML_SCHEMAP_INTERNAL,
18280		    WXS_BASIC_CAST type, NULL,
18281		    "Internal error: xmlSchemaTypeFixup, "
18282		    "complex type '%s': the <simpleContent><restriction> "
18283		    "is missing a <simpleType> child, but was not catched "
18284		    "by xmlSchemaCheckSRCCT()", type->name);
18285		goto exit_failure;
18286	    }
18287	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18288	    /*
18289	    * SPEC (3) If <extension> + base is <complexType> with
18290	    * <simpleType> content, "...then the {content type} of that
18291	    * complex type definition"
18292	    */
18293	    if (baseType->contentTypeDef == NULL) {
18294		/*
18295		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18296		* should have catched this already.
18297		*/
18298		xmlSchemaPCustomErr(pctxt,
18299		    XML_SCHEMAP_INTERNAL,
18300		    WXS_BASIC_CAST type, NULL,
18301		    "Internal error: xmlSchemaTypeFixup, "
18302		    "complex type '%s': the <extension>ed base type is "
18303		    "a complex type with no simple content type",
18304		    type->name);
18305		goto exit_failure;
18306	    }
18307	    type->contentTypeDef = baseType->contentTypeDef;
18308	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18309	    /*
18310	    * SPEC (4) <extension> + base is <simpleType>
18311	    * "... then that simple type definition"
18312	    */
18313	    type->contentTypeDef = baseType;
18314	} else {
18315	    /*
18316	    * TODO: Check if this ever happens.
18317	    */
18318	    xmlSchemaPCustomErr(pctxt,
18319		XML_SCHEMAP_INTERNAL,
18320		WXS_BASIC_CAST type, NULL,
18321		"Internal error: xmlSchemaTypeFixup, "
18322		"complex type '%s' with <simpleContent>: unhandled "
18323		"derivation case", type->name);
18324	    goto exit_failure;
18325	}
18326    } else {
18327	int dummySequence = 0;
18328	xmlSchemaParticlePtr particle =
18329	    (xmlSchemaParticlePtr) type->subtypes;
18330	/*
18331	* Corresponds to <complexType><complexContent>...
18332	*
18333	* NOTE that the effective mixed was already set during parsing of
18334	* <complexType> and <complexContent>; its flag value is
18335	* XML_SCHEMAS_TYPE_MIXED.
18336	*
18337	* Compute the "effective content":
18338	* (2.1.1) + (2.1.2) + (2.1.3)
18339	*/
18340	if ((particle == NULL) ||
18341	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18342	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18343	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18344	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18345	    (particle->minOccurs == 0))) &&
18346	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18347	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18348		/*
18349		* SPEC (2.1.4) "If the `effective mixed` is true, then
18350		* a particle whose properties are as follows:..."
18351		*
18352		* Empty sequence model group with
18353		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18354		* NOTE that we sill assign it the <complexType> node to
18355		* somehow anchor it in the doc.
18356		*/
18357		if ((particle == NULL) ||
18358		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18359		    /*
18360		    * Create the particle.
18361		    */
18362		    particle = xmlSchemaAddParticle(pctxt,
18363			type->node, 1, 1);
18364		    if (particle == NULL)
18365			goto exit_failure;
18366		    /*
18367		    * Create the model group.
18368		    */ /* URGENT TODO: avoid adding to pending items. */
18369		    particle->children = (xmlSchemaTreeItemPtr)
18370			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18371			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18372		    if (particle->children == NULL)
18373			goto exit_failure;
18374
18375		    type->subtypes = (xmlSchemaTypePtr) particle;
18376		}
18377		dummySequence = 1;
18378		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18379	    } else {
18380		/*
18381		* SPEC (2.1.5) "otherwise empty"
18382		*/
18383		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18384	    }
18385	} else {
18386	    /*
18387	    * SPEC (2.2) "otherwise the particle corresponding to the
18388	    * <all>, <choice>, <group> or <sequence> among the
18389	    * [children]."
18390	    */
18391	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18392	}
18393	/*
18394	* Compute the "content type".
18395	*/
18396	if (WXS_IS_RESTRICTION(type)) {
18397	    /*
18398	    * SPEC (3.1) "If <restriction>..."
18399	    * (3.1.1) + (3.1.2) */
18400	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18401		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18402		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18403	    }
18404	} else {
18405	    /*
18406	    * SPEC (3.2) "If <extension>..."
18407	    */
18408	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18409		/*
18410		* SPEC (3.2.1)
18411		* "If the `effective content` is empty, then the
18412		*  {content type} of the [...] base ..."
18413		*/
18414		type->contentType = baseType->contentType;
18415		type->subtypes = baseType->subtypes;
18416		/*
18417		* Fixes bug #347316:
18418		* This is the case when the base type has a simple
18419		* type definition as content.
18420		*/
18421		type->contentTypeDef = baseType->contentTypeDef;
18422		/*
18423		* NOTE that the effective mixed is ignored here.
18424		*/
18425	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18426		/*
18427		* SPEC (3.2.2)
18428		*/
18429		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18430		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18431	    } else {
18432		/*
18433		* SPEC (3.2.3)
18434		*/
18435		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18436		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18437		    /*
18438		    * "A model group whose {compositor} is sequence and whose
18439		    * {particles} are..."
18440		    */
18441		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18442		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18443		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18444			XML_SCHEMA_TYPE_ALL))
18445		{
18446		    /*
18447		    * SPEC cos-all-limited (1)
18448		    */
18449		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18450			/* TODO: error code */
18451			XML_SCHEMAP_COS_ALL_LIMITED,
18452			WXS_ITEM_NODE(type), NULL,
18453			"The type has an 'all' model group in its "
18454			"{content type} and thus cannot be derived from "
18455			"a non-empty type, since this would produce a "
18456			"'sequence' model group containing the 'all' "
18457			"model group; 'all' model groups are not "
18458			"allowed to appear inside other model groups",
18459			NULL, NULL);
18460
18461		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18462		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18463		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18464			XML_SCHEMA_TYPE_ALL))
18465		{
18466		    /*
18467		    * SPEC cos-all-limited (1)
18468		    */
18469		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18470			/* TODO: error code */
18471			XML_SCHEMAP_COS_ALL_LIMITED,
18472			WXS_ITEM_NODE(type), NULL,
18473			"A type cannot be derived by extension from a type "
18474			"which has an 'all' model group in its "
18475			"{content type}, since this would produce a "
18476			"'sequence' model group containing the 'all' "
18477			"model group; 'all' model groups are not "
18478			"allowed to appear inside other model groups",
18479			NULL, NULL);
18480
18481		} else if (! dummySequence) {
18482		    xmlSchemaTreeItemPtr effectiveContent =
18483			(xmlSchemaTreeItemPtr) type->subtypes;
18484		    /*
18485		    * Create the particle.
18486		    */
18487		    particle = xmlSchemaAddParticle(pctxt,
18488			type->node, 1, 1);
18489		    if (particle == NULL)
18490			goto exit_failure;
18491		    /*
18492		    * Create the "sequence" model group.
18493		    */
18494		    particle->children = (xmlSchemaTreeItemPtr)
18495			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18496			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18497		    if (particle->children == NULL)
18498			goto exit_failure;
18499		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18500		    /*
18501		    * SPEC "the particle of the {content type} of
18502		    * the ... base ..."
18503		    * Create a duplicate of the base type's particle
18504		    * and assign its "term" to it.
18505		    */
18506		    particle->children->children =
18507			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18508			type->node,
18509			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18510			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18511		    if (particle->children->children == NULL)
18512			goto exit_failure;
18513		    particle = (xmlSchemaParticlePtr)
18514			particle->children->children;
18515		    particle->children =
18516			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18517		    /*
18518		    * SPEC "followed by the `effective content`."
18519		    */
18520		    particle->next = effectiveContent;
18521		    /*
18522		    * This all will result in:
18523		    * new-particle
18524		    *   --> new-sequence(
18525		    *         new-particle
18526		    *           --> base-model,
18527		    *         this-particle
18528		    *	        --> this-model
18529		    *	    )
18530		    */
18531		} else {
18532		    /*
18533		    * This is the case when there is already an empty
18534		    * <sequence> with minOccurs==maxOccurs==1.
18535		    * Just add the base types's content type.
18536		    * NOTE that, although we miss to add an intermediate
18537		    * <sequence>, this should produce no difference to
18538		    * neither the regex compilation of the content model,
18539		    * nor to the complex type contraints.
18540		    */
18541		    particle->children->children =
18542			(xmlSchemaTreeItemPtr) baseType->subtypes;
18543		}
18544	    }
18545	}
18546    }
18547    /*
18548    * Now fixup attribute uses:
18549    *   - expand attr. group references
18550    *     - intersect attribute wildcards
18551    *   - inherit attribute uses of the base type
18552    *   - inherit or union attr. wildcards if extending
18553    *   - apply attr. use prohibitions if restricting
18554    */
18555    res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18556    HFAILURE HERROR
18557    /*
18558    * Apply the complex type component constraints; this will not
18559    * check attributes, since this is done in
18560    * xmlSchemaFixupTypeAttributeUses().
18561    */
18562    res = xmlSchemaCheckCTComponent(pctxt, type);
18563    HFAILURE HERROR
18564
18565#ifdef DEBUG_TYPE
18566    xmlSchemaDebugFixedType(pctxt, type);
18567#endif
18568    if (olderrs != pctxt->nberrors)
18569	return(pctxt->err);
18570    else
18571	return(0);
18572
18573exit_error:
18574    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18575#ifdef DEBUG_TYPE
18576    xmlSchemaDebugFixedType(pctxt, type);
18577#endif
18578    return(pctxt->err);
18579
18580exit_failure:
18581    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18582#ifdef DEBUG_TYPE
18583    xmlSchemaDebugFixedType(pctxt, type);
18584#endif
18585    return(-1);
18586}
18587
18588
18589/**
18590 * xmlSchemaTypeFixup:
18591 * @typeDecl:  the schema type definition
18592 * @ctxt:  the schema parser context
18593 *
18594 * Fixes the content model of the type.
18595 * URGENT TODO: We need an int result!
18596 */
18597static int
18598xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18599                   xmlSchemaAbstractCtxtPtr actxt)
18600{
18601    if (type == NULL)
18602        return(0);
18603    if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18604	AERROR_INT("xmlSchemaTypeFixup",
18605	    "this function needs a parser context");
18606	return(-1);
18607    }
18608    if (! WXS_IS_TYPE_NOT_FIXED(type))
18609	return(0);
18610    if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18611	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18612    else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18613	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18614    return(0);
18615}
18616
18617/**
18618 * xmlSchemaCheckFacet:
18619 * @facet:  the facet
18620 * @typeDecl:  the schema type definition
18621 * @pctxt:  the schema parser context or NULL
18622 * @name: the optional name of the type
18623 *
18624 * Checks and computes the values of facets.
18625 *
18626 * Returns 0 if valid, a positive error code if not valid and
18627 *         -1 in case of an internal or API error.
18628 */
18629int
18630xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18631                    xmlSchemaTypePtr typeDecl,
18632                    xmlSchemaParserCtxtPtr pctxt,
18633		    const xmlChar * name ATTRIBUTE_UNUSED)
18634{
18635    int ret = 0, ctxtGiven;
18636
18637    if ((facet == NULL) || (typeDecl == NULL))
18638        return(-1);
18639    /*
18640    * TODO: will the parser context be given if used from
18641    * the relaxNG module?
18642    */
18643    if (pctxt == NULL)
18644	ctxtGiven = 0;
18645    else
18646	ctxtGiven = 1;
18647
18648    switch (facet->type) {
18649        case XML_SCHEMA_FACET_MININCLUSIVE:
18650        case XML_SCHEMA_FACET_MINEXCLUSIVE:
18651        case XML_SCHEMA_FACET_MAXINCLUSIVE:
18652        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18653	case XML_SCHEMA_FACET_ENUMERATION: {
18654                /*
18655                 * Okay we need to validate the value
18656                 * at that point.
18657                 */
18658		xmlSchemaTypePtr base;
18659
18660		/* 4.3.5.5 Constraints on enumeration Schema Components
18661		* Schema Component Constraint: enumeration valid restriction
18662		* It is an `error` if any member of {value} is not in the
18663		* `value space` of {base type definition}.
18664		*
18665		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18666		* The value `must` be in the
18667		* `value space` of the `base type`.
18668		*/
18669		/*
18670		* This function is intended to deliver a compiled value
18671		* on the facet. In this implementation of XML Schemata the
18672		* type holding a facet, won't be a built-in type.
18673		* Thus to ensure that other API
18674		* calls (relaxng) do work, if the given type is a built-in
18675		* type, we will assume that the given built-in type *is
18676		* already* the base type.
18677		*/
18678		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18679		    base = typeDecl->baseType;
18680		    if (base == NULL) {
18681			PERROR_INT("xmlSchemaCheckFacet",
18682			    "a type user derived type has no base type");
18683			return (-1);
18684		    }
18685		} else
18686		    base = typeDecl;
18687
18688		if (! ctxtGiven) {
18689		    /*
18690		    * A context is needed if called from RelaxNG.
18691		    */
18692		    pctxt = xmlSchemaNewParserCtxt("*");
18693		    if (pctxt == NULL)
18694			return (-1);
18695		}
18696		/*
18697		* NOTE: This call does not check the content nodes,
18698		* since they are not available:
18699		* facet->node is just the node holding the facet
18700		* definition, *not* the attribute holding the *value*
18701		* of the facet.
18702		*/
18703		ret = xmlSchemaVCheckCVCSimpleType(
18704		    ACTXT_CAST pctxt, facet->node, base,
18705		    facet->value, &(facet->val), 1, 1, 0);
18706                if (ret != 0) {
18707		    if (ret < 0) {
18708			/* No error message for RelaxNG. */
18709			if (ctxtGiven) {
18710			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18711				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18712				"Internal error: xmlSchemaCheckFacet, "
18713				"failed to validate the value '%s' of the "
18714				"facet '%s' against the base type",
18715				facet->value, xmlSchemaFacetTypeToString(facet->type));
18716			}
18717			goto internal_error;
18718		    }
18719		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18720		    /* No error message for RelaxNG. */
18721		    if (ctxtGiven) {
18722			xmlChar *str = NULL;
18723
18724			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18725			    ret, facet->node, WXS_BASIC_CAST facet,
18726			    "The value '%s' of the facet does not validate "
18727			    "against the base type '%s'",
18728			    facet->value,
18729			    xmlSchemaFormatQName(&str,
18730				base->targetNamespace, base->name));
18731			FREE_AND_NULL(str);
18732		    }
18733		    goto exit;
18734                } else if (facet->val == NULL) {
18735		    if (ctxtGiven) {
18736			PERROR_INT("xmlSchemaCheckFacet",
18737			    "value was not computed");
18738		    }
18739		    TODO
18740		}
18741                break;
18742            }
18743        case XML_SCHEMA_FACET_PATTERN:
18744            facet->regexp = xmlRegexpCompile(facet->value);
18745            if (facet->regexp == NULL) {
18746		ret = XML_SCHEMAP_REGEXP_INVALID;
18747		/* No error message for RelaxNG. */
18748		if (ctxtGiven) {
18749		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18750			ret, facet->node, WXS_BASIC_CAST typeDecl,
18751			"The value '%s' of the facet 'pattern' is not a "
18752			"valid regular expression",
18753			facet->value, NULL);
18754		}
18755            }
18756            break;
18757        case XML_SCHEMA_FACET_TOTALDIGITS:
18758        case XML_SCHEMA_FACET_FRACTIONDIGITS:
18759        case XML_SCHEMA_FACET_LENGTH:
18760        case XML_SCHEMA_FACET_MAXLENGTH:
18761        case XML_SCHEMA_FACET_MINLENGTH:
18762
18763	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18764		ret = xmlSchemaValidatePredefinedType(
18765		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18766		    facet->value, &(facet->val));
18767	    } else {
18768		ret = xmlSchemaValidatePredefinedType(
18769		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18770		    facet->value, &(facet->val));
18771	    }
18772	    if (ret != 0) {
18773		if (ret < 0) {
18774		    /* No error message for RelaxNG. */
18775		    if (ctxtGiven) {
18776			PERROR_INT("xmlSchemaCheckFacet",
18777			    "validating facet value");
18778		    }
18779		    goto internal_error;
18780		}
18781		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18782		/* No error message for RelaxNG. */
18783		if (ctxtGiven) {
18784		    /* error code */
18785		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18786			ret, facet->node, WXS_BASIC_CAST typeDecl,
18787			"The value '%s' of the facet '%s' is not a valid '%s'",
18788			facet->value,
18789			xmlSchemaFacetTypeToString(facet->type),
18790			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18791			    BAD_CAST "nonNegativeInteger" :
18792			    BAD_CAST "positiveInteger",
18793			NULL);
18794		}
18795	    }
18796	    break;
18797
18798        case XML_SCHEMA_FACET_WHITESPACE:{
18799                if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18800                    facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18801                } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18802                    facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18803                } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18804                    facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18805                } else {
18806		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18807                    /* No error message for RelaxNG. */
18808		    if (ctxtGiven) {
18809			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18810			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18811			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18812			    "The value '%s' of the facet 'whitespace' is not "
18813			    "valid", facet->value, NULL);
18814                    }
18815                }
18816            }
18817        default:
18818            break;
18819    }
18820exit:
18821    if ((! ctxtGiven) && (pctxt != NULL))
18822	xmlSchemaFreeParserCtxt(pctxt);
18823    return (ret);
18824internal_error:
18825    if ((! ctxtGiven) && (pctxt != NULL))
18826	xmlSchemaFreeParserCtxt(pctxt);
18827    return (-1);
18828}
18829
18830/**
18831 * xmlSchemaCheckFacetValues:
18832 * @typeDecl:  the schema type definition
18833 * @ctxt:  the schema parser context
18834 *
18835 * Checks the default values types, especially for facets
18836 */
18837static int
18838xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18839			  xmlSchemaParserCtxtPtr pctxt)
18840{
18841    int res, olderrs = pctxt->nberrors;
18842    const xmlChar *name = typeDecl->name;
18843    /*
18844    * NOTE: It is intended to use the facets list, instead
18845    * of facetSet.
18846    */
18847    if (typeDecl->facets != NULL) {
18848	xmlSchemaFacetPtr facet = typeDecl->facets;
18849
18850	/*
18851	* Temporarily assign the "schema" to the validation context
18852	* of the parser context. This is needed for NOTATION validation.
18853	*/
18854	if (pctxt->vctxt == NULL) {
18855	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18856		return(-1);
18857	}
18858	pctxt->vctxt->schema = pctxt->schema;
18859	while (facet != NULL) {
18860	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18861	    HFAILURE
18862	    facet = facet->next;
18863	}
18864	pctxt->vctxt->schema = NULL;
18865    }
18866    if (olderrs != pctxt->nberrors)
18867	return(pctxt->err);
18868    return(0);
18869exit_failure:
18870    return(-1);
18871}
18872
18873/**
18874 * xmlSchemaGetCircModelGrDefRef:
18875 * @ctxtMGroup: the searched model group
18876 * @selfMGroup: the second searched model group
18877 * @particle: the first particle
18878 *
18879 * This one is intended to be used by
18880 * xmlSchemaCheckGroupDefCircular only.
18881 *
18882 * Returns the particle with the circular model group definition reference,
18883 * otherwise NULL.
18884 */
18885static xmlSchemaTreeItemPtr
18886xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18887			      xmlSchemaTreeItemPtr particle)
18888{
18889    xmlSchemaTreeItemPtr circ = NULL;
18890    xmlSchemaTreeItemPtr term;
18891    xmlSchemaModelGroupDefPtr gdef;
18892
18893    for (; particle != NULL; particle = particle->next) {
18894	term = particle->children;
18895	if (term == NULL)
18896	    continue;
18897	switch (term->type) {
18898	    case XML_SCHEMA_TYPE_GROUP:
18899		gdef = (xmlSchemaModelGroupDefPtr) term;
18900		if (gdef == groupDef)
18901		    return (particle);
18902		/*
18903		* Mark this model group definition to avoid infinite
18904		* recursion on circular references not yet examined.
18905		*/
18906		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18907		    continue;
18908		if (gdef->children != NULL) {
18909		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18910		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18911			gdef->children->children);
18912		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18913		    if (circ != NULL)
18914			return (circ);
18915		}
18916		break;
18917	    case XML_SCHEMA_TYPE_SEQUENCE:
18918	    case XML_SCHEMA_TYPE_CHOICE:
18919	    case XML_SCHEMA_TYPE_ALL:
18920		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18921		if (circ != NULL)
18922		    return (circ);
18923		break;
18924	    default:
18925		break;
18926	}
18927    }
18928    return (NULL);
18929}
18930
18931/**
18932 * xmlSchemaCheckGroupDefCircular:
18933 * @item:  the model group definition
18934 * @ctxt:  the parser context
18935 * @name:  the name
18936 *
18937 * Checks for circular references to model group definitions.
18938 */
18939static void
18940xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18941			       xmlSchemaParserCtxtPtr ctxt)
18942{
18943    /*
18944    * Schema Component Constraint: Model Group Correct
18945    * 2 Circular groups are disallowed. That is, within the {particles}
18946    * of a group there must not be at any depth a particle whose {term}
18947    * is the group itself.
18948    */
18949    if ((item == NULL) ||
18950	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18951	(item->children == NULL))
18952	return;
18953    {
18954	xmlSchemaTreeItemPtr circ;
18955
18956	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18957	if (circ != NULL) {
18958	    xmlChar *str = NULL;
18959	    /*
18960	    * TODO: The error report is not adequate: this constraint
18961	    * is defined for model groups but not definitions, but since
18962	    * there cannot be any circular model groups without a model group
18963	    * definition (if not using a construction API), we check those
18964	    * defintions only.
18965	    */
18966	    xmlSchemaPCustomErr(ctxt,
18967		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18968		NULL, WXS_ITEM_NODE(circ),
18969		"Circular reference to the model group definition '%s' "
18970		"defined", xmlSchemaFormatQName(&str,
18971		    item->targetNamespace, item->name));
18972	    FREE_AND_NULL(str)
18973	    /*
18974	    * NOTE: We will cut the reference to avoid further
18975	    * confusion of the processor. This is a fatal error.
18976	    */
18977	    circ->children = NULL;
18978	}
18979    }
18980}
18981
18982/**
18983 * xmlSchemaModelGroupToModelGroupDefFixup:
18984 * @ctxt:  the parser context
18985 * @mg:  the model group
18986 *
18987 * Assigns the model group of model group definitions to the "term"
18988 * of the referencing particle.
18989 * In xmlSchemaResolveModelGroupParticleReferences the model group
18990 * definitions were assigned to the "term", since needed for the
18991 * circularity check.
18992 *
18993 * Schema Component Constraint:
18994 *     All Group Limited (cos-all-limited) (1.2)
18995 */
18996static void
18997xmlSchemaModelGroupToModelGroupDefFixup(
18998    xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18999    xmlSchemaModelGroupPtr mg)
19000{
19001    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19002
19003    while (particle != NULL) {
19004	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19005	    ((WXS_PARTICLE_TERM(particle))->type !=
19006		XML_SCHEMA_TYPE_GROUP))
19007	{
19008	    particle = WXS_PTC_CAST particle->next;
19009	    continue;
19010	}
19011	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19012	    /*
19013	    * TODO: Remove the particle.
19014	    */
19015	    WXS_PARTICLE_TERM(particle) = NULL;
19016	    particle = WXS_PTC_CAST particle->next;
19017	    continue;
19018	}
19019	/*
19020	* Assign the model group to the {term} of the particle.
19021	*/
19022	WXS_PARTICLE_TERM(particle) =
19023	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19024
19025	particle = WXS_PTC_CAST particle->next;
19026    }
19027}
19028
19029/**
19030 * xmlSchemaCheckAttrGroupCircularRecur:
19031 * @ctxtGr: the searched attribute group
19032 * @attr: the current attribute list to be processed
19033 *
19034 * This one is intended to be used by
19035 * xmlSchemaCheckAttrGroupCircular only.
19036 *
19037 * Returns the circular attribute grou reference, otherwise NULL.
19038 */
19039static xmlSchemaQNameRefPtr
19040xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19041				     xmlSchemaItemListPtr list)
19042{
19043    xmlSchemaAttributeGroupPtr gr;
19044    xmlSchemaQNameRefPtr ref, circ;
19045    int i;
19046    /*
19047    * We will search for an attribute group reference which
19048    * references the context attribute group.
19049    */
19050    for (i = 0; i < list->nbItems; i++) {
19051	ref = list->items[i];
19052	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19053	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19054	    (ref->item != NULL))
19055	{
19056	    gr = WXS_ATTR_GROUP_CAST ref->item;
19057	    if (gr == ctxtGr)
19058		return(ref);
19059	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19060		continue;
19061	    /*
19062	    * Mark as visited to avoid infinite recursion on
19063	    * circular references not yet examined.
19064	    */
19065	    if ((gr->attrUses) &&
19066		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19067	    {
19068		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19069		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19070		    (xmlSchemaItemListPtr) gr->attrUses);
19071		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19072		if (circ != NULL)
19073		    return (circ);
19074	    }
19075
19076	}
19077    }
19078    return (NULL);
19079}
19080
19081/**
19082 * xmlSchemaCheckAttrGroupCircular:
19083 * attrGr:  the attribute group definition
19084 * @ctxt:  the parser context
19085 * @name:  the name
19086 *
19087 * Checks for circular references of attribute groups.
19088 */
19089static int
19090xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19091				xmlSchemaParserCtxtPtr ctxt)
19092{
19093    /*
19094    * Schema Representation Constraint:
19095    * Attribute Group Definition Representation OK
19096    * 3 Circular group reference is disallowed outside <redefine>.
19097    * That is, unless this element information item's parent is
19098    * <redefine>, then among the [children], if any, there must
19099    * not be an <attributeGroup> with ref [attribute] which resolves
19100    * to the component corresponding to this <attributeGroup>. Indirect
19101    * circularity is also ruled out. That is, when QName resolution
19102    * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19103    * any <attributeGroup>s with a ref [attribute] among the [children],
19104    * it must not be the case that a `QName` is encountered at any depth
19105    * which resolves to the component corresponding to this <attributeGroup>.
19106    */
19107    if (attrGr->attrUses == NULL)
19108	return(0);
19109    else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19110	return(0);
19111    else {
19112	xmlSchemaQNameRefPtr circ;
19113
19114	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19115	    (xmlSchemaItemListPtr) attrGr->attrUses);
19116	if (circ != NULL) {
19117	    xmlChar *str = NULL;
19118	    /*
19119	    * TODO: Report the referenced attr group as QName.
19120	    */
19121	    xmlSchemaPCustomErr(ctxt,
19122		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19123		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19124		"Circular reference to the attribute group '%s' "
19125		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19126	    FREE_AND_NULL(str);
19127	    /*
19128	    * NOTE: We will cut the reference to avoid further
19129	    * confusion of the processor.
19130	    * BADSPEC TODO: The spec should define how to process in this case.
19131	    */
19132	    circ->item = NULL;
19133	    return(ctxt->err);
19134	}
19135    }
19136    return(0);
19137}
19138
19139static int
19140xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19141				  xmlSchemaAttributeGroupPtr attrGr);
19142
19143/**
19144 * xmlSchemaExpandAttributeGroupRefs:
19145 * @pctxt: the parser context
19146 * @node: the node of the component holding the attribute uses
19147 * @completeWild: the intersected wildcard to be returned
19148 * @list: the attribute uses
19149 *
19150 * Substitutes contained attribute group references
19151 * for their attribute uses. Wilcards are intersected.
19152 * Attribute use prohibitions are removed from the list
19153 * and returned via the @prohibs list.
19154 * Pointlessness of attr. prohibs, if a matching attr. decl
19155 * is existent a well, are checked.
19156 */
19157static int
19158xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19159				  xmlSchemaBasicItemPtr item,
19160				  xmlSchemaWildcardPtr *completeWild,
19161				  xmlSchemaItemListPtr list,
19162				  xmlSchemaItemListPtr prohibs)
19163{
19164    xmlSchemaAttributeGroupPtr gr;
19165    xmlSchemaAttributeUsePtr use;
19166    xmlSchemaItemListPtr sublist;
19167    int i, j;
19168    int created = (*completeWild == NULL) ? 0 : 1;
19169
19170    if (prohibs)
19171	prohibs->nbItems = 0;
19172
19173    for (i = 0; i < list->nbItems; i++) {
19174	use = list->items[i];
19175
19176	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19177	    if (prohibs == NULL) {
19178		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19179		    "unexpected attr prohibition found");
19180		return(-1);
19181	    }
19182	    /*
19183	    * Remove from attribute uses.
19184	    */
19185	    if (xmlSchemaItemListRemove(list, i) == -1)
19186		return(-1);
19187	    i--;
19188	    /*
19189	    * Note that duplicate prohibitions were already
19190	    * handled at parsing time.
19191	    */
19192	    /*
19193	    * Add to list of prohibitions.
19194	    */
19195	    xmlSchemaItemListAddSize(prohibs, 2, use);
19196	    continue;
19197	}
19198	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19199	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19200	{
19201	    if ((WXS_QNAME_CAST use)->item == NULL)
19202		return(-1);
19203	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19204	    /*
19205	    * Expand the referenced attr. group.
19206	    * TODO: remove this, this is done in a previous step, so
19207	    * already done here.
19208	    */
19209	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19210		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19211		    return(-1);
19212	    }
19213	    /*
19214	    * Build the 'complete' wildcard; i.e. intersect multiple
19215	    * wildcards.
19216	    */
19217	    if (gr->attributeWildcard != NULL) {
19218		if (*completeWild == NULL) {
19219		    *completeWild = gr->attributeWildcard;
19220		} else {
19221		    if (! created) {
19222			xmlSchemaWildcardPtr tmpWild;
19223
19224			 /*
19225			* Copy the first encountered wildcard as context,
19226			* except for the annotation.
19227			*
19228			* Although the complete wildcard might not correspond
19229			* to any node in the schema, we will anchor it on
19230			* the node of the owner component.
19231			*/
19232			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19233			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19234			    WXS_ITEM_NODE(item));
19235			if (tmpWild == NULL)
19236			    return(-1);
19237			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19238			    tmpWild, *completeWild) == -1)
19239			    return (-1);
19240			tmpWild->processContents = (*completeWild)->processContents;
19241			*completeWild = tmpWild;
19242			created = 1;
19243		    }
19244
19245		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19246			gr->attributeWildcard) == -1)
19247			return(-1);
19248		}
19249	    }
19250	    /*
19251	    * Just remove the reference if the referenced group does not
19252	    * contain any attribute uses.
19253	    */
19254	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19255	    if ((sublist == NULL) || sublist->nbItems == 0) {
19256		if (xmlSchemaItemListRemove(list, i) == -1)
19257		    return(-1);
19258		i--;
19259		continue;
19260	    }
19261	    /*
19262	    * Add the attribute uses.
19263	    */
19264	    list->items[i] = sublist->items[0];
19265	    if (sublist->nbItems != 1) {
19266		for (j = 1; j < sublist->nbItems; j++) {
19267		    i++;
19268		    if (xmlSchemaItemListInsert(list,
19269			    sublist->items[j], i) == -1)
19270			return(-1);
19271		}
19272	    }
19273	}
19274
19275    }
19276    /*
19277    * Handle pointless prohibitions of declared attributes.
19278    */
19279    if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19280	xmlSchemaAttributeUseProhibPtr prohib;
19281
19282	for (i = prohibs->nbItems -1; i >= 0; i--) {
19283	    prohib = prohibs->items[i];
19284	    for (j = 0; j < list->nbItems; j++) {
19285		use = list->items[j];
19286
19287		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19288		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19289		{
19290		    xmlChar *str = NULL;
19291
19292		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19293			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19294			prohib->node, NULL,
19295			"Skipping pointless attribute use prohibition "
19296			"'%s', since a corresponding attribute use "
19297			"exists already in the type definition",
19298			xmlSchemaFormatQName(&str,
19299			    prohib->targetNamespace, prohib->name),
19300			NULL, NULL);
19301		    FREE_AND_NULL(str);
19302		    /*
19303		    * Remove the prohibition.
19304		    */
19305		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19306			return(-1);
19307		    break;
19308		}
19309	    }
19310	}
19311    }
19312    return(0);
19313}
19314
19315/**
19316 * xmlSchemaAttributeGroupExpandRefs:
19317 * @pctxt:  the parser context
19318 * @attrGr:  the attribute group definition
19319 *
19320 * Computation of:
19321 * {attribute uses} property
19322 * {attribute wildcard} property
19323 *
19324 * Substitutes contained attribute group references
19325 * for their attribute uses. Wilcards are intersected.
19326 */
19327static int
19328xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19329				  xmlSchemaAttributeGroupPtr attrGr)
19330{
19331    if ((attrGr->attrUses == NULL) ||
19332	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19333	return(0);
19334
19335    attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19336    if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19337	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19338	return(-1);
19339    return(0);
19340}
19341
19342/**
19343 * xmlSchemaAttributeGroupExpandRefs:
19344 * @pctxt:  the parser context
19345 * @attrGr:  the attribute group definition
19346 *
19347 * Substitutes contained attribute group references
19348 * for their attribute uses. Wilcards are intersected.
19349 *
19350 * Schema Component Constraint:
19351 *    Attribute Group Definition Properties Correct (ag-props-correct)
19352 */
19353static int
19354xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19355				  xmlSchemaAttributeGroupPtr attrGr)
19356{
19357    /*
19358    * SPEC ag-props-correct
19359    * (1) "The values of the properties of an attribute group definition
19360    * must be as described in the property tableau in The Attribute
19361    * Group Definition Schema Component ($3.6.1), modulo the impact of
19362    * Missing Sub-components ($5.3);"
19363    */
19364
19365    if ((attrGr->attrUses != NULL) &&
19366	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19367    {
19368	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19369	xmlSchemaAttributeUsePtr use, tmp;
19370	int i, j, hasId = 0;
19371
19372	for (i = uses->nbItems -1; i >= 0; i--) {
19373	    use = uses->items[i];
19374	    /*
19375	    * SPEC ag-props-correct
19376	    * (2) "Two distinct members of the {attribute uses} must not have
19377	    * {attribute declaration}s both of whose {name}s match and whose
19378	    * {target namespace}s are identical."
19379	    */
19380	    if (i > 0) {
19381		for (j = i -1; j >= 0; j--) {
19382		    tmp = uses->items[j];
19383		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19384			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19385			(WXS_ATTRUSE_DECL_TNS(use) ==
19386			WXS_ATTRUSE_DECL_TNS(tmp)))
19387		    {
19388			xmlChar *str = NULL;
19389
19390			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19391			    XML_SCHEMAP_AG_PROPS_CORRECT,
19392			    attrGr->node, WXS_BASIC_CAST attrGr,
19393			    "Duplicate %s",
19394			    xmlSchemaGetComponentDesignation(&str, use),
19395			    NULL);
19396			FREE_AND_NULL(str);
19397			/*
19398			* Remove the duplicate.
19399			*/
19400			if (xmlSchemaItemListRemove(uses, i) == -1)
19401			    return(-1);
19402			goto next_use;
19403		    }
19404		}
19405	    }
19406	    /*
19407	    * SPEC ag-props-correct
19408	    * (3) "Two distinct members of the {attribute uses} must not have
19409	    * {attribute declaration}s both of whose {type definition}s are or
19410	    * are derived from ID."
19411	    * TODO: Does 'derived' include member-types of unions?
19412	    */
19413	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19414		if (xmlSchemaIsDerivedFromBuiltInType(
19415		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19416		{
19417		    if (hasId) {
19418			xmlChar *str = NULL;
19419
19420			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19421			    XML_SCHEMAP_AG_PROPS_CORRECT,
19422			    attrGr->node, WXS_BASIC_CAST attrGr,
19423			    "There must not exist more than one attribute "
19424			    "declaration of type 'xs:ID' "
19425			    "(or derived from 'xs:ID'). The %s violates this "
19426			    "constraint",
19427			    xmlSchemaGetComponentDesignation(&str, use),
19428			    NULL);
19429			FREE_AND_NULL(str);
19430			if (xmlSchemaItemListRemove(uses, i) == -1)
19431			    return(-1);
19432		    }
19433		    hasId = 1;
19434		}
19435	    }
19436next_use: {}
19437	}
19438    }
19439    return(0);
19440}
19441
19442/**
19443 * xmlSchemaResolveAttrGroupReferences:
19444 * @attrgrpDecl:  the schema attribute definition
19445 * @ctxt:  the schema parser context
19446 * @name:  the attribute name
19447 *
19448 * Resolves references to attribute group definitions.
19449 */
19450static int
19451xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19452				    xmlSchemaParserCtxtPtr ctxt)
19453{
19454    xmlSchemaAttributeGroupPtr group;
19455
19456    if (ref->item != NULL)
19457        return(0);
19458    group = xmlSchemaGetAttributeGroup(ctxt->schema,
19459	ref->name,
19460	ref->targetNamespace);
19461    if (group == NULL) {
19462	xmlSchemaPResCompAttrErr(ctxt,
19463	    XML_SCHEMAP_SRC_RESOLVE,
19464	    NULL, ref->node,
19465	    "ref", ref->name, ref->targetNamespace,
19466	    ref->itemType, NULL);
19467	return(ctxt->err);
19468    }
19469    ref->item = WXS_BASIC_CAST group;
19470    return(0);
19471}
19472
19473/**
19474 * xmlSchemaCheckAttrPropsCorrect:
19475 * @item:  an schema attribute declaration/use
19476 * @ctxt:  a schema parser context
19477 * @name:  the name of the attribute
19478 *
19479 *
19480 * Schema Component Constraint:
19481 *    Attribute Declaration Properties Correct (a-props-correct)
19482 *
19483 * Validates the value constraints of an attribute declaration/use.
19484 * NOTE that this needs the simle type definitions to be already
19485 *   builded and checked.
19486 */
19487static int
19488xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19489			       xmlSchemaAttributePtr attr)
19490{
19491
19492    /*
19493    * SPEC a-props-correct (1)
19494    * "The values of the properties of an attribute declaration must
19495    * be as described in the property tableau in The Attribute
19496    * Declaration Schema Component ($3.2.1), modulo the impact of
19497    * Missing Sub-components ($5.3)."
19498    */
19499
19500    if (WXS_ATTR_TYPEDEF(attr) == NULL)
19501	return(0);
19502
19503    if (attr->defValue != NULL) {
19504	int ret;
19505
19506	/*
19507	* SPEC a-props-correct (3)
19508	* "If the {type definition} is or is derived from ID then there
19509	* must not be a {value constraint}."
19510	*/
19511	if (xmlSchemaIsDerivedFromBuiltInType(
19512	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19513	{
19514	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19515		XML_SCHEMAP_A_PROPS_CORRECT_3,
19516		NULL, WXS_BASIC_CAST attr,
19517		"Value constraints are not allowed if the type definition "
19518		"is or is derived from xs:ID",
19519		NULL, NULL);
19520	    return(pctxt->err);
19521	}
19522	/*
19523	* SPEC a-props-correct (2)
19524	* "if there is a {value constraint}, the canonical lexical
19525	* representation of its value must be `valid` with respect
19526	* to the {type definition} as defined in String Valid ($3.14.4)."
19527	* TODO: Don't care about the *canonical* stuff here, this requirement
19528	* will be removed in WXS 1.1 anyway.
19529	*/
19530	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19531	    attr->node, WXS_ATTR_TYPEDEF(attr),
19532	    attr->defValue, &(attr->defVal),
19533	    1, 1, 0);
19534	if (ret != 0) {
19535	    if (ret < 0) {
19536		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19537		    "calling xmlSchemaVCheckCVCSimpleType()");
19538		return(-1);
19539	    }
19540	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19541		XML_SCHEMAP_A_PROPS_CORRECT_2,
19542		NULL, WXS_BASIC_CAST attr,
19543		"The value of the value constraint is not valid",
19544		NULL, NULL);
19545	    return(pctxt->err);
19546	}
19547    }
19548
19549    return(0);
19550}
19551
19552static xmlSchemaElementPtr
19553xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19554				 xmlSchemaElementPtr ancestor)
19555{
19556    xmlSchemaElementPtr ret;
19557
19558    if (WXS_SUBST_HEAD(ancestor) == NULL)
19559	return (NULL);
19560    if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19561	return (ancestor);
19562
19563    if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19564	return (NULL);
19565    WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19566    ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19567	WXS_SUBST_HEAD(ancestor));
19568    WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19569
19570    return (ret);
19571}
19572
19573/**
19574 * xmlSchemaCheckElemPropsCorrect:
19575 * @ctxt:  a schema parser context
19576 * @decl: the element declaration
19577 * @name:  the name of the attribute
19578 *
19579 * Schema Component Constraint:
19580 * Element Declaration Properties Correct (e-props-correct)
19581 *
19582 * STATUS:
19583 *   missing: (6)
19584 */
19585static int
19586xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19587			       xmlSchemaElementPtr elemDecl)
19588{
19589    int ret = 0;
19590    xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19591    /*
19592    * SPEC (1) "The values of the properties of an element declaration
19593    * must be as described in the property tableau in The Element
19594    * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19595    * Sub-components ($5.3)."
19596    */
19597    if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19598	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19599
19600	xmlSchemaCheckElementDeclComponent(head, pctxt);
19601	/*
19602	* SPEC (3) "If there is a non-`absent` {substitution group
19603	* affiliation}, then {scope} must be global."
19604	*/
19605	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19606	    xmlSchemaPCustomErr(pctxt,
19607		XML_SCHEMAP_E_PROPS_CORRECT_3,
19608		WXS_BASIC_CAST elemDecl, NULL,
19609		"Only global element declarations can have a "
19610		"substitution group affiliation", NULL);
19611	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19612	}
19613	/*
19614	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19615	* That is, it must not be possible to return to an element declaration
19616	* by repeatedly following the {substitution group affiliation}
19617	* property."
19618	*/
19619	if (head == elemDecl)
19620	    circ = head;
19621	else if (WXS_SUBST_HEAD(head) != NULL)
19622	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19623	else
19624	    circ = NULL;
19625	if (circ != NULL) {
19626	    xmlChar *strA = NULL, *strB = NULL;
19627
19628	    xmlSchemaPCustomErrExt(pctxt,
19629		XML_SCHEMAP_E_PROPS_CORRECT_6,
19630		WXS_BASIC_CAST circ, NULL,
19631		"The element declaration '%s' defines a circular "
19632		"substitution group to element declaration '%s'",
19633		xmlSchemaGetComponentQName(&strA, circ),
19634		xmlSchemaGetComponentQName(&strB, head),
19635		NULL);
19636	    FREE_AND_NULL(strA)
19637	    FREE_AND_NULL(strB)
19638	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19639	}
19640	/*
19641	* SPEC (4) "If there is a {substitution group affiliation},
19642	* the {type definition}
19643	* of the element declaration must be validly derived from the {type
19644	* definition} of the {substitution group affiliation}, given the value
19645	* of the {substitution group exclusions} of the {substitution group
19646	* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19647	* (if the {type definition} is complex) or as defined in
19648	* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19649	* simple)."
19650	*
19651	* NOTE: {substitution group exclusions} means the values of the
19652	* attribute "final".
19653	*/
19654
19655	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19656	    int set = 0;
19657
19658	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19659		set |= SUBSET_EXTENSION;
19660	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19661		set |= SUBSET_RESTRICTION;
19662
19663	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19664		WXS_ELEM_TYPEDEF(head), set) != 0) {
19665		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19666
19667		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19668		xmlSchemaPCustomErrExt(pctxt,
19669		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19670		    WXS_BASIC_CAST elemDecl, NULL,
19671		    "The type definition '%s' was "
19672		    "either rejected by the substitution group "
19673		    "affiliation '%s', or not validly derived from its type "
19674		    "definition '%s'",
19675		    xmlSchemaGetComponentQName(&strA, typeDef),
19676		    xmlSchemaGetComponentQName(&strB, head),
19677		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19678		FREE_AND_NULL(strA)
19679		FREE_AND_NULL(strB)
19680		FREE_AND_NULL(strC)
19681	    }
19682	}
19683    }
19684    /*
19685    * SPEC (5) "If the {type definition} or {type definition}'s
19686    * {content type}
19687    * is or is derived from ID then there must not be a {value constraint}.
19688    * Note: The use of ID as a type definition for elements goes beyond
19689    * XML 1.0, and should be avoided if backwards compatibility is desired"
19690    */
19691    if ((elemDecl->value != NULL) &&
19692	((WXS_IS_SIMPLE(typeDef) &&
19693	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19694	 (WXS_IS_COMPLEX(typeDef) &&
19695	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19696	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19697	    XML_SCHEMAS_ID)))) {
19698
19699	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19700	xmlSchemaPCustomErr(pctxt,
19701	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19702	    WXS_BASIC_CAST elemDecl, NULL,
19703	    "The type definition (or type definition's content type) is or "
19704	    "is derived from ID; value constraints are not allowed in "
19705	    "conjunction with such a type definition", NULL);
19706    } else if (elemDecl->value != NULL) {
19707	int vcret;
19708	xmlNodePtr node = NULL;
19709
19710	/*
19711	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19712	* representation of its value must be `valid` with respect to the
19713	* {type definition} as defined in Element Default Valid (Immediate)
19714	* ($3.3.6)."
19715	*/
19716	if (typeDef == NULL) {
19717	    xmlSchemaPErr(pctxt, elemDecl->node,
19718		XML_SCHEMAP_INTERNAL,
19719		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19720		"type is missing... skipping validation of "
19721		"the value constraint", NULL, NULL);
19722	    return (-1);
19723	}
19724	if (elemDecl->node != NULL) {
19725	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19726		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19727		    BAD_CAST "fixed");
19728	    else
19729		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19730		    BAD_CAST "default");
19731	}
19732	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19733	    typeDef, elemDecl->value, &(elemDecl->defVal));
19734	if (vcret != 0) {
19735	    if (vcret < 0) {
19736		PERROR_INT("xmlSchemaElemCheckValConstr",
19737		    "failed to validate the value constraint of an "
19738		    "element declaration");
19739		return (-1);
19740	    }
19741	    return (vcret);
19742	}
19743    }
19744
19745    return (ret);
19746}
19747
19748/**
19749 * xmlSchemaCheckElemSubstGroup:
19750 * @ctxt:  a schema parser context
19751 * @decl: the element declaration
19752 * @name:  the name of the attribute
19753 *
19754 * Schema Component Constraint:
19755 * Substitution Group (cos-equiv-class)
19756 *
19757 * In Libxml2 the subst. groups will be precomputed, in terms of that
19758 * a list will be built for each subst. group head, holding all direct
19759 * referents to this head.
19760 * NOTE that this function needs:
19761 *   1. circular subst. groups to be checked beforehand
19762 *   2. the declaration's type to be derived from the head's type
19763 *
19764 * STATUS:
19765 *
19766 */
19767static void
19768xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19769			     xmlSchemaElementPtr elemDecl)
19770{
19771    if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19772	/* SPEC (1) "Its {abstract} is false." */
19773	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19774	return;
19775    {
19776	xmlSchemaElementPtr head;
19777	xmlSchemaTypePtr headType, type;
19778	int set, methSet;
19779	/*
19780	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19781	* {disallowed substitutions} as the blocking constraint, as defined in
19782	* Substitution Group OK (Transitive) ($3.3.6)."
19783	*/
19784	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19785	    head = WXS_SUBST_HEAD(head)) {
19786	    set = 0;
19787	    methSet = 0;
19788	    /*
19789	    * The blocking constraints.
19790	    */
19791	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19792		continue;
19793	    headType = head->subtypes;
19794	    type = elemDecl->subtypes;
19795	    if (headType == type)
19796		goto add_member;
19797	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19798		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19799	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19800		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19801	    /*
19802	    * SPEC: Substitution Group OK (Transitive) (2.3)
19803	    * "The set of all {derivation method}s involved in the
19804	    * derivation of D's {type definition} from C's {type definition}
19805	    * does not intersect with the union of the blocking constraint,
19806	    * C's {prohibited substitutions} (if C is complex, otherwise the
19807	    * empty set) and the {prohibited substitutions} (respectively the
19808	    * empty set) of any intermediate {type definition}s in the
19809	    * derivation of D's {type definition} from C's {type definition}."
19810	    */
19811	    /*
19812	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19813	    * subst.head axis, the methSet does not need to be computed for
19814	    * the full depth over and over.
19815	    */
19816	    /*
19817	    * The set of all {derivation method}s involved in the derivation
19818	    */
19819	    while ((type != NULL) && (type != headType)) {
19820		if ((WXS_IS_EXTENSION(type)) &&
19821		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19822		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19823
19824		if (WXS_IS_RESTRICTION(type) &&
19825		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19826		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19827
19828		type = type->baseType;
19829	    }
19830	    /*
19831	    * The {prohibited substitutions} of all intermediate types +
19832	    * the head's type.
19833	    */
19834	    type = elemDecl->subtypes->baseType;
19835	    while (type != NULL) {
19836		if (WXS_IS_COMPLEX(type)) {
19837		    if ((type->flags &
19838			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19839			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19840		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19841		    if ((type->flags &
19842			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19843			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19844		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19845		} else
19846		    break;
19847		if (type == headType)
19848		    break;
19849		type = type->baseType;
19850	    }
19851	    if ((set != 0) &&
19852		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19853		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19854		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19855		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19856		continue;
19857	    }
19858add_member:
19859	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19860	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19861		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19862	}
19863    }
19864}
19865
19866#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19867/**
19868 * xmlSchemaCheckElementDeclComponent
19869 * @pctxt: the schema parser context
19870 * @ctxtComponent: the context component (an element declaration)
19871 * @ctxtParticle: the first particle of the context component
19872 * @searchParticle: the element declaration particle to be analysed
19873 *
19874 * Schema Component Constraint: Element Declarations Consistent
19875 */
19876static int
19877xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19878				    xmlSchemaBasicItemPtr ctxtComponent,
19879				    xmlSchemaParticlePtr ctxtParticle,
19880				    xmlSchemaParticlePtr searchParticle,
19881				    xmlSchemaParticlePtr curParticle,
19882				    int search)
19883{
19884    return(0);
19885
19886    int ret = 0;
19887    xmlSchemaParticlePtr cur = curParticle;
19888    if (curParticle == NULL) {
19889	return(0);
19890    }
19891    if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19892	/*
19893	* Just return in this case. A missing "term" of the particle
19894	* might arise due to an invalid "term" component.
19895	*/
19896	return(0);
19897    }
19898    while (cur != NULL) {
19899	switch (WXS_PARTICLE_TERM(cur)->type) {
19900	    case XML_SCHEMA_TYPE_ANY:
19901		break;
19902	    case XML_SCHEMA_TYPE_ELEMENT:
19903		if (search == 0) {
19904		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19905			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19906		    if (ret != 0)
19907			return(ret);
19908		} else {
19909		    xmlSchemaElementPtr elem =
19910			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19911		    /*
19912		    * SPEC Element Declarations Consistent:
19913		    * "If the {particles} contains, either directly,
19914		    * indirectly (that is, within the {particles} of a
19915		    * contained model group, recursively) or `implicitly`
19916		    * two or more element declaration particles with
19917		    * the same {name} and {target namespace}, then
19918		    * all their type definitions must be the same
19919		    * top-level definition [...]"
19920		    */
19921		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19922			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19923			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19924			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19925		    {
19926			xmlChar *strA = NULL, *strB = NULL;
19927
19928			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19929			    /* TODO: error code */
19930			    XML_SCHEMAP_COS_NONAMBIG,
19931			    WXS_ITEM_NODE(cur), NULL,
19932			    "In the content model of %s, there are multiple "
19933			    "element declarations for '%s' with different "
19934			    "type definitions",
19935			    xmlSchemaGetComponentDesignation(&strA,
19936				ctxtComponent),
19937			    xmlSchemaFormatQName(&strB,
19938				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19939				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19940			FREE_AND_NULL(strA);
19941			FREE_AND_NULL(strB);
19942			return(XML_SCHEMAP_COS_NONAMBIG);
19943		    }
19944		}
19945		break;
19946	    case XML_SCHEMA_TYPE_SEQUENCE: {
19947		break;
19948		}
19949	    case XML_SCHEMA_TYPE_CHOICE:{
19950		/*
19951		xmlSchemaTreeItemPtr sub;
19952
19953		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19954		while (sub != NULL) {
19955		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19956			ctxtParticle, ctxtElem);
19957		    if (ret != 0)
19958			return(ret);
19959		    sub = sub->next;
19960		}
19961		*/
19962		break;
19963		}
19964	    case XML_SCHEMA_TYPE_ALL:
19965		break;
19966	    case XML_SCHEMA_TYPE_GROUP:
19967		break;
19968	    default:
19969		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19970		    "xmlSchemaCheckElementDeclConsistent",
19971		    "found unexpected term of type '%s' in content model",
19972		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19973		return(-1);
19974	}
19975	cur = (xmlSchemaParticlePtr) cur->next;
19976    }
19977
19978exit:
19979    return(ret);
19980}
19981#endif
19982
19983/**
19984 * xmlSchemaCheckElementDeclComponent
19985 * @item:  an schema element declaration/particle
19986 * @ctxt:  a schema parser context
19987 * @name:  the name of the attribute
19988 *
19989 * Validates the value constraints of an element declaration.
19990 * Adds substitution group members.
19991 */
19992static void
19993xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19994				   xmlSchemaParserCtxtPtr ctxt)
19995{
19996    if (elemDecl == NULL)
19997	return;
19998    if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19999	return;
20000    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20001    if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20002	/*
20003	* Adds substitution group members.
20004	*/
20005	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20006    }
20007}
20008
20009/**
20010 * xmlSchemaResolveModelGroupParticleReferences:
20011 * @particle:  a particle component
20012 * @ctxt:  a parser context
20013 *
20014 * Resolves references of a model group's {particles} to
20015 * model group definitions and to element declarations.
20016 */
20017static void
20018xmlSchemaResolveModelGroupParticleReferences(
20019    xmlSchemaParserCtxtPtr ctxt,
20020    xmlSchemaModelGroupPtr mg)
20021{
20022    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20023    xmlSchemaQNameRefPtr ref;
20024    xmlSchemaBasicItemPtr refItem;
20025
20026    /*
20027    * URGENT TODO: Test this.
20028    */
20029    while (particle != NULL) {
20030	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20031	    ((WXS_PARTICLE_TERM(particle))->type !=
20032		XML_SCHEMA_EXTRA_QNAMEREF))
20033	{
20034	    goto next_particle;
20035	}
20036	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20037	/*
20038	* Resolve the reference.
20039	* NULL the {term} by default.
20040	*/
20041	particle->children = NULL;
20042
20043	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20044	    ref->itemType, ref->name, ref->targetNamespace);
20045	if (refItem == NULL) {
20046	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20047		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20048		ref->targetNamespace, ref->itemType, NULL);
20049	    /* TODO: remove the particle. */
20050	    goto next_particle;
20051	}
20052	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20053	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20054		/* TODO: remove the particle. */
20055		goto next_particle;
20056	    /*
20057	    * NOTE that we will assign the model group definition
20058	    * itself to the "term" of the particle. This will ease
20059	    * the check for circular model group definitions. After
20060	    * that the "term" will be assigned the model group of the
20061	    * model group definition.
20062	    */
20063	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20064		    XML_SCHEMA_TYPE_ALL) {
20065		/*
20066		* SPEC cos-all-limited (1)
20067		* SPEC cos-all-limited (1.2)
20068		* "It appears only as the value of one or both of the
20069		* following properties:"
20070		* (1.1) "the {model group} property of a model group
20071		*        definition."
20072		* (1.2) "the {term} property of a particle [... of] the "
20073		* {content type} of a complex type definition."
20074		*/
20075		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20076		    /* TODO: error code */
20077		    XML_SCHEMAP_COS_ALL_LIMITED,
20078		    WXS_ITEM_NODE(particle), NULL,
20079		    "A model group definition is referenced, but "
20080		    "it contains an 'all' model group, which "
20081		    "cannot be contained by model groups",
20082		    NULL, NULL);
20083		/* TODO: remove the particle. */
20084		goto next_particle;
20085	    }
20086	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20087	} else {
20088	    /*
20089	    * TODO: Are referenced element declarations the only
20090	    * other components we expect here?
20091	    */
20092	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20093	}
20094next_particle:
20095	particle = WXS_PTC_CAST particle->next;
20096    }
20097}
20098
20099static int
20100xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20101		       xmlSchemaValPtr y)
20102{
20103    xmlSchemaTypePtr tx, ty, ptx, pty;
20104    int ret;
20105
20106    while (x != NULL) {
20107	/* Same types. */
20108	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20109	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20110	ptx = xmlSchemaGetPrimitiveType(tx);
20111	pty = xmlSchemaGetPrimitiveType(ty);
20112	/*
20113	* (1) if a datatype T' is `derived` by `restriction` from an
20114	* atomic datatype T then the `value space` of T' is a subset of
20115	* the `value space` of T. */
20116	/*
20117	* (2) if datatypes T' and T'' are `derived` by `restriction`
20118	* from a common atomic ancestor T then the `value space`s of T'
20119	* and T'' may overlap.
20120	*/
20121	if (ptx != pty)
20122	    return(0);
20123	/*
20124	* We assume computed values to be normalized, so do a fast
20125	* string comparison for string based types.
20126	*/
20127	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20128	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20129	    if (! xmlStrEqual(
20130		xmlSchemaValueGetAsString(x),
20131		xmlSchemaValueGetAsString(y)))
20132		return (0);
20133	} else {
20134	    ret = xmlSchemaCompareValuesWhtsp(
20135		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20136		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20137	    if (ret == -2)
20138		return(-1);
20139	    if (ret != 0)
20140		return(0);
20141	}
20142	/*
20143	* Lists.
20144	*/
20145	x = xmlSchemaValueGetNext(x);
20146	if (x != NULL) {
20147	    y = xmlSchemaValueGetNext(y);
20148	    if (y == NULL)
20149		return (0);
20150	} else if (xmlSchemaValueGetNext(y) != NULL)
20151	    return (0);
20152	else
20153	    return (1);
20154    }
20155    return (0);
20156}
20157
20158/**
20159 * xmlSchemaResolveAttrUseReferences:
20160 * @item:  an attribute use
20161 * @ctxt:  a parser context
20162 *
20163 * Resolves the referenced attribute declaration.
20164 */
20165static int
20166xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20167				  xmlSchemaParserCtxtPtr ctxt)
20168{
20169    if ((ctxt == NULL) || (ause == NULL))
20170	return(-1);
20171    if ((ause->attrDecl == NULL) ||
20172	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20173	return(0);
20174
20175    {
20176	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20177
20178	/*
20179	* TODO: Evaluate, what errors could occur if the declaration is not
20180	* found.
20181	*/
20182	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20183	    ref->name, ref->targetNamespace);
20184        if (ause->attrDecl == NULL) {
20185	    xmlSchemaPResCompAttrErr(ctxt,
20186		XML_SCHEMAP_SRC_RESOLVE,
20187		WXS_BASIC_CAST ause, ause->node,
20188		"ref", ref->name, ref->targetNamespace,
20189		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20190            return(ctxt->err);;
20191        }
20192    }
20193    return(0);
20194}
20195
20196/**
20197 * xmlSchemaCheckAttrUsePropsCorrect:
20198 * @ctxt:  a parser context
20199 * @use:  an attribute use
20200 *
20201 * Schema Component Constraint:
20202 * Attribute Use Correct (au-props-correct)
20203 *
20204 */
20205static int
20206xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20207			     xmlSchemaAttributeUsePtr use)
20208{
20209    if ((ctxt == NULL) || (use == NULL))
20210	return(-1);
20211    if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20212	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20213	return(0);
20214
20215    /*
20216    * SPEC au-props-correct (1)
20217    * "The values of the properties of an attribute use must be as
20218    * described in the property tableau in The Attribute Use Schema
20219    * Component ($3.5.1), modulo the impact of Missing
20220    * Sub-components ($5.3)."
20221    */
20222
20223    if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20224	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20225        ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20226    {
20227	xmlSchemaPCustomErr(ctxt,
20228	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20229	    WXS_BASIC_CAST use, NULL,
20230	    "The attribute declaration has a 'fixed' value constraint "
20231	    ", thus the attribute use must also have a 'fixed' value "
20232	    "constraint",
20233	    NULL);
20234	return(ctxt->err);
20235    }
20236    /*
20237    * Compute and check the value constraint's value.
20238    */
20239    if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20240	int ret;
20241	/*
20242	* TODO: The spec seems to be missing a check of the
20243	* value constraint of the attribute use. We will do it here.
20244	*/
20245	/*
20246	* SPEC a-props-correct (3)
20247	*/
20248	if (xmlSchemaIsDerivedFromBuiltInType(
20249	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20250	{
20251	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20252		XML_SCHEMAP_AU_PROPS_CORRECT,
20253		NULL, WXS_BASIC_CAST use,
20254		"Value constraints are not allowed if the type definition "
20255		"is or is derived from xs:ID",
20256		NULL, NULL);
20257	    return(ctxt->err);
20258	}
20259
20260	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20261	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20262	    use->defValue, &(use->defVal),
20263	    1, 1, 0);
20264	if (ret != 0) {
20265	    if (ret < 0) {
20266		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20267		    "calling xmlSchemaVCheckCVCSimpleType()");
20268		return(-1);
20269	    }
20270	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20271		XML_SCHEMAP_AU_PROPS_CORRECT,
20272		NULL, WXS_BASIC_CAST use,
20273		"The value of the value constraint is not valid",
20274		NULL, NULL);
20275	    return(ctxt->err);
20276	}
20277    }
20278    /*
20279    * SPEC au-props-correct (2)
20280    * "If the {attribute declaration} has a fixed
20281    * {value constraint}, then if the attribute use itself has a
20282    * {value constraint}, it must also be fixed and its value must match
20283    * that of the {attribute declaration}'s {value constraint}."
20284    */
20285    if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20286	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20287    {
20288	if (! xmlSchemaAreValuesEqual(use->defVal,
20289		(WXS_ATTRUSE_DECL(use))->defVal))
20290	{
20291	    xmlSchemaPCustomErr(ctxt,
20292		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20293		WXS_BASIC_CAST use, NULL,
20294		"The 'fixed' value constraint of the attribute use "
20295		"must match the attribute declaration's value "
20296		"constraint '%s'",
20297		(WXS_ATTRUSE_DECL(use))->defValue);
20298	}
20299	return(ctxt->err);
20300    }
20301    return(0);
20302}
20303
20304
20305
20306
20307/**
20308 * xmlSchemaResolveAttrTypeReferences:
20309 * @item:  an attribute declaration
20310 * @ctxt:  a parser context
20311 *
20312 * Resolves the referenced type definition component.
20313 */
20314static int
20315xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20316				   xmlSchemaParserCtxtPtr ctxt)
20317{
20318    /*
20319    * The simple type definition corresponding to the <simpleType> element
20320    * information item in the [children], if present, otherwise the simple
20321    * type definition `resolved` to by the `actual value` of the type
20322    * [attribute], if present, otherwise the `simple ur-type definition`.
20323    */
20324    if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20325	return(0);
20326    item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20327    if (item->subtypes != NULL)
20328        return(0);
20329    if (item->typeName != NULL) {
20330        xmlSchemaTypePtr type;
20331
20332	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20333	    item->typeNs);
20334	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20335	    xmlSchemaPResCompAttrErr(ctxt,
20336		XML_SCHEMAP_SRC_RESOLVE,
20337		WXS_BASIC_CAST item, item->node,
20338		"type", item->typeName, item->typeNs,
20339		XML_SCHEMA_TYPE_SIMPLE, NULL);
20340	    return(ctxt->err);
20341	} else
20342	    item->subtypes = type;
20343
20344    } else {
20345	/*
20346	* The type defaults to the xs:anySimpleType.
20347	*/
20348	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20349    }
20350    return(0);
20351}
20352
20353/**
20354 * xmlSchemaResolveIDCKeyReferences:
20355 * @idc:  the identity-constraint definition
20356 * @ctxt:  the schema parser context
20357 * @name:  the attribute name
20358 *
20359 * Resolve keyRef references to key/unique IDCs.
20360 * Schema Component Constraint:
20361 *   Identity-constraint Definition Properties Correct (c-props-correct)
20362 */
20363static int
20364xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20365			  xmlSchemaParserCtxtPtr pctxt)
20366{
20367    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20368        return(0);
20369    if (idc->ref->name != NULL) {
20370	idc->ref->item = (xmlSchemaBasicItemPtr)
20371	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20372		idc->ref->targetNamespace);
20373        if (idc->ref->item == NULL) {
20374	    /*
20375	    * TODO: It is actually not an error to fail to resolve
20376	    * at this stage. BUT we need to be that strict!
20377	    */
20378	    xmlSchemaPResCompAttrErr(pctxt,
20379		XML_SCHEMAP_SRC_RESOLVE,
20380		WXS_BASIC_CAST idc, idc->node,
20381		"refer", idc->ref->name,
20382		idc->ref->targetNamespace,
20383		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20384            return(pctxt->err);
20385	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20386	    /*
20387	    * SPEC c-props-correct (1)
20388	    */
20389	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20390		XML_SCHEMAP_C_PROPS_CORRECT,
20391		NULL, WXS_BASIC_CAST idc,
20392		"The keyref references a keyref",
20393		NULL, NULL);
20394	    idc->ref->item = NULL;
20395	    return(pctxt->err);
20396	} else {
20397	    if (idc->nbFields !=
20398		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20399		xmlChar *str = NULL;
20400		xmlSchemaIDCPtr refer;
20401
20402		refer = (xmlSchemaIDCPtr) idc->ref->item;
20403		/*
20404		* SPEC c-props-correct(2)
20405		* "If the {identity-constraint category} is keyref,
20406		* the cardinality of the {fields} must equal that of
20407		* the {fields} of the {referenced key}.
20408		*/
20409		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20410		    XML_SCHEMAP_C_PROPS_CORRECT,
20411		    NULL, WXS_BASIC_CAST idc,
20412		    "The cardinality of the keyref differs from the "
20413		    "cardinality of the referenced key/unique '%s'",
20414		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20415			refer->name),
20416		    NULL);
20417		FREE_AND_NULL(str)
20418		return(pctxt->err);
20419	    }
20420	}
20421    }
20422    return(0);
20423}
20424
20425static int
20426xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20427				       xmlSchemaParserCtxtPtr pctxt)
20428{
20429    if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20430	prohib->targetNamespace) == NULL) {
20431
20432	xmlSchemaPResCompAttrErr(pctxt,
20433	    XML_SCHEMAP_SRC_RESOLVE,
20434	    NULL, prohib->node,
20435	    "ref", prohib->name, prohib->targetNamespace,
20436	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20437	return(XML_SCHEMAP_SRC_RESOLVE);
20438    }
20439    return(0);
20440}
20441
20442#define WXS_REDEFINED_TYPE(c) \
20443(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20444
20445#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20446(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20447
20448#define WXS_REDEFINED_ATTR_GROUP(c) \
20449(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20450
20451static int
20452xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20453{
20454    int err = 0;
20455    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20456    xmlSchemaBasicItemPtr prev, item;
20457    int wasRedefined;
20458
20459    if (redef == NULL)
20460	return(0);
20461
20462    do {
20463	item = redef->item;
20464	/*
20465	* First try to locate the redefined component in the
20466	* schema graph starting with the redefined schema.
20467	* NOTE: According to this schema bug entry:
20468	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20469	*   it's not clear if the referenced component needs to originate
20470	*   from the <redefine>d schema _document_ or the schema; the latter
20471	*   would include all imported and included sub-schemas of the
20472	*   <redefine>d schema. Currenlty we latter approach is used.
20473	*   SUPPLEMENT: It seems that the WG moves towards the latter
20474	*   approach, so we are doing it right.
20475	*
20476	*/
20477	prev = xmlSchemaFindRedefCompInGraph(
20478	    redef->targetBucket, item->type,
20479	    redef->refName, redef->refTargetNs);
20480	if (prev == NULL) {
20481	    xmlChar *str = NULL;
20482	    xmlNodePtr node;
20483
20484	    /*
20485	    * SPEC src-redefine:
20486	    * (6.2.1) "The `actual value` of its own name attribute plus
20487	    * target namespace must successfully `resolve` to a model
20488	    * group definition in I."
20489	    * (7.2.1) "The `actual value` of its own name attribute plus
20490	    * target namespace must successfully `resolve` to an attribute
20491	    * group definition in I."
20492
20493	    *
20494	    * Note that, if we are redefining with the use of references
20495	    * to components, the spec assumes the src-resolve to be used;
20496	    * but this won't assure that we search only *inside* the
20497	    * redefined schema.
20498	    */
20499	    if (redef->reference)
20500		node = WXS_ITEM_NODE(redef->reference);
20501	    else
20502		node = WXS_ITEM_NODE(item);
20503	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20504		/*
20505		* TODO: error code.
20506		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20507		* reference kind.
20508		*/
20509		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20510		"The %s '%s' to be redefined could not be found in "
20511		"the redefined schema",
20512		WXS_ITEM_TYPE_NAME(item),
20513		xmlSchemaFormatQName(&str, redef->refTargetNs,
20514		    redef->refName));
20515	    FREE_AND_NULL(str);
20516	    err = pctxt->err;
20517	    redef = redef->next;
20518	    continue;
20519	}
20520	/*
20521	* TODO: Obtaining and setting the redefinition state is really
20522	* clumsy.
20523	*/
20524	wasRedefined = 0;
20525	switch (item->type) {
20526	    case XML_SCHEMA_TYPE_COMPLEX:
20527	    case XML_SCHEMA_TYPE_SIMPLE:
20528		if ((WXS_TYPE_CAST prev)->flags &
20529		    XML_SCHEMAS_TYPE_REDEFINED)
20530		{
20531		    wasRedefined = 1;
20532		    break;
20533		}
20534		/* Mark it as redefined. */
20535		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20536		/*
20537		* Assign the redefined type to the
20538		* base type of the redefining type.
20539		* TODO: How
20540		*/
20541		((xmlSchemaTypePtr) item)->baseType =
20542		    (xmlSchemaTypePtr) prev;
20543		break;
20544	    case XML_SCHEMA_TYPE_GROUP:
20545		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20546		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20547		{
20548		    wasRedefined = 1;
20549		    break;
20550		}
20551		/* Mark it as redefined. */
20552		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20553		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20554		if (redef->reference != NULL) {
20555		    /*
20556		    * Overwrite the QName-reference with the
20557		    * referenced model group def.
20558		    */
20559		    (WXS_PTC_CAST redef->reference)->children =
20560			WXS_TREE_CAST prev;
20561		}
20562		redef->target = prev;
20563		break;
20564	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20565		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20566		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20567		{
20568		    wasRedefined = 1;
20569		    break;
20570		}
20571		(WXS_ATTR_GROUP_CAST prev)->flags |=
20572		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20573		if (redef->reference != NULL) {
20574		    /*
20575		    * Assign the redefined attribute group to the
20576		    * QName-reference component.
20577		    * This is the easy case, since we will just
20578		    * expand the redefined group.
20579		    */
20580		    (WXS_QNAME_CAST redef->reference)->item = prev;
20581		    redef->target = NULL;
20582		} else {
20583		    /*
20584		    * This is the complicated case: we need
20585		    * to apply src-redefine (7.2.2) at a later
20586		    * stage, i.e. when attribute group references
20587		    * have beed expanded and simple types have
20588		    * beed fixed.
20589		    */
20590		    redef->target = prev;
20591		}
20592		break;
20593	    default:
20594		PERROR_INT("xmlSchemaResolveRedefReferences",
20595		    "Unexpected redefined component type");
20596		return(-1);
20597	}
20598	if (wasRedefined) {
20599	    xmlChar *str = NULL;
20600	    xmlNodePtr node;
20601
20602	    if (redef->reference)
20603		node = WXS_ITEM_NODE(redef->reference);
20604	    else
20605		node = WXS_ITEM_NODE(redef->item);
20606
20607	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20608		/* TODO: error code. */
20609		XML_SCHEMAP_SRC_REDEFINE,
20610		node, NULL,
20611		"The referenced %s was already redefined. Multiple "
20612		"redefinition of the same component is not supported",
20613		xmlSchemaGetComponentDesignation(&str, prev),
20614		NULL);
20615	    FREE_AND_NULL(str)
20616	    err = pctxt->err;
20617	    redef = redef->next;
20618	    continue;
20619	}
20620	redef = redef->next;
20621    } while (redef != NULL);
20622
20623    return(err);
20624}
20625
20626static int
20627xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20628{
20629    int err = 0;
20630    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20631    xmlSchemaBasicItemPtr item;
20632
20633    if (redef == NULL)
20634	return(0);
20635
20636    do {
20637	if (redef->target == NULL) {
20638	    redef = redef->next;
20639	    continue;
20640	}
20641	item = redef->item;
20642
20643	switch (item->type) {
20644	    case XML_SCHEMA_TYPE_SIMPLE:
20645	    case XML_SCHEMA_TYPE_COMPLEX:
20646		/*
20647		* Since the spec wants the {name} of the redefined
20648		* type to be 'absent', we'll NULL it.
20649		*/
20650		(WXS_TYPE_CAST redef->target)->name = NULL;
20651
20652		/*
20653		* TODO: Seems like there's nothing more to do. The normal
20654		* inheritance mechanism is used. But not 100% sure.
20655		*/
20656		break;
20657	    case XML_SCHEMA_TYPE_GROUP:
20658		/*
20659		* URGENT TODO:
20660		* SPEC src-redefine:
20661		* (6.2.2) "The {model group} of the model group definition
20662		* which corresponds to it per XML Representation of Model
20663		* Group Definition Schema Components ($3.7.2) must be a
20664		* `valid restriction` of the {model group} of that model
20665		* group definition in I, as defined in Particle Valid
20666		* (Restriction) ($3.9.6)."
20667		*/
20668		break;
20669	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20670		/*
20671		* SPEC src-redefine:
20672		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20673		* the attribute group definition which corresponds to it
20674		* per XML Representation of Attribute Group Definition Schema
20675		* Components ($3.6.2) must be `valid restrictions` of the
20676		* {attribute uses} and {attribute wildcard} of that attribute
20677		* group definition in I, as defined in clause 2, clause 3 and
20678		* clause 4 of Derivation Valid (Restriction, Complex)
20679		* ($3.4.6) (where references to the base type definition are
20680		* understood as references to the attribute group definition
20681		* in I)."
20682		*/
20683		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20684		    XML_SCHEMA_ACTION_REDEFINE,
20685		    item, redef->target,
20686		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20687		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20688		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20689		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20690		if (err == -1)
20691		    return(-1);
20692		break;
20693	    default:
20694		break;
20695	}
20696	redef = redef->next;
20697    } while (redef != NULL);
20698    return(0);
20699}
20700
20701
20702static int
20703xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20704		       xmlSchemaBucketPtr bucket)
20705{
20706    xmlSchemaBasicItemPtr item;
20707    int err;
20708    xmlHashTablePtr *table;
20709    const xmlChar *name;
20710    int i;
20711
20712#define WXS_GET_GLOBAL_HASH(c, slot) { \
20713    if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20714	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20715    else \
20716	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20717
20718    /*
20719    * Add global components to the schema's hash tables.
20720    * This is the place where duplicate components will be
20721    * detected.
20722    * TODO: I think normally we should support imports of the
20723    *   same namespace from multiple locations. We don't do currently,
20724    *   but if we do then according to:
20725    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20726    *   we would need, if imported directly, to import redefined
20727    *   components as well to be able to catch clashing components.
20728    *   (I hope I'll still know what this means after some months :-()
20729    */
20730    if (bucket == NULL)
20731	return(-1);
20732    if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20733	return(0);
20734    bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20735
20736    for (i = 0; i < bucket->globals->nbItems; i++) {
20737	item = bucket->globals->items[i];
20738	table = NULL;
20739	switch (item->type) {
20740	    case XML_SCHEMA_TYPE_COMPLEX:
20741	    case XML_SCHEMA_TYPE_SIMPLE:
20742		if (WXS_REDEFINED_TYPE(item))
20743		    continue;
20744		name = (WXS_TYPE_CAST item)->name;
20745		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20746		break;
20747	    case XML_SCHEMA_TYPE_ELEMENT:
20748		name = (WXS_ELEM_CAST item)->name;
20749		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20750		break;
20751	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20752		name = (WXS_ATTR_CAST item)->name;
20753		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20754		break;
20755	    case XML_SCHEMA_TYPE_GROUP:
20756		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20757		    continue;
20758		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20759		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20760		break;
20761	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20762		if (WXS_REDEFINED_ATTR_GROUP(item))
20763		    continue;
20764		name = (WXS_ATTR_GROUP_CAST item)->name;
20765		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20766		break;
20767	    case XML_SCHEMA_TYPE_IDC_KEY:
20768	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20769	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20770		name = (WXS_IDC_CAST item)->name;
20771		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20772		break;
20773	    case XML_SCHEMA_TYPE_NOTATION:
20774		name = ((xmlSchemaNotationPtr) item)->name;
20775		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20776		break;
20777	    default:
20778		PERROR_INT("xmlSchemaAddComponents",
20779		    "Unexpected global component type");
20780		continue;
20781	}
20782	if (*table == NULL) {
20783	    *table = xmlHashCreateDict(10, pctxt->dict);
20784	    if (*table == NULL) {
20785		PERROR_INT("xmlSchemaAddComponents",
20786		    "failed to create a component hash table");
20787		return(-1);
20788	    }
20789	}
20790	err = xmlHashAddEntry(*table, name, item);
20791	if (err != 0) {
20792	    xmlChar *str = NULL;
20793
20794	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20795		XML_SCHEMAP_REDEFINED_TYPE,
20796		WXS_ITEM_NODE(item),
20797		WXS_BASIC_CAST item,
20798		"A global %s '%s' does already exist",
20799		WXS_ITEM_TYPE_NAME(item),
20800		xmlSchemaGetComponentQName(&str, item));
20801	    FREE_AND_NULL(str);
20802	}
20803    }
20804    /*
20805    * Process imported/included schemas.
20806    */
20807    if (bucket->relations != NULL) {
20808	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20809	do {
20810	    if ((rel->bucket != NULL) &&
20811		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20812		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20813		    return(-1);
20814	    }
20815	    rel = rel->next;
20816	} while (rel != NULL);
20817    }
20818    return(0);
20819}
20820
20821static int
20822xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20823			 xmlSchemaBucketPtr rootBucket)
20824{
20825    xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20826    xmlSchemaTreeItemPtr item, *items;
20827    int nbItems, i, ret = 0;
20828    xmlSchemaBucketPtr oldbucket = con->bucket;
20829    xmlSchemaElementPtr elemDecl;
20830
20831#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20832
20833    if ((con->pending == NULL) ||
20834	(con->pending->nbItems == 0))
20835	return(0);
20836
20837    /*
20838    * Since xmlSchemaFixupComplexType() will create new particles
20839    * (local components), and those particle components need a bucket
20840    * on the constructor, we'll assure here that the constructor has
20841    * a bucket.
20842    * TODO: Think about storing locals _only_ on the main bucket.
20843    */
20844    if (con->bucket == NULL)
20845	con->bucket = rootBucket;
20846
20847    /* TODO:
20848    * SPEC (src-redefine):
20849    * (6.2) "If it has no such self-reference, then all of the
20850    * following must be true:"
20851
20852    * (6.2.2) The {model group} of the model group definition which
20853    * corresponds to it per XML Representation of Model Group
20854    * Definition Schema Components ($3.7.2) must be a `valid
20855    * restriction` of the {model group} of that model group definition
20856    * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20857    */
20858    xmlSchemaCheckSRCRedefineFirst(pctxt);
20859
20860    /*
20861    * Add global components to the schemata's hash tables.
20862    */
20863    xmlSchemaAddComponents(pctxt, rootBucket);
20864
20865    pctxt->ctxtType = NULL;
20866    items = (xmlSchemaTreeItemPtr *) con->pending->items;
20867    nbItems = con->pending->nbItems;
20868    /*
20869    * Now that we have parsed *all* the schema document(s) and converted
20870    * them to schema components, we can resolve references, apply component
20871    * constraints, create the FSA from the content model, etc.
20872    */
20873    /*
20874    * Resolve references of..
20875    *
20876    * 1. element declarations:
20877    *   - the type definition
20878    *   - the substitution group affiliation
20879    * 2. simple/complex types:
20880    *   - the base type definition
20881    *   - the memberTypes of union types
20882    *   - the itemType of list types
20883    * 3. attributes declarations and attribute uses:
20884    *   - the type definition
20885    *   - if an attribute use, then the attribute declaration
20886    * 4. attribute group references:
20887    *   - the attribute group definition
20888    * 5. particles:
20889    *   - the term of the particle (e.g. a model group)
20890    * 6. IDC key-references:
20891    *   - the referenced IDC 'key' or 'unique' definition
20892    * 7. Attribute prohibitions which had a "ref" attribute.
20893    */
20894    for (i = 0; i < nbItems; i++) {
20895	item = items[i];
20896	switch (item->type) {
20897	    case XML_SCHEMA_TYPE_ELEMENT:
20898		xmlSchemaResolveElementReferences(
20899		    (xmlSchemaElementPtr) item, pctxt);
20900		FIXHFAILURE;
20901		break;
20902	    case XML_SCHEMA_TYPE_COMPLEX:
20903	    case XML_SCHEMA_TYPE_SIMPLE:
20904		xmlSchemaResolveTypeReferences(
20905		    (xmlSchemaTypePtr) item, pctxt);
20906		FIXHFAILURE;
20907		break;
20908	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20909		xmlSchemaResolveAttrTypeReferences(
20910		    (xmlSchemaAttributePtr) item, pctxt);
20911		FIXHFAILURE;
20912		break;
20913	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20914		xmlSchemaResolveAttrUseReferences(
20915		    (xmlSchemaAttributeUsePtr) item, pctxt);
20916		FIXHFAILURE;
20917		break;
20918	    case XML_SCHEMA_EXTRA_QNAMEREF:
20919		if ((WXS_QNAME_CAST item)->itemType ==
20920		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20921		{
20922		    xmlSchemaResolveAttrGroupReferences(
20923			WXS_QNAME_CAST item, pctxt);
20924		}
20925		FIXHFAILURE;
20926		break;
20927	    case XML_SCHEMA_TYPE_SEQUENCE:
20928	    case XML_SCHEMA_TYPE_CHOICE:
20929	    case XML_SCHEMA_TYPE_ALL:
20930		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20931		    WXS_MODEL_GROUP_CAST item);
20932		FIXHFAILURE;
20933		break;
20934	    case XML_SCHEMA_TYPE_IDC_KEY:
20935	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20936	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20937		xmlSchemaResolveIDCKeyReferences(
20938		    (xmlSchemaIDCPtr) item, pctxt);
20939		FIXHFAILURE;
20940		break;
20941	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20942		/*
20943		* Handle attribue prohibition which had a
20944		* "ref" attribute.
20945		*/
20946		xmlSchemaResolveAttrUseProhibReferences(
20947		    WXS_ATTR_PROHIB_CAST item, pctxt);
20948		FIXHFAILURE;
20949		break;
20950	    default:
20951		break;
20952	}
20953    }
20954    if (pctxt->nberrors != 0)
20955	goto exit_error;
20956
20957    /*
20958    * Now that all references are resolved we
20959    * can check for circularity of...
20960    * 1. the base axis of type definitions
20961    * 2. nested model group definitions
20962    * 3. nested attribute group definitions
20963    * TODO: check for circual substitution groups.
20964    */
20965    for (i = 0; i < nbItems; i++) {
20966	item = items[i];
20967	/*
20968	* Let's better stop on the first error here.
20969	*/
20970	switch (item->type) {
20971	    case XML_SCHEMA_TYPE_COMPLEX:
20972	    case XML_SCHEMA_TYPE_SIMPLE:
20973		xmlSchemaCheckTypeDefCircular(
20974		    (xmlSchemaTypePtr) item, pctxt);
20975		FIXHFAILURE;
20976		if (pctxt->nberrors != 0)
20977		    goto exit_error;
20978		break;
20979	    case XML_SCHEMA_TYPE_GROUP:
20980		xmlSchemaCheckGroupDefCircular(
20981		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20982		FIXHFAILURE;
20983		if (pctxt->nberrors != 0)
20984		    goto exit_error;
20985		break;
20986	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20987		xmlSchemaCheckAttrGroupCircular(
20988		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20989		FIXHFAILURE;
20990		if (pctxt->nberrors != 0)
20991		    goto exit_error;
20992		break;
20993	    default:
20994		break;
20995	}
20996    }
20997    if (pctxt->nberrors != 0)
20998	goto exit_error;
20999    /*
21000    * Model group definition references:
21001    * Such a reference is reflected by a particle at the component
21002    * level. Until now the 'term' of such particles pointed
21003    * to the model group definition; this was done, in order to
21004    * ease circularity checks. Now we need to set the 'term' of
21005    * such particles to the model group of the model group definition.
21006    */
21007    for (i = 0; i < nbItems; i++) {
21008	item = items[i];
21009	switch (item->type) {
21010	    case XML_SCHEMA_TYPE_SEQUENCE:
21011	    case XML_SCHEMA_TYPE_CHOICE:
21012		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21013		    WXS_MODEL_GROUP_CAST item);
21014		break;
21015	    default:
21016		break;
21017	}
21018    }
21019    if (pctxt->nberrors != 0)
21020	goto exit_error;
21021    /*
21022    * Expand attribute group references of attribute group definitions.
21023    */
21024    for (i = 0; i < nbItems; i++) {
21025	item = items[i];
21026	switch (item->type) {
21027            case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21028		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21029		    WXS_ATTR_GROUP_HAS_REFS(item))
21030		{
21031		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21032			WXS_ATTR_GROUP_CAST item);
21033		    FIXHFAILURE;
21034		}
21035		break;
21036	    default:
21037		break;
21038	}
21039    }
21040    if (pctxt->nberrors != 0)
21041	goto exit_error;
21042    /*
21043    * First compute the variety of simple types. This is needed as
21044    * a seperate step, since otherwise we won't be able to detect
21045    * circular union types in all cases.
21046    */
21047    for (i = 0; i < nbItems; i++) {
21048	item = items[i];
21049	switch (item->type) {
21050            case XML_SCHEMA_TYPE_SIMPLE:
21051		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21052		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21053			(xmlSchemaTypePtr) item);
21054		    FIXHFAILURE;
21055		}
21056		break;
21057	    default:
21058		break;
21059	}
21060    }
21061    if (pctxt->nberrors != 0)
21062	goto exit_error;
21063    /*
21064    * Detect circular union types. Note that this needs the variety to
21065    * be already computed.
21066    */
21067    for (i = 0; i < nbItems; i++) {
21068	item = items[i];
21069	switch (item->type) {
21070            case XML_SCHEMA_TYPE_SIMPLE:
21071		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21072		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21073			(xmlSchemaTypePtr) item);
21074		    FIXHFAILURE;
21075		}
21076		break;
21077	    default:
21078		break;
21079	}
21080    }
21081    if (pctxt->nberrors != 0)
21082	goto exit_error;
21083
21084    /*
21085    * Do the complete type fixup for simple types.
21086    */
21087    for (i = 0; i < nbItems; i++) {
21088	item = items[i];
21089	switch (item->type) {
21090            case XML_SCHEMA_TYPE_SIMPLE:
21091		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21092		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21093		    FIXHFAILURE;
21094		}
21095		break;
21096	    default:
21097		break;
21098	}
21099    }
21100    if (pctxt->nberrors != 0)
21101	goto exit_error;
21102    /*
21103    * At this point we need build and check all simple types.
21104    */
21105    /*
21106    * Apply contraints for attribute declarations.
21107    */
21108    for (i = 0; i < nbItems; i++) {
21109	item = items[i];
21110	switch (item->type) {
21111	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21112		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21113		FIXHFAILURE;
21114		break;
21115	    default:
21116		break;
21117	}
21118    }
21119    if (pctxt->nberrors != 0)
21120	goto exit_error;
21121    /*
21122    * Apply constraints for attribute uses.
21123    */
21124    for (i = 0; i < nbItems; i++) {
21125	item = items[i];
21126	switch (item->type) {
21127	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21128		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21129		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21130			WXS_ATTR_USE_CAST item);
21131		    FIXHFAILURE;
21132		}
21133		break;
21134	    default:
21135		break;
21136	}
21137    }
21138    if (pctxt->nberrors != 0)
21139	goto exit_error;
21140
21141    /*
21142    * Apply constraints for attribute group definitions.
21143    */
21144    for (i = 0; i < nbItems; i++) {
21145	item = items[i];
21146	switch (item->type) {
21147	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21148	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21149		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21150	    {
21151		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21152		FIXHFAILURE;
21153	    }
21154	    break;
21155	default:
21156	    break;
21157	}
21158    }
21159    if (pctxt->nberrors != 0)
21160	goto exit_error;
21161
21162    /*
21163    * Apply constraints for redefinitions.
21164    */
21165    if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21166	xmlSchemaCheckSRCRedefineSecond(pctxt);
21167    if (pctxt->nberrors != 0)
21168	goto exit_error;
21169
21170    /*
21171    * Complex types are builded and checked.
21172    */
21173    for (i = 0; i < nbItems; i++) {
21174	item = con->pending->items[i];
21175	switch (item->type) {
21176	    case XML_SCHEMA_TYPE_COMPLEX:
21177		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21178		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21179		    FIXHFAILURE;
21180		}
21181		break;
21182	    default:
21183		break;
21184	}
21185    }
21186    if (pctxt->nberrors != 0)
21187	goto exit_error;
21188
21189    /*
21190    * The list could have changed, since xmlSchemaFixupComplexType()
21191    * will create particles and model groups in some cases.
21192    */
21193    items = (xmlSchemaTreeItemPtr *) con->pending->items;
21194    nbItems = con->pending->nbItems;
21195
21196    /*
21197    * Apply some constraints for element declarations.
21198    */
21199    for (i = 0; i < nbItems; i++) {
21200	item = items[i];
21201	switch (item->type) {
21202	    case XML_SCHEMA_TYPE_ELEMENT:
21203		elemDecl = (xmlSchemaElementPtr) item;
21204
21205		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21206		{
21207		    xmlSchemaCheckElementDeclComponent(
21208			(xmlSchemaElementPtr) elemDecl, pctxt);
21209		    FIXHFAILURE;
21210		}
21211
21212#ifdef WXS_ELEM_DECL_CONS_ENABLED
21213		/*
21214		* Schema Component Constraint: Element Declarations Consistent
21215		* Apply this constraint to local types of element declarations.
21216		*/
21217		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21218		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21219		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21220		{
21221		    xmlSchemaCheckElementDeclConsistent(pctxt,
21222			WXS_BASIC_CAST elemDecl,
21223			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21224			NULL, NULL, 0);
21225		}
21226#endif
21227		break;
21228	    default:
21229		break;
21230	}
21231    }
21232    if (pctxt->nberrors != 0)
21233	goto exit_error;
21234
21235    /*
21236    * Finally we can build the automaton from the content model of
21237    * complex types.
21238    */
21239
21240    for (i = 0; i < nbItems; i++) {
21241	item = items[i];
21242	switch (item->type) {
21243	    case XML_SCHEMA_TYPE_COMPLEX:
21244		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21245		/* FIXHFAILURE; */
21246		break;
21247	    default:
21248		break;
21249	}
21250    }
21251    if (pctxt->nberrors != 0)
21252	goto exit_error;
21253    /*
21254    * URGENT TODO: cos-element-consistent
21255    */
21256    goto exit;
21257
21258exit_error:
21259    ret = pctxt->err;
21260    goto exit;
21261
21262exit_failure:
21263    ret = -1;
21264
21265exit:
21266    /*
21267    * Reset the constructor. This is needed for XSI acquisition, since
21268    * those items will be processed over and over again for every XSI
21269    * if not cleared here.
21270    */
21271    con->bucket = oldbucket;
21272    con->pending->nbItems = 0;
21273    if (con->substGroups != NULL) {
21274	xmlHashFree(con->substGroups,
21275	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21276	con->substGroups = NULL;
21277    }
21278    if (con->redefs != NULL) {
21279	xmlSchemaRedefListFree(con->redefs);
21280	con->redefs = NULL;
21281    }
21282    return(ret);
21283}
21284/**
21285 * xmlSchemaParse:
21286 * @ctxt:  a schema validation context
21287 *
21288 * parse a schema definition resource and build an internal
21289 * XML Shema struture which can be used to validate instances.
21290 *
21291 * Returns the internal XML Schema structure built from the resource or
21292 *         NULL in case of error
21293 */
21294xmlSchemaPtr
21295xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21296{
21297    xmlSchemaPtr mainSchema = NULL;
21298    xmlSchemaBucketPtr bucket = NULL;
21299    int res;
21300
21301    /*
21302    * This one is used if the schema to be parsed was specified via
21303    * the API; i.e. not automatically by the validated instance document.
21304    */
21305
21306    xmlSchemaInitTypes();
21307
21308    if (ctxt == NULL)
21309        return (NULL);
21310
21311    /* TODO: Init the context. Is this all we need?*/
21312    ctxt->nberrors = 0;
21313    ctxt->err = 0;
21314    ctxt->counter = 0;
21315
21316    /* Create the *main* schema. */
21317    mainSchema = xmlSchemaNewSchema(ctxt);
21318    if (mainSchema == NULL)
21319	goto exit_failure;
21320    /*
21321    * Create the schema constructor.
21322    */
21323    if (ctxt->constructor == NULL) {
21324	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21325	if (ctxt->constructor == NULL)
21326	    return(NULL);
21327	/* Take ownership of the constructor to be able to free it. */
21328	ctxt->ownsConstructor = 1;
21329    }
21330    ctxt->constructor->mainSchema = mainSchema;
21331    /*
21332    * Locate and add the schema document.
21333    */
21334    res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21335	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21336	NULL, NULL, &bucket);
21337    if (res == -1)
21338	goto exit_failure;
21339    if (res != 0)
21340	goto exit;
21341
21342    if (bucket == NULL) {
21343	/* TODO: Error code, actually we failed to *locate* the schema. */
21344	if (ctxt->URL)
21345	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21346		NULL, NULL,
21347		"Failed to locate the main schema resource at '%s'",
21348		ctxt->URL, NULL);
21349	else
21350	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21351		NULL, NULL,
21352		"Failed to locate the main schema resource",
21353		    NULL, NULL);
21354	goto exit;
21355    }
21356    /* Then do the parsing for good. */
21357    if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21358	goto exit_failure;
21359    if (ctxt->nberrors != 0)
21360	goto exit;
21361
21362    mainSchema->doc = bucket->doc;
21363    mainSchema->preserve = ctxt->preserve;
21364
21365    ctxt->schema = mainSchema;
21366
21367    if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21368	goto exit_failure;
21369
21370    /*
21371    * TODO: This is not nice, since we cannot distinguish from the
21372    * result if there was an internal error or not.
21373    */
21374exit:
21375    if (ctxt->nberrors != 0) {
21376	if (mainSchema) {
21377	    xmlSchemaFree(mainSchema);
21378	    mainSchema = NULL;
21379	}
21380	if (ctxt->constructor) {
21381	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21382	    ctxt->constructor = NULL;
21383	    ctxt->ownsConstructor = 0;
21384	}
21385    }
21386    ctxt->schema = NULL;
21387    return(mainSchema);
21388exit_failure:
21389    /*
21390    * Quite verbose, but should catch internal errors, which were
21391    * not communitated.
21392    */
21393    if (mainSchema) {
21394        xmlSchemaFree(mainSchema);
21395	mainSchema = NULL;
21396    }
21397    if (ctxt->constructor) {
21398	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21399	ctxt->constructor = NULL;
21400	ctxt->ownsConstructor = 0;
21401    }
21402    PERROR_INT2("xmlSchemaParse",
21403	"An internal error occured");
21404    ctxt->schema = NULL;
21405    return(NULL);
21406}
21407
21408/**
21409 * xmlSchemaSetParserErrors:
21410 * @ctxt:  a schema validation context
21411 * @err:  the error callback
21412 * @warn:  the warning callback
21413 * @ctx:  contextual data for the callbacks
21414 *
21415 * Set the callback functions used to handle errors for a validation context
21416 */
21417void
21418xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21419                         xmlSchemaValidityErrorFunc err,
21420                         xmlSchemaValidityWarningFunc warn, void *ctx)
21421{
21422    if (ctxt == NULL)
21423        return;
21424    ctxt->error = err;
21425    ctxt->warning = warn;
21426    ctxt->errCtxt = ctx;
21427    if (ctxt->vctxt != NULL)
21428	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21429}
21430
21431/**
21432 * xmlSchemaSetParserStructuredErrors:
21433 * @ctxt:  a schema parser context
21434 * @serror:  the structured error function
21435 * @ctx: the functions context
21436 *
21437 * Set the structured error callback
21438 */
21439void
21440xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21441				   xmlStructuredErrorFunc serror,
21442				   void *ctx)
21443{
21444    if (ctxt == NULL)
21445	return;
21446    ctxt->serror = serror;
21447    ctxt->errCtxt = ctx;
21448    if (ctxt->vctxt != NULL)
21449	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21450}
21451
21452/**
21453 * xmlSchemaGetParserErrors:
21454 * @ctxt:  a XMl-Schema parser context
21455 * @err: the error callback result
21456 * @warn: the warning callback result
21457 * @ctx: contextual data for the callbacks result
21458 *
21459 * Get the callback information used to handle errors for a parser context
21460 *
21461 * Returns -1 in case of failure, 0 otherwise
21462 */
21463int
21464xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21465			 xmlSchemaValidityErrorFunc * err,
21466			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21467{
21468	if (ctxt == NULL)
21469		return(-1);
21470	if (err != NULL)
21471		*err = ctxt->error;
21472	if (warn != NULL)
21473		*warn = ctxt->warning;
21474	if (ctx != NULL)
21475		*ctx = ctxt->errCtxt;
21476	return(0);
21477}
21478
21479/**
21480 * xmlSchemaFacetTypeToString:
21481 * @type:  the facet type
21482 *
21483 * Convert the xmlSchemaTypeType to a char string.
21484 *
21485 * Returns the char string representation of the facet type if the
21486 *     type is a facet and an "Internal Error" string otherwise.
21487 */
21488static const xmlChar *
21489xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21490{
21491    switch (type) {
21492        case XML_SCHEMA_FACET_PATTERN:
21493            return (BAD_CAST "pattern");
21494        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21495            return (BAD_CAST "maxExclusive");
21496        case XML_SCHEMA_FACET_MAXINCLUSIVE:
21497            return (BAD_CAST "maxInclusive");
21498        case XML_SCHEMA_FACET_MINEXCLUSIVE:
21499            return (BAD_CAST "minExclusive");
21500        case XML_SCHEMA_FACET_MININCLUSIVE:
21501            return (BAD_CAST "minInclusive");
21502        case XML_SCHEMA_FACET_WHITESPACE:
21503            return (BAD_CAST "whiteSpace");
21504        case XML_SCHEMA_FACET_ENUMERATION:
21505            return (BAD_CAST "enumeration");
21506        case XML_SCHEMA_FACET_LENGTH:
21507            return (BAD_CAST "length");
21508        case XML_SCHEMA_FACET_MAXLENGTH:
21509            return (BAD_CAST "maxLength");
21510        case XML_SCHEMA_FACET_MINLENGTH:
21511            return (BAD_CAST "minLength");
21512        case XML_SCHEMA_FACET_TOTALDIGITS:
21513            return (BAD_CAST "totalDigits");
21514        case XML_SCHEMA_FACET_FRACTIONDIGITS:
21515            return (BAD_CAST "fractionDigits");
21516        default:
21517            break;
21518    }
21519    return (BAD_CAST "Internal Error");
21520}
21521
21522static xmlSchemaWhitespaceValueType
21523xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21524{
21525    /*
21526    * The normalization type can be changed only for types which are derived
21527    * from xsd:string.
21528    */
21529    if (type->type == XML_SCHEMA_TYPE_BASIC) {
21530	/*
21531	* Note that we assume a whitespace of preserve for anySimpleType.
21532	*/
21533	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21534	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21535	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21536	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21537	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21538	else {
21539	    /*
21540	    * For all `atomic` datatypes other than string (and types `derived`
21541	    * by `restriction` from it) the value of whiteSpace is fixed to
21542	    * collapse
21543	    * Note that this includes built-in list datatypes.
21544	    */
21545	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21546	}
21547    } else if (WXS_IS_LIST(type)) {
21548	/*
21549	* For list types the facet "whiteSpace" is fixed to "collapse".
21550	*/
21551	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21552    } else if (WXS_IS_UNION(type)) {
21553	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21554    } else if (WXS_IS_ATOMIC(type)) {
21555	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21556	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21557	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21558	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21559	else
21560	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21561    }
21562    return (-1);
21563}
21564
21565/************************************************************************
21566 *									*
21567 *			Simple type validation				*
21568 *									*
21569 ************************************************************************/
21570
21571
21572/************************************************************************
21573 *									*
21574 *			DOM Validation code				*
21575 *									*
21576 ************************************************************************/
21577
21578/**
21579 * xmlSchemaAssembleByLocation:
21580 * @pctxt:  a schema parser context
21581 * @vctxt:  a schema validation context
21582 * @schema: the existing schema
21583 * @node: the node that fired the assembling
21584 * @nsName: the namespace name of the new schema
21585 * @location: the location of the schema
21586 *
21587 * Expands an existing schema by an additional schema.
21588 *
21589 * Returns 0 if the new schema is correct, a positive error code
21590 * number otherwise and -1 in case of an internal or API error.
21591 */
21592static int
21593xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21594			    xmlSchemaPtr schema,
21595			    xmlNodePtr node,
21596			    const xmlChar *nsName,
21597			    const xmlChar *location)
21598{
21599    int ret = 0;
21600    xmlSchemaParserCtxtPtr pctxt;
21601    xmlSchemaBucketPtr bucket = NULL;
21602
21603    if ((vctxt == NULL) || (schema == NULL))
21604	return (-1);
21605
21606    if (vctxt->pctxt == NULL) {
21607	VERROR_INT("xmlSchemaAssembleByLocation",
21608	    "no parser context available");
21609	return(-1);
21610    }
21611    pctxt = vctxt->pctxt;
21612    if (pctxt->constructor == NULL) {
21613	PERROR_INT("xmlSchemaAssembleByLocation",
21614	    "no constructor");
21615	return(-1);
21616    }
21617    /*
21618    * Acquire the schema document.
21619    */
21620    location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21621	location, node);
21622    /*
21623    * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21624    * the process will automatically change this to
21625    * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21626    */
21627    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21628	location, NULL, NULL, 0, node, NULL, nsName,
21629	&bucket);
21630    if (ret != 0)
21631	return(ret);
21632    if (bucket == NULL) {
21633	/*
21634	* Generate a warning that the document could not be located.
21635	*/
21636	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21637	    node, NULL,
21638	    "The document at location '%s' could not be acquired",
21639	    location, NULL, NULL);
21640	return(ret);
21641    }
21642    /*
21643    * The first located schema will be handled as if all other
21644    * schemas imported by XSI were imported by this first schema.
21645    */
21646    if ((bucket != NULL) &&
21647	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21648	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21649    /*
21650    * TODO: Is this handled like an import? I.e. is it not an error
21651    * if the schema cannot be located?
21652    */
21653    if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21654	return(0);
21655    /*
21656    * We will reuse the parser context for every schema imported
21657    * directly via XSI. So reset the context.
21658    */
21659    pctxt->nberrors = 0;
21660    pctxt->err = 0;
21661    pctxt->doc = bucket->doc;
21662
21663    ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21664    if (ret == -1) {
21665	pctxt->doc = NULL;
21666	goto exit_failure;
21667    }
21668    /* Paranoid error channelling. */
21669    if ((ret == 0) && (pctxt->nberrors != 0))
21670	ret = pctxt->err;
21671    if (pctxt->nberrors == 0) {
21672	/*
21673	* Only bother to fixup pending components, if there was
21674	* no error yet.
21675	* For every XSI acquired schema (and its sub-schemata) we will
21676	* fixup the components.
21677	*/
21678	xmlSchemaFixupComponents(pctxt, bucket);
21679	ret = pctxt->err;
21680	/*
21681	* Not nice, but we need somehow to channel the schema parser
21682	* error to the validation context.
21683	*/
21684	if ((ret != 0) && (vctxt->err == 0))
21685	    vctxt->err = ret;
21686	vctxt->nberrors += pctxt->nberrors;
21687    } else {
21688	/* Add to validation error sum. */
21689	vctxt->nberrors += pctxt->nberrors;
21690    }
21691    pctxt->doc = NULL;
21692    return(ret);
21693exit_failure:
21694    pctxt->doc = NULL;
21695    return (-1);
21696}
21697
21698static xmlSchemaAttrInfoPtr
21699xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21700			 int metaType)
21701{
21702    if (vctxt->nbAttrInfos == 0)
21703	return (NULL);
21704    {
21705	int i;
21706	xmlSchemaAttrInfoPtr iattr;
21707
21708	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21709	    iattr = vctxt->attrInfos[i];
21710	    if (iattr->metaType == metaType)
21711		return (iattr);
21712	}
21713
21714    }
21715    return (NULL);
21716}
21717
21718/**
21719 * xmlSchemaAssembleByXSI:
21720 * @vctxt:  a schema validation context
21721 *
21722 * Expands an existing schema by an additional schema using
21723 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21724 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21725 * must be set to 1.
21726 *
21727 * Returns 0 if the new schema is correct, a positive error code
21728 * number otherwise and -1 in case of an internal or API error.
21729 */
21730static int
21731xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21732{
21733    const xmlChar *cur, *end;
21734    const xmlChar *nsname = NULL, *location;
21735    int count = 0;
21736    int ret = 0;
21737    xmlSchemaAttrInfoPtr iattr;
21738
21739    /*
21740    * Parse the value; we will assume an even number of values
21741    * to be given (this is how Xerces and XSV work).
21742    *
21743    * URGENT TODO: !! This needs to work for both
21744    * @noNamespaceSchemaLocation AND @schemaLocation on the same
21745    * element !!
21746    */
21747    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21748	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21749    if (iattr == NULL)
21750	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21751	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21752    if (iattr == NULL)
21753	return (0);
21754    cur = iattr->value;
21755    do {
21756	/*
21757	* TODO: Move the string parsing mechanism away from here.
21758	*/
21759	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21760	    /*
21761	    * Get the namespace name.
21762	    */
21763	    while (IS_BLANK_CH(*cur))
21764		cur++;
21765	    end = cur;
21766	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21767		end++;
21768	    if (end == cur)
21769		break;
21770	    count++; /* TODO: Don't use the schema's dict. */
21771	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21772	    cur = end;
21773	}
21774	/*
21775	* Get the URI.
21776	*/
21777	while (IS_BLANK_CH(*cur))
21778	    cur++;
21779	end = cur;
21780	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21781	    end++;
21782	if (end == cur) {
21783	    if (iattr->metaType ==
21784		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21785	    {
21786		/*
21787		* If using @schemaLocation then tuples are expected.
21788		* I.e. the namespace name *and* the document's URI.
21789		*/
21790		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21791		    iattr->node, NULL,
21792		    "The value must consist of tuples: the target namespace "
21793		    "name and the document's URI", NULL, NULL, NULL);
21794	    }
21795	    break;
21796	}
21797	count++; /* TODO: Don't use the schema's dict. */
21798	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21799	cur = end;
21800	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21801	    iattr->node, nsname, location);
21802	if (ret == -1) {
21803	    VERROR_INT("xmlSchemaAssembleByXSI",
21804		"assembling schemata");
21805	    return (-1);
21806	}
21807    } while (*cur != 0);
21808    return (ret);
21809}
21810
21811static const xmlChar *
21812xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21813			 const xmlChar *prefix)
21814{
21815    if (vctxt->sax != NULL) {
21816	int i, j;
21817	xmlSchemaNodeInfoPtr inode;
21818
21819	for (i = vctxt->depth; i >= 0; i--) {
21820	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21821		inode = vctxt->elemInfos[i];
21822		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21823		    if (((prefix == NULL) &&
21824			    (inode->nsBindings[j] == NULL)) ||
21825			((prefix != NULL) && xmlStrEqual(prefix,
21826			    inode->nsBindings[j]))) {
21827
21828			/*
21829			* Note that the namespace bindings are already
21830			* in a string dict.
21831			*/
21832			return (inode->nsBindings[j+1]);
21833		    }
21834		}
21835	    }
21836	}
21837	return (NULL);
21838#ifdef LIBXML_READER_ENABLED
21839    } else if (vctxt->reader != NULL) {
21840	xmlChar *nsName;
21841
21842	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21843	if (nsName != NULL) {
21844	    const xmlChar *ret;
21845
21846	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21847	    xmlFree(nsName);
21848	    return (ret);
21849	} else
21850	    return (NULL);
21851#endif
21852    } else {
21853	xmlNsPtr ns;
21854
21855	if ((vctxt->inode->node == NULL) ||
21856	    (vctxt->inode->node->doc == NULL)) {
21857	    VERROR_INT("xmlSchemaLookupNamespace",
21858		"no node or node's doc avaliable");
21859	    return (NULL);
21860	}
21861	ns = xmlSearchNs(vctxt->inode->node->doc,
21862	    vctxt->inode->node, prefix);
21863	if (ns != NULL)
21864	    return (ns->href);
21865	return (NULL);
21866    }
21867}
21868
21869/*
21870* This one works on the schema of the validation context.
21871*/
21872static int
21873xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21874			  xmlSchemaPtr schema,
21875			  xmlNodePtr node,
21876			  const xmlChar *value,
21877			  xmlSchemaValPtr *val,
21878			  int valNeeded)
21879{
21880    int ret;
21881
21882    if (vctxt && (vctxt->schema == NULL)) {
21883	VERROR_INT("xmlSchemaValidateNotation",
21884	    "a schema is needed on the validation context");
21885	return (-1);
21886    }
21887    ret = xmlValidateQName(value, 1);
21888    if (ret != 0)
21889	return (ret);
21890    {
21891	xmlChar *localName = NULL;
21892	xmlChar *prefix = NULL;
21893
21894	localName = xmlSplitQName2(value, &prefix);
21895	if (prefix != NULL) {
21896	    const xmlChar *nsName = NULL;
21897
21898	    if (vctxt != NULL)
21899		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21900	    else if (node != NULL) {
21901		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21902		if (ns != NULL)
21903		    nsName = ns->href;
21904	    } else {
21905		xmlFree(prefix);
21906		xmlFree(localName);
21907		return (1);
21908	    }
21909	    if (nsName == NULL) {
21910		xmlFree(prefix);
21911		xmlFree(localName);
21912		return (1);
21913	    }
21914	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21915		if ((valNeeded) && (val != NULL)) {
21916		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21917						       xmlStrdup(nsName));
21918		    if (*val == NULL)
21919			ret = -1;
21920		}
21921	    } else
21922		ret = 1;
21923	    xmlFree(prefix);
21924	    xmlFree(localName);
21925	} else {
21926	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21927		if (valNeeded && (val != NULL)) {
21928		    (*val) = xmlSchemaNewNOTATIONValue(
21929			BAD_CAST xmlStrdup(value), NULL);
21930		    if (*val == NULL)
21931			ret = -1;
21932		}
21933	    } else
21934		return (1);
21935	}
21936    }
21937    return (ret);
21938}
21939
21940static int
21941xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21942		       const xmlChar* lname,
21943		       const xmlChar* nsname)
21944{
21945    int i;
21946
21947    lname = xmlDictLookup(vctxt->dict, lname, -1);
21948    if (lname == NULL)
21949	return(-1);
21950    if (nsname != NULL) {
21951	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21952	if (nsname == NULL)
21953	    return(-1);
21954    }
21955    for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21956	if ((vctxt->nodeQNames->items [i] == lname) &&
21957	    (vctxt->nodeQNames->items[i +1] == nsname))
21958	    /* Already there */
21959	    return(i);
21960    }
21961    /* Add new entry. */
21962    i = vctxt->nodeQNames->nbItems;
21963    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21964    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21965    return(i);
21966}
21967
21968/************************************************************************
21969 *									*
21970 *  Validation of identity-constraints (IDC)                            *
21971 *									*
21972 ************************************************************************/
21973
21974/**
21975 * xmlSchemaAugmentIDC:
21976 * @idcDef: the IDC definition
21977 *
21978 * Creates an augmented IDC definition item.
21979 *
21980 * Returns the item, or NULL on internal errors.
21981 */
21982static void
21983xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21984		    xmlSchemaValidCtxtPtr vctxt)
21985{
21986    xmlSchemaIDCAugPtr aidc;
21987
21988    aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21989    if (aidc == NULL) {
21990	xmlSchemaVErrMemory(vctxt,
21991	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21992	    NULL);
21993	return;
21994    }
21995    aidc->keyrefDepth = -1;
21996    aidc->def = idcDef;
21997    aidc->next = NULL;
21998    if (vctxt->aidcs == NULL)
21999	vctxt->aidcs = aidc;
22000    else {
22001	aidc->next = vctxt->aidcs;
22002	vctxt->aidcs = aidc;
22003    }
22004    /*
22005    * Save if we have keyrefs at all.
22006    */
22007    if ((vctxt->hasKeyrefs == 0) &&
22008	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22009	vctxt->hasKeyrefs = 1;
22010}
22011
22012/**
22013 * xmlSchemaAugmentImportedIDC:
22014 * @imported: the imported schema
22015 *
22016 * Creates an augmented IDC definition for the imported schema.
22017 */
22018static void
22019xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
22020    if (imported->schema->idcDef != NULL) {
22021	    xmlHashScan(imported->schema->idcDef ,
22022	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
22023    }
22024}
22025
22026/**
22027 * xmlSchemaIDCNewBinding:
22028 * @idcDef: the IDC definition of this binding
22029 *
22030 * Creates a new IDC binding.
22031 *
22032 * Returns the new IDC binding, NULL on internal errors.
22033 */
22034static xmlSchemaPSVIIDCBindingPtr
22035xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22036{
22037    xmlSchemaPSVIIDCBindingPtr ret;
22038
22039    ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22040	    sizeof(xmlSchemaPSVIIDCBinding));
22041    if (ret == NULL) {
22042	xmlSchemaVErrMemory(NULL,
22043	    "allocating a PSVI IDC binding item", NULL);
22044	return (NULL);
22045    }
22046    memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22047    ret->definition = idcDef;
22048    return (ret);
22049}
22050
22051/**
22052 * xmlSchemaIDCStoreNodeTableItem:
22053 * @vctxt: the WXS validation context
22054 * @item: the IDC node table item
22055 *
22056 * The validation context is used to store IDC node table items.
22057 * They are stored to avoid copying them if IDC node-tables are merged
22058 * with corresponding parent IDC node-tables (bubbling).
22059 *
22060 * Returns 0 if succeeded, -1 on internal errors.
22061 */
22062static int
22063xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22064			       xmlSchemaPSVIIDCNodePtr item)
22065{
22066    /*
22067    * Add to gobal list.
22068    */
22069    if (vctxt->idcNodes == NULL) {
22070	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22071	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22072	if (vctxt->idcNodes == NULL) {
22073	    xmlSchemaVErrMemory(vctxt,
22074		"allocating the IDC node table item list", NULL);
22075	    return (-1);
22076	}
22077	vctxt->sizeIdcNodes = 20;
22078    } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22079	vctxt->sizeIdcNodes *= 2;
22080	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22081	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22082	    sizeof(xmlSchemaPSVIIDCNodePtr));
22083	if (vctxt->idcNodes == NULL) {
22084	    xmlSchemaVErrMemory(vctxt,
22085		"re-allocating the IDC node table item list", NULL);
22086	    return (-1);
22087	}
22088    }
22089    vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22090
22091    return (0);
22092}
22093
22094/**
22095 * xmlSchemaIDCStoreKey:
22096 * @vctxt: the WXS validation context
22097 * @item: the IDC key
22098 *
22099 * The validation context is used to store an IDC key.
22100 *
22101 * Returns 0 if succeeded, -1 on internal errors.
22102 */
22103static int
22104xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22105		     xmlSchemaPSVIIDCKeyPtr key)
22106{
22107    /*
22108    * Add to gobal list.
22109    */
22110    if (vctxt->idcKeys == NULL) {
22111	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22112	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22113	if (vctxt->idcKeys == NULL) {
22114	    xmlSchemaVErrMemory(vctxt,
22115		"allocating the IDC key storage list", NULL);
22116	    return (-1);
22117	}
22118	vctxt->sizeIdcKeys = 40;
22119    } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22120	vctxt->sizeIdcKeys *= 2;
22121	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22122	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22123	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22124	if (vctxt->idcKeys == NULL) {
22125	    xmlSchemaVErrMemory(vctxt,
22126		"re-allocating the IDC key storage list", NULL);
22127	    return (-1);
22128	}
22129    }
22130    vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22131
22132    return (0);
22133}
22134
22135/**
22136 * xmlSchemaIDCAppendNodeTableItem:
22137 * @bind: the IDC binding
22138 * @ntItem: the node-table item
22139 *
22140 * Appends the IDC node-table item to the binding.
22141 *
22142 * Returns 0 on success and -1 on internal errors.
22143 */
22144static int
22145xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22146				xmlSchemaPSVIIDCNodePtr ntItem)
22147{
22148    if (bind->nodeTable == NULL) {
22149	bind->sizeNodes = 10;
22150	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22151	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22152	if (bind->nodeTable == NULL) {
22153	    xmlSchemaVErrMemory(NULL,
22154		"allocating an array of IDC node-table items", NULL);
22155	    return(-1);
22156	}
22157    } else if (bind->sizeNodes <= bind->nbNodes) {
22158	bind->sizeNodes *= 2;
22159	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22160	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22161		sizeof(xmlSchemaPSVIIDCNodePtr));
22162	if (bind->nodeTable == NULL) {
22163	    xmlSchemaVErrMemory(NULL,
22164		"re-allocating an array of IDC node-table items", NULL);
22165	    return(-1);
22166	}
22167    }
22168    bind->nodeTable[bind->nbNodes++] = ntItem;
22169    return(0);
22170}
22171
22172/**
22173 * xmlSchemaIDCAcquireBinding:
22174 * @vctxt: the WXS validation context
22175 * @matcher: the IDC matcher
22176 *
22177 * Looks up an PSVI IDC binding, for the IDC definition and
22178 * of the given matcher. If none found, a new one is created
22179 * and added to the IDC table.
22180 *
22181 * Returns an IDC binding or NULL on internal errors.
22182 */
22183static xmlSchemaPSVIIDCBindingPtr
22184xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22185			  xmlSchemaIDCMatcherPtr matcher)
22186{
22187    xmlSchemaNodeInfoPtr ielem;
22188
22189    ielem = vctxt->elemInfos[matcher->depth];
22190
22191    if (ielem->idcTable == NULL) {
22192	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22193	if (ielem->idcTable == NULL)
22194	    return (NULL);
22195	return(ielem->idcTable);
22196    } else {
22197	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22198
22199	bind = ielem->idcTable;
22200	do {
22201	    if (bind->definition == matcher->aidc->def)
22202		return(bind);
22203	    if (bind->next == NULL) {
22204		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22205		if (bind->next == NULL)
22206		    return (NULL);
22207		return(bind->next);
22208	    }
22209	    bind = bind->next;
22210	} while (bind != NULL);
22211    }
22212    return (NULL);
22213}
22214
22215static xmlSchemaItemListPtr
22216xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22217			     xmlSchemaIDCMatcherPtr matcher)
22218{
22219    if (matcher->targets == NULL)
22220	matcher->targets = xmlSchemaItemListCreate();
22221    return(matcher->targets);
22222}
22223
22224/**
22225 * xmlSchemaIDCFreeKey:
22226 * @key: the IDC key
22227 *
22228 * Frees an IDC key together with its compiled value.
22229 */
22230static void
22231xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22232{
22233    if (key->val != NULL)
22234	xmlSchemaFreeValue(key->val);
22235    xmlFree(key);
22236}
22237
22238/**
22239 * xmlSchemaIDCFreeBinding:
22240 *
22241 * Frees an IDC binding. Note that the node table-items
22242 * are not freed.
22243 */
22244static void
22245xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22246{
22247    if (bind->nodeTable != NULL)
22248	xmlFree(bind->nodeTable);
22249    if (bind->dupls != NULL)
22250	xmlSchemaItemListFree(bind->dupls);
22251    xmlFree(bind);
22252}
22253
22254/**
22255 * xmlSchemaIDCFreeIDCTable:
22256 * @bind: the first IDC binding in the list
22257 *
22258 * Frees an IDC table, i.e. all the IDC bindings in the list.
22259 */
22260static void
22261xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22262{
22263    xmlSchemaPSVIIDCBindingPtr prev;
22264
22265    while (bind != NULL) {
22266	prev = bind;
22267	bind = bind->next;
22268	xmlSchemaIDCFreeBinding(prev);
22269    }
22270}
22271
22272/**
22273 * xmlSchemaIDCFreeMatcherList:
22274 * @matcher: the first IDC matcher in the list
22275 *
22276 * Frees a list of IDC matchers.
22277 */
22278static void
22279xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22280{
22281    xmlSchemaIDCMatcherPtr next;
22282
22283    while (matcher != NULL) {
22284	next = matcher->next;
22285	if (matcher->keySeqs != NULL) {
22286	    int i;
22287	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22288		if (matcher->keySeqs[i] != NULL)
22289		    xmlFree(matcher->keySeqs[i]);
22290	    xmlFree(matcher->keySeqs);
22291	}
22292	if (matcher->targets != NULL) {
22293	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22294		int i;
22295		xmlSchemaPSVIIDCNodePtr idcNode;
22296		/*
22297		* Node-table items for keyrefs are not stored globally
22298		* to the validation context, since they are not bubbled.
22299		* We need to free them here.
22300		*/
22301		for (i = 0; i < matcher->targets->nbItems; i++) {
22302		    idcNode =
22303			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22304		    xmlFree(idcNode->keys);
22305		    xmlFree(idcNode);
22306		}
22307	    }
22308	    xmlSchemaItemListFree(matcher->targets);
22309	}
22310	xmlFree(matcher);
22311	matcher = next;
22312    }
22313}
22314
22315/**
22316 * xmlSchemaIDCReleaseMatcherList:
22317 * @vctxt: the WXS validation context
22318 * @matcher: the first IDC matcher in the list
22319 *
22320 * Caches a list of IDC matchers for reuse.
22321 */
22322static void
22323xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22324			       xmlSchemaIDCMatcherPtr matcher)
22325{
22326    xmlSchemaIDCMatcherPtr next;
22327
22328    while (matcher != NULL) {
22329	next = matcher->next;
22330	if (matcher->keySeqs != NULL) {
22331	    int i;
22332	    /*
22333	    * Don't free the array, but only the content.
22334	    */
22335	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22336		if (matcher->keySeqs[i] != NULL) {
22337		    xmlFree(matcher->keySeqs[i]);
22338		    matcher->keySeqs[i] = NULL;
22339		}
22340	}
22341	if (matcher->targets) {
22342	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22343		int i;
22344		xmlSchemaPSVIIDCNodePtr idcNode;
22345		/*
22346		* Node-table items for keyrefs are not stored globally
22347		* to the validation context, since they are not bubbled.
22348		* We need to free them here.
22349		*/
22350		for (i = 0; i < matcher->targets->nbItems; i++) {
22351		    idcNode =
22352			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22353		    xmlFree(idcNode->keys);
22354		    xmlFree(idcNode);
22355		}
22356	    }
22357	    xmlSchemaItemListFree(matcher->targets);
22358	    matcher->targets = NULL;
22359	}
22360	matcher->next = NULL;
22361	/*
22362	* Cache the matcher.
22363	*/
22364	if (vctxt->idcMatcherCache != NULL)
22365	    matcher->nextCached = vctxt->idcMatcherCache;
22366	vctxt->idcMatcherCache = matcher;
22367
22368	matcher = next;
22369    }
22370}
22371
22372/**
22373 * xmlSchemaIDCAddStateObject:
22374 * @vctxt: the WXS validation context
22375 * @matcher: the IDC matcher
22376 * @sel: the XPath information
22377 * @parent: the parent "selector" state object if any
22378 * @type: "selector" or "field"
22379 *
22380 * Creates/reuses and activates state objects for the given
22381 * XPath information; if the XPath expression consists of unions,
22382 * multiple state objects are created for every unioned expression.
22383 *
22384 * Returns 0 on success and -1 on internal errors.
22385 */
22386static int
22387xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22388			xmlSchemaIDCMatcherPtr matcher,
22389			xmlSchemaIDCSelectPtr sel,
22390			int type)
22391{
22392    xmlSchemaIDCStateObjPtr sto;
22393
22394    /*
22395    * Reuse the state objects from the pool.
22396    */
22397    if (vctxt->xpathStatePool != NULL) {
22398	sto = vctxt->xpathStatePool;
22399	vctxt->xpathStatePool = sto->next;
22400	sto->next = NULL;
22401    } else {
22402	/*
22403	* Create a new state object.
22404	*/
22405	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22406	if (sto == NULL) {
22407	    xmlSchemaVErrMemory(NULL,
22408		"allocating an IDC state object", NULL);
22409	    return (-1);
22410	}
22411	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22412    }
22413    /*
22414    * Add to global list.
22415    */
22416    if (vctxt->xpathStates != NULL)
22417	sto->next = vctxt->xpathStates;
22418    vctxt->xpathStates = sto;
22419
22420    /*
22421    * Free the old xpath validation context.
22422    */
22423    if (sto->xpathCtxt != NULL)
22424	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22425
22426    /*
22427    * Create a new XPath (pattern) validation context.
22428    */
22429    sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22430	(xmlPatternPtr) sel->xpathComp);
22431    if (sto->xpathCtxt == NULL) {
22432	VERROR_INT("xmlSchemaIDCAddStateObject",
22433	    "failed to create an XPath validation context");
22434	return (-1);
22435    }
22436    sto->type = type;
22437    sto->depth = vctxt->depth;
22438    sto->matcher = matcher;
22439    sto->sel = sel;
22440    sto->nbHistory = 0;
22441
22442#ifdef DEBUG_IDC
22443    xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22444	sto->sel->xpath);
22445#endif
22446    return (0);
22447}
22448
22449/**
22450 * xmlSchemaXPathEvaluate:
22451 * @vctxt: the WXS validation context
22452 * @nodeType: the nodeType of the current node
22453 *
22454 * Evaluates all active XPath state objects.
22455 *
22456 * Returns the number of IC "field" state objects which resolved to
22457 * this node, 0 if none resolved and -1 on internal errors.
22458 */
22459static int
22460xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22461		       xmlElementType nodeType)
22462{
22463    xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22464    int res, resolved = 0, depth = vctxt->depth;
22465
22466    if (vctxt->xpathStates == NULL)
22467	return (0);
22468
22469    if (nodeType == XML_ATTRIBUTE_NODE)
22470	depth++;
22471#ifdef DEBUG_IDC
22472    {
22473	xmlChar *str = NULL;
22474	xmlGenericError(xmlGenericErrorContext,
22475	    "IDC: EVAL on %s, depth %d, type %d\n",
22476	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22477		vctxt->inode->localName), depth, nodeType);
22478	FREE_AND_NULL(str)
22479    }
22480#endif
22481    /*
22482    * Process all active XPath state objects.
22483    */
22484    first = vctxt->xpathStates;
22485    sto = first;
22486    while (sto != head) {
22487#ifdef DEBUG_IDC
22488	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22489	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22490		sto->matcher->aidc->def->name, sto->sel->xpath);
22491	else
22492	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22493		sto->matcher->aidc->def->name, sto->sel->xpath);
22494#endif
22495	if (nodeType == XML_ELEMENT_NODE)
22496	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22497		vctxt->inode->localName, vctxt->inode->nsName);
22498	else
22499	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22500		vctxt->inode->localName, vctxt->inode->nsName);
22501
22502	if (res == -1) {
22503	    VERROR_INT("xmlSchemaXPathEvaluate",
22504		"calling xmlStreamPush()");
22505	    return (-1);
22506	}
22507	if (res == 0)
22508	    goto next_sto;
22509	/*
22510	* Full match.
22511	*/
22512#ifdef DEBUG_IDC
22513	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22514	    "MATCH\n");
22515#endif
22516	/*
22517	* Register a match in the state object history.
22518	*/
22519	if (sto->history == NULL) {
22520	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22521	    if (sto->history == NULL) {
22522		xmlSchemaVErrMemory(NULL,
22523		    "allocating the state object history", NULL);
22524		return(-1);
22525	    }
22526	    sto->sizeHistory = 5;
22527	} else if (sto->sizeHistory <= sto->nbHistory) {
22528	    sto->sizeHistory *= 2;
22529	    sto->history = (int *) xmlRealloc(sto->history,
22530		sto->sizeHistory * sizeof(int));
22531	    if (sto->history == NULL) {
22532		xmlSchemaVErrMemory(NULL,
22533		    "re-allocating the state object history", NULL);
22534		return(-1);
22535	    }
22536	}
22537	sto->history[sto->nbHistory++] = depth;
22538
22539#ifdef DEBUG_IDC
22540	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22541	    vctxt->depth);
22542#endif
22543
22544	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22545	    xmlSchemaIDCSelectPtr sel;
22546	    /*
22547	    * Activate state objects for the IDC fields of
22548	    * the IDC selector.
22549	    */
22550#ifdef DEBUG_IDC
22551	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22552		"activating field states\n");
22553#endif
22554	    sel = sto->matcher->aidc->def->fields;
22555	    while (sel != NULL) {
22556		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22557		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22558		    return (-1);
22559		sel = sel->next;
22560	    }
22561	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22562	    /*
22563	    * An IDC key node was found by the IDC field.
22564	    */
22565#ifdef DEBUG_IDC
22566	    xmlGenericError(xmlGenericErrorContext,
22567		"IDC:     key found\n");
22568#endif
22569	    /*
22570	    * Notify that the character value of this node is
22571	    * needed.
22572	    */
22573	    if (resolved == 0) {
22574		if ((vctxt->inode->flags &
22575		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22576		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22577	    }
22578	    resolved++;
22579	}
22580next_sto:
22581	if (sto->next == NULL) {
22582	    /*
22583	    * Evaluate field state objects created on this node as well.
22584	    */
22585	    head = first;
22586	    sto = vctxt->xpathStates;
22587	} else
22588	    sto = sto->next;
22589    }
22590    return (resolved);
22591}
22592
22593static const xmlChar *
22594xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22595			      xmlChar **buf,
22596			      xmlSchemaPSVIIDCKeyPtr *seq,
22597			      int count)
22598{
22599    int i, res;
22600    xmlChar *value = NULL;
22601
22602    *buf = xmlStrdup(BAD_CAST "[");
22603    for (i = 0; i < count; i++) {
22604	*buf = xmlStrcat(*buf, BAD_CAST "'");
22605	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22606	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22607	    &value);
22608	if (res == 0)
22609	    *buf = xmlStrcat(*buf, BAD_CAST value);
22610	else {
22611	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22612		"failed to compute a canonical value");
22613	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22614	}
22615	if (i < count -1)
22616	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22617	else
22618	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22619	if (value != NULL) {
22620	    xmlFree(value);
22621	    value = NULL;
22622	}
22623    }
22624    *buf = xmlStrcat(*buf, BAD_CAST "]");
22625
22626    return (BAD_CAST *buf);
22627}
22628
22629/**
22630 * xmlSchemaXPathPop:
22631 * @vctxt: the WXS validation context
22632 *
22633 * Pops all XPath states.
22634 *
22635 * Returns 0 on success and -1 on internal errors.
22636 */
22637static int
22638xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22639{
22640    xmlSchemaIDCStateObjPtr sto;
22641    int res;
22642
22643    if (vctxt->xpathStates == NULL)
22644	return(0);
22645    sto = vctxt->xpathStates;
22646    do {
22647	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22648	if (res == -1)
22649	    return (-1);
22650	sto = sto->next;
22651    } while (sto != NULL);
22652    return(0);
22653}
22654
22655/**
22656 * xmlSchemaXPathProcessHistory:
22657 * @vctxt: the WXS validation context
22658 * @type: the simple/complex type of the current node if any at all
22659 * @val: the precompiled value
22660 *
22661 * Processes and pops the history items of the IDC state objects.
22662 * IDC key-sequences are validated/created on IDC bindings.
22663 *
22664 * Returns 0 on success and -1 on internal errors.
22665 */
22666static int
22667xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22668			     int depth)
22669{
22670    xmlSchemaIDCStateObjPtr sto, nextsto;
22671    int res, matchDepth;
22672    xmlSchemaPSVIIDCKeyPtr key = NULL;
22673    xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22674
22675    if (vctxt->xpathStates == NULL)
22676	return (0);
22677    sto = vctxt->xpathStates;
22678
22679#ifdef DEBUG_IDC
22680    {
22681	xmlChar *str = NULL;
22682	xmlGenericError(xmlGenericErrorContext,
22683	    "IDC: BACK on %s, depth %d\n",
22684	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22685		vctxt->inode->localName), vctxt->depth);
22686	FREE_AND_NULL(str)
22687    }
22688#endif
22689    /*
22690    * Evaluate the state objects.
22691    */
22692    while (sto != NULL) {
22693	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22694	if (res == -1) {
22695	    VERROR_INT("xmlSchemaXPathProcessHistory",
22696		"calling xmlStreamPop()");
22697	    return (-1);
22698	}
22699#ifdef DEBUG_IDC
22700	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22701	    sto->sel->xpath);
22702#endif
22703	if (sto->nbHistory == 0)
22704	    goto deregister_check;
22705
22706	matchDepth = sto->history[sto->nbHistory -1];
22707
22708	/*
22709	* Only matches at the current depth are of interest.
22710	*/
22711	if (matchDepth != depth) {
22712	    sto = sto->next;
22713	    continue;
22714	}
22715	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22716	    /*
22717	    * NOTE: According to
22718	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22719	    *   ... the simple-content of complex types is also allowed.
22720	    */
22721
22722	    if (WXS_IS_COMPLEX(type)) {
22723		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22724		    /*
22725		    * Sanity check for complex types with simple content.
22726		    */
22727		    simpleType = type->contentTypeDef;
22728		    if (simpleType == NULL) {
22729			VERROR_INT("xmlSchemaXPathProcessHistory",
22730			    "field resolves to a CT with simple content "
22731			    "but the CT is missing the ST definition");
22732			return (-1);
22733		    }
22734		} else
22735		    simpleType = NULL;
22736	    } else
22737		simpleType = type;
22738	    if (simpleType == NULL) {
22739		xmlChar *str = NULL;
22740
22741		/*
22742		* Not qualified if the field resolves to a node of non
22743		* simple type.
22744		*/
22745		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22746		    XML_SCHEMAV_CVC_IDC, NULL,
22747		    WXS_BASIC_CAST sto->matcher->aidc->def,
22748		    "The XPath '%s' of a field of %s does evaluate to a node of "
22749		    "non-simple type",
22750		    sto->sel->xpath,
22751		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22752		FREE_AND_NULL(str);
22753		sto->nbHistory--;
22754		goto deregister_check;
22755	    }
22756
22757	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22758		/*
22759		* Failed to provide the normalized value; maybe
22760		* the value was invalid.
22761		*/
22762		VERROR(XML_SCHEMAV_CVC_IDC,
22763		    WXS_BASIC_CAST sto->matcher->aidc->def,
22764		    "Warning: No precomputed value available, the value "
22765		    "was either invalid or something strange happend");
22766		sto->nbHistory--;
22767		goto deregister_check;
22768	    } else {
22769		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22770		xmlSchemaPSVIIDCKeyPtr *keySeq;
22771		int pos, idx;
22772
22773		/*
22774		* The key will be anchored on the matcher's list of
22775		* key-sequences. The position in this list is determined
22776		* by the target node's depth relative to the matcher's
22777		* depth of creation (i.e. the depth of the scope element).
22778		*
22779		* Element        Depth    Pos   List-entries
22780		* <scope>          0              NULL
22781		*   <bar>          1              NULL
22782		*     <target/>    2       2      target
22783		*   <bar>
22784                * </scope>
22785		*
22786		* The size of the list is only dependant on the depth of
22787		* the tree.
22788		* An entry will be NULLed in selector_leave, i.e. when
22789		* we hit the target's
22790		*/
22791		pos = sto->depth - matcher->depth;
22792		idx = sto->sel->index;
22793
22794		/*
22795		* Create/grow the array of key-sequences.
22796		*/
22797		if (matcher->keySeqs == NULL) {
22798		    if (pos > 9)
22799			matcher->sizeKeySeqs = pos * 2;
22800		    else
22801			matcher->sizeKeySeqs = 10;
22802		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22803			xmlMalloc(matcher->sizeKeySeqs *
22804			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22805		    if (matcher->keySeqs == NULL) {
22806			xmlSchemaVErrMemory(NULL,
22807			    "allocating an array of key-sequences",
22808			    NULL);
22809			return(-1);
22810		    }
22811		    memset(matcher->keySeqs, 0,
22812			matcher->sizeKeySeqs *
22813			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22814		} else if (pos >= matcher->sizeKeySeqs) {
22815		    int i = matcher->sizeKeySeqs;
22816
22817		    matcher->sizeKeySeqs *= 2;
22818		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22819			xmlRealloc(matcher->keySeqs,
22820			matcher->sizeKeySeqs *
22821			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22822		    if (matcher->keySeqs == NULL) {
22823			xmlSchemaVErrMemory(NULL,
22824			    "reallocating an array of key-sequences",
22825			    NULL);
22826			return (-1);
22827		    }
22828		    /*
22829		    * The array needs to be NULLed.
22830		    * TODO: Use memset?
22831		    */
22832		    for (; i < matcher->sizeKeySeqs; i++)
22833			matcher->keySeqs[i] = NULL;
22834		}
22835
22836		/*
22837		* Get/create the key-sequence.
22838		*/
22839		keySeq = matcher->keySeqs[pos];
22840		if (keySeq == NULL) {
22841		    goto create_sequence;
22842		} else if (keySeq[idx] != NULL) {
22843		    xmlChar *str = NULL;
22844		    /*
22845		    * cvc-identity-constraint:
22846		    * 3 For each node in the `target node set` all
22847		    * of the {fields}, with that node as the context
22848		    * node, evaluate to either an empty node-set or
22849		    * a node-set with exactly one member, which must
22850		    * have a simple type.
22851		    *
22852		    * The key was already set; report an error.
22853		    */
22854		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22855			XML_SCHEMAV_CVC_IDC, NULL,
22856			WXS_BASIC_CAST matcher->aidc->def,
22857			"The XPath '%s' of a field of %s evaluates to a "
22858			"node-set with more than one member",
22859			sto->sel->xpath,
22860			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22861		    FREE_AND_NULL(str);
22862		    sto->nbHistory--;
22863		    goto deregister_check;
22864		} else
22865		    goto create_key;
22866
22867create_sequence:
22868		/*
22869		* Create a key-sequence.
22870		*/
22871		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22872		    matcher->aidc->def->nbFields *
22873		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22874		if (keySeq == NULL) {
22875		    xmlSchemaVErrMemory(NULL,
22876			"allocating an IDC key-sequence", NULL);
22877		    return(-1);
22878		}
22879		memset(keySeq, 0, matcher->aidc->def->nbFields *
22880		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22881		matcher->keySeqs[pos] = keySeq;
22882create_key:
22883		/*
22884		* Create a key once per node only.
22885		*/
22886		if (key == NULL) {
22887		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22888			sizeof(xmlSchemaPSVIIDCKey));
22889		    if (key == NULL) {
22890			xmlSchemaVErrMemory(NULL,
22891			    "allocating a IDC key", NULL);
22892			xmlFree(keySeq);
22893			matcher->keySeqs[pos] = NULL;
22894			return(-1);
22895		    }
22896		    /*
22897		    * Consume the compiled value.
22898		    */
22899		    key->type = simpleType;
22900		    key->val = vctxt->inode->val;
22901		    vctxt->inode->val = NULL;
22902		    /*
22903		    * Store the key in a global list.
22904		    */
22905		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22906			xmlSchemaIDCFreeKey(key);
22907			return (-1);
22908		    }
22909		}
22910		keySeq[idx] = key;
22911	    }
22912	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22913
22914	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22915	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22916	    xmlSchemaPSVIIDCNodePtr ntItem;
22917	    xmlSchemaIDCMatcherPtr matcher;
22918	    xmlSchemaIDCPtr idc;
22919	    xmlSchemaItemListPtr targets;
22920	    int pos, i, j, nbKeys;
22921	    /*
22922	    * Here we have the following scenario:
22923	    * An IDC 'selector' state object resolved to a target node,
22924	    * during the time this target node was in the
22925	    * ancestor-or-self axis, the 'field' state object(s) looked
22926	    * out for matching nodes to create a key-sequence for this
22927	    * target node. Now we are back to this target node and need
22928	    * to put the key-sequence, together with the target node
22929	    * itself, into the node-table of the corresponding IDC
22930	    * binding.
22931	    */
22932	    matcher = sto->matcher;
22933	    idc = matcher->aidc->def;
22934	    nbKeys = idc->nbFields;
22935	    pos = depth - matcher->depth;
22936	    /*
22937	    * Check if the matcher has any key-sequences at all, plus
22938	    * if it has a key-sequence for the current target node.
22939	    */
22940	    if ((matcher->keySeqs == NULL) ||
22941		(matcher->sizeKeySeqs <= pos)) {
22942		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22943		    goto selector_key_error;
22944		else
22945		    goto selector_leave;
22946	    }
22947
22948	    keySeq = &(matcher->keySeqs[pos]);
22949	    if (*keySeq == NULL) {
22950		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22951		    goto selector_key_error;
22952		else
22953		    goto selector_leave;
22954	    }
22955
22956	    for (i = 0; i < nbKeys; i++) {
22957		if ((*keySeq)[i] == NULL) {
22958		    /*
22959		    * Not qualified, if not all fields did resolve.
22960		    */
22961		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22962			/*
22963			* All fields of a "key" IDC must resolve.
22964			*/
22965			goto selector_key_error;
22966		    }
22967		    goto selector_leave;
22968		}
22969	    }
22970	    /*
22971	    * All fields did resolve.
22972	    */
22973
22974	    /*
22975	    * 4.1 If the {identity-constraint category} is unique(/key),
22976	    * then no two members of the `qualified node set` have
22977	    * `key-sequences` whose members are pairwise equal, as
22978	    * defined by Equal in [XML Schemas: Datatypes].
22979	    *
22980	    * Get the IDC binding from the matcher and check for
22981	    * duplicate key-sequences.
22982	    */
22983#if 0
22984	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22985#endif
22986	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22987	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22988		(targets->nbItems != 0)) {
22989		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22990
22991		i = 0;
22992		res = 0;
22993		/*
22994		* Compare the key-sequences, key by key.
22995		*/
22996		do {
22997		    bkeySeq =
22998			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22999		    for (j = 0; j < nbKeys; j++) {
23000			ckey = (*keySeq)[j];
23001			bkey = bkeySeq[j];
23002			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23003			if (res == -1) {
23004			    return (-1);
23005			} else if (res == 0) {
23006			    /*
23007			    * One of the keys differs, so the key-sequence
23008			    * won't be equal; get out.
23009			    */
23010			    break;
23011			}
23012		    }
23013		    if (res == 1) {
23014			/*
23015			* Duplicate key-sequence found.
23016			*/
23017			break;
23018		    }
23019		    i++;
23020		} while (i < targets->nbItems);
23021		if (i != targets->nbItems) {
23022		    xmlChar *str = NULL, *strB = NULL;
23023		    /*
23024		    * TODO: Try to report the key-sequence.
23025		    */
23026		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23027			XML_SCHEMAV_CVC_IDC, NULL,
23028			WXS_BASIC_CAST idc,
23029			"Duplicate key-sequence %s in %s",
23030			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23031			    (*keySeq), nbKeys),
23032			xmlSchemaGetIDCDesignation(&strB, idc));
23033		    FREE_AND_NULL(str);
23034		    FREE_AND_NULL(strB);
23035		    goto selector_leave;
23036		}
23037	    }
23038	    /*
23039	    * Add a node-table item to the IDC binding.
23040	    */
23041	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23042		sizeof(xmlSchemaPSVIIDCNode));
23043	    if (ntItem == NULL) {
23044		xmlSchemaVErrMemory(NULL,
23045		    "allocating an IDC node-table item", NULL);
23046		xmlFree(*keySeq);
23047		*keySeq = NULL;
23048		return(-1);
23049	    }
23050	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23051
23052	    /*
23053	    * Store the node-table item in a global list.
23054	    */
23055	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23056		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23057		    xmlFree(ntItem);
23058		    xmlFree(*keySeq);
23059		    *keySeq = NULL;
23060		    return (-1);
23061		}
23062		ntItem->nodeQNameID = -1;
23063	    } else {
23064		/*
23065		* Save a cached QName for this node on the IDC node, to be
23066		* able to report it, even if the node is not saved.
23067		*/
23068		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23069		    vctxt->inode->localName, vctxt->inode->nsName);
23070		if (ntItem->nodeQNameID == -1) {
23071		    xmlFree(ntItem);
23072		    xmlFree(*keySeq);
23073		    *keySeq = NULL;
23074		    return (-1);
23075		}
23076	    }
23077	    /*
23078	    * Init the node-table item: Save the node, position and
23079	    * consume the key-sequence.
23080	    */
23081	    ntItem->node = vctxt->node;
23082	    ntItem->nodeLine = vctxt->inode->nodeLine;
23083	    ntItem->keys = *keySeq;
23084	    *keySeq = NULL;
23085#if 0
23086	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23087#endif
23088	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23089		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23090		    /*
23091		    * Free the item, since keyref items won't be
23092		    * put on a global list.
23093		    */
23094		    xmlFree(ntItem->keys);
23095		    xmlFree(ntItem);
23096		}
23097		return (-1);
23098	    }
23099
23100	    goto selector_leave;
23101selector_key_error:
23102	    {
23103		xmlChar *str = NULL;
23104		/*
23105		* 4.2.1 (KEY) The `target node set` and the
23106		* `qualified node set` are equal, that is, every
23107		* member of the `target node set` is also a member
23108		* of the `qualified node set` and vice versa.
23109		*/
23110		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23111		    XML_SCHEMAV_CVC_IDC, NULL,
23112		    WXS_BASIC_CAST idc,
23113		    "Not all fields of %s evaluate to a node",
23114		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23115		FREE_AND_NULL(str);
23116	    }
23117selector_leave:
23118	    /*
23119	    * Free the key-sequence if not added to the IDC table.
23120	    */
23121	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23122		xmlFree(*keySeq);
23123		*keySeq = NULL;
23124	    }
23125	} /* if selector */
23126
23127	sto->nbHistory--;
23128
23129deregister_check:
23130	/*
23131	* Deregister state objects if they reach the depth of creation.
23132	*/
23133	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23134#ifdef DEBUG_IDC
23135	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23136		sto->sel->xpath);
23137#endif
23138	    if (vctxt->xpathStates != sto) {
23139		VERROR_INT("xmlSchemaXPathProcessHistory",
23140		    "The state object to be removed is not the first "
23141		    "in the list");
23142	    }
23143	    nextsto = sto->next;
23144	    /*
23145	    * Unlink from the list of active XPath state objects.
23146	    */
23147	    vctxt->xpathStates = sto->next;
23148	    sto->next = vctxt->xpathStatePool;
23149	    /*
23150	    * Link it to the pool of reusable state objects.
23151	    */
23152	    vctxt->xpathStatePool = sto;
23153	    sto = nextsto;
23154	} else
23155	    sto = sto->next;
23156    } /* while (sto != NULL) */
23157    return (0);
23158}
23159
23160/**
23161 * xmlSchemaIDCRegisterMatchers:
23162 * @vctxt: the WXS validation context
23163 * @elemDecl: the element declaration
23164 *
23165 * Creates helper objects to evaluate IDC selectors/fields
23166 * successively.
23167 *
23168 * Returns 0 if OK and -1 on internal errors.
23169 */
23170static int
23171xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23172			     xmlSchemaElementPtr elemDecl)
23173{
23174    xmlSchemaIDCMatcherPtr matcher, last = NULL;
23175    xmlSchemaIDCPtr idc, refIdc;
23176    xmlSchemaIDCAugPtr aidc;
23177
23178    idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23179    if (idc == NULL)
23180	return (0);
23181
23182#ifdef DEBUG_IDC
23183    {
23184	xmlChar *str = NULL;
23185	xmlGenericError(xmlGenericErrorContext,
23186	    "IDC: REGISTER on %s, depth %d\n",
23187	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23188		vctxt->inode->localName), vctxt->depth);
23189	FREE_AND_NULL(str)
23190    }
23191#endif
23192    if (vctxt->inode->idcMatchers != NULL) {
23193	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23194	    "The chain of IDC matchers is expected to be empty");
23195	return (-1);
23196    }
23197    do {
23198	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23199	    /*
23200	    * Since IDCs bubbles are expensive we need to know the
23201	    * depth at which the bubbles should stop; this will be
23202	    * the depth of the top-most keyref IDC. If no keyref
23203	    * references a key/unique IDC, the keyrefDepth will
23204	    * be -1, indicating that no bubbles are needed.
23205	    */
23206	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23207	    if (refIdc != NULL) {
23208		/*
23209		* Remember that we have keyrefs on this node.
23210		*/
23211		vctxt->inode->hasKeyrefs = 1;
23212		/*
23213		* Lookup the referenced augmented IDC info.
23214		*/
23215		aidc = vctxt->aidcs;
23216		while (aidc != NULL) {
23217		    if (aidc->def == refIdc)
23218			break;
23219		    aidc = aidc->next;
23220		}
23221		if (aidc == NULL) {
23222		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23223			"Could not find an augmented IDC item for an IDC "
23224			"definition");
23225		    return (-1);
23226		}
23227		if ((aidc->keyrefDepth == -1) ||
23228		    (vctxt->depth < aidc->keyrefDepth))
23229		    aidc->keyrefDepth = vctxt->depth;
23230	    }
23231	}
23232	/*
23233	* Lookup the augmented IDC item for the IDC definition.
23234	*/
23235	aidc = vctxt->aidcs;
23236	while (aidc != NULL) {
23237	    if (aidc->def == idc)
23238		break;
23239	    aidc = aidc->next;
23240	}
23241	if (aidc == NULL) {
23242	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23243		"Could not find an augmented IDC item for an IDC definition");
23244	    return (-1);
23245	}
23246	/*
23247	* Create an IDC matcher for every IDC definition.
23248	*/
23249	if (vctxt->idcMatcherCache != NULL) {
23250	    /*
23251	    * Reuse a cached matcher.
23252	    */
23253	    matcher = vctxt->idcMatcherCache;
23254	    vctxt->idcMatcherCache = matcher->nextCached;
23255	    matcher->nextCached = NULL;
23256	} else {
23257	    matcher = (xmlSchemaIDCMatcherPtr)
23258		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23259	    if (matcher == NULL) {
23260		xmlSchemaVErrMemory(vctxt,
23261		    "allocating an IDC matcher", NULL);
23262		return (-1);
23263	    }
23264	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23265	}
23266	if (last == NULL)
23267	    vctxt->inode->idcMatchers = matcher;
23268	else
23269	    last->next = matcher;
23270	last = matcher;
23271
23272	matcher->type = IDC_MATCHER;
23273	matcher->depth = vctxt->depth;
23274	matcher->aidc = aidc;
23275	matcher->idcType = aidc->def->type;
23276#ifdef DEBUG_IDC
23277	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23278#endif
23279	/*
23280	* Init the automaton state object.
23281	*/
23282	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23283	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23284	    return (-1);
23285
23286	idc = idc->next;
23287    } while (idc != NULL);
23288    return (0);
23289}
23290
23291static int
23292xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23293			   xmlSchemaNodeInfoPtr ielem)
23294{
23295    xmlSchemaPSVIIDCBindingPtr bind;
23296    int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23297    xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23298    xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23299
23300    xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23301    /* vctxt->createIDCNodeTables */
23302    while (matcher != NULL) {
23303	/*
23304	* Skip keyref IDCs and empty IDC target-lists.
23305	*/
23306	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23307	    WXS_ILIST_IS_EMPTY(matcher->targets))
23308	{
23309	    matcher = matcher->next;
23310	    continue;
23311	}
23312	/*
23313	* If we _want_ the IDC node-table to be created in any case
23314	* then do so. Otherwise create them only if keyrefs need them.
23315	*/
23316	if ((! vctxt->createIDCNodeTables) &&
23317	    ((matcher->aidc->keyrefDepth == -1) ||
23318	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23319	{
23320	    matcher = matcher->next;
23321	    continue;
23322	}
23323	/*
23324	* Get/create the IDC binding on this element for the IDC definition.
23325	*/
23326	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23327
23328	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23329	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23330	    nbDupls = bind->dupls->nbItems;
23331	} else {
23332	    dupls = NULL;
23333	    nbDupls = 0;
23334	}
23335	if (bind->nodeTable != NULL) {
23336	    nbNodeTable = bind->nbNodes;
23337	} else {
23338	    nbNodeTable = 0;
23339	}
23340
23341	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23342	    /*
23343	    * Transfer all IDC target-nodes to the IDC node-table.
23344	    */
23345	    bind->nodeTable =
23346		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23347	    bind->sizeNodes = matcher->targets->sizeItems;
23348	    bind->nbNodes = matcher->targets->nbItems;
23349
23350	    matcher->targets->items = NULL;
23351	    matcher->targets->sizeItems = 0;
23352	    matcher->targets->nbItems = 0;
23353	} else {
23354	    /*
23355	    * Compare the key-sequences and add to the IDC node-table.
23356	    */
23357	    nbTargets = matcher->targets->nbItems;
23358	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23359	    nbFields = matcher->aidc->def->nbFields;
23360	    i = 0;
23361	    do {
23362		keys = targets[i]->keys;
23363		if (nbDupls) {
23364		    /*
23365		    * Search in already found duplicates first.
23366		    */
23367		    j = 0;
23368		    do {
23369			if (nbFields == 1) {
23370			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23371				dupls[j]->keys[0]->val);
23372			    if (res == -1)
23373				goto internal_error;
23374			    if (res == 1) {
23375				/*
23376				* Equal key-sequence.
23377				*/
23378				goto next_target;
23379			    }
23380			} else {
23381			    res = 0;
23382			    ntkeys = dupls[j]->keys;
23383			    for (k = 0; k < nbFields; k++) {
23384				res = xmlSchemaAreValuesEqual(keys[k]->val,
23385				    ntkeys[k]->val);
23386				if (res == -1)
23387				    goto internal_error;
23388				if (res == 0) {
23389				    /*
23390				    * One of the keys differs.
23391				    */
23392				    break;
23393				}
23394			    }
23395			    if (res == 1) {
23396				/*
23397				* Equal key-sequence found.
23398				*/
23399				goto next_target;
23400			    }
23401			}
23402			j++;
23403		    } while (j < nbDupls);
23404		}
23405		if (nbNodeTable) {
23406		    j = 0;
23407		    do {
23408			if (nbFields == 1) {
23409			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23410				bind->nodeTable[j]->keys[0]->val);
23411			    if (res == -1)
23412				goto internal_error;
23413			    if (res == 0) {
23414				/*
23415				* The key-sequence differs.
23416				*/
23417				goto next_node_table_entry;
23418			    }
23419			} else {
23420			    res = 0;
23421			    ntkeys = bind->nodeTable[j]->keys;
23422			    for (k = 0; k < nbFields; k++) {
23423				res = xmlSchemaAreValuesEqual(keys[k]->val,
23424				    ntkeys[k]->val);
23425				if (res == -1)
23426				    goto internal_error;
23427				if (res == 0) {
23428				    /*
23429				    * One of the keys differs.
23430				    */
23431				    goto next_node_table_entry;
23432				}
23433			    }
23434			}
23435			/*
23436			* Add the duplicate to the list of duplicates.
23437			*/
23438			if (bind->dupls == NULL) {
23439			    bind->dupls = xmlSchemaItemListCreate();
23440			    if (bind->dupls == NULL)
23441				goto internal_error;
23442			}
23443			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23444			    goto internal_error;
23445			/*
23446			* Remove the duplicate entry from the IDC node-table.
23447			*/
23448			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23449			bind->nbNodes--;
23450
23451			goto next_target;
23452
23453next_node_table_entry:
23454			j++;
23455		    } while (j < nbNodeTable);
23456		}
23457		/*
23458		* If everything is fine, then add the IDC target-node to
23459		* the IDC node-table.
23460		*/
23461		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23462		    goto internal_error;
23463
23464next_target:
23465		i++;
23466	    } while (i < nbTargets);
23467	}
23468	matcher = matcher->next;
23469    }
23470    return(0);
23471
23472internal_error:
23473    return(-1);
23474}
23475
23476/**
23477 * xmlSchemaBubbleIDCNodeTables:
23478 * @depth: the current tree depth
23479 *
23480 * Merges IDC bindings of an element at @depth into the corresponding IDC
23481 * bindings of its parent element. If a duplicate note-table entry is found,
23482 * both, the parent node-table entry and child entry are discarded from the
23483 * node-table of the parent.
23484 *
23485 * Returns 0 if OK and -1 on internal errors.
23486 */
23487static int
23488xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23489{
23490    xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23491    xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23492    xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23493    xmlSchemaIDCAugPtr aidc;
23494    int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23495
23496    bind = vctxt->inode->idcTable;
23497    if (bind == NULL) {
23498	/* Fine, no table, no bubbles. */
23499	return (0);
23500    }
23501
23502    parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23503    /*
23504    * Walk all bindings; create new or add to existing bindings.
23505    * Remove duplicate key-sequences.
23506    */
23507    while (bind != NULL) {
23508
23509	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23510	    goto next_binding;
23511	/*
23512	* Check if the key/unique IDC table needs to be bubbled.
23513	*/
23514	if (! vctxt->createIDCNodeTables) {
23515	    aidc = vctxt->aidcs;
23516	    do {
23517		if (aidc->def == bind->definition) {
23518		    if ((aidc->keyrefDepth == -1) ||
23519			(aidc->keyrefDepth >= vctxt->depth)) {
23520			goto next_binding;
23521		    }
23522		    break;
23523		}
23524		aidc = aidc->next;
23525	    } while (aidc != NULL);
23526	}
23527
23528	if (parTable != NULL)
23529	    parBind = *parTable;
23530	/*
23531	* Search a matching parent binding for the
23532	* IDC definition.
23533	*/
23534	while (parBind != NULL) {
23535	    if (parBind->definition == bind->definition)
23536		break;
23537	    parBind = parBind->next;
23538	}
23539
23540	if (parBind != NULL) {
23541	    /*
23542	    * Compare every node-table entry of the child node,
23543	    * i.e. the key-sequence within, ...
23544	    */
23545	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23546
23547	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23548		oldDupls = parBind->dupls->nbItems;
23549		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23550	    } else {
23551		dupls = NULL;
23552		oldDupls = 0;
23553	    }
23554
23555	    parNodes = parBind->nodeTable;
23556	    nbFields = bind->definition->nbFields;
23557
23558	    for (i = 0; i < bind->nbNodes; i++) {
23559		node = bind->nodeTable[i];
23560		if (node == NULL)
23561		    continue;
23562		/*
23563		* ...with every key-sequence of the parent node, already
23564		* evaluated to be a duplicate key-sequence.
23565		*/
23566		if (oldDupls) {
23567		    j = 0;
23568		    while (j < oldDupls) {
23569			if (nbFields == 1) {
23570			    ret = xmlSchemaAreValuesEqual(
23571				node->keys[0]->val,
23572				dupls[j]->keys[0]->val);
23573			    if (ret == -1)
23574				goto internal_error;
23575			    if (ret == 0) {
23576				j++;
23577				continue;
23578			    }
23579			} else {
23580			    parNode = dupls[j];
23581			    for (k = 0; k < nbFields; k++) {
23582				ret = xmlSchemaAreValuesEqual(
23583				    node->keys[k]->val,
23584				    parNode->keys[k]->val);
23585				if (ret == -1)
23586				    goto internal_error;
23587				if (ret == 0)
23588				    break;
23589			    }
23590			}
23591			if (ret == 1)
23592			    /* Duplicate found. */
23593			    break;
23594			j++;
23595		    }
23596		    if (j != oldDupls) {
23597			/* Duplicate found. Skip this entry. */
23598			continue;
23599		    }
23600		}
23601		/*
23602		* ... and with every key-sequence of the parent node.
23603		*/
23604		if (oldNum) {
23605		    j = 0;
23606		    while (j < oldNum) {
23607			parNode = parNodes[j];
23608			if (nbFields == 1) {
23609			    ret = xmlSchemaAreValuesEqual(
23610				node->keys[0]->val,
23611				parNode->keys[0]->val);
23612			    if (ret == -1)
23613				goto internal_error;
23614			    if (ret == 0) {
23615				j++;
23616				continue;
23617			    }
23618			} else {
23619			    for (k = 0; k < nbFields; k++) {
23620				ret = xmlSchemaAreValuesEqual(
23621				    node->keys[k]->val,
23622				    parNode->keys[k]->val);
23623				if (ret == -1)
23624				    goto internal_error;
23625				if (ret == 0)
23626				    break;
23627			    }
23628			}
23629			if (ret == 1)
23630			    /* Duplicate found. */
23631			    break;
23632			j++;
23633		    }
23634		    if (j != oldNum) {
23635			/*
23636			* Handle duplicates. Move the duplicate in
23637			* the parent's node-table to the list of
23638			* duplicates.
23639			*/
23640			oldNum--;
23641			parBind->nbNodes--;
23642			/*
23643			* Move last old item to pos of duplicate.
23644			*/
23645			parNodes[j] = parNodes[oldNum];
23646
23647			if (parBind->nbNodes != oldNum) {
23648			    /*
23649			    * If new items exist, move last new item to
23650			    * last of old items.
23651			    */
23652			    parNodes[oldNum] =
23653				parNodes[parBind->nbNodes];
23654			}
23655			if (parBind->dupls == NULL) {
23656			    parBind->dupls = xmlSchemaItemListCreate();
23657			    if (parBind->dupls == NULL)
23658				goto internal_error;
23659			}
23660			xmlSchemaItemListAdd(parBind->dupls, parNode);
23661		    } else {
23662			/*
23663			* Add the node-table entry (node and key-sequence) of
23664			* the child node to the node table of the parent node.
23665			*/
23666			if (parBind->nodeTable == NULL) {
23667			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23668				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23669			    if (parBind->nodeTable == NULL) {
23670				xmlSchemaVErrMemory(NULL,
23671				    "allocating IDC list of node-table items", NULL);
23672				goto internal_error;
23673			    }
23674			    parBind->sizeNodes = 1;
23675			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23676			    parBind->sizeNodes *= 2;
23677			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23678				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23679				sizeof(xmlSchemaPSVIIDCNodePtr));
23680			    if (parBind->nodeTable == NULL) {
23681				xmlSchemaVErrMemory(NULL,
23682				    "re-allocating IDC list of node-table items", NULL);
23683				goto internal_error;
23684			    }
23685			}
23686			parNodes = parBind->nodeTable;
23687			/*
23688			* Append the new node-table entry to the 'new node-table
23689			* entries' section.
23690			*/
23691			parNodes[parBind->nbNodes++] = node;
23692		    }
23693
23694		}
23695
23696	    }
23697	} else {
23698	    /*
23699	    * No binding for the IDC was found: create a new one and
23700	    * copy all node-tables.
23701	    */
23702	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23703	    if (parBind == NULL)
23704		goto internal_error;
23705
23706	    /*
23707	    * TODO: Hmm, how to optimize the initial number of
23708	    * allocated entries?
23709	    */
23710	    if (bind->nbNodes != 0) {
23711		/*
23712		* Add all IDC node-table entries.
23713		*/
23714		if (! vctxt->psviExposeIDCNodeTables) {
23715		    /*
23716		    * Just move the entries.
23717		    * NOTE: this is quite save here, since
23718		    * all the keyref lookups have already been
23719		    * performed.
23720		    */
23721		    parBind->nodeTable = bind->nodeTable;
23722		    bind->nodeTable = NULL;
23723		    parBind->sizeNodes = bind->sizeNodes;
23724		    bind->sizeNodes = 0;
23725		    parBind->nbNodes = bind->nbNodes;
23726		    bind->nbNodes = 0;
23727		} else {
23728		    /*
23729		    * Copy the entries.
23730		    */
23731		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23732			xmlMalloc(bind->nbNodes *
23733			sizeof(xmlSchemaPSVIIDCNodePtr));
23734		    if (parBind->nodeTable == NULL) {
23735			xmlSchemaVErrMemory(NULL,
23736			    "allocating an array of IDC node-table "
23737			    "items", NULL);
23738			xmlSchemaIDCFreeBinding(parBind);
23739			goto internal_error;
23740		    }
23741		    parBind->sizeNodes = bind->nbNodes;
23742		    parBind->nbNodes = bind->nbNodes;
23743		    memcpy(parBind->nodeTable, bind->nodeTable,
23744			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23745		}
23746	    }
23747	    if (bind->dupls) {
23748		/*
23749		* Move the duplicates.
23750		*/
23751		if (parBind->dupls != NULL)
23752		    xmlSchemaItemListFree(parBind->dupls);
23753		parBind->dupls = bind->dupls;
23754		bind->dupls = NULL;
23755	    }
23756            if (parTable != NULL) {
23757                if (*parTable == NULL)
23758                    *parTable = parBind;
23759                else {
23760                    parBind->next = *parTable;
23761                    *parTable = parBind;
23762                }
23763            }
23764	}
23765
23766next_binding:
23767	bind = bind->next;
23768    }
23769    return (0);
23770
23771internal_error:
23772    return(-1);
23773}
23774
23775/**
23776 * xmlSchemaCheckCVCIDCKeyRef:
23777 * @vctxt: the WXS validation context
23778 * @elemDecl: the element declaration
23779 *
23780 * Check the cvc-idc-keyref constraints.
23781 */
23782static int
23783xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23784{
23785    xmlSchemaIDCMatcherPtr matcher;
23786    xmlSchemaPSVIIDCBindingPtr bind;
23787
23788    matcher = vctxt->inode->idcMatchers;
23789    /*
23790    * Find a keyref.
23791    */
23792    while (matcher != NULL) {
23793	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23794	    matcher->targets &&
23795	    matcher->targets->nbItems)
23796	{
23797	    int i, j, k, res, nbFields, hasDupls;
23798	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23799	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23800
23801	    nbFields = matcher->aidc->def->nbFields;
23802
23803	    /*
23804	    * Find the IDC node-table for the referenced IDC key/unique.
23805	    */
23806	    bind = vctxt->inode->idcTable;
23807	    while (bind != NULL) {
23808		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23809		    bind->definition)
23810		    break;
23811		bind = bind->next;
23812	    }
23813	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23814	    /*
23815	    * Search for a matching key-sequences.
23816	    */
23817	    for (i = 0; i < matcher->targets->nbItems; i++) {
23818		res = 0;
23819		refNode = matcher->targets->items[i];
23820		if (bind != NULL) {
23821		    refKeys = refNode->keys;
23822		    for (j = 0; j < bind->nbNodes; j++) {
23823			keys = bind->nodeTable[j]->keys;
23824			for (k = 0; k < nbFields; k++) {
23825			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23826				refKeys[k]->val);
23827			    if (res == 0)
23828				break;
23829			    else if (res == -1) {
23830				return (-1);
23831			    }
23832			}
23833			if (res == 1) {
23834			    /*
23835			    * Match found.
23836			    */
23837			    break;
23838			}
23839		    }
23840		    if ((res == 0) && hasDupls) {
23841			/*
23842			* Search in duplicates
23843			*/
23844			for (j = 0; j < bind->dupls->nbItems; j++) {
23845			    keys = ((xmlSchemaPSVIIDCNodePtr)
23846				bind->dupls->items[j])->keys;
23847			    for (k = 0; k < nbFields; k++) {
23848				res = xmlSchemaAreValuesEqual(keys[k]->val,
23849				    refKeys[k]->val);
23850				if (res == 0)
23851				    break;
23852				else if (res == -1) {
23853				    return (-1);
23854				}
23855			    }
23856			    if (res == 1) {
23857				/*
23858				* Match in duplicates found.
23859				*/
23860				xmlChar *str = NULL, *strB = NULL;
23861				xmlSchemaKeyrefErr(vctxt,
23862				    XML_SCHEMAV_CVC_IDC, refNode,
23863				    (xmlSchemaTypePtr) matcher->aidc->def,
23864				    "More than one match found for "
23865				    "key-sequence %s of keyref '%s'",
23866				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23867					refNode->keys, nbFields),
23868				    xmlSchemaGetComponentQName(&strB,
23869					matcher->aidc->def));
23870				FREE_AND_NULL(str);
23871				FREE_AND_NULL(strB);
23872				break;
23873			    }
23874			}
23875		    }
23876		}
23877
23878		if (res == 0) {
23879		    xmlChar *str = NULL, *strB = NULL;
23880		    xmlSchemaKeyrefErr(vctxt,
23881			XML_SCHEMAV_CVC_IDC, refNode,
23882			(xmlSchemaTypePtr) matcher->aidc->def,
23883			"No match found for key-sequence %s of keyref '%s'",
23884			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23885			    refNode->keys, nbFields),
23886			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23887		    FREE_AND_NULL(str);
23888		    FREE_AND_NULL(strB);
23889		}
23890	    }
23891	}
23892	matcher = matcher->next;
23893    }
23894    /* TODO: Return an error if any error encountered. */
23895    return (0);
23896}
23897
23898/************************************************************************
23899 *									*
23900 *			XML Reader validation code                      *
23901 *									*
23902 ************************************************************************/
23903
23904static xmlSchemaAttrInfoPtr
23905xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23906{
23907    xmlSchemaAttrInfoPtr iattr;
23908    /*
23909    * Grow/create list of attribute infos.
23910    */
23911    if (vctxt->attrInfos == NULL) {
23912	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23913	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23914	vctxt->sizeAttrInfos = 1;
23915	if (vctxt->attrInfos == NULL) {
23916	    xmlSchemaVErrMemory(vctxt,
23917		"allocating attribute info list", NULL);
23918	    return (NULL);
23919	}
23920    } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23921	vctxt->sizeAttrInfos++;
23922	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23923	    xmlRealloc(vctxt->attrInfos,
23924		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23925	if (vctxt->attrInfos == NULL) {
23926	    xmlSchemaVErrMemory(vctxt,
23927		"re-allocating attribute info list", NULL);
23928	    return (NULL);
23929	}
23930    } else {
23931	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23932	if (iattr->localName != NULL) {
23933	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23934		"attr info not cleared");
23935	    return (NULL);
23936	}
23937	iattr->nodeType = XML_ATTRIBUTE_NODE;
23938	return (iattr);
23939    }
23940    /*
23941    * Create an attribute info.
23942    */
23943    iattr = (xmlSchemaAttrInfoPtr)
23944	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23945    if (iattr == NULL) {
23946	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23947	return (NULL);
23948    }
23949    memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23950    iattr->nodeType = XML_ATTRIBUTE_NODE;
23951    vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23952
23953    return (iattr);
23954}
23955
23956static int
23957xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23958			xmlNodePtr attrNode,
23959			int nodeLine,
23960			const xmlChar *localName,
23961			const xmlChar *nsName,
23962			int ownedNames,
23963			xmlChar *value,
23964			int ownedValue)
23965{
23966    xmlSchemaAttrInfoPtr attr;
23967
23968    attr = xmlSchemaGetFreshAttrInfo(vctxt);
23969    if (attr == NULL) {
23970	VERROR_INT("xmlSchemaPushAttribute",
23971	    "calling xmlSchemaGetFreshAttrInfo()");
23972	return (-1);
23973    }
23974    attr->node = attrNode;
23975    attr->nodeLine = nodeLine;
23976    attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23977    attr->localName = localName;
23978    attr->nsName = nsName;
23979    if (ownedNames)
23980	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23981    /*
23982    * Evaluate if it's an XSI attribute.
23983    */
23984    if (nsName != NULL) {
23985	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23986	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23987		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23988	    }
23989	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23990	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23991		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23992	    }
23993	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23994	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23995		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23996	    }
23997	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23998	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23999		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24000	    }
24001	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24002	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24003	}
24004    }
24005    attr->value = value;
24006    if (ownedValue)
24007	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24008    if (attr->metaType != 0)
24009	attr->state = XML_SCHEMAS_ATTR_META;
24010    return (0);
24011}
24012
24013/**
24014 * xmlSchemaClearElemInfo:
24015 * @vctxt: the WXS validation context
24016 * @ielem: the element information item
24017 */
24018static void
24019xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24020		       xmlSchemaNodeInfoPtr ielem)
24021{
24022    ielem->hasKeyrefs = 0;
24023    ielem->appliedXPath = 0;
24024    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24025	FREE_AND_NULL(ielem->localName);
24026	FREE_AND_NULL(ielem->nsName);
24027    } else {
24028	ielem->localName = NULL;
24029	ielem->nsName = NULL;
24030    }
24031    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24032	FREE_AND_NULL(ielem->value);
24033    } else {
24034	ielem->value = NULL;
24035    }
24036    if (ielem->val != NULL) {
24037	/*
24038	* PSVI TODO: Be careful not to free it when the value is
24039	* exposed via PSVI.
24040	*/
24041	xmlSchemaFreeValue(ielem->val);
24042	ielem->val = NULL;
24043    }
24044    if (ielem->idcMatchers != NULL) {
24045	/*
24046	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24047	*   Does it work?
24048	*/
24049	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24050#if 0
24051	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24052#endif
24053	ielem->idcMatchers = NULL;
24054    }
24055    if (ielem->idcTable != NULL) {
24056	/*
24057	* OPTIMIZE TODO: Use a pool of IDC tables??.
24058	*/
24059	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24060	ielem->idcTable = NULL;
24061    }
24062    if (ielem->regexCtxt != NULL) {
24063	xmlRegFreeExecCtxt(ielem->regexCtxt);
24064	ielem->regexCtxt = NULL;
24065    }
24066    if (ielem->nsBindings != NULL) {
24067	xmlFree((xmlChar **)ielem->nsBindings);
24068	ielem->nsBindings = NULL;
24069	ielem->nbNsBindings = 0;
24070	ielem->sizeNsBindings = 0;
24071    }
24072}
24073
24074/**
24075 * xmlSchemaGetFreshElemInfo:
24076 * @vctxt: the schema validation context
24077 *
24078 * Creates/reuses and initializes the element info item for
24079 * the currect tree depth.
24080 *
24081 * Returns the element info item or NULL on API or internal errors.
24082 */
24083static xmlSchemaNodeInfoPtr
24084xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24085{
24086    xmlSchemaNodeInfoPtr info = NULL;
24087
24088    if (vctxt->depth > vctxt->sizeElemInfos) {
24089	VERROR_INT("xmlSchemaGetFreshElemInfo",
24090	    "inconsistent depth encountered");
24091	return (NULL);
24092    }
24093    if (vctxt->elemInfos == NULL) {
24094	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24095	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24096	if (vctxt->elemInfos == NULL) {
24097	    xmlSchemaVErrMemory(vctxt,
24098		"allocating the element info array", NULL);
24099	    return (NULL);
24100	}
24101	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24102	vctxt->sizeElemInfos = 10;
24103    } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24104	int i = vctxt->sizeElemInfos;
24105
24106	vctxt->sizeElemInfos *= 2;
24107	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24108	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24109	    sizeof(xmlSchemaNodeInfoPtr));
24110	if (vctxt->elemInfos == NULL) {
24111	    xmlSchemaVErrMemory(vctxt,
24112		"re-allocating the element info array", NULL);
24113	    return (NULL);
24114	}
24115	/*
24116	* We need the new memory to be NULLed.
24117	* TODO: Use memset instead?
24118	*/
24119	for (; i < vctxt->sizeElemInfos; i++)
24120	    vctxt->elemInfos[i] = NULL;
24121    } else
24122	info = vctxt->elemInfos[vctxt->depth];
24123
24124    if (info == NULL) {
24125	info = (xmlSchemaNodeInfoPtr)
24126	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24127	if (info == NULL) {
24128	    xmlSchemaVErrMemory(vctxt,
24129		"allocating an element info", NULL);
24130	    return (NULL);
24131	}
24132	vctxt->elemInfos[vctxt->depth] = info;
24133    } else {
24134	if (info->localName != NULL) {
24135	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24136		"elem info has not been cleared");
24137	    return (NULL);
24138	}
24139    }
24140    memset(info, 0, sizeof(xmlSchemaNodeInfo));
24141    info->nodeType = XML_ELEMENT_NODE;
24142    info->depth = vctxt->depth;
24143
24144    return (info);
24145}
24146
24147#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24148#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24149#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24150
24151static int
24152xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24153			xmlNodePtr node,
24154			xmlSchemaTypePtr type,
24155			xmlSchemaValType valType,
24156			const xmlChar * value,
24157			xmlSchemaValPtr val,
24158			unsigned long length,
24159			int fireErrors)
24160{
24161    int ret, error = 0;
24162
24163    xmlSchemaTypePtr tmpType;
24164    xmlSchemaFacetLinkPtr facetLink;
24165    xmlSchemaFacetPtr facet;
24166    unsigned long len = 0;
24167    xmlSchemaWhitespaceValueType ws;
24168
24169    /*
24170    * In Libxml2, derived built-in types have currently no explicit facets.
24171    */
24172    if (type->type == XML_SCHEMA_TYPE_BASIC)
24173	return (0);
24174
24175    /*
24176    * NOTE: Do not jump away, if the facetSet of the given type is
24177    * empty: until now, "pattern" and "enumeration" facets of the
24178    * *base types* need to be checked as well.
24179    */
24180    if (type->facetSet == NULL)
24181	goto pattern_and_enum;
24182
24183    if (! WXS_IS_ATOMIC(type)) {
24184	if (WXS_IS_LIST(type))
24185	    goto WXS_IS_LIST;
24186	else
24187	    goto pattern_and_enum;
24188    }
24189    /*
24190    * Whitespace handling is only of importance for string-based
24191    * types.
24192    */
24193    tmpType = xmlSchemaGetPrimitiveType(type);
24194    if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24195	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24196	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24197    } else
24198	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24199    /*
24200    * If the value was not computed (for string or
24201    * anySimpleType based types), then use the provided
24202    * type.
24203    */
24204    if (val == NULL)
24205	valType = valType;
24206    else
24207	valType = xmlSchemaGetValType(val);
24208
24209    ret = 0;
24210    for (facetLink = type->facetSet; facetLink != NULL;
24211	facetLink = facetLink->next) {
24212	/*
24213	* Skip the pattern "whiteSpace": it is used to
24214	* format the character content beforehand.
24215	*/
24216	switch (facetLink->facet->type) {
24217	    case XML_SCHEMA_FACET_WHITESPACE:
24218	    case XML_SCHEMA_FACET_PATTERN:
24219	    case XML_SCHEMA_FACET_ENUMERATION:
24220		continue;
24221	    case XML_SCHEMA_FACET_LENGTH:
24222	    case XML_SCHEMA_FACET_MINLENGTH:
24223	    case XML_SCHEMA_FACET_MAXLENGTH:
24224		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24225		    valType, value, val, &len, ws);
24226		break;
24227	    default:
24228		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24229		    valType, value, val, ws);
24230		break;
24231	}
24232	if (ret < 0) {
24233	    AERROR_INT("xmlSchemaValidateFacets",
24234		"validating against a atomic type facet");
24235	    return (-1);
24236	} else if (ret > 0) {
24237	    if (fireErrors)
24238		xmlSchemaFacetErr(actxt, ret, node,
24239		value, len, type, facetLink->facet, NULL, NULL, NULL);
24240	    else
24241		return (ret);
24242	    if (error == 0)
24243		error = ret;
24244	}
24245	ret = 0;
24246    }
24247
24248WXS_IS_LIST:
24249    if (! WXS_IS_LIST(type))
24250	goto pattern_and_enum;
24251    /*
24252    * "length", "minLength" and "maxLength" of list types.
24253    */
24254    ret = 0;
24255    for (facetLink = type->facetSet; facetLink != NULL;
24256	facetLink = facetLink->next) {
24257
24258	switch (facetLink->facet->type) {
24259	    case XML_SCHEMA_FACET_LENGTH:
24260	    case XML_SCHEMA_FACET_MINLENGTH:
24261	    case XML_SCHEMA_FACET_MAXLENGTH:
24262		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24263		    value, length, NULL);
24264		break;
24265	    default:
24266		continue;
24267	}
24268	if (ret < 0) {
24269	    AERROR_INT("xmlSchemaValidateFacets",
24270		"validating against a list type facet");
24271	    return (-1);
24272	} else if (ret > 0) {
24273	    if (fireErrors)
24274		xmlSchemaFacetErr(actxt, ret, node,
24275		value, length, type, facetLink->facet, NULL, NULL, NULL);
24276	    else
24277		return (ret);
24278	    if (error == 0)
24279		error = ret;
24280	}
24281	ret = 0;
24282    }
24283
24284pattern_and_enum:
24285    if (error >= 0) {
24286	int found = 0;
24287	/*
24288	* Process enumerations. Facet values are in the value space
24289	* of the defining type's base type. This seems to be a bug in the
24290	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24291	* Only the first set of enumerations in the ancestor-or-self axis
24292	* is used for validation.
24293	*/
24294	ret = 0;
24295	tmpType = type;
24296	do {
24297	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24298		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24299		    continue;
24300		found = 1;
24301		ret = xmlSchemaAreValuesEqual(facet->val, val);
24302		if (ret == 1)
24303		    break;
24304		else if (ret < 0) {
24305		    AERROR_INT("xmlSchemaValidateFacets",
24306			"validating against an enumeration facet");
24307		    return (-1);
24308		}
24309	    }
24310	    if (ret != 0)
24311		break;
24312	    /*
24313	    * Break on the first set of enumerations. Any additional
24314	    *  enumerations which might be existent on the ancestors
24315	    *  of the current type are restricted by this set; thus
24316	    *  *must* *not* be taken into account.
24317	    */
24318	    if (found)
24319		break;
24320	    tmpType = tmpType->baseType;
24321	} while ((tmpType != NULL) &&
24322	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24323	if (found && (ret == 0)) {
24324	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24325	    if (fireErrors) {
24326		xmlSchemaFacetErr(actxt, ret, node,
24327		    value, 0, type, NULL, NULL, NULL, NULL);
24328	    } else
24329		return (ret);
24330	    if (error == 0)
24331		error = ret;
24332	}
24333    }
24334
24335    if (error >= 0) {
24336	int found;
24337	/*
24338	* Process patters. Pattern facets are ORed at type level
24339	* and ANDed if derived. Walk the base type axis.
24340	*/
24341	tmpType = type;
24342	facet = NULL;
24343	do {
24344	    found = 0;
24345	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24346		facetLink = facetLink->next) {
24347		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24348		    continue;
24349		found = 1;
24350		/*
24351		* NOTE that for patterns, @value needs to be the
24352		* normalized vaule.
24353		*/
24354		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24355		if (ret == 1)
24356		    break;
24357		else if (ret < 0) {
24358		    AERROR_INT("xmlSchemaValidateFacets",
24359			"validating against a pattern facet");
24360		    return (-1);
24361		} else {
24362		    /*
24363		    * Save the last non-validating facet.
24364		    */
24365		    facet = facetLink->facet;
24366		}
24367	    }
24368	    if (found && (ret != 1)) {
24369		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24370		if (fireErrors) {
24371		    xmlSchemaFacetErr(actxt, ret, node,
24372			value, 0, type, facet, NULL, NULL, NULL);
24373		} else
24374		    return (ret);
24375		if (error == 0)
24376		    error = ret;
24377		break;
24378	    }
24379	    tmpType = tmpType->baseType;
24380	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24381    }
24382
24383    return (error);
24384}
24385
24386static xmlChar *
24387xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24388			const xmlChar *value)
24389{
24390    switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24391	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24392	    return (xmlSchemaCollapseString(value));
24393	case XML_SCHEMA_WHITESPACE_REPLACE:
24394	    return (xmlSchemaWhiteSpaceReplace(value));
24395	default:
24396	    return (NULL);
24397    }
24398}
24399
24400static int
24401xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24402		       const xmlChar *value,
24403		       xmlSchemaValPtr *val,
24404		       int valNeeded)
24405{
24406    int ret;
24407    const xmlChar *nsName;
24408    xmlChar *local, *prefix = NULL;
24409
24410    ret = xmlValidateQName(value, 1);
24411    if (ret != 0) {
24412	if (ret == -1) {
24413	    VERROR_INT("xmlSchemaValidateQName",
24414		"calling xmlValidateQName()");
24415	    return (-1);
24416	}
24417	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24418    }
24419    /*
24420    * NOTE: xmlSplitQName2 will always return a duplicated
24421    * strings.
24422    */
24423    local = xmlSplitQName2(value, &prefix);
24424    if (local == NULL)
24425	local = xmlStrdup(value);
24426    /*
24427    * OPTIMIZE TODO: Use flags for:
24428    *  - is there any namespace binding?
24429    *  - is there a default namespace?
24430    */
24431    nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24432
24433    if (prefix != NULL) {
24434	xmlFree(prefix);
24435	/*
24436	* A namespace must be found if the prefix is
24437	* NOT NULL.
24438	*/
24439	if (nsName == NULL) {
24440	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24441	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24442		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24443		"The QName value '%s' has no "
24444		"corresponding namespace declaration in "
24445		"scope", value, NULL);
24446	    if (local != NULL)
24447		xmlFree(local);
24448	    return (ret);
24449	}
24450    }
24451    if (valNeeded && val) {
24452	if (nsName != NULL)
24453	    *val = xmlSchemaNewQNameValue(
24454		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24455	else
24456	    *val = xmlSchemaNewQNameValue(NULL,
24457		BAD_CAST local);
24458    } else
24459	xmlFree(local);
24460    return (0);
24461}
24462
24463/*
24464* cvc-simple-type
24465*/
24466static int
24467xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24468			     xmlNodePtr node,
24469			     xmlSchemaTypePtr type,
24470			     const xmlChar *value,
24471			     xmlSchemaValPtr *retVal,
24472			     int fireErrors,
24473			     int normalize,
24474			     int isNormalized)
24475{
24476    int ret = 0, valNeeded = (retVal) ? 1 : 0;
24477    xmlSchemaValPtr val = NULL;
24478    /* xmlSchemaWhitespaceValueType ws; */
24479    xmlChar *normValue = NULL;
24480
24481#define NORMALIZE(atype) \
24482    if ((! isNormalized) && \
24483    (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24484	normValue = xmlSchemaNormalizeValue(atype, value); \
24485	if (normValue != NULL) \
24486	    value = normValue; \
24487	isNormalized = 1; \
24488    }
24489
24490    if ((retVal != NULL) && (*retVal != NULL)) {
24491	xmlSchemaFreeValue(*retVal);
24492	*retVal = NULL;
24493    }
24494    /*
24495    * 3.14.4 Simple Type Definition Validation Rules
24496    * Validation Rule: String Valid
24497    */
24498    /*
24499    * 1 It is schema-valid with respect to that definition as defined
24500    * by Datatype Valid in [XML Schemas: Datatypes].
24501    */
24502    /*
24503    * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24504    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24505    * the string must be a `declared entity name`.
24506    */
24507    /*
24508    * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24509    * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24510    * then every whitespace-delimited substring of the string must be a `declared
24511    * entity name`.
24512    */
24513    /*
24514    * 2.3 otherwise no further condition applies.
24515    */
24516    if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24517	valNeeded = 1;
24518    if (value == NULL)
24519	value = BAD_CAST "";
24520    if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24521	xmlSchemaTypePtr biType; /* The built-in type. */
24522	/*
24523	* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24524	* a literal in the `lexical space` of {base type definition}"
24525	*/
24526	/*
24527	* Whitespace-normalize.
24528	*/
24529	NORMALIZE(type);
24530	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24531	    /*
24532	    * Get the built-in type.
24533	    */
24534	    biType = type->baseType;
24535	    while ((biType != NULL) &&
24536		(biType->type != XML_SCHEMA_TYPE_BASIC))
24537		biType = biType->baseType;
24538
24539	    if (biType == NULL) {
24540		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24541		    "could not get the built-in type");
24542		goto internal_error;
24543	    }
24544	} else
24545	    biType = type;
24546	/*
24547	* NOTATIONs need to be processed here, since they need
24548	* to lookup in the hashtable of NOTATION declarations of the schema.
24549	*/
24550	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24551	    switch (biType->builtInType) {
24552		case XML_SCHEMAS_NOTATION:
24553		    ret = xmlSchemaValidateNotation(
24554			(xmlSchemaValidCtxtPtr) actxt,
24555			((xmlSchemaValidCtxtPtr) actxt)->schema,
24556			NULL, value, &val, valNeeded);
24557		    break;
24558		case XML_SCHEMAS_QNAME:
24559		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24560			value, &val, valNeeded);
24561		    break;
24562		default:
24563		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24564		    if (valNeeded)
24565			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24566			    value, &val, node);
24567		    else
24568			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24569			    value, NULL, node);
24570		    break;
24571	    }
24572	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24573	    switch (biType->builtInType) {
24574		case XML_SCHEMAS_NOTATION:
24575		    ret = xmlSchemaValidateNotation(NULL,
24576			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24577			value, &val, valNeeded);
24578		    break;
24579		default:
24580		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24581		    if (valNeeded)
24582			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24583			    value, &val, node);
24584		    else
24585			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24586			    value, NULL, node);
24587		    break;
24588	    }
24589	} else {
24590	    /*
24591	    * Validation via a public API is not implemented yet.
24592	    */
24593	    TODO
24594	    goto internal_error;
24595	}
24596	if (ret != 0) {
24597	    if (ret < 0) {
24598		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24599		    "validating against a built-in type");
24600		goto internal_error;
24601	    }
24602	    if (WXS_IS_LIST(type))
24603		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24604	    else
24605		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24606	}
24607	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24608	    /*
24609	    * Check facets.
24610	    */
24611	    ret = xmlSchemaValidateFacets(actxt, node, type,
24612		(xmlSchemaValType) biType->builtInType, value, val,
24613		0, fireErrors);
24614	    if (ret != 0) {
24615		if (ret < 0) {
24616		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24617			"validating facets of atomic simple type");
24618		    goto internal_error;
24619		}
24620		if (WXS_IS_LIST(type))
24621		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24622		else
24623		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24624	    }
24625	}
24626	if (fireErrors && (ret > 0))
24627	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24628    } else if (WXS_IS_LIST(type)) {
24629
24630	xmlSchemaTypePtr itemType;
24631	const xmlChar *cur, *end;
24632	xmlChar *tmpValue = NULL;
24633	unsigned long len = 0;
24634	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24635	/* 1.2.2 if {variety} is `list` then the string must be a sequence
24636	* of white space separated tokens, each of which `match`es a literal
24637	* in the `lexical space` of {item type definition}
24638	*/
24639	/*
24640	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24641	* the list type has an enum or pattern facet.
24642	*/
24643	NORMALIZE(type);
24644	/*
24645	* VAL TODO: Optimize validation of empty values.
24646	* VAL TODO: We do not have computed values for lists.
24647	*/
24648	itemType = WXS_LIST_ITEMTYPE(type);
24649	cur = value;
24650	do {
24651	    while (IS_BLANK_CH(*cur))
24652		cur++;
24653	    end = cur;
24654	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24655		end++;
24656	    if (end == cur)
24657		break;
24658	    tmpValue = xmlStrndup(cur, end - cur);
24659	    len++;
24660
24661	    if (valNeeded)
24662		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24663		    tmpValue, &curVal, fireErrors, 0, 1);
24664	    else
24665		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24666		    tmpValue, NULL, fireErrors, 0, 1);
24667	    FREE_AND_NULL(tmpValue);
24668	    if (curVal != NULL) {
24669		/*
24670		* Add to list of computed values.
24671		*/
24672		if (val == NULL)
24673		    val = curVal;
24674		else
24675		    xmlSchemaValueAppend(prevVal, curVal);
24676		prevVal = curVal;
24677		curVal = NULL;
24678	    }
24679	    if (ret != 0) {
24680		if (ret < 0) {
24681		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24682			"validating an item of list simple type");
24683		    goto internal_error;
24684		}
24685		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24686		break;
24687	    }
24688	    cur = end;
24689	} while (*cur != 0);
24690	FREE_AND_NULL(tmpValue);
24691	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24692	    /*
24693	    * Apply facets (pattern, enumeration).
24694	    */
24695	    ret = xmlSchemaValidateFacets(actxt, node, type,
24696		XML_SCHEMAS_UNKNOWN, value, val,
24697		len, fireErrors);
24698	    if (ret != 0) {
24699		if (ret < 0) {
24700		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24701			"validating facets of list simple type");
24702		    goto internal_error;
24703		}
24704		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24705	    }
24706	}
24707	if (fireErrors && (ret > 0)) {
24708	    /*
24709	    * Report the normalized value.
24710	    */
24711	    normalize = 1;
24712	    NORMALIZE(type);
24713	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24714	}
24715    } else if (WXS_IS_UNION(type)) {
24716	xmlSchemaTypeLinkPtr memberLink;
24717	/*
24718	* TODO: For all datatypes `derived` by `union`  whiteSpace does
24719	* not apply directly; however, the normalization behavior of `union`
24720	* types is controlled by the value of whiteSpace on that one of the
24721	* `memberTypes` against which the `union` is successfully validated.
24722	*
24723	* This means that the value is normalized by the first validating
24724	* member type, then the facets of the union type are applied. This
24725	* needs changing of the value!
24726	*/
24727
24728	/*
24729	* 1.2.3 if {variety} is `union` then the string must `match` a
24730	* literal in the `lexical space` of at least one member of
24731	* {member type definitions}
24732	*/
24733	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24734	if (memberLink == NULL) {
24735	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24736		"union simple type has no member types");
24737	    goto internal_error;
24738	}
24739	/*
24740	* Always normalize union type values, since we currently
24741	* cannot store the whitespace information with the value
24742	* itself; otherwise a later value-comparison would be
24743	* not possible.
24744	*/
24745	while (memberLink != NULL) {
24746	    if (valNeeded)
24747		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24748		    memberLink->type, value, &val, 0, 1, 0);
24749	    else
24750		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24751		    memberLink->type, value, NULL, 0, 1, 0);
24752	    if (ret <= 0)
24753		break;
24754	    memberLink = memberLink->next;
24755	}
24756	if (ret != 0) {
24757	    if (ret < 0) {
24758		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24759		    "validating members of union simple type");
24760		goto internal_error;
24761	    }
24762	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24763	}
24764	/*
24765	* Apply facets (pattern, enumeration).
24766	*/
24767	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24768	    /*
24769	    * The normalization behavior of `union` types is controlled by
24770	    * the value of whiteSpace on that one of the `memberTypes`
24771	    * against which the `union` is successfully validated.
24772	    */
24773	    NORMALIZE(memberLink->type);
24774	    ret = xmlSchemaValidateFacets(actxt, node, type,
24775		XML_SCHEMAS_UNKNOWN, value, val,
24776		0, fireErrors);
24777	    if (ret != 0) {
24778		if (ret < 0) {
24779		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24780			"validating facets of union simple type");
24781		    goto internal_error;
24782		}
24783		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24784	    }
24785	}
24786	if (fireErrors && (ret > 0))
24787	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24788    }
24789
24790    if (normValue != NULL)
24791	xmlFree(normValue);
24792    if (ret == 0) {
24793	if (retVal != NULL)
24794	    *retVal = val;
24795	else if (val != NULL)
24796	    xmlSchemaFreeValue(val);
24797    } else if (val != NULL)
24798	xmlSchemaFreeValue(val);
24799    return (ret);
24800internal_error:
24801    if (normValue != NULL)
24802	xmlFree(normValue);
24803    if (val != NULL)
24804	xmlSchemaFreeValue(val);
24805    return (-1);
24806}
24807
24808static int
24809xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24810			   const xmlChar *value,
24811			   const xmlChar **nsName,
24812			   const xmlChar **localName)
24813{
24814    int ret = 0;
24815
24816    if ((nsName == NULL) || (localName == NULL))
24817	return (-1);
24818    *nsName = NULL;
24819    *localName = NULL;
24820
24821    ret = xmlValidateQName(value, 1);
24822    if (ret == -1)
24823	return (-1);
24824    if (ret > 0) {
24825	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24826	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24827	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24828	return (1);
24829    }
24830    {
24831	xmlChar *local = NULL;
24832	xmlChar *prefix;
24833
24834	/*
24835	* NOTE: xmlSplitQName2 will return a duplicated
24836	* string.
24837	*/
24838	local = xmlSplitQName2(value, &prefix);
24839	if (local == NULL)
24840	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24841	else {
24842	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24843	    xmlFree(local);
24844	}
24845
24846	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24847
24848	if (prefix != NULL) {
24849	    xmlFree(prefix);
24850	    /*
24851	    * A namespace must be found if the prefix is NOT NULL.
24852	    */
24853	    if (*nsName == NULL) {
24854		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24855		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24856		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24857		    "The QName value '%s' has no "
24858		    "corresponding namespace declaration in scope",
24859		    value, NULL);
24860		return (2);
24861	    }
24862	}
24863    }
24864    return (0);
24865}
24866
24867static int
24868xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24869			xmlSchemaAttrInfoPtr iattr,
24870			xmlSchemaTypePtr *localType,
24871			xmlSchemaElementPtr elemDecl)
24872{
24873    int ret = 0;
24874    /*
24875    * cvc-elt (3.3.4) : (4)
24876    * AND
24877    * Schema-Validity Assessment (Element) (cvc-assess-elt)
24878    *   (1.2.1.2.1) - (1.2.1.2.4)
24879    * Handle 'xsi:type'.
24880    */
24881    if (localType == NULL)
24882	return (-1);
24883    *localType = NULL;
24884    if (iattr == NULL)
24885	return (0);
24886    else {
24887	const xmlChar *nsName = NULL, *local = NULL;
24888	/*
24889	* TODO: We should report a *warning* that the type was overriden
24890	* by the instance.
24891	*/
24892	ACTIVATE_ATTRIBUTE(iattr);
24893	/*
24894	* (cvc-elt) (3.3.4) : (4.1)
24895	* (cvc-assess-elt) (1.2.1.2.2)
24896	*/
24897	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24898	    &nsName, &local);
24899	if (ret != 0) {
24900	    if (ret < 0) {
24901		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24902		    "calling xmlSchemaQNameExpand() to validate the "
24903		    "attribute 'xsi:type'");
24904		goto internal_error;
24905	    }
24906	    goto exit;
24907	}
24908	/*
24909	* (cvc-elt) (3.3.4) : (4.2)
24910	* (cvc-assess-elt) (1.2.1.2.3)
24911	*/
24912	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24913	if (*localType == NULL) {
24914	    xmlChar *str = NULL;
24915
24916	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24917		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24918		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24919		"The QName value '%s' of the xsi:type attribute does not "
24920		"resolve to a type definition",
24921		xmlSchemaFormatQName(&str, nsName, local), NULL);
24922	    FREE_AND_NULL(str);
24923	    ret = vctxt->err;
24924	    goto exit;
24925	}
24926	if (elemDecl != NULL) {
24927	    int set = 0;
24928
24929	    /*
24930	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24931	    * "The `local type definition` must be validly
24932	    * derived from the {type definition} given the union of
24933	    * the {disallowed substitutions} and the {type definition}'s
24934	    * {prohibited substitutions}, as defined in
24935	    * Type Derivation OK (Complex) ($3.4.6)
24936	    * (if it is a complex type definition),
24937	    * or given {disallowed substitutions} as defined in Type
24938	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24939	    * definition)."
24940	    *
24941	    * {disallowed substitutions}: the "block" on the element decl.
24942	    * {prohibited substitutions}: the "block" on the type def.
24943	    */
24944	    /*
24945	    * OPTIMIZE TODO: We could map types already evaluated
24946	    * to be validly derived from other types to avoid checking
24947	    * this over and over for the same types.
24948	    */
24949	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24950		(elemDecl->subtypes->flags &
24951		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24952		set |= SUBSET_EXTENSION;
24953
24954	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24955		(elemDecl->subtypes->flags &
24956		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24957		set |= SUBSET_RESTRICTION;
24958
24959	    /*
24960	    * REMOVED and CHANGED since this produced a parser context
24961	    * which adds to the string dict of the schema. So this would
24962	    * change the schema and we don't want this. We don't need
24963	    * the parser context anymore.
24964	    *
24965	    * if ((vctxt->pctxt == NULL) &&
24966	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24967	    *	    return (-1);
24968	    */
24969
24970	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24971		elemDecl->subtypes, set) != 0) {
24972		xmlChar *str = NULL;
24973
24974		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24975		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24976		    "The type definition '%s', specified by xsi:type, is "
24977		    "blocked or not validly derived from the type definition "
24978		    "of the element declaration",
24979		    xmlSchemaFormatQName(&str,
24980			(*localType)->targetNamespace,
24981			(*localType)->name),
24982		    NULL);
24983		FREE_AND_NULL(str);
24984		ret = vctxt->err;
24985		*localType = NULL;
24986	    }
24987	}
24988    }
24989exit:
24990    ACTIVATE_ELEM;
24991    return (ret);
24992internal_error:
24993    ACTIVATE_ELEM;
24994    return (-1);
24995}
24996
24997static int
24998xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24999{
25000    xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25001    xmlSchemaTypePtr actualType;
25002
25003    /*
25004    * cvc-elt (3.3.4) : 1
25005    */
25006    if (elemDecl == NULL) {
25007	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25008	    "No matching declaration available");
25009        return (vctxt->err);
25010    }
25011    actualType = WXS_ELEM_TYPEDEF(elemDecl);
25012    /*
25013    * cvc-elt (3.3.4) : 2
25014    */
25015    if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25016	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25017	    "The element declaration is abstract");
25018        return (vctxt->err);
25019    }
25020    if (actualType == NULL) {
25021	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25022	    "The type definition is absent");
25023	return (XML_SCHEMAV_CVC_TYPE_1);
25024    }
25025    if (vctxt->nbAttrInfos != 0) {
25026	int ret;
25027	xmlSchemaAttrInfoPtr iattr;
25028	/*
25029	* cvc-elt (3.3.4) : 3
25030	* Handle 'xsi:nil'.
25031	*/
25032	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25033	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25034	if (iattr) {
25035	    ACTIVATE_ATTRIBUTE(iattr);
25036	    /*
25037	    * Validate the value.
25038	    */
25039	    ret = xmlSchemaVCheckCVCSimpleType(
25040		ACTXT_CAST vctxt, NULL,
25041		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25042		iattr->value, &(iattr->val), 1, 0, 0);
25043	    ACTIVATE_ELEM;
25044	    if (ret < 0) {
25045		VERROR_INT("xmlSchemaValidateElemDecl",
25046		    "calling xmlSchemaVCheckCVCSimpleType() to "
25047		    "validate the attribute 'xsi:nil'");
25048		return (-1);
25049	    }
25050	    if (ret == 0) {
25051		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25052		    /*
25053		    * cvc-elt (3.3.4) : 3.1
25054		    */
25055		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25056			"The element is not 'nillable'");
25057		    /* Does not return an error on purpose. */
25058		} else {
25059		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25060			/*
25061			* cvc-elt (3.3.4) : 3.2.2
25062			*/
25063			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25064			    (elemDecl->value != NULL)) {
25065			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25066				"The element cannot be 'nilled' because "
25067				"there is a fixed value constraint defined "
25068				"for it");
25069			     /* Does not return an error on purpose. */
25070			} else
25071			    vctxt->inode->flags |=
25072				XML_SCHEMA_ELEM_INFO_NILLED;
25073		    }
25074		}
25075	    }
25076	}
25077	/*
25078	* cvc-elt (3.3.4) : 4
25079	* Handle 'xsi:type'.
25080	*/
25081	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25082	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25083	if (iattr) {
25084	    xmlSchemaTypePtr localType = NULL;
25085
25086	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25087		elemDecl);
25088	    if (ret != 0) {
25089		if (ret == -1) {
25090		    VERROR_INT("xmlSchemaValidateElemDecl",
25091			"calling xmlSchemaProcessXSIType() to "
25092			"process the attribute 'xsi:type'");
25093		    return (-1);
25094		}
25095		/* Does not return an error on purpose. */
25096	    }
25097	    if (localType != NULL) {
25098		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25099		actualType = localType;
25100	    }
25101	}
25102    }
25103    /*
25104    * IDC: Register identity-constraint XPath matchers.
25105    */
25106    if ((elemDecl->idcs != NULL) &&
25107	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25108	    return (-1);
25109    /*
25110    * No actual type definition.
25111    */
25112    if (actualType == NULL) {
25113	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25114	    "The type definition is absent");
25115	return (XML_SCHEMAV_CVC_TYPE_1);
25116    }
25117    /*
25118    * Remember the actual type definition.
25119    */
25120    vctxt->inode->typeDef = actualType;
25121
25122    return (0);
25123}
25124
25125static int
25126xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25127{
25128    xmlSchemaAttrInfoPtr iattr;
25129    int ret = 0, i;
25130
25131    /*
25132    * SPEC cvc-type (3.1.1)
25133    * "The attributes of must be empty, excepting those whose namespace
25134    * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25135    * whose local name is one of type, nil, schemaLocation or
25136    * noNamespaceSchemaLocation."
25137    */
25138    if (vctxt->nbAttrInfos == 0)
25139	return (0);
25140    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25141	iattr = vctxt->attrInfos[i];
25142	if (! iattr->metaType) {
25143	    ACTIVATE_ATTRIBUTE(iattr)
25144	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25145		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25146	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25147        }
25148    }
25149    ACTIVATE_ELEM
25150    return (ret);
25151}
25152
25153/*
25154* Cleanup currently used attribute infos.
25155*/
25156static void
25157xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25158{
25159    int i;
25160    xmlSchemaAttrInfoPtr attr;
25161
25162    if (vctxt->nbAttrInfos == 0)
25163	return;
25164    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25165	attr = vctxt->attrInfos[i];
25166	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25167	    if (attr->localName != NULL)
25168		xmlFree((xmlChar *) attr->localName);
25169	    if (attr->nsName != NULL)
25170		xmlFree((xmlChar *) attr->nsName);
25171	}
25172	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25173	    if (attr->value != NULL)
25174		xmlFree((xmlChar *) attr->value);
25175	}
25176	if (attr->val != NULL) {
25177	    xmlSchemaFreeValue(attr->val);
25178	    attr->val = NULL;
25179	}
25180	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25181    }
25182    vctxt->nbAttrInfos = 0;
25183}
25184
25185/*
25186* 3.4.4 Complex Type Definition Validation Rules
25187*   Element Locally Valid (Complex Type) (cvc-complex-type)
25188* 3.2.4 Attribute Declaration Validation Rules
25189*   Validation Rule: Attribute Locally Valid (cvc-attribute)
25190*   Attribute Locally Valid (Use) (cvc-au)
25191*
25192* Only "assessed" attribute information items will be visible to
25193* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25194*/
25195static int
25196xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25197{
25198    xmlSchemaTypePtr type = vctxt->inode->typeDef;
25199    xmlSchemaItemListPtr attrUseList;
25200    xmlSchemaAttributeUsePtr attrUse = NULL;
25201    xmlSchemaAttributePtr attrDecl = NULL;
25202    xmlSchemaAttrInfoPtr iattr, tmpiattr;
25203    int i, j, found, nbAttrs, nbUses;
25204    int xpathRes = 0, res, wildIDs = 0, fixed;
25205    xmlNodePtr defAttrOwnerElem = NULL;
25206
25207    /*
25208    * SPEC (cvc-attribute)
25209    * (1) "The declaration must not be `absent` (see Missing
25210    * Sub-components ($5.3) for how this can fail to be
25211    * the case)."
25212    * (2) "Its {type definition} must not be absent."
25213    *
25214    * NOTE (1) + (2): This is not handled here, since we currently do not
25215    * allow validation against schemas which have missing sub-components.
25216    *
25217    * SPEC (cvc-complex-type)
25218    * (3) "For each attribute information item in the element information
25219    * item's [attributes] excepting those whose [namespace name] is
25220    * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25221    * [local name] is one of type, nil, schemaLocation or
25222    * noNamespaceSchemaLocation, the appropriate case among the following
25223    * must be true:
25224    *
25225    */
25226    attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25227    /*
25228    * @nbAttrs is the number of attributes present in the instance.
25229    */
25230    nbAttrs = vctxt->nbAttrInfos;
25231    if (attrUseList != NULL)
25232	nbUses = attrUseList->nbItems;
25233    else
25234	nbUses = 0;
25235    for (i = 0; i < nbUses; i++) {
25236        found = 0;
25237	attrUse = attrUseList->items[i];
25238	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25239        for (j = 0; j < nbAttrs; j++) {
25240	    iattr = vctxt->attrInfos[j];
25241	    /*
25242	    * SPEC (cvc-complex-type) (3)
25243	    * Skip meta attributes.
25244	    */
25245	    if (iattr->metaType)
25246		continue;
25247	    if (iattr->localName[0] != attrDecl->name[0])
25248		continue;
25249	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25250		continue;
25251	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25252		continue;
25253	    found = 1;
25254	    /*
25255	    * SPEC (cvc-complex-type)
25256	    * (3.1) "If there is among the {attribute uses} an attribute
25257	    * use with an {attribute declaration} whose {name} matches
25258	    * the attribute information item's [local name] and whose
25259	    * {target namespace} is identical to the attribute information
25260	    * item's [namespace name] (where an `absent` {target namespace}
25261	    * is taken to be identical to a [namespace name] with no value),
25262	    * then the attribute information must be `valid` with respect
25263	    * to that attribute use as per Attribute Locally Valid (Use)
25264	    * ($3.5.4). In this case the {attribute declaration} of that
25265	    * attribute use is the `context-determined declaration` for the
25266	    * attribute information item with respect to Schema-Validity
25267	    * Assessment (Attribute) ($3.2.4) and
25268	    * Assessment Outcome (Attribute) ($3.2.5).
25269	    */
25270	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25271	    iattr->use = attrUse;
25272	    /*
25273	    * Context-determined declaration.
25274	    */
25275	    iattr->decl = attrDecl;
25276	    iattr->typeDef = attrDecl->subtypes;
25277	    break;
25278	}
25279
25280	if (found)
25281	    continue;
25282
25283	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25284	    /*
25285	    * Handle non-existent, required attributes.
25286	    *
25287	    * SPEC (cvc-complex-type)
25288	    * (4) "The {attribute declaration} of each attribute use in
25289	    * the {attribute uses} whose {required} is true matches one
25290	    * of the attribute information items in the element information
25291	    * item's [attributes] as per clause 3.1 above."
25292	    */
25293	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25294	    if (tmpiattr == NULL) {
25295		VERROR_INT(
25296		    "xmlSchemaVAttributesComplex",
25297		    "calling xmlSchemaGetFreshAttrInfo()");
25298		return (-1);
25299	    }
25300	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25301	    tmpiattr->use = attrUse;
25302	    tmpiattr->decl = attrDecl;
25303	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25304	    ((attrUse->defValue != NULL) ||
25305	     (attrDecl->defValue != NULL))) {
25306	    /*
25307	    * Handle non-existent, optional, default/fixed attributes.
25308	    */
25309	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25310	    if (tmpiattr == NULL) {
25311		VERROR_INT(
25312		    "xmlSchemaVAttributesComplex",
25313		    "calling xmlSchemaGetFreshAttrInfo()");
25314		return (-1);
25315	    }
25316	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25317	    tmpiattr->use = attrUse;
25318	    tmpiattr->decl = attrDecl;
25319	    tmpiattr->typeDef = attrDecl->subtypes;
25320	    tmpiattr->localName = attrDecl->name;
25321	    tmpiattr->nsName = attrDecl->targetNamespace;
25322	}
25323    }
25324
25325    if (vctxt->nbAttrInfos == 0)
25326	return (0);
25327    /*
25328    * Validate against the wildcard.
25329    */
25330    if (type->attributeWildcard != NULL) {
25331	/*
25332	* SPEC (cvc-complex-type)
25333	* (3.2.1) "There must be an {attribute wildcard}."
25334	*/
25335	for (i = 0; i < nbAttrs; i++) {
25336	    iattr = vctxt->attrInfos[i];
25337	    /*
25338	    * SPEC (cvc-complex-type) (3)
25339	    * Skip meta attributes.
25340	    */
25341	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25342		continue;
25343	    /*
25344	    * SPEC (cvc-complex-type)
25345	    * (3.2.2) "The attribute information item must be `valid` with
25346	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25347	    *
25348	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25349	    * "... its [namespace name] must be `valid` with respect to
25350	    * the wildcard constraint, as defined in Wildcard allows
25351	    * Namespace Name ($3.10.4)."
25352	    */
25353	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25354		    iattr->nsName) == 0) {
25355		/*
25356		* Handle processContents.
25357		*
25358		* SPEC (cvc-wildcard):
25359		* processContents | context-determined declaration:
25360		* "strict"          "mustFind"
25361		* "lax"             "none"
25362		* "skip"            "skip"
25363		*/
25364		if (type->attributeWildcard->processContents ==
25365		    XML_SCHEMAS_ANY_SKIP) {
25366		     /*
25367		    * context-determined declaration = "skip"
25368		    *
25369		    * SPEC PSVI Assessment Outcome (Attribute)
25370		    * [validity] = "notKnown"
25371		    * [validation attempted] = "none"
25372		    */
25373		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25374		    continue;
25375		}
25376		/*
25377		* Find an attribute declaration.
25378		*/
25379		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25380		    iattr->localName, iattr->nsName);
25381		if (iattr->decl != NULL) {
25382		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25383		    /*
25384		    * SPEC (cvc-complex-type)
25385		    * (5) "Let [Definition:]  the wild IDs be the set of
25386		    * all attribute information item to which clause 3.2
25387		    * applied and whose `validation` resulted in a
25388		    * `context-determined declaration` of mustFind or no
25389		    * `context-determined declaration` at all, and whose
25390		    * [local name] and [namespace name] resolve (as
25391		    * defined by QName resolution (Instance) ($3.15.4)) to
25392		    * an attribute declaration whose {type definition} is
25393		    * or is derived from ID. Then all of the following
25394		    * must be true:"
25395		    */
25396		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25397		    if (xmlSchemaIsDerivedFromBuiltInType(
25398			iattr->typeDef, XML_SCHEMAS_ID)) {
25399			/*
25400			* SPEC (5.1) "There must be no more than one
25401			* item in `wild IDs`."
25402			*/
25403			if (wildIDs != 0) {
25404			    /* VAL TODO */
25405			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25406			    TODO
25407			    continue;
25408			}
25409			wildIDs++;
25410			/*
25411			* SPEC (cvc-complex-type)
25412			* (5.2) "If `wild IDs` is non-empty, there must not
25413			* be any attribute uses among the {attribute uses}
25414			* whose {attribute declaration}'s {type definition}
25415			* is or is derived from ID."
25416			*/
25417                        if (attrUseList != NULL) {
25418                            for (j = 0; j < attrUseList->nbItems; j++) {
25419                                if (xmlSchemaIsDerivedFromBuiltInType(
25420                                    WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25421                                    XML_SCHEMAS_ID)) {
25422                                    /* URGENT VAL TODO: implement */
25423                            iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25424                                    TODO
25425                                    break;
25426                                }
25427                            }
25428                        }
25429		    }
25430		} else if (type->attributeWildcard->processContents ==
25431		    XML_SCHEMAS_ANY_LAX) {
25432		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25433		    /*
25434		    * SPEC PSVI Assessment Outcome (Attribute)
25435		    * [validity] = "notKnown"
25436		    * [validation attempted] = "none"
25437		    */
25438		} else {
25439		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25440		}
25441	    }
25442	}
25443    }
25444
25445    if (vctxt->nbAttrInfos == 0)
25446	return (0);
25447
25448    /*
25449    * Get the owner element; needed for creation of default attributes.
25450    * This fixes bug #341337, reported by David Grohmann.
25451    */
25452    if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25453	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25454	if (ielem && ielem->node && ielem->node->doc)
25455	    defAttrOwnerElem = ielem->node;
25456    }
25457    /*
25458    * Validate values, create default attributes, evaluate IDCs.
25459    */
25460    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25461	iattr = vctxt->attrInfos[i];
25462	/*
25463	* VAL TODO: Note that we won't try to resolve IDCs to
25464	* "lax" and "skip" validated attributes. Check what to
25465	* do in this case.
25466	*/
25467	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25468	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25469	    continue;
25470	/*
25471	* VAL TODO: What to do if the type definition is missing?
25472	*/
25473	if (iattr->typeDef == NULL) {
25474	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25475	    continue;
25476	}
25477
25478	ACTIVATE_ATTRIBUTE(iattr);
25479	fixed = 0;
25480	xpathRes = 0;
25481
25482	if (vctxt->xpathStates != NULL) {
25483	    /*
25484	    * Evaluate IDCs.
25485	    */
25486	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25487		XML_ATTRIBUTE_NODE);
25488	    if (xpathRes == -1) {
25489		VERROR_INT("xmlSchemaVAttributesComplex",
25490		    "calling xmlSchemaXPathEvaluate()");
25491		goto internal_error;
25492	    }
25493	}
25494
25495	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25496	    /*
25497	    * Default/fixed attributes.
25498	    * We need the value only if we need to resolve IDCs or
25499	    * will create default attributes.
25500	    */
25501	    if ((xpathRes) || (defAttrOwnerElem)) {
25502		if (iattr->use->defValue != NULL) {
25503		    iattr->value = (xmlChar *) iattr->use->defValue;
25504		    iattr->val = iattr->use->defVal;
25505		} else {
25506		    iattr->value = (xmlChar *) iattr->decl->defValue;
25507		    iattr->val = iattr->decl->defVal;
25508		}
25509		/*
25510		* IDCs will consume the precomputed default value,
25511		* so we need to clone it.
25512		*/
25513		if (iattr->val == NULL) {
25514		    VERROR_INT("xmlSchemaVAttributesComplex",
25515			"default/fixed value on an attribute use was "
25516			"not precomputed");
25517		    goto internal_error;
25518		}
25519		iattr->val = xmlSchemaCopyValue(iattr->val);
25520		if (iattr->val == NULL) {
25521		    VERROR_INT("xmlSchemaVAttributesComplex",
25522			"calling xmlSchemaCopyValue()");
25523		    goto internal_error;
25524		}
25525	    }
25526	    /*
25527	    * PSVI: Add the default attribute to the current element.
25528	    * VAL TODO: Should we use the *normalized* value? This currently
25529	    *   uses the *initial* value.
25530	    */
25531
25532	    if (defAttrOwnerElem) {
25533		xmlChar *normValue;
25534		const xmlChar *value;
25535
25536		value = iattr->value;
25537		/*
25538		* Normalize the value.
25539		*/
25540		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25541		    iattr->value);
25542		if (normValue != NULL)
25543		    value = BAD_CAST normValue;
25544
25545		if (iattr->nsName == NULL) {
25546		    if (xmlNewProp(defAttrOwnerElem,
25547			iattr->localName, value) == NULL) {
25548			VERROR_INT("xmlSchemaVAttributesComplex",
25549			    "callling xmlNewProp()");
25550			if (normValue != NULL)
25551			    xmlFree(normValue);
25552			goto internal_error;
25553		    }
25554		} else {
25555		    xmlNsPtr ns;
25556
25557		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25558			defAttrOwnerElem, iattr->nsName);
25559		    if (ns == NULL) {
25560			xmlChar prefix[12];
25561			int counter = 0;
25562
25563			/*
25564			* Create a namespace declaration on the validation
25565			* root node if no namespace declaration is in scope.
25566			*/
25567			do {
25568			    snprintf((char *) prefix, 12, "p%d", counter++);
25569			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25570				defAttrOwnerElem, BAD_CAST prefix);
25571			    if (counter > 1000) {
25572				VERROR_INT(
25573				    "xmlSchemaVAttributesComplex",
25574				    "could not compute a ns prefix for a "
25575				    "default/fixed attribute");
25576				if (normValue != NULL)
25577				    xmlFree(normValue);
25578				goto internal_error;
25579			    }
25580			} while (ns != NULL);
25581			ns = xmlNewNs(vctxt->validationRoot,
25582			    iattr->nsName, BAD_CAST prefix);
25583		    }
25584		    /*
25585		    * TODO:
25586		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25587		    * If we have QNames: do we need to ensure there's a
25588		    * prefix defined for the QName?
25589		    */
25590		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25591		}
25592		if (normValue != NULL)
25593		    xmlFree(normValue);
25594	    }
25595	    /*
25596	    * Go directly to IDC evaluation.
25597	    */
25598	    goto eval_idcs;
25599	}
25600	/*
25601	* Validate the value.
25602	*/
25603	if (vctxt->value != NULL) {
25604	    /*
25605	    * Free last computed value; just for safety reasons.
25606	    */
25607	    xmlSchemaFreeValue(vctxt->value);
25608	    vctxt->value = NULL;
25609	}
25610	/*
25611	* Note that the attribute *use* can be unavailable, if
25612	* the attribute was a wild attribute.
25613	*/
25614	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25615	    ((iattr->use != NULL) &&
25616	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25617	    fixed = 1;
25618	else
25619	    fixed = 0;
25620	/*
25621	* SPEC (cvc-attribute)
25622	* (3) "The item's `normalized value` must be locally `valid`
25623	* with respect to that {type definition} as per
25624	* String Valid ($3.14.4)."
25625	*
25626	* VAL TODO: Do we already have the
25627	* "normalized attribute value" here?
25628	*/
25629	if (xpathRes || fixed) {
25630	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25631	    /*
25632	    * Request a computed value.
25633	    */
25634	    res = xmlSchemaVCheckCVCSimpleType(
25635		ACTXT_CAST vctxt,
25636		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25637		1, 1, 0);
25638	} else {
25639	    res = xmlSchemaVCheckCVCSimpleType(
25640		ACTXT_CAST vctxt,
25641		iattr->node, iattr->typeDef, iattr->value, NULL,
25642		1, 0, 0);
25643	}
25644
25645	if (res != 0) {
25646	    if (res == -1) {
25647		VERROR_INT("xmlSchemaVAttributesComplex",
25648		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25649		goto internal_error;
25650	    }
25651	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25652	    /*
25653	    * SPEC PSVI Assessment Outcome (Attribute)
25654	    * [validity] = "invalid"
25655	    */
25656	    goto eval_idcs;
25657	}
25658
25659	if (fixed) {
25660	    /*
25661	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25662	    * "For an attribute information item to be `valid`
25663	    * with respect to an attribute use its *normalized*
25664	    * value must match the *canonical* lexical
25665	    * representation of the attribute use's {value
25666	    * constraint}value, if it is present and fixed."
25667	    *
25668	    * VAL TODO: The requirement for the *canonical* value
25669	    * will be removed in XML Schema 1.1.
25670	    */
25671	    /*
25672	    * SPEC Attribute Locally Valid (cvc-attribute)
25673	    * (4) "The item's *actual* value must match the *value* of
25674	    * the {value constraint}, if it is present and fixed."
25675	    */
25676	    if (iattr->val == NULL) {
25677		/* VAL TODO: A value was not precomputed. */
25678		TODO
25679		goto eval_idcs;
25680	    }
25681	    if ((iattr->use != NULL) &&
25682		(iattr->use->defValue != NULL)) {
25683		if (iattr->use->defVal == NULL) {
25684		    /* VAL TODO: A default value was not precomputed. */
25685		    TODO
25686		    goto eval_idcs;
25687		}
25688		iattr->vcValue = iattr->use->defValue;
25689		/*
25690		if (xmlSchemaCompareValuesWhtsp(attr->val,
25691		    (xmlSchemaWhitespaceValueType) ws,
25692		    attr->use->defVal,
25693		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25694		*/
25695		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25696		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25697	    } else {
25698		if (iattr->decl->defVal == NULL) {
25699		    /* VAL TODO: A default value was not precomputed. */
25700		    TODO
25701		    goto eval_idcs;
25702		}
25703		iattr->vcValue = iattr->decl->defValue;
25704		/*
25705		if (xmlSchemaCompareValuesWhtsp(attr->val,
25706		    (xmlSchemaWhitespaceValueType) ws,
25707		    attrDecl->defVal,
25708		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25709		*/
25710		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25711		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25712	    }
25713	    /*
25714	    * [validity] = "valid"
25715	    */
25716	}
25717eval_idcs:
25718	/*
25719	* Evaluate IDCs.
25720	*/
25721	if (xpathRes) {
25722	    if (xmlSchemaXPathProcessHistory(vctxt,
25723		vctxt->depth +1) == -1) {
25724		VERROR_INT("xmlSchemaVAttributesComplex",
25725		    "calling xmlSchemaXPathEvaluate()");
25726		goto internal_error;
25727	    }
25728	} else if (vctxt->xpathStates != NULL)
25729	    xmlSchemaXPathPop(vctxt);
25730    }
25731
25732    /*
25733    * Report errors.
25734    */
25735    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25736	iattr = vctxt->attrInfos[i];
25737	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25738	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25739	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25740	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25741	    continue;
25742	ACTIVATE_ATTRIBUTE(iattr);
25743	switch (iattr->state) {
25744	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25745		    xmlChar *str = NULL;
25746		    ACTIVATE_ELEM;
25747		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25748			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25749			"The attribute '%s' is required but missing",
25750			xmlSchemaFormatQName(&str,
25751			    iattr->decl->targetNamespace,
25752			    iattr->decl->name),
25753			NULL);
25754		    FREE_AND_NULL(str)
25755		    break;
25756		}
25757	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25758		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25759		    "The type definition is absent");
25760		break;
25761	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25762		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25763		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25764		    "The value '%s' does not match the fixed "
25765		    "value constraint '%s'",
25766		    iattr->value, iattr->vcValue);
25767		break;
25768	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25769		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25770		    "No matching global attribute declaration available, but "
25771		    "demanded by the strict wildcard");
25772		break;
25773	    case XML_SCHEMAS_ATTR_UNKNOWN:
25774		if (iattr->metaType)
25775		    break;
25776		/*
25777		* MAYBE VAL TODO: One might report different error messages
25778		* for the following errors.
25779		*/
25780		if (type->attributeWildcard == NULL) {
25781		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25782			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25783		} else {
25784		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25785			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25786		}
25787		break;
25788	    default:
25789		break;
25790	}
25791    }
25792
25793    ACTIVATE_ELEM;
25794    return (0);
25795internal_error:
25796    ACTIVATE_ELEM;
25797    return (-1);
25798}
25799
25800static int
25801xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25802			      int *skip)
25803{
25804    xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25805    /*
25806    * The namespace of the element was already identified to be
25807    * matching the wildcard.
25808    */
25809    if ((skip == NULL) || (wild == NULL) ||
25810	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25811	VERROR_INT("xmlSchemaValidateElemWildcard",
25812	    "bad arguments");
25813	return (-1);
25814    }
25815    *skip = 0;
25816    if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25817	/*
25818	* URGENT VAL TODO: Either we need to position the stream to the
25819	* next sibling, or walk the whole subtree.
25820	*/
25821	*skip = 1;
25822	return (0);
25823    }
25824    {
25825	xmlSchemaElementPtr decl = NULL;
25826
25827	decl = xmlSchemaGetElem(vctxt->schema,
25828	    vctxt->inode->localName, vctxt->inode->nsName);
25829	if (decl != NULL) {
25830	    vctxt->inode->decl = decl;
25831	    return (0);
25832	}
25833    }
25834    if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25835	/* VAL TODO: Change to proper error code. */
25836	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25837	    "No matching global element declaration available, but "
25838	    "demanded by the strict wildcard");
25839	return (vctxt->err);
25840    }
25841    if (vctxt->nbAttrInfos != 0) {
25842	xmlSchemaAttrInfoPtr iattr;
25843	/*
25844	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25845	* (1.2.1.2.1) - (1.2.1.2.3 )
25846	*
25847	* Use the xsi:type attribute for the type definition.
25848	*/
25849	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25850	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25851	if (iattr != NULL) {
25852	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25853		&(vctxt->inode->typeDef), NULL) == -1) {
25854		VERROR_INT("xmlSchemaValidateElemWildcard",
25855		    "calling xmlSchemaProcessXSIType() to "
25856		    "process the attribute 'xsi:nil'");
25857		return (-1);
25858	    }
25859	    /*
25860	    * Don't return an error on purpose.
25861	    */
25862	    return (0);
25863	}
25864    }
25865    /*
25866    * SPEC Validation Rule: Schema-Validity Assessment (Element)
25867    *
25868    * Fallback to "anyType".
25869    */
25870    vctxt->inode->typeDef =
25871	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25872    return (0);
25873}
25874
25875/*
25876* xmlSchemaCheckCOSValidDefault:
25877*
25878* This will be called if: not nilled, no content and a default/fixed
25879* value is provided.
25880*/
25881
25882static int
25883xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25884			      const xmlChar *value,
25885			      xmlSchemaValPtr *val)
25886{
25887    int ret = 0;
25888    xmlSchemaNodeInfoPtr inode = vctxt->inode;
25889
25890    /*
25891    * cos-valid-default:
25892    * Schema Component Constraint: Element Default Valid (Immediate)
25893    * For a string to be a valid default with respect to a type
25894    * definition the appropriate case among the following must be true:
25895    */
25896    if WXS_IS_COMPLEX(inode->typeDef) {
25897	/*
25898	* Complex type.
25899	*
25900	* SPEC (2.1) "its {content type} must be a simple type definition
25901	* or mixed."
25902	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25903	* type}'s particle must be `emptiable` as defined by
25904	* Particle Emptiable ($3.9.6)."
25905	*/
25906	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25907	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25908	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25909	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25910	    /* NOTE that this covers (2.2.2) as well. */
25911	    VERROR(ret, NULL,
25912		"For a string to be a valid default, the type definition "
25913		"must be a simple type or a complex type with simple content "
25914		"or mixed content and a particle emptiable");
25915	    return(ret);
25916	}
25917    }
25918    /*
25919    * 1 If the type definition is a simple type definition, then the string
25920    * must be `valid` with respect to that definition as defined by String
25921    * Valid ($3.14.4).
25922    *
25923    * AND
25924    *
25925    * 2.2.1 If the {content type} is a simple type definition, then the
25926    * string must be `valid` with respect to that simple type definition
25927    * as defined by String Valid ($3.14.4).
25928    */
25929    if (WXS_IS_SIMPLE(inode->typeDef)) {
25930
25931	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25932	    NULL, inode->typeDef, value, val, 1, 1, 0);
25933
25934    } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25935
25936	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25937	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25938    }
25939    if (ret < 0) {
25940	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25941	    "calling xmlSchemaVCheckCVCSimpleType()");
25942    }
25943    return (ret);
25944}
25945
25946static void
25947xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25948			       const xmlChar * name ATTRIBUTE_UNUSED,
25949			       xmlSchemaElementPtr item,
25950			       xmlSchemaNodeInfoPtr inode)
25951{
25952    inode->decl = item;
25953#ifdef DEBUG_CONTENT
25954    {
25955	xmlChar *str = NULL;
25956
25957	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25958	    xmlGenericError(xmlGenericErrorContext,
25959		"AUTOMATON callback for '%s' [declaration]\n",
25960		xmlSchemaFormatQName(&str,
25961		inode->localName, inode->nsName));
25962	} else {
25963	    xmlGenericError(xmlGenericErrorContext,
25964		    "AUTOMATON callback for '%s' [wildcard]\n",
25965		    xmlSchemaFormatQName(&str,
25966		    inode->localName, inode->nsName));
25967
25968	}
25969	FREE_AND_NULL(str)
25970    }
25971#endif
25972}
25973
25974static int
25975xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25976{
25977    vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25978    if (vctxt->inode == NULL) {
25979	VERROR_INT("xmlSchemaValidatorPushElem",
25980	    "calling xmlSchemaGetFreshElemInfo()");
25981	return (-1);
25982    }
25983    vctxt->nbAttrInfos = 0;
25984    return (0);
25985}
25986
25987static int
25988xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25989			     xmlSchemaNodeInfoPtr inode,
25990			     xmlSchemaTypePtr type,
25991			     const xmlChar *value)
25992{
25993    if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25994	return (xmlSchemaVCheckCVCSimpleType(
25995	    ACTXT_CAST vctxt, NULL,
25996	    type, value, &(inode->val), 1, 1, 0));
25997    else
25998	return (xmlSchemaVCheckCVCSimpleType(
25999	    ACTXT_CAST vctxt, NULL,
26000	    type, value, NULL, 1, 0, 0));
26001}
26002
26003
26004
26005/*
26006* Process END of element.
26007*/
26008static int
26009xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26010{
26011    int ret = 0;
26012    xmlSchemaNodeInfoPtr inode = vctxt->inode;
26013
26014    if (vctxt->nbAttrInfos != 0)
26015	xmlSchemaClearAttrInfos(vctxt);
26016    if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26017	/*
26018	* This element was not expected;
26019	* we will not validate child elements of broken parents.
26020	* Skip validation of all content of the parent.
26021	*/
26022	vctxt->skipDepth = vctxt->depth -1;
26023	goto end_elem;
26024    }
26025    if ((inode->typeDef == NULL) ||
26026	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26027	/*
26028	* 1. the type definition might be missing if the element was
26029	*    error prone
26030	* 2. it might be abstract.
26031	*/
26032	goto end_elem;
26033    }
26034    /*
26035    * Check the content model.
26036    */
26037    if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26038	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26039
26040	/*
26041	* Workaround for "anyType".
26042	*/
26043	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26044	    goto character_content;
26045
26046	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26047	    xmlChar *values[10];
26048	    int terminal, nbval = 10, nbneg;
26049
26050	    if (inode->regexCtxt == NULL) {
26051		/*
26052		* Create the regex context.
26053		*/
26054		inode->regexCtxt =
26055		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26056		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26057		    vctxt);
26058		if (inode->regexCtxt == NULL) {
26059		    VERROR_INT("xmlSchemaValidatorPopElem",
26060			"failed to create a regex context");
26061		    goto internal_error;
26062		}
26063#ifdef DEBUG_AUTOMATA
26064		xmlGenericError(xmlGenericErrorContext,
26065		    "AUTOMATON create on '%s'\n", inode->localName);
26066#endif
26067	    }
26068
26069	    /*
26070	     * Do not check further content if the node has been nilled
26071	     */
26072	    if (INODE_NILLED(inode)) {
26073		ret = 0;
26074#ifdef DEBUG_AUTOMATA
26075		xmlGenericError(xmlGenericErrorContext,
26076		    "AUTOMATON succeeded on nilled '%s'\n",
26077		    inode->localName);
26078#endif
26079                goto skip_nilled;
26080	    }
26081
26082	    /*
26083	    * Get hold of the still expected content, since a further
26084	    * call to xmlRegExecPushString() will loose this information.
26085	    */
26086	    xmlRegExecNextValues(inode->regexCtxt,
26087		&nbval, &nbneg, &values[0], &terminal);
26088	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26089	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26090		/*
26091		* Still missing something.
26092		*/
26093		ret = 1;
26094		inode->flags |=
26095		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26096		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26097		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26098		    "Missing child element(s)",
26099		    nbval, nbneg, values);
26100#ifdef DEBUG_AUTOMATA
26101		xmlGenericError(xmlGenericErrorContext,
26102		    "AUTOMATON missing ERROR on '%s'\n",
26103		    inode->localName);
26104#endif
26105	    } else {
26106		/*
26107		* Content model is satisfied.
26108		*/
26109		ret = 0;
26110#ifdef DEBUG_AUTOMATA
26111		xmlGenericError(xmlGenericErrorContext,
26112		    "AUTOMATON succeeded on '%s'\n",
26113		    inode->localName);
26114#endif
26115	    }
26116
26117	}
26118    }
26119
26120skip_nilled:
26121
26122    if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26123	goto end_elem;
26124
26125character_content:
26126
26127    if (vctxt->value != NULL) {
26128	xmlSchemaFreeValue(vctxt->value);
26129	vctxt->value = NULL;
26130    }
26131    /*
26132    * Check character content.
26133    */
26134    if (inode->decl == NULL) {
26135	/*
26136	* Speedup if no declaration exists.
26137	*/
26138	if (WXS_IS_SIMPLE(inode->typeDef)) {
26139	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26140		inode, inode->typeDef, inode->value);
26141	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26142	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26143		inode, inode->typeDef->contentTypeDef,
26144		inode->value);
26145	}
26146	if (ret < 0) {
26147	    VERROR_INT("xmlSchemaValidatorPopElem",
26148		"calling xmlSchemaVCheckCVCSimpleType()");
26149	    goto internal_error;
26150	}
26151	goto end_elem;
26152    }
26153    /*
26154    * cvc-elt (3.3.4) : 5
26155    * The appropriate case among the following must be true:
26156    */
26157    /*
26158    * cvc-elt (3.3.4) : 5.1
26159    * If the declaration has a {value constraint},
26160    * the item has neither element nor character [children] and
26161    * clause 3.2 has not applied, then all of the following must be true:
26162    */
26163    if ((inode->decl->value != NULL) &&
26164	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26165	(! INODE_NILLED(inode))) {
26166	/*
26167	* cvc-elt (3.3.4) : 5.1.1
26168	* If the `actual type definition` is a `local type definition`
26169	* then the canonical lexical representation of the {value constraint}
26170	* value must be a valid default for the `actual type definition` as
26171	* defined in Element Default Valid (Immediate) ($3.3.6).
26172	*/
26173	/*
26174	* NOTE: 'local' above means types acquired by xsi:type.
26175	* NOTE: Although the *canonical* value is stated, it is not
26176	* relevant if canonical or not. Additionally XML Schema 1.1
26177	* will removed this requirement as well.
26178	*/
26179	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26180
26181	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26182		inode->decl->value, &(inode->val));
26183	    if (ret != 0) {
26184		if (ret < 0) {
26185		    VERROR_INT("xmlSchemaValidatorPopElem",
26186			"calling xmlSchemaCheckCOSValidDefault()");
26187		    goto internal_error;
26188		}
26189		goto end_elem;
26190	    }
26191	    /*
26192	    * Stop here, to avoid redundant validation of the value
26193	    * (see following).
26194	    */
26195	    goto default_psvi;
26196	}
26197	/*
26198	* cvc-elt (3.3.4) : 5.1.2
26199	* The element information item with the canonical lexical
26200	* representation of the {value constraint} value used as its
26201	* `normalized value` must be `valid` with respect to the
26202	* `actual type definition` as defined by Element Locally Valid (Type)
26203	* ($3.3.4).
26204	*/
26205	if (WXS_IS_SIMPLE(inode->typeDef)) {
26206	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26207		inode, inode->typeDef, inode->decl->value);
26208	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26209	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26210		inode, inode->typeDef->contentTypeDef,
26211		inode->decl->value);
26212	}
26213	if (ret != 0) {
26214	    if (ret < 0) {
26215		VERROR_INT("xmlSchemaValidatorPopElem",
26216		    "calling xmlSchemaVCheckCVCSimpleType()");
26217		goto internal_error;
26218	    }
26219	    goto end_elem;
26220	}
26221
26222default_psvi:
26223	/*
26224	* PSVI: Create a text node on the instance element.
26225	*/
26226	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26227	    (inode->node != NULL)) {
26228	    xmlNodePtr textChild;
26229	    xmlChar *normValue;
26230	    /*
26231	    * VAL TODO: Normalize the value.
26232	    */
26233	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26234		inode->decl->value);
26235	    if (normValue != NULL) {
26236		textChild = xmlNewText(BAD_CAST normValue);
26237		xmlFree(normValue);
26238	    } else
26239		textChild = xmlNewText(inode->decl->value);
26240	    if (textChild == NULL) {
26241		VERROR_INT("xmlSchemaValidatorPopElem",
26242		    "calling xmlNewText()");
26243		goto internal_error;
26244	    } else
26245		xmlAddChild(inode->node, textChild);
26246	}
26247
26248    } else if (! INODE_NILLED(inode)) {
26249	/*
26250	* 5.2.1 The element information item must be `valid` with respect
26251	* to the `actual type definition` as defined by Element Locally
26252	* Valid (Type) ($3.3.4).
26253	*/
26254	if (WXS_IS_SIMPLE(inode->typeDef)) {
26255	     /*
26256	    * SPEC (cvc-type) (3.1)
26257	    * "If the type definition is a simple type definition, ..."
26258	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26259	    * (Element) ($3.3.4) did not apply, then the `normalized value`
26260	    * must be `valid` with respect to the type definition as defined
26261	    * by String Valid ($3.14.4).
26262	    */
26263	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26264		    inode, inode->typeDef, inode->value);
26265	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26266	    /*
26267	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26268	    * definition, then the element information item must be
26269	    * `valid` with respect to the type definition as per
26270	    * Element Locally Valid (Complex Type) ($3.4.4);"
26271	    *
26272	    * SPEC (cvc-complex-type) (2.2)
26273	    * "If the {content type} is a simple type definition, ...
26274	    * the `normalized value` of the element information item is
26275	    * `valid` with respect to that simple type definition as
26276	    * defined by String Valid ($3.14.4)."
26277	    */
26278	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26279		inode, inode->typeDef->contentTypeDef, inode->value);
26280	}
26281	if (ret != 0) {
26282	    if (ret < 0) {
26283		VERROR_INT("xmlSchemaValidatorPopElem",
26284		    "calling xmlSchemaVCheckCVCSimpleType()");
26285		goto internal_error;
26286	    }
26287	    goto end_elem;
26288	}
26289	/*
26290	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26291	* not applied, all of the following must be true:
26292	*/
26293	if ((inode->decl->value != NULL) &&
26294	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26295
26296	    /*
26297	    * TODO: We will need a computed value, when comparison is
26298	    * done on computed values.
26299	    */
26300	    /*
26301	    * 5.2.2.1 The element information item must have no element
26302	    * information item [children].
26303	    */
26304	    if (inode->flags &
26305		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26306		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26307		VERROR(ret, NULL,
26308		    "The content must not containt element nodes since "
26309		    "there is a fixed value constraint");
26310		goto end_elem;
26311	    } else {
26312		/*
26313		* 5.2.2.2 The appropriate case among the following must
26314		* be true:
26315		*/
26316		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26317		    /*
26318		    * 5.2.2.2.1 If the {content type} of the `actual type
26319		    * definition` is mixed, then the *initial value* of the
26320		    * item must match the canonical lexical representation
26321		    * of the {value constraint} value.
26322		    *
26323		    * ... the *initial value* of an element information
26324		    * item is the string composed of, in order, the
26325		    * [character code] of each character information item in
26326		    * the [children] of that element information item.
26327		    */
26328		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26329			/*
26330			* VAL TODO: Report invalid & expected values as well.
26331			* VAL TODO: Implement the canonical stuff.
26332			*/
26333			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26334			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26335			    ret, NULL, NULL,
26336			    "The initial value '%s' does not match the fixed "
26337			    "value constraint '%s'",
26338			    inode->value, inode->decl->value);
26339			goto end_elem;
26340		    }
26341		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26342		    /*
26343		    * 5.2.2.2.2 If the {content type} of the `actual type
26344		    * definition` is a simple type definition, then the
26345		    * *actual value* of the item must match the canonical
26346		    * lexical representation of the {value constraint} value.
26347		    */
26348		    /*
26349		    * VAL TODO: *actual value* is the normalized value, impl.
26350		    *           this.
26351		    * VAL TODO: Report invalid & expected values as well.
26352		    * VAL TODO: Implement a comparison with the computed values.
26353		    */
26354		    if (! xmlStrEqual(inode->value,
26355			    inode->decl->value)) {
26356			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26357			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26358			    ret, NULL, NULL,
26359			    "The actual value '%s' does not match the fixed "
26360			    "value constraint '%s'",
26361			    inode->value,
26362			    inode->decl->value);
26363			goto end_elem;
26364		    }
26365		}
26366	    }
26367	}
26368    }
26369
26370end_elem:
26371    if (vctxt->depth < 0) {
26372	/* TODO: raise error? */
26373	return (0);
26374    }
26375    if (vctxt->depth == vctxt->skipDepth)
26376	vctxt->skipDepth = -1;
26377    /*
26378    * Evaluate the history of XPath state objects.
26379    */
26380    if (inode->appliedXPath &&
26381	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26382	goto internal_error;
26383    /*
26384    * MAYBE TODO:
26385    * SPEC (6) "The element information item must be `valid` with
26386    * respect to each of the {identity-constraint definitions} as per
26387    * Identity-constraint Satisfied ($3.11.4)."
26388    */
26389    /*
26390    * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26391    *   need to be built in any case.
26392    *   We will currently build IDC node-tables and bubble them only if
26393    *   keyrefs do exist.
26394    */
26395
26396    /*
26397    * Add the current IDC target-nodes to the IDC node-tables.
26398    */
26399    if ((inode->idcMatchers != NULL) &&
26400	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26401    {
26402	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26403	    goto internal_error;
26404    }
26405    /*
26406    * Validate IDC keyrefs.
26407    */
26408    if (vctxt->inode->hasKeyrefs)
26409	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26410	    goto internal_error;
26411    /*
26412    * Merge/free the IDC table.
26413    */
26414    if (inode->idcTable != NULL) {
26415#ifdef DEBUG_IDC_NODE_TABLE
26416	xmlSchemaDebugDumpIDCTable(stdout,
26417	    inode->nsName,
26418	    inode->localName,
26419	    inode->idcTable);
26420#endif
26421	if ((vctxt->depth > 0) &&
26422	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26423	{
26424	    /*
26425	    * Merge the IDC node table with the table of the parent node.
26426	    */
26427	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26428		goto internal_error;
26429	}
26430    }
26431    /*
26432    * Clear the current ielem.
26433    * VAL TODO: Don't free the PSVI IDC tables if they are
26434    * requested for the PSVI.
26435    */
26436    xmlSchemaClearElemInfo(vctxt, inode);
26437    /*
26438    * Skip further processing if we are on the validation root.
26439    */
26440    if (vctxt->depth == 0) {
26441	vctxt->depth--;
26442	vctxt->inode = NULL;
26443	return (0);
26444    }
26445    /*
26446    * Reset the keyrefDepth if needed.
26447    */
26448    if (vctxt->aidcs != NULL) {
26449	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26450	do {
26451	    if (aidc->keyrefDepth == vctxt->depth) {
26452		/*
26453		* A 'keyrefDepth' of a key/unique IDC matches the current
26454		* depth, this means that we are leaving the scope of the
26455		* top-most keyref IDC which refers to this IDC.
26456		*/
26457		aidc->keyrefDepth = -1;
26458	    }
26459	    aidc = aidc->next;
26460	} while (aidc != NULL);
26461    }
26462    vctxt->depth--;
26463    vctxt->inode = vctxt->elemInfos[vctxt->depth];
26464    /*
26465    * VAL TODO: 7 If the element information item is the `validation root`, it must be
26466    * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26467    */
26468    return (ret);
26469
26470internal_error:
26471    vctxt->err = -1;
26472    return (-1);
26473}
26474
26475/*
26476* 3.4.4 Complex Type Definition Validation Rules
26477* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26478*/
26479static int
26480xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26481{
26482    xmlSchemaNodeInfoPtr pielem;
26483    xmlSchemaTypePtr ptype;
26484    int ret = 0;
26485
26486    if (vctxt->depth <= 0) {
26487	VERROR_INT("xmlSchemaValidateChildElem",
26488	    "not intended for the validation root");
26489	return (-1);
26490    }
26491    pielem = vctxt->elemInfos[vctxt->depth -1];
26492    if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26493	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26494    /*
26495    * Handle 'nilled' elements.
26496    */
26497    if (INODE_NILLED(pielem)) {
26498	/*
26499	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26500	*/
26501	ACTIVATE_PARENT_ELEM;
26502	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26503	VERROR(ret, NULL,
26504	    "Neither character nor element content is allowed, "
26505	    "because the element was 'nilled'");
26506	ACTIVATE_ELEM;
26507	goto unexpected_elem;
26508    }
26509
26510    ptype = pielem->typeDef;
26511
26512    if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26513	/*
26514	* Workaround for "anyType": we have currently no content model
26515	* assigned for "anyType", so handle it explicitely.
26516	* "anyType" has an unbounded, lax "any" wildcard.
26517	*/
26518	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26519	    vctxt->inode->localName,
26520	    vctxt->inode->nsName);
26521
26522	if (vctxt->inode->decl == NULL) {
26523	    xmlSchemaAttrInfoPtr iattr;
26524	    /*
26525	    * Process "xsi:type".
26526	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26527	    */
26528	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26529		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26530	    if (iattr != NULL) {
26531		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26532		    &(vctxt->inode->typeDef), NULL);
26533		if (ret != 0) {
26534		    if (ret == -1) {
26535			VERROR_INT("xmlSchemaValidateChildElem",
26536			    "calling xmlSchemaProcessXSIType() to "
26537			    "process the attribute 'xsi:nil'");
26538			return (-1);
26539		    }
26540		    return (ret);
26541		}
26542	    } else {
26543		 /*
26544		 * Fallback to "anyType".
26545		 *
26546		 * SPEC (cvc-assess-elt)
26547		 * "If the item cannot be `strictly assessed`, [...]
26548		 * an element information item's schema validity may be laxly
26549		 * assessed if its `context-determined declaration` is not
26550		 * skip by `validating` with respect to the `ur-type
26551		 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26552		*/
26553		vctxt->inode->typeDef =
26554		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26555	    }
26556	}
26557	return (0);
26558    }
26559
26560    switch (ptype->contentType) {
26561	case XML_SCHEMA_CONTENT_EMPTY:
26562	    /*
26563	    * SPEC (2.1) "If the {content type} is empty, then the
26564	    * element information item has no character or element
26565	    * information item [children]."
26566	    */
26567	    ACTIVATE_PARENT_ELEM
26568	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26569	    VERROR(ret, NULL,
26570		"Element content is not allowed, "
26571		"because the content type is empty");
26572	    ACTIVATE_ELEM
26573	    goto unexpected_elem;
26574	    break;
26575
26576	case XML_SCHEMA_CONTENT_MIXED:
26577        case XML_SCHEMA_CONTENT_ELEMENTS: {
26578	    xmlRegExecCtxtPtr regexCtxt;
26579	    xmlChar *values[10];
26580	    int terminal, nbval = 10, nbneg;
26581
26582	    /* VAL TODO: Optimized "anyType" validation.*/
26583
26584	    if (ptype->contModel == NULL) {
26585		VERROR_INT("xmlSchemaValidateChildElem",
26586		    "type has elem content but no content model");
26587		return (-1);
26588	    }
26589	    /*
26590	    * Safety belf for evaluation if the cont. model was already
26591	    * examined to be invalid.
26592	    */
26593	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26594		VERROR_INT("xmlSchemaValidateChildElem",
26595		    "validating elem, but elem content is already invalid");
26596		return (-1);
26597	    }
26598
26599	    regexCtxt = pielem->regexCtxt;
26600	    if (regexCtxt == NULL) {
26601		/*
26602		* Create the regex context.
26603		*/
26604		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26605		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26606		    vctxt);
26607		if (regexCtxt == NULL) {
26608		    VERROR_INT("xmlSchemaValidateChildElem",
26609			"failed to create a regex context");
26610		    return (-1);
26611		}
26612		pielem->regexCtxt = regexCtxt;
26613#ifdef DEBUG_AUTOMATA
26614		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26615		    pielem->localName);
26616#endif
26617	    }
26618
26619	    /*
26620	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26621	    * then the sequence of the element information item's
26622	    * element information item [children], if any, taken in
26623	    * order, is `valid` with respect to the {content type}'s
26624	    * particle, as defined in Element Sequence Locally Valid
26625	    * (Particle) ($3.9.4)."
26626	    */
26627	    ret = xmlRegExecPushString2(regexCtxt,
26628		vctxt->inode->localName,
26629		vctxt->inode->nsName,
26630		vctxt->inode);
26631#ifdef DEBUG_AUTOMATA
26632	    if (ret < 0)
26633		xmlGenericError(xmlGenericErrorContext,
26634		"AUTOMATON push ERROR for '%s' on '%s'\n",
26635		vctxt->inode->localName, pielem->localName);
26636	    else
26637		xmlGenericError(xmlGenericErrorContext,
26638		"AUTOMATON push OK for '%s' on '%s'\n",
26639		vctxt->inode->localName, pielem->localName);
26640#endif
26641	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26642		VERROR_INT("xmlSchemaValidateChildElem",
26643		    "calling xmlRegExecPushString2()");
26644		return (-1);
26645	    }
26646	    if (ret < 0) {
26647		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26648		    &values[0], &terminal);
26649		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26650		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26651		    "This element is not expected",
26652		    nbval, nbneg, values);
26653		ret = vctxt->err;
26654		goto unexpected_elem;
26655	    } else
26656		ret = 0;
26657	}
26658	    break;
26659	case XML_SCHEMA_CONTENT_SIMPLE:
26660	case XML_SCHEMA_CONTENT_BASIC:
26661	    ACTIVATE_PARENT_ELEM
26662	    if (WXS_IS_COMPLEX(ptype)) {
26663		/*
26664		* SPEC (cvc-complex-type) (2.2)
26665		* "If the {content type} is a simple type definition, then
26666		* the element information item has no element information
26667		* item [children], ..."
26668		*/
26669		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26670		VERROR(ret, NULL, "Element content is not allowed, "
26671		    "because the content type is a simple type definition");
26672	    } else {
26673		/*
26674		* SPEC (cvc-type) (3.1.2) "The element information item must
26675		* have no element information item [children]."
26676		*/
26677		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26678		VERROR(ret, NULL, "Element content is not allowed, "
26679		    "because the type definition is simple");
26680	    }
26681	    ACTIVATE_ELEM
26682	    ret = vctxt->err;
26683	    goto unexpected_elem;
26684	    break;
26685
26686	default:
26687	    break;
26688    }
26689    return (ret);
26690unexpected_elem:
26691    /*
26692    * Pop this element and set the skipDepth to skip
26693    * all further content of the parent element.
26694    */
26695    vctxt->skipDepth = vctxt->depth;
26696    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26697    pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26698    return (ret);
26699}
26700
26701#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26702#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26703#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26704
26705static int
26706xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26707		  int nodeType, const xmlChar *value, int len,
26708		  int mode, int *consumed)
26709{
26710    /*
26711    * Unfortunately we have to duplicate the text sometimes.
26712    * OPTIMIZE: Maybe we could skip it, if:
26713    *   1. content type is simple
26714    *   2. whitespace is "collapse"
26715    *   3. it consists of whitespace only
26716    *
26717    * Process character content.
26718    */
26719    if (consumed != NULL)
26720	*consumed = 0;
26721    if (INODE_NILLED(vctxt->inode)) {
26722	/*
26723	* SPEC cvc-elt (3.3.4 - 3.2.1)
26724	* "The element information item must have no character or
26725	* element information item [children]."
26726	*/
26727	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26728	    "Neither character nor element content is allowed "
26729	    "because the element is 'nilled'");
26730	return (vctxt->err);
26731    }
26732    /*
26733    * SPEC (2.1) "If the {content type} is empty, then the
26734    * element information item has no character or element
26735    * information item [children]."
26736    */
26737    if (vctxt->inode->typeDef->contentType ==
26738	    XML_SCHEMA_CONTENT_EMPTY) {
26739	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26740	    "Character content is not allowed, "
26741	    "because the content type is empty");
26742	return (vctxt->err);
26743    }
26744
26745    if (vctxt->inode->typeDef->contentType ==
26746	    XML_SCHEMA_CONTENT_ELEMENTS) {
26747	if ((nodeType != XML_TEXT_NODE) ||
26748	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26749	    /*
26750	    * SPEC cvc-complex-type (2.3)
26751	    * "If the {content type} is element-only, then the
26752	    * element information item has no character information
26753	    * item [children] other than those whose [character
26754	    * code] is defined as a white space in [XML 1.0 (Second
26755	    * Edition)]."
26756	    */
26757	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26758		"Character content other than whitespace is not allowed "
26759		"because the content type is 'element-only'");
26760	    return (vctxt->err);
26761	}
26762	return (0);
26763    }
26764
26765    if ((value == NULL) || (value[0] == 0))
26766	return (0);
26767    /*
26768    * Save the value.
26769    * NOTE that even if the content type is *mixed*, we need the
26770    * *initial value* for default/fixed value constraints.
26771    */
26772    if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26773	((vctxt->inode->decl == NULL) ||
26774	(vctxt->inode->decl->value == NULL)))
26775	return (0);
26776
26777    if (vctxt->inode->value == NULL) {
26778	/*
26779	* Set the value.
26780	*/
26781	switch (mode) {
26782	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26783		/*
26784		* When working on a tree.
26785		*/
26786		vctxt->inode->value = value;
26787		break;
26788	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26789		/*
26790		* When working with the reader.
26791		* The value will be freed by the element info.
26792		*/
26793		vctxt->inode->value = value;
26794		if (consumed != NULL)
26795		    *consumed = 1;
26796		vctxt->inode->flags |=
26797		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26798		break;
26799	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26800		/*
26801		* When working with SAX.
26802		* The value will be freed by the element info.
26803		*/
26804		if (len != -1)
26805		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26806		else
26807		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26808		vctxt->inode->flags |=
26809		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26810		break;
26811	    default:
26812		break;
26813	}
26814    } else {
26815	if (len < 0)
26816	    len = xmlStrlen(value);
26817	/*
26818	* Concat the value.
26819	*/
26820	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26821	    vctxt->inode->value = BAD_CAST xmlStrncat(
26822		(xmlChar *) vctxt->inode->value, value, len);
26823	} else {
26824	    vctxt->inode->value =
26825		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26826	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26827	}
26828    }
26829
26830    return (0);
26831}
26832
26833static int
26834xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26835{
26836    int ret = 0;
26837
26838    if ((vctxt->skipDepth != -1) &&
26839	(vctxt->depth >= vctxt->skipDepth)) {
26840	VERROR_INT("xmlSchemaValidateElem",
26841	    "in skip-state");
26842	goto internal_error;
26843    }
26844    if (vctxt->xsiAssemble) {
26845	/*
26846	* We will stop validation if there was an error during
26847	* dynamic schema construction.
26848	* Note that we simply set @skipDepth to 0, this could
26849	* mean that a streaming document via SAX would be
26850	* still read to the end but it won't be validated any more.
26851	* TODO: If we are sure how to stop the validation at once
26852	*   for all input scenarios, then this should be changed to
26853	*   instantly stop the validation.
26854	*/
26855	ret = xmlSchemaAssembleByXSI(vctxt);
26856	if (ret != 0) {
26857	    if (ret == -1)
26858		goto internal_error;
26859	    vctxt->skipDepth = 0;
26860	    return(ret);
26861	}
26862        /*
26863         * Augment the IDC definitions for the main schema and all imported ones
26864         * NOTE: main schema is the first in the imported list
26865         */
26866        xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26867    }
26868    if (vctxt->depth > 0) {
26869	/*
26870	* Validate this element against the content model
26871	* of the parent.
26872	*/
26873	ret = xmlSchemaValidateChildElem(vctxt);
26874	if (ret != 0) {
26875	    if (ret < 0) {
26876		VERROR_INT("xmlSchemaValidateElem",
26877		    "calling xmlSchemaStreamValidateChildElement()");
26878		goto internal_error;
26879	    }
26880	    goto exit;
26881	}
26882	if (vctxt->depth == vctxt->skipDepth)
26883	    goto exit;
26884	if ((vctxt->inode->decl == NULL) &&
26885	    (vctxt->inode->typeDef == NULL)) {
26886	    VERROR_INT("xmlSchemaValidateElem",
26887		"the child element was valid but neither the "
26888		"declaration nor the type was set");
26889	    goto internal_error;
26890	}
26891    } else {
26892	/*
26893	* Get the declaration of the validation root.
26894	*/
26895	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26896	    vctxt->inode->localName,
26897	    vctxt->inode->nsName);
26898	if (vctxt->inode->decl == NULL) {
26899	    ret = XML_SCHEMAV_CVC_ELT_1;
26900	    VERROR(ret, NULL,
26901		"No matching global declaration available "
26902		"for the validation root");
26903	    goto exit;
26904	}
26905    }
26906
26907    if (vctxt->inode->decl == NULL)
26908	goto type_validation;
26909
26910    if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26911	int skip;
26912	/*
26913	* Wildcards.
26914	*/
26915	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26916	if (ret != 0) {
26917	    if (ret < 0) {
26918		VERROR_INT("xmlSchemaValidateElem",
26919		    "calling xmlSchemaValidateElemWildcard()");
26920		goto internal_error;
26921	    }
26922	    goto exit;
26923	}
26924	if (skip) {
26925	    vctxt->skipDepth = vctxt->depth;
26926	    goto exit;
26927	}
26928	/*
26929	* The declaration might be set by the wildcard validation,
26930	* when the processContents is "lax" or "strict".
26931	*/
26932	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26933	    /*
26934	    * Clear the "decl" field to not confuse further processing.
26935	    */
26936	    vctxt->inode->decl = NULL;
26937	    goto type_validation;
26938	}
26939    }
26940    /*
26941    * Validate against the declaration.
26942    */
26943    ret = xmlSchemaValidateElemDecl(vctxt);
26944    if (ret != 0) {
26945	if (ret < 0) {
26946	    VERROR_INT("xmlSchemaValidateElem",
26947		"calling xmlSchemaValidateElemDecl()");
26948	    goto internal_error;
26949	}
26950	goto exit;
26951    }
26952    /*
26953    * Validate against the type definition.
26954    */
26955type_validation:
26956
26957    if (vctxt->inode->typeDef == NULL) {
26958	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26959	ret = XML_SCHEMAV_CVC_TYPE_1;
26960	VERROR(ret, NULL,
26961	    "The type definition is absent");
26962	goto exit;
26963    }
26964    if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26965	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26966	ret = XML_SCHEMAV_CVC_TYPE_2;
26967	    VERROR(ret, NULL,
26968	    "The type definition is abstract");
26969	goto exit;
26970    }
26971    /*
26972    * Evaluate IDCs. Do it here, since new IDC matchers are registered
26973    * during validation against the declaration. This must be done
26974    * _before_ attribute validation.
26975    */
26976    if (vctxt->xpathStates != NULL) {
26977	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26978	vctxt->inode->appliedXPath = 1;
26979	if (ret == -1) {
26980	    VERROR_INT("xmlSchemaValidateElem",
26981		"calling xmlSchemaXPathEvaluate()");
26982	    goto internal_error;
26983	}
26984    }
26985    /*
26986    * Validate attributes.
26987    */
26988    if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26989	if ((vctxt->nbAttrInfos != 0) ||
26990	    (vctxt->inode->typeDef->attrUses != NULL)) {
26991
26992	    ret = xmlSchemaVAttributesComplex(vctxt);
26993	}
26994    } else if (vctxt->nbAttrInfos != 0) {
26995
26996	ret = xmlSchemaVAttributesSimple(vctxt);
26997    }
26998    /*
26999    * Clear registered attributes.
27000    */
27001    if (vctxt->nbAttrInfos != 0)
27002	xmlSchemaClearAttrInfos(vctxt);
27003    if (ret == -1) {
27004	VERROR_INT("xmlSchemaValidateElem",
27005	    "calling attributes validation");
27006	goto internal_error;
27007    }
27008    /*
27009    * Don't return an error if attributes are invalid on purpose.
27010    */
27011    ret = 0;
27012
27013exit:
27014    if (ret != 0)
27015	vctxt->skipDepth = vctxt->depth;
27016    return (ret);
27017internal_error:
27018    return (-1);
27019}
27020
27021#ifdef XML_SCHEMA_READER_ENABLED
27022static int
27023xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27024{
27025    const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27026    int depth, nodeType, ret = 0, consumed;
27027    xmlSchemaNodeInfoPtr ielem;
27028
27029    vctxt->depth = -1;
27030    ret = xmlTextReaderRead(vctxt->reader);
27031    /*
27032    * Move to the document element.
27033    */
27034    while (ret == 1) {
27035	nodeType = xmlTextReaderNodeType(vctxt->reader);
27036	if (nodeType == XML_ELEMENT_NODE)
27037	    goto root_found;
27038	ret = xmlTextReaderRead(vctxt->reader);
27039    }
27040    goto exit;
27041
27042root_found:
27043
27044    do {
27045	depth = xmlTextReaderDepth(vctxt->reader);
27046	nodeType = xmlTextReaderNodeType(vctxt->reader);
27047
27048	if (nodeType == XML_ELEMENT_NODE) {
27049
27050	    vctxt->depth++;
27051	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27052		VERROR_INT("xmlSchemaVReaderWalk",
27053		    "calling xmlSchemaValidatorPushElem()");
27054		goto internal_error;
27055	    }
27056	    ielem = vctxt->inode;
27057	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27058	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27059	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27060	    /*
27061	    * Is the element empty?
27062	    */
27063	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27064	    if (ret == -1) {
27065		VERROR_INT("xmlSchemaVReaderWalk",
27066		    "calling xmlTextReaderIsEmptyElement()");
27067		goto internal_error;
27068	    }
27069	    if (ret) {
27070		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27071	    }
27072	    /*
27073	    * Register attributes.
27074	    */
27075	    vctxt->nbAttrInfos = 0;
27076	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27077	    if (ret == -1) {
27078		VERROR_INT("xmlSchemaVReaderWalk",
27079		    "calling xmlTextReaderMoveToFirstAttribute()");
27080		goto internal_error;
27081	    }
27082	    if (ret == 1) {
27083		do {
27084		    /*
27085		    * VAL TODO: How do we know that the reader works on a
27086		    * node tree, to be able to pass a node here?
27087		    */
27088		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27089			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27090			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27091			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27092
27093			VERROR_INT("xmlSchemaVReaderWalk",
27094			    "calling xmlSchemaValidatorPushAttribute()");
27095			goto internal_error;
27096		    }
27097		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27098		    if (ret == -1) {
27099			VERROR_INT("xmlSchemaVReaderWalk",
27100			    "calling xmlTextReaderMoveToFirstAttribute()");
27101			goto internal_error;
27102		    }
27103		} while (ret == 1);
27104		/*
27105		* Back to element position.
27106		*/
27107		ret = xmlTextReaderMoveToElement(vctxt->reader);
27108		if (ret == -1) {
27109		    VERROR_INT("xmlSchemaVReaderWalk",
27110			"calling xmlTextReaderMoveToElement()");
27111		    goto internal_error;
27112		}
27113	    }
27114	    /*
27115	    * Validate the element.
27116	    */
27117	    ret= xmlSchemaValidateElem(vctxt);
27118	    if (ret != 0) {
27119		if (ret == -1) {
27120		    VERROR_INT("xmlSchemaVReaderWalk",
27121			"calling xmlSchemaValidateElem()");
27122		    goto internal_error;
27123		}
27124		goto exit;
27125	    }
27126	    if (vctxt->depth == vctxt->skipDepth) {
27127		int curDepth;
27128		/*
27129		* Skip all content.
27130		*/
27131		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27132		    ret = xmlTextReaderRead(vctxt->reader);
27133		    curDepth = xmlTextReaderDepth(vctxt->reader);
27134		    while ((ret == 1) && (curDepth != depth)) {
27135			ret = xmlTextReaderRead(vctxt->reader);
27136			curDepth = xmlTextReaderDepth(vctxt->reader);
27137		    }
27138		    if (ret < 0) {
27139			/*
27140			* VAL TODO: A reader error occured; what to do here?
27141			*/
27142			ret = 1;
27143			goto exit;
27144		    }
27145		}
27146		goto leave_elem;
27147	    }
27148	    /*
27149	    * READER VAL TODO: Is an END_ELEM really never called
27150	    * if the elem is empty?
27151	    */
27152	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27153		goto leave_elem;
27154	} else if (nodeType == END_ELEM) {
27155	    /*
27156	    * Process END of element.
27157	    */
27158leave_elem:
27159	    ret = xmlSchemaValidatorPopElem(vctxt);
27160	    if (ret != 0) {
27161		if (ret < 0) {
27162		    VERROR_INT("xmlSchemaVReaderWalk",
27163			"calling xmlSchemaValidatorPopElem()");
27164		    goto internal_error;
27165		}
27166		goto exit;
27167	    }
27168	    if (vctxt->depth >= 0)
27169		ielem = vctxt->inode;
27170	    else
27171		ielem = NULL;
27172	} else if ((nodeType == XML_TEXT_NODE) ||
27173	    (nodeType == XML_CDATA_SECTION_NODE) ||
27174	    (nodeType == WHTSP) ||
27175	    (nodeType == SIGN_WHTSP)) {
27176	    /*
27177	    * Process character content.
27178	    */
27179	    xmlChar *value;
27180
27181	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27182		nodeType = XML_TEXT_NODE;
27183
27184	    value = xmlTextReaderValue(vctxt->reader);
27185	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27186		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27187	    if (! consumed)
27188		xmlFree(value);
27189	    if (ret == -1) {
27190		VERROR_INT("xmlSchemaVReaderWalk",
27191		    "calling xmlSchemaVPushText()");
27192		goto internal_error;
27193	    }
27194	} else if ((nodeType == XML_ENTITY_NODE) ||
27195	    (nodeType == XML_ENTITY_REF_NODE)) {
27196	    /*
27197	    * VAL TODO: What to do with entities?
27198	    */
27199	    TODO
27200	}
27201	/*
27202	* Read next node.
27203	*/
27204	ret = xmlTextReaderRead(vctxt->reader);
27205    } while (ret == 1);
27206
27207exit:
27208    return (ret);
27209internal_error:
27210    return (-1);
27211}
27212#endif
27213
27214/************************************************************************
27215 *									*
27216 *			SAX validation handlers				*
27217 *									*
27218 ************************************************************************/
27219
27220/*
27221* Process text content.
27222*/
27223static void
27224xmlSchemaSAXHandleText(void *ctx,
27225		       const xmlChar * ch,
27226		       int len)
27227{
27228    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27229
27230    if (vctxt->depth < 0)
27231	return;
27232    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27233	return;
27234    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27235	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27236    if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27237	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27238	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27239	    "calling xmlSchemaVPushText()");
27240	vctxt->err = -1;
27241	xmlStopParser(vctxt->parserCtxt);
27242    }
27243}
27244
27245/*
27246* Process CDATA content.
27247*/
27248static void
27249xmlSchemaSAXHandleCDataSection(void *ctx,
27250			     const xmlChar * ch,
27251			     int len)
27252{
27253    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27254
27255    if (vctxt->depth < 0)
27256	return;
27257    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27258	return;
27259    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27260	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27261    if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27262	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27263	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27264	    "calling xmlSchemaVPushText()");
27265	vctxt->err = -1;
27266	xmlStopParser(vctxt->parserCtxt);
27267    }
27268}
27269
27270static void
27271xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27272			    const xmlChar * name ATTRIBUTE_UNUSED)
27273{
27274    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27275
27276    if (vctxt->depth < 0)
27277	return;
27278    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27279	return;
27280    /* SAX VAL TODO: What to do here? */
27281    TODO
27282}
27283
27284static void
27285xmlSchemaSAXHandleStartElementNs(void *ctx,
27286				 const xmlChar * localname,
27287				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27288				 const xmlChar * URI,
27289				 int nb_namespaces,
27290				 const xmlChar ** namespaces,
27291				 int nb_attributes,
27292				 int nb_defaulted ATTRIBUTE_UNUSED,
27293				 const xmlChar ** attributes)
27294{
27295    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27296    int ret;
27297    xmlSchemaNodeInfoPtr ielem;
27298    int i, j;
27299
27300    /*
27301    * SAX VAL TODO: What to do with nb_defaulted?
27302    */
27303    /*
27304    * Skip elements if inside a "skip" wildcard or invalid.
27305    */
27306    vctxt->depth++;
27307    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27308	return;
27309    /*
27310    * Push the element.
27311    */
27312    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27313	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27314	    "calling xmlSchemaValidatorPushElem()");
27315	goto internal_error;
27316    }
27317    ielem = vctxt->inode;
27318    /*
27319    * TODO: Is this OK?
27320    */
27321    ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27322    ielem->localName = localname;
27323    ielem->nsName = URI;
27324    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27325    /*
27326    * Register namespaces on the elem info.
27327    */
27328    if (nb_namespaces != 0) {
27329	/*
27330	* Although the parser builds its own namespace list,
27331	* we have no access to it, so we'll use an own one.
27332	*/
27333        for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27334	    /*
27335	    * Store prefix and namespace name.
27336	    */
27337	    if (ielem->nsBindings == NULL) {
27338		ielem->nsBindings =
27339		    (const xmlChar **) xmlMalloc(10 *
27340			sizeof(const xmlChar *));
27341		if (ielem->nsBindings == NULL) {
27342		    xmlSchemaVErrMemory(vctxt,
27343			"allocating namespace bindings for SAX validation",
27344			NULL);
27345		    goto internal_error;
27346		}
27347		ielem->nbNsBindings = 0;
27348		ielem->sizeNsBindings = 5;
27349	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27350		ielem->sizeNsBindings *= 2;
27351		ielem->nsBindings =
27352		    (const xmlChar **) xmlRealloc(
27353			(void *) ielem->nsBindings,
27354			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27355		if (ielem->nsBindings == NULL) {
27356		    xmlSchemaVErrMemory(vctxt,
27357			"re-allocating namespace bindings for SAX validation",
27358			NULL);
27359		    goto internal_error;
27360		}
27361	    }
27362
27363	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27364	    if (namespaces[j+1][0] == 0) {
27365		/*
27366		* Handle xmlns="".
27367		*/
27368		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27369	    } else
27370		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27371		    namespaces[j+1];
27372	    ielem->nbNsBindings++;
27373	}
27374    }
27375    /*
27376    * Register attributes.
27377    * SAX VAL TODO: We are not adding namespace declaration
27378    * attributes yet.
27379    */
27380    if (nb_attributes != 0) {
27381	xmlChar *value;
27382
27383        for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27384	    /*
27385	    * Duplicate the value.
27386	    */
27387	    value = xmlStrndup(attributes[j+3],
27388		attributes[j+4] - attributes[j+3]);
27389	    /*
27390	    * TODO: Set the node line.
27391	    */
27392	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27393		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27394		value, 1);
27395	    if (ret == -1) {
27396		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27397		    "calling xmlSchemaValidatorPushAttribute()");
27398		goto internal_error;
27399	    }
27400	}
27401    }
27402    /*
27403    * Validate the element.
27404    */
27405    ret = xmlSchemaValidateElem(vctxt);
27406    if (ret != 0) {
27407	if (ret == -1) {
27408	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27409		"calling xmlSchemaValidateElem()");
27410	    goto internal_error;
27411	}
27412	goto exit;
27413    }
27414
27415exit:
27416    return;
27417internal_error:
27418    vctxt->err = -1;
27419    xmlStopParser(vctxt->parserCtxt);
27420    return;
27421}
27422
27423static void
27424xmlSchemaSAXHandleEndElementNs(void *ctx,
27425			       const xmlChar * localname ATTRIBUTE_UNUSED,
27426			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27427			       const xmlChar * URI ATTRIBUTE_UNUSED)
27428{
27429    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27430    int res;
27431
27432    /*
27433    * Skip elements if inside a "skip" wildcard or if invalid.
27434    */
27435    if (vctxt->skipDepth != -1) {
27436	if (vctxt->depth > vctxt->skipDepth) {
27437	    vctxt->depth--;
27438	    return;
27439	} else
27440	    vctxt->skipDepth = -1;
27441    }
27442    /*
27443    * SAX VAL TODO: Just a temporary check.
27444    */
27445    if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27446	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27447	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27448	    "elem pop mismatch");
27449    }
27450    res = xmlSchemaValidatorPopElem(vctxt);
27451    if (res != 0) {
27452	if (res < 0) {
27453	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27454		"calling xmlSchemaValidatorPopElem()");
27455	    goto internal_error;
27456	}
27457	goto exit;
27458    }
27459exit:
27460    return;
27461internal_error:
27462    vctxt->err = -1;
27463    xmlStopParser(vctxt->parserCtxt);
27464    return;
27465}
27466
27467/************************************************************************
27468 *									*
27469 *			Validation interfaces				*
27470 *									*
27471 ************************************************************************/
27472
27473/**
27474 * xmlSchemaNewValidCtxt:
27475 * @schema:  a precompiled XML Schemas
27476 *
27477 * Create an XML Schemas validation context based on the given schema.
27478 *
27479 * Returns the validation context or NULL in case of error
27480 */
27481xmlSchemaValidCtxtPtr
27482xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27483{
27484    xmlSchemaValidCtxtPtr ret;
27485
27486    ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27487    if (ret == NULL) {
27488        xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27489        return (NULL);
27490    }
27491    memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27492    ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27493    ret->dict = xmlDictCreate();
27494    ret->nodeQNames = xmlSchemaItemListCreate();
27495    ret->schema = schema;
27496    return (ret);
27497}
27498
27499/**
27500 * xmlSchemaValidateSetFilename:
27501 * @vctxt: the schema validation context
27502 * @filename: the file name
27503 *
27504 * Workaround to provide file error reporting information when this is
27505 * not provided by current APIs
27506 */
27507void
27508xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27509    if (vctxt == NULL)
27510        return;
27511    if (vctxt->filename != NULL)
27512        xmlFree(vctxt->filename);
27513    if (filename != NULL)
27514        vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27515    else
27516        vctxt->filename = NULL;
27517}
27518
27519/**
27520 * xmlSchemaClearValidCtxt:
27521 * @vctxt: the schema validation context
27522 *
27523 * Free the resources associated to the schema validation context;
27524 * leaves some fields alive intended for reuse of the context.
27525 */
27526static void
27527xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27528{
27529    if (vctxt == NULL)
27530        return;
27531
27532    /*
27533    * TODO: Should we clear the flags?
27534    *   Might be problematic if one reuses the context
27535    *   and assumes that the options remain the same.
27536    */
27537    vctxt->flags = 0;
27538    vctxt->validationRoot = NULL;
27539    vctxt->doc = NULL;
27540#ifdef LIBXML_READER_ENABLED
27541    vctxt->reader = NULL;
27542#endif
27543    vctxt->hasKeyrefs = 0;
27544
27545    if (vctxt->value != NULL) {
27546        xmlSchemaFreeValue(vctxt->value);
27547	vctxt->value = NULL;
27548    }
27549    /*
27550    * Augmented IDC information.
27551    */
27552    if (vctxt->aidcs != NULL) {
27553	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27554	do {
27555	    next = cur->next;
27556	    xmlFree(cur);
27557	    cur = next;
27558	} while (cur != NULL);
27559	vctxt->aidcs = NULL;
27560    }
27561    if (vctxt->idcMatcherCache != NULL) {
27562	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27563
27564	while (matcher) {
27565	    tmp = matcher;
27566	    matcher = matcher->nextCached;
27567	    xmlSchemaIDCFreeMatcherList(tmp);
27568	}
27569	vctxt->idcMatcherCache = NULL;
27570    }
27571
27572
27573    if (vctxt->idcNodes != NULL) {
27574	int i;
27575	xmlSchemaPSVIIDCNodePtr item;
27576
27577	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27578	    item = vctxt->idcNodes[i];
27579	    xmlFree(item->keys);
27580	    xmlFree(item);
27581	}
27582	xmlFree(vctxt->idcNodes);
27583	vctxt->idcNodes = NULL;
27584	vctxt->nbIdcNodes = 0;
27585	vctxt->sizeIdcNodes = 0;
27586    }
27587    /*
27588    * Note that we won't delete the XPath state pool here.
27589    */
27590    if (vctxt->xpathStates != NULL) {
27591	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27592	vctxt->xpathStates = NULL;
27593    }
27594    /*
27595    * Attribute info.
27596    */
27597    if (vctxt->nbAttrInfos != 0) {
27598	xmlSchemaClearAttrInfos(vctxt);
27599    }
27600    /*
27601    * Element info.
27602    */
27603    if (vctxt->elemInfos != NULL) {
27604	int i;
27605	xmlSchemaNodeInfoPtr ei;
27606
27607	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27608	    ei = vctxt->elemInfos[i];
27609	    if (ei == NULL)
27610		break;
27611	    xmlSchemaClearElemInfo(vctxt, ei);
27612	}
27613    }
27614    xmlSchemaItemListClear(vctxt->nodeQNames);
27615    /* Recreate the dict. */
27616    xmlDictFree(vctxt->dict);
27617    /*
27618    * TODO: Is is save to recreate it? Do we have a scenario
27619    * where the user provides the dict?
27620    */
27621    vctxt->dict = xmlDictCreate();
27622
27623    if (vctxt->filename != NULL) {
27624        xmlFree(vctxt->filename);
27625	vctxt->filename = NULL;
27626    }
27627}
27628
27629/**
27630 * xmlSchemaFreeValidCtxt:
27631 * @ctxt:  the schema validation context
27632 *
27633 * Free the resources associated to the schema validation context
27634 */
27635void
27636xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27637{
27638    if (ctxt == NULL)
27639        return;
27640    if (ctxt->value != NULL)
27641        xmlSchemaFreeValue(ctxt->value);
27642    if (ctxt->pctxt != NULL)
27643	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27644    if (ctxt->idcNodes != NULL) {
27645	int i;
27646	xmlSchemaPSVIIDCNodePtr item;
27647
27648	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27649	    item = ctxt->idcNodes[i];
27650	    xmlFree(item->keys);
27651	    xmlFree(item);
27652	}
27653	xmlFree(ctxt->idcNodes);
27654    }
27655    if (ctxt->idcKeys != NULL) {
27656	int i;
27657	for (i = 0; i < ctxt->nbIdcKeys; i++)
27658	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27659	xmlFree(ctxt->idcKeys);
27660    }
27661
27662    if (ctxt->xpathStates != NULL) {
27663	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27664	ctxt->xpathStates = NULL;
27665    }
27666    if (ctxt->xpathStatePool != NULL) {
27667	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27668	ctxt->xpathStatePool = NULL;
27669    }
27670
27671    /*
27672    * Augmented IDC information.
27673    */
27674    if (ctxt->aidcs != NULL) {
27675	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27676	do {
27677	    next = cur->next;
27678	    xmlFree(cur);
27679	    cur = next;
27680	} while (cur != NULL);
27681    }
27682    if (ctxt->attrInfos != NULL) {
27683	int i;
27684	xmlSchemaAttrInfoPtr attr;
27685
27686	/* Just a paranoid call to the cleanup. */
27687	if (ctxt->nbAttrInfos != 0)
27688	    xmlSchemaClearAttrInfos(ctxt);
27689	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27690	    attr = ctxt->attrInfos[i];
27691	    xmlFree(attr);
27692	}
27693	xmlFree(ctxt->attrInfos);
27694    }
27695    if (ctxt->elemInfos != NULL) {
27696	int i;
27697	xmlSchemaNodeInfoPtr ei;
27698
27699	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27700	    ei = ctxt->elemInfos[i];
27701	    if (ei == NULL)
27702		break;
27703	    xmlSchemaClearElemInfo(ctxt, ei);
27704	    xmlFree(ei);
27705	}
27706	xmlFree(ctxt->elemInfos);
27707    }
27708    if (ctxt->nodeQNames != NULL)
27709	xmlSchemaItemListFree(ctxt->nodeQNames);
27710    if (ctxt->dict != NULL)
27711	xmlDictFree(ctxt->dict);
27712    if (ctxt->filename != NULL)
27713	xmlFree(ctxt->filename);
27714    xmlFree(ctxt);
27715}
27716
27717/**
27718 * xmlSchemaIsValid:
27719 * @ctxt: the schema validation context
27720 *
27721 * Check if any error was detected during validation.
27722 *
27723 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27724 *         of internal error.
27725 */
27726int
27727xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27728{
27729    if (ctxt == NULL)
27730        return(-1);
27731    return(ctxt->err == 0);
27732}
27733
27734/**
27735 * xmlSchemaSetValidErrors:
27736 * @ctxt:  a schema validation context
27737 * @err:  the error function
27738 * @warn: the warning function
27739 * @ctx: the functions context
27740 *
27741 * Set the error and warning callback informations
27742 */
27743void
27744xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27745                        xmlSchemaValidityErrorFunc err,
27746                        xmlSchemaValidityWarningFunc warn, void *ctx)
27747{
27748    if (ctxt == NULL)
27749        return;
27750    ctxt->error = err;
27751    ctxt->warning = warn;
27752    ctxt->errCtxt = ctx;
27753    if (ctxt->pctxt != NULL)
27754	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27755}
27756
27757/**
27758 * xmlSchemaSetValidStructuredErrors:
27759 * @ctxt:  a schema validation context
27760 * @serror:  the structured error function
27761 * @ctx: the functions context
27762 *
27763 * Set the structured error callback
27764 */
27765void
27766xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27767				  xmlStructuredErrorFunc serror, void *ctx)
27768{
27769    if (ctxt == NULL)
27770        return;
27771	ctxt->serror = serror;
27772    ctxt->error = NULL;
27773    ctxt->warning = NULL;
27774    ctxt->errCtxt = ctx;
27775    if (ctxt->pctxt != NULL)
27776	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27777}
27778
27779/**
27780 * xmlSchemaGetValidErrors:
27781 * @ctxt: a XML-Schema validation context
27782 * @err: the error function result
27783 * @warn: the warning function result
27784 * @ctx: the functions context result
27785 *
27786 * Get the error and warning callback informations
27787 *
27788 * Returns -1 in case of error and 0 otherwise
27789 */
27790int
27791xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27792			xmlSchemaValidityErrorFunc * err,
27793			xmlSchemaValidityWarningFunc * warn, void **ctx)
27794{
27795	if (ctxt == NULL)
27796		return (-1);
27797	if (err != NULL)
27798		*err = ctxt->error;
27799	if (warn != NULL)
27800		*warn = ctxt->warning;
27801	if (ctx != NULL)
27802		*ctx = ctxt->errCtxt;
27803	return (0);
27804}
27805
27806
27807/**
27808 * xmlSchemaSetValidOptions:
27809 * @ctxt:	a schema validation context
27810 * @options: a combination of xmlSchemaValidOption
27811 *
27812 * Sets the options to be used during the validation.
27813 *
27814 * Returns 0 in case of success, -1 in case of an
27815 * API error.
27816 */
27817int
27818xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27819			 int options)
27820
27821{
27822    int i;
27823
27824    if (ctxt == NULL)
27825	return (-1);
27826    /*
27827    * WARNING: Change the start value if adding to the
27828    * xmlSchemaValidOption.
27829    * TODO: Is there an other, more easy to maintain,
27830    * way?
27831    */
27832    for (i = 1; i < (int) sizeof(int) * 8; i++) {
27833        if (options & 1<<i)
27834	    return (-1);
27835    }
27836    ctxt->options = options;
27837    return (0);
27838}
27839
27840/**
27841 * xmlSchemaValidCtxtGetOptions:
27842 * @ctxt: a schema validation context
27843 *
27844 * Get the validation context options.
27845 *
27846 * Returns the option combination or -1 on error.
27847 */
27848int
27849xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27850
27851{
27852    if (ctxt == NULL)
27853	return (-1);
27854    else
27855	return (ctxt->options);
27856}
27857
27858static int
27859xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27860{
27861    xmlAttrPtr attr;
27862    int ret = 0;
27863    xmlSchemaNodeInfoPtr ielem = NULL;
27864    xmlNodePtr node, valRoot;
27865    const xmlChar *nsName;
27866
27867    /* DOC VAL TODO: Move this to the start function. */
27868    if (vctxt->validationRoot != NULL)
27869        valRoot = vctxt->validationRoot;
27870    else
27871	valRoot = xmlDocGetRootElement(vctxt->doc);
27872    if (valRoot == NULL) {
27873	/* VAL TODO: Error code? */
27874	VERROR(1, NULL, "The document has no document element");
27875	return (1);
27876    }
27877    vctxt->depth = -1;
27878    vctxt->validationRoot = valRoot;
27879    node = valRoot;
27880    while (node != NULL) {
27881	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27882	    goto next_sibling;
27883	if (node->type == XML_ELEMENT_NODE) {
27884
27885	    /*
27886	    * Init the node-info.
27887	    */
27888	    vctxt->depth++;
27889	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27890		goto internal_error;
27891	    ielem = vctxt->inode;
27892	    ielem->node = node;
27893	    ielem->nodeLine = node->line;
27894	    ielem->localName = node->name;
27895	    if (node->ns != NULL)
27896		ielem->nsName = node->ns->href;
27897	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27898	    /*
27899	    * Register attributes.
27900	    * DOC VAL TODO: We do not register namespace declaration
27901	    * attributes yet.
27902	    */
27903	    vctxt->nbAttrInfos = 0;
27904	    if (node->properties != NULL) {
27905		attr = node->properties;
27906		do {
27907		    if (attr->ns != NULL)
27908			nsName = attr->ns->href;
27909		    else
27910			nsName = NULL;
27911		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27912			(xmlNodePtr) attr,
27913			/*
27914			* Note that we give it the line number of the
27915			* parent element.
27916			*/
27917			ielem->nodeLine,
27918			attr->name, nsName, 0,
27919			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27920		    if (ret == -1) {
27921			VERROR_INT("xmlSchemaDocWalk",
27922			    "calling xmlSchemaValidatorPushAttribute()");
27923			goto internal_error;
27924		    }
27925		    attr = attr->next;
27926		} while (attr);
27927	    }
27928	    /*
27929	    * Validate the element.
27930	    */
27931	    ret = xmlSchemaValidateElem(vctxt);
27932	    if (ret != 0) {
27933		if (ret == -1) {
27934		    VERROR_INT("xmlSchemaDocWalk",
27935			"calling xmlSchemaValidateElem()");
27936		    goto internal_error;
27937		}
27938		/*
27939		* Don't stop validation; just skip the content
27940		* of this element.
27941		*/
27942		goto leave_node;
27943	    }
27944	    if ((vctxt->skipDepth != -1) &&
27945		(vctxt->depth >= vctxt->skipDepth))
27946		goto leave_node;
27947	} else if ((node->type == XML_TEXT_NODE) ||
27948	    (node->type == XML_CDATA_SECTION_NODE)) {
27949	    /*
27950	    * Process character content.
27951	    */
27952	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27953		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27954	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27955		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27956	    if (ret < 0) {
27957		VERROR_INT("xmlSchemaVDocWalk",
27958		    "calling xmlSchemaVPushText()");
27959		goto internal_error;
27960	    }
27961	    /*
27962	    * DOC VAL TODO: Should we skip further validation of the
27963	    * element content here?
27964	    */
27965	} else if ((node->type == XML_ENTITY_NODE) ||
27966	    (node->type == XML_ENTITY_REF_NODE)) {
27967	    /*
27968	    * DOC VAL TODO: What to do with entities?
27969	    */
27970	    VERROR_INT("xmlSchemaVDocWalk",
27971		"there is at least one entity reference in the node-tree "
27972		"currently being validated. Processing of entities with "
27973		"this XML Schema processor is not supported (yet). Please "
27974		"substitute entities before validation.");
27975	    goto internal_error;
27976	} else {
27977	    goto leave_node;
27978	    /*
27979	    * DOC VAL TODO: XInclude nodes, etc.
27980	    */
27981	}
27982	/*
27983	* Walk the doc.
27984	*/
27985	if (node->children != NULL) {
27986	    node = node->children;
27987	    continue;
27988	}
27989leave_node:
27990	if (node->type == XML_ELEMENT_NODE) {
27991	    /*
27992	    * Leaving the scope of an element.
27993	    */
27994	    if (node != vctxt->inode->node) {
27995		VERROR_INT("xmlSchemaVDocWalk",
27996		    "element position mismatch");
27997		goto internal_error;
27998	    }
27999	    ret = xmlSchemaValidatorPopElem(vctxt);
28000	    if (ret != 0) {
28001		if (ret < 0) {
28002		    VERROR_INT("xmlSchemaVDocWalk",
28003			"calling xmlSchemaValidatorPopElem()");
28004		    goto internal_error;
28005		}
28006	    }
28007	    if (node == valRoot)
28008		goto exit;
28009	}
28010next_sibling:
28011	if (node->next != NULL)
28012	    node = node->next;
28013	else {
28014	    node = node->parent;
28015	    goto leave_node;
28016	}
28017    }
28018
28019exit:
28020    return (ret);
28021internal_error:
28022    return (-1);
28023}
28024
28025static int
28026xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28027    /*
28028    * Some initialization.
28029    */
28030    vctxt->err = 0;
28031    vctxt->nberrors = 0;
28032    vctxt->depth = -1;
28033    vctxt->skipDepth = -1;
28034    vctxt->xsiAssemble = 0;
28035    vctxt->hasKeyrefs = 0;
28036#ifdef ENABLE_IDC_NODE_TABLES_TEST
28037    vctxt->createIDCNodeTables = 1;
28038#else
28039    vctxt->createIDCNodeTables = 0;
28040#endif
28041    /*
28042    * Create a schema + parser if necessary.
28043    */
28044    if (vctxt->schema == NULL) {
28045	xmlSchemaParserCtxtPtr pctxt;
28046
28047	vctxt->xsiAssemble = 1;
28048	/*
28049	* If not schema was given then we will create a schema
28050	* dynamically using XSI schema locations.
28051	*
28052	* Create the schema parser context.
28053	*/
28054	if ((vctxt->pctxt == NULL) &&
28055	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28056	   return (-1);
28057	pctxt = vctxt->pctxt;
28058	pctxt->xsiAssemble = 1;
28059	/*
28060	* Create the schema.
28061	*/
28062	vctxt->schema = xmlSchemaNewSchema(pctxt);
28063	if (vctxt->schema == NULL)
28064	    return (-1);
28065	/*
28066	* Create the schema construction context.
28067	*/
28068	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28069	if (pctxt->constructor == NULL)
28070	    return(-1);
28071	pctxt->constructor->mainSchema = vctxt->schema;
28072	/*
28073	* Take ownership of the constructor to be able to free it.
28074	*/
28075	pctxt->ownsConstructor = 1;
28076    }
28077    /*
28078    * Augment the IDC definitions for the main schema and all imported ones
28079    * NOTE: main schema if the first in the imported list
28080    */
28081    xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28082
28083    return(0);
28084}
28085
28086static void
28087xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28088    if (vctxt->xsiAssemble) {
28089	if (vctxt->schema != NULL) {
28090	    xmlSchemaFree(vctxt->schema);
28091	    vctxt->schema = NULL;
28092	}
28093    }
28094    xmlSchemaClearValidCtxt(vctxt);
28095}
28096
28097static int
28098xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28099{
28100    int ret = 0;
28101
28102    if (xmlSchemaPreRun(vctxt) < 0)
28103        return(-1);
28104
28105    if (vctxt->doc != NULL) {
28106	/*
28107	 * Tree validation.
28108	 */
28109	ret = xmlSchemaVDocWalk(vctxt);
28110#ifdef LIBXML_READER_ENABLED
28111    } else if (vctxt->reader != NULL) {
28112	/*
28113	 * XML Reader validation.
28114	 */
28115#ifdef XML_SCHEMA_READER_ENABLED
28116	ret = xmlSchemaVReaderWalk(vctxt);
28117#endif
28118#endif
28119    } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28120	/*
28121	 * SAX validation.
28122	 */
28123	ret = xmlParseDocument(vctxt->parserCtxt);
28124    } else {
28125	VERROR_INT("xmlSchemaVStart",
28126	    "no instance to validate");
28127	ret = -1;
28128    }
28129
28130    xmlSchemaPostRun(vctxt);
28131    if (ret == 0)
28132	ret = vctxt->err;
28133    return (ret);
28134}
28135
28136/**
28137 * xmlSchemaValidateOneElement:
28138 * @ctxt:  a schema validation context
28139 * @elem:  an element node
28140 *
28141 * Validate a branch of a tree, starting with the given @elem.
28142 *
28143 * Returns 0 if the element and its subtree is valid, a positive error
28144 * code number otherwise and -1 in case of an internal or API error.
28145 */
28146int
28147xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28148{
28149    if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28150	return (-1);
28151
28152    if (ctxt->schema == NULL)
28153	return (-1);
28154
28155    ctxt->doc = elem->doc;
28156    ctxt->node = elem;
28157    ctxt->validationRoot = elem;
28158    return(xmlSchemaVStart(ctxt));
28159}
28160
28161/**
28162 * xmlSchemaValidateDoc:
28163 * @ctxt:  a schema validation context
28164 * @doc:  a parsed document tree
28165 *
28166 * Validate a document tree in memory.
28167 *
28168 * Returns 0 if the document is schemas valid, a positive error code
28169 *     number otherwise and -1 in case of internal or API error.
28170 */
28171int
28172xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28173{
28174    if ((ctxt == NULL) || (doc == NULL))
28175        return (-1);
28176
28177    ctxt->doc = doc;
28178    ctxt->node = xmlDocGetRootElement(doc);
28179    if (ctxt->node == NULL) {
28180        xmlSchemaCustomErr(ACTXT_CAST ctxt,
28181	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28182	    (xmlNodePtr) doc, NULL,
28183	    "The document has no document element", NULL, NULL);
28184        return (ctxt->err);
28185    }
28186    ctxt->validationRoot = ctxt->node;
28187    return (xmlSchemaVStart(ctxt));
28188}
28189
28190
28191/************************************************************************
28192 *									*
28193 *		Function and data for SAX streaming API			*
28194 *									*
28195 ************************************************************************/
28196typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28197typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28198
28199struct _xmlSchemaSplitSAXData {
28200    xmlSAXHandlerPtr      user_sax;
28201    void                 *user_data;
28202    xmlSchemaValidCtxtPtr ctxt;
28203    xmlSAXHandlerPtr      schemas_sax;
28204};
28205
28206#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28207
28208struct _xmlSchemaSAXPlug {
28209    unsigned int magic;
28210
28211    /* the original callbacks informations */
28212    xmlSAXHandlerPtr     *user_sax_ptr;
28213    xmlSAXHandlerPtr      user_sax;
28214    void                **user_data_ptr;
28215    void                 *user_data;
28216
28217    /* the block plugged back and validation informations */
28218    xmlSAXHandler         schemas_sax;
28219    xmlSchemaValidCtxtPtr ctxt;
28220};
28221
28222/* All those functions just bounces to the user provided SAX handlers */
28223static void
28224internalSubsetSplit(void *ctx, const xmlChar *name,
28225	       const xmlChar *ExternalID, const xmlChar *SystemID)
28226{
28227    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28228    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28229        (ctxt->user_sax->internalSubset != NULL))
28230	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28231	                               SystemID);
28232}
28233
28234static int
28235isStandaloneSplit(void *ctx)
28236{
28237    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28238    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28239        (ctxt->user_sax->isStandalone != NULL))
28240	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28241    return(0);
28242}
28243
28244static int
28245hasInternalSubsetSplit(void *ctx)
28246{
28247    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28248    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28249        (ctxt->user_sax->hasInternalSubset != NULL))
28250	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28251    return(0);
28252}
28253
28254static int
28255hasExternalSubsetSplit(void *ctx)
28256{
28257    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28258    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28259        (ctxt->user_sax->hasExternalSubset != NULL))
28260	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28261    return(0);
28262}
28263
28264static void
28265externalSubsetSplit(void *ctx, const xmlChar *name,
28266	       const xmlChar *ExternalID, const xmlChar *SystemID)
28267{
28268    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28269    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28270        (ctxt->user_sax->externalSubset != NULL))
28271	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28272	                               SystemID);
28273}
28274
28275static xmlParserInputPtr
28276resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28277{
28278    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28279    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28280        (ctxt->user_sax->resolveEntity != NULL))
28281	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28282	                                     systemId));
28283    return(NULL);
28284}
28285
28286static xmlEntityPtr
28287getEntitySplit(void *ctx, const xmlChar *name)
28288{
28289    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28290    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28291        (ctxt->user_sax->getEntity != NULL))
28292	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28293    return(NULL);
28294}
28295
28296static xmlEntityPtr
28297getParameterEntitySplit(void *ctx, const xmlChar *name)
28298{
28299    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28300    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28301        (ctxt->user_sax->getParameterEntity != NULL))
28302	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28303    return(NULL);
28304}
28305
28306
28307static void
28308entityDeclSplit(void *ctx, const xmlChar *name, int type,
28309          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28310{
28311    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28312    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28313        (ctxt->user_sax->entityDecl != NULL))
28314	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28315	                           systemId, content);
28316}
28317
28318static void
28319attributeDeclSplit(void *ctx, const xmlChar * elem,
28320                   const xmlChar * name, int type, int def,
28321                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
28322{
28323    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28324    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28325        (ctxt->user_sax->attributeDecl != NULL)) {
28326	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28327	                              def, defaultValue, tree);
28328    } else {
28329	xmlFreeEnumeration(tree);
28330    }
28331}
28332
28333static void
28334elementDeclSplit(void *ctx, const xmlChar *name, int type,
28335	    xmlElementContentPtr content)
28336{
28337    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28338    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28339        (ctxt->user_sax->elementDecl != NULL))
28340	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28341}
28342
28343static void
28344notationDeclSplit(void *ctx, const xmlChar *name,
28345	     const xmlChar *publicId, const xmlChar *systemId)
28346{
28347    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28348    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28349        (ctxt->user_sax->notationDecl != NULL))
28350	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28351	                             systemId);
28352}
28353
28354static void
28355unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28356		   const xmlChar *publicId, const xmlChar *systemId,
28357		   const xmlChar *notationName)
28358{
28359    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28360    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28361        (ctxt->user_sax->unparsedEntityDecl != NULL))
28362	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28363	                                   systemId, notationName);
28364}
28365
28366static void
28367setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28368{
28369    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28370    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28371        (ctxt->user_sax->setDocumentLocator != NULL))
28372	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28373}
28374
28375static void
28376startDocumentSplit(void *ctx)
28377{
28378    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28379    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28380        (ctxt->user_sax->startDocument != NULL))
28381	ctxt->user_sax->startDocument(ctxt->user_data);
28382}
28383
28384static void
28385endDocumentSplit(void *ctx)
28386{
28387    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28388    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28389        (ctxt->user_sax->endDocument != NULL))
28390	ctxt->user_sax->endDocument(ctxt->user_data);
28391}
28392
28393static void
28394processingInstructionSplit(void *ctx, const xmlChar *target,
28395                      const xmlChar *data)
28396{
28397    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28398    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28399        (ctxt->user_sax->processingInstruction != NULL))
28400	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28401}
28402
28403static void
28404commentSplit(void *ctx, const xmlChar *value)
28405{
28406    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28407    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28408        (ctxt->user_sax->comment != NULL))
28409	ctxt->user_sax->comment(ctxt->user_data, value);
28410}
28411
28412/*
28413 * Varargs error callbacks to the user application, harder ...
28414 */
28415
28416static void XMLCDECL
28417warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28418    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28419    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28420        (ctxt->user_sax->warning != NULL)) {
28421	TODO
28422    }
28423}
28424static void XMLCDECL
28425errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28426    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28427    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28428        (ctxt->user_sax->error != NULL)) {
28429	TODO
28430    }
28431}
28432static void XMLCDECL
28433fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28434    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28435    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28436        (ctxt->user_sax->fatalError != NULL)) {
28437	TODO
28438    }
28439}
28440
28441/*
28442 * Those are function where both the user handler and the schemas handler
28443 * need to be called.
28444 */
28445static void
28446charactersSplit(void *ctx, const xmlChar *ch, int len)
28447{
28448    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28449    if (ctxt == NULL)
28450        return;
28451    if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28452	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28453    if (ctxt->ctxt != NULL)
28454	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28455}
28456
28457static void
28458ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28459{
28460    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28461    if (ctxt == NULL)
28462        return;
28463    if ((ctxt->user_sax != NULL) &&
28464        (ctxt->user_sax->ignorableWhitespace != NULL))
28465	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28466    if (ctxt->ctxt != NULL)
28467	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28468}
28469
28470static void
28471cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28472{
28473    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28474    if (ctxt == NULL)
28475        return;
28476    if ((ctxt->user_sax != NULL) &&
28477        (ctxt->user_sax->cdataBlock != NULL))
28478	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28479    if (ctxt->ctxt != NULL)
28480	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28481}
28482
28483static void
28484referenceSplit(void *ctx, const xmlChar *name)
28485{
28486    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28487    if (ctxt == NULL)
28488        return;
28489    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28490        (ctxt->user_sax->reference != NULL))
28491	ctxt->user_sax->reference(ctxt->user_data, name);
28492    if (ctxt->ctxt != NULL)
28493        xmlSchemaSAXHandleReference(ctxt->user_data, name);
28494}
28495
28496static void
28497startElementNsSplit(void *ctx, const xmlChar * localname,
28498		    const xmlChar * prefix, const xmlChar * URI,
28499		    int nb_namespaces, const xmlChar ** namespaces,
28500		    int nb_attributes, int nb_defaulted,
28501		    const xmlChar ** attributes) {
28502    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28503    if (ctxt == NULL)
28504        return;
28505    if ((ctxt->user_sax != NULL) &&
28506        (ctxt->user_sax->startElementNs != NULL))
28507	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28508	                               URI, nb_namespaces, namespaces,
28509				       nb_attributes, nb_defaulted,
28510				       attributes);
28511    if (ctxt->ctxt != NULL)
28512	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28513	                                 URI, nb_namespaces, namespaces,
28514					 nb_attributes, nb_defaulted,
28515					 attributes);
28516}
28517
28518static void
28519endElementNsSplit(void *ctx, const xmlChar * localname,
28520		    const xmlChar * prefix, const xmlChar * URI) {
28521    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28522    if (ctxt == NULL)
28523        return;
28524    if ((ctxt->user_sax != NULL) &&
28525        (ctxt->user_sax->endElementNs != NULL))
28526	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28527    if (ctxt->ctxt != NULL)
28528	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28529}
28530
28531/**
28532 * xmlSchemaSAXPlug:
28533 * @ctxt:  a schema validation context
28534 * @sax:  a pointer to the original xmlSAXHandlerPtr
28535 * @user_data:  a pointer to the original SAX user data pointer
28536 *
28537 * Plug a SAX based validation layer in a SAX parsing event flow.
28538 * The original @saxptr and @dataptr data are replaced by new pointers
28539 * but the calls to the original will be maintained.
28540 *
28541 * Returns a pointer to a data structure needed to unplug the validation layer
28542 *         or NULL in case of errors.
28543 */
28544xmlSchemaSAXPlugPtr
28545xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28546		 xmlSAXHandlerPtr *sax, void **user_data)
28547{
28548    xmlSchemaSAXPlugPtr ret;
28549    xmlSAXHandlerPtr old_sax;
28550
28551    if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28552        return(NULL);
28553
28554    /*
28555     * We only allow to plug into SAX2 event streams
28556     */
28557    old_sax = *sax;
28558    if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28559        return(NULL);
28560    if ((old_sax != NULL) &&
28561        (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28562        ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28563        return(NULL);
28564
28565    /*
28566     * everything seems right allocate the local data needed for that layer
28567     */
28568    ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28569    if (ret == NULL) {
28570        return(NULL);
28571    }
28572    memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28573    ret->magic = XML_SAX_PLUG_MAGIC;
28574    ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28575    ret->ctxt = ctxt;
28576    ret->user_sax_ptr = sax;
28577    ret->user_sax = old_sax;
28578    if (old_sax == NULL) {
28579        /*
28580	 * go direct, no need for the split block and functions.
28581	 */
28582	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28583	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28584	/*
28585	 * Note that we use the same text-function for both, to prevent
28586	 * the parser from testing for ignorable whitespace.
28587	 */
28588	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28589	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28590
28591	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28592	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28593
28594	ret->user_data = ctxt;
28595	*user_data = ctxt;
28596    } else {
28597       /*
28598        * for each callback unused by Schemas initialize it to the Split
28599	* routine only if non NULL in the user block, this can speed up
28600	* things at the SAX level.
28601	*/
28602        if (old_sax->internalSubset != NULL)
28603            ret->schemas_sax.internalSubset = internalSubsetSplit;
28604        if (old_sax->isStandalone != NULL)
28605            ret->schemas_sax.isStandalone = isStandaloneSplit;
28606        if (old_sax->hasInternalSubset != NULL)
28607            ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28608        if (old_sax->hasExternalSubset != NULL)
28609            ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28610        if (old_sax->resolveEntity != NULL)
28611            ret->schemas_sax.resolveEntity = resolveEntitySplit;
28612        if (old_sax->getEntity != NULL)
28613            ret->schemas_sax.getEntity = getEntitySplit;
28614        if (old_sax->entityDecl != NULL)
28615            ret->schemas_sax.entityDecl = entityDeclSplit;
28616        if (old_sax->notationDecl != NULL)
28617            ret->schemas_sax.notationDecl = notationDeclSplit;
28618        if (old_sax->attributeDecl != NULL)
28619            ret->schemas_sax.attributeDecl = attributeDeclSplit;
28620        if (old_sax->elementDecl != NULL)
28621            ret->schemas_sax.elementDecl = elementDeclSplit;
28622        if (old_sax->unparsedEntityDecl != NULL)
28623            ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28624        if (old_sax->setDocumentLocator != NULL)
28625            ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28626        if (old_sax->startDocument != NULL)
28627            ret->schemas_sax.startDocument = startDocumentSplit;
28628        if (old_sax->endDocument != NULL)
28629            ret->schemas_sax.endDocument = endDocumentSplit;
28630        if (old_sax->processingInstruction != NULL)
28631            ret->schemas_sax.processingInstruction = processingInstructionSplit;
28632        if (old_sax->comment != NULL)
28633            ret->schemas_sax.comment = commentSplit;
28634        if (old_sax->warning != NULL)
28635            ret->schemas_sax.warning = warningSplit;
28636        if (old_sax->error != NULL)
28637            ret->schemas_sax.error = errorSplit;
28638        if (old_sax->fatalError != NULL)
28639            ret->schemas_sax.fatalError = fatalErrorSplit;
28640        if (old_sax->getParameterEntity != NULL)
28641            ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28642        if (old_sax->externalSubset != NULL)
28643            ret->schemas_sax.externalSubset = externalSubsetSplit;
28644
28645	/*
28646	 * the 6 schemas callback have to go to the splitter functions
28647	 * Note that we use the same text-function for ignorableWhitespace
28648	 * if possible, to prevent the parser from testing for ignorable
28649	 * whitespace.
28650	 */
28651        ret->schemas_sax.characters = charactersSplit;
28652	if ((old_sax->ignorableWhitespace != NULL) &&
28653	    (old_sax->ignorableWhitespace != old_sax->characters))
28654	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28655	else
28656	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28657        ret->schemas_sax.cdataBlock = cdataBlockSplit;
28658        ret->schemas_sax.reference = referenceSplit;
28659        ret->schemas_sax.startElementNs = startElementNsSplit;
28660        ret->schemas_sax.endElementNs = endElementNsSplit;
28661
28662	ret->user_data_ptr = user_data;
28663	ret->user_data = *user_data;
28664	*user_data = ret;
28665    }
28666
28667    /*
28668     * plug the pointers back.
28669     */
28670    *sax = &(ret->schemas_sax);
28671    ctxt->sax = *sax;
28672    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28673    xmlSchemaPreRun(ctxt);
28674    return(ret);
28675}
28676
28677/**
28678 * xmlSchemaSAXUnplug:
28679 * @plug:  a data structure returned by xmlSchemaSAXPlug
28680 *
28681 * Unplug a SAX based validation layer in a SAX parsing event flow.
28682 * The original pointers used in the call are restored.
28683 *
28684 * Returns 0 in case of success and -1 in case of failure.
28685 */
28686int
28687xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28688{
28689    xmlSAXHandlerPtr *sax;
28690    void **user_data;
28691
28692    if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28693        return(-1);
28694    plug->magic = 0;
28695
28696    xmlSchemaPostRun(plug->ctxt);
28697    /* restore the data */
28698    sax = plug->user_sax_ptr;
28699    *sax = plug->user_sax;
28700    if (plug->user_sax != NULL) {
28701	user_data = plug->user_data_ptr;
28702	*user_data = plug->user_data;
28703    }
28704
28705    /* free and return */
28706    xmlFree(plug);
28707    return(0);
28708}
28709
28710/**
28711 * xmlSchemaValidateSetLocator:
28712 * @vctxt: a schema validation context
28713 * @f: the locator function pointer
28714 * @ctxt: the locator context
28715 *
28716 * Allows to set a locator function to the validation context,
28717 * which will be used to provide file and line information since
28718 * those are not provided as part of the SAX validation flow
28719 * Setting @f to NULL disable the locator.
28720 */
28721
28722void
28723xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28724                            xmlSchemaValidityLocatorFunc f,
28725			    void *ctxt)
28726{
28727    if (vctxt == NULL) return;
28728    vctxt->locFunc = f;
28729    vctxt->locCtxt = ctxt;
28730}
28731
28732/**
28733 * xmlSchemaValidateStreamLocator:
28734 * @ctx: the xmlTextReaderPtr used
28735 * @file: returned file information
28736 * @line: returned line information
28737 *
28738 * Internal locator function for the readers
28739 *
28740 * Returns 0 in case the Schema validation could be (des)activated and
28741 *         -1 in case of error.
28742 */
28743static int
28744xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28745                               unsigned long *line) {
28746    xmlParserCtxtPtr ctxt;
28747
28748    if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28749        return(-1);
28750
28751    if (file != NULL)
28752        *file = NULL;
28753    if (line != NULL)
28754        *line = 0;
28755
28756    ctxt = (xmlParserCtxtPtr) ctx;
28757    if (ctxt->input != NULL) {
28758       if (file != NULL)
28759           *file = ctxt->input->filename;
28760       if (line != NULL)
28761           *line = ctxt->input->line;
28762       return(0);
28763    }
28764    return(-1);
28765}
28766
28767/**
28768 * xmlSchemaValidateStream:
28769 * @ctxt:  a schema validation context
28770 * @input:  the input to use for reading the data
28771 * @enc:  an optional encoding information
28772 * @sax:  a SAX handler for the resulting events
28773 * @user_data:  the context to provide to the SAX handler.
28774 *
28775 * Validate an input based on a flow of SAX event from the parser
28776 * and forward the events to the @sax handler with the provided @user_data
28777 * the user provided @sax handler must be a SAX2 one.
28778 *
28779 * Returns 0 if the document is schemas valid, a positive error code
28780 *     number otherwise and -1 in case of internal or API error.
28781 */
28782int
28783xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28784                        xmlParserInputBufferPtr input, xmlCharEncoding enc,
28785                        xmlSAXHandlerPtr sax, void *user_data)
28786{
28787    xmlSchemaSAXPlugPtr plug = NULL;
28788    xmlSAXHandlerPtr old_sax = NULL;
28789    xmlParserCtxtPtr pctxt = NULL;
28790    xmlParserInputPtr inputStream = NULL;
28791    int ret;
28792
28793    if ((ctxt == NULL) || (input == NULL))
28794        return (-1);
28795
28796    /*
28797     * prepare the parser
28798     */
28799    pctxt = xmlNewParserCtxt();
28800    if (pctxt == NULL)
28801        return (-1);
28802    old_sax = pctxt->sax;
28803    pctxt->sax = sax;
28804    pctxt->userData = user_data;
28805#if 0
28806    if (options)
28807        xmlCtxtUseOptions(pctxt, options);
28808#endif
28809    pctxt->linenumbers = 1;
28810    xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28811
28812    inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28813    if (inputStream == NULL) {
28814        ret = -1;
28815	goto done;
28816    }
28817    inputPush(pctxt, inputStream);
28818    ctxt->parserCtxt = pctxt;
28819    ctxt->input = input;
28820
28821    /*
28822     * Plug the validation and launch the parsing
28823     */
28824    plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28825    if (plug == NULL) {
28826        ret = -1;
28827	goto done;
28828    }
28829    ctxt->input = input;
28830    ctxt->enc = enc;
28831    ctxt->sax = pctxt->sax;
28832    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28833    ret = xmlSchemaVStart(ctxt);
28834
28835    if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28836	ret = ctxt->parserCtxt->errNo;
28837	if (ret == 0)
28838	    ret = 1;
28839    }
28840
28841done:
28842    ctxt->parserCtxt = NULL;
28843    ctxt->sax = NULL;
28844    ctxt->input = NULL;
28845    if (plug != NULL) {
28846        xmlSchemaSAXUnplug(plug);
28847    }
28848    /* cleanup */
28849    if (pctxt != NULL) {
28850	pctxt->sax = old_sax;
28851	xmlFreeParserCtxt(pctxt);
28852    }
28853    return (ret);
28854}
28855
28856/**
28857 * xmlSchemaValidateFile:
28858 * @ctxt: a schema validation context
28859 * @filename: the URI of the instance
28860 * @options: a future set of options, currently unused
28861 *
28862 * Do a schemas validation of the given resource, it will use the
28863 * SAX streamable validation internally.
28864 *
28865 * Returns 0 if the document is valid, a positive error code
28866 *     number otherwise and -1 in case of an internal or API error.
28867 */
28868int
28869xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28870                      const char * filename,
28871		      int options ATTRIBUTE_UNUSED)
28872{
28873    int ret;
28874    xmlParserInputBufferPtr input;
28875
28876    if ((ctxt == NULL) || (filename == NULL))
28877        return (-1);
28878
28879    input = xmlParserInputBufferCreateFilename(filename,
28880	XML_CHAR_ENCODING_NONE);
28881    if (input == NULL)
28882	return (-1);
28883    ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28884	NULL, NULL);
28885    return (ret);
28886}
28887
28888/**
28889 * xmlSchemaValidCtxtGetParserCtxt:
28890 * @ctxt: a schema validation context
28891 *
28892 * allow access to the parser context of the schema validation context
28893 *
28894 * Returns the parser context of the schema validation context or NULL
28895 *         in case of error.
28896 */
28897xmlParserCtxtPtr
28898xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28899{
28900    if (ctxt == NULL)
28901        return(NULL);
28902    return (ctxt->parserCtxt);
28903}
28904
28905#define bottom_xmlschemas
28906#include "elfgcchack.h"
28907#endif /* LIBXML_SCHEMAS_ENABLED */
28908