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 cononical 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	    if (errorLevel != XML_ERR_WARNING) {
2043		vctxt->nberrors++;
2044		vctxt->err = error;
2045		channel = vctxt->error;
2046	    } else {
2047		channel = vctxt->warning;
2048	    }
2049	    schannel = vctxt->serror;
2050	    data = vctxt->errCtxt;
2051
2052	    /*
2053	    * Error node. If we specify a line number, then
2054	    * do not channel any node to the error function.
2055	    */
2056	    if (line == 0) {
2057		if ((node == NULL) &&
2058		    (vctxt->depth >= 0) &&
2059		    (vctxt->inode != NULL)) {
2060		    node = vctxt->inode->node;
2061		}
2062		/*
2063		* Get filename and line if no node-tree.
2064		*/
2065		if ((node == NULL) &&
2066		    (vctxt->parserCtxt != NULL) &&
2067		    (vctxt->parserCtxt->input != NULL)) {
2068		    file = vctxt->parserCtxt->input->filename;
2069		    line = vctxt->parserCtxt->input->line;
2070		}
2071	    } else {
2072		/*
2073		* Override the given node's (if any) position
2074		* and channel only the given line number.
2075		*/
2076		node = NULL;
2077		/*
2078		* Get filename.
2079		*/
2080		if (vctxt->doc != NULL)
2081		    file = (const char *) vctxt->doc->URL;
2082		else if ((vctxt->parserCtxt != NULL) &&
2083		    (vctxt->parserCtxt->input != NULL))
2084		    file = vctxt->parserCtxt->input->filename;
2085	    }
2086	    if (vctxt->locFunc != NULL) {
2087	        if ((file == NULL) || (line == 0)) {
2088		    unsigned long l;
2089		    const char *f;
2090		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2091		    if (file == NULL)
2092		        file = f;
2093		    if (line == 0)
2094		        line = (int) l;
2095		}
2096	    }
2097	    if ((file == NULL) && (vctxt->filename != NULL))
2098	        file = vctxt->filename;
2099
2100	    __xmlRaiseError(schannel, channel, data, ctxt,
2101		node, XML_FROM_SCHEMASV,
2102		error, errorLevel, file, line,
2103		(const char *) str1, (const char *) str2,
2104		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2105
2106	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2107	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2108	    if (errorLevel != XML_ERR_WARNING) {
2109		pctxt->nberrors++;
2110		pctxt->err = error;
2111		channel = pctxt->error;
2112	    } else {
2113		channel = pctxt->warning;
2114	    }
2115	    schannel = pctxt->serror;
2116	    data = pctxt->errCtxt;
2117	    __xmlRaiseError(schannel, channel, data, ctxt,
2118		node, XML_FROM_SCHEMASP, error,
2119		errorLevel, NULL, 0,
2120		(const char *) str1, (const char *) str2,
2121		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2122	} else {
2123	    TODO
2124	}
2125    }
2126}
2127
2128/**
2129 * xmlSchemaErr3:
2130 * @ctxt: the validation context
2131 * @node: the context node
2132 * @error: the error code
2133 * @msg: the error message
2134 * @str1: extra data
2135 * @str2: extra data
2136 * @str3: extra data
2137 *
2138 * Handle a validation error
2139 */
2140static void
2141xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2142	      int error, xmlNodePtr node, const char *msg,
2143	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2144{
2145    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2146	msg, str1, str2, str3, NULL);
2147}
2148
2149static void
2150xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2151	      int error, xmlNodePtr node, const char *msg,
2152	      const xmlChar *str1, const xmlChar *str2,
2153	      const xmlChar *str3, const xmlChar *str4)
2154{
2155    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2156	msg, str1, str2, str3, str4);
2157}
2158
2159static void
2160xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2161	     int error, xmlNodePtr node, const char *msg,
2162	     const xmlChar *str1, const xmlChar *str2)
2163{
2164    xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2165}
2166
2167static xmlChar *
2168xmlSchemaFormatNodeForError(xmlChar ** msg,
2169			    xmlSchemaAbstractCtxtPtr actxt,
2170			    xmlNodePtr node)
2171{
2172    xmlChar *str = NULL;
2173
2174    *msg = NULL;
2175    if ((node != NULL) &&
2176	(node->type != XML_ELEMENT_NODE) &&
2177	(node->type != XML_ATTRIBUTE_NODE))
2178    {
2179	/*
2180	* Don't try to format other nodes than element and
2181	* attribute nodes.
2182	* Play save and return an empty string.
2183	*/
2184	*msg = xmlStrdup(BAD_CAST "");
2185	return(*msg);
2186    }
2187    if (node != NULL) {
2188	/*
2189	* Work on tree nodes.
2190	*/
2191	if (node->type == XML_ATTRIBUTE_NODE) {
2192	    xmlNodePtr elem = node->parent;
2193
2194	    *msg = xmlStrdup(BAD_CAST "Element '");
2195	    if (elem->ns != NULL)
2196		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2197		    elem->ns->href, elem->name));
2198	    else
2199		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2200		    NULL, elem->name));
2201	    FREE_AND_NULL(str);
2202	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2203	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2204	} else {
2205	    *msg = xmlStrdup(BAD_CAST "Element '");
2206	}
2207	if (node->ns != NULL)
2208	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2209	    node->ns->href, node->name));
2210	else
2211	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2212	    NULL, node->name));
2213	FREE_AND_NULL(str);
2214	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2215    } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2216	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2217	/*
2218	* Work on node infos.
2219	*/
2220	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2221	    xmlSchemaNodeInfoPtr ielem =
2222		vctxt->elemInfos[vctxt->depth];
2223
2224	    *msg = xmlStrdup(BAD_CAST "Element '");
2225	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2226		ielem->nsName, ielem->localName));
2227	    FREE_AND_NULL(str);
2228	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2229	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2230	} else {
2231	    *msg = xmlStrdup(BAD_CAST "Element '");
2232	}
2233	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2234	    vctxt->inode->nsName, vctxt->inode->localName));
2235	FREE_AND_NULL(str);
2236	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2237    } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2238	/*
2239	* Hmm, no node while parsing?
2240	* Return an empty string, in case NULL will break something.
2241	*/
2242	*msg = xmlStrdup(BAD_CAST "");
2243    } else {
2244	TODO
2245	return (NULL);
2246    }
2247    /*
2248    * VAL TODO: The output of the given schema component is currently
2249    * disabled.
2250    */
2251#if 0
2252    if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2253	*msg = xmlStrcat(*msg, BAD_CAST " [");
2254	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2255	    NULL, type, NULL, 0));
2256	FREE_AND_NULL(str)
2257	*msg = xmlStrcat(*msg, BAD_CAST "]");
2258    }
2259#endif
2260    return (*msg);
2261}
2262
2263static void
2264xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2265		     const char *funcName,
2266		     const char *message,
2267		     const xmlChar *str1,
2268		     const xmlChar *str2)
2269{
2270    xmlChar *msg = NULL;
2271
2272    if (actxt == NULL)
2273        return;
2274    msg = xmlStrdup(BAD_CAST "Internal error: ");
2275    msg = xmlStrcat(msg, BAD_CAST funcName);
2276    msg = xmlStrcat(msg, BAD_CAST ", ");
2277    msg = xmlStrcat(msg, BAD_CAST message);
2278    msg = xmlStrcat(msg, BAD_CAST ".\n");
2279
2280    if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2281	xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2282	    (const char *) msg, str1, str2);
2283
2284    else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2285	xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2286	    (const char *) msg, str1, str2);
2287
2288    FREE_AND_NULL(msg)
2289}
2290
2291static void
2292xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2293		     const char *funcName,
2294		     const char *message)
2295{
2296    xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2297}
2298
2299#if 0
2300static void
2301xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2302		     const char *funcName,
2303		     const char *message,
2304		     const xmlChar *str1,
2305		     const xmlChar *str2)
2306{
2307    xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2308	str1, str2);
2309}
2310#endif
2311
2312static void
2313xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2314		   xmlParserErrors error,
2315		   xmlNodePtr node,
2316		   xmlSchemaBasicItemPtr item,
2317		   const char *message,
2318		   const xmlChar *str1, const xmlChar *str2,
2319		   const xmlChar *str3, const xmlChar *str4)
2320{
2321    xmlChar *msg = NULL;
2322
2323    if ((node == NULL) && (item != NULL) &&
2324	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2325	node = WXS_ITEM_NODE(item);
2326	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2327	msg = xmlStrcat(msg, BAD_CAST ": ");
2328    } else
2329	xmlSchemaFormatNodeForError(&msg, actxt, node);
2330    msg = xmlStrcat(msg, (const xmlChar *) message);
2331    msg = xmlStrcat(msg, BAD_CAST ".\n");
2332    xmlSchemaErr4(actxt, error, node,
2333	(const char *) msg, str1, str2, str3, str4);
2334    FREE_AND_NULL(msg)
2335}
2336
2337static void
2338xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2339		   xmlParserErrors error,
2340		   xmlNodePtr node,
2341		   xmlSchemaBasicItemPtr item,
2342		   const char *message,
2343		   const xmlChar *str1,
2344		   const xmlChar *str2)
2345{
2346    xmlSchemaCustomErr4(actxt, error, node, item,
2347	message, str1, str2, NULL, NULL);
2348}
2349
2350
2351
2352static void
2353xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2354		   xmlParserErrors error,
2355		   xmlNodePtr node,
2356		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2357		   const char *message,
2358		   const xmlChar *str1,
2359		   const xmlChar *str2,
2360		   const xmlChar *str3)
2361{
2362    xmlChar *msg = NULL;
2363
2364    xmlSchemaFormatNodeForError(&msg, actxt, node);
2365    msg = xmlStrcat(msg, (const xmlChar *) message);
2366    msg = xmlStrcat(msg, BAD_CAST ".\n");
2367
2368    /* URGENT TODO: Set the error code to something sane. */
2369    xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2370	(const char *) msg, str1, str2, str3, NULL);
2371
2372    FREE_AND_NULL(msg)
2373}
2374
2375
2376
2377static void
2378xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2379		   xmlParserErrors error,
2380		   xmlSchemaPSVIIDCNodePtr idcNode,
2381		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2382		   const char *message,
2383		   const xmlChar *str1,
2384		   const xmlChar *str2)
2385{
2386    xmlChar *msg = NULL, *qname = NULL;
2387
2388    msg = xmlStrdup(BAD_CAST "Element '%s': ");
2389    msg = xmlStrcat(msg, (const xmlChar *) message);
2390    msg = xmlStrcat(msg, BAD_CAST ".\n");
2391    xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2392	error, NULL, idcNode->nodeLine, (const char *) msg,
2393	xmlSchemaFormatQName(&qname,
2394	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2395	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2396	str1, str2, NULL);
2397    FREE_AND_NULL(qname);
2398    FREE_AND_NULL(msg);
2399}
2400
2401static int
2402xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2403			   xmlNodePtr node)
2404{
2405    if (node != NULL)
2406	return (node->type);
2407    if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2408	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2409	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2410    return (-1);
2411}
2412
2413static int
2414xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2415{
2416    switch (item->type) {
2417	case XML_SCHEMA_TYPE_COMPLEX:
2418	case XML_SCHEMA_TYPE_SIMPLE:
2419	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2420		return(1);
2421	    break;
2422	case XML_SCHEMA_TYPE_GROUP:
2423	    return (1);
2424	case XML_SCHEMA_TYPE_ELEMENT:
2425	    if ( ((xmlSchemaElementPtr) item)->flags &
2426		XML_SCHEMAS_ELEM_GLOBAL)
2427		return(1);
2428	    break;
2429	case XML_SCHEMA_TYPE_ATTRIBUTE:
2430	    if ( ((xmlSchemaAttributePtr) item)->flags &
2431		XML_SCHEMAS_ATTR_GLOBAL)
2432		return(1);
2433	    break;
2434	/* Note that attribute groups are always global. */
2435	default:
2436	    return(1);
2437    }
2438    return (0);
2439}
2440
2441static void
2442xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2443		       xmlParserErrors error,
2444		       xmlNodePtr node,
2445		       const xmlChar *value,
2446		       xmlSchemaTypePtr type,
2447		       int displayValue)
2448{
2449    xmlChar *msg = NULL;
2450
2451    xmlSchemaFormatNodeForError(&msg, actxt, node);
2452
2453    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2454	    XML_ATTRIBUTE_NODE))
2455	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2456    else
2457	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2458	    "value of ");
2459
2460    if (! xmlSchemaIsGlobalItem(type))
2461	msg = xmlStrcat(msg, BAD_CAST "the local ");
2462    else
2463	msg = xmlStrcat(msg, BAD_CAST "the ");
2464
2465    if (WXS_IS_ATOMIC(type))
2466	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2467    else if (WXS_IS_LIST(type))
2468	msg = xmlStrcat(msg, BAD_CAST "list type");
2469    else if (WXS_IS_UNION(type))
2470	msg = xmlStrcat(msg, BAD_CAST "union type");
2471
2472    if (xmlSchemaIsGlobalItem(type)) {
2473	xmlChar *str = NULL;
2474	msg = xmlStrcat(msg, BAD_CAST " '");
2475	if (type->builtInType != 0) {
2476	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2477	    msg = xmlStrcat(msg, type->name);
2478	} else
2479	    msg = xmlStrcat(msg,
2480		xmlSchemaFormatQName(&str,
2481		    type->targetNamespace, type->name));
2482	msg = xmlStrcat(msg, BAD_CAST "'");
2483	FREE_AND_NULL(str);
2484    }
2485    msg = xmlStrcat(msg, BAD_CAST ".\n");
2486    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2487	    XML_ATTRIBUTE_NODE))
2488	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2489    else
2490	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2491    FREE_AND_NULL(msg)
2492}
2493
2494static const xmlChar *
2495xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2496			      xmlSchemaNodeInfoPtr ni,
2497			      xmlNodePtr node)
2498{
2499    if (node != NULL) {
2500	if (node->ns != NULL)
2501	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2502	else
2503	    return (xmlSchemaFormatQName(str, NULL, node->name));
2504    } else if (ni != NULL)
2505	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2506    return (NULL);
2507}
2508
2509static void
2510xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2511			xmlParserErrors error,
2512			xmlSchemaAttrInfoPtr ni,
2513			xmlNodePtr node)
2514{
2515    xmlChar *msg = NULL, *str = NULL;
2516
2517    xmlSchemaFormatNodeForError(&msg, actxt, node);
2518    msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2519    xmlSchemaErr(actxt, error, node, (const char *) msg,
2520	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2521	NULL);
2522    FREE_AND_NULL(str)
2523    FREE_AND_NULL(msg)
2524}
2525
2526static void
2527xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2528		        xmlParserErrors error,
2529		        xmlNodePtr node,
2530			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2531			const char *message,
2532			int nbval,
2533			int nbneg,
2534			xmlChar **values)
2535{
2536    xmlChar *str = NULL, *msg = NULL;
2537    xmlChar *localName, *nsName;
2538    const xmlChar *cur, *end;
2539    int i;
2540
2541    xmlSchemaFormatNodeForError(&msg, actxt, node);
2542    msg = xmlStrcat(msg, (const xmlChar *) message);
2543    msg = xmlStrcat(msg, BAD_CAST ".");
2544    /*
2545    * Note that is does not make sense to report that we have a
2546    * wildcard here, since the wildcard might be unfolded into
2547    * multiple transitions.
2548    */
2549    if (nbval + nbneg > 0) {
2550	if (nbval + nbneg > 1) {
2551	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2552	} else
2553	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2554	nsName = NULL;
2555
2556	for (i = 0; i < nbval + nbneg; i++) {
2557	    cur = values[i];
2558	    if (cur == NULL)
2559	        continue;
2560	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2561	        (cur[3] == ' ')) {
2562		cur += 4;
2563		str = xmlStrcat(str, BAD_CAST "##other");
2564	    }
2565	    /*
2566	    * Get the local name.
2567	    */
2568	    localName = NULL;
2569
2570	    end = cur;
2571	    if (*end == '*') {
2572		localName = xmlStrdup(BAD_CAST "*");
2573		end++;
2574	    } else {
2575		while ((*end != 0) && (*end != '|'))
2576		    end++;
2577		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2578	    }
2579	    if (*end != 0) {
2580		end++;
2581		/*
2582		* Skip "*|*" if they come with negated expressions, since
2583		* they represent the same negated wildcard.
2584		*/
2585		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2586		    /*
2587		    * Get the namespace name.
2588		    */
2589		    cur = end;
2590		    if (*end == '*') {
2591			nsName = xmlStrdup(BAD_CAST "{*}");
2592		    } else {
2593			while (*end != 0)
2594			    end++;
2595
2596			if (i >= nbval)
2597			    nsName = xmlStrdup(BAD_CAST "{##other:");
2598			else
2599			    nsName = xmlStrdup(BAD_CAST "{");
2600
2601			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2602			nsName = xmlStrcat(nsName, BAD_CAST "}");
2603		    }
2604		    str = xmlStrcat(str, BAD_CAST nsName);
2605		    FREE_AND_NULL(nsName)
2606		} else {
2607		    FREE_AND_NULL(localName);
2608		    continue;
2609		}
2610	    }
2611	    str = xmlStrcat(str, BAD_CAST localName);
2612	    FREE_AND_NULL(localName);
2613
2614	    if (i < nbval + nbneg -1)
2615		str = xmlStrcat(str, BAD_CAST ", ");
2616	}
2617	str = xmlStrcat(str, BAD_CAST " ).\n");
2618	msg = xmlStrcat(msg, BAD_CAST str);
2619	FREE_AND_NULL(str)
2620    } else
2621      msg = xmlStrcat(msg, BAD_CAST "\n");
2622    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2623    xmlFree(msg);
2624}
2625
2626static void
2627xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2628		  xmlParserErrors error,
2629		  xmlNodePtr node,
2630		  const xmlChar *value,
2631		  unsigned long length,
2632		  xmlSchemaTypePtr type,
2633		  xmlSchemaFacetPtr facet,
2634		  const char *message,
2635		  const xmlChar *str1,
2636		  const xmlChar *str2)
2637{
2638    xmlChar *str = NULL, *msg = NULL;
2639    xmlSchemaTypeType facetType;
2640    int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2641
2642    xmlSchemaFormatNodeForError(&msg, actxt, node);
2643    if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2644	facetType = XML_SCHEMA_FACET_ENUMERATION;
2645	/*
2646	* If enumerations are validated, one must not expect the
2647	* facet to be given.
2648	*/
2649    } else
2650	facetType = facet->type;
2651    msg = xmlStrcat(msg, BAD_CAST "[");
2652    msg = xmlStrcat(msg, BAD_CAST "facet '");
2653    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2654    msg = xmlStrcat(msg, BAD_CAST "'] ");
2655    if (message == NULL) {
2656	/*
2657	* Use a default message.
2658	*/
2659	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2660	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2661	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2662
2663	    char len[25], actLen[25];
2664
2665	    /* FIXME, TODO: What is the max expected string length of the
2666	    * this value?
2667	    */
2668	    if (nodeType == XML_ATTRIBUTE_NODE)
2669		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2670	    else
2671		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2672
2673	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2674	    snprintf(actLen, 24, "%lu", length);
2675
2676	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2677		msg = xmlStrcat(msg,
2678		BAD_CAST "this differs from the allowed length of '%s'.\n");
2679	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2680		msg = xmlStrcat(msg,
2681		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2682	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2683		msg = xmlStrcat(msg,
2684		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2685
2686	    if (nodeType == XML_ATTRIBUTE_NODE)
2687		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2688		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2689	    else
2690		xmlSchemaErr(actxt, error, node, (const char *) msg,
2691		    (const xmlChar *) actLen, (const xmlChar *) len);
2692
2693	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2694	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2695		"of the set {%s}.\n");
2696	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2697		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2698	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2699	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2700		"by the pattern '%s'.\n");
2701	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2702		facet->value);
2703	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2704	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2705		"minimum value allowed ('%s').\n");
2706	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2707		facet->value);
2708	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2709	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2710		"maximum value allowed ('%s').\n");
2711	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2712		facet->value);
2713	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2714	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2715		"'%s'.\n");
2716	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2717		facet->value);
2718	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2719	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2720		"'%s'.\n");
2721	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2722		facet->value);
2723	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2724	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2725		"digits than are allowed ('%s').\n");
2726	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2727		facet->value);
2728	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2729	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2730		"digits than are allowed ('%s').\n");
2731	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2732		facet->value);
2733	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2734	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2735	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2736	} else {
2737	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2738	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2739	}
2740    } else {
2741	msg = xmlStrcat(msg, (const xmlChar *) message);
2742	msg = xmlStrcat(msg, BAD_CAST ".\n");
2743	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2744    }
2745    FREE_AND_NULL(str)
2746    xmlFree(msg);
2747}
2748
2749#define VERROR(err, type, msg) \
2750    xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2751
2752#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2753
2754#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2755#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2756
2757#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2758
2759
2760/**
2761 * xmlSchemaPMissingAttrErr:
2762 * @ctxt: the schema validation context
2763 * @ownerDes: the designation of  the owner
2764 * @ownerName: the name of the owner
2765 * @ownerItem: the owner as a schema object
2766 * @ownerElem: the owner as an element node
2767 * @node: the parent element node of the missing attribute node
2768 * @type: the corresponding type of the attribute node
2769 *
2770 * Reports an illegal attribute.
2771 */
2772static void
2773xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2774			 xmlParserErrors error,
2775			 xmlSchemaBasicItemPtr ownerItem,
2776			 xmlNodePtr ownerElem,
2777			 const char *name,
2778			 const char *message)
2779{
2780    xmlChar *des = NULL;
2781
2782    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2783
2784    if (message != NULL)
2785	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2786    else
2787	xmlSchemaPErr(ctxt, ownerElem, error,
2788	    "%s: The attribute '%s' is required but missing.\n",
2789	    BAD_CAST des, BAD_CAST name);
2790    FREE_AND_NULL(des);
2791}
2792
2793
2794/**
2795 * xmlSchemaPResCompAttrErr:
2796 * @ctxt: the schema validation context
2797 * @error: the error code
2798 * @ownerDes: the designation of  the owner
2799 * @ownerItem: the owner as a schema object
2800 * @ownerElem: the owner as an element node
2801 * @name: the name of the attribute holding the QName
2802 * @refName: the referenced local name
2803 * @refURI: the referenced namespace URI
2804 * @message: optional message
2805 *
2806 * Used to report QName attribute values that failed to resolve
2807 * to schema components.
2808 */
2809static void
2810xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2811			 xmlParserErrors error,
2812			 xmlSchemaBasicItemPtr ownerItem,
2813			 xmlNodePtr ownerElem,
2814			 const char *name,
2815			 const xmlChar *refName,
2816			 const xmlChar *refURI,
2817			 xmlSchemaTypeType refType,
2818			 const char *refTypeStr)
2819{
2820    xmlChar *des = NULL, *strA = NULL;
2821
2822    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2823    if (refTypeStr == NULL)
2824	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2825	xmlSchemaPErrExt(ctxt, ownerElem, error,
2826	    NULL, NULL, NULL,
2827	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2828	    "%s.\n", BAD_CAST des, BAD_CAST name,
2829	    xmlSchemaFormatQName(&strA, refURI, refName),
2830	    BAD_CAST refTypeStr, NULL);
2831    FREE_AND_NULL(des)
2832    FREE_AND_NULL(strA)
2833}
2834
2835/**
2836 * xmlSchemaPCustomAttrErr:
2837 * @ctxt: the schema parser context
2838 * @error: the error code
2839 * @ownerDes: the designation of the owner
2840 * @ownerItem: the owner as a schema object
2841 * @attr: the illegal attribute node
2842 *
2843 * Reports an illegal attribute during the parse.
2844 */
2845static void
2846xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2847			xmlParserErrors error,
2848			xmlChar **ownerDes,
2849			xmlSchemaBasicItemPtr ownerItem,
2850			xmlAttrPtr attr,
2851			const char *msg)
2852{
2853    xmlChar *des = NULL;
2854
2855    if (ownerDes == NULL)
2856	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2857    else if (*ownerDes == NULL) {
2858	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2859	des = *ownerDes;
2860    } else
2861	des = *ownerDes;
2862    if (attr == NULL) {
2863	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2864	    "%s, attribute '%s': %s.\n",
2865	    BAD_CAST des, (const xmlChar *) "Unknown",
2866	    (const xmlChar *) msg, NULL, NULL);
2867    } else {
2868	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2869	    "%s, attribute '%s': %s.\n",
2870	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2871    }
2872    if (ownerDes == NULL)
2873	FREE_AND_NULL(des);
2874}
2875
2876/**
2877 * xmlSchemaPIllegalAttrErr:
2878 * @ctxt: the schema parser context
2879 * @error: the error code
2880 * @ownerDes: the designation of the attribute's owner
2881 * @ownerItem: the attribute's owner item
2882 * @attr: the illegal attribute node
2883 *
2884 * Reports an illegal attribute during the parse.
2885 */
2886static void
2887xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2888			 xmlParserErrors error,
2889			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2890			 xmlAttrPtr attr)
2891{
2892    xmlChar *strA = NULL, *strB = NULL;
2893
2894    xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2895    xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2896	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2897	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2898	NULL, NULL);
2899    FREE_AND_NULL(strA);
2900    FREE_AND_NULL(strB);
2901}
2902
2903/**
2904 * xmlSchemaPCustomErr:
2905 * @ctxt: the schema parser context
2906 * @error: the error code
2907 * @itemDes: the designation of the schema item
2908 * @item: the schema item
2909 * @itemElem: the node of the schema item
2910 * @message: the error message
2911 * @str1: an optional param for the error message
2912 * @str2: an optional param for the error message
2913 * @str3: an optional param for the error message
2914 *
2915 * Reports an error during parsing.
2916 */
2917static void
2918xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2919		    xmlParserErrors error,
2920		    xmlSchemaBasicItemPtr item,
2921		    xmlNodePtr itemElem,
2922		    const char *message,
2923		    const xmlChar *str1,
2924		    const xmlChar *str2,
2925		    const xmlChar *str3)
2926{
2927    xmlChar *des = NULL, *msg = NULL;
2928
2929    xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2930    msg = xmlStrdup(BAD_CAST "%s: ");
2931    msg = xmlStrcat(msg, (const xmlChar *) message);
2932    msg = xmlStrcat(msg, BAD_CAST ".\n");
2933    if ((itemElem == NULL) && (item != NULL))
2934	itemElem = WXS_ITEM_NODE(item);
2935    xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2936	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2937    FREE_AND_NULL(des);
2938    FREE_AND_NULL(msg);
2939}
2940
2941/**
2942 * xmlSchemaPCustomErr:
2943 * @ctxt: the schema parser context
2944 * @error: the error code
2945 * @itemDes: the designation of the schema item
2946 * @item: the schema item
2947 * @itemElem: the node of the schema item
2948 * @message: the error message
2949 * @str1: the optional param for the error message
2950 *
2951 * Reports an error during parsing.
2952 */
2953static void
2954xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2955		    xmlParserErrors error,
2956		    xmlSchemaBasicItemPtr item,
2957		    xmlNodePtr itemElem,
2958		    const char *message,
2959		    const xmlChar *str1)
2960{
2961    xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2962	str1, NULL, NULL);
2963}
2964
2965/**
2966 * xmlSchemaPAttrUseErr:
2967 * @ctxt: the schema parser context
2968 * @error: the error code
2969 * @itemDes: the designation of the schema type
2970 * @item: the schema type
2971 * @itemElem: the node of the schema type
2972 * @attr: the invalid schema attribute
2973 * @message: the error message
2974 * @str1: the optional param for the error message
2975 *
2976 * Reports an attribute use error during parsing.
2977 */
2978static void
2979xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2980		    xmlParserErrors error,
2981		    xmlNodePtr node,
2982		    xmlSchemaBasicItemPtr ownerItem,
2983		    const xmlSchemaAttributeUsePtr attruse,
2984		    const char *message,
2985		    const xmlChar *str1, const xmlChar *str2,
2986		    const xmlChar *str3,const xmlChar *str4)
2987{
2988    xmlChar *str = NULL, *msg = NULL;
2989
2990    xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2991    msg = xmlStrcat(msg, BAD_CAST ", ");
2992    msg = xmlStrcat(msg,
2993	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2994	WXS_BASIC_CAST attruse, NULL));
2995    FREE_AND_NULL(str);
2996    msg = xmlStrcat(msg, BAD_CAST ": ");
2997    msg = xmlStrcat(msg, (const xmlChar *) message);
2998    msg = xmlStrcat(msg, BAD_CAST ".\n");
2999    xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3000	(const char *) msg, str1, str2, str3, str4);
3001    xmlFree(msg);
3002}
3003
3004/**
3005 * xmlSchemaPIllegalFacetAtomicErr:
3006 * @ctxt: the schema parser context
3007 * @error: the error code
3008 * @type: the schema type
3009 * @baseType: the base type of type
3010 * @facet: the illegal facet
3011 *
3012 * Reports an illegal facet for atomic simple types.
3013 */
3014static void
3015xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3016			  xmlParserErrors error,
3017			  xmlSchemaTypePtr type,
3018			  xmlSchemaTypePtr baseType,
3019			  xmlSchemaFacetPtr facet)
3020{
3021    xmlChar *des = NULL, *strT = NULL;
3022
3023    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3024    xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3025	"%s: The facet '%s' is not allowed on types derived from the "
3026	"type %s.\n",
3027	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3028	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3029	NULL, NULL);
3030    FREE_AND_NULL(des);
3031    FREE_AND_NULL(strT);
3032}
3033
3034/**
3035 * xmlSchemaPIllegalFacetListUnionErr:
3036 * @ctxt: the schema parser context
3037 * @error: the error code
3038 * @itemDes: the designation of the schema item involved
3039 * @item: the schema item involved
3040 * @facet: the illegal facet
3041 *
3042 * Reports an illegal facet for <list> and <union>.
3043 */
3044static void
3045xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3046			  xmlParserErrors error,
3047			  xmlSchemaTypePtr type,
3048			  xmlSchemaFacetPtr facet)
3049{
3050    xmlChar *des = NULL;
3051
3052    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3053	type->node);
3054    xmlSchemaPErr(ctxt, type->node, error,
3055	"%s: The facet '%s' is not allowed.\n",
3056	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3057    FREE_AND_NULL(des);
3058}
3059
3060/**
3061 * xmlSchemaPMutualExclAttrErr:
3062 * @ctxt: the schema validation context
3063 * @error: the error code
3064 * @elemDes: the designation of the parent element node
3065 * @attr: the bad attribute node
3066 * @type: the corresponding type of the attribute node
3067 *
3068 * Reports an illegal attribute.
3069 */
3070static void
3071xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3072			 xmlParserErrors error,
3073			 xmlSchemaBasicItemPtr ownerItem,
3074			 xmlAttrPtr attr,
3075			 const char *name1,
3076			 const char *name2)
3077{
3078    xmlChar *des = NULL;
3079
3080    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3081    xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3082	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3083	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3084    FREE_AND_NULL(des);
3085}
3086
3087/**
3088 * xmlSchemaPSimpleTypeErr:
3089 * @ctxt:  the schema validation context
3090 * @error: the error code
3091 * @type: the type specifier
3092 * @ownerDes: the designation of the owner
3093 * @ownerItem: the schema object if existent
3094 * @node: the validated node
3095 * @value: the validated value
3096 *
3097 * Reports a simple type validation error.
3098 * TODO: Should this report the value of an element as well?
3099 */
3100static void
3101xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3102			xmlParserErrors error,
3103			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3104			xmlNodePtr node,
3105			xmlSchemaTypePtr type,
3106			const char *expected,
3107			const xmlChar *value,
3108			const char *message,
3109			const xmlChar *str1,
3110			const xmlChar *str2)
3111{
3112    xmlChar *msg = NULL;
3113
3114    xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3115    if (message == NULL) {
3116	/*
3117	* Use default messages.
3118	*/
3119	if (type != NULL) {
3120	    if (node->type == XML_ATTRIBUTE_NODE)
3121		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3122	    else
3123		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3124		"valid value of ");
3125	    if (! xmlSchemaIsGlobalItem(type))
3126		msg = xmlStrcat(msg, BAD_CAST "the local ");
3127	    else
3128		msg = xmlStrcat(msg, BAD_CAST "the ");
3129
3130	    if (WXS_IS_ATOMIC(type))
3131		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3132	    else if (WXS_IS_LIST(type))
3133		msg = xmlStrcat(msg, BAD_CAST "list type");
3134	    else if (WXS_IS_UNION(type))
3135		msg = xmlStrcat(msg, BAD_CAST "union type");
3136
3137	    if (xmlSchemaIsGlobalItem(type)) {
3138		xmlChar *str = NULL;
3139		msg = xmlStrcat(msg, BAD_CAST " '");
3140		if (type->builtInType != 0) {
3141		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3142		    msg = xmlStrcat(msg, type->name);
3143		} else
3144		    msg = xmlStrcat(msg,
3145			xmlSchemaFormatQName(&str,
3146			    type->targetNamespace, type->name));
3147		msg = xmlStrcat(msg, BAD_CAST "'.");
3148		FREE_AND_NULL(str);
3149	    }
3150	} else {
3151	    if (node->type == XML_ATTRIBUTE_NODE)
3152		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3153	    else
3154		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3155		"valid.");
3156	}
3157	if (expected) {
3158	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3159	    msg = xmlStrcat(msg, BAD_CAST expected);
3160	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3161	} else
3162	    msg = xmlStrcat(msg, BAD_CAST "\n");
3163	if (node->type == XML_ATTRIBUTE_NODE)
3164	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3165	else
3166	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3167    } else {
3168	msg = xmlStrcat(msg, BAD_CAST message);
3169	msg = xmlStrcat(msg, BAD_CAST ".\n");
3170	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3171	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3172    }
3173    /* Cleanup. */
3174    FREE_AND_NULL(msg)
3175}
3176
3177/**
3178 * xmlSchemaPContentErr:
3179 * @ctxt: the schema parser context
3180 * @error: the error code
3181 * @onwerDes: the designation of the holder of the content
3182 * @ownerItem: the owner item of the holder of the content
3183 * @ownerElem: the node of the holder of the content
3184 * @child: the invalid child node
3185 * @message: the optional error message
3186 * @content: the optional string describing the correct content
3187 *
3188 * Reports an error concerning the content of a schema element.
3189 */
3190static void
3191xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3192		     xmlParserErrors error,
3193		     xmlSchemaBasicItemPtr ownerItem,
3194		     xmlNodePtr ownerElem,
3195		     xmlNodePtr child,
3196		     const char *message,
3197		     const char *content)
3198{
3199    xmlChar *des = NULL;
3200
3201    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3202    if (message != NULL)
3203	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3204	    "%s: %s.\n",
3205	    BAD_CAST des, BAD_CAST message);
3206    else {
3207	if (content != NULL) {
3208	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3209		"%s: The content is not valid. Expected is %s.\n",
3210		BAD_CAST des, BAD_CAST content);
3211	} else {
3212	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3213		"%s: The content is not valid.\n",
3214		BAD_CAST des, NULL);
3215	}
3216    }
3217    FREE_AND_NULL(des)
3218}
3219
3220/************************************************************************
3221 *									*
3222 *			Streamable error functions                      *
3223 *									*
3224 ************************************************************************/
3225
3226
3227
3228
3229/************************************************************************
3230 *									*
3231 *			Validation helper functions			*
3232 *									*
3233 ************************************************************************/
3234
3235
3236/************************************************************************
3237 *									*
3238 *			Allocation functions				*
3239 *									*
3240 ************************************************************************/
3241
3242/**
3243 * xmlSchemaNewSchemaForParserCtxt:
3244 * @ctxt:  a schema validation context
3245 *
3246 * Allocate a new Schema structure.
3247 *
3248 * Returns the newly allocated structure or NULL in case or error
3249 */
3250static xmlSchemaPtr
3251xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3252{
3253    xmlSchemaPtr ret;
3254
3255    ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3256    if (ret == NULL) {
3257        xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3258        return (NULL);
3259    }
3260    memset(ret, 0, sizeof(xmlSchema));
3261    ret->dict = ctxt->dict;
3262    xmlDictReference(ret->dict);
3263
3264    return (ret);
3265}
3266
3267/**
3268 * xmlSchemaNewFacet:
3269 *
3270 * Allocate a new Facet structure.
3271 *
3272 * Returns the newly allocated structure or NULL in case or error
3273 */
3274xmlSchemaFacetPtr
3275xmlSchemaNewFacet(void)
3276{
3277    xmlSchemaFacetPtr ret;
3278
3279    ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3280    if (ret == NULL) {
3281        return (NULL);
3282    }
3283    memset(ret, 0, sizeof(xmlSchemaFacet));
3284
3285    return (ret);
3286}
3287
3288/**
3289 * xmlSchemaNewAnnot:
3290 * @ctxt:  a schema validation context
3291 * @node:  a node
3292 *
3293 * Allocate a new annotation structure.
3294 *
3295 * Returns the newly allocated structure or NULL in case or error
3296 */
3297static xmlSchemaAnnotPtr
3298xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3299{
3300    xmlSchemaAnnotPtr ret;
3301
3302    ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3303    if (ret == NULL) {
3304        xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3305        return (NULL);
3306    }
3307    memset(ret, 0, sizeof(xmlSchemaAnnot));
3308    ret->content = node;
3309    return (ret);
3310}
3311
3312static xmlSchemaItemListPtr
3313xmlSchemaItemListCreate(void)
3314{
3315    xmlSchemaItemListPtr ret;
3316
3317    ret = xmlMalloc(sizeof(xmlSchemaItemList));
3318    if (ret == NULL) {
3319	xmlSchemaPErrMemory(NULL,
3320	    "allocating an item list structure", NULL);
3321	return (NULL);
3322    }
3323    memset(ret, 0, sizeof(xmlSchemaItemList));
3324    return (ret);
3325}
3326
3327static void
3328xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3329{
3330    if (list->items != NULL) {
3331	xmlFree(list->items);
3332	list->items = NULL;
3333    }
3334    list->nbItems = 0;
3335    list->sizeItems = 0;
3336}
3337
3338static int
3339xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3340{
3341    if (list->items == NULL) {
3342	list->items = (void **) xmlMalloc(
3343	    20 * sizeof(void *));
3344	if (list->items == NULL) {
3345	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3346	    return(-1);
3347	}
3348	list->sizeItems = 20;
3349    } else if (list->sizeItems <= list->nbItems) {
3350	list->sizeItems *= 2;
3351	list->items = (void **) xmlRealloc(list->items,
3352	    list->sizeItems * sizeof(void *));
3353	if (list->items == NULL) {
3354	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3355	    list->sizeItems = 0;
3356	    return(-1);
3357	}
3358    }
3359    list->items[list->nbItems++] = item;
3360    return(0);
3361}
3362
3363static int
3364xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3365			 int initialSize,
3366			 void *item)
3367{
3368    if (list->items == NULL) {
3369	if (initialSize <= 0)
3370	    initialSize = 1;
3371	list->items = (void **) xmlMalloc(
3372	    initialSize * sizeof(void *));
3373	if (list->items == NULL) {
3374	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3375	    return(-1);
3376	}
3377	list->sizeItems = initialSize;
3378    } else if (list->sizeItems <= list->nbItems) {
3379	list->sizeItems *= 2;
3380	list->items = (void **) xmlRealloc(list->items,
3381	    list->sizeItems * sizeof(void *));
3382	if (list->items == NULL) {
3383	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3384	    list->sizeItems = 0;
3385	    return(-1);
3386	}
3387    }
3388    list->items[list->nbItems++] = item;
3389    return(0);
3390}
3391
3392static int
3393xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3394{
3395    if (list->items == NULL) {
3396	list->items = (void **) xmlMalloc(
3397	    20 * sizeof(void *));
3398	if (list->items == NULL) {
3399	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3400	    return(-1);
3401	}
3402	list->sizeItems = 20;
3403    } else if (list->sizeItems <= list->nbItems) {
3404	list->sizeItems *= 2;
3405	list->items = (void **) xmlRealloc(list->items,
3406	    list->sizeItems * sizeof(void *));
3407	if (list->items == NULL) {
3408	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3409	    list->sizeItems = 0;
3410	    return(-1);
3411	}
3412    }
3413    /*
3414    * Just append if the index is greater/equal than the item count.
3415    */
3416    if (idx >= list->nbItems) {
3417	list->items[list->nbItems++] = item;
3418    } else {
3419	int i;
3420	for (i = list->nbItems; i > idx; i--)
3421	    list->items[i] = list->items[i-1];
3422	list->items[idx] = item;
3423	list->nbItems++;
3424    }
3425    return(0);
3426}
3427
3428#if 0 /* enable if ever needed */
3429static int
3430xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3431			    int initialSize,
3432			    void *item,
3433			    int idx)
3434{
3435    if (list->items == NULL) {
3436	if (initialSize <= 0)
3437	    initialSize = 1;
3438	list->items = (void **) xmlMalloc(
3439	    initialSize * sizeof(void *));
3440	if (list->items == NULL) {
3441	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3442	    return(-1);
3443	}
3444	list->sizeItems = initialSize;
3445    } else if (list->sizeItems <= list->nbItems) {
3446	list->sizeItems *= 2;
3447	list->items = (void **) xmlRealloc(list->items,
3448	    list->sizeItems * sizeof(void *));
3449	if (list->items == NULL) {
3450	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3451	    list->sizeItems = 0;
3452	    return(-1);
3453	}
3454    }
3455    /*
3456    * Just append if the index is greater/equal than the item count.
3457    */
3458    if (idx >= list->nbItems) {
3459	list->items[list->nbItems++] = item;
3460    } else {
3461	int i;
3462	for (i = list->nbItems; i > idx; i--)
3463	    list->items[i] = list->items[i-1];
3464	list->items[idx] = item;
3465	list->nbItems++;
3466    }
3467    return(0);
3468}
3469#endif
3470
3471static int
3472xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3473{
3474    int i;
3475    if ((list->items == NULL) || (idx >= list->nbItems)) {
3476	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3477	    "index error.\n");
3478	return(-1);
3479    }
3480
3481    if (list->nbItems == 1) {
3482	/* TODO: Really free the list? */
3483	xmlFree(list->items);
3484	list->items = NULL;
3485	list->nbItems = 0;
3486	list->sizeItems = 0;
3487    } else if (list->nbItems -1 == idx) {
3488	list->nbItems--;
3489    } else {
3490	for (i = idx; i < list->nbItems -1; i++)
3491	    list->items[i] = list->items[i+1];
3492	list->nbItems--;
3493    }
3494    return(0);
3495}
3496
3497/**
3498 * xmlSchemaItemListFree:
3499 * @annot:  a schema type structure
3500 *
3501 * Deallocate a annotation structure
3502 */
3503static void
3504xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3505{
3506    if (list == NULL)
3507	return;
3508    if (list->items != NULL)
3509	xmlFree(list->items);
3510    xmlFree(list);
3511}
3512
3513static void
3514xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3515{
3516    if (bucket == NULL)
3517	return;
3518    if (bucket->globals != NULL) {
3519	xmlSchemaComponentListFree(bucket->globals);
3520	xmlSchemaItemListFree(bucket->globals);
3521    }
3522    if (bucket->locals != NULL) {
3523	xmlSchemaComponentListFree(bucket->locals);
3524	xmlSchemaItemListFree(bucket->locals);
3525    }
3526    if (bucket->relations != NULL) {
3527	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3528	do {
3529	    prev = cur;
3530	    cur = cur->next;
3531	    xmlFree(prev);
3532	} while (cur != NULL);
3533    }
3534    if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3535	xmlFreeDoc(bucket->doc);
3536    }
3537    if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3538	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3539	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3540    }
3541    xmlFree(bucket);
3542}
3543
3544static xmlSchemaBucketPtr
3545xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3546			 int type, const xmlChar *targetNamespace)
3547{
3548    xmlSchemaBucketPtr ret;
3549    int size;
3550    xmlSchemaPtr mainSchema;
3551
3552    if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3553	PERROR_INT("xmlSchemaBucketCreate",
3554	    "no main schema on constructor");
3555	return(NULL);
3556    }
3557    mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3558    /* Create the schema bucket. */
3559    if (WXS_IS_BUCKET_INCREDEF(type))
3560	size = sizeof(xmlSchemaInclude);
3561    else
3562	size = sizeof(xmlSchemaImport);
3563    ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3564    if (ret == NULL) {
3565	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3566	return(NULL);
3567    }
3568    memset(ret, 0, size);
3569    ret->targetNamespace = targetNamespace;
3570    ret->type = type;
3571    ret->globals = xmlSchemaItemListCreate();
3572    if (ret->globals == NULL) {
3573	xmlFree(ret);
3574	return(NULL);
3575    }
3576    ret->locals = xmlSchemaItemListCreate();
3577    if (ret->locals == NULL) {
3578	xmlFree(ret);
3579	return(NULL);
3580    }
3581    /*
3582    * The following will assure that only the first bucket is marked as
3583    * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3584    * For each following import buckets an xmlSchema will be created.
3585    * An xmlSchema will be created for every distinct targetNamespace.
3586    * We assign the targetNamespace to the schemata here.
3587    */
3588    if (! WXS_HAS_BUCKETS(pctxt)) {
3589	if (WXS_IS_BUCKET_INCREDEF(type)) {
3590	    PERROR_INT("xmlSchemaBucketCreate",
3591		"first bucket but it's an include or redefine");
3592	    xmlSchemaBucketFree(ret);
3593	    return(NULL);
3594	}
3595	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3596	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3597	/* Point to the *main* schema. */
3598	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3599	WXS_IMPBUCKET(ret)->schema = mainSchema;
3600	/*
3601	* Ensure that the main schema gets a targetNamespace.
3602	*/
3603	mainSchema->targetNamespace = targetNamespace;
3604    } else {
3605	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3606	    PERROR_INT("xmlSchemaBucketCreate",
3607		"main bucket but it's not the first one");
3608	    xmlSchemaBucketFree(ret);
3609	    return(NULL);
3610	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3611	    /*
3612	    * Create a schema for imports and assign the
3613	    * targetNamespace.
3614	    */
3615	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3616	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3617		xmlSchemaBucketFree(ret);
3618		return(NULL);
3619	    }
3620	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3621	}
3622    }
3623    if (WXS_IS_BUCKET_IMPMAIN(type)) {
3624	int res;
3625	/*
3626	* Imports go into the "schemasImports" slot of the main *schema*.
3627	* Note that we create an import entry for the main schema as well; i.e.,
3628	* even if there's only one schema, we'll get an import.
3629	*/
3630	if (mainSchema->schemasImports == NULL) {
3631	    mainSchema->schemasImports = xmlHashCreateDict(5,
3632		WXS_CONSTRUCTOR(pctxt)->dict);
3633	    if (mainSchema->schemasImports == NULL) {
3634		xmlSchemaBucketFree(ret);
3635		return(NULL);
3636	    }
3637	}
3638	if (targetNamespace == NULL)
3639	    res = xmlHashAddEntry(mainSchema->schemasImports,
3640		XML_SCHEMAS_NO_NAMESPACE, ret);
3641	else
3642	    res = xmlHashAddEntry(mainSchema->schemasImports,
3643		targetNamespace, ret);
3644	if (res != 0) {
3645	    PERROR_INT("xmlSchemaBucketCreate",
3646		"failed to add the schema bucket to the hash");
3647	    xmlSchemaBucketFree(ret);
3648	    return(NULL);
3649	}
3650    } else {
3651	/* Set the @ownerImport of an include bucket. */
3652	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3653	    WXS_INCBUCKET(ret)->ownerImport =
3654		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3655	else
3656	    WXS_INCBUCKET(ret)->ownerImport =
3657		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3658
3659	/* Includes got into the "includes" slot of the *main* schema. */
3660	if (mainSchema->includes == NULL) {
3661	    mainSchema->includes = xmlSchemaItemListCreate();
3662	    if (mainSchema->includes == NULL) {
3663		xmlSchemaBucketFree(ret);
3664		return(NULL);
3665	    }
3666	}
3667	xmlSchemaItemListAdd(mainSchema->includes, ret);
3668    }
3669    /*
3670    * Add to list of all buckets; this is used for lookup
3671    * during schema construction time only.
3672    */
3673    if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3674	return(NULL);
3675    return(ret);
3676}
3677
3678static int
3679xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3680{
3681    if (*list == NULL) {
3682	*list = xmlSchemaItemListCreate();
3683	if (*list == NULL)
3684	    return(-1);
3685    }
3686    xmlSchemaItemListAddSize(*list, initialSize, item);
3687    return(0);
3688}
3689
3690/**
3691 * xmlSchemaFreeAnnot:
3692 * @annot:  a schema type structure
3693 *
3694 * Deallocate a annotation structure
3695 */
3696static void
3697xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3698{
3699    if (annot == NULL)
3700        return;
3701    if (annot->next == NULL) {
3702	xmlFree(annot);
3703    } else {
3704	xmlSchemaAnnotPtr prev;
3705
3706	do {
3707	    prev = annot;
3708	    annot = annot->next;
3709	    xmlFree(prev);
3710	} while (annot != NULL);
3711    }
3712}
3713
3714/**
3715 * xmlSchemaFreeNotation:
3716 * @schema:  a schema notation structure
3717 *
3718 * Deallocate a Schema Notation structure.
3719 */
3720static void
3721xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3722{
3723    if (nota == NULL)
3724        return;
3725    xmlFree(nota);
3726}
3727
3728/**
3729 * xmlSchemaFreeAttribute:
3730 * @attr:  an attribute declaration
3731 *
3732 * Deallocates an attribute declaration structure.
3733 */
3734static void
3735xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3736{
3737    if (attr == NULL)
3738        return;
3739    if (attr->annot != NULL)
3740	xmlSchemaFreeAnnot(attr->annot);
3741    if (attr->defVal != NULL)
3742	xmlSchemaFreeValue(attr->defVal);
3743    xmlFree(attr);
3744}
3745
3746/**
3747 * xmlSchemaFreeAttributeUse:
3748 * @use:  an attribute use
3749 *
3750 * Deallocates an attribute use structure.
3751 */
3752static void
3753xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3754{
3755    if (use == NULL)
3756        return;
3757    if (use->annot != NULL)
3758	xmlSchemaFreeAnnot(use->annot);
3759    if (use->defVal != NULL)
3760	xmlSchemaFreeValue(use->defVal);
3761    xmlFree(use);
3762}
3763
3764/**
3765 * xmlSchemaFreeAttributeUseProhib:
3766 * @prohib:  an attribute use prohibition
3767 *
3768 * Deallocates an attribute use structure.
3769 */
3770static void
3771xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3772{
3773    if (prohib == NULL)
3774        return;
3775    xmlFree(prohib);
3776}
3777
3778/**
3779 * xmlSchemaFreeWildcardNsSet:
3780 * set:  a schema wildcard namespace
3781 *
3782 * Deallocates a list of wildcard constraint structures.
3783 */
3784static void
3785xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3786{
3787    xmlSchemaWildcardNsPtr next;
3788
3789    while (set != NULL) {
3790	next = set->next;
3791	xmlFree(set);
3792	set = next;
3793    }
3794}
3795
3796/**
3797 * xmlSchemaFreeWildcard:
3798 * @wildcard:  a wildcard structure
3799 *
3800 * Deallocates a wildcard structure.
3801 */
3802void
3803xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3804{
3805    if (wildcard == NULL)
3806        return;
3807    if (wildcard->annot != NULL)
3808        xmlSchemaFreeAnnot(wildcard->annot);
3809    if (wildcard->nsSet != NULL)
3810	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3811    if (wildcard->negNsSet != NULL)
3812	xmlFree(wildcard->negNsSet);
3813    xmlFree(wildcard);
3814}
3815
3816/**
3817 * xmlSchemaFreeAttributeGroup:
3818 * @schema:  a schema attribute group structure
3819 *
3820 * Deallocate a Schema Attribute Group structure.
3821 */
3822static void
3823xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3824{
3825    if (attrGr == NULL)
3826        return;
3827    if (attrGr->annot != NULL)
3828        xmlSchemaFreeAnnot(attrGr->annot);
3829    if (attrGr->attrUses != NULL)
3830	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3831    xmlFree(attrGr);
3832}
3833
3834/**
3835 * xmlSchemaFreeQNameRef:
3836 * @item: a QName reference structure
3837 *
3838 * Deallocatea a QName reference structure.
3839 */
3840static void
3841xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3842{
3843    xmlFree(item);
3844}
3845
3846/**
3847 * xmlSchemaFreeTypeLinkList:
3848 * @alink: a type link
3849 *
3850 * Deallocate a list of types.
3851 */
3852static void
3853xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3854{
3855    xmlSchemaTypeLinkPtr next;
3856
3857    while (link != NULL) {
3858	next = link->next;
3859	xmlFree(link);
3860	link = next;
3861    }
3862}
3863
3864static void
3865xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3866{
3867    xmlSchemaIDCStateObjPtr next;
3868    while (sto != NULL) {
3869	next = sto->next;
3870	if (sto->history != NULL)
3871	    xmlFree(sto->history);
3872	if (sto->xpathCtxt != NULL)
3873	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3874	xmlFree(sto);
3875	sto = next;
3876    }
3877}
3878
3879/**
3880 * xmlSchemaFreeIDC:
3881 * @idc: a identity-constraint definition
3882 *
3883 * Deallocates an identity-constraint definition.
3884 */
3885static void
3886xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3887{
3888    xmlSchemaIDCSelectPtr cur, prev;
3889
3890    if (idcDef == NULL)
3891	return;
3892    if (idcDef->annot != NULL)
3893        xmlSchemaFreeAnnot(idcDef->annot);
3894    /* Selector */
3895    if (idcDef->selector != NULL) {
3896	if (idcDef->selector->xpathComp != NULL)
3897	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3898	xmlFree(idcDef->selector);
3899    }
3900    /* Fields */
3901    if (idcDef->fields != NULL) {
3902	cur = idcDef->fields;
3903	do {
3904	    prev = cur;
3905	    cur = cur->next;
3906	    if (prev->xpathComp != NULL)
3907		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3908	    xmlFree(prev);
3909	} while (cur != NULL);
3910    }
3911    xmlFree(idcDef);
3912}
3913
3914/**
3915 * xmlSchemaFreeElement:
3916 * @schema:  a schema element structure
3917 *
3918 * Deallocate a Schema Element structure.
3919 */
3920static void
3921xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3922{
3923    if (elem == NULL)
3924        return;
3925    if (elem->annot != NULL)
3926        xmlSchemaFreeAnnot(elem->annot);
3927    if (elem->contModel != NULL)
3928        xmlRegFreeRegexp(elem->contModel);
3929    if (elem->defVal != NULL)
3930	xmlSchemaFreeValue(elem->defVal);
3931    xmlFree(elem);
3932}
3933
3934/**
3935 * xmlSchemaFreeFacet:
3936 * @facet:  a schema facet structure
3937 *
3938 * Deallocate a Schema Facet structure.
3939 */
3940void
3941xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3942{
3943    if (facet == NULL)
3944        return;
3945    if (facet->val != NULL)
3946        xmlSchemaFreeValue(facet->val);
3947    if (facet->regexp != NULL)
3948        xmlRegFreeRegexp(facet->regexp);
3949    if (facet->annot != NULL)
3950        xmlSchemaFreeAnnot(facet->annot);
3951    xmlFree(facet);
3952}
3953
3954/**
3955 * xmlSchemaFreeType:
3956 * @type:  a schema type structure
3957 *
3958 * Deallocate a Schema Type structure.
3959 */
3960void
3961xmlSchemaFreeType(xmlSchemaTypePtr type)
3962{
3963    if (type == NULL)
3964        return;
3965    if (type->annot != NULL)
3966        xmlSchemaFreeAnnot(type->annot);
3967    if (type->facets != NULL) {
3968        xmlSchemaFacetPtr facet, next;
3969
3970        facet = type->facets;
3971        while (facet != NULL) {
3972            next = facet->next;
3973            xmlSchemaFreeFacet(facet);
3974            facet = next;
3975        }
3976    }
3977    if (type->attrUses != NULL)
3978	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3979    if (type->memberTypes != NULL)
3980	xmlSchemaFreeTypeLinkList(type->memberTypes);
3981    if (type->facetSet != NULL) {
3982	xmlSchemaFacetLinkPtr next, link;
3983
3984	link = type->facetSet;
3985	do {
3986	    next = link->next;
3987	    xmlFree(link);
3988	    link = next;
3989	} while (link != NULL);
3990    }
3991    if (type->contModel != NULL)
3992        xmlRegFreeRegexp(type->contModel);
3993    xmlFree(type);
3994}
3995
3996/**
3997 * xmlSchemaFreeModelGroupDef:
3998 * @item:  a schema model group definition
3999 *
4000 * Deallocates a schema model group definition.
4001 */
4002static void
4003xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4004{
4005    if (item->annot != NULL)
4006	xmlSchemaFreeAnnot(item->annot);
4007    xmlFree(item);
4008}
4009
4010/**
4011 * xmlSchemaFreeModelGroup:
4012 * @item:  a schema model group
4013 *
4014 * Deallocates a schema model group structure.
4015 */
4016static void
4017xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4018{
4019    if (item->annot != NULL)
4020	xmlSchemaFreeAnnot(item->annot);
4021    xmlFree(item);
4022}
4023
4024static void
4025xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4026{
4027    if ((list == NULL) || (list->nbItems == 0))
4028	return;
4029    {
4030	xmlSchemaTreeItemPtr item;
4031	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4032	int i;
4033
4034	for (i = 0; i < list->nbItems; i++) {
4035	    item = items[i];
4036	    if (item == NULL)
4037		continue;
4038	    switch (item->type) {
4039		case XML_SCHEMA_TYPE_SIMPLE:
4040		case XML_SCHEMA_TYPE_COMPLEX:
4041		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4042		    break;
4043		case XML_SCHEMA_TYPE_ATTRIBUTE:
4044		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4045		    break;
4046		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4047		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4048		    break;
4049		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4050		    xmlSchemaFreeAttributeUseProhib(
4051			(xmlSchemaAttributeUseProhibPtr) item);
4052		    break;
4053		case XML_SCHEMA_TYPE_ELEMENT:
4054		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4055		    break;
4056		case XML_SCHEMA_TYPE_PARTICLE:
4057		    if (item->annot != NULL)
4058			xmlSchemaFreeAnnot(item->annot);
4059		    xmlFree(item);
4060		    break;
4061		case XML_SCHEMA_TYPE_SEQUENCE:
4062		case XML_SCHEMA_TYPE_CHOICE:
4063		case XML_SCHEMA_TYPE_ALL:
4064		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4065		    break;
4066		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4067		    xmlSchemaFreeAttributeGroup(
4068			(xmlSchemaAttributeGroupPtr) item);
4069		    break;
4070		case XML_SCHEMA_TYPE_GROUP:
4071		    xmlSchemaFreeModelGroupDef(
4072			(xmlSchemaModelGroupDefPtr) item);
4073		    break;
4074		case XML_SCHEMA_TYPE_ANY:
4075		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4076		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4077		    break;
4078		case XML_SCHEMA_TYPE_IDC_KEY:
4079		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4080		case XML_SCHEMA_TYPE_IDC_KEYREF:
4081		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4082		    break;
4083		case XML_SCHEMA_TYPE_NOTATION:
4084		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4085		    break;
4086		case XML_SCHEMA_EXTRA_QNAMEREF:
4087		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4088		    break;
4089		default: {
4090		    /* TODO: This should never be hit. */
4091		    xmlSchemaPSimpleInternalErr(NULL,
4092			"Internal error: xmlSchemaComponentListFree, "
4093			"unexpected component type '%s'\n",
4094			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4095			 }
4096		    break;
4097	    }
4098	}
4099	list->nbItems = 0;
4100    }
4101}
4102
4103/**
4104 * xmlSchemaFree:
4105 * @schema:  a schema structure
4106 *
4107 * Deallocate a Schema structure.
4108 */
4109void
4110xmlSchemaFree(xmlSchemaPtr schema)
4111{
4112    if (schema == NULL)
4113        return;
4114    /* @volatiles is not used anymore :-/ */
4115    if (schema->volatiles != NULL)
4116	TODO
4117    /*
4118    * Note that those slots are not responsible for freeing
4119    * schema components anymore; this will now be done by
4120    * the schema buckets.
4121    */
4122    if (schema->notaDecl != NULL)
4123        xmlHashFree(schema->notaDecl, NULL);
4124    if (schema->attrDecl != NULL)
4125        xmlHashFree(schema->attrDecl, NULL);
4126    if (schema->attrgrpDecl != NULL)
4127        xmlHashFree(schema->attrgrpDecl, NULL);
4128    if (schema->elemDecl != NULL)
4129        xmlHashFree(schema->elemDecl, NULL);
4130    if (schema->typeDecl != NULL)
4131        xmlHashFree(schema->typeDecl, NULL);
4132    if (schema->groupDecl != NULL)
4133        xmlHashFree(schema->groupDecl, NULL);
4134    if (schema->idcDef != NULL)
4135        xmlHashFree(schema->idcDef, NULL);
4136
4137    if (schema->schemasImports != NULL)
4138	xmlHashFree(schema->schemasImports,
4139		    (xmlHashDeallocator) xmlSchemaBucketFree);
4140    if (schema->includes != NULL) {
4141	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4142	int i;
4143	for (i = 0; i < list->nbItems; i++) {
4144	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4145	}
4146	xmlSchemaItemListFree(list);
4147    }
4148    if (schema->annot != NULL)
4149        xmlSchemaFreeAnnot(schema->annot);
4150    /* Never free the doc here, since this will be done by the buckets. */
4151
4152    xmlDictFree(schema->dict);
4153    xmlFree(schema);
4154}
4155
4156/************************************************************************
4157 *									*
4158 *			Debug functions					*
4159 *									*
4160 ************************************************************************/
4161
4162#ifdef LIBXML_OUTPUT_ENABLED
4163
4164static void
4165xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4166
4167/**
4168 * xmlSchemaElementDump:
4169 * @elem:  an element
4170 * @output:  the file output
4171 *
4172 * Dump the element
4173 */
4174static void
4175xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4176                     const xmlChar * name ATTRIBUTE_UNUSED,
4177		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4178                     const xmlChar * context ATTRIBUTE_UNUSED)
4179{
4180    if (elem == NULL)
4181        return;
4182
4183
4184    fprintf(output, "Element");
4185    if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4186	fprintf(output, " (global)");
4187    fprintf(output, ": '%s' ", elem->name);
4188    if (namespace != NULL)
4189	fprintf(output, "ns '%s'", namespace);
4190    fprintf(output, "\n");
4191#if 0
4192    if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4193	fprintf(output, "  min %d ", elem->minOccurs);
4194        if (elem->maxOccurs >= UNBOUNDED)
4195            fprintf(output, "max: unbounded\n");
4196        else if (elem->maxOccurs != 1)
4197            fprintf(output, "max: %d\n", elem->maxOccurs);
4198        else
4199            fprintf(output, "\n");
4200    }
4201#endif
4202    /*
4203    * Misc other properties.
4204    */
4205    if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4206	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4207	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4208	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4209	fprintf(output, "  props: ");
4210	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4211	    fprintf(output, "[fixed] ");
4212	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4213	    fprintf(output, "[default] ");
4214	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4215	    fprintf(output, "[abstract] ");
4216	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4217	    fprintf(output, "[nillable] ");
4218	fprintf(output, "\n");
4219    }
4220    /*
4221    * Default/fixed value.
4222    */
4223    if (elem->value != NULL)
4224	fprintf(output, "  value: '%s'\n", elem->value);
4225    /*
4226    * Type.
4227    */
4228    if (elem->namedType != NULL) {
4229	fprintf(output, "  type: '%s' ", elem->namedType);
4230	if (elem->namedTypeNs != NULL)
4231	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4232	else
4233	    fprintf(output, "\n");
4234    } else if (elem->subtypes != NULL) {
4235	/*
4236	* Dump local types.
4237	*/
4238	xmlSchemaTypeDump(elem->subtypes, output);
4239    }
4240    /*
4241    * Substitution group.
4242    */
4243    if (elem->substGroup != NULL) {
4244	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4245	if (elem->substGroupNs != NULL)
4246	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4247	else
4248	    fprintf(output, "\n");
4249    }
4250}
4251
4252/**
4253 * xmlSchemaAnnotDump:
4254 * @output:  the file output
4255 * @annot:  a annotation
4256 *
4257 * Dump the annotation
4258 */
4259static void
4260xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4261{
4262    xmlChar *content;
4263
4264    if (annot == NULL)
4265        return;
4266
4267    content = xmlNodeGetContent(annot->content);
4268    if (content != NULL) {
4269        fprintf(output, "  Annot: %s\n", content);
4270        xmlFree(content);
4271    } else
4272        fprintf(output, "  Annot: empty\n");
4273}
4274
4275/**
4276 * xmlSchemaContentModelDump:
4277 * @particle: the schema particle
4278 * @output: the file output
4279 * @depth: the depth used for intentation
4280 *
4281 * Dump a SchemaType structure
4282 */
4283static void
4284xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4285{
4286    xmlChar *str = NULL;
4287    xmlSchemaTreeItemPtr term;
4288    char shift[100];
4289    int i;
4290
4291    if (particle == NULL)
4292	return;
4293    for (i = 0;((i < depth) && (i < 25));i++)
4294        shift[2 * i] = shift[2 * i + 1] = ' ';
4295    shift[2 * i] = shift[2 * i + 1] = 0;
4296    fprintf(output, "%s", shift);
4297    if (particle->children == NULL) {
4298	fprintf(output, "MISSING particle term\n");
4299	return;
4300    }
4301    term = particle->children;
4302    if (term == NULL) {
4303	fprintf(output, "(NULL)");
4304    } else {
4305	switch (term->type) {
4306	    case XML_SCHEMA_TYPE_ELEMENT:
4307		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4308		    ((xmlSchemaElementPtr)term)->targetNamespace,
4309		    ((xmlSchemaElementPtr)term)->name));
4310		FREE_AND_NULL(str);
4311		break;
4312	    case XML_SCHEMA_TYPE_SEQUENCE:
4313		fprintf(output, "SEQUENCE");
4314		break;
4315	    case XML_SCHEMA_TYPE_CHOICE:
4316		fprintf(output, "CHOICE");
4317		break;
4318	    case XML_SCHEMA_TYPE_ALL:
4319		fprintf(output, "ALL");
4320		break;
4321	    case XML_SCHEMA_TYPE_ANY:
4322		fprintf(output, "ANY");
4323		break;
4324	    default:
4325		fprintf(output, "UNKNOWN\n");
4326		return;
4327	}
4328    }
4329    if (particle->minOccurs != 1)
4330	fprintf(output, " min: %d", particle->minOccurs);
4331    if (particle->maxOccurs >= UNBOUNDED)
4332	fprintf(output, " max: unbounded");
4333    else if (particle->maxOccurs != 1)
4334	fprintf(output, " max: %d", particle->maxOccurs);
4335    fprintf(output, "\n");
4336    if (term &&
4337	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4338	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4339	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4340	 (term->children != NULL)) {
4341	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4342	    output, depth +1);
4343    }
4344    if (particle->next != NULL)
4345	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4346		output, depth);
4347}
4348
4349/**
4350 * xmlSchemaAttrUsesDump:
4351 * @uses:  attribute uses list
4352 * @output:  the file output
4353 *
4354 * Dumps a list of attribute use components.
4355 */
4356static void
4357xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4358{
4359    xmlSchemaAttributeUsePtr use;
4360    xmlSchemaAttributeUseProhibPtr prohib;
4361    xmlSchemaQNameRefPtr ref;
4362    const xmlChar *name, *tns;
4363    xmlChar *str = NULL;
4364    int i;
4365
4366    if ((uses == NULL) || (uses->nbItems == 0))
4367        return;
4368
4369    fprintf(output, "  attributes:\n");
4370    for (i = 0; i < uses->nbItems; i++) {
4371	use = uses->items[i];
4372	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4373	    fprintf(output, "  [prohibition] ");
4374	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4375	    name = prohib->name;
4376	    tns = prohib->targetNamespace;
4377	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4378	    fprintf(output, "  [reference] ");
4379	    ref = (xmlSchemaQNameRefPtr) use;
4380	    name = ref->name;
4381	    tns = ref->targetNamespace;
4382	} else {
4383	    fprintf(output, "  [use] ");
4384	    name = WXS_ATTRUSE_DECL_NAME(use);
4385	    tns = WXS_ATTRUSE_DECL_TNS(use);
4386	}
4387	fprintf(output, "'%s'\n",
4388	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4389	FREE_AND_NULL(str);
4390    }
4391}
4392
4393/**
4394 * xmlSchemaTypeDump:
4395 * @output:  the file output
4396 * @type:  a type structure
4397 *
4398 * Dump a SchemaType structure
4399 */
4400static void
4401xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4402{
4403    if (type == NULL) {
4404        fprintf(output, "Type: NULL\n");
4405        return;
4406    }
4407    fprintf(output, "Type: ");
4408    if (type->name != NULL)
4409        fprintf(output, "'%s' ", type->name);
4410    else
4411        fprintf(output, "(no name) ");
4412    if (type->targetNamespace != NULL)
4413	fprintf(output, "ns '%s' ", type->targetNamespace);
4414    switch (type->type) {
4415        case XML_SCHEMA_TYPE_BASIC:
4416            fprintf(output, "[basic] ");
4417            break;
4418        case XML_SCHEMA_TYPE_SIMPLE:
4419            fprintf(output, "[simple] ");
4420            break;
4421        case XML_SCHEMA_TYPE_COMPLEX:
4422            fprintf(output, "[complex] ");
4423            break;
4424        case XML_SCHEMA_TYPE_SEQUENCE:
4425            fprintf(output, "[sequence] ");
4426            break;
4427        case XML_SCHEMA_TYPE_CHOICE:
4428            fprintf(output, "[choice] ");
4429            break;
4430        case XML_SCHEMA_TYPE_ALL:
4431            fprintf(output, "[all] ");
4432            break;
4433        case XML_SCHEMA_TYPE_UR:
4434            fprintf(output, "[ur] ");
4435            break;
4436        case XML_SCHEMA_TYPE_RESTRICTION:
4437            fprintf(output, "[restriction] ");
4438            break;
4439        case XML_SCHEMA_TYPE_EXTENSION:
4440            fprintf(output, "[extension] ");
4441            break;
4442        default:
4443            fprintf(output, "[unknown type %d] ", type->type);
4444            break;
4445    }
4446    fprintf(output, "content: ");
4447    switch (type->contentType) {
4448        case XML_SCHEMA_CONTENT_UNKNOWN:
4449            fprintf(output, "[unknown] ");
4450            break;
4451        case XML_SCHEMA_CONTENT_EMPTY:
4452            fprintf(output, "[empty] ");
4453            break;
4454        case XML_SCHEMA_CONTENT_ELEMENTS:
4455            fprintf(output, "[element] ");
4456            break;
4457        case XML_SCHEMA_CONTENT_MIXED:
4458            fprintf(output, "[mixed] ");
4459            break;
4460        case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4461	/* not used. */
4462            break;
4463        case XML_SCHEMA_CONTENT_BASIC:
4464            fprintf(output, "[basic] ");
4465            break;
4466        case XML_SCHEMA_CONTENT_SIMPLE:
4467            fprintf(output, "[simple] ");
4468            break;
4469        case XML_SCHEMA_CONTENT_ANY:
4470            fprintf(output, "[any] ");
4471            break;
4472    }
4473    fprintf(output, "\n");
4474    if (type->base != NULL) {
4475        fprintf(output, "  base type: '%s'", type->base);
4476	if (type->baseNs != NULL)
4477	    fprintf(output, " ns '%s'\n", type->baseNs);
4478	else
4479	    fprintf(output, "\n");
4480    }
4481    if (type->attrUses != NULL)
4482	xmlSchemaAttrUsesDump(type->attrUses, output);
4483    if (type->annot != NULL)
4484        xmlSchemaAnnotDump(output, type->annot);
4485#ifdef DUMP_CONTENT_MODEL
4486    if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4487	(type->subtypes != NULL)) {
4488	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4489	    output, 1);
4490    }
4491#endif
4492}
4493
4494/**
4495 * xmlSchemaDump:
4496 * @output:  the file output
4497 * @schema:  a schema structure
4498 *
4499 * Dump a Schema structure.
4500 */
4501void
4502xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4503{
4504    if (output == NULL)
4505        return;
4506    if (schema == NULL) {
4507        fprintf(output, "Schemas: NULL\n");
4508        return;
4509    }
4510    fprintf(output, "Schemas: ");
4511    if (schema->name != NULL)
4512        fprintf(output, "%s, ", schema->name);
4513    else
4514        fprintf(output, "no name, ");
4515    if (schema->targetNamespace != NULL)
4516        fprintf(output, "%s", (const char *) schema->targetNamespace);
4517    else
4518        fprintf(output, "no target namespace");
4519    fprintf(output, "\n");
4520    if (schema->annot != NULL)
4521        xmlSchemaAnnotDump(output, schema->annot);
4522    xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4523                output);
4524    xmlHashScanFull(schema->elemDecl,
4525                    (xmlHashScannerFull) xmlSchemaElementDump, output);
4526}
4527
4528#ifdef DEBUG_IDC_NODE_TABLE
4529/**
4530 * xmlSchemaDebugDumpIDCTable:
4531 * @vctxt: the WXS validation context
4532 *
4533 * Displays the current IDC table for debug purposes.
4534 */
4535static void
4536xmlSchemaDebugDumpIDCTable(FILE * output,
4537			   const xmlChar *namespaceName,
4538			   const xmlChar *localName,
4539			   xmlSchemaPSVIIDCBindingPtr bind)
4540{
4541    xmlChar *str = NULL;
4542    const xmlChar *value;
4543    xmlSchemaPSVIIDCNodePtr tab;
4544    xmlSchemaPSVIIDCKeyPtr key;
4545    int i, j, res;
4546
4547    fprintf(output, "IDC: TABLES on '%s'\n",
4548	xmlSchemaFormatQName(&str, namespaceName, localName));
4549    FREE_AND_NULL(str)
4550
4551    if (bind == NULL)
4552	return;
4553    do {
4554	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4555	    xmlSchemaGetComponentQName(&str,
4556		bind->definition), bind->nbNodes);
4557	FREE_AND_NULL(str)
4558	for (i = 0; i < bind->nbNodes; i++) {
4559	    tab = bind->nodeTable[i];
4560	    fprintf(output, "         ( ");
4561	    for (j = 0; j < bind->definition->nbFields; j++) {
4562		key = tab->keys[j];
4563		if ((key != NULL) && (key->val != NULL)) {
4564		    res = xmlSchemaGetCanonValue(key->val, &value);
4565		    if (res >= 0)
4566			fprintf(output, "'%s' ", value);
4567		    else
4568			fprintf(output, "CANON-VALUE-FAILED ");
4569		    if (res == 0)
4570			FREE_AND_NULL(value)
4571		} else if (key != NULL)
4572		    fprintf(output, "(no val), ");
4573		else
4574		    fprintf(output, "(key missing), ");
4575	    }
4576	    fprintf(output, ")\n");
4577	}
4578	if (bind->dupls && bind->dupls->nbItems) {
4579	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4580	    for (i = 0; i < bind->dupls->nbItems; i++) {
4581		tab = bind->dupls->items[i];
4582		fprintf(output, "         ( ");
4583		for (j = 0; j < bind->definition->nbFields; j++) {
4584		    key = tab->keys[j];
4585		    if ((key != NULL) && (key->val != NULL)) {
4586			res = xmlSchemaGetCanonValue(key->val, &value);
4587			if (res >= 0)
4588			    fprintf(output, "'%s' ", value);
4589			else
4590			    fprintf(output, "CANON-VALUE-FAILED ");
4591			if (res == 0)
4592			    FREE_AND_NULL(value)
4593		    } else if (key != NULL)
4594		    fprintf(output, "(no val), ");
4595			else
4596			    fprintf(output, "(key missing), ");
4597		}
4598		fprintf(output, ")\n");
4599	    }
4600	}
4601	bind = bind->next;
4602    } while (bind != NULL);
4603}
4604#endif /* DEBUG_IDC */
4605#endif /* LIBXML_OUTPUT_ENABLED */
4606
4607/************************************************************************
4608 *									*
4609 *			Utilities					*
4610 *									*
4611 ************************************************************************/
4612
4613/**
4614 * xmlSchemaGetPropNode:
4615 * @node: the element node
4616 * @name: the name of the attribute
4617 *
4618 * Seeks an attribute with a name of @name in
4619 * no namespace.
4620 *
4621 * Returns the attribute or NULL if not present.
4622 */
4623static xmlAttrPtr
4624xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4625{
4626    xmlAttrPtr prop;
4627
4628    if ((node == NULL) || (name == NULL))
4629	return(NULL);
4630    prop = node->properties;
4631    while (prop != NULL) {
4632        if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4633	    return(prop);
4634	prop = prop->next;
4635    }
4636    return (NULL);
4637}
4638
4639/**
4640 * xmlSchemaGetPropNodeNs:
4641 * @node: the element node
4642 * @uri: the uri
4643 * @name: the name of the attribute
4644 *
4645 * Seeks an attribute with a local name of @name and
4646 * a namespace URI of @uri.
4647 *
4648 * Returns the attribute or NULL if not present.
4649 */
4650static xmlAttrPtr
4651xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4652{
4653    xmlAttrPtr prop;
4654
4655    if ((node == NULL) || (name == NULL))
4656	return(NULL);
4657    prop = node->properties;
4658    while (prop != NULL) {
4659	if ((prop->ns != NULL) &&
4660	    xmlStrEqual(prop->name, BAD_CAST name) &&
4661	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4662	    return(prop);
4663	prop = prop->next;
4664    }
4665    return (NULL);
4666}
4667
4668static const xmlChar *
4669xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4670{
4671    xmlChar *val;
4672    const xmlChar *ret;
4673
4674    val = xmlNodeGetContent(node);
4675    if (val == NULL)
4676	val = xmlStrdup((xmlChar *)"");
4677    ret = xmlDictLookup(ctxt->dict, val, -1);
4678    xmlFree(val);
4679    return(ret);
4680}
4681
4682static const xmlChar *
4683xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4684{
4685    return((const xmlChar*) xmlNodeGetContent(node));
4686}
4687
4688/**
4689 * xmlSchemaGetProp:
4690 * @ctxt: the parser context
4691 * @node: the node
4692 * @name: the property name
4693 *
4694 * Read a attribute value and internalize the string
4695 *
4696 * Returns the string or NULL if not present.
4697 */
4698static const xmlChar *
4699xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4700                 const char *name)
4701{
4702    xmlChar *val;
4703    const xmlChar *ret;
4704
4705    val = xmlGetNoNsProp(node, BAD_CAST name);
4706    if (val == NULL)
4707        return(NULL);
4708    ret = xmlDictLookup(ctxt->dict, val, -1);
4709    xmlFree(val);
4710    return(ret);
4711}
4712
4713/************************************************************************
4714 *									*
4715 *			Parsing functions				*
4716 *									*
4717 ************************************************************************/
4718
4719#define WXS_FIND_GLOBAL_ITEM(slot)			\
4720    if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4721	ret = xmlHashLookup(schema->slot, name); \
4722	if (ret != NULL) goto exit; \
4723    } \
4724    if (xmlHashSize(schema->schemasImports) > 1) { \
4725	xmlSchemaImportPtr import; \
4726	if (nsName == NULL) \
4727	    import = xmlHashLookup(schema->schemasImports, \
4728		XML_SCHEMAS_NO_NAMESPACE); \
4729	else \
4730	    import = xmlHashLookup(schema->schemasImports, nsName); \
4731	if (import == NULL) \
4732	    goto exit; \
4733	ret = xmlHashLookup(import->schema->slot, name); \
4734    }
4735
4736/**
4737 * xmlSchemaGetElem:
4738 * @schema:  the schema context
4739 * @name:  the element name
4740 * @ns:  the element namespace
4741 *
4742 * Lookup a global element declaration in the schema.
4743 *
4744 * Returns the element declaration or NULL if not found.
4745 */
4746static xmlSchemaElementPtr
4747xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4748                 const xmlChar * nsName)
4749{
4750    xmlSchemaElementPtr ret = NULL;
4751
4752    if ((name == NULL) || (schema == NULL))
4753        return(NULL);
4754    if (schema != NULL) {
4755	WXS_FIND_GLOBAL_ITEM(elemDecl)
4756    }
4757exit:
4758#ifdef DEBUG
4759    if (ret == NULL) {
4760        if (nsName == NULL)
4761            fprintf(stderr, "Unable to lookup element decl. %s", name);
4762        else
4763            fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4764                    nsName);
4765    }
4766#endif
4767    return (ret);
4768}
4769
4770/**
4771 * xmlSchemaGetType:
4772 * @schema:  the main schema
4773 * @name:  the type's name
4774 * nsName:  the type's namespace
4775 *
4776 * Lookup a type in the schemas or the predefined types
4777 *
4778 * Returns the group definition or NULL if not found.
4779 */
4780static xmlSchemaTypePtr
4781xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4782                 const xmlChar * nsName)
4783{
4784    xmlSchemaTypePtr ret = NULL;
4785
4786    if (name == NULL)
4787        return (NULL);
4788    /* First try the built-in types. */
4789    if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4790	ret = xmlSchemaGetPredefinedType(name, nsName);
4791	if (ret != NULL)
4792	    goto exit;
4793	/*
4794	* Note that we try the parsed schemas as well here
4795	* since one might have parsed the S4S, which contain more
4796	* than the built-in types.
4797	* TODO: Can we optimize this?
4798	*/
4799    }
4800    if (schema != NULL) {
4801	WXS_FIND_GLOBAL_ITEM(typeDecl)
4802    }
4803exit:
4804
4805#ifdef DEBUG
4806    if (ret == NULL) {
4807        if (nsName == NULL)
4808            fprintf(stderr, "Unable to lookup type %s", name);
4809        else
4810            fprintf(stderr, "Unable to lookup type %s:%s", name,
4811                    nsName);
4812    }
4813#endif
4814    return (ret);
4815}
4816
4817/**
4818 * xmlSchemaGetAttributeDecl:
4819 * @schema:  the context of the schema
4820 * @name:  the name of the attribute
4821 * @ns:  the target namespace of the attribute
4822 *
4823 * Lookup a an attribute in the schema or imported schemas
4824 *
4825 * Returns the attribute declaration or NULL if not found.
4826 */
4827static xmlSchemaAttributePtr
4828xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4829                 const xmlChar * nsName)
4830{
4831    xmlSchemaAttributePtr ret = NULL;
4832
4833    if ((name == NULL) || (schema == NULL))
4834        return (NULL);
4835    if (schema != NULL) {
4836	WXS_FIND_GLOBAL_ITEM(attrDecl)
4837    }
4838exit:
4839#ifdef DEBUG
4840    if (ret == NULL) {
4841        if (nsName == NULL)
4842            fprintf(stderr, "Unable to lookup attribute %s", name);
4843        else
4844            fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4845                    nsName);
4846    }
4847#endif
4848    return (ret);
4849}
4850
4851/**
4852 * xmlSchemaGetAttributeGroup:
4853 * @schema:  the context of the schema
4854 * @name:  the name of the attribute group
4855 * @ns:  the target namespace of the attribute group
4856 *
4857 * Lookup a an attribute group in the schema or imported schemas
4858 *
4859 * Returns the attribute group definition or NULL if not found.
4860 */
4861static xmlSchemaAttributeGroupPtr
4862xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4863                 const xmlChar * nsName)
4864{
4865    xmlSchemaAttributeGroupPtr ret = NULL;
4866
4867    if ((name == NULL) || (schema == NULL))
4868        return (NULL);
4869    if (schema != NULL) {
4870	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4871    }
4872exit:
4873    /* TODO:
4874    if ((ret != NULL) && (ret->redef != NULL)) {
4875	* Return the last redefinition. *
4876	ret = ret->redef;
4877    }
4878    */
4879#ifdef DEBUG
4880    if (ret == NULL) {
4881        if (nsName == NULL)
4882            fprintf(stderr, "Unable to lookup attribute group %s", name);
4883        else
4884            fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4885                    nsName);
4886    }
4887#endif
4888    return (ret);
4889}
4890
4891/**
4892 * xmlSchemaGetGroup:
4893 * @schema:  the context of the schema
4894 * @name:  the name of the group
4895 * @ns:  the target namespace of the group
4896 *
4897 * Lookup a group in the schema or imported schemas
4898 *
4899 * Returns the group definition or NULL if not found.
4900 */
4901static xmlSchemaModelGroupDefPtr
4902xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4903                 const xmlChar * nsName)
4904{
4905    xmlSchemaModelGroupDefPtr ret = NULL;
4906
4907    if ((name == NULL) || (schema == NULL))
4908        return (NULL);
4909    if (schema != NULL) {
4910	WXS_FIND_GLOBAL_ITEM(groupDecl)
4911    }
4912exit:
4913
4914#ifdef DEBUG
4915    if (ret == NULL) {
4916        if (nsName == NULL)
4917            fprintf(stderr, "Unable to lookup group %s", name);
4918        else
4919            fprintf(stderr, "Unable to lookup group %s:%s", name,
4920                    nsName);
4921    }
4922#endif
4923    return (ret);
4924}
4925
4926static xmlSchemaNotationPtr
4927xmlSchemaGetNotation(xmlSchemaPtr schema,
4928		     const xmlChar *name,
4929		     const xmlChar *nsName)
4930{
4931    xmlSchemaNotationPtr ret = NULL;
4932
4933    if ((name == NULL) || (schema == NULL))
4934        return (NULL);
4935    if (schema != NULL) {
4936	WXS_FIND_GLOBAL_ITEM(notaDecl)
4937    }
4938exit:
4939    return (ret);
4940}
4941
4942static xmlSchemaIDCPtr
4943xmlSchemaGetIDC(xmlSchemaPtr schema,
4944		const xmlChar *name,
4945		const xmlChar *nsName)
4946{
4947    xmlSchemaIDCPtr ret = NULL;
4948
4949    if ((name == NULL) || (schema == NULL))
4950        return (NULL);
4951    if (schema != NULL) {
4952	WXS_FIND_GLOBAL_ITEM(idcDef)
4953    }
4954exit:
4955    return (ret);
4956}
4957
4958/**
4959 * xmlSchemaGetNamedComponent:
4960 * @schema:  the schema
4961 * @name:  the name of the group
4962 * @ns:  the target namespace of the group
4963 *
4964 * Lookup a group in the schema or imported schemas
4965 *
4966 * Returns the group definition or NULL if not found.
4967 */
4968static xmlSchemaBasicItemPtr
4969xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4970			   xmlSchemaTypeType itemType,
4971			   const xmlChar *name,
4972			   const xmlChar *targetNs)
4973{
4974    switch (itemType) {
4975	case XML_SCHEMA_TYPE_GROUP:
4976	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4977		name, targetNs));
4978	case XML_SCHEMA_TYPE_ELEMENT:
4979	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4980		name, targetNs));
4981	default:
4982	    TODO
4983	    return (NULL);
4984    }
4985}
4986
4987/************************************************************************
4988 *									*
4989 *			Parsing functions				*
4990 *									*
4991 ************************************************************************/
4992
4993#define IS_BLANK_NODE(n)						\
4994    (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4995
4996/**
4997 * xmlSchemaIsBlank:
4998 * @str:  a string
4999 * @len: the length of the string or -1
5000 *
5001 * Check if a string is ignorable
5002 *
5003 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5004 */
5005static int
5006xmlSchemaIsBlank(xmlChar * str, int len)
5007{
5008    if (str == NULL)
5009        return (1);
5010    if (len < 0) {
5011	while (*str != 0) {
5012	    if (!(IS_BLANK_CH(*str)))
5013		return (0);
5014	    str++;
5015	}
5016    } else while ((*str != 0) && (len != 0)) {
5017	if (!(IS_BLANK_CH(*str)))
5018	    return (0);
5019	str++;
5020	len--;
5021    }
5022
5023    return (1);
5024}
5025
5026#define WXS_COMP_NAME(c, t) ((t) (c))->name
5027#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5028/*
5029* xmlSchemaFindRedefCompInGraph:
5030* ATTENTION TODO: This uses pointer comp. for strings.
5031*/
5032static xmlSchemaBasicItemPtr
5033xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5034			      xmlSchemaTypeType type,
5035			      const xmlChar *name,
5036			      const xmlChar *nsName)
5037{
5038    xmlSchemaBasicItemPtr ret;
5039    int i;
5040
5041    if ((bucket == NULL) || (name == NULL))
5042	return(NULL);
5043    if ((bucket->globals == NULL) ||
5044	(bucket->globals->nbItems == 0))
5045	goto subschemas;
5046    /*
5047    * Search in global components.
5048    */
5049    for (i = 0; i < bucket->globals->nbItems; i++) {
5050	ret = bucket->globals->items[i];
5051	if (ret->type == type) {
5052	    switch (type) {
5053		case XML_SCHEMA_TYPE_COMPLEX:
5054		case XML_SCHEMA_TYPE_SIMPLE:
5055		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5056			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5057			nsName))
5058		    {
5059			return(ret);
5060		    }
5061		    break;
5062		case XML_SCHEMA_TYPE_GROUP:
5063		    if ((WXS_COMP_NAME(ret,
5064			    xmlSchemaModelGroupDefPtr) == name) &&
5065			(WXS_COMP_TNS(ret,
5066			    xmlSchemaModelGroupDefPtr) == nsName))
5067		    {
5068			return(ret);
5069		    }
5070		    break;
5071		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5072		    if ((WXS_COMP_NAME(ret,
5073			    xmlSchemaAttributeGroupPtr) == name) &&
5074			(WXS_COMP_TNS(ret,
5075			    xmlSchemaAttributeGroupPtr) == nsName))
5076		    {
5077			return(ret);
5078		    }
5079		    break;
5080		default:
5081		    /* Should not be hit. */
5082		    return(NULL);
5083	    }
5084	}
5085    }
5086subschemas:
5087    /*
5088    * Process imported/included schemas.
5089    */
5090    if (bucket->relations != NULL) {
5091	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5092
5093	/*
5094	* TODO: Marking the bucket will not avoid multiple searches
5095	* in the same schema, but avoids at least circularity.
5096	*/
5097	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5098	do {
5099	    if ((rel->bucket != NULL) &&
5100		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5101		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5102		    type, name, nsName);
5103		if (ret != NULL)
5104		    return(ret);
5105	    }
5106	    rel = rel->next;
5107	} while (rel != NULL);
5108	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5109    }
5110    return(NULL);
5111}
5112
5113/**
5114 * xmlSchemaAddNotation:
5115 * @ctxt:  a schema parser context
5116 * @schema:  the schema being built
5117 * @name:  the item name
5118 *
5119 * Add an XML schema annotation declaration
5120 * *WARNING* this interface is highly subject to change
5121 *
5122 * Returns the new struture or NULL in case of error
5123 */
5124static xmlSchemaNotationPtr
5125xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5126                     const xmlChar *name, const xmlChar *nsName,
5127		     xmlNodePtr node ATTRIBUTE_UNUSED)
5128{
5129    xmlSchemaNotationPtr ret = NULL;
5130
5131    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5132        return (NULL);
5133
5134    ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5135    if (ret == NULL) {
5136        xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5137        return (NULL);
5138    }
5139    memset(ret, 0, sizeof(xmlSchemaNotation));
5140    ret->type = XML_SCHEMA_TYPE_NOTATION;
5141    ret->name = name;
5142    ret->targetNamespace = nsName;
5143    /* TODO: do we need the node to be set?
5144    * ret->node = node;*/
5145    WXS_ADD_GLOBAL(ctxt, ret);
5146    return (ret);
5147}
5148
5149/**
5150 * xmlSchemaAddAttribute:
5151 * @ctxt:  a schema parser context
5152 * @schema:  the schema being built
5153 * @name:  the item name
5154 * @namespace:  the namespace
5155 *
5156 * Add an XML schema Attrribute declaration
5157 * *WARNING* this interface is highly subject to change
5158 *
5159 * Returns the new struture or NULL in case of error
5160 */
5161static xmlSchemaAttributePtr
5162xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5163                      const xmlChar * name, const xmlChar * nsName,
5164		      xmlNodePtr node, int topLevel)
5165{
5166    xmlSchemaAttributePtr ret = NULL;
5167
5168    if ((ctxt == NULL) || (schema == NULL))
5169        return (NULL);
5170
5171    ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5172    if (ret == NULL) {
5173        xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5174        return (NULL);
5175    }
5176    memset(ret, 0, sizeof(xmlSchemaAttribute));
5177    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5178    ret->node = node;
5179    ret->name = name;
5180    ret->targetNamespace = nsName;
5181
5182    if (topLevel)
5183	WXS_ADD_GLOBAL(ctxt, ret);
5184    else
5185	WXS_ADD_LOCAL(ctxt, ret);
5186    WXS_ADD_PENDING(ctxt, ret);
5187    return (ret);
5188}
5189
5190/**
5191 * xmlSchemaAddAttributeUse:
5192 * @ctxt:  a schema parser context
5193 * @schema:  the schema being built
5194 * @name:  the item name
5195 * @namespace:  the namespace
5196 *
5197 * Add an XML schema Attrribute declaration
5198 * *WARNING* this interface is highly subject to change
5199 *
5200 * Returns the new struture or NULL in case of error
5201 */
5202static xmlSchemaAttributeUsePtr
5203xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5204			 xmlNodePtr node)
5205{
5206    xmlSchemaAttributeUsePtr ret = NULL;
5207
5208    if (pctxt == NULL)
5209        return (NULL);
5210
5211    ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5212    if (ret == NULL) {
5213        xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5214        return (NULL);
5215    }
5216    memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5217    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5218    ret->node = node;
5219
5220    WXS_ADD_LOCAL(pctxt, ret);
5221    return (ret);
5222}
5223
5224/*
5225* xmlSchemaAddRedef:
5226*
5227* Adds a redefinition information. This is used at a later stage to:
5228* resolve references to the redefined components and to check constraints.
5229*/
5230static xmlSchemaRedefPtr
5231xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5232		  xmlSchemaBucketPtr targetBucket,
5233		  void *item,
5234		  const xmlChar *refName,
5235		  const xmlChar *refTargetNs)
5236{
5237    xmlSchemaRedefPtr ret;
5238
5239    ret = (xmlSchemaRedefPtr)
5240	xmlMalloc(sizeof(xmlSchemaRedef));
5241    if (ret == NULL) {
5242	xmlSchemaPErrMemory(pctxt,
5243	    "allocating redefinition info", NULL);
5244	return (NULL);
5245    }
5246    memset(ret, 0, sizeof(xmlSchemaRedef));
5247    ret->item = item;
5248    ret->targetBucket = targetBucket;
5249    ret->refName = refName;
5250    ret->refTargetNs = refTargetNs;
5251    if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5252	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5253    else
5254	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5255    WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5256
5257    return (ret);
5258}
5259
5260/**
5261 * xmlSchemaAddAttributeGroupDefinition:
5262 * @ctxt:  a schema parser context
5263 * @schema:  the schema being built
5264 * @name:  the item name
5265 * @nsName:  the target namespace
5266 * @node: the corresponding node
5267 *
5268 * Add an XML schema Attrribute Group definition.
5269 *
5270 * Returns the new struture or NULL in case of error
5271 */
5272static xmlSchemaAttributeGroupPtr
5273xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5274                           xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5275			   const xmlChar *name,
5276			   const xmlChar *nsName,
5277			   xmlNodePtr node)
5278{
5279    xmlSchemaAttributeGroupPtr ret = NULL;
5280
5281    if ((pctxt == NULL) || (name == NULL))
5282        return (NULL);
5283
5284    ret = (xmlSchemaAttributeGroupPtr)
5285        xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5286    if (ret == NULL) {
5287	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5288	return (NULL);
5289    }
5290    memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5291    ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5292    ret->name = name;
5293    ret->targetNamespace = nsName;
5294    ret->node = node;
5295
5296    /* TODO: Remove the flag. */
5297    ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5298    if (pctxt->isRedefine) {
5299	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5300	    ret, name, nsName);
5301	if (pctxt->redef == NULL) {
5302	    xmlFree(ret);
5303	    return(NULL);
5304	}
5305	pctxt->redefCounter = 0;
5306    }
5307    WXS_ADD_GLOBAL(pctxt, ret);
5308    WXS_ADD_PENDING(pctxt, ret);
5309    return (ret);
5310}
5311
5312/**
5313 * xmlSchemaAddElement:
5314 * @ctxt:  a schema parser context
5315 * @schema:  the schema being built
5316 * @name:  the type name
5317 * @namespace:  the type namespace
5318 *
5319 * Add an XML schema Element declaration
5320 * *WARNING* this interface is highly subject to change
5321 *
5322 * Returns the new struture or NULL in case of error
5323 */
5324static xmlSchemaElementPtr
5325xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5326                    const xmlChar * name, const xmlChar * nsName,
5327		    xmlNodePtr node, int topLevel)
5328{
5329    xmlSchemaElementPtr ret = NULL;
5330
5331    if ((ctxt == NULL) || (name == NULL))
5332        return (NULL);
5333
5334    ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5335    if (ret == NULL) {
5336        xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5337        return (NULL);
5338    }
5339    memset(ret, 0, sizeof(xmlSchemaElement));
5340    ret->type = XML_SCHEMA_TYPE_ELEMENT;
5341    ret->name = name;
5342    ret->targetNamespace = nsName;
5343    ret->node = node;
5344
5345    if (topLevel)
5346	WXS_ADD_GLOBAL(ctxt, ret);
5347    else
5348	WXS_ADD_LOCAL(ctxt, ret);
5349    WXS_ADD_PENDING(ctxt, ret);
5350    return (ret);
5351}
5352
5353/**
5354 * xmlSchemaAddType:
5355 * @ctxt:  a schema parser context
5356 * @schema:  the schema being built
5357 * @name:  the item name
5358 * @namespace:  the namespace
5359 *
5360 * Add an XML schema item
5361 * *WARNING* this interface is highly subject to change
5362 *
5363 * Returns the new struture or NULL in case of error
5364 */
5365static xmlSchemaTypePtr
5366xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5367		 xmlSchemaTypeType type,
5368                 const xmlChar * name, const xmlChar * nsName,
5369		 xmlNodePtr node, int topLevel)
5370{
5371    xmlSchemaTypePtr ret = NULL;
5372
5373    if ((ctxt == NULL) || (schema == NULL))
5374        return (NULL);
5375
5376    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5377    if (ret == NULL) {
5378        xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5379        return (NULL);
5380    }
5381    memset(ret, 0, sizeof(xmlSchemaType));
5382    ret->type = type;
5383    ret->name = name;
5384    ret->targetNamespace = nsName;
5385    ret->node = node;
5386    if (topLevel) {
5387	if (ctxt->isRedefine) {
5388	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5389		ret, name, nsName);
5390	    if (ctxt->redef == NULL) {
5391		xmlFree(ret);
5392		return(NULL);
5393	    }
5394	    ctxt->redefCounter = 0;
5395	}
5396	WXS_ADD_GLOBAL(ctxt, ret);
5397    } else
5398	WXS_ADD_LOCAL(ctxt, ret);
5399    WXS_ADD_PENDING(ctxt, ret);
5400    return (ret);
5401}
5402
5403static xmlSchemaQNameRefPtr
5404xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5405		     xmlSchemaTypeType refType,
5406		     const xmlChar *refName,
5407		     const xmlChar *refNs)
5408{
5409    xmlSchemaQNameRefPtr ret;
5410
5411    ret = (xmlSchemaQNameRefPtr)
5412	xmlMalloc(sizeof(xmlSchemaQNameRef));
5413    if (ret == NULL) {
5414	xmlSchemaPErrMemory(pctxt,
5415	    "allocating QName reference item", NULL);
5416	return (NULL);
5417    }
5418    ret->node = NULL;
5419    ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5420    ret->name = refName;
5421    ret->targetNamespace = refNs;
5422    ret->item = NULL;
5423    ret->itemType = refType;
5424    /*
5425    * Store the reference item in the schema.
5426    */
5427    WXS_ADD_LOCAL(pctxt, ret);
5428    return (ret);
5429}
5430
5431static xmlSchemaAttributeUseProhibPtr
5432xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5433{
5434    xmlSchemaAttributeUseProhibPtr ret;
5435
5436    ret = (xmlSchemaAttributeUseProhibPtr)
5437	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5438    if (ret == NULL) {
5439	xmlSchemaPErrMemory(pctxt,
5440	    "allocating attribute use prohibition", NULL);
5441	return (NULL);
5442    }
5443    memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5444    ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5445    WXS_ADD_LOCAL(pctxt, ret);
5446    return (ret);
5447}
5448
5449
5450/**
5451 * xmlSchemaAddModelGroup:
5452 * @ctxt:  a schema parser context
5453 * @schema:  the schema being built
5454 * @type: the "compositor" type of the model group
5455 * @node: the node in the schema doc
5456 *
5457 * Adds a schema model group
5458 * *WARNING* this interface is highly subject to change
5459 *
5460 * Returns the new struture or NULL in case of error
5461 */
5462static xmlSchemaModelGroupPtr
5463xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5464		       xmlSchemaPtr schema,
5465		       xmlSchemaTypeType type,
5466		       xmlNodePtr node)
5467{
5468    xmlSchemaModelGroupPtr ret = NULL;
5469
5470    if ((ctxt == NULL) || (schema == NULL))
5471        return (NULL);
5472
5473    ret = (xmlSchemaModelGroupPtr)
5474	xmlMalloc(sizeof(xmlSchemaModelGroup));
5475    if (ret == NULL) {
5476	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5477	    NULL);
5478	return (NULL);
5479    }
5480    memset(ret, 0, sizeof(xmlSchemaModelGroup));
5481    ret->type = type;
5482    ret->node = node;
5483    WXS_ADD_LOCAL(ctxt, ret);
5484    if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5485	(type == XML_SCHEMA_TYPE_CHOICE))
5486	WXS_ADD_PENDING(ctxt, ret);
5487    return (ret);
5488}
5489
5490
5491/**
5492 * xmlSchemaAddParticle:
5493 * @ctxt:  a schema parser context
5494 * @schema:  the schema being built
5495 * @node: the corresponding node in the schema doc
5496 * @min: the minOccurs
5497 * @max: the maxOccurs
5498 *
5499 * Adds an XML schema particle component.
5500 * *WARNING* this interface is highly subject to change
5501 *
5502 * Returns the new struture or NULL in case of error
5503 */
5504static xmlSchemaParticlePtr
5505xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5506		     xmlNodePtr node, int min, int max)
5507{
5508    xmlSchemaParticlePtr ret = NULL;
5509    if (ctxt == NULL)
5510        return (NULL);
5511
5512#ifdef DEBUG
5513    fprintf(stderr, "Adding particle component\n");
5514#endif
5515    ret = (xmlSchemaParticlePtr)
5516	xmlMalloc(sizeof(xmlSchemaParticle));
5517    if (ret == NULL) {
5518	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5519	    NULL);
5520	return (NULL);
5521    }
5522    ret->type = XML_SCHEMA_TYPE_PARTICLE;
5523    ret->annot = NULL;
5524    ret->node = node;
5525    ret->minOccurs = min;
5526    ret->maxOccurs = max;
5527    ret->next = NULL;
5528    ret->children = NULL;
5529
5530    WXS_ADD_LOCAL(ctxt, ret);
5531    /*
5532    * Note that addition to pending components will be done locally
5533    * to the specific parsing function, since the most particles
5534    * need not to be fixed up (i.e. the reference to be resolved).
5535    * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5536    */
5537    return (ret);
5538}
5539
5540/**
5541 * xmlSchemaAddModelGroupDefinition:
5542 * @ctxt:  a schema validation context
5543 * @schema:  the schema being built
5544 * @name:  the group name
5545 *
5546 * Add an XML schema Group definition
5547 *
5548 * Returns the new struture or NULL in case of error
5549 */
5550static xmlSchemaModelGroupDefPtr
5551xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5552				 xmlSchemaPtr schema,
5553				 const xmlChar *name,
5554				 const xmlChar *nsName,
5555				 xmlNodePtr node)
5556{
5557    xmlSchemaModelGroupDefPtr ret = NULL;
5558
5559    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5560        return (NULL);
5561
5562    ret = (xmlSchemaModelGroupDefPtr)
5563	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5564    if (ret == NULL) {
5565        xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5566        return (NULL);
5567    }
5568    memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5569    ret->name = name;
5570    ret->type = XML_SCHEMA_TYPE_GROUP;
5571    ret->node = node;
5572    ret->targetNamespace = nsName;
5573
5574    if (ctxt->isRedefine) {
5575	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5576	    ret, name, nsName);
5577	if (ctxt->redef == NULL) {
5578	    xmlFree(ret);
5579	    return(NULL);
5580	}
5581	ctxt->redefCounter = 0;
5582    }
5583    WXS_ADD_GLOBAL(ctxt, ret);
5584    WXS_ADD_PENDING(ctxt, ret);
5585    return (ret);
5586}
5587
5588/**
5589 * xmlSchemaNewWildcardNs:
5590 * @ctxt:  a schema validation context
5591 *
5592 * Creates a new wildcard namespace constraint.
5593 *
5594 * Returns the new struture or NULL in case of error
5595 */
5596static xmlSchemaWildcardNsPtr
5597xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5598{
5599    xmlSchemaWildcardNsPtr ret;
5600
5601    ret = (xmlSchemaWildcardNsPtr)
5602	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5603    if (ret == NULL) {
5604	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5605	return (NULL);
5606    }
5607    ret->value = NULL;
5608    ret->next = NULL;
5609    return (ret);
5610}
5611
5612static xmlSchemaIDCPtr
5613xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5614                  const xmlChar *name, const xmlChar *nsName,
5615		  int category, xmlNodePtr node)
5616{
5617    xmlSchemaIDCPtr ret = NULL;
5618
5619    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5620        return (NULL);
5621
5622    ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5623    if (ret == NULL) {
5624        xmlSchemaPErrMemory(ctxt,
5625	    "allocating an identity-constraint definition", NULL);
5626        return (NULL);
5627    }
5628    memset(ret, 0, sizeof(xmlSchemaIDC));
5629    /* The target namespace of the parent element declaration. */
5630    ret->targetNamespace = nsName;
5631    ret->name = name;
5632    ret->type = category;
5633    ret->node = node;
5634
5635    WXS_ADD_GLOBAL(ctxt, ret);
5636    /*
5637    * Only keyrefs need to be fixup up.
5638    */
5639    if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5640	WXS_ADD_PENDING(ctxt, ret);
5641    return (ret);
5642}
5643
5644/**
5645 * xmlSchemaAddWildcard:
5646 * @ctxt:  a schema validation context
5647 * @schema: a schema
5648 *
5649 * Adds a wildcard.
5650 * It corresponds to a xsd:anyAttribute and xsd:any.
5651 *
5652 * Returns the new struture or NULL in case of error
5653 */
5654static xmlSchemaWildcardPtr
5655xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5656		     xmlSchemaTypeType type, xmlNodePtr node)
5657{
5658    xmlSchemaWildcardPtr ret = NULL;
5659
5660    if ((ctxt == NULL) || (schema == NULL))
5661        return (NULL);
5662
5663    ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5664    if (ret == NULL) {
5665        xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5666        return (NULL);
5667    }
5668    memset(ret, 0, sizeof(xmlSchemaWildcard));
5669    ret->type = type;
5670    ret->node = node;
5671    WXS_ADD_LOCAL(ctxt, ret);
5672    return (ret);
5673}
5674
5675static void
5676xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5677{
5678    if (group == NULL)
5679	return;
5680    if (group->members != NULL)
5681	xmlSchemaItemListFree(group->members);
5682    xmlFree(group);
5683}
5684
5685static xmlSchemaSubstGroupPtr
5686xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5687		       xmlSchemaElementPtr head)
5688{
5689    xmlSchemaSubstGroupPtr ret;
5690
5691    /* Init subst group hash. */
5692    if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5693	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5694	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5695	    return(NULL);
5696    }
5697    /* Create a new substitution group. */
5698    ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5699    if (ret == NULL) {
5700	xmlSchemaPErrMemory(NULL,
5701	    "allocating a substitution group container", NULL);
5702	return(NULL);
5703    }
5704    memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5705    ret->head = head;
5706    /* Create list of members. */
5707    ret->members = xmlSchemaItemListCreate();
5708    if (ret->members == NULL) {
5709	xmlSchemaSubstGroupFree(ret);
5710	return(NULL);
5711    }
5712    /* Add subst group to hash. */
5713    if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5714	head->name, head->targetNamespace, ret) != 0) {
5715	PERROR_INT("xmlSchemaSubstGroupAdd",
5716	    "failed to add a new substitution container");
5717	xmlSchemaSubstGroupFree(ret);
5718	return(NULL);
5719    }
5720    return(ret);
5721}
5722
5723static xmlSchemaSubstGroupPtr
5724xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5725		       xmlSchemaElementPtr head)
5726{
5727    if (WXS_SUBST_GROUPS(pctxt) == NULL)
5728	return(NULL);
5729    return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5730	head->name, head->targetNamespace));
5731
5732}
5733
5734/**
5735 * xmlSchemaAddElementSubstitutionMember:
5736 * @pctxt:  a schema parser context
5737 * @head:  the head of the substitution group
5738 * @member: the new member of the substitution group
5739 *
5740 * Allocate a new annotation structure.
5741 *
5742 * Returns the newly allocated structure or NULL in case or error
5743 */
5744static int
5745xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5746				      xmlSchemaElementPtr head,
5747				      xmlSchemaElementPtr member)
5748{
5749    xmlSchemaSubstGroupPtr substGroup = NULL;
5750
5751    if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5752	return (-1);
5753
5754    substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5755    if (substGroup == NULL)
5756	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5757    if (substGroup == NULL)
5758	return(-1);
5759    if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5760	return(-1);
5761    return(0);
5762}
5763
5764/************************************************************************
5765 *									*
5766 *		Utilities for parsing					*
5767 *									*
5768 ************************************************************************/
5769
5770/**
5771 * xmlSchemaPValAttrNodeQNameValue:
5772 * @ctxt:  a schema parser context
5773 * @schema: the schema context
5774 * @ownerDes: the designation of the parent element
5775 * @ownerItem: the parent as a schema object
5776 * @value:  the QName value
5777 * @local: the resulting local part if found, the attribute value otherwise
5778 * @uri:  the resulting namespace URI if found
5779 *
5780 * Extracts the local name and the URI of a QName value and validates it.
5781 * This one is intended to be used on attribute values that
5782 * should resolve to schema components.
5783 *
5784 * Returns 0, in case the QName is valid, a positive error code
5785 * if not valid and -1 if an internal error occurs.
5786 */
5787static int
5788xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5789				       xmlSchemaPtr schema,
5790				       xmlSchemaBasicItemPtr ownerItem,
5791				       xmlAttrPtr attr,
5792				       const xmlChar *value,
5793				       const xmlChar **uri,
5794				       const xmlChar **local)
5795{
5796    const xmlChar *pref;
5797    xmlNsPtr ns;
5798    int len, ret;
5799
5800    *uri = NULL;
5801    *local = NULL;
5802    ret = xmlValidateQName(value, 1);
5803    if (ret > 0) {
5804	xmlSchemaPSimpleTypeErr(ctxt,
5805	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5806	    ownerItem, (xmlNodePtr) attr,
5807	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5808	    NULL, value, NULL, NULL, NULL);
5809	*local = value;
5810	return (ctxt->err);
5811    } else if (ret < 0)
5812	return (-1);
5813
5814    if (!strchr((char *) value, ':')) {
5815	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5816	if (ns)
5817	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5818	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5819	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5820	    * parser context. */
5821	    /*
5822	    * This one takes care of included schemas with no
5823	    * target namespace.
5824	    */
5825	    *uri = ctxt->targetNamespace;
5826	}
5827	*local = xmlDictLookup(ctxt->dict, value, -1);
5828	return (0);
5829    }
5830    /*
5831    * At this point xmlSplitQName3 has to return a local name.
5832    */
5833    *local = xmlSplitQName3(value, &len);
5834    *local = xmlDictLookup(ctxt->dict, *local, -1);
5835    pref = xmlDictLookup(ctxt->dict, value, len);
5836    ns = xmlSearchNs(attr->doc, attr->parent, pref);
5837    if (ns == NULL) {
5838	xmlSchemaPSimpleTypeErr(ctxt,
5839	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5840	    ownerItem, (xmlNodePtr) attr,
5841	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5842	    "The value '%s' of simple type 'xs:QName' has no "
5843	    "corresponding namespace declaration in scope", value, NULL);
5844	return (ctxt->err);
5845    } else {
5846        *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5847    }
5848    return (0);
5849}
5850
5851/**
5852 * xmlSchemaPValAttrNodeQName:
5853 * @ctxt:  a schema parser context
5854 * @schema: the schema context
5855 * @ownerDes: the designation of the owner element
5856 * @ownerItem: the owner as a schema object
5857 * @attr:  the attribute node
5858 * @local: the resulting local part if found, the attribute value otherwise
5859 * @uri:  the resulting namespace URI if found
5860 *
5861 * Extracts and validates the QName of an attribute value.
5862 * This one is intended to be used on attribute values that
5863 * should resolve to schema components.
5864 *
5865 * Returns 0, in case the QName is valid, a positive error code
5866 * if not valid and -1 if an internal error occurs.
5867 */
5868static int
5869xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5870				       xmlSchemaPtr schema,
5871				       xmlSchemaBasicItemPtr ownerItem,
5872				       xmlAttrPtr attr,
5873				       const xmlChar **uri,
5874				       const xmlChar **local)
5875{
5876    const xmlChar *value;
5877
5878    value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5879    return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5880	ownerItem, attr, value, uri, local));
5881}
5882
5883/**
5884 * xmlSchemaPValAttrQName:
5885 * @ctxt:  a schema parser context
5886 * @schema: the schema context
5887 * @ownerDes: the designation of the parent element
5888 * @ownerItem: the owner as a schema object
5889 * @ownerElem:  the parent node of the attribute
5890 * @name:  the name of the attribute
5891 * @local: the resulting local part if found, the attribute value otherwise
5892 * @uri:  the resulting namespace URI if found
5893 *
5894 * Extracts and validates the QName of an attribute value.
5895 *
5896 * Returns 0, in case the QName is valid, a positive error code
5897 * if not valid and -1 if an internal error occurs.
5898 */
5899static int
5900xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5901				   xmlSchemaPtr schema,
5902				   xmlSchemaBasicItemPtr ownerItem,
5903				   xmlNodePtr ownerElem,
5904				   const char *name,
5905				   const xmlChar **uri,
5906				   const xmlChar **local)
5907{
5908    xmlAttrPtr attr;
5909
5910    attr = xmlSchemaGetPropNode(ownerElem, name);
5911    if (attr == NULL) {
5912	*local = NULL;
5913	*uri = NULL;
5914	return (0);
5915    }
5916    return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5917	ownerItem, attr, uri, local));
5918}
5919
5920/**
5921 * xmlSchemaPValAttrID:
5922 * @ctxt:  a schema parser context
5923 * @schema: the schema context
5924 * @ownerDes: the designation of the parent element
5925 * @ownerItem: the owner as a schema object
5926 * @ownerElem:  the parent node of the attribute
5927 * @name:  the name of the attribute
5928 *
5929 * Extracts and validates the ID of an attribute value.
5930 *
5931 * Returns 0, in case the ID is valid, a positive error code
5932 * if not valid and -1 if an internal error occurs.
5933 */
5934static int
5935xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5936{
5937    int ret;
5938    const xmlChar *value;
5939
5940    if (attr == NULL)
5941	return(0);
5942    value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5943    ret = xmlValidateNCName(value, 1);
5944    if (ret == 0) {
5945	/*
5946	* NOTE: the IDness might have already be declared in the DTD
5947	*/
5948	if (attr->atype != XML_ATTRIBUTE_ID) {
5949	    xmlIDPtr res;
5950	    xmlChar *strip;
5951
5952	    /*
5953	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5954	    * moment.
5955	    */
5956	    strip = xmlSchemaCollapseString(value);
5957	    if (strip != NULL) {
5958		xmlFree((xmlChar *) value);
5959		value = strip;
5960	    }
5961	    res = xmlAddID(NULL, attr->doc, value, attr);
5962	    if (res == NULL) {
5963		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5964		xmlSchemaPSimpleTypeErr(ctxt,
5965		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5966		    NULL, (xmlNodePtr) attr,
5967		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5968		    NULL, NULL, "Duplicate value '%s' of simple "
5969		    "type 'xs:ID'", value, NULL);
5970	    } else
5971		attr->atype = XML_ATTRIBUTE_ID;
5972	}
5973    } else if (ret > 0) {
5974	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5975	xmlSchemaPSimpleTypeErr(ctxt,
5976	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5977	    NULL, (xmlNodePtr) attr,
5978	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5979	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5980	    "not a valid 'xs:NCName'",
5981	    value, NULL);
5982    }
5983    if (value != NULL)
5984	xmlFree((xmlChar *)value);
5985
5986    return (ret);
5987}
5988
5989static int
5990xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5991		    xmlNodePtr ownerElem,
5992		    const xmlChar *name)
5993{
5994    xmlAttrPtr attr;
5995
5996    attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5997    if (attr == NULL)
5998	return(0);
5999    return(xmlSchemaPValAttrNodeID(ctxt, attr));
6000
6001}
6002
6003/**
6004 * xmlGetMaxOccurs:
6005 * @ctxt:  a schema validation context
6006 * @node:  a subtree containing XML Schema informations
6007 *
6008 * Get the maxOccurs property
6009 *
6010 * Returns the default if not found, or the value
6011 */
6012static int
6013xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6014		int min, int max, int def, const char *expected)
6015{
6016    const xmlChar *val, *cur;
6017    int ret = 0;
6018    xmlAttrPtr attr;
6019
6020    attr = xmlSchemaGetPropNode(node, "maxOccurs");
6021    if (attr == NULL)
6022	return (def);
6023    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6024
6025    if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6026	if (max != UNBOUNDED) {
6027	    xmlSchemaPSimpleTypeErr(ctxt,
6028		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6029		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6030		NULL, (xmlNodePtr) attr, NULL, expected,
6031		val, NULL, NULL, NULL);
6032	    return (def);
6033	} else
6034	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6035    }
6036
6037    cur = val;
6038    while (IS_BLANK_CH(*cur))
6039        cur++;
6040    if (*cur == 0) {
6041        xmlSchemaPSimpleTypeErr(ctxt,
6042	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6043	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6044	    NULL, (xmlNodePtr) attr, NULL, expected,
6045	    val, NULL, NULL, NULL);
6046	return (def);
6047    }
6048    while ((*cur >= '0') && (*cur <= '9')) {
6049        ret = ret * 10 + (*cur - '0');
6050        cur++;
6051    }
6052    while (IS_BLANK_CH(*cur))
6053        cur++;
6054    /*
6055    * TODO: Restrict the maximal value to Integer.
6056    */
6057    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6058	xmlSchemaPSimpleTypeErr(ctxt,
6059	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6060	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6061	    NULL, (xmlNodePtr) attr, NULL, expected,
6062	    val, NULL, NULL, NULL);
6063        return (def);
6064    }
6065    return (ret);
6066}
6067
6068/**
6069 * xmlGetMinOccurs:
6070 * @ctxt:  a schema validation context
6071 * @node:  a subtree containing XML Schema informations
6072 *
6073 * Get the minOccurs property
6074 *
6075 * Returns the default if not found, or the value
6076 */
6077static int
6078xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6079		int min, int max, int def, const char *expected)
6080{
6081    const xmlChar *val, *cur;
6082    int ret = 0;
6083    xmlAttrPtr attr;
6084
6085    attr = xmlSchemaGetPropNode(node, "minOccurs");
6086    if (attr == NULL)
6087	return (def);
6088    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6089    cur = val;
6090    while (IS_BLANK_CH(*cur))
6091        cur++;
6092    if (*cur == 0) {
6093        xmlSchemaPSimpleTypeErr(ctxt,
6094	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6095	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6096	    NULL, (xmlNodePtr) attr, NULL, expected,
6097	    val, NULL, NULL, NULL);
6098        return (def);
6099    }
6100    while ((*cur >= '0') && (*cur <= '9')) {
6101        ret = ret * 10 + (*cur - '0');
6102        cur++;
6103    }
6104    while (IS_BLANK_CH(*cur))
6105        cur++;
6106    /*
6107    * TODO: Restrict the maximal value to Integer.
6108    */
6109    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6110	xmlSchemaPSimpleTypeErr(ctxt,
6111	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6112	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6113	    NULL, (xmlNodePtr) attr, NULL, expected,
6114	    val, NULL, NULL, NULL);
6115        return (def);
6116    }
6117    return (ret);
6118}
6119
6120/**
6121 * xmlSchemaPGetBoolNodeValue:
6122 * @ctxt:  a schema validation context
6123 * @ownerDes:  owner designation
6124 * @ownerItem:  the owner as a schema item
6125 * @node: the node holding the value
6126 *
6127 * Converts a boolean string value into 1 or 0.
6128 *
6129 * Returns 0 or 1.
6130 */
6131static int
6132xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6133			   xmlSchemaBasicItemPtr ownerItem,
6134			   xmlNodePtr node)
6135{
6136    xmlChar *value = NULL;
6137    int res = 0;
6138
6139    value = xmlNodeGetContent(node);
6140    /*
6141    * 3.2.2.1 Lexical representation
6142    * An instance of a datatype that is defined as �boolean�
6143    * can have the following legal literals {true, false, 1, 0}.
6144    */
6145    if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6146        res = 1;
6147    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6148        res = 0;
6149    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6150	res = 1;
6151    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6152        res = 0;
6153    else {
6154        xmlSchemaPSimpleTypeErr(ctxt,
6155	    XML_SCHEMAP_INVALID_BOOLEAN,
6156	    ownerItem, node,
6157	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6158	    NULL, BAD_CAST value,
6159	    NULL, NULL, NULL);
6160    }
6161    if (value != NULL)
6162	xmlFree(value);
6163    return (res);
6164}
6165
6166/**
6167 * xmlGetBooleanProp:
6168 * @ctxt:  a schema validation context
6169 * @node:  a subtree containing XML Schema informations
6170 * @name:  the attribute name
6171 * @def:  the default value
6172 *
6173 * Evaluate if a boolean property is set
6174 *
6175 * Returns the default if not found, 0 if found to be false,
6176 * 1 if found to be true
6177 */
6178static int
6179xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6180		  xmlNodePtr node,
6181                  const char *name, int def)
6182{
6183    const xmlChar *val;
6184
6185    val = xmlSchemaGetProp(ctxt, node, name);
6186    if (val == NULL)
6187        return (def);
6188    /*
6189    * 3.2.2.1 Lexical representation
6190    * An instance of a datatype that is defined as �boolean�
6191    * can have the following legal literals {true, false, 1, 0}.
6192    */
6193    if (xmlStrEqual(val, BAD_CAST "true"))
6194        def = 1;
6195    else if (xmlStrEqual(val, BAD_CAST "false"))
6196        def = 0;
6197    else if (xmlStrEqual(val, BAD_CAST "1"))
6198	def = 1;
6199    else if (xmlStrEqual(val, BAD_CAST "0"))
6200        def = 0;
6201    else {
6202        xmlSchemaPSimpleTypeErr(ctxt,
6203	    XML_SCHEMAP_INVALID_BOOLEAN,
6204	    NULL,
6205	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6206	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6207	    NULL, val, NULL, NULL, NULL);
6208    }
6209    return (def);
6210}
6211
6212/************************************************************************
6213 *									*
6214 *		Shema extraction from an Infoset			*
6215 *									*
6216 ************************************************************************/
6217static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6218                                                 ctxt, xmlSchemaPtr schema,
6219                                                 xmlNodePtr node,
6220						 int topLevel);
6221static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6222                                                  ctxt,
6223                                                  xmlSchemaPtr schema,
6224                                                  xmlNodePtr node,
6225						  int topLevel);
6226static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6227                                                  ctxt,
6228                                                  xmlSchemaPtr schema,
6229                                                  xmlNodePtr node,
6230						  xmlSchemaTypeType parentType);
6231static xmlSchemaBasicItemPtr
6232xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6233			     xmlSchemaPtr schema,
6234			     xmlNodePtr node,
6235			     xmlSchemaItemListPtr uses,
6236			     int parentType);
6237static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6238                                           xmlSchemaPtr schema,
6239                                           xmlNodePtr node);
6240static xmlSchemaWildcardPtr
6241xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6242                           xmlSchemaPtr schema, xmlNodePtr node);
6243
6244/**
6245 * xmlSchemaPValAttrNodeValue:
6246 *
6247 * @ctxt:  a schema parser context
6248 * @ownerDes: the designation of the parent element
6249 * @ownerItem: the schema object owner if existent
6250 * @attr:  the schema attribute node being validated
6251 * @value: the value
6252 * @type: the built-in type to be validated against
6253 *
6254 * Validates a value against the given built-in type.
6255 * This one is intended to be used internally for validation
6256 * of schema attribute values during parsing of the schema.
6257 *
6258 * Returns 0 if the value is valid, a positive error code
6259 * number otherwise and -1 in case of an internal or API error.
6260 */
6261static int
6262xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6263			   xmlSchemaBasicItemPtr ownerItem,
6264			   xmlAttrPtr attr,
6265			   const xmlChar *value,
6266			   xmlSchemaTypePtr type)
6267{
6268
6269    int ret = 0;
6270
6271    /*
6272    * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6273    * one is really meant to be used internally, so better not.
6274    */
6275    if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6276	return (-1);
6277    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6278	PERROR_INT("xmlSchemaPValAttrNodeValue",
6279	    "the given type is not a built-in type");
6280	return (-1);
6281    }
6282    switch (type->builtInType) {
6283	case XML_SCHEMAS_NCNAME:
6284	case XML_SCHEMAS_QNAME:
6285	case XML_SCHEMAS_ANYURI:
6286	case XML_SCHEMAS_TOKEN:
6287	case XML_SCHEMAS_LANGUAGE:
6288	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6289		(xmlNodePtr) attr);
6290	    break;
6291	default: {
6292	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6293		"validation using the given type is not supported while "
6294		"parsing a schema");
6295	    return (-1);
6296	}
6297    }
6298    /*
6299    * TODO: Should we use the S4S error codes instead?
6300    */
6301    if (ret < 0) {
6302	PERROR_INT("xmlSchemaPValAttrNodeValue",
6303	    "failed to validate a schema attribute value");
6304	return (-1);
6305    } else if (ret > 0) {
6306	if (WXS_IS_LIST(type))
6307	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6308	else
6309	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6310	xmlSchemaPSimpleTypeErr(pctxt,
6311	    ret, ownerItem, (xmlNodePtr) attr,
6312	    type, NULL, value, NULL, NULL, NULL);
6313    }
6314    return (ret);
6315}
6316
6317/**
6318 * xmlSchemaPValAttrNode:
6319 *
6320 * @ctxt:  a schema parser context
6321 * @ownerDes: the designation of the parent element
6322 * @ownerItem: the schema object owner if existent
6323 * @attr:  the schema attribute node being validated
6324 * @type: the built-in type to be validated against
6325 * @value: the resulting value if any
6326 *
6327 * Extracts and validates a value against the given built-in type.
6328 * This one is intended to be used internally for validation
6329 * of schema attribute values during parsing of the schema.
6330 *
6331 * Returns 0 if the value is valid, a positive error code
6332 * number otherwise and -1 in case of an internal or API error.
6333 */
6334static int
6335xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6336			   xmlSchemaBasicItemPtr ownerItem,
6337			   xmlAttrPtr attr,
6338			   xmlSchemaTypePtr type,
6339			   const xmlChar **value)
6340{
6341    const xmlChar *val;
6342
6343    if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6344	return (-1);
6345
6346    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6347    if (value != NULL)
6348	*value = val;
6349
6350    return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6351	val, type));
6352}
6353
6354/**
6355 * xmlSchemaPValAttr:
6356 *
6357 * @ctxt:  a schema parser context
6358 * @node: the element node of the attribute
6359 * @ownerDes: the designation of the parent element
6360 * @ownerItem: the schema object owner if existent
6361 * @ownerElem: the owner element node
6362 * @name:  the name of the schema attribute node
6363 * @type: the built-in type to be validated against
6364 * @value: the resulting value if any
6365 *
6366 * Extracts and validates a value against the given built-in type.
6367 * This one is intended to be used internally for validation
6368 * of schema attribute values during parsing of the schema.
6369 *
6370 * Returns 0 if the value is valid, a positive error code
6371 * number otherwise and -1 in case of an internal or API error.
6372 */
6373static int
6374xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6375		       xmlSchemaBasicItemPtr ownerItem,
6376		       xmlNodePtr ownerElem,
6377		       const char *name,
6378		       xmlSchemaTypePtr type,
6379		       const xmlChar **value)
6380{
6381    xmlAttrPtr attr;
6382
6383    if ((ctxt == NULL) || (type == NULL)) {
6384	if (value != NULL)
6385	    *value = NULL;
6386	return (-1);
6387    }
6388    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6389	if (value != NULL)
6390	    *value = NULL;
6391	xmlSchemaPErr(ctxt, ownerElem,
6392	    XML_SCHEMAP_INTERNAL,
6393	    "Internal error: xmlSchemaPValAttr, the given "
6394	    "type '%s' is not a built-in type.\n",
6395	    type->name, NULL);
6396	return (-1);
6397    }
6398    attr = xmlSchemaGetPropNode(ownerElem, name);
6399    if (attr == NULL) {
6400	if (value != NULL)
6401	    *value = NULL;
6402	return (0);
6403    }
6404    return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6405	type, value));
6406}
6407
6408static int
6409xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6410		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6411		  xmlNodePtr node,
6412		  xmlAttrPtr attr,
6413		  const xmlChar *namespaceName)
6414{
6415    /* TODO: Pointer comparison instead? */
6416    if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6417	return (0);
6418    if (xmlStrEqual(xmlSchemaNs, namespaceName))
6419	return (0);
6420    /*
6421    * Check if the referenced namespace was <import>ed.
6422    */
6423    if (WXS_BUCKET(pctxt)->relations != NULL) {
6424	xmlSchemaSchemaRelationPtr rel;
6425
6426	rel = WXS_BUCKET(pctxt)->relations;
6427	do {
6428	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6429		xmlStrEqual(namespaceName, rel->importNamespace))
6430		return (0);
6431	    rel = rel->next;
6432	} while (rel != NULL);
6433    }
6434    /*
6435    * No matching <import>ed namespace found.
6436    */
6437    {
6438	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6439
6440	if (namespaceName == NULL)
6441	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6442		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6443		"References from this schema to components in no "
6444		"namespace are not allowed, since not indicated by an "
6445		"import statement", NULL, NULL);
6446	else
6447	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6448		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6449		"References from this schema to components in the "
6450		"namespace '%s' are not allowed, since not indicated by an "
6451		"import statement", namespaceName, NULL);
6452    }
6453    return (XML_SCHEMAP_SRC_RESOLVE);
6454}
6455
6456/**
6457 * xmlSchemaParseLocalAttributes:
6458 * @ctxt:  a schema validation context
6459 * @schema:  the schema being built
6460 * @node:  a subtree containing XML Schema informations
6461 * @type:  the hosting type where the attributes will be anchored
6462 *
6463 * Parses attribute uses and attribute declarations and
6464 * attribute group references.
6465 */
6466static int
6467xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6468                        xmlNodePtr *child, xmlSchemaItemListPtr *list,
6469			int parentType, int *hasRefs)
6470{
6471    void *item;
6472
6473    while ((IS_SCHEMA((*child), "attribute")) ||
6474           (IS_SCHEMA((*child), "attributeGroup"))) {
6475        if (IS_SCHEMA((*child), "attribute")) {
6476	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6477		*list, parentType);
6478        } else {
6479            item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6480	    if ((item != NULL) && (hasRefs != NULL))
6481		*hasRefs = 1;
6482        }
6483	if (item != NULL) {
6484	    if (*list == NULL) {
6485		/* TODO: Customize grow factor. */
6486		*list = xmlSchemaItemListCreate();
6487		if (*list == NULL)
6488		    return(-1);
6489	    }
6490	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6491		return(-1);
6492	}
6493        *child = (*child)->next;
6494    }
6495    return (0);
6496}
6497
6498/**
6499 * xmlSchemaParseAnnotation:
6500 * @ctxt:  a schema validation context
6501 * @schema:  the schema being built
6502 * @node:  a subtree containing XML Schema informations
6503 *
6504 * parse a XML schema Attrribute declaration
6505 * *WARNING* this interface is highly subject to change
6506 *
6507 * Returns -1 in case of error, 0 if the declaration is improper and
6508 *         1 in case of success.
6509 */
6510static xmlSchemaAnnotPtr
6511xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6512{
6513    xmlSchemaAnnotPtr ret;
6514    xmlNodePtr child = NULL;
6515    xmlAttrPtr attr;
6516    int barked = 0;
6517
6518    /*
6519    * INFO: S4S completed.
6520    */
6521    /*
6522    * id = ID
6523    * {any attributes with non-schema namespace . . .}>
6524    * Content: (appinfo | documentation)*
6525    */
6526    if ((ctxt == NULL) || (node == NULL))
6527        return (NULL);
6528    if (needed)
6529	ret = xmlSchemaNewAnnot(ctxt, node);
6530    else
6531	ret = NULL;
6532    attr = node->properties;
6533    while (attr != NULL) {
6534	if (((attr->ns == NULL) &&
6535	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6536	    ((attr->ns != NULL) &&
6537	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6538
6539	    xmlSchemaPIllegalAttrErr(ctxt,
6540		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6541	}
6542	attr = attr->next;
6543    }
6544    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6545    /*
6546    * And now for the children...
6547    */
6548    child = node->children;
6549    while (child != NULL) {
6550	if (IS_SCHEMA(child, "appinfo")) {
6551	    /* TODO: make available the content of "appinfo". */
6552	    /*
6553	    * source = anyURI
6554	    * {any attributes with non-schema namespace . . .}>
6555	    * Content: ({any})*
6556	    */
6557	    attr = child->properties;
6558	    while (attr != NULL) {
6559		if (((attr->ns == NULL) &&
6560		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6561		     ((attr->ns != NULL) &&
6562		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6563
6564		    xmlSchemaPIllegalAttrErr(ctxt,
6565			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6566		}
6567		attr = attr->next;
6568	    }
6569	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6570		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6571	    child = child->next;
6572	} else if (IS_SCHEMA(child, "documentation")) {
6573	    /* TODO: make available the content of "documentation". */
6574	    /*
6575	    * source = anyURI
6576	    * {any attributes with non-schema namespace . . .}>
6577	    * Content: ({any})*
6578	    */
6579	    attr = child->properties;
6580	    while (attr != NULL) {
6581		if (attr->ns == NULL) {
6582		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6583			xmlSchemaPIllegalAttrErr(ctxt,
6584			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6585		    }
6586		} else {
6587		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6588			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6589			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6590
6591			xmlSchemaPIllegalAttrErr(ctxt,
6592			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6593		    }
6594		}
6595		attr = attr->next;
6596	    }
6597	    /*
6598	    * Attribute "xml:lang".
6599	    */
6600	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6601	    if (attr != NULL)
6602		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6603		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6604	    child = child->next;
6605	} else {
6606	    if (!barked)
6607		xmlSchemaPContentErr(ctxt,
6608		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6609		    NULL, node, child, NULL, "(appinfo | documentation)*");
6610	    barked = 1;
6611	    child = child->next;
6612	}
6613    }
6614
6615    return (ret);
6616}
6617
6618/**
6619 * xmlSchemaParseFacet:
6620 * @ctxt:  a schema validation context
6621 * @schema:  the schema being built
6622 * @node:  a subtree containing XML Schema informations
6623 *
6624 * parse a XML schema Facet declaration
6625 * *WARNING* this interface is highly subject to change
6626 *
6627 * Returns the new type structure or NULL in case of error
6628 */
6629static xmlSchemaFacetPtr
6630xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6631                    xmlNodePtr node)
6632{
6633    xmlSchemaFacetPtr facet;
6634    xmlNodePtr child = NULL;
6635    const xmlChar *value;
6636
6637    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6638        return (NULL);
6639
6640    facet = xmlSchemaNewFacet();
6641    if (facet == NULL) {
6642        xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6643        return (NULL);
6644    }
6645    facet->node = node;
6646    value = xmlSchemaGetProp(ctxt, node, "value");
6647    if (value == NULL) {
6648        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6649                       "Facet %s has no value\n", node->name, NULL);
6650        xmlSchemaFreeFacet(facet);
6651        return (NULL);
6652    }
6653    if (IS_SCHEMA(node, "minInclusive")) {
6654        facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6655    } else if (IS_SCHEMA(node, "minExclusive")) {
6656        facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6657    } else if (IS_SCHEMA(node, "maxInclusive")) {
6658        facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6659    } else if (IS_SCHEMA(node, "maxExclusive")) {
6660        facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6661    } else if (IS_SCHEMA(node, "totalDigits")) {
6662        facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6663    } else if (IS_SCHEMA(node, "fractionDigits")) {
6664        facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6665    } else if (IS_SCHEMA(node, "pattern")) {
6666        facet->type = XML_SCHEMA_FACET_PATTERN;
6667    } else if (IS_SCHEMA(node, "enumeration")) {
6668        facet->type = XML_SCHEMA_FACET_ENUMERATION;
6669    } else if (IS_SCHEMA(node, "whiteSpace")) {
6670        facet->type = XML_SCHEMA_FACET_WHITESPACE;
6671    } else if (IS_SCHEMA(node, "length")) {
6672        facet->type = XML_SCHEMA_FACET_LENGTH;
6673    } else if (IS_SCHEMA(node, "maxLength")) {
6674        facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6675    } else if (IS_SCHEMA(node, "minLength")) {
6676        facet->type = XML_SCHEMA_FACET_MINLENGTH;
6677    } else {
6678        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6679                       "Unknown facet type %s\n", node->name, NULL);
6680        xmlSchemaFreeFacet(facet);
6681        return (NULL);
6682    }
6683    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6684    facet->value = value;
6685    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6686	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6687	const xmlChar *fixed;
6688
6689	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6690	if (fixed != NULL) {
6691	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6692		facet->fixed = 1;
6693	}
6694    }
6695    child = node->children;
6696
6697    if (IS_SCHEMA(child, "annotation")) {
6698        facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6699        child = child->next;
6700    }
6701    if (child != NULL) {
6702        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6703                       "Facet %s has unexpected child content\n",
6704                       node->name, NULL);
6705    }
6706    return (facet);
6707}
6708
6709/**
6710 * xmlSchemaParseWildcardNs:
6711 * @ctxt:  a schema parser context
6712 * @wildc:  the wildcard, already created
6713 * @node:  a subtree containing XML Schema informations
6714 *
6715 * Parses the attribute "processContents" and "namespace"
6716 * of a xsd:anyAttribute and xsd:any.
6717 * *WARNING* this interface is highly subject to change
6718 *
6719 * Returns 0 if everything goes fine, a positive error code
6720 * if something is not valid and -1 if an internal error occurs.
6721 */
6722static int
6723xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6724			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6725			 xmlSchemaWildcardPtr wildc,
6726			 xmlNodePtr node)
6727{
6728    const xmlChar *pc, *ns, *dictnsItem;
6729    int ret = 0;
6730    xmlChar *nsItem;
6731    xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6732    xmlAttrPtr attr;
6733
6734    pc = xmlSchemaGetProp(ctxt, node, "processContents");
6735    if ((pc == NULL)
6736        || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6737        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6738    } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6739        wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6740    } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6741        wildc->processContents = XML_SCHEMAS_ANY_LAX;
6742    } else {
6743        xmlSchemaPSimpleTypeErr(ctxt,
6744	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6745	    NULL, node,
6746	    NULL, "(strict | skip | lax)", pc,
6747	    NULL, NULL, NULL);
6748        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6749	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6750    }
6751    /*
6752     * Build the namespace constraints.
6753     */
6754    attr = xmlSchemaGetPropNode(node, "namespace");
6755    ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6756    if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6757	wildc->any = 1;
6758    else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6759	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6760	if (wildc->negNsSet == NULL) {
6761	    return (-1);
6762	}
6763	wildc->negNsSet->value = ctxt->targetNamespace;
6764    } else {
6765	const xmlChar *end, *cur;
6766
6767	cur = ns;
6768	do {
6769	    while (IS_BLANK_CH(*cur))
6770		cur++;
6771	    end = cur;
6772	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6773		end++;
6774	    if (end == cur)
6775		break;
6776	    nsItem = xmlStrndup(cur, end - cur);
6777	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6778		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6779		xmlSchemaPSimpleTypeErr(ctxt,
6780		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6781		    NULL, (xmlNodePtr) attr,
6782		    NULL,
6783		    "((##any | ##other) | List of (xs:anyURI | "
6784		    "(##targetNamespace | ##local)))",
6785		    nsItem, NULL, NULL, NULL);
6786		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6787	    } else {
6788		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6789		    dictnsItem = ctxt->targetNamespace;
6790		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6791		    dictnsItem = NULL;
6792		} else {
6793		    /*
6794		    * Validate the item (anyURI).
6795		    */
6796		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6797			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6798		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6799		}
6800		/*
6801		* Avoid dublicate namespaces.
6802		*/
6803		tmp = wildc->nsSet;
6804		while (tmp != NULL) {
6805		    if (dictnsItem == tmp->value)
6806			break;
6807		    tmp = tmp->next;
6808		}
6809		if (tmp == NULL) {
6810		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6811		    if (tmp == NULL) {
6812			xmlFree(nsItem);
6813			return (-1);
6814		    }
6815		    tmp->value = dictnsItem;
6816		    tmp->next = NULL;
6817		    if (wildc->nsSet == NULL)
6818			wildc->nsSet = tmp;
6819		    else if (lastNs != NULL)
6820			lastNs->next = tmp;
6821		    lastNs = tmp;
6822		}
6823
6824	    }
6825	    xmlFree(nsItem);
6826	    cur = end;
6827	} while (*cur != 0);
6828    }
6829    return (ret);
6830}
6831
6832static int
6833xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6834				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6835				 xmlNodePtr node,
6836				 int minOccurs,
6837				 int maxOccurs) {
6838
6839    if ((maxOccurs == 0) && ( minOccurs == 0))
6840	return (0);
6841    if (maxOccurs != UNBOUNDED) {
6842	/*
6843	* TODO: Maybe we should better not create the particle,
6844	* if min/max is invalid, since it could confuse the build of the
6845	* content model.
6846	*/
6847	/*
6848	* 3.9.6 Schema Component Constraint: Particle Correct
6849	*
6850	*/
6851	if (maxOccurs < 1) {
6852	    /*
6853	    * 2.2 {max occurs} must be greater than or equal to 1.
6854	    */
6855	    xmlSchemaPCustomAttrErr(ctxt,
6856		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6857		NULL, NULL,
6858		xmlSchemaGetPropNode(node, "maxOccurs"),
6859		"The value must be greater than or equal to 1");
6860	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6861	} else if (minOccurs > maxOccurs) {
6862	    /*
6863	    * 2.1 {min occurs} must not be greater than {max occurs}.
6864	    */
6865	    xmlSchemaPCustomAttrErr(ctxt,
6866		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6867		NULL, NULL,
6868		xmlSchemaGetPropNode(node, "minOccurs"),
6869		"The value must not be greater than the value of 'maxOccurs'");
6870	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6871	}
6872    }
6873    return (0);
6874}
6875
6876/**
6877 * xmlSchemaParseAny:
6878 * @ctxt:  a schema validation context
6879 * @schema:  the schema being built
6880 * @node:  a subtree containing XML Schema informations
6881 *
6882 * Parsea a XML schema <any> element. A particle and wildcard
6883 * will be created (except if minOccurs==maxOccurs==0, in this case
6884 * nothing will be created).
6885 * *WARNING* this interface is highly subject to change
6886 *
6887 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6888 */
6889static xmlSchemaParticlePtr
6890xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6891                  xmlNodePtr node)
6892{
6893    xmlSchemaParticlePtr particle;
6894    xmlNodePtr child = NULL;
6895    xmlSchemaWildcardPtr wild;
6896    int min, max;
6897    xmlAttrPtr attr;
6898    xmlSchemaAnnotPtr annot = NULL;
6899
6900    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6901        return (NULL);
6902    /*
6903    * Check for illegal attributes.
6904    */
6905    attr = node->properties;
6906    while (attr != NULL) {
6907	if (attr->ns == NULL) {
6908	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6909		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6910		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6911	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6912		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6913		xmlSchemaPIllegalAttrErr(ctxt,
6914		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6915	    }
6916	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6917	    xmlSchemaPIllegalAttrErr(ctxt,
6918		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6919	}
6920	attr = attr->next;
6921    }
6922    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6923    /*
6924    * minOccurs/maxOccurs.
6925    */
6926    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6927	"(xs:nonNegativeInteger | unbounded)");
6928    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6929	"xs:nonNegativeInteger");
6930    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6931    /*
6932    * Create & parse the wildcard.
6933    */
6934    wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6935    if (wild == NULL)
6936	return (NULL);
6937    xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6938    /*
6939    * And now for the children...
6940    */
6941    child = node->children;
6942    if (IS_SCHEMA(child, "annotation")) {
6943        annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6944        child = child->next;
6945    }
6946    if (child != NULL) {
6947	xmlSchemaPContentErr(ctxt,
6948	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6949	    NULL, node, child,
6950	    NULL, "(annotation?)");
6951    }
6952    /*
6953    * No component if minOccurs==maxOccurs==0.
6954    */
6955    if ((min == 0) && (max == 0)) {
6956	/* Don't free the wildcard, since it's already on the list. */
6957	return (NULL);
6958    }
6959    /*
6960    * Create the particle.
6961    */
6962    particle = xmlSchemaAddParticle(ctxt, node, min, max);
6963    if (particle == NULL)
6964        return (NULL);
6965    particle->annot = annot;
6966    particle->children = (xmlSchemaTreeItemPtr) wild;
6967
6968    return (particle);
6969}
6970
6971/**
6972 * xmlSchemaParseNotation:
6973 * @ctxt:  a schema validation context
6974 * @schema:  the schema being built
6975 * @node:  a subtree containing XML Schema informations
6976 *
6977 * parse a XML schema Notation declaration
6978 *
6979 * Returns the new structure or NULL in case of error
6980 */
6981static xmlSchemaNotationPtr
6982xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6983                       xmlNodePtr node)
6984{
6985    const xmlChar *name;
6986    xmlSchemaNotationPtr ret;
6987    xmlNodePtr child = NULL;
6988
6989    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6990        return (NULL);
6991    name = xmlSchemaGetProp(ctxt, node, "name");
6992    if (name == NULL) {
6993        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6994                       "Notation has no name\n", NULL, NULL);
6995        return (NULL);
6996    }
6997    ret = xmlSchemaAddNotation(ctxt, schema, name,
6998	ctxt->targetNamespace, node);
6999    if (ret == NULL)
7000        return (NULL);
7001    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7002
7003    child = node->children;
7004    if (IS_SCHEMA(child, "annotation")) {
7005        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7006        child = child->next;
7007    }
7008    if (child != NULL) {
7009	xmlSchemaPContentErr(ctxt,
7010	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7011	    NULL, node, child,
7012	    NULL, "(annotation?)");
7013    }
7014
7015    return (ret);
7016}
7017
7018/**
7019 * xmlSchemaParseAnyAttribute:
7020 * @ctxt:  a schema validation context
7021 * @schema:  the schema being built
7022 * @node:  a subtree containing XML Schema informations
7023 *
7024 * parse a XML schema AnyAttrribute declaration
7025 * *WARNING* this interface is highly subject to change
7026 *
7027 * Returns a wildcard or NULL.
7028 */
7029static xmlSchemaWildcardPtr
7030xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7031                           xmlSchemaPtr schema, xmlNodePtr node)
7032{
7033    xmlSchemaWildcardPtr ret;
7034    xmlNodePtr child = NULL;
7035    xmlAttrPtr attr;
7036
7037    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7038        return (NULL);
7039
7040    ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7041	node);
7042    if (ret == NULL) {
7043        return (NULL);
7044    }
7045    /*
7046    * Check for illegal attributes.
7047    */
7048    attr = node->properties;
7049    while (attr != NULL) {
7050	if (attr->ns == NULL) {
7051	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7052	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7053		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7054		xmlSchemaPIllegalAttrErr(ctxt,
7055		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7056	    }
7057	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7058	    xmlSchemaPIllegalAttrErr(ctxt,
7059		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7060	}
7061	attr = attr->next;
7062    }
7063    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7064    /*
7065    * Parse the namespace list.
7066    */
7067    if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7068	return (NULL);
7069    /*
7070    * And now for the children...
7071    */
7072    child = node->children;
7073    if (IS_SCHEMA(child, "annotation")) {
7074        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7075        child = child->next;
7076    }
7077    if (child != NULL) {
7078	xmlSchemaPContentErr(ctxt,
7079	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7080	    NULL, node, child,
7081	    NULL, "(annotation?)");
7082    }
7083
7084    return (ret);
7085}
7086
7087
7088/**
7089 * xmlSchemaParseAttribute:
7090 * @ctxt:  a schema validation context
7091 * @schema:  the schema being built
7092 * @node:  a subtree containing XML Schema informations
7093 *
7094 * parse a XML schema Attrribute declaration
7095 * *WARNING* this interface is highly subject to change
7096 *
7097 * Returns the attribute declaration.
7098 */
7099static xmlSchemaBasicItemPtr
7100xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7101			     xmlSchemaPtr schema,
7102			     xmlNodePtr node,
7103			     xmlSchemaItemListPtr uses,
7104			     int parentType)
7105{
7106    const xmlChar *attrValue, *name = NULL, *ns = NULL;
7107    xmlSchemaAttributeUsePtr use = NULL;
7108    xmlNodePtr child = NULL;
7109    xmlAttrPtr attr;
7110    const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7111    int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7112    int	nberrors, hasForm = 0, defValueType = 0;
7113
7114#define WXS_ATTR_DEF_VAL_DEFAULT 1
7115#define WXS_ATTR_DEF_VAL_FIXED 2
7116
7117    /*
7118     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7119     */
7120
7121    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7122        return (NULL);
7123    attr = xmlSchemaGetPropNode(node, "ref");
7124    if (attr != NULL) {
7125	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7126	    NULL, attr, &tmpNs, &tmpName) != 0) {
7127	    return (NULL);
7128	}
7129	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7130	    return(NULL);
7131	isRef = 1;
7132    }
7133    nberrors = pctxt->nberrors;
7134    /*
7135    * Check for illegal attributes.
7136    */
7137    attr = node->properties;
7138    while (attr != NULL) {
7139	if (attr->ns == NULL) {
7140	    if (isRef) {
7141		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7142		    xmlSchemaPValAttrNodeID(pctxt, attr);
7143		    goto attr_next;
7144		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7145		    goto attr_next;
7146		}
7147	    } else {
7148		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7149		    goto attr_next;
7150		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7151		    xmlSchemaPValAttrNodeID(pctxt, attr);
7152		    goto attr_next;
7153		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7154		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7155			attr, &tmpNs, &tmpName);
7156		    goto attr_next;
7157		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7158		    /*
7159		    * Evaluate the target namespace
7160		    */
7161		    hasForm = 1;
7162		    attrValue = xmlSchemaGetNodeContent(pctxt,
7163			(xmlNodePtr) attr);
7164		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7165			ns = pctxt->targetNamespace;
7166		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7167		    {
7168			xmlSchemaPSimpleTypeErr(pctxt,
7169			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7170			    NULL, (xmlNodePtr) attr,
7171			    NULL, "(qualified | unqualified)",
7172			    attrValue, NULL, NULL, NULL);
7173		    }
7174		    goto attr_next;
7175		}
7176	    }
7177	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7178
7179		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7180		/* TODO: Maybe we need to normalize the value beforehand. */
7181		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7182		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7183		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7184		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7185		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7186		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7187		else {
7188		    xmlSchemaPSimpleTypeErr(pctxt,
7189			XML_SCHEMAP_INVALID_ATTR_USE,
7190			NULL, (xmlNodePtr) attr,
7191			NULL, "(optional | prohibited | required)",
7192			attrValue, NULL, NULL, NULL);
7193		}
7194		goto attr_next;
7195	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7196		/*
7197		* 3.2.3 : 1
7198		* default and fixed must not both be present.
7199		*/
7200		if (defValue) {
7201		    xmlSchemaPMutualExclAttrErr(pctxt,
7202			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7203			NULL, attr, "default", "fixed");
7204		} else {
7205		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7206		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7207		}
7208		goto attr_next;
7209	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7210		/*
7211		* 3.2.3 : 1
7212		* default and fixed must not both be present.
7213		*/
7214		if (defValue) {
7215		    xmlSchemaPMutualExclAttrErr(pctxt,
7216			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7217			NULL, attr, "default", "fixed");
7218		} else {
7219		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7220		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7221		}
7222		goto attr_next;
7223	    }
7224	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7225	    goto attr_next;
7226
7227	xmlSchemaPIllegalAttrErr(pctxt,
7228	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7229
7230attr_next:
7231	attr = attr->next;
7232    }
7233    /*
7234    * 3.2.3 : 2
7235    * If default and use are both present, use must have
7236    * the actual value optional.
7237    */
7238    if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7239	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7240	xmlSchemaPSimpleTypeErr(pctxt,
7241	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7242	    NULL, node, NULL,
7243	    "(optional | prohibited | required)", NULL,
7244	    "The value of the attribute 'use' must be 'optional' "
7245	    "if the attribute 'default' is present",
7246	    NULL, NULL);
7247    }
7248    /*
7249    * We want correct attributes.
7250    */
7251    if (nberrors != pctxt->nberrors)
7252	return(NULL);
7253    if (! isRef) {
7254	xmlSchemaAttributePtr attrDecl;
7255
7256	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7257	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7258	    ns = pctxt->targetNamespace;
7259	/*
7260	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7261	* TODO: Move this to the component layer.
7262	*/
7263	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7264	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7265		XML_SCHEMAP_NO_XSI,
7266		node, NULL,
7267		"The target namespace must not match '%s'",
7268		xmlSchemaInstanceNs, NULL);
7269	}
7270	attr = xmlSchemaGetPropNode(node, "name");
7271	if (attr == NULL) {
7272	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7273		NULL, node, "name", NULL);
7274	    return (NULL);
7275	}
7276	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7277	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7278	    return (NULL);
7279	}
7280	/*
7281	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7282	* TODO: Move this to the component layer.
7283	*/
7284	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7285	    xmlSchemaPSimpleTypeErr(pctxt,
7286		XML_SCHEMAP_NO_XMLNS,
7287		NULL, (xmlNodePtr) attr,
7288		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7289		"The value of the attribute must not match 'xmlns'",
7290		NULL, NULL);
7291	    return (NULL);
7292	}
7293	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7294	    goto check_children;
7295	/*
7296	* Create the attribute use component.
7297	*/
7298	use = xmlSchemaAddAttributeUse(pctxt, node);
7299	if (use == NULL)
7300	    return(NULL);
7301	use->occurs = occurs;
7302	/*
7303	* Create the attribute declaration.
7304	*/
7305	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7306	if (attrDecl == NULL)
7307	    return (NULL);
7308	if (tmpName != NULL) {
7309	    attrDecl->typeName = tmpName;
7310	    attrDecl->typeNs = tmpNs;
7311	}
7312	use->attrDecl = attrDecl;
7313	/*
7314	* Value constraint.
7315	*/
7316	if (defValue != NULL) {
7317	    attrDecl->defValue = defValue;
7318	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7319		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7320	}
7321    } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7322	xmlSchemaQNameRefPtr ref;
7323
7324	/*
7325	* Create the attribute use component.
7326	*/
7327	use = xmlSchemaAddAttributeUse(pctxt, node);
7328	if (use == NULL)
7329	    return(NULL);
7330	/*
7331	* We need to resolve the reference at later stage.
7332	*/
7333	WXS_ADD_PENDING(pctxt, use);
7334	use->occurs = occurs;
7335	/*
7336	* Create a QName reference to the attribute declaration.
7337	*/
7338	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7339	    tmpName, tmpNs);
7340	if (ref == NULL)
7341	    return(NULL);
7342	/*
7343	* Assign the reference. This will be substituted for the
7344	* referenced attribute declaration when the QName is resolved.
7345	*/
7346	use->attrDecl = WXS_ATTR_CAST ref;
7347	/*
7348	* Value constraint.
7349	*/
7350	if (defValue != NULL)
7351	    use->defValue = defValue;
7352	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7353		use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7354    }
7355
7356check_children:
7357    /*
7358    * And now for the children...
7359    */
7360    child = node->children;
7361    if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7362	xmlSchemaAttributeUseProhibPtr prohib;
7363
7364	if (IS_SCHEMA(child, "annotation")) {
7365	    xmlSchemaParseAnnotation(pctxt, child, 0);
7366	    child = child->next;
7367	}
7368	if (child != NULL) {
7369	    xmlSchemaPContentErr(pctxt,
7370		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7371		NULL, node, child, NULL,
7372		"(annotation?)");
7373	}
7374	/*
7375	* Check for pointlessness of attribute prohibitions.
7376	*/
7377	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7378	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7379		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7380		node, NULL,
7381		"Skipping attribute use prohibition, since it is "
7382		"pointless inside an <attributeGroup>",
7383		NULL, NULL, NULL);
7384	    return(NULL);
7385	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7386	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7387		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7388		node, NULL,
7389		"Skipping attribute use prohibition, since it is "
7390		"pointless when extending a type",
7391		NULL, NULL, NULL);
7392	    return(NULL);
7393	}
7394	if (! isRef) {
7395	    tmpName = name;
7396	    tmpNs = ns;
7397	}
7398	/*
7399	* Check for duplicate attribute prohibitions.
7400	*/
7401	if (uses) {
7402	    int i;
7403
7404	    for (i = 0; i < uses->nbItems; i++) {
7405		use = uses->items[i];
7406		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7407		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7408		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7409		{
7410		    xmlChar *str = NULL;
7411
7412		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7413			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7414			node, NULL,
7415			"Skipping duplicate attribute use prohibition '%s'",
7416			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7417			NULL, NULL);
7418		    FREE_AND_NULL(str)
7419		    return(NULL);
7420		}
7421	    }
7422	}
7423	/*
7424	* Create the attribute prohibition helper component.
7425	*/
7426	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7427	if (prohib == NULL)
7428	    return(NULL);
7429	prohib->node = node;
7430	prohib->name = tmpName;
7431	prohib->targetNamespace = tmpNs;
7432	if (isRef) {
7433	    /*
7434	    * We need at least to resolve to the attribute declaration.
7435	    */
7436	    WXS_ADD_PENDING(pctxt, prohib);
7437	}
7438	return(WXS_BASIC_CAST prohib);
7439    } else {
7440	if (IS_SCHEMA(child, "annotation")) {
7441	    /*
7442	    * TODO: Should this go into the attr decl?
7443	    */
7444	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7445	    child = child->next;
7446	}
7447	if (isRef) {
7448	    if (child != NULL) {
7449		if (IS_SCHEMA(child, "simpleType"))
7450		    /*
7451		    * 3.2.3 : 3.2
7452		    * If ref is present, then all of <simpleType>,
7453		    * form and type must be absent.
7454		    */
7455		    xmlSchemaPContentErr(pctxt,
7456			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7457			NULL, node, child, NULL,
7458			"(annotation?)");
7459		else
7460		    xmlSchemaPContentErr(pctxt,
7461			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7462			NULL, node, child, NULL,
7463			"(annotation?)");
7464	    }
7465	} else {
7466	    if (IS_SCHEMA(child, "simpleType")) {
7467		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7468		    /*
7469		    * 3.2.3 : 4
7470		    * type and <simpleType> must not both be present.
7471		    */
7472		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7473			NULL, node, child,
7474			"The attribute 'type' and the <simpleType> child "
7475			"are mutually exclusive", NULL);
7476		} else
7477		    WXS_ATTRUSE_TYPEDEF(use) =
7478			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7479		child = child->next;
7480	    }
7481	    if (child != NULL)
7482		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7483		NULL, node, child, NULL,
7484		"(annotation?, simpleType?)");
7485	}
7486    }
7487    return (WXS_BASIC_CAST use);
7488}
7489
7490
7491static xmlSchemaAttributePtr
7492xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7493			      xmlSchemaPtr schema,
7494			      xmlNodePtr node)
7495{
7496    const xmlChar *attrValue;
7497    xmlSchemaAttributePtr ret;
7498    xmlNodePtr child = NULL;
7499    xmlAttrPtr attr;
7500
7501    /*
7502     * Note that the w3c spec assumes the schema to be validated with schema
7503     * for schemas beforehand.
7504     *
7505     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7506     */
7507    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7508        return (NULL);
7509    /*
7510    * 3.2.3 : 3.1
7511    * One of ref or name must be present, but not both
7512    */
7513    attr = xmlSchemaGetPropNode(node, "name");
7514    if (attr == NULL) {
7515	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7516	    NULL, node, "name", NULL);
7517	return (NULL);
7518    }
7519    if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7520	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7521	return (NULL);
7522    }
7523    /*
7524    * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7525    * TODO: Move this to the component layer.
7526    */
7527    if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7528	xmlSchemaPSimpleTypeErr(pctxt,
7529	    XML_SCHEMAP_NO_XMLNS,
7530	    NULL, (xmlNodePtr) attr,
7531	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7532	    "The value of the attribute must not match 'xmlns'",
7533	    NULL, NULL);
7534	return (NULL);
7535    }
7536    /*
7537    * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7538    * TODO: Move this to the component layer.
7539    *       Or better leave it here and add it to the component layer
7540    *       if we have a schema construction API.
7541    */
7542    if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7543	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7544	    XML_SCHEMAP_NO_XSI, node, NULL,
7545	    "The target namespace must not match '%s'",
7546	    xmlSchemaInstanceNs, NULL);
7547    }
7548
7549    ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7550	pctxt->targetNamespace, node, 1);
7551    if (ret == NULL)
7552	return (NULL);
7553    ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7554
7555    /*
7556    * Check for illegal attributes.
7557    */
7558    attr = node->properties;
7559    while (attr != NULL) {
7560	if (attr->ns == NULL) {
7561	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7562		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7563		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7564		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7565		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7566	    {
7567		xmlSchemaPIllegalAttrErr(pctxt,
7568		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7569	    }
7570	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7571	    xmlSchemaPIllegalAttrErr(pctxt,
7572		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7573	}
7574	attr = attr->next;
7575    }
7576    xmlSchemaPValAttrQName(pctxt, schema, NULL,
7577	node, "type", &ret->typeNs, &ret->typeName);
7578
7579    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7580    /*
7581    * Attribute "fixed".
7582    */
7583    ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7584    if (ret->defValue != NULL)
7585	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7586    /*
7587    * Attribute "default".
7588    */
7589    attr = xmlSchemaGetPropNode(node, "default");
7590    if (attr != NULL) {
7591	/*
7592	* 3.2.3 : 1
7593	* default and fixed must not both be present.
7594	*/
7595	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7596	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7597		WXS_BASIC_CAST ret, attr, "default", "fixed");
7598	} else
7599	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7600    }
7601    /*
7602    * And now for the children...
7603    */
7604    child = node->children;
7605    if (IS_SCHEMA(child, "annotation")) {
7606        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7607        child = child->next;
7608    }
7609    if (IS_SCHEMA(child, "simpleType")) {
7610	if (ret->typeName != NULL) {
7611	    /*
7612	    * 3.2.3 : 4
7613	    * type and <simpleType> must not both be present.
7614	    */
7615	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7616		NULL, node, child,
7617		"The attribute 'type' and the <simpleType> child "
7618		"are mutually exclusive", NULL);
7619	} else
7620	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7621	child = child->next;
7622    }
7623    if (child != NULL)
7624	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7625	    NULL, node, child, NULL,
7626	    "(annotation?, simpleType?)");
7627
7628    return (ret);
7629}
7630
7631/**
7632 * xmlSchemaParseAttributeGroupRef:
7633 * @ctxt:  a schema validation context
7634 * @schema:  the schema being built
7635 * @node:  a subtree containing XML Schema informations
7636 *
7637 * Parse an attribute group definition reference.
7638 * Note that a reference to an attribute group does not
7639 * correspond to any component at all.
7640 * *WARNING* this interface is highly subject to change
7641 *
7642 * Returns the attribute group or NULL in case of error.
7643 */
7644static xmlSchemaQNameRefPtr
7645xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7646				xmlSchemaPtr schema,
7647				xmlNodePtr node)
7648{
7649    xmlSchemaQNameRefPtr ret;
7650    xmlNodePtr child = NULL;
7651    xmlAttrPtr attr;
7652    const xmlChar *refNs = NULL, *ref = NULL;
7653
7654    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7655        return (NULL);
7656
7657    attr = xmlSchemaGetPropNode(node, "ref");
7658    if (attr == NULL) {
7659	xmlSchemaPMissingAttrErr(pctxt,
7660	    XML_SCHEMAP_S4S_ATTR_MISSING,
7661	    NULL, node, "ref", NULL);
7662	return (NULL);
7663    }
7664    xmlSchemaPValAttrNodeQName(pctxt, schema,
7665	NULL, attr, &refNs, &ref);
7666    if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7667	return(NULL);
7668
7669    /*
7670    * Check for illegal attributes.
7671    */
7672    attr = node->properties;
7673    while (attr != NULL) {
7674	if (attr->ns == NULL) {
7675	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7676		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7677	    {
7678		xmlSchemaPIllegalAttrErr(pctxt,
7679		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7680	    }
7681	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7682	    xmlSchemaPIllegalAttrErr(pctxt,
7683		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7684	}
7685	attr = attr->next;
7686    }
7687    /* Attribute ID */
7688    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7689
7690    /*
7691    * And now for the children...
7692    */
7693    child = node->children;
7694    if (IS_SCHEMA(child, "annotation")) {
7695	/*
7696	* TODO: We do not have a place to store the annotation, do we?
7697	*/
7698        xmlSchemaParseAnnotation(pctxt, child, 0);
7699        child = child->next;
7700    }
7701    if (child != NULL) {
7702	xmlSchemaPContentErr(pctxt,
7703	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7704	    NULL, node, child, NULL,
7705	    "(annotation?)");
7706    }
7707
7708    /*
7709    * Handle attribute group redefinitions.
7710    */
7711    if (pctxt->isRedefine && pctxt->redef &&
7712	(pctxt->redef->item->type ==
7713	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7714	(ref == pctxt->redef->refName) &&
7715	(refNs == pctxt->redef->refTargetNs))
7716    {
7717	/*
7718	* SPEC src-redefine:
7719	* (7.1) "If it has an <attributeGroup> among its contents
7720	* the �actual value� of whose ref [attribute] is the same
7721	* as the �actual value� of its own name attribute plus
7722	* target namespace, then it must have exactly one such group."
7723	*/
7724	if (pctxt->redefCounter != 0) {
7725	    xmlChar *str = NULL;
7726
7727	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7728		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7729		"The redefining attribute group definition "
7730		"'%s' must not contain more than one "
7731		"reference to the redefined definition",
7732		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7733	    FREE_AND_NULL(str);
7734	    return(NULL);
7735	}
7736	pctxt->redefCounter++;
7737	/*
7738	* URGENT TODO: How to ensure that the reference will not be
7739	* handled by the normal component resolution mechanism?
7740	*/
7741	ret = xmlSchemaNewQNameRef(pctxt,
7742	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7743	if (ret == NULL)
7744	    return(NULL);
7745	ret->node = node;
7746	pctxt->redef->reference = WXS_BASIC_CAST ret;
7747    } else {
7748	/*
7749	* Create a QName-reference helper component. We will substitute this
7750	* component for the attribute uses of the referenced attribute group
7751	* definition.
7752	*/
7753	ret = xmlSchemaNewQNameRef(pctxt,
7754	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7755	if (ret == NULL)
7756	    return(NULL);
7757	ret->node = node;
7758	/* Add to pending items, to be able to resolve the reference. */
7759	WXS_ADD_PENDING(pctxt, ret);
7760    }
7761    return (ret);
7762}
7763
7764/**
7765 * xmlSchemaParseAttributeGroupDefinition:
7766 * @pctxt:  a schema validation context
7767 * @schema:  the schema being built
7768 * @node:  a subtree containing XML Schema informations
7769 *
7770 * parse a XML schema Attribute Group declaration
7771 * *WARNING* this interface is highly subject to change
7772 *
7773 * Returns the attribute group definition or NULL in case of error.
7774 */
7775static xmlSchemaAttributeGroupPtr
7776xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7777				       xmlSchemaPtr schema,
7778				       xmlNodePtr node)
7779{
7780    const xmlChar *name;
7781    xmlSchemaAttributeGroupPtr ret;
7782    xmlNodePtr child = NULL;
7783    xmlAttrPtr attr;
7784    int hasRefs = 0;
7785
7786    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7787        return (NULL);
7788
7789    attr = xmlSchemaGetPropNode(node, "name");
7790    if (attr == NULL) {
7791	xmlSchemaPMissingAttrErr(pctxt,
7792	    XML_SCHEMAP_S4S_ATTR_MISSING,
7793	    NULL, node, "name", NULL);
7794	return (NULL);
7795    }
7796    /*
7797    * The name is crucial, exit if invalid.
7798    */
7799    if (xmlSchemaPValAttrNode(pctxt,
7800	NULL, attr,
7801	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7802	return (NULL);
7803    }
7804    ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7805	name, pctxt->targetNamespace, node);
7806    if (ret == NULL)
7807	return (NULL);
7808    /*
7809    * Check for illegal attributes.
7810    */
7811    attr = node->properties;
7812    while (attr != NULL) {
7813	if (attr->ns == NULL) {
7814	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7815		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7816	    {
7817		xmlSchemaPIllegalAttrErr(pctxt,
7818		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7819	    }
7820	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7821	    xmlSchemaPIllegalAttrErr(pctxt,
7822		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7823	}
7824	attr = attr->next;
7825    }
7826    /* Attribute ID */
7827    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7828    /*
7829    * And now for the children...
7830    */
7831    child = node->children;
7832    if (IS_SCHEMA(child, "annotation")) {
7833        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7834        child = child->next;
7835    }
7836    /*
7837    * Parse contained attribute decls/refs.
7838    */
7839    if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7840	(xmlSchemaItemListPtr *) &(ret->attrUses),
7841	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7842	return(NULL);
7843    if (hasRefs)
7844	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7845    /*
7846    * Parse the attribute wildcard.
7847    */
7848    if (IS_SCHEMA(child, "anyAttribute")) {
7849	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7850	    schema, child);
7851	child = child->next;
7852    }
7853    if (child != NULL) {
7854	xmlSchemaPContentErr(pctxt,
7855	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7856	    NULL, node, child, NULL,
7857	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7858    }
7859    return (ret);
7860}
7861
7862/**
7863 * xmlSchemaPValAttrFormDefault:
7864 * @value:  the value
7865 * @flags: the flags to be modified
7866 * @flagQualified: the specific flag for "qualified"
7867 *
7868 * Returns 0 if the value is valid, 1 otherwise.
7869 */
7870static int
7871xmlSchemaPValAttrFormDefault(const xmlChar *value,
7872			     int *flags,
7873			     int flagQualified)
7874{
7875    if (xmlStrEqual(value, BAD_CAST "qualified")) {
7876	if  ((*flags & flagQualified) == 0)
7877	    *flags |= flagQualified;
7878    } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7879	return (1);
7880
7881    return (0);
7882}
7883
7884/**
7885 * xmlSchemaPValAttrBlockFinal:
7886 * @value:  the value
7887 * @flags: the flags to be modified
7888 * @flagAll: the specific flag for "#all"
7889 * @flagExtension: the specific flag for "extension"
7890 * @flagRestriction: the specific flag for "restriction"
7891 * @flagSubstitution: the specific flag for "substitution"
7892 * @flagList: the specific flag for "list"
7893 * @flagUnion: the specific flag for "union"
7894 *
7895 * Validates the value of the attribute "final" and "block". The value
7896 * is converted into the specified flag values and returned in @flags.
7897 *
7898 * Returns 0 if the value is valid, 1 otherwise.
7899 */
7900
7901static int
7902xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7903			    int *flags,
7904			    int flagAll,
7905			    int flagExtension,
7906			    int flagRestriction,
7907			    int flagSubstitution,
7908			    int flagList,
7909			    int flagUnion)
7910{
7911    int ret = 0;
7912
7913    /*
7914    * TODO: This does not check for dublicate entries.
7915    */
7916    if ((flags == NULL) || (value == NULL))
7917	return (-1);
7918    if (value[0] == 0)
7919	return (0);
7920    if (xmlStrEqual(value, BAD_CAST "#all")) {
7921	if (flagAll != -1)
7922	    *flags |= flagAll;
7923	else {
7924	    if (flagExtension != -1)
7925		*flags |= flagExtension;
7926	    if (flagRestriction != -1)
7927		*flags |= flagRestriction;
7928	    if (flagSubstitution != -1)
7929		*flags |= flagSubstitution;
7930	    if (flagList != -1)
7931		*flags |= flagList;
7932	    if (flagUnion != -1)
7933		*flags |= flagUnion;
7934	}
7935    } else {
7936	const xmlChar *end, *cur = value;
7937	xmlChar *item;
7938
7939	do {
7940	    while (IS_BLANK_CH(*cur))
7941		cur++;
7942	    end = cur;
7943	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7944		end++;
7945	    if (end == cur)
7946		break;
7947	    item = xmlStrndup(cur, end - cur);
7948	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7949		if (flagExtension != -1) {
7950		    if ((*flags & flagExtension) == 0)
7951			*flags |= flagExtension;
7952		} else
7953		    ret = 1;
7954	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7955		if (flagRestriction != -1) {
7956		    if ((*flags & flagRestriction) == 0)
7957			*flags |= flagRestriction;
7958		} else
7959		    ret = 1;
7960	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7961		if (flagSubstitution != -1) {
7962		    if ((*flags & flagSubstitution) == 0)
7963			*flags |= flagSubstitution;
7964		} else
7965		    ret = 1;
7966	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
7967		if (flagList != -1) {
7968		    if ((*flags & flagList) == 0)
7969			*flags |= flagList;
7970		} else
7971		    ret = 1;
7972	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
7973		if (flagUnion != -1) {
7974		    if ((*flags & flagUnion) == 0)
7975			*flags |= flagUnion;
7976		} else
7977		    ret = 1;
7978	    } else
7979		ret = 1;
7980	    if (item != NULL)
7981		xmlFree(item);
7982	    cur = end;
7983	} while ((ret == 0) && (*cur != 0));
7984    }
7985
7986    return (ret);
7987}
7988
7989static int
7990xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7991			     xmlSchemaIDCPtr idc,
7992			     xmlSchemaIDCSelectPtr selector,
7993			     xmlAttrPtr attr,
7994			     int isField)
7995{
7996    xmlNodePtr node;
7997
7998    /*
7999    * c-selector-xpath:
8000    * Schema Component Constraint: Selector Value OK
8001    *
8002    * TODO: 1 The {selector} must be a valid XPath expression, as defined
8003    * in [XPath].
8004    */
8005    if (selector == NULL) {
8006	xmlSchemaPErr(ctxt, idc->node,
8007	    XML_SCHEMAP_INTERNAL,
8008	    "Internal error: xmlSchemaCheckCSelectorXPath, "
8009	    "the selector is not specified.\n", NULL, NULL);
8010	return (-1);
8011    }
8012    if (attr == NULL)
8013	node = idc->node;
8014    else
8015	node = (xmlNodePtr) attr;
8016    if (selector->xpath == NULL) {
8017	xmlSchemaPCustomErr(ctxt,
8018	    /* TODO: Adjust error code. */
8019	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8020	    NULL, node,
8021	    "The XPath expression of the selector is not valid", NULL);
8022	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8023    } else {
8024	const xmlChar **nsArray = NULL;
8025	xmlNsPtr *nsList = NULL;
8026	/*
8027	* Compile the XPath expression.
8028	*/
8029	/*
8030	* TODO: We need the array of in-scope namespaces for compilation.
8031	* TODO: Call xmlPatterncompile with different options for selector/
8032	* field.
8033	*/
8034	if (attr == NULL)
8035	    nsList = NULL;
8036	else
8037	    nsList = xmlGetNsList(attr->doc, attr->parent);
8038	/*
8039	* Build an array of prefixes and namespaces.
8040	*/
8041	if (nsList != NULL) {
8042	    int i, count = 0;
8043
8044	    for (i = 0; nsList[i] != NULL; i++)
8045		count++;
8046
8047	    nsArray = (const xmlChar **) xmlMalloc(
8048		(count * 2 + 1) * sizeof(const xmlChar *));
8049	    if (nsArray == NULL) {
8050		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8051		    NULL);
8052		xmlFree(nsList);
8053		return (-1);
8054	    }
8055	    for (i = 0; i < count; i++) {
8056		nsArray[2 * i] = nsList[i]->href;
8057		nsArray[2 * i + 1] = nsList[i]->prefix;
8058	    }
8059	    nsArray[count * 2] = NULL;
8060	    xmlFree(nsList);
8061	}
8062	/*
8063	* TODO: Differentiate between "selector" and "field".
8064	*/
8065	if (isField)
8066	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8067		NULL, XML_PATTERN_XSFIELD, nsArray);
8068	else
8069	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8070		NULL, XML_PATTERN_XSSEL, nsArray);
8071	if (nsArray != NULL)
8072	    xmlFree((xmlChar **) nsArray);
8073
8074	if (selector->xpathComp == NULL) {
8075	    xmlSchemaPCustomErr(ctxt,
8076		/* TODO: Adjust error code? */
8077		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8078		NULL, node,
8079		"The XPath expression '%s' could not be "
8080		"compiled", selector->xpath);
8081	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8082	}
8083    }
8084    return (0);
8085}
8086
8087#define ADD_ANNOTATION(annot)   \
8088    xmlSchemaAnnotPtr cur = item->annot; \
8089    if (item->annot == NULL) {  \
8090	item->annot = annot;    \
8091	return (annot);         \
8092    }                           \
8093    cur = item->annot;          \
8094    if (cur->next != NULL) {    \
8095	cur = cur->next;	\
8096    }                           \
8097    cur->next = annot;
8098
8099/**
8100 * xmlSchemaAssignAnnotation:
8101 * @item: the schema component
8102 * @annot: the annotation
8103 *
8104 * Adds the annotation to the given schema component.
8105 *
8106 * Returns the given annotaion.
8107 */
8108static xmlSchemaAnnotPtr
8109xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8110		       xmlSchemaAnnotPtr annot)
8111{
8112    if ((annItem == NULL) || (annot == NULL))
8113	return (NULL);
8114    switch (annItem->type) {
8115	case XML_SCHEMA_TYPE_ELEMENT: {
8116		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8117		ADD_ANNOTATION(annot)
8118	    }
8119	    break;
8120	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8121		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8122		ADD_ANNOTATION(annot)
8123	    }
8124	    break;
8125	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8126	case XML_SCHEMA_TYPE_ANY: {
8127		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8128		ADD_ANNOTATION(annot)
8129	    }
8130	    break;
8131	case XML_SCHEMA_TYPE_PARTICLE:
8132	case XML_SCHEMA_TYPE_IDC_KEY:
8133	case XML_SCHEMA_TYPE_IDC_KEYREF:
8134	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8135		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8136		ADD_ANNOTATION(annot)
8137	    }
8138	    break;
8139	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8140		xmlSchemaAttributeGroupPtr item =
8141		    (xmlSchemaAttributeGroupPtr) annItem;
8142		ADD_ANNOTATION(annot)
8143	    }
8144	    break;
8145	case XML_SCHEMA_TYPE_NOTATION: {
8146		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8147		ADD_ANNOTATION(annot)
8148	    }
8149	    break;
8150	case XML_SCHEMA_FACET_MININCLUSIVE:
8151	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8152	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8153	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8154	case XML_SCHEMA_FACET_TOTALDIGITS:
8155	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8156	case XML_SCHEMA_FACET_PATTERN:
8157	case XML_SCHEMA_FACET_ENUMERATION:
8158	case XML_SCHEMA_FACET_WHITESPACE:
8159	case XML_SCHEMA_FACET_LENGTH:
8160	case XML_SCHEMA_FACET_MAXLENGTH:
8161	case XML_SCHEMA_FACET_MINLENGTH: {
8162		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8163		ADD_ANNOTATION(annot)
8164	    }
8165	    break;
8166	case XML_SCHEMA_TYPE_SIMPLE:
8167	case XML_SCHEMA_TYPE_COMPLEX: {
8168		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8169		ADD_ANNOTATION(annot)
8170	    }
8171	    break;
8172	case XML_SCHEMA_TYPE_GROUP: {
8173		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8174		ADD_ANNOTATION(annot)
8175	    }
8176	    break;
8177	case XML_SCHEMA_TYPE_SEQUENCE:
8178	case XML_SCHEMA_TYPE_CHOICE:
8179	case XML_SCHEMA_TYPE_ALL: {
8180		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8181		ADD_ANNOTATION(annot)
8182	    }
8183	    break;
8184	default:
8185	     xmlSchemaPCustomErr(NULL,
8186		XML_SCHEMAP_INTERNAL,
8187		NULL, NULL,
8188		"Internal error: xmlSchemaAddAnnotation, "
8189		"The item is not a annotated schema component", NULL);
8190	     break;
8191    }
8192    return (annot);
8193}
8194
8195/**
8196 * xmlSchemaParseIDCSelectorAndField:
8197 * @ctxt:  a schema validation context
8198 * @schema:  the schema being built
8199 * @node:  a subtree containing XML Schema informations
8200 *
8201 * Parses a XML Schema identity-contraint definition's
8202 * <selector> and <field> elements.
8203 *
8204 * Returns the parsed identity-constraint definition.
8205 */
8206static xmlSchemaIDCSelectPtr
8207xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8208			  xmlSchemaIDCPtr idc,
8209			  xmlNodePtr node,
8210			  int isField)
8211{
8212    xmlSchemaIDCSelectPtr item;
8213    xmlNodePtr child = NULL;
8214    xmlAttrPtr attr;
8215
8216    /*
8217    * Check for illegal attributes.
8218    */
8219    attr = node->properties;
8220    while (attr != NULL) {
8221	if (attr->ns == NULL) {
8222	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8223		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8224		xmlSchemaPIllegalAttrErr(ctxt,
8225		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8226	    }
8227	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8228	    xmlSchemaPIllegalAttrErr(ctxt,
8229		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8230	}
8231	attr = attr->next;
8232    }
8233    /*
8234    * Create the item.
8235    */
8236    item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8237    if (item == NULL) {
8238        xmlSchemaPErrMemory(ctxt,
8239	    "allocating a 'selector' of an identity-constraint definition",
8240	    NULL);
8241        return (NULL);
8242    }
8243    memset(item, 0, sizeof(xmlSchemaIDCSelect));
8244    /*
8245    * Attribute "xpath" (mandatory).
8246    */
8247    attr = xmlSchemaGetPropNode(node, "xpath");
8248    if (attr == NULL) {
8249	xmlSchemaPMissingAttrErr(ctxt,
8250	    XML_SCHEMAP_S4S_ATTR_MISSING,
8251	    NULL, node,
8252	    "name", NULL);
8253    } else {
8254	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8255	/*
8256	* URGENT TODO: "field"s have an other syntax than "selector"s.
8257	*/
8258
8259	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8260	    isField) == -1) {
8261	    xmlSchemaPErr(ctxt,
8262		(xmlNodePtr) attr,
8263		XML_SCHEMAP_INTERNAL,
8264		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8265		"validating the XPath expression of a IDC selector.\n",
8266		NULL, NULL);
8267	}
8268
8269    }
8270    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8271    /*
8272    * And now for the children...
8273    */
8274    child = node->children;
8275    if (IS_SCHEMA(child, "annotation")) {
8276	/*
8277	* Add the annotation to the parent IDC.
8278	*/
8279	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8280	    xmlSchemaParseAnnotation(ctxt, child, 1));
8281	child = child->next;
8282    }
8283    if (child != NULL) {
8284	xmlSchemaPContentErr(ctxt,
8285	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8286	    NULL, node, child,
8287	    NULL, "(annotation?)");
8288    }
8289
8290    return (item);
8291}
8292
8293/**
8294 * xmlSchemaParseIDC:
8295 * @ctxt:  a schema validation context
8296 * @schema:  the schema being built
8297 * @node:  a subtree containing XML Schema informations
8298 *
8299 * Parses a XML Schema identity-contraint definition.
8300 *
8301 * Returns the parsed identity-constraint definition.
8302 */
8303static xmlSchemaIDCPtr
8304xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8305		  xmlSchemaPtr schema,
8306		  xmlNodePtr node,
8307		  xmlSchemaTypeType idcCategory,
8308		  const xmlChar *targetNamespace)
8309{
8310    xmlSchemaIDCPtr item = NULL;
8311    xmlNodePtr child = NULL;
8312    xmlAttrPtr attr;
8313    const xmlChar *name = NULL;
8314    xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8315
8316    /*
8317    * Check for illegal attributes.
8318    */
8319    attr = node->properties;
8320    while (attr != NULL) {
8321	if (attr->ns == NULL) {
8322	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8323		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8324		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8325		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8326		xmlSchemaPIllegalAttrErr(ctxt,
8327		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8328	    }
8329	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8330	    xmlSchemaPIllegalAttrErr(ctxt,
8331		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8332	}
8333	attr = attr->next;
8334    }
8335    /*
8336    * Attribute "name" (mandatory).
8337    */
8338    attr = xmlSchemaGetPropNode(node, "name");
8339    if (attr == NULL) {
8340	xmlSchemaPMissingAttrErr(ctxt,
8341	    XML_SCHEMAP_S4S_ATTR_MISSING,
8342	    NULL, node,
8343	    "name", NULL);
8344	return (NULL);
8345    } else if (xmlSchemaPValAttrNode(ctxt,
8346	NULL, attr,
8347	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8348	return (NULL);
8349    }
8350    /* Create the component. */
8351    item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8352	idcCategory, node);
8353    if (item == NULL)
8354	return(NULL);
8355
8356    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8357    if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8358	/*
8359	* Attribute "refer" (mandatory).
8360	*/
8361	attr = xmlSchemaGetPropNode(node, "refer");
8362	if (attr == NULL) {
8363	    xmlSchemaPMissingAttrErr(ctxt,
8364		XML_SCHEMAP_S4S_ATTR_MISSING,
8365		NULL, node,
8366		"refer", NULL);
8367	} else {
8368	    /*
8369	    * Create a reference item.
8370	    */
8371	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8372		NULL, NULL);
8373	    if (item->ref == NULL)
8374		return (NULL);
8375	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8376		NULL, attr,
8377		&(item->ref->targetNamespace),
8378		&(item->ref->name));
8379	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8380		item->ref->targetNamespace);
8381	}
8382    }
8383    /*
8384    * And now for the children...
8385    */
8386    child = node->children;
8387    if (IS_SCHEMA(child, "annotation")) {
8388	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8389	child = child->next;
8390    }
8391    if (child == NULL) {
8392	xmlSchemaPContentErr(ctxt,
8393		XML_SCHEMAP_S4S_ELEM_MISSING,
8394		NULL, node, child,
8395		"A child element is missing",
8396		"(annotation?, (selector, field+))");
8397    }
8398    /*
8399    * Child element <selector>.
8400    */
8401    if (IS_SCHEMA(child, "selector")) {
8402	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8403	    item, child, 0);
8404	child = child->next;
8405	/*
8406	* Child elements <field>.
8407	*/
8408	if (IS_SCHEMA(child, "field")) {
8409	    do {
8410		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8411		    item, child, 1);
8412		if (field != NULL) {
8413		    field->index = item->nbFields;
8414		    item->nbFields++;
8415		    if (lastField != NULL)
8416			lastField->next = field;
8417		    else
8418			item->fields = field;
8419		    lastField = field;
8420		}
8421		child = child->next;
8422	    } while (IS_SCHEMA(child, "field"));
8423	} else {
8424	    xmlSchemaPContentErr(ctxt,
8425		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8426		NULL, node, child,
8427		NULL, "(annotation?, (selector, field+))");
8428	}
8429    }
8430    if (child != NULL) {
8431	xmlSchemaPContentErr(ctxt,
8432	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8433	    NULL, node, child,
8434	    NULL, "(annotation?, (selector, field+))");
8435    }
8436
8437    return (item);
8438}
8439
8440/**
8441 * xmlSchemaParseElement:
8442 * @ctxt:  a schema validation context
8443 * @schema:  the schema being built
8444 * @node:  a subtree containing XML Schema informations
8445 * @topLevel: indicates if this is global declaration
8446 *
8447 * Parses a XML schema element declaration.
8448 * *WARNING* this interface is highly subject to change
8449 *
8450 * Returns the element declaration or a particle; NULL in case
8451 * of an error or if the particle has minOccurs==maxOccurs==0.
8452 */
8453static xmlSchemaBasicItemPtr
8454xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8455                      xmlNodePtr node, int *isElemRef, int topLevel)
8456{
8457    xmlSchemaElementPtr decl = NULL;
8458    xmlSchemaParticlePtr particle = NULL;
8459    xmlSchemaAnnotPtr annot = NULL;
8460    xmlNodePtr child = NULL;
8461    xmlAttrPtr attr, nameAttr;
8462    int min, max, isRef = 0;
8463    xmlChar *des = NULL;
8464
8465    /* 3.3.3 Constraints on XML Representations of Element Declarations */
8466    /* TODO: Complete implementation of 3.3.6 */
8467
8468    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8469        return (NULL);
8470
8471    if (isElemRef != NULL)
8472	*isElemRef = 0;
8473    /*
8474    * If we get a "ref" attribute on a local <element> we will assume it's
8475    * a reference - even if there's a "name" attribute; this seems to be more
8476    * robust.
8477    */
8478    nameAttr = xmlSchemaGetPropNode(node, "name");
8479    attr = xmlSchemaGetPropNode(node, "ref");
8480    if ((topLevel) || (attr == NULL)) {
8481	if (nameAttr == NULL) {
8482	    xmlSchemaPMissingAttrErr(ctxt,
8483		XML_SCHEMAP_S4S_ATTR_MISSING,
8484		NULL, node, "name", NULL);
8485	    return (NULL);
8486	}
8487    } else
8488	isRef = 1;
8489
8490    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8491    child = node->children;
8492    if (IS_SCHEMA(child, "annotation")) {
8493	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8494	child = child->next;
8495    }
8496    /*
8497    * Skip particle part if a global declaration.
8498    */
8499    if (topLevel)
8500	goto declaration_part;
8501    /*
8502    * The particle part ==================================================
8503    */
8504    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8505    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8506    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8507    particle = xmlSchemaAddParticle(ctxt, node, min, max);
8508    if (particle == NULL)
8509	goto return_null;
8510
8511    /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8512
8513    if (isRef) {
8514	const xmlChar *refNs = NULL, *ref = NULL;
8515	xmlSchemaQNameRefPtr refer = NULL;
8516	/*
8517	* The reference part =============================================
8518	*/
8519	if (isElemRef != NULL)
8520	    *isElemRef = 1;
8521
8522	xmlSchemaPValAttrNodeQName(ctxt, schema,
8523	    NULL, attr, &refNs, &ref);
8524	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8525	/*
8526	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8527	*/
8528	if (nameAttr != NULL) {
8529	    xmlSchemaPMutualExclAttrErr(ctxt,
8530		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8531	}
8532	/*
8533	* Check for illegal attributes.
8534	*/
8535	attr = node->properties;
8536	while (attr != NULL) {
8537	    if (attr->ns == NULL) {
8538		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8539		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8540		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8541		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8542		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8543		{
8544		    attr = attr->next;
8545		    continue;
8546		} else {
8547		    /* SPEC (3.3.3 : 2.2) */
8548		    xmlSchemaPCustomAttrErr(ctxt,
8549			XML_SCHEMAP_SRC_ELEMENT_2_2,
8550			NULL, NULL, attr,
8551			"Only the attributes 'minOccurs', 'maxOccurs' and "
8552			"'id' are allowed in addition to 'ref'");
8553		    break;
8554		}
8555	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8556		xmlSchemaPIllegalAttrErr(ctxt,
8557		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8558	    }
8559	    attr = attr->next;
8560	}
8561	/*
8562	* No children except <annotation> expected.
8563	*/
8564	if (child != NULL) {
8565	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8566		NULL, node, child, NULL, "(annotation?)");
8567	}
8568	if ((min == 0) && (max == 0))
8569	    goto return_null;
8570	/*
8571	* Create the reference item and attach it to the particle.
8572	*/
8573	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8574	    ref, refNs);
8575	if (refer == NULL)
8576	    goto return_null;
8577	particle->children = (xmlSchemaTreeItemPtr) refer;
8578	particle->annot = annot;
8579	/*
8580	* Add the particle to pending components, since the reference
8581	* need to be resolved.
8582	*/
8583	WXS_ADD_PENDING(ctxt, particle);
8584	return ((xmlSchemaBasicItemPtr) particle);
8585    }
8586    /*
8587    * The declaration part ===============================================
8588    */
8589declaration_part:
8590    {
8591	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8592	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8593
8594	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8595	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8596	    goto return_null;
8597	/*
8598	* Evaluate the target namespace.
8599	*/
8600	if (topLevel) {
8601	    ns = ctxt->targetNamespace;
8602	} else {
8603	    attr = xmlSchemaGetPropNode(node, "form");
8604	    if (attr != NULL) {
8605		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8606		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8607		    ns = ctxt->targetNamespace;
8608		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8609		    xmlSchemaPSimpleTypeErr(ctxt,
8610			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8611			NULL, (xmlNodePtr) attr,
8612			NULL, "(qualified | unqualified)",
8613			attrValue, NULL, NULL, NULL);
8614		}
8615	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8616		ns = ctxt->targetNamespace;
8617	}
8618	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8619	if (decl == NULL) {
8620	    goto return_null;
8621	}
8622	/*
8623	* Check for illegal attributes.
8624	*/
8625	attr = node->properties;
8626	while (attr != NULL) {
8627	    if (attr->ns == NULL) {
8628		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8629		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8630		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8631		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8632		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8633		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8634		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8635		{
8636		    if (topLevel == 0) {
8637			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8638			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8639			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8640			{
8641			    xmlSchemaPIllegalAttrErr(ctxt,
8642				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8643			}
8644		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8645			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8646			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8647
8648			xmlSchemaPIllegalAttrErr(ctxt,
8649			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8650		    }
8651		}
8652	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8653
8654		xmlSchemaPIllegalAttrErr(ctxt,
8655		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8656	    }
8657	    attr = attr->next;
8658	}
8659	/*
8660	* Extract/validate attributes.
8661	*/
8662	if (topLevel) {
8663	    /*
8664	    * Process top attributes of global element declarations here.
8665	    */
8666	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8667	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8668	    xmlSchemaPValAttrQName(ctxt, schema,
8669		NULL, node, "substitutionGroup",
8670		&(decl->substGroupNs), &(decl->substGroup));
8671	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8672		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8673	    /*
8674	    * Attribute "final".
8675	    */
8676	    attr = xmlSchemaGetPropNode(node, "final");
8677	    if (attr == NULL) {
8678		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8679		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8680		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8681		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8682	    } else {
8683		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8684		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8685		    -1,
8686		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8687		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8688		    xmlSchemaPSimpleTypeErr(ctxt,
8689			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8690			NULL, (xmlNodePtr) attr,
8691			NULL, "(#all | List of (extension | restriction))",
8692			attrValue, NULL, NULL, NULL);
8693		}
8694	    }
8695	}
8696	/*
8697	* Attribute "block".
8698	*/
8699	attr = xmlSchemaGetPropNode(node, "block");
8700	if (attr == NULL) {
8701	    /*
8702	    * Apply default "block" values.
8703	    */
8704	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8705		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8706	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8707		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8708	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8709		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8710	} else {
8711	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8712	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8713		-1,
8714		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8715		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8716		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8717		xmlSchemaPSimpleTypeErr(ctxt,
8718		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8719		    NULL, (xmlNodePtr) attr,
8720		    NULL, "(#all | List of (extension | "
8721		    "restriction | substitution))", attrValue,
8722		    NULL, NULL, NULL);
8723	    }
8724	}
8725	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8726	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8727
8728	attr = xmlSchemaGetPropNode(node, "type");
8729	if (attr != NULL) {
8730	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8731		NULL, attr,
8732		&(decl->namedTypeNs), &(decl->namedType));
8733	    xmlSchemaCheckReference(ctxt, schema, node,
8734		attr, decl->namedTypeNs);
8735	}
8736	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8737	attr = xmlSchemaGetPropNode(node, "fixed");
8738	if (attr != NULL) {
8739	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8740	    if (decl->value != NULL) {
8741		/*
8742		* 3.3.3 : 1
8743		* default and fixed must not both be present.
8744		*/
8745		xmlSchemaPMutualExclAttrErr(ctxt,
8746		    XML_SCHEMAP_SRC_ELEMENT_1,
8747		    NULL, attr, "default", "fixed");
8748	    } else {
8749		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8750		decl->value = fixed;
8751	    }
8752	}
8753	/*
8754	* And now for the children...
8755	*/
8756	if (IS_SCHEMA(child, "complexType")) {
8757	    /*
8758	    * 3.3.3 : 3
8759	    * "type" and either <simpleType> or <complexType> are mutually
8760	    * exclusive
8761	    */
8762	    if (decl->namedType != NULL) {
8763		xmlSchemaPContentErr(ctxt,
8764		    XML_SCHEMAP_SRC_ELEMENT_3,
8765		    NULL, node, child,
8766		    "The attribute 'type' and the <complexType> child are "
8767		    "mutually exclusive", NULL);
8768	    } else
8769		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8770	    child = child->next;
8771	} else if (IS_SCHEMA(child, "simpleType")) {
8772	    /*
8773	    * 3.3.3 : 3
8774	    * "type" and either <simpleType> or <complexType> are
8775	    * mutually exclusive
8776	    */
8777	    if (decl->namedType != NULL) {
8778		xmlSchemaPContentErr(ctxt,
8779		    XML_SCHEMAP_SRC_ELEMENT_3,
8780		    NULL, node, child,
8781		    "The attribute 'type' and the <simpleType> child are "
8782		    "mutually exclusive", NULL);
8783	    } else
8784		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8785	    child = child->next;
8786	}
8787	while ((IS_SCHEMA(child, "unique")) ||
8788	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8789	    if (IS_SCHEMA(child, "unique")) {
8790		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8791		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8792	    } else if (IS_SCHEMA(child, "key")) {
8793		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8794		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8795	    } else if (IS_SCHEMA(child, "keyref")) {
8796		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8797		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8798	    }
8799	    if (lastIDC != NULL)
8800		lastIDC->next = curIDC;
8801	    else
8802		decl->idcs = (void *) curIDC;
8803	    lastIDC = curIDC;
8804	    child = child->next;
8805	}
8806	if (child != NULL) {
8807	    xmlSchemaPContentErr(ctxt,
8808		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8809		NULL, node, child,
8810		NULL, "(annotation?, ((simpleType | complexType)?, "
8811		"(unique | key | keyref)*))");
8812	}
8813	decl->annot = annot;
8814    }
8815    /*
8816    * NOTE: Element Declaration Representation OK 4. will be checked at a
8817    * different layer.
8818    */
8819    FREE_AND_NULL(des)
8820    if (topLevel)
8821	return ((xmlSchemaBasicItemPtr) decl);
8822    else {
8823	particle->children = (xmlSchemaTreeItemPtr) decl;
8824	return ((xmlSchemaBasicItemPtr) particle);
8825    }
8826
8827return_null:
8828    FREE_AND_NULL(des);
8829    if (annot != NULL) {
8830	if (particle != NULL)
8831	    particle->annot = NULL;
8832	if (decl != NULL)
8833	    decl->annot = NULL;
8834	xmlSchemaFreeAnnot(annot);
8835    }
8836    return (NULL);
8837}
8838
8839/**
8840 * xmlSchemaParseUnion:
8841 * @ctxt:  a schema validation context
8842 * @schema:  the schema being built
8843 * @node:  a subtree containing XML Schema informations
8844 *
8845 * parse a XML schema Union definition
8846 * *WARNING* this interface is highly subject to change
8847 *
8848 * Returns -1 in case of internal error, 0 in case of success and a positive
8849 * error code otherwise.
8850 */
8851static int
8852xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8853                    xmlNodePtr node)
8854{
8855    xmlSchemaTypePtr type;
8856    xmlNodePtr child = NULL;
8857    xmlAttrPtr attr;
8858    const xmlChar *cur = NULL;
8859
8860    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8861        return (-1);
8862    /* Not a component, don't create it. */
8863    type = ctxt->ctxtType;
8864    /*
8865    * Mark the simple type as being of variety "union".
8866    */
8867    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8868    /*
8869    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8870    * then the �simple ur-type definition�."
8871    */
8872    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8873    /*
8874    * Check for illegal attributes.
8875    */
8876    attr = node->properties;
8877    while (attr != NULL) {
8878	if (attr->ns == NULL) {
8879	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8880		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8881		xmlSchemaPIllegalAttrErr(ctxt,
8882		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8883	    }
8884	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8885	    xmlSchemaPIllegalAttrErr(ctxt,
8886		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8887	}
8888	attr = attr->next;
8889    }
8890    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8891    /*
8892    * Attribute "memberTypes". This is a list of QNames.
8893    * TODO: Check the value to contain anything.
8894    */
8895    attr = xmlSchemaGetPropNode(node, "memberTypes");
8896    if (attr != NULL) {
8897	const xmlChar *end;
8898	xmlChar *tmp;
8899	const xmlChar *localName, *nsName;
8900	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8901	xmlSchemaQNameRefPtr ref;
8902
8903	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8904	type->base = cur;
8905	do {
8906	    while (IS_BLANK_CH(*cur))
8907		cur++;
8908	    end = cur;
8909	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8910		end++;
8911	    if (end == cur)
8912		break;
8913	    tmp = xmlStrndup(cur, end - cur);
8914	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8915		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8916		/*
8917		* Create the member type link.
8918		*/
8919		link = (xmlSchemaTypeLinkPtr)
8920		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8921		if (link == NULL) {
8922		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8923			"allocating a type link", NULL);
8924		    return (-1);
8925		}
8926		link->type = NULL;
8927		link->next = NULL;
8928		if (lastLink == NULL)
8929		    type->memberTypes = link;
8930		else
8931		    lastLink->next = link;
8932		lastLink = link;
8933		/*
8934		* Create a reference item.
8935		*/
8936		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8937		    localName, nsName);
8938		if (ref == NULL) {
8939		    FREE_AND_NULL(tmp)
8940		    return (-1);
8941		}
8942		/*
8943		* Assign the reference to the link, it will be resolved
8944		* later during fixup of the union simple type.
8945		*/
8946		link->type = (xmlSchemaTypePtr) ref;
8947	    }
8948	    FREE_AND_NULL(tmp)
8949	    cur = end;
8950	} while (*cur != 0);
8951
8952    }
8953    /*
8954    * And now for the children...
8955    */
8956    child = node->children;
8957    if (IS_SCHEMA(child, "annotation")) {
8958	/*
8959	* Add the annotation to the simple type ancestor.
8960	*/
8961	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8962	    xmlSchemaParseAnnotation(ctxt, child, 1));
8963        child = child->next;
8964    }
8965    if (IS_SCHEMA(child, "simpleType")) {
8966	xmlSchemaTypePtr subtype, last = NULL;
8967
8968	/*
8969	* Anchor the member types in the "subtypes" field of the
8970	* simple type.
8971	*/
8972	while (IS_SCHEMA(child, "simpleType")) {
8973	    subtype = (xmlSchemaTypePtr)
8974		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8975	    if (subtype != NULL) {
8976		if (last == NULL) {
8977		    type->subtypes = subtype;
8978		    last = subtype;
8979		} else {
8980		    last->next = subtype;
8981		    last = subtype;
8982		}
8983		last->next = NULL;
8984	    }
8985	    child = child->next;
8986	}
8987    }
8988    if (child != NULL) {
8989	xmlSchemaPContentErr(ctxt,
8990	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8991	    NULL, node, child, NULL, "(annotation?, simpleType*)");
8992    }
8993    if ((attr == NULL) && (type->subtypes == NULL)) {
8994	 /*
8995	* src-union-memberTypes-or-simpleTypes
8996	* Either the memberTypes [attribute] of the <union> element must
8997	* be non-empty or there must be at least one simpleType [child].
8998	*/
8999	xmlSchemaPCustomErr(ctxt,
9000	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9001	    NULL, node,
9002	    "Either the attribute 'memberTypes' or "
9003	    "at least one <simpleType> child must be present", NULL);
9004    }
9005    return (0);
9006}
9007
9008/**
9009 * xmlSchemaParseList:
9010 * @ctxt:  a schema validation context
9011 * @schema:  the schema being built
9012 * @node:  a subtree containing XML Schema informations
9013 *
9014 * parse a XML schema List definition
9015 * *WARNING* this interface is highly subject to change
9016 *
9017 * Returns -1 in case of error, 0 if the declaration is improper and
9018 *         1 in case of success.
9019 */
9020static xmlSchemaTypePtr
9021xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9022                   xmlNodePtr node)
9023{
9024    xmlSchemaTypePtr type;
9025    xmlNodePtr child = NULL;
9026    xmlAttrPtr attr;
9027
9028    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9029        return (NULL);
9030    /* Not a component, don't create it. */
9031    type = ctxt->ctxtType;
9032    /*
9033    * Mark the type as being of variety "list".
9034    */
9035    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9036    /*
9037    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9038    * then the �simple ur-type definition�."
9039    */
9040    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9041    /*
9042    * Check for illegal attributes.
9043    */
9044    attr = node->properties;
9045    while (attr != NULL) {
9046	if (attr->ns == NULL) {
9047	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9048		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9049		xmlSchemaPIllegalAttrErr(ctxt,
9050		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9051	    }
9052	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9053	    xmlSchemaPIllegalAttrErr(ctxt,
9054		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9055	}
9056	attr = attr->next;
9057    }
9058
9059    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9060
9061    /*
9062    * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9063    * fields for holding the reference to the itemType.
9064    *
9065    * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9066    * the "ref" fields.
9067    */
9068    xmlSchemaPValAttrQName(ctxt, schema, NULL,
9069	node, "itemType", &(type->baseNs), &(type->base));
9070    /*
9071    * And now for the children...
9072    */
9073    child = node->children;
9074    if (IS_SCHEMA(child, "annotation")) {
9075	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9076	    xmlSchemaParseAnnotation(ctxt, child, 1));
9077        child = child->next;
9078    }
9079    if (IS_SCHEMA(child, "simpleType")) {
9080	/*
9081	* src-list-itemType-or-simpleType
9082	* Either the itemType [attribute] or the <simpleType> [child] of
9083	* the <list> element must be present, but not both.
9084	*/
9085	if (type->base != NULL) {
9086	    xmlSchemaPCustomErr(ctxt,
9087		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9088		NULL, node,
9089		"The attribute 'itemType' and the <simpleType> child "
9090		"are mutually exclusive", NULL);
9091	} else {
9092	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9093	}
9094        child = child->next;
9095    } else if (type->base == NULL) {
9096	xmlSchemaPCustomErr(ctxt,
9097	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9098	    NULL, node,
9099	    "Either the attribute 'itemType' or the <simpleType> child "
9100	    "must be present", NULL);
9101    }
9102    if (child != NULL) {
9103	xmlSchemaPContentErr(ctxt,
9104	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9105	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9106    }
9107    if ((type->base == NULL) &&
9108	(type->subtypes == NULL) &&
9109	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9110	xmlSchemaPCustomErr(ctxt,
9111	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9112	    NULL, node,
9113	    "Either the attribute 'itemType' or the <simpleType> child "
9114	    "must be present", NULL);
9115    }
9116    return (NULL);
9117}
9118
9119/**
9120 * xmlSchemaParseSimpleType:
9121 * @ctxt:  a schema validation context
9122 * @schema:  the schema being built
9123 * @node:  a subtree containing XML Schema informations
9124 *
9125 * parse a XML schema Simple Type definition
9126 * *WARNING* this interface is highly subject to change
9127 *
9128 * Returns -1 in case of error, 0 if the declaration is improper and
9129 * 1 in case of success.
9130 */
9131static xmlSchemaTypePtr
9132xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9133                         xmlNodePtr node, int topLevel)
9134{
9135    xmlSchemaTypePtr type, oldCtxtType;
9136    xmlNodePtr child = NULL;
9137    const xmlChar *attrValue = NULL;
9138    xmlAttrPtr attr;
9139    int hasRestriction = 0;
9140
9141    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9142        return (NULL);
9143
9144    if (topLevel) {
9145	attr = xmlSchemaGetPropNode(node, "name");
9146	if (attr == NULL) {
9147	    xmlSchemaPMissingAttrErr(ctxt,
9148		XML_SCHEMAP_S4S_ATTR_MISSING,
9149		NULL, node,
9150		"name", NULL);
9151	    return (NULL);
9152	} else {
9153	    if (xmlSchemaPValAttrNode(ctxt,
9154		NULL, attr,
9155		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9156		return (NULL);
9157	    /*
9158	    * Skip built-in types.
9159	    */
9160	    if (ctxt->isS4S) {
9161		xmlSchemaTypePtr biType;
9162
9163		if (ctxt->isRedefine) {
9164		    /*
9165		    * REDEFINE: Disallow redefinition of built-in-types.
9166		    * TODO: It seems that the spec does not say anything
9167		    * about this case.
9168		    */
9169		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9170			NULL, node,
9171			"Redefinition of built-in simple types is not "
9172			"supported", NULL);
9173		    return(NULL);
9174		}
9175		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9176		if (biType != NULL)
9177		    return (biType);
9178	    }
9179	}
9180    }
9181    /*
9182    * TargetNamespace:
9183    * SPEC "The �actual value� of the targetNamespace [attribute]
9184    * of the <schema> ancestor element information item if present,
9185    * otherwise �absent�.
9186    */
9187    if (topLevel == 0) {
9188#ifdef ENABLE_NAMED_LOCALS
9189        char buf[40];
9190#endif
9191	/*
9192	* Parse as local simple type definition.
9193	*/
9194#ifdef ENABLE_NAMED_LOCALS
9195        snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9196	type = xmlSchemaAddType(ctxt, schema,
9197	    XML_SCHEMA_TYPE_SIMPLE,
9198	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9199	    ctxt->targetNamespace, node, 0);
9200#else
9201	type = xmlSchemaAddType(ctxt, schema,
9202	    XML_SCHEMA_TYPE_SIMPLE,
9203	    NULL, ctxt->targetNamespace, node, 0);
9204#endif
9205	if (type == NULL)
9206	    return (NULL);
9207	type->type = XML_SCHEMA_TYPE_SIMPLE;
9208	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9209	/*
9210	* Check for illegal attributes.
9211	*/
9212	attr = node->properties;
9213	while (attr != NULL) {
9214	    if (attr->ns == NULL) {
9215		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9216		    xmlSchemaPIllegalAttrErr(ctxt,
9217			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9218		}
9219	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9220		    xmlSchemaPIllegalAttrErr(ctxt,
9221			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9222	    }
9223	    attr = attr->next;
9224	}
9225    } else {
9226	/*
9227	* Parse as global simple type definition.
9228	*
9229	* Note that attrValue is the value of the attribute "name" here.
9230	*/
9231	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9232	    attrValue, ctxt->targetNamespace, node, 1);
9233	if (type == NULL)
9234	    return (NULL);
9235	type->type = XML_SCHEMA_TYPE_SIMPLE;
9236	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9237	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9238	/*
9239	* Check for illegal attributes.
9240	*/
9241	attr = node->properties;
9242	while (attr != NULL) {
9243	    if (attr->ns == NULL) {
9244		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9245		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9246		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9247		    xmlSchemaPIllegalAttrErr(ctxt,
9248			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9249		}
9250	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9251		xmlSchemaPIllegalAttrErr(ctxt,
9252		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9253	    }
9254	    attr = attr->next;
9255	}
9256	/*
9257	* Attribute "final".
9258	*/
9259	attr = xmlSchemaGetPropNode(node, "final");
9260	if (attr == NULL) {
9261	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9262		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9263	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9264		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9265	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9266		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9267	} else {
9268	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9269	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9270		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9271		XML_SCHEMAS_TYPE_FINAL_LIST,
9272		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9273
9274		xmlSchemaPSimpleTypeErr(ctxt,
9275		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9276		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9277		    NULL, "(#all | List of (list | union | restriction)",
9278		    attrValue, NULL, NULL, NULL);
9279	    }
9280	}
9281    }
9282    type->targetNamespace = ctxt->targetNamespace;
9283    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9284    /*
9285    * And now for the children...
9286    */
9287    oldCtxtType = ctxt->ctxtType;
9288
9289    ctxt->ctxtType = type;
9290
9291    child = node->children;
9292    if (IS_SCHEMA(child, "annotation")) {
9293        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9294        child = child->next;
9295    }
9296    if (child == NULL) {
9297	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9298	    NULL, node, child, NULL,
9299	    "(annotation?, (restriction | list | union))");
9300    } else if (IS_SCHEMA(child, "restriction")) {
9301        xmlSchemaParseRestriction(ctxt, schema, child,
9302	    XML_SCHEMA_TYPE_SIMPLE);
9303	hasRestriction = 1;
9304        child = child->next;
9305    } else if (IS_SCHEMA(child, "list")) {
9306        xmlSchemaParseList(ctxt, schema, child);
9307        child = child->next;
9308    } else if (IS_SCHEMA(child, "union")) {
9309        xmlSchemaParseUnion(ctxt, schema, child);
9310        child = child->next;
9311    }
9312    if (child != NULL) {
9313	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9314	    NULL, node, child, NULL,
9315	    "(annotation?, (restriction | list | union))");
9316    }
9317    /*
9318    * REDEFINE: SPEC src-redefine (5)
9319    * "Within the [children], each <simpleType> must have a
9320    * <restriction> among its [children] ... the �actual value� of whose
9321    * base [attribute] must be the same as the �actual value� of its own
9322    * name attribute plus target namespace;"
9323    */
9324    if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9325	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9326	    NULL, node, "This is a redefinition, thus the "
9327	    "<simpleType> must have a <restriction> child", NULL);
9328    }
9329
9330    ctxt->ctxtType = oldCtxtType;
9331    return (type);
9332}
9333
9334/**
9335 * xmlSchemaParseModelGroupDefRef:
9336 * @ctxt:  the parser context
9337 * @schema: the schema being built
9338 * @node:  the node
9339 *
9340 * Parses a reference to a model group definition.
9341 *
9342 * We will return a particle component with a qname-component or
9343 * NULL in case of an error.
9344 */
9345static xmlSchemaTreeItemPtr
9346xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9347			       xmlSchemaPtr schema,
9348			       xmlNodePtr node)
9349{
9350    xmlSchemaParticlePtr item;
9351    xmlNodePtr child = NULL;
9352    xmlAttrPtr attr;
9353    const xmlChar *ref = NULL, *refNs = NULL;
9354    int min, max;
9355
9356    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9357        return (NULL);
9358
9359    attr = xmlSchemaGetPropNode(node, "ref");
9360    if (attr == NULL) {
9361	xmlSchemaPMissingAttrErr(ctxt,
9362	    XML_SCHEMAP_S4S_ATTR_MISSING,
9363	    NULL, node, "ref", NULL);
9364	return (NULL);
9365    } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9366	attr, &refNs, &ref) != 0) {
9367	return (NULL);
9368    }
9369    xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9370    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9371    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9372	"(xs:nonNegativeInteger | unbounded)");
9373    /*
9374    * Check for illegal attributes.
9375    */
9376    attr = node->properties;
9377    while (attr != NULL) {
9378	if (attr->ns == NULL) {
9379	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9380		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9381		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9382		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9383		xmlSchemaPIllegalAttrErr(ctxt,
9384		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9385	    }
9386	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9387	    xmlSchemaPIllegalAttrErr(ctxt,
9388		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9389	}
9390	attr = attr->next;
9391    }
9392    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9393    item = xmlSchemaAddParticle(ctxt, node, min, max);
9394    if (item == NULL)
9395	return (NULL);
9396    /*
9397    * Create a qname-reference and set as the term; it will be substituted
9398    * for the model group after the reference has been resolved.
9399    */
9400    item->children = (xmlSchemaTreeItemPtr)
9401	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9402    xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9403    /*
9404    * And now for the children...
9405    */
9406    child = node->children;
9407    /* TODO: Is annotation even allowed for a model group reference? */
9408    if (IS_SCHEMA(child, "annotation")) {
9409	/*
9410	* TODO: What to do exactly with the annotation?
9411	*/
9412	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9413	child = child->next;
9414    }
9415    if (child != NULL) {
9416	xmlSchemaPContentErr(ctxt,
9417	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9418	    NULL, node, child, NULL,
9419	    "(annotation?)");
9420    }
9421    /*
9422    * Corresponds to no component at all if minOccurs==maxOccurs==0.
9423    */
9424    if ((min == 0) && (max == 0))
9425	return (NULL);
9426
9427    return ((xmlSchemaTreeItemPtr) item);
9428}
9429
9430/**
9431 * xmlSchemaParseModelGroupDefinition:
9432 * @ctxt:  a schema validation context
9433 * @schema:  the schema being built
9434 * @node:  a subtree containing XML Schema informations
9435 *
9436 * Parses a XML schema model group definition.
9437 *
9438 * Note that the contraint src-redefine (6.2) can't be applied until
9439 * references have been resolved. So we will do this at the
9440 * component fixup level.
9441 *
9442 * *WARNING* this interface is highly subject to change
9443 *
9444 * Returns -1 in case of error, 0 if the declaration is improper and
9445 *         1 in case of success.
9446 */
9447static xmlSchemaModelGroupDefPtr
9448xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9449				   xmlSchemaPtr schema,
9450				   xmlNodePtr node)
9451{
9452    xmlSchemaModelGroupDefPtr item;
9453    xmlNodePtr child = NULL;
9454    xmlAttrPtr attr;
9455    const xmlChar *name;
9456
9457    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9458        return (NULL);
9459
9460    attr = xmlSchemaGetPropNode(node, "name");
9461    if (attr == NULL) {
9462	xmlSchemaPMissingAttrErr(ctxt,
9463	    XML_SCHEMAP_S4S_ATTR_MISSING,
9464	    NULL, node,
9465	    "name", NULL);
9466	return (NULL);
9467    } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9468	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9469	return (NULL);
9470    }
9471    item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9472	ctxt->targetNamespace, node);
9473    if (item == NULL)
9474	return (NULL);
9475    /*
9476    * Check for illegal attributes.
9477    */
9478    attr = node->properties;
9479    while (attr != NULL) {
9480	if (attr->ns == NULL) {
9481	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9482		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9483		xmlSchemaPIllegalAttrErr(ctxt,
9484		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9485	    }
9486	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9487	    xmlSchemaPIllegalAttrErr(ctxt,
9488		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9489	}
9490	attr = attr->next;
9491    }
9492    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9493    /*
9494    * And now for the children...
9495    */
9496    child = node->children;
9497    if (IS_SCHEMA(child, "annotation")) {
9498	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9499	child = child->next;
9500    }
9501    if (IS_SCHEMA(child, "all")) {
9502	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9503	    XML_SCHEMA_TYPE_ALL, 0);
9504	child = child->next;
9505    } else if (IS_SCHEMA(child, "choice")) {
9506	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9507	    XML_SCHEMA_TYPE_CHOICE, 0);
9508	child = child->next;
9509    } else if (IS_SCHEMA(child, "sequence")) {
9510	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9511	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9512	child = child->next;
9513    }
9514
9515
9516
9517    if (child != NULL) {
9518	xmlSchemaPContentErr(ctxt,
9519	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9520	    NULL, node, child, NULL,
9521	    "(annotation?, (all | choice | sequence)?)");
9522    }
9523    return (item);
9524}
9525
9526/**
9527 * xmlSchemaCleanupDoc:
9528 * @ctxt:  a schema validation context
9529 * @node:  the root of the document.
9530 *
9531 * removes unwanted nodes in a schemas document tree
9532 */
9533static void
9534xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9535{
9536    xmlNodePtr delete, cur;
9537
9538    if ((ctxt == NULL) || (root == NULL)) return;
9539
9540    /*
9541     * Remove all the blank text nodes
9542     */
9543    delete = NULL;
9544    cur = root;
9545    while (cur != NULL) {
9546        if (delete != NULL) {
9547            xmlUnlinkNode(delete);
9548            xmlFreeNode(delete);
9549            delete = NULL;
9550        }
9551        if (cur->type == XML_TEXT_NODE) {
9552            if (IS_BLANK_NODE(cur)) {
9553                if (xmlNodeGetSpacePreserve(cur) != 1) {
9554                    delete = cur;
9555                }
9556            }
9557        } else if ((cur->type != XML_ELEMENT_NODE) &&
9558                   (cur->type != XML_CDATA_SECTION_NODE)) {
9559            delete = cur;
9560            goto skip_children;
9561        }
9562
9563        /*
9564         * Skip to next node
9565         */
9566        if (cur->children != NULL) {
9567            if ((cur->children->type != XML_ENTITY_DECL) &&
9568                (cur->children->type != XML_ENTITY_REF_NODE) &&
9569                (cur->children->type != XML_ENTITY_NODE)) {
9570                cur = cur->children;
9571                continue;
9572            }
9573        }
9574      skip_children:
9575        if (cur->next != NULL) {
9576            cur = cur->next;
9577            continue;
9578        }
9579
9580        do {
9581            cur = cur->parent;
9582            if (cur == NULL)
9583                break;
9584            if (cur == root) {
9585                cur = NULL;
9586                break;
9587            }
9588            if (cur->next != NULL) {
9589                cur = cur->next;
9590                break;
9591            }
9592        } while (cur != NULL);
9593    }
9594    if (delete != NULL) {
9595        xmlUnlinkNode(delete);
9596        xmlFreeNode(delete);
9597        delete = NULL;
9598    }
9599}
9600
9601
9602static void
9603xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9604{
9605    if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9606	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9607
9608    if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9609	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9610
9611    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9612	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9613    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9614	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9615    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9616	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9617    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9618	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9619
9620    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9621	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9622    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9623	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9624    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9625	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9626}
9627
9628static int
9629xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9630			     xmlSchemaPtr schema,
9631			     xmlNodePtr node)
9632{
9633    xmlAttrPtr attr;
9634    const xmlChar *val;
9635    int res = 0, oldErrs = ctxt->nberrors;
9636
9637    /*
9638    * Those flags should be moved to the parser context flags,
9639    * since they are not visible at the component level. I.e.
9640    * they are used if processing schema *documents* only.
9641    */
9642    res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9643    HFAILURE;
9644
9645    /*
9646    * Since the version is of type xs:token, we won't bother to
9647    * check it.
9648    */
9649    /* REMOVED:
9650    attr = xmlSchemaGetPropNode(node, "version");
9651    if (attr != NULL) {
9652	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9653	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9654	HFAILURE;
9655    }
9656    */
9657    attr = xmlSchemaGetPropNode(node, "targetNamespace");
9658    if (attr != NULL) {
9659	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9660	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9661	HFAILURE;
9662	if (res != 0) {
9663	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9664	    goto exit;
9665	}
9666    }
9667    attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9668    if (attr != NULL) {
9669	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9670	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9671	    XML_SCHEMAS_QUALIF_ELEM);
9672	HFAILURE;
9673	if (res != 0) {
9674	    xmlSchemaPSimpleTypeErr(ctxt,
9675		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9676		NULL, (xmlNodePtr) attr, NULL,
9677		"(qualified | unqualified)", val, NULL, NULL, NULL);
9678	}
9679    }
9680    attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9681    if (attr != NULL) {
9682	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9683	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9684	    XML_SCHEMAS_QUALIF_ATTR);
9685	HFAILURE;
9686	if (res != 0) {
9687	    xmlSchemaPSimpleTypeErr(ctxt,
9688		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9689		NULL, (xmlNodePtr) attr, NULL,
9690		"(qualified | unqualified)", val, NULL, NULL, NULL);
9691	}
9692    }
9693    attr = xmlSchemaGetPropNode(node, "finalDefault");
9694    if (attr != NULL) {
9695	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9696	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9697	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9698	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9699	    -1,
9700	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9701	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9702	HFAILURE;
9703	if (res != 0) {
9704	    xmlSchemaPSimpleTypeErr(ctxt,
9705		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9706		NULL, (xmlNodePtr) attr, NULL,
9707		"(#all | List of (extension | restriction | list | union))",
9708		val, NULL, NULL, NULL);
9709	}
9710    }
9711    attr = xmlSchemaGetPropNode(node, "blockDefault");
9712    if (attr != NULL) {
9713	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9714	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9715	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9716	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9717	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9718	HFAILURE;
9719	if (res != 0) {
9720	    xmlSchemaPSimpleTypeErr(ctxt,
9721		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9722		NULL, (xmlNodePtr) attr, NULL,
9723		"(#all | List of (extension | restriction | substitution))",
9724		val, NULL, NULL, NULL);
9725	}
9726    }
9727
9728exit:
9729    if (oldErrs != ctxt->nberrors)
9730	res = ctxt->err;
9731    return(res);
9732exit_failure:
9733    return(-1);
9734}
9735
9736/**
9737 * xmlSchemaParseSchemaTopLevel:
9738 * @ctxt:  a schema validation context
9739 * @schema:  the schemas
9740 * @nodes:  the list of top level nodes
9741 *
9742 * Returns the internal XML Schema structure built from the resource or
9743 *         NULL in case of error
9744 */
9745static int
9746xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9747                             xmlSchemaPtr schema, xmlNodePtr nodes)
9748{
9749    xmlNodePtr child;
9750    xmlSchemaAnnotPtr annot;
9751    int res = 0, oldErrs, tmpOldErrs;
9752
9753    if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9754        return(-1);
9755
9756    oldErrs = ctxt->nberrors;
9757    child = nodes;
9758    while ((IS_SCHEMA(child, "include")) ||
9759	   (IS_SCHEMA(child, "import")) ||
9760	   (IS_SCHEMA(child, "redefine")) ||
9761	   (IS_SCHEMA(child, "annotation"))) {
9762	if (IS_SCHEMA(child, "annotation")) {
9763	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9764	    if (schema->annot == NULL)
9765		schema->annot = annot;
9766	    else
9767		xmlSchemaFreeAnnot(annot);
9768	} else if (IS_SCHEMA(child, "import")) {
9769	    tmpOldErrs = ctxt->nberrors;
9770	    res = xmlSchemaParseImport(ctxt, schema, child);
9771	    HFAILURE;
9772	    HSTOP(ctxt);
9773	    if (tmpOldErrs != ctxt->nberrors)
9774		goto exit;
9775	} else if (IS_SCHEMA(child, "include")) {
9776	    tmpOldErrs = ctxt->nberrors;
9777	    res = xmlSchemaParseInclude(ctxt, schema, child);
9778	    HFAILURE;
9779	    HSTOP(ctxt);
9780	    if (tmpOldErrs != ctxt->nberrors)
9781		goto exit;
9782	} else if (IS_SCHEMA(child, "redefine")) {
9783	    tmpOldErrs = ctxt->nberrors;
9784	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9785	    HFAILURE;
9786	    HSTOP(ctxt);
9787	    if (tmpOldErrs != ctxt->nberrors)
9788		goto exit;
9789	}
9790	child = child->next;
9791    }
9792    /*
9793    * URGENT TODO: Change the functions to return int results.
9794    * We need especially to catch internal errors.
9795    */
9796    while (child != NULL) {
9797	if (IS_SCHEMA(child, "complexType")) {
9798	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9799	    child = child->next;
9800	} else if (IS_SCHEMA(child, "simpleType")) {
9801	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9802	    child = child->next;
9803	} else if (IS_SCHEMA(child, "element")) {
9804	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9805	    child = child->next;
9806	} else if (IS_SCHEMA(child, "attribute")) {
9807	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9808	    child = child->next;
9809	} else if (IS_SCHEMA(child, "attributeGroup")) {
9810	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9811	    child = child->next;
9812	} else if (IS_SCHEMA(child, "group")) {
9813	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9814	    child = child->next;
9815	} else if (IS_SCHEMA(child, "notation")) {
9816	    xmlSchemaParseNotation(ctxt, schema, child);
9817	    child = child->next;
9818	} else {
9819	    xmlSchemaPContentErr(ctxt,
9820		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9821		NULL, child->parent, child,
9822		NULL, "((include | import | redefine | annotation)*, "
9823		"(((simpleType | complexType | group | attributeGroup) "
9824		"| element | attribute | notation), annotation*)*)");
9825	    child = child->next;
9826	}
9827	while (IS_SCHEMA(child, "annotation")) {
9828	    /*
9829	    * TODO: We should add all annotations.
9830	    */
9831	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9832	    if (schema->annot == NULL)
9833		schema->annot = annot;
9834	    else
9835		xmlSchemaFreeAnnot(annot);
9836	    child = child->next;
9837	}
9838    }
9839exit:
9840    ctxt->ctxtType = NULL;
9841    if (oldErrs != ctxt->nberrors)
9842	res = ctxt->err;
9843    return(res);
9844exit_failure:
9845    return(-1);
9846}
9847
9848static xmlSchemaSchemaRelationPtr
9849xmlSchemaSchemaRelationCreate(void)
9850{
9851    xmlSchemaSchemaRelationPtr ret;
9852
9853    ret = (xmlSchemaSchemaRelationPtr)
9854	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9855    if (ret == NULL) {
9856	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9857	return(NULL);
9858    }
9859    memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9860    return(ret);
9861}
9862
9863#if 0
9864static void
9865xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9866{
9867    xmlFree(rel);
9868}
9869#endif
9870
9871static void
9872xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9873{
9874    xmlSchemaRedefPtr prev;
9875
9876    while (redef != NULL) {
9877	prev = redef;
9878	redef = redef->next;
9879	xmlFree(prev);
9880    }
9881}
9882
9883static void
9884xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9885{
9886    /*
9887    * After the construction context has been freed, there will be
9888    * no schema graph available any more. Only the schema buckets
9889    * will stay alive, which are put into the "schemasImports" and
9890    * "includes" slots of the xmlSchema.
9891    */
9892    if (con->buckets != NULL)
9893	xmlSchemaItemListFree(con->buckets);
9894    if (con->pending != NULL)
9895	xmlSchemaItemListFree(con->pending);
9896    if (con->substGroups != NULL)
9897	xmlHashFree(con->substGroups,
9898	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9899    if (con->redefs != NULL)
9900	xmlSchemaRedefListFree(con->redefs);
9901    if (con->dict != NULL)
9902	xmlDictFree(con->dict);
9903    xmlFree(con);
9904}
9905
9906static xmlSchemaConstructionCtxtPtr
9907xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9908{
9909    xmlSchemaConstructionCtxtPtr ret;
9910
9911    ret = (xmlSchemaConstructionCtxtPtr)
9912	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9913    if (ret == NULL) {
9914        xmlSchemaPErrMemory(NULL,
9915	    "allocating schema construction context", NULL);
9916        return (NULL);
9917    }
9918    memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9919
9920    ret->buckets = xmlSchemaItemListCreate();
9921    if (ret->buckets == NULL) {
9922	xmlSchemaPErrMemory(NULL,
9923	    "allocating list of schema buckets", NULL);
9924	xmlFree(ret);
9925        return (NULL);
9926    }
9927    ret->pending = xmlSchemaItemListCreate();
9928    if (ret->pending == NULL) {
9929	xmlSchemaPErrMemory(NULL,
9930	    "allocating list of pending global components", NULL);
9931	xmlSchemaConstructionCtxtFree(ret);
9932        return (NULL);
9933    }
9934    ret->dict = dict;
9935    xmlDictReference(dict);
9936    return(ret);
9937}
9938
9939static xmlSchemaParserCtxtPtr
9940xmlSchemaParserCtxtCreate(void)
9941{
9942    xmlSchemaParserCtxtPtr ret;
9943
9944    ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9945    if (ret == NULL) {
9946        xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9947                            NULL);
9948        return (NULL);
9949    }
9950    memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9951    ret->type = XML_SCHEMA_CTXT_PARSER;
9952    ret->attrProhibs = xmlSchemaItemListCreate();
9953    if (ret->attrProhibs == NULL) {
9954	xmlFree(ret);
9955	return(NULL);
9956    }
9957    return(ret);
9958}
9959
9960/**
9961 * xmlSchemaNewParserCtxtUseDict:
9962 * @URL:  the location of the schema
9963 * @dict: the dictionary to be used
9964 *
9965 * Create an XML Schemas parse context for that file/resource expected
9966 * to contain an XML Schemas file.
9967 *
9968 * Returns the parser context or NULL in case of error
9969 */
9970static xmlSchemaParserCtxtPtr
9971xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9972{
9973    xmlSchemaParserCtxtPtr ret;
9974
9975    ret = xmlSchemaParserCtxtCreate();
9976    if (ret == NULL)
9977        return (NULL);
9978    ret->dict = dict;
9979    xmlDictReference(dict);
9980    if (URL != NULL)
9981	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9982    return (ret);
9983}
9984
9985static int
9986xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9987{
9988    if (vctxt->pctxt == NULL) {
9989        if (vctxt->schema != NULL)
9990	    vctxt->pctxt =
9991		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9992	else
9993	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9994	if (vctxt->pctxt == NULL) {
9995	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9996		"failed to create a temp. parser context");
9997	    return (-1);
9998	}
9999	/* TODO: Pass user data. */
10000	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10001	    vctxt->warning, vctxt->errCtxt);
10002	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10003	    vctxt->errCtxt);
10004    }
10005    return (0);
10006}
10007
10008/**
10009 * xmlSchemaGetSchemaBucket:
10010 * @pctxt: the schema parser context
10011 * @schemaLocation: the URI of the schema document
10012 *
10013 * Returns a schema bucket if it was already parsed.
10014 *
10015 * Returns a schema bucket if it was already parsed from
10016 *         @schemaLocation, NULL otherwise.
10017 */
10018static xmlSchemaBucketPtr
10019xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10020			    const xmlChar *schemaLocation)
10021{
10022    xmlSchemaBucketPtr cur;
10023    xmlSchemaItemListPtr list;
10024
10025    list = pctxt->constructor->buckets;
10026    if (list->nbItems == 0)
10027	return(NULL);
10028    else {
10029	int i;
10030	for (i = 0; i < list->nbItems; i++) {
10031	    cur = (xmlSchemaBucketPtr) list->items[i];
10032	    /* Pointer comparison! */
10033	    if (cur->schemaLocation == schemaLocation)
10034		return(cur);
10035	}
10036    }
10037    return(NULL);
10038}
10039
10040static xmlSchemaBucketPtr
10041xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10042				     const xmlChar *schemaLocation,
10043				     const xmlChar *targetNamespace)
10044{
10045    xmlSchemaBucketPtr cur;
10046    xmlSchemaItemListPtr list;
10047
10048    list = pctxt->constructor->buckets;
10049    if (list->nbItems == 0)
10050	return(NULL);
10051    else {
10052	int i;
10053	for (i = 0; i < list->nbItems; i++) {
10054	    cur = (xmlSchemaBucketPtr) list->items[i];
10055	    /* Pointer comparison! */
10056	    if ((cur->origTargetNamespace == NULL) &&
10057		(cur->schemaLocation == schemaLocation) &&
10058		(cur->targetNamespace == targetNamespace))
10059		return(cur);
10060	}
10061    }
10062    return(NULL);
10063}
10064
10065
10066#define IS_BAD_SCHEMA_DOC(b) \
10067    (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10068
10069static xmlSchemaBucketPtr
10070xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10071				 const xmlChar *targetNamespace,
10072				 int imported)
10073{
10074    xmlSchemaBucketPtr cur;
10075    xmlSchemaItemListPtr list;
10076
10077    list = pctxt->constructor->buckets;
10078    if (list->nbItems == 0)
10079	return(NULL);
10080    else {
10081	int i;
10082	for (i = 0; i < list->nbItems; i++) {
10083	    cur = (xmlSchemaBucketPtr) list->items[i];
10084	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10085		(cur->origTargetNamespace == targetNamespace) &&
10086		((imported && cur->imported) ||
10087		 ((!imported) && (!cur->imported))))
10088		return(cur);
10089	}
10090    }
10091    return(NULL);
10092}
10093
10094static int
10095xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10096		     xmlSchemaPtr schema,
10097		     xmlSchemaBucketPtr bucket)
10098{
10099    int oldFlags;
10100    xmlDocPtr oldDoc;
10101    xmlNodePtr node;
10102    int ret, oldErrs;
10103    xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10104
10105    /*
10106    * Save old values; reset the *main* schema.
10107    * URGENT TODO: This is not good; move the per-document information
10108    * to the parser. Get rid of passing the main schema to the
10109    * parsing functions.
10110    */
10111    oldFlags = schema->flags;
10112    oldDoc = schema->doc;
10113    if (schema->flags != 0)
10114	xmlSchemaClearSchemaDefaults(schema);
10115    schema->doc = bucket->doc;
10116    pctxt->schema = schema;
10117    /*
10118    * Keep the current target namespace on the parser *not* on the
10119    * main schema.
10120    */
10121    pctxt->targetNamespace = bucket->targetNamespace;
10122    WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10123
10124    if ((bucket->targetNamespace != NULL) &&
10125	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10126	/*
10127	* We are parsing the schema for schemas!
10128	*/
10129	pctxt->isS4S = 1;
10130    }
10131    /* Mark it as parsed, even if parsing fails. */
10132    bucket->parsed++;
10133    /* Compile the schema doc. */
10134    node = xmlDocGetRootElement(bucket->doc);
10135    ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10136    if (ret != 0)
10137	goto exit;
10138    /* An empty schema; just get out. */
10139    if (node->children == NULL)
10140	goto exit;
10141    oldErrs = pctxt->nberrors;
10142    ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10143    if (ret != 0)
10144	goto exit;
10145    /*
10146    * TODO: Not nice, but I'm not 100% sure we will get always an error
10147    * as a result of the obove functions; so better rely on pctxt->err
10148    * as well.
10149    */
10150    if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10151	ret = pctxt->err;
10152	goto exit;
10153    }
10154
10155exit:
10156    WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10157    /* Restore schema values. */
10158    schema->doc = oldDoc;
10159    schema->flags = oldFlags;
10160    return(ret);
10161}
10162
10163static int
10164xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10165		     xmlSchemaPtr schema,
10166		     xmlSchemaBucketPtr bucket)
10167{
10168    xmlSchemaParserCtxtPtr newpctxt;
10169    int res = 0;
10170
10171    if (bucket == NULL)
10172	return(0);
10173    if (bucket->parsed) {
10174	PERROR_INT("xmlSchemaParseNewDoc",
10175	    "reparsing a schema doc");
10176	return(-1);
10177    }
10178    if (bucket->doc == NULL) {
10179	PERROR_INT("xmlSchemaParseNewDoc",
10180	    "parsing a schema doc, but there's no doc");
10181	return(-1);
10182    }
10183    if (pctxt->constructor == NULL) {
10184	PERROR_INT("xmlSchemaParseNewDoc",
10185	    "no constructor");
10186	return(-1);
10187    }
10188    /* Create and init the temporary parser context. */
10189    newpctxt = xmlSchemaNewParserCtxtUseDict(
10190	(const char *) bucket->schemaLocation, pctxt->dict);
10191    if (newpctxt == NULL)
10192	return(-1);
10193    newpctxt->constructor = pctxt->constructor;
10194    /*
10195    * TODO: Can we avoid that the parser knows about the main schema?
10196    * It would be better if he knows about the current schema bucket
10197    * only.
10198    */
10199    newpctxt->schema = schema;
10200    xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10201	pctxt->errCtxt);
10202    xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10203	pctxt->errCtxt);
10204    newpctxt->counter = pctxt->counter;
10205
10206
10207    res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10208
10209    /* Channel back errors and cleanup the temporary parser context. */
10210    if (res != 0)
10211	pctxt->err = res;
10212    pctxt->nberrors += newpctxt->nberrors;
10213    pctxt->counter = newpctxt->counter;
10214    newpctxt->constructor = NULL;
10215    /* Free the parser context. */
10216    xmlSchemaFreeParserCtxt(newpctxt);
10217    return(res);
10218}
10219
10220static void
10221xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10222				xmlSchemaSchemaRelationPtr rel)
10223{
10224    xmlSchemaSchemaRelationPtr cur = bucket->relations;
10225
10226    if (cur == NULL) {
10227	bucket->relations = rel;
10228	return;
10229    }
10230    while (cur->next != NULL)
10231	cur = cur->next;
10232    cur->next = rel;
10233}
10234
10235
10236static const xmlChar *
10237xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10238			  xmlNodePtr ctxtNode)
10239{
10240    /*
10241    * Build an absolue location URI.
10242    */
10243    if (location != NULL) {
10244	if (ctxtNode == NULL)
10245	    return(location);
10246	else {
10247	    xmlChar *base, *URI;
10248	    const xmlChar *ret = NULL;
10249
10250	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10251	    if (base == NULL) {
10252		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10253	    } else {
10254		URI = xmlBuildURI(location, base);
10255		xmlFree(base);
10256	    }
10257	    if (URI != NULL) {
10258		ret = xmlDictLookup(dict, URI, -1);
10259		xmlFree(URI);
10260		return(ret);
10261	    }
10262	}
10263    }
10264    return(NULL);
10265}
10266
10267
10268
10269/**
10270 * xmlSchemaAddSchemaDoc:
10271 * @pctxt:  a schema validation context
10272 * @schema:  the schema being built
10273 * @node:  a subtree containing XML Schema informations
10274 *
10275 * Parse an included (and to-be-redefined) XML schema document.
10276 *
10277 * Returns 0 on success, a positive error code on errors and
10278 *         -1 in case of an internal or API error.
10279 */
10280
10281static int
10282xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10283		int type, /* import or include or redefine */
10284		const xmlChar *schemaLocation,
10285		xmlDocPtr schemaDoc,
10286		const char *schemaBuffer,
10287		int schemaBufferLen,
10288		xmlNodePtr invokingNode,
10289		const xmlChar *sourceTargetNamespace,
10290		const xmlChar *importNamespace,
10291		xmlSchemaBucketPtr *bucket)
10292{
10293    const xmlChar *targetNamespace = NULL;
10294    xmlSchemaSchemaRelationPtr relation = NULL;
10295    xmlDocPtr doc = NULL;
10296    int res = 0, err = 0, located = 0, preserveDoc = 0;
10297    xmlSchemaBucketPtr bkt = NULL;
10298
10299    if (bucket != NULL)
10300	*bucket = NULL;
10301
10302    switch (type) {
10303	case XML_SCHEMA_SCHEMA_IMPORT:
10304	case XML_SCHEMA_SCHEMA_MAIN:
10305	    err = XML_SCHEMAP_SRC_IMPORT;
10306	    break;
10307	case XML_SCHEMA_SCHEMA_INCLUDE:
10308	    err = XML_SCHEMAP_SRC_INCLUDE;
10309	    break;
10310	case XML_SCHEMA_SCHEMA_REDEFINE:
10311	    err = XML_SCHEMAP_SRC_REDEFINE;
10312	    break;
10313    }
10314
10315
10316    /* Special handling for the main schema:
10317    * skip the location and relation logic and just parse the doc.
10318    * We need just a bucket to be returned in this case.
10319    */
10320    if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10321	goto doc_load;
10322
10323    /* Note that we expect the location to be an absulute URI. */
10324    if (schemaLocation != NULL) {
10325	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10326	if ((bkt != NULL) &&
10327	    (pctxt->constructor->bucket == bkt)) {
10328	    /* Report self-imports/inclusions/redefinitions. */
10329
10330	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10331		invokingNode, NULL,
10332		"The schema must not import/include/redefine itself",
10333		NULL, NULL);
10334	    goto exit;
10335	}
10336    }
10337    /*
10338    * Create a relation for the graph of schemas.
10339    */
10340    relation = xmlSchemaSchemaRelationCreate();
10341    if (relation == NULL)
10342	return(-1);
10343    xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10344	relation);
10345    relation->type = type;
10346
10347    /*
10348    * Save the namespace import information.
10349    */
10350    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10351	relation->importNamespace = importNamespace;
10352	if (schemaLocation == NULL) {
10353	    /*
10354	    * No location; this is just an import of the namespace.
10355	    * Note that we don't assign a bucket to the relation
10356	    * in this case.
10357	    */
10358	    goto exit;
10359	}
10360	targetNamespace = importNamespace;
10361    }
10362
10363    /* Did we already fetch the doc? */
10364    if (bkt != NULL) {
10365	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10366	    /*
10367	    * We included/redefined and then try to import a schema,
10368	    * but the new location provided for import was different.
10369	    */
10370	    if (schemaLocation == NULL)
10371		schemaLocation = BAD_CAST "in_memory_buffer";
10372	    if (!xmlStrEqual(schemaLocation,
10373		bkt->schemaLocation)) {
10374		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10375		    invokingNode, NULL,
10376		    "The schema document '%s' cannot be imported, since "
10377		    "it was already included or redefined",
10378		    schemaLocation, NULL);
10379		goto exit;
10380	    }
10381	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10382	    /*
10383	    * We imported and then try to include/redefine a schema,
10384	    * but the new location provided for the include/redefine
10385	    * was different.
10386	    */
10387	    if (schemaLocation == NULL)
10388		schemaLocation = BAD_CAST "in_memory_buffer";
10389	    if (!xmlStrEqual(schemaLocation,
10390		bkt->schemaLocation)) {
10391		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10392		    invokingNode, NULL,
10393		    "The schema document '%s' cannot be included or "
10394		    "redefined, since it was already imported",
10395		    schemaLocation, NULL);
10396		goto exit;
10397	    }
10398	}
10399    }
10400
10401    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10402	/*
10403	* Given that the schemaLocation [attribute] is only a hint, it is open
10404	* to applications to ignore all but the first <import> for a given
10405	* namespace, regardless of the �actual value� of schemaLocation, but
10406	* such a strategy risks missing useful information when new
10407	* schemaLocations are offered.
10408	*
10409	* We will use the first <import> that comes with a location.
10410	* Further <import>s *with* a location, will result in an error.
10411	* TODO: Better would be to just report a warning here, but
10412	* we'll try it this way until someone complains.
10413	*
10414	* Schema Document Location Strategy:
10415	* 3 Based on the namespace name, identify an existing schema document,
10416	* either as a resource which is an XML document or a <schema> element
10417	* information item, in some local schema repository;
10418	* 5 Attempt to resolve the namespace name to locate such a resource.
10419	*
10420	* NOTE: (3) and (5) are not supported.
10421	*/
10422	if (bkt != NULL) {
10423	    relation->bucket = bkt;
10424	    goto exit;
10425	}
10426	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10427	    importNamespace, 1);
10428
10429	if (bkt != NULL) {
10430	    relation->bucket = bkt;
10431	    if (bkt->schemaLocation == NULL) {
10432		/* First given location of the schema; load the doc. */
10433		bkt->schemaLocation = schemaLocation;
10434	    } else {
10435		if (!xmlStrEqual(schemaLocation,
10436		    bkt->schemaLocation)) {
10437		    /*
10438		    * Additional location given; just skip it.
10439		    * URGENT TODO: We should report a warning here.
10440		    * res = XML_SCHEMAP_SRC_IMPORT;
10441		    */
10442		    if (schemaLocation == NULL)
10443			schemaLocation = BAD_CAST "in_memory_buffer";
10444
10445		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10446			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10447			invokingNode, NULL,
10448			"Skipping import of schema located at '%s' for the "
10449			"namespace '%s', since this namespace was already "
10450			"imported with the schema located at '%s'",
10451			schemaLocation, importNamespace, bkt->schemaLocation);
10452		}
10453		goto exit;
10454	    }
10455	}
10456	/*
10457	* No bucket + first location: load the doc and create a
10458	* bucket.
10459	*/
10460    } else {
10461	/* <include> and <redefine> */
10462	if (bkt != NULL) {
10463
10464	    if ((bkt->origTargetNamespace == NULL) &&
10465		(bkt->targetNamespace != sourceTargetNamespace)) {
10466		xmlSchemaBucketPtr chamel;
10467
10468		/*
10469		* Chameleon include/redefine: skip loading only if it was
10470		* aleady build for the targetNamespace of the including
10471		* schema.
10472		*/
10473		/*
10474		* URGENT TODO: If the schema is a chameleon-include then copy
10475		* the components into the including schema and modify the
10476		* targetNamespace of those components, do nothing otherwise.
10477		* NOTE: This is currently worked-around by compiling the
10478		* chameleon for every destinct including targetNamespace; thus
10479		* not performant at the moment.
10480		* TODO: Check when the namespace in wildcards for chameleons
10481		* needs to be converted: before we built wildcard intersections
10482		* or after.
10483		*   Answer: after!
10484		*/
10485		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10486		    schemaLocation, sourceTargetNamespace);
10487		if (chamel != NULL) {
10488		    /* A fitting chameleon was already parsed; NOP. */
10489		    relation->bucket = chamel;
10490		    goto exit;
10491		}
10492		/*
10493		* We need to parse the chameleon again for a different
10494		* targetNamespace.
10495		* CHAMELEON TODO: Optimize this by only parsing the
10496		* chameleon once, and then copying the components to
10497		* the new targetNamespace.
10498		*/
10499		bkt = NULL;
10500	    } else {
10501		relation->bucket = bkt;
10502		goto exit;
10503	    }
10504	}
10505    }
10506    if ((bkt != NULL) && (bkt->doc != NULL)) {
10507	PERROR_INT("xmlSchemaAddSchemaDoc",
10508	    "trying to load a schema doc, but a doc is already "
10509	    "assigned to the schema bucket");
10510	goto exit_failure;
10511    }
10512
10513doc_load:
10514    /*
10515    * Load the document.
10516    */
10517    if (schemaDoc != NULL) {
10518	doc = schemaDoc;
10519	/* Don' free this one, since it was provided by the caller. */
10520	preserveDoc = 1;
10521	/* TODO: Does the context or the doc hold the location? */
10522	if (schemaDoc->URL != NULL)
10523	    schemaLocation = xmlDictLookup(pctxt->dict,
10524		schemaDoc->URL, -1);
10525        else
10526	    schemaLocation = BAD_CAST "in_memory_buffer";
10527    } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10528	xmlParserCtxtPtr parserCtxt;
10529
10530	parserCtxt = xmlNewParserCtxt();
10531	if (parserCtxt == NULL) {
10532	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10533		"allocating a parser context", NULL);
10534	    goto exit_failure;
10535	}
10536	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10537	    /*
10538	    * TODO: Do we have to burden the schema parser dict with all
10539	    * the content of the schema doc?
10540	    */
10541	    xmlDictFree(parserCtxt->dict);
10542	    parserCtxt->dict = pctxt->dict;
10543	    xmlDictReference(parserCtxt->dict);
10544	}
10545	if (schemaLocation != NULL) {
10546	    /* Parse from file. */
10547	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10548		NULL, SCHEMAS_PARSE_OPTIONS);
10549	} else if (schemaBuffer != NULL) {
10550	    /* Parse from memory buffer. */
10551	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10552		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10553	    schemaLocation = BAD_CAST "in_memory_buffer";
10554	    if (doc != NULL)
10555		doc->URL = xmlStrdup(schemaLocation);
10556	}
10557	/*
10558	* For <import>:
10559	* 2.1 The referent is (a fragment of) a resource which is an
10560	* XML document (see clause 1.1), which in turn corresponds to
10561	* a <schema> element information item in a well-formed information
10562	* set, which in turn corresponds to a valid schema.
10563	* TODO: (2.1) fragments of XML documents are not supported.
10564	*
10565	* 2.2 The referent is a <schema> element information item in
10566	* a well-formed information set, which in turn corresponds
10567	* to a valid schema.
10568	* TODO: (2.2) is not supported.
10569	*/
10570	if (doc == NULL) {
10571	    xmlErrorPtr lerr;
10572	    lerr = xmlGetLastError();
10573	    /*
10574	    * Check if this a parser error, or if the document could
10575	    * just not be located.
10576	    * TODO: Try to find specific error codes to react only on
10577	    * localisation failures.
10578	    */
10579	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10580		/*
10581		* We assume a parser error here.
10582		*/
10583		located = 1;
10584		/* TODO: Error code ?? */
10585		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10586		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10587		    invokingNode, NULL,
10588		    "Failed to parse the XML resource '%s'",
10589		    schemaLocation, NULL);
10590	    }
10591	}
10592	xmlFreeParserCtxt(parserCtxt);
10593	if ((doc == NULL) && located)
10594	    goto exit_error;
10595    } else {
10596	xmlSchemaPErr(pctxt, NULL,
10597	    XML_SCHEMAP_NOTHING_TO_PARSE,
10598	    "No information for parsing was provided with the "
10599	    "given schema parser context.\n",
10600	    NULL, NULL);
10601	goto exit_failure;
10602    }
10603    /*
10604    * Preprocess the document.
10605    */
10606    if (doc != NULL) {
10607	xmlNodePtr docElem = NULL;
10608
10609	located = 1;
10610	docElem = xmlDocGetRootElement(doc);
10611	if (docElem == NULL) {
10612	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10613		invokingNode, NULL,
10614		"The document '%s' has no document element",
10615		schemaLocation, NULL);
10616	    goto exit_error;
10617	}
10618	/*
10619	* Remove all the blank text nodes.
10620	*/
10621	xmlSchemaCleanupDoc(pctxt, docElem);
10622	/*
10623	* Check the schema's top level element.
10624	*/
10625	if (!IS_SCHEMA(docElem, "schema")) {
10626	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10627		invokingNode, NULL,
10628		"The XML document '%s' is not a schema document",
10629		schemaLocation, NULL);
10630	    goto exit_error;
10631	}
10632	/*
10633	* Note that we don't apply a type check for the
10634	* targetNamespace value here.
10635	*/
10636	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10637	    "targetNamespace");
10638    }
10639
10640/* after_doc_loading: */
10641    if ((bkt == NULL) && located) {
10642	/* Only create a bucket if the schema was located. */
10643        bkt = xmlSchemaBucketCreate(pctxt, type,
10644	    targetNamespace);
10645	if (bkt == NULL)
10646	    goto exit_failure;
10647    }
10648    if (bkt != NULL) {
10649	bkt->schemaLocation = schemaLocation;
10650	bkt->located = located;
10651	if (doc != NULL) {
10652	    bkt->doc = doc;
10653	    bkt->targetNamespace = targetNamespace;
10654	    bkt->origTargetNamespace = targetNamespace;
10655	    if (preserveDoc)
10656		bkt->preserveDoc = 1;
10657	}
10658	if (WXS_IS_BUCKET_IMPMAIN(type))
10659	    bkt->imported++;
10660	    /*
10661	    * Add it to the graph of schemas.
10662	    */
10663	if (relation != NULL)
10664	    relation->bucket = bkt;
10665    }
10666
10667exit:
10668    /*
10669    * Return the bucket explicitely; this is needed for the
10670    * main schema.
10671    */
10672    if (bucket != NULL)
10673	*bucket = bkt;
10674    return (0);
10675
10676exit_error:
10677    if ((doc != NULL) && (! preserveDoc)) {
10678	xmlFreeDoc(doc);
10679	if (bkt != NULL)
10680	    bkt->doc = NULL;
10681    }
10682    return(pctxt->err);
10683
10684exit_failure:
10685    if ((doc != NULL) && (! preserveDoc)) {
10686	xmlFreeDoc(doc);
10687	if (bkt != NULL)
10688	    bkt->doc = NULL;
10689    }
10690    return (-1);
10691}
10692
10693/**
10694 * xmlSchemaParseImport:
10695 * @ctxt:  a schema validation context
10696 * @schema:  the schema being built
10697 * @node:  a subtree containing XML Schema informations
10698 *
10699 * parse a XML schema Import definition
10700 * *WARNING* this interface is highly subject to change
10701 *
10702 * Returns 0 in case of success, a positive error code if
10703 * not valid and -1 in case of an internal error.
10704 */
10705static int
10706xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10707                     xmlNodePtr node)
10708{
10709    xmlNodePtr child;
10710    const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10711    const xmlChar *thisTargetNamespace;
10712    xmlAttrPtr attr;
10713    int ret = 0;
10714    xmlSchemaBucketPtr bucket = NULL;
10715
10716    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10717        return (-1);
10718
10719    /*
10720    * Check for illegal attributes.
10721    */
10722    attr = node->properties;
10723    while (attr != NULL) {
10724	if (attr->ns == NULL) {
10725	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10726		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10727		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10728		xmlSchemaPIllegalAttrErr(pctxt,
10729		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10730	    }
10731	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10732	    xmlSchemaPIllegalAttrErr(pctxt,
10733		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10734	}
10735	attr = attr->next;
10736    }
10737    /*
10738    * Extract and validate attributes.
10739    */
10740    if (xmlSchemaPValAttr(pctxt, NULL, node,
10741	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10742	&namespaceName) != 0) {
10743	xmlSchemaPSimpleTypeErr(pctxt,
10744	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10745	    NULL, node,
10746	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10747	    NULL, namespaceName, NULL, NULL, NULL);
10748	return (pctxt->err);
10749    }
10750
10751    if (xmlSchemaPValAttr(pctxt, NULL, node,
10752	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10753	&schemaLocation) != 0) {
10754	xmlSchemaPSimpleTypeErr(pctxt,
10755	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10756	    NULL, node,
10757	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10758	    NULL, namespaceName, NULL, NULL, NULL);
10759	return (pctxt->err);
10760    }
10761    /*
10762    * And now for the children...
10763    */
10764    child = node->children;
10765    if (IS_SCHEMA(child, "annotation")) {
10766        /*
10767         * the annotation here is simply discarded ...
10768	 * TODO: really?
10769         */
10770        child = child->next;
10771    }
10772    if (child != NULL) {
10773	xmlSchemaPContentErr(pctxt,
10774	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10775	    NULL, node, child, NULL,
10776	    "(annotation?)");
10777    }
10778    /*
10779    * Apply additional constraints.
10780    *
10781    * Note that it is important to use the original @targetNamespace
10782    * (or none at all), to rule out imports of schemas _with_ a
10783    * @targetNamespace if the importing schema is a chameleon schema
10784    * (with no @targetNamespace).
10785    */
10786    thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10787    if (namespaceName != NULL) {
10788	/*
10789	* 1.1 If the namespace [attribute] is present, then its �actual value�
10790	* must not match the �actual value� of the enclosing <schema>'s
10791	* targetNamespace [attribute].
10792	*/
10793	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10794	    xmlSchemaPCustomErr(pctxt,
10795		XML_SCHEMAP_SRC_IMPORT_1_1,
10796		NULL, node,
10797		"The value of the attribute 'namespace' must not match "
10798		"the target namespace '%s' of the importing schema",
10799		thisTargetNamespace);
10800	    return (pctxt->err);
10801	}
10802    } else {
10803	/*
10804	* 1.2 If the namespace [attribute] is not present, then the enclosing
10805	* <schema> must have a targetNamespace [attribute].
10806	*/
10807	if (thisTargetNamespace == NULL) {
10808	    xmlSchemaPCustomErr(pctxt,
10809		XML_SCHEMAP_SRC_IMPORT_1_2,
10810		NULL, node,
10811		"The attribute 'namespace' must be existent if "
10812		"the importing schema has no target namespace",
10813		NULL);
10814	    return (pctxt->err);
10815	}
10816    }
10817    /*
10818    * Locate and acquire the schema document.
10819    */
10820    if (schemaLocation != NULL)
10821	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10822	    schemaLocation, node);
10823    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10824	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10825	namespaceName, &bucket);
10826
10827    if (ret != 0)
10828	return(ret);
10829
10830    /*
10831    * For <import>: "It is *not* an error for the application
10832    * schema reference strategy to fail."
10833    * So just don't parse if no schema document was found.
10834    * Note that we will get no bucket if the schema could not be
10835    * located or if there was no schemaLocation.
10836    */
10837    if ((bucket == NULL) && (schemaLocation != NULL)) {
10838	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10839	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10840	    node, NULL,
10841	    "Failed to locate a schema at location '%s'. "
10842	    "Skipping the import", schemaLocation, NULL, NULL);
10843    }
10844
10845    if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10846	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10847    }
10848
10849    return (ret);
10850}
10851
10852static int
10853xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10854				     xmlSchemaPtr schema,
10855				     xmlNodePtr node,
10856				     xmlChar **schemaLocation,
10857				     int type)
10858{
10859    xmlAttrPtr attr;
10860
10861    if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10862	(schemaLocation == NULL))
10863        return (-1);
10864
10865    *schemaLocation = NULL;
10866    /*
10867    * Check for illegal attributes.
10868    * Applies for both <include> and <redefine>.
10869    */
10870    attr = node->properties;
10871    while (attr != NULL) {
10872	if (attr->ns == NULL) {
10873	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10874		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10875		xmlSchemaPIllegalAttrErr(pctxt,
10876		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10877	    }
10878	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10879	    xmlSchemaPIllegalAttrErr(pctxt,
10880		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10881	}
10882	attr = attr->next;
10883    }
10884    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10885    /*
10886    * Preliminary step, extract the URI-Reference and make an URI
10887    * from the base.
10888    */
10889    /*
10890    * Attribute "schemaLocation" is mandatory.
10891    */
10892    attr = xmlSchemaGetPropNode(node, "schemaLocation");
10893    if (attr != NULL) {
10894        xmlChar *base = NULL;
10895        xmlChar *uri = NULL;
10896
10897	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10898	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10899	    (const xmlChar **) schemaLocation) != 0)
10900	    goto exit_error;
10901	base = xmlNodeGetBase(node->doc, node);
10902	if (base == NULL) {
10903	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10904	} else {
10905	    uri = xmlBuildURI(*schemaLocation, base);
10906	    xmlFree(base);
10907	}
10908	if (uri == NULL) {
10909	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10910		"could not build an URI from the schemaLocation")
10911	    goto exit_failure;
10912	}
10913	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10914	xmlFree(uri);
10915    } else {
10916	xmlSchemaPMissingAttrErr(pctxt,
10917	    XML_SCHEMAP_S4S_ATTR_MISSING,
10918	    NULL, node, "schemaLocation", NULL);
10919	goto exit_error;
10920    }
10921    /*
10922    * Report self-inclusion and self-redefinition.
10923    */
10924    if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10925	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10926	    xmlSchemaPCustomErr(pctxt,
10927		XML_SCHEMAP_SRC_REDEFINE,
10928		NULL, node,
10929		"The schema document '%s' cannot redefine itself.",
10930		*schemaLocation);
10931	} else {
10932	    xmlSchemaPCustomErr(pctxt,
10933		XML_SCHEMAP_SRC_INCLUDE,
10934		NULL, node,
10935		"The schema document '%s' cannot include itself.",
10936		*schemaLocation);
10937	}
10938	goto exit_error;
10939    }
10940
10941    return(0);
10942exit_error:
10943    return(pctxt->err);
10944exit_failure:
10945    return(-1);
10946}
10947
10948static int
10949xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10950				xmlSchemaPtr schema,
10951				xmlNodePtr node,
10952				int type)
10953{
10954    xmlNodePtr child = NULL;
10955    const xmlChar *schemaLocation = NULL;
10956    int res = 0; /* hasRedefinitions = 0 */
10957    int isChameleon = 0, wasChameleon = 0;
10958    xmlSchemaBucketPtr bucket = NULL;
10959
10960    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10961        return (-1);
10962
10963    /*
10964    * Parse attributes. Note that the returned schemaLocation will
10965    * be already converted to an absolute URI.
10966    */
10967    res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10968	node, (xmlChar **) (&schemaLocation), type);
10969    if (res != 0)
10970	return(res);
10971    /*
10972    * Load and add the schema document.
10973    */
10974    res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10975	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10976    if (res != 0)
10977	return(res);
10978    /*
10979    * If we get no schema bucket back, then this means that the schema
10980    * document could not be located or was broken XML or was not
10981    * a schema document.
10982    */
10983    if ((bucket == NULL) || (bucket->doc == NULL)) {
10984	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10985	    /*
10986	    * WARNING for <include>:
10987	    * We will raise an error if the schema cannot be located
10988	    * for inclusions, since the that was the feedback from the
10989	    * schema people. I.e. the following spec piece will *not* be
10990	    * satisfied:
10991	    * SPEC src-include: "It is not an error for the �actual value� of the
10992	    * schemaLocation [attribute] to fail to resolve it all, in which
10993	    * case no corresponding inclusion is performed.
10994	    * So do we need a warning report here?"
10995	    */
10996	    res = XML_SCHEMAP_SRC_INCLUDE;
10997	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10998		node, NULL,
10999		"Failed to load the document '%s' for inclusion",
11000		schemaLocation, NULL);
11001	} else {
11002	    /*
11003	    * NOTE: This was changed to raise an error even if no redefinitions
11004	    * are specified.
11005	    *
11006	    * SPEC src-redefine (1)
11007	    * "If there are any element information items among the [children]
11008	    * other than <annotation> then the �actual value� of the
11009	    * schemaLocation [attribute] must successfully resolve."
11010	    * TODO: Ask the WG if a the location has always to resolve
11011	    * here as well!
11012	    */
11013	    res = XML_SCHEMAP_SRC_REDEFINE;
11014	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11015		node, NULL,
11016		"Failed to load the document '%s' for redefinition",
11017		schemaLocation, NULL);
11018	}
11019    } else {
11020	/*
11021	* Check targetNamespace sanity before parsing the new schema.
11022	* TODO: Note that we won't check further content if the
11023	* targetNamespace was bad.
11024	*/
11025	if (bucket->origTargetNamespace != NULL) {
11026	    /*
11027	    * SPEC src-include (2.1)
11028	    * "SII has a targetNamespace [attribute], and its �actual
11029	    * value� is identical to the �actual value� of the targetNamespace
11030	    * [attribute] of SII� (which must have such an [attribute])."
11031	    */
11032	    if (pctxt->targetNamespace == NULL) {
11033		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11034		    XML_SCHEMAP_SRC_INCLUDE,
11035		    node, NULL,
11036		    "The target namespace of the included/redefined schema "
11037		    "'%s' has to be absent, since the including/redefining "
11038		    "schema has no target namespace",
11039		    schemaLocation, NULL);
11040		goto exit_error;
11041	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11042		pctxt->targetNamespace)) {
11043		/* TODO: Change error function. */
11044		xmlSchemaPCustomErrExt(pctxt,
11045		    XML_SCHEMAP_SRC_INCLUDE,
11046		    NULL, node,
11047		    "The target namespace '%s' of the included/redefined "
11048		    "schema '%s' differs from '%s' of the "
11049		    "including/redefining schema",
11050		    bucket->origTargetNamespace, schemaLocation,
11051		    pctxt->targetNamespace);
11052		goto exit_error;
11053	    }
11054	} else if (pctxt->targetNamespace != NULL) {
11055	    /*
11056	    * Chameleons: the original target namespace will
11057	    * differ from the resulting namespace.
11058	    */
11059	    isChameleon = 1;
11060	    if (bucket->parsed &&
11061		bucket->origTargetNamespace != NULL) {
11062		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11063		    XML_SCHEMAP_SRC_INCLUDE,
11064		    node, NULL,
11065		    "The target namespace of the included/redefined schema "
11066		    "'%s' has to be absent or the same as the "
11067		    "including/redefining schema's target namespace",
11068		    schemaLocation, NULL);
11069		goto exit_error;
11070	    }
11071	    bucket->targetNamespace = pctxt->targetNamespace;
11072	}
11073    }
11074    /*
11075    * Parse the schema.
11076    */
11077    if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11078	if (isChameleon) {
11079	    /* TODO: Get rid of this flag on the schema itself. */
11080	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11081		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11082	    } else
11083		wasChameleon = 1;
11084	}
11085	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11086	/* Restore chameleon flag. */
11087	if (isChameleon && (!wasChameleon))
11088	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11089    }
11090    /*
11091    * And now for the children...
11092    */
11093    child = node->children;
11094    if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11095	/*
11096	* Parse (simpleType | complexType | group | attributeGroup))*
11097	*/
11098	pctxt->redefined = bucket;
11099	/*
11100	* How to proceed if the redefined schema was not located?
11101	*/
11102	pctxt->isRedefine = 1;
11103	while (IS_SCHEMA(child, "annotation") ||
11104	    IS_SCHEMA(child, "simpleType") ||
11105	    IS_SCHEMA(child, "complexType") ||
11106	    IS_SCHEMA(child, "group") ||
11107	    IS_SCHEMA(child, "attributeGroup")) {
11108	    if (IS_SCHEMA(child, "annotation")) {
11109		/*
11110		* TODO: discard or not?
11111		*/
11112	    } else if (IS_SCHEMA(child, "simpleType")) {
11113		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11114	    } else if (IS_SCHEMA(child, "complexType")) {
11115		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11116		/* hasRedefinitions = 1; */
11117	    } else if (IS_SCHEMA(child, "group")) {
11118		/* hasRedefinitions = 1; */
11119		xmlSchemaParseModelGroupDefinition(pctxt,
11120		    schema, child);
11121	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11122		/* hasRedefinitions = 1; */
11123		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11124		    child);
11125	    }
11126	    child = child->next;
11127	}
11128	pctxt->redefined = NULL;
11129	pctxt->isRedefine = 0;
11130    } else {
11131	if (IS_SCHEMA(child, "annotation")) {
11132	    /*
11133	    * TODO: discard or not?
11134	    */
11135	    child = child->next;
11136	}
11137    }
11138    if (child != NULL) {
11139	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11140	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11141	    xmlSchemaPContentErr(pctxt, res,
11142		NULL, node, child, NULL,
11143		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11144	} else {
11145	     xmlSchemaPContentErr(pctxt, res,
11146		NULL, node, child, NULL,
11147		"(annotation?)");
11148	}
11149    }
11150    return(res);
11151
11152exit_error:
11153    return(pctxt->err);
11154}
11155
11156static int
11157xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11158                       xmlNodePtr node)
11159{
11160    int res;
11161#ifndef ENABLE_REDEFINE
11162    TODO
11163    return(0);
11164#endif
11165    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11166	XML_SCHEMA_SCHEMA_REDEFINE);
11167    if (res != 0)
11168	return(res);
11169    return(0);
11170}
11171
11172static int
11173xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11174                       xmlNodePtr node)
11175{
11176    int res;
11177
11178    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11179	XML_SCHEMA_SCHEMA_INCLUDE);
11180    if (res != 0)
11181	return(res);
11182    return(0);
11183}
11184
11185/**
11186 * xmlSchemaParseModelGroup:
11187 * @ctxt:  a schema validation context
11188 * @schema:  the schema being built
11189 * @node:  a subtree containing XML Schema informations
11190 * @type: the "compositor" type
11191 * @particleNeeded: if a a model group with a particle
11192 *
11193 * parse a XML schema Sequence definition.
11194 * Applies parts of:
11195 *   Schema Representation Constraint:
11196 *     Redefinition Constraints and Semantics (src-redefine)
11197 *     (6.1), (6.1.1), (6.1.2)
11198 *
11199 *   Schema Component Constraint:
11200 *     All Group Limited (cos-all-limited) (2)
11201 *     TODO: Actually this should go to component-level checks,
11202 *     but is done here due to performance. Move it to an other layer
11203 *     is schema construction via an API is implemented.
11204 *
11205 * *WARNING* this interface is highly subject to change
11206 *
11207 * Returns -1 in case of error, 0 if the declaration is improper and
11208 *         1 in case of success.
11209 */
11210static xmlSchemaTreeItemPtr
11211xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11212			 xmlNodePtr node, xmlSchemaTypeType type,
11213			 int withParticle)
11214{
11215    xmlSchemaModelGroupPtr item;
11216    xmlSchemaParticlePtr particle = NULL;
11217    xmlNodePtr child = NULL;
11218    xmlAttrPtr attr;
11219    int min = 1, max = 1, isElemRef, hasRefs = 0;
11220
11221    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11222        return (NULL);
11223    /*
11224    * Create a model group with the given compositor.
11225    */
11226    item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11227    if (item == NULL)
11228	return (NULL);
11229
11230    if (withParticle) {
11231	if (type == XML_SCHEMA_TYPE_ALL) {
11232	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11233	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11234	} else {
11235	    /* choice + sequence */
11236	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11237	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11238		"(xs:nonNegativeInteger | unbounded)");
11239	}
11240	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11241	/*
11242	* Create a particle
11243	*/
11244	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11245	if (particle == NULL)
11246	    return (NULL);
11247	particle->children = (xmlSchemaTreeItemPtr) item;
11248	/*
11249	* Check for illegal attributes.
11250	*/
11251	attr = node->properties;
11252	while (attr != NULL) {
11253	    if (attr->ns == NULL) {
11254		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11255		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11256		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11257		    xmlSchemaPIllegalAttrErr(ctxt,
11258			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11259		}
11260	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11261		xmlSchemaPIllegalAttrErr(ctxt,
11262		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11263	    }
11264	    attr = attr->next;
11265	}
11266    } else {
11267	/*
11268	* Check for illegal attributes.
11269	*/
11270	attr = node->properties;
11271	while (attr != NULL) {
11272	    if (attr->ns == NULL) {
11273		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11274		    xmlSchemaPIllegalAttrErr(ctxt,
11275			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11276		}
11277	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11278		xmlSchemaPIllegalAttrErr(ctxt,
11279		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11280	    }
11281	    attr = attr->next;
11282	}
11283    }
11284
11285    /*
11286    * Extract and validate attributes.
11287    */
11288    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11289    /*
11290    * And now for the children...
11291    */
11292    child = node->children;
11293    if (IS_SCHEMA(child, "annotation")) {
11294        item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11295        child = child->next;
11296    }
11297    if (type == XML_SCHEMA_TYPE_ALL) {
11298	xmlSchemaParticlePtr part, last = NULL;
11299
11300	while (IS_SCHEMA(child, "element")) {
11301	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11302		schema, child, &isElemRef, 0);
11303	    /*
11304	    * SPEC cos-all-limited (2)
11305	    * "The {max occurs} of all the particles in the {particles}
11306	    * of the ('all') group must be 0 or 1.
11307	    */
11308	    if (part != NULL) {
11309		if (isElemRef)
11310		    hasRefs++;
11311		if (part->minOccurs > 1) {
11312		    xmlSchemaPCustomErr(ctxt,
11313			XML_SCHEMAP_COS_ALL_LIMITED,
11314			NULL, child,
11315			"Invalid value for minOccurs (must be 0 or 1)",
11316			NULL);
11317		    /* Reset to 1. */
11318		    part->minOccurs = 1;
11319		}
11320		if (part->maxOccurs > 1) {
11321		    xmlSchemaPCustomErr(ctxt,
11322			XML_SCHEMAP_COS_ALL_LIMITED,
11323			NULL, child,
11324			"Invalid value for maxOccurs (must be 0 or 1)",
11325			NULL);
11326		    /* Reset to 1. */
11327		    part->maxOccurs = 1;
11328		}
11329		if (last == NULL)
11330		    item->children = (xmlSchemaTreeItemPtr) part;
11331		else
11332		    last->next = (xmlSchemaTreeItemPtr) part;
11333		last = part;
11334	    }
11335	    child = child->next;
11336	}
11337	if (child != NULL) {
11338	    xmlSchemaPContentErr(ctxt,
11339		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11340		NULL, node, child, NULL,
11341		"(annotation?, (annotation?, element*)");
11342	}
11343    } else {
11344	/* choice + sequence */
11345	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11346
11347	while ((IS_SCHEMA(child, "element")) ||
11348	    (IS_SCHEMA(child, "group")) ||
11349	    (IS_SCHEMA(child, "any")) ||
11350	    (IS_SCHEMA(child, "choice")) ||
11351	    (IS_SCHEMA(child, "sequence"))) {
11352
11353	    if (IS_SCHEMA(child, "element")) {
11354		part = (xmlSchemaTreeItemPtr)
11355		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11356		if (part && isElemRef)
11357		    hasRefs++;
11358	    } else if (IS_SCHEMA(child, "group")) {
11359		part =
11360		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11361		if (part != NULL)
11362		    hasRefs++;
11363		/*
11364		* Handle redefinitions.
11365		*/
11366		if (ctxt->isRedefine && ctxt->redef &&
11367		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11368		    part && part->children)
11369		{
11370		    if ((xmlSchemaGetQNameRefName(part->children) ==
11371			    ctxt->redef->refName) &&
11372			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11373			    ctxt->redef->refTargetNs))
11374		    {
11375			/*
11376			* SPEC src-redefine:
11377			* (6.1) "If it has a <group> among its contents at
11378			* some level the �actual value� of whose ref
11379			* [attribute] is the same as the �actual value� of
11380			* its own name attribute plus target namespace, then
11381			* all of the following must be true:"
11382			* (6.1.1) "It must have exactly one such group."
11383			*/
11384			if (ctxt->redefCounter != 0) {
11385			    xmlChar *str = NULL;
11386
11387			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11388				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11389				"The redefining model group definition "
11390				"'%s' must not contain more than one "
11391				"reference to the redefined definition",
11392				xmlSchemaFormatQName(&str,
11393				    ctxt->redef->refTargetNs,
11394				    ctxt->redef->refName),
11395				NULL);
11396			    FREE_AND_NULL(str)
11397			    part = NULL;
11398			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11399			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11400			{
11401			    xmlChar *str = NULL;
11402			    /*
11403			    * SPEC src-redefine:
11404			    * (6.1.2) "The �actual value� of both that
11405			    * group's minOccurs and maxOccurs [attribute]
11406			    * must be 1 (or �absent�).
11407			    */
11408			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11409				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11410				"The redefining model group definition "
11411				"'%s' must not contain a reference to the "
11412				"redefined definition with a "
11413				"maxOccurs/minOccurs other than 1",
11414				xmlSchemaFormatQName(&str,
11415				    ctxt->redef->refTargetNs,
11416				    ctxt->redef->refName),
11417				NULL);
11418			    FREE_AND_NULL(str)
11419			    part = NULL;
11420			}
11421			ctxt->redef->reference = WXS_BASIC_CAST part;
11422			ctxt->redefCounter++;
11423		    }
11424		}
11425	    } else if (IS_SCHEMA(child, "any")) {
11426		part = (xmlSchemaTreeItemPtr)
11427		    xmlSchemaParseAny(ctxt, schema, child);
11428	    } else if (IS_SCHEMA(child, "choice")) {
11429		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11430		    XML_SCHEMA_TYPE_CHOICE, 1);
11431	    } else if (IS_SCHEMA(child, "sequence")) {
11432		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11433		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11434	    }
11435	    if (part != NULL) {
11436		if (last == NULL)
11437		    item->children = part;
11438		else
11439		    last->next = part;
11440		last = part;
11441	    }
11442	    child = child->next;
11443	}
11444	if (child != NULL) {
11445	    xmlSchemaPContentErr(ctxt,
11446		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11447		NULL, node, child, NULL,
11448		"(annotation?, (element | group | choice | sequence | any)*)");
11449	}
11450    }
11451    if ((max == 0) && (min == 0))
11452	return (NULL);
11453    if (hasRefs) {
11454	/*
11455	* We need to resolve references.
11456	*/
11457	WXS_ADD_PENDING(ctxt, item);
11458    }
11459    if (withParticle)
11460	return ((xmlSchemaTreeItemPtr) particle);
11461    else
11462	return ((xmlSchemaTreeItemPtr) item);
11463}
11464
11465/**
11466 * xmlSchemaParseRestriction:
11467 * @ctxt:  a schema validation context
11468 * @schema:  the schema being built
11469 * @node:  a subtree containing XML Schema informations
11470 *
11471 * parse a XML schema Restriction definition
11472 * *WARNING* this interface is highly subject to change
11473 *
11474 * Returns the type definition or NULL in case of error
11475 */
11476static xmlSchemaTypePtr
11477xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11478                          xmlNodePtr node, xmlSchemaTypeType parentType)
11479{
11480    xmlSchemaTypePtr type;
11481    xmlNodePtr child = NULL;
11482    xmlAttrPtr attr;
11483
11484    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11485        return (NULL);
11486    /* Not a component, don't create it. */
11487    type = ctxt->ctxtType;
11488    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11489
11490    /*
11491    * Check for illegal attributes.
11492    */
11493    attr = node->properties;
11494    while (attr != NULL) {
11495	if (attr->ns == NULL) {
11496	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11497		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11498		xmlSchemaPIllegalAttrErr(ctxt,
11499		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11500	    }
11501	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11502	    xmlSchemaPIllegalAttrErr(ctxt,
11503		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11504	}
11505	attr = attr->next;
11506    }
11507    /*
11508    * Extract and validate attributes.
11509    */
11510    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11511    /*
11512    * Attribute
11513    */
11514    /*
11515    * Extract the base type. The "base" attribute is mandatory if inside
11516    * a complex type or if redefining.
11517    *
11518    * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11519    * among its [children]), the simple type definition which is
11520    * the {content type} of the type definition �resolved� to by
11521    * the �actual value� of the base [attribute]"
11522    */
11523    if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11524	&(type->baseNs), &(type->base)) == 0)
11525    {
11526	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11527	    xmlSchemaPMissingAttrErr(ctxt,
11528		XML_SCHEMAP_S4S_ATTR_MISSING,
11529		NULL, node, "base", NULL);
11530	} else if ((ctxt->isRedefine) &&
11531	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11532	{
11533	    if (type->base == NULL) {
11534		xmlSchemaPMissingAttrErr(ctxt,
11535		    XML_SCHEMAP_S4S_ATTR_MISSING,
11536		    NULL, node, "base", NULL);
11537	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11538		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11539	    {
11540		xmlChar *str1 = NULL, *str2 = NULL;
11541		/*
11542		* REDEFINE: SPEC src-redefine (5)
11543		* "Within the [children], each <simpleType> must have a
11544		* <restriction> among its [children] ... the �actual value� of
11545		* whose base [attribute] must be the same as the �actual value�
11546		* of its own name attribute plus target namespace;"
11547		*/
11548		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11549		    NULL, node, "This is a redefinition, but the QName "
11550		    "value '%s' of the 'base' attribute does not match the "
11551		    "type's designation '%s'",
11552		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11553		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11554			type->name), NULL);
11555		FREE_AND_NULL(str1);
11556		FREE_AND_NULL(str2);
11557		/* Avoid confusion and erase the values. */
11558		type->base = NULL;
11559		type->baseNs = NULL;
11560	    }
11561	}
11562    }
11563    /*
11564    * And now for the children...
11565    */
11566    child = node->children;
11567    if (IS_SCHEMA(child, "annotation")) {
11568	/*
11569	* Add the annotation to the simple type ancestor.
11570	*/
11571	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11572	    xmlSchemaParseAnnotation(ctxt, child, 1));
11573        child = child->next;
11574    }
11575    if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11576	/*
11577	* Corresponds to <simpleType><restriction><simpleType>.
11578	*/
11579	if (IS_SCHEMA(child, "simpleType")) {
11580	    if (type->base != NULL) {
11581		/*
11582		* src-restriction-base-or-simpleType
11583		* Either the base [attribute] or the simpleType [child] of the
11584		* <restriction> element must be present, but not both.
11585		*/
11586		xmlSchemaPContentErr(ctxt,
11587		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11588		    NULL, node, child,
11589		    "The attribute 'base' and the <simpleType> child are "
11590		    "mutually exclusive", NULL);
11591	    } else {
11592		type->baseType = (xmlSchemaTypePtr)
11593		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11594	    }
11595	    child = child->next;
11596	} else if (type->base == NULL) {
11597	    xmlSchemaPContentErr(ctxt,
11598		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11599		NULL, node, child,
11600		"Either the attribute 'base' or a <simpleType> child "
11601		"must be present", NULL);
11602	}
11603    } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11604	/*
11605	* Corresponds to <complexType><complexContent><restriction>...
11606	* followed by:
11607	*
11608	* Model groups <all>, <choice> and <sequence>.
11609	*/
11610	if (IS_SCHEMA(child, "all")) {
11611	    type->subtypes = (xmlSchemaTypePtr)
11612		xmlSchemaParseModelGroup(ctxt, schema, child,
11613		    XML_SCHEMA_TYPE_ALL, 1);
11614	    child = child->next;
11615	} else if (IS_SCHEMA(child, "choice")) {
11616	    type->subtypes = (xmlSchemaTypePtr)
11617		xmlSchemaParseModelGroup(ctxt,
11618		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11619	    child = child->next;
11620	} else if (IS_SCHEMA(child, "sequence")) {
11621	    type->subtypes = (xmlSchemaTypePtr)
11622		xmlSchemaParseModelGroup(ctxt, schema, child,
11623		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11624	    child = child->next;
11625	/*
11626	* Model group reference <group>.
11627	*/
11628	} else if (IS_SCHEMA(child, "group")) {
11629	    type->subtypes = (xmlSchemaTypePtr)
11630		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11631	    /*
11632	    * Note that the reference will be resolved in
11633	    * xmlSchemaResolveTypeReferences();
11634	    */
11635	    child = child->next;
11636	}
11637    } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11638	/*
11639	* Corresponds to <complexType><simpleContent><restriction>...
11640	*
11641	* "1.1 the simple type definition corresponding to the <simpleType>
11642	* among the [children] of <restriction> if there is one;"
11643	*/
11644	if (IS_SCHEMA(child, "simpleType")) {
11645	    /*
11646	    * We will store the to-be-restricted simple type in
11647	    * type->contentTypeDef *temporarily*.
11648	    */
11649	    type->contentTypeDef = (xmlSchemaTypePtr)
11650		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11651	    if ( type->contentTypeDef == NULL)
11652		return (NULL);
11653	    child = child->next;
11654	}
11655    }
11656
11657    if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11658	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11659	xmlSchemaFacetPtr facet, lastfacet = NULL;
11660	/*
11661	* Corresponds to <complexType><simpleContent><restriction>...
11662	* <simpleType><restriction>...
11663	*/
11664
11665	/*
11666	* Add the facets to the simple type ancestor.
11667	*/
11668	/*
11669	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11670	* Simple Type Definition Schema Representation Constraint:
11671	* *Single Facet Value*
11672	*/
11673	while ((IS_SCHEMA(child, "minInclusive")) ||
11674	    (IS_SCHEMA(child, "minExclusive")) ||
11675	    (IS_SCHEMA(child, "maxInclusive")) ||
11676	    (IS_SCHEMA(child, "maxExclusive")) ||
11677	    (IS_SCHEMA(child, "totalDigits")) ||
11678	    (IS_SCHEMA(child, "fractionDigits")) ||
11679	    (IS_SCHEMA(child, "pattern")) ||
11680	    (IS_SCHEMA(child, "enumeration")) ||
11681	    (IS_SCHEMA(child, "whiteSpace")) ||
11682	    (IS_SCHEMA(child, "length")) ||
11683	    (IS_SCHEMA(child, "maxLength")) ||
11684	    (IS_SCHEMA(child, "minLength"))) {
11685	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11686	    if (facet != NULL) {
11687		if (lastfacet == NULL)
11688		    type->facets = facet;
11689		else
11690		    lastfacet->next = facet;
11691		lastfacet = facet;
11692		lastfacet->next = NULL;
11693	    }
11694	    child = child->next;
11695	}
11696	/*
11697	* Create links for derivation and validation.
11698	*/
11699	if (type->facets != NULL) {
11700	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11701
11702	    facet = type->facets;
11703	    do {
11704		facetLink = (xmlSchemaFacetLinkPtr)
11705		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11706		if (facetLink == NULL) {
11707		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11708		    xmlFree(facetLink);
11709		    return (NULL);
11710		}
11711		facetLink->facet = facet;
11712		facetLink->next = NULL;
11713		if (lastFacetLink == NULL)
11714		    type->facetSet = facetLink;
11715		else
11716		    lastFacetLink->next = facetLink;
11717		lastFacetLink = facetLink;
11718		facet = facet->next;
11719	    } while (facet != NULL);
11720	}
11721    }
11722    if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11723	/*
11724	* Attribute uses/declarations.
11725	*/
11726	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11727	    (xmlSchemaItemListPtr *) &(type->attrUses),
11728	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11729	    return(NULL);
11730	/*
11731	* Attribute wildcard.
11732	*/
11733	if (IS_SCHEMA(child, "anyAttribute")) {
11734	    type->attributeWildcard =
11735		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11736	    child = child->next;
11737	}
11738    }
11739    if (child != NULL) {
11740	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11741	    xmlSchemaPContentErr(ctxt,
11742		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11743		NULL, node, child, NULL,
11744		"annotation?, (group | all | choice | sequence)?, "
11745		"((attribute | attributeGroup)*, anyAttribute?))");
11746	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11747	     xmlSchemaPContentErr(ctxt,
11748		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11749		NULL, node, child, NULL,
11750		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11751		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11752		"length | minLength | maxLength | enumeration | whiteSpace | "
11753		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11754	} else {
11755	    /* Simple type */
11756	    xmlSchemaPContentErr(ctxt,
11757		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11758		NULL, node, child, NULL,
11759		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11760		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11761		"length | minLength | maxLength | enumeration | whiteSpace | "
11762		"pattern)*))");
11763	}
11764    }
11765    return (NULL);
11766}
11767
11768/**
11769 * xmlSchemaParseExtension:
11770 * @ctxt:  a schema validation context
11771 * @schema:  the schema being built
11772 * @node:  a subtree containing XML Schema informations
11773 *
11774 * Parses an <extension>, which is found inside a
11775 * <simpleContent> or <complexContent>.
11776 * *WARNING* this interface is highly subject to change.
11777 *
11778 * TODO: Returns the type definition or NULL in case of error
11779 */
11780static xmlSchemaTypePtr
11781xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11782                        xmlNodePtr node, xmlSchemaTypeType parentType)
11783{
11784    xmlSchemaTypePtr type;
11785    xmlNodePtr child = NULL;
11786    xmlAttrPtr attr;
11787
11788    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11789        return (NULL);
11790    /* Not a component, don't create it. */
11791    type = ctxt->ctxtType;
11792    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11793
11794    /*
11795    * Check for illegal attributes.
11796    */
11797    attr = node->properties;
11798    while (attr != NULL) {
11799	if (attr->ns == NULL) {
11800	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11801		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11802		xmlSchemaPIllegalAttrErr(ctxt,
11803		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11804	    }
11805	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11806	    xmlSchemaPIllegalAttrErr(ctxt,
11807		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11808	}
11809	attr = attr->next;
11810    }
11811
11812    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11813
11814    /*
11815    * Attribute "base" - mandatory.
11816    */
11817    if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11818	"base", &(type->baseNs), &(type->base)) == 0) &&
11819	(type->base == NULL)) {
11820	xmlSchemaPMissingAttrErr(ctxt,
11821	    XML_SCHEMAP_S4S_ATTR_MISSING,
11822	    NULL, node, "base", NULL);
11823    }
11824    /*
11825    * And now for the children...
11826    */
11827    child = node->children;
11828    if (IS_SCHEMA(child, "annotation")) {
11829	/*
11830	* Add the annotation to the type ancestor.
11831	*/
11832	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11833	    xmlSchemaParseAnnotation(ctxt, child, 1));
11834        child = child->next;
11835    }
11836    if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11837	/*
11838	* Corresponds to <complexType><complexContent><extension>... and:
11839	*
11840	* Model groups <all>, <choice>, <sequence> and <group>.
11841	*/
11842	if (IS_SCHEMA(child, "all")) {
11843	    type->subtypes = (xmlSchemaTypePtr)
11844		xmlSchemaParseModelGroup(ctxt, schema,
11845		    child, XML_SCHEMA_TYPE_ALL, 1);
11846	    child = child->next;
11847	} else if (IS_SCHEMA(child, "choice")) {
11848	    type->subtypes = (xmlSchemaTypePtr)
11849		xmlSchemaParseModelGroup(ctxt, schema,
11850		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11851	    child = child->next;
11852	} else if (IS_SCHEMA(child, "sequence")) {
11853	    type->subtypes = (xmlSchemaTypePtr)
11854		xmlSchemaParseModelGroup(ctxt, schema,
11855		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11856	    child = child->next;
11857	} else if (IS_SCHEMA(child, "group")) {
11858	    type->subtypes = (xmlSchemaTypePtr)
11859		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11860	    /*
11861	    * Note that the reference will be resolved in
11862	    * xmlSchemaResolveTypeReferences();
11863	    */
11864	    child = child->next;
11865	}
11866    }
11867    if (child != NULL) {
11868	/*
11869	* Attribute uses/declarations.
11870	*/
11871	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11872	    (xmlSchemaItemListPtr *) &(type->attrUses),
11873	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11874	    return(NULL);
11875	/*
11876	* Attribute wildcard.
11877	*/
11878	if (IS_SCHEMA(child, "anyAttribute")) {
11879	    ctxt->ctxtType->attributeWildcard =
11880		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11881	    child = child->next;
11882	}
11883    }
11884    if (child != NULL) {
11885	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11886	    /* Complex content extension. */
11887	    xmlSchemaPContentErr(ctxt,
11888		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11889		NULL, node, child, NULL,
11890		"(annotation?, ((group | all | choice | sequence)?, "
11891		"((attribute | attributeGroup)*, anyAttribute?)))");
11892	} else {
11893	    /* Simple content extension. */
11894	    xmlSchemaPContentErr(ctxt,
11895		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11896		NULL, node, child, NULL,
11897		"(annotation?, ((attribute | attributeGroup)*, "
11898		"anyAttribute?))");
11899	}
11900    }
11901    return (NULL);
11902}
11903
11904/**
11905 * xmlSchemaParseSimpleContent:
11906 * @ctxt:  a schema validation context
11907 * @schema:  the schema being built
11908 * @node:  a subtree containing XML Schema informations
11909 *
11910 * parse a XML schema SimpleContent definition
11911 * *WARNING* this interface is highly subject to change
11912 *
11913 * Returns the type definition or NULL in case of error
11914 */
11915static int
11916xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11917                            xmlSchemaPtr schema, xmlNodePtr node,
11918			    int *hasRestrictionOrExtension)
11919{
11920    xmlSchemaTypePtr type;
11921    xmlNodePtr child = NULL;
11922    xmlAttrPtr attr;
11923
11924    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11925	(hasRestrictionOrExtension == NULL))
11926        return (-1);
11927    *hasRestrictionOrExtension = 0;
11928    /* Not a component, don't create it. */
11929    type = ctxt->ctxtType;
11930    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11931    /*
11932    * Check for illegal attributes.
11933    */
11934    attr = node->properties;
11935    while (attr != NULL) {
11936	if (attr->ns == NULL) {
11937	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11938		xmlSchemaPIllegalAttrErr(ctxt,
11939		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11940	    }
11941	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11942	    xmlSchemaPIllegalAttrErr(ctxt,
11943		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11944	}
11945	attr = attr->next;
11946    }
11947
11948    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11949
11950    /*
11951    * And now for the children...
11952    */
11953    child = node->children;
11954    if (IS_SCHEMA(child, "annotation")) {
11955	/*
11956	* Add the annotation to the complex type ancestor.
11957	*/
11958	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11959	    xmlSchemaParseAnnotation(ctxt, child, 1));
11960        child = child->next;
11961    }
11962    if (child == NULL) {
11963	xmlSchemaPContentErr(ctxt,
11964	    XML_SCHEMAP_S4S_ELEM_MISSING,
11965	    NULL, node, NULL, NULL,
11966	    "(annotation?, (restriction | extension))");
11967    }
11968    if (child == NULL) {
11969	xmlSchemaPContentErr(ctxt,
11970	    XML_SCHEMAP_S4S_ELEM_MISSING,
11971	    NULL, node, NULL, NULL,
11972	    "(annotation?, (restriction | extension))");
11973    }
11974    if (IS_SCHEMA(child, "restriction")) {
11975        xmlSchemaParseRestriction(ctxt, schema, child,
11976	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11977	(*hasRestrictionOrExtension) = 1;
11978        child = child->next;
11979    } else if (IS_SCHEMA(child, "extension")) {
11980        xmlSchemaParseExtension(ctxt, schema, child,
11981	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11982	(*hasRestrictionOrExtension) = 1;
11983        child = child->next;
11984    }
11985    if (child != NULL) {
11986	xmlSchemaPContentErr(ctxt,
11987	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11988	    NULL, node, child, NULL,
11989	    "(annotation?, (restriction | extension))");
11990    }
11991    return (0);
11992}
11993
11994/**
11995 * xmlSchemaParseComplexContent:
11996 * @ctxt:  a schema validation context
11997 * @schema:  the schema being built
11998 * @node:  a subtree containing XML Schema informations
11999 *
12000 * parse a XML schema ComplexContent definition
12001 * *WARNING* this interface is highly subject to change
12002 *
12003 * Returns the type definition or NULL in case of error
12004 */
12005static int
12006xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12007                             xmlSchemaPtr schema, xmlNodePtr node,
12008			     int *hasRestrictionOrExtension)
12009{
12010    xmlSchemaTypePtr type;
12011    xmlNodePtr child = NULL;
12012    xmlAttrPtr attr;
12013
12014    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12015	(hasRestrictionOrExtension == NULL))
12016        return (-1);
12017    *hasRestrictionOrExtension = 0;
12018    /* Not a component, don't create it. */
12019    type = ctxt->ctxtType;
12020    /*
12021    * Check for illegal attributes.
12022    */
12023    attr = node->properties;
12024    while (attr != NULL) {
12025	if (attr->ns == NULL) {
12026	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12027		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12028	    {
12029		xmlSchemaPIllegalAttrErr(ctxt,
12030		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12031	    }
12032	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12033	    xmlSchemaPIllegalAttrErr(ctxt,
12034		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12035	}
12036	attr = attr->next;
12037    }
12038
12039    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12040
12041    /*
12042    * Set the 'mixed' on the complex type ancestor.
12043    */
12044    if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12045	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12046	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12047    }
12048    child = node->children;
12049    if (IS_SCHEMA(child, "annotation")) {
12050	/*
12051	* Add the annotation to the complex type ancestor.
12052	*/
12053	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12054	    xmlSchemaParseAnnotation(ctxt, child, 1));
12055        child = child->next;
12056    }
12057    if (child == NULL) {
12058	xmlSchemaPContentErr(ctxt,
12059	    XML_SCHEMAP_S4S_ELEM_MISSING,
12060	    NULL, node, NULL,
12061	    NULL, "(annotation?, (restriction | extension))");
12062    }
12063    if (child == NULL) {
12064	xmlSchemaPContentErr(ctxt,
12065	    XML_SCHEMAP_S4S_ELEM_MISSING,
12066	    NULL, node, NULL,
12067	    NULL, "(annotation?, (restriction | extension))");
12068    }
12069    if (IS_SCHEMA(child, "restriction")) {
12070        xmlSchemaParseRestriction(ctxt, schema, child,
12071	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12072	(*hasRestrictionOrExtension) = 1;
12073        child = child->next;
12074    } else if (IS_SCHEMA(child, "extension")) {
12075        xmlSchemaParseExtension(ctxt, schema, child,
12076	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12077	(*hasRestrictionOrExtension) = 1;
12078        child = child->next;
12079    }
12080    if (child != NULL) {
12081	xmlSchemaPContentErr(ctxt,
12082	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12083	    NULL, node, child,
12084	    NULL, "(annotation?, (restriction | extension))");
12085    }
12086    return (0);
12087}
12088
12089/**
12090 * xmlSchemaParseComplexType:
12091 * @ctxt:  a schema validation context
12092 * @schema:  the schema being built
12093 * @node:  a subtree containing XML Schema informations
12094 *
12095 * parse a XML schema Complex Type definition
12096 * *WARNING* this interface is highly subject to change
12097 *
12098 * Returns the type definition or NULL in case of error
12099 */
12100static xmlSchemaTypePtr
12101xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12102                          xmlNodePtr node, int topLevel)
12103{
12104    xmlSchemaTypePtr type, ctxtType;
12105    xmlNodePtr child = NULL;
12106    const xmlChar *name = NULL;
12107    xmlAttrPtr attr;
12108    const xmlChar *attrValue;
12109#ifdef ENABLE_NAMED_LOCALS
12110    char buf[40];
12111#endif
12112    int final = 0, block = 0, hasRestrictionOrExtension = 0;
12113
12114
12115    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12116        return (NULL);
12117
12118    ctxtType = ctxt->ctxtType;
12119
12120    if (topLevel) {
12121	attr = xmlSchemaGetPropNode(node, "name");
12122	if (attr == NULL) {
12123	    xmlSchemaPMissingAttrErr(ctxt,
12124		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12125	    return (NULL);
12126	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12127	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12128	    return (NULL);
12129	}
12130    }
12131
12132    if (topLevel == 0) {
12133	/*
12134	* Parse as local complex type definition.
12135	*/
12136#ifdef ENABLE_NAMED_LOCALS
12137        snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12138	type = xmlSchemaAddType(ctxt, schema,
12139	    XML_SCHEMA_TYPE_COMPLEX,
12140	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12141	    ctxt->targetNamespace, node, 0);
12142#else
12143	type = xmlSchemaAddType(ctxt, schema,
12144	    XML_SCHEMA_TYPE_COMPLEX,
12145	    NULL, ctxt->targetNamespace, node, 0);
12146#endif
12147	if (type == NULL)
12148	    return (NULL);
12149	name = type->name;
12150	type->node = node;
12151	type->type = XML_SCHEMA_TYPE_COMPLEX;
12152	/*
12153	* TODO: We need the target namespace.
12154	*/
12155    } else {
12156	/*
12157	* Parse as global complex type definition.
12158	*/
12159	type = xmlSchemaAddType(ctxt, schema,
12160	    XML_SCHEMA_TYPE_COMPLEX,
12161	    name, ctxt->targetNamespace, node, 1);
12162	if (type == NULL)
12163	    return (NULL);
12164	type->node = node;
12165	type->type = XML_SCHEMA_TYPE_COMPLEX;
12166	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12167    }
12168    type->targetNamespace = ctxt->targetNamespace;
12169    /*
12170    * Handle attributes.
12171    */
12172    attr = node->properties;
12173    while (attr != NULL) {
12174	if (attr->ns == NULL) {
12175	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12176		/*
12177		* Attribute "id".
12178		*/
12179		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12180	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12181		/*
12182		* Attribute "mixed".
12183		*/
12184		if (xmlSchemaPGetBoolNodeValue(ctxt,
12185			NULL, (xmlNodePtr) attr))
12186		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12187	    } else if (topLevel) {
12188		/*
12189		* Attributes of global complex type definitions.
12190		*/
12191		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12192		    /* Pass. */
12193		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12194		    /*
12195		    * Attribute "abstract".
12196		    */
12197		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12198			    NULL, (xmlNodePtr) attr))
12199			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12200		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12201		    /*
12202		    * Attribute "final".
12203		    */
12204		    attrValue = xmlSchemaGetNodeContent(ctxt,
12205			(xmlNodePtr) attr);
12206		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12207			&(type->flags),
12208			-1,
12209			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12210			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12211			-1, -1, -1) != 0)
12212		    {
12213			xmlSchemaPSimpleTypeErr(ctxt,
12214			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12215			    NULL, (xmlNodePtr) attr, NULL,
12216			    "(#all | List of (extension | restriction))",
12217			    attrValue, NULL, NULL, NULL);
12218		    } else
12219			final = 1;
12220		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12221		    /*
12222		    * Attribute "block".
12223		    */
12224		    attrValue = xmlSchemaGetNodeContent(ctxt,
12225			(xmlNodePtr) attr);
12226		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12227			-1,
12228			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12229			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12230			-1, -1, -1) != 0) {
12231			xmlSchemaPSimpleTypeErr(ctxt,
12232			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12233			    NULL, (xmlNodePtr) attr, NULL,
12234			    "(#all | List of (extension | restriction)) ",
12235			    attrValue, NULL, NULL, NULL);
12236		    } else
12237			block = 1;
12238		} else {
12239			xmlSchemaPIllegalAttrErr(ctxt,
12240			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12241		}
12242	    } else {
12243		xmlSchemaPIllegalAttrErr(ctxt,
12244		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12245	    }
12246	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12247	    xmlSchemaPIllegalAttrErr(ctxt,
12248		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12249	}
12250	attr = attr->next;
12251    }
12252    if (! block) {
12253	/*
12254	* Apply default "block" values.
12255	*/
12256	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12257	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12258	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12259	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12260    }
12261    if (! final) {
12262	/*
12263	* Apply default "block" values.
12264	*/
12265	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12266	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12267	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12268	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12269    }
12270    /*
12271    * And now for the children...
12272    */
12273    child = node->children;
12274    if (IS_SCHEMA(child, "annotation")) {
12275        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12276        child = child->next;
12277    }
12278    ctxt->ctxtType = type;
12279    if (IS_SCHEMA(child, "simpleContent")) {
12280	/*
12281	* <complexType><simpleContent>...
12282	* 3.4.3 : 2.2
12283	* Specifying mixed='true' when the <simpleContent>
12284	* alternative is chosen has no effect
12285	*/
12286	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12287	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12288        xmlSchemaParseSimpleContent(ctxt, schema, child,
12289	    &hasRestrictionOrExtension);
12290        child = child->next;
12291    } else if (IS_SCHEMA(child, "complexContent")) {
12292	/*
12293	* <complexType><complexContent>...
12294	*/
12295	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12296        xmlSchemaParseComplexContent(ctxt, schema, child,
12297	    &hasRestrictionOrExtension);
12298        child = child->next;
12299    } else {
12300	/*
12301	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12302	*
12303	* SPEC
12304	* "...the third alternative (neither <simpleContent> nor
12305	* <complexContent>) is chosen. This case is understood as shorthand
12306	* for complex content restricting the �ur-type definition�, and the
12307	* details of the mappings should be modified as necessary.
12308	*/
12309	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12310	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12311	/*
12312	* Parse model groups.
12313	*/
12314        if (IS_SCHEMA(child, "all")) {
12315            type->subtypes = (xmlSchemaTypePtr)
12316		xmlSchemaParseModelGroup(ctxt, schema, child,
12317		    XML_SCHEMA_TYPE_ALL, 1);
12318            child = child->next;
12319        } else if (IS_SCHEMA(child, "choice")) {
12320            type->subtypes = (xmlSchemaTypePtr)
12321		xmlSchemaParseModelGroup(ctxt, schema, child,
12322		    XML_SCHEMA_TYPE_CHOICE, 1);
12323            child = child->next;
12324        } else if (IS_SCHEMA(child, "sequence")) {
12325            type->subtypes = (xmlSchemaTypePtr)
12326		xmlSchemaParseModelGroup(ctxt, schema, child,
12327		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12328            child = child->next;
12329        } else if (IS_SCHEMA(child, "group")) {
12330            type->subtypes = (xmlSchemaTypePtr)
12331		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12332	    /*
12333	    * Note that the reference will be resolved in
12334	    * xmlSchemaResolveTypeReferences();
12335	    */
12336            child = child->next;
12337        }
12338	/*
12339	* Parse attribute decls/refs.
12340	*/
12341        if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12342	    (xmlSchemaItemListPtr *) &(type->attrUses),
12343	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12344	    return(NULL);
12345	/*
12346	* Parse attribute wildcard.
12347	*/
12348	if (IS_SCHEMA(child, "anyAttribute")) {
12349	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12350	    child = child->next;
12351	}
12352    }
12353    if (child != NULL) {
12354	xmlSchemaPContentErr(ctxt,
12355	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12356	    NULL, node, child,
12357	    NULL, "(annotation?, (simpleContent | complexContent | "
12358	    "((group | all | choice | sequence)?, ((attribute | "
12359	    "attributeGroup)*, anyAttribute?))))");
12360    }
12361    /*
12362    * REDEFINE: SPEC src-redefine (5)
12363    */
12364    if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12365	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12366	    NULL, node, "This is a redefinition, thus the "
12367	    "<complexType> must have a <restriction> or <extension> "
12368	    "grand-child", NULL);
12369    }
12370    ctxt->ctxtType = ctxtType;
12371    return (type);
12372}
12373
12374/************************************************************************
12375 *									*
12376 *			Validating using Schemas			*
12377 *									*
12378 ************************************************************************/
12379
12380/************************************************************************
12381 *									*
12382 *			Reading/Writing Schemas				*
12383 *									*
12384 ************************************************************************/
12385
12386#if 0 /* Will be enabled if it is clear what options are needed. */
12387/**
12388 * xmlSchemaParserCtxtSetOptions:
12389 * @ctxt:	a schema parser context
12390 * @options: a combination of xmlSchemaParserOption
12391 *
12392 * Sets the options to be used during the parse.
12393 *
12394 * Returns 0 in case of success, -1 in case of an
12395 * API error.
12396 */
12397static int
12398xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12399			      int options)
12400
12401{
12402    int i;
12403
12404    if (ctxt == NULL)
12405	return (-1);
12406    /*
12407    * WARNING: Change the start value if adding to the
12408    * xmlSchemaParseOption.
12409    */
12410    for (i = 1; i < (int) sizeof(int) * 8; i++) {
12411        if (options & 1<<i) {
12412	    return (-1);
12413        }
12414    }
12415    ctxt->options = options;
12416    return (0);
12417}
12418
12419/**
12420 * xmlSchemaValidCtxtGetOptions:
12421 * @ctxt: a schema parser context
12422 *
12423 * Returns the option combination of the parser context.
12424 */
12425static int
12426xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12427
12428{
12429    if (ctxt == NULL)
12430	return (-1);
12431    else
12432	return (ctxt->options);
12433}
12434#endif
12435
12436/**
12437 * xmlSchemaNewParserCtxt:
12438 * @URL:  the location of the schema
12439 *
12440 * Create an XML Schemas parse context for that file/resource expected
12441 * to contain an XML Schemas file.
12442 *
12443 * Returns the parser context or NULL in case of error
12444 */
12445xmlSchemaParserCtxtPtr
12446xmlSchemaNewParserCtxt(const char *URL)
12447{
12448    xmlSchemaParserCtxtPtr ret;
12449
12450    if (URL == NULL)
12451        return (NULL);
12452
12453    ret = xmlSchemaParserCtxtCreate();
12454    if (ret == NULL)
12455	return(NULL);
12456    ret->dict = xmlDictCreate();
12457    ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12458    return (ret);
12459}
12460
12461/**
12462 * xmlSchemaNewMemParserCtxt:
12463 * @buffer:  a pointer to a char array containing the schemas
12464 * @size:  the size of the array
12465 *
12466 * Create an XML Schemas parse context for that memory buffer expected
12467 * to contain an XML Schemas file.
12468 *
12469 * Returns the parser context or NULL in case of error
12470 */
12471xmlSchemaParserCtxtPtr
12472xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12473{
12474    xmlSchemaParserCtxtPtr ret;
12475
12476    if ((buffer == NULL) || (size <= 0))
12477        return (NULL);
12478    ret = xmlSchemaParserCtxtCreate();
12479    if (ret == NULL)
12480	return(NULL);
12481    ret->buffer = buffer;
12482    ret->size = size;
12483    ret->dict = xmlDictCreate();
12484    return (ret);
12485}
12486
12487/**
12488 * xmlSchemaNewDocParserCtxt:
12489 * @doc:  a preparsed document tree
12490 *
12491 * Create an XML Schemas parse context for that document.
12492 * NB. The document may be modified during the parsing process.
12493 *
12494 * Returns the parser context or NULL in case of error
12495 */
12496xmlSchemaParserCtxtPtr
12497xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12498{
12499    xmlSchemaParserCtxtPtr ret;
12500
12501    if (doc == NULL)
12502      return (NULL);
12503    ret = xmlSchemaParserCtxtCreate();
12504    if (ret == NULL)
12505	return(NULL);
12506    ret->doc = doc;
12507    ret->dict = xmlDictCreate();
12508    /* The application has responsibility for the document */
12509    ret->preserve = 1;
12510
12511    return (ret);
12512}
12513
12514/**
12515 * xmlSchemaFreeParserCtxt:
12516 * @ctxt:  the schema parser context
12517 *
12518 * Free the resources associated to the schema parser context
12519 */
12520void
12521xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12522{
12523    if (ctxt == NULL)
12524        return;
12525    if (ctxt->doc != NULL && !ctxt->preserve)
12526        xmlFreeDoc(ctxt->doc);
12527    if (ctxt->vctxt != NULL) {
12528	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12529    }
12530    if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12531	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12532	ctxt->constructor = NULL;
12533	ctxt->ownsConstructor = 0;
12534    }
12535    if (ctxt->attrProhibs != NULL)
12536	xmlSchemaItemListFree(ctxt->attrProhibs);
12537    xmlDictFree(ctxt->dict);
12538    xmlFree(ctxt);
12539}
12540
12541/************************************************************************
12542 *									*
12543 *			Building the content models			*
12544 *									*
12545 ************************************************************************/
12546
12547/**
12548 * xmlSchemaBuildContentModelForSubstGroup:
12549 *
12550 * Returns 1 if nillable, 0 otherwise
12551 */
12552static int
12553xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12554	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12555{
12556    xmlAutomataStatePtr start, tmp;
12557    xmlSchemaElementPtr elemDecl, member;
12558    xmlSchemaSubstGroupPtr substGroup;
12559    int i;
12560    int ret = 0;
12561
12562    elemDecl = (xmlSchemaElementPtr) particle->children;
12563    /*
12564    * Wrap the substitution group with a CHOICE.
12565    */
12566    start = pctxt->state;
12567    if (end == NULL)
12568	end = xmlAutomataNewState(pctxt->am);
12569    substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12570    if (substGroup == NULL) {
12571	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12572	    XML_SCHEMAP_INTERNAL,
12573	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12574	    "declaration is marked having a subst. group but none "
12575	    "available.\n", elemDecl->name, NULL);
12576	return(0);
12577    }
12578    if (counter >= 0) {
12579	/*
12580	* NOTE that we put the declaration in, even if it's abstract.
12581	* However, an error will be raised during *validation* if an element
12582	* information item shall be validated against an abstract element
12583	* declaration.
12584	*/
12585	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12586        xmlAutomataNewTransition2(pctxt->am, tmp, end,
12587	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12588	/*
12589	* Add subst. group members.
12590	*/
12591	for (i = 0; i < substGroup->members->nbItems; i++) {
12592	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12593            xmlAutomataNewTransition2(pctxt->am, tmp, end,
12594		               member->name, member->targetNamespace, member);
12595	}
12596    } else if (particle->maxOccurs == 1) {
12597	/*
12598	* NOTE that we put the declaration in, even if it's abstract,
12599	*/
12600	xmlAutomataNewEpsilon(pctxt->am,
12601	    xmlAutomataNewTransition2(pctxt->am,
12602	    start, NULL,
12603	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12604	/*
12605	* Add subst. group members.
12606	*/
12607	for (i = 0; i < substGroup->members->nbItems; i++) {
12608	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12609	    /*
12610	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12611	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12612	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12613	    *  section in xmlSchemaBuildAContentModel() ).
12614	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12615	    *  intended for the above "counter" section originally. I.e.,
12616	    *  check xs:all with subst-groups.
12617	    *
12618	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12619	    *	               member->name, member->targetNamespace,
12620	    *		       1, 1, member);
12621	    */
12622	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12623		member->name, member->targetNamespace, member);
12624	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12625	}
12626    } else {
12627	xmlAutomataStatePtr hop;
12628	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12629	    UNBOUNDED : particle->maxOccurs - 1;
12630	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12631
12632	counter =
12633	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12634	    maxOccurs);
12635	hop = xmlAutomataNewState(pctxt->am);
12636
12637	xmlAutomataNewEpsilon(pctxt->am,
12638	    xmlAutomataNewTransition2(pctxt->am,
12639	    start, NULL,
12640	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12641	    hop);
12642	/*
12643	 * Add subst. group members.
12644	 */
12645	for (i = 0; i < substGroup->members->nbItems; i++) {
12646	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12647	    xmlAutomataNewEpsilon(pctxt->am,
12648		xmlAutomataNewTransition2(pctxt->am,
12649		start, NULL,
12650		member->name, member->targetNamespace, member),
12651		hop);
12652	}
12653	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12654	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12655    }
12656    if (particle->minOccurs == 0) {
12657	xmlAutomataNewEpsilon(pctxt->am, start, end);
12658        ret = 1;
12659    }
12660    pctxt->state = end;
12661    return(ret);
12662}
12663
12664/**
12665 * xmlSchemaBuildContentModelForElement:
12666 *
12667 * Returns 1 if nillable, 0 otherwise
12668 */
12669static int
12670xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12671				     xmlSchemaParticlePtr particle)
12672{
12673    int ret = 0;
12674
12675    if (((xmlSchemaElementPtr) particle->children)->flags &
12676	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12677	/*
12678	* Substitution groups.
12679	*/
12680	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12681    } else {
12682	xmlSchemaElementPtr elemDecl;
12683	xmlAutomataStatePtr start;
12684
12685	elemDecl = (xmlSchemaElementPtr) particle->children;
12686
12687	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12688	    return(0);
12689	if (particle->maxOccurs == 1) {
12690	    start = ctxt->state;
12691	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12692		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12693	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12694	           (particle->minOccurs < 2)) {
12695	    /* Special case. */
12696	    start = ctxt->state;
12697	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12698		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12699	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12700		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12701	} else {
12702	    int counter;
12703	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12704			    UNBOUNDED : particle->maxOccurs - 1;
12705	    int minOccurs = particle->minOccurs < 1 ?
12706			    0 : particle->minOccurs - 1;
12707
12708	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12709	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12710	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12711		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12712	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12713	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12714		NULL, counter);
12715	}
12716	if (particle->minOccurs == 0) {
12717	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12718            ret = 1;
12719        }
12720    }
12721    return(ret);
12722}
12723
12724/**
12725 * xmlSchemaBuildAContentModel:
12726 * @ctxt:  the schema parser context
12727 * @particle:  the particle component
12728 * @name:  the complex type's name whose content is being built
12729 *
12730 * Create the automaton for the {content type} of a complex type.
12731 *
12732 * Returns 1 if the content is nillable, 0 otherwise
12733 */
12734static int
12735xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12736			    xmlSchemaParticlePtr particle)
12737{
12738    int ret = 0, tmp2;
12739
12740    if (particle == NULL) {
12741	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12742	return(1);
12743    }
12744    if (particle->children == NULL) {
12745	/*
12746	* Just return in this case. A missing "term" of the particle
12747	* might arise due to an invalid "term" component.
12748	*/
12749	return(1);
12750    }
12751
12752    switch (particle->children->type) {
12753	case XML_SCHEMA_TYPE_ANY: {
12754	    xmlAutomataStatePtr start, end;
12755	    xmlSchemaWildcardPtr wild;
12756	    xmlSchemaWildcardNsPtr ns;
12757
12758	    wild = (xmlSchemaWildcardPtr) particle->children;
12759
12760	    start = pctxt->state;
12761	    end = xmlAutomataNewState(pctxt->am);
12762
12763	    if (particle->maxOccurs == 1) {
12764		if (wild->any == 1) {
12765		    /*
12766		    * We need to add both transitions:
12767		    *
12768		    * 1. the {"*", "*"} for elements in a namespace.
12769		    */
12770		    pctxt->state =
12771			xmlAutomataNewTransition2(pctxt->am,
12772			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12773		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12774		    /*
12775		    * 2. the {"*"} for elements in no namespace.
12776		    */
12777		    pctxt->state =
12778			xmlAutomataNewTransition2(pctxt->am,
12779			start, NULL, BAD_CAST "*", NULL, wild);
12780		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12781
12782		} else if (wild->nsSet != NULL) {
12783		    ns = wild->nsSet;
12784		    do {
12785			pctxt->state = start;
12786			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12787			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12788			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12789			ns = ns->next;
12790		    } while (ns != NULL);
12791
12792		} else if (wild->negNsSet != NULL) {
12793		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12794			start, end, BAD_CAST "*", wild->negNsSet->value,
12795			wild);
12796		}
12797	    } else {
12798		int counter;
12799		xmlAutomataStatePtr hop;
12800		int maxOccurs =
12801		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12802                                           particle->maxOccurs - 1;
12803		int minOccurs =
12804		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12805
12806		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12807		hop = xmlAutomataNewState(pctxt->am);
12808		if (wild->any == 1) {
12809		    pctxt->state =
12810			xmlAutomataNewTransition2(pctxt->am,
12811			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12812		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12813		    pctxt->state =
12814			xmlAutomataNewTransition2(pctxt->am,
12815			start, NULL, BAD_CAST "*", NULL, wild);
12816		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12817		} else if (wild->nsSet != NULL) {
12818		    ns = wild->nsSet;
12819		    do {
12820			pctxt->state =
12821			    xmlAutomataNewTransition2(pctxt->am,
12822				start, NULL, BAD_CAST "*", ns->value, wild);
12823			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12824			ns = ns->next;
12825		    } while (ns != NULL);
12826
12827		} else if (wild->negNsSet != NULL) {
12828		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12829			start, hop, BAD_CAST "*", wild->negNsSet->value,
12830			wild);
12831		}
12832		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12833		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12834	    }
12835	    if (particle->minOccurs == 0) {
12836		xmlAutomataNewEpsilon(pctxt->am, start, end);
12837                ret = 1;
12838	    }
12839	    pctxt->state = end;
12840            break;
12841	}
12842        case XML_SCHEMA_TYPE_ELEMENT:
12843	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12844	    break;
12845        case XML_SCHEMA_TYPE_SEQUENCE:{
12846            xmlSchemaTreeItemPtr sub;
12847
12848            ret = 1;
12849            /*
12850             * If max and min occurances are default (1) then
12851             * simply iterate over the particles of the <sequence>.
12852             */
12853            if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12854                sub = particle->children->children;
12855
12856                while (sub != NULL) {
12857                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
12858                                        (xmlSchemaParticlePtr) sub);
12859                    if (tmp2 != 1) ret = 0;
12860                    sub = sub->next;
12861                }
12862            } else {
12863                xmlAutomataStatePtr oldstate = pctxt->state;
12864
12865                if (particle->maxOccurs >= UNBOUNDED) {
12866                    if (particle->minOccurs > 1) {
12867                        xmlAutomataStatePtr tmp;
12868                        int counter;
12869
12870                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12871                            oldstate, NULL);
12872                        oldstate = pctxt->state;
12873
12874                        counter = xmlAutomataNewCounter(pctxt->am,
12875                            particle->minOccurs - 1, UNBOUNDED);
12876
12877                        sub = particle->children->children;
12878                        while (sub != NULL) {
12879                            tmp2 = xmlSchemaBuildAContentModel(pctxt,
12880                                            (xmlSchemaParticlePtr) sub);
12881                            if (tmp2 != 1) ret = 0;
12882                            sub = sub->next;
12883                        }
12884                        tmp = pctxt->state;
12885                        xmlAutomataNewCountedTrans(pctxt->am, tmp,
12886                                                   oldstate, counter);
12887                        pctxt->state =
12888                            xmlAutomataNewCounterTrans(pctxt->am, tmp,
12889                                                       NULL, counter);
12890                        if (ret == 1)
12891                            xmlAutomataNewEpsilon(pctxt->am,
12892                                                oldstate, pctxt->state);
12893
12894                    } else {
12895                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12896                            oldstate, NULL);
12897                        oldstate = pctxt->state;
12898
12899                        sub = particle->children->children;
12900                        while (sub != NULL) {
12901                            tmp2 = xmlSchemaBuildAContentModel(pctxt,
12902                                        (xmlSchemaParticlePtr) sub);
12903                            if (tmp2 != 1) ret = 0;
12904                            sub = sub->next;
12905                        }
12906                        xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12907                                              oldstate);
12908                        /*
12909                         * epsilon needed to block previous trans from
12910                         * being allowed to enter back from another
12911                         * construct
12912                         */
12913                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12914                                            pctxt->state, NULL);
12915                        if (particle->minOccurs == 0) {
12916                            xmlAutomataNewEpsilon(pctxt->am,
12917                                oldstate, pctxt->state);
12918                            ret = 1;
12919                        }
12920                    }
12921                } else if ((particle->maxOccurs > 1)
12922                           || (particle->minOccurs > 1)) {
12923                    xmlAutomataStatePtr tmp;
12924                    int counter;
12925
12926                    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12927                        oldstate, NULL);
12928                    oldstate = pctxt->state;
12929
12930                    counter = xmlAutomataNewCounter(pctxt->am,
12931                        particle->minOccurs - 1,
12932                        particle->maxOccurs - 1);
12933
12934                    sub = particle->children->children;
12935                    while (sub != NULL) {
12936                        tmp2 = xmlSchemaBuildAContentModel(pctxt,
12937                                        (xmlSchemaParticlePtr) sub);
12938                        if (tmp2 != 1) ret = 0;
12939                        sub = sub->next;
12940                    }
12941                    tmp = pctxt->state;
12942                    xmlAutomataNewCountedTrans(pctxt->am,
12943                        tmp, oldstate, counter);
12944                    pctxt->state =
12945                        xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12946                                                   counter);
12947                    if ((particle->minOccurs == 0) || (ret == 1)) {
12948                        xmlAutomataNewEpsilon(pctxt->am,
12949                                            oldstate, pctxt->state);
12950                        ret = 1;
12951                    }
12952                } else {
12953                    sub = particle->children->children;
12954                    while (sub != NULL) {
12955                        tmp2 = xmlSchemaBuildAContentModel(pctxt,
12956                                        (xmlSchemaParticlePtr) sub);
12957                        if (tmp2 != 1) ret = 0;
12958                        sub = sub->next;
12959                    }
12960
12961		    /*
12962		     * epsilon needed to block previous trans from
12963		     * being allowed to enter back from another
12964		     * construct
12965		     */
12966		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12967					pctxt->state, NULL);
12968
12969                    if (particle->minOccurs == 0) {
12970                        xmlAutomataNewEpsilon(pctxt->am, oldstate,
12971                                              pctxt->state);
12972                        ret = 1;
12973                    }
12974                }
12975            }
12976            break;
12977        }
12978        case XML_SCHEMA_TYPE_CHOICE:{
12979            xmlSchemaTreeItemPtr sub;
12980            xmlAutomataStatePtr start, end;
12981
12982            ret = 0;
12983            start = pctxt->state;
12984            end = xmlAutomataNewState(pctxt->am);
12985
12986            /*
12987             * iterate over the subtypes and remerge the end with an
12988             * epsilon transition
12989             */
12990            if (particle->maxOccurs == 1) {
12991                sub = particle->children->children;
12992                while (sub != NULL) {
12993                    pctxt->state = start;
12994                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
12995                                        (xmlSchemaParticlePtr) sub);
12996                    if (tmp2 == 1) ret = 1;
12997                    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12998                    sub = sub->next;
12999                }
13000            } else {
13001                int counter;
13002                xmlAutomataStatePtr hop, base;
13003                int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13004                    UNBOUNDED : particle->maxOccurs - 1;
13005                int minOccurs =
13006                    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13007
13008                /*
13009                 * use a counter to keep track of the number of transtions
13010                 * which went through the choice.
13011                 */
13012                counter =
13013                    xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13014                hop = xmlAutomataNewState(pctxt->am);
13015                base = xmlAutomataNewState(pctxt->am);
13016
13017                sub = particle->children->children;
13018                while (sub != NULL) {
13019                    pctxt->state = base;
13020                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
13021                                        (xmlSchemaParticlePtr) sub);
13022                    if (tmp2 == 1) ret = 1;
13023                    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13024                    sub = sub->next;
13025                }
13026                xmlAutomataNewEpsilon(pctxt->am, start, base);
13027                xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13028                xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13029                if (ret == 1)
13030                    xmlAutomataNewEpsilon(pctxt->am, base, end);
13031            }
13032            if (particle->minOccurs == 0) {
13033                xmlAutomataNewEpsilon(pctxt->am, start, end);
13034                ret = 1;
13035            }
13036            pctxt->state = end;
13037            break;
13038        }
13039        case XML_SCHEMA_TYPE_ALL:{
13040            xmlAutomataStatePtr start, tmp;
13041            xmlSchemaParticlePtr sub;
13042            xmlSchemaElementPtr elemDecl;
13043
13044            ret = 1;
13045
13046            sub = (xmlSchemaParticlePtr) particle->children->children;
13047            if (sub == NULL)
13048                break;
13049
13050            ret = 0;
13051
13052            start = pctxt->state;
13053            tmp = xmlAutomataNewState(pctxt->am);
13054            xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13055            pctxt->state = tmp;
13056            while (sub != NULL) {
13057                pctxt->state = tmp;
13058
13059                elemDecl = (xmlSchemaElementPtr) sub->children;
13060                if (elemDecl == NULL) {
13061                    PERROR_INT("xmlSchemaBuildAContentModel",
13062                        "<element> particle has no term");
13063                    return(ret);
13064                };
13065                /*
13066                * NOTE: The {max occurs} of all the particles in the
13067                * {particles} of the group must be 0 or 1; this is
13068                * already ensured during the parse of the content of
13069                * <all>.
13070                */
13071                if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13072                    int counter;
13073
13074                    /*
13075                     * This is an abstract group, we need to share
13076                     * the same counter for all the element transitions
13077                     * derived from the group
13078                     */
13079                    counter = xmlAutomataNewCounter(pctxt->am,
13080                                       sub->minOccurs, sub->maxOccurs);
13081                    xmlSchemaBuildContentModelForSubstGroup(pctxt,
13082                                       sub, counter, pctxt->state);
13083                } else {
13084                    if ((sub->minOccurs == 1) &&
13085                        (sub->maxOccurs == 1)) {
13086                        xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13087                                                pctxt->state,
13088                                                elemDecl->name,
13089                                                elemDecl->targetNamespace,
13090                                                1, 1, elemDecl);
13091                    } else if ((sub->minOccurs == 0) &&
13092                        (sub->maxOccurs == 1)) {
13093
13094                        xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13095                                                 pctxt->state,
13096                                                 elemDecl->name,
13097                                                 elemDecl->targetNamespace,
13098                                                 0,
13099                                                 1,
13100                                                 elemDecl);
13101                    }
13102                }
13103                sub = (xmlSchemaParticlePtr) sub->next;
13104            }
13105            pctxt->state =
13106                xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13107            if (particle->minOccurs == 0) {
13108                xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13109                ret = 1;
13110            }
13111            break;
13112        }
13113	case XML_SCHEMA_TYPE_GROUP:
13114	    /*
13115	    * If we hit a model group definition, then this means that
13116	    * it was empty, thus was not substituted for the containing
13117	    * model group. Just do nothing in this case.
13118	    * TODO: But the group should be substituted and not occur at
13119	    * all in the content model at this point. Fix this.
13120	    */
13121            ret = 1;
13122	    break;
13123        default:
13124	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13125		"xmlSchemaBuildAContentModel",
13126		"found unexpected term of type '%s' in content model",
13127		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13128            return(ret);
13129    }
13130    return(ret);
13131}
13132
13133/**
13134 * xmlSchemaBuildContentModel:
13135 * @ctxt:  the schema parser context
13136 * @type:  the complex type definition
13137 * @name:  the element name
13138 *
13139 * Builds the content model of the complex type.
13140 */
13141static void
13142xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13143			   xmlSchemaParserCtxtPtr ctxt)
13144{
13145    if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13146	(type->contModel != NULL) ||
13147	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13148	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13149	return;
13150
13151#ifdef DEBUG_CONTENT
13152    xmlGenericError(xmlGenericErrorContext,
13153                    "Building content model for %s\n", name);
13154#endif
13155    ctxt->am = NULL;
13156    ctxt->am = xmlNewAutomata();
13157    if (ctxt->am == NULL) {
13158        xmlGenericError(xmlGenericErrorContext,
13159	    "Cannot create automata for complex type %s\n", type->name);
13160        return;
13161    }
13162    ctxt->state = xmlAutomataGetInitState(ctxt->am);
13163    /*
13164    * Build the automaton.
13165    */
13166    xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13167    xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13168    type->contModel = xmlAutomataCompile(ctxt->am);
13169    if (type->contModel == NULL) {
13170        xmlSchemaPCustomErr(ctxt,
13171	    XML_SCHEMAP_INTERNAL,
13172	    WXS_BASIC_CAST type, type->node,
13173	    "Failed to compile the content model", NULL);
13174    } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13175        xmlSchemaPCustomErr(ctxt,
13176	    XML_SCHEMAP_NOT_DETERMINISTIC,
13177	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13178	    WXS_BASIC_CAST type, type->node,
13179	    "The content model is not determinist", NULL);
13180    } else {
13181#ifdef DEBUG_CONTENT_REGEXP
13182        xmlGenericError(xmlGenericErrorContext,
13183                        "Content model of %s:\n", type->name);
13184        xmlRegexpPrint(stderr, type->contModel);
13185#endif
13186    }
13187    ctxt->state = NULL;
13188    xmlFreeAutomata(ctxt->am);
13189    ctxt->am = NULL;
13190}
13191
13192/**
13193 * xmlSchemaResolveElementReferences:
13194 * @elem:  the schema element context
13195 * @ctxt:  the schema parser context
13196 *
13197 * Resolves the references of an element declaration
13198 * or particle, which has an element declaration as it's
13199 * term.
13200 */
13201static void
13202xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13203				  xmlSchemaParserCtxtPtr ctxt)
13204{
13205    if ((ctxt == NULL) || (elemDecl == NULL) ||
13206	((elemDecl != NULL) &&
13207	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13208        return;
13209    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13210
13211    if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13212	xmlSchemaTypePtr type;
13213
13214	/* (type definition) ... otherwise the type definition �resolved�
13215	* to by the �actual value� of the type [attribute] ...
13216	*/
13217	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13218	    elemDecl->namedTypeNs);
13219	if (type == NULL) {
13220	    xmlSchemaPResCompAttrErr(ctxt,
13221		XML_SCHEMAP_SRC_RESOLVE,
13222		WXS_BASIC_CAST elemDecl, elemDecl->node,
13223		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13224		XML_SCHEMA_TYPE_BASIC, "type definition");
13225	} else
13226	    elemDecl->subtypes = type;
13227    }
13228    if (elemDecl->substGroup != NULL) {
13229	xmlSchemaElementPtr substHead;
13230
13231	/*
13232	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13233	* substitutionGroup?
13234	*/
13235	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13236	    elemDecl->substGroupNs);
13237	if (substHead == NULL) {
13238	    xmlSchemaPResCompAttrErr(ctxt,
13239		XML_SCHEMAP_SRC_RESOLVE,
13240		WXS_BASIC_CAST elemDecl, NULL,
13241		"substitutionGroup", elemDecl->substGroup,
13242		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13243	} else {
13244	    xmlSchemaResolveElementReferences(substHead, ctxt);
13245	    /*
13246	    * Set the "substitution group affiliation".
13247	    * NOTE that now we use the "refDecl" field for this.
13248	    */
13249	    WXS_SUBST_HEAD(elemDecl) = substHead;
13250	    /*
13251	    * The type definitions is set to:
13252	    * SPEC "...the {type definition} of the element
13253	    * declaration �resolved� to by the �actual value�
13254	    * of the substitutionGroup [attribute], if present"
13255	    */
13256	    if (elemDecl->subtypes == NULL)
13257		elemDecl->subtypes = substHead->subtypes;
13258	}
13259    }
13260    /*
13261    * SPEC "The definition of anyType serves as the default type definition
13262    * for element declarations whose XML representation does not specify one."
13263    */
13264    if ((elemDecl->subtypes == NULL) &&
13265	(elemDecl->namedType == NULL) &&
13266	(elemDecl->substGroup == NULL))
13267	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13268}
13269
13270/**
13271 * xmlSchemaResolveUnionMemberTypes:
13272 * @ctxt:  the schema parser context
13273 * @type:  the schema simple type definition
13274 *
13275 * Checks and builds the "member type definitions" property of the union
13276 * simple type. This handles part (1), part (2) is done in
13277 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13278 *
13279 * Returns -1 in case of an internal error, 0 otherwise.
13280 */
13281static int
13282xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13283				 xmlSchemaTypePtr type)
13284{
13285
13286    xmlSchemaTypeLinkPtr link, lastLink, newLink;
13287    xmlSchemaTypePtr memberType;
13288
13289    /*
13290    * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13291    * define the explicit members as the type definitions �resolved�
13292    * to by the items in the �actual value� of the memberTypes [attribute],
13293    * if any, followed by the type definitions corresponding to the
13294    * <simpleType>s among the [children] of <union>, if any."
13295    */
13296    /*
13297    * Resolve references.
13298    */
13299    link = type->memberTypes;
13300    lastLink = NULL;
13301    while (link != NULL) {
13302	const xmlChar *name, *nsName;
13303
13304	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13305	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13306
13307	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13308	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13309	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13310		WXS_BASIC_CAST type, type->node, "memberTypes",
13311		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13312	    /*
13313	    * Remove the member type link.
13314	    */
13315	    if (lastLink == NULL)
13316		type->memberTypes = link->next;
13317	    else
13318		lastLink->next = link->next;
13319	    newLink = link;
13320	    link = link->next;
13321	    xmlFree(newLink);
13322	} else {
13323	    link->type = memberType;
13324	    lastLink = link;
13325	    link = link->next;
13326	}
13327    }
13328    /*
13329    * Add local simple types,
13330    */
13331    memberType = type->subtypes;
13332    while (memberType != NULL) {
13333	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13334	if (link == NULL) {
13335	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13336	    return (-1);
13337	}
13338	link->type = memberType;
13339	link->next = NULL;
13340	if (lastLink == NULL)
13341	    type->memberTypes = link;
13342	else
13343	    lastLink->next = link;
13344	lastLink = link;
13345	memberType = memberType->next;
13346    }
13347    return (0);
13348}
13349
13350/**
13351 * xmlSchemaIsDerivedFromBuiltInType:
13352 * @ctxt:  the schema parser context
13353 * @type:  the type definition
13354 * @valType: the value type
13355 *
13356 *
13357 * Returns 1 if the type has the given value type, or
13358 * is derived from such a type.
13359 */
13360static int
13361xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13362{
13363    if (type == NULL)
13364	return (0);
13365    if (WXS_IS_COMPLEX(type))
13366	return (0);
13367    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13368	if (type->builtInType == valType)
13369	    return(1);
13370	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13371	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13372	    return (0);
13373	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13374    }
13375    return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13376}
13377
13378#if 0
13379/**
13380 * xmlSchemaIsDerivedFromBuiltInType:
13381 * @ctxt:  the schema parser context
13382 * @type:  the type definition
13383 * @valType: the value type
13384 *
13385 *
13386 * Returns 1 if the type has the given value type, or
13387 * is derived from such a type.
13388 */
13389static int
13390xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13391{
13392    if (type == NULL)
13393	return (0);
13394    if (WXS_IS_COMPLEX(type))
13395	return (0);
13396    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13397	if (type->builtInType == valType)
13398	    return(1);
13399	return (0);
13400    } else
13401	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13402
13403    return (0);
13404}
13405
13406static xmlSchemaTypePtr
13407xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13408{
13409    if (type == NULL)
13410	return (NULL);
13411    if (WXS_IS_COMPLEX(type))
13412	return (NULL);
13413    if (type->type == XML_SCHEMA_TYPE_BASIC)
13414	return(type);
13415    return(xmlSchemaQueryBuiltInType(type->subtypes));
13416}
13417#endif
13418
13419/**
13420 * xmlSchemaGetPrimitiveType:
13421 * @type:  the simpleType definition
13422 *
13423 * Returns the primitive type of the given type or
13424 * NULL in case of error.
13425 */
13426static xmlSchemaTypePtr
13427xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13428{
13429
13430    while (type != NULL) {
13431	/*
13432	* Note that anySimpleType is actually not a primitive type
13433	* but we need that here.
13434	*/
13435	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13436	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13437	    return (type);
13438	type = type->baseType;
13439    }
13440
13441    return (NULL);
13442}
13443
13444#if 0
13445/**
13446 * xmlSchemaGetBuiltInTypeAncestor:
13447 * @type:  the simpleType definition
13448 *
13449 * Returns the primitive type of the given type or
13450 * NULL in case of error.
13451 */
13452static xmlSchemaTypePtr
13453xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13454{
13455    if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13456	return (0);
13457    while (type != NULL) {
13458	if (type->type == XML_SCHEMA_TYPE_BASIC)
13459	    return (type);
13460	type = type->baseType;
13461    }
13462
13463    return (NULL);
13464}
13465#endif
13466
13467/**
13468 * xmlSchemaCloneWildcardNsConstraints:
13469 * @ctxt:  the schema parser context
13470 * @dest:  the destination wildcard
13471 * @source: the source wildcard
13472 *
13473 * Clones the namespace constraints of source
13474 * and assignes them to dest.
13475 * Returns -1 on internal error, 0 otherwise.
13476 */
13477static int
13478xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13479				    xmlSchemaWildcardPtr dest,
13480				    xmlSchemaWildcardPtr source)
13481{
13482    xmlSchemaWildcardNsPtr cur, tmp, last;
13483
13484    if ((source == NULL) || (dest == NULL))
13485	return(-1);
13486    dest->any = source->any;
13487    cur = source->nsSet;
13488    last = NULL;
13489    while (cur != NULL) {
13490	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13491	if (tmp == NULL)
13492	    return(-1);
13493	tmp->value = cur->value;
13494	if (last == NULL)
13495	    dest->nsSet = tmp;
13496	else
13497	    last->next = tmp;
13498	last = tmp;
13499	cur = cur->next;
13500    }
13501    if (dest->negNsSet != NULL)
13502	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13503    if (source->negNsSet != NULL) {
13504	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13505	if (dest->negNsSet == NULL)
13506	    return(-1);
13507	dest->negNsSet->value = source->negNsSet->value;
13508    } else
13509	dest->negNsSet = NULL;
13510    return(0);
13511}
13512
13513/**
13514 * xmlSchemaUnionWildcards:
13515 * @ctxt:  the schema parser context
13516 * @completeWild:  the first wildcard
13517 * @curWild: the second wildcard
13518 *
13519 * Unions the namespace constraints of the given wildcards.
13520 * @completeWild will hold the resulting union.
13521 * Returns a positive error code on failure, -1 in case of an
13522 * internal error, 0 otherwise.
13523 */
13524static int
13525xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13526			    xmlSchemaWildcardPtr completeWild,
13527			    xmlSchemaWildcardPtr curWild)
13528{
13529    xmlSchemaWildcardNsPtr cur, curB, tmp;
13530
13531    /*
13532    * 1 If O1 and O2 are the same value, then that value must be the
13533    * value.
13534    */
13535    if ((completeWild->any == curWild->any) &&
13536	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13537	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13538
13539	if ((completeWild->negNsSet == NULL) ||
13540	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13541
13542	    if (completeWild->nsSet != NULL) {
13543		int found = 0;
13544
13545		/*
13546		* Check equality of sets.
13547		*/
13548		cur = completeWild->nsSet;
13549		while (cur != NULL) {
13550		    found = 0;
13551		    curB = curWild->nsSet;
13552		    while (curB != NULL) {
13553			if (cur->value == curB->value) {
13554			    found = 1;
13555			    break;
13556			}
13557			curB = curB->next;
13558		    }
13559		    if (!found)
13560			break;
13561		    cur = cur->next;
13562		}
13563		if (found)
13564		    return(0);
13565	    } else
13566		return(0);
13567	}
13568    }
13569    /*
13570    * 2 If either O1 or O2 is any, then any must be the value
13571    */
13572    if (completeWild->any != curWild->any) {
13573	if (completeWild->any == 0) {
13574	    completeWild->any = 1;
13575	    if (completeWild->nsSet != NULL) {
13576		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13577		completeWild->nsSet = NULL;
13578	    }
13579	    if (completeWild->negNsSet != NULL) {
13580		xmlFree(completeWild->negNsSet);
13581		completeWild->negNsSet = NULL;
13582	    }
13583	}
13584	return (0);
13585    }
13586    /*
13587    * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13588    * then the union of those sets must be the value.
13589    */
13590    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13591	int found;
13592	xmlSchemaWildcardNsPtr start;
13593
13594	cur = curWild->nsSet;
13595	start = completeWild->nsSet;
13596	while (cur != NULL) {
13597	    found = 0;
13598	    curB = start;
13599	    while (curB != NULL) {
13600		if (cur->value == curB->value) {
13601		    found = 1;
13602		    break;
13603		}
13604		curB = curB->next;
13605	    }
13606	    if (!found) {
13607		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13608		if (tmp == NULL)
13609		    return (-1);
13610		tmp->value = cur->value;
13611		tmp->next = completeWild->nsSet;
13612		completeWild->nsSet = tmp;
13613	    }
13614	    cur = cur->next;
13615	}
13616
13617	return(0);
13618    }
13619    /*
13620    * 4 If the two are negations of different values (namespace names
13621    * or �absent�), then a pair of not and �absent� must be the value.
13622    */
13623    if ((completeWild->negNsSet != NULL) &&
13624	(curWild->negNsSet != NULL) &&
13625	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13626	completeWild->negNsSet->value = NULL;
13627
13628	return(0);
13629    }
13630    /*
13631     * 5.
13632     */
13633    if (((completeWild->negNsSet != NULL) &&
13634	(completeWild->negNsSet->value != NULL) &&
13635	(curWild->nsSet != NULL)) ||
13636	((curWild->negNsSet != NULL) &&
13637	(curWild->negNsSet->value != NULL) &&
13638	(completeWild->nsSet != NULL))) {
13639
13640	int nsFound, absentFound = 0;
13641
13642	if (completeWild->nsSet != NULL) {
13643	    cur = completeWild->nsSet;
13644	    curB = curWild->negNsSet;
13645	} else {
13646	    cur = curWild->nsSet;
13647	    curB = completeWild->negNsSet;
13648	}
13649	nsFound = 0;
13650	while (cur != NULL) {
13651	    if (cur->value == NULL)
13652		absentFound = 1;
13653	    else if (cur->value == curB->value)
13654		nsFound = 1;
13655	    if (nsFound && absentFound)
13656		break;
13657	    cur = cur->next;
13658	}
13659
13660	if (nsFound && absentFound) {
13661	    /*
13662	    * 5.1 If the set S includes both the negated namespace
13663	    * name and �absent�, then any must be the value.
13664	    */
13665	    completeWild->any = 1;
13666	    if (completeWild->nsSet != NULL) {
13667		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13668		completeWild->nsSet = NULL;
13669	    }
13670	    if (completeWild->negNsSet != NULL) {
13671		xmlFree(completeWild->negNsSet);
13672		completeWild->negNsSet = NULL;
13673	    }
13674	} else if (nsFound && (!absentFound)) {
13675	    /*
13676	    * 5.2 If the set S includes the negated namespace name
13677	    * but not �absent�, then a pair of not and �absent� must
13678	    * be the value.
13679	    */
13680	    if (completeWild->nsSet != NULL) {
13681		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13682		completeWild->nsSet = NULL;
13683	    }
13684	    if (completeWild->negNsSet == NULL) {
13685		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13686		if (completeWild->negNsSet == NULL)
13687		    return (-1);
13688	    }
13689	    completeWild->negNsSet->value = NULL;
13690	} else if ((!nsFound) && absentFound) {
13691	    /*
13692	    * 5.3 If the set S includes �absent� but not the negated
13693	    * namespace name, then the union is not expressible.
13694	    */
13695	    xmlSchemaPErr(ctxt, completeWild->node,
13696		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13697		"The union of the wilcard is not expressible.\n",
13698		NULL, NULL);
13699	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13700	} else if ((!nsFound) && (!absentFound)) {
13701	    /*
13702	    * 5.4 If the set S does not include either the negated namespace
13703	    * name or �absent�, then whichever of O1 or O2 is a pair of not
13704	    * and a namespace name must be the value.
13705	    */
13706	    if (completeWild->negNsSet == NULL) {
13707		if (completeWild->nsSet != NULL) {
13708		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13709		    completeWild->nsSet = NULL;
13710		}
13711		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13712		if (completeWild->negNsSet == NULL)
13713		    return (-1);
13714		completeWild->negNsSet->value = curWild->negNsSet->value;
13715	    }
13716	}
13717	return (0);
13718    }
13719    /*
13720     * 6.
13721     */
13722    if (((completeWild->negNsSet != NULL) &&
13723	(completeWild->negNsSet->value == NULL) &&
13724	(curWild->nsSet != NULL)) ||
13725	((curWild->negNsSet != NULL) &&
13726	(curWild->negNsSet->value == NULL) &&
13727	(completeWild->nsSet != NULL))) {
13728
13729	if (completeWild->nsSet != NULL) {
13730	    cur = completeWild->nsSet;
13731	} else {
13732	    cur = curWild->nsSet;
13733	}
13734	while (cur != NULL) {
13735	    if (cur->value == NULL) {
13736		/*
13737		* 6.1 If the set S includes �absent�, then any must be the
13738		* value.
13739		*/
13740		completeWild->any = 1;
13741		if (completeWild->nsSet != NULL) {
13742		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13743		    completeWild->nsSet = NULL;
13744		}
13745		if (completeWild->negNsSet != NULL) {
13746		    xmlFree(completeWild->negNsSet);
13747		    completeWild->negNsSet = NULL;
13748		}
13749		return (0);
13750	    }
13751	    cur = cur->next;
13752	}
13753	if (completeWild->negNsSet == NULL) {
13754	    /*
13755	    * 6.2 If the set S does not include �absent�, then a pair of not
13756	    * and �absent� must be the value.
13757	    */
13758	    if (completeWild->nsSet != NULL) {
13759		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13760		completeWild->nsSet = NULL;
13761	    }
13762	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13763	    if (completeWild->negNsSet == NULL)
13764		return (-1);
13765	    completeWild->negNsSet->value = NULL;
13766	}
13767	return (0);
13768    }
13769    return (0);
13770
13771}
13772
13773/**
13774 * xmlSchemaIntersectWildcards:
13775 * @ctxt:  the schema parser context
13776 * @completeWild:  the first wildcard
13777 * @curWild: the second wildcard
13778 *
13779 * Intersects the namespace constraints of the given wildcards.
13780 * @completeWild will hold the resulting intersection.
13781 * Returns a positive error code on failure, -1 in case of an
13782 * internal error, 0 otherwise.
13783 */
13784static int
13785xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13786			    xmlSchemaWildcardPtr completeWild,
13787			    xmlSchemaWildcardPtr curWild)
13788{
13789    xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13790
13791    /*
13792    * 1 If O1 and O2 are the same value, then that value must be the
13793    * value.
13794    */
13795    if ((completeWild->any == curWild->any) &&
13796	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13797	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13798
13799	if ((completeWild->negNsSet == NULL) ||
13800	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13801
13802	    if (completeWild->nsSet != NULL) {
13803		int found = 0;
13804
13805		/*
13806		* Check equality of sets.
13807		*/
13808		cur = completeWild->nsSet;
13809		while (cur != NULL) {
13810		    found = 0;
13811		    curB = curWild->nsSet;
13812		    while (curB != NULL) {
13813			if (cur->value == curB->value) {
13814			    found = 1;
13815			    break;
13816			}
13817			curB = curB->next;
13818		    }
13819		    if (!found)
13820			break;
13821		    cur = cur->next;
13822		}
13823		if (found)
13824		    return(0);
13825	    } else
13826		return(0);
13827	}
13828    }
13829    /*
13830    * 2 If either O1 or O2 is any, then the other must be the value.
13831    */
13832    if ((completeWild->any != curWild->any) && (completeWild->any)) {
13833	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13834	    return(-1);
13835	return(0);
13836    }
13837    /*
13838    * 3 If either O1 or O2 is a pair of not and a value (a namespace
13839    * name or �absent�) and the other is a set of (namespace names or
13840    * �absent�), then that set, minus the negated value if it was in
13841    * the set, minus �absent� if it was in the set, must be the value.
13842    */
13843    if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13844	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13845	const xmlChar *neg;
13846
13847	if (completeWild->nsSet == NULL) {
13848	    neg = completeWild->negNsSet->value;
13849	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13850		return(-1);
13851	} else
13852	    neg = curWild->negNsSet->value;
13853	/*
13854	* Remove absent and negated.
13855	*/
13856	prev = NULL;
13857	cur = completeWild->nsSet;
13858	while (cur != NULL) {
13859	    if (cur->value == NULL) {
13860		if (prev == NULL)
13861		    completeWild->nsSet = cur->next;
13862		else
13863		    prev->next = cur->next;
13864		xmlFree(cur);
13865		break;
13866	    }
13867	    prev = cur;
13868	    cur = cur->next;
13869	}
13870	if (neg != NULL) {
13871	    prev = NULL;
13872	    cur = completeWild->nsSet;
13873	    while (cur != NULL) {
13874		if (cur->value == neg) {
13875		    if (prev == NULL)
13876			completeWild->nsSet = cur->next;
13877		    else
13878			prev->next = cur->next;
13879		    xmlFree(cur);
13880		    break;
13881		}
13882		prev = cur;
13883		cur = cur->next;
13884	    }
13885	}
13886
13887	return(0);
13888    }
13889    /*
13890    * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13891    * then the intersection of those sets must be the value.
13892    */
13893    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13894	int found;
13895
13896	cur = completeWild->nsSet;
13897	prev = NULL;
13898	while (cur != NULL) {
13899	    found = 0;
13900	    curB = curWild->nsSet;
13901	    while (curB != NULL) {
13902		if (cur->value == curB->value) {
13903		    found = 1;
13904		    break;
13905		}
13906		curB = curB->next;
13907	    }
13908	    if (!found) {
13909		if (prev == NULL)
13910		    completeWild->nsSet = cur->next;
13911		else
13912		    prev->next = cur->next;
13913		tmp = cur->next;
13914		xmlFree(cur);
13915		cur = tmp;
13916		continue;
13917	    }
13918	    prev = cur;
13919	    cur = cur->next;
13920	}
13921
13922	return(0);
13923    }
13924    /* 5 If the two are negations of different namespace names,
13925    * then the intersection is not expressible
13926    */
13927    if ((completeWild->negNsSet != NULL) &&
13928	(curWild->negNsSet != NULL) &&
13929	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13930	(completeWild->negNsSet->value != NULL) &&
13931	(curWild->negNsSet->value != NULL)) {
13932
13933	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13934	    "The intersection of the wilcard is not expressible.\n",
13935	    NULL, NULL);
13936	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13937    }
13938    /*
13939    * 6 If the one is a negation of a namespace name and the other
13940    * is a negation of �absent�, then the one which is the negation
13941    * of a namespace name must be the value.
13942    */
13943    if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13944	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13945	(completeWild->negNsSet->value == NULL)) {
13946	completeWild->negNsSet->value =  curWild->negNsSet->value;
13947    }
13948    return(0);
13949}
13950
13951/**
13952 * xmlSchemaIsWildcardNsConstraintSubset:
13953 * @ctxt:  the schema parser context
13954 * @sub:  the first wildcard
13955 * @super: the second wildcard
13956 *
13957 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13958 *
13959 * Returns 0 if the namespace constraint of @sub is an intensional
13960 * subset of @super, 1 otherwise.
13961 */
13962static int
13963xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13964			  xmlSchemaWildcardPtr super)
13965{
13966    /*
13967    * 1 super must be any.
13968    */
13969    if (super->any)
13970	return (0);
13971    /*
13972    * 2.1 sub must be a pair of not and a namespace name or �absent�.
13973    * 2.2 super must be a pair of not and the same value.
13974    */
13975    if ((sub->negNsSet != NULL) &&
13976	(super->negNsSet != NULL) &&
13977	(sub->negNsSet->value == super->negNsSet->value))
13978	return (0);
13979    /*
13980    * 3.1 sub must be a set whose members are either namespace names or �absent�.
13981    */
13982    if (sub->nsSet != NULL) {
13983	/*
13984	* 3.2.1 super must be the same set or a superset thereof.
13985	*/
13986	if (super->nsSet != NULL) {
13987	    xmlSchemaWildcardNsPtr cur, curB;
13988	    int found = 0;
13989
13990	    cur = sub->nsSet;
13991	    while (cur != NULL) {
13992		found = 0;
13993		curB = super->nsSet;
13994		while (curB != NULL) {
13995		    if (cur->value == curB->value) {
13996			found = 1;
13997			break;
13998		    }
13999		    curB = curB->next;
14000		}
14001		if (!found)
14002		    return (1);
14003		cur = cur->next;
14004	    }
14005	    if (found)
14006		return (0);
14007	} else if (super->negNsSet != NULL) {
14008	    xmlSchemaWildcardNsPtr cur;
14009	    /*
14010	    * 3.2.2 super must be a pair of not and a namespace name or
14011	    * �absent� and that value must not be in sub's set.
14012	    */
14013	    cur = sub->nsSet;
14014	    while (cur != NULL) {
14015		if (cur->value == super->negNsSet->value)
14016		    return (1);
14017		cur = cur->next;
14018	    }
14019	    return (0);
14020	}
14021    }
14022    return (1);
14023}
14024
14025static int
14026xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14027				     int *fixed,
14028				     const xmlChar **value,
14029				     xmlSchemaValPtr *val)
14030{
14031    *fixed = 0;
14032    *value = NULL;
14033    if (val != 0)
14034	*val = NULL;
14035
14036    if (attruse->defValue != NULL) {
14037	*value = attruse->defValue;
14038	if (val != NULL)
14039	    *val = attruse->defVal;
14040	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14041	    *fixed = 1;
14042	return(1);
14043    } else if ((attruse->attrDecl != NULL) &&
14044	(attruse->attrDecl->defValue != NULL)) {
14045	*value = attruse->attrDecl->defValue;
14046	if (val != NULL)
14047	    *val = attruse->attrDecl->defVal;
14048	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14049	    *fixed = 1;
14050	return(1);
14051    }
14052    return(0);
14053}
14054/**
14055 * xmlSchemaCheckCVCWildcardNamespace:
14056 * @wild:  the wildcard
14057 * @ns:  the namespace
14058 *
14059 * Validation Rule: Wildcard allows Namespace Name
14060 * (cvc-wildcard-namespace)
14061 *
14062 * Returns 0 if the given namespace matches the wildcard,
14063 * 1 otherwise and -1 on API errors.
14064 */
14065static int
14066xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14067				   const xmlChar* ns)
14068{
14069    if (wild == NULL)
14070	return(-1);
14071
14072    if (wild->any)
14073	return(0);
14074    else if (wild->nsSet != NULL) {
14075	xmlSchemaWildcardNsPtr cur;
14076
14077	cur = wild->nsSet;
14078	while (cur != NULL) {
14079	    if (xmlStrEqual(cur->value, ns))
14080		return(0);
14081	    cur = cur->next;
14082	}
14083    } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14084	(!xmlStrEqual(wild->negNsSet->value, ns)))
14085	return(0);
14086
14087    return(1);
14088}
14089
14090#define XML_SCHEMA_ACTION_DERIVE 0
14091#define XML_SCHEMA_ACTION_REDEFINE 1
14092
14093#define WXS_ACTION_STR(a) \
14094((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14095
14096/*
14097* Schema Component Constraint:
14098*   Derivation Valid (Restriction, Complex)
14099*   derivation-ok-restriction (2) - (4)
14100*
14101* ATTENTION:
14102* In XML Schema 1.1 this will be:
14103* Validation Rule:
14104*     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14105*
14106*/
14107static int
14108xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14109				       int action,
14110				       xmlSchemaBasicItemPtr item,
14111				       xmlSchemaBasicItemPtr baseItem,
14112				       xmlSchemaItemListPtr uses,
14113				       xmlSchemaItemListPtr baseUses,
14114				       xmlSchemaWildcardPtr wild,
14115				       xmlSchemaWildcardPtr baseWild)
14116{
14117    xmlSchemaAttributeUsePtr cur = NULL, bcur;
14118    int i, j, found; /* err = 0; */
14119    const xmlChar *bEffValue;
14120    int effFixed;
14121
14122    if (uses != NULL) {
14123	for (i = 0; i < uses->nbItems; i++) {
14124	    cur = uses->items[i];
14125	    found = 0;
14126	    if (baseUses == NULL)
14127		goto not_found;
14128	    for (j = 0; j < baseUses->nbItems; j++) {
14129		bcur = baseUses->items[j];
14130		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14131			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14132		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14133			WXS_ATTRUSE_DECL_TNS(bcur)))
14134		{
14135		    /*
14136		    * (2.1) "If there is an attribute use in the {attribute
14137		    * uses} of the {base type definition} (call this B) whose
14138		    * {attribute declaration} has the same {name} and {target
14139		    * namespace}, then  all of the following must be true:"
14140		    */
14141		    found = 1;
14142
14143		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14144			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14145		    {
14146			xmlChar *str = NULL;
14147			/*
14148			* (2.1.1) "one of the following must be true:"
14149			* (2.1.1.1) "B's {required} is false."
14150			* (2.1.1.2) "R's {required} is true."
14151			*/
14152			xmlSchemaPAttrUseErr4(pctxt,
14153			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14154			    WXS_ITEM_NODE(item), item, cur,
14155			    "The 'optional' attribute use is inconsistent "
14156			    "with the corresponding 'required' attribute use of "
14157			    "the %s %s",
14158			    WXS_ACTION_STR(action),
14159			    xmlSchemaGetComponentDesignation(&str, baseItem),
14160			    NULL, NULL);
14161			FREE_AND_NULL(str);
14162			/* err = pctxt->err; */
14163		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14164			WXS_ATTRUSE_TYPEDEF(cur),
14165			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14166		    {
14167			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14168
14169			/*
14170			* SPEC (2.1.2) "R's {attribute declaration}'s
14171			* {type definition} must be validly derived from
14172			* B's {type definition} given the empty set as
14173			* defined in Type Derivation OK (Simple) (�3.14.6)."
14174			*/
14175			xmlSchemaPAttrUseErr4(pctxt,
14176			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14177			    WXS_ITEM_NODE(item), item, cur,
14178			    "The attribute declaration's %s "
14179			    "is not validly derived from "
14180			    "the corresponding %s of the "
14181			    "attribute declaration in the %s %s",
14182			    xmlSchemaGetComponentDesignation(&strA,
14183				WXS_ATTRUSE_TYPEDEF(cur)),
14184			    xmlSchemaGetComponentDesignation(&strB,
14185				WXS_ATTRUSE_TYPEDEF(bcur)),
14186			    WXS_ACTION_STR(action),
14187			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14188			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14189			FREE_AND_NULL(strA);
14190			FREE_AND_NULL(strB);
14191			FREE_AND_NULL(strC);
14192			/* err = pctxt->err; */
14193		    } else {
14194			/*
14195			* 2.1.3 [Definition:]  Let the effective value
14196			* constraint of an attribute use be its {value
14197			* constraint}, if present, otherwise its {attribute
14198			* declaration}'s {value constraint} .
14199			*/
14200			xmlSchemaGetEffectiveValueConstraint(bcur,
14201			    &effFixed, &bEffValue, NULL);
14202			/*
14203			* 2.1.3 ... one of the following must be true
14204			*
14205			* 2.1.3.1 B's �effective value constraint� is
14206			* �absent� or default.
14207			*/
14208			if ((bEffValue != NULL) &&
14209			    (effFixed == 1)) {
14210			    const xmlChar *rEffValue = NULL;
14211
14212			    xmlSchemaGetEffectiveValueConstraint(bcur,
14213				&effFixed, &rEffValue, NULL);
14214			    /*
14215			    * 2.1.3.2 R's �effective value constraint� is
14216			    * fixed with the same string as B's.
14217			    * MAYBE TODO: Compare the computed values.
14218			    *       Hmm, it says "same string" so
14219			    *       string-equality might really be sufficient.
14220			    */
14221			    if ((effFixed == 0) ||
14222				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14223			    {
14224				xmlChar *str = NULL;
14225
14226				xmlSchemaPAttrUseErr4(pctxt,
14227				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14228				    WXS_ITEM_NODE(item), item, cur,
14229				    "The effective value constraint of the "
14230				    "attribute use is inconsistent with "
14231				    "its correspondent in the %s %s",
14232				    WXS_ACTION_STR(action),
14233				    xmlSchemaGetComponentDesignation(&str,
14234					baseItem),
14235				    NULL, NULL);
14236				FREE_AND_NULL(str);
14237				/* err = pctxt->err; */
14238			    }
14239			}
14240		    }
14241		    break;
14242		}
14243	    }
14244not_found:
14245	    if (!found) {
14246		/*
14247		* (2.2) "otherwise the {base type definition} must have an
14248		* {attribute wildcard} and the {target namespace} of the
14249		* R's {attribute declaration} must be �valid� with respect
14250		* to that wildcard, as defined in Wildcard allows Namespace
14251		* Name (�3.10.4)."
14252		*/
14253		if ((baseWild == NULL) ||
14254		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14255		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14256		{
14257		    xmlChar *str = NULL;
14258
14259		    xmlSchemaPAttrUseErr4(pctxt,
14260			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14261			WXS_ITEM_NODE(item), item, cur,
14262			"Neither a matching attribute use, "
14263			"nor a matching wildcard exists in the %s %s",
14264			WXS_ACTION_STR(action),
14265			xmlSchemaGetComponentDesignation(&str, baseItem),
14266			NULL, NULL);
14267		    FREE_AND_NULL(str);
14268		    /* err = pctxt->err; */
14269		}
14270	    }
14271	}
14272    }
14273    /*
14274    * SPEC derivation-ok-restriction (3):
14275    * (3) "For each attribute use in the {attribute uses} of the {base type
14276    * definition} whose {required} is true, there must be an attribute
14277    * use with an {attribute declaration} with the same {name} and
14278    * {target namespace} as its {attribute declaration} in the {attribute
14279    * uses} of the complex type definition itself whose {required} is true.
14280    */
14281    if (baseUses != NULL) {
14282	for (j = 0; j < baseUses->nbItems; j++) {
14283	    bcur = baseUses->items[j];
14284	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14285		continue;
14286	    found = 0;
14287	    if (uses != NULL) {
14288		for (i = 0; i < uses->nbItems; i++) {
14289		    cur = uses->items[i];
14290		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14291			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14292			(WXS_ATTRUSE_DECL_TNS(cur) ==
14293			WXS_ATTRUSE_DECL_TNS(bcur))) {
14294			found = 1;
14295			break;
14296		    }
14297		}
14298	    }
14299	    if (!found) {
14300		xmlChar *strA = NULL, *strB = NULL;
14301
14302		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14303		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14304		    NULL, item,
14305		    "A matching attribute use for the "
14306		    "'required' %s of the %s %s is missing",
14307		    xmlSchemaGetComponentDesignation(&strA, bcur),
14308		    WXS_ACTION_STR(action),
14309		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14310		    NULL);
14311		FREE_AND_NULL(strA);
14312		FREE_AND_NULL(strB);
14313	    }
14314	}
14315    }
14316    /*
14317    * derivation-ok-restriction (4)
14318    */
14319    if (wild != NULL) {
14320	/*
14321	* (4) "If there is an {attribute wildcard}, all of the
14322	* following must be true:"
14323	*/
14324	if (baseWild == NULL) {
14325	    xmlChar *str = NULL;
14326
14327	    /*
14328	    * (4.1) "The {base type definition} must also have one."
14329	    */
14330	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14331		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14332		NULL, item,
14333		"The %s has an attribute wildcard, "
14334		"but the %s %s '%s' does not have one",
14335		WXS_ITEM_TYPE_NAME(item),
14336		WXS_ACTION_STR(action),
14337		WXS_ITEM_TYPE_NAME(baseItem),
14338		xmlSchemaGetComponentQName(&str, baseItem));
14339	    FREE_AND_NULL(str);
14340	    return(pctxt->err);
14341	} else if ((baseWild->any == 0) &&
14342		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14343	{
14344	    xmlChar *str = NULL;
14345	    /*
14346	    * (4.2) "The complex type definition's {attribute wildcard}'s
14347	    * {namespace constraint} must be a subset of the {base type
14348	    * definition}'s {attribute wildcard}'s {namespace constraint},
14349	    * as defined by Wildcard Subset (�3.10.6)."
14350	    */
14351	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14352		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14353		NULL, item,
14354		"The attribute wildcard is not a valid "
14355		"subset of the wildcard in the %s %s '%s'",
14356		WXS_ACTION_STR(action),
14357		WXS_ITEM_TYPE_NAME(baseItem),
14358		xmlSchemaGetComponentQName(&str, baseItem),
14359		NULL);
14360	    FREE_AND_NULL(str);
14361	    return(pctxt->err);
14362	}
14363	/* 4.3 Unless the {base type definition} is the �ur-type
14364	* definition�, the complex type definition's {attribute
14365	* wildcard}'s {process contents} must be identical to or
14366	* stronger than the {base type definition}'s {attribute
14367	* wildcard}'s {process contents}, where strict is stronger
14368	* than lax is stronger than skip.
14369	*/
14370	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14371	    (wild->processContents < baseWild->processContents)) {
14372	    xmlChar *str = NULL;
14373	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14374		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14375		NULL, baseItem,
14376		"The {process contents} of the attribute wildcard is "
14377		"weaker than the one in the %s %s '%s'",
14378		WXS_ACTION_STR(action),
14379		WXS_ITEM_TYPE_NAME(baseItem),
14380		xmlSchemaGetComponentQName(&str, baseItem),
14381		NULL);
14382	    FREE_AND_NULL(str)
14383		return(pctxt->err);
14384	}
14385    }
14386    return(0);
14387}
14388
14389
14390static int
14391xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14392				  xmlSchemaBasicItemPtr item,
14393				  xmlSchemaWildcardPtr *completeWild,
14394				  xmlSchemaItemListPtr list,
14395				  xmlSchemaItemListPtr prohibs);
14396/**
14397 * xmlSchemaFixupTypeAttributeUses:
14398 * @ctxt:  the schema parser context
14399 * @type:  the complex type definition
14400 *
14401 *
14402 * Builds the wildcard and the attribute uses on the given complex type.
14403 * Returns -1 if an internal error occurs, 0 otherwise.
14404 *
14405 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14406 * strings, so recheck this if we start to hardcode some schemata, since
14407 * they might not be in the same dict.
14408 * NOTE: It is allowed to "extend" the xs:anyType type.
14409 */
14410static int
14411xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14412				  xmlSchemaTypePtr type)
14413{
14414    xmlSchemaTypePtr baseType = NULL;
14415    xmlSchemaAttributeUsePtr use;
14416    xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14417
14418    if (type->baseType == NULL) {
14419	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14420	    "no base type");
14421        return (-1);
14422    }
14423    baseType = type->baseType;
14424    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14425	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14426	    return(-1);
14427
14428    uses = type->attrUses;
14429    baseUses = baseType->attrUses;
14430    /*
14431    * Expand attribute group references. And build the 'complete'
14432    * wildcard, i.e. intersect multiple wildcards.
14433    * Move attribute prohibitions into a separate list.
14434    */
14435    if (uses != NULL) {
14436	if (WXS_IS_RESTRICTION(type)) {
14437	    /*
14438	    * This one will transfer all attr. prohibitions
14439	    * into pctxt->attrProhibs.
14440	    */
14441	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14442		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14443		pctxt->attrProhibs) == -1)
14444	    {
14445		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14446		"failed to expand attributes");
14447	    }
14448	    if (pctxt->attrProhibs->nbItems != 0)
14449		prohibs = pctxt->attrProhibs;
14450	} else {
14451	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14452		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14453		NULL) == -1)
14454	    {
14455		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14456		"failed to expand attributes");
14457	    }
14458	}
14459    }
14460    /*
14461    * Inherit the attribute uses of the base type.
14462    */
14463    if (baseUses != NULL) {
14464	int i, j;
14465	xmlSchemaAttributeUseProhibPtr pro;
14466
14467	if (WXS_IS_RESTRICTION(type)) {
14468	    int usesCount;
14469	    xmlSchemaAttributeUsePtr tmp;
14470
14471	    if (uses != NULL)
14472		usesCount = uses->nbItems;
14473	    else
14474		usesCount = 0;
14475
14476	    /* Restriction. */
14477	    for (i = 0; i < baseUses->nbItems; i++) {
14478		use = baseUses->items[i];
14479		if (prohibs) {
14480		    /*
14481		    * Filter out prohibited uses.
14482		    */
14483		    for (j = 0; j < prohibs->nbItems; j++) {
14484			pro = prohibs->items[j];
14485			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14486			    (WXS_ATTRUSE_DECL_TNS(use) ==
14487				pro->targetNamespace))
14488			{
14489			    goto inherit_next;
14490			}
14491		    }
14492		}
14493		if (usesCount) {
14494		    /*
14495		    * Filter out existing uses.
14496		    */
14497		    for (j = 0; j < usesCount; j++) {
14498			tmp = uses->items[j];
14499			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14500				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14501			    (WXS_ATTRUSE_DECL_TNS(use) ==
14502				WXS_ATTRUSE_DECL_TNS(tmp)))
14503			{
14504			    goto inherit_next;
14505			}
14506		    }
14507		}
14508		if (uses == NULL) {
14509		    type->attrUses = xmlSchemaItemListCreate();
14510		    if (type->attrUses == NULL)
14511			goto exit_failure;
14512		    uses = type->attrUses;
14513		}
14514		xmlSchemaItemListAddSize(uses, 2, use);
14515inherit_next: {}
14516	    }
14517	} else {
14518	    /* Extension. */
14519	    for (i = 0; i < baseUses->nbItems; i++) {
14520		use = baseUses->items[i];
14521		if (uses == NULL) {
14522		    type->attrUses = xmlSchemaItemListCreate();
14523		    if (type->attrUses == NULL)
14524			goto exit_failure;
14525		    uses = type->attrUses;
14526		}
14527		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14528	    }
14529	}
14530    }
14531    /*
14532    * Shrink attr. uses.
14533    */
14534    if (uses) {
14535	if (uses->nbItems == 0) {
14536	    xmlSchemaItemListFree(uses);
14537	    type->attrUses = NULL;
14538	}
14539	/*
14540	* TODO: We could shrink the size of the array
14541	* to fit the actual number of items.
14542	*/
14543    }
14544    /*
14545    * Compute the complete wildcard.
14546    */
14547    if (WXS_IS_EXTENSION(type)) {
14548	if (baseType->attributeWildcard != NULL) {
14549	    /*
14550	    * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14551	    * the appropriate case among the following:"
14552	    */
14553	    if (type->attributeWildcard != NULL) {
14554		/*
14555		* Union the complete wildcard with the base wildcard.
14556		* SPEC {attribute wildcard}
14557		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14558		* and {annotation} are those of the �complete wildcard�,
14559		* and whose {namespace constraint} is the intensional union
14560		* of the {namespace constraint} of the �complete wildcard�
14561		* and of the �base wildcard�, as defined in Attribute
14562		* Wildcard Union (�3.10.6)."
14563		*/
14564		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14565		    baseType->attributeWildcard) == -1)
14566		    goto exit_failure;
14567	    } else {
14568		/*
14569		* (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14570		* then the �base wildcard�."
14571		*/
14572		type->attributeWildcard = baseType->attributeWildcard;
14573	    }
14574	} else {
14575	    /*
14576	    * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14577	    * �complete wildcard"
14578	    * NOOP
14579	    */
14580	}
14581    } else {
14582	/*
14583	* SPEC {attribute wildcard}
14584	* (3.1) "If the <restriction> alternative is chosen, then the
14585	* �complete wildcard�;"
14586	* NOOP
14587	*/
14588    }
14589
14590    return (0);
14591
14592exit_failure:
14593    return(-1);
14594}
14595
14596/**
14597 * xmlSchemaTypeFinalContains:
14598 * @schema:  the schema
14599 * @type:  the type definition
14600 * @final: the final
14601 *
14602 * Evaluates if a type definition contains the given "final".
14603 * This does take "finalDefault" into account as well.
14604 *
14605 * Returns 1 if the type does containt the given "final",
14606 * 0 otherwise.
14607 */
14608static int
14609xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14610{
14611    if (type == NULL)
14612	return (0);
14613    if (type->flags & final)
14614	return (1);
14615    else
14616	return (0);
14617}
14618
14619/**
14620 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14621 * @type:  the Union Simple Type
14622 *
14623 * Returns a list of member types of @type if existing,
14624 * returns NULL otherwise.
14625 */
14626static xmlSchemaTypeLinkPtr
14627xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14628{
14629    while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14630	if (type->memberTypes != NULL)
14631	    return (type->memberTypes);
14632	else
14633	    type = type->baseType;
14634    }
14635    return (NULL);
14636}
14637
14638/**
14639 * xmlSchemaGetParticleTotalRangeMin:
14640 * @particle: the particle
14641 *
14642 * Schema Component Constraint: Effective Total Range
14643 * (all and sequence) + (choice)
14644 *
14645 * Returns the minimun Effective Total Range.
14646 */
14647static int
14648xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14649{
14650    if ((particle->children == NULL) ||
14651	(particle->minOccurs == 0))
14652	return (0);
14653    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14654	int min = -1, cur;
14655	xmlSchemaParticlePtr part =
14656	    (xmlSchemaParticlePtr) particle->children->children;
14657
14658	if (part == NULL)
14659	    return (0);
14660	while (part != NULL) {
14661	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14662		(part->children->type == XML_SCHEMA_TYPE_ANY))
14663		cur = part->minOccurs;
14664	    else
14665		cur = xmlSchemaGetParticleTotalRangeMin(part);
14666	    if (cur == 0)
14667		return (0);
14668	    if ((min > cur) || (min == -1))
14669		min = cur;
14670	    part = (xmlSchemaParticlePtr) part->next;
14671	}
14672	return (particle->minOccurs * min);
14673    } else {
14674	/* <all> and <sequence> */
14675	int sum = 0;
14676	xmlSchemaParticlePtr part =
14677	    (xmlSchemaParticlePtr) particle->children->children;
14678
14679	if (part == NULL)
14680	    return (0);
14681	do {
14682	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14683		(part->children->type == XML_SCHEMA_TYPE_ANY))
14684		sum += part->minOccurs;
14685	    else
14686		sum += xmlSchemaGetParticleTotalRangeMin(part);
14687	    part = (xmlSchemaParticlePtr) part->next;
14688	} while (part != NULL);
14689	return (particle->minOccurs * sum);
14690    }
14691}
14692
14693#if 0
14694/**
14695 * xmlSchemaGetParticleTotalRangeMax:
14696 * @particle: the particle
14697 *
14698 * Schema Component Constraint: Effective Total Range
14699 * (all and sequence) + (choice)
14700 *
14701 * Returns the maximum Effective Total Range.
14702 */
14703static int
14704xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14705{
14706    if ((particle->children == NULL) ||
14707	(particle->children->children == NULL))
14708	return (0);
14709    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14710	int max = -1, cur;
14711	xmlSchemaParticlePtr part =
14712	    (xmlSchemaParticlePtr) particle->children->children;
14713
14714	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14715	    if (part->children == NULL)
14716		continue;
14717	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14718		(part->children->type == XML_SCHEMA_TYPE_ANY))
14719		cur = part->maxOccurs;
14720	    else
14721		cur = xmlSchemaGetParticleTotalRangeMax(part);
14722	    if (cur == UNBOUNDED)
14723		return (UNBOUNDED);
14724	    if ((max < cur) || (max == -1))
14725		max = cur;
14726	}
14727	/* TODO: Handle overflows? */
14728	return (particle->maxOccurs * max);
14729    } else {
14730	/* <all> and <sequence> */
14731	int sum = 0, cur;
14732	xmlSchemaParticlePtr part =
14733	    (xmlSchemaParticlePtr) particle->children->children;
14734
14735	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14736	    if (part->children == NULL)
14737		continue;
14738	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14739		(part->children->type == XML_SCHEMA_TYPE_ANY))
14740		cur = part->maxOccurs;
14741	    else
14742		cur = xmlSchemaGetParticleTotalRangeMax(part);
14743	    if (cur == UNBOUNDED)
14744		return (UNBOUNDED);
14745	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14746		return (UNBOUNDED);
14747	    sum += cur;
14748	}
14749	/* TODO: Handle overflows? */
14750	return (particle->maxOccurs * sum);
14751    }
14752}
14753#endif
14754
14755/**
14756 * xmlSchemaIsParticleEmptiable:
14757 * @particle: the particle
14758 *
14759 * Schema Component Constraint: Particle Emptiable
14760 * Checks whether the given particle is emptiable.
14761 *
14762 * Returns 1 if emptiable, 0 otherwise.
14763 */
14764static int
14765xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14766{
14767    /*
14768    * SPEC (1) "Its {min occurs} is 0."
14769    */
14770    if ((particle == NULL) || (particle->minOccurs == 0) ||
14771	(particle->children == NULL))
14772	return (1);
14773    /*
14774    * SPEC (2) "Its {term} is a group and the minimum part of the
14775    * effective total range of that group, [...] is 0."
14776    */
14777    if (WXS_IS_MODEL_GROUP(particle->children)) {
14778	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14779	    return (1);
14780    }
14781    return (0);
14782}
14783
14784/**
14785 * xmlSchemaCheckCOSSTDerivedOK:
14786 * @actxt: a context
14787 * @type:  the derived simple type definition
14788 * @baseType:  the base type definition
14789 * @subset: the subset of ('restriction', ect.)
14790 *
14791 * Schema Component Constraint:
14792 * Type Derivation OK (Simple) (cos-st-derived-OK)
14793 *
14794 * Checks wheter @type can be validly
14795 * derived from @baseType.
14796 *
14797 * Returns 0 on success, an positive error code otherwise.
14798 */
14799static int
14800xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14801			     xmlSchemaTypePtr type,
14802			     xmlSchemaTypePtr baseType,
14803			     int subset)
14804{
14805    /*
14806    * 1 They are the same type definition.
14807    * TODO: The identy check might have to be more complex than this.
14808    */
14809    if (type == baseType)
14810	return (0);
14811    /*
14812    * 2.1 restriction is not in the subset, or in the {final}
14813    * of its own {base type definition};
14814    *
14815    * NOTE that this will be used also via "xsi:type".
14816    *
14817    * TODO: Revise this, it looks strange. How can the "type"
14818    * not be fixed or *in* fixing?
14819    */
14820    if (WXS_IS_TYPE_NOT_FIXED(type))
14821	if (xmlSchemaTypeFixup(type, actxt) == -1)
14822	    return(-1);
14823    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14824	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14825	    return(-1);
14826    if ((subset & SUBSET_RESTRICTION) ||
14827	(xmlSchemaTypeFinalContains(type->baseType,
14828	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14829	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14830    }
14831    /* 2.2 */
14832    if (type->baseType == baseType) {
14833	/*
14834	* 2.2.1 D's �base type definition� is B.
14835	*/
14836	return (0);
14837    }
14838    /*
14839    * 2.2.2 D's �base type definition� is not the �ur-type definition�
14840    * and is validly derived from B given the subset, as defined by this
14841    * constraint.
14842    */
14843    if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14844	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14845	    baseType, subset) == 0)) {
14846	return (0);
14847    }
14848    /*
14849    * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14850    * definition�.
14851    */
14852    if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14853	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14854	return (0);
14855    }
14856    /*
14857    * 2.2.4 B's {variety} is union and D is validly derived from a type
14858    * definition in B's {member type definitions} given the subset, as
14859    * defined by this constraint.
14860    *
14861    * NOTE: This seems not to involve built-in types, since there is no
14862    * built-in Union Simple Type.
14863    */
14864    if (WXS_IS_UNION(baseType)) {
14865	xmlSchemaTypeLinkPtr cur;
14866
14867	cur = baseType->memberTypes;
14868	while (cur != NULL) {
14869	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14870		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14871		    return(-1);
14872	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14873		    type, cur->type, subset) == 0)
14874	    {
14875		/*
14876		* It just has to be validly derived from at least one
14877		* member-type.
14878		*/
14879		return (0);
14880	    }
14881	    cur = cur->next;
14882	}
14883    }
14884    return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14885}
14886
14887/**
14888 * xmlSchemaCheckTypeDefCircularInternal:
14889 * @pctxt:  the schema parser context
14890 * @ctxtType:  the type definition
14891 * @ancestor: an ancestor of @ctxtType
14892 *
14893 * Checks st-props-correct (2) + ct-props-correct (3).
14894 * Circular type definitions are not allowed.
14895 *
14896 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14897 * circular, 0 otherwise.
14898 */
14899static int
14900xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14901			   xmlSchemaTypePtr ctxtType,
14902			   xmlSchemaTypePtr ancestor)
14903{
14904    int ret;
14905
14906    if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14907	return (0);
14908
14909    if (ctxtType == ancestor) {
14910	xmlSchemaPCustomErr(pctxt,
14911	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14912	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14913	    "The definition is circular", NULL);
14914	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14915    }
14916    if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14917	/*
14918	* Avoid inifinite recursion on circular types not yet checked.
14919	*/
14920	return (0);
14921    }
14922    ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14923    ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14924	ancestor->baseType);
14925    ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14926    return (ret);
14927}
14928
14929/**
14930 * xmlSchemaCheckTypeDefCircular:
14931 * @item:  the complex/simple type definition
14932 * @ctxt:  the parser context
14933 * @name:  the name
14934 *
14935 * Checks for circular type definitions.
14936 */
14937static void
14938xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14939			      xmlSchemaParserCtxtPtr ctxt)
14940{
14941    if ((item == NULL) ||
14942	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14943	(item->baseType == NULL))
14944	return;
14945    xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14946	item->baseType);
14947}
14948
14949/*
14950* Simple Type Definition Representation OK (src-simple-type) 4
14951*
14952* "4 Circular union type definition is disallowed. That is, if the
14953* <union> alternative is chosen, there must not be any entries in the
14954* memberTypes [attribute] at any depth which resolve to the component
14955* corresponding to the <simpleType>."
14956*
14957* Note that this should work on the *representation* of a component,
14958* thus assumes any union types in the member types not being yet
14959* substituted. At this stage we need the variety of the types
14960* to be already computed.
14961*/
14962static int
14963xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14964					xmlSchemaTypePtr ctxType,
14965					xmlSchemaTypeLinkPtr members)
14966{
14967    xmlSchemaTypeLinkPtr member;
14968    xmlSchemaTypePtr memberType;
14969
14970    member = members;
14971    while (member != NULL) {
14972	memberType = member->type;
14973	while ((memberType != NULL) &&
14974	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14975	    if (memberType == ctxType) {
14976		xmlSchemaPCustomErr(pctxt,
14977		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14978		    WXS_BASIC_CAST ctxType, NULL,
14979		    "The union type definition is circular", NULL);
14980		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14981	    }
14982	    if ((WXS_IS_UNION(memberType)) &&
14983		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14984	    {
14985		int res;
14986		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14987		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14988		    ctxType,
14989		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14990		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14991		if (res != 0)
14992		    return(res);
14993	    }
14994	    memberType = memberType->baseType;
14995	}
14996	member = member->next;
14997    }
14998    return(0);
14999}
15000
15001static int
15002xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15003				   xmlSchemaTypePtr type)
15004{
15005    if (! WXS_IS_UNION(type))
15006	return(0);
15007    return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15008	type->memberTypes));
15009}
15010
15011/**
15012 * xmlSchemaResolveTypeReferences:
15013 * @item:  the complex/simple type definition
15014 * @ctxt:  the parser context
15015 * @name:  the name
15016 *
15017 * Resolvese type definition references
15018 */
15019static void
15020xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15021			 xmlSchemaParserCtxtPtr ctxt)
15022{
15023    if (typeDef == NULL)
15024	return;
15025
15026    /*
15027    * Resolve the base type.
15028    */
15029    if (typeDef->baseType == NULL) {
15030	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15031	    typeDef->base, typeDef->baseNs);
15032	if (typeDef->baseType == NULL) {
15033	    xmlSchemaPResCompAttrErr(ctxt,
15034		XML_SCHEMAP_SRC_RESOLVE,
15035		WXS_BASIC_CAST typeDef, typeDef->node,
15036		"base", typeDef->base, typeDef->baseNs,
15037		XML_SCHEMA_TYPE_SIMPLE, NULL);
15038	    return;
15039	}
15040    }
15041    if (WXS_IS_SIMPLE(typeDef)) {
15042	if (WXS_IS_UNION(typeDef)) {
15043	    /*
15044	    * Resolve the memberTypes.
15045	    */
15046	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15047	    return;
15048	} else if (WXS_IS_LIST(typeDef)) {
15049	    /*
15050	    * Resolve the itemType.
15051	    */
15052	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15053
15054		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15055		    typeDef->base, typeDef->baseNs);
15056
15057		if ((typeDef->subtypes == NULL) ||
15058		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15059		{
15060		    typeDef->subtypes = NULL;
15061		    xmlSchemaPResCompAttrErr(ctxt,
15062			XML_SCHEMAP_SRC_RESOLVE,
15063			WXS_BASIC_CAST typeDef, typeDef->node,
15064			"itemType", typeDef->base, typeDef->baseNs,
15065			XML_SCHEMA_TYPE_SIMPLE, NULL);
15066		}
15067	    }
15068	    return;
15069	}
15070    }
15071    /*
15072    * The ball of letters below means, that if we have a particle
15073    * which has a QName-helper component as its {term}, we want
15074    * to resolve it...
15075    */
15076    else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15077	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15078	    XML_SCHEMA_TYPE_PARTICLE) &&
15079	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15080	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15081	    XML_SCHEMA_EXTRA_QNAMEREF))
15082    {
15083	xmlSchemaQNameRefPtr ref =
15084	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15085	xmlSchemaModelGroupDefPtr groupDef;
15086
15087	/*
15088	* URGENT TODO: Test this.
15089	*/
15090	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15091	/*
15092	* Resolve the MG definition reference.
15093	*/
15094	groupDef =
15095	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15096		ref->itemType, ref->name, ref->targetNamespace);
15097	if (groupDef == NULL) {
15098	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15099		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15100		"ref", ref->name, ref->targetNamespace, ref->itemType,
15101		NULL);
15102	    /* Remove the particle. */
15103	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15104	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15105	    /* Remove the particle. */
15106	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15107	else {
15108	    /*
15109	    * Assign the MG definition's {model group} to the
15110	    * particle's {term}.
15111	    */
15112	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15113
15114	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15115		/*
15116		* SPEC cos-all-limited (1.2)
15117		* "1.2 the {term} property of a particle with
15118		* {max occurs}=1 which is part of a pair which constitutes
15119		* the {content type} of a complex type definition."
15120		*/
15121		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15122		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15123			/* TODO: error code */
15124			XML_SCHEMAP_COS_ALL_LIMITED,
15125			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15126			"The particle's {max occurs} must be 1, since the "
15127			"reference resolves to an 'all' model group",
15128			NULL, NULL);
15129		}
15130	    }
15131	}
15132    }
15133}
15134
15135
15136
15137/**
15138 * xmlSchemaCheckSTPropsCorrect:
15139 * @ctxt:  the schema parser context
15140 * @type:  the simple type definition
15141 *
15142 * Checks st-props-correct.
15143 *
15144 * Returns 0 if the properties are correct,
15145 * if not, a positive error code and -1 on internal
15146 * errors.
15147 */
15148static int
15149xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15150			     xmlSchemaTypePtr type)
15151{
15152    xmlSchemaTypePtr baseType = type->baseType;
15153    xmlChar *str = NULL;
15154
15155    /* STATE: error funcs converted. */
15156    /*
15157    * Schema Component Constraint: Simple Type Definition Properties Correct
15158    *
15159    * NOTE: This is somehow redundant, since we actually built a simple type
15160    * to have all the needed information; this acts as an self test.
15161    */
15162    /* Base type: If the datatype has been �derived� by �restriction�
15163    * then the Simple Type Definition component from which it is �derived�,
15164    * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15165    */
15166    if (baseType == NULL) {
15167	/*
15168	* TODO: Think about: "modulo the impact of Missing
15169	* Sub-components (�5.3)."
15170	*/
15171	xmlSchemaPCustomErr(ctxt,
15172	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15173	    WXS_BASIC_CAST type, NULL,
15174	    "No base type existent", NULL);
15175	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15176
15177    }
15178    if (! WXS_IS_SIMPLE(baseType)) {
15179	xmlSchemaPCustomErr(ctxt,
15180	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15181	    WXS_BASIC_CAST type, NULL,
15182	    "The base type '%s' is not a simple type",
15183	    xmlSchemaGetComponentQName(&str, baseType));
15184	FREE_AND_NULL(str)
15185	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15186    }
15187    if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15188	(WXS_IS_RESTRICTION(type) == 0) &&
15189	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15190         (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15191	xmlSchemaPCustomErr(ctxt,
15192	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15193	    WXS_BASIC_CAST type, NULL,
15194	    "A type, derived by list or union, must have "
15195	    "the simple ur-type definition as base type, not '%s'",
15196	    xmlSchemaGetComponentQName(&str, baseType));
15197	FREE_AND_NULL(str)
15198	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15199    }
15200    /*
15201    * Variety: One of {atomic, list, union}.
15202    */
15203    if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15204	(! WXS_IS_LIST(type))) {
15205	xmlSchemaPCustomErr(ctxt,
15206	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15207	    WXS_BASIC_CAST type, NULL,
15208	    "The variety is absent", NULL);
15209	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15210    }
15211    /* TODO: Finish this. Hmm, is this finished? */
15212
15213    /*
15214    * 3 The {final} of the {base type definition} must not contain restriction.
15215    */
15216    if (xmlSchemaTypeFinalContains(baseType,
15217	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15218	xmlSchemaPCustomErr(ctxt,
15219	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15220	    WXS_BASIC_CAST type, NULL,
15221	    "The 'final' of its base type '%s' must not contain "
15222	    "'restriction'",
15223	    xmlSchemaGetComponentQName(&str, baseType));
15224	FREE_AND_NULL(str)
15225	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15226    }
15227
15228    /*
15229    * 2 All simple type definitions must be derived ultimately from the �simple
15230    * ur-type definition (so� circular definitions are disallowed). That is, it
15231    * must be possible to reach a built-in primitive datatype or the �simple
15232    * ur-type definition� by repeatedly following the {base type definition}.
15233    *
15234    * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15235    */
15236    return (0);
15237}
15238
15239/**
15240 * xmlSchemaCheckCOSSTRestricts:
15241 * @ctxt:  the schema parser context
15242 * @type:  the simple type definition
15243 *
15244 * Schema Component Constraint:
15245 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15246
15247 * Checks if the given @type (simpleType) is derived validly by restriction.
15248 * STATUS:
15249 *
15250 * Returns -1 on internal errors, 0 if the type is validly derived,
15251 * a positive error code otherwise.
15252 */
15253static int
15254xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15255			     xmlSchemaTypePtr type)
15256{
15257    xmlChar *str = NULL;
15258
15259    if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15260	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15261	    "given type is not a user-derived simpleType");
15262	return (-1);
15263    }
15264
15265    if (WXS_IS_ATOMIC(type)) {
15266	xmlSchemaTypePtr primitive;
15267	/*
15268	* 1.1 The {base type definition} must be an atomic simple
15269	* type definition or a built-in primitive datatype.
15270	*/
15271	if (! WXS_IS_ATOMIC(type->baseType)) {
15272	    xmlSchemaPCustomErr(pctxt,
15273		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15274		WXS_BASIC_CAST type, NULL,
15275		"The base type '%s' is not an atomic simple type",
15276		xmlSchemaGetComponentQName(&str, type->baseType));
15277	    FREE_AND_NULL(str)
15278	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15279	}
15280	/* 1.2 The {final} of the {base type definition} must not contain
15281	* restriction.
15282	*/
15283	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15284	if (xmlSchemaTypeFinalContains(type->baseType,
15285	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15286	    xmlSchemaPCustomErr(pctxt,
15287		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15288		WXS_BASIC_CAST type, NULL,
15289		"The final of its base type '%s' must not contain 'restriction'",
15290		xmlSchemaGetComponentQName(&str, type->baseType));
15291	    FREE_AND_NULL(str)
15292	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15293	}
15294
15295	/*
15296	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15297	* type definition}, as specified in the appropriate subsection of 3.2
15298	* Primitive datatypes.
15299	*/
15300	if (type->facets != NULL) {
15301	    xmlSchemaFacetPtr facet;
15302	    int ok = 1;
15303
15304	    primitive = xmlSchemaGetPrimitiveType(type);
15305	    if (primitive == NULL) {
15306		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15307		    "failed to get primitive type");
15308		return (-1);
15309	    }
15310	    facet = type->facets;
15311	    do {
15312		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15313		    ok = 0;
15314		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15315			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15316			type, primitive, facet);
15317		}
15318		facet = facet->next;
15319	    } while (facet != NULL);
15320	    if (ok == 0)
15321		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15322	}
15323	/*
15324	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15325	* of the {base type definition} (call this BF),then the DF's {value}
15326	* must be a valid restriction of BF's {value} as defined in
15327	* [XML Schemas: Datatypes]."
15328	*
15329	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15330	* xmlSchemaDeriveAndValidateFacets()
15331	*/
15332    } else if (WXS_IS_LIST(type)) {
15333	xmlSchemaTypePtr itemType = NULL;
15334
15335	itemType = type->subtypes;
15336	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15337	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15338		"failed to evaluate the item type");
15339	    return (-1);
15340	}
15341	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15342	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15343	/*
15344	* 2.1 The {item type definition} must have a {variety} of atomic or
15345	* union (in which case all the {member type definitions}
15346	* must be atomic).
15347	*/
15348	if ((! WXS_IS_ATOMIC(itemType)) &&
15349	    (! WXS_IS_UNION(itemType))) {
15350	    xmlSchemaPCustomErr(pctxt,
15351		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15352		WXS_BASIC_CAST type, NULL,
15353		"The item type '%s' does not have a variety of atomic or union",
15354		xmlSchemaGetComponentQName(&str, itemType));
15355	    FREE_AND_NULL(str)
15356	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15357	} else if (WXS_IS_UNION(itemType)) {
15358	    xmlSchemaTypeLinkPtr member;
15359
15360	    member = itemType->memberTypes;
15361	    while (member != NULL) {
15362		if (! WXS_IS_ATOMIC(member->type)) {
15363		    xmlSchemaPCustomErr(pctxt,
15364			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15365			WXS_BASIC_CAST type, NULL,
15366			"The item type is a union type, but the "
15367			"member type '%s' of this item type is not atomic",
15368			xmlSchemaGetComponentQName(&str, member->type));
15369		    FREE_AND_NULL(str)
15370		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15371		}
15372		member = member->next;
15373	    }
15374	}
15375
15376	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15377	    xmlSchemaFacetPtr facet;
15378	    /*
15379	    * This is the case if we have: <simpleType><list ..
15380	    */
15381	    /*
15382	    * 2.3.1
15383	    * 2.3.1.1 The {final} of the {item type definition} must not
15384	    * contain list.
15385	    */
15386	    if (xmlSchemaTypeFinalContains(itemType,
15387		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15388		xmlSchemaPCustomErr(pctxt,
15389		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15390		    WXS_BASIC_CAST type, NULL,
15391		    "The final of its item type '%s' must not contain 'list'",
15392		    xmlSchemaGetComponentQName(&str, itemType));
15393		FREE_AND_NULL(str)
15394		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15395	    }
15396	    /*
15397	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15398	    * facet component.
15399	    * OPTIMIZE TODO: the S4S already disallows any facet
15400	    * to be specified.
15401	    */
15402	    if (type->facets != NULL) {
15403		facet = type->facets;
15404		do {
15405		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15406			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15407			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15408			    type, facet);
15409			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15410		    }
15411		    facet = facet->next;
15412		} while (facet != NULL);
15413	    }
15414	    /*
15415	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15416	    * A �list� datatype can be �derived� from an �atomic� datatype
15417	    * whose �lexical space� allows space (such as string or anyURI)or
15418	    * a �union� datatype any of whose {member type definitions}'s
15419	    * �lexical space� allows space.
15420	    */
15421	} else {
15422	    /*
15423	    * This is the case if we have: <simpleType><restriction ...
15424	    * I.e. the variety of "list" is inherited.
15425	    */
15426	    /*
15427	    * 2.3.2
15428	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15429	    */
15430	    if (! WXS_IS_LIST(type->baseType)) {
15431		xmlSchemaPCustomErr(pctxt,
15432		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15433		    WXS_BASIC_CAST type, NULL,
15434		    "The base type '%s' must be a list type",
15435		    xmlSchemaGetComponentQName(&str, type->baseType));
15436		FREE_AND_NULL(str)
15437		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15438	    }
15439	    /*
15440	    * 2.3.2.2 The {final} of the {base type definition} must not
15441	    * contain restriction.
15442	    */
15443	    if (xmlSchemaTypeFinalContains(type->baseType,
15444		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15445		xmlSchemaPCustomErr(pctxt,
15446		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15447		    WXS_BASIC_CAST type, NULL,
15448		    "The 'final' of the base type '%s' must not contain 'restriction'",
15449		    xmlSchemaGetComponentQName(&str, type->baseType));
15450		FREE_AND_NULL(str)
15451		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15452	    }
15453	    /*
15454	    * 2.3.2.3 The {item type definition} must be validly derived
15455	    * from the {base type definition}'s {item type definition} given
15456	    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15457	    */
15458	    {
15459		xmlSchemaTypePtr baseItemType;
15460
15461		baseItemType = type->baseType->subtypes;
15462		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15463		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15464			"failed to eval the item type of a base type");
15465		    return (-1);
15466		}
15467		if ((itemType != baseItemType) &&
15468		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15469			baseItemType, 0) != 0)) {
15470		    xmlChar *strBIT = NULL, *strBT = NULL;
15471		    xmlSchemaPCustomErrExt(pctxt,
15472			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15473			WXS_BASIC_CAST type, NULL,
15474			"The item type '%s' is not validly derived from "
15475			"the item type '%s' of the base type '%s'",
15476			xmlSchemaGetComponentQName(&str, itemType),
15477			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15478			xmlSchemaGetComponentQName(&strBT, type->baseType));
15479
15480		    FREE_AND_NULL(str)
15481		    FREE_AND_NULL(strBIT)
15482		    FREE_AND_NULL(strBT)
15483		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15484		}
15485	    }
15486
15487	    if (type->facets != NULL) {
15488		xmlSchemaFacetPtr facet;
15489		int ok = 1;
15490		/*
15491		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15492		* and enumeration facet components are allowed among the {facets}.
15493		*/
15494		facet = type->facets;
15495		do {
15496		    switch (facet->type) {
15497			case XML_SCHEMA_FACET_LENGTH:
15498			case XML_SCHEMA_FACET_MINLENGTH:
15499			case XML_SCHEMA_FACET_MAXLENGTH:
15500			case XML_SCHEMA_FACET_WHITESPACE:
15501			    /*
15502			    * TODO: 2.5.1.2 List datatypes
15503			    * The value of �whiteSpace� is fixed to the value collapse.
15504			    */
15505			case XML_SCHEMA_FACET_PATTERN:
15506			case XML_SCHEMA_FACET_ENUMERATION:
15507			    break;
15508			default: {
15509			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15510				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15511				type, facet);
15512			    /*
15513			    * We could return, but it's nicer to report all
15514			    * invalid facets.
15515			    */
15516			    ok = 0;
15517			}
15518		    }
15519		    facet = facet->next;
15520		} while (facet != NULL);
15521		if (ok == 0)
15522		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15523		/*
15524		* SPEC (2.3.2.5) (same as 1.3.2)
15525		*
15526		* NOTE (2.3.2.5) This is currently done in
15527		* xmlSchemaDeriveAndValidateFacets()
15528		*/
15529	    }
15530	}
15531    } else if (WXS_IS_UNION(type)) {
15532	/*
15533	* 3.1 The {member type definitions} must all have {variety} of
15534	* atomic or list.
15535	*/
15536	xmlSchemaTypeLinkPtr member;
15537
15538	member = type->memberTypes;
15539	while (member != NULL) {
15540	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15541		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15542
15543	    if ((! WXS_IS_ATOMIC(member->type)) &&
15544		(! WXS_IS_LIST(member->type))) {
15545		xmlSchemaPCustomErr(pctxt,
15546		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15547		    WXS_BASIC_CAST type, NULL,
15548		    "The member type '%s' is neither an atomic, nor a list type",
15549		    xmlSchemaGetComponentQName(&str, member->type));
15550		FREE_AND_NULL(str)
15551		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15552	    }
15553	    member = member->next;
15554	}
15555	/*
15556	* 3.3.1 If the {base type definition} is the �simple ur-type
15557	* definition�
15558	*/
15559	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15560	    /*
15561	    * 3.3.1.1 All of the {member type definitions} must have a
15562	    * {final} which does not contain union.
15563	    */
15564	    member = type->memberTypes;
15565	    while (member != NULL) {
15566		if (xmlSchemaTypeFinalContains(member->type,
15567		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15568		    xmlSchemaPCustomErr(pctxt,
15569			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15570			WXS_BASIC_CAST type, NULL,
15571			"The 'final' of member type '%s' contains 'union'",
15572			xmlSchemaGetComponentQName(&str, member->type));
15573		    FREE_AND_NULL(str)
15574		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15575		}
15576		member = member->next;
15577	    }
15578	    /*
15579	    * 3.3.1.2 The {facets} must be empty.
15580	    */
15581	    if (type->facetSet != NULL) {
15582		xmlSchemaPCustomErr(pctxt,
15583		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15584		    WXS_BASIC_CAST type, NULL,
15585		    "No facets allowed", NULL);
15586		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15587	    }
15588	} else {
15589	    /*
15590	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15591	    * I.e. the variety of "list" is inherited.
15592	    */
15593	    if (! WXS_IS_UNION(type->baseType)) {
15594		xmlSchemaPCustomErr(pctxt,
15595		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15596		    WXS_BASIC_CAST type, NULL,
15597		    "The base type '%s' is not a union type",
15598		    xmlSchemaGetComponentQName(&str, type->baseType));
15599		FREE_AND_NULL(str)
15600		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15601	    }
15602	    /*
15603	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15604	    */
15605	    if (xmlSchemaTypeFinalContains(type->baseType,
15606		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15607		xmlSchemaPCustomErr(pctxt,
15608		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15609		    WXS_BASIC_CAST type, NULL,
15610		    "The 'final' of its base type '%s' must not contain 'restriction'",
15611		    xmlSchemaGetComponentQName(&str, type->baseType));
15612		FREE_AND_NULL(str)
15613		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15614	    }
15615	    /*
15616	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15617	    * derived from the corresponding type definitions in the {base
15618	    * type definition}'s {member type definitions} given the empty set,
15619	    * as defined in Type Derivation OK (Simple) (�3.14.6).
15620	    */
15621	    {
15622		xmlSchemaTypeLinkPtr baseMember;
15623
15624		/*
15625		* OPTIMIZE: if the type is restricting, it has no local defined
15626		* member types and inherits the member types of the base type;
15627		* thus a check for equality can be skipped.
15628		*/
15629		/*
15630		* Even worse: I cannot see a scenario where a restricting
15631		* union simple type can have other member types as the member
15632		* types of it's base type. This check seems not necessary with
15633		* respect to the derivation process in libxml2.
15634		* But necessary if constructing types with an API.
15635		*/
15636		if (type->memberTypes != NULL) {
15637		    member = type->memberTypes;
15638		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15639		    if ((member == NULL) && (baseMember != NULL)) {
15640			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15641			    "different number of member types in base");
15642		    }
15643		    while (member != NULL) {
15644			if (baseMember == NULL) {
15645			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15646			    "different number of member types in base");
15647			} else if ((member->type != baseMember->type) &&
15648			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15649				member->type, baseMember->type, 0) != 0)) {
15650			    xmlChar *strBMT = NULL, *strBT = NULL;
15651
15652			    xmlSchemaPCustomErrExt(pctxt,
15653				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15654				WXS_BASIC_CAST type, NULL,
15655				"The member type %s is not validly "
15656				"derived from its corresponding member "
15657				"type %s of the base type %s",
15658				xmlSchemaGetComponentQName(&str, member->type),
15659				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15660				xmlSchemaGetComponentQName(&strBT, type->baseType));
15661			    FREE_AND_NULL(str)
15662			    FREE_AND_NULL(strBMT)
15663			    FREE_AND_NULL(strBT)
15664			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15665			}
15666			member = member->next;
15667                        if (baseMember != NULL)
15668                            baseMember = baseMember->next;
15669		    }
15670		}
15671	    }
15672	    /*
15673	    * 3.3.2.4 Only pattern and enumeration facet components are
15674	    * allowed among the {facets}.
15675	    */
15676	    if (type->facets != NULL) {
15677		xmlSchemaFacetPtr facet;
15678		int ok = 1;
15679
15680		facet = type->facets;
15681		do {
15682		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15683			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15684			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15685				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15686				type, facet);
15687			ok = 0;
15688		    }
15689		    facet = facet->next;
15690		} while (facet != NULL);
15691		if (ok == 0)
15692		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15693
15694	    }
15695	    /*
15696	    * SPEC (3.3.2.5) (same as 1.3.2)
15697	    *
15698	    * NOTE (3.3.2.5) This is currently done in
15699	    * xmlSchemaDeriveAndValidateFacets()
15700	    */
15701	}
15702    }
15703
15704    return (0);
15705}
15706
15707/**
15708 * xmlSchemaCheckSRCSimpleType:
15709 * @ctxt:  the schema parser context
15710 * @type:  the simple type definition
15711 *
15712 * Checks crc-simple-type constraints.
15713 *
15714 * Returns 0 if the constraints are satisfied,
15715 * if not a positive error code and -1 on internal
15716 * errors.
15717 */
15718#if 0
15719static int
15720xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15721			    xmlSchemaTypePtr type)
15722{
15723    /*
15724    * src-simple-type.1 The corresponding simple type definition, if any,
15725    * must satisfy the conditions set out in Constraints on Simple Type
15726    * Definition Schema Components (�3.14.6).
15727    */
15728    if (WXS_IS_RESTRICTION(type)) {
15729	/*
15730	* src-simple-type.2 "If the <restriction> alternative is chosen,
15731	* either it must have a base [attribute] or a <simpleType> among its
15732	* [children], but not both."
15733	* NOTE: This is checked in the parse function of <restriction>.
15734	*/
15735	/*
15736	*
15737	*/
15738    } else if (WXS_IS_LIST(type)) {
15739	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15740	* an itemType [attribute] or a <simpleType> among its [children],
15741	* but not both."
15742	*
15743	* NOTE: This is checked in the parse function of <list>.
15744	*/
15745    } else if (WXS_IS_UNION(type)) {
15746	/*
15747	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15748	*/
15749    }
15750    return (0);
15751}
15752#endif
15753
15754static int
15755xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15756{
15757   if (ctxt->vctxt == NULL) {
15758	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15759	if (ctxt->vctxt == NULL) {
15760	    xmlSchemaPErr(ctxt, NULL,
15761		XML_SCHEMAP_INTERNAL,
15762		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15763		"failed to create a temp. validation context.\n",
15764		NULL, NULL);
15765	    return (-1);
15766	}
15767	/* TODO: Pass user data. */
15768	xmlSchemaSetValidErrors(ctxt->vctxt,
15769	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15770	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15771	    ctxt->serror, ctxt->errCtxt);
15772    }
15773    return (0);
15774}
15775
15776static int
15777xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15778			     xmlNodePtr node,
15779			     xmlSchemaTypePtr type,
15780			     const xmlChar *value,
15781			     xmlSchemaValPtr *retVal,
15782			     int fireErrors,
15783			     int normalize,
15784			     int isNormalized);
15785
15786/**
15787 * xmlSchemaParseCheckCOSValidDefault:
15788 * @pctxt:  the schema parser context
15789 * @type:  the simple type definition
15790 * @value: the default value
15791 * @node: an optional node (the holder of the value)
15792 *
15793 * Schema Component Constraint: Element Default Valid (Immediate)
15794 * (cos-valid-default)
15795 * This will be used by the parser only. For the validator there's
15796 * an other version.
15797 *
15798 * Returns 0 if the constraints are satisfied,
15799 * if not, a positive error code and -1 on internal
15800 * errors.
15801 */
15802static int
15803xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15804				   xmlNodePtr node,
15805				   xmlSchemaTypePtr type,
15806				   const xmlChar *value,
15807				   xmlSchemaValPtr *val)
15808{
15809    int ret = 0;
15810
15811    /*
15812    * cos-valid-default:
15813    * Schema Component Constraint: Element Default Valid (Immediate)
15814    * For a string to be a valid default with respect to a type
15815    * definition the appropriate case among the following must be true:
15816    */
15817    if WXS_IS_COMPLEX(type) {
15818	/*
15819	* Complex type.
15820	*
15821	* SPEC (2.1) "its {content type} must be a simple type definition
15822	* or mixed."
15823	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15824	* type}'s particle must be �emptiable� as defined by
15825	* Particle Emptiable (�3.9.6)."
15826	*/
15827	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15828	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15829	    /* NOTE that this covers (2.2.2) as well. */
15830	    xmlSchemaPCustomErr(pctxt,
15831		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15832		WXS_BASIC_CAST type, type->node,
15833		"For a string to be a valid default, the type definition "
15834		"must be a simple type or a complex type with mixed content "
15835		"and a particle emptiable", NULL);
15836	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15837	}
15838    }
15839    /*
15840    * 1 If the type definition is a simple type definition, then the string
15841    * must be �valid� with respect to that definition as defined by String
15842    * Valid (�3.14.4).
15843    *
15844    * AND
15845    *
15846    * 2.2.1 If the {content type} is a simple type definition, then the
15847    * string must be �valid� with respect to that simple type definition
15848    * as defined by String Valid (�3.14.4).
15849    */
15850    if (WXS_IS_SIMPLE(type))
15851	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15852	    type, value, val, 1, 1, 0);
15853    else if (WXS_HAS_SIMPLE_CONTENT(type))
15854	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15855	    type->contentTypeDef, value, val, 1, 1, 0);
15856    else
15857	return (ret);
15858
15859    if (ret < 0) {
15860	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15861	    "calling xmlSchemaVCheckCVCSimpleType()");
15862    }
15863
15864    return (ret);
15865}
15866
15867/**
15868 * xmlSchemaCheckCTPropsCorrect:
15869 * @ctxt:  the schema parser context
15870 * @type:  the complex type definition
15871 *
15872 *.(4.6) Constraints on Complex Type Definition Schema Components
15873 * Schema Component Constraint:
15874 * Complex Type Definition Properties Correct (ct-props-correct)
15875 * STATUS: (seems) complete
15876 *
15877 * Returns 0 if the constraints are satisfied, a positive
15878 * error code if not and -1 if an internal error occured.
15879 */
15880static int
15881xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15882			     xmlSchemaTypePtr type)
15883{
15884    /*
15885    * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15886    *
15887    * SPEC (1) "The values of the properties of a complex type definition must
15888    * be as described in the property tableau in The Complex Type Definition
15889    * Schema Component (�3.4.1), modulo the impact of Missing
15890    * Sub-components (�5.3)."
15891    */
15892    if ((type->baseType != NULL) &&
15893	(WXS_IS_SIMPLE(type->baseType)) &&
15894	(WXS_IS_EXTENSION(type) == 0)) {
15895	/*
15896	* SPEC (2) "If the {base type definition} is a simple type definition,
15897	* the {derivation method} must be extension."
15898	*/
15899	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15900	    XML_SCHEMAP_SRC_CT_1,
15901	    NULL, WXS_BASIC_CAST type,
15902	    "If the base type is a simple type, the derivation method must be "
15903	    "'extension'", NULL, NULL);
15904	return (XML_SCHEMAP_SRC_CT_1);
15905    }
15906    /*
15907    * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15908    * definition�. That is, it must be possible to reach the �ur-type
15909    * definition by repeatedly following the {base type definition}."
15910    *
15911    * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15912    */
15913    /*
15914    * NOTE that (4) and (5) need the following:
15915    *   - attribute uses need to be already inherited (apply attr. prohibitions)
15916    *   - attribute group references need to be expanded already
15917    *   - simple types need to be typefixed already
15918    */
15919    if (type->attrUses &&
15920	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15921    {
15922	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15923	xmlSchemaAttributeUsePtr use, tmp;
15924	int i, j, hasId = 0;
15925
15926	for (i = uses->nbItems -1; i >= 0; i--) {
15927	    use = uses->items[i];
15928
15929	    /*
15930	    * SPEC ct-props-correct
15931	    * (4) "Two distinct attribute declarations in the
15932	    * {attribute uses} must not have identical {name}s and
15933	    * {target namespace}s."
15934	    */
15935	    if (i > 0) {
15936		for (j = i -1; j >= 0; j--) {
15937		    tmp = uses->items[j];
15938		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15939			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15940			(WXS_ATTRUSE_DECL_TNS(use) ==
15941			WXS_ATTRUSE_DECL_TNS(tmp)))
15942		    {
15943			xmlChar *str = NULL;
15944
15945			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15946			    XML_SCHEMAP_AG_PROPS_CORRECT,
15947			    NULL, WXS_BASIC_CAST type,
15948			    "Duplicate %s",
15949			    xmlSchemaGetComponentDesignation(&str, use),
15950			    NULL);
15951			FREE_AND_NULL(str);
15952			/*
15953			* Remove the duplicate.
15954			*/
15955			if (xmlSchemaItemListRemove(uses, i) == -1)
15956			    goto exit_failure;
15957			goto next_use;
15958		    }
15959		}
15960	    }
15961	    /*
15962	    * SPEC ct-props-correct
15963	    * (5) "Two distinct attribute declarations in the
15964	    * {attribute uses} must not have {type definition}s which
15965	    * are or are derived from ID."
15966	    */
15967	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15968		if (xmlSchemaIsDerivedFromBuiltInType(
15969		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15970		{
15971		    if (hasId) {
15972			xmlChar *str = NULL;
15973
15974			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15975			    XML_SCHEMAP_AG_PROPS_CORRECT,
15976			    NULL, WXS_BASIC_CAST type,
15977			    "There must not exist more than one attribute "
15978			    "declaration of type 'xs:ID' "
15979			    "(or derived from 'xs:ID'). The %s violates this "
15980			    "constraint",
15981			    xmlSchemaGetComponentDesignation(&str, use),
15982			    NULL);
15983			FREE_AND_NULL(str);
15984			if (xmlSchemaItemListRemove(uses, i) == -1)
15985			    goto exit_failure;
15986		    }
15987
15988		    hasId = 1;
15989		}
15990	    }
15991next_use: {}
15992	}
15993    }
15994    return (0);
15995exit_failure:
15996    return(-1);
15997}
15998
15999static int
16000xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16001		       xmlSchemaTypePtr typeB)
16002{
16003    /*
16004    * TODO: This should implement component-identity
16005    * in the future.
16006    */
16007    if ((typeA == NULL) || (typeB == NULL))
16008	return (0);
16009    return (typeA == typeB);
16010}
16011
16012/**
16013 * xmlSchemaCheckCOSCTDerivedOK:
16014 * @ctxt:  the schema parser context
16015 * @type:  the to-be derived complex type definition
16016 * @baseType:  the base complex type definition
16017 * @set: the given set
16018 *
16019 * Schema Component Constraint:
16020 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16021 *
16022 * STATUS: completed
16023 *
16024 * Returns 0 if the constraints are satisfied, or 1
16025 * if not.
16026 */
16027static int
16028xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16029			     xmlSchemaTypePtr type,
16030			     xmlSchemaTypePtr baseType,
16031			     int set)
16032{
16033    int equal = xmlSchemaAreEqualTypes(type, baseType);
16034    /* TODO: Error codes. */
16035    /*
16036    * SPEC "For a complex type definition (call it D, for derived)
16037    * to be validly derived from a type definition (call this
16038    * B, for base) given a subset of {extension, restriction}
16039    * all of the following must be true:"
16040    */
16041    if (! equal) {
16042	/*
16043	* SPEC (1) "If B and D are not the same type definition, then the
16044	* {derivation method} of D must not be in the subset."
16045	*/
16046	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16047	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16048	    return (1);
16049    } else {
16050	/*
16051	* SPEC (2.1) "B and D must be the same type definition."
16052	*/
16053	return (0);
16054    }
16055    /*
16056    * SPEC (2.2) "B must be D's {base type definition}."
16057    */
16058    if (type->baseType == baseType)
16059	return (0);
16060    /*
16061    * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
16062    * definition�."
16063    */
16064    if (WXS_IS_ANYTYPE(type->baseType))
16065	return (1);
16066
16067    if (WXS_IS_COMPLEX(type->baseType)) {
16068	/*
16069	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16070	* must be validly derived from B given the subset as defined by this
16071	* constraint."
16072	*/
16073	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16074	    baseType, set));
16075    } else {
16076	/*
16077	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16078	* must be validly derived from B given the subset as defined in Type
16079	* Derivation OK (Simple) (�3.14.6).
16080	*/
16081	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16082	    baseType, set));
16083    }
16084}
16085
16086/**
16087 * xmlSchemaCheckCOSDerivedOK:
16088 * @type:  the derived simple type definition
16089 * @baseType:  the base type definition
16090 *
16091 * Calls:
16092 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16093 *
16094 * Checks wheter @type can be validly derived from @baseType.
16095 *
16096 * Returns 0 on success, an positive error code otherwise.
16097 */
16098static int
16099xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16100			   xmlSchemaTypePtr type,
16101			   xmlSchemaTypePtr baseType,
16102			   int set)
16103{
16104    if (WXS_IS_SIMPLE(type))
16105	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16106    else
16107	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16108}
16109
16110/**
16111 * xmlSchemaCheckCOSCTExtends:
16112 * @ctxt:  the schema parser context
16113 * @type:  the complex type definition
16114 *
16115 * (3.4.6) Constraints on Complex Type Definition Schema Components
16116 * Schema Component Constraint:
16117 * Derivation Valid (Extension) (cos-ct-extends)
16118 *
16119 * STATUS:
16120 *   missing:
16121 *     (1.5)
16122 *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16123 *
16124 * Returns 0 if the constraints are satisfied, a positive
16125 * error code if not and -1 if an internal error occured.
16126 */
16127static int
16128xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16129			   xmlSchemaTypePtr type)
16130{
16131    xmlSchemaTypePtr base = type->baseType;
16132    /*
16133    * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16134    * temporarily only.
16135    */
16136    /*
16137    * SPEC (1) "If the {base type definition} is a complex type definition,
16138    * then all of the following must be true:"
16139    */
16140    if (WXS_IS_COMPLEX(base)) {
16141	/*
16142	* SPEC (1.1) "The {final} of the {base type definition} must not
16143	* contain extension."
16144	*/
16145	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16146	    xmlSchemaPCustomErr(ctxt,
16147		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16148		WXS_BASIC_CAST type, NULL,
16149		"The 'final' of the base type definition "
16150		"contains 'extension'", NULL);
16151	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16152	}
16153
16154	/*
16155	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16156	* since they are automatically satisfied through the
16157	* inheriting mechanism.
16158	* Note that even if redefining components, the inheriting mechanism
16159	* is used.
16160	*/
16161#if 0
16162	/*
16163	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16164	* uses}
16165	* of the complex type definition itself, that is, for every attribute
16166	* use in the {attribute uses} of the {base type definition}, there
16167	* must be an attribute use in the {attribute uses} of the complex
16168	* type definition itself whose {attribute declaration} has the same
16169	* {name}, {target namespace} and {type definition} as its attribute
16170	* declaration"
16171	*/
16172	if (base->attrUses != NULL) {
16173	    int i, j, found;
16174	    xmlSchemaAttributeUsePtr use, buse;
16175
16176	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16177		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16178		found = 0;
16179		if (type->attrUses != NULL) {
16180		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16181		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16182		    {
16183			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16184				WXS_ATTRUSE_DECL_NAME(buse)) &&
16185			    (WXS_ATTRUSE_DECL_TNS(use) ==
16186				WXS_ATTRUSE_DECL_TNS(buse)) &&
16187			    (WXS_ATTRUSE_TYPEDEF(use) ==
16188				WXS_ATTRUSE_TYPEDEF(buse))
16189			{
16190			    found = 1;
16191			    break;
16192			}
16193		    }
16194		}
16195		if (! found) {
16196		    xmlChar *str = NULL;
16197
16198		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16199			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16200			NULL, WXS_BASIC_CAST type,
16201			/*
16202			* TODO: The report does not indicate that also the
16203			* type needs to be the same.
16204			*/
16205			"This type is missing a matching correspondent "
16206			"for its {base type}'s %s in its {attribute uses}",
16207			xmlSchemaGetComponentDesignation(&str,
16208			    buse->children),
16209			NULL);
16210		    FREE_AND_NULL(str)
16211		}
16212	    }
16213	}
16214	/*
16215	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16216	* definition must also have one, and the base type definition's
16217	* {attribute  wildcard}'s {namespace constraint} must be a subset
16218	* of the complex  type definition's {attribute wildcard}'s {namespace
16219	* constraint}, as defined by Wildcard Subset (�3.10.6)."
16220	*/
16221
16222	/*
16223	* MAYBE TODO: Enable if ever needed. But this will be needed only
16224	* if created the type via a schema construction API.
16225	*/
16226	if (base->attributeWildcard != NULL) {
16227	    if (type->attributeWilcard == NULL) {
16228		xmlChar *str = NULL;
16229
16230		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16231		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16232		    NULL, type,
16233		    "The base %s has an attribute wildcard, "
16234		    "but this type is missing an attribute wildcard",
16235		    xmlSchemaGetComponentDesignation(&str, base));
16236		FREE_AND_NULL(str)
16237
16238	    } else if (xmlSchemaCheckCOSNSSubset(
16239		base->attributeWildcard, type->attributeWildcard))
16240	    {
16241		xmlChar *str = NULL;
16242
16243		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16244		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16245		    NULL, type,
16246		    "The attribute wildcard is not a valid "
16247		    "superset of the one in the base %s",
16248		    xmlSchemaGetComponentDesignation(&str, base));
16249		FREE_AND_NULL(str)
16250	    }
16251	}
16252#endif
16253	/*
16254	* SPEC (1.4) "One of the following must be true:"
16255	*/
16256	if ((type->contentTypeDef != NULL) &&
16257	    (type->contentTypeDef == base->contentTypeDef)) {
16258	    /*
16259	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16260	    * and the {content type} of the complex type definition itself
16261	    * must be the same simple type definition"
16262	    * PASS
16263	    */
16264	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16265	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16266	    /*
16267	    * SPEC (1.4.2) "The {content type} of both the {base type
16268	    * definition} and the complex type definition itself must
16269	    * be empty."
16270	    * PASS
16271	    */
16272	} else {
16273	    /*
16274	    * SPEC (1.4.3) "All of the following must be true:"
16275	    */
16276	    if (type->subtypes == NULL) {
16277		/*
16278		* SPEC 1.4.3.1 The {content type} of the complex type
16279		* definition itself must specify a particle.
16280		*/
16281		xmlSchemaPCustomErr(ctxt,
16282		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16283		    WXS_BASIC_CAST type, NULL,
16284		    "The content type must specify a particle", NULL);
16285		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16286	    }
16287	    /*
16288	    * SPEC (1.4.3.2) "One of the following must be true:"
16289	    */
16290	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16291		/*
16292		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16293		* definition} must be empty.
16294		* PASS
16295		*/
16296	    } else {
16297		/*
16298		* SPEC (1.4.3.2.2) "All of the following must be true:"
16299		*/
16300		if ((type->contentType != base->contentType) ||
16301		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16302		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16303		    /*
16304		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16305		    * or both must be element-only."
16306		    */
16307		    xmlSchemaPCustomErr(ctxt,
16308			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16309			WXS_BASIC_CAST type, NULL,
16310			"The content type of both, the type and its base "
16311			"type, must either 'mixed' or 'element-only'", NULL);
16312		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16313		}
16314		/*
16315		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16316		* complex type definition must be a �valid extension�
16317		* of the {base type definition}'s particle, as defined
16318		* in Particle Valid (Extension) (�3.9.6)."
16319		*
16320		* NOTE that we won't check "Particle Valid (Extension)",
16321		* since it is ensured by the derivation process in
16322		* xmlSchemaTypeFixup(). We need to implement this when heading
16323		* for a construction API
16324		* TODO: !! This is needed to be checked if redefining a type !!
16325		*/
16326	    }
16327	    /*
16328	    * URGENT TODO (1.5)
16329	    */
16330	}
16331    } else {
16332	/*
16333	* SPEC (2) "If the {base type definition} is a simple type definition,
16334	* then all of the following must be true:"
16335	*/
16336	if (type->contentTypeDef != base) {
16337	    /*
16338	    * SPEC (2.1) "The {content type} must be the same simple type
16339	    * definition."
16340	    */
16341	    xmlSchemaPCustomErr(ctxt,
16342		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16343		WXS_BASIC_CAST type, NULL,
16344		"The content type must be the simple base type", NULL);
16345	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16346	}
16347	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16348	    /*
16349	    * SPEC (2.2) "The {final} of the {base type definition} must not
16350	    * contain extension"
16351	    * NOTE that this is the same as (1.1).
16352	    */
16353	    xmlSchemaPCustomErr(ctxt,
16354		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16355		WXS_BASIC_CAST type, NULL,
16356		"The 'final' of the base type definition "
16357		"contains 'extension'", NULL);
16358	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16359	}
16360    }
16361    return (0);
16362}
16363
16364/**
16365 * xmlSchemaCheckDerivationOKRestriction:
16366 * @ctxt:  the schema parser context
16367 * @type:  the complex type definition
16368 *
16369 * (3.4.6) Constraints on Complex Type Definition Schema Components
16370 * Schema Component Constraint:
16371 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16372 *
16373 * STATUS:
16374 *   missing:
16375 *     (5.4.2) ???
16376 *
16377 * ATTENTION:
16378 * In XML Schema 1.1 this will be:
16379 * Validation Rule: Checking complex type subsumption
16380 *
16381 * Returns 0 if the constraints are satisfied, a positive
16382 * error code if not and -1 if an internal error occured.
16383 */
16384static int
16385xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16386				      xmlSchemaTypePtr type)
16387{
16388    xmlSchemaTypePtr base;
16389
16390    /*
16391    * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16392    * temporarily only.
16393    */
16394    base = type->baseType;
16395    if (! WXS_IS_COMPLEX(base)) {
16396	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16397	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16398	    type->node, WXS_BASIC_CAST type,
16399	    "The base type must be a complex type", NULL, NULL);
16400	return(ctxt->err);
16401    }
16402    if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16403	/*
16404	* SPEC (1) "The {base type definition} must be a complex type
16405	* definition whose {final} does not contain restriction."
16406	*/
16407	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16408	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16409	    type->node, WXS_BASIC_CAST type,
16410	    "The 'final' of the base type definition "
16411	    "contains 'restriction'", NULL, NULL);
16412	return (ctxt->err);
16413    }
16414    /*
16415    * SPEC (2), (3) and (4)
16416    * Those are handled in a separate function, since the
16417    * same constraints are needed for redefinition of
16418    * attribute groups as well.
16419    */
16420    if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16421	XML_SCHEMA_ACTION_DERIVE,
16422	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16423	type->attrUses, base->attrUses,
16424	type->attributeWildcard,
16425	base->attributeWildcard) == -1)
16426    {
16427	return(-1);
16428    }
16429    /*
16430    * SPEC (5) "One of the following must be true:"
16431    */
16432    if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16433	/*
16434	* SPEC (5.1) "The {base type definition} must be the
16435	* �ur-type definition�."
16436	* PASS
16437	*/
16438    } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16439	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16440	/*
16441	* SPEC (5.2.1) "The {content type} of the complex type definition
16442	* must be a simple type definition"
16443	*
16444	* SPEC (5.2.2) "One of the following must be true:"
16445	*/
16446	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16447	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16448	{
16449	    int err;
16450	    /*
16451	    * SPEC (5.2.2.1) "The {content type} of the {base type
16452	    * definition} must be a simple type definition from which
16453	    * the {content type} is validly derived given the empty
16454	    * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16455	    *
16456	    * ATTENTION TODO: This seems not needed if the type implicitely
16457	    * derived from the base type.
16458	    *
16459	    */
16460	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16461		type->contentTypeDef, base->contentTypeDef, 0);
16462	    if (err != 0) {
16463		xmlChar *strA = NULL, *strB = NULL;
16464
16465		if (err == -1)
16466		    return(-1);
16467		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16468		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16469		    NULL, WXS_BASIC_CAST type,
16470		    "The {content type} %s is not validly derived from the "
16471		    "base type's {content type} %s",
16472		    xmlSchemaGetComponentDesignation(&strA,
16473			type->contentTypeDef),
16474		    xmlSchemaGetComponentDesignation(&strB,
16475			base->contentTypeDef));
16476		FREE_AND_NULL(strA);
16477		FREE_AND_NULL(strB);
16478		return(ctxt->err);
16479	    }
16480	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16481	    (xmlSchemaIsParticleEmptiable(
16482		(xmlSchemaParticlePtr) base->subtypes))) {
16483	    /*
16484	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16485	    * and have a particle which is �emptiable� as defined in
16486	    * Particle Emptiable (�3.9.6)."
16487	    * PASS
16488	    */
16489	} else {
16490	    xmlSchemaPCustomErr(ctxt,
16491		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16492		WXS_BASIC_CAST type, NULL,
16493		"The content type of the base type must be either "
16494		"a simple type or 'mixed' and an emptiable particle", NULL);
16495	    return (ctxt->err);
16496	}
16497    } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16498	/*
16499	* SPEC (5.3.1) "The {content type} of the complex type itself must
16500	* be empty"
16501	*/
16502	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16503	    /*
16504	    * SPEC (5.3.2.1) "The {content type} of the {base type
16505	    * definition} must also be empty."
16506	    * PASS
16507	    */
16508	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16509	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16510	    xmlSchemaIsParticleEmptiable(
16511		(xmlSchemaParticlePtr) base->subtypes)) {
16512	    /*
16513	    * SPEC (5.3.2.2) "The {content type} of the {base type
16514	    * definition} must be elementOnly or mixed and have a particle
16515	    * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16516	    * PASS
16517	    */
16518	} else {
16519	    xmlSchemaPCustomErr(ctxt,
16520		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16521		WXS_BASIC_CAST type, NULL,
16522		"The content type of the base type must be either "
16523		"empty or 'mixed' (or 'elements-only') and an emptiable "
16524		"particle", NULL);
16525	    return (ctxt->err);
16526	}
16527    } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16528	WXS_HAS_MIXED_CONTENT(type)) {
16529	/*
16530	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16531	* itself must be element-only"
16532	*/
16533	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16534	    /*
16535	    * SPEC (5.4.1.2) "The {content type} of the complex type
16536	    * definition itself and of the {base type definition} must be
16537	    * mixed"
16538	    */
16539	    xmlSchemaPCustomErr(ctxt,
16540		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16541		WXS_BASIC_CAST type, NULL,
16542		"If the content type is 'mixed', then the content type of the "
16543		"base type must also be 'mixed'", NULL);
16544	    return (ctxt->err);
16545	}
16546	/*
16547	* SPEC (5.4.2) "The particle of the complex type definition itself
16548	* must be a �valid restriction� of the particle of the {content
16549	* type} of the {base type definition} as defined in Particle Valid
16550	* (Restriction) (�3.9.6).
16551	*
16552	* URGENT TODO: (5.4.2)
16553	*/
16554    } else {
16555	xmlSchemaPCustomErr(ctxt,
16556	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16557	    WXS_BASIC_CAST type, NULL,
16558	    "The type is not a valid restriction of its base type", NULL);
16559	return (ctxt->err);
16560    }
16561    return (0);
16562}
16563
16564/**
16565 * xmlSchemaCheckCTComponent:
16566 * @ctxt:  the schema parser context
16567 * @type:  the complex type definition
16568 *
16569 * (3.4.6) Constraints on Complex Type Definition Schema Components
16570 *
16571 * Returns 0 if the constraints are satisfied, a positive
16572 * error code if not and -1 if an internal error occured.
16573 */
16574static int
16575xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16576			  xmlSchemaTypePtr type)
16577{
16578    int ret;
16579    /*
16580    * Complex Type Definition Properties Correct
16581    */
16582    ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16583    if (ret != 0)
16584	return (ret);
16585    if (WXS_IS_EXTENSION(type))
16586	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16587    else
16588	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16589    return (ret);
16590}
16591
16592/**
16593 * xmlSchemaCheckSRCCT:
16594 * @ctxt:  the schema parser context
16595 * @type:  the complex type definition
16596 *
16597 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16598 * Schema Representation Constraint:
16599 * Complex Type Definition Representation OK (src-ct)
16600 *
16601 * Returns 0 if the constraints are satisfied, a positive
16602 * error code if not and -1 if an internal error occured.
16603 */
16604static int
16605xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16606		    xmlSchemaTypePtr type)
16607{
16608    xmlSchemaTypePtr base;
16609    int ret = 0;
16610
16611    /*
16612    * TODO: Adjust the error codes here, as I used
16613    * XML_SCHEMAP_SRC_CT_1 only yet.
16614    */
16615    base = type->baseType;
16616    if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16617	/*
16618	* 1 If the <complexContent> alternative is chosen, the type definition
16619	* �resolved� to by the �actual value� of the base [attribute]
16620	* must be a complex type definition;
16621	*/
16622	if (! WXS_IS_COMPLEX(base)) {
16623	    xmlChar *str = NULL;
16624	    xmlSchemaPCustomErr(ctxt,
16625		XML_SCHEMAP_SRC_CT_1,
16626		WXS_BASIC_CAST type, type->node,
16627		"If using <complexContent>, the base type is expected to be "
16628		"a complex type. The base type '%s' is a simple type",
16629		xmlSchemaFormatQName(&str, base->targetNamespace,
16630		base->name));
16631	    FREE_AND_NULL(str)
16632	    return (XML_SCHEMAP_SRC_CT_1);
16633	}
16634    } else {
16635	/*
16636	* SPEC
16637	* 2 If the <simpleContent> alternative is chosen, all of the
16638	* following must be true:
16639	* 2.1 The type definition �resolved� to by the �actual value� of the
16640	* base [attribute] must be one of the following:
16641	*/
16642	if (WXS_IS_SIMPLE(base)) {
16643	    if (WXS_IS_EXTENSION(type) == 0) {
16644		xmlChar *str = NULL;
16645		/*
16646		* 2.1.3 only if the <extension> alternative is also
16647		* chosen, a simple type definition.
16648		*/
16649		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16650		xmlSchemaPCustomErr(ctxt,
16651		    XML_SCHEMAP_SRC_CT_1,
16652		    WXS_BASIC_CAST type, NULL,
16653		    "If using <simpleContent> and <restriction>, the base "
16654		    "type must be a complex type. The base type '%s' is "
16655		    "a simple type",
16656		    xmlSchemaFormatQName(&str, base->targetNamespace,
16657			base->name));
16658		FREE_AND_NULL(str)
16659		return (XML_SCHEMAP_SRC_CT_1);
16660	    }
16661	} else {
16662	    /* Base type is a complex type. */
16663	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16664		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16665		/*
16666		* 2.1.1 a complex type definition whose {content type} is a
16667		* simple type definition;
16668		* PASS
16669		*/
16670		if (base->contentTypeDef == NULL) {
16671		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16672			WXS_BASIC_CAST type, NULL,
16673			"Internal error: xmlSchemaCheckSRCCT, "
16674			"'%s', base type has no content type",
16675			type->name);
16676		    return (-1);
16677		}
16678	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16679		(WXS_IS_RESTRICTION(type))) {
16680
16681		/*
16682		* 2.1.2 only if the <restriction> alternative is also
16683		* chosen, a complex type definition whose {content type}
16684		* is mixed and a particle emptiable.
16685		*/
16686		if (! xmlSchemaIsParticleEmptiable(
16687		    (xmlSchemaParticlePtr) base->subtypes)) {
16688		    ret = XML_SCHEMAP_SRC_CT_1;
16689		} else
16690		    /*
16691		    * Attention: at this point the <simpleType> child is in
16692		    * ->contentTypeDef (put there during parsing).
16693		    */
16694		    if (type->contentTypeDef == NULL) {
16695		    xmlChar *str = NULL;
16696		    /*
16697		    * 2.2 If clause 2.1.2 above is satisfied, then there
16698		    * must be a <simpleType> among the [children] of
16699		    * <restriction>.
16700		    */
16701		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16702		    xmlSchemaPCustomErr(ctxt,
16703			XML_SCHEMAP_SRC_CT_1,
16704			WXS_BASIC_CAST type, NULL,
16705			"A <simpleType> is expected among the children "
16706			"of <restriction>, if <simpleContent> is used and "
16707			"the base type '%s' is a complex type",
16708			xmlSchemaFormatQName(&str, base->targetNamespace,
16709			base->name));
16710		    FREE_AND_NULL(str)
16711		    return (XML_SCHEMAP_SRC_CT_1);
16712		}
16713	    } else {
16714		ret = XML_SCHEMAP_SRC_CT_1;
16715	    }
16716	}
16717	if (ret > 0) {
16718	    xmlChar *str = NULL;
16719	    if (WXS_IS_RESTRICTION(type)) {
16720		xmlSchemaPCustomErr(ctxt,
16721		    XML_SCHEMAP_SRC_CT_1,
16722		    WXS_BASIC_CAST type, NULL,
16723		    "If <simpleContent> and <restriction> is used, the "
16724		    "base type must be a simple type or a complex type with "
16725		    "mixed content and particle emptiable. The base type "
16726		    "'%s' is none of those",
16727		    xmlSchemaFormatQName(&str, base->targetNamespace,
16728		    base->name));
16729	    } else {
16730		xmlSchemaPCustomErr(ctxt,
16731		    XML_SCHEMAP_SRC_CT_1,
16732		    WXS_BASIC_CAST type, NULL,
16733		    "If <simpleContent> and <extension> is used, the "
16734		    "base type must be a simple type. The base type '%s' "
16735		    "is a complex type",
16736		    xmlSchemaFormatQName(&str, base->targetNamespace,
16737		    base->name));
16738	    }
16739	    FREE_AND_NULL(str)
16740	}
16741    }
16742    /*
16743    * SPEC (3) "The corresponding complex type definition component must
16744    * satisfy the conditions set out in Constraints on Complex Type
16745    * Definition Schema Components (�3.4.6);"
16746    * NOTE (3) will be done in xmlSchemaTypeFixup().
16747    */
16748    /*
16749    * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16750    * above for {attribute wildcard} is satisfied, the intensional
16751    * intersection must be expressible, as defined in Attribute Wildcard
16752    * Intersection (�3.10.6).
16753    * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16754    */
16755    return (ret);
16756}
16757
16758#ifdef ENABLE_PARTICLE_RESTRICTION
16759/**
16760 * xmlSchemaCheckParticleRangeOK:
16761 * @ctxt:  the schema parser context
16762 * @type:  the complex type definition
16763 *
16764 * (3.9.6) Constraints on Particle Schema Components
16765 * Schema Component Constraint:
16766 * Occurrence Range OK (range-ok)
16767 *
16768 * STATUS: complete
16769 *
16770 * Returns 0 if the constraints are satisfied, a positive
16771 * error code if not and -1 if an internal error occured.
16772 */
16773static int
16774xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16775			      int bmin, int bmax)
16776{
16777    if (rmin < bmin)
16778	return (1);
16779    if ((bmax != UNBOUNDED) &&
16780	(rmax > bmax))
16781	return (1);
16782    return (0);
16783}
16784
16785/**
16786 * xmlSchemaCheckRCaseNameAndTypeOK:
16787 * @ctxt:  the schema parser context
16788 * @r: the restricting element declaration particle
16789 * @b: the base element declaration particle
16790 *
16791 * (3.9.6) Constraints on Particle Schema Components
16792 * Schema Component Constraint:
16793 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16794 * (rcase-NameAndTypeOK)
16795 *
16796 * STATUS:
16797 *   MISSING (3.2.3)
16798 *   CLARIFY: (3.2.2)
16799 *
16800 * Returns 0 if the constraints are satisfied, a positive
16801 * error code if not and -1 if an internal error occured.
16802 */
16803static int
16804xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16805				 xmlSchemaParticlePtr r,
16806				 xmlSchemaParticlePtr b)
16807{
16808    xmlSchemaElementPtr elemR, elemB;
16809
16810    /* TODO: Error codes (rcase-NameAndTypeOK). */
16811    elemR = (xmlSchemaElementPtr) r->children;
16812    elemB = (xmlSchemaElementPtr) b->children;
16813    /*
16814    * SPEC (1) "The declarations' {name}s and {target namespace}s are
16815    * the same."
16816    */
16817    if ((elemR != elemB) &&
16818	((! xmlStrEqual(elemR->name, elemB->name)) ||
16819	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16820	return (1);
16821    /*
16822    * SPEC (2) "R's occurrence range is a valid restriction of B's
16823    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16824    */
16825    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16826	    b->minOccurs, b->maxOccurs) != 0)
16827	return (1);
16828    /*
16829    * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16830    * {scope} are global."
16831    */
16832    if (elemR == elemB)
16833	return (0);
16834    /*
16835    * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16836    */
16837    if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16838	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16839	 return (1);
16840    /*
16841    * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16842    * or is not fixed, or R's declaration's {value constraint} is fixed
16843    * with the same value."
16844    */
16845    if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16846	((elemR->value == NULL) ||
16847	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16848	 /* TODO: Equality of the initial value or normalized or canonical? */
16849	 (! xmlStrEqual(elemR->value, elemB->value))))
16850	 return (1);
16851    /*
16852    * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16853    * definitions} is a subset of B's declaration's {identity-constraint
16854    * definitions}, if any."
16855    */
16856    if (elemB->idcs != NULL) {
16857	/* TODO */
16858    }
16859    /*
16860    * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16861    * superset of B's declaration's {disallowed substitutions}."
16862    */
16863    if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16864	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16865	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16866	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16867	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16868	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16869	 return (1);
16870    /*
16871    * SPEC (3.2.5) "R's {type definition} is validly derived given
16872    * {extension, list, union} from B's {type definition}"
16873    *
16874    * BADSPEC TODO: What's the point of adding "list" and "union" to the
16875    * set, if the corresponding constraints handle "restriction" and
16876    * "extension" only?
16877    *
16878    */
16879    {
16880	int set = 0;
16881
16882	set |= SUBSET_EXTENSION;
16883	set |= SUBSET_LIST;
16884	set |= SUBSET_UNION;
16885	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16886	    elemB->subtypes, set) != 0)
16887	    return (1);
16888    }
16889    return (0);
16890}
16891
16892/**
16893 * xmlSchemaCheckRCaseNSCompat:
16894 * @ctxt:  the schema parser context
16895 * @r: the restricting element declaration particle
16896 * @b: the base wildcard particle
16897 *
16898 * (3.9.6) Constraints on Particle Schema Components
16899 * Schema Component Constraint:
16900 * Particle Derivation OK (Elt:Any -- NSCompat)
16901 * (rcase-NSCompat)
16902 *
16903 * STATUS: complete
16904 *
16905 * Returns 0 if the constraints are satisfied, a positive
16906 * error code if not and -1 if an internal error occured.
16907 */
16908static int
16909xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16910			    xmlSchemaParticlePtr r,
16911			    xmlSchemaParticlePtr b)
16912{
16913    /* TODO:Error codes (rcase-NSCompat). */
16914    /*
16915    * SPEC "For an element declaration particle to be a �valid restriction�
16916    * of a wildcard particle all of the following must be true:"
16917    *
16918    * SPEC (1) "The element declaration's {target namespace} is �valid�
16919    * with respect to the wildcard's {namespace constraint} as defined by
16920    * Wildcard allows Namespace Name (�3.10.4)."
16921    */
16922    if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16923	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16924	return (1);
16925    /*
16926    * SPEC (2) "R's occurrence range is a valid restriction of B's
16927    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16928    */
16929    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16930	    b->minOccurs, b->maxOccurs) != 0)
16931	return (1);
16932
16933    return (0);
16934}
16935
16936/**
16937 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16938 * @ctxt:  the schema parser context
16939 * @r: the restricting element declaration particle
16940 * @b: the base model group particle
16941 *
16942 * (3.9.6) Constraints on Particle Schema Components
16943 * Schema Component Constraint:
16944 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16945 * (rcase-RecurseAsIfGroup)
16946 *
16947 * STATUS: TODO
16948 *
16949 * Returns 0 if the constraints are satisfied, a positive
16950 * error code if not and -1 if an internal error occured.
16951 */
16952static int
16953xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16954				    xmlSchemaParticlePtr r,
16955				    xmlSchemaParticlePtr b)
16956{
16957    /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16958    TODO
16959    return (0);
16960}
16961
16962/**
16963 * xmlSchemaCheckRCaseNSSubset:
16964 * @ctxt:  the schema parser context
16965 * @r: the restricting wildcard particle
16966 * @b: the base wildcard particle
16967 *
16968 * (3.9.6) Constraints on Particle Schema Components
16969 * Schema Component Constraint:
16970 * Particle Derivation OK (Any:Any -- NSSubset)
16971 * (rcase-NSSubset)
16972 *
16973 * STATUS: complete
16974 *
16975 * Returns 0 if the constraints are satisfied, a positive
16976 * error code if not and -1 if an internal error occured.
16977 */
16978static int
16979xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16980				    xmlSchemaParticlePtr r,
16981				    xmlSchemaParticlePtr b,
16982				    int isAnyTypeBase)
16983{
16984    /* TODO: Error codes (rcase-NSSubset). */
16985    /*
16986    * SPEC (1) "R's occurrence range is a valid restriction of B's
16987    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16988    */
16989    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16990	    b->minOccurs, b->maxOccurs))
16991	return (1);
16992    /*
16993    * SPEC (2) "R's {namespace constraint} must be an intensional subset
16994    * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16995    */
16996    if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16997	(xmlSchemaWildcardPtr) b->children))
16998	return (1);
16999    /*
17000    * SPEC (3) "Unless B is the content model wildcard of the �ur-type
17001    * definition�, R's {process contents} must be identical to or stronger
17002    * than B's {process contents}, where strict is stronger than lax is
17003    * stronger than skip."
17004    */
17005    if (! isAnyTypeBase) {
17006	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17007	    ((xmlSchemaWildcardPtr) b->children)->processContents)
17008	    return (1);
17009    }
17010
17011    return (0);
17012}
17013
17014/**
17015 * xmlSchemaCheckCOSParticleRestrict:
17016 * @ctxt:  the schema parser context
17017 * @type:  the complex type definition
17018 *
17019 * (3.9.6) Constraints on Particle Schema Components
17020 * Schema Component Constraint:
17021 * Particle Valid (Restriction) (cos-particle-restrict)
17022 *
17023 * STATUS: TODO
17024 *
17025 * Returns 0 if the constraints are satisfied, a positive
17026 * error code if not and -1 if an internal error occured.
17027 */
17028static int
17029xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17030				  xmlSchemaParticlePtr r,
17031				  xmlSchemaParticlePtr b)
17032{
17033    int ret = 0;
17034
17035    /*part = WXS_TYPE_PARTICLE(type);
17036    basePart = WXS_TYPE_PARTICLE(base);
17037    */
17038
17039    TODO
17040
17041    /*
17042    * SPEC (1) "They are the same particle."
17043    */
17044    if (r == b)
17045	return (0);
17046
17047
17048    return (0);
17049}
17050
17051#if 0
17052/**
17053 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17054 * @ctxt:  the schema parser context
17055 * @r: the model group particle
17056 * @b: the base wildcard particle
17057 *
17058 * (3.9.6) Constraints on Particle Schema Components
17059 * Schema Component Constraint:
17060 * Particle Derivation OK (All/Choice/Sequence:Any --
17061 *                         NSRecurseCheckCardinality)
17062 * (rcase-NSRecurseCheckCardinality)
17063 *
17064 * STATUS: TODO: subst-groups
17065 *
17066 * Returns 0 if the constraints are satisfied, a positive
17067 * error code if not and -1 if an internal error occured.
17068 */
17069static int
17070xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17071					     xmlSchemaParticlePtr r,
17072					     xmlSchemaParticlePtr b)
17073{
17074    xmlSchemaParticlePtr part;
17075    /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17076    if ((r->children == NULL) || (r->children->children == NULL))
17077	return (-1);
17078    /*
17079    * SPEC "For a group particle to be a �valid restriction� of a
17080    * wildcard particle..."
17081    *
17082    * SPEC (1) "Every member of the {particles} of the group is a �valid
17083    * restriction� of the wildcard as defined by
17084    * Particle Valid (Restriction) (�3.9.6)."
17085    */
17086    part = (xmlSchemaParticlePtr) r->children->children;
17087    do {
17088	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17089	    return (1);
17090	part = (xmlSchemaParticlePtr) part->next;
17091    } while (part != NULL);
17092    /*
17093    * SPEC (2) "The effective total range of the group [...] is a
17094    * valid restriction of B's occurrence range as defined by
17095    * Occurrence Range OK (�3.9.6)."
17096    */
17097    if (xmlSchemaCheckParticleRangeOK(
17098	    xmlSchemaGetParticleTotalRangeMin(r),
17099	    xmlSchemaGetParticleTotalRangeMax(r),
17100	    b->minOccurs, b->maxOccurs) != 0)
17101	return (1);
17102    return (0);
17103}
17104#endif
17105
17106/**
17107 * xmlSchemaCheckRCaseRecurse:
17108 * @ctxt:  the schema parser context
17109 * @r: the <all> or <sequence> model group particle
17110 * @b: the base <all> or <sequence> model group particle
17111 *
17112 * (3.9.6) Constraints on Particle Schema Components
17113 * Schema Component Constraint:
17114 * Particle Derivation OK (All:All,Sequence:Sequence --
17115                           Recurse)
17116 * (rcase-Recurse)
17117 *
17118 * STATUS:  ?
17119 * TODO: subst-groups
17120 *
17121 * Returns 0 if the constraints are satisfied, a positive
17122 * error code if not and -1 if an internal error occured.
17123 */
17124static int
17125xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17126			   xmlSchemaParticlePtr r,
17127			   xmlSchemaParticlePtr b)
17128{
17129    /* xmlSchemaParticlePtr part; */
17130    /* TODO: Error codes (rcase-Recurse). */
17131    if ((r->children == NULL) || (b->children == NULL) ||
17132	(r->children->type != b->children->type))
17133	return (-1);
17134    /*
17135    * SPEC "For an all or sequence group particle to be a �valid
17136    * restriction� of another group particle with the same {compositor}..."
17137    *
17138    * SPEC (1) "R's occurrence range is a valid restriction of B's
17139    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17140    */
17141    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17142	    b->minOccurs, b->maxOccurs))
17143	return (1);
17144
17145
17146    return (0);
17147}
17148
17149#endif
17150
17151#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17152    xmlSchemaPCustomErrExt(pctxt,      \
17153	XML_SCHEMAP_INVALID_FACET_VALUE, \
17154	WXS_BASIC_CAST fac1, fac1->node, \
17155	"It is an error for both '%s' and '%s' to be specified on the "\
17156	"same type definition", \
17157	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17158	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17159
17160#define FACET_RESTR_ERR(fac1, msg) \
17161    xmlSchemaPCustomErr(pctxt,      \
17162	XML_SCHEMAP_INVALID_FACET_VALUE, \
17163	WXS_BASIC_CAST fac1, fac1->node, \
17164	msg, NULL);
17165
17166#define FACET_RESTR_FIXED_ERR(fac) \
17167    xmlSchemaPCustomErr(pctxt, \
17168	XML_SCHEMAP_INVALID_FACET_VALUE, \
17169	WXS_BASIC_CAST fac, fac->node, \
17170	"The base type's facet is 'fixed', thus the value must not " \
17171	"differ", NULL);
17172
17173static void
17174xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17175			xmlSchemaFacetPtr facet1,
17176			xmlSchemaFacetPtr facet2,
17177			int lessGreater,
17178			int orEqual,
17179			int ofBase)
17180{
17181    xmlChar *msg = NULL;
17182
17183    msg = xmlStrdup(BAD_CAST "'");
17184    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17185    msg = xmlStrcat(msg, BAD_CAST "' has to be");
17186    if (lessGreater == 0)
17187	msg = xmlStrcat(msg, BAD_CAST " equal to");
17188    if (lessGreater == 1)
17189	msg = xmlStrcat(msg, BAD_CAST " greater than");
17190    else
17191	msg = xmlStrcat(msg, BAD_CAST " less than");
17192
17193    if (orEqual)
17194	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17195    msg = xmlStrcat(msg, BAD_CAST " '");
17196    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17197    if (ofBase)
17198	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17199    else
17200	msg = xmlStrcat(msg, BAD_CAST "'");
17201
17202    xmlSchemaPCustomErr(pctxt,
17203	XML_SCHEMAP_INVALID_FACET_VALUE,
17204	WXS_BASIC_CAST facet1, NULL,
17205	(const char *) msg, NULL);
17206
17207    if (msg != NULL)
17208	xmlFree(msg);
17209}
17210
17211/*
17212* xmlSchemaDeriveAndValidateFacets:
17213*
17214* Schema Component Constraint: Simple Type Restriction (Facets)
17215* (st-restrict-facets)
17216*/
17217static int
17218xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17219				 xmlSchemaTypePtr type)
17220{
17221    xmlSchemaTypePtr base = type->baseType;
17222    xmlSchemaFacetLinkPtr link, cur, last = NULL;
17223    xmlSchemaFacetPtr facet, bfacet,
17224	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17225	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17226	fmininc = NULL, fmaxinc = NULL,
17227	fminexc = NULL, fmaxexc = NULL,
17228	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17229	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17230	bfmininc = NULL, bfmaxinc = NULL,
17231	bfminexc = NULL, bfmaxexc = NULL;
17232    int res; /* err = 0, fixedErr; */
17233
17234    /*
17235    * SPEC st-restrict-facets 1:
17236    * "The {variety} of R is the same as that of B."
17237    */
17238    /*
17239    * SPEC st-restrict-facets 2:
17240    * "If {variety} is atomic, the {primitive type definition}
17241    * of R is the same as that of B."
17242    *
17243    * NOTE: we leave 1 & 2 out for now, since this will be
17244    * satisfied by the derivation process.
17245    * CONSTRUCTION TODO: Maybe needed if using a construction API.
17246    */
17247    /*
17248    * SPEC st-restrict-facets 3:
17249    * "The {facets} of R are the union of S and the {facets}
17250    * of B, eliminating duplicates. To eliminate duplicates,
17251    * when a facet of the same kind occurs in both S and the
17252    * {facets} of B, the one in the {facets} of B is not
17253    * included, with the exception of enumeration and pattern
17254    * facets, for which multiple occurrences with distinct values
17255    * are allowed."
17256    */
17257
17258    if ((type->facetSet == NULL) && (base->facetSet == NULL))
17259	return (0);
17260
17261    last = type->facetSet;
17262    if (last != NULL)
17263	while (last->next != NULL)
17264	    last = last->next;
17265
17266    for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17267	facet = cur->facet;
17268	switch (facet->type) {
17269	    case XML_SCHEMA_FACET_LENGTH:
17270		flength = facet; break;
17271	    case XML_SCHEMA_FACET_MINLENGTH:
17272		fminlen = facet; break;
17273	    case XML_SCHEMA_FACET_MININCLUSIVE:
17274		fmininc = facet; break;
17275	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17276		fminexc = facet; break;
17277	    case XML_SCHEMA_FACET_MAXLENGTH:
17278		fmaxlen = facet; break;
17279	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17280		fmaxinc = facet; break;
17281	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17282		fmaxexc = facet; break;
17283	    case XML_SCHEMA_FACET_TOTALDIGITS:
17284		ftotdig = facet; break;
17285	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17286		ffracdig = facet; break;
17287	    default:
17288		break;
17289	}
17290    }
17291    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17292	facet = cur->facet;
17293	switch (facet->type) {
17294	    case XML_SCHEMA_FACET_LENGTH:
17295		bflength = facet; break;
17296	    case XML_SCHEMA_FACET_MINLENGTH:
17297		bfminlen = facet; break;
17298	    case XML_SCHEMA_FACET_MININCLUSIVE:
17299		bfmininc = facet; break;
17300	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17301		bfminexc = facet; break;
17302	    case XML_SCHEMA_FACET_MAXLENGTH:
17303		bfmaxlen = facet; break;
17304	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17305		bfmaxinc = facet; break;
17306	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17307		bfmaxexc = facet; break;
17308	    case XML_SCHEMA_FACET_TOTALDIGITS:
17309		bftotdig = facet; break;
17310	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17311		bffracdig = facet; break;
17312	    default:
17313		break;
17314	}
17315    }
17316    /*
17317    * length and minLength or maxLength (2.2) + (3.2)
17318    */
17319    if (flength && (fminlen || fmaxlen)) {
17320	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17321	    "either of 'minLength' or 'maxLength' to be specified on "
17322	    "the same type definition")
17323    }
17324    /*
17325    * Mutual exclusions in the same derivation step.
17326    */
17327    if ((fmaxinc) && (fmaxexc)) {
17328	/*
17329	* SCC "maxInclusive and maxExclusive"
17330	*/
17331	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17332    }
17333    if ((fmininc) && (fminexc)) {
17334	/*
17335	* SCC "minInclusive and minExclusive"
17336	*/
17337	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17338    }
17339
17340    if (flength && bflength) {
17341	/*
17342	* SCC "length valid restriction"
17343	* The values have to be equal.
17344	*/
17345	res = xmlSchemaCompareValues(flength->val, bflength->val);
17346	if (res == -2)
17347	    goto internal_error;
17348	if (res != 0)
17349	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17350	if ((res != 0) && (bflength->fixed)) {
17351	    FACET_RESTR_FIXED_ERR(flength)
17352	}
17353
17354    }
17355    if (fminlen && bfminlen) {
17356	/*
17357	* SCC "minLength valid restriction"
17358	* minLength >= BASE minLength
17359	*/
17360	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17361	if (res == -2)
17362	    goto internal_error;
17363	if (res == -1)
17364	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17365	if ((res != 0) && (bfminlen->fixed)) {
17366	    FACET_RESTR_FIXED_ERR(fminlen)
17367	}
17368    }
17369    if (fmaxlen && bfmaxlen) {
17370	/*
17371	* SCC "maxLength valid restriction"
17372	* maxLength <= BASE minLength
17373	*/
17374	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17375	if (res == -2)
17376	    goto internal_error;
17377	if (res == 1)
17378	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17379	if ((res != 0) && (bfmaxlen->fixed)) {
17380	    FACET_RESTR_FIXED_ERR(fmaxlen)
17381	}
17382    }
17383    /*
17384    * SCC "length and minLength or maxLength"
17385    */
17386    if (! flength)
17387	flength = bflength;
17388    if (flength) {
17389	if (! fminlen)
17390	    fminlen = bfminlen;
17391	if (fminlen) {
17392	    /* (1.1) length >= minLength */
17393	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17394	    if (res == -2)
17395		goto internal_error;
17396	    if (res == -1)
17397		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17398	}
17399	if (! fmaxlen)
17400	    fmaxlen = bfmaxlen;
17401	if (fmaxlen) {
17402	    /* (2.1) length <= maxLength */
17403	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17404	    if (res == -2)
17405		goto internal_error;
17406	    if (res == 1)
17407		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17408	}
17409    }
17410    if (fmaxinc) {
17411	/*
17412	* "maxInclusive"
17413	*/
17414	if (fmininc) {
17415	    /* SCC "maxInclusive >= minInclusive" */
17416	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17417	    if (res == -2)
17418		goto internal_error;
17419	    if (res == -1) {
17420		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17421	    }
17422	}
17423	/*
17424	* SCC "maxInclusive valid restriction"
17425	*/
17426	if (bfmaxinc) {
17427	    /* maxInclusive <= BASE maxInclusive */
17428	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17429	    if (res == -2)
17430		goto internal_error;
17431	    if (res == 1)
17432		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17433	    if ((res != 0) && (bfmaxinc->fixed)) {
17434		FACET_RESTR_FIXED_ERR(fmaxinc)
17435	    }
17436	}
17437	if (bfmaxexc) {
17438	    /* maxInclusive < BASE maxExclusive */
17439	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17440	    if (res == -2)
17441		goto internal_error;
17442	    if (res != -1) {
17443		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17444	    }
17445	}
17446	if (bfmininc) {
17447	    /* maxInclusive >= BASE minInclusive */
17448	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17449	    if (res == -2)
17450		goto internal_error;
17451	    if (res == -1) {
17452		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17453	    }
17454	}
17455	if (bfminexc) {
17456	    /* maxInclusive > BASE minExclusive */
17457	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17458	    if (res == -2)
17459		goto internal_error;
17460	    if (res != 1) {
17461		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17462	    }
17463	}
17464    }
17465    if (fmaxexc) {
17466	/*
17467	* "maxExclusive >= minExclusive"
17468	*/
17469	if (fminexc) {
17470	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17471	    if (res == -2)
17472		goto internal_error;
17473	    if (res == -1) {
17474		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17475	    }
17476	}
17477	/*
17478	* "maxExclusive valid restriction"
17479	*/
17480	if (bfmaxexc) {
17481	    /* maxExclusive <= BASE maxExclusive */
17482	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17483	    if (res == -2)
17484		goto internal_error;
17485	    if (res == 1) {
17486		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17487	    }
17488	    if ((res != 0) && (bfmaxexc->fixed)) {
17489		FACET_RESTR_FIXED_ERR(fmaxexc)
17490	    }
17491	}
17492	if (bfmaxinc) {
17493	    /* maxExclusive <= BASE maxInclusive */
17494	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17495	    if (res == -2)
17496		goto internal_error;
17497	    if (res == 1) {
17498		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17499	    }
17500	}
17501	if (bfmininc) {
17502	    /* maxExclusive > BASE minInclusive */
17503	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17504	    if (res == -2)
17505		goto internal_error;
17506	    if (res != 1) {
17507		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17508	    }
17509	}
17510	if (bfminexc) {
17511	    /* maxExclusive > BASE minExclusive */
17512	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17513	    if (res == -2)
17514		goto internal_error;
17515	    if (res != 1) {
17516		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17517	    }
17518	}
17519    }
17520    if (fminexc) {
17521	/*
17522	* "minExclusive < maxInclusive"
17523	*/
17524	if (fmaxinc) {
17525	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17526	    if (res == -2)
17527		goto internal_error;
17528	    if (res != -1) {
17529		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17530	    }
17531	}
17532	/*
17533	* "minExclusive valid restriction"
17534	*/
17535	if (bfminexc) {
17536	    /* minExclusive >= BASE minExclusive */
17537	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17538	    if (res == -2)
17539		goto internal_error;
17540	    if (res == -1) {
17541		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17542	    }
17543	    if ((res != 0) && (bfminexc->fixed)) {
17544		FACET_RESTR_FIXED_ERR(fminexc)
17545	    }
17546	}
17547	if (bfmaxinc) {
17548	    /* minExclusive <= BASE maxInclusive */
17549	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17550	    if (res == -2)
17551		goto internal_error;
17552	    if (res == 1) {
17553		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17554	    }
17555	}
17556	if (bfmininc) {
17557	    /* minExclusive >= BASE minInclusive */
17558	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17559	    if (res == -2)
17560		goto internal_error;
17561	    if (res == -1) {
17562		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17563	    }
17564	}
17565	if (bfmaxexc) {
17566	    /* minExclusive < BASE maxExclusive */
17567	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17568	    if (res == -2)
17569		goto internal_error;
17570	    if (res != -1) {
17571		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17572	    }
17573	}
17574    }
17575    if (fmininc) {
17576	/*
17577	* "minInclusive < maxExclusive"
17578	*/
17579	if (fmaxexc) {
17580	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17581	    if (res == -2)
17582		goto internal_error;
17583	    if (res != -1) {
17584		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17585	    }
17586	}
17587	/*
17588	* "minExclusive valid restriction"
17589	*/
17590	if (bfmininc) {
17591	    /* minInclusive >= BASE minInclusive */
17592	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17593	    if (res == -2)
17594		goto internal_error;
17595	    if (res == -1) {
17596		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17597	    }
17598	    if ((res != 0) && (bfmininc->fixed)) {
17599		FACET_RESTR_FIXED_ERR(fmininc)
17600	    }
17601	}
17602	if (bfmaxinc) {
17603	    /* minInclusive <= BASE maxInclusive */
17604	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17605	    if (res == -2)
17606		goto internal_error;
17607	    if (res == 1) {
17608		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17609	    }
17610	}
17611	if (bfminexc) {
17612	    /* minInclusive > BASE minExclusive */
17613	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17614	    if (res == -2)
17615		goto internal_error;
17616	    if (res != 1)
17617		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17618	}
17619	if (bfmaxexc) {
17620	    /* minInclusive < BASE maxExclusive */
17621	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17622	    if (res == -2)
17623		goto internal_error;
17624	    if (res != -1)
17625		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17626	}
17627    }
17628    if (ftotdig && bftotdig) {
17629	/*
17630	* SCC " totalDigits valid restriction"
17631	* totalDigits <= BASE totalDigits
17632	*/
17633	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17634	if (res == -2)
17635	    goto internal_error;
17636	if (res == 1)
17637	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17638	    -1, 1, 1);
17639	if ((res != 0) && (bftotdig->fixed)) {
17640	    FACET_RESTR_FIXED_ERR(ftotdig)
17641	}
17642    }
17643    if (ffracdig && bffracdig) {
17644	/*
17645	* SCC  "fractionDigits valid restriction"
17646	* fractionDigits <= BASE fractionDigits
17647	*/
17648	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17649	if (res == -2)
17650	    goto internal_error;
17651	if (res == 1)
17652	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17653	    -1, 1, 1);
17654	if ((res != 0) && (bffracdig->fixed)) {
17655	    FACET_RESTR_FIXED_ERR(ffracdig)
17656	}
17657    }
17658    /*
17659    * SCC "fractionDigits less than or equal to totalDigits"
17660    */
17661    if (! ftotdig)
17662	ftotdig = bftotdig;
17663    if (! ffracdig)
17664	ffracdig = bffracdig;
17665    if (ftotdig && ffracdig) {
17666	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17667	if (res == -2)
17668	    goto internal_error;
17669	if (res == 1)
17670	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17671		-1, 1, 0);
17672    }
17673    /*
17674    * *Enumerations* won' be added here, since only the first set
17675    * of enumerations in the ancestor-or-self axis is used
17676    * for validation, plus we need to use the base type of those
17677    * enumerations for whitespace.
17678    *
17679    * *Patterns*: won't be add here, since they are ORed at
17680    * type level and ANDed at ancestor level. This will
17681    * happed during validation by walking the base axis
17682    * of the type.
17683    */
17684    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17685	bfacet = cur->facet;
17686	/*
17687	* Special handling of enumerations and patterns.
17688	* TODO: hmm, they should not appear in the set, so remove this.
17689	*/
17690	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17691	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17692	    continue;
17693	/*
17694	* Search for a duplicate facet in the current type.
17695	*/
17696	link = type->facetSet;
17697	/* err = 0; */
17698	/* fixedErr = 0; */
17699	while (link != NULL) {
17700	    facet = link->facet;
17701	    if (facet->type == bfacet->type) {
17702		switch (facet->type) {
17703		    case XML_SCHEMA_FACET_WHITESPACE:
17704			/*
17705			* The whitespace must be stronger.
17706			*/
17707			if (facet->whitespace < bfacet->whitespace) {
17708			    FACET_RESTR_ERR(facet,
17709				"The 'whitespace' value has to be equal to "
17710				"or stronger than the 'whitespace' value of "
17711				"the base type")
17712			}
17713			if ((bfacet->fixed) &&
17714			    (facet->whitespace != bfacet->whitespace)) {
17715			    FACET_RESTR_FIXED_ERR(facet)
17716			}
17717			break;
17718		    default:
17719			break;
17720		}
17721		/* Duplicate found. */
17722		break;
17723	    }
17724	    link = link->next;
17725	}
17726	/*
17727	* If no duplicate was found: add the base types's facet
17728	* to the set.
17729	*/
17730	if (link == NULL) {
17731	    link = (xmlSchemaFacetLinkPtr)
17732		xmlMalloc(sizeof(xmlSchemaFacetLink));
17733	    if (link == NULL) {
17734		xmlSchemaPErrMemory(pctxt,
17735		    "deriving facets, creating a facet link", NULL);
17736		return (-1);
17737	    }
17738	    link->facet = cur->facet;
17739	    link->next = NULL;
17740	    if (last == NULL)
17741		type->facetSet = link;
17742	    else
17743		last->next = link;
17744	    last = link;
17745	}
17746
17747    }
17748
17749    return (0);
17750internal_error:
17751    PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17752	"an error occured");
17753    return (-1);
17754}
17755
17756static int
17757xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17758					     xmlSchemaTypePtr type)
17759{
17760    xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17761    /*
17762    * The actual value is then formed by replacing any union type
17763    * definition in the �explicit members� with the members of their
17764    * {member type definitions}, in order.
17765    *
17766    * TODO: There's a bug entry at
17767    * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17768    * which indicates that we'll keep the union types the future.
17769    */
17770    link = type->memberTypes;
17771    while (link != NULL) {
17772
17773	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17774	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17775
17776	if (WXS_IS_UNION(link->type)) {
17777	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17778	    if (subLink != NULL) {
17779		link->type = subLink->type;
17780		if (subLink->next != NULL) {
17781		    lastLink = link->next;
17782		    subLink = subLink->next;
17783		    prevLink = link;
17784		    while (subLink != NULL) {
17785			newLink = (xmlSchemaTypeLinkPtr)
17786			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17787			if (newLink == NULL) {
17788			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17789				NULL);
17790			    return (-1);
17791			}
17792			newLink->type = subLink->type;
17793			prevLink->next = newLink;
17794			prevLink = newLink;
17795			newLink->next = lastLink;
17796
17797			subLink = subLink->next;
17798		    }
17799		}
17800	    }
17801	}
17802	link = link->next;
17803    }
17804    return (0);
17805}
17806
17807static void
17808xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17809{
17810    int has = 0, needVal = 0, normVal = 0;
17811
17812    has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17813    if (has) {
17814	needVal = (type->baseType->flags &
17815	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17816	normVal = (type->baseType->flags &
17817	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17818    }
17819    if (type->facets != NULL) {
17820	xmlSchemaFacetPtr fac;
17821
17822	for (fac = type->facets; fac != NULL; fac = fac->next) {
17823	    switch (fac->type) {
17824		case XML_SCHEMA_FACET_WHITESPACE:
17825		    break;
17826		case XML_SCHEMA_FACET_PATTERN:
17827		    normVal = 1;
17828		    has = 1;
17829		    break;
17830		case XML_SCHEMA_FACET_ENUMERATION:
17831		    needVal = 1;
17832		    normVal = 1;
17833		    has = 1;
17834		    break;
17835		default:
17836		    has = 1;
17837		    break;
17838	    }
17839	}
17840    }
17841    if (normVal)
17842	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17843    if (needVal)
17844	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17845    if (has)
17846	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17847
17848    if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17849	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17850	/*
17851	* OPTIMIZE VAL TODO: Some facets need a computed value.
17852	*/
17853	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17854	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17855	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17856	}
17857    }
17858}
17859
17860static int
17861xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17862{
17863
17864
17865    /*
17866    * Evaluate the whitespace-facet value.
17867    */
17868    if (WXS_IS_LIST(type)) {
17869	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17870	return (0);
17871    } else if (WXS_IS_UNION(type))
17872	return (0);
17873
17874    if (type->facetSet != NULL) {
17875	xmlSchemaFacetLinkPtr lin;
17876
17877	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17878	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17879		switch (lin->facet->whitespace) {
17880		case XML_SCHEMAS_FACET_PRESERVE:
17881		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17882		    break;
17883		case XML_SCHEMAS_FACET_REPLACE:
17884		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17885		    break;
17886		case XML_SCHEMAS_FACET_COLLAPSE:
17887		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17888		    break;
17889		default:
17890		    return (-1);
17891		}
17892		return (0);
17893	    }
17894	}
17895    }
17896    /*
17897    * For all �atomic� datatypes other than string (and types �derived�
17898    * by �restriction� from it) the value of whiteSpace is fixed to
17899    * collapse
17900    */
17901    {
17902	xmlSchemaTypePtr anc;
17903
17904	for (anc = type->baseType; anc != NULL &&
17905		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17906		anc = anc->baseType) {
17907
17908	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17909		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17910		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17911
17912		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17913		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17914		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17915
17916		} else
17917		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17918		break;
17919	    }
17920	}
17921    }
17922    return (0);
17923}
17924
17925static int
17926xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17927			  xmlSchemaTypePtr type)
17928{
17929    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17930	return(0);
17931    if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17932	return(0);
17933    type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17934
17935    if (WXS_IS_LIST(type)) {
17936	/*
17937	* Corresponds to <simpleType><list>...
17938	*/
17939	if (type->subtypes == NULL) {
17940	    /*
17941	    * This one is really needed, so get out.
17942	    */
17943	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17944		"list type has no item-type assigned");
17945	    return(-1);
17946	}
17947    } else if (WXS_IS_UNION(type)) {
17948	/*
17949	* Corresponds to <simpleType><union>...
17950	*/
17951	if (type->memberTypes == NULL) {
17952	    /*
17953	    * This one is really needed, so get out.
17954	    */
17955	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17956		"union type has no member-types assigned");
17957	    return(-1);
17958	}
17959    } else {
17960	/*
17961	* Corresponds to <simpleType><restriction>...
17962	*/
17963	if (type->baseType == NULL) {
17964	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17965		"type has no base-type assigned");
17966	    return(-1);
17967	}
17968	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17969	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17970		return(-1);
17971	/*
17972	* Variety
17973	* If the <restriction> alternative is chosen, then the
17974	* {variety} of the {base type definition}.
17975	*/
17976	if (WXS_IS_ATOMIC(type->baseType))
17977	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17978	else if (WXS_IS_LIST(type->baseType)) {
17979	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17980	    /*
17981	    * Inherit the itemType.
17982	    */
17983	    type->subtypes = type->baseType->subtypes;
17984	} else if (WXS_IS_UNION(type->baseType)) {
17985	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17986	    /*
17987	    * NOTE that we won't assign the memberTypes of the base,
17988	    * since this will make trouble when freeing them; we will
17989	    * use a lookup function to access them instead.
17990	    */
17991	}
17992    }
17993    return(0);
17994}
17995
17996#ifdef DEBUG_TYPE
17997static void
17998xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17999		       xmlSchemaTypePtr type)
18000{
18001    if (type->node != NULL) {
18002        xmlGenericError(xmlGenericErrorContext,
18003                        "Type of %s : %s:%d :", name,
18004                        type->node->doc->URL,
18005                        xmlGetLineNo(type->node));
18006    } else {
18007        xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18008    }
18009    if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18010	switch (type->contentType) {
18011	    case XML_SCHEMA_CONTENT_SIMPLE:
18012		xmlGenericError(xmlGenericErrorContext, "simple\n");
18013		break;
18014	    case XML_SCHEMA_CONTENT_ELEMENTS:
18015		xmlGenericError(xmlGenericErrorContext, "elements\n");
18016		break;
18017	    case XML_SCHEMA_CONTENT_UNKNOWN:
18018		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18019		break;
18020	    case XML_SCHEMA_CONTENT_EMPTY:
18021		xmlGenericError(xmlGenericErrorContext, "empty\n");
18022		break;
18023	    case XML_SCHEMA_CONTENT_MIXED:
18024		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18025		    type->subtypes))
18026		    xmlGenericError(xmlGenericErrorContext,
18027			"mixed as emptiable particle\n");
18028		else
18029		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18030		break;
18031		/* Removed, since not used. */
18032		/*
18033		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18034		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18035		break;
18036		*/
18037	    case XML_SCHEMA_CONTENT_BASIC:
18038		xmlGenericError(xmlGenericErrorContext, "basic\n");
18039		break;
18040	    default:
18041		xmlGenericError(xmlGenericErrorContext,
18042		    "not registered !!!\n");
18043		break;
18044	}
18045    }
18046}
18047#endif
18048
18049/*
18050* 3.14.6 Constraints on Simple Type Definition Schema Components
18051*/
18052static int
18053xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18054				 xmlSchemaTypePtr type)
18055{
18056    int res, olderrs = pctxt->nberrors;
18057
18058    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18059	return(-1);
18060
18061    if (! WXS_IS_TYPE_NOT_FIXED(type))
18062	return(0);
18063
18064    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18065    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18066
18067    if (type->baseType == NULL) {
18068	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18069	    "missing baseType");
18070	goto exit_failure;
18071    }
18072    if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18073	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18074    /*
18075    * If a member type of a union is a union itself, we need to substitute
18076    * that member type for its member types.
18077    * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18078    * types in WXS 1.1.
18079    */
18080    if ((type->memberTypes != NULL) &&
18081	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18082	return(-1);
18083    /*
18084    * SPEC src-simple-type 1
18085    * "The corresponding simple type definition, if any, must satisfy
18086    * the conditions set out in Constraints on Simple Type Definition
18087    * Schema Components (�3.14.6)."
18088    */
18089    /*
18090    * Schema Component Constraint: Simple Type Definition Properties Correct
18091    * (st-props-correct)
18092    */
18093    res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18094    HFAILURE HERROR
18095    /*
18096    * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18097    * (cos-st-restricts)
18098    */
18099    res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18100    HFAILURE HERROR
18101    /*
18102    * TODO: Removed the error report, since it got annoying to get an
18103    * extra error report, if anything failed until now.
18104    * Enable this if needed.
18105    *
18106    * xmlSchemaPErr(ctxt, type->node,
18107    *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18108    *    "Simple type '%s' does not satisfy the constraints "
18109    *    "on simple type definitions.\n",
18110    *    type->name, NULL);
18111    */
18112    /*
18113    * Schema Component Constraint: Simple Type Restriction (Facets)
18114    * (st-restrict-facets)
18115    */
18116    res = xmlSchemaCheckFacetValues(type, pctxt);
18117    HFAILURE HERROR
18118    if ((type->facetSet != NULL) ||
18119	(type->baseType->facetSet != NULL)) {
18120	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18121	HFAILURE HERROR
18122    }
18123    /*
18124    * Whitespace value.
18125    */
18126    res = xmlSchemaTypeFixupWhitespace(type);
18127    HFAILURE HERROR
18128    xmlSchemaTypeFixupOptimFacets(type);
18129
18130exit_error:
18131#ifdef DEBUG_TYPE
18132    xmlSchemaDebugFixedType(pctxt, type);
18133#endif
18134    if (olderrs != pctxt->nberrors)
18135	return(pctxt->err);
18136    return(0);
18137
18138exit_failure:
18139#ifdef DEBUG_TYPE
18140    xmlSchemaDebugFixedType(pctxt, type);
18141#endif
18142    return(-1);
18143}
18144
18145static int
18146xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18147			  xmlSchemaTypePtr type)
18148{
18149    int res = 0, olderrs = pctxt->nberrors;
18150    xmlSchemaTypePtr baseType = type->baseType;
18151
18152    if (! WXS_IS_TYPE_NOT_FIXED(type))
18153	return(0);
18154    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18155    if (baseType == NULL) {
18156	PERROR_INT("xmlSchemaFixupComplexType",
18157	    "missing baseType");
18158	goto exit_failure;
18159    }
18160    /*
18161    * Fixup the base type.
18162    */
18163    if (WXS_IS_TYPE_NOT_FIXED(baseType))
18164	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18165    if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18166	/*
18167	* Skip fixup if the base type is invalid.
18168	* TODO: Generate a warning!
18169	*/
18170	return(0);
18171    }
18172    /*
18173    * This basically checks if the base type can be derived.
18174    */
18175    res = xmlSchemaCheckSRCCT(pctxt, type);
18176    HFAILURE HERROR
18177    /*
18178    * Fixup the content type.
18179    */
18180    if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18181	/*
18182	* Corresponds to <complexType><simpleContent>...
18183	*/
18184	if ((WXS_IS_COMPLEX(baseType)) &&
18185	    (baseType->contentTypeDef != NULL) &&
18186	    (WXS_IS_RESTRICTION(type))) {
18187	    xmlSchemaTypePtr contentBase, content;
18188#ifdef ENABLE_NAMED_LOCALS
18189	    char buf[30];
18190	    const xmlChar *tmpname;
18191#endif
18192	    /*
18193	    * SPEC (1) If <restriction> + base type is <complexType>,
18194	    * "whose own {content type} is a simple type..."
18195	    */
18196	    if (type->contentTypeDef != NULL) {
18197		/*
18198		* SPEC (1.1) "the simple type definition corresponding to the
18199		* <simpleType> among the [children] of <restriction> if there
18200		* is one;"
18201		* Note that this "<simpleType> among the [children]" was put
18202		* into ->contentTypeDef during parsing.
18203		*/
18204		contentBase = type->contentTypeDef;
18205		type->contentTypeDef = NULL;
18206	    } else {
18207		/*
18208		* (1.2) "...otherwise (<restriction> has no <simpleType>
18209		* among its [children]), the simple type definition which
18210		* is the {content type} of the ... base type."
18211		*/
18212		contentBase = baseType->contentTypeDef;
18213	    }
18214	    /*
18215	    * SPEC
18216	    * "... a simple type definition which restricts the simple
18217	    * type definition identified in clause 1.1 or clause 1.2
18218	    * with a set of facet components"
18219	    *
18220	    * Create the anonymous simple type, which will be the content
18221	    * type of the complex type.
18222	    */
18223#ifdef ENABLE_NAMED_LOCALS
18224	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18225	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18226	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18227		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18228		type->node, 0);
18229#else
18230	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18231		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18232		type->node, 0);
18233#endif
18234	    if (content == NULL)
18235		goto exit_failure;
18236	    /*
18237	    * We will use the same node as for the <complexType>
18238	    * to have it somehow anchored in the schema doc.
18239	    */
18240	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18241	    content->baseType = contentBase;
18242	    /*
18243	    * Move the facets, previously anchored on the
18244	    * complexType during parsing.
18245	    */
18246	    content->facets = type->facets;
18247	    type->facets = NULL;
18248	    content->facetSet = type->facetSet;
18249	    type->facetSet = NULL;
18250
18251	    type->contentTypeDef = content;
18252	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18253		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18254	    /*
18255	    * Fixup the newly created type. We don't need to check
18256	    * for circularity here.
18257	    */
18258	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18259	    HFAILURE HERROR
18260	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18261	    HFAILURE HERROR
18262
18263	} else if ((WXS_IS_COMPLEX(baseType)) &&
18264	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18265	    (WXS_IS_RESTRICTION(type))) {
18266	    /*
18267	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18268	    * an emptiable particle, then a simple type definition which
18269	    * restricts the <restriction>'s <simpleType> child.
18270	    */
18271	    if ((type->contentTypeDef == NULL) ||
18272		(type->contentTypeDef->baseType == NULL)) {
18273		/*
18274		* TODO: Check if this ever happens.
18275		*/
18276		xmlSchemaPCustomErr(pctxt,
18277		    XML_SCHEMAP_INTERNAL,
18278		    WXS_BASIC_CAST type, NULL,
18279		    "Internal error: xmlSchemaTypeFixup, "
18280		    "complex type '%s': the <simpleContent><restriction> "
18281		    "is missing a <simpleType> child, but was not catched "
18282		    "by xmlSchemaCheckSRCCT()", type->name);
18283		goto exit_failure;
18284	    }
18285	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18286	    /*
18287	    * SPEC (3) If <extension> + base is <complexType> with
18288	    * <simpleType> content, "...then the {content type} of that
18289	    * complex type definition"
18290	    */
18291	    if (baseType->contentTypeDef == NULL) {
18292		/*
18293		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18294		* should have catched this already.
18295		*/
18296		xmlSchemaPCustomErr(pctxt,
18297		    XML_SCHEMAP_INTERNAL,
18298		    WXS_BASIC_CAST type, NULL,
18299		    "Internal error: xmlSchemaTypeFixup, "
18300		    "complex type '%s': the <extension>ed base type is "
18301		    "a complex type with no simple content type",
18302		    type->name);
18303		goto exit_failure;
18304	    }
18305	    type->contentTypeDef = baseType->contentTypeDef;
18306	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18307	    /*
18308	    * SPEC (4) <extension> + base is <simpleType>
18309	    * "... then that simple type definition"
18310	    */
18311	    type->contentTypeDef = baseType;
18312	} else {
18313	    /*
18314	    * TODO: Check if this ever happens.
18315	    */
18316	    xmlSchemaPCustomErr(pctxt,
18317		XML_SCHEMAP_INTERNAL,
18318		WXS_BASIC_CAST type, NULL,
18319		"Internal error: xmlSchemaTypeFixup, "
18320		"complex type '%s' with <simpleContent>: unhandled "
18321		"derivation case", type->name);
18322	    goto exit_failure;
18323	}
18324    } else {
18325	int dummySequence = 0;
18326	xmlSchemaParticlePtr particle =
18327	    (xmlSchemaParticlePtr) type->subtypes;
18328	/*
18329	* Corresponds to <complexType><complexContent>...
18330	*
18331	* NOTE that the effective mixed was already set during parsing of
18332	* <complexType> and <complexContent>; its flag value is
18333	* XML_SCHEMAS_TYPE_MIXED.
18334	*
18335	* Compute the "effective content":
18336	* (2.1.1) + (2.1.2) + (2.1.3)
18337	*/
18338	if ((particle == NULL) ||
18339	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18340	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18341	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18342	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18343	    (particle->minOccurs == 0))) &&
18344	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18345	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18346		/*
18347		* SPEC (2.1.4) "If the �effective mixed� is true, then
18348		* a particle whose properties are as follows:..."
18349		*
18350		* Empty sequence model group with
18351		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18352		* NOTE that we sill assign it the <complexType> node to
18353		* somehow anchor it in the doc.
18354		*/
18355		if ((particle == NULL) ||
18356		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18357		    /*
18358		    * Create the particle.
18359		    */
18360		    particle = xmlSchemaAddParticle(pctxt,
18361			type->node, 1, 1);
18362		    if (particle == NULL)
18363			goto exit_failure;
18364		    /*
18365		    * Create the model group.
18366		    */ /* URGENT TODO: avoid adding to pending items. */
18367		    particle->children = (xmlSchemaTreeItemPtr)
18368			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18369			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18370		    if (particle->children == NULL)
18371			goto exit_failure;
18372
18373		    type->subtypes = (xmlSchemaTypePtr) particle;
18374		}
18375		dummySequence = 1;
18376		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18377	    } else {
18378		/*
18379		* SPEC (2.1.5) "otherwise empty"
18380		*/
18381		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18382	    }
18383	} else {
18384	    /*
18385	    * SPEC (2.2) "otherwise the particle corresponding to the
18386	    * <all>, <choice>, <group> or <sequence> among the
18387	    * [children]."
18388	    */
18389	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18390	}
18391	/*
18392	* Compute the "content type".
18393	*/
18394	if (WXS_IS_RESTRICTION(type)) {
18395	    /*
18396	    * SPEC (3.1) "If <restriction>..."
18397	    * (3.1.1) + (3.1.2) */
18398	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18399		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18400		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18401	    }
18402	} else {
18403	    /*
18404	    * SPEC (3.2) "If <extension>..."
18405	    */
18406	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18407		/*
18408		* SPEC (3.2.1)
18409		* "If the �effective content� is empty, then the
18410		*  {content type} of the [...] base ..."
18411		*/
18412		type->contentType = baseType->contentType;
18413		type->subtypes = baseType->subtypes;
18414		/*
18415		* Fixes bug #347316:
18416		* This is the case when the base type has a simple
18417		* type definition as content.
18418		*/
18419		type->contentTypeDef = baseType->contentTypeDef;
18420		/*
18421		* NOTE that the effective mixed is ignored here.
18422		*/
18423	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18424		/*
18425		* SPEC (3.2.2)
18426		*/
18427		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18428		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18429	    } else {
18430		/*
18431		* SPEC (3.2.3)
18432		*/
18433		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18434		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18435		    /*
18436		    * "A model group whose {compositor} is sequence and whose
18437		    * {particles} are..."
18438		    */
18439		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18440		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18441		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18442			XML_SCHEMA_TYPE_ALL))
18443		{
18444		    /*
18445		    * SPEC cos-all-limited (1)
18446		    */
18447		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18448			/* TODO: error code */
18449			XML_SCHEMAP_COS_ALL_LIMITED,
18450			WXS_ITEM_NODE(type), NULL,
18451			"The type has an 'all' model group in its "
18452			"{content type} and thus cannot be derived from "
18453			"a non-empty type, since this would produce a "
18454			"'sequence' model group containing the 'all' "
18455			"model group; 'all' model groups are not "
18456			"allowed to appear inside other model groups",
18457			NULL, NULL);
18458
18459		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18460		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18461		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18462			XML_SCHEMA_TYPE_ALL))
18463		{
18464		    /*
18465		    * SPEC cos-all-limited (1)
18466		    */
18467		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18468			/* TODO: error code */
18469			XML_SCHEMAP_COS_ALL_LIMITED,
18470			WXS_ITEM_NODE(type), NULL,
18471			"A type cannot be derived by extension from a type "
18472			"which has an 'all' model group in its "
18473			"{content type}, since this would produce a "
18474			"'sequence' model group containing the 'all' "
18475			"model group; 'all' model groups are not "
18476			"allowed to appear inside other model groups",
18477			NULL, NULL);
18478
18479		} else if (! dummySequence) {
18480		    xmlSchemaTreeItemPtr effectiveContent =
18481			(xmlSchemaTreeItemPtr) type->subtypes;
18482		    /*
18483		    * Create the particle.
18484		    */
18485		    particle = xmlSchemaAddParticle(pctxt,
18486			type->node, 1, 1);
18487		    if (particle == NULL)
18488			goto exit_failure;
18489		    /*
18490		    * Create the "sequence" model group.
18491		    */
18492		    particle->children = (xmlSchemaTreeItemPtr)
18493			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18494			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18495		    if (particle->children == NULL)
18496			goto exit_failure;
18497		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18498		    /*
18499		    * SPEC "the particle of the {content type} of
18500		    * the ... base ..."
18501		    * Create a duplicate of the base type's particle
18502		    * and assign its "term" to it.
18503		    */
18504		    particle->children->children =
18505			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18506			type->node,
18507			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18508			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18509		    if (particle->children->children == NULL)
18510			goto exit_failure;
18511		    particle = (xmlSchemaParticlePtr)
18512			particle->children->children;
18513		    particle->children =
18514			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18515		    /*
18516		    * SPEC "followed by the �effective content�."
18517		    */
18518		    particle->next = effectiveContent;
18519		    /*
18520		    * This all will result in:
18521		    * new-particle
18522		    *   --> new-sequence(
18523		    *         new-particle
18524		    *           --> base-model,
18525		    *         this-particle
18526		    *	        --> this-model
18527		    *	    )
18528		    */
18529		} else {
18530		    /*
18531		    * This is the case when there is already an empty
18532		    * <sequence> with minOccurs==maxOccurs==1.
18533		    * Just add the base types's content type.
18534		    * NOTE that, although we miss to add an intermediate
18535		    * <sequence>, this should produce no difference to
18536		    * neither the regex compilation of the content model,
18537		    * nor to the complex type contraints.
18538		    */
18539		    particle->children->children =
18540			(xmlSchemaTreeItemPtr) baseType->subtypes;
18541		}
18542	    }
18543	}
18544    }
18545    /*
18546    * Now fixup attribute uses:
18547    *   - expand attr. group references
18548    *     - intersect attribute wildcards
18549    *   - inherit attribute uses of the base type
18550    *   - inherit or union attr. wildcards if extending
18551    *   - apply attr. use prohibitions if restricting
18552    */
18553    res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18554    HFAILURE HERROR
18555    /*
18556    * Apply the complex type component constraints; this will not
18557    * check attributes, since this is done in
18558    * xmlSchemaFixupTypeAttributeUses().
18559    */
18560    res = xmlSchemaCheckCTComponent(pctxt, type);
18561    HFAILURE HERROR
18562
18563#ifdef DEBUG_TYPE
18564    xmlSchemaDebugFixedType(pctxt, type);
18565#endif
18566    if (olderrs != pctxt->nberrors)
18567	return(pctxt->err);
18568    else
18569	return(0);
18570
18571exit_error:
18572    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18573#ifdef DEBUG_TYPE
18574    xmlSchemaDebugFixedType(pctxt, type);
18575#endif
18576    return(pctxt->err);
18577
18578exit_failure:
18579    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18580#ifdef DEBUG_TYPE
18581    xmlSchemaDebugFixedType(pctxt, type);
18582#endif
18583    return(-1);
18584}
18585
18586
18587/**
18588 * xmlSchemaTypeFixup:
18589 * @typeDecl:  the schema type definition
18590 * @ctxt:  the schema parser context
18591 *
18592 * Fixes the content model of the type.
18593 * URGENT TODO: We need an int result!
18594 */
18595static int
18596xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18597                   xmlSchemaAbstractCtxtPtr actxt)
18598{
18599    if (type == NULL)
18600        return(0);
18601    if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18602	AERROR_INT("xmlSchemaTypeFixup",
18603	    "this function needs a parser context");
18604	return(-1);
18605    }
18606    if (! WXS_IS_TYPE_NOT_FIXED(type))
18607	return(0);
18608    if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18609	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18610    else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18611	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18612    return(0);
18613}
18614
18615/**
18616 * xmlSchemaCheckFacet:
18617 * @facet:  the facet
18618 * @typeDecl:  the schema type definition
18619 * @pctxt:  the schema parser context or NULL
18620 * @name: the optional name of the type
18621 *
18622 * Checks and computes the values of facets.
18623 *
18624 * Returns 0 if valid, a positive error code if not valid and
18625 *         -1 in case of an internal or API error.
18626 */
18627int
18628xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18629                    xmlSchemaTypePtr typeDecl,
18630                    xmlSchemaParserCtxtPtr pctxt,
18631		    const xmlChar * name ATTRIBUTE_UNUSED)
18632{
18633    int ret = 0, ctxtGiven;
18634
18635    if ((facet == NULL) || (typeDecl == NULL))
18636        return(-1);
18637    /*
18638    * TODO: will the parser context be given if used from
18639    * the relaxNG module?
18640    */
18641    if (pctxt == NULL)
18642	ctxtGiven = 0;
18643    else
18644	ctxtGiven = 1;
18645
18646    switch (facet->type) {
18647        case XML_SCHEMA_FACET_MININCLUSIVE:
18648        case XML_SCHEMA_FACET_MINEXCLUSIVE:
18649        case XML_SCHEMA_FACET_MAXINCLUSIVE:
18650        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18651	case XML_SCHEMA_FACET_ENUMERATION: {
18652                /*
18653                 * Okay we need to validate the value
18654                 * at that point.
18655                 */
18656		xmlSchemaTypePtr base;
18657
18658		/* 4.3.5.5 Constraints on enumeration Schema Components
18659		* Schema Component Constraint: enumeration valid restriction
18660		* It is an �error� if any member of {value} is not in the
18661		* �value space� of {base type definition}.
18662		*
18663		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18664		* The value �must� be in the
18665		* �value space� of the �base type�.
18666		*/
18667		/*
18668		* This function is intended to deliver a compiled value
18669		* on the facet. In this implementation of XML Schemata the
18670		* type holding a facet, won't be a built-in type.
18671		* Thus to ensure that other API
18672		* calls (relaxng) do work, if the given type is a built-in
18673		* type, we will assume that the given built-in type *is
18674		* already* the base type.
18675		*/
18676		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18677		    base = typeDecl->baseType;
18678		    if (base == NULL) {
18679			PERROR_INT("xmlSchemaCheckFacet",
18680			    "a type user derived type has no base type");
18681			return (-1);
18682		    }
18683		} else
18684		    base = typeDecl;
18685
18686		if (! ctxtGiven) {
18687		    /*
18688		    * A context is needed if called from RelaxNG.
18689		    */
18690		    pctxt = xmlSchemaNewParserCtxt("*");
18691		    if (pctxt == NULL)
18692			return (-1);
18693		}
18694		/*
18695		* NOTE: This call does not check the content nodes,
18696		* since they are not available:
18697		* facet->node is just the node holding the facet
18698		* definition, *not* the attribute holding the *value*
18699		* of the facet.
18700		*/
18701		ret = xmlSchemaVCheckCVCSimpleType(
18702		    ACTXT_CAST pctxt, facet->node, base,
18703		    facet->value, &(facet->val), 1, 1, 0);
18704                if (ret != 0) {
18705		    if (ret < 0) {
18706			/* No error message for RelaxNG. */
18707			if (ctxtGiven) {
18708			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18709				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18710				"Internal error: xmlSchemaCheckFacet, "
18711				"failed to validate the value '%s' of the "
18712				"facet '%s' against the base type",
18713				facet->value, xmlSchemaFacetTypeToString(facet->type));
18714			}
18715			goto internal_error;
18716		    }
18717		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18718		    /* No error message for RelaxNG. */
18719		    if (ctxtGiven) {
18720			xmlChar *str = NULL;
18721
18722			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18723			    ret, facet->node, WXS_BASIC_CAST facet,
18724			    "The value '%s' of the facet does not validate "
18725			    "against the base type '%s'",
18726			    facet->value,
18727			    xmlSchemaFormatQName(&str,
18728				base->targetNamespace, base->name));
18729			FREE_AND_NULL(str);
18730		    }
18731		    goto exit;
18732                } else if (facet->val == NULL) {
18733		    if (ctxtGiven) {
18734			PERROR_INT("xmlSchemaCheckFacet",
18735			    "value was not computed");
18736		    }
18737		    TODO
18738		}
18739                break;
18740            }
18741        case XML_SCHEMA_FACET_PATTERN:
18742            facet->regexp = xmlRegexpCompile(facet->value);
18743            if (facet->regexp == NULL) {
18744		ret = XML_SCHEMAP_REGEXP_INVALID;
18745		/* No error message for RelaxNG. */
18746		if (ctxtGiven) {
18747		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18748			ret, facet->node, WXS_BASIC_CAST typeDecl,
18749			"The value '%s' of the facet 'pattern' is not a "
18750			"valid regular expression",
18751			facet->value, NULL);
18752		}
18753            }
18754            break;
18755        case XML_SCHEMA_FACET_TOTALDIGITS:
18756        case XML_SCHEMA_FACET_FRACTIONDIGITS:
18757        case XML_SCHEMA_FACET_LENGTH:
18758        case XML_SCHEMA_FACET_MAXLENGTH:
18759        case XML_SCHEMA_FACET_MINLENGTH:
18760
18761	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18762		ret = xmlSchemaValidatePredefinedType(
18763		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18764		    facet->value, &(facet->val));
18765	    } else {
18766		ret = xmlSchemaValidatePredefinedType(
18767		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18768		    facet->value, &(facet->val));
18769	    }
18770	    if (ret != 0) {
18771		if (ret < 0) {
18772		    /* No error message for RelaxNG. */
18773		    if (ctxtGiven) {
18774			PERROR_INT("xmlSchemaCheckFacet",
18775			    "validating facet value");
18776		    }
18777		    goto internal_error;
18778		}
18779		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18780		/* No error message for RelaxNG. */
18781		if (ctxtGiven) {
18782		    /* error code */
18783		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18784			ret, facet->node, WXS_BASIC_CAST typeDecl,
18785			"The value '%s' of the facet '%s' is not a valid '%s'",
18786			facet->value,
18787			xmlSchemaFacetTypeToString(facet->type),
18788			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18789			    BAD_CAST "nonNegativeInteger" :
18790			    BAD_CAST "positiveInteger",
18791			NULL);
18792		}
18793	    }
18794	    break;
18795
18796        case XML_SCHEMA_FACET_WHITESPACE:{
18797                if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18798                    facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18799                } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18800                    facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18801                } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18802                    facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18803                } else {
18804		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18805                    /* No error message for RelaxNG. */
18806		    if (ctxtGiven) {
18807			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18808			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18809			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18810			    "The value '%s' of the facet 'whitespace' is not "
18811			    "valid", facet->value, NULL);
18812                    }
18813                }
18814            }
18815        default:
18816            break;
18817    }
18818exit:
18819    if ((! ctxtGiven) && (pctxt != NULL))
18820	xmlSchemaFreeParserCtxt(pctxt);
18821    return (ret);
18822internal_error:
18823    if ((! ctxtGiven) && (pctxt != NULL))
18824	xmlSchemaFreeParserCtxt(pctxt);
18825    return (-1);
18826}
18827
18828/**
18829 * xmlSchemaCheckFacetValues:
18830 * @typeDecl:  the schema type definition
18831 * @ctxt:  the schema parser context
18832 *
18833 * Checks the default values types, especially for facets
18834 */
18835static int
18836xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18837			  xmlSchemaParserCtxtPtr pctxt)
18838{
18839    int res, olderrs = pctxt->nberrors;
18840    const xmlChar *name = typeDecl->name;
18841    /*
18842    * NOTE: It is intended to use the facets list, instead
18843    * of facetSet.
18844    */
18845    if (typeDecl->facets != NULL) {
18846	xmlSchemaFacetPtr facet = typeDecl->facets;
18847
18848	/*
18849	* Temporarily assign the "schema" to the validation context
18850	* of the parser context. This is needed for NOTATION validation.
18851	*/
18852	if (pctxt->vctxt == NULL) {
18853	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18854		return(-1);
18855	}
18856	pctxt->vctxt->schema = pctxt->schema;
18857	while (facet != NULL) {
18858	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18859	    HFAILURE
18860	    facet = facet->next;
18861	}
18862	pctxt->vctxt->schema = NULL;
18863    }
18864    if (olderrs != pctxt->nberrors)
18865	return(pctxt->err);
18866    return(0);
18867exit_failure:
18868    return(-1);
18869}
18870
18871/**
18872 * xmlSchemaGetCircModelGrDefRef:
18873 * @ctxtMGroup: the searched model group
18874 * @selfMGroup: the second searched model group
18875 * @particle: the first particle
18876 *
18877 * This one is intended to be used by
18878 * xmlSchemaCheckGroupDefCircular only.
18879 *
18880 * Returns the particle with the circular model group definition reference,
18881 * otherwise NULL.
18882 */
18883static xmlSchemaTreeItemPtr
18884xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18885			      xmlSchemaTreeItemPtr particle)
18886{
18887    xmlSchemaTreeItemPtr circ = NULL;
18888    xmlSchemaTreeItemPtr term;
18889    xmlSchemaModelGroupDefPtr gdef;
18890
18891    for (; particle != NULL; particle = particle->next) {
18892	term = particle->children;
18893	if (term == NULL)
18894	    continue;
18895	switch (term->type) {
18896	    case XML_SCHEMA_TYPE_GROUP:
18897		gdef = (xmlSchemaModelGroupDefPtr) term;
18898		if (gdef == groupDef)
18899		    return (particle);
18900		/*
18901		* Mark this model group definition to avoid infinite
18902		* recursion on circular references not yet examined.
18903		*/
18904		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18905		    continue;
18906		if (gdef->children != NULL) {
18907		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18908		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18909			gdef->children->children);
18910		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18911		    if (circ != NULL)
18912			return (circ);
18913		}
18914		break;
18915	    case XML_SCHEMA_TYPE_SEQUENCE:
18916	    case XML_SCHEMA_TYPE_CHOICE:
18917	    case XML_SCHEMA_TYPE_ALL:
18918		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18919		if (circ != NULL)
18920		    return (circ);
18921		break;
18922	    default:
18923		break;
18924	}
18925    }
18926    return (NULL);
18927}
18928
18929/**
18930 * xmlSchemaCheckGroupDefCircular:
18931 * @item:  the model group definition
18932 * @ctxt:  the parser context
18933 * @name:  the name
18934 *
18935 * Checks for circular references to model group definitions.
18936 */
18937static void
18938xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18939			       xmlSchemaParserCtxtPtr ctxt)
18940{
18941    /*
18942    * Schema Component Constraint: Model Group Correct
18943    * 2 Circular groups are disallowed. That is, within the {particles}
18944    * of a group there must not be at any depth a particle whose {term}
18945    * is the group itself.
18946    */
18947    if ((item == NULL) ||
18948	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18949	(item->children == NULL))
18950	return;
18951    {
18952	xmlSchemaTreeItemPtr circ;
18953
18954	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18955	if (circ != NULL) {
18956	    xmlChar *str = NULL;
18957	    /*
18958	    * TODO: The error report is not adequate: this constraint
18959	    * is defined for model groups but not definitions, but since
18960	    * there cannot be any circular model groups without a model group
18961	    * definition (if not using a construction API), we check those
18962	    * defintions only.
18963	    */
18964	    xmlSchemaPCustomErr(ctxt,
18965		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18966		NULL, WXS_ITEM_NODE(circ),
18967		"Circular reference to the model group definition '%s' "
18968		"defined", xmlSchemaFormatQName(&str,
18969		    item->targetNamespace, item->name));
18970	    FREE_AND_NULL(str)
18971	    /*
18972	    * NOTE: We will cut the reference to avoid further
18973	    * confusion of the processor. This is a fatal error.
18974	    */
18975	    circ->children = NULL;
18976	}
18977    }
18978}
18979
18980/**
18981 * xmlSchemaModelGroupToModelGroupDefFixup:
18982 * @ctxt:  the parser context
18983 * @mg:  the model group
18984 *
18985 * Assigns the model group of model group definitions to the "term"
18986 * of the referencing particle.
18987 * In xmlSchemaResolveModelGroupParticleReferences the model group
18988 * definitions were assigned to the "term", since needed for the
18989 * circularity check.
18990 *
18991 * Schema Component Constraint:
18992 *     All Group Limited (cos-all-limited) (1.2)
18993 */
18994static void
18995xmlSchemaModelGroupToModelGroupDefFixup(
18996    xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18997    xmlSchemaModelGroupPtr mg)
18998{
18999    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19000
19001    while (particle != NULL) {
19002	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19003	    ((WXS_PARTICLE_TERM(particle))->type !=
19004		XML_SCHEMA_TYPE_GROUP))
19005	{
19006	    particle = WXS_PTC_CAST particle->next;
19007	    continue;
19008	}
19009	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19010	    /*
19011	    * TODO: Remove the particle.
19012	    */
19013	    WXS_PARTICLE_TERM(particle) = NULL;
19014	    particle = WXS_PTC_CAST particle->next;
19015	    continue;
19016	}
19017	/*
19018	* Assign the model group to the {term} of the particle.
19019	*/
19020	WXS_PARTICLE_TERM(particle) =
19021	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19022
19023	particle = WXS_PTC_CAST particle->next;
19024    }
19025}
19026
19027/**
19028 * xmlSchemaCheckAttrGroupCircularRecur:
19029 * @ctxtGr: the searched attribute group
19030 * @attr: the current attribute list to be processed
19031 *
19032 * This one is intended to be used by
19033 * xmlSchemaCheckAttrGroupCircular only.
19034 *
19035 * Returns the circular attribute grou reference, otherwise NULL.
19036 */
19037static xmlSchemaQNameRefPtr
19038xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19039				     xmlSchemaItemListPtr list)
19040{
19041    xmlSchemaAttributeGroupPtr gr;
19042    xmlSchemaQNameRefPtr ref, circ;
19043    int i;
19044    /*
19045    * We will search for an attribute group reference which
19046    * references the context attribute group.
19047    */
19048    for (i = 0; i < list->nbItems; i++) {
19049	ref = list->items[i];
19050	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19051	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19052	    (ref->item != NULL))
19053	{
19054	    gr = WXS_ATTR_GROUP_CAST ref->item;
19055	    if (gr == ctxtGr)
19056		return(ref);
19057	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19058		continue;
19059	    /*
19060	    * Mark as visited to avoid infinite recursion on
19061	    * circular references not yet examined.
19062	    */
19063	    if ((gr->attrUses) &&
19064		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19065	    {
19066		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19067		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19068		    (xmlSchemaItemListPtr) gr->attrUses);
19069		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19070		if (circ != NULL)
19071		    return (circ);
19072	    }
19073
19074	}
19075    }
19076    return (NULL);
19077}
19078
19079/**
19080 * xmlSchemaCheckAttrGroupCircular:
19081 * attrGr:  the attribute group definition
19082 * @ctxt:  the parser context
19083 * @name:  the name
19084 *
19085 * Checks for circular references of attribute groups.
19086 */
19087static int
19088xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19089				xmlSchemaParserCtxtPtr ctxt)
19090{
19091    /*
19092    * Schema Representation Constraint:
19093    * Attribute Group Definition Representation OK
19094    * 3 Circular group reference is disallowed outside <redefine>.
19095    * That is, unless this element information item's parent is
19096    * <redefine>, then among the [children], if any, there must
19097    * not be an <attributeGroup> with ref [attribute] which resolves
19098    * to the component corresponding to this <attributeGroup>. Indirect
19099    * circularity is also ruled out. That is, when QName resolution
19100    * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19101    * any <attributeGroup>s with a ref [attribute] among the [children],
19102    * it must not be the case that a �QName� is encountered at any depth
19103    * which resolves to the component corresponding to this <attributeGroup>.
19104    */
19105    if (attrGr->attrUses == NULL)
19106	return(0);
19107    else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19108	return(0);
19109    else {
19110	xmlSchemaQNameRefPtr circ;
19111
19112	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19113	    (xmlSchemaItemListPtr) attrGr->attrUses);
19114	if (circ != NULL) {
19115	    xmlChar *str = NULL;
19116	    /*
19117	    * TODO: Report the referenced attr group as QName.
19118	    */
19119	    xmlSchemaPCustomErr(ctxt,
19120		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19121		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19122		"Circular reference to the attribute group '%s' "
19123		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19124	    FREE_AND_NULL(str);
19125	    /*
19126	    * NOTE: We will cut the reference to avoid further
19127	    * confusion of the processor.
19128	    * BADSPEC TODO: The spec should define how to process in this case.
19129	    */
19130	    circ->item = NULL;
19131	    return(ctxt->err);
19132	}
19133    }
19134    return(0);
19135}
19136
19137static int
19138xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19139				  xmlSchemaAttributeGroupPtr attrGr);
19140
19141/**
19142 * xmlSchemaExpandAttributeGroupRefs:
19143 * @pctxt: the parser context
19144 * @node: the node of the component holding the attribute uses
19145 * @completeWild: the intersected wildcard to be returned
19146 * @list: the attribute uses
19147 *
19148 * Substitutes contained attribute group references
19149 * for their attribute uses. Wilcards are intersected.
19150 * Attribute use prohibitions are removed from the list
19151 * and returned via the @prohibs list.
19152 * Pointlessness of attr. prohibs, if a matching attr. decl
19153 * is existent a well, are checked.
19154 */
19155static int
19156xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19157				  xmlSchemaBasicItemPtr item,
19158				  xmlSchemaWildcardPtr *completeWild,
19159				  xmlSchemaItemListPtr list,
19160				  xmlSchemaItemListPtr prohibs)
19161{
19162    xmlSchemaAttributeGroupPtr gr;
19163    xmlSchemaAttributeUsePtr use;
19164    xmlSchemaItemListPtr sublist;
19165    int i, j;
19166    int created = (*completeWild == NULL) ? 0 : 1;
19167
19168    if (prohibs)
19169	prohibs->nbItems = 0;
19170
19171    for (i = 0; i < list->nbItems; i++) {
19172	use = list->items[i];
19173
19174	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19175	    if (prohibs == NULL) {
19176		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19177		    "unexpected attr prohibition found");
19178		return(-1);
19179	    }
19180	    /*
19181	    * Remove from attribute uses.
19182	    */
19183	    if (xmlSchemaItemListRemove(list, i) == -1)
19184		return(-1);
19185	    i--;
19186	    /*
19187	    * Note that duplicate prohibitions were already
19188	    * handled at parsing time.
19189	    */
19190	    /*
19191	    * Add to list of prohibitions.
19192	    */
19193	    xmlSchemaItemListAddSize(prohibs, 2, use);
19194	    continue;
19195	}
19196	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19197	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19198	{
19199	    if ((WXS_QNAME_CAST use)->item == NULL)
19200		return(-1);
19201	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19202	    /*
19203	    * Expand the referenced attr. group.
19204	    * TODO: remove this, this is done in a previous step, so
19205	    * already done here.
19206	    */
19207	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19208		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19209		    return(-1);
19210	    }
19211	    /*
19212	    * Build the 'complete' wildcard; i.e. intersect multiple
19213	    * wildcards.
19214	    */
19215	    if (gr->attributeWildcard != NULL) {
19216		if (*completeWild == NULL) {
19217		    *completeWild = gr->attributeWildcard;
19218		} else {
19219		    if (! created) {
19220			xmlSchemaWildcardPtr tmpWild;
19221
19222			 /*
19223			* Copy the first encountered wildcard as context,
19224			* except for the annotation.
19225			*
19226			* Although the complete wildcard might not correspond
19227			* to any node in the schema, we will anchor it on
19228			* the node of the owner component.
19229			*/
19230			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19231			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19232			    WXS_ITEM_NODE(item));
19233			if (tmpWild == NULL)
19234			    return(-1);
19235			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19236			    tmpWild, *completeWild) == -1)
19237			    return (-1);
19238			tmpWild->processContents = (*completeWild)->processContents;
19239			*completeWild = tmpWild;
19240			created = 1;
19241		    }
19242
19243		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19244			gr->attributeWildcard) == -1)
19245			return(-1);
19246		}
19247	    }
19248	    /*
19249	    * Just remove the reference if the referenced group does not
19250	    * contain any attribute uses.
19251	    */
19252	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19253	    if ((sublist == NULL) || sublist->nbItems == 0) {
19254		if (xmlSchemaItemListRemove(list, i) == -1)
19255		    return(-1);
19256		i--;
19257		continue;
19258	    }
19259	    /*
19260	    * Add the attribute uses.
19261	    */
19262	    list->items[i] = sublist->items[0];
19263	    if (sublist->nbItems != 1) {
19264		for (j = 1; j < sublist->nbItems; j++) {
19265		    i++;
19266		    if (xmlSchemaItemListInsert(list,
19267			    sublist->items[j], i) == -1)
19268			return(-1);
19269		}
19270	    }
19271	}
19272
19273    }
19274    /*
19275    * Handle pointless prohibitions of declared attributes.
19276    */
19277    if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19278	xmlSchemaAttributeUseProhibPtr prohib;
19279
19280	for (i = prohibs->nbItems -1; i >= 0; i--) {
19281	    prohib = prohibs->items[i];
19282	    for (j = 0; j < list->nbItems; j++) {
19283		use = list->items[j];
19284
19285		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19286		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19287		{
19288		    xmlChar *str = NULL;
19289
19290		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19291			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19292			prohib->node, NULL,
19293			"Skipping pointless attribute use prohibition "
19294			"'%s', since a corresponding attribute use "
19295			"exists already in the type definition",
19296			xmlSchemaFormatQName(&str,
19297			    prohib->targetNamespace, prohib->name),
19298			NULL, NULL);
19299		    FREE_AND_NULL(str);
19300		    /*
19301		    * Remove the prohibition.
19302		    */
19303		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19304			return(-1);
19305		    break;
19306		}
19307	    }
19308	}
19309    }
19310    return(0);
19311}
19312
19313/**
19314 * xmlSchemaAttributeGroupExpandRefs:
19315 * @pctxt:  the parser context
19316 * @attrGr:  the attribute group definition
19317 *
19318 * Computation of:
19319 * {attribute uses} property
19320 * {attribute wildcard} property
19321 *
19322 * Substitutes contained attribute group references
19323 * for their attribute uses. Wilcards are intersected.
19324 */
19325static int
19326xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19327				  xmlSchemaAttributeGroupPtr attrGr)
19328{
19329    if ((attrGr->attrUses == NULL) ||
19330	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19331	return(0);
19332
19333    attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19334    if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19335	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19336	return(-1);
19337    return(0);
19338}
19339
19340/**
19341 * xmlSchemaAttributeGroupExpandRefs:
19342 * @pctxt:  the parser context
19343 * @attrGr:  the attribute group definition
19344 *
19345 * Substitutes contained attribute group references
19346 * for their attribute uses. Wilcards are intersected.
19347 *
19348 * Schema Component Constraint:
19349 *    Attribute Group Definition Properties Correct (ag-props-correct)
19350 */
19351static int
19352xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19353				  xmlSchemaAttributeGroupPtr attrGr)
19354{
19355    /*
19356    * SPEC ag-props-correct
19357    * (1) "The values of the properties of an attribute group definition
19358    * must be as described in the property tableau in The Attribute
19359    * Group Definition Schema Component (�3.6.1), modulo the impact of
19360    * Missing Sub-components (�5.3);"
19361    */
19362
19363    if ((attrGr->attrUses != NULL) &&
19364	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19365    {
19366	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19367	xmlSchemaAttributeUsePtr use, tmp;
19368	int i, j, hasId = 0;
19369
19370	for (i = uses->nbItems -1; i >= 0; i--) {
19371	    use = uses->items[i];
19372	    /*
19373	    * SPEC ag-props-correct
19374	    * (2) "Two distinct members of the {attribute uses} must not have
19375	    * {attribute declaration}s both of whose {name}s match and whose
19376	    * {target namespace}s are identical."
19377	    */
19378	    if (i > 0) {
19379		for (j = i -1; j >= 0; j--) {
19380		    tmp = uses->items[j];
19381		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19382			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19383			(WXS_ATTRUSE_DECL_TNS(use) ==
19384			WXS_ATTRUSE_DECL_TNS(tmp)))
19385		    {
19386			xmlChar *str = NULL;
19387
19388			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19389			    XML_SCHEMAP_AG_PROPS_CORRECT,
19390			    attrGr->node, WXS_BASIC_CAST attrGr,
19391			    "Duplicate %s",
19392			    xmlSchemaGetComponentDesignation(&str, use),
19393			    NULL);
19394			FREE_AND_NULL(str);
19395			/*
19396			* Remove the duplicate.
19397			*/
19398			if (xmlSchemaItemListRemove(uses, i) == -1)
19399			    return(-1);
19400			goto next_use;
19401		    }
19402		}
19403	    }
19404	    /*
19405	    * SPEC ag-props-correct
19406	    * (3) "Two distinct members of the {attribute uses} must not have
19407	    * {attribute declaration}s both of whose {type definition}s are or
19408	    * are derived from ID."
19409	    * TODO: Does 'derived' include member-types of unions?
19410	    */
19411	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19412		if (xmlSchemaIsDerivedFromBuiltInType(
19413		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19414		{
19415		    if (hasId) {
19416			xmlChar *str = NULL;
19417
19418			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19419			    XML_SCHEMAP_AG_PROPS_CORRECT,
19420			    attrGr->node, WXS_BASIC_CAST attrGr,
19421			    "There must not exist more than one attribute "
19422			    "declaration of type 'xs:ID' "
19423			    "(or derived from 'xs:ID'). The %s violates this "
19424			    "constraint",
19425			    xmlSchemaGetComponentDesignation(&str, use),
19426			    NULL);
19427			FREE_AND_NULL(str);
19428			if (xmlSchemaItemListRemove(uses, i) == -1)
19429			    return(-1);
19430		    }
19431		    hasId = 1;
19432		}
19433	    }
19434next_use: {}
19435	}
19436    }
19437    return(0);
19438}
19439
19440/**
19441 * xmlSchemaResolveAttrGroupReferences:
19442 * @attrgrpDecl:  the schema attribute definition
19443 * @ctxt:  the schema parser context
19444 * @name:  the attribute name
19445 *
19446 * Resolves references to attribute group definitions.
19447 */
19448static int
19449xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19450				    xmlSchemaParserCtxtPtr ctxt)
19451{
19452    xmlSchemaAttributeGroupPtr group;
19453
19454    if (ref->item != NULL)
19455        return(0);
19456    group = xmlSchemaGetAttributeGroup(ctxt->schema,
19457	ref->name,
19458	ref->targetNamespace);
19459    if (group == NULL) {
19460	xmlSchemaPResCompAttrErr(ctxt,
19461	    XML_SCHEMAP_SRC_RESOLVE,
19462	    NULL, ref->node,
19463	    "ref", ref->name, ref->targetNamespace,
19464	    ref->itemType, NULL);
19465	return(ctxt->err);
19466    }
19467    ref->item = WXS_BASIC_CAST group;
19468    return(0);
19469}
19470
19471/**
19472 * xmlSchemaCheckAttrPropsCorrect:
19473 * @item:  an schema attribute declaration/use
19474 * @ctxt:  a schema parser context
19475 * @name:  the name of the attribute
19476 *
19477 *
19478 * Schema Component Constraint:
19479 *    Attribute Declaration Properties Correct (a-props-correct)
19480 *
19481 * Validates the value constraints of an attribute declaration/use.
19482 * NOTE that this needs the simle type definitions to be already
19483 *   builded and checked.
19484 */
19485static int
19486xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19487			       xmlSchemaAttributePtr attr)
19488{
19489
19490    /*
19491    * SPEC a-props-correct (1)
19492    * "The values of the properties of an attribute declaration must
19493    * be as described in the property tableau in The Attribute
19494    * Declaration Schema Component (�3.2.1), modulo the impact of
19495    * Missing Sub-components (�5.3)."
19496    */
19497
19498    if (WXS_ATTR_TYPEDEF(attr) == NULL)
19499	return(0);
19500
19501    if (attr->defValue != NULL) {
19502	int ret;
19503
19504	/*
19505	* SPEC a-props-correct (3)
19506	* "If the {type definition} is or is derived from ID then there
19507	* must not be a {value constraint}."
19508	*/
19509	if (xmlSchemaIsDerivedFromBuiltInType(
19510	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19511	{
19512	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19513		XML_SCHEMAP_A_PROPS_CORRECT_3,
19514		NULL, WXS_BASIC_CAST attr,
19515		"Value constraints are not allowed if the type definition "
19516		"is or is derived from xs:ID",
19517		NULL, NULL);
19518	    return(pctxt->err);
19519	}
19520	/*
19521	* SPEC a-props-correct (2)
19522	* "if there is a {value constraint}, the canonical lexical
19523	* representation of its value must be �valid� with respect
19524	* to the {type definition} as defined in String Valid (�3.14.4)."
19525	* TODO: Don't care about the *cononical* stuff here, this requirement
19526	* will be removed in WXS 1.1 anyway.
19527	*/
19528	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19529	    attr->node, WXS_ATTR_TYPEDEF(attr),
19530	    attr->defValue, &(attr->defVal),
19531	    1, 1, 0);
19532	if (ret != 0) {
19533	    if (ret < 0) {
19534		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19535		    "calling xmlSchemaVCheckCVCSimpleType()");
19536		return(-1);
19537	    }
19538	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19539		XML_SCHEMAP_A_PROPS_CORRECT_2,
19540		NULL, WXS_BASIC_CAST attr,
19541		"The value of the value constraint is not valid",
19542		NULL, NULL);
19543	    return(pctxt->err);
19544	}
19545    }
19546
19547    return(0);
19548}
19549
19550static xmlSchemaElementPtr
19551xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19552				 xmlSchemaElementPtr ancestor)
19553{
19554    xmlSchemaElementPtr ret;
19555
19556    if (WXS_SUBST_HEAD(ancestor) == NULL)
19557	return (NULL);
19558    if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19559	return (ancestor);
19560
19561    if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19562	return (NULL);
19563    WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19564    ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19565	WXS_SUBST_HEAD(ancestor));
19566    WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19567
19568    return (ret);
19569}
19570
19571/**
19572 * xmlSchemaCheckElemPropsCorrect:
19573 * @ctxt:  a schema parser context
19574 * @decl: the element declaration
19575 * @name:  the name of the attribute
19576 *
19577 * Schema Component Constraint:
19578 * Element Declaration Properties Correct (e-props-correct)
19579 *
19580 * STATUS:
19581 *   missing: (6)
19582 */
19583static int
19584xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19585			       xmlSchemaElementPtr elemDecl)
19586{
19587    int ret = 0;
19588    xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19589    /*
19590    * SPEC (1) "The values of the properties of an element declaration
19591    * must be as described in the property tableau in The Element
19592    * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19593    * Sub-components (�5.3)."
19594    */
19595    if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19596	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19597
19598	xmlSchemaCheckElementDeclComponent(head, pctxt);
19599	/*
19600	* SPEC (3) "If there is a non-�absent� {substitution group
19601	* affiliation}, then {scope} must be global."
19602	*/
19603	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19604	    xmlSchemaPCustomErr(pctxt,
19605		XML_SCHEMAP_E_PROPS_CORRECT_3,
19606		WXS_BASIC_CAST elemDecl, NULL,
19607		"Only global element declarations can have a "
19608		"substitution group affiliation", NULL);
19609	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19610	}
19611	/*
19612	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19613	* That is, it must not be possible to return to an element declaration
19614	* by repeatedly following the {substitution group affiliation}
19615	* property."
19616	*/
19617	if (head == elemDecl)
19618	    circ = head;
19619	else if (WXS_SUBST_HEAD(head) != NULL)
19620	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19621	else
19622	    circ = NULL;
19623	if (circ != NULL) {
19624	    xmlChar *strA = NULL, *strB = NULL;
19625
19626	    xmlSchemaPCustomErrExt(pctxt,
19627		XML_SCHEMAP_E_PROPS_CORRECT_6,
19628		WXS_BASIC_CAST circ, NULL,
19629		"The element declaration '%s' defines a circular "
19630		"substitution group to element declaration '%s'",
19631		xmlSchemaGetComponentQName(&strA, circ),
19632		xmlSchemaGetComponentQName(&strB, head),
19633		NULL);
19634	    FREE_AND_NULL(strA)
19635	    FREE_AND_NULL(strB)
19636	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19637	}
19638	/*
19639	* SPEC (4) "If there is a {substitution group affiliation},
19640	* the {type definition}
19641	* of the element declaration must be validly derived from the {type
19642	* definition} of the {substitution group affiliation}, given the value
19643	* of the {substitution group exclusions} of the {substitution group
19644	* affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19645	* (if the {type definition} is complex) or as defined in
19646	* Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19647	* simple)."
19648	*
19649	* NOTE: {substitution group exclusions} means the values of the
19650	* attribute "final".
19651	*/
19652
19653	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19654	    int set = 0;
19655
19656	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19657		set |= SUBSET_EXTENSION;
19658	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19659		set |= SUBSET_RESTRICTION;
19660
19661	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19662		WXS_ELEM_TYPEDEF(head), set) != 0) {
19663		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19664
19665		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19666		xmlSchemaPCustomErrExt(pctxt,
19667		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19668		    WXS_BASIC_CAST elemDecl, NULL,
19669		    "The type definition '%s' was "
19670		    "either rejected by the substitution group "
19671		    "affiliation '%s', or not validly derived from its type "
19672		    "definition '%s'",
19673		    xmlSchemaGetComponentQName(&strA, typeDef),
19674		    xmlSchemaGetComponentQName(&strB, head),
19675		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19676		FREE_AND_NULL(strA)
19677		FREE_AND_NULL(strB)
19678		FREE_AND_NULL(strC)
19679	    }
19680	}
19681    }
19682    /*
19683    * SPEC (5) "If the {type definition} or {type definition}'s
19684    * {content type}
19685    * is or is derived from ID then there must not be a {value constraint}.
19686    * Note: The use of ID as a type definition for elements goes beyond
19687    * XML 1.0, and should be avoided if backwards compatibility is desired"
19688    */
19689    if ((elemDecl->value != NULL) &&
19690	((WXS_IS_SIMPLE(typeDef) &&
19691	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19692	 (WXS_IS_COMPLEX(typeDef) &&
19693	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19694	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19695	    XML_SCHEMAS_ID)))) {
19696
19697	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19698	xmlSchemaPCustomErr(pctxt,
19699	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19700	    WXS_BASIC_CAST elemDecl, NULL,
19701	    "The type definition (or type definition's content type) is or "
19702	    "is derived from ID; value constraints are not allowed in "
19703	    "conjunction with such a type definition", NULL);
19704    } else if (elemDecl->value != NULL) {
19705	int vcret;
19706	xmlNodePtr node = NULL;
19707
19708	/*
19709	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19710	* representation of its value must be �valid� with respect to the
19711	* {type definition} as defined in Element Default Valid (Immediate)
19712	* (�3.3.6)."
19713	*/
19714	if (typeDef == NULL) {
19715	    xmlSchemaPErr(pctxt, elemDecl->node,
19716		XML_SCHEMAP_INTERNAL,
19717		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19718		"type is missing... skipping validation of "
19719		"the value constraint", NULL, NULL);
19720	    return (-1);
19721	}
19722	if (elemDecl->node != NULL) {
19723	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19724		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19725		    BAD_CAST "fixed");
19726	    else
19727		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19728		    BAD_CAST "default");
19729	}
19730	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19731	    typeDef, elemDecl->value, &(elemDecl->defVal));
19732	if (vcret != 0) {
19733	    if (vcret < 0) {
19734		PERROR_INT("xmlSchemaElemCheckValConstr",
19735		    "failed to validate the value constraint of an "
19736		    "element declaration");
19737		return (-1);
19738	    }
19739	    return (vcret);
19740	}
19741    }
19742
19743    return (ret);
19744}
19745
19746/**
19747 * xmlSchemaCheckElemSubstGroup:
19748 * @ctxt:  a schema parser context
19749 * @decl: the element declaration
19750 * @name:  the name of the attribute
19751 *
19752 * Schema Component Constraint:
19753 * Substitution Group (cos-equiv-class)
19754 *
19755 * In Libxml2 the subst. groups will be precomputed, in terms of that
19756 * a list will be built for each subst. group head, holding all direct
19757 * referents to this head.
19758 * NOTE that this function needs:
19759 *   1. circular subst. groups to be checked beforehand
19760 *   2. the declaration's type to be derived from the head's type
19761 *
19762 * STATUS:
19763 *
19764 */
19765static void
19766xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19767			     xmlSchemaElementPtr elemDecl)
19768{
19769    if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19770	/* SPEC (1) "Its {abstract} is false." */
19771	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19772	return;
19773    {
19774	xmlSchemaElementPtr head;
19775	xmlSchemaTypePtr headType, type;
19776	int set, methSet;
19777	/*
19778	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19779	* {disallowed substitutions} as the blocking constraint, as defined in
19780	* Substitution Group OK (Transitive) (�3.3.6)."
19781	*/
19782	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19783	    head = WXS_SUBST_HEAD(head)) {
19784	    set = 0;
19785	    methSet = 0;
19786	    /*
19787	    * The blocking constraints.
19788	    */
19789	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19790		continue;
19791	    headType = head->subtypes;
19792	    type = elemDecl->subtypes;
19793	    if (headType == type)
19794		goto add_member;
19795	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19796		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19797	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19798		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19799	    /*
19800	    * SPEC: Substitution Group OK (Transitive) (2.3)
19801	    * "The set of all {derivation method}s involved in the
19802	    * derivation of D's {type definition} from C's {type definition}
19803	    * does not intersect with the union of the blocking constraint,
19804	    * C's {prohibited substitutions} (if C is complex, otherwise the
19805	    * empty set) and the {prohibited substitutions} (respectively the
19806	    * empty set) of any intermediate {type definition}s in the
19807	    * derivation of D's {type definition} from C's {type definition}."
19808	    */
19809	    /*
19810	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19811	    * subst.head axis, the methSet does not need to be computed for
19812	    * the full depth over and over.
19813	    */
19814	    /*
19815	    * The set of all {derivation method}s involved in the derivation
19816	    */
19817	    while ((type != NULL) && (type != headType)) {
19818		if ((WXS_IS_EXTENSION(type)) &&
19819		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19820		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19821
19822		if (WXS_IS_RESTRICTION(type) &&
19823		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19824		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19825
19826		type = type->baseType;
19827	    }
19828	    /*
19829	    * The {prohibited substitutions} of all intermediate types +
19830	    * the head's type.
19831	    */
19832	    type = elemDecl->subtypes->baseType;
19833	    while (type != NULL) {
19834		if (WXS_IS_COMPLEX(type)) {
19835		    if ((type->flags &
19836			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19837			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19838		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19839		    if ((type->flags &
19840			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19841			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19842		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19843		} else
19844		    break;
19845		if (type == headType)
19846		    break;
19847		type = type->baseType;
19848	    }
19849	    if ((set != 0) &&
19850		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19851		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19852		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19853		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19854		continue;
19855	    }
19856add_member:
19857	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19858	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19859		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19860	}
19861    }
19862}
19863
19864#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19865/**
19866 * xmlSchemaCheckElementDeclComponent
19867 * @pctxt: the schema parser context
19868 * @ctxtComponent: the context component (an element declaration)
19869 * @ctxtParticle: the first particle of the context component
19870 * @searchParticle: the element declaration particle to be analysed
19871 *
19872 * Schema Component Constraint: Element Declarations Consistent
19873 */
19874static int
19875xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19876				    xmlSchemaBasicItemPtr ctxtComponent,
19877				    xmlSchemaParticlePtr ctxtParticle,
19878				    xmlSchemaParticlePtr searchParticle,
19879				    xmlSchemaParticlePtr curParticle,
19880				    int search)
19881{
19882    return(0);
19883
19884    int ret = 0;
19885    xmlSchemaParticlePtr cur = curParticle;
19886    if (curParticle == NULL) {
19887	return(0);
19888    }
19889    if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19890	/*
19891	* Just return in this case. A missing "term" of the particle
19892	* might arise due to an invalid "term" component.
19893	*/
19894	return(0);
19895    }
19896    while (cur != NULL) {
19897	switch (WXS_PARTICLE_TERM(cur)->type) {
19898	    case XML_SCHEMA_TYPE_ANY:
19899		break;
19900	    case XML_SCHEMA_TYPE_ELEMENT:
19901		if (search == 0) {
19902		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19903			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19904		    if (ret != 0)
19905			return(ret);
19906		} else {
19907		    xmlSchemaElementPtr elem =
19908			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19909		    /*
19910		    * SPEC Element Declarations Consistent:
19911		    * "If the {particles} contains, either directly,
19912		    * indirectly (that is, within the {particles} of a
19913		    * contained model group, recursively) or �implicitly�
19914		    * two or more element declaration particles with
19915		    * the same {name} and {target namespace}, then
19916		    * all their type definitions must be the same
19917		    * top-level definition [...]"
19918		    */
19919		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19920			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19921			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19922			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19923		    {
19924			xmlChar *strA = NULL, *strB = NULL;
19925
19926			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19927			    /* TODO: error code */
19928			    XML_SCHEMAP_COS_NONAMBIG,
19929			    WXS_ITEM_NODE(cur), NULL,
19930			    "In the content model of %s, there are multiple "
19931			    "element declarations for '%s' with different "
19932			    "type definitions",
19933			    xmlSchemaGetComponentDesignation(&strA,
19934				ctxtComponent),
19935			    xmlSchemaFormatQName(&strB,
19936				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19937				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19938			FREE_AND_NULL(strA);
19939			FREE_AND_NULL(strB);
19940			return(XML_SCHEMAP_COS_NONAMBIG);
19941		    }
19942		}
19943		break;
19944	    case XML_SCHEMA_TYPE_SEQUENCE: {
19945		break;
19946		}
19947	    case XML_SCHEMA_TYPE_CHOICE:{
19948		/*
19949		xmlSchemaTreeItemPtr sub;
19950
19951		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19952		while (sub != NULL) {
19953		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19954			ctxtParticle, ctxtElem);
19955		    if (ret != 0)
19956			return(ret);
19957		    sub = sub->next;
19958		}
19959		*/
19960		break;
19961		}
19962	    case XML_SCHEMA_TYPE_ALL:
19963		break;
19964	    case XML_SCHEMA_TYPE_GROUP:
19965		break;
19966	    default:
19967		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19968		    "xmlSchemaCheckElementDeclConsistent",
19969		    "found unexpected term of type '%s' in content model",
19970		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19971		return(-1);
19972	}
19973	cur = (xmlSchemaParticlePtr) cur->next;
19974    }
19975
19976exit:
19977    return(ret);
19978}
19979#endif
19980
19981/**
19982 * xmlSchemaCheckElementDeclComponent
19983 * @item:  an schema element declaration/particle
19984 * @ctxt:  a schema parser context
19985 * @name:  the name of the attribute
19986 *
19987 * Validates the value constraints of an element declaration.
19988 * Adds substitution group members.
19989 */
19990static void
19991xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19992				   xmlSchemaParserCtxtPtr ctxt)
19993{
19994    if (elemDecl == NULL)
19995	return;
19996    if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19997	return;
19998    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19999    if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20000	/*
20001	* Adds substitution group members.
20002	*/
20003	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20004    }
20005}
20006
20007/**
20008 * xmlSchemaResolveModelGroupParticleReferences:
20009 * @particle:  a particle component
20010 * @ctxt:  a parser context
20011 *
20012 * Resolves references of a model group's {particles} to
20013 * model group definitions and to element declarations.
20014 */
20015static void
20016xmlSchemaResolveModelGroupParticleReferences(
20017    xmlSchemaParserCtxtPtr ctxt,
20018    xmlSchemaModelGroupPtr mg)
20019{
20020    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20021    xmlSchemaQNameRefPtr ref;
20022    xmlSchemaBasicItemPtr refItem;
20023
20024    /*
20025    * URGENT TODO: Test this.
20026    */
20027    while (particle != NULL) {
20028	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20029	    ((WXS_PARTICLE_TERM(particle))->type !=
20030		XML_SCHEMA_EXTRA_QNAMEREF))
20031	{
20032	    goto next_particle;
20033	}
20034	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20035	/*
20036	* Resolve the reference.
20037	* NULL the {term} by default.
20038	*/
20039	particle->children = NULL;
20040
20041	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20042	    ref->itemType, ref->name, ref->targetNamespace);
20043	if (refItem == NULL) {
20044	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20045		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20046		ref->targetNamespace, ref->itemType, NULL);
20047	    /* TODO: remove the particle. */
20048	    goto next_particle;
20049	}
20050	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20051	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20052		/* TODO: remove the particle. */
20053		goto next_particle;
20054	    /*
20055	    * NOTE that we will assign the model group definition
20056	    * itself to the "term" of the particle. This will ease
20057	    * the check for circular model group definitions. After
20058	    * that the "term" will be assigned the model group of the
20059	    * model group definition.
20060	    */
20061	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20062		    XML_SCHEMA_TYPE_ALL) {
20063		/*
20064		* SPEC cos-all-limited (1)
20065		* SPEC cos-all-limited (1.2)
20066		* "It appears only as the value of one or both of the
20067		* following properties:"
20068		* (1.1) "the {model group} property of a model group
20069		*        definition."
20070		* (1.2) "the {term} property of a particle [... of] the "
20071		* {content type} of a complex type definition."
20072		*/
20073		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20074		    /* TODO: error code */
20075		    XML_SCHEMAP_COS_ALL_LIMITED,
20076		    WXS_ITEM_NODE(particle), NULL,
20077		    "A model group definition is referenced, but "
20078		    "it contains an 'all' model group, which "
20079		    "cannot be contained by model groups",
20080		    NULL, NULL);
20081		/* TODO: remove the particle. */
20082		goto next_particle;
20083	    }
20084	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20085	} else {
20086	    /*
20087	    * TODO: Are referenced element declarations the only
20088	    * other components we expect here?
20089	    */
20090	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20091	}
20092next_particle:
20093	particle = WXS_PTC_CAST particle->next;
20094    }
20095}
20096
20097static int
20098xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20099		       xmlSchemaValPtr y)
20100{
20101    xmlSchemaTypePtr tx, ty, ptx, pty;
20102    int ret;
20103
20104    while (x != NULL) {
20105	/* Same types. */
20106	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20107	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20108	ptx = xmlSchemaGetPrimitiveType(tx);
20109	pty = xmlSchemaGetPrimitiveType(ty);
20110	/*
20111	* (1) if a datatype T' is �derived� by �restriction� from an
20112	* atomic datatype T then the �value space� of T' is a subset of
20113	* the �value space� of T. */
20114	/*
20115	* (2) if datatypes T' and T'' are �derived� by �restriction�
20116	* from a common atomic ancestor T then the �value space�s of T'
20117	* and T'' may overlap.
20118	*/
20119	if (ptx != pty)
20120	    return(0);
20121	/*
20122	* We assume computed values to be normalized, so do a fast
20123	* string comparison for string based types.
20124	*/
20125	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20126	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20127	    if (! xmlStrEqual(
20128		xmlSchemaValueGetAsString(x),
20129		xmlSchemaValueGetAsString(y)))
20130		return (0);
20131	} else {
20132	    ret = xmlSchemaCompareValuesWhtsp(
20133		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20134		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20135	    if (ret == -2)
20136		return(-1);
20137	    if (ret != 0)
20138		return(0);
20139	}
20140	/*
20141	* Lists.
20142	*/
20143	x = xmlSchemaValueGetNext(x);
20144	if (x != NULL) {
20145	    y = xmlSchemaValueGetNext(y);
20146	    if (y == NULL)
20147		return (0);
20148	} else if (xmlSchemaValueGetNext(y) != NULL)
20149	    return (0);
20150	else
20151	    return (1);
20152    }
20153    return (0);
20154}
20155
20156/**
20157 * xmlSchemaResolveAttrUseReferences:
20158 * @item:  an attribute use
20159 * @ctxt:  a parser context
20160 *
20161 * Resolves the referenced attribute declaration.
20162 */
20163static int
20164xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20165				  xmlSchemaParserCtxtPtr ctxt)
20166{
20167    if ((ctxt == NULL) || (ause == NULL))
20168	return(-1);
20169    if ((ause->attrDecl == NULL) ||
20170	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20171	return(0);
20172
20173    {
20174	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20175
20176	/*
20177	* TODO: Evaluate, what errors could occur if the declaration is not
20178	* found.
20179	*/
20180	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20181	    ref->name, ref->targetNamespace);
20182        if (ause->attrDecl == NULL) {
20183	    xmlSchemaPResCompAttrErr(ctxt,
20184		XML_SCHEMAP_SRC_RESOLVE,
20185		WXS_BASIC_CAST ause, ause->node,
20186		"ref", ref->name, ref->targetNamespace,
20187		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20188            return(ctxt->err);;
20189        }
20190    }
20191    return(0);
20192}
20193
20194/**
20195 * xmlSchemaCheckAttrUsePropsCorrect:
20196 * @ctxt:  a parser context
20197 * @use:  an attribute use
20198 *
20199 * Schema Component Constraint:
20200 * Attribute Use Correct (au-props-correct)
20201 *
20202 */
20203static int
20204xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20205			     xmlSchemaAttributeUsePtr use)
20206{
20207    if ((ctxt == NULL) || (use == NULL))
20208	return(-1);
20209    if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20210	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20211	return(0);
20212
20213    /*
20214    * SPEC au-props-correct (1)
20215    * "The values of the properties of an attribute use must be as
20216    * described in the property tableau in The Attribute Use Schema
20217    * Component (�3.5.1), modulo the impact of Missing
20218    * Sub-components (�5.3)."
20219    */
20220
20221    if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20222	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20223        ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20224    {
20225	xmlSchemaPCustomErr(ctxt,
20226	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20227	    WXS_BASIC_CAST use, NULL,
20228	    "The attribute declaration has a 'fixed' value constraint "
20229	    ", thus the attribute use must also have a 'fixed' value "
20230	    "constraint",
20231	    NULL);
20232	return(ctxt->err);
20233    }
20234    /*
20235    * Compute and check the value constraint's value.
20236    */
20237    if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20238	int ret;
20239	/*
20240	* TODO: The spec seems to be missing a check of the
20241	* value constraint of the attribute use. We will do it here.
20242	*/
20243	/*
20244	* SPEC a-props-correct (3)
20245	*/
20246	if (xmlSchemaIsDerivedFromBuiltInType(
20247	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20248	{
20249	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20250		XML_SCHEMAP_AU_PROPS_CORRECT,
20251		NULL, WXS_BASIC_CAST use,
20252		"Value constraints are not allowed if the type definition "
20253		"is or is derived from xs:ID",
20254		NULL, NULL);
20255	    return(ctxt->err);
20256	}
20257
20258	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20259	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20260	    use->defValue, &(use->defVal),
20261	    1, 1, 0);
20262	if (ret != 0) {
20263	    if (ret < 0) {
20264		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20265		    "calling xmlSchemaVCheckCVCSimpleType()");
20266		return(-1);
20267	    }
20268	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20269		XML_SCHEMAP_AU_PROPS_CORRECT,
20270		NULL, WXS_BASIC_CAST use,
20271		"The value of the value constraint is not valid",
20272		NULL, NULL);
20273	    return(ctxt->err);
20274	}
20275    }
20276    /*
20277    * SPEC au-props-correct (2)
20278    * "If the {attribute declaration} has a fixed
20279    * {value constraint}, then if the attribute use itself has a
20280    * {value constraint}, it must also be fixed and its value must match
20281    * that of the {attribute declaration}'s {value constraint}."
20282    */
20283    if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20284	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20285    {
20286	if (! xmlSchemaAreValuesEqual(use->defVal,
20287		(WXS_ATTRUSE_DECL(use))->defVal))
20288	{
20289	    xmlSchemaPCustomErr(ctxt,
20290		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20291		WXS_BASIC_CAST use, NULL,
20292		"The 'fixed' value constraint of the attribute use "
20293		"must match the attribute declaration's value "
20294		"constraint '%s'",
20295		(WXS_ATTRUSE_DECL(use))->defValue);
20296	}
20297	return(ctxt->err);
20298    }
20299    return(0);
20300}
20301
20302
20303
20304
20305/**
20306 * xmlSchemaResolveAttrTypeReferences:
20307 * @item:  an attribute declaration
20308 * @ctxt:  a parser context
20309 *
20310 * Resolves the referenced type definition component.
20311 */
20312static int
20313xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20314				   xmlSchemaParserCtxtPtr ctxt)
20315{
20316    /*
20317    * The simple type definition corresponding to the <simpleType> element
20318    * information item in the [children], if present, otherwise the simple
20319    * type definition �resolved� to by the �actual value� of the type
20320    * [attribute], if present, otherwise the �simple ur-type definition�.
20321    */
20322    if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20323	return(0);
20324    item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20325    if (item->subtypes != NULL)
20326        return(0);
20327    if (item->typeName != NULL) {
20328        xmlSchemaTypePtr type;
20329
20330	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20331	    item->typeNs);
20332	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20333	    xmlSchemaPResCompAttrErr(ctxt,
20334		XML_SCHEMAP_SRC_RESOLVE,
20335		WXS_BASIC_CAST item, item->node,
20336		"type", item->typeName, item->typeNs,
20337		XML_SCHEMA_TYPE_SIMPLE, NULL);
20338	    return(ctxt->err);
20339	} else
20340	    item->subtypes = type;
20341
20342    } else {
20343	/*
20344	* The type defaults to the xs:anySimpleType.
20345	*/
20346	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20347    }
20348    return(0);
20349}
20350
20351/**
20352 * xmlSchemaResolveIDCKeyReferences:
20353 * @idc:  the identity-constraint definition
20354 * @ctxt:  the schema parser context
20355 * @name:  the attribute name
20356 *
20357 * Resolve keyRef references to key/unique IDCs.
20358 * Schema Component Constraint:
20359 *   Identity-constraint Definition Properties Correct (c-props-correct)
20360 */
20361static int
20362xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20363			  xmlSchemaParserCtxtPtr pctxt)
20364{
20365    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20366        return(0);
20367    if (idc->ref->name != NULL) {
20368	idc->ref->item = (xmlSchemaBasicItemPtr)
20369	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20370		idc->ref->targetNamespace);
20371        if (idc->ref->item == NULL) {
20372	    /*
20373	    * TODO: It is actually not an error to fail to resolve
20374	    * at this stage. BUT we need to be that strict!
20375	    */
20376	    xmlSchemaPResCompAttrErr(pctxt,
20377		XML_SCHEMAP_SRC_RESOLVE,
20378		WXS_BASIC_CAST idc, idc->node,
20379		"refer", idc->ref->name,
20380		idc->ref->targetNamespace,
20381		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20382            return(pctxt->err);
20383	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20384	    /*
20385	    * SPEC c-props-correct (1)
20386	    */
20387	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20388		XML_SCHEMAP_C_PROPS_CORRECT,
20389		NULL, WXS_BASIC_CAST idc,
20390		"The keyref references a keyref",
20391		NULL, NULL);
20392	    idc->ref->item = NULL;
20393	    return(pctxt->err);
20394	} else {
20395	    if (idc->nbFields !=
20396		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20397		xmlChar *str = NULL;
20398		xmlSchemaIDCPtr refer;
20399
20400		refer = (xmlSchemaIDCPtr) idc->ref->item;
20401		/*
20402		* SPEC c-props-correct(2)
20403		* "If the {identity-constraint category} is keyref,
20404		* the cardinality of the {fields} must equal that of
20405		* the {fields} of the {referenced key}.
20406		*/
20407		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20408		    XML_SCHEMAP_C_PROPS_CORRECT,
20409		    NULL, WXS_BASIC_CAST idc,
20410		    "The cardinality of the keyref differs from the "
20411		    "cardinality of the referenced key/unique '%s'",
20412		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20413			refer->name),
20414		    NULL);
20415		FREE_AND_NULL(str)
20416		return(pctxt->err);
20417	    }
20418	}
20419    }
20420    return(0);
20421}
20422
20423static int
20424xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20425				       xmlSchemaParserCtxtPtr pctxt)
20426{
20427    if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20428	prohib->targetNamespace) == NULL) {
20429
20430	xmlSchemaPResCompAttrErr(pctxt,
20431	    XML_SCHEMAP_SRC_RESOLVE,
20432	    NULL, prohib->node,
20433	    "ref", prohib->name, prohib->targetNamespace,
20434	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20435	return(XML_SCHEMAP_SRC_RESOLVE);
20436    }
20437    return(0);
20438}
20439
20440#define WXS_REDEFINED_TYPE(c) \
20441(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20442
20443#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20444(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20445
20446#define WXS_REDEFINED_ATTR_GROUP(c) \
20447(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20448
20449static int
20450xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20451{
20452    int err = 0;
20453    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20454    xmlSchemaBasicItemPtr prev, item;
20455    int wasRedefined;
20456
20457    if (redef == NULL)
20458	return(0);
20459
20460    do {
20461	item = redef->item;
20462	/*
20463	* First try to locate the redefined component in the
20464	* schema graph starting with the redefined schema.
20465	* NOTE: According to this schema bug entry:
20466	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20467	*   it's not clear if the referenced component needs to originate
20468	*   from the <redefine>d schema _document_ or the schema; the latter
20469	*   would include all imported and included sub-schemas of the
20470	*   <redefine>d schema. Currenlty we latter approach is used.
20471	*   SUPPLEMENT: It seems that the WG moves towards the latter
20472	*   approach, so we are doing it right.
20473	*
20474	*/
20475	prev = xmlSchemaFindRedefCompInGraph(
20476	    redef->targetBucket, item->type,
20477	    redef->refName, redef->refTargetNs);
20478	if (prev == NULL) {
20479	    xmlChar *str = NULL;
20480	    xmlNodePtr node;
20481
20482	    /*
20483	    * SPEC src-redefine:
20484	    * (6.2.1) "The �actual value� of its own name attribute plus
20485	    * target namespace must successfully �resolve� to a model
20486	    * group definition in I."
20487	    * (7.2.1) "The �actual value� of its own name attribute plus
20488	    * target namespace must successfully �resolve� to an attribute
20489	    * group definition in I."
20490
20491	    *
20492	    * Note that, if we are redefining with the use of references
20493	    * to components, the spec assumes the src-resolve to be used;
20494	    * but this won't assure that we search only *inside* the
20495	    * redefined schema.
20496	    */
20497	    if (redef->reference)
20498		node = WXS_ITEM_NODE(redef->reference);
20499	    else
20500		node = WXS_ITEM_NODE(item);
20501	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20502		/*
20503		* TODO: error code.
20504		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20505		* reference kind.
20506		*/
20507		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20508		"The %s '%s' to be redefined could not be found in "
20509		"the redefined schema",
20510		WXS_ITEM_TYPE_NAME(item),
20511		xmlSchemaFormatQName(&str, redef->refTargetNs,
20512		    redef->refName));
20513	    FREE_AND_NULL(str);
20514	    err = pctxt->err;
20515	    redef = redef->next;
20516	    continue;
20517	}
20518	/*
20519	* TODO: Obtaining and setting the redefinition state is really
20520	* clumsy.
20521	*/
20522	wasRedefined = 0;
20523	switch (item->type) {
20524	    case XML_SCHEMA_TYPE_COMPLEX:
20525	    case XML_SCHEMA_TYPE_SIMPLE:
20526		if ((WXS_TYPE_CAST prev)->flags &
20527		    XML_SCHEMAS_TYPE_REDEFINED)
20528		{
20529		    wasRedefined = 1;
20530		    break;
20531		}
20532		/* Mark it as redefined. */
20533		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20534		/*
20535		* Assign the redefined type to the
20536		* base type of the redefining type.
20537		* TODO: How
20538		*/
20539		((xmlSchemaTypePtr) item)->baseType =
20540		    (xmlSchemaTypePtr) prev;
20541		break;
20542	    case XML_SCHEMA_TYPE_GROUP:
20543		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20544		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20545		{
20546		    wasRedefined = 1;
20547		    break;
20548		}
20549		/* Mark it as redefined. */
20550		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20551		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20552		if (redef->reference != NULL) {
20553		    /*
20554		    * Overwrite the QName-reference with the
20555		    * referenced model group def.
20556		    */
20557		    (WXS_PTC_CAST redef->reference)->children =
20558			WXS_TREE_CAST prev;
20559		}
20560		redef->target = prev;
20561		break;
20562	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20563		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20564		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20565		{
20566		    wasRedefined = 1;
20567		    break;
20568		}
20569		(WXS_ATTR_GROUP_CAST prev)->flags |=
20570		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20571		if (redef->reference != NULL) {
20572		    /*
20573		    * Assign the redefined attribute group to the
20574		    * QName-reference component.
20575		    * This is the easy case, since we will just
20576		    * expand the redefined group.
20577		    */
20578		    (WXS_QNAME_CAST redef->reference)->item = prev;
20579		    redef->target = NULL;
20580		} else {
20581		    /*
20582		    * This is the complicated case: we need
20583		    * to apply src-redefine (7.2.2) at a later
20584		    * stage, i.e. when attribute group references
20585		    * have beed expanded and simple types have
20586		    * beed fixed.
20587		    */
20588		    redef->target = prev;
20589		}
20590		break;
20591	    default:
20592		PERROR_INT("xmlSchemaResolveRedefReferences",
20593		    "Unexpected redefined component type");
20594		return(-1);
20595	}
20596	if (wasRedefined) {
20597	    xmlChar *str = NULL;
20598	    xmlNodePtr node;
20599
20600	    if (redef->reference)
20601		node = WXS_ITEM_NODE(redef->reference);
20602	    else
20603		node = WXS_ITEM_NODE(redef->item);
20604
20605	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20606		/* TODO: error code. */
20607		XML_SCHEMAP_SRC_REDEFINE,
20608		node, NULL,
20609		"The referenced %s was already redefined. Multiple "
20610		"redefinition of the same component is not supported",
20611		xmlSchemaGetComponentDesignation(&str, prev),
20612		NULL);
20613	    FREE_AND_NULL(str)
20614	    err = pctxt->err;
20615	    redef = redef->next;
20616	    continue;
20617	}
20618	redef = redef->next;
20619    } while (redef != NULL);
20620
20621    return(err);
20622}
20623
20624static int
20625xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20626{
20627    int err = 0;
20628    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20629    xmlSchemaBasicItemPtr item;
20630
20631    if (redef == NULL)
20632	return(0);
20633
20634    do {
20635	if (redef->target == NULL) {
20636	    redef = redef->next;
20637	    continue;
20638	}
20639	item = redef->item;
20640
20641	switch (item->type) {
20642	    case XML_SCHEMA_TYPE_SIMPLE:
20643	    case XML_SCHEMA_TYPE_COMPLEX:
20644		/*
20645		* Since the spec wants the {name} of the redefined
20646		* type to be 'absent', we'll NULL it.
20647		*/
20648		(WXS_TYPE_CAST redef->target)->name = NULL;
20649
20650		/*
20651		* TODO: Seems like there's nothing more to do. The normal
20652		* inheritance mechanism is used. But not 100% sure.
20653		*/
20654		break;
20655	    case XML_SCHEMA_TYPE_GROUP:
20656		/*
20657		* URGENT TODO:
20658		* SPEC src-redefine:
20659		* (6.2.2) "The {model group} of the model group definition
20660		* which corresponds to it per XML Representation of Model
20661		* Group Definition Schema Components (�3.7.2) must be a
20662		* �valid restriction� of the {model group} of that model
20663		* group definition in I, as defined in Particle Valid
20664		* (Restriction) (�3.9.6)."
20665		*/
20666		break;
20667	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20668		/*
20669		* SPEC src-redefine:
20670		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20671		* the attribute group definition which corresponds to it
20672		* per XML Representation of Attribute Group Definition Schema
20673		* Components (�3.6.2) must be �valid restrictions� of the
20674		* {attribute uses} and {attribute wildcard} of that attribute
20675		* group definition in I, as defined in clause 2, clause 3 and
20676		* clause 4 of Derivation Valid (Restriction, Complex)
20677		* (�3.4.6) (where references to the base type definition are
20678		* understood as references to the attribute group definition
20679		* in I)."
20680		*/
20681		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20682		    XML_SCHEMA_ACTION_REDEFINE,
20683		    item, redef->target,
20684		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20685		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20686		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20687		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20688		if (err == -1)
20689		    return(-1);
20690		break;
20691	    default:
20692		break;
20693	}
20694	redef = redef->next;
20695    } while (redef != NULL);
20696    return(0);
20697}
20698
20699
20700static int
20701xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20702		       xmlSchemaBucketPtr bucket)
20703{
20704    xmlSchemaBasicItemPtr item;
20705    int err;
20706    xmlHashTablePtr *table;
20707    const xmlChar *name;
20708    int i;
20709
20710#define WXS_GET_GLOBAL_HASH(c, slot) { \
20711    if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20712	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20713    else \
20714	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20715
20716    /*
20717    * Add global components to the schema's hash tables.
20718    * This is the place where duplicate components will be
20719    * detected.
20720    * TODO: I think normally we should support imports of the
20721    *   same namespace from multiple locations. We don't do currently,
20722    *   but if we do then according to:
20723    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20724    *   we would need, if imported directly, to import redefined
20725    *   components as well to be able to catch clashing components.
20726    *   (I hope I'll still know what this means after some months :-()
20727    */
20728    if (bucket == NULL)
20729	return(-1);
20730    if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20731	return(0);
20732    bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20733
20734    for (i = 0; i < bucket->globals->nbItems; i++) {
20735	item = bucket->globals->items[i];
20736	table = NULL;
20737	switch (item->type) {
20738	    case XML_SCHEMA_TYPE_COMPLEX:
20739	    case XML_SCHEMA_TYPE_SIMPLE:
20740		if (WXS_REDEFINED_TYPE(item))
20741		    continue;
20742		name = (WXS_TYPE_CAST item)->name;
20743		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20744		break;
20745	    case XML_SCHEMA_TYPE_ELEMENT:
20746		name = (WXS_ELEM_CAST item)->name;
20747		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20748		break;
20749	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20750		name = (WXS_ATTR_CAST item)->name;
20751		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20752		break;
20753	    case XML_SCHEMA_TYPE_GROUP:
20754		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20755		    continue;
20756		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20757		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20758		break;
20759	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20760		if (WXS_REDEFINED_ATTR_GROUP(item))
20761		    continue;
20762		name = (WXS_ATTR_GROUP_CAST item)->name;
20763		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20764		break;
20765	    case XML_SCHEMA_TYPE_IDC_KEY:
20766	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20767	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20768		name = (WXS_IDC_CAST item)->name;
20769		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20770		break;
20771	    case XML_SCHEMA_TYPE_NOTATION:
20772		name = ((xmlSchemaNotationPtr) item)->name;
20773		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20774		break;
20775	    default:
20776		PERROR_INT("xmlSchemaAddComponents",
20777		    "Unexpected global component type");
20778		continue;
20779	}
20780	if (*table == NULL) {
20781	    *table = xmlHashCreateDict(10, pctxt->dict);
20782	    if (*table == NULL) {
20783		PERROR_INT("xmlSchemaAddComponents",
20784		    "failed to create a component hash table");
20785		return(-1);
20786	    }
20787	}
20788	err = xmlHashAddEntry(*table, name, item);
20789	if (err != 0) {
20790	    xmlChar *str = NULL;
20791
20792	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20793		XML_SCHEMAP_REDEFINED_TYPE,
20794		WXS_ITEM_NODE(item),
20795		WXS_BASIC_CAST item,
20796		"A global %s '%s' does already exist",
20797		WXS_ITEM_TYPE_NAME(item),
20798		xmlSchemaGetComponentQName(&str, item));
20799	    FREE_AND_NULL(str);
20800	}
20801    }
20802    /*
20803    * Process imported/included schemas.
20804    */
20805    if (bucket->relations != NULL) {
20806	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20807	do {
20808	    if ((rel->bucket != NULL) &&
20809		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20810		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20811		    return(-1);
20812	    }
20813	    rel = rel->next;
20814	} while (rel != NULL);
20815    }
20816    return(0);
20817}
20818
20819static int
20820xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20821			 xmlSchemaBucketPtr rootBucket)
20822{
20823    xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20824    xmlSchemaTreeItemPtr item, *items;
20825    int nbItems, i, ret = 0;
20826    xmlSchemaBucketPtr oldbucket = con->bucket;
20827    xmlSchemaElementPtr elemDecl;
20828
20829#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20830
20831    if ((con->pending == NULL) ||
20832	(con->pending->nbItems == 0))
20833	return(0);
20834
20835    /*
20836    * Since xmlSchemaFixupComplexType() will create new particles
20837    * (local components), and those particle components need a bucket
20838    * on the constructor, we'll assure here that the constructor has
20839    * a bucket.
20840    * TODO: Think about storing locals _only_ on the main bucket.
20841    */
20842    if (con->bucket == NULL)
20843	con->bucket = rootBucket;
20844
20845    /* TODO:
20846    * SPEC (src-redefine):
20847    * (6.2) "If it has no such self-reference, then all of the
20848    * following must be true:"
20849
20850    * (6.2.2) The {model group} of the model group definition which
20851    * corresponds to it per XML Representation of Model Group
20852    * Definition Schema Components (�3.7.2) must be a �valid
20853    * restriction� of the {model group} of that model group definition
20854    * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20855    */
20856    xmlSchemaCheckSRCRedefineFirst(pctxt);
20857
20858    /*
20859    * Add global components to the schemata's hash tables.
20860    */
20861    xmlSchemaAddComponents(pctxt, rootBucket);
20862
20863    pctxt->ctxtType = NULL;
20864    items = (xmlSchemaTreeItemPtr *) con->pending->items;
20865    nbItems = con->pending->nbItems;
20866    /*
20867    * Now that we have parsed *all* the schema document(s) and converted
20868    * them to schema components, we can resolve references, apply component
20869    * constraints, create the FSA from the content model, etc.
20870    */
20871    /*
20872    * Resolve references of..
20873    *
20874    * 1. element declarations:
20875    *   - the type definition
20876    *   - the substitution group affiliation
20877    * 2. simple/complex types:
20878    *   - the base type definition
20879    *   - the memberTypes of union types
20880    *   - the itemType of list types
20881    * 3. attributes declarations and attribute uses:
20882    *   - the type definition
20883    *   - if an attribute use, then the attribute declaration
20884    * 4. attribute group references:
20885    *   - the attribute group definition
20886    * 5. particles:
20887    *   - the term of the particle (e.g. a model group)
20888    * 6. IDC key-references:
20889    *   - the referenced IDC 'key' or 'unique' definition
20890    * 7. Attribute prohibitions which had a "ref" attribute.
20891    */
20892    for (i = 0; i < nbItems; i++) {
20893	item = items[i];
20894	switch (item->type) {
20895	    case XML_SCHEMA_TYPE_ELEMENT:
20896		xmlSchemaResolveElementReferences(
20897		    (xmlSchemaElementPtr) item, pctxt);
20898		FIXHFAILURE;
20899		break;
20900	    case XML_SCHEMA_TYPE_COMPLEX:
20901	    case XML_SCHEMA_TYPE_SIMPLE:
20902		xmlSchemaResolveTypeReferences(
20903		    (xmlSchemaTypePtr) item, pctxt);
20904		FIXHFAILURE;
20905		break;
20906	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20907		xmlSchemaResolveAttrTypeReferences(
20908		    (xmlSchemaAttributePtr) item, pctxt);
20909		FIXHFAILURE;
20910		break;
20911	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20912		xmlSchemaResolveAttrUseReferences(
20913		    (xmlSchemaAttributeUsePtr) item, pctxt);
20914		FIXHFAILURE;
20915		break;
20916	    case XML_SCHEMA_EXTRA_QNAMEREF:
20917		if ((WXS_QNAME_CAST item)->itemType ==
20918		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20919		{
20920		    xmlSchemaResolveAttrGroupReferences(
20921			WXS_QNAME_CAST item, pctxt);
20922		}
20923		FIXHFAILURE;
20924		break;
20925	    case XML_SCHEMA_TYPE_SEQUENCE:
20926	    case XML_SCHEMA_TYPE_CHOICE:
20927	    case XML_SCHEMA_TYPE_ALL:
20928		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20929		    WXS_MODEL_GROUP_CAST item);
20930		FIXHFAILURE;
20931		break;
20932	    case XML_SCHEMA_TYPE_IDC_KEY:
20933	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20934	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20935		xmlSchemaResolveIDCKeyReferences(
20936		    (xmlSchemaIDCPtr) item, pctxt);
20937		FIXHFAILURE;
20938		break;
20939	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20940		/*
20941		* Handle attribue prohibition which had a
20942		* "ref" attribute.
20943		*/
20944		xmlSchemaResolveAttrUseProhibReferences(
20945		    WXS_ATTR_PROHIB_CAST item, pctxt);
20946		FIXHFAILURE;
20947		break;
20948	    default:
20949		break;
20950	}
20951    }
20952    if (pctxt->nberrors != 0)
20953	goto exit_error;
20954
20955    /*
20956    * Now that all references are resolved we
20957    * can check for circularity of...
20958    * 1. the base axis of type definitions
20959    * 2. nested model group definitions
20960    * 3. nested attribute group definitions
20961    * TODO: check for circual substitution groups.
20962    */
20963    for (i = 0; i < nbItems; i++) {
20964	item = items[i];
20965	/*
20966	* Let's better stop on the first error here.
20967	*/
20968	switch (item->type) {
20969	    case XML_SCHEMA_TYPE_COMPLEX:
20970	    case XML_SCHEMA_TYPE_SIMPLE:
20971		xmlSchemaCheckTypeDefCircular(
20972		    (xmlSchemaTypePtr) item, pctxt);
20973		FIXHFAILURE;
20974		if (pctxt->nberrors != 0)
20975		    goto exit_error;
20976		break;
20977	    case XML_SCHEMA_TYPE_GROUP:
20978		xmlSchemaCheckGroupDefCircular(
20979		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20980		FIXHFAILURE;
20981		if (pctxt->nberrors != 0)
20982		    goto exit_error;
20983		break;
20984	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20985		xmlSchemaCheckAttrGroupCircular(
20986		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20987		FIXHFAILURE;
20988		if (pctxt->nberrors != 0)
20989		    goto exit_error;
20990		break;
20991	    default:
20992		break;
20993	}
20994    }
20995    if (pctxt->nberrors != 0)
20996	goto exit_error;
20997    /*
20998    * Model group definition references:
20999    * Such a reference is reflected by a particle at the component
21000    * level. Until now the 'term' of such particles pointed
21001    * to the model group definition; this was done, in order to
21002    * ease circularity checks. Now we need to set the 'term' of
21003    * such particles to the model group of the model group definition.
21004    */
21005    for (i = 0; i < nbItems; i++) {
21006	item = items[i];
21007	switch (item->type) {
21008	    case XML_SCHEMA_TYPE_SEQUENCE:
21009	    case XML_SCHEMA_TYPE_CHOICE:
21010		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21011		    WXS_MODEL_GROUP_CAST item);
21012		break;
21013	    default:
21014		break;
21015	}
21016    }
21017    if (pctxt->nberrors != 0)
21018	goto exit_error;
21019    /*
21020    * Expand attribute group references of attribute group definitions.
21021    */
21022    for (i = 0; i < nbItems; i++) {
21023	item = items[i];
21024	switch (item->type) {
21025            case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21026		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21027		    WXS_ATTR_GROUP_HAS_REFS(item))
21028		{
21029		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21030			WXS_ATTR_GROUP_CAST item);
21031		    FIXHFAILURE;
21032		}
21033		break;
21034	    default:
21035		break;
21036	}
21037    }
21038    if (pctxt->nberrors != 0)
21039	goto exit_error;
21040    /*
21041    * First compute the variety of simple types. This is needed as
21042    * a seperate step, since otherwise we won't be able to detect
21043    * circular union types in all cases.
21044    */
21045    for (i = 0; i < nbItems; i++) {
21046	item = items[i];
21047	switch (item->type) {
21048            case XML_SCHEMA_TYPE_SIMPLE:
21049		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21050		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21051			(xmlSchemaTypePtr) item);
21052		    FIXHFAILURE;
21053		}
21054		break;
21055	    default:
21056		break;
21057	}
21058    }
21059    if (pctxt->nberrors != 0)
21060	goto exit_error;
21061    /*
21062    * Detect circular union types. Note that this needs the variety to
21063    * be already computed.
21064    */
21065    for (i = 0; i < nbItems; i++) {
21066	item = items[i];
21067	switch (item->type) {
21068            case XML_SCHEMA_TYPE_SIMPLE:
21069		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21070		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21071			(xmlSchemaTypePtr) item);
21072		    FIXHFAILURE;
21073		}
21074		break;
21075	    default:
21076		break;
21077	}
21078    }
21079    if (pctxt->nberrors != 0)
21080	goto exit_error;
21081
21082    /*
21083    * Do the complete type fixup for simple types.
21084    */
21085    for (i = 0; i < nbItems; i++) {
21086	item = items[i];
21087	switch (item->type) {
21088            case XML_SCHEMA_TYPE_SIMPLE:
21089		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21090		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21091		    FIXHFAILURE;
21092		}
21093		break;
21094	    default:
21095		break;
21096	}
21097    }
21098    if (pctxt->nberrors != 0)
21099	goto exit_error;
21100    /*
21101    * At this point we need build and check all simple types.
21102    */
21103    /*
21104    * Apply contraints for attribute declarations.
21105    */
21106    for (i = 0; i < nbItems; i++) {
21107	item = items[i];
21108	switch (item->type) {
21109	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21110		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21111		FIXHFAILURE;
21112		break;
21113	    default:
21114		break;
21115	}
21116    }
21117    if (pctxt->nberrors != 0)
21118	goto exit_error;
21119    /*
21120    * Apply constraints for attribute uses.
21121    */
21122    for (i = 0; i < nbItems; i++) {
21123	item = items[i];
21124	switch (item->type) {
21125	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21126		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21127		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21128			WXS_ATTR_USE_CAST item);
21129		    FIXHFAILURE;
21130		}
21131		break;
21132	    default:
21133		break;
21134	}
21135    }
21136    if (pctxt->nberrors != 0)
21137	goto exit_error;
21138
21139    /*
21140    * Apply constraints for attribute group definitions.
21141    */
21142    for (i = 0; i < nbItems; i++) {
21143	item = items[i];
21144	switch (item->type) {
21145	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21146	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21147		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21148	    {
21149		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21150		FIXHFAILURE;
21151	    }
21152	    break;
21153	default:
21154	    break;
21155	}
21156    }
21157    if (pctxt->nberrors != 0)
21158	goto exit_error;
21159
21160    /*
21161    * Apply constraints for redefinitions.
21162    */
21163    if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21164	xmlSchemaCheckSRCRedefineSecond(pctxt);
21165    if (pctxt->nberrors != 0)
21166	goto exit_error;
21167
21168    /*
21169    * Complex types are builded and checked.
21170    */
21171    for (i = 0; i < nbItems; i++) {
21172	item = con->pending->items[i];
21173	switch (item->type) {
21174	    case XML_SCHEMA_TYPE_COMPLEX:
21175		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21176		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21177		    FIXHFAILURE;
21178		}
21179		break;
21180	    default:
21181		break;
21182	}
21183    }
21184    if (pctxt->nberrors != 0)
21185	goto exit_error;
21186
21187    /*
21188    * The list could have changed, since xmlSchemaFixupComplexType()
21189    * will create particles and model groups in some cases.
21190    */
21191    items = (xmlSchemaTreeItemPtr *) con->pending->items;
21192    nbItems = con->pending->nbItems;
21193
21194    /*
21195    * Apply some constraints for element declarations.
21196    */
21197    for (i = 0; i < nbItems; i++) {
21198	item = items[i];
21199	switch (item->type) {
21200	    case XML_SCHEMA_TYPE_ELEMENT:
21201		elemDecl = (xmlSchemaElementPtr) item;
21202
21203		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21204		{
21205		    xmlSchemaCheckElementDeclComponent(
21206			(xmlSchemaElementPtr) elemDecl, pctxt);
21207		    FIXHFAILURE;
21208		}
21209
21210#ifdef WXS_ELEM_DECL_CONS_ENABLED
21211		/*
21212		* Schema Component Constraint: Element Declarations Consistent
21213		* Apply this constraint to local types of element declarations.
21214		*/
21215		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21216		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21217		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21218		{
21219		    xmlSchemaCheckElementDeclConsistent(pctxt,
21220			WXS_BASIC_CAST elemDecl,
21221			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21222			NULL, NULL, 0);
21223		}
21224#endif
21225		break;
21226	    default:
21227		break;
21228	}
21229    }
21230    if (pctxt->nberrors != 0)
21231	goto exit_error;
21232
21233    /*
21234    * Finally we can build the automaton from the content model of
21235    * complex types.
21236    */
21237
21238    for (i = 0; i < nbItems; i++) {
21239	item = items[i];
21240	switch (item->type) {
21241	    case XML_SCHEMA_TYPE_COMPLEX:
21242		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21243		/* FIXHFAILURE; */
21244		break;
21245	    default:
21246		break;
21247	}
21248    }
21249    if (pctxt->nberrors != 0)
21250	goto exit_error;
21251    /*
21252    * URGENT TODO: cos-element-consistent
21253    */
21254    goto exit;
21255
21256exit_error:
21257    ret = pctxt->err;
21258    goto exit;
21259
21260exit_failure:
21261    ret = -1;
21262
21263exit:
21264    /*
21265    * Reset the constructor. This is needed for XSI acquisition, since
21266    * those items will be processed over and over again for every XSI
21267    * if not cleared here.
21268    */
21269    con->bucket = oldbucket;
21270    con->pending->nbItems = 0;
21271    if (con->substGroups != NULL) {
21272	xmlHashFree(con->substGroups,
21273	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21274	con->substGroups = NULL;
21275    }
21276    if (con->redefs != NULL) {
21277	xmlSchemaRedefListFree(con->redefs);
21278	con->redefs = NULL;
21279    }
21280    return(ret);
21281}
21282/**
21283 * xmlSchemaParse:
21284 * @ctxt:  a schema validation context
21285 *
21286 * parse a schema definition resource and build an internal
21287 * XML Shema struture which can be used to validate instances.
21288 *
21289 * Returns the internal XML Schema structure built from the resource or
21290 *         NULL in case of error
21291 */
21292xmlSchemaPtr
21293xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21294{
21295    xmlSchemaPtr mainSchema = NULL;
21296    xmlSchemaBucketPtr bucket = NULL;
21297    int res;
21298
21299    /*
21300    * This one is used if the schema to be parsed was specified via
21301    * the API; i.e. not automatically by the validated instance document.
21302    */
21303
21304    xmlSchemaInitTypes();
21305
21306    if (ctxt == NULL)
21307        return (NULL);
21308
21309    /* TODO: Init the context. Is this all we need?*/
21310    ctxt->nberrors = 0;
21311    ctxt->err = 0;
21312    ctxt->counter = 0;
21313
21314    /* Create the *main* schema. */
21315    mainSchema = xmlSchemaNewSchema(ctxt);
21316    if (mainSchema == NULL)
21317	goto exit_failure;
21318    /*
21319    * Create the schema constructor.
21320    */
21321    if (ctxt->constructor == NULL) {
21322	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21323	if (ctxt->constructor == NULL)
21324	    return(NULL);
21325	/* Take ownership of the constructor to be able to free it. */
21326	ctxt->ownsConstructor = 1;
21327    }
21328    ctxt->constructor->mainSchema = mainSchema;
21329    /*
21330    * Locate and add the schema document.
21331    */
21332    res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21333	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21334	NULL, NULL, &bucket);
21335    if (res == -1)
21336	goto exit_failure;
21337    if (res != 0)
21338	goto exit;
21339
21340    if (bucket == NULL) {
21341	/* TODO: Error code, actually we failed to *locate* the schema. */
21342	if (ctxt->URL)
21343	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21344		NULL, NULL,
21345		"Failed to locate the main schema resource at '%s'",
21346		ctxt->URL, NULL);
21347	else
21348	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21349		NULL, NULL,
21350		"Failed to locate the main schema resource",
21351		    NULL, NULL);
21352	goto exit;
21353    }
21354    /* Then do the parsing for good. */
21355    if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21356	goto exit_failure;
21357    if (ctxt->nberrors != 0)
21358	goto exit;
21359
21360    mainSchema->doc = bucket->doc;
21361    mainSchema->preserve = ctxt->preserve;
21362
21363    ctxt->schema = mainSchema;
21364
21365    if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21366	goto exit_failure;
21367
21368    /*
21369    * TODO: This is not nice, since we cannot distinguish from the
21370    * result if there was an internal error or not.
21371    */
21372exit:
21373    if (ctxt->nberrors != 0) {
21374	if (mainSchema) {
21375	    xmlSchemaFree(mainSchema);
21376	    mainSchema = NULL;
21377	}
21378	if (ctxt->constructor) {
21379	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21380	    ctxt->constructor = NULL;
21381	    ctxt->ownsConstructor = 0;
21382	}
21383    }
21384    ctxt->schema = NULL;
21385    return(mainSchema);
21386exit_failure:
21387    /*
21388    * Quite verbose, but should catch internal errors, which were
21389    * not communitated.
21390    */
21391    if (mainSchema) {
21392        xmlSchemaFree(mainSchema);
21393	mainSchema = NULL;
21394    }
21395    if (ctxt->constructor) {
21396	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21397	ctxt->constructor = NULL;
21398	ctxt->ownsConstructor = 0;
21399    }
21400    PERROR_INT2("xmlSchemaParse",
21401	"An internal error occured");
21402    ctxt->schema = NULL;
21403    return(NULL);
21404}
21405
21406/**
21407 * xmlSchemaSetParserErrors:
21408 * @ctxt:  a schema validation context
21409 * @err:  the error callback
21410 * @warn:  the warning callback
21411 * @ctx:  contextual data for the callbacks
21412 *
21413 * Set the callback functions used to handle errors for a validation context
21414 */
21415void
21416xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21417                         xmlSchemaValidityErrorFunc err,
21418                         xmlSchemaValidityWarningFunc warn, void *ctx)
21419{
21420    if (ctxt == NULL)
21421        return;
21422    ctxt->error = err;
21423    ctxt->warning = warn;
21424    ctxt->errCtxt = ctx;
21425    if (ctxt->vctxt != NULL)
21426	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21427}
21428
21429/**
21430 * xmlSchemaSetParserStructuredErrors:
21431 * @ctxt:  a schema parser context
21432 * @serror:  the structured error function
21433 * @ctx: the functions context
21434 *
21435 * Set the structured error callback
21436 */
21437void
21438xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21439				   xmlStructuredErrorFunc serror,
21440				   void *ctx)
21441{
21442    if (ctxt == NULL)
21443	return;
21444    ctxt->serror = serror;
21445    ctxt->errCtxt = ctx;
21446    if (ctxt->vctxt != NULL)
21447	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21448}
21449
21450/**
21451 * xmlSchemaGetParserErrors:
21452 * @ctxt:  a XMl-Schema parser context
21453 * @err: the error callback result
21454 * @warn: the warning callback result
21455 * @ctx: contextual data for the callbacks result
21456 *
21457 * Get the callback information used to handle errors for a parser context
21458 *
21459 * Returns -1 in case of failure, 0 otherwise
21460 */
21461int
21462xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21463			 xmlSchemaValidityErrorFunc * err,
21464			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21465{
21466	if (ctxt == NULL)
21467		return(-1);
21468	if (err != NULL)
21469		*err = ctxt->error;
21470	if (warn != NULL)
21471		*warn = ctxt->warning;
21472	if (ctx != NULL)
21473		*ctx = ctxt->errCtxt;
21474	return(0);
21475}
21476
21477/**
21478 * xmlSchemaFacetTypeToString:
21479 * @type:  the facet type
21480 *
21481 * Convert the xmlSchemaTypeType to a char string.
21482 *
21483 * Returns the char string representation of the facet type if the
21484 *     type is a facet and an "Internal Error" string otherwise.
21485 */
21486static const xmlChar *
21487xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21488{
21489    switch (type) {
21490        case XML_SCHEMA_FACET_PATTERN:
21491            return (BAD_CAST "pattern");
21492        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21493            return (BAD_CAST "maxExclusive");
21494        case XML_SCHEMA_FACET_MAXINCLUSIVE:
21495            return (BAD_CAST "maxInclusive");
21496        case XML_SCHEMA_FACET_MINEXCLUSIVE:
21497            return (BAD_CAST "minExclusive");
21498        case XML_SCHEMA_FACET_MININCLUSIVE:
21499            return (BAD_CAST "minInclusive");
21500        case XML_SCHEMA_FACET_WHITESPACE:
21501            return (BAD_CAST "whiteSpace");
21502        case XML_SCHEMA_FACET_ENUMERATION:
21503            return (BAD_CAST "enumeration");
21504        case XML_SCHEMA_FACET_LENGTH:
21505            return (BAD_CAST "length");
21506        case XML_SCHEMA_FACET_MAXLENGTH:
21507            return (BAD_CAST "maxLength");
21508        case XML_SCHEMA_FACET_MINLENGTH:
21509            return (BAD_CAST "minLength");
21510        case XML_SCHEMA_FACET_TOTALDIGITS:
21511            return (BAD_CAST "totalDigits");
21512        case XML_SCHEMA_FACET_FRACTIONDIGITS:
21513            return (BAD_CAST "fractionDigits");
21514        default:
21515            break;
21516    }
21517    return (BAD_CAST "Internal Error");
21518}
21519
21520static xmlSchemaWhitespaceValueType
21521xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21522{
21523    /*
21524    * The normalization type can be changed only for types which are derived
21525    * from xsd:string.
21526    */
21527    if (type->type == XML_SCHEMA_TYPE_BASIC) {
21528	/*
21529	* Note that we assume a whitespace of preserve for anySimpleType.
21530	*/
21531	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21532	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21533	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21534	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21535	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21536	else {
21537	    /*
21538	    * For all �atomic� datatypes other than string (and types �derived�
21539	    * by �restriction� from it) the value of whiteSpace is fixed to
21540	    * collapse
21541	    * Note that this includes built-in list datatypes.
21542	    */
21543	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21544	}
21545    } else if (WXS_IS_LIST(type)) {
21546	/*
21547	* For list types the facet "whiteSpace" is fixed to "collapse".
21548	*/
21549	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21550    } else if (WXS_IS_UNION(type)) {
21551	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21552    } else if (WXS_IS_ATOMIC(type)) {
21553	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21554	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21555	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21556	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21557	else
21558	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21559    }
21560    return (-1);
21561}
21562
21563/************************************************************************
21564 *									*
21565 *			Simple type validation				*
21566 *									*
21567 ************************************************************************/
21568
21569
21570/************************************************************************
21571 *									*
21572 *			DOM Validation code				*
21573 *									*
21574 ************************************************************************/
21575
21576/**
21577 * xmlSchemaAssembleByLocation:
21578 * @pctxt:  a schema parser context
21579 * @vctxt:  a schema validation context
21580 * @schema: the existing schema
21581 * @node: the node that fired the assembling
21582 * @nsName: the namespace name of the new schema
21583 * @location: the location of the schema
21584 *
21585 * Expands an existing schema by an additional schema.
21586 *
21587 * Returns 0 if the new schema is correct, a positive error code
21588 * number otherwise and -1 in case of an internal or API error.
21589 */
21590static int
21591xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21592			    xmlSchemaPtr schema,
21593			    xmlNodePtr node,
21594			    const xmlChar *nsName,
21595			    const xmlChar *location)
21596{
21597    int ret = 0;
21598    xmlSchemaParserCtxtPtr pctxt;
21599    xmlSchemaBucketPtr bucket = NULL;
21600
21601    if ((vctxt == NULL) || (schema == NULL))
21602	return (-1);
21603
21604    if (vctxt->pctxt == NULL) {
21605	VERROR_INT("xmlSchemaAssembleByLocation",
21606	    "no parser context available");
21607	return(-1);
21608    }
21609    pctxt = vctxt->pctxt;
21610    if (pctxt->constructor == NULL) {
21611	PERROR_INT("xmlSchemaAssembleByLocation",
21612	    "no constructor");
21613	return(-1);
21614    }
21615    /*
21616    * Acquire the schema document.
21617    */
21618    location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21619	location, node);
21620    /*
21621    * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21622    * the process will automatically change this to
21623    * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21624    */
21625    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21626	location, NULL, NULL, 0, node, NULL, nsName,
21627	&bucket);
21628    if (ret != 0)
21629	return(ret);
21630    if (bucket == NULL) {
21631	/*
21632	* Generate a warning that the document could not be located.
21633	*/
21634	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21635	    node, NULL,
21636	    "The document at location '%s' could not be acquired",
21637	    location, NULL, NULL);
21638	return(ret);
21639    }
21640    /*
21641    * The first located schema will be handled as if all other
21642    * schemas imported by XSI were imported by this first schema.
21643    */
21644    if ((bucket != NULL) &&
21645	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21646	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21647    /*
21648    * TODO: Is this handled like an import? I.e. is it not an error
21649    * if the schema cannot be located?
21650    */
21651    if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21652	return(0);
21653    /*
21654    * We will reuse the parser context for every schema imported
21655    * directly via XSI. So reset the context.
21656    */
21657    pctxt->nberrors = 0;
21658    pctxt->err = 0;
21659    pctxt->doc = bucket->doc;
21660
21661    ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21662    if (ret == -1) {
21663	pctxt->doc = NULL;
21664	goto exit_failure;
21665    }
21666    /* Paranoid error channelling. */
21667    if ((ret == 0) && (pctxt->nberrors != 0))
21668	ret = pctxt->err;
21669    if (pctxt->nberrors == 0) {
21670	/*
21671	* Only bother to fixup pending components, if there was
21672	* no error yet.
21673	* For every XSI acquired schema (and its sub-schemata) we will
21674	* fixup the components.
21675	*/
21676	xmlSchemaFixupComponents(pctxt, bucket);
21677	ret = pctxt->err;
21678	/*
21679	* Not nice, but we need somehow to channel the schema parser
21680	* error to the validation context.
21681	*/
21682	if ((ret != 0) && (vctxt->err == 0))
21683	    vctxt->err = ret;
21684	vctxt->nberrors += pctxt->nberrors;
21685    } else {
21686	/* Add to validation error sum. */
21687	vctxt->nberrors += pctxt->nberrors;
21688    }
21689    pctxt->doc = NULL;
21690    return(ret);
21691exit_failure:
21692    pctxt->doc = NULL;
21693    return (-1);
21694}
21695
21696static xmlSchemaAttrInfoPtr
21697xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21698			 int metaType)
21699{
21700    if (vctxt->nbAttrInfos == 0)
21701	return (NULL);
21702    {
21703	int i;
21704	xmlSchemaAttrInfoPtr iattr;
21705
21706	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21707	    iattr = vctxt->attrInfos[i];
21708	    if (iattr->metaType == metaType)
21709		return (iattr);
21710	}
21711
21712    }
21713    return (NULL);
21714}
21715
21716/**
21717 * xmlSchemaAssembleByXSI:
21718 * @vctxt:  a schema validation context
21719 *
21720 * Expands an existing schema by an additional schema using
21721 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21722 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21723 * must be set to 1.
21724 *
21725 * Returns 0 if the new schema is correct, a positive error code
21726 * number otherwise and -1 in case of an internal or API error.
21727 */
21728static int
21729xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21730{
21731    const xmlChar *cur, *end;
21732    const xmlChar *nsname = NULL, *location;
21733    int count = 0;
21734    int ret = 0;
21735    xmlSchemaAttrInfoPtr iattr;
21736
21737    /*
21738    * Parse the value; we will assume an even number of values
21739    * to be given (this is how Xerces and XSV work).
21740    *
21741    * URGENT TODO: !! This needs to work for both
21742    * @noNamespaceSchemaLocation AND @schemaLocation on the same
21743    * element !!
21744    */
21745    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21746	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21747    if (iattr == NULL)
21748	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21749	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21750    if (iattr == NULL)
21751	return (0);
21752    cur = iattr->value;
21753    do {
21754	/*
21755	* TODO: Move the string parsing mechanism away from here.
21756	*/
21757	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21758	    /*
21759	    * Get the namespace name.
21760	    */
21761	    while (IS_BLANK_CH(*cur))
21762		cur++;
21763	    end = cur;
21764	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21765		end++;
21766	    if (end == cur)
21767		break;
21768	    count++; /* TODO: Don't use the schema's dict. */
21769	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21770	    cur = end;
21771	}
21772	/*
21773	* Get the URI.
21774	*/
21775	while (IS_BLANK_CH(*cur))
21776	    cur++;
21777	end = cur;
21778	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21779	    end++;
21780	if (end == cur) {
21781	    if (iattr->metaType ==
21782		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21783	    {
21784		/*
21785		* If using @schemaLocation then tuples are expected.
21786		* I.e. the namespace name *and* the document's URI.
21787		*/
21788		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21789		    iattr->node, NULL,
21790		    "The value must consist of tuples: the target namespace "
21791		    "name and the document's URI", NULL, NULL, NULL);
21792	    }
21793	    break;
21794	}
21795	count++; /* TODO: Don't use the schema's dict. */
21796	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21797	cur = end;
21798	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21799	    iattr->node, nsname, location);
21800	if (ret == -1) {
21801	    VERROR_INT("xmlSchemaAssembleByXSI",
21802		"assembling schemata");
21803	    return (-1);
21804	}
21805    } while (*cur != 0);
21806    return (ret);
21807}
21808
21809static const xmlChar *
21810xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21811			 const xmlChar *prefix)
21812{
21813    if (vctxt->sax != NULL) {
21814	int i, j;
21815	xmlSchemaNodeInfoPtr inode;
21816
21817	for (i = vctxt->depth; i >= 0; i--) {
21818	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21819		inode = vctxt->elemInfos[i];
21820		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21821		    if (((prefix == NULL) &&
21822			    (inode->nsBindings[j] == NULL)) ||
21823			((prefix != NULL) && xmlStrEqual(prefix,
21824			    inode->nsBindings[j]))) {
21825
21826			/*
21827			* Note that the namespace bindings are already
21828			* in a string dict.
21829			*/
21830			return (inode->nsBindings[j+1]);
21831		    }
21832		}
21833	    }
21834	}
21835	return (NULL);
21836#ifdef LIBXML_READER_ENABLED
21837    } else if (vctxt->reader != NULL) {
21838	xmlChar *nsName;
21839
21840	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21841	if (nsName != NULL) {
21842	    const xmlChar *ret;
21843
21844	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21845	    xmlFree(nsName);
21846	    return (ret);
21847	} else
21848	    return (NULL);
21849#endif
21850    } else {
21851	xmlNsPtr ns;
21852
21853	if ((vctxt->inode->node == NULL) ||
21854	    (vctxt->inode->node->doc == NULL)) {
21855	    VERROR_INT("xmlSchemaLookupNamespace",
21856		"no node or node's doc avaliable");
21857	    return (NULL);
21858	}
21859	ns = xmlSearchNs(vctxt->inode->node->doc,
21860	    vctxt->inode->node, prefix);
21861	if (ns != NULL)
21862	    return (ns->href);
21863	return (NULL);
21864    }
21865}
21866
21867/*
21868* This one works on the schema of the validation context.
21869*/
21870static int
21871xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21872			  xmlSchemaPtr schema,
21873			  xmlNodePtr node,
21874			  const xmlChar *value,
21875			  xmlSchemaValPtr *val,
21876			  int valNeeded)
21877{
21878    int ret;
21879
21880    if (vctxt && (vctxt->schema == NULL)) {
21881	VERROR_INT("xmlSchemaValidateNotation",
21882	    "a schema is needed on the validation context");
21883	return (-1);
21884    }
21885    ret = xmlValidateQName(value, 1);
21886    if (ret != 0)
21887	return (ret);
21888    {
21889	xmlChar *localName = NULL;
21890	xmlChar *prefix = NULL;
21891
21892	localName = xmlSplitQName2(value, &prefix);
21893	if (prefix != NULL) {
21894	    const xmlChar *nsName = NULL;
21895
21896	    if (vctxt != NULL)
21897		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21898	    else if (node != NULL) {
21899		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21900		if (ns != NULL)
21901		    nsName = ns->href;
21902	    } else {
21903		xmlFree(prefix);
21904		xmlFree(localName);
21905		return (1);
21906	    }
21907	    if (nsName == NULL) {
21908		xmlFree(prefix);
21909		xmlFree(localName);
21910		return (1);
21911	    }
21912	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21913		if ((valNeeded) && (val != NULL)) {
21914		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21915						       xmlStrdup(nsName));
21916		    if (*val == NULL)
21917			ret = -1;
21918		}
21919	    } else
21920		ret = 1;
21921	    xmlFree(prefix);
21922	    xmlFree(localName);
21923	} else {
21924	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21925		if (valNeeded && (val != NULL)) {
21926		    (*val) = xmlSchemaNewNOTATIONValue(
21927			BAD_CAST xmlStrdup(value), NULL);
21928		    if (*val == NULL)
21929			ret = -1;
21930		}
21931	    } else
21932		return (1);
21933	}
21934    }
21935    return (ret);
21936}
21937
21938static int
21939xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21940		       const xmlChar* lname,
21941		       const xmlChar* nsname)
21942{
21943    int i;
21944
21945    lname = xmlDictLookup(vctxt->dict, lname, -1);
21946    if (lname == NULL)
21947	return(-1);
21948    if (nsname != NULL) {
21949	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21950	if (nsname == NULL)
21951	    return(-1);
21952    }
21953    for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21954	if ((vctxt->nodeQNames->items [i] == lname) &&
21955	    (vctxt->nodeQNames->items[i +1] == nsname))
21956	    /* Already there */
21957	    return(i);
21958    }
21959    /* Add new entry. */
21960    i = vctxt->nodeQNames->nbItems;
21961    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21962    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21963    return(i);
21964}
21965
21966/************************************************************************
21967 *									*
21968 *  Validation of identity-constraints (IDC)                            *
21969 *									*
21970 ************************************************************************/
21971
21972/**
21973 * xmlSchemaAugmentIDC:
21974 * @idcDef: the IDC definition
21975 *
21976 * Creates an augmented IDC definition item.
21977 *
21978 * Returns the item, or NULL on internal errors.
21979 */
21980static void
21981xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21982		    xmlSchemaValidCtxtPtr vctxt)
21983{
21984    xmlSchemaIDCAugPtr aidc;
21985
21986    aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21987    if (aidc == NULL) {
21988	xmlSchemaVErrMemory(vctxt,
21989	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21990	    NULL);
21991	return;
21992    }
21993    aidc->keyrefDepth = -1;
21994    aidc->def = idcDef;
21995    aidc->next = NULL;
21996    if (vctxt->aidcs == NULL)
21997	vctxt->aidcs = aidc;
21998    else {
21999	aidc->next = vctxt->aidcs;
22000	vctxt->aidcs = aidc;
22001    }
22002    /*
22003    * Save if we have keyrefs at all.
22004    */
22005    if ((vctxt->hasKeyrefs == 0) &&
22006	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22007	vctxt->hasKeyrefs = 1;
22008}
22009
22010/**
22011 * xmlSchemaAugmentImportedIDC:
22012 * @imported: the imported schema
22013 *
22014 * Creates an augmented IDC definition for the imported schema.
22015 */
22016static void
22017xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
22018    if (imported->schema->idcDef != NULL) {
22019	    xmlHashScan(imported->schema->idcDef ,
22020	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
22021    }
22022}
22023
22024/**
22025 * xmlSchemaIDCNewBinding:
22026 * @idcDef: the IDC definition of this binding
22027 *
22028 * Creates a new IDC binding.
22029 *
22030 * Returns the new IDC binding, NULL on internal errors.
22031 */
22032static xmlSchemaPSVIIDCBindingPtr
22033xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22034{
22035    xmlSchemaPSVIIDCBindingPtr ret;
22036
22037    ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22038	    sizeof(xmlSchemaPSVIIDCBinding));
22039    if (ret == NULL) {
22040	xmlSchemaVErrMemory(NULL,
22041	    "allocating a PSVI IDC binding item", NULL);
22042	return (NULL);
22043    }
22044    memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22045    ret->definition = idcDef;
22046    return (ret);
22047}
22048
22049/**
22050 * xmlSchemaIDCStoreNodeTableItem:
22051 * @vctxt: the WXS validation context
22052 * @item: the IDC node table item
22053 *
22054 * The validation context is used to store IDC node table items.
22055 * They are stored to avoid copying them if IDC node-tables are merged
22056 * with corresponding parent IDC node-tables (bubbling).
22057 *
22058 * Returns 0 if succeeded, -1 on internal errors.
22059 */
22060static int
22061xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22062			       xmlSchemaPSVIIDCNodePtr item)
22063{
22064    /*
22065    * Add to gobal list.
22066    */
22067    if (vctxt->idcNodes == NULL) {
22068	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22069	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22070	if (vctxt->idcNodes == NULL) {
22071	    xmlSchemaVErrMemory(vctxt,
22072		"allocating the IDC node table item list", NULL);
22073	    return (-1);
22074	}
22075	vctxt->sizeIdcNodes = 20;
22076    } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22077	vctxt->sizeIdcNodes *= 2;
22078	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22079	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22080	    sizeof(xmlSchemaPSVIIDCNodePtr));
22081	if (vctxt->idcNodes == NULL) {
22082	    xmlSchemaVErrMemory(vctxt,
22083		"re-allocating the IDC node table item list", NULL);
22084	    return (-1);
22085	}
22086    }
22087    vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22088
22089    return (0);
22090}
22091
22092/**
22093 * xmlSchemaIDCStoreKey:
22094 * @vctxt: the WXS validation context
22095 * @item: the IDC key
22096 *
22097 * The validation context is used to store an IDC key.
22098 *
22099 * Returns 0 if succeeded, -1 on internal errors.
22100 */
22101static int
22102xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22103		     xmlSchemaPSVIIDCKeyPtr key)
22104{
22105    /*
22106    * Add to gobal list.
22107    */
22108    if (vctxt->idcKeys == NULL) {
22109	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22110	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22111	if (vctxt->idcKeys == NULL) {
22112	    xmlSchemaVErrMemory(vctxt,
22113		"allocating the IDC key storage list", NULL);
22114	    return (-1);
22115	}
22116	vctxt->sizeIdcKeys = 40;
22117    } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22118	vctxt->sizeIdcKeys *= 2;
22119	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22120	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22121	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22122	if (vctxt->idcKeys == NULL) {
22123	    xmlSchemaVErrMemory(vctxt,
22124		"re-allocating the IDC key storage list", NULL);
22125	    return (-1);
22126	}
22127    }
22128    vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22129
22130    return (0);
22131}
22132
22133/**
22134 * xmlSchemaIDCAppendNodeTableItem:
22135 * @bind: the IDC binding
22136 * @ntItem: the node-table item
22137 *
22138 * Appends the IDC node-table item to the binding.
22139 *
22140 * Returns 0 on success and -1 on internal errors.
22141 */
22142static int
22143xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22144				xmlSchemaPSVIIDCNodePtr ntItem)
22145{
22146    if (bind->nodeTable == NULL) {
22147	bind->sizeNodes = 10;
22148	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22149	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22150	if (bind->nodeTable == NULL) {
22151	    xmlSchemaVErrMemory(NULL,
22152		"allocating an array of IDC node-table items", NULL);
22153	    return(-1);
22154	}
22155    } else if (bind->sizeNodes <= bind->nbNodes) {
22156	bind->sizeNodes *= 2;
22157	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22158	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22159		sizeof(xmlSchemaPSVIIDCNodePtr));
22160	if (bind->nodeTable == NULL) {
22161	    xmlSchemaVErrMemory(NULL,
22162		"re-allocating an array of IDC node-table items", NULL);
22163	    return(-1);
22164	}
22165    }
22166    bind->nodeTable[bind->nbNodes++] = ntItem;
22167    return(0);
22168}
22169
22170/**
22171 * xmlSchemaIDCAcquireBinding:
22172 * @vctxt: the WXS validation context
22173 * @matcher: the IDC matcher
22174 *
22175 * Looks up an PSVI IDC binding, for the IDC definition and
22176 * of the given matcher. If none found, a new one is created
22177 * and added to the IDC table.
22178 *
22179 * Returns an IDC binding or NULL on internal errors.
22180 */
22181static xmlSchemaPSVIIDCBindingPtr
22182xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22183			  xmlSchemaIDCMatcherPtr matcher)
22184{
22185    xmlSchemaNodeInfoPtr ielem;
22186
22187    ielem = vctxt->elemInfos[matcher->depth];
22188
22189    if (ielem->idcTable == NULL) {
22190	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22191	if (ielem->idcTable == NULL)
22192	    return (NULL);
22193	return(ielem->idcTable);
22194    } else {
22195	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22196
22197	bind = ielem->idcTable;
22198	do {
22199	    if (bind->definition == matcher->aidc->def)
22200		return(bind);
22201	    if (bind->next == NULL) {
22202		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22203		if (bind->next == NULL)
22204		    return (NULL);
22205		return(bind->next);
22206	    }
22207	    bind = bind->next;
22208	} while (bind != NULL);
22209    }
22210    return (NULL);
22211}
22212
22213static xmlSchemaItemListPtr
22214xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22215			     xmlSchemaIDCMatcherPtr matcher)
22216{
22217    if (matcher->targets == NULL)
22218	matcher->targets = xmlSchemaItemListCreate();
22219    return(matcher->targets);
22220}
22221
22222/**
22223 * xmlSchemaIDCFreeKey:
22224 * @key: the IDC key
22225 *
22226 * Frees an IDC key together with its compiled value.
22227 */
22228static void
22229xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22230{
22231    if (key->val != NULL)
22232	xmlSchemaFreeValue(key->val);
22233    xmlFree(key);
22234}
22235
22236/**
22237 * xmlSchemaIDCFreeBinding:
22238 *
22239 * Frees an IDC binding. Note that the node table-items
22240 * are not freed.
22241 */
22242static void
22243xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22244{
22245    if (bind->nodeTable != NULL)
22246	xmlFree(bind->nodeTable);
22247    if (bind->dupls != NULL)
22248	xmlSchemaItemListFree(bind->dupls);
22249    xmlFree(bind);
22250}
22251
22252/**
22253 * xmlSchemaIDCFreeIDCTable:
22254 * @bind: the first IDC binding in the list
22255 *
22256 * Frees an IDC table, i.e. all the IDC bindings in the list.
22257 */
22258static void
22259xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22260{
22261    xmlSchemaPSVIIDCBindingPtr prev;
22262
22263    while (bind != NULL) {
22264	prev = bind;
22265	bind = bind->next;
22266	xmlSchemaIDCFreeBinding(prev);
22267    }
22268}
22269
22270/**
22271 * xmlSchemaIDCFreeMatcherList:
22272 * @matcher: the first IDC matcher in the list
22273 *
22274 * Frees a list of IDC matchers.
22275 */
22276static void
22277xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22278{
22279    xmlSchemaIDCMatcherPtr next;
22280
22281    while (matcher != NULL) {
22282	next = matcher->next;
22283	if (matcher->keySeqs != NULL) {
22284	    int i;
22285	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22286		if (matcher->keySeqs[i] != NULL)
22287		    xmlFree(matcher->keySeqs[i]);
22288	    xmlFree(matcher->keySeqs);
22289	}
22290	if (matcher->targets != NULL) {
22291	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22292		int i;
22293		xmlSchemaPSVIIDCNodePtr idcNode;
22294		/*
22295		* Node-table items for keyrefs are not stored globally
22296		* to the validation context, since they are not bubbled.
22297		* We need to free them here.
22298		*/
22299		for (i = 0; i < matcher->targets->nbItems; i++) {
22300		    idcNode =
22301			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22302		    xmlFree(idcNode->keys);
22303		    xmlFree(idcNode);
22304		}
22305	    }
22306	    xmlSchemaItemListFree(matcher->targets);
22307	}
22308	xmlFree(matcher);
22309	matcher = next;
22310    }
22311}
22312
22313/**
22314 * xmlSchemaIDCReleaseMatcherList:
22315 * @vctxt: the WXS validation context
22316 * @matcher: the first IDC matcher in the list
22317 *
22318 * Caches a list of IDC matchers for reuse.
22319 */
22320static void
22321xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22322			       xmlSchemaIDCMatcherPtr matcher)
22323{
22324    xmlSchemaIDCMatcherPtr next;
22325
22326    while (matcher != NULL) {
22327	next = matcher->next;
22328	if (matcher->keySeqs != NULL) {
22329	    int i;
22330	    /*
22331	    * Don't free the array, but only the content.
22332	    */
22333	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22334		if (matcher->keySeqs[i] != NULL) {
22335		    xmlFree(matcher->keySeqs[i]);
22336		    matcher->keySeqs[i] = NULL;
22337		}
22338	}
22339	if (matcher->targets) {
22340	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22341		int i;
22342		xmlSchemaPSVIIDCNodePtr idcNode;
22343		/*
22344		* Node-table items for keyrefs are not stored globally
22345		* to the validation context, since they are not bubbled.
22346		* We need to free them here.
22347		*/
22348		for (i = 0; i < matcher->targets->nbItems; i++) {
22349		    idcNode =
22350			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22351		    xmlFree(idcNode->keys);
22352		    xmlFree(idcNode);
22353		}
22354	    }
22355	    xmlSchemaItemListFree(matcher->targets);
22356	    matcher->targets = NULL;
22357	}
22358	matcher->next = NULL;
22359	/*
22360	* Cache the matcher.
22361	*/
22362	if (vctxt->idcMatcherCache != NULL)
22363	    matcher->nextCached = vctxt->idcMatcherCache;
22364	vctxt->idcMatcherCache = matcher;
22365
22366	matcher = next;
22367    }
22368}
22369
22370/**
22371 * xmlSchemaIDCAddStateObject:
22372 * @vctxt: the WXS validation context
22373 * @matcher: the IDC matcher
22374 * @sel: the XPath information
22375 * @parent: the parent "selector" state object if any
22376 * @type: "selector" or "field"
22377 *
22378 * Creates/reuses and activates state objects for the given
22379 * XPath information; if the XPath expression consists of unions,
22380 * multiple state objects are created for every unioned expression.
22381 *
22382 * Returns 0 on success and -1 on internal errors.
22383 */
22384static int
22385xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22386			xmlSchemaIDCMatcherPtr matcher,
22387			xmlSchemaIDCSelectPtr sel,
22388			int type)
22389{
22390    xmlSchemaIDCStateObjPtr sto;
22391
22392    /*
22393    * Reuse the state objects from the pool.
22394    */
22395    if (vctxt->xpathStatePool != NULL) {
22396	sto = vctxt->xpathStatePool;
22397	vctxt->xpathStatePool = sto->next;
22398	sto->next = NULL;
22399    } else {
22400	/*
22401	* Create a new state object.
22402	*/
22403	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22404	if (sto == NULL) {
22405	    xmlSchemaVErrMemory(NULL,
22406		"allocating an IDC state object", NULL);
22407	    return (-1);
22408	}
22409	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22410    }
22411    /*
22412    * Add to global list.
22413    */
22414    if (vctxt->xpathStates != NULL)
22415	sto->next = vctxt->xpathStates;
22416    vctxt->xpathStates = sto;
22417
22418    /*
22419    * Free the old xpath validation context.
22420    */
22421    if (sto->xpathCtxt != NULL)
22422	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22423
22424    /*
22425    * Create a new XPath (pattern) validation context.
22426    */
22427    sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22428	(xmlPatternPtr) sel->xpathComp);
22429    if (sto->xpathCtxt == NULL) {
22430	VERROR_INT("xmlSchemaIDCAddStateObject",
22431	    "failed to create an XPath validation context");
22432	return (-1);
22433    }
22434    sto->type = type;
22435    sto->depth = vctxt->depth;
22436    sto->matcher = matcher;
22437    sto->sel = sel;
22438    sto->nbHistory = 0;
22439
22440#ifdef DEBUG_IDC
22441    xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22442	sto->sel->xpath);
22443#endif
22444    return (0);
22445}
22446
22447/**
22448 * xmlSchemaXPathEvaluate:
22449 * @vctxt: the WXS validation context
22450 * @nodeType: the nodeType of the current node
22451 *
22452 * Evaluates all active XPath state objects.
22453 *
22454 * Returns the number of IC "field" state objects which resolved to
22455 * this node, 0 if none resolved and -1 on internal errors.
22456 */
22457static int
22458xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22459		       xmlElementType nodeType)
22460{
22461    xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22462    int res, resolved = 0, depth = vctxt->depth;
22463
22464    if (vctxt->xpathStates == NULL)
22465	return (0);
22466
22467    if (nodeType == XML_ATTRIBUTE_NODE)
22468	depth++;
22469#ifdef DEBUG_IDC
22470    {
22471	xmlChar *str = NULL;
22472	xmlGenericError(xmlGenericErrorContext,
22473	    "IDC: EVAL on %s, depth %d, type %d\n",
22474	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22475		vctxt->inode->localName), depth, nodeType);
22476	FREE_AND_NULL(str)
22477    }
22478#endif
22479    /*
22480    * Process all active XPath state objects.
22481    */
22482    first = vctxt->xpathStates;
22483    sto = first;
22484    while (sto != head) {
22485#ifdef DEBUG_IDC
22486	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22487	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22488		sto->matcher->aidc->def->name, sto->sel->xpath);
22489	else
22490	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22491		sto->matcher->aidc->def->name, sto->sel->xpath);
22492#endif
22493	if (nodeType == XML_ELEMENT_NODE)
22494	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22495		vctxt->inode->localName, vctxt->inode->nsName);
22496	else
22497	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22498		vctxt->inode->localName, vctxt->inode->nsName);
22499
22500	if (res == -1) {
22501	    VERROR_INT("xmlSchemaXPathEvaluate",
22502		"calling xmlStreamPush()");
22503	    return (-1);
22504	}
22505	if (res == 0)
22506	    goto next_sto;
22507	/*
22508	* Full match.
22509	*/
22510#ifdef DEBUG_IDC
22511	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22512	    "MATCH\n");
22513#endif
22514	/*
22515	* Register a match in the state object history.
22516	*/
22517	if (sto->history == NULL) {
22518	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22519	    if (sto->history == NULL) {
22520		xmlSchemaVErrMemory(NULL,
22521		    "allocating the state object history", NULL);
22522		return(-1);
22523	    }
22524	    sto->sizeHistory = 5;
22525	} else if (sto->sizeHistory <= sto->nbHistory) {
22526	    sto->sizeHistory *= 2;
22527	    sto->history = (int *) xmlRealloc(sto->history,
22528		sto->sizeHistory * sizeof(int));
22529	    if (sto->history == NULL) {
22530		xmlSchemaVErrMemory(NULL,
22531		    "re-allocating the state object history", NULL);
22532		return(-1);
22533	    }
22534	}
22535	sto->history[sto->nbHistory++] = depth;
22536
22537#ifdef DEBUG_IDC
22538	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22539	    vctxt->depth);
22540#endif
22541
22542	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22543	    xmlSchemaIDCSelectPtr sel;
22544	    /*
22545	    * Activate state objects for the IDC fields of
22546	    * the IDC selector.
22547	    */
22548#ifdef DEBUG_IDC
22549	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22550		"activating field states\n");
22551#endif
22552	    sel = sto->matcher->aidc->def->fields;
22553	    while (sel != NULL) {
22554		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22555		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22556		    return (-1);
22557		sel = sel->next;
22558	    }
22559	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22560	    /*
22561	    * An IDC key node was found by the IDC field.
22562	    */
22563#ifdef DEBUG_IDC
22564	    xmlGenericError(xmlGenericErrorContext,
22565		"IDC:     key found\n");
22566#endif
22567	    /*
22568	    * Notify that the character value of this node is
22569	    * needed.
22570	    */
22571	    if (resolved == 0) {
22572		if ((vctxt->inode->flags &
22573		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22574		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22575	    }
22576	    resolved++;
22577	}
22578next_sto:
22579	if (sto->next == NULL) {
22580	    /*
22581	    * Evaluate field state objects created on this node as well.
22582	    */
22583	    head = first;
22584	    sto = vctxt->xpathStates;
22585	} else
22586	    sto = sto->next;
22587    }
22588    return (resolved);
22589}
22590
22591static const xmlChar *
22592xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22593			      xmlChar **buf,
22594			      xmlSchemaPSVIIDCKeyPtr *seq,
22595			      int count)
22596{
22597    int i, res;
22598    xmlChar *value = NULL;
22599
22600    *buf = xmlStrdup(BAD_CAST "[");
22601    for (i = 0; i < count; i++) {
22602	*buf = xmlStrcat(*buf, BAD_CAST "'");
22603	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22604	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22605	    &value);
22606	if (res == 0)
22607	    *buf = xmlStrcat(*buf, BAD_CAST value);
22608	else {
22609	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22610		"failed to compute a canonical value");
22611	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22612	}
22613	if (i < count -1)
22614	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22615	else
22616	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22617	if (value != NULL) {
22618	    xmlFree(value);
22619	    value = NULL;
22620	}
22621    }
22622    *buf = xmlStrcat(*buf, BAD_CAST "]");
22623
22624    return (BAD_CAST *buf);
22625}
22626
22627/**
22628 * xmlSchemaXPathPop:
22629 * @vctxt: the WXS validation context
22630 *
22631 * Pops all XPath states.
22632 *
22633 * Returns 0 on success and -1 on internal errors.
22634 */
22635static int
22636xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22637{
22638    xmlSchemaIDCStateObjPtr sto;
22639    int res;
22640
22641    if (vctxt->xpathStates == NULL)
22642	return(0);
22643    sto = vctxt->xpathStates;
22644    do {
22645	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22646	if (res == -1)
22647	    return (-1);
22648	sto = sto->next;
22649    } while (sto != NULL);
22650    return(0);
22651}
22652
22653/**
22654 * xmlSchemaXPathProcessHistory:
22655 * @vctxt: the WXS validation context
22656 * @type: the simple/complex type of the current node if any at all
22657 * @val: the precompiled value
22658 *
22659 * Processes and pops the history items of the IDC state objects.
22660 * IDC key-sequences are validated/created on IDC bindings.
22661 *
22662 * Returns 0 on success and -1 on internal errors.
22663 */
22664static int
22665xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22666			     int depth)
22667{
22668    xmlSchemaIDCStateObjPtr sto, nextsto;
22669    int res, matchDepth;
22670    xmlSchemaPSVIIDCKeyPtr key = NULL;
22671    xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22672
22673    if (vctxt->xpathStates == NULL)
22674	return (0);
22675    sto = vctxt->xpathStates;
22676
22677#ifdef DEBUG_IDC
22678    {
22679	xmlChar *str = NULL;
22680	xmlGenericError(xmlGenericErrorContext,
22681	    "IDC: BACK on %s, depth %d\n",
22682	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22683		vctxt->inode->localName), vctxt->depth);
22684	FREE_AND_NULL(str)
22685    }
22686#endif
22687    /*
22688    * Evaluate the state objects.
22689    */
22690    while (sto != NULL) {
22691	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22692	if (res == -1) {
22693	    VERROR_INT("xmlSchemaXPathProcessHistory",
22694		"calling xmlStreamPop()");
22695	    return (-1);
22696	}
22697#ifdef DEBUG_IDC
22698	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22699	    sto->sel->xpath);
22700#endif
22701	if (sto->nbHistory == 0)
22702	    goto deregister_check;
22703
22704	matchDepth = sto->history[sto->nbHistory -1];
22705
22706	/*
22707	* Only matches at the current depth are of interest.
22708	*/
22709	if (matchDepth != depth) {
22710	    sto = sto->next;
22711	    continue;
22712	}
22713	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22714	    /*
22715	    * NOTE: According to
22716	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22717	    *   ... the simple-content of complex types is also allowed.
22718	    */
22719
22720	    if (WXS_IS_COMPLEX(type)) {
22721		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22722		    /*
22723		    * Sanity check for complex types with simple content.
22724		    */
22725		    simpleType = type->contentTypeDef;
22726		    if (simpleType == NULL) {
22727			VERROR_INT("xmlSchemaXPathProcessHistory",
22728			    "field resolves to a CT with simple content "
22729			    "but the CT is missing the ST definition");
22730			return (-1);
22731		    }
22732		} else
22733		    simpleType = NULL;
22734	    } else
22735		simpleType = type;
22736	    if (simpleType == NULL) {
22737		xmlChar *str = NULL;
22738
22739		/*
22740		* Not qualified if the field resolves to a node of non
22741		* simple type.
22742		*/
22743		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22744		    XML_SCHEMAV_CVC_IDC, NULL,
22745		    WXS_BASIC_CAST sto->matcher->aidc->def,
22746		    "The XPath '%s' of a field of %s does evaluate to a node of "
22747		    "non-simple type",
22748		    sto->sel->xpath,
22749		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22750		FREE_AND_NULL(str);
22751		sto->nbHistory--;
22752		goto deregister_check;
22753	    }
22754
22755	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22756		/*
22757		* Failed to provide the normalized value; maybe
22758		* the value was invalid.
22759		*/
22760		VERROR(XML_SCHEMAV_CVC_IDC,
22761		    WXS_BASIC_CAST sto->matcher->aidc->def,
22762		    "Warning: No precomputed value available, the value "
22763		    "was either invalid or something strange happend");
22764		sto->nbHistory--;
22765		goto deregister_check;
22766	    } else {
22767		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22768		xmlSchemaPSVIIDCKeyPtr *keySeq;
22769		int pos, idx;
22770
22771		/*
22772		* The key will be anchored on the matcher's list of
22773		* key-sequences. The position in this list is determined
22774		* by the target node's depth relative to the matcher's
22775		* depth of creation (i.e. the depth of the scope element).
22776		*
22777		* Element        Depth    Pos   List-entries
22778		* <scope>          0              NULL
22779		*   <bar>          1              NULL
22780		*     <target/>    2       2      target
22781		*   <bar>
22782                * </scope>
22783		*
22784		* The size of the list is only dependant on the depth of
22785		* the tree.
22786		* An entry will be NULLed in selector_leave, i.e. when
22787		* we hit the target's
22788		*/
22789		pos = sto->depth - matcher->depth;
22790		idx = sto->sel->index;
22791
22792		/*
22793		* Create/grow the array of key-sequences.
22794		*/
22795		if (matcher->keySeqs == NULL) {
22796		    if (pos > 9)
22797			matcher->sizeKeySeqs = pos * 2;
22798		    else
22799			matcher->sizeKeySeqs = 10;
22800		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22801			xmlMalloc(matcher->sizeKeySeqs *
22802			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22803		    if (matcher->keySeqs == NULL) {
22804			xmlSchemaVErrMemory(NULL,
22805			    "allocating an array of key-sequences",
22806			    NULL);
22807			return(-1);
22808		    }
22809		    memset(matcher->keySeqs, 0,
22810			matcher->sizeKeySeqs *
22811			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22812		} else if (pos >= matcher->sizeKeySeqs) {
22813		    int i = matcher->sizeKeySeqs;
22814
22815		    matcher->sizeKeySeqs *= 2;
22816		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22817			xmlRealloc(matcher->keySeqs,
22818			matcher->sizeKeySeqs *
22819			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22820		    if (matcher->keySeqs == NULL) {
22821			xmlSchemaVErrMemory(NULL,
22822			    "reallocating an array of key-sequences",
22823			    NULL);
22824			return (-1);
22825		    }
22826		    /*
22827		    * The array needs to be NULLed.
22828		    * TODO: Use memset?
22829		    */
22830		    for (; i < matcher->sizeKeySeqs; i++)
22831			matcher->keySeqs[i] = NULL;
22832		}
22833
22834		/*
22835		* Get/create the key-sequence.
22836		*/
22837		keySeq = matcher->keySeqs[pos];
22838		if (keySeq == NULL) {
22839		    goto create_sequence;
22840		} else if (keySeq[idx] != NULL) {
22841		    xmlChar *str = NULL;
22842		    /*
22843		    * cvc-identity-constraint:
22844		    * 3 For each node in the �target node set� all
22845		    * of the {fields}, with that node as the context
22846		    * node, evaluate to either an empty node-set or
22847		    * a node-set with exactly one member, which must
22848		    * have a simple type.
22849		    *
22850		    * The key was already set; report an error.
22851		    */
22852		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22853			XML_SCHEMAV_CVC_IDC, NULL,
22854			WXS_BASIC_CAST matcher->aidc->def,
22855			"The XPath '%s' of a field of %s evaluates to a "
22856			"node-set with more than one member",
22857			sto->sel->xpath,
22858			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22859		    FREE_AND_NULL(str);
22860		    sto->nbHistory--;
22861		    goto deregister_check;
22862		} else
22863		    goto create_key;
22864
22865create_sequence:
22866		/*
22867		* Create a key-sequence.
22868		*/
22869		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22870		    matcher->aidc->def->nbFields *
22871		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22872		if (keySeq == NULL) {
22873		    xmlSchemaVErrMemory(NULL,
22874			"allocating an IDC key-sequence", NULL);
22875		    return(-1);
22876		}
22877		memset(keySeq, 0, matcher->aidc->def->nbFields *
22878		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22879		matcher->keySeqs[pos] = keySeq;
22880create_key:
22881		/*
22882		* Create a key once per node only.
22883		*/
22884		if (key == NULL) {
22885		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22886			sizeof(xmlSchemaPSVIIDCKey));
22887		    if (key == NULL) {
22888			xmlSchemaVErrMemory(NULL,
22889			    "allocating a IDC key", NULL);
22890			xmlFree(keySeq);
22891			matcher->keySeqs[pos] = NULL;
22892			return(-1);
22893		    }
22894		    /*
22895		    * Consume the compiled value.
22896		    */
22897		    key->type = simpleType;
22898		    key->val = vctxt->inode->val;
22899		    vctxt->inode->val = NULL;
22900		    /*
22901		    * Store the key in a global list.
22902		    */
22903		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22904			xmlSchemaIDCFreeKey(key);
22905			return (-1);
22906		    }
22907		}
22908		keySeq[idx] = key;
22909	    }
22910	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22911
22912	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22913	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22914	    xmlSchemaPSVIIDCNodePtr ntItem;
22915	    xmlSchemaIDCMatcherPtr matcher;
22916	    xmlSchemaIDCPtr idc;
22917	    xmlSchemaItemListPtr targets;
22918	    int pos, i, j, nbKeys;
22919	    /*
22920	    * Here we have the following scenario:
22921	    * An IDC 'selector' state object resolved to a target node,
22922	    * during the time this target node was in the
22923	    * ancestor-or-self axis, the 'field' state object(s) looked
22924	    * out for matching nodes to create a key-sequence for this
22925	    * target node. Now we are back to this target node and need
22926	    * to put the key-sequence, together with the target node
22927	    * itself, into the node-table of the corresponding IDC
22928	    * binding.
22929	    */
22930	    matcher = sto->matcher;
22931	    idc = matcher->aidc->def;
22932	    nbKeys = idc->nbFields;
22933	    pos = depth - matcher->depth;
22934	    /*
22935	    * Check if the matcher has any key-sequences at all, plus
22936	    * if it has a key-sequence for the current target node.
22937	    */
22938	    if ((matcher->keySeqs == NULL) ||
22939		(matcher->sizeKeySeqs <= pos)) {
22940		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22941		    goto selector_key_error;
22942		else
22943		    goto selector_leave;
22944	    }
22945
22946	    keySeq = &(matcher->keySeqs[pos]);
22947	    if (*keySeq == NULL) {
22948		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22949		    goto selector_key_error;
22950		else
22951		    goto selector_leave;
22952	    }
22953
22954	    for (i = 0; i < nbKeys; i++) {
22955		if ((*keySeq)[i] == NULL) {
22956		    /*
22957		    * Not qualified, if not all fields did resolve.
22958		    */
22959		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22960			/*
22961			* All fields of a "key" IDC must resolve.
22962			*/
22963			goto selector_key_error;
22964		    }
22965		    goto selector_leave;
22966		}
22967	    }
22968	    /*
22969	    * All fields did resolve.
22970	    */
22971
22972	    /*
22973	    * 4.1 If the {identity-constraint category} is unique(/key),
22974	    * then no two members of the �qualified node set� have
22975	    * �key-sequences� whose members are pairwise equal, as
22976	    * defined by Equal in [XML Schemas: Datatypes].
22977	    *
22978	    * Get the IDC binding from the matcher and check for
22979	    * duplicate key-sequences.
22980	    */
22981#if 0
22982	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22983#endif
22984	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22985	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22986		(targets->nbItems != 0)) {
22987		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22988
22989		i = 0;
22990		res = 0;
22991		/*
22992		* Compare the key-sequences, key by key.
22993		*/
22994		do {
22995		    bkeySeq =
22996			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22997		    for (j = 0; j < nbKeys; j++) {
22998			ckey = (*keySeq)[j];
22999			bkey = bkeySeq[j];
23000			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23001			if (res == -1) {
23002			    return (-1);
23003			} else if (res == 0) {
23004			    /*
23005			    * One of the keys differs, so the key-sequence
23006			    * won't be equal; get out.
23007			    */
23008			    break;
23009			}
23010		    }
23011		    if (res == 1) {
23012			/*
23013			* Duplicate key-sequence found.
23014			*/
23015			break;
23016		    }
23017		    i++;
23018		} while (i < targets->nbItems);
23019		if (i != targets->nbItems) {
23020		    xmlChar *str = NULL, *strB = NULL;
23021		    /*
23022		    * TODO: Try to report the key-sequence.
23023		    */
23024		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23025			XML_SCHEMAV_CVC_IDC, NULL,
23026			WXS_BASIC_CAST idc,
23027			"Duplicate key-sequence %s in %s",
23028			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23029			    (*keySeq), nbKeys),
23030			xmlSchemaGetIDCDesignation(&strB, idc));
23031		    FREE_AND_NULL(str);
23032		    FREE_AND_NULL(strB);
23033		    goto selector_leave;
23034		}
23035	    }
23036	    /*
23037	    * Add a node-table item to the IDC binding.
23038	    */
23039	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23040		sizeof(xmlSchemaPSVIIDCNode));
23041	    if (ntItem == NULL) {
23042		xmlSchemaVErrMemory(NULL,
23043		    "allocating an IDC node-table item", NULL);
23044		xmlFree(*keySeq);
23045		*keySeq = NULL;
23046		return(-1);
23047	    }
23048	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23049
23050	    /*
23051	    * Store the node-table item in a global list.
23052	    */
23053	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23054		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23055		    xmlFree(ntItem);
23056		    xmlFree(*keySeq);
23057		    *keySeq = NULL;
23058		    return (-1);
23059		}
23060		ntItem->nodeQNameID = -1;
23061	    } else {
23062		/*
23063		* Save a cached QName for this node on the IDC node, to be
23064		* able to report it, even if the node is not saved.
23065		*/
23066		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23067		    vctxt->inode->localName, vctxt->inode->nsName);
23068		if (ntItem->nodeQNameID == -1) {
23069		    xmlFree(ntItem);
23070		    xmlFree(*keySeq);
23071		    *keySeq = NULL;
23072		    return (-1);
23073		}
23074	    }
23075	    /*
23076	    * Init the node-table item: Save the node, position and
23077	    * consume the key-sequence.
23078	    */
23079	    ntItem->node = vctxt->node;
23080	    ntItem->nodeLine = vctxt->inode->nodeLine;
23081	    ntItem->keys = *keySeq;
23082	    *keySeq = NULL;
23083#if 0
23084	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23085#endif
23086	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23087		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23088		    /*
23089		    * Free the item, since keyref items won't be
23090		    * put on a global list.
23091		    */
23092		    xmlFree(ntItem->keys);
23093		    xmlFree(ntItem);
23094		}
23095		return (-1);
23096	    }
23097
23098	    goto selector_leave;
23099selector_key_error:
23100	    {
23101		xmlChar *str = NULL;
23102		/*
23103		* 4.2.1 (KEY) The �target node set� and the
23104		* �qualified node set� are equal, that is, every
23105		* member of the �target node set� is also a member
23106		* of the �qualified node set� and vice versa.
23107		*/
23108		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23109		    XML_SCHEMAV_CVC_IDC, NULL,
23110		    WXS_BASIC_CAST idc,
23111		    "Not all fields of %s evaluate to a node",
23112		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23113		FREE_AND_NULL(str);
23114	    }
23115selector_leave:
23116	    /*
23117	    * Free the key-sequence if not added to the IDC table.
23118	    */
23119	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23120		xmlFree(*keySeq);
23121		*keySeq = NULL;
23122	    }
23123	} /* if selector */
23124
23125	sto->nbHistory--;
23126
23127deregister_check:
23128	/*
23129	* Deregister state objects if they reach the depth of creation.
23130	*/
23131	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23132#ifdef DEBUG_IDC
23133	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23134		sto->sel->xpath);
23135#endif
23136	    if (vctxt->xpathStates != sto) {
23137		VERROR_INT("xmlSchemaXPathProcessHistory",
23138		    "The state object to be removed is not the first "
23139		    "in the list");
23140	    }
23141	    nextsto = sto->next;
23142	    /*
23143	    * Unlink from the list of active XPath state objects.
23144	    */
23145	    vctxt->xpathStates = sto->next;
23146	    sto->next = vctxt->xpathStatePool;
23147	    /*
23148	    * Link it to the pool of reusable state objects.
23149	    */
23150	    vctxt->xpathStatePool = sto;
23151	    sto = nextsto;
23152	} else
23153	    sto = sto->next;
23154    } /* while (sto != NULL) */
23155    return (0);
23156}
23157
23158/**
23159 * xmlSchemaIDCRegisterMatchers:
23160 * @vctxt: the WXS validation context
23161 * @elemDecl: the element declaration
23162 *
23163 * Creates helper objects to evaluate IDC selectors/fields
23164 * successively.
23165 *
23166 * Returns 0 if OK and -1 on internal errors.
23167 */
23168static int
23169xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23170			     xmlSchemaElementPtr elemDecl)
23171{
23172    xmlSchemaIDCMatcherPtr matcher, last = NULL;
23173    xmlSchemaIDCPtr idc, refIdc;
23174    xmlSchemaIDCAugPtr aidc;
23175
23176    idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23177    if (idc == NULL)
23178	return (0);
23179
23180#ifdef DEBUG_IDC
23181    {
23182	xmlChar *str = NULL;
23183	xmlGenericError(xmlGenericErrorContext,
23184	    "IDC: REGISTER on %s, depth %d\n",
23185	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23186		vctxt->inode->localName), vctxt->depth);
23187	FREE_AND_NULL(str)
23188    }
23189#endif
23190    if (vctxt->inode->idcMatchers != NULL) {
23191	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23192	    "The chain of IDC matchers is expected to be empty");
23193	return (-1);
23194    }
23195    do {
23196	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23197	    /*
23198	    * Since IDCs bubbles are expensive we need to know the
23199	    * depth at which the bubbles should stop; this will be
23200	    * the depth of the top-most keyref IDC. If no keyref
23201	    * references a key/unique IDC, the keyrefDepth will
23202	    * be -1, indicating that no bubbles are needed.
23203	    */
23204	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23205	    if (refIdc != NULL) {
23206		/*
23207		* Remember that we have keyrefs on this node.
23208		*/
23209		vctxt->inode->hasKeyrefs = 1;
23210		/*
23211		* Lookup the referenced augmented IDC info.
23212		*/
23213		aidc = vctxt->aidcs;
23214		while (aidc != NULL) {
23215		    if (aidc->def == refIdc)
23216			break;
23217		    aidc = aidc->next;
23218		}
23219		if (aidc == NULL) {
23220		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23221			"Could not find an augmented IDC item for an IDC "
23222			"definition");
23223		    return (-1);
23224		}
23225		if ((aidc->keyrefDepth == -1) ||
23226		    (vctxt->depth < aidc->keyrefDepth))
23227		    aidc->keyrefDepth = vctxt->depth;
23228	    }
23229	}
23230	/*
23231	* Lookup the augmented IDC item for the IDC definition.
23232	*/
23233	aidc = vctxt->aidcs;
23234	while (aidc != NULL) {
23235	    if (aidc->def == idc)
23236		break;
23237	    aidc = aidc->next;
23238	}
23239	if (aidc == NULL) {
23240	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23241		"Could not find an augmented IDC item for an IDC definition");
23242	    return (-1);
23243	}
23244	/*
23245	* Create an IDC matcher for every IDC definition.
23246	*/
23247	if (vctxt->idcMatcherCache != NULL) {
23248	    /*
23249	    * Reuse a cached matcher.
23250	    */
23251	    matcher = vctxt->idcMatcherCache;
23252	    vctxt->idcMatcherCache = matcher->nextCached;
23253	    matcher->nextCached = NULL;
23254	} else {
23255	    matcher = (xmlSchemaIDCMatcherPtr)
23256		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23257	    if (matcher == NULL) {
23258		xmlSchemaVErrMemory(vctxt,
23259		    "allocating an IDC matcher", NULL);
23260		return (-1);
23261	    }
23262	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23263	}
23264	if (last == NULL)
23265	    vctxt->inode->idcMatchers = matcher;
23266	else
23267	    last->next = matcher;
23268	last = matcher;
23269
23270	matcher->type = IDC_MATCHER;
23271	matcher->depth = vctxt->depth;
23272	matcher->aidc = aidc;
23273	matcher->idcType = aidc->def->type;
23274#ifdef DEBUG_IDC
23275	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23276#endif
23277	/*
23278	* Init the automaton state object.
23279	*/
23280	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23281	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23282	    return (-1);
23283
23284	idc = idc->next;
23285    } while (idc != NULL);
23286    return (0);
23287}
23288
23289static int
23290xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23291			   xmlSchemaNodeInfoPtr ielem)
23292{
23293    xmlSchemaPSVIIDCBindingPtr bind;
23294    int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23295    xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23296    xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23297
23298    xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23299    /* vctxt->createIDCNodeTables */
23300    while (matcher != NULL) {
23301	/*
23302	* Skip keyref IDCs and empty IDC target-lists.
23303	*/
23304	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23305	    WXS_ILIST_IS_EMPTY(matcher->targets))
23306	{
23307	    matcher = matcher->next;
23308	    continue;
23309	}
23310	/*
23311	* If we _want_ the IDC node-table to be created in any case
23312	* then do so. Otherwise create them only if keyrefs need them.
23313	*/
23314	if ((! vctxt->createIDCNodeTables) &&
23315	    ((matcher->aidc->keyrefDepth == -1) ||
23316	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23317	{
23318	    matcher = matcher->next;
23319	    continue;
23320	}
23321	/*
23322	* Get/create the IDC binding on this element for the IDC definition.
23323	*/
23324	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23325
23326	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23327	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23328	    nbDupls = bind->dupls->nbItems;
23329	} else {
23330	    dupls = NULL;
23331	    nbDupls = 0;
23332	}
23333	if (bind->nodeTable != NULL) {
23334	    nbNodeTable = bind->nbNodes;
23335	} else {
23336	    nbNodeTable = 0;
23337	}
23338
23339	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23340	    /*
23341	    * Transfer all IDC target-nodes to the IDC node-table.
23342	    */
23343	    bind->nodeTable =
23344		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23345	    bind->sizeNodes = matcher->targets->sizeItems;
23346	    bind->nbNodes = matcher->targets->nbItems;
23347
23348	    matcher->targets->items = NULL;
23349	    matcher->targets->sizeItems = 0;
23350	    matcher->targets->nbItems = 0;
23351	} else {
23352	    /*
23353	    * Compare the key-sequences and add to the IDC node-table.
23354	    */
23355	    nbTargets = matcher->targets->nbItems;
23356	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23357	    nbFields = matcher->aidc->def->nbFields;
23358	    i = 0;
23359	    do {
23360		keys = targets[i]->keys;
23361		if (nbDupls) {
23362		    /*
23363		    * Search in already found duplicates first.
23364		    */
23365		    j = 0;
23366		    do {
23367			if (nbFields == 1) {
23368			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23369				dupls[j]->keys[0]->val);
23370			    if (res == -1)
23371				goto internal_error;
23372			    if (res == 1) {
23373				/*
23374				* Equal key-sequence.
23375				*/
23376				goto next_target;
23377			    }
23378			} else {
23379			    res = 0;
23380			    ntkeys = dupls[j]->keys;
23381			    for (k = 0; k < nbFields; k++) {
23382				res = xmlSchemaAreValuesEqual(keys[k]->val,
23383				    ntkeys[k]->val);
23384				if (res == -1)
23385				    goto internal_error;
23386				if (res == 0) {
23387				    /*
23388				    * One of the keys differs.
23389				    */
23390				    break;
23391				}
23392			    }
23393			    if (res == 1) {
23394				/*
23395				* Equal key-sequence found.
23396				*/
23397				goto next_target;
23398			    }
23399			}
23400			j++;
23401		    } while (j < nbDupls);
23402		}
23403		if (nbNodeTable) {
23404		    j = 0;
23405		    do {
23406			if (nbFields == 1) {
23407			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23408				bind->nodeTable[j]->keys[0]->val);
23409			    if (res == -1)
23410				goto internal_error;
23411			    if (res == 0) {
23412				/*
23413				* The key-sequence differs.
23414				*/
23415				goto next_node_table_entry;
23416			    }
23417			} else {
23418			    res = 0;
23419			    ntkeys = bind->nodeTable[j]->keys;
23420			    for (k = 0; k < nbFields; k++) {
23421				res = xmlSchemaAreValuesEqual(keys[k]->val,
23422				    ntkeys[k]->val);
23423				if (res == -1)
23424				    goto internal_error;
23425				if (res == 0) {
23426				    /*
23427				    * One of the keys differs.
23428				    */
23429				    goto next_node_table_entry;
23430				}
23431			    }
23432			}
23433			/*
23434			* Add the duplicate to the list of duplicates.
23435			*/
23436			if (bind->dupls == NULL) {
23437			    bind->dupls = xmlSchemaItemListCreate();
23438			    if (bind->dupls == NULL)
23439				goto internal_error;
23440			}
23441			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23442			    goto internal_error;
23443			/*
23444			* Remove the duplicate entry from the IDC node-table.
23445			*/
23446			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23447			bind->nbNodes--;
23448
23449			goto next_target;
23450
23451next_node_table_entry:
23452			j++;
23453		    } while (j < nbNodeTable);
23454		}
23455		/*
23456		* If everything is fine, then add the IDC target-node to
23457		* the IDC node-table.
23458		*/
23459		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23460		    goto internal_error;
23461
23462next_target:
23463		i++;
23464	    } while (i < nbTargets);
23465	}
23466	matcher = matcher->next;
23467    }
23468    return(0);
23469
23470internal_error:
23471    return(-1);
23472}
23473
23474/**
23475 * xmlSchemaBubbleIDCNodeTables:
23476 * @depth: the current tree depth
23477 *
23478 * Merges IDC bindings of an element at @depth into the corresponding IDC
23479 * bindings of its parent element. If a duplicate note-table entry is found,
23480 * both, the parent node-table entry and child entry are discarded from the
23481 * node-table of the parent.
23482 *
23483 * Returns 0 if OK and -1 on internal errors.
23484 */
23485static int
23486xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23487{
23488    xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23489    xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23490    xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23491    xmlSchemaIDCAugPtr aidc;
23492    int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23493
23494    bind = vctxt->inode->idcTable;
23495    if (bind == NULL) {
23496	/* Fine, no table, no bubbles. */
23497	return (0);
23498    }
23499
23500    parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23501    /*
23502    * Walk all bindings; create new or add to existing bindings.
23503    * Remove duplicate key-sequences.
23504    */
23505    while (bind != NULL) {
23506
23507	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23508	    goto next_binding;
23509	/*
23510	* Check if the key/unique IDC table needs to be bubbled.
23511	*/
23512	if (! vctxt->createIDCNodeTables) {
23513	    aidc = vctxt->aidcs;
23514	    do {
23515		if (aidc->def == bind->definition) {
23516		    if ((aidc->keyrefDepth == -1) ||
23517			(aidc->keyrefDepth >= vctxt->depth)) {
23518			goto next_binding;
23519		    }
23520		    break;
23521		}
23522		aidc = aidc->next;
23523	    } while (aidc != NULL);
23524	}
23525
23526	if (parTable != NULL)
23527	    parBind = *parTable;
23528	/*
23529	* Search a matching parent binding for the
23530	* IDC definition.
23531	*/
23532	while (parBind != NULL) {
23533	    if (parBind->definition == bind->definition)
23534		break;
23535	    parBind = parBind->next;
23536	}
23537
23538	if (parBind != NULL) {
23539	    /*
23540	    * Compare every node-table entry of the child node,
23541	    * i.e. the key-sequence within, ...
23542	    */
23543	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23544
23545	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23546		oldDupls = parBind->dupls->nbItems;
23547		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23548	    } else {
23549		dupls = NULL;
23550		oldDupls = 0;
23551	    }
23552
23553	    parNodes = parBind->nodeTable;
23554	    nbFields = bind->definition->nbFields;
23555
23556	    for (i = 0; i < bind->nbNodes; i++) {
23557		node = bind->nodeTable[i];
23558		if (node == NULL)
23559		    continue;
23560		/*
23561		* ...with every key-sequence of the parent node, already
23562		* evaluated to be a duplicate key-sequence.
23563		*/
23564		if (oldDupls) {
23565		    j = 0;
23566		    while (j < oldDupls) {
23567			if (nbFields == 1) {
23568			    ret = xmlSchemaAreValuesEqual(
23569				node->keys[0]->val,
23570				dupls[j]->keys[0]->val);
23571			    if (ret == -1)
23572				goto internal_error;
23573			    if (ret == 0) {
23574				j++;
23575				continue;
23576			    }
23577			} else {
23578			    parNode = dupls[j];
23579			    for (k = 0; k < nbFields; k++) {
23580				ret = xmlSchemaAreValuesEqual(
23581				    node->keys[k]->val,
23582				    parNode->keys[k]->val);
23583				if (ret == -1)
23584				    goto internal_error;
23585				if (ret == 0)
23586				    break;
23587			    }
23588			}
23589			if (ret == 1)
23590			    /* Duplicate found. */
23591			    break;
23592			j++;
23593		    }
23594		    if (j != oldDupls) {
23595			/* Duplicate found. Skip this entry. */
23596			continue;
23597		    }
23598		}
23599		/*
23600		* ... and with every key-sequence of the parent node.
23601		*/
23602		if (oldNum) {
23603		    j = 0;
23604		    while (j < oldNum) {
23605			parNode = parNodes[j];
23606			if (nbFields == 1) {
23607			    ret = xmlSchemaAreValuesEqual(
23608				node->keys[0]->val,
23609				parNode->keys[0]->val);
23610			    if (ret == -1)
23611				goto internal_error;
23612			    if (ret == 0) {
23613				j++;
23614				continue;
23615			    }
23616			} else {
23617			    for (k = 0; k < nbFields; k++) {
23618				ret = xmlSchemaAreValuesEqual(
23619				    node->keys[k]->val,
23620				    parNode->keys[k]->val);
23621				if (ret == -1)
23622				    goto internal_error;
23623				if (ret == 0)
23624				    break;
23625			    }
23626			}
23627			if (ret == 1)
23628			    /* Duplicate found. */
23629			    break;
23630			j++;
23631		    }
23632		    if (j != oldNum) {
23633			/*
23634			* Handle duplicates. Move the duplicate in
23635			* the parent's node-table to the list of
23636			* duplicates.
23637			*/
23638			oldNum--;
23639			parBind->nbNodes--;
23640			/*
23641			* Move last old item to pos of duplicate.
23642			*/
23643			parNodes[j] = parNodes[oldNum];
23644
23645			if (parBind->nbNodes != oldNum) {
23646			    /*
23647			    * If new items exist, move last new item to
23648			    * last of old items.
23649			    */
23650			    parNodes[oldNum] =
23651				parNodes[parBind->nbNodes];
23652			}
23653			if (parBind->dupls == NULL) {
23654			    parBind->dupls = xmlSchemaItemListCreate();
23655			    if (parBind->dupls == NULL)
23656				goto internal_error;
23657			}
23658			xmlSchemaItemListAdd(parBind->dupls, parNode);
23659		    } else {
23660			/*
23661			* Add the node-table entry (node and key-sequence) of
23662			* the child node to the node table of the parent node.
23663			*/
23664			if (parBind->nodeTable == NULL) {
23665			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23666				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23667			    if (parBind->nodeTable == NULL) {
23668				xmlSchemaVErrMemory(NULL,
23669				    "allocating IDC list of node-table items", NULL);
23670				goto internal_error;
23671			    }
23672			    parBind->sizeNodes = 1;
23673			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23674			    parBind->sizeNodes *= 2;
23675			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23676				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23677				sizeof(xmlSchemaPSVIIDCNodePtr));
23678			    if (parBind->nodeTable == NULL) {
23679				xmlSchemaVErrMemory(NULL,
23680				    "re-allocating IDC list of node-table items", NULL);
23681				goto internal_error;
23682			    }
23683			}
23684			parNodes = parBind->nodeTable;
23685			/*
23686			* Append the new node-table entry to the 'new node-table
23687			* entries' section.
23688			*/
23689			parNodes[parBind->nbNodes++] = node;
23690		    }
23691
23692		}
23693
23694	    }
23695	} else {
23696	    /*
23697	    * No binding for the IDC was found: create a new one and
23698	    * copy all node-tables.
23699	    */
23700	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23701	    if (parBind == NULL)
23702		goto internal_error;
23703
23704	    /*
23705	    * TODO: Hmm, how to optimize the initial number of
23706	    * allocated entries?
23707	    */
23708	    if (bind->nbNodes != 0) {
23709		/*
23710		* Add all IDC node-table entries.
23711		*/
23712		if (! vctxt->psviExposeIDCNodeTables) {
23713		    /*
23714		    * Just move the entries.
23715		    * NOTE: this is quite save here, since
23716		    * all the keyref lookups have already been
23717		    * performed.
23718		    */
23719		    parBind->nodeTable = bind->nodeTable;
23720		    bind->nodeTable = NULL;
23721		    parBind->sizeNodes = bind->sizeNodes;
23722		    bind->sizeNodes = 0;
23723		    parBind->nbNodes = bind->nbNodes;
23724		    bind->nbNodes = 0;
23725		} else {
23726		    /*
23727		    * Copy the entries.
23728		    */
23729		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23730			xmlMalloc(bind->nbNodes *
23731			sizeof(xmlSchemaPSVIIDCNodePtr));
23732		    if (parBind->nodeTable == NULL) {
23733			xmlSchemaVErrMemory(NULL,
23734			    "allocating an array of IDC node-table "
23735			    "items", NULL);
23736			xmlSchemaIDCFreeBinding(parBind);
23737			goto internal_error;
23738		    }
23739		    parBind->sizeNodes = bind->nbNodes;
23740		    parBind->nbNodes = bind->nbNodes;
23741		    memcpy(parBind->nodeTable, bind->nodeTable,
23742			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23743		}
23744	    }
23745	    if (bind->dupls) {
23746		/*
23747		* Move the duplicates.
23748		*/
23749		if (parBind->dupls != NULL)
23750		    xmlSchemaItemListFree(parBind->dupls);
23751		parBind->dupls = bind->dupls;
23752		bind->dupls = NULL;
23753	    }
23754            if (parTable != NULL) {
23755                if (*parTable == NULL)
23756                    *parTable = parBind;
23757                else {
23758                    parBind->next = *parTable;
23759                    *parTable = parBind;
23760                }
23761            }
23762	}
23763
23764next_binding:
23765	bind = bind->next;
23766    }
23767    return (0);
23768
23769internal_error:
23770    return(-1);
23771}
23772
23773/**
23774 * xmlSchemaCheckCVCIDCKeyRef:
23775 * @vctxt: the WXS validation context
23776 * @elemDecl: the element declaration
23777 *
23778 * Check the cvc-idc-keyref constraints.
23779 */
23780static int
23781xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23782{
23783    xmlSchemaIDCMatcherPtr matcher;
23784    xmlSchemaPSVIIDCBindingPtr bind;
23785
23786    matcher = vctxt->inode->idcMatchers;
23787    /*
23788    * Find a keyref.
23789    */
23790    while (matcher != NULL) {
23791	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23792	    matcher->targets &&
23793	    matcher->targets->nbItems)
23794	{
23795	    int i, j, k, res, nbFields, hasDupls;
23796	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23797	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23798
23799	    nbFields = matcher->aidc->def->nbFields;
23800
23801	    /*
23802	    * Find the IDC node-table for the referenced IDC key/unique.
23803	    */
23804	    bind = vctxt->inode->idcTable;
23805	    while (bind != NULL) {
23806		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23807		    bind->definition)
23808		    break;
23809		bind = bind->next;
23810	    }
23811	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23812	    /*
23813	    * Search for a matching key-sequences.
23814	    */
23815	    for (i = 0; i < matcher->targets->nbItems; i++) {
23816		res = 0;
23817		refNode = matcher->targets->items[i];
23818		if (bind != NULL) {
23819		    refKeys = refNode->keys;
23820		    for (j = 0; j < bind->nbNodes; j++) {
23821			keys = bind->nodeTable[j]->keys;
23822			for (k = 0; k < nbFields; k++) {
23823			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23824				refKeys[k]->val);
23825			    if (res == 0)
23826				break;
23827			    else if (res == -1) {
23828				return (-1);
23829			    }
23830			}
23831			if (res == 1) {
23832			    /*
23833			    * Match found.
23834			    */
23835			    break;
23836			}
23837		    }
23838		    if ((res == 0) && hasDupls) {
23839			/*
23840			* Search in duplicates
23841			*/
23842			for (j = 0; j < bind->dupls->nbItems; j++) {
23843			    keys = ((xmlSchemaPSVIIDCNodePtr)
23844				bind->dupls->items[j])->keys;
23845			    for (k = 0; k < nbFields; k++) {
23846				res = xmlSchemaAreValuesEqual(keys[k]->val,
23847				    refKeys[k]->val);
23848				if (res == 0)
23849				    break;
23850				else if (res == -1) {
23851				    return (-1);
23852				}
23853			    }
23854			    if (res == 1) {
23855				/*
23856				* Match in duplicates found.
23857				*/
23858				xmlChar *str = NULL, *strB = NULL;
23859				xmlSchemaKeyrefErr(vctxt,
23860				    XML_SCHEMAV_CVC_IDC, refNode,
23861				    (xmlSchemaTypePtr) matcher->aidc->def,
23862				    "More than one match found for "
23863				    "key-sequence %s of keyref '%s'",
23864				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23865					refNode->keys, nbFields),
23866				    xmlSchemaGetComponentQName(&strB,
23867					matcher->aidc->def));
23868				FREE_AND_NULL(str);
23869				FREE_AND_NULL(strB);
23870				break;
23871			    }
23872			}
23873		    }
23874		}
23875
23876		if (res == 0) {
23877		    xmlChar *str = NULL, *strB = NULL;
23878		    xmlSchemaKeyrefErr(vctxt,
23879			XML_SCHEMAV_CVC_IDC, refNode,
23880			(xmlSchemaTypePtr) matcher->aidc->def,
23881			"No match found for key-sequence %s of keyref '%s'",
23882			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23883			    refNode->keys, nbFields),
23884			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23885		    FREE_AND_NULL(str);
23886		    FREE_AND_NULL(strB);
23887		}
23888	    }
23889	}
23890	matcher = matcher->next;
23891    }
23892    /* TODO: Return an error if any error encountered. */
23893    return (0);
23894}
23895
23896/************************************************************************
23897 *									*
23898 *			XML Reader validation code                      *
23899 *									*
23900 ************************************************************************/
23901
23902static xmlSchemaAttrInfoPtr
23903xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23904{
23905    xmlSchemaAttrInfoPtr iattr;
23906    /*
23907    * Grow/create list of attribute infos.
23908    */
23909    if (vctxt->attrInfos == NULL) {
23910	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23911	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23912	vctxt->sizeAttrInfos = 1;
23913	if (vctxt->attrInfos == NULL) {
23914	    xmlSchemaVErrMemory(vctxt,
23915		"allocating attribute info list", NULL);
23916	    return (NULL);
23917	}
23918    } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23919	vctxt->sizeAttrInfos++;
23920	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23921	    xmlRealloc(vctxt->attrInfos,
23922		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23923	if (vctxt->attrInfos == NULL) {
23924	    xmlSchemaVErrMemory(vctxt,
23925		"re-allocating attribute info list", NULL);
23926	    return (NULL);
23927	}
23928    } else {
23929	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23930	if (iattr->localName != NULL) {
23931	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23932		"attr info not cleared");
23933	    return (NULL);
23934	}
23935	iattr->nodeType = XML_ATTRIBUTE_NODE;
23936	return (iattr);
23937    }
23938    /*
23939    * Create an attribute info.
23940    */
23941    iattr = (xmlSchemaAttrInfoPtr)
23942	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23943    if (iattr == NULL) {
23944	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23945	return (NULL);
23946    }
23947    memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23948    iattr->nodeType = XML_ATTRIBUTE_NODE;
23949    vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23950
23951    return (iattr);
23952}
23953
23954static int
23955xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23956			xmlNodePtr attrNode,
23957			int nodeLine,
23958			const xmlChar *localName,
23959			const xmlChar *nsName,
23960			int ownedNames,
23961			xmlChar *value,
23962			int ownedValue)
23963{
23964    xmlSchemaAttrInfoPtr attr;
23965
23966    attr = xmlSchemaGetFreshAttrInfo(vctxt);
23967    if (attr == NULL) {
23968	VERROR_INT("xmlSchemaPushAttribute",
23969	    "calling xmlSchemaGetFreshAttrInfo()");
23970	return (-1);
23971    }
23972    attr->node = attrNode;
23973    attr->nodeLine = nodeLine;
23974    attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23975    attr->localName = localName;
23976    attr->nsName = nsName;
23977    if (ownedNames)
23978	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23979    /*
23980    * Evaluate if it's an XSI attribute.
23981    */
23982    if (nsName != NULL) {
23983	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23984	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23985		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23986	    }
23987	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23988	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23989		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23990	    }
23991	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23992	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23993		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23994	    }
23995	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23996	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23997		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23998	    }
23999	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24000	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24001	}
24002    }
24003    attr->value = value;
24004    if (ownedValue)
24005	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24006    if (attr->metaType != 0)
24007	attr->state = XML_SCHEMAS_ATTR_META;
24008    return (0);
24009}
24010
24011/**
24012 * xmlSchemaClearElemInfo:
24013 * @vctxt: the WXS validation context
24014 * @ielem: the element information item
24015 */
24016static void
24017xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24018		       xmlSchemaNodeInfoPtr ielem)
24019{
24020    ielem->hasKeyrefs = 0;
24021    ielem->appliedXPath = 0;
24022    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24023	FREE_AND_NULL(ielem->localName);
24024	FREE_AND_NULL(ielem->nsName);
24025    } else {
24026	ielem->localName = NULL;
24027	ielem->nsName = NULL;
24028    }
24029    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24030	FREE_AND_NULL(ielem->value);
24031    } else {
24032	ielem->value = NULL;
24033    }
24034    if (ielem->val != NULL) {
24035	/*
24036	* PSVI TODO: Be careful not to free it when the value is
24037	* exposed via PSVI.
24038	*/
24039	xmlSchemaFreeValue(ielem->val);
24040	ielem->val = NULL;
24041    }
24042    if (ielem->idcMatchers != NULL) {
24043	/*
24044	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24045	*   Does it work?
24046	*/
24047	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24048#if 0
24049	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24050#endif
24051	ielem->idcMatchers = NULL;
24052    }
24053    if (ielem->idcTable != NULL) {
24054	/*
24055	* OPTIMIZE TODO: Use a pool of IDC tables??.
24056	*/
24057	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24058	ielem->idcTable = NULL;
24059    }
24060    if (ielem->regexCtxt != NULL) {
24061	xmlRegFreeExecCtxt(ielem->regexCtxt);
24062	ielem->regexCtxt = NULL;
24063    }
24064    if (ielem->nsBindings != NULL) {
24065	xmlFree((xmlChar **)ielem->nsBindings);
24066	ielem->nsBindings = NULL;
24067	ielem->nbNsBindings = 0;
24068	ielem->sizeNsBindings = 0;
24069    }
24070}
24071
24072/**
24073 * xmlSchemaGetFreshElemInfo:
24074 * @vctxt: the schema validation context
24075 *
24076 * Creates/reuses and initializes the element info item for
24077 * the currect tree depth.
24078 *
24079 * Returns the element info item or NULL on API or internal errors.
24080 */
24081static xmlSchemaNodeInfoPtr
24082xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24083{
24084    xmlSchemaNodeInfoPtr info = NULL;
24085
24086    if (vctxt->depth > vctxt->sizeElemInfos) {
24087	VERROR_INT("xmlSchemaGetFreshElemInfo",
24088	    "inconsistent depth encountered");
24089	return (NULL);
24090    }
24091    if (vctxt->elemInfos == NULL) {
24092	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24093	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24094	if (vctxt->elemInfos == NULL) {
24095	    xmlSchemaVErrMemory(vctxt,
24096		"allocating the element info array", NULL);
24097	    return (NULL);
24098	}
24099	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24100	vctxt->sizeElemInfos = 10;
24101    } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24102	int i = vctxt->sizeElemInfos;
24103
24104	vctxt->sizeElemInfos *= 2;
24105	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24106	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24107	    sizeof(xmlSchemaNodeInfoPtr));
24108	if (vctxt->elemInfos == NULL) {
24109	    xmlSchemaVErrMemory(vctxt,
24110		"re-allocating the element info array", NULL);
24111	    return (NULL);
24112	}
24113	/*
24114	* We need the new memory to be NULLed.
24115	* TODO: Use memset instead?
24116	*/
24117	for (; i < vctxt->sizeElemInfos; i++)
24118	    vctxt->elemInfos[i] = NULL;
24119    } else
24120	info = vctxt->elemInfos[vctxt->depth];
24121
24122    if (info == NULL) {
24123	info = (xmlSchemaNodeInfoPtr)
24124	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24125	if (info == NULL) {
24126	    xmlSchemaVErrMemory(vctxt,
24127		"allocating an element info", NULL);
24128	    return (NULL);
24129	}
24130	vctxt->elemInfos[vctxt->depth] = info;
24131    } else {
24132	if (info->localName != NULL) {
24133	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24134		"elem info has not been cleared");
24135	    return (NULL);
24136	}
24137    }
24138    memset(info, 0, sizeof(xmlSchemaNodeInfo));
24139    info->nodeType = XML_ELEMENT_NODE;
24140    info->depth = vctxt->depth;
24141
24142    return (info);
24143}
24144
24145#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24146#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24147#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24148
24149static int
24150xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24151			xmlNodePtr node,
24152			xmlSchemaTypePtr type,
24153			xmlSchemaValType valType,
24154			const xmlChar * value,
24155			xmlSchemaValPtr val,
24156			unsigned long length,
24157			int fireErrors)
24158{
24159    int ret, error = 0;
24160
24161    xmlSchemaTypePtr tmpType;
24162    xmlSchemaFacetLinkPtr facetLink;
24163    xmlSchemaFacetPtr facet;
24164    unsigned long len = 0;
24165    xmlSchemaWhitespaceValueType ws;
24166
24167    /*
24168    * In Libxml2, derived built-in types have currently no explicit facets.
24169    */
24170    if (type->type == XML_SCHEMA_TYPE_BASIC)
24171	return (0);
24172
24173    /*
24174    * NOTE: Do not jump away, if the facetSet of the given type is
24175    * empty: until now, "pattern" and "enumeration" facets of the
24176    * *base types* need to be checked as well.
24177    */
24178    if (type->facetSet == NULL)
24179	goto pattern_and_enum;
24180
24181    if (! WXS_IS_ATOMIC(type)) {
24182	if (WXS_IS_LIST(type))
24183	    goto WXS_IS_LIST;
24184	else
24185	    goto pattern_and_enum;
24186    }
24187    /*
24188    * Whitespace handling is only of importance for string-based
24189    * types.
24190    */
24191    tmpType = xmlSchemaGetPrimitiveType(type);
24192    if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24193	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24194	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24195    } else
24196	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24197    /*
24198    * If the value was not computed (for string or
24199    * anySimpleType based types), then use the provided
24200    * type.
24201    */
24202    if (val == NULL)
24203	valType = valType;
24204    else
24205	valType = xmlSchemaGetValType(val);
24206
24207    ret = 0;
24208    for (facetLink = type->facetSet; facetLink != NULL;
24209	facetLink = facetLink->next) {
24210	/*
24211	* Skip the pattern "whiteSpace": it is used to
24212	* format the character content beforehand.
24213	*/
24214	switch (facetLink->facet->type) {
24215	    case XML_SCHEMA_FACET_WHITESPACE:
24216	    case XML_SCHEMA_FACET_PATTERN:
24217	    case XML_SCHEMA_FACET_ENUMERATION:
24218		continue;
24219	    case XML_SCHEMA_FACET_LENGTH:
24220	    case XML_SCHEMA_FACET_MINLENGTH:
24221	    case XML_SCHEMA_FACET_MAXLENGTH:
24222		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24223		    valType, value, val, &len, ws);
24224		break;
24225	    default:
24226		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24227		    valType, value, val, ws);
24228		break;
24229	}
24230	if (ret < 0) {
24231	    AERROR_INT("xmlSchemaValidateFacets",
24232		"validating against a atomic type facet");
24233	    return (-1);
24234	} else if (ret > 0) {
24235	    if (fireErrors)
24236		xmlSchemaFacetErr(actxt, ret, node,
24237		value, len, type, facetLink->facet, NULL, NULL, NULL);
24238	    else
24239		return (ret);
24240	    if (error == 0)
24241		error = ret;
24242	}
24243	ret = 0;
24244    }
24245
24246WXS_IS_LIST:
24247    if (! WXS_IS_LIST(type))
24248	goto pattern_and_enum;
24249    /*
24250    * "length", "minLength" and "maxLength" of list types.
24251    */
24252    ret = 0;
24253    for (facetLink = type->facetSet; facetLink != NULL;
24254	facetLink = facetLink->next) {
24255
24256	switch (facetLink->facet->type) {
24257	    case XML_SCHEMA_FACET_LENGTH:
24258	    case XML_SCHEMA_FACET_MINLENGTH:
24259	    case XML_SCHEMA_FACET_MAXLENGTH:
24260		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24261		    value, length, NULL);
24262		break;
24263	    default:
24264		continue;
24265	}
24266	if (ret < 0) {
24267	    AERROR_INT("xmlSchemaValidateFacets",
24268		"validating against a list type facet");
24269	    return (-1);
24270	} else if (ret > 0) {
24271	    if (fireErrors)
24272		xmlSchemaFacetErr(actxt, ret, node,
24273		value, length, type, facetLink->facet, NULL, NULL, NULL);
24274	    else
24275		return (ret);
24276	    if (error == 0)
24277		error = ret;
24278	}
24279	ret = 0;
24280    }
24281
24282pattern_and_enum:
24283    if (error >= 0) {
24284	int found = 0;
24285	/*
24286	* Process enumerations. Facet values are in the value space
24287	* of the defining type's base type. This seems to be a bug in the
24288	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24289	* Only the first set of enumerations in the ancestor-or-self axis
24290	* is used for validation.
24291	*/
24292	ret = 0;
24293	tmpType = type;
24294	do {
24295	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24296		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24297		    continue;
24298		found = 1;
24299		ret = xmlSchemaAreValuesEqual(facet->val, val);
24300		if (ret == 1)
24301		    break;
24302		else if (ret < 0) {
24303		    AERROR_INT("xmlSchemaValidateFacets",
24304			"validating against an enumeration facet");
24305		    return (-1);
24306		}
24307	    }
24308	    if (ret != 0)
24309		break;
24310	    /*
24311	    * Break on the first set of enumerations. Any additional
24312	    *  enumerations which might be existent on the ancestors
24313	    *  of the current type are restricted by this set; thus
24314	    *  *must* *not* be taken into account.
24315	    */
24316	    if (found)
24317		break;
24318	    tmpType = tmpType->baseType;
24319	} while ((tmpType != NULL) &&
24320	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24321	if (found && (ret == 0)) {
24322	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24323	    if (fireErrors) {
24324		xmlSchemaFacetErr(actxt, ret, node,
24325		    value, 0, type, NULL, NULL, NULL, NULL);
24326	    } else
24327		return (ret);
24328	    if (error == 0)
24329		error = ret;
24330	}
24331    }
24332
24333    if (error >= 0) {
24334	int found;
24335	/*
24336	* Process patters. Pattern facets are ORed at type level
24337	* and ANDed if derived. Walk the base type axis.
24338	*/
24339	tmpType = type;
24340	facet = NULL;
24341	do {
24342	    found = 0;
24343	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24344		facetLink = facetLink->next) {
24345		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24346		    continue;
24347		found = 1;
24348		/*
24349		* NOTE that for patterns, @value needs to be the
24350		* normalized vaule.
24351		*/
24352		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24353		if (ret == 1)
24354		    break;
24355		else if (ret < 0) {
24356		    AERROR_INT("xmlSchemaValidateFacets",
24357			"validating against a pattern facet");
24358		    return (-1);
24359		} else {
24360		    /*
24361		    * Save the last non-validating facet.
24362		    */
24363		    facet = facetLink->facet;
24364		}
24365	    }
24366	    if (found && (ret != 1)) {
24367		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24368		if (fireErrors) {
24369		    xmlSchemaFacetErr(actxt, ret, node,
24370			value, 0, type, facet, NULL, NULL, NULL);
24371		} else
24372		    return (ret);
24373		if (error == 0)
24374		    error = ret;
24375		break;
24376	    }
24377	    tmpType = tmpType->baseType;
24378	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24379    }
24380
24381    return (error);
24382}
24383
24384static xmlChar *
24385xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24386			const xmlChar *value)
24387{
24388    switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24389	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24390	    return (xmlSchemaCollapseString(value));
24391	case XML_SCHEMA_WHITESPACE_REPLACE:
24392	    return (xmlSchemaWhiteSpaceReplace(value));
24393	default:
24394	    return (NULL);
24395    }
24396}
24397
24398static int
24399xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24400		       const xmlChar *value,
24401		       xmlSchemaValPtr *val,
24402		       int valNeeded)
24403{
24404    int ret;
24405    const xmlChar *nsName;
24406    xmlChar *local, *prefix = NULL;
24407
24408    ret = xmlValidateQName(value, 1);
24409    if (ret != 0) {
24410	if (ret == -1) {
24411	    VERROR_INT("xmlSchemaValidateQName",
24412		"calling xmlValidateQName()");
24413	    return (-1);
24414	}
24415	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24416    }
24417    /*
24418    * NOTE: xmlSplitQName2 will always return a duplicated
24419    * strings.
24420    */
24421    local = xmlSplitQName2(value, &prefix);
24422    if (local == NULL)
24423	local = xmlStrdup(value);
24424    /*
24425    * OPTIMIZE TODO: Use flags for:
24426    *  - is there any namespace binding?
24427    *  - is there a default namespace?
24428    */
24429    nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24430
24431    if (prefix != NULL) {
24432	xmlFree(prefix);
24433	/*
24434	* A namespace must be found if the prefix is
24435	* NOT NULL.
24436	*/
24437	if (nsName == NULL) {
24438	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24439	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24440		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24441		"The QName value '%s' has no "
24442		"corresponding namespace declaration in "
24443		"scope", value, NULL);
24444	    if (local != NULL)
24445		xmlFree(local);
24446	    return (ret);
24447	}
24448    }
24449    if (valNeeded && val) {
24450	if (nsName != NULL)
24451	    *val = xmlSchemaNewQNameValue(
24452		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24453	else
24454	    *val = xmlSchemaNewQNameValue(NULL,
24455		BAD_CAST local);
24456    } else
24457	xmlFree(local);
24458    return (0);
24459}
24460
24461/*
24462* cvc-simple-type
24463*/
24464static int
24465xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24466			     xmlNodePtr node,
24467			     xmlSchemaTypePtr type,
24468			     const xmlChar *value,
24469			     xmlSchemaValPtr *retVal,
24470			     int fireErrors,
24471			     int normalize,
24472			     int isNormalized)
24473{
24474    int ret = 0, valNeeded = (retVal) ? 1 : 0;
24475    xmlSchemaValPtr val = NULL;
24476    /* xmlSchemaWhitespaceValueType ws; */
24477    xmlChar *normValue = NULL;
24478
24479#define NORMALIZE(atype) \
24480    if ((! isNormalized) && \
24481    (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24482	normValue = xmlSchemaNormalizeValue(atype, value); \
24483	if (normValue != NULL) \
24484	    value = normValue; \
24485	isNormalized = 1; \
24486    }
24487
24488    if ((retVal != NULL) && (*retVal != NULL)) {
24489	xmlSchemaFreeValue(*retVal);
24490	*retVal = NULL;
24491    }
24492    /*
24493    * 3.14.4 Simple Type Definition Validation Rules
24494    * Validation Rule: String Valid
24495    */
24496    /*
24497    * 1 It is schema-valid with respect to that definition as defined
24498    * by Datatype Valid in [XML Schemas: Datatypes].
24499    */
24500    /*
24501    * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24502    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24503    * the string must be a �declared entity name�.
24504    */
24505    /*
24506    * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24507    * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24508    * then every whitespace-delimited substring of the string must be a �declared
24509    * entity name�.
24510    */
24511    /*
24512    * 2.3 otherwise no further condition applies.
24513    */
24514    if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24515	valNeeded = 1;
24516    if (value == NULL)
24517	value = BAD_CAST "";
24518    if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24519	xmlSchemaTypePtr biType; /* The built-in type. */
24520	/*
24521	* SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24522	* a literal in the �lexical space� of {base type definition}"
24523	*/
24524	/*
24525	* Whitespace-normalize.
24526	*/
24527	NORMALIZE(type);
24528	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24529	    /*
24530	    * Get the built-in type.
24531	    */
24532	    biType = type->baseType;
24533	    while ((biType != NULL) &&
24534		(biType->type != XML_SCHEMA_TYPE_BASIC))
24535		biType = biType->baseType;
24536
24537	    if (biType == NULL) {
24538		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24539		    "could not get the built-in type");
24540		goto internal_error;
24541	    }
24542	} else
24543	    biType = type;
24544	/*
24545	* NOTATIONs need to be processed here, since they need
24546	* to lookup in the hashtable of NOTATION declarations of the schema.
24547	*/
24548	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24549	    switch (biType->builtInType) {
24550		case XML_SCHEMAS_NOTATION:
24551		    ret = xmlSchemaValidateNotation(
24552			(xmlSchemaValidCtxtPtr) actxt,
24553			((xmlSchemaValidCtxtPtr) actxt)->schema,
24554			NULL, value, &val, valNeeded);
24555		    break;
24556		case XML_SCHEMAS_QNAME:
24557		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24558			value, &val, valNeeded);
24559		    break;
24560		default:
24561		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24562		    if (valNeeded)
24563			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24564			    value, &val, node);
24565		    else
24566			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24567			    value, NULL, node);
24568		    break;
24569	    }
24570	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24571	    switch (biType->builtInType) {
24572		case XML_SCHEMAS_NOTATION:
24573		    ret = xmlSchemaValidateNotation(NULL,
24574			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24575			value, &val, valNeeded);
24576		    break;
24577		default:
24578		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24579		    if (valNeeded)
24580			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24581			    value, &val, node);
24582		    else
24583			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24584			    value, NULL, node);
24585		    break;
24586	    }
24587	} else {
24588	    /*
24589	    * Validation via a public API is not implemented yet.
24590	    */
24591	    TODO
24592	    goto internal_error;
24593	}
24594	if (ret != 0) {
24595	    if (ret < 0) {
24596		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24597		    "validating against a built-in type");
24598		goto internal_error;
24599	    }
24600	    if (WXS_IS_LIST(type))
24601		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24602	    else
24603		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24604	}
24605	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24606	    /*
24607	    * Check facets.
24608	    */
24609	    ret = xmlSchemaValidateFacets(actxt, node, type,
24610		(xmlSchemaValType) biType->builtInType, value, val,
24611		0, fireErrors);
24612	    if (ret != 0) {
24613		if (ret < 0) {
24614		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24615			"validating facets of atomic simple type");
24616		    goto internal_error;
24617		}
24618		if (WXS_IS_LIST(type))
24619		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24620		else
24621		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24622	    }
24623	}
24624	if (fireErrors && (ret > 0))
24625	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24626    } else if (WXS_IS_LIST(type)) {
24627
24628	xmlSchemaTypePtr itemType;
24629	const xmlChar *cur, *end;
24630	xmlChar *tmpValue = NULL;
24631	unsigned long len = 0;
24632	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24633	/* 1.2.2 if {variety} is �list� then the string must be a sequence
24634	* of white space separated tokens, each of which �match�es a literal
24635	* in the �lexical space� of {item type definition}
24636	*/
24637	/*
24638	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24639	* the list type has an enum or pattern facet.
24640	*/
24641	NORMALIZE(type);
24642	/*
24643	* VAL TODO: Optimize validation of empty values.
24644	* VAL TODO: We do not have computed values for lists.
24645	*/
24646	itemType = WXS_LIST_ITEMTYPE(type);
24647	cur = value;
24648	do {
24649	    while (IS_BLANK_CH(*cur))
24650		cur++;
24651	    end = cur;
24652	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24653		end++;
24654	    if (end == cur)
24655		break;
24656	    tmpValue = xmlStrndup(cur, end - cur);
24657	    len++;
24658
24659	    if (valNeeded)
24660		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24661		    tmpValue, &curVal, fireErrors, 0, 1);
24662	    else
24663		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24664		    tmpValue, NULL, fireErrors, 0, 1);
24665	    FREE_AND_NULL(tmpValue);
24666	    if (curVal != NULL) {
24667		/*
24668		* Add to list of computed values.
24669		*/
24670		if (val == NULL)
24671		    val = curVal;
24672		else
24673		    xmlSchemaValueAppend(prevVal, curVal);
24674		prevVal = curVal;
24675		curVal = NULL;
24676	    }
24677	    if (ret != 0) {
24678		if (ret < 0) {
24679		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24680			"validating an item of list simple type");
24681		    goto internal_error;
24682		}
24683		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24684		break;
24685	    }
24686	    cur = end;
24687	} while (*cur != 0);
24688	FREE_AND_NULL(tmpValue);
24689	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24690	    /*
24691	    * Apply facets (pattern, enumeration).
24692	    */
24693	    ret = xmlSchemaValidateFacets(actxt, node, type,
24694		XML_SCHEMAS_UNKNOWN, value, val,
24695		len, fireErrors);
24696	    if (ret != 0) {
24697		if (ret < 0) {
24698		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24699			"validating facets of list simple type");
24700		    goto internal_error;
24701		}
24702		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24703	    }
24704	}
24705	if (fireErrors && (ret > 0)) {
24706	    /*
24707	    * Report the normalized value.
24708	    */
24709	    normalize = 1;
24710	    NORMALIZE(type);
24711	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24712	}
24713    } else if (WXS_IS_UNION(type)) {
24714	xmlSchemaTypeLinkPtr memberLink;
24715	/*
24716	* TODO: For all datatypes �derived� by �union�  whiteSpace does
24717	* not apply directly; however, the normalization behavior of �union�
24718	* types is controlled by the value of whiteSpace on that one of the
24719	* �memberTypes� against which the �union� is successfully validated.
24720	*
24721	* This means that the value is normalized by the first validating
24722	* member type, then the facets of the union type are applied. This
24723	* needs changing of the value!
24724	*/
24725
24726	/*
24727	* 1.2.3 if {variety} is �union� then the string must �match� a
24728	* literal in the �lexical space� of at least one member of
24729	* {member type definitions}
24730	*/
24731	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24732	if (memberLink == NULL) {
24733	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24734		"union simple type has no member types");
24735	    goto internal_error;
24736	}
24737	/*
24738	* Always normalize union type values, since we currently
24739	* cannot store the whitespace information with the value
24740	* itself; otherwise a later value-comparison would be
24741	* not possible.
24742	*/
24743	while (memberLink != NULL) {
24744	    if (valNeeded)
24745		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24746		    memberLink->type, value, &val, 0, 1, 0);
24747	    else
24748		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24749		    memberLink->type, value, NULL, 0, 1, 0);
24750	    if (ret <= 0)
24751		break;
24752	    memberLink = memberLink->next;
24753	}
24754	if (ret != 0) {
24755	    if (ret < 0) {
24756		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24757		    "validating members of union simple type");
24758		goto internal_error;
24759	    }
24760	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24761	}
24762	/*
24763	* Apply facets (pattern, enumeration).
24764	*/
24765	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24766	    /*
24767	    * The normalization behavior of �union� types is controlled by
24768	    * the value of whiteSpace on that one of the �memberTypes�
24769	    * against which the �union� is successfully validated.
24770	    */
24771	    NORMALIZE(memberLink->type);
24772	    ret = xmlSchemaValidateFacets(actxt, node, type,
24773		XML_SCHEMAS_UNKNOWN, value, val,
24774		0, fireErrors);
24775	    if (ret != 0) {
24776		if (ret < 0) {
24777		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24778			"validating facets of union simple type");
24779		    goto internal_error;
24780		}
24781		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24782	    }
24783	}
24784	if (fireErrors && (ret > 0))
24785	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24786    }
24787
24788    if (normValue != NULL)
24789	xmlFree(normValue);
24790    if (ret == 0) {
24791	if (retVal != NULL)
24792	    *retVal = val;
24793	else if (val != NULL)
24794	    xmlSchemaFreeValue(val);
24795    } else if (val != NULL)
24796	xmlSchemaFreeValue(val);
24797    return (ret);
24798internal_error:
24799    if (normValue != NULL)
24800	xmlFree(normValue);
24801    if (val != NULL)
24802	xmlSchemaFreeValue(val);
24803    return (-1);
24804}
24805
24806static int
24807xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24808			   const xmlChar *value,
24809			   const xmlChar **nsName,
24810			   const xmlChar **localName)
24811{
24812    int ret = 0;
24813
24814    if ((nsName == NULL) || (localName == NULL))
24815	return (-1);
24816    *nsName = NULL;
24817    *localName = NULL;
24818
24819    ret = xmlValidateQName(value, 1);
24820    if (ret == -1)
24821	return (-1);
24822    if (ret > 0) {
24823	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24824	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24825	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24826	return (1);
24827    }
24828    {
24829	xmlChar *local = NULL;
24830	xmlChar *prefix;
24831
24832	/*
24833	* NOTE: xmlSplitQName2 will return a duplicated
24834	* string.
24835	*/
24836	local = xmlSplitQName2(value, &prefix);
24837	if (local == NULL)
24838	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24839	else {
24840	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24841	    xmlFree(local);
24842	}
24843
24844	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24845
24846	if (prefix != NULL) {
24847	    xmlFree(prefix);
24848	    /*
24849	    * A namespace must be found if the prefix is NOT NULL.
24850	    */
24851	    if (*nsName == NULL) {
24852		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24853		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24854		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24855		    "The QName value '%s' has no "
24856		    "corresponding namespace declaration in scope",
24857		    value, NULL);
24858		return (2);
24859	    }
24860	}
24861    }
24862    return (0);
24863}
24864
24865static int
24866xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24867			xmlSchemaAttrInfoPtr iattr,
24868			xmlSchemaTypePtr *localType,
24869			xmlSchemaElementPtr elemDecl)
24870{
24871    int ret = 0;
24872    /*
24873    * cvc-elt (3.3.4) : (4)
24874    * AND
24875    * Schema-Validity Assessment (Element) (cvc-assess-elt)
24876    *   (1.2.1.2.1) - (1.2.1.2.4)
24877    * Handle 'xsi:type'.
24878    */
24879    if (localType == NULL)
24880	return (-1);
24881    *localType = NULL;
24882    if (iattr == NULL)
24883	return (0);
24884    else {
24885	const xmlChar *nsName = NULL, *local = NULL;
24886	/*
24887	* TODO: We should report a *warning* that the type was overriden
24888	* by the instance.
24889	*/
24890	ACTIVATE_ATTRIBUTE(iattr);
24891	/*
24892	* (cvc-elt) (3.3.4) : (4.1)
24893	* (cvc-assess-elt) (1.2.1.2.2)
24894	*/
24895	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24896	    &nsName, &local);
24897	if (ret != 0) {
24898	    if (ret < 0) {
24899		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24900		    "calling xmlSchemaQNameExpand() to validate the "
24901		    "attribute 'xsi:type'");
24902		goto internal_error;
24903	    }
24904	    goto exit;
24905	}
24906	/*
24907	* (cvc-elt) (3.3.4) : (4.2)
24908	* (cvc-assess-elt) (1.2.1.2.3)
24909	*/
24910	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24911	if (*localType == NULL) {
24912	    xmlChar *str = NULL;
24913
24914	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24915		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24916		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24917		"The QName value '%s' of the xsi:type attribute does not "
24918		"resolve to a type definition",
24919		xmlSchemaFormatQName(&str, nsName, local), NULL);
24920	    FREE_AND_NULL(str);
24921	    ret = vctxt->err;
24922	    goto exit;
24923	}
24924	if (elemDecl != NULL) {
24925	    int set = 0;
24926
24927	    /*
24928	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24929	    * "The �local type definition� must be validly
24930	    * derived from the {type definition} given the union of
24931	    * the {disallowed substitutions} and the {type definition}'s
24932	    * {prohibited substitutions}, as defined in
24933	    * Type Derivation OK (Complex) (�3.4.6)
24934	    * (if it is a complex type definition),
24935	    * or given {disallowed substitutions} as defined in Type
24936	    * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24937	    * definition)."
24938	    *
24939	    * {disallowed substitutions}: the "block" on the element decl.
24940	    * {prohibited substitutions}: the "block" on the type def.
24941	    */
24942	    /*
24943	    * OPTIMIZE TODO: We could map types already evaluated
24944	    * to be validly derived from other types to avoid checking
24945	    * this over and over for the same types.
24946	    */
24947	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24948		(elemDecl->subtypes->flags &
24949		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24950		set |= SUBSET_EXTENSION;
24951
24952	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24953		(elemDecl->subtypes->flags &
24954		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24955		set |= SUBSET_RESTRICTION;
24956
24957	    /*
24958	    * REMOVED and CHANGED since this produced a parser context
24959	    * which adds to the string dict of the schema. So this would
24960	    * change the schema and we don't want this. We don't need
24961	    * the parser context anymore.
24962	    *
24963	    * if ((vctxt->pctxt == NULL) &&
24964	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24965	    *	    return (-1);
24966	    */
24967
24968	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24969		elemDecl->subtypes, set) != 0) {
24970		xmlChar *str = NULL;
24971
24972		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24973		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24974		    "The type definition '%s', specified by xsi:type, is "
24975		    "blocked or not validly derived from the type definition "
24976		    "of the element declaration",
24977		    xmlSchemaFormatQName(&str,
24978			(*localType)->targetNamespace,
24979			(*localType)->name),
24980		    NULL);
24981		FREE_AND_NULL(str);
24982		ret = vctxt->err;
24983		*localType = NULL;
24984	    }
24985	}
24986    }
24987exit:
24988    ACTIVATE_ELEM;
24989    return (ret);
24990internal_error:
24991    ACTIVATE_ELEM;
24992    return (-1);
24993}
24994
24995static int
24996xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24997{
24998    xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24999    xmlSchemaTypePtr actualType;
25000
25001    /*
25002    * cvc-elt (3.3.4) : 1
25003    */
25004    if (elemDecl == NULL) {
25005	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25006	    "No matching declaration available");
25007        return (vctxt->err);
25008    }
25009    actualType = WXS_ELEM_TYPEDEF(elemDecl);
25010    /*
25011    * cvc-elt (3.3.4) : 2
25012    */
25013    if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25014	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25015	    "The element declaration is abstract");
25016        return (vctxt->err);
25017    }
25018    if (actualType == NULL) {
25019	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25020	    "The type definition is absent");
25021	return (XML_SCHEMAV_CVC_TYPE_1);
25022    }
25023    if (vctxt->nbAttrInfos != 0) {
25024	int ret;
25025	xmlSchemaAttrInfoPtr iattr;
25026	/*
25027	* cvc-elt (3.3.4) : 3
25028	* Handle 'xsi:nil'.
25029	*/
25030	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25031	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25032	if (iattr) {
25033	    ACTIVATE_ATTRIBUTE(iattr);
25034	    /*
25035	    * Validate the value.
25036	    */
25037	    ret = xmlSchemaVCheckCVCSimpleType(
25038		ACTXT_CAST vctxt, NULL,
25039		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25040		iattr->value, &(iattr->val), 1, 0, 0);
25041	    ACTIVATE_ELEM;
25042	    if (ret < 0) {
25043		VERROR_INT("xmlSchemaValidateElemDecl",
25044		    "calling xmlSchemaVCheckCVCSimpleType() to "
25045		    "validate the attribute 'xsi:nil'");
25046		return (-1);
25047	    }
25048	    if (ret == 0) {
25049		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25050		    /*
25051		    * cvc-elt (3.3.4) : 3.1
25052		    */
25053		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25054			"The element is not 'nillable'");
25055		    /* Does not return an error on purpose. */
25056		} else {
25057		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25058			/*
25059			* cvc-elt (3.3.4) : 3.2.2
25060			*/
25061			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25062			    (elemDecl->value != NULL)) {
25063			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25064				"The element cannot be 'nilled' because "
25065				"there is a fixed value constraint defined "
25066				"for it");
25067			     /* Does not return an error on purpose. */
25068			} else
25069			    vctxt->inode->flags |=
25070				XML_SCHEMA_ELEM_INFO_NILLED;
25071		    }
25072		}
25073	    }
25074	}
25075	/*
25076	* cvc-elt (3.3.4) : 4
25077	* Handle 'xsi:type'.
25078	*/
25079	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25080	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25081	if (iattr) {
25082	    xmlSchemaTypePtr localType = NULL;
25083
25084	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25085		elemDecl);
25086	    if (ret != 0) {
25087		if (ret == -1) {
25088		    VERROR_INT("xmlSchemaValidateElemDecl",
25089			"calling xmlSchemaProcessXSIType() to "
25090			"process the attribute 'xsi:type'");
25091		    return (-1);
25092		}
25093		/* Does not return an error on purpose. */
25094	    }
25095	    if (localType != NULL) {
25096		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25097		actualType = localType;
25098	    }
25099	}
25100    }
25101    /*
25102    * IDC: Register identity-constraint XPath matchers.
25103    */
25104    if ((elemDecl->idcs != NULL) &&
25105	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25106	    return (-1);
25107    /*
25108    * No actual type definition.
25109    */
25110    if (actualType == NULL) {
25111	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25112	    "The type definition is absent");
25113	return (XML_SCHEMAV_CVC_TYPE_1);
25114    }
25115    /*
25116    * Remember the actual type definition.
25117    */
25118    vctxt->inode->typeDef = actualType;
25119
25120    return (0);
25121}
25122
25123static int
25124xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25125{
25126    xmlSchemaAttrInfoPtr iattr;
25127    int ret = 0, i;
25128
25129    /*
25130    * SPEC cvc-type (3.1.1)
25131    * "The attributes of must be empty, excepting those whose namespace
25132    * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25133    * whose local name is one of type, nil, schemaLocation or
25134    * noNamespaceSchemaLocation."
25135    */
25136    if (vctxt->nbAttrInfos == 0)
25137	return (0);
25138    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25139	iattr = vctxt->attrInfos[i];
25140	if (! iattr->metaType) {
25141	    ACTIVATE_ATTRIBUTE(iattr)
25142	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25143		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25144	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25145        }
25146    }
25147    ACTIVATE_ELEM
25148    return (ret);
25149}
25150
25151/*
25152* Cleanup currently used attribute infos.
25153*/
25154static void
25155xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25156{
25157    int i;
25158    xmlSchemaAttrInfoPtr attr;
25159
25160    if (vctxt->nbAttrInfos == 0)
25161	return;
25162    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25163	attr = vctxt->attrInfos[i];
25164	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25165	    if (attr->localName != NULL)
25166		xmlFree((xmlChar *) attr->localName);
25167	    if (attr->nsName != NULL)
25168		xmlFree((xmlChar *) attr->nsName);
25169	}
25170	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25171	    if (attr->value != NULL)
25172		xmlFree((xmlChar *) attr->value);
25173	}
25174	if (attr->val != NULL) {
25175	    xmlSchemaFreeValue(attr->val);
25176	    attr->val = NULL;
25177	}
25178	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25179    }
25180    vctxt->nbAttrInfos = 0;
25181}
25182
25183/*
25184* 3.4.4 Complex Type Definition Validation Rules
25185*   Element Locally Valid (Complex Type) (cvc-complex-type)
25186* 3.2.4 Attribute Declaration Validation Rules
25187*   Validation Rule: Attribute Locally Valid (cvc-attribute)
25188*   Attribute Locally Valid (Use) (cvc-au)
25189*
25190* Only "assessed" attribute information items will be visible to
25191* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25192*/
25193static int
25194xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25195{
25196    xmlSchemaTypePtr type = vctxt->inode->typeDef;
25197    xmlSchemaItemListPtr attrUseList;
25198    xmlSchemaAttributeUsePtr attrUse = NULL;
25199    xmlSchemaAttributePtr attrDecl = NULL;
25200    xmlSchemaAttrInfoPtr iattr, tmpiattr;
25201    int i, j, found, nbAttrs, nbUses;
25202    int xpathRes = 0, res, wildIDs = 0, fixed;
25203    xmlNodePtr defAttrOwnerElem = NULL;
25204
25205    /*
25206    * SPEC (cvc-attribute)
25207    * (1) "The declaration must not be �absent� (see Missing
25208    * Sub-components (�5.3) for how this can fail to be
25209    * the case)."
25210    * (2) "Its {type definition} must not be absent."
25211    *
25212    * NOTE (1) + (2): This is not handled here, since we currently do not
25213    * allow validation against schemas which have missing sub-components.
25214    *
25215    * SPEC (cvc-complex-type)
25216    * (3) "For each attribute information item in the element information
25217    * item's [attributes] excepting those whose [namespace name] is
25218    * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25219    * [local name] is one of type, nil, schemaLocation or
25220    * noNamespaceSchemaLocation, the appropriate case among the following
25221    * must be true:
25222    *
25223    */
25224    attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25225    /*
25226    * @nbAttrs is the number of attributes present in the instance.
25227    */
25228    nbAttrs = vctxt->nbAttrInfos;
25229    if (attrUseList != NULL)
25230	nbUses = attrUseList->nbItems;
25231    else
25232	nbUses = 0;
25233    for (i = 0; i < nbUses; i++) {
25234        found = 0;
25235	attrUse = attrUseList->items[i];
25236	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25237        for (j = 0; j < nbAttrs; j++) {
25238	    iattr = vctxt->attrInfos[j];
25239	    /*
25240	    * SPEC (cvc-complex-type) (3)
25241	    * Skip meta attributes.
25242	    */
25243	    if (iattr->metaType)
25244		continue;
25245	    if (iattr->localName[0] != attrDecl->name[0])
25246		continue;
25247	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25248		continue;
25249	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25250		continue;
25251	    found = 1;
25252	    /*
25253	    * SPEC (cvc-complex-type)
25254	    * (3.1) "If there is among the {attribute uses} an attribute
25255	    * use with an {attribute declaration} whose {name} matches
25256	    * the attribute information item's [local name] and whose
25257	    * {target namespace} is identical to the attribute information
25258	    * item's [namespace name] (where an �absent� {target namespace}
25259	    * is taken to be identical to a [namespace name] with no value),
25260	    * then the attribute information must be �valid� with respect
25261	    * to that attribute use as per Attribute Locally Valid (Use)
25262	    * (�3.5.4). In this case the {attribute declaration} of that
25263	    * attribute use is the �context-determined declaration� for the
25264	    * attribute information item with respect to Schema-Validity
25265	    * Assessment (Attribute) (�3.2.4) and
25266	    * Assessment Outcome (Attribute) (�3.2.5).
25267	    */
25268	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25269	    iattr->use = attrUse;
25270	    /*
25271	    * Context-determined declaration.
25272	    */
25273	    iattr->decl = attrDecl;
25274	    iattr->typeDef = attrDecl->subtypes;
25275	    break;
25276	}
25277
25278	if (found)
25279	    continue;
25280
25281	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25282	    /*
25283	    * Handle non-existent, required attributes.
25284	    *
25285	    * SPEC (cvc-complex-type)
25286	    * (4) "The {attribute declaration} of each attribute use in
25287	    * the {attribute uses} whose {required} is true matches one
25288	    * of the attribute information items in the element information
25289	    * item's [attributes] as per clause 3.1 above."
25290	    */
25291	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25292	    if (tmpiattr == NULL) {
25293		VERROR_INT(
25294		    "xmlSchemaVAttributesComplex",
25295		    "calling xmlSchemaGetFreshAttrInfo()");
25296		return (-1);
25297	    }
25298	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25299	    tmpiattr->use = attrUse;
25300	    tmpiattr->decl = attrDecl;
25301	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25302	    ((attrUse->defValue != NULL) ||
25303	     (attrDecl->defValue != NULL))) {
25304	    /*
25305	    * Handle non-existent, optional, default/fixed attributes.
25306	    */
25307	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25308	    if (tmpiattr == NULL) {
25309		VERROR_INT(
25310		    "xmlSchemaVAttributesComplex",
25311		    "calling xmlSchemaGetFreshAttrInfo()");
25312		return (-1);
25313	    }
25314	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25315	    tmpiattr->use = attrUse;
25316	    tmpiattr->decl = attrDecl;
25317	    tmpiattr->typeDef = attrDecl->subtypes;
25318	    tmpiattr->localName = attrDecl->name;
25319	    tmpiattr->nsName = attrDecl->targetNamespace;
25320	}
25321    }
25322
25323    if (vctxt->nbAttrInfos == 0)
25324	return (0);
25325    /*
25326    * Validate against the wildcard.
25327    */
25328    if (type->attributeWildcard != NULL) {
25329	/*
25330	* SPEC (cvc-complex-type)
25331	* (3.2.1) "There must be an {attribute wildcard}."
25332	*/
25333	for (i = 0; i < nbAttrs; i++) {
25334	    iattr = vctxt->attrInfos[i];
25335	    /*
25336	    * SPEC (cvc-complex-type) (3)
25337	    * Skip meta attributes.
25338	    */
25339	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25340		continue;
25341	    /*
25342	    * SPEC (cvc-complex-type)
25343	    * (3.2.2) "The attribute information item must be �valid� with
25344	    * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25345	    *
25346	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25347	    * "... its [namespace name] must be �valid� with respect to
25348	    * the wildcard constraint, as defined in Wildcard allows
25349	    * Namespace Name (�3.10.4)."
25350	    */
25351	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25352		    iattr->nsName) == 0) {
25353		/*
25354		* Handle processContents.
25355		*
25356		* SPEC (cvc-wildcard):
25357		* processContents | context-determined declaration:
25358		* "strict"          "mustFind"
25359		* "lax"             "none"
25360		* "skip"            "skip"
25361		*/
25362		if (type->attributeWildcard->processContents ==
25363		    XML_SCHEMAS_ANY_SKIP) {
25364		     /*
25365		    * context-determined declaration = "skip"
25366		    *
25367		    * SPEC PSVI Assessment Outcome (Attribute)
25368		    * [validity] = "notKnown"
25369		    * [validation attempted] = "none"
25370		    */
25371		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25372		    continue;
25373		}
25374		/*
25375		* Find an attribute declaration.
25376		*/
25377		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25378		    iattr->localName, iattr->nsName);
25379		if (iattr->decl != NULL) {
25380		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25381		    /*
25382		    * SPEC (cvc-complex-type)
25383		    * (5) "Let [Definition:]  the wild IDs be the set of
25384		    * all attribute information item to which clause 3.2
25385		    * applied and whose �validation� resulted in a
25386		    * �context-determined declaration� of mustFind or no
25387		    * �context-determined declaration� at all, and whose
25388		    * [local name] and [namespace name] resolve (as
25389		    * defined by QName resolution (Instance) (�3.15.4)) to
25390		    * an attribute declaration whose {type definition} is
25391		    * or is derived from ID. Then all of the following
25392		    * must be true:"
25393		    */
25394		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25395		    if (xmlSchemaIsDerivedFromBuiltInType(
25396			iattr->typeDef, XML_SCHEMAS_ID)) {
25397			/*
25398			* SPEC (5.1) "There must be no more than one
25399			* item in �wild IDs�."
25400			*/
25401			if (wildIDs != 0) {
25402			    /* VAL TODO */
25403			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25404			    TODO
25405			    continue;
25406			}
25407			wildIDs++;
25408			/*
25409			* SPEC (cvc-complex-type)
25410			* (5.2) "If �wild IDs� is non-empty, there must not
25411			* be any attribute uses among the {attribute uses}
25412			* whose {attribute declaration}'s {type definition}
25413			* is or is derived from ID."
25414			*/
25415                        if (attrUseList != NULL) {
25416                            for (j = 0; j < attrUseList->nbItems; j++) {
25417                                if (xmlSchemaIsDerivedFromBuiltInType(
25418                                    WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25419                                    XML_SCHEMAS_ID)) {
25420                                    /* URGENT VAL TODO: implement */
25421                            iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25422                                    TODO
25423                                    break;
25424                                }
25425                            }
25426                        }
25427		    }
25428		} else if (type->attributeWildcard->processContents ==
25429		    XML_SCHEMAS_ANY_LAX) {
25430		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25431		    /*
25432		    * SPEC PSVI Assessment Outcome (Attribute)
25433		    * [validity] = "notKnown"
25434		    * [validation attempted] = "none"
25435		    */
25436		} else {
25437		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25438		}
25439	    }
25440	}
25441    }
25442
25443    if (vctxt->nbAttrInfos == 0)
25444	return (0);
25445
25446    /*
25447    * Get the owner element; needed for creation of default attributes.
25448    * This fixes bug #341337, reported by David Grohmann.
25449    */
25450    if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25451	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25452	if (ielem && ielem->node && ielem->node->doc)
25453	    defAttrOwnerElem = ielem->node;
25454    }
25455    /*
25456    * Validate values, create default attributes, evaluate IDCs.
25457    */
25458    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25459	iattr = vctxt->attrInfos[i];
25460	/*
25461	* VAL TODO: Note that we won't try to resolve IDCs to
25462	* "lax" and "skip" validated attributes. Check what to
25463	* do in this case.
25464	*/
25465	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25466	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25467	    continue;
25468	/*
25469	* VAL TODO: What to do if the type definition is missing?
25470	*/
25471	if (iattr->typeDef == NULL) {
25472	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25473	    continue;
25474	}
25475
25476	ACTIVATE_ATTRIBUTE(iattr);
25477	fixed = 0;
25478	xpathRes = 0;
25479
25480	if (vctxt->xpathStates != NULL) {
25481	    /*
25482	    * Evaluate IDCs.
25483	    */
25484	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25485		XML_ATTRIBUTE_NODE);
25486	    if (xpathRes == -1) {
25487		VERROR_INT("xmlSchemaVAttributesComplex",
25488		    "calling xmlSchemaXPathEvaluate()");
25489		goto internal_error;
25490	    }
25491	}
25492
25493	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25494	    /*
25495	    * Default/fixed attributes.
25496	    * We need the value only if we need to resolve IDCs or
25497	    * will create default attributes.
25498	    */
25499	    if ((xpathRes) || (defAttrOwnerElem)) {
25500		if (iattr->use->defValue != NULL) {
25501		    iattr->value = (xmlChar *) iattr->use->defValue;
25502		    iattr->val = iattr->use->defVal;
25503		} else {
25504		    iattr->value = (xmlChar *) iattr->decl->defValue;
25505		    iattr->val = iattr->decl->defVal;
25506		}
25507		/*
25508		* IDCs will consume the precomputed default value,
25509		* so we need to clone it.
25510		*/
25511		if (iattr->val == NULL) {
25512		    VERROR_INT("xmlSchemaVAttributesComplex",
25513			"default/fixed value on an attribute use was "
25514			"not precomputed");
25515		    goto internal_error;
25516		}
25517		iattr->val = xmlSchemaCopyValue(iattr->val);
25518		if (iattr->val == NULL) {
25519		    VERROR_INT("xmlSchemaVAttributesComplex",
25520			"calling xmlSchemaCopyValue()");
25521		    goto internal_error;
25522		}
25523	    }
25524	    /*
25525	    * PSVI: Add the default attribute to the current element.
25526	    * VAL TODO: Should we use the *normalized* value? This currently
25527	    *   uses the *initial* value.
25528	    */
25529
25530	    if (defAttrOwnerElem) {
25531		xmlChar *normValue;
25532		const xmlChar *value;
25533
25534		value = iattr->value;
25535		/*
25536		* Normalize the value.
25537		*/
25538		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25539		    iattr->value);
25540		if (normValue != NULL)
25541		    value = BAD_CAST normValue;
25542
25543		if (iattr->nsName == NULL) {
25544		    if (xmlNewProp(defAttrOwnerElem,
25545			iattr->localName, value) == NULL) {
25546			VERROR_INT("xmlSchemaVAttributesComplex",
25547			    "callling xmlNewProp()");
25548			if (normValue != NULL)
25549			    xmlFree(normValue);
25550			goto internal_error;
25551		    }
25552		} else {
25553		    xmlNsPtr ns;
25554
25555		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25556			defAttrOwnerElem, iattr->nsName);
25557		    if (ns == NULL) {
25558			xmlChar prefix[12];
25559			int counter = 0;
25560
25561			/*
25562			* Create a namespace declaration on the validation
25563			* root node if no namespace declaration is in scope.
25564			*/
25565			do {
25566			    snprintf((char *) prefix, 12, "p%d", counter++);
25567			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25568				defAttrOwnerElem, BAD_CAST prefix);
25569			    if (counter > 1000) {
25570				VERROR_INT(
25571				    "xmlSchemaVAttributesComplex",
25572				    "could not compute a ns prefix for a "
25573				    "default/fixed attribute");
25574				if (normValue != NULL)
25575				    xmlFree(normValue);
25576				goto internal_error;
25577			    }
25578			} while (ns != NULL);
25579			ns = xmlNewNs(vctxt->validationRoot,
25580			    iattr->nsName, BAD_CAST prefix);
25581		    }
25582		    /*
25583		    * TODO:
25584		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25585		    * If we have QNames: do we need to ensure there's a
25586		    * prefix defined for the QName?
25587		    */
25588		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25589		}
25590		if (normValue != NULL)
25591		    xmlFree(normValue);
25592	    }
25593	    /*
25594	    * Go directly to IDC evaluation.
25595	    */
25596	    goto eval_idcs;
25597	}
25598	/*
25599	* Validate the value.
25600	*/
25601	if (vctxt->value != NULL) {
25602	    /*
25603	    * Free last computed value; just for safety reasons.
25604	    */
25605	    xmlSchemaFreeValue(vctxt->value);
25606	    vctxt->value = NULL;
25607	}
25608	/*
25609	* Note that the attribute *use* can be unavailable, if
25610	* the attribute was a wild attribute.
25611	*/
25612	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25613	    ((iattr->use != NULL) &&
25614	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25615	    fixed = 1;
25616	else
25617	    fixed = 0;
25618	/*
25619	* SPEC (cvc-attribute)
25620	* (3) "The item's �normalized value� must be locally �valid�
25621	* with respect to that {type definition} as per
25622	* String Valid (�3.14.4)."
25623	*
25624	* VAL TODO: Do we already have the
25625	* "normalized attribute value" here?
25626	*/
25627	if (xpathRes || fixed) {
25628	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25629	    /*
25630	    * Request a computed value.
25631	    */
25632	    res = xmlSchemaVCheckCVCSimpleType(
25633		ACTXT_CAST vctxt,
25634		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25635		1, 1, 0);
25636	} else {
25637	    res = xmlSchemaVCheckCVCSimpleType(
25638		ACTXT_CAST vctxt,
25639		iattr->node, iattr->typeDef, iattr->value, NULL,
25640		1, 0, 0);
25641	}
25642
25643	if (res != 0) {
25644	    if (res == -1) {
25645		VERROR_INT("xmlSchemaVAttributesComplex",
25646		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25647		goto internal_error;
25648	    }
25649	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25650	    /*
25651	    * SPEC PSVI Assessment Outcome (Attribute)
25652	    * [validity] = "invalid"
25653	    */
25654	    goto eval_idcs;
25655	}
25656
25657	if (fixed) {
25658	    /*
25659	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25660	    * "For an attribute information item to be�valid�
25661	    * with respect to an attribute use its *normalized*
25662	    * value� must match the *canonical* lexical
25663	    * representation of the attribute use's {value
25664	    * constraint}value, if it is present and fixed."
25665	    *
25666	    * VAL TODO: The requirement for the *canonical* value
25667	    * will be removed in XML Schema 1.1.
25668	    */
25669	    /*
25670	    * SPEC Attribute Locally Valid (cvc-attribute)
25671	    * (4) "The item's *actual* value� must match the *value* of
25672	    * the {value constraint}, if it is present and fixed."
25673	    */
25674	    if (iattr->val == NULL) {
25675		/* VAL TODO: A value was not precomputed. */
25676		TODO
25677		goto eval_idcs;
25678	    }
25679	    if ((iattr->use != NULL) &&
25680		(iattr->use->defValue != NULL)) {
25681		if (iattr->use->defVal == NULL) {
25682		    /* VAL TODO: A default value was not precomputed. */
25683		    TODO
25684		    goto eval_idcs;
25685		}
25686		iattr->vcValue = iattr->use->defValue;
25687		/*
25688		if (xmlSchemaCompareValuesWhtsp(attr->val,
25689		    (xmlSchemaWhitespaceValueType) ws,
25690		    attr->use->defVal,
25691		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25692		*/
25693		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25694		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25695	    } else {
25696		if (iattr->decl->defVal == NULL) {
25697		    /* VAL TODO: A default value was not precomputed. */
25698		    TODO
25699		    goto eval_idcs;
25700		}
25701		iattr->vcValue = iattr->decl->defValue;
25702		/*
25703		if (xmlSchemaCompareValuesWhtsp(attr->val,
25704		    (xmlSchemaWhitespaceValueType) ws,
25705		    attrDecl->defVal,
25706		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25707		*/
25708		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25709		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25710	    }
25711	    /*
25712	    * [validity] = "valid"
25713	    */
25714	}
25715eval_idcs:
25716	/*
25717	* Evaluate IDCs.
25718	*/
25719	if (xpathRes) {
25720	    if (xmlSchemaXPathProcessHistory(vctxt,
25721		vctxt->depth +1) == -1) {
25722		VERROR_INT("xmlSchemaVAttributesComplex",
25723		    "calling xmlSchemaXPathEvaluate()");
25724		goto internal_error;
25725	    }
25726	} else if (vctxt->xpathStates != NULL)
25727	    xmlSchemaXPathPop(vctxt);
25728    }
25729
25730    /*
25731    * Report errors.
25732    */
25733    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25734	iattr = vctxt->attrInfos[i];
25735	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25736	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25737	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25738	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25739	    continue;
25740	ACTIVATE_ATTRIBUTE(iattr);
25741	switch (iattr->state) {
25742	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25743		    xmlChar *str = NULL;
25744		    ACTIVATE_ELEM;
25745		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25746			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25747			"The attribute '%s' is required but missing",
25748			xmlSchemaFormatQName(&str,
25749			    iattr->decl->targetNamespace,
25750			    iattr->decl->name),
25751			NULL);
25752		    FREE_AND_NULL(str)
25753		    break;
25754		}
25755	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25756		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25757		    "The type definition is absent");
25758		break;
25759	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25760		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25761		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25762		    "The value '%s' does not match the fixed "
25763		    "value constraint '%s'",
25764		    iattr->value, iattr->vcValue);
25765		break;
25766	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25767		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25768		    "No matching global attribute declaration available, but "
25769		    "demanded by the strict wildcard");
25770		break;
25771	    case XML_SCHEMAS_ATTR_UNKNOWN:
25772		if (iattr->metaType)
25773		    break;
25774		/*
25775		* MAYBE VAL TODO: One might report different error messages
25776		* for the following errors.
25777		*/
25778		if (type->attributeWildcard == NULL) {
25779		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25780			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25781		} else {
25782		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25783			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25784		}
25785		break;
25786	    default:
25787		break;
25788	}
25789    }
25790
25791    ACTIVATE_ELEM;
25792    return (0);
25793internal_error:
25794    ACTIVATE_ELEM;
25795    return (-1);
25796}
25797
25798static int
25799xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25800			      int *skip)
25801{
25802    xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25803    /*
25804    * The namespace of the element was already identified to be
25805    * matching the wildcard.
25806    */
25807    if ((skip == NULL) || (wild == NULL) ||
25808	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25809	VERROR_INT("xmlSchemaValidateElemWildcard",
25810	    "bad arguments");
25811	return (-1);
25812    }
25813    *skip = 0;
25814    if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25815	/*
25816	* URGENT VAL TODO: Either we need to position the stream to the
25817	* next sibling, or walk the whole subtree.
25818	*/
25819	*skip = 1;
25820	return (0);
25821    }
25822    {
25823	xmlSchemaElementPtr decl = NULL;
25824
25825	decl = xmlSchemaGetElem(vctxt->schema,
25826	    vctxt->inode->localName, vctxt->inode->nsName);
25827	if (decl != NULL) {
25828	    vctxt->inode->decl = decl;
25829	    return (0);
25830	}
25831    }
25832    if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25833	/* VAL TODO: Change to proper error code. */
25834	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25835	    "No matching global element declaration available, but "
25836	    "demanded by the strict wildcard");
25837	return (vctxt->err);
25838    }
25839    if (vctxt->nbAttrInfos != 0) {
25840	xmlSchemaAttrInfoPtr iattr;
25841	/*
25842	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25843	* (1.2.1.2.1) - (1.2.1.2.3 )
25844	*
25845	* Use the xsi:type attribute for the type definition.
25846	*/
25847	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25848	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25849	if (iattr != NULL) {
25850	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25851		&(vctxt->inode->typeDef), NULL) == -1) {
25852		VERROR_INT("xmlSchemaValidateElemWildcard",
25853		    "calling xmlSchemaProcessXSIType() to "
25854		    "process the attribute 'xsi:nil'");
25855		return (-1);
25856	    }
25857	    /*
25858	    * Don't return an error on purpose.
25859	    */
25860	    return (0);
25861	}
25862    }
25863    /*
25864    * SPEC Validation Rule: Schema-Validity Assessment (Element)
25865    *
25866    * Fallback to "anyType".
25867    */
25868    vctxt->inode->typeDef =
25869	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25870    return (0);
25871}
25872
25873/*
25874* xmlSchemaCheckCOSValidDefault:
25875*
25876* This will be called if: not nilled, no content and a default/fixed
25877* value is provided.
25878*/
25879
25880static int
25881xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25882			      const xmlChar *value,
25883			      xmlSchemaValPtr *val)
25884{
25885    int ret = 0;
25886    xmlSchemaNodeInfoPtr inode = vctxt->inode;
25887
25888    /*
25889    * cos-valid-default:
25890    * Schema Component Constraint: Element Default Valid (Immediate)
25891    * For a string to be a valid default with respect to a type
25892    * definition the appropriate case among the following must be true:
25893    */
25894    if WXS_IS_COMPLEX(inode->typeDef) {
25895	/*
25896	* Complex type.
25897	*
25898	* SPEC (2.1) "its {content type} must be a simple type definition
25899	* or mixed."
25900	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25901	* type}'s particle must be �emptiable� as defined by
25902	* Particle Emptiable (�3.9.6)."
25903	*/
25904	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25905	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25906	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25907	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25908	    /* NOTE that this covers (2.2.2) as well. */
25909	    VERROR(ret, NULL,
25910		"For a string to be a valid default, the type definition "
25911		"must be a simple type or a complex type with simple content "
25912		"or mixed content and a particle emptiable");
25913	    return(ret);
25914	}
25915    }
25916    /*
25917    * 1 If the type definition is a simple type definition, then the string
25918    * must be �valid� with respect to that definition as defined by String
25919    * Valid (�3.14.4).
25920    *
25921    * AND
25922    *
25923    * 2.2.1 If the {content type} is a simple type definition, then the
25924    * string must be �valid� with respect to that simple type definition
25925    * as defined by String Valid (�3.14.4).
25926    */
25927    if (WXS_IS_SIMPLE(inode->typeDef)) {
25928
25929	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25930	    NULL, inode->typeDef, value, val, 1, 1, 0);
25931
25932    } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25933
25934	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25935	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25936    }
25937    if (ret < 0) {
25938	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25939	    "calling xmlSchemaVCheckCVCSimpleType()");
25940    }
25941    return (ret);
25942}
25943
25944static void
25945xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25946			       const xmlChar * name ATTRIBUTE_UNUSED,
25947			       xmlSchemaElementPtr item,
25948			       xmlSchemaNodeInfoPtr inode)
25949{
25950    inode->decl = item;
25951#ifdef DEBUG_CONTENT
25952    {
25953	xmlChar *str = NULL;
25954
25955	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25956	    xmlGenericError(xmlGenericErrorContext,
25957		"AUTOMATON callback for '%s' [declaration]\n",
25958		xmlSchemaFormatQName(&str,
25959		inode->localName, inode->nsName));
25960	} else {
25961	    xmlGenericError(xmlGenericErrorContext,
25962		    "AUTOMATON callback for '%s' [wildcard]\n",
25963		    xmlSchemaFormatQName(&str,
25964		    inode->localName, inode->nsName));
25965
25966	}
25967	FREE_AND_NULL(str)
25968    }
25969#endif
25970}
25971
25972static int
25973xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25974{
25975    vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25976    if (vctxt->inode == NULL) {
25977	VERROR_INT("xmlSchemaValidatorPushElem",
25978	    "calling xmlSchemaGetFreshElemInfo()");
25979	return (-1);
25980    }
25981    vctxt->nbAttrInfos = 0;
25982    return (0);
25983}
25984
25985static int
25986xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25987			     xmlSchemaNodeInfoPtr inode,
25988			     xmlSchemaTypePtr type,
25989			     const xmlChar *value)
25990{
25991    if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25992	return (xmlSchemaVCheckCVCSimpleType(
25993	    ACTXT_CAST vctxt, NULL,
25994	    type, value, &(inode->val), 1, 1, 0));
25995    else
25996	return (xmlSchemaVCheckCVCSimpleType(
25997	    ACTXT_CAST vctxt, NULL,
25998	    type, value, NULL, 1, 0, 0));
25999}
26000
26001
26002
26003/*
26004* Process END of element.
26005*/
26006static int
26007xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26008{
26009    int ret = 0;
26010    xmlSchemaNodeInfoPtr inode = vctxt->inode;
26011
26012    if (vctxt->nbAttrInfos != 0)
26013	xmlSchemaClearAttrInfos(vctxt);
26014    if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26015	/*
26016	* This element was not expected;
26017	* we will not validate child elements of broken parents.
26018	* Skip validation of all content of the parent.
26019	*/
26020	vctxt->skipDepth = vctxt->depth -1;
26021	goto end_elem;
26022    }
26023    if ((inode->typeDef == NULL) ||
26024	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26025	/*
26026	* 1. the type definition might be missing if the element was
26027	*    error prone
26028	* 2. it might be abstract.
26029	*/
26030	goto end_elem;
26031    }
26032    /*
26033    * Check the content model.
26034    */
26035    if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26036	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26037
26038	/*
26039	* Workaround for "anyType".
26040	*/
26041	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26042	    goto character_content;
26043
26044	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26045	    xmlChar *values[10];
26046	    int terminal, nbval = 10, nbneg;
26047
26048	    if (inode->regexCtxt == NULL) {
26049		/*
26050		* Create the regex context.
26051		*/
26052		inode->regexCtxt =
26053		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26054		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26055		    vctxt);
26056		if (inode->regexCtxt == NULL) {
26057		    VERROR_INT("xmlSchemaValidatorPopElem",
26058			"failed to create a regex context");
26059		    goto internal_error;
26060		}
26061#ifdef DEBUG_AUTOMATA
26062		xmlGenericError(xmlGenericErrorContext,
26063		    "AUTOMATON create on '%s'\n", inode->localName);
26064#endif
26065	    }
26066
26067	    /*
26068	     * Do not check further content if the node has been nilled
26069	     */
26070	    if (INODE_NILLED(inode)) {
26071		ret = 0;
26072#ifdef DEBUG_AUTOMATA
26073		xmlGenericError(xmlGenericErrorContext,
26074		    "AUTOMATON succeeded on nilled '%s'\n",
26075		    inode->localName);
26076#endif
26077                goto skip_nilled;
26078	    }
26079
26080	    /*
26081	    * Get hold of the still expected content, since a further
26082	    * call to xmlRegExecPushString() will loose this information.
26083	    */
26084	    xmlRegExecNextValues(inode->regexCtxt,
26085		&nbval, &nbneg, &values[0], &terminal);
26086	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26087	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26088		/*
26089		* Still missing something.
26090		*/
26091		ret = 1;
26092		inode->flags |=
26093		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26094		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26095		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26096		    "Missing child element(s)",
26097		    nbval, nbneg, values);
26098#ifdef DEBUG_AUTOMATA
26099		xmlGenericError(xmlGenericErrorContext,
26100		    "AUTOMATON missing ERROR on '%s'\n",
26101		    inode->localName);
26102#endif
26103	    } else {
26104		/*
26105		* Content model is satisfied.
26106		*/
26107		ret = 0;
26108#ifdef DEBUG_AUTOMATA
26109		xmlGenericError(xmlGenericErrorContext,
26110		    "AUTOMATON succeeded on '%s'\n",
26111		    inode->localName);
26112#endif
26113	    }
26114
26115	}
26116    }
26117
26118skip_nilled:
26119
26120    if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26121	goto end_elem;
26122
26123character_content:
26124
26125    if (vctxt->value != NULL) {
26126	xmlSchemaFreeValue(vctxt->value);
26127	vctxt->value = NULL;
26128    }
26129    /*
26130    * Check character content.
26131    */
26132    if (inode->decl == NULL) {
26133	/*
26134	* Speedup if no declaration exists.
26135	*/
26136	if (WXS_IS_SIMPLE(inode->typeDef)) {
26137	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26138		inode, inode->typeDef, inode->value);
26139	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26140	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26141		inode, inode->typeDef->contentTypeDef,
26142		inode->value);
26143	}
26144	if (ret < 0) {
26145	    VERROR_INT("xmlSchemaValidatorPopElem",
26146		"calling xmlSchemaVCheckCVCSimpleType()");
26147	    goto internal_error;
26148	}
26149	goto end_elem;
26150    }
26151    /*
26152    * cvc-elt (3.3.4) : 5
26153    * The appropriate case among the following must be true:
26154    */
26155    /*
26156    * cvc-elt (3.3.4) : 5.1
26157    * If the declaration has a {value constraint},
26158    * the item has neither element nor character [children] and
26159    * clause 3.2 has not applied, then all of the following must be true:
26160    */
26161    if ((inode->decl->value != NULL) &&
26162	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26163	(! INODE_NILLED(inode))) {
26164	/*
26165	* cvc-elt (3.3.4) : 5.1.1
26166	* If the �actual type definition� is a �local type definition�
26167	* then the canonical lexical representation of the {value constraint}
26168	* value must be a valid default for the �actual type definition� as
26169	* defined in Element Default Valid (Immediate) (�3.3.6).
26170	*/
26171	/*
26172	* NOTE: 'local' above means types acquired by xsi:type.
26173	* NOTE: Although the *canonical* value is stated, it is not
26174	* relevant if canonical or not. Additionally XML Schema 1.1
26175	* will removed this requirement as well.
26176	*/
26177	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26178
26179	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26180		inode->decl->value, &(inode->val));
26181	    if (ret != 0) {
26182		if (ret < 0) {
26183		    VERROR_INT("xmlSchemaValidatorPopElem",
26184			"calling xmlSchemaCheckCOSValidDefault()");
26185		    goto internal_error;
26186		}
26187		goto end_elem;
26188	    }
26189	    /*
26190	    * Stop here, to avoid redundant validation of the value
26191	    * (see following).
26192	    */
26193	    goto default_psvi;
26194	}
26195	/*
26196	* cvc-elt (3.3.4) : 5.1.2
26197	* The element information item with the canonical lexical
26198	* representation of the {value constraint} value used as its
26199	* �normalized value� must be �valid� with respect to the
26200	* �actual type definition� as defined by Element Locally Valid (Type)
26201	* (�3.3.4).
26202	*/
26203	if (WXS_IS_SIMPLE(inode->typeDef)) {
26204	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26205		inode, inode->typeDef, inode->decl->value);
26206	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26207	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26208		inode, inode->typeDef->contentTypeDef,
26209		inode->decl->value);
26210	}
26211	if (ret != 0) {
26212	    if (ret < 0) {
26213		VERROR_INT("xmlSchemaValidatorPopElem",
26214		    "calling xmlSchemaVCheckCVCSimpleType()");
26215		goto internal_error;
26216	    }
26217	    goto end_elem;
26218	}
26219
26220default_psvi:
26221	/*
26222	* PSVI: Create a text node on the instance element.
26223	*/
26224	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26225	    (inode->node != NULL)) {
26226	    xmlNodePtr textChild;
26227	    xmlChar *normValue;
26228	    /*
26229	    * VAL TODO: Normalize the value.
26230	    */
26231	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26232		inode->decl->value);
26233	    if (normValue != NULL) {
26234		textChild = xmlNewText(BAD_CAST normValue);
26235		xmlFree(normValue);
26236	    } else
26237		textChild = xmlNewText(inode->decl->value);
26238	    if (textChild == NULL) {
26239		VERROR_INT("xmlSchemaValidatorPopElem",
26240		    "calling xmlNewText()");
26241		goto internal_error;
26242	    } else
26243		xmlAddChild(inode->node, textChild);
26244	}
26245
26246    } else if (! INODE_NILLED(inode)) {
26247	/*
26248	* 5.2.1 The element information item must be �valid� with respect
26249	* to the �actual type definition� as defined by Element Locally
26250	* Valid (Type) (�3.3.4).
26251	*/
26252	if (WXS_IS_SIMPLE(inode->typeDef)) {
26253	     /*
26254	    * SPEC (cvc-type) (3.1)
26255	    * "If the type definition is a simple type definition, ..."
26256	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26257	    * (Element) (�3.3.4) did not apply, then the �normalized value�
26258	    * must be �valid� with respect to the type definition as defined
26259	    * by String Valid (�3.14.4).
26260	    */
26261	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26262		    inode, inode->typeDef, inode->value);
26263	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26264	    /*
26265	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26266	    * definition, then the element information item must be
26267	    * �valid� with respect to the type definition as per
26268	    * Element Locally Valid (Complex Type) (�3.4.4);"
26269	    *
26270	    * SPEC (cvc-complex-type) (2.2)
26271	    * "If the {content type} is a simple type definition, ...
26272	    * the �normalized value� of the element information item is
26273	    * �valid� with respect to that simple type definition as
26274	    * defined by String Valid (�3.14.4)."
26275	    */
26276	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26277		inode, inode->typeDef->contentTypeDef, inode->value);
26278	}
26279	if (ret != 0) {
26280	    if (ret < 0) {
26281		VERROR_INT("xmlSchemaValidatorPopElem",
26282		    "calling xmlSchemaVCheckCVCSimpleType()");
26283		goto internal_error;
26284	    }
26285	    goto end_elem;
26286	}
26287	/*
26288	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26289	* not applied, all of the following must be true:
26290	*/
26291	if ((inode->decl->value != NULL) &&
26292	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26293
26294	    /*
26295	    * TODO: We will need a computed value, when comparison is
26296	    * done on computed values.
26297	    */
26298	    /*
26299	    * 5.2.2.1 The element information item must have no element
26300	    * information item [children].
26301	    */
26302	    if (inode->flags &
26303		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26304		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26305		VERROR(ret, NULL,
26306		    "The content must not containt element nodes since "
26307		    "there is a fixed value constraint");
26308		goto end_elem;
26309	    } else {
26310		/*
26311		* 5.2.2.2 The appropriate case among the following must
26312		* be true:
26313		*/
26314		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26315		    /*
26316		    * 5.2.2.2.1 If the {content type} of the �actual type
26317		    * definition� is mixed, then the *initial value* of the
26318		    * item must match the canonical lexical representation
26319		    * of the {value constraint} value.
26320		    *
26321		    * ... the *initial value* of an element information
26322		    * item is the string composed of, in order, the
26323		    * [character code] of each character information item in
26324		    * the [children] of that element information item.
26325		    */
26326		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26327			/*
26328			* VAL TODO: Report invalid & expected values as well.
26329			* VAL TODO: Implement the canonical stuff.
26330			*/
26331			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26332			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26333			    ret, NULL, NULL,
26334			    "The initial value '%s' does not match the fixed "
26335			    "value constraint '%s'",
26336			    inode->value, inode->decl->value);
26337			goto end_elem;
26338		    }
26339		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26340		    /*
26341		    * 5.2.2.2.2 If the {content type} of the �actual type
26342		    * definition� is a simple type definition, then the
26343		    * *actual value* of the item must match the canonical
26344		    * lexical representation of the {value constraint} value.
26345		    */
26346		    /*
26347		    * VAL TODO: *actual value* is the normalized value, impl.
26348		    *           this.
26349		    * VAL TODO: Report invalid & expected values as well.
26350		    * VAL TODO: Implement a comparison with the computed values.
26351		    */
26352		    if (! xmlStrEqual(inode->value,
26353			    inode->decl->value)) {
26354			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26355			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26356			    ret, NULL, NULL,
26357			    "The actual value '%s' does not match the fixed "
26358			    "value constraint '%s'",
26359			    inode->value,
26360			    inode->decl->value);
26361			goto end_elem;
26362		    }
26363		}
26364	    }
26365	}
26366    }
26367
26368end_elem:
26369    if (vctxt->depth < 0) {
26370	/* TODO: raise error? */
26371	return (0);
26372    }
26373    if (vctxt->depth == vctxt->skipDepth)
26374	vctxt->skipDepth = -1;
26375    /*
26376    * Evaluate the history of XPath state objects.
26377    */
26378    if (inode->appliedXPath &&
26379	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26380	goto internal_error;
26381    /*
26382    * MAYBE TODO:
26383    * SPEC (6) "The element information item must be �valid� with
26384    * respect to each of the {identity-constraint definitions} as per
26385    * Identity-constraint Satisfied (�3.11.4)."
26386    */
26387    /*
26388    * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26389    *   need to be built in any case.
26390    *   We will currently build IDC node-tables and bubble them only if
26391    *   keyrefs do exist.
26392    */
26393
26394    /*
26395    * Add the current IDC target-nodes to the IDC node-tables.
26396    */
26397    if ((inode->idcMatchers != NULL) &&
26398	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26399    {
26400	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26401	    goto internal_error;
26402    }
26403    /*
26404    * Validate IDC keyrefs.
26405    */
26406    if (vctxt->inode->hasKeyrefs)
26407	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26408	    goto internal_error;
26409    /*
26410    * Merge/free the IDC table.
26411    */
26412    if (inode->idcTable != NULL) {
26413#ifdef DEBUG_IDC_NODE_TABLE
26414	xmlSchemaDebugDumpIDCTable(stdout,
26415	    inode->nsName,
26416	    inode->localName,
26417	    inode->idcTable);
26418#endif
26419	if ((vctxt->depth > 0) &&
26420	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26421	{
26422	    /*
26423	    * Merge the IDC node table with the table of the parent node.
26424	    */
26425	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26426		goto internal_error;
26427	}
26428    }
26429    /*
26430    * Clear the current ielem.
26431    * VAL TODO: Don't free the PSVI IDC tables if they are
26432    * requested for the PSVI.
26433    */
26434    xmlSchemaClearElemInfo(vctxt, inode);
26435    /*
26436    * Skip further processing if we are on the validation root.
26437    */
26438    if (vctxt->depth == 0) {
26439	vctxt->depth--;
26440	vctxt->inode = NULL;
26441	return (0);
26442    }
26443    /*
26444    * Reset the keyrefDepth if needed.
26445    */
26446    if (vctxt->aidcs != NULL) {
26447	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26448	do {
26449	    if (aidc->keyrefDepth == vctxt->depth) {
26450		/*
26451		* A 'keyrefDepth' of a key/unique IDC matches the current
26452		* depth, this means that we are leaving the scope of the
26453		* top-most keyref IDC which refers to this IDC.
26454		*/
26455		aidc->keyrefDepth = -1;
26456	    }
26457	    aidc = aidc->next;
26458	} while (aidc != NULL);
26459    }
26460    vctxt->depth--;
26461    vctxt->inode = vctxt->elemInfos[vctxt->depth];
26462    /*
26463    * VAL TODO: 7 If the element information item is the �validation root�, it must be
26464    * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26465    */
26466    return (ret);
26467
26468internal_error:
26469    vctxt->err = -1;
26470    return (-1);
26471}
26472
26473/*
26474* 3.4.4 Complex Type Definition Validation Rules
26475* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26476*/
26477static int
26478xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26479{
26480    xmlSchemaNodeInfoPtr pielem;
26481    xmlSchemaTypePtr ptype;
26482    int ret = 0;
26483
26484    if (vctxt->depth <= 0) {
26485	VERROR_INT("xmlSchemaValidateChildElem",
26486	    "not intended for the validation root");
26487	return (-1);
26488    }
26489    pielem = vctxt->elemInfos[vctxt->depth -1];
26490    if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26491	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26492    /*
26493    * Handle 'nilled' elements.
26494    */
26495    if (INODE_NILLED(pielem)) {
26496	/*
26497	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26498	*/
26499	ACTIVATE_PARENT_ELEM;
26500	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26501	VERROR(ret, NULL,
26502	    "Neither character nor element content is allowed, "
26503	    "because the element was 'nilled'");
26504	ACTIVATE_ELEM;
26505	goto unexpected_elem;
26506    }
26507
26508    ptype = pielem->typeDef;
26509
26510    if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26511	/*
26512	* Workaround for "anyType": we have currently no content model
26513	* assigned for "anyType", so handle it explicitely.
26514	* "anyType" has an unbounded, lax "any" wildcard.
26515	*/
26516	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26517	    vctxt->inode->localName,
26518	    vctxt->inode->nsName);
26519
26520	if (vctxt->inode->decl == NULL) {
26521	    xmlSchemaAttrInfoPtr iattr;
26522	    /*
26523	    * Process "xsi:type".
26524	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26525	    */
26526	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26527		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26528	    if (iattr != NULL) {
26529		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26530		    &(vctxt->inode->typeDef), NULL);
26531		if (ret != 0) {
26532		    if (ret == -1) {
26533			VERROR_INT("xmlSchemaValidateChildElem",
26534			    "calling xmlSchemaProcessXSIType() to "
26535			    "process the attribute 'xsi:nil'");
26536			return (-1);
26537		    }
26538		    return (ret);
26539		}
26540	    } else {
26541		 /*
26542		 * Fallback to "anyType".
26543		 *
26544		 * SPEC (cvc-assess-elt)
26545		 * "If the item cannot be �strictly assessed�, [...]
26546		 * an element information item's schema validity may be laxly
26547		 * assessed if its �context-determined declaration� is not
26548		 * skip by �validating� with respect to the �ur-type
26549		 * definition� as per Element Locally Valid (Type) (�3.3.4)."
26550		*/
26551		vctxt->inode->typeDef =
26552		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26553	    }
26554	}
26555	return (0);
26556    }
26557
26558    switch (ptype->contentType) {
26559	case XML_SCHEMA_CONTENT_EMPTY:
26560	    /*
26561	    * SPEC (2.1) "If the {content type} is empty, then the
26562	    * element information item has no character or element
26563	    * information item [children]."
26564	    */
26565	    ACTIVATE_PARENT_ELEM
26566	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26567	    VERROR(ret, NULL,
26568		"Element content is not allowed, "
26569		"because the content type is empty");
26570	    ACTIVATE_ELEM
26571	    goto unexpected_elem;
26572	    break;
26573
26574	case XML_SCHEMA_CONTENT_MIXED:
26575        case XML_SCHEMA_CONTENT_ELEMENTS: {
26576	    xmlRegExecCtxtPtr regexCtxt;
26577	    xmlChar *values[10];
26578	    int terminal, nbval = 10, nbneg;
26579
26580	    /* VAL TODO: Optimized "anyType" validation.*/
26581
26582	    if (ptype->contModel == NULL) {
26583		VERROR_INT("xmlSchemaValidateChildElem",
26584		    "type has elem content but no content model");
26585		return (-1);
26586	    }
26587	    /*
26588	    * Safety belf for evaluation if the cont. model was already
26589	    * examined to be invalid.
26590	    */
26591	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26592		VERROR_INT("xmlSchemaValidateChildElem",
26593		    "validating elem, but elem content is already invalid");
26594		return (-1);
26595	    }
26596
26597	    regexCtxt = pielem->regexCtxt;
26598	    if (regexCtxt == NULL) {
26599		/*
26600		* Create the regex context.
26601		*/
26602		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26603		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26604		    vctxt);
26605		if (regexCtxt == NULL) {
26606		    VERROR_INT("xmlSchemaValidateChildElem",
26607			"failed to create a regex context");
26608		    return (-1);
26609		}
26610		pielem->regexCtxt = regexCtxt;
26611#ifdef DEBUG_AUTOMATA
26612		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26613		    pielem->localName);
26614#endif
26615	    }
26616
26617	    /*
26618	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26619	    * then the sequence of the element information item's
26620	    * element information item [children], if any, taken in
26621	    * order, is �valid� with respect to the {content type}'s
26622	    * particle, as defined in Element Sequence Locally Valid
26623	    * (Particle) (�3.9.4)."
26624	    */
26625	    ret = xmlRegExecPushString2(regexCtxt,
26626		vctxt->inode->localName,
26627		vctxt->inode->nsName,
26628		vctxt->inode);
26629#ifdef DEBUG_AUTOMATA
26630	    if (ret < 0)
26631		xmlGenericError(xmlGenericErrorContext,
26632		"AUTOMATON push ERROR for '%s' on '%s'\n",
26633		vctxt->inode->localName, pielem->localName);
26634	    else
26635		xmlGenericError(xmlGenericErrorContext,
26636		"AUTOMATON push OK for '%s' on '%s'\n",
26637		vctxt->inode->localName, pielem->localName);
26638#endif
26639	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26640		VERROR_INT("xmlSchemaValidateChildElem",
26641		    "calling xmlRegExecPushString2()");
26642		return (-1);
26643	    }
26644	    if (ret < 0) {
26645		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26646		    &values[0], &terminal);
26647		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26648		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26649		    "This element is not expected",
26650		    nbval, nbneg, values);
26651		ret = vctxt->err;
26652		goto unexpected_elem;
26653	    } else
26654		ret = 0;
26655	}
26656	    break;
26657	case XML_SCHEMA_CONTENT_SIMPLE:
26658	case XML_SCHEMA_CONTENT_BASIC:
26659	    ACTIVATE_PARENT_ELEM
26660	    if (WXS_IS_COMPLEX(ptype)) {
26661		/*
26662		* SPEC (cvc-complex-type) (2.2)
26663		* "If the {content type} is a simple type definition, then
26664		* the element information item has no element information
26665		* item [children], ..."
26666		*/
26667		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26668		VERROR(ret, NULL, "Element content is not allowed, "
26669		    "because the content type is a simple type definition");
26670	    } else {
26671		/*
26672		* SPEC (cvc-type) (3.1.2) "The element information item must
26673		* have no element information item [children]."
26674		*/
26675		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26676		VERROR(ret, NULL, "Element content is not allowed, "
26677		    "because the type definition is simple");
26678	    }
26679	    ACTIVATE_ELEM
26680	    ret = vctxt->err;
26681	    goto unexpected_elem;
26682	    break;
26683
26684	default:
26685	    break;
26686    }
26687    return (ret);
26688unexpected_elem:
26689    /*
26690    * Pop this element and set the skipDepth to skip
26691    * all further content of the parent element.
26692    */
26693    vctxt->skipDepth = vctxt->depth;
26694    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26695    pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26696    return (ret);
26697}
26698
26699#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26700#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26701#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26702
26703static int
26704xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26705		  int nodeType, const xmlChar *value, int len,
26706		  int mode, int *consumed)
26707{
26708    /*
26709    * Unfortunately we have to duplicate the text sometimes.
26710    * OPTIMIZE: Maybe we could skip it, if:
26711    *   1. content type is simple
26712    *   2. whitespace is "collapse"
26713    *   3. it consists of whitespace only
26714    *
26715    * Process character content.
26716    */
26717    if (consumed != NULL)
26718	*consumed = 0;
26719    if (INODE_NILLED(vctxt->inode)) {
26720	/*
26721	* SPEC cvc-elt (3.3.4 - 3.2.1)
26722	* "The element information item must have no character or
26723	* element information item [children]."
26724	*/
26725	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26726	    "Neither character nor element content is allowed "
26727	    "because the element is 'nilled'");
26728	return (vctxt->err);
26729    }
26730    /*
26731    * SPEC (2.1) "If the {content type} is empty, then the
26732    * element information item has no character or element
26733    * information item [children]."
26734    */
26735    if (vctxt->inode->typeDef->contentType ==
26736	    XML_SCHEMA_CONTENT_EMPTY) {
26737	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26738	    "Character content is not allowed, "
26739	    "because the content type is empty");
26740	return (vctxt->err);
26741    }
26742
26743    if (vctxt->inode->typeDef->contentType ==
26744	    XML_SCHEMA_CONTENT_ELEMENTS) {
26745	if ((nodeType != XML_TEXT_NODE) ||
26746	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26747	    /*
26748	    * SPEC cvc-complex-type (2.3)
26749	    * "If the {content type} is element-only, then the
26750	    * element information item has no character information
26751	    * item [children] other than those whose [character
26752	    * code] is defined as a white space in [XML 1.0 (Second
26753	    * Edition)]."
26754	    */
26755	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26756		"Character content other than whitespace is not allowed "
26757		"because the content type is 'element-only'");
26758	    return (vctxt->err);
26759	}
26760	return (0);
26761    }
26762
26763    if ((value == NULL) || (value[0] == 0))
26764	return (0);
26765    /*
26766    * Save the value.
26767    * NOTE that even if the content type is *mixed*, we need the
26768    * *initial value* for default/fixed value constraints.
26769    */
26770    if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26771	((vctxt->inode->decl == NULL) ||
26772	(vctxt->inode->decl->value == NULL)))
26773	return (0);
26774
26775    if (vctxt->inode->value == NULL) {
26776	/*
26777	* Set the value.
26778	*/
26779	switch (mode) {
26780	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26781		/*
26782		* When working on a tree.
26783		*/
26784		vctxt->inode->value = value;
26785		break;
26786	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26787		/*
26788		* When working with the reader.
26789		* The value will be freed by the element info.
26790		*/
26791		vctxt->inode->value = value;
26792		if (consumed != NULL)
26793		    *consumed = 1;
26794		vctxt->inode->flags |=
26795		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26796		break;
26797	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26798		/*
26799		* When working with SAX.
26800		* The value will be freed by the element info.
26801		*/
26802		if (len != -1)
26803		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26804		else
26805		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26806		vctxt->inode->flags |=
26807		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26808		break;
26809	    default:
26810		break;
26811	}
26812    } else {
26813	if (len < 0)
26814	    len = xmlStrlen(value);
26815	/*
26816	* Concat the value.
26817	*/
26818	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26819	    vctxt->inode->value = BAD_CAST xmlStrncat(
26820		(xmlChar *) vctxt->inode->value, value, len);
26821	} else {
26822	    vctxt->inode->value =
26823		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26824	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26825	}
26826    }
26827
26828    return (0);
26829}
26830
26831static int
26832xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26833{
26834    int ret = 0;
26835
26836    if ((vctxt->skipDepth != -1) &&
26837	(vctxt->depth >= vctxt->skipDepth)) {
26838	VERROR_INT("xmlSchemaValidateElem",
26839	    "in skip-state");
26840	goto internal_error;
26841    }
26842    if (vctxt->xsiAssemble) {
26843	/*
26844	* We will stop validation if there was an error during
26845	* dynamic schema construction.
26846	* Note that we simply set @skipDepth to 0, this could
26847	* mean that a streaming document via SAX would be
26848	* still read to the end but it won't be validated any more.
26849	* TODO: If we are sure how to stop the validation at once
26850	*   for all input scenarios, then this should be changed to
26851	*   instantly stop the validation.
26852	*/
26853	ret = xmlSchemaAssembleByXSI(vctxt);
26854	if (ret != 0) {
26855	    if (ret == -1)
26856		goto internal_error;
26857	    vctxt->skipDepth = 0;
26858	    return(ret);
26859	}
26860        /*
26861         * Augment the IDC definitions for the main schema and all imported ones
26862         * NOTE: main schema is the first in the imported list
26863         */
26864        xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26865    }
26866    if (vctxt->depth > 0) {
26867	/*
26868	* Validate this element against the content model
26869	* of the parent.
26870	*/
26871	ret = xmlSchemaValidateChildElem(vctxt);
26872	if (ret != 0) {
26873	    if (ret < 0) {
26874		VERROR_INT("xmlSchemaValidateElem",
26875		    "calling xmlSchemaStreamValidateChildElement()");
26876		goto internal_error;
26877	    }
26878	    goto exit;
26879	}
26880	if (vctxt->depth == vctxt->skipDepth)
26881	    goto exit;
26882	if ((vctxt->inode->decl == NULL) &&
26883	    (vctxt->inode->typeDef == NULL)) {
26884	    VERROR_INT("xmlSchemaValidateElem",
26885		"the child element was valid but neither the "
26886		"declaration nor the type was set");
26887	    goto internal_error;
26888	}
26889    } else {
26890	/*
26891	* Get the declaration of the validation root.
26892	*/
26893	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26894	    vctxt->inode->localName,
26895	    vctxt->inode->nsName);
26896	if (vctxt->inode->decl == NULL) {
26897	    ret = XML_SCHEMAV_CVC_ELT_1;
26898	    VERROR(ret, NULL,
26899		"No matching global declaration available "
26900		"for the validation root");
26901	    goto exit;
26902	}
26903    }
26904
26905    if (vctxt->inode->decl == NULL)
26906	goto type_validation;
26907
26908    if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26909	int skip;
26910	/*
26911	* Wildcards.
26912	*/
26913	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26914	if (ret != 0) {
26915	    if (ret < 0) {
26916		VERROR_INT("xmlSchemaValidateElem",
26917		    "calling xmlSchemaValidateElemWildcard()");
26918		goto internal_error;
26919	    }
26920	    goto exit;
26921	}
26922	if (skip) {
26923	    vctxt->skipDepth = vctxt->depth;
26924	    goto exit;
26925	}
26926	/*
26927	* The declaration might be set by the wildcard validation,
26928	* when the processContents is "lax" or "strict".
26929	*/
26930	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26931	    /*
26932	    * Clear the "decl" field to not confuse further processing.
26933	    */
26934	    vctxt->inode->decl = NULL;
26935	    goto type_validation;
26936	}
26937    }
26938    /*
26939    * Validate against the declaration.
26940    */
26941    ret = xmlSchemaValidateElemDecl(vctxt);
26942    if (ret != 0) {
26943	if (ret < 0) {
26944	    VERROR_INT("xmlSchemaValidateElem",
26945		"calling xmlSchemaValidateElemDecl()");
26946	    goto internal_error;
26947	}
26948	goto exit;
26949    }
26950    /*
26951    * Validate against the type definition.
26952    */
26953type_validation:
26954
26955    if (vctxt->inode->typeDef == NULL) {
26956	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26957	ret = XML_SCHEMAV_CVC_TYPE_1;
26958	VERROR(ret, NULL,
26959	    "The type definition is absent");
26960	goto exit;
26961    }
26962    if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26963	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26964	ret = XML_SCHEMAV_CVC_TYPE_2;
26965	    VERROR(ret, NULL,
26966	    "The type definition is abstract");
26967	goto exit;
26968    }
26969    /*
26970    * Evaluate IDCs. Do it here, since new IDC matchers are registered
26971    * during validation against the declaration. This must be done
26972    * _before_ attribute validation.
26973    */
26974    if (vctxt->xpathStates != NULL) {
26975	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26976	vctxt->inode->appliedXPath = 1;
26977	if (ret == -1) {
26978	    VERROR_INT("xmlSchemaValidateElem",
26979		"calling xmlSchemaXPathEvaluate()");
26980	    goto internal_error;
26981	}
26982    }
26983    /*
26984    * Validate attributes.
26985    */
26986    if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26987	if ((vctxt->nbAttrInfos != 0) ||
26988	    (vctxt->inode->typeDef->attrUses != NULL)) {
26989
26990	    ret = xmlSchemaVAttributesComplex(vctxt);
26991	}
26992    } else if (vctxt->nbAttrInfos != 0) {
26993
26994	ret = xmlSchemaVAttributesSimple(vctxt);
26995    }
26996    /*
26997    * Clear registered attributes.
26998    */
26999    if (vctxt->nbAttrInfos != 0)
27000	xmlSchemaClearAttrInfos(vctxt);
27001    if (ret == -1) {
27002	VERROR_INT("xmlSchemaValidateElem",
27003	    "calling attributes validation");
27004	goto internal_error;
27005    }
27006    /*
27007    * Don't return an error if attributes are invalid on purpose.
27008    */
27009    ret = 0;
27010
27011exit:
27012    if (ret != 0)
27013	vctxt->skipDepth = vctxt->depth;
27014    return (ret);
27015internal_error:
27016    return (-1);
27017}
27018
27019#ifdef XML_SCHEMA_READER_ENABLED
27020static int
27021xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27022{
27023    const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27024    int depth, nodeType, ret = 0, consumed;
27025    xmlSchemaNodeInfoPtr ielem;
27026
27027    vctxt->depth = -1;
27028    ret = xmlTextReaderRead(vctxt->reader);
27029    /*
27030    * Move to the document element.
27031    */
27032    while (ret == 1) {
27033	nodeType = xmlTextReaderNodeType(vctxt->reader);
27034	if (nodeType == XML_ELEMENT_NODE)
27035	    goto root_found;
27036	ret = xmlTextReaderRead(vctxt->reader);
27037    }
27038    goto exit;
27039
27040root_found:
27041
27042    do {
27043	depth = xmlTextReaderDepth(vctxt->reader);
27044	nodeType = xmlTextReaderNodeType(vctxt->reader);
27045
27046	if (nodeType == XML_ELEMENT_NODE) {
27047
27048	    vctxt->depth++;
27049	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27050		VERROR_INT("xmlSchemaVReaderWalk",
27051		    "calling xmlSchemaValidatorPushElem()");
27052		goto internal_error;
27053	    }
27054	    ielem = vctxt->inode;
27055	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27056	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27057	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27058	    /*
27059	    * Is the element empty?
27060	    */
27061	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27062	    if (ret == -1) {
27063		VERROR_INT("xmlSchemaVReaderWalk",
27064		    "calling xmlTextReaderIsEmptyElement()");
27065		goto internal_error;
27066	    }
27067	    if (ret) {
27068		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27069	    }
27070	    /*
27071	    * Register attributes.
27072	    */
27073	    vctxt->nbAttrInfos = 0;
27074	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27075	    if (ret == -1) {
27076		VERROR_INT("xmlSchemaVReaderWalk",
27077		    "calling xmlTextReaderMoveToFirstAttribute()");
27078		goto internal_error;
27079	    }
27080	    if (ret == 1) {
27081		do {
27082		    /*
27083		    * VAL TODO: How do we know that the reader works on a
27084		    * node tree, to be able to pass a node here?
27085		    */
27086		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27087			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27088			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27089			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27090
27091			VERROR_INT("xmlSchemaVReaderWalk",
27092			    "calling xmlSchemaValidatorPushAttribute()");
27093			goto internal_error;
27094		    }
27095		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27096		    if (ret == -1) {
27097			VERROR_INT("xmlSchemaVReaderWalk",
27098			    "calling xmlTextReaderMoveToFirstAttribute()");
27099			goto internal_error;
27100		    }
27101		} while (ret == 1);
27102		/*
27103		* Back to element position.
27104		*/
27105		ret = xmlTextReaderMoveToElement(vctxt->reader);
27106		if (ret == -1) {
27107		    VERROR_INT("xmlSchemaVReaderWalk",
27108			"calling xmlTextReaderMoveToElement()");
27109		    goto internal_error;
27110		}
27111	    }
27112	    /*
27113	    * Validate the element.
27114	    */
27115	    ret= xmlSchemaValidateElem(vctxt);
27116	    if (ret != 0) {
27117		if (ret == -1) {
27118		    VERROR_INT("xmlSchemaVReaderWalk",
27119			"calling xmlSchemaValidateElem()");
27120		    goto internal_error;
27121		}
27122		goto exit;
27123	    }
27124	    if (vctxt->depth == vctxt->skipDepth) {
27125		int curDepth;
27126		/*
27127		* Skip all content.
27128		*/
27129		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27130		    ret = xmlTextReaderRead(vctxt->reader);
27131		    curDepth = xmlTextReaderDepth(vctxt->reader);
27132		    while ((ret == 1) && (curDepth != depth)) {
27133			ret = xmlTextReaderRead(vctxt->reader);
27134			curDepth = xmlTextReaderDepth(vctxt->reader);
27135		    }
27136		    if (ret < 0) {
27137			/*
27138			* VAL TODO: A reader error occured; what to do here?
27139			*/
27140			ret = 1;
27141			goto exit;
27142		    }
27143		}
27144		goto leave_elem;
27145	    }
27146	    /*
27147	    * READER VAL TODO: Is an END_ELEM really never called
27148	    * if the elem is empty?
27149	    */
27150	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27151		goto leave_elem;
27152	} else if (nodeType == END_ELEM) {
27153	    /*
27154	    * Process END of element.
27155	    */
27156leave_elem:
27157	    ret = xmlSchemaValidatorPopElem(vctxt);
27158	    if (ret != 0) {
27159		if (ret < 0) {
27160		    VERROR_INT("xmlSchemaVReaderWalk",
27161			"calling xmlSchemaValidatorPopElem()");
27162		    goto internal_error;
27163		}
27164		goto exit;
27165	    }
27166	    if (vctxt->depth >= 0)
27167		ielem = vctxt->inode;
27168	    else
27169		ielem = NULL;
27170	} else if ((nodeType == XML_TEXT_NODE) ||
27171	    (nodeType == XML_CDATA_SECTION_NODE) ||
27172	    (nodeType == WHTSP) ||
27173	    (nodeType == SIGN_WHTSP)) {
27174	    /*
27175	    * Process character content.
27176	    */
27177	    xmlChar *value;
27178
27179	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27180		nodeType = XML_TEXT_NODE;
27181
27182	    value = xmlTextReaderValue(vctxt->reader);
27183	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27184		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27185	    if (! consumed)
27186		xmlFree(value);
27187	    if (ret == -1) {
27188		VERROR_INT("xmlSchemaVReaderWalk",
27189		    "calling xmlSchemaVPushText()");
27190		goto internal_error;
27191	    }
27192	} else if ((nodeType == XML_ENTITY_NODE) ||
27193	    (nodeType == XML_ENTITY_REF_NODE)) {
27194	    /*
27195	    * VAL TODO: What to do with entities?
27196	    */
27197	    TODO
27198	}
27199	/*
27200	* Read next node.
27201	*/
27202	ret = xmlTextReaderRead(vctxt->reader);
27203    } while (ret == 1);
27204
27205exit:
27206    return (ret);
27207internal_error:
27208    return (-1);
27209}
27210#endif
27211
27212/************************************************************************
27213 *									*
27214 *			SAX validation handlers				*
27215 *									*
27216 ************************************************************************/
27217
27218/*
27219* Process text content.
27220*/
27221static void
27222xmlSchemaSAXHandleText(void *ctx,
27223		       const xmlChar * ch,
27224		       int len)
27225{
27226    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27227
27228    if (vctxt->depth < 0)
27229	return;
27230    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27231	return;
27232    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27233	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27234    if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27235	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27236	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27237	    "calling xmlSchemaVPushText()");
27238	vctxt->err = -1;
27239	xmlStopParser(vctxt->parserCtxt);
27240    }
27241}
27242
27243/*
27244* Process CDATA content.
27245*/
27246static void
27247xmlSchemaSAXHandleCDataSection(void *ctx,
27248			     const xmlChar * ch,
27249			     int len)
27250{
27251    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27252
27253    if (vctxt->depth < 0)
27254	return;
27255    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27256	return;
27257    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27258	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27259    if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27260	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27261	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27262	    "calling xmlSchemaVPushText()");
27263	vctxt->err = -1;
27264	xmlStopParser(vctxt->parserCtxt);
27265    }
27266}
27267
27268static void
27269xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27270			    const xmlChar * name ATTRIBUTE_UNUSED)
27271{
27272    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27273
27274    if (vctxt->depth < 0)
27275	return;
27276    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27277	return;
27278    /* SAX VAL TODO: What to do here? */
27279    TODO
27280}
27281
27282static void
27283xmlSchemaSAXHandleStartElementNs(void *ctx,
27284				 const xmlChar * localname,
27285				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27286				 const xmlChar * URI,
27287				 int nb_namespaces,
27288				 const xmlChar ** namespaces,
27289				 int nb_attributes,
27290				 int nb_defaulted ATTRIBUTE_UNUSED,
27291				 const xmlChar ** attributes)
27292{
27293    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27294    int ret;
27295    xmlSchemaNodeInfoPtr ielem;
27296    int i, j;
27297
27298    /*
27299    * SAX VAL TODO: What to do with nb_defaulted?
27300    */
27301    /*
27302    * Skip elements if inside a "skip" wildcard or invalid.
27303    */
27304    vctxt->depth++;
27305    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27306	return;
27307    /*
27308    * Push the element.
27309    */
27310    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27311	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27312	    "calling xmlSchemaValidatorPushElem()");
27313	goto internal_error;
27314    }
27315    ielem = vctxt->inode;
27316    /*
27317    * TODO: Is this OK?
27318    */
27319    ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27320    ielem->localName = localname;
27321    ielem->nsName = URI;
27322    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27323    /*
27324    * Register namespaces on the elem info.
27325    */
27326    if (nb_namespaces != 0) {
27327	/*
27328	* Although the parser builds its own namespace list,
27329	* we have no access to it, so we'll use an own one.
27330	*/
27331        for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27332	    /*
27333	    * Store prefix and namespace name.
27334	    */
27335	    if (ielem->nsBindings == NULL) {
27336		ielem->nsBindings =
27337		    (const xmlChar **) xmlMalloc(10 *
27338			sizeof(const xmlChar *));
27339		if (ielem->nsBindings == NULL) {
27340		    xmlSchemaVErrMemory(vctxt,
27341			"allocating namespace bindings for SAX validation",
27342			NULL);
27343		    goto internal_error;
27344		}
27345		ielem->nbNsBindings = 0;
27346		ielem->sizeNsBindings = 5;
27347	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27348		ielem->sizeNsBindings *= 2;
27349		ielem->nsBindings =
27350		    (const xmlChar **) xmlRealloc(
27351			(void *) ielem->nsBindings,
27352			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27353		if (ielem->nsBindings == NULL) {
27354		    xmlSchemaVErrMemory(vctxt,
27355			"re-allocating namespace bindings for SAX validation",
27356			NULL);
27357		    goto internal_error;
27358		}
27359	    }
27360
27361	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27362	    if (namespaces[j+1][0] == 0) {
27363		/*
27364		* Handle xmlns="".
27365		*/
27366		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27367	    } else
27368		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27369		    namespaces[j+1];
27370	    ielem->nbNsBindings++;
27371	}
27372    }
27373    /*
27374    * Register attributes.
27375    * SAX VAL TODO: We are not adding namespace declaration
27376    * attributes yet.
27377    */
27378    if (nb_attributes != 0) {
27379	xmlChar *value;
27380
27381        for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27382	    /*
27383	    * Duplicate the value.
27384	    */
27385	    value = xmlStrndup(attributes[j+3],
27386		attributes[j+4] - attributes[j+3]);
27387	    /*
27388	    * TODO: Set the node line.
27389	    */
27390	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27391		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27392		value, 1);
27393	    if (ret == -1) {
27394		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27395		    "calling xmlSchemaValidatorPushAttribute()");
27396		goto internal_error;
27397	    }
27398	}
27399    }
27400    /*
27401    * Validate the element.
27402    */
27403    ret = xmlSchemaValidateElem(vctxt);
27404    if (ret != 0) {
27405	if (ret == -1) {
27406	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27407		"calling xmlSchemaValidateElem()");
27408	    goto internal_error;
27409	}
27410	goto exit;
27411    }
27412
27413exit:
27414    return;
27415internal_error:
27416    vctxt->err = -1;
27417    xmlStopParser(vctxt->parserCtxt);
27418    return;
27419}
27420
27421static void
27422xmlSchemaSAXHandleEndElementNs(void *ctx,
27423			       const xmlChar * localname ATTRIBUTE_UNUSED,
27424			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27425			       const xmlChar * URI ATTRIBUTE_UNUSED)
27426{
27427    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27428    int res;
27429
27430    /*
27431    * Skip elements if inside a "skip" wildcard or if invalid.
27432    */
27433    if (vctxt->skipDepth != -1) {
27434	if (vctxt->depth > vctxt->skipDepth) {
27435	    vctxt->depth--;
27436	    return;
27437	} else
27438	    vctxt->skipDepth = -1;
27439    }
27440    /*
27441    * SAX VAL TODO: Just a temporary check.
27442    */
27443    if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27444	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27445	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27446	    "elem pop mismatch");
27447    }
27448    res = xmlSchemaValidatorPopElem(vctxt);
27449    if (res != 0) {
27450	if (res < 0) {
27451	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27452		"calling xmlSchemaValidatorPopElem()");
27453	    goto internal_error;
27454	}
27455	goto exit;
27456    }
27457exit:
27458    return;
27459internal_error:
27460    vctxt->err = -1;
27461    xmlStopParser(vctxt->parserCtxt);
27462    return;
27463}
27464
27465/************************************************************************
27466 *									*
27467 *			Validation interfaces				*
27468 *									*
27469 ************************************************************************/
27470
27471/**
27472 * xmlSchemaNewValidCtxt:
27473 * @schema:  a precompiled XML Schemas
27474 *
27475 * Create an XML Schemas validation context based on the given schema.
27476 *
27477 * Returns the validation context or NULL in case of error
27478 */
27479xmlSchemaValidCtxtPtr
27480xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27481{
27482    xmlSchemaValidCtxtPtr ret;
27483
27484    ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27485    if (ret == NULL) {
27486        xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27487        return (NULL);
27488    }
27489    memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27490    ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27491    ret->dict = xmlDictCreate();
27492    ret->nodeQNames = xmlSchemaItemListCreate();
27493    ret->schema = schema;
27494    return (ret);
27495}
27496
27497/**
27498 * xmlSchemaValidateSetFilename:
27499 * @vctxt: the schema validation context
27500 * @filename: the file name
27501 *
27502 * Workaround to provide file error reporting information when this is
27503 * not provided by current APIs
27504 */
27505void
27506xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27507    if (vctxt == NULL)
27508        return;
27509    if (vctxt->filename != NULL)
27510        xmlFree(vctxt->filename);
27511    if (filename != NULL)
27512        vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27513    else
27514        vctxt->filename = NULL;
27515}
27516
27517/**
27518 * xmlSchemaClearValidCtxt:
27519 * @vctxt: the schema validation context
27520 *
27521 * Free the resources associated to the schema validation context;
27522 * leaves some fields alive intended for reuse of the context.
27523 */
27524static void
27525xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27526{
27527    if (vctxt == NULL)
27528        return;
27529
27530    /*
27531    * TODO: Should we clear the flags?
27532    *   Might be problematic if one reuses the context
27533    *   and assumes that the options remain the same.
27534    */
27535    vctxt->flags = 0;
27536    vctxt->validationRoot = NULL;
27537    vctxt->doc = NULL;
27538#ifdef LIBXML_READER_ENABLED
27539    vctxt->reader = NULL;
27540#endif
27541    vctxt->hasKeyrefs = 0;
27542
27543    if (vctxt->value != NULL) {
27544        xmlSchemaFreeValue(vctxt->value);
27545	vctxt->value = NULL;
27546    }
27547    /*
27548    * Augmented IDC information.
27549    */
27550    if (vctxt->aidcs != NULL) {
27551	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27552	do {
27553	    next = cur->next;
27554	    xmlFree(cur);
27555	    cur = next;
27556	} while (cur != NULL);
27557	vctxt->aidcs = NULL;
27558    }
27559    if (vctxt->idcMatcherCache != NULL) {
27560	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27561
27562	while (matcher) {
27563	    tmp = matcher;
27564	    matcher = matcher->nextCached;
27565	    xmlSchemaIDCFreeMatcherList(tmp);
27566	}
27567	vctxt->idcMatcherCache = NULL;
27568    }
27569
27570
27571    if (vctxt->idcNodes != NULL) {
27572	int i;
27573	xmlSchemaPSVIIDCNodePtr item;
27574
27575	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27576	    item = vctxt->idcNodes[i];
27577	    xmlFree(item->keys);
27578	    xmlFree(item);
27579	}
27580	xmlFree(vctxt->idcNodes);
27581	vctxt->idcNodes = NULL;
27582	vctxt->nbIdcNodes = 0;
27583	vctxt->sizeIdcNodes = 0;
27584    }
27585    /*
27586    * Note that we won't delete the XPath state pool here.
27587    */
27588    if (vctxt->xpathStates != NULL) {
27589	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27590	vctxt->xpathStates = NULL;
27591    }
27592    /*
27593    * Attribute info.
27594    */
27595    if (vctxt->nbAttrInfos != 0) {
27596	xmlSchemaClearAttrInfos(vctxt);
27597    }
27598    /*
27599    * Element info.
27600    */
27601    if (vctxt->elemInfos != NULL) {
27602	int i;
27603	xmlSchemaNodeInfoPtr ei;
27604
27605	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27606	    ei = vctxt->elemInfos[i];
27607	    if (ei == NULL)
27608		break;
27609	    xmlSchemaClearElemInfo(vctxt, ei);
27610	}
27611    }
27612    xmlSchemaItemListClear(vctxt->nodeQNames);
27613    /* Recreate the dict. */
27614    xmlDictFree(vctxt->dict);
27615    /*
27616    * TODO: Is is save to recreate it? Do we have a scenario
27617    * where the user provides the dict?
27618    */
27619    vctxt->dict = xmlDictCreate();
27620
27621    if (vctxt->filename != NULL) {
27622        xmlFree(vctxt->filename);
27623	vctxt->filename = NULL;
27624    }
27625}
27626
27627/**
27628 * xmlSchemaFreeValidCtxt:
27629 * @ctxt:  the schema validation context
27630 *
27631 * Free the resources associated to the schema validation context
27632 */
27633void
27634xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27635{
27636    if (ctxt == NULL)
27637        return;
27638    if (ctxt->value != NULL)
27639        xmlSchemaFreeValue(ctxt->value);
27640    if (ctxt->pctxt != NULL)
27641	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27642    if (ctxt->idcNodes != NULL) {
27643	int i;
27644	xmlSchemaPSVIIDCNodePtr item;
27645
27646	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27647	    item = ctxt->idcNodes[i];
27648	    xmlFree(item->keys);
27649	    xmlFree(item);
27650	}
27651	xmlFree(ctxt->idcNodes);
27652    }
27653    if (ctxt->idcKeys != NULL) {
27654	int i;
27655	for (i = 0; i < ctxt->nbIdcKeys; i++)
27656	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27657	xmlFree(ctxt->idcKeys);
27658    }
27659
27660    if (ctxt->xpathStates != NULL) {
27661	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27662	ctxt->xpathStates = NULL;
27663    }
27664    if (ctxt->xpathStatePool != NULL) {
27665	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27666	ctxt->xpathStatePool = NULL;
27667    }
27668
27669    /*
27670    * Augmented IDC information.
27671    */
27672    if (ctxt->aidcs != NULL) {
27673	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27674	do {
27675	    next = cur->next;
27676	    xmlFree(cur);
27677	    cur = next;
27678	} while (cur != NULL);
27679    }
27680    if (ctxt->attrInfos != NULL) {
27681	int i;
27682	xmlSchemaAttrInfoPtr attr;
27683
27684	/* Just a paranoid call to the cleanup. */
27685	if (ctxt->nbAttrInfos != 0)
27686	    xmlSchemaClearAttrInfos(ctxt);
27687	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27688	    attr = ctxt->attrInfos[i];
27689	    xmlFree(attr);
27690	}
27691	xmlFree(ctxt->attrInfos);
27692    }
27693    if (ctxt->elemInfos != NULL) {
27694	int i;
27695	xmlSchemaNodeInfoPtr ei;
27696
27697	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27698	    ei = ctxt->elemInfos[i];
27699	    if (ei == NULL)
27700		break;
27701	    xmlSchemaClearElemInfo(ctxt, ei);
27702	    xmlFree(ei);
27703	}
27704	xmlFree(ctxt->elemInfos);
27705    }
27706    if (ctxt->nodeQNames != NULL)
27707	xmlSchemaItemListFree(ctxt->nodeQNames);
27708    if (ctxt->dict != NULL)
27709	xmlDictFree(ctxt->dict);
27710    if (ctxt->filename != NULL)
27711	xmlFree(ctxt->filename);
27712    xmlFree(ctxt);
27713}
27714
27715/**
27716 * xmlSchemaIsValid:
27717 * @ctxt: the schema validation context
27718 *
27719 * Check if any error was detected during validation.
27720 *
27721 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27722 *         of internal error.
27723 */
27724int
27725xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27726{
27727    if (ctxt == NULL)
27728        return(-1);
27729    return(ctxt->err == 0);
27730}
27731
27732/**
27733 * xmlSchemaSetValidErrors:
27734 * @ctxt:  a schema validation context
27735 * @err:  the error function
27736 * @warn: the warning function
27737 * @ctx: the functions context
27738 *
27739 * Set the error and warning callback informations
27740 */
27741void
27742xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27743                        xmlSchemaValidityErrorFunc err,
27744                        xmlSchemaValidityWarningFunc warn, void *ctx)
27745{
27746    if (ctxt == NULL)
27747        return;
27748    ctxt->error = err;
27749    ctxt->warning = warn;
27750    ctxt->errCtxt = ctx;
27751    if (ctxt->pctxt != NULL)
27752	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27753}
27754
27755/**
27756 * xmlSchemaSetValidStructuredErrors:
27757 * @ctxt:  a schema validation context
27758 * @serror:  the structured error function
27759 * @ctx: the functions context
27760 *
27761 * Set the structured error callback
27762 */
27763void
27764xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27765				  xmlStructuredErrorFunc serror, void *ctx)
27766{
27767    if (ctxt == NULL)
27768        return;
27769	ctxt->serror = serror;
27770    ctxt->error = NULL;
27771    ctxt->warning = NULL;
27772    ctxt->errCtxt = ctx;
27773    if (ctxt->pctxt != NULL)
27774	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27775}
27776
27777/**
27778 * xmlSchemaGetValidErrors:
27779 * @ctxt: a XML-Schema validation context
27780 * @err: the error function result
27781 * @warn: the warning function result
27782 * @ctx: the functions context result
27783 *
27784 * Get the error and warning callback informations
27785 *
27786 * Returns -1 in case of error and 0 otherwise
27787 */
27788int
27789xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27790			xmlSchemaValidityErrorFunc * err,
27791			xmlSchemaValidityWarningFunc * warn, void **ctx)
27792{
27793	if (ctxt == NULL)
27794		return (-1);
27795	if (err != NULL)
27796		*err = ctxt->error;
27797	if (warn != NULL)
27798		*warn = ctxt->warning;
27799	if (ctx != NULL)
27800		*ctx = ctxt->errCtxt;
27801	return (0);
27802}
27803
27804
27805/**
27806 * xmlSchemaSetValidOptions:
27807 * @ctxt:	a schema validation context
27808 * @options: a combination of xmlSchemaValidOption
27809 *
27810 * Sets the options to be used during the validation.
27811 *
27812 * Returns 0 in case of success, -1 in case of an
27813 * API error.
27814 */
27815int
27816xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27817			 int options)
27818
27819{
27820    int i;
27821
27822    if (ctxt == NULL)
27823	return (-1);
27824    /*
27825    * WARNING: Change the start value if adding to the
27826    * xmlSchemaValidOption.
27827    * TODO: Is there an other, more easy to maintain,
27828    * way?
27829    */
27830    for (i = 1; i < (int) sizeof(int) * 8; i++) {
27831        if (options & 1<<i)
27832	    return (-1);
27833    }
27834    ctxt->options = options;
27835    return (0);
27836}
27837
27838/**
27839 * xmlSchemaValidCtxtGetOptions:
27840 * @ctxt: a schema validation context
27841 *
27842 * Get the validation context options.
27843 *
27844 * Returns the option combination or -1 on error.
27845 */
27846int
27847xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27848
27849{
27850    if (ctxt == NULL)
27851	return (-1);
27852    else
27853	return (ctxt->options);
27854}
27855
27856static int
27857xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27858{
27859    xmlAttrPtr attr;
27860    int ret = 0;
27861    xmlSchemaNodeInfoPtr ielem = NULL;
27862    xmlNodePtr node, valRoot;
27863    const xmlChar *nsName;
27864
27865    /* DOC VAL TODO: Move this to the start function. */
27866    if (vctxt->validationRoot != NULL)
27867        valRoot = vctxt->validationRoot;
27868    else
27869	valRoot = xmlDocGetRootElement(vctxt->doc);
27870    if (valRoot == NULL) {
27871	/* VAL TODO: Error code? */
27872	VERROR(1, NULL, "The document has no document element");
27873	return (1);
27874    }
27875    vctxt->depth = -1;
27876    vctxt->validationRoot = valRoot;
27877    node = valRoot;
27878    while (node != NULL) {
27879	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27880	    goto next_sibling;
27881	if (node->type == XML_ELEMENT_NODE) {
27882
27883	    /*
27884	    * Init the node-info.
27885	    */
27886	    vctxt->depth++;
27887	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27888		goto internal_error;
27889	    ielem = vctxt->inode;
27890	    ielem->node = node;
27891	    ielem->nodeLine = node->line;
27892	    ielem->localName = node->name;
27893	    if (node->ns != NULL)
27894		ielem->nsName = node->ns->href;
27895	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27896	    /*
27897	    * Register attributes.
27898	    * DOC VAL TODO: We do not register namespace declaration
27899	    * attributes yet.
27900	    */
27901	    vctxt->nbAttrInfos = 0;
27902	    if (node->properties != NULL) {
27903		attr = node->properties;
27904		do {
27905		    if (attr->ns != NULL)
27906			nsName = attr->ns->href;
27907		    else
27908			nsName = NULL;
27909		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27910			(xmlNodePtr) attr,
27911			/*
27912			* Note that we give it the line number of the
27913			* parent element.
27914			*/
27915			ielem->nodeLine,
27916			attr->name, nsName, 0,
27917			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27918		    if (ret == -1) {
27919			VERROR_INT("xmlSchemaDocWalk",
27920			    "calling xmlSchemaValidatorPushAttribute()");
27921			goto internal_error;
27922		    }
27923		    attr = attr->next;
27924		} while (attr);
27925	    }
27926	    /*
27927	    * Validate the element.
27928	    */
27929	    ret = xmlSchemaValidateElem(vctxt);
27930	    if (ret != 0) {
27931		if (ret == -1) {
27932		    VERROR_INT("xmlSchemaDocWalk",
27933			"calling xmlSchemaValidateElem()");
27934		    goto internal_error;
27935		}
27936		/*
27937		* Don't stop validation; just skip the content
27938		* of this element.
27939		*/
27940		goto leave_node;
27941	    }
27942	    if ((vctxt->skipDepth != -1) &&
27943		(vctxt->depth >= vctxt->skipDepth))
27944		goto leave_node;
27945	} else if ((node->type == XML_TEXT_NODE) ||
27946	    (node->type == XML_CDATA_SECTION_NODE)) {
27947	    /*
27948	    * Process character content.
27949	    */
27950	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27951		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27952	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27953		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27954	    if (ret < 0) {
27955		VERROR_INT("xmlSchemaVDocWalk",
27956		    "calling xmlSchemaVPushText()");
27957		goto internal_error;
27958	    }
27959	    /*
27960	    * DOC VAL TODO: Should we skip further validation of the
27961	    * element content here?
27962	    */
27963	} else if ((node->type == XML_ENTITY_NODE) ||
27964	    (node->type == XML_ENTITY_REF_NODE)) {
27965	    /*
27966	    * DOC VAL TODO: What to do with entities?
27967	    */
27968	    VERROR_INT("xmlSchemaVDocWalk",
27969		"there is at least one entity reference in the node-tree "
27970		"currently being validated. Processing of entities with "
27971		"this XML Schema processor is not supported (yet). Please "
27972		"substitute entities before validation.");
27973	    goto internal_error;
27974	} else {
27975	    goto leave_node;
27976	    /*
27977	    * DOC VAL TODO: XInclude nodes, etc.
27978	    */
27979	}
27980	/*
27981	* Walk the doc.
27982	*/
27983	if (node->children != NULL) {
27984	    node = node->children;
27985	    continue;
27986	}
27987leave_node:
27988	if (node->type == XML_ELEMENT_NODE) {
27989	    /*
27990	    * Leaving the scope of an element.
27991	    */
27992	    if (node != vctxt->inode->node) {
27993		VERROR_INT("xmlSchemaVDocWalk",
27994		    "element position mismatch");
27995		goto internal_error;
27996	    }
27997	    ret = xmlSchemaValidatorPopElem(vctxt);
27998	    if (ret != 0) {
27999		if (ret < 0) {
28000		    VERROR_INT("xmlSchemaVDocWalk",
28001			"calling xmlSchemaValidatorPopElem()");
28002		    goto internal_error;
28003		}
28004	    }
28005	    if (node == valRoot)
28006		goto exit;
28007	}
28008next_sibling:
28009	if (node->next != NULL)
28010	    node = node->next;
28011	else {
28012	    node = node->parent;
28013	    goto leave_node;
28014	}
28015    }
28016
28017exit:
28018    return (ret);
28019internal_error:
28020    return (-1);
28021}
28022
28023static int
28024xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28025    /*
28026    * Some initialization.
28027    */
28028    vctxt->err = 0;
28029    vctxt->nberrors = 0;
28030    vctxt->depth = -1;
28031    vctxt->skipDepth = -1;
28032    vctxt->xsiAssemble = 0;
28033    vctxt->hasKeyrefs = 0;
28034#ifdef ENABLE_IDC_NODE_TABLES_TEST
28035    vctxt->createIDCNodeTables = 1;
28036#else
28037    vctxt->createIDCNodeTables = 0;
28038#endif
28039    /*
28040    * Create a schema + parser if necessary.
28041    */
28042    if (vctxt->schema == NULL) {
28043	xmlSchemaParserCtxtPtr pctxt;
28044
28045	vctxt->xsiAssemble = 1;
28046	/*
28047	* If not schema was given then we will create a schema
28048	* dynamically using XSI schema locations.
28049	*
28050	* Create the schema parser context.
28051	*/
28052	if ((vctxt->pctxt == NULL) &&
28053	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28054	   return (-1);
28055	pctxt = vctxt->pctxt;
28056	pctxt->xsiAssemble = 1;
28057	/*
28058	* Create the schema.
28059	*/
28060	vctxt->schema = xmlSchemaNewSchema(pctxt);
28061	if (vctxt->schema == NULL)
28062	    return (-1);
28063	/*
28064	* Create the schema construction context.
28065	*/
28066	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28067	if (pctxt->constructor == NULL)
28068	    return(-1);
28069	pctxt->constructor->mainSchema = vctxt->schema;
28070	/*
28071	* Take ownership of the constructor to be able to free it.
28072	*/
28073	pctxt->ownsConstructor = 1;
28074    }
28075    /*
28076    * Augment the IDC definitions for the main schema and all imported ones
28077    * NOTE: main schema if the first in the imported list
28078    */
28079    xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28080
28081    return(0);
28082}
28083
28084static void
28085xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28086    if (vctxt->xsiAssemble) {
28087	if (vctxt->schema != NULL) {
28088	    xmlSchemaFree(vctxt->schema);
28089	    vctxt->schema = NULL;
28090	}
28091    }
28092    xmlSchemaClearValidCtxt(vctxt);
28093}
28094
28095static int
28096xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28097{
28098    int ret = 0;
28099
28100    if (xmlSchemaPreRun(vctxt) < 0)
28101        return(-1);
28102
28103    if (vctxt->doc != NULL) {
28104	/*
28105	 * Tree validation.
28106	 */
28107	ret = xmlSchemaVDocWalk(vctxt);
28108#ifdef LIBXML_READER_ENABLED
28109    } else if (vctxt->reader != NULL) {
28110	/*
28111	 * XML Reader validation.
28112	 */
28113#ifdef XML_SCHEMA_READER_ENABLED
28114	ret = xmlSchemaVReaderWalk(vctxt);
28115#endif
28116#endif
28117    } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28118	/*
28119	 * SAX validation.
28120	 */
28121	ret = xmlParseDocument(vctxt->parserCtxt);
28122    } else {
28123	VERROR_INT("xmlSchemaVStart",
28124	    "no instance to validate");
28125	ret = -1;
28126    }
28127
28128    xmlSchemaPostRun(vctxt);
28129    if (ret == 0)
28130	ret = vctxt->err;
28131    return (ret);
28132}
28133
28134/**
28135 * xmlSchemaValidateOneElement:
28136 * @ctxt:  a schema validation context
28137 * @elem:  an element node
28138 *
28139 * Validate a branch of a tree, starting with the given @elem.
28140 *
28141 * Returns 0 if the element and its subtree is valid, a positive error
28142 * code number otherwise and -1 in case of an internal or API error.
28143 */
28144int
28145xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28146{
28147    if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28148	return (-1);
28149
28150    if (ctxt->schema == NULL)
28151	return (-1);
28152
28153    ctxt->doc = elem->doc;
28154    ctxt->node = elem;
28155    ctxt->validationRoot = elem;
28156    return(xmlSchemaVStart(ctxt));
28157}
28158
28159/**
28160 * xmlSchemaValidateDoc:
28161 * @ctxt:  a schema validation context
28162 * @doc:  a parsed document tree
28163 *
28164 * Validate a document tree in memory.
28165 *
28166 * Returns 0 if the document is schemas valid, a positive error code
28167 *     number otherwise and -1 in case of internal or API error.
28168 */
28169int
28170xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28171{
28172    if ((ctxt == NULL) || (doc == NULL))
28173        return (-1);
28174
28175    ctxt->doc = doc;
28176    ctxt->node = xmlDocGetRootElement(doc);
28177    if (ctxt->node == NULL) {
28178        xmlSchemaCustomErr(ACTXT_CAST ctxt,
28179	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28180	    (xmlNodePtr) doc, NULL,
28181	    "The document has no document element", NULL, NULL);
28182        return (ctxt->err);
28183    }
28184    ctxt->validationRoot = ctxt->node;
28185    return (xmlSchemaVStart(ctxt));
28186}
28187
28188
28189/************************************************************************
28190 *									*
28191 *		Function and data for SAX streaming API			*
28192 *									*
28193 ************************************************************************/
28194typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28195typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28196
28197struct _xmlSchemaSplitSAXData {
28198    xmlSAXHandlerPtr      user_sax;
28199    void                 *user_data;
28200    xmlSchemaValidCtxtPtr ctxt;
28201    xmlSAXHandlerPtr      schemas_sax;
28202};
28203
28204#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28205
28206struct _xmlSchemaSAXPlug {
28207    unsigned int magic;
28208
28209    /* the original callbacks informations */
28210    xmlSAXHandlerPtr     *user_sax_ptr;
28211    xmlSAXHandlerPtr      user_sax;
28212    void                **user_data_ptr;
28213    void                 *user_data;
28214
28215    /* the block plugged back and validation informations */
28216    xmlSAXHandler         schemas_sax;
28217    xmlSchemaValidCtxtPtr ctxt;
28218};
28219
28220/* All those functions just bounces to the user provided SAX handlers */
28221static void
28222internalSubsetSplit(void *ctx, const xmlChar *name,
28223	       const xmlChar *ExternalID, const xmlChar *SystemID)
28224{
28225    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28226    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28227        (ctxt->user_sax->internalSubset != NULL))
28228	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28229	                               SystemID);
28230}
28231
28232static int
28233isStandaloneSplit(void *ctx)
28234{
28235    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28236    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28237        (ctxt->user_sax->isStandalone != NULL))
28238	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28239    return(0);
28240}
28241
28242static int
28243hasInternalSubsetSplit(void *ctx)
28244{
28245    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28246    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28247        (ctxt->user_sax->hasInternalSubset != NULL))
28248	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28249    return(0);
28250}
28251
28252static int
28253hasExternalSubsetSplit(void *ctx)
28254{
28255    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28256    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28257        (ctxt->user_sax->hasExternalSubset != NULL))
28258	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28259    return(0);
28260}
28261
28262static void
28263externalSubsetSplit(void *ctx, const xmlChar *name,
28264	       const xmlChar *ExternalID, const xmlChar *SystemID)
28265{
28266    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28267    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28268        (ctxt->user_sax->externalSubset != NULL))
28269	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28270	                               SystemID);
28271}
28272
28273static xmlParserInputPtr
28274resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28275{
28276    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28277    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28278        (ctxt->user_sax->resolveEntity != NULL))
28279	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28280	                                     systemId));
28281    return(NULL);
28282}
28283
28284static xmlEntityPtr
28285getEntitySplit(void *ctx, const xmlChar *name)
28286{
28287    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28288    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28289        (ctxt->user_sax->getEntity != NULL))
28290	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28291    return(NULL);
28292}
28293
28294static xmlEntityPtr
28295getParameterEntitySplit(void *ctx, const xmlChar *name)
28296{
28297    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28298    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28299        (ctxt->user_sax->getParameterEntity != NULL))
28300	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28301    return(NULL);
28302}
28303
28304
28305static void
28306entityDeclSplit(void *ctx, const xmlChar *name, int type,
28307          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28308{
28309    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28310    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28311        (ctxt->user_sax->entityDecl != NULL))
28312	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28313	                           systemId, content);
28314}
28315
28316static void
28317attributeDeclSplit(void *ctx, const xmlChar * elem,
28318                   const xmlChar * name, int type, int def,
28319                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
28320{
28321    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28322    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28323        (ctxt->user_sax->attributeDecl != NULL)) {
28324	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28325	                              def, defaultValue, tree);
28326    } else {
28327	xmlFreeEnumeration(tree);
28328    }
28329}
28330
28331static void
28332elementDeclSplit(void *ctx, const xmlChar *name, int type,
28333	    xmlElementContentPtr content)
28334{
28335    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28336    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28337        (ctxt->user_sax->elementDecl != NULL))
28338	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28339}
28340
28341static void
28342notationDeclSplit(void *ctx, const xmlChar *name,
28343	     const xmlChar *publicId, const xmlChar *systemId)
28344{
28345    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28346    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28347        (ctxt->user_sax->notationDecl != NULL))
28348	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28349	                             systemId);
28350}
28351
28352static void
28353unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28354		   const xmlChar *publicId, const xmlChar *systemId,
28355		   const xmlChar *notationName)
28356{
28357    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28358    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28359        (ctxt->user_sax->unparsedEntityDecl != NULL))
28360	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28361	                                   systemId, notationName);
28362}
28363
28364static void
28365setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28366{
28367    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28368    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28369        (ctxt->user_sax->setDocumentLocator != NULL))
28370	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28371}
28372
28373static void
28374startDocumentSplit(void *ctx)
28375{
28376    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28377    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28378        (ctxt->user_sax->startDocument != NULL))
28379	ctxt->user_sax->startDocument(ctxt->user_data);
28380}
28381
28382static void
28383endDocumentSplit(void *ctx)
28384{
28385    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28386    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28387        (ctxt->user_sax->endDocument != NULL))
28388	ctxt->user_sax->endDocument(ctxt->user_data);
28389}
28390
28391static void
28392processingInstructionSplit(void *ctx, const xmlChar *target,
28393                      const xmlChar *data)
28394{
28395    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28396    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28397        (ctxt->user_sax->processingInstruction != NULL))
28398	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28399}
28400
28401static void
28402commentSplit(void *ctx, const xmlChar *value)
28403{
28404    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28405    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28406        (ctxt->user_sax->comment != NULL))
28407	ctxt->user_sax->comment(ctxt->user_data, value);
28408}
28409
28410/*
28411 * Varargs error callbacks to the user application, harder ...
28412 */
28413
28414static void XMLCDECL
28415warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28416    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28417    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28418        (ctxt->user_sax->warning != NULL)) {
28419	TODO
28420    }
28421}
28422static void XMLCDECL
28423errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28424    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28425    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28426        (ctxt->user_sax->error != NULL)) {
28427	TODO
28428    }
28429}
28430static void XMLCDECL
28431fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28432    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28433    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28434        (ctxt->user_sax->fatalError != NULL)) {
28435	TODO
28436    }
28437}
28438
28439/*
28440 * Those are function where both the user handler and the schemas handler
28441 * need to be called.
28442 */
28443static void
28444charactersSplit(void *ctx, const xmlChar *ch, int len)
28445{
28446    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28447    if (ctxt == NULL)
28448        return;
28449    if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28450	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28451    if (ctxt->ctxt != NULL)
28452	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28453}
28454
28455static void
28456ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28457{
28458    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28459    if (ctxt == NULL)
28460        return;
28461    if ((ctxt->user_sax != NULL) &&
28462        (ctxt->user_sax->ignorableWhitespace != NULL))
28463	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28464    if (ctxt->ctxt != NULL)
28465	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28466}
28467
28468static void
28469cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28470{
28471    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28472    if (ctxt == NULL)
28473        return;
28474    if ((ctxt->user_sax != NULL) &&
28475        (ctxt->user_sax->cdataBlock != NULL))
28476	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28477    if (ctxt->ctxt != NULL)
28478	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28479}
28480
28481static void
28482referenceSplit(void *ctx, const xmlChar *name)
28483{
28484    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28485    if (ctxt == NULL)
28486        return;
28487    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28488        (ctxt->user_sax->reference != NULL))
28489	ctxt->user_sax->reference(ctxt->user_data, name);
28490    if (ctxt->ctxt != NULL)
28491        xmlSchemaSAXHandleReference(ctxt->user_data, name);
28492}
28493
28494static void
28495startElementNsSplit(void *ctx, const xmlChar * localname,
28496		    const xmlChar * prefix, const xmlChar * URI,
28497		    int nb_namespaces, const xmlChar ** namespaces,
28498		    int nb_attributes, int nb_defaulted,
28499		    const xmlChar ** attributes) {
28500    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28501    if (ctxt == NULL)
28502        return;
28503    if ((ctxt->user_sax != NULL) &&
28504        (ctxt->user_sax->startElementNs != NULL))
28505	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28506	                               URI, nb_namespaces, namespaces,
28507				       nb_attributes, nb_defaulted,
28508				       attributes);
28509    if (ctxt->ctxt != NULL)
28510	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28511	                                 URI, nb_namespaces, namespaces,
28512					 nb_attributes, nb_defaulted,
28513					 attributes);
28514}
28515
28516static void
28517endElementNsSplit(void *ctx, const xmlChar * localname,
28518		    const xmlChar * prefix, const xmlChar * URI) {
28519    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28520    if (ctxt == NULL)
28521        return;
28522    if ((ctxt->user_sax != NULL) &&
28523        (ctxt->user_sax->endElementNs != NULL))
28524	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28525    if (ctxt->ctxt != NULL)
28526	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28527}
28528
28529/**
28530 * xmlSchemaSAXPlug:
28531 * @ctxt:  a schema validation context
28532 * @sax:  a pointer to the original xmlSAXHandlerPtr
28533 * @user_data:  a pointer to the original SAX user data pointer
28534 *
28535 * Plug a SAX based validation layer in a SAX parsing event flow.
28536 * The original @saxptr and @dataptr data are replaced by new pointers
28537 * but the calls to the original will be maintained.
28538 *
28539 * Returns a pointer to a data structure needed to unplug the validation layer
28540 *         or NULL in case of errors.
28541 */
28542xmlSchemaSAXPlugPtr
28543xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28544		 xmlSAXHandlerPtr *sax, void **user_data)
28545{
28546    xmlSchemaSAXPlugPtr ret;
28547    xmlSAXHandlerPtr old_sax;
28548
28549    if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28550        return(NULL);
28551
28552    /*
28553     * We only allow to plug into SAX2 event streams
28554     */
28555    old_sax = *sax;
28556    if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28557        return(NULL);
28558    if ((old_sax != NULL) &&
28559        (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28560        ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28561        return(NULL);
28562
28563    /*
28564     * everything seems right allocate the local data needed for that layer
28565     */
28566    ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28567    if (ret == NULL) {
28568        return(NULL);
28569    }
28570    memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28571    ret->magic = XML_SAX_PLUG_MAGIC;
28572    ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28573    ret->ctxt = ctxt;
28574    ret->user_sax_ptr = sax;
28575    ret->user_sax = old_sax;
28576    if (old_sax == NULL) {
28577        /*
28578	 * go direct, no need for the split block and functions.
28579	 */
28580	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28581	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28582	/*
28583	 * Note that we use the same text-function for both, to prevent
28584	 * the parser from testing for ignorable whitespace.
28585	 */
28586	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28587	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28588
28589	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28590	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28591
28592	ret->user_data = ctxt;
28593	*user_data = ctxt;
28594    } else {
28595       /*
28596        * for each callback unused by Schemas initialize it to the Split
28597	* routine only if non NULL in the user block, this can speed up
28598	* things at the SAX level.
28599	*/
28600        if (old_sax->internalSubset != NULL)
28601            ret->schemas_sax.internalSubset = internalSubsetSplit;
28602        if (old_sax->isStandalone != NULL)
28603            ret->schemas_sax.isStandalone = isStandaloneSplit;
28604        if (old_sax->hasInternalSubset != NULL)
28605            ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28606        if (old_sax->hasExternalSubset != NULL)
28607            ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28608        if (old_sax->resolveEntity != NULL)
28609            ret->schemas_sax.resolveEntity = resolveEntitySplit;
28610        if (old_sax->getEntity != NULL)
28611            ret->schemas_sax.getEntity = getEntitySplit;
28612        if (old_sax->entityDecl != NULL)
28613            ret->schemas_sax.entityDecl = entityDeclSplit;
28614        if (old_sax->notationDecl != NULL)
28615            ret->schemas_sax.notationDecl = notationDeclSplit;
28616        if (old_sax->attributeDecl != NULL)
28617            ret->schemas_sax.attributeDecl = attributeDeclSplit;
28618        if (old_sax->elementDecl != NULL)
28619            ret->schemas_sax.elementDecl = elementDeclSplit;
28620        if (old_sax->unparsedEntityDecl != NULL)
28621            ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28622        if (old_sax->setDocumentLocator != NULL)
28623            ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28624        if (old_sax->startDocument != NULL)
28625            ret->schemas_sax.startDocument = startDocumentSplit;
28626        if (old_sax->endDocument != NULL)
28627            ret->schemas_sax.endDocument = endDocumentSplit;
28628        if (old_sax->processingInstruction != NULL)
28629            ret->schemas_sax.processingInstruction = processingInstructionSplit;
28630        if (old_sax->comment != NULL)
28631            ret->schemas_sax.comment = commentSplit;
28632        if (old_sax->warning != NULL)
28633            ret->schemas_sax.warning = warningSplit;
28634        if (old_sax->error != NULL)
28635            ret->schemas_sax.error = errorSplit;
28636        if (old_sax->fatalError != NULL)
28637            ret->schemas_sax.fatalError = fatalErrorSplit;
28638        if (old_sax->getParameterEntity != NULL)
28639            ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28640        if (old_sax->externalSubset != NULL)
28641            ret->schemas_sax.externalSubset = externalSubsetSplit;
28642
28643	/*
28644	 * the 6 schemas callback have to go to the splitter functions
28645	 * Note that we use the same text-function for ignorableWhitespace
28646	 * if possible, to prevent the parser from testing for ignorable
28647	 * whitespace.
28648	 */
28649        ret->schemas_sax.characters = charactersSplit;
28650	if ((old_sax->ignorableWhitespace != NULL) &&
28651	    (old_sax->ignorableWhitespace != old_sax->characters))
28652	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28653	else
28654	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28655        ret->schemas_sax.cdataBlock = cdataBlockSplit;
28656        ret->schemas_sax.reference = referenceSplit;
28657        ret->schemas_sax.startElementNs = startElementNsSplit;
28658        ret->schemas_sax.endElementNs = endElementNsSplit;
28659
28660	ret->user_data_ptr = user_data;
28661	ret->user_data = *user_data;
28662	*user_data = ret;
28663    }
28664
28665    /*
28666     * plug the pointers back.
28667     */
28668    *sax = &(ret->schemas_sax);
28669    ctxt->sax = *sax;
28670    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28671    xmlSchemaPreRun(ctxt);
28672    return(ret);
28673}
28674
28675/**
28676 * xmlSchemaSAXUnplug:
28677 * @plug:  a data structure returned by xmlSchemaSAXPlug
28678 *
28679 * Unplug a SAX based validation layer in a SAX parsing event flow.
28680 * The original pointers used in the call are restored.
28681 *
28682 * Returns 0 in case of success and -1 in case of failure.
28683 */
28684int
28685xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28686{
28687    xmlSAXHandlerPtr *sax;
28688    void **user_data;
28689
28690    if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28691        return(-1);
28692    plug->magic = 0;
28693
28694    xmlSchemaPostRun(plug->ctxt);
28695    /* restore the data */
28696    sax = plug->user_sax_ptr;
28697    *sax = plug->user_sax;
28698    if (plug->user_sax != NULL) {
28699	user_data = plug->user_data_ptr;
28700	*user_data = plug->user_data;
28701    }
28702
28703    /* free and return */
28704    xmlFree(plug);
28705    return(0);
28706}
28707
28708/**
28709 * xmlSchemaValidateSetLocator:
28710 * @vctxt: a schema validation context
28711 * @f: the locator function pointer
28712 * @ctxt: the locator context
28713 *
28714 * Allows to set a locator function to the validation context,
28715 * which will be used to provide file and line information since
28716 * those are not provided as part of the SAX validation flow
28717 * Setting @f to NULL disable the locator.
28718 */
28719
28720void
28721xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28722                            xmlSchemaValidityLocatorFunc f,
28723			    void *ctxt)
28724{
28725    if (vctxt == NULL) return;
28726    vctxt->locFunc = f;
28727    vctxt->locCtxt = ctxt;
28728}
28729
28730/**
28731 * xmlSchemaValidateStreamLocator:
28732 * @ctx: the xmlTextReaderPtr used
28733 * @file: returned file information
28734 * @line: returned line information
28735 *
28736 * Internal locator function for the readers
28737 *
28738 * Returns 0 in case the Schema validation could be (des)activated and
28739 *         -1 in case of error.
28740 */
28741static int
28742xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28743                               unsigned long *line) {
28744    xmlParserCtxtPtr ctxt;
28745
28746    if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28747        return(-1);
28748
28749    if (file != NULL)
28750        *file = NULL;
28751    if (line != NULL)
28752        *line = 0;
28753
28754    ctxt = (xmlParserCtxtPtr) ctx;
28755    if (ctxt->input != NULL) {
28756       if (file != NULL)
28757           *file = ctxt->input->filename;
28758       if (line != NULL)
28759           *line = ctxt->input->line;
28760       return(0);
28761    }
28762    return(-1);
28763}
28764
28765/**
28766 * xmlSchemaValidateStream:
28767 * @ctxt:  a schema validation context
28768 * @input:  the input to use for reading the data
28769 * @enc:  an optional encoding information
28770 * @sax:  a SAX handler for the resulting events
28771 * @user_data:  the context to provide to the SAX handler.
28772 *
28773 * Validate an input based on a flow of SAX event from the parser
28774 * and forward the events to the @sax handler with the provided @user_data
28775 * the user provided @sax handler must be a SAX2 one.
28776 *
28777 * Returns 0 if the document is schemas valid, a positive error code
28778 *     number otherwise and -1 in case of internal or API error.
28779 */
28780int
28781xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28782                        xmlParserInputBufferPtr input, xmlCharEncoding enc,
28783                        xmlSAXHandlerPtr sax, void *user_data)
28784{
28785    xmlSchemaSAXPlugPtr plug = NULL;
28786    xmlSAXHandlerPtr old_sax = NULL;
28787    xmlParserCtxtPtr pctxt = NULL;
28788    xmlParserInputPtr inputStream = NULL;
28789    int ret;
28790
28791    if ((ctxt == NULL) || (input == NULL))
28792        return (-1);
28793
28794    /*
28795     * prepare the parser
28796     */
28797    pctxt = xmlNewParserCtxt();
28798    if (pctxt == NULL)
28799        return (-1);
28800    old_sax = pctxt->sax;
28801    pctxt->sax = sax;
28802    pctxt->userData = user_data;
28803#if 0
28804    if (options)
28805        xmlCtxtUseOptions(pctxt, options);
28806#endif
28807    pctxt->linenumbers = 1;
28808    xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28809
28810    inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28811    if (inputStream == NULL) {
28812        ret = -1;
28813	goto done;
28814    }
28815    inputPush(pctxt, inputStream);
28816    ctxt->parserCtxt = pctxt;
28817    ctxt->input = input;
28818
28819    /*
28820     * Plug the validation and launch the parsing
28821     */
28822    plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28823    if (plug == NULL) {
28824        ret = -1;
28825	goto done;
28826    }
28827    ctxt->input = input;
28828    ctxt->enc = enc;
28829    ctxt->sax = pctxt->sax;
28830    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28831    ret = xmlSchemaVStart(ctxt);
28832
28833    if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28834	ret = ctxt->parserCtxt->errNo;
28835	if (ret == 0)
28836	    ret = 1;
28837    }
28838
28839done:
28840    ctxt->parserCtxt = NULL;
28841    ctxt->sax = NULL;
28842    ctxt->input = NULL;
28843    if (plug != NULL) {
28844        xmlSchemaSAXUnplug(plug);
28845    }
28846    /* cleanup */
28847    if (pctxt != NULL) {
28848	pctxt->sax = old_sax;
28849	xmlFreeParserCtxt(pctxt);
28850    }
28851    return (ret);
28852}
28853
28854/**
28855 * xmlSchemaValidateFile:
28856 * @ctxt: a schema validation context
28857 * @filename: the URI of the instance
28858 * @options: a future set of options, currently unused
28859 *
28860 * Do a schemas validation of the given resource, it will use the
28861 * SAX streamable validation internally.
28862 *
28863 * Returns 0 if the document is valid, a positive error code
28864 *     number otherwise and -1 in case of an internal or API error.
28865 */
28866int
28867xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28868                      const char * filename,
28869		      int options ATTRIBUTE_UNUSED)
28870{
28871    int ret;
28872    xmlParserInputBufferPtr input;
28873
28874    if ((ctxt == NULL) || (filename == NULL))
28875        return (-1);
28876
28877    input = xmlParserInputBufferCreateFilename(filename,
28878	XML_CHAR_ENCODING_NONE);
28879    if (input == NULL)
28880	return (-1);
28881    ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28882	NULL, NULL);
28883    return (ret);
28884}
28885
28886/**
28887 * xmlSchemaValidCtxtGetParserCtxt:
28888 * @ctxt: a schema validation context
28889 *
28890 * allow access to the parser context of the schema validation context
28891 *
28892 * Returns the parser context of the schema validation context or NULL
28893 *         in case of error.
28894 */
28895xmlParserCtxtPtr
28896xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28897{
28898    if (ctxt == NULL)
28899        return(NULL);
28900    return (ctxt->parserCtxt);
28901}
28902
28903#define bottom_xmlschemas
28904#include "elfgcchack.h"
28905#endif /* LIBXML_SCHEMAS_ENABLED */
28906