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
979    int err;
980    int nberrors;
981
982    xmlNodePtr node;
983    xmlNodePtr cur;
984    /* xmlSchemaTypePtr type; */
985
986    xmlRegExecCtxtPtr regexp;
987    xmlSchemaValPtr value;
988
989    int valueWS;
990    int options;
991    xmlNodePtr validationRoot;
992    xmlSchemaParserCtxtPtr pctxt;
993    int xsiAssemble;
994
995    int depth;
996    xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
997    int sizeElemInfos;
998    xmlSchemaNodeInfoPtr inode; /* the current element information */
999
1000    xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1001
1002    xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1003    xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1004    xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1005
1006    xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1007    int nbIdcNodes;
1008    int sizeIdcNodes;
1009
1010    xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1011    int nbIdcKeys;
1012    int sizeIdcKeys;
1013
1014    int flags;
1015
1016    xmlDictPtr dict;
1017
1018#ifdef LIBXML_READER_ENABLED
1019    xmlTextReaderPtr reader;
1020#endif
1021
1022    xmlSchemaAttrInfoPtr *attrInfos;
1023    int nbAttrInfos;
1024    int sizeAttrInfos;
1025
1026    int skipDepth;
1027    xmlSchemaItemListPtr nodeQNames;
1028    int hasKeyrefs;
1029    int createIDCNodeTables;
1030    int psviExposeIDCNodeTables;
1031};
1032
1033/**
1034 * xmlSchemaSubstGroup:
1035 *
1036 *
1037 */
1038typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1039typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1040struct _xmlSchemaSubstGroup {
1041    xmlSchemaElementPtr head;
1042    xmlSchemaItemListPtr members;
1043};
1044
1045/************************************************************************
1046 * 									*
1047 * 			Some predeclarations				*
1048 * 									*
1049 ************************************************************************/
1050
1051static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1052                                 xmlSchemaPtr schema,
1053                                 xmlNodePtr node);
1054static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1055                                 xmlSchemaPtr schema,
1056                                 xmlNodePtr node);
1057static int
1058xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1059                   xmlSchemaAbstractCtxtPtr ctxt);
1060static const xmlChar *
1061xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1062static int
1063xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1064                     xmlNodePtr node);
1065static int
1066xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1067                       xmlSchemaParserCtxtPtr ctxt);
1068static void
1069xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1070static xmlSchemaWhitespaceValueType
1071xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1072static xmlSchemaTreeItemPtr
1073xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1074			 xmlNodePtr node, xmlSchemaTypeType type,
1075			 int withParticle);
1076static const xmlChar *
1077xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1078static xmlSchemaTypeLinkPtr
1079xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1080static void
1081xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1082		     const char *funcName,
1083		     const char *message);
1084static int
1085xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1086			     xmlSchemaTypePtr type,
1087			     xmlSchemaTypePtr baseType,
1088			     int subset);
1089static void
1090xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1091				   xmlSchemaParserCtxtPtr ctxt);
1092static void
1093xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1094static xmlSchemaQNameRefPtr
1095xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1096				xmlSchemaPtr schema,
1097				xmlNodePtr node);
1098
1099/************************************************************************
1100 *									*
1101 * 			Helper functions			        *
1102 *									*
1103 ************************************************************************/
1104
1105/**
1106 * xmlSchemaItemTypeToStr:
1107 * @type: the type of the schema item
1108 *
1109 * Returns the component name of a schema item.
1110 */
1111static const xmlChar *
1112xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1113{
1114    switch (type) {
1115	case XML_SCHEMA_TYPE_BASIC:
1116	    return(BAD_CAST "simple type definition");
1117	case XML_SCHEMA_TYPE_SIMPLE:
1118	    return(BAD_CAST "simple type definition");
1119	case XML_SCHEMA_TYPE_COMPLEX:
1120	    return(BAD_CAST "complex type definition");
1121	case XML_SCHEMA_TYPE_ELEMENT:
1122	    return(BAD_CAST "element declaration");
1123	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1124	    return(BAD_CAST "attribute use");
1125	case XML_SCHEMA_TYPE_ATTRIBUTE:
1126	    return(BAD_CAST "attribute declaration");
1127	case XML_SCHEMA_TYPE_GROUP:
1128	    return(BAD_CAST "model group definition");
1129	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1130	    return(BAD_CAST "attribute group definition");
1131	case XML_SCHEMA_TYPE_NOTATION:
1132	    return(BAD_CAST "notation declaration");
1133	case XML_SCHEMA_TYPE_SEQUENCE:
1134	    return(BAD_CAST "model group (sequence)");
1135	case XML_SCHEMA_TYPE_CHOICE:
1136	    return(BAD_CAST "model group (choice)");
1137	case XML_SCHEMA_TYPE_ALL:
1138	    return(BAD_CAST "model group (all)");
1139	case XML_SCHEMA_TYPE_PARTICLE:
1140	    return(BAD_CAST "particle");
1141	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1142	    return(BAD_CAST "unique identity-constraint");
1143	    /* return(BAD_CAST "IDC (unique)"); */
1144	case XML_SCHEMA_TYPE_IDC_KEY:
1145	    return(BAD_CAST "key identity-constraint");
1146	    /* return(BAD_CAST "IDC (key)"); */
1147	case XML_SCHEMA_TYPE_IDC_KEYREF:
1148	    return(BAD_CAST "keyref identity-constraint");
1149	    /* return(BAD_CAST "IDC (keyref)"); */
1150	case XML_SCHEMA_TYPE_ANY:
1151	    return(BAD_CAST "wildcard (any)");
1152	case XML_SCHEMA_EXTRA_QNAMEREF:
1153	    return(BAD_CAST "[helper component] QName reference");
1154	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1155	    return(BAD_CAST "[helper component] attribute use prohibition");
1156	default:
1157	    return(BAD_CAST "Not a schema component");
1158    }
1159}
1160
1161/**
1162 * xmlSchemaGetComponentTypeStr:
1163 * @type: the type of the schema item
1164 *
1165 * Returns the component name of a schema item.
1166 */
1167static const xmlChar *
1168xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1169{
1170    switch (item->type) {
1171	case XML_SCHEMA_TYPE_BASIC:
1172	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1173		return(BAD_CAST "complex type definition");
1174	    else
1175		return(BAD_CAST "simple type definition");
1176	default:
1177	    return(xmlSchemaItemTypeToStr(item->type));
1178    }
1179}
1180
1181/**
1182 * xmlSchemaGetComponentNode:
1183 * @item: a schema component
1184 *
1185 * Returns node associated with the schema component.
1186 * NOTE that such a node need not be available; plus, a component's
1187 * node need not to reflect the component directly, since there is no
1188 * one-to-one relationship between the XML Schema representation and
1189 * the component representation.
1190 */
1191static xmlNodePtr
1192xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1193{
1194    switch (item->type) {
1195	case XML_SCHEMA_TYPE_ELEMENT:
1196	    return (((xmlSchemaElementPtr) item)->node);
1197	case XML_SCHEMA_TYPE_ATTRIBUTE:
1198	    return (((xmlSchemaAttributePtr) item)->node);
1199	case XML_SCHEMA_TYPE_COMPLEX:
1200	case XML_SCHEMA_TYPE_SIMPLE:
1201	    return (((xmlSchemaTypePtr) item)->node);
1202	case XML_SCHEMA_TYPE_ANY:
1203	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1204	    return (((xmlSchemaWildcardPtr) item)->node);
1205	case XML_SCHEMA_TYPE_PARTICLE:
1206	    return (((xmlSchemaParticlePtr) item)->node);
1207	case XML_SCHEMA_TYPE_SEQUENCE:
1208	case XML_SCHEMA_TYPE_CHOICE:
1209	case XML_SCHEMA_TYPE_ALL:
1210	    return (((xmlSchemaModelGroupPtr) item)->node);
1211	case XML_SCHEMA_TYPE_GROUP:
1212	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1213	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1214	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1215	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1216	case XML_SCHEMA_TYPE_IDC_KEY:
1217	case XML_SCHEMA_TYPE_IDC_KEYREF:
1218	    return (((xmlSchemaIDCPtr) item)->node);
1219	case XML_SCHEMA_EXTRA_QNAMEREF:
1220	    return(((xmlSchemaQNameRefPtr) item)->node);
1221	/* TODO: What to do with NOTATIONs?
1222	case XML_SCHEMA_TYPE_NOTATION:
1223	    return (((xmlSchemaNotationPtr) item)->node);
1224	*/
1225	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1226	    return (((xmlSchemaAttributeUsePtr) item)->node);
1227	default:
1228	    return (NULL);
1229    }
1230}
1231
1232#if 0
1233/**
1234 * xmlSchemaGetNextComponent:
1235 * @item: a schema component
1236 *
1237 * Returns the next sibling of the schema component.
1238 */
1239static xmlSchemaBasicItemPtr
1240xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1241{
1242    switch (item->type) {
1243	case XML_SCHEMA_TYPE_ELEMENT:
1244	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1245	case XML_SCHEMA_TYPE_ATTRIBUTE:
1246	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1247	case XML_SCHEMA_TYPE_COMPLEX:
1248	case XML_SCHEMA_TYPE_SIMPLE:
1249	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1250	case XML_SCHEMA_TYPE_ANY:
1251	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1252	    return (NULL);
1253	case XML_SCHEMA_TYPE_PARTICLE:
1254	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1255	case XML_SCHEMA_TYPE_SEQUENCE:
1256	case XML_SCHEMA_TYPE_CHOICE:
1257	case XML_SCHEMA_TYPE_ALL:
1258	    return (NULL);
1259	case XML_SCHEMA_TYPE_GROUP:
1260	    return (NULL);
1261	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1262	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1263	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1264	case XML_SCHEMA_TYPE_IDC_KEY:
1265	case XML_SCHEMA_TYPE_IDC_KEYREF:
1266	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1267	default:
1268	    return (NULL);
1269    }
1270}
1271#endif
1272
1273
1274/**
1275 * xmlSchemaFormatQName:
1276 * @buf: the string buffer
1277 * @namespaceName:  the namespace name
1278 * @localName: the local name
1279 *
1280 * Returns the given QName in the format "{namespaceName}localName" or
1281 * just "localName" if @namespaceName is NULL.
1282 *
1283 * Returns the localName if @namespaceName is NULL, a formatted
1284 * string otherwise.
1285 */
1286static const xmlChar*
1287xmlSchemaFormatQName(xmlChar **buf,
1288		     const xmlChar *namespaceName,
1289		     const xmlChar *localName)
1290{
1291    FREE_AND_NULL(*buf)
1292    if (namespaceName != NULL) {
1293	*buf = xmlStrdup(BAD_CAST "{");
1294	*buf = xmlStrcat(*buf, namespaceName);
1295	*buf = xmlStrcat(*buf, BAD_CAST "}");
1296    }
1297    if (localName != NULL) {
1298	if (namespaceName == NULL)
1299	    return(localName);
1300	*buf = xmlStrcat(*buf, localName);
1301    } else {
1302	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1303    }
1304    return ((const xmlChar *) *buf);
1305}
1306
1307static const xmlChar*
1308xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1309{
1310    if (ns != NULL)
1311	return (xmlSchemaFormatQName(buf, ns->href, localName));
1312    else
1313	return (xmlSchemaFormatQName(buf, NULL, localName));
1314}
1315
1316static const xmlChar *
1317xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1318{
1319    switch (item->type) {
1320	case XML_SCHEMA_TYPE_ELEMENT:
1321	    return (((xmlSchemaElementPtr) item)->name);
1322	case XML_SCHEMA_TYPE_ATTRIBUTE:
1323	    return (((xmlSchemaAttributePtr) item)->name);
1324	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1325	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1326	case XML_SCHEMA_TYPE_BASIC:
1327	case XML_SCHEMA_TYPE_SIMPLE:
1328	case XML_SCHEMA_TYPE_COMPLEX:
1329	    return (((xmlSchemaTypePtr) item)->name);
1330	case XML_SCHEMA_TYPE_GROUP:
1331	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1332	case XML_SCHEMA_TYPE_IDC_KEY:
1333	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1334	case XML_SCHEMA_TYPE_IDC_KEYREF:
1335	    return (((xmlSchemaIDCPtr) item)->name);
1336	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1337	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1338		return(xmlSchemaGetComponentName(
1339		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1340	    } else
1341		return(NULL);
1342	case XML_SCHEMA_EXTRA_QNAMEREF:
1343	    return (((xmlSchemaQNameRefPtr) item)->name);
1344	case XML_SCHEMA_TYPE_NOTATION:
1345	    return (((xmlSchemaNotationPtr) item)->name);
1346	default:
1347	    /*
1348	    * Other components cannot have names.
1349	    */
1350	    break;
1351    }
1352    return (NULL);
1353}
1354
1355#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1356#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1357/*
1358static const xmlChar *
1359xmlSchemaGetQNameRefName(void *ref)
1360{
1361    return(((xmlSchemaQNameRefPtr) ref)->name);
1362}
1363
1364static const xmlChar *
1365xmlSchemaGetQNameRefTargetNs(void *ref)
1366{
1367    return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1368}
1369*/
1370
1371static const xmlChar *
1372xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1373{
1374    switch (item->type) {
1375	case XML_SCHEMA_TYPE_ELEMENT:
1376	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1377	case XML_SCHEMA_TYPE_ATTRIBUTE:
1378	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1379	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1380	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1381	case XML_SCHEMA_TYPE_BASIC:
1382	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1383	case XML_SCHEMA_TYPE_SIMPLE:
1384	case XML_SCHEMA_TYPE_COMPLEX:
1385	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1386	case XML_SCHEMA_TYPE_GROUP:
1387	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1388	case XML_SCHEMA_TYPE_IDC_KEY:
1389	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1390	case XML_SCHEMA_TYPE_IDC_KEYREF:
1391	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1392	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1393	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1394		return(xmlSchemaGetComponentTargetNs(
1395		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1396	    }
1397	    /* TODO: Will returning NULL break something? */
1398	    break;
1399	case XML_SCHEMA_EXTRA_QNAMEREF:
1400	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1401	case XML_SCHEMA_TYPE_NOTATION:
1402	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1403	default:
1404	    /*
1405	    * Other components cannot have names.
1406	    */
1407	    break;
1408    }
1409    return (NULL);
1410}
1411
1412static const xmlChar*
1413xmlSchemaGetComponentQName(xmlChar **buf,
1414			   void *item)
1415{
1416    return (xmlSchemaFormatQName(buf,
1417	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1418	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1419}
1420
1421static const xmlChar*
1422xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1423{
1424    xmlChar *str = NULL;
1425
1426    *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1427    *buf = xmlStrcat(*buf, BAD_CAST " '");
1428    *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1429	(xmlSchemaBasicItemPtr) item));
1430    *buf = xmlStrcat(*buf, BAD_CAST "'");
1431    FREE_AND_NULL(str);
1432    return(*buf);
1433}
1434
1435static const xmlChar*
1436xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1437{
1438    return(xmlSchemaGetComponentDesignation(buf, idc));
1439}
1440
1441/**
1442 * xmlSchemaWildcardPCToString:
1443 * @pc: the type of processContents
1444 *
1445 * Returns a string representation of the type of
1446 * processContents.
1447 */
1448static const xmlChar *
1449xmlSchemaWildcardPCToString(int pc)
1450{
1451    switch (pc) {
1452	case XML_SCHEMAS_ANY_SKIP:
1453	    return (BAD_CAST "skip");
1454	case XML_SCHEMAS_ANY_LAX:
1455	    return (BAD_CAST "lax");
1456	case XML_SCHEMAS_ANY_STRICT:
1457	    return (BAD_CAST "strict");
1458	default:
1459	    return (BAD_CAST "invalid process contents");
1460    }
1461}
1462
1463/**
1464 * xmlSchemaGetCanonValueWhtspExt:
1465 * @val: the precomputed value
1466 * @retValue: the returned value
1467 * @ws: the whitespace type of the value
1468 *
1469 * Get a the cononical representation of the value.
1470 * The caller has to free the returned retValue.
1471 *
1472 * Returns 0 if the value could be built and -1 in case of
1473 *         API errors or if the value type is not supported yet.
1474 */
1475static int
1476xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1477			       xmlSchemaWhitespaceValueType ws,
1478			       xmlChar **retValue)
1479{
1480    int list;
1481    xmlSchemaValType valType;
1482    const xmlChar *value, *value2 = NULL;
1483
1484
1485    if ((retValue == NULL) || (val == NULL))
1486	return (-1);
1487    list = xmlSchemaValueGetNext(val) ? 1 : 0;
1488    *retValue = NULL;
1489    do {
1490	value = NULL;
1491	valType = xmlSchemaGetValType(val);
1492	switch (valType) {
1493	    case XML_SCHEMAS_STRING:
1494	    case XML_SCHEMAS_NORMSTRING:
1495	    case XML_SCHEMAS_ANYSIMPLETYPE:
1496		value = xmlSchemaValueGetAsString(val);
1497		if (value != NULL) {
1498		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1499			value2 = xmlSchemaCollapseString(value);
1500		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1501			value2 = xmlSchemaWhiteSpaceReplace(value);
1502		    if (value2 != NULL)
1503			value = value2;
1504		}
1505		break;
1506	    default:
1507		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1508		    if (value2 != NULL)
1509			xmlFree((xmlChar *) value2);
1510		    goto internal_error;
1511		}
1512		value = value2;
1513	}
1514	if (*retValue == NULL)
1515	    if (value == NULL) {
1516		if (! list)
1517		    *retValue = xmlStrdup(BAD_CAST "");
1518	    } else
1519		*retValue = xmlStrdup(value);
1520	else if (value != NULL) {
1521	    /* List. */
1522	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1523	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1524	}
1525	FREE_AND_NULL(value2)
1526	val = xmlSchemaValueGetNext(val);
1527    } while (val != NULL);
1528
1529    return (0);
1530internal_error:
1531    if (*retValue != NULL)
1532	xmlFree((xmlChar *) (*retValue));
1533    if (value2 != NULL)
1534	xmlFree((xmlChar *) value2);
1535    return (-1);
1536}
1537
1538/**
1539 * xmlSchemaFormatItemForReport:
1540 * @buf: the string buffer
1541 * @itemDes: the designation of the item
1542 * @itemName: the name of the item
1543 * @item: the item as an object
1544 * @itemNode: the node of the item
1545 * @local: the local name
1546 * @parsing: if the function is used during the parse
1547 *
1548 * Returns a representation of the given item used
1549 * for error reports.
1550 *
1551 * The following order is used to build the resulting
1552 * designation if the arguments are not NULL:
1553 * 1a. If itemDes not NULL -> itemDes
1554 * 1b. If (itemDes not NULL) and (itemName not NULL)
1555 *     -> itemDes + itemName
1556 * 2. If the preceding was NULL and (item not NULL) -> item
1557 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1558 *
1559 * If the itemNode is an attribute node, the name of the attribute
1560 * will be appended to the result.
1561 *
1562 * Returns the formatted string and sets @buf to the resulting value.
1563 */
1564static xmlChar*
1565xmlSchemaFormatItemForReport(xmlChar **buf,
1566		     const xmlChar *itemDes,
1567		     xmlSchemaBasicItemPtr item,
1568		     xmlNodePtr itemNode)
1569{
1570    xmlChar *str = NULL;
1571    int named = 1;
1572
1573    if (*buf != NULL) {
1574	xmlFree(*buf);
1575	*buf = NULL;
1576    }
1577
1578    if (itemDes != NULL) {
1579	*buf = xmlStrdup(itemDes);
1580    } else if (item != NULL) {
1581	switch (item->type) {
1582	case XML_SCHEMA_TYPE_BASIC: {
1583	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1584
1585	    if (WXS_IS_ATOMIC(type))
1586		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1587	    else if (WXS_IS_LIST(type))
1588		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1589	    else if (WXS_IS_UNION(type))
1590		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1591	    else
1592		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1593	    *buf = xmlStrcat(*buf, type->name);
1594	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1595	    }
1596	    break;
1597	case XML_SCHEMA_TYPE_SIMPLE: {
1598	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1599
1600	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1601		*buf = xmlStrdup(BAD_CAST"");
1602	    } else {
1603		*buf = xmlStrdup(BAD_CAST "local ");
1604	    }
1605	    if (WXS_IS_ATOMIC(type))
1606		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1607	    else if (WXS_IS_LIST(type))
1608		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1609	    else if (WXS_IS_UNION(type))
1610		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1611	    else
1612		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1613	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1614		*buf = xmlStrcat(*buf, BAD_CAST " '");
1615		*buf = xmlStrcat(*buf, type->name);
1616		*buf = xmlStrcat(*buf, BAD_CAST "'");
1617	    }
1618	    }
1619	    break;
1620	case XML_SCHEMA_TYPE_COMPLEX: {
1621	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1622
1623	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1624		*buf = xmlStrdup(BAD_CAST "");
1625	    else
1626		*buf = xmlStrdup(BAD_CAST "local ");
1627	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1628	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1629		*buf = xmlStrcat(*buf, BAD_CAST " '");
1630		*buf = xmlStrcat(*buf, type->name);
1631		*buf = xmlStrcat(*buf, BAD_CAST "'");
1632	    }
1633	    }
1634	    break;
1635	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1636		xmlSchemaAttributeUsePtr ause;
1637
1638		ause = WXS_ATTR_USE_CAST item;
1639		*buf = xmlStrdup(BAD_CAST "attribute use ");
1640		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1641		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1642		    *buf = xmlStrcat(*buf,
1643			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1644		    FREE_AND_NULL(str)
1645			*buf = xmlStrcat(*buf, BAD_CAST "'");
1646		} else {
1647		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1648		}
1649	    }
1650	    break;
1651	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1652		xmlSchemaAttributePtr attr;
1653
1654		attr = (xmlSchemaAttributePtr) item;
1655		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1656		*buf = xmlStrcat(*buf, BAD_CAST " '");
1657		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1658		    attr->targetNamespace, attr->name));
1659		FREE_AND_NULL(str)
1660		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1661	    }
1662	    break;
1663	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1664	    xmlSchemaGetComponentDesignation(buf, item);
1665	    break;
1666	case XML_SCHEMA_TYPE_ELEMENT: {
1667		xmlSchemaElementPtr elem;
1668
1669		elem = (xmlSchemaElementPtr) item;
1670		*buf = xmlStrdup(BAD_CAST "element decl.");
1671		*buf = xmlStrcat(*buf, BAD_CAST " '");
1672		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1673		    elem->targetNamespace, elem->name));
1674		*buf = xmlStrcat(*buf, BAD_CAST "'");
1675	    }
1676	    break;
1677	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1678	case XML_SCHEMA_TYPE_IDC_KEY:
1679	case XML_SCHEMA_TYPE_IDC_KEYREF:
1680	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1681		*buf = xmlStrdup(BAD_CAST "unique '");
1682	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1683		*buf = xmlStrdup(BAD_CAST "key '");
1684	    else
1685		*buf = xmlStrdup(BAD_CAST "keyRef '");
1686	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1687	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1688	    break;
1689	case XML_SCHEMA_TYPE_ANY:
1690	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1691	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1692		    ((xmlSchemaWildcardPtr) item)->processContents));
1693	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1694	    break;
1695	case XML_SCHEMA_FACET_MININCLUSIVE:
1696	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1697	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1698	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1699	case XML_SCHEMA_FACET_TOTALDIGITS:
1700	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1701	case XML_SCHEMA_FACET_PATTERN:
1702	case XML_SCHEMA_FACET_ENUMERATION:
1703	case XML_SCHEMA_FACET_WHITESPACE:
1704	case XML_SCHEMA_FACET_LENGTH:
1705	case XML_SCHEMA_FACET_MAXLENGTH:
1706	case XML_SCHEMA_FACET_MINLENGTH:
1707	    *buf = xmlStrdup(BAD_CAST "facet '");
1708	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1709	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1710	    break;
1711	case XML_SCHEMA_TYPE_GROUP: {
1712		*buf = xmlStrdup(BAD_CAST "model group def.");
1713		*buf = xmlStrcat(*buf, BAD_CAST " '");
1714		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1715		*buf = xmlStrcat(*buf, BAD_CAST "'");
1716		FREE_AND_NULL(str)
1717	    }
1718	    break;
1719	case XML_SCHEMA_TYPE_SEQUENCE:
1720	case XML_SCHEMA_TYPE_CHOICE:
1721	case XML_SCHEMA_TYPE_ALL:
1722	case XML_SCHEMA_TYPE_PARTICLE:
1723	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1724	    break;
1725	case XML_SCHEMA_TYPE_NOTATION: {
1726		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1727		*buf = xmlStrcat(*buf, BAD_CAST " '");
1728		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1729		*buf = xmlStrcat(*buf, BAD_CAST "'");
1730		FREE_AND_NULL(str);
1731	    }
1732	default:
1733	    named = 0;
1734	}
1735    } else
1736	named = 0;
1737
1738    if ((named == 0) && (itemNode != NULL)) {
1739	xmlNodePtr elem;
1740
1741	if (itemNode->type == XML_ATTRIBUTE_NODE)
1742	    elem = itemNode->parent;
1743	else
1744	    elem = itemNode;
1745	*buf = xmlStrdup(BAD_CAST "Element '");
1746	if (elem->ns != NULL) {
1747	    *buf = xmlStrcat(*buf,
1748		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1749	    FREE_AND_NULL(str)
1750	} else
1751	    *buf = xmlStrcat(*buf, elem->name);
1752	*buf = xmlStrcat(*buf, BAD_CAST "'");
1753
1754    }
1755    if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1756	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1757	if (itemNode->ns != NULL) {
1758	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1759		itemNode->ns->href, itemNode->name));
1760	    FREE_AND_NULL(str)
1761	} else
1762	    *buf = xmlStrcat(*buf, itemNode->name);
1763	*buf = xmlStrcat(*buf, BAD_CAST "'");
1764    }
1765    FREE_AND_NULL(str)
1766
1767    return (*buf);
1768}
1769
1770/**
1771 * xmlSchemaFormatFacetEnumSet:
1772 * @buf: the string buffer
1773 * @type: the type holding the enumeration facets
1774 *
1775 * Builds a string consisting of all enumeration elements.
1776 *
1777 * Returns a string of all enumeration elements.
1778 */
1779static const xmlChar *
1780xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1781			    xmlChar **buf, xmlSchemaTypePtr type)
1782{
1783    xmlSchemaFacetPtr facet;
1784    xmlSchemaWhitespaceValueType ws;
1785    xmlChar *value = NULL;
1786    int res, found = 0;
1787
1788    if (*buf != NULL)
1789	xmlFree(*buf);
1790    *buf = NULL;
1791
1792    do {
1793	/*
1794	* Use the whitespace type of the base type.
1795	*/
1796	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1797	for (facet = type->facets; facet != NULL; facet = facet->next) {
1798	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1799		continue;
1800	    found = 1;
1801	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1802		ws, &value);
1803	    if (res == -1) {
1804		xmlSchemaInternalErr(actxt,
1805		    "xmlSchemaFormatFacetEnumSet",
1806		    "compute the canonical lexical representation");
1807		if (*buf != NULL)
1808		    xmlFree(*buf);
1809		*buf = NULL;
1810		return (NULL);
1811	    }
1812	    if (*buf == NULL)
1813		*buf = xmlStrdup(BAD_CAST "'");
1814	    else
1815		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1816	    *buf = xmlStrcat(*buf, BAD_CAST value);
1817	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1818	    if (value != NULL) {
1819		xmlFree((xmlChar *)value);
1820		value = NULL;
1821	    }
1822	}
1823	/*
1824	* The enumeration facet of a type restricts the enumeration
1825	* facet of the ancestor type; i.e., such restricted enumerations
1826	* do not belong to the set of the given type. Thus we break
1827	* on the first found enumeration.
1828	*/
1829	if (found)
1830	    break;
1831	type = type->baseType;
1832    } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1833
1834    return ((const xmlChar *) *buf);
1835}
1836
1837/************************************************************************
1838 *									*
1839 * 			Error functions				        *
1840 *									*
1841 ************************************************************************/
1842
1843#if 0
1844static void
1845xmlSchemaErrMemory(const char *msg)
1846{
1847    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1848                     msg);
1849}
1850#endif
1851
1852static void
1853xmlSchemaPSimpleErr(const char *msg)
1854{
1855    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1856                     msg);
1857}
1858
1859/**
1860 * xmlSchemaPErrMemory:
1861 * @node: a context node
1862 * @extra:  extra informations
1863 *
1864 * Handle an out of memory condition
1865 */
1866static void
1867xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1868                    const char *extra, xmlNodePtr node)
1869{
1870    if (ctxt != NULL)
1871        ctxt->nberrors++;
1872    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1873                     extra);
1874}
1875
1876/**
1877 * xmlSchemaPErr:
1878 * @ctxt: the parsing context
1879 * @node: the context node
1880 * @error: the error code
1881 * @msg: the error message
1882 * @str1: extra data
1883 * @str2: extra data
1884 *
1885 * Handle a parser error
1886 */
1887static void
1888xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1889              const char *msg, const xmlChar * str1, const xmlChar * str2)
1890{
1891    xmlGenericErrorFunc channel = NULL;
1892    xmlStructuredErrorFunc schannel = NULL;
1893    void *data = NULL;
1894
1895    if (ctxt != NULL) {
1896        ctxt->nberrors++;
1897	ctxt->err = error;
1898        channel = ctxt->error;
1899        data = ctxt->errCtxt;
1900	schannel = ctxt->serror;
1901    }
1902    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1903                    error, XML_ERR_ERROR, NULL, 0,
1904                    (const char *) str1, (const char *) str2, NULL, 0, 0,
1905                    msg, str1, str2);
1906}
1907
1908/**
1909 * xmlSchemaPErr2:
1910 * @ctxt: the parsing context
1911 * @node: the context node
1912 * @node: the current child
1913 * @error: the error code
1914 * @msg: the error message
1915 * @str1: extra data
1916 * @str2: extra data
1917 *
1918 * Handle a parser error
1919 */
1920static void
1921xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1922               xmlNodePtr child, int error,
1923               const char *msg, const xmlChar * str1, const xmlChar * str2)
1924{
1925    if (child != NULL)
1926        xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1927    else
1928        xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1929}
1930
1931
1932/**
1933 * xmlSchemaPErrExt:
1934 * @ctxt: the parsing context
1935 * @node: the context node
1936 * @error: the error code
1937 * @strData1: extra data
1938 * @strData2: extra data
1939 * @strData3: extra data
1940 * @msg: the message
1941 * @str1:  extra parameter for the message display
1942 * @str2:  extra parameter for the message display
1943 * @str3:  extra parameter for the message display
1944 * @str4:  extra parameter for the message display
1945 * @str5:  extra parameter for the message display
1946 *
1947 * Handle a parser error
1948 */
1949static void
1950xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1951		const xmlChar * strData1, const xmlChar * strData2,
1952		const xmlChar * strData3, const char *msg, const xmlChar * str1,
1953		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1954		const xmlChar * str5)
1955{
1956
1957    xmlGenericErrorFunc channel = NULL;
1958    xmlStructuredErrorFunc schannel = NULL;
1959    void *data = NULL;
1960
1961    if (ctxt != NULL) {
1962        ctxt->nberrors++;
1963	ctxt->err = error;
1964        channel = ctxt->error;
1965        data = ctxt->errCtxt;
1966	schannel = ctxt->serror;
1967    }
1968    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1969                    error, XML_ERR_ERROR, NULL, 0,
1970                    (const char *) strData1, (const char *) strData2,
1971		    (const char *) strData3, 0, 0, msg, str1, str2,
1972		    str3, str4, str5);
1973}
1974
1975/************************************************************************
1976 *									*
1977 * 			Allround error functions			*
1978 *									*
1979 ************************************************************************/
1980
1981/**
1982 * xmlSchemaVTypeErrMemory:
1983 * @node: a context node
1984 * @extra:  extra informations
1985 *
1986 * Handle an out of memory condition
1987 */
1988static void
1989xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1990                    const char *extra, xmlNodePtr node)
1991{
1992    if (ctxt != NULL) {
1993        ctxt->nberrors++;
1994        ctxt->err = XML_SCHEMAV_INTERNAL;
1995    }
1996    __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1997                     extra);
1998}
1999
2000static void
2001xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2002			    const char *msg, const xmlChar *str)
2003{
2004     __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2005	 msg, (const char *) str);
2006}
2007
2008#define WXS_ERROR_TYPE_ERROR 1
2009#define WXS_ERROR_TYPE_WARNING 2
2010/**
2011 * xmlSchemaErr3:
2012 * @ctxt: the validation context
2013 * @node: the context node
2014 * @error: the error code
2015 * @msg: the error message
2016 * @str1: extra data
2017 * @str2: extra data
2018 * @str3: extra data
2019 *
2020 * Handle a validation error
2021 */
2022static void
2023xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2024		  xmlErrorLevel errorLevel,
2025		  int error, xmlNodePtr node, int line, const char *msg,
2026		  const xmlChar *str1, const xmlChar *str2,
2027		  const xmlChar *str3, const xmlChar *str4)
2028{
2029    xmlStructuredErrorFunc schannel = NULL;
2030    xmlGenericErrorFunc channel = NULL;
2031    void *data = NULL;
2032
2033    if (ctxt != NULL) {
2034	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2035	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2036	    const char *file = NULL;
2037	    if (errorLevel != XML_ERR_WARNING) {
2038		vctxt->nberrors++;
2039		vctxt->err = error;
2040		channel = vctxt->error;
2041	    } else {
2042		channel = vctxt->warning;
2043	    }
2044	    schannel = vctxt->serror;
2045	    data = vctxt->errCtxt;
2046
2047	    /*
2048	    * Error node. If we specify a line number, then
2049	    * do not channel any node to the error function.
2050	    */
2051	    if (line == 0) {
2052		if ((node == NULL) &&
2053		    (vctxt->depth >= 0) &&
2054		    (vctxt->inode != NULL)) {
2055		    node = vctxt->inode->node;
2056		}
2057		/*
2058		* Get filename and line if no node-tree.
2059		*/
2060		if ((node == NULL) &&
2061		    (vctxt->parserCtxt != NULL) &&
2062		    (vctxt->parserCtxt->input != NULL)) {
2063		    file = vctxt->parserCtxt->input->filename;
2064		    line = vctxt->parserCtxt->input->line;
2065		}
2066	    } else {
2067		/*
2068		* Override the given node's (if any) position
2069		* and channel only the given line number.
2070		*/
2071		node = NULL;
2072		/*
2073		* Get filename.
2074		*/
2075		if (vctxt->doc != NULL)
2076		    file = (const char *) vctxt->doc->URL;
2077		else if ((vctxt->parserCtxt != NULL) &&
2078		    (vctxt->parserCtxt->input != NULL))
2079		    file = vctxt->parserCtxt->input->filename;
2080	    }
2081	    __xmlRaiseError(schannel, channel, data, ctxt,
2082		node, XML_FROM_SCHEMASV,
2083		error, errorLevel, file, line,
2084		(const char *) str1, (const char *) str2,
2085		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2086
2087	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2088	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2089	    if (errorLevel != XML_ERR_WARNING) {
2090		pctxt->nberrors++;
2091		pctxt->err = error;
2092		channel = pctxt->error;
2093	    } else {
2094		channel = pctxt->warning;
2095	    }
2096	    schannel = pctxt->serror;
2097	    data = pctxt->errCtxt;
2098	    __xmlRaiseError(schannel, channel, data, ctxt,
2099		node, XML_FROM_SCHEMASP, error,
2100		errorLevel, NULL, 0,
2101		(const char *) str1, (const char *) str2,
2102		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2103	} else {
2104	    TODO
2105	}
2106    }
2107}
2108
2109/**
2110 * xmlSchemaErr3:
2111 * @ctxt: the validation context
2112 * @node: the context node
2113 * @error: the error code
2114 * @msg: the error message
2115 * @str1: extra data
2116 * @str2: extra data
2117 * @str3: extra data
2118 *
2119 * Handle a validation error
2120 */
2121static void
2122xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2123	      int error, xmlNodePtr node, const char *msg,
2124	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2125{
2126    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2127	msg, str1, str2, str3, NULL);
2128}
2129
2130static void
2131xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2132	      int error, xmlNodePtr node, const char *msg,
2133	      const xmlChar *str1, const xmlChar *str2,
2134	      const xmlChar *str3, const xmlChar *str4)
2135{
2136    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2137	msg, str1, str2, str3, str4);
2138}
2139
2140static void
2141xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2142	     int error, xmlNodePtr node, const char *msg,
2143	     const xmlChar *str1, const xmlChar *str2)
2144{
2145    xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2146}
2147
2148static xmlChar *
2149xmlSchemaFormatNodeForError(xmlChar ** msg,
2150			    xmlSchemaAbstractCtxtPtr actxt,
2151			    xmlNodePtr node)
2152{
2153    xmlChar *str = NULL;
2154
2155    *msg = NULL;
2156    if ((node != NULL) &&
2157	(node->type != XML_ELEMENT_NODE) &&
2158	(node->type != XML_ATTRIBUTE_NODE))
2159    {
2160	/*
2161	* Don't try to format other nodes than element and
2162	* attribute nodes.
2163	* Play save and return an empty string.
2164	*/
2165	*msg = xmlStrdup(BAD_CAST "");
2166	return(*msg);
2167    }
2168    if (node != NULL) {
2169	/*
2170	* Work on tree nodes.
2171	*/
2172	if (node->type == XML_ATTRIBUTE_NODE) {
2173	    xmlNodePtr elem = node->parent;
2174
2175	    *msg = xmlStrdup(BAD_CAST "Element '");
2176	    if (elem->ns != NULL)
2177		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2178		    elem->ns->href, elem->name));
2179	    else
2180		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2181		    NULL, elem->name));
2182	    FREE_AND_NULL(str);
2183	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2184	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2185	} else {
2186	    *msg = xmlStrdup(BAD_CAST "Element '");
2187	}
2188	if (node->ns != NULL)
2189	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2190	    node->ns->href, node->name));
2191	else
2192	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2193	    NULL, node->name));
2194	FREE_AND_NULL(str);
2195	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2196    } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2197	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2198	/*
2199	* Work on node infos.
2200	*/
2201	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2202	    xmlSchemaNodeInfoPtr ielem =
2203		vctxt->elemInfos[vctxt->depth];
2204
2205	    *msg = xmlStrdup(BAD_CAST "Element '");
2206	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2207		ielem->nsName, ielem->localName));
2208	    FREE_AND_NULL(str);
2209	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2210	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2211	} else {
2212	    *msg = xmlStrdup(BAD_CAST "Element '");
2213	}
2214	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2215	    vctxt->inode->nsName, vctxt->inode->localName));
2216	FREE_AND_NULL(str);
2217	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2218    } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2219	/*
2220	* Hmm, no node while parsing?
2221	* Return an empty string, in case NULL will break something.
2222	*/
2223	*msg = xmlStrdup(BAD_CAST "");
2224    } else {
2225	TODO
2226	return (NULL);
2227    }
2228    /*
2229    * VAL TODO: The output of the given schema component is currently
2230    * disabled.
2231    */
2232#if 0
2233    if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2234	*msg = xmlStrcat(*msg, BAD_CAST " [");
2235	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2236	    NULL, type, NULL, 0));
2237	FREE_AND_NULL(str)
2238	*msg = xmlStrcat(*msg, BAD_CAST "]");
2239    }
2240#endif
2241    return (*msg);
2242}
2243
2244static void
2245xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2246		     const char *funcName,
2247		     const char *message,
2248		     const xmlChar *str1,
2249		     const xmlChar *str2)
2250{
2251    xmlChar *msg = NULL;
2252
2253    if (actxt == NULL)
2254        return;
2255    msg = xmlStrdup(BAD_CAST "Internal error: ");
2256    msg = xmlStrcat(msg, BAD_CAST funcName);
2257    msg = xmlStrcat(msg, BAD_CAST ", ");
2258    msg = xmlStrcat(msg, BAD_CAST message);
2259    msg = xmlStrcat(msg, BAD_CAST ".\n");
2260
2261    if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2262	xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2263	    (const char *) msg, str1, str2);
2264
2265    else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2266	xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2267	    (const char *) msg, str1, str2);
2268
2269    FREE_AND_NULL(msg)
2270}
2271
2272static void
2273xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2274		     const char *funcName,
2275		     const char *message)
2276{
2277    xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2278}
2279
2280#if 0
2281static void
2282xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2283		     const char *funcName,
2284		     const char *message,
2285		     const xmlChar *str1,
2286		     const xmlChar *str2)
2287{
2288    xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2289	str1, str2);
2290}
2291#endif
2292
2293static void
2294xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2295		   xmlParserErrors error,
2296		   xmlNodePtr node,
2297		   xmlSchemaBasicItemPtr item,
2298		   const char *message,
2299		   const xmlChar *str1, const xmlChar *str2,
2300		   const xmlChar *str3, const xmlChar *str4)
2301{
2302    xmlChar *msg = NULL;
2303
2304    if ((node == NULL) && (item != NULL) &&
2305	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2306	node = WXS_ITEM_NODE(item);
2307	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2308	msg = xmlStrcat(msg, BAD_CAST ": ");
2309    } else
2310	xmlSchemaFormatNodeForError(&msg, actxt, node);
2311    msg = xmlStrcat(msg, (const xmlChar *) message);
2312    msg = xmlStrcat(msg, BAD_CAST ".\n");
2313    xmlSchemaErr4(actxt, error, node,
2314	(const char *) msg, str1, str2, str3, str4);
2315    FREE_AND_NULL(msg)
2316}
2317
2318static void
2319xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2320		   xmlParserErrors error,
2321		   xmlNodePtr node,
2322		   xmlSchemaBasicItemPtr item,
2323		   const char *message,
2324		   const xmlChar *str1,
2325		   const xmlChar *str2)
2326{
2327    xmlSchemaCustomErr4(actxt, error, node, item,
2328	message, str1, str2, NULL, NULL);
2329}
2330
2331
2332
2333static void
2334xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2335		   xmlParserErrors error,
2336		   xmlNodePtr node,
2337		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2338		   const char *message,
2339		   const xmlChar *str1,
2340		   const xmlChar *str2,
2341		   const xmlChar *str3)
2342{
2343    xmlChar *msg = NULL;
2344
2345    xmlSchemaFormatNodeForError(&msg, actxt, node);
2346    msg = xmlStrcat(msg, (const xmlChar *) message);
2347    msg = xmlStrcat(msg, BAD_CAST ".\n");
2348
2349    /* URGENT TODO: Set the error code to something sane. */
2350    xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2351	(const char *) msg, str1, str2, str3, NULL);
2352
2353    FREE_AND_NULL(msg)
2354}
2355
2356
2357
2358static void
2359xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2360		   xmlParserErrors error,
2361		   xmlSchemaPSVIIDCNodePtr idcNode,
2362		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2363		   const char *message,
2364		   const xmlChar *str1,
2365		   const xmlChar *str2)
2366{
2367    xmlChar *msg = NULL, *qname = NULL;
2368
2369    msg = xmlStrdup(BAD_CAST "Element '%s': ");
2370    msg = xmlStrcat(msg, (const xmlChar *) message);
2371    msg = xmlStrcat(msg, BAD_CAST ".\n");
2372    xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2373	error, NULL, idcNode->nodeLine, (const char *) msg,
2374	xmlSchemaFormatQName(&qname,
2375	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2376	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2377	str1, str2, NULL);
2378    FREE_AND_NULL(qname);
2379    FREE_AND_NULL(msg);
2380}
2381
2382static int
2383xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2384			   xmlNodePtr node)
2385{
2386    if (node != NULL)
2387	return (node->type);
2388    if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2389	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2390	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2391    return (-1);
2392}
2393
2394static int
2395xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2396{
2397    switch (item->type) {
2398	case XML_SCHEMA_TYPE_COMPLEX:
2399	case XML_SCHEMA_TYPE_SIMPLE:
2400	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2401		return(1);
2402	    break;
2403	case XML_SCHEMA_TYPE_GROUP:
2404	    return (1);
2405	case XML_SCHEMA_TYPE_ELEMENT:
2406	    if ( ((xmlSchemaElementPtr) item)->flags &
2407		XML_SCHEMAS_ELEM_GLOBAL)
2408		return(1);
2409	    break;
2410	case XML_SCHEMA_TYPE_ATTRIBUTE:
2411	    if ( ((xmlSchemaAttributePtr) item)->flags &
2412		XML_SCHEMAS_ATTR_GLOBAL)
2413		return(1);
2414	    break;
2415	/* Note that attribute groups are always global. */
2416	default:
2417	    return(1);
2418    }
2419    return (0);
2420}
2421
2422static void
2423xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2424		       xmlParserErrors error,
2425		       xmlNodePtr node,
2426		       const xmlChar *value,
2427		       xmlSchemaTypePtr type,
2428		       int displayValue)
2429{
2430    xmlChar *msg = NULL;
2431
2432    xmlSchemaFormatNodeForError(&msg, actxt, node);
2433
2434    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2435	    XML_ATTRIBUTE_NODE))
2436	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2437    else
2438	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2439	    "value of ");
2440
2441    if (! xmlSchemaIsGlobalItem(type))
2442	msg = xmlStrcat(msg, BAD_CAST "the local ");
2443    else
2444	msg = xmlStrcat(msg, BAD_CAST "the ");
2445
2446    if (WXS_IS_ATOMIC(type))
2447	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2448    else if (WXS_IS_LIST(type))
2449	msg = xmlStrcat(msg, BAD_CAST "list type");
2450    else if (WXS_IS_UNION(type))
2451	msg = xmlStrcat(msg, BAD_CAST "union type");
2452
2453    if (xmlSchemaIsGlobalItem(type)) {
2454	xmlChar *str = NULL;
2455	msg = xmlStrcat(msg, BAD_CAST " '");
2456	if (type->builtInType != 0) {
2457	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2458	    msg = xmlStrcat(msg, type->name);
2459	} else
2460	    msg = xmlStrcat(msg,
2461		xmlSchemaFormatQName(&str,
2462		    type->targetNamespace, type->name));
2463	msg = xmlStrcat(msg, BAD_CAST "'");
2464	FREE_AND_NULL(str);
2465    }
2466    msg = xmlStrcat(msg, BAD_CAST ".\n");
2467    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2468	    XML_ATTRIBUTE_NODE))
2469	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2470    else
2471	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2472    FREE_AND_NULL(msg)
2473}
2474
2475static const xmlChar *
2476xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2477			      xmlSchemaNodeInfoPtr ni,
2478			      xmlNodePtr node)
2479{
2480    if (node != NULL) {
2481	if (node->ns != NULL)
2482	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2483	else
2484	    return (xmlSchemaFormatQName(str, NULL, node->name));
2485    } else if (ni != NULL)
2486	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2487    return (NULL);
2488}
2489
2490static void
2491xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2492			xmlParserErrors error,
2493			xmlSchemaAttrInfoPtr ni,
2494			xmlNodePtr node)
2495{
2496    xmlChar *msg = NULL, *str = NULL;
2497
2498    xmlSchemaFormatNodeForError(&msg, actxt, node);
2499    msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2500    xmlSchemaErr(actxt, error, node, (const char *) msg,
2501	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2502	NULL);
2503    FREE_AND_NULL(str)
2504    FREE_AND_NULL(msg)
2505}
2506
2507static void
2508xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2509		        xmlParserErrors error,
2510		        xmlNodePtr node,
2511			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2512			const char *message,
2513			int nbval,
2514			int nbneg,
2515			xmlChar **values)
2516{
2517    xmlChar *str = NULL, *msg = NULL;
2518    xmlChar *localName, *nsName;
2519    const xmlChar *cur, *end;
2520    int i;
2521
2522    xmlSchemaFormatNodeForError(&msg, actxt, node);
2523    msg = xmlStrcat(msg, (const xmlChar *) message);
2524    msg = xmlStrcat(msg, BAD_CAST ".");
2525    /*
2526    * Note that is does not make sense to report that we have a
2527    * wildcard here, since the wildcard might be unfolded into
2528    * multiple transitions.
2529    */
2530    if (nbval + nbneg > 0) {
2531	if (nbval + nbneg > 1) {
2532	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2533	} else
2534	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2535	nsName = NULL;
2536
2537	for (i = 0; i < nbval + nbneg; i++) {
2538	    cur = values[i];
2539	    if (cur == NULL)
2540	        continue;
2541	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2542	        (cur[3] == ' ')) {
2543		cur += 4;
2544		str = xmlStrcat(str, BAD_CAST "##other");
2545	    }
2546	    /*
2547	    * Get the local name.
2548	    */
2549	    localName = NULL;
2550
2551	    end = cur;
2552	    if (*end == '*') {
2553		localName = xmlStrdup(BAD_CAST "*");
2554		end++;
2555	    } else {
2556		while ((*end != 0) && (*end != '|'))
2557		    end++;
2558		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2559	    }
2560	    if (*end != 0) {
2561		end++;
2562		/*
2563		* Skip "*|*" if they come with negated expressions, since
2564		* they represent the same negated wildcard.
2565		*/
2566		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2567		    /*
2568		    * Get the namespace name.
2569		    */
2570		    cur = end;
2571		    if (*end == '*') {
2572			nsName = xmlStrdup(BAD_CAST "{*}");
2573		    } else {
2574			while (*end != 0)
2575			    end++;
2576
2577			if (i >= nbval)
2578			    nsName = xmlStrdup(BAD_CAST "{##other:");
2579			else
2580			    nsName = xmlStrdup(BAD_CAST "{");
2581
2582			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2583			nsName = xmlStrcat(nsName, BAD_CAST "}");
2584		    }
2585		    str = xmlStrcat(str, BAD_CAST nsName);
2586		    FREE_AND_NULL(nsName)
2587		} else {
2588		    FREE_AND_NULL(localName);
2589		    continue;
2590		}
2591	    }
2592	    str = xmlStrcat(str, BAD_CAST localName);
2593	    FREE_AND_NULL(localName);
2594
2595	    if (i < nbval + nbneg -1)
2596		str = xmlStrcat(str, BAD_CAST ", ");
2597	}
2598	str = xmlStrcat(str, BAD_CAST " ).\n");
2599	msg = xmlStrcat(msg, BAD_CAST str);
2600	FREE_AND_NULL(str)
2601    } else
2602      msg = xmlStrcat(msg, BAD_CAST "\n");
2603    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2604    xmlFree(msg);
2605}
2606
2607static void
2608xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2609		  xmlParserErrors error,
2610		  xmlNodePtr node,
2611		  const xmlChar *value,
2612		  unsigned long length,
2613		  xmlSchemaTypePtr type,
2614		  xmlSchemaFacetPtr facet,
2615		  const char *message,
2616		  const xmlChar *str1,
2617		  const xmlChar *str2)
2618{
2619    xmlChar *str = NULL, *msg = NULL;
2620    xmlSchemaTypeType facetType;
2621    int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2622
2623    xmlSchemaFormatNodeForError(&msg, actxt, node);
2624    if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2625	facetType = XML_SCHEMA_FACET_ENUMERATION;
2626	/*
2627	* If enumerations are validated, one must not expect the
2628	* facet to be given.
2629	*/
2630    } else
2631	facetType = facet->type;
2632    msg = xmlStrcat(msg, BAD_CAST "[");
2633    msg = xmlStrcat(msg, BAD_CAST "facet '");
2634    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2635    msg = xmlStrcat(msg, BAD_CAST "'] ");
2636    if (message == NULL) {
2637	/*
2638	* Use a default message.
2639	*/
2640	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2641	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2642	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2643
2644	    char len[25], actLen[25];
2645
2646	    /* FIXME, TODO: What is the max expected string length of the
2647	    * this value?
2648	    */
2649	    if (nodeType == XML_ATTRIBUTE_NODE)
2650		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2651	    else
2652		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2653
2654	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2655	    snprintf(actLen, 24, "%lu", length);
2656
2657	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2658		msg = xmlStrcat(msg,
2659		BAD_CAST "this differs from the allowed length of '%s'.\n");
2660	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2661		msg = xmlStrcat(msg,
2662		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2663	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2664		msg = xmlStrcat(msg,
2665		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2666
2667	    if (nodeType == XML_ATTRIBUTE_NODE)
2668		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2669		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2670	    else
2671		xmlSchemaErr(actxt, error, node, (const char *) msg,
2672		    (const xmlChar *) actLen, (const xmlChar *) len);
2673
2674	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2675	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2676		"of the set {%s}.\n");
2677	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2679	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2680	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2681		"by the pattern '%s'.\n");
2682	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683		facet->value);
2684	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2685	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2686		"minimum value allowed ('%s').\n");
2687	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2688		facet->value);
2689	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2690	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2691		"maximum value allowed ('%s').\n");
2692	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2693		facet->value);
2694	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2695	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2696		"'%s'.\n");
2697	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2698		facet->value);
2699	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2700	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2701		"'%s'.\n");
2702	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2703		facet->value);
2704	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2705	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2706		"digits than are allowed ('%s').\n");
2707	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2708		facet->value);
2709	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2710	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2711		"digits than are allowed ('%s').\n");
2712	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2713		facet->value);
2714	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2715	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2716	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2717	} else {
2718	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2719	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2720	}
2721    } else {
2722	msg = xmlStrcat(msg, (const xmlChar *) message);
2723	msg = xmlStrcat(msg, BAD_CAST ".\n");
2724	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2725    }
2726    FREE_AND_NULL(str)
2727    xmlFree(msg);
2728}
2729
2730#define VERROR(err, type, msg) \
2731    xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2732
2733#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2734
2735#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2736#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2737
2738#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2739
2740
2741/**
2742 * xmlSchemaPMissingAttrErr:
2743 * @ctxt: the schema validation context
2744 * @ownerDes: the designation of  the owner
2745 * @ownerName: the name of the owner
2746 * @ownerItem: the owner as a schema object
2747 * @ownerElem: the owner as an element node
2748 * @node: the parent element node of the missing attribute node
2749 * @type: the corresponding type of the attribute node
2750 *
2751 * Reports an illegal attribute.
2752 */
2753static void
2754xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2755			 xmlParserErrors error,
2756			 xmlSchemaBasicItemPtr ownerItem,
2757			 xmlNodePtr ownerElem,
2758			 const char *name,
2759			 const char *message)
2760{
2761    xmlChar *des = NULL;
2762
2763    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2764
2765    if (message != NULL)
2766	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2767    else
2768	xmlSchemaPErr(ctxt, ownerElem, error,
2769	    "%s: The attribute '%s' is required but missing.\n",
2770	    BAD_CAST des, BAD_CAST name);
2771    FREE_AND_NULL(des);
2772}
2773
2774
2775/**
2776 * xmlSchemaPResCompAttrErr:
2777 * @ctxt: the schema validation context
2778 * @error: the error code
2779 * @ownerDes: the designation of  the owner
2780 * @ownerItem: the owner as a schema object
2781 * @ownerElem: the owner as an element node
2782 * @name: the name of the attribute holding the QName
2783 * @refName: the referenced local name
2784 * @refURI: the referenced namespace URI
2785 * @message: optional message
2786 *
2787 * Used to report QName attribute values that failed to resolve
2788 * to schema components.
2789 */
2790static void
2791xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2792			 xmlParserErrors error,
2793			 xmlSchemaBasicItemPtr ownerItem,
2794			 xmlNodePtr ownerElem,
2795			 const char *name,
2796			 const xmlChar *refName,
2797			 const xmlChar *refURI,
2798			 xmlSchemaTypeType refType,
2799			 const char *refTypeStr)
2800{
2801    xmlChar *des = NULL, *strA = NULL;
2802
2803    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2804    if (refTypeStr == NULL)
2805	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2806	xmlSchemaPErrExt(ctxt, ownerElem, error,
2807	    NULL, NULL, NULL,
2808	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2809	    "%s.\n", BAD_CAST des, BAD_CAST name,
2810	    xmlSchemaFormatQName(&strA, refURI, refName),
2811	    BAD_CAST refTypeStr, NULL);
2812    FREE_AND_NULL(des)
2813    FREE_AND_NULL(strA)
2814}
2815
2816/**
2817 * xmlSchemaPCustomAttrErr:
2818 * @ctxt: the schema parser context
2819 * @error: the error code
2820 * @ownerDes: the designation of the owner
2821 * @ownerItem: the owner as a schema object
2822 * @attr: the illegal attribute node
2823 *
2824 * Reports an illegal attribute during the parse.
2825 */
2826static void
2827xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2828			xmlParserErrors error,
2829			xmlChar **ownerDes,
2830			xmlSchemaBasicItemPtr ownerItem,
2831			xmlAttrPtr attr,
2832			const char *msg)
2833{
2834    xmlChar *des = NULL;
2835
2836    if (ownerDes == NULL)
2837	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2838    else if (*ownerDes == NULL) {
2839	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2840	des = *ownerDes;
2841    } else
2842	des = *ownerDes;
2843    if (attr == NULL) {
2844	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2845	    "%s, attribute '%s': %s.\n",
2846	    BAD_CAST des, (const xmlChar *) "Unknown",
2847	    (const xmlChar *) msg, NULL, NULL);
2848    } else {
2849	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2850	    "%s, attribute '%s': %s.\n",
2851	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2852    }
2853    if (ownerDes == NULL)
2854	FREE_AND_NULL(des);
2855}
2856
2857/**
2858 * xmlSchemaPIllegalAttrErr:
2859 * @ctxt: the schema parser context
2860 * @error: the error code
2861 * @ownerDes: the designation of the attribute's owner
2862 * @ownerItem: the attribute's owner item
2863 * @attr: the illegal attribute node
2864 *
2865 * Reports an illegal attribute during the parse.
2866 */
2867static void
2868xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2869			 xmlParserErrors error,
2870			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2871			 xmlAttrPtr attr)
2872{
2873    xmlChar *strA = NULL, *strB = NULL;
2874
2875    xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2876    xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2877	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2878	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2879	NULL, NULL);
2880    FREE_AND_NULL(strA);
2881    FREE_AND_NULL(strB);
2882}
2883
2884/**
2885 * xmlSchemaPCustomErr:
2886 * @ctxt: the schema parser context
2887 * @error: the error code
2888 * @itemDes: the designation of the schema item
2889 * @item: the schema item
2890 * @itemElem: the node of the schema item
2891 * @message: the error message
2892 * @str1: an optional param for the error message
2893 * @str2: an optional param for the error message
2894 * @str3: an optional param for the error message
2895 *
2896 * Reports an error during parsing.
2897 */
2898static void
2899xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2900		    xmlParserErrors error,
2901		    xmlSchemaBasicItemPtr item,
2902		    xmlNodePtr itemElem,
2903		    const char *message,
2904		    const xmlChar *str1,
2905		    const xmlChar *str2,
2906		    const xmlChar *str3)
2907{
2908    xmlChar *des = NULL, *msg = NULL;
2909
2910    xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2911    msg = xmlStrdup(BAD_CAST "%s: ");
2912    msg = xmlStrcat(msg, (const xmlChar *) message);
2913    msg = xmlStrcat(msg, BAD_CAST ".\n");
2914    if ((itemElem == NULL) && (item != NULL))
2915	itemElem = WXS_ITEM_NODE(item);
2916    xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2917	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2918    FREE_AND_NULL(des);
2919    FREE_AND_NULL(msg);
2920}
2921
2922/**
2923 * xmlSchemaPCustomErr:
2924 * @ctxt: the schema parser context
2925 * @error: the error code
2926 * @itemDes: the designation of the schema item
2927 * @item: the schema item
2928 * @itemElem: the node of the schema item
2929 * @message: the error message
2930 * @str1: the optional param for the error message
2931 *
2932 * Reports an error during parsing.
2933 */
2934static void
2935xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2936		    xmlParserErrors error,
2937		    xmlSchemaBasicItemPtr item,
2938		    xmlNodePtr itemElem,
2939		    const char *message,
2940		    const xmlChar *str1)
2941{
2942    xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2943	str1, NULL, NULL);
2944}
2945
2946/**
2947 * xmlSchemaPAttrUseErr:
2948 * @ctxt: the schema parser context
2949 * @error: the error code
2950 * @itemDes: the designation of the schema type
2951 * @item: the schema type
2952 * @itemElem: the node of the schema type
2953 * @attr: the invalid schema attribute
2954 * @message: the error message
2955 * @str1: the optional param for the error message
2956 *
2957 * Reports an attribute use error during parsing.
2958 */
2959static void
2960xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2961		    xmlParserErrors error,
2962		    xmlNodePtr node,
2963		    xmlSchemaBasicItemPtr ownerItem,
2964		    const xmlSchemaAttributeUsePtr attruse,
2965		    const char *message,
2966		    const xmlChar *str1, const xmlChar *str2,
2967		    const xmlChar *str3,const xmlChar *str4)
2968{
2969    xmlChar *str = NULL, *msg = NULL;
2970
2971    xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2972    msg = xmlStrcat(msg, BAD_CAST ", ");
2973    msg = xmlStrcat(msg,
2974	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2975	WXS_BASIC_CAST attruse, NULL));
2976    FREE_AND_NULL(str);
2977    msg = xmlStrcat(msg, BAD_CAST ": ");
2978    msg = xmlStrcat(msg, (const xmlChar *) message);
2979    msg = xmlStrcat(msg, BAD_CAST ".\n");
2980    xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2981	(const char *) msg, str1, str2, str3, str4);
2982    xmlFree(msg);
2983}
2984
2985/**
2986 * xmlSchemaPIllegalFacetAtomicErr:
2987 * @ctxt: the schema parser context
2988 * @error: the error code
2989 * @type: the schema type
2990 * @baseType: the base type of type
2991 * @facet: the illegal facet
2992 *
2993 * Reports an illegal facet for atomic simple types.
2994 */
2995static void
2996xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2997			  xmlParserErrors error,
2998			  xmlSchemaTypePtr type,
2999			  xmlSchemaTypePtr baseType,
3000			  xmlSchemaFacetPtr facet)
3001{
3002    xmlChar *des = NULL, *strT = NULL;
3003
3004    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3005    xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3006	"%s: The facet '%s' is not allowed on types derived from the "
3007	"type %s.\n",
3008	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3009	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3010	NULL, NULL);
3011    FREE_AND_NULL(des);
3012    FREE_AND_NULL(strT);
3013}
3014
3015/**
3016 * xmlSchemaPIllegalFacetListUnionErr:
3017 * @ctxt: the schema parser context
3018 * @error: the error code
3019 * @itemDes: the designation of the schema item involved
3020 * @item: the schema item involved
3021 * @facet: the illegal facet
3022 *
3023 * Reports an illegal facet for <list> and <union>.
3024 */
3025static void
3026xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3027			  xmlParserErrors error,
3028			  xmlSchemaTypePtr type,
3029			  xmlSchemaFacetPtr facet)
3030{
3031    xmlChar *des = NULL;
3032
3033    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3034	type->node);
3035    xmlSchemaPErr(ctxt, type->node, error,
3036	"%s: The facet '%s' is not allowed.\n",
3037	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3038    FREE_AND_NULL(des);
3039}
3040
3041/**
3042 * xmlSchemaPMutualExclAttrErr:
3043 * @ctxt: the schema validation context
3044 * @error: the error code
3045 * @elemDes: the designation of the parent element node
3046 * @attr: the bad attribute node
3047 * @type: the corresponding type of the attribute node
3048 *
3049 * Reports an illegal attribute.
3050 */
3051static void
3052xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3053			 xmlParserErrors error,
3054			 xmlSchemaBasicItemPtr ownerItem,
3055			 xmlAttrPtr attr,
3056			 const char *name1,
3057			 const char *name2)
3058{
3059    xmlChar *des = NULL;
3060
3061    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3062    xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3063	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3064	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3065    FREE_AND_NULL(des);
3066}
3067
3068/**
3069 * xmlSchemaPSimpleTypeErr:
3070 * @ctxt:  the schema validation context
3071 * @error: the error code
3072 * @type: the type specifier
3073 * @ownerDes: the designation of the owner
3074 * @ownerItem: the schema object if existent
3075 * @node: the validated node
3076 * @value: the validated value
3077 *
3078 * Reports a simple type validation error.
3079 * TODO: Should this report the value of an element as well?
3080 */
3081static void
3082xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3083			xmlParserErrors error,
3084			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3085			xmlNodePtr node,
3086			xmlSchemaTypePtr type,
3087			const char *expected,
3088			const xmlChar *value,
3089			const char *message,
3090			const xmlChar *str1,
3091			const xmlChar *str2)
3092{
3093    xmlChar *msg = NULL;
3094
3095    xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3096    if (message == NULL) {
3097	/*
3098	* Use default messages.
3099	*/
3100	if (type != NULL) {
3101	    if (node->type == XML_ATTRIBUTE_NODE)
3102		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3103	    else
3104		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3105		"valid value of ");
3106	    if (! xmlSchemaIsGlobalItem(type))
3107		msg = xmlStrcat(msg, BAD_CAST "the local ");
3108	    else
3109		msg = xmlStrcat(msg, BAD_CAST "the ");
3110
3111	    if (WXS_IS_ATOMIC(type))
3112		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3113	    else if (WXS_IS_LIST(type))
3114		msg = xmlStrcat(msg, BAD_CAST "list type");
3115	    else if (WXS_IS_UNION(type))
3116		msg = xmlStrcat(msg, BAD_CAST "union type");
3117
3118	    if (xmlSchemaIsGlobalItem(type)) {
3119		xmlChar *str = NULL;
3120		msg = xmlStrcat(msg, BAD_CAST " '");
3121		if (type->builtInType != 0) {
3122		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3123		    msg = xmlStrcat(msg, type->name);
3124		} else
3125		    msg = xmlStrcat(msg,
3126			xmlSchemaFormatQName(&str,
3127			    type->targetNamespace, type->name));
3128		msg = xmlStrcat(msg, BAD_CAST "'.");
3129		FREE_AND_NULL(str);
3130	    }
3131	} else {
3132	    if (node->type == XML_ATTRIBUTE_NODE)
3133		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3134	    else
3135		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3136		"valid.");
3137	}
3138	if (expected) {
3139	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3140	    msg = xmlStrcat(msg, BAD_CAST expected);
3141	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3142	} else
3143	    msg = xmlStrcat(msg, BAD_CAST "\n");
3144	if (node->type == XML_ATTRIBUTE_NODE)
3145	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3146	else
3147	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3148    } else {
3149	msg = xmlStrcat(msg, BAD_CAST message);
3150	msg = xmlStrcat(msg, BAD_CAST ".\n");
3151	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3152	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3153    }
3154    /* Cleanup. */
3155    FREE_AND_NULL(msg)
3156}
3157
3158/**
3159 * xmlSchemaPContentErr:
3160 * @ctxt: the schema parser context
3161 * @error: the error code
3162 * @onwerDes: the designation of the holder of the content
3163 * @ownerItem: the owner item of the holder of the content
3164 * @ownerElem: the node of the holder of the content
3165 * @child: the invalid child node
3166 * @message: the optional error message
3167 * @content: the optional string describing the correct content
3168 *
3169 * Reports an error concerning the content of a schema element.
3170 */
3171static void
3172xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3173		     xmlParserErrors error,
3174		     xmlSchemaBasicItemPtr ownerItem,
3175		     xmlNodePtr ownerElem,
3176		     xmlNodePtr child,
3177		     const char *message,
3178		     const char *content)
3179{
3180    xmlChar *des = NULL;
3181
3182    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3183    if (message != NULL)
3184	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3185	    "%s: %s.\n",
3186	    BAD_CAST des, BAD_CAST message);
3187    else {
3188	if (content != NULL) {
3189	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3190		"%s: The content is not valid. Expected is %s.\n",
3191		BAD_CAST des, BAD_CAST content);
3192	} else {
3193	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3194		"%s: The content is not valid.\n",
3195		BAD_CAST des, NULL);
3196	}
3197    }
3198    FREE_AND_NULL(des)
3199}
3200
3201/************************************************************************
3202 * 									*
3203 * 			Streamable error functions                      *
3204 * 									*
3205 ************************************************************************/
3206
3207
3208
3209
3210/************************************************************************
3211 * 									*
3212 * 			Validation helper functions			*
3213 * 									*
3214 ************************************************************************/
3215
3216
3217/************************************************************************
3218 * 									*
3219 * 			Allocation functions				*
3220 * 									*
3221 ************************************************************************/
3222
3223/**
3224 * xmlSchemaNewSchemaForParserCtxt:
3225 * @ctxt:  a schema validation context
3226 *
3227 * Allocate a new Schema structure.
3228 *
3229 * Returns the newly allocated structure or NULL in case or error
3230 */
3231static xmlSchemaPtr
3232xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3233{
3234    xmlSchemaPtr ret;
3235
3236    ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3237    if (ret == NULL) {
3238        xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3239        return (NULL);
3240    }
3241    memset(ret, 0, sizeof(xmlSchema));
3242    ret->dict = ctxt->dict;
3243    xmlDictReference(ret->dict);
3244
3245    return (ret);
3246}
3247
3248/**
3249 * xmlSchemaNewFacet:
3250 *
3251 * Allocate a new Facet structure.
3252 *
3253 * Returns the newly allocated structure or NULL in case or error
3254 */
3255xmlSchemaFacetPtr
3256xmlSchemaNewFacet(void)
3257{
3258    xmlSchemaFacetPtr ret;
3259
3260    ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3261    if (ret == NULL) {
3262        return (NULL);
3263    }
3264    memset(ret, 0, sizeof(xmlSchemaFacet));
3265
3266    return (ret);
3267}
3268
3269/**
3270 * xmlSchemaNewAnnot:
3271 * @ctxt:  a schema validation context
3272 * @node:  a node
3273 *
3274 * Allocate a new annotation structure.
3275 *
3276 * Returns the newly allocated structure or NULL in case or error
3277 */
3278static xmlSchemaAnnotPtr
3279xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3280{
3281    xmlSchemaAnnotPtr ret;
3282
3283    ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3284    if (ret == NULL) {
3285        xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3286        return (NULL);
3287    }
3288    memset(ret, 0, sizeof(xmlSchemaAnnot));
3289    ret->content = node;
3290    return (ret);
3291}
3292
3293static xmlSchemaItemListPtr
3294xmlSchemaItemListCreate(void)
3295{
3296    xmlSchemaItemListPtr ret;
3297
3298    ret = xmlMalloc(sizeof(xmlSchemaItemList));
3299    if (ret == NULL) {
3300	xmlSchemaPErrMemory(NULL,
3301	    "allocating an item list structure", NULL);
3302	return (NULL);
3303    }
3304    memset(ret, 0, sizeof(xmlSchemaItemList));
3305    return (ret);
3306}
3307
3308static void
3309xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3310{
3311    if (list->items != NULL) {
3312	xmlFree(list->items);
3313	list->items = NULL;
3314    }
3315    list->nbItems = 0;
3316    list->sizeItems = 0;
3317}
3318
3319static int
3320xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3321{
3322    if (list->items == NULL) {
3323	list->items = (void **) xmlMalloc(
3324	    20 * sizeof(void *));
3325	if (list->items == NULL) {
3326	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3327	    return(-1);
3328	}
3329	list->sizeItems = 20;
3330    } else if (list->sizeItems <= list->nbItems) {
3331	list->sizeItems *= 2;
3332	list->items = (void **) xmlRealloc(list->items,
3333	    list->sizeItems * sizeof(void *));
3334	if (list->items == NULL) {
3335	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3336	    list->sizeItems = 0;
3337	    return(-1);
3338	}
3339    }
3340    list->items[list->nbItems++] = item;
3341    return(0);
3342}
3343
3344static int
3345xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3346			 int initialSize,
3347			 void *item)
3348{
3349    if (list->items == NULL) {
3350	if (initialSize <= 0)
3351	    initialSize = 1;
3352	list->items = (void **) xmlMalloc(
3353	    initialSize * sizeof(void *));
3354	if (list->items == NULL) {
3355	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3356	    return(-1);
3357	}
3358	list->sizeItems = initialSize;
3359    } else if (list->sizeItems <= list->nbItems) {
3360	list->sizeItems *= 2;
3361	list->items = (void **) xmlRealloc(list->items,
3362	    list->sizeItems * sizeof(void *));
3363	if (list->items == NULL) {
3364	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3365	    list->sizeItems = 0;
3366	    return(-1);
3367	}
3368    }
3369    list->items[list->nbItems++] = item;
3370    return(0);
3371}
3372
3373static int
3374xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3375{
3376    if (list->items == NULL) {
3377	list->items = (void **) xmlMalloc(
3378	    20 * sizeof(void *));
3379	if (list->items == NULL) {
3380	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3381	    return(-1);
3382	}
3383	list->sizeItems = 20;
3384    } else if (list->sizeItems <= list->nbItems) {
3385	list->sizeItems *= 2;
3386	list->items = (void **) xmlRealloc(list->items,
3387	    list->sizeItems * sizeof(void *));
3388	if (list->items == NULL) {
3389	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3390	    list->sizeItems = 0;
3391	    return(-1);
3392	}
3393    }
3394    /*
3395    * Just append if the index is greater/equal than the item count.
3396    */
3397    if (idx >= list->nbItems) {
3398	list->items[list->nbItems++] = item;
3399    } else {
3400	int i;
3401	for (i = list->nbItems; i > idx; i--)
3402	    list->items[i] = list->items[i-1];
3403	list->items[idx] = item;
3404	list->nbItems++;
3405    }
3406    return(0);
3407}
3408
3409#if 0 /* enable if ever needed */
3410static int
3411xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3412			    int initialSize,
3413			    void *item,
3414			    int idx)
3415{
3416    if (list->items == NULL) {
3417	if (initialSize <= 0)
3418	    initialSize = 1;
3419	list->items = (void **) xmlMalloc(
3420	    initialSize * sizeof(void *));
3421	if (list->items == NULL) {
3422	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3423	    return(-1);
3424	}
3425	list->sizeItems = initialSize;
3426    } else if (list->sizeItems <= list->nbItems) {
3427	list->sizeItems *= 2;
3428	list->items = (void **) xmlRealloc(list->items,
3429	    list->sizeItems * sizeof(void *));
3430	if (list->items == NULL) {
3431	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3432	    list->sizeItems = 0;
3433	    return(-1);
3434	}
3435    }
3436    /*
3437    * Just append if the index is greater/equal than the item count.
3438    */
3439    if (idx >= list->nbItems) {
3440	list->items[list->nbItems++] = item;
3441    } else {
3442	int i;
3443	for (i = list->nbItems; i > idx; i--)
3444	    list->items[i] = list->items[i-1];
3445	list->items[idx] = item;
3446	list->nbItems++;
3447    }
3448    return(0);
3449}
3450#endif
3451
3452static int
3453xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3454{
3455    int i;
3456    if ((list->items == NULL) || (idx >= list->nbItems)) {
3457	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3458	    "index error.\n");
3459	return(-1);
3460    }
3461
3462    if (list->nbItems == 1) {
3463	/* TODO: Really free the list? */
3464	xmlFree(list->items);
3465	list->items = NULL;
3466	list->nbItems = 0;
3467	list->sizeItems = 0;
3468    } else if (list->nbItems -1 == idx) {
3469	list->nbItems--;
3470    } else {
3471	for (i = idx; i < list->nbItems -1; i++)
3472	    list->items[i] = list->items[i+1];
3473	list->nbItems--;
3474    }
3475    return(0);
3476}
3477
3478/**
3479 * xmlSchemaItemListFree:
3480 * @annot:  a schema type structure
3481 *
3482 * Deallocate a annotation structure
3483 */
3484static void
3485xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3486{
3487    if (list == NULL)
3488	return;
3489    if (list->items != NULL)
3490	xmlFree(list->items);
3491    xmlFree(list);
3492}
3493
3494static void
3495xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3496{
3497    if (bucket == NULL)
3498	return;
3499    if (bucket->globals != NULL) {
3500	xmlSchemaComponentListFree(bucket->globals);
3501	xmlSchemaItemListFree(bucket->globals);
3502    }
3503    if (bucket->locals != NULL) {
3504	xmlSchemaComponentListFree(bucket->locals);
3505	xmlSchemaItemListFree(bucket->locals);
3506    }
3507    if (bucket->relations != NULL) {
3508	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3509	do {
3510	    prev = cur;
3511	    cur = cur->next;
3512	    xmlFree(prev);
3513	} while (cur != NULL);
3514    }
3515    if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3516	xmlFreeDoc(bucket->doc);
3517    }
3518    if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3519	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3520	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3521    }
3522    xmlFree(bucket);
3523}
3524
3525static xmlSchemaBucketPtr
3526xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3527			 int type, const xmlChar *targetNamespace)
3528{
3529    xmlSchemaBucketPtr ret;
3530    int size;
3531    xmlSchemaPtr mainSchema;
3532
3533    if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3534	PERROR_INT("xmlSchemaBucketCreate",
3535	    "no main schema on constructor");
3536	return(NULL);
3537    }
3538    mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3539    /* Create the schema bucket. */
3540    if (WXS_IS_BUCKET_INCREDEF(type))
3541	size = sizeof(xmlSchemaInclude);
3542    else
3543	size = sizeof(xmlSchemaImport);
3544    ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3545    if (ret == NULL) {
3546	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3547	return(NULL);
3548    }
3549    memset(ret, 0, size);
3550    ret->targetNamespace = targetNamespace;
3551    ret->type = type;
3552    ret->globals = xmlSchemaItemListCreate();
3553    if (ret->globals == NULL) {
3554	xmlFree(ret);
3555	return(NULL);
3556    }
3557    ret->locals = xmlSchemaItemListCreate();
3558    if (ret->locals == NULL) {
3559	xmlFree(ret);
3560	return(NULL);
3561    }
3562    /*
3563    * The following will assure that only the first bucket is marked as
3564    * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3565    * For each following import buckets an xmlSchema will be created.
3566    * An xmlSchema will be created for every distinct targetNamespace.
3567    * We assign the targetNamespace to the schemata here.
3568    */
3569    if (! WXS_HAS_BUCKETS(pctxt)) {
3570	if (WXS_IS_BUCKET_INCREDEF(type)) {
3571	    PERROR_INT("xmlSchemaBucketCreate",
3572		"first bucket but it's an include or redefine");
3573	    xmlSchemaBucketFree(ret);
3574	    return(NULL);
3575	}
3576	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3577	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3578	/* Point to the *main* schema. */
3579	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3580	WXS_IMPBUCKET(ret)->schema = mainSchema;
3581	/*
3582	* Ensure that the main schema gets a targetNamespace.
3583	*/
3584	mainSchema->targetNamespace = targetNamespace;
3585    } else {
3586	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3587	    PERROR_INT("xmlSchemaBucketCreate",
3588		"main bucket but it's not the first one");
3589	    xmlSchemaBucketFree(ret);
3590	    return(NULL);
3591	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3592	    /*
3593	    * Create a schema for imports and assign the
3594	    * targetNamespace.
3595	    */
3596	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3597	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3598		xmlSchemaBucketFree(ret);
3599		return(NULL);
3600	    }
3601	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3602	}
3603    }
3604    if (WXS_IS_BUCKET_IMPMAIN(type)) {
3605	int res;
3606	/*
3607	* Imports go into the "schemasImports" slot of the main *schema*.
3608	* Note that we create an import entry for the main schema as well; i.e.,
3609	* even if there's only one schema, we'll get an import.
3610	*/
3611	if (mainSchema->schemasImports == NULL) {
3612	    mainSchema->schemasImports = xmlHashCreateDict(5,
3613		WXS_CONSTRUCTOR(pctxt)->dict);
3614	    if (mainSchema->schemasImports == NULL) {
3615		xmlSchemaBucketFree(ret);
3616		return(NULL);
3617	    }
3618	}
3619	if (targetNamespace == NULL)
3620	    res = xmlHashAddEntry(mainSchema->schemasImports,
3621		XML_SCHEMAS_NO_NAMESPACE, ret);
3622	else
3623	    res = xmlHashAddEntry(mainSchema->schemasImports,
3624		targetNamespace, ret);
3625	if (res != 0) {
3626	    PERROR_INT("xmlSchemaBucketCreate",
3627		"failed to add the schema bucket to the hash");
3628	    xmlSchemaBucketFree(ret);
3629	    return(NULL);
3630	}
3631    } else {
3632	/* Set the @ownerImport of an include bucket. */
3633	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3634	    WXS_INCBUCKET(ret)->ownerImport =
3635		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3636	else
3637	    WXS_INCBUCKET(ret)->ownerImport =
3638		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3639
3640	/* Includes got into the "includes" slot of the *main* schema. */
3641	if (mainSchema->includes == NULL) {
3642	    mainSchema->includes = xmlSchemaItemListCreate();
3643	    if (mainSchema->includes == NULL) {
3644		xmlSchemaBucketFree(ret);
3645		return(NULL);
3646	    }
3647	}
3648	xmlSchemaItemListAdd(mainSchema->includes, ret);
3649    }
3650    /*
3651    * Add to list of all buckets; this is used for lookup
3652    * during schema construction time only.
3653    */
3654    if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3655	return(NULL);
3656    return(ret);
3657}
3658
3659static int
3660xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3661{
3662    if (*list == NULL) {
3663	*list = xmlSchemaItemListCreate();
3664	if (*list == NULL)
3665	    return(-1);
3666    }
3667    xmlSchemaItemListAddSize(*list, initialSize, item);
3668    return(0);
3669}
3670
3671/**
3672 * xmlSchemaFreeAnnot:
3673 * @annot:  a schema type structure
3674 *
3675 * Deallocate a annotation structure
3676 */
3677static void
3678xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3679{
3680    if (annot == NULL)
3681        return;
3682    if (annot->next == NULL) {
3683	xmlFree(annot);
3684    } else {
3685	xmlSchemaAnnotPtr prev;
3686
3687	do {
3688	    prev = annot;
3689	    annot = annot->next;
3690	    xmlFree(prev);
3691	} while (annot != NULL);
3692    }
3693}
3694
3695/**
3696 * xmlSchemaFreeNotation:
3697 * @schema:  a schema notation structure
3698 *
3699 * Deallocate a Schema Notation structure.
3700 */
3701static void
3702xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3703{
3704    if (nota == NULL)
3705        return;
3706    xmlFree(nota);
3707}
3708
3709/**
3710 * xmlSchemaFreeAttribute:
3711 * @attr:  an attribute declaration
3712 *
3713 * Deallocates an attribute declaration structure.
3714 */
3715static void
3716xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3717{
3718    if (attr == NULL)
3719        return;
3720    if (attr->annot != NULL)
3721	xmlSchemaFreeAnnot(attr->annot);
3722    if (attr->defVal != NULL)
3723	xmlSchemaFreeValue(attr->defVal);
3724    xmlFree(attr);
3725}
3726
3727/**
3728 * xmlSchemaFreeAttributeUse:
3729 * @use:  an attribute use
3730 *
3731 * Deallocates an attribute use structure.
3732 */
3733static void
3734xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3735{
3736    if (use == NULL)
3737        return;
3738    if (use->annot != NULL)
3739	xmlSchemaFreeAnnot(use->annot);
3740    if (use->defVal != NULL)
3741	xmlSchemaFreeValue(use->defVal);
3742    xmlFree(use);
3743}
3744
3745/**
3746 * xmlSchemaFreeAttributeUseProhib:
3747 * @prohib:  an attribute use prohibition
3748 *
3749 * Deallocates an attribute use structure.
3750 */
3751static void
3752xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3753{
3754    if (prohib == NULL)
3755        return;
3756    xmlFree(prohib);
3757}
3758
3759/**
3760 * xmlSchemaFreeWildcardNsSet:
3761 * set:  a schema wildcard namespace
3762 *
3763 * Deallocates a list of wildcard constraint structures.
3764 */
3765static void
3766xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3767{
3768    xmlSchemaWildcardNsPtr next;
3769
3770    while (set != NULL) {
3771	next = set->next;
3772	xmlFree(set);
3773	set = next;
3774    }
3775}
3776
3777/**
3778 * xmlSchemaFreeWildcard:
3779 * @wildcard:  a wildcard structure
3780 *
3781 * Deallocates a wildcard structure.
3782 */
3783void
3784xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3785{
3786    if (wildcard == NULL)
3787        return;
3788    if (wildcard->annot != NULL)
3789        xmlSchemaFreeAnnot(wildcard->annot);
3790    if (wildcard->nsSet != NULL)
3791	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3792    if (wildcard->negNsSet != NULL)
3793	xmlFree(wildcard->negNsSet);
3794    xmlFree(wildcard);
3795}
3796
3797/**
3798 * xmlSchemaFreeAttributeGroup:
3799 * @schema:  a schema attribute group structure
3800 *
3801 * Deallocate a Schema Attribute Group structure.
3802 */
3803static void
3804xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3805{
3806    if (attrGr == NULL)
3807        return;
3808    if (attrGr->annot != NULL)
3809        xmlSchemaFreeAnnot(attrGr->annot);
3810    if (attrGr->attrUses != NULL)
3811	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3812    xmlFree(attrGr);
3813}
3814
3815/**
3816 * xmlSchemaFreeQNameRef:
3817 * @item: a QName reference structure
3818 *
3819 * Deallocatea a QName reference structure.
3820 */
3821static void
3822xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3823{
3824    xmlFree(item);
3825}
3826
3827/**
3828 * xmlSchemaFreeTypeLinkList:
3829 * @alink: a type link
3830 *
3831 * Deallocate a list of types.
3832 */
3833static void
3834xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3835{
3836    xmlSchemaTypeLinkPtr next;
3837
3838    while (link != NULL) {
3839	next = link->next;
3840	xmlFree(link);
3841	link = next;
3842    }
3843}
3844
3845static void
3846xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3847{
3848    xmlSchemaIDCStateObjPtr next;
3849    while (sto != NULL) {
3850	next = sto->next;
3851	if (sto->history != NULL)
3852	    xmlFree(sto->history);
3853	if (sto->xpathCtxt != NULL)
3854	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3855	xmlFree(sto);
3856	sto = next;
3857    }
3858}
3859
3860/**
3861 * xmlSchemaFreeIDC:
3862 * @idc: a identity-constraint definition
3863 *
3864 * Deallocates an identity-constraint definition.
3865 */
3866static void
3867xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3868{
3869    xmlSchemaIDCSelectPtr cur, prev;
3870
3871    if (idcDef == NULL)
3872	return;
3873    if (idcDef->annot != NULL)
3874        xmlSchemaFreeAnnot(idcDef->annot);
3875    /* Selector */
3876    if (idcDef->selector != NULL) {
3877	if (idcDef->selector->xpathComp != NULL)
3878	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3879	xmlFree(idcDef->selector);
3880    }
3881    /* Fields */
3882    if (idcDef->fields != NULL) {
3883	cur = idcDef->fields;
3884	do {
3885	    prev = cur;
3886	    cur = cur->next;
3887	    if (prev->xpathComp != NULL)
3888		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3889	    xmlFree(prev);
3890	} while (cur != NULL);
3891    }
3892    xmlFree(idcDef);
3893}
3894
3895/**
3896 * xmlSchemaFreeElement:
3897 * @schema:  a schema element structure
3898 *
3899 * Deallocate a Schema Element structure.
3900 */
3901static void
3902xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3903{
3904    if (elem == NULL)
3905        return;
3906    if (elem->annot != NULL)
3907        xmlSchemaFreeAnnot(elem->annot);
3908    if (elem->contModel != NULL)
3909        xmlRegFreeRegexp(elem->contModel);
3910    if (elem->defVal != NULL)
3911	xmlSchemaFreeValue(elem->defVal);
3912    xmlFree(elem);
3913}
3914
3915/**
3916 * xmlSchemaFreeFacet:
3917 * @facet:  a schema facet structure
3918 *
3919 * Deallocate a Schema Facet structure.
3920 */
3921void
3922xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3923{
3924    if (facet == NULL)
3925        return;
3926    if (facet->val != NULL)
3927        xmlSchemaFreeValue(facet->val);
3928    if (facet->regexp != NULL)
3929        xmlRegFreeRegexp(facet->regexp);
3930    if (facet->annot != NULL)
3931        xmlSchemaFreeAnnot(facet->annot);
3932    xmlFree(facet);
3933}
3934
3935/**
3936 * xmlSchemaFreeType:
3937 * @type:  a schema type structure
3938 *
3939 * Deallocate a Schema Type structure.
3940 */
3941void
3942xmlSchemaFreeType(xmlSchemaTypePtr type)
3943{
3944    if (type == NULL)
3945        return;
3946    if (type->annot != NULL)
3947        xmlSchemaFreeAnnot(type->annot);
3948    if (type->facets != NULL) {
3949        xmlSchemaFacetPtr facet, next;
3950
3951        facet = type->facets;
3952        while (facet != NULL) {
3953            next = facet->next;
3954            xmlSchemaFreeFacet(facet);
3955            facet = next;
3956        }
3957    }
3958    if (type->attrUses != NULL)
3959	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3960    if (type->memberTypes != NULL)
3961	xmlSchemaFreeTypeLinkList(type->memberTypes);
3962    if (type->facetSet != NULL) {
3963	xmlSchemaFacetLinkPtr next, link;
3964
3965	link = type->facetSet;
3966	do {
3967	    next = link->next;
3968	    xmlFree(link);
3969	    link = next;
3970	} while (link != NULL);
3971    }
3972    if (type->contModel != NULL)
3973        xmlRegFreeRegexp(type->contModel);
3974    xmlFree(type);
3975}
3976
3977/**
3978 * xmlSchemaFreeModelGroupDef:
3979 * @item:  a schema model group definition
3980 *
3981 * Deallocates a schema model group definition.
3982 */
3983static void
3984xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3985{
3986    if (item->annot != NULL)
3987	xmlSchemaFreeAnnot(item->annot);
3988    xmlFree(item);
3989}
3990
3991/**
3992 * xmlSchemaFreeModelGroup:
3993 * @item:  a schema model group
3994 *
3995 * Deallocates a schema model group structure.
3996 */
3997static void
3998xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3999{
4000    if (item->annot != NULL)
4001	xmlSchemaFreeAnnot(item->annot);
4002    xmlFree(item);
4003}
4004
4005static void
4006xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4007{
4008    if ((list == NULL) || (list->nbItems == 0))
4009	return;
4010    {
4011	xmlSchemaTreeItemPtr item;
4012	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4013	int i;
4014
4015	for (i = 0; i < list->nbItems; i++) {
4016	    item = items[i];
4017	    if (item == NULL)
4018		continue;
4019	    switch (item->type) {
4020		case XML_SCHEMA_TYPE_SIMPLE:
4021		case XML_SCHEMA_TYPE_COMPLEX:
4022		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4023		    break;
4024		case XML_SCHEMA_TYPE_ATTRIBUTE:
4025		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4026		    break;
4027		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4028		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4029		    break;
4030		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4031		    xmlSchemaFreeAttributeUseProhib(
4032			(xmlSchemaAttributeUseProhibPtr) item);
4033		    break;
4034		case XML_SCHEMA_TYPE_ELEMENT:
4035		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4036		    break;
4037		case XML_SCHEMA_TYPE_PARTICLE:
4038		    if (item->annot != NULL)
4039			xmlSchemaFreeAnnot(item->annot);
4040		    xmlFree(item);
4041		    break;
4042		case XML_SCHEMA_TYPE_SEQUENCE:
4043		case XML_SCHEMA_TYPE_CHOICE:
4044		case XML_SCHEMA_TYPE_ALL:
4045		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4046		    break;
4047		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4048		    xmlSchemaFreeAttributeGroup(
4049			(xmlSchemaAttributeGroupPtr) item);
4050		    break;
4051		case XML_SCHEMA_TYPE_GROUP:
4052		    xmlSchemaFreeModelGroupDef(
4053			(xmlSchemaModelGroupDefPtr) item);
4054		    break;
4055		case XML_SCHEMA_TYPE_ANY:
4056		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4057		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4058		    break;
4059		case XML_SCHEMA_TYPE_IDC_KEY:
4060		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4061		case XML_SCHEMA_TYPE_IDC_KEYREF:
4062		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4063		    break;
4064		case XML_SCHEMA_TYPE_NOTATION:
4065		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4066		    break;
4067		case XML_SCHEMA_EXTRA_QNAMEREF:
4068		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4069		    break;
4070		default: {
4071		    /* TODO: This should never be hit. */
4072		    xmlSchemaPSimpleInternalErr(NULL,
4073			"Internal error: xmlSchemaComponentListFree, "
4074			"unexpected component type '%s'\n",
4075			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4076			 }
4077		    break;
4078	    }
4079	}
4080	list->nbItems = 0;
4081    }
4082}
4083
4084/**
4085 * xmlSchemaFree:
4086 * @schema:  a schema structure
4087 *
4088 * Deallocate a Schema structure.
4089 */
4090void
4091xmlSchemaFree(xmlSchemaPtr schema)
4092{
4093    if (schema == NULL)
4094        return;
4095    /* @volatiles is not used anymore :-/ */
4096    if (schema->volatiles != NULL)
4097	TODO
4098    /*
4099    * Note that those slots are not responsible for freeing
4100    * schema components anymore; this will now be done by
4101    * the schema buckets.
4102    */
4103    if (schema->notaDecl != NULL)
4104        xmlHashFree(schema->notaDecl, NULL);
4105    if (schema->attrDecl != NULL)
4106        xmlHashFree(schema->attrDecl, NULL);
4107    if (schema->attrgrpDecl != NULL)
4108        xmlHashFree(schema->attrgrpDecl, NULL);
4109    if (schema->elemDecl != NULL)
4110        xmlHashFree(schema->elemDecl, NULL);
4111    if (schema->typeDecl != NULL)
4112        xmlHashFree(schema->typeDecl, NULL);
4113    if (schema->groupDecl != NULL)
4114        xmlHashFree(schema->groupDecl, NULL);
4115    if (schema->idcDef != NULL)
4116        xmlHashFree(schema->idcDef, NULL);
4117
4118    if (schema->schemasImports != NULL)
4119	xmlHashFree(schema->schemasImports,
4120		    (xmlHashDeallocator) xmlSchemaBucketFree);
4121    if (schema->includes != NULL) {
4122	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4123	int i;
4124	for (i = 0; i < list->nbItems; i++) {
4125	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4126	}
4127	xmlSchemaItemListFree(list);
4128    }
4129    if (schema->annot != NULL)
4130        xmlSchemaFreeAnnot(schema->annot);
4131    /* Never free the doc here, since this will be done by the buckets. */
4132
4133    xmlDictFree(schema->dict);
4134    xmlFree(schema);
4135}
4136
4137/************************************************************************
4138 * 									*
4139 * 			Debug functions					*
4140 * 									*
4141 ************************************************************************/
4142
4143#ifdef LIBXML_OUTPUT_ENABLED
4144
4145static void
4146xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4147
4148/**
4149 * xmlSchemaElementDump:
4150 * @elem:  an element
4151 * @output:  the file output
4152 *
4153 * Dump the element
4154 */
4155static void
4156xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4157                     const xmlChar * name ATTRIBUTE_UNUSED,
4158		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4159                     const xmlChar * context ATTRIBUTE_UNUSED)
4160{
4161    if (elem == NULL)
4162        return;
4163
4164
4165    fprintf(output, "Element");
4166    if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4167	fprintf(output, " (global)");
4168    fprintf(output, ": '%s' ", elem->name);
4169    if (namespace != NULL)
4170	fprintf(output, "ns '%s'", namespace);
4171    fprintf(output, "\n");
4172#if 0
4173    if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4174	fprintf(output, "  min %d ", elem->minOccurs);
4175        if (elem->maxOccurs >= UNBOUNDED)
4176            fprintf(output, "max: unbounded\n");
4177        else if (elem->maxOccurs != 1)
4178            fprintf(output, "max: %d\n", elem->maxOccurs);
4179        else
4180            fprintf(output, "\n");
4181    }
4182#endif
4183    /*
4184    * Misc other properties.
4185    */
4186    if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4187	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4188	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4189	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4190	fprintf(output, "  props: ");
4191	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4192	    fprintf(output, "[fixed] ");
4193	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4194	    fprintf(output, "[default] ");
4195	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4196	    fprintf(output, "[abstract] ");
4197	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4198	    fprintf(output, "[nillable] ");
4199	fprintf(output, "\n");
4200    }
4201    /*
4202    * Default/fixed value.
4203    */
4204    if (elem->value != NULL)
4205	fprintf(output, "  value: '%s'\n", elem->value);
4206    /*
4207    * Type.
4208    */
4209    if (elem->namedType != NULL) {
4210	fprintf(output, "  type: '%s' ", elem->namedType);
4211	if (elem->namedTypeNs != NULL)
4212	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4213	else
4214	    fprintf(output, "\n");
4215    } else if (elem->subtypes != NULL) {
4216	/*
4217	* Dump local types.
4218	*/
4219	xmlSchemaTypeDump(elem->subtypes, output);
4220    }
4221    /*
4222    * Substitution group.
4223    */
4224    if (elem->substGroup != NULL) {
4225	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4226	if (elem->substGroupNs != NULL)
4227	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4228	else
4229	    fprintf(output, "\n");
4230    }
4231}
4232
4233/**
4234 * xmlSchemaAnnotDump:
4235 * @output:  the file output
4236 * @annot:  a annotation
4237 *
4238 * Dump the annotation
4239 */
4240static void
4241xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4242{
4243    xmlChar *content;
4244
4245    if (annot == NULL)
4246        return;
4247
4248    content = xmlNodeGetContent(annot->content);
4249    if (content != NULL) {
4250        fprintf(output, "  Annot: %s\n", content);
4251        xmlFree(content);
4252    } else
4253        fprintf(output, "  Annot: empty\n");
4254}
4255
4256/**
4257 * xmlSchemaContentModelDump:
4258 * @particle: the schema particle
4259 * @output: the file output
4260 * @depth: the depth used for intentation
4261 *
4262 * Dump a SchemaType structure
4263 */
4264static void
4265xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4266{
4267    xmlChar *str = NULL;
4268    xmlSchemaTreeItemPtr term;
4269    char shift[100];
4270    int i;
4271
4272    if (particle == NULL)
4273	return;
4274    for (i = 0;((i < depth) && (i < 25));i++)
4275        shift[2 * i] = shift[2 * i + 1] = ' ';
4276    shift[2 * i] = shift[2 * i + 1] = 0;
4277    fprintf(output, "%s", shift);
4278    if (particle->children == NULL) {
4279	fprintf(output, "MISSING particle term\n");
4280	return;
4281    }
4282    term = particle->children;
4283    if (term == NULL) {
4284	fprintf(output, "(NULL)");
4285    } else {
4286	switch (term->type) {
4287	    case XML_SCHEMA_TYPE_ELEMENT:
4288		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4289		    ((xmlSchemaElementPtr)term)->targetNamespace,
4290		    ((xmlSchemaElementPtr)term)->name));
4291		FREE_AND_NULL(str);
4292		break;
4293	    case XML_SCHEMA_TYPE_SEQUENCE:
4294		fprintf(output, "SEQUENCE");
4295		break;
4296	    case XML_SCHEMA_TYPE_CHOICE:
4297		fprintf(output, "CHOICE");
4298		break;
4299	    case XML_SCHEMA_TYPE_ALL:
4300		fprintf(output, "ALL");
4301		break;
4302	    case XML_SCHEMA_TYPE_ANY:
4303		fprintf(output, "ANY");
4304		break;
4305	    default:
4306		fprintf(output, "UNKNOWN\n");
4307		return;
4308	}
4309    }
4310    if (particle->minOccurs != 1)
4311	fprintf(output, " min: %d", particle->minOccurs);
4312    if (particle->maxOccurs >= UNBOUNDED)
4313	fprintf(output, " max: unbounded");
4314    else if (particle->maxOccurs != 1)
4315	fprintf(output, " max: %d", particle->maxOccurs);
4316    fprintf(output, "\n");
4317    if (term &&
4318	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4319	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4320	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4321	 (term->children != NULL)) {
4322	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4323	    output, depth +1);
4324    }
4325    if (particle->next != NULL)
4326	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4327		output, depth);
4328}
4329
4330/**
4331 * xmlSchemaAttrUsesDump:
4332 * @uses:  attribute uses list
4333 * @output:  the file output
4334 *
4335 * Dumps a list of attribute use components.
4336 */
4337static void
4338xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4339{
4340    xmlSchemaAttributeUsePtr use;
4341    xmlSchemaAttributeUseProhibPtr prohib;
4342    xmlSchemaQNameRefPtr ref;
4343    const xmlChar *name, *tns;
4344    xmlChar *str = NULL;
4345    int i;
4346
4347    if ((uses == NULL) || (uses->nbItems == 0))
4348        return;
4349
4350    fprintf(output, "  attributes:\n");
4351    for (i = 0; i < uses->nbItems; i++) {
4352	use = uses->items[i];
4353	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4354	    fprintf(output, "  [prohibition] ");
4355	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4356	    name = prohib->name;
4357	    tns = prohib->targetNamespace;
4358	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4359	    fprintf(output, "  [reference] ");
4360	    ref = (xmlSchemaQNameRefPtr) use;
4361	    name = ref->name;
4362	    tns = ref->targetNamespace;
4363	} else {
4364	    fprintf(output, "  [use] ");
4365	    name = WXS_ATTRUSE_DECL_NAME(use);
4366	    tns = WXS_ATTRUSE_DECL_TNS(use);
4367	}
4368	fprintf(output, "'%s'\n",
4369	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4370	FREE_AND_NULL(str);
4371    }
4372}
4373
4374/**
4375 * xmlSchemaTypeDump:
4376 * @output:  the file output
4377 * @type:  a type structure
4378 *
4379 * Dump a SchemaType structure
4380 */
4381static void
4382xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4383{
4384    if (type == NULL) {
4385        fprintf(output, "Type: NULL\n");
4386        return;
4387    }
4388    fprintf(output, "Type: ");
4389    if (type->name != NULL)
4390        fprintf(output, "'%s' ", type->name);
4391    else
4392        fprintf(output, "(no name) ");
4393    if (type->targetNamespace != NULL)
4394	fprintf(output, "ns '%s' ", type->targetNamespace);
4395    switch (type->type) {
4396        case XML_SCHEMA_TYPE_BASIC:
4397            fprintf(output, "[basic] ");
4398            break;
4399        case XML_SCHEMA_TYPE_SIMPLE:
4400            fprintf(output, "[simple] ");
4401            break;
4402        case XML_SCHEMA_TYPE_COMPLEX:
4403            fprintf(output, "[complex] ");
4404            break;
4405        case XML_SCHEMA_TYPE_SEQUENCE:
4406            fprintf(output, "[sequence] ");
4407            break;
4408        case XML_SCHEMA_TYPE_CHOICE:
4409            fprintf(output, "[choice] ");
4410            break;
4411        case XML_SCHEMA_TYPE_ALL:
4412            fprintf(output, "[all] ");
4413            break;
4414        case XML_SCHEMA_TYPE_UR:
4415            fprintf(output, "[ur] ");
4416            break;
4417        case XML_SCHEMA_TYPE_RESTRICTION:
4418            fprintf(output, "[restriction] ");
4419            break;
4420        case XML_SCHEMA_TYPE_EXTENSION:
4421            fprintf(output, "[extension] ");
4422            break;
4423        default:
4424            fprintf(output, "[unknown type %d] ", type->type);
4425            break;
4426    }
4427    fprintf(output, "content: ");
4428    switch (type->contentType) {
4429        case XML_SCHEMA_CONTENT_UNKNOWN:
4430            fprintf(output, "[unknown] ");
4431            break;
4432        case XML_SCHEMA_CONTENT_EMPTY:
4433            fprintf(output, "[empty] ");
4434            break;
4435        case XML_SCHEMA_CONTENT_ELEMENTS:
4436            fprintf(output, "[element] ");
4437            break;
4438        case XML_SCHEMA_CONTENT_MIXED:
4439            fprintf(output, "[mixed] ");
4440            break;
4441        case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4442	/* not used. */
4443            break;
4444        case XML_SCHEMA_CONTENT_BASIC:
4445            fprintf(output, "[basic] ");
4446            break;
4447        case XML_SCHEMA_CONTENT_SIMPLE:
4448            fprintf(output, "[simple] ");
4449            break;
4450        case XML_SCHEMA_CONTENT_ANY:
4451            fprintf(output, "[any] ");
4452            break;
4453    }
4454    fprintf(output, "\n");
4455    if (type->base != NULL) {
4456        fprintf(output, "  base type: '%s'", type->base);
4457	if (type->baseNs != NULL)
4458	    fprintf(output, " ns '%s'\n", type->baseNs);
4459	else
4460	    fprintf(output, "\n");
4461    }
4462    if (type->attrUses != NULL)
4463	xmlSchemaAttrUsesDump(type->attrUses, output);
4464    if (type->annot != NULL)
4465        xmlSchemaAnnotDump(output, type->annot);
4466#ifdef DUMP_CONTENT_MODEL
4467    if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4468	(type->subtypes != NULL)) {
4469	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4470	    output, 1);
4471    }
4472#endif
4473}
4474
4475/**
4476 * xmlSchemaDump:
4477 * @output:  the file output
4478 * @schema:  a schema structure
4479 *
4480 * Dump a Schema structure.
4481 */
4482void
4483xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4484{
4485    if (output == NULL)
4486        return;
4487    if (schema == NULL) {
4488        fprintf(output, "Schemas: NULL\n");
4489        return;
4490    }
4491    fprintf(output, "Schemas: ");
4492    if (schema->name != NULL)
4493        fprintf(output, "%s, ", schema->name);
4494    else
4495        fprintf(output, "no name, ");
4496    if (schema->targetNamespace != NULL)
4497        fprintf(output, "%s", (const char *) schema->targetNamespace);
4498    else
4499        fprintf(output, "no target namespace");
4500    fprintf(output, "\n");
4501    if (schema->annot != NULL)
4502        xmlSchemaAnnotDump(output, schema->annot);
4503    xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4504                output);
4505    xmlHashScanFull(schema->elemDecl,
4506                    (xmlHashScannerFull) xmlSchemaElementDump, output);
4507}
4508
4509#ifdef DEBUG_IDC_NODE_TABLE
4510/**
4511 * xmlSchemaDebugDumpIDCTable:
4512 * @vctxt: the WXS validation context
4513 *
4514 * Displays the current IDC table for debug purposes.
4515 */
4516static void
4517xmlSchemaDebugDumpIDCTable(FILE * output,
4518			   const xmlChar *namespaceName,
4519			   const xmlChar *localName,
4520			   xmlSchemaPSVIIDCBindingPtr bind)
4521{
4522    xmlChar *str = NULL;
4523    const xmlChar *value;
4524    xmlSchemaPSVIIDCNodePtr tab;
4525    xmlSchemaPSVIIDCKeyPtr key;
4526    int i, j, res;
4527
4528    fprintf(output, "IDC: TABLES on '%s'\n",
4529	xmlSchemaFormatQName(&str, namespaceName, localName));
4530    FREE_AND_NULL(str)
4531
4532    if (bind == NULL)
4533	return;
4534    do {
4535	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4536	    xmlSchemaGetComponentQName(&str,
4537		bind->definition), bind->nbNodes);
4538	FREE_AND_NULL(str)
4539	for (i = 0; i < bind->nbNodes; i++) {
4540	    tab = bind->nodeTable[i];
4541	    fprintf(output, "         ( ");
4542	    for (j = 0; j < bind->definition->nbFields; j++) {
4543		key = tab->keys[j];
4544		if ((key != NULL) && (key->val != NULL)) {
4545		    res = xmlSchemaGetCanonValue(key->val, &value);
4546		    if (res >= 0)
4547			fprintf(output, "'%s' ", value);
4548		    else
4549			fprintf(output, "CANON-VALUE-FAILED ");
4550		    if (res == 0)
4551			FREE_AND_NULL(value)
4552		} else if (key != NULL)
4553		    fprintf(output, "(no val), ");
4554		else
4555		    fprintf(output, "(key missing), ");
4556	    }
4557	    fprintf(output, ")\n");
4558	}
4559	if (bind->dupls && bind->dupls->nbItems) {
4560	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4561	    for (i = 0; i < bind->dupls->nbItems; i++) {
4562		tab = bind->dupls->items[i];
4563		fprintf(output, "         ( ");
4564		for (j = 0; j < bind->definition->nbFields; j++) {
4565		    key = tab->keys[j];
4566		    if ((key != NULL) && (key->val != NULL)) {
4567			res = xmlSchemaGetCanonValue(key->val, &value);
4568			if (res >= 0)
4569			    fprintf(output, "'%s' ", value);
4570			else
4571			    fprintf(output, "CANON-VALUE-FAILED ");
4572			if (res == 0)
4573			    FREE_AND_NULL(value)
4574		    } else if (key != NULL)
4575		    fprintf(output, "(no val), ");
4576			else
4577			    fprintf(output, "(key missing), ");
4578		}
4579		fprintf(output, ")\n");
4580	    }
4581	}
4582	bind = bind->next;
4583    } while (bind != NULL);
4584}
4585#endif /* DEBUG_IDC */
4586#endif /* LIBXML_OUTPUT_ENABLED */
4587
4588/************************************************************************
4589 *									*
4590 * 			Utilities					*
4591 *									*
4592 ************************************************************************/
4593
4594/**
4595 * xmlSchemaGetPropNode:
4596 * @node: the element node
4597 * @name: the name of the attribute
4598 *
4599 * Seeks an attribute with a name of @name in
4600 * no namespace.
4601 *
4602 * Returns the attribute or NULL if not present.
4603 */
4604static xmlAttrPtr
4605xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4606{
4607    xmlAttrPtr prop;
4608
4609    if ((node == NULL) || (name == NULL))
4610	return(NULL);
4611    prop = node->properties;
4612    while (prop != NULL) {
4613        if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4614	    return(prop);
4615	prop = prop->next;
4616    }
4617    return (NULL);
4618}
4619
4620/**
4621 * xmlSchemaGetPropNodeNs:
4622 * @node: the element node
4623 * @uri: the uri
4624 * @name: the name of the attribute
4625 *
4626 * Seeks an attribute with a local name of @name and
4627 * a namespace URI of @uri.
4628 *
4629 * Returns the attribute or NULL if not present.
4630 */
4631static xmlAttrPtr
4632xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4633{
4634    xmlAttrPtr prop;
4635
4636    if ((node == NULL) || (name == NULL))
4637	return(NULL);
4638    prop = node->properties;
4639    while (prop != NULL) {
4640	if ((prop->ns != NULL) &&
4641	    xmlStrEqual(prop->name, BAD_CAST name) &&
4642	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4643	    return(prop);
4644	prop = prop->next;
4645    }
4646    return (NULL);
4647}
4648
4649static const xmlChar *
4650xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4651{
4652    xmlChar *val;
4653    const xmlChar *ret;
4654
4655    val = xmlNodeGetContent(node);
4656    if (val == NULL)
4657	val = xmlStrdup((xmlChar *)"");
4658    ret = xmlDictLookup(ctxt->dict, val, -1);
4659    xmlFree(val);
4660    return(ret);
4661}
4662
4663static const xmlChar *
4664xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4665{
4666    return((const xmlChar*) xmlNodeGetContent(node));
4667}
4668
4669/**
4670 * xmlSchemaGetProp:
4671 * @ctxt: the parser context
4672 * @node: the node
4673 * @name: the property name
4674 *
4675 * Read a attribute value and internalize the string
4676 *
4677 * Returns the string or NULL if not present.
4678 */
4679static const xmlChar *
4680xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4681                 const char *name)
4682{
4683    xmlChar *val;
4684    const xmlChar *ret;
4685
4686    val = xmlGetNoNsProp(node, BAD_CAST name);
4687    if (val == NULL)
4688        return(NULL);
4689    ret = xmlDictLookup(ctxt->dict, val, -1);
4690    xmlFree(val);
4691    return(ret);
4692}
4693
4694/************************************************************************
4695 * 									*
4696 * 			Parsing functions				*
4697 * 									*
4698 ************************************************************************/
4699
4700#define WXS_FIND_GLOBAL_ITEM(slot)			\
4701    if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4702	ret = xmlHashLookup(schema->slot, name); \
4703	if (ret != NULL) goto exit; \
4704    } \
4705    if (xmlHashSize(schema->schemasImports) > 1) { \
4706	xmlSchemaImportPtr import; \
4707	if (nsName == NULL) \
4708	    import = xmlHashLookup(schema->schemasImports, \
4709		XML_SCHEMAS_NO_NAMESPACE); \
4710	else \
4711	    import = xmlHashLookup(schema->schemasImports, nsName); \
4712	if (import == NULL) \
4713	    goto exit; \
4714	ret = xmlHashLookup(import->schema->slot, name); \
4715    }
4716
4717/**
4718 * xmlSchemaGetElem:
4719 * @schema:  the schema context
4720 * @name:  the element name
4721 * @ns:  the element namespace
4722 *
4723 * Lookup a global element declaration in the schema.
4724 *
4725 * Returns the element declaration or NULL if not found.
4726 */
4727static xmlSchemaElementPtr
4728xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4729                 const xmlChar * nsName)
4730{
4731    xmlSchemaElementPtr ret = NULL;
4732
4733    if ((name == NULL) || (schema == NULL))
4734        return(NULL);
4735    if (schema != NULL) {
4736	WXS_FIND_GLOBAL_ITEM(elemDecl)
4737    }
4738exit:
4739#ifdef DEBUG
4740    if (ret == NULL) {
4741        if (nsName == NULL)
4742            fprintf(stderr, "Unable to lookup element decl. %s", name);
4743        else
4744            fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4745                    nsName);
4746    }
4747#endif
4748    return (ret);
4749}
4750
4751/**
4752 * xmlSchemaGetType:
4753 * @schema:  the main schema
4754 * @name:  the type's name
4755 * nsName:  the type's namespace
4756 *
4757 * Lookup a type in the schemas or the predefined types
4758 *
4759 * Returns the group definition or NULL if not found.
4760 */
4761static xmlSchemaTypePtr
4762xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4763                 const xmlChar * nsName)
4764{
4765    xmlSchemaTypePtr ret = NULL;
4766
4767    if (name == NULL)
4768        return (NULL);
4769    /* First try the built-in types. */
4770    if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4771	ret = xmlSchemaGetPredefinedType(name, nsName);
4772	if (ret != NULL)
4773	    goto exit;
4774	/*
4775	* Note that we try the parsed schemas as well here
4776	* since one might have parsed the S4S, which contain more
4777	* than the built-in types.
4778	* TODO: Can we optimize this?
4779	*/
4780    }
4781    if (schema != NULL) {
4782	WXS_FIND_GLOBAL_ITEM(typeDecl)
4783    }
4784exit:
4785
4786#ifdef DEBUG
4787    if (ret == NULL) {
4788        if (nsName == NULL)
4789            fprintf(stderr, "Unable to lookup type %s", name);
4790        else
4791            fprintf(stderr, "Unable to lookup type %s:%s", name,
4792                    nsName);
4793    }
4794#endif
4795    return (ret);
4796}
4797
4798/**
4799 * xmlSchemaGetAttributeDecl:
4800 * @schema:  the context of the schema
4801 * @name:  the name of the attribute
4802 * @ns:  the target namespace of the attribute
4803 *
4804 * Lookup a an attribute in the schema or imported schemas
4805 *
4806 * Returns the attribute declaration or NULL if not found.
4807 */
4808static xmlSchemaAttributePtr
4809xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4810                 const xmlChar * nsName)
4811{
4812    xmlSchemaAttributePtr ret = NULL;
4813
4814    if ((name == NULL) || (schema == NULL))
4815        return (NULL);
4816    if (schema != NULL) {
4817	WXS_FIND_GLOBAL_ITEM(attrDecl)
4818    }
4819exit:
4820#ifdef DEBUG
4821    if (ret == NULL) {
4822        if (nsName == NULL)
4823            fprintf(stderr, "Unable to lookup attribute %s", name);
4824        else
4825            fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4826                    nsName);
4827    }
4828#endif
4829    return (ret);
4830}
4831
4832/**
4833 * xmlSchemaGetAttributeGroup:
4834 * @schema:  the context of the schema
4835 * @name:  the name of the attribute group
4836 * @ns:  the target namespace of the attribute group
4837 *
4838 * Lookup a an attribute group in the schema or imported schemas
4839 *
4840 * Returns the attribute group definition or NULL if not found.
4841 */
4842static xmlSchemaAttributeGroupPtr
4843xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4844                 const xmlChar * nsName)
4845{
4846    xmlSchemaAttributeGroupPtr ret = NULL;
4847
4848    if ((name == NULL) || (schema == NULL))
4849        return (NULL);
4850    if (schema != NULL) {
4851	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4852    }
4853exit:
4854    /* TODO:
4855    if ((ret != NULL) && (ret->redef != NULL)) {
4856	* Return the last redefinition. *
4857	ret = ret->redef;
4858    }
4859    */
4860#ifdef DEBUG
4861    if (ret == NULL) {
4862        if (nsName == NULL)
4863            fprintf(stderr, "Unable to lookup attribute group %s", name);
4864        else
4865            fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4866                    nsName);
4867    }
4868#endif
4869    return (ret);
4870}
4871
4872/**
4873 * xmlSchemaGetGroup:
4874 * @schema:  the context of the schema
4875 * @name:  the name of the group
4876 * @ns:  the target namespace of the group
4877 *
4878 * Lookup a group in the schema or imported schemas
4879 *
4880 * Returns the group definition or NULL if not found.
4881 */
4882static xmlSchemaModelGroupDefPtr
4883xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4884                 const xmlChar * nsName)
4885{
4886    xmlSchemaModelGroupDefPtr ret = NULL;
4887
4888    if ((name == NULL) || (schema == NULL))
4889        return (NULL);
4890    if (schema != NULL) {
4891	WXS_FIND_GLOBAL_ITEM(groupDecl)
4892    }
4893exit:
4894
4895#ifdef DEBUG
4896    if (ret == NULL) {
4897        if (nsName == NULL)
4898            fprintf(stderr, "Unable to lookup group %s", name);
4899        else
4900            fprintf(stderr, "Unable to lookup group %s:%s", name,
4901                    nsName);
4902    }
4903#endif
4904    return (ret);
4905}
4906
4907static xmlSchemaNotationPtr
4908xmlSchemaGetNotation(xmlSchemaPtr schema,
4909		     const xmlChar *name,
4910		     const xmlChar *nsName)
4911{
4912    xmlSchemaNotationPtr ret = NULL;
4913
4914    if ((name == NULL) || (schema == NULL))
4915        return (NULL);
4916    if (schema != NULL) {
4917	WXS_FIND_GLOBAL_ITEM(notaDecl)
4918    }
4919exit:
4920    return (ret);
4921}
4922
4923static xmlSchemaIDCPtr
4924xmlSchemaGetIDC(xmlSchemaPtr schema,
4925		const xmlChar *name,
4926		const xmlChar *nsName)
4927{
4928    xmlSchemaIDCPtr ret = NULL;
4929
4930    if ((name == NULL) || (schema == NULL))
4931        return (NULL);
4932    if (schema != NULL) {
4933	WXS_FIND_GLOBAL_ITEM(idcDef)
4934    }
4935exit:
4936    return (ret);
4937}
4938
4939/**
4940 * xmlSchemaGetNamedComponent:
4941 * @schema:  the schema
4942 * @name:  the name of the group
4943 * @ns:  the target namespace of the group
4944 *
4945 * Lookup a group in the schema or imported schemas
4946 *
4947 * Returns the group definition or NULL if not found.
4948 */
4949static xmlSchemaBasicItemPtr
4950xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4951			   xmlSchemaTypeType itemType,
4952			   const xmlChar *name,
4953			   const xmlChar *targetNs)
4954{
4955    switch (itemType) {
4956	case XML_SCHEMA_TYPE_GROUP:
4957	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4958		name, targetNs));
4959	case XML_SCHEMA_TYPE_ELEMENT:
4960	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4961		name, targetNs));
4962	default:
4963	    TODO
4964	    return (NULL);
4965    }
4966}
4967
4968/************************************************************************
4969 * 									*
4970 * 			Parsing functions				*
4971 * 									*
4972 ************************************************************************/
4973
4974#define IS_BLANK_NODE(n)						\
4975    (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4976
4977/**
4978 * xmlSchemaIsBlank:
4979 * @str:  a string
4980 * @len: the length of the string or -1
4981 *
4982 * Check if a string is ignorable
4983 *
4984 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4985 */
4986static int
4987xmlSchemaIsBlank(xmlChar * str, int len)
4988{
4989    if (str == NULL)
4990        return (1);
4991    if (len < 0) {
4992	while (*str != 0) {
4993	    if (!(IS_BLANK_CH(*str)))
4994		return (0);
4995	    str++;
4996	}
4997    } else while ((*str != 0) && (len != 0)) {
4998	if (!(IS_BLANK_CH(*str)))
4999	    return (0);
5000	str++;
5001	len--;
5002    }
5003
5004    return (1);
5005}
5006
5007#define WXS_COMP_NAME(c, t) ((t) (c))->name
5008#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5009/*
5010* xmlSchemaFindRedefCompInGraph:
5011* ATTENTION TODO: This uses pointer comp. for strings.
5012*/
5013static xmlSchemaBasicItemPtr
5014xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5015			      xmlSchemaTypeType type,
5016			      const xmlChar *name,
5017			      const xmlChar *nsName)
5018{
5019    xmlSchemaBasicItemPtr ret;
5020    int i;
5021
5022    if ((bucket == NULL) || (name == NULL))
5023	return(NULL);
5024    if ((bucket->globals == NULL) ||
5025	(bucket->globals->nbItems == 0))
5026	goto subschemas;
5027    /*
5028    * Search in global components.
5029    */
5030    for (i = 0; i < bucket->globals->nbItems; i++) {
5031	ret = bucket->globals->items[i];
5032	if (ret->type == type) {
5033	    switch (type) {
5034		case XML_SCHEMA_TYPE_COMPLEX:
5035		case XML_SCHEMA_TYPE_SIMPLE:
5036		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5037			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5038			nsName))
5039		    {
5040			return(ret);
5041		    }
5042		    break;
5043		case XML_SCHEMA_TYPE_GROUP:
5044		    if ((WXS_COMP_NAME(ret,
5045			    xmlSchemaModelGroupDefPtr) == name) &&
5046			(WXS_COMP_TNS(ret,
5047			    xmlSchemaModelGroupDefPtr) == nsName))
5048		    {
5049			return(ret);
5050		    }
5051		    break;
5052		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5053		    if ((WXS_COMP_NAME(ret,
5054			    xmlSchemaAttributeGroupPtr) == name) &&
5055			(WXS_COMP_TNS(ret,
5056			    xmlSchemaAttributeGroupPtr) == nsName))
5057		    {
5058			return(ret);
5059		    }
5060		    break;
5061		default:
5062		    /* Should not be hit. */
5063		    return(NULL);
5064	    }
5065	}
5066    }
5067subschemas:
5068    /*
5069    * Process imported/included schemas.
5070    */
5071    if (bucket->relations != NULL) {
5072	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5073
5074	/*
5075	* TODO: Marking the bucket will not avoid multiple searches
5076	* in the same schema, but avoids at least circularity.
5077	*/
5078	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5079	do {
5080	    if ((rel->bucket != NULL) &&
5081		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5082		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5083		    type, name, nsName);
5084		if (ret != NULL)
5085		    return(ret);
5086	    }
5087	    rel = rel->next;
5088	} while (rel != NULL);
5089	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5090    }
5091    return(NULL);
5092}
5093
5094/**
5095 * xmlSchemaAddNotation:
5096 * @ctxt:  a schema parser context
5097 * @schema:  the schema being built
5098 * @name:  the item name
5099 *
5100 * Add an XML schema annotation declaration
5101 * *WARNING* this interface is highly subject to change
5102 *
5103 * Returns the new struture or NULL in case of error
5104 */
5105static xmlSchemaNotationPtr
5106xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5107                     const xmlChar *name, const xmlChar *nsName,
5108		     xmlNodePtr node ATTRIBUTE_UNUSED)
5109{
5110    xmlSchemaNotationPtr ret = NULL;
5111
5112    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5113        return (NULL);
5114
5115    ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5116    if (ret == NULL) {
5117        xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5118        return (NULL);
5119    }
5120    memset(ret, 0, sizeof(xmlSchemaNotation));
5121    ret->type = XML_SCHEMA_TYPE_NOTATION;
5122    ret->name = name;
5123    ret->targetNamespace = nsName;
5124    /* TODO: do we need the node to be set?
5125    * ret->node = node;*/
5126    WXS_ADD_GLOBAL(ctxt, ret);
5127    return (ret);
5128}
5129
5130/**
5131 * xmlSchemaAddAttribute:
5132 * @ctxt:  a schema parser context
5133 * @schema:  the schema being built
5134 * @name:  the item name
5135 * @namespace:  the namespace
5136 *
5137 * Add an XML schema Attrribute declaration
5138 * *WARNING* this interface is highly subject to change
5139 *
5140 * Returns the new struture or NULL in case of error
5141 */
5142static xmlSchemaAttributePtr
5143xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5144                      const xmlChar * name, const xmlChar * nsName,
5145		      xmlNodePtr node, int topLevel)
5146{
5147    xmlSchemaAttributePtr ret = NULL;
5148
5149    if ((ctxt == NULL) || (schema == NULL))
5150        return (NULL);
5151
5152    ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5153    if (ret == NULL) {
5154        xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5155        return (NULL);
5156    }
5157    memset(ret, 0, sizeof(xmlSchemaAttribute));
5158    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5159    ret->node = node;
5160    ret->name = name;
5161    ret->targetNamespace = nsName;
5162
5163    if (topLevel)
5164	WXS_ADD_GLOBAL(ctxt, ret);
5165    else
5166	WXS_ADD_LOCAL(ctxt, ret);
5167    WXS_ADD_PENDING(ctxt, ret);
5168    return (ret);
5169}
5170
5171/**
5172 * xmlSchemaAddAttributeUse:
5173 * @ctxt:  a schema parser context
5174 * @schema:  the schema being built
5175 * @name:  the item name
5176 * @namespace:  the namespace
5177 *
5178 * Add an XML schema Attrribute declaration
5179 * *WARNING* this interface is highly subject to change
5180 *
5181 * Returns the new struture or NULL in case of error
5182 */
5183static xmlSchemaAttributeUsePtr
5184xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5185			 xmlNodePtr node)
5186{
5187    xmlSchemaAttributeUsePtr ret = NULL;
5188
5189    if (pctxt == NULL)
5190        return (NULL);
5191
5192    ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5193    if (ret == NULL) {
5194        xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5195        return (NULL);
5196    }
5197    memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5198    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5199    ret->node = node;
5200
5201    WXS_ADD_LOCAL(pctxt, ret);
5202    return (ret);
5203}
5204
5205/*
5206* xmlSchemaAddRedef:
5207*
5208* Adds a redefinition information. This is used at a later stage to:
5209* resolve references to the redefined components and to check constraints.
5210*/
5211static xmlSchemaRedefPtr
5212xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5213		  xmlSchemaBucketPtr targetBucket,
5214		  void *item,
5215		  const xmlChar *refName,
5216		  const xmlChar *refTargetNs)
5217{
5218    xmlSchemaRedefPtr ret;
5219
5220    ret = (xmlSchemaRedefPtr)
5221	xmlMalloc(sizeof(xmlSchemaRedef));
5222    if (ret == NULL) {
5223	xmlSchemaPErrMemory(pctxt,
5224	    "allocating redefinition info", NULL);
5225	return (NULL);
5226    }
5227    memset(ret, 0, sizeof(xmlSchemaRedef));
5228    ret->item = item;
5229    ret->targetBucket = targetBucket;
5230    ret->refName = refName;
5231    ret->refTargetNs = refTargetNs;
5232    if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5233	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5234    else
5235	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5236    WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5237
5238    return (ret);
5239}
5240
5241/**
5242 * xmlSchemaAddAttributeGroupDefinition:
5243 * @ctxt:  a schema parser context
5244 * @schema:  the schema being built
5245 * @name:  the item name
5246 * @nsName:  the target namespace
5247 * @node: the corresponding node
5248 *
5249 * Add an XML schema Attrribute Group definition.
5250 *
5251 * Returns the new struture or NULL in case of error
5252 */
5253static xmlSchemaAttributeGroupPtr
5254xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5255                           xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5256			   const xmlChar *name,
5257			   const xmlChar *nsName,
5258			   xmlNodePtr node)
5259{
5260    xmlSchemaAttributeGroupPtr ret = NULL;
5261
5262    if ((pctxt == NULL) || (name == NULL))
5263        return (NULL);
5264
5265    ret = (xmlSchemaAttributeGroupPtr)
5266        xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5267    if (ret == NULL) {
5268	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5269	return (NULL);
5270    }
5271    memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5272    ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5273    ret->name = name;
5274    ret->targetNamespace = nsName;
5275    ret->node = node;
5276
5277    /* TODO: Remove the flag. */
5278    ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5279    if (pctxt->isRedefine) {
5280	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5281	    ret, name, nsName);
5282	if (pctxt->redef == NULL) {
5283	    xmlFree(ret);
5284	    return(NULL);
5285	}
5286	pctxt->redefCounter = 0;
5287    }
5288    WXS_ADD_GLOBAL(pctxt, ret);
5289    WXS_ADD_PENDING(pctxt, ret);
5290    return (ret);
5291}
5292
5293/**
5294 * xmlSchemaAddElement:
5295 * @ctxt:  a schema parser context
5296 * @schema:  the schema being built
5297 * @name:  the type name
5298 * @namespace:  the type namespace
5299 *
5300 * Add an XML schema Element declaration
5301 * *WARNING* this interface is highly subject to change
5302 *
5303 * Returns the new struture or NULL in case of error
5304 */
5305static xmlSchemaElementPtr
5306xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5307                    const xmlChar * name, const xmlChar * nsName,
5308		    xmlNodePtr node, int topLevel)
5309{
5310    xmlSchemaElementPtr ret = NULL;
5311
5312    if ((ctxt == NULL) || (name == NULL))
5313        return (NULL);
5314
5315    ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5316    if (ret == NULL) {
5317        xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5318        return (NULL);
5319    }
5320    memset(ret, 0, sizeof(xmlSchemaElement));
5321    ret->type = XML_SCHEMA_TYPE_ELEMENT;
5322    ret->name = name;
5323    ret->targetNamespace = nsName;
5324    ret->node = node;
5325
5326    if (topLevel)
5327	WXS_ADD_GLOBAL(ctxt, ret);
5328    else
5329	WXS_ADD_LOCAL(ctxt, ret);
5330    WXS_ADD_PENDING(ctxt, ret);
5331    return (ret);
5332}
5333
5334/**
5335 * xmlSchemaAddType:
5336 * @ctxt:  a schema parser context
5337 * @schema:  the schema being built
5338 * @name:  the item name
5339 * @namespace:  the namespace
5340 *
5341 * Add an XML schema item
5342 * *WARNING* this interface is highly subject to change
5343 *
5344 * Returns the new struture or NULL in case of error
5345 */
5346static xmlSchemaTypePtr
5347xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5348		 xmlSchemaTypeType type,
5349                 const xmlChar * name, const xmlChar * nsName,
5350		 xmlNodePtr node, int topLevel)
5351{
5352    xmlSchemaTypePtr ret = NULL;
5353
5354    if ((ctxt == NULL) || (schema == NULL))
5355        return (NULL);
5356
5357    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5358    if (ret == NULL) {
5359        xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5360        return (NULL);
5361    }
5362    memset(ret, 0, sizeof(xmlSchemaType));
5363    ret->type = type;
5364    ret->name = name;
5365    ret->targetNamespace = nsName;
5366    ret->node = node;
5367    if (topLevel) {
5368	if (ctxt->isRedefine) {
5369	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5370		ret, name, nsName);
5371	    if (ctxt->redef == NULL) {
5372		xmlFree(ret);
5373		return(NULL);
5374	    }
5375	    ctxt->redefCounter = 0;
5376	}
5377	WXS_ADD_GLOBAL(ctxt, ret);
5378    } else
5379	WXS_ADD_LOCAL(ctxt, ret);
5380    WXS_ADD_PENDING(ctxt, ret);
5381    return (ret);
5382}
5383
5384static xmlSchemaQNameRefPtr
5385xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5386		     xmlSchemaTypeType refType,
5387		     const xmlChar *refName,
5388		     const xmlChar *refNs)
5389{
5390    xmlSchemaQNameRefPtr ret;
5391
5392    ret = (xmlSchemaQNameRefPtr)
5393	xmlMalloc(sizeof(xmlSchemaQNameRef));
5394    if (ret == NULL) {
5395	xmlSchemaPErrMemory(pctxt,
5396	    "allocating QName reference item", NULL);
5397	return (NULL);
5398    }
5399    ret->node = NULL;
5400    ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5401    ret->name = refName;
5402    ret->targetNamespace = refNs;
5403    ret->item = NULL;
5404    ret->itemType = refType;
5405    /*
5406    * Store the reference item in the schema.
5407    */
5408    WXS_ADD_LOCAL(pctxt, ret);
5409    return (ret);
5410}
5411
5412static xmlSchemaAttributeUseProhibPtr
5413xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5414{
5415    xmlSchemaAttributeUseProhibPtr ret;
5416
5417    ret = (xmlSchemaAttributeUseProhibPtr)
5418	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5419    if (ret == NULL) {
5420	xmlSchemaPErrMemory(pctxt,
5421	    "allocating attribute use prohibition", NULL);
5422	return (NULL);
5423    }
5424    memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5425    ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5426    WXS_ADD_LOCAL(pctxt, ret);
5427    return (ret);
5428}
5429
5430
5431/**
5432 * xmlSchemaAddModelGroup:
5433 * @ctxt:  a schema parser context
5434 * @schema:  the schema being built
5435 * @type: the "compositor" type of the model group
5436 * @node: the node in the schema doc
5437 *
5438 * Adds a schema model group
5439 * *WARNING* this interface is highly subject to change
5440 *
5441 * Returns the new struture or NULL in case of error
5442 */
5443static xmlSchemaModelGroupPtr
5444xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5445		       xmlSchemaPtr schema,
5446		       xmlSchemaTypeType type,
5447		       xmlNodePtr node)
5448{
5449    xmlSchemaModelGroupPtr ret = NULL;
5450
5451    if ((ctxt == NULL) || (schema == NULL))
5452        return (NULL);
5453
5454    ret = (xmlSchemaModelGroupPtr)
5455	xmlMalloc(sizeof(xmlSchemaModelGroup));
5456    if (ret == NULL) {
5457	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5458	    NULL);
5459	return (NULL);
5460    }
5461    memset(ret, 0, sizeof(xmlSchemaModelGroup));
5462    ret->type = type;
5463    ret->node = node;
5464    WXS_ADD_LOCAL(ctxt, ret);
5465    if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5466	(type == XML_SCHEMA_TYPE_CHOICE))
5467	WXS_ADD_PENDING(ctxt, ret);
5468    return (ret);
5469}
5470
5471
5472/**
5473 * xmlSchemaAddParticle:
5474 * @ctxt:  a schema parser context
5475 * @schema:  the schema being built
5476 * @node: the corresponding node in the schema doc
5477 * @min: the minOccurs
5478 * @max: the maxOccurs
5479 *
5480 * Adds an XML schema particle component.
5481 * *WARNING* this interface is highly subject to change
5482 *
5483 * Returns the new struture or NULL in case of error
5484 */
5485static xmlSchemaParticlePtr
5486xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5487		     xmlNodePtr node, int min, int max)
5488{
5489    xmlSchemaParticlePtr ret = NULL;
5490    if (ctxt == NULL)
5491        return (NULL);
5492
5493#ifdef DEBUG
5494    fprintf(stderr, "Adding particle component\n");
5495#endif
5496    ret = (xmlSchemaParticlePtr)
5497	xmlMalloc(sizeof(xmlSchemaParticle));
5498    if (ret == NULL) {
5499	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5500	    NULL);
5501	return (NULL);
5502    }
5503    ret->type = XML_SCHEMA_TYPE_PARTICLE;
5504    ret->annot = NULL;
5505    ret->node = node;
5506    ret->minOccurs = min;
5507    ret->maxOccurs = max;
5508    ret->next = NULL;
5509    ret->children = NULL;
5510
5511    WXS_ADD_LOCAL(ctxt, ret);
5512    /*
5513    * Note that addition to pending components will be done locally
5514    * to the specific parsing function, since the most particles
5515    * need not to be fixed up (i.e. the reference to be resolved).
5516    * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5517    */
5518    return (ret);
5519}
5520
5521/**
5522 * xmlSchemaAddModelGroupDefinition:
5523 * @ctxt:  a schema validation context
5524 * @schema:  the schema being built
5525 * @name:  the group name
5526 *
5527 * Add an XML schema Group definition
5528 *
5529 * Returns the new struture or NULL in case of error
5530 */
5531static xmlSchemaModelGroupDefPtr
5532xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5533				 xmlSchemaPtr schema,
5534				 const xmlChar *name,
5535				 const xmlChar *nsName,
5536				 xmlNodePtr node)
5537{
5538    xmlSchemaModelGroupDefPtr ret = NULL;
5539
5540    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5541        return (NULL);
5542
5543    ret = (xmlSchemaModelGroupDefPtr)
5544	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5545    if (ret == NULL) {
5546        xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5547        return (NULL);
5548    }
5549    memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5550    ret->name = name;
5551    ret->type = XML_SCHEMA_TYPE_GROUP;
5552    ret->node = node;
5553    ret->targetNamespace = nsName;
5554
5555    if (ctxt->isRedefine) {
5556	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5557	    ret, name, nsName);
5558	if (ctxt->redef == NULL) {
5559	    xmlFree(ret);
5560	    return(NULL);
5561	}
5562	ctxt->redefCounter = 0;
5563    }
5564    WXS_ADD_GLOBAL(ctxt, ret);
5565    WXS_ADD_PENDING(ctxt, ret);
5566    return (ret);
5567}
5568
5569/**
5570 * xmlSchemaNewWildcardNs:
5571 * @ctxt:  a schema validation context
5572 *
5573 * Creates a new wildcard namespace constraint.
5574 *
5575 * Returns the new struture or NULL in case of error
5576 */
5577static xmlSchemaWildcardNsPtr
5578xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5579{
5580    xmlSchemaWildcardNsPtr ret;
5581
5582    ret = (xmlSchemaWildcardNsPtr)
5583	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5584    if (ret == NULL) {
5585	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5586	return (NULL);
5587    }
5588    ret->value = NULL;
5589    ret->next = NULL;
5590    return (ret);
5591}
5592
5593static xmlSchemaIDCPtr
5594xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5595                  const xmlChar *name, const xmlChar *nsName,
5596		  int category, xmlNodePtr node)
5597{
5598    xmlSchemaIDCPtr ret = NULL;
5599
5600    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5601        return (NULL);
5602
5603    ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5604    if (ret == NULL) {
5605        xmlSchemaPErrMemory(ctxt,
5606	    "allocating an identity-constraint definition", NULL);
5607        return (NULL);
5608    }
5609    memset(ret, 0, sizeof(xmlSchemaIDC));
5610    /* The target namespace of the parent element declaration. */
5611    ret->targetNamespace = nsName;
5612    ret->name = name;
5613    ret->type = category;
5614    ret->node = node;
5615
5616    WXS_ADD_GLOBAL(ctxt, ret);
5617    /*
5618    * Only keyrefs need to be fixup up.
5619    */
5620    if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5621	WXS_ADD_PENDING(ctxt, ret);
5622    return (ret);
5623}
5624
5625/**
5626 * xmlSchemaAddWildcard:
5627 * @ctxt:  a schema validation context
5628 * @schema: a schema
5629 *
5630 * Adds a wildcard.
5631 * It corresponds to a xsd:anyAttribute and xsd:any.
5632 *
5633 * Returns the new struture or NULL in case of error
5634 */
5635static xmlSchemaWildcardPtr
5636xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5637		     xmlSchemaTypeType type, xmlNodePtr node)
5638{
5639    xmlSchemaWildcardPtr ret = NULL;
5640
5641    if ((ctxt == NULL) || (schema == NULL))
5642        return (NULL);
5643
5644    ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5645    if (ret == NULL) {
5646        xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5647        return (NULL);
5648    }
5649    memset(ret, 0, sizeof(xmlSchemaWildcard));
5650    ret->type = type;
5651    ret->node = node;
5652    WXS_ADD_LOCAL(ctxt, ret);
5653    return (ret);
5654}
5655
5656static void
5657xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5658{
5659    if (group == NULL)
5660	return;
5661    if (group->members != NULL)
5662	xmlSchemaItemListFree(group->members);
5663    xmlFree(group);
5664}
5665
5666static xmlSchemaSubstGroupPtr
5667xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5668		       xmlSchemaElementPtr head)
5669{
5670    xmlSchemaSubstGroupPtr ret;
5671
5672    /* Init subst group hash. */
5673    if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5674	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5675	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5676	    return(NULL);
5677    }
5678    /* Create a new substitution group. */
5679    ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5680    if (ret == NULL) {
5681	xmlSchemaPErrMemory(NULL,
5682	    "allocating a substitution group container", NULL);
5683	return(NULL);
5684    }
5685    memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5686    ret->head = head;
5687    /* Create list of members. */
5688    ret->members = xmlSchemaItemListCreate();
5689    if (ret->members == NULL) {
5690	xmlSchemaSubstGroupFree(ret);
5691	return(NULL);
5692    }
5693    /* Add subst group to hash. */
5694    if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5695	head->name, head->targetNamespace, ret) != 0) {
5696	PERROR_INT("xmlSchemaSubstGroupAdd",
5697	    "failed to add a new substitution container");
5698	xmlSchemaSubstGroupFree(ret);
5699	return(NULL);
5700    }
5701    return(ret);
5702}
5703
5704static xmlSchemaSubstGroupPtr
5705xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5706		       xmlSchemaElementPtr head)
5707{
5708    if (WXS_SUBST_GROUPS(pctxt) == NULL)
5709	return(NULL);
5710    return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5711	head->name, head->targetNamespace));
5712
5713}
5714
5715/**
5716 * xmlSchemaAddElementSubstitutionMember:
5717 * @pctxt:  a schema parser context
5718 * @head:  the head of the substitution group
5719 * @member: the new member of the substitution group
5720 *
5721 * Allocate a new annotation structure.
5722 *
5723 * Returns the newly allocated structure or NULL in case or error
5724 */
5725static int
5726xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5727				      xmlSchemaElementPtr head,
5728				      xmlSchemaElementPtr member)
5729{
5730    xmlSchemaSubstGroupPtr substGroup = NULL;
5731
5732    if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5733	return (-1);
5734
5735    substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5736    if (substGroup == NULL)
5737	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5738    if (substGroup == NULL)
5739	return(-1);
5740    if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5741	return(-1);
5742    return(0);
5743}
5744
5745/************************************************************************
5746 * 									*
5747 *		Utilities for parsing					*
5748 * 									*
5749 ************************************************************************/
5750
5751/**
5752 * xmlSchemaPValAttrNodeQNameValue:
5753 * @ctxt:  a schema parser context
5754 * @schema: the schema context
5755 * @ownerDes: the designation of the parent element
5756 * @ownerItem: the parent as a schema object
5757 * @value:  the QName value
5758 * @local: the resulting local part if found, the attribute value otherwise
5759 * @uri:  the resulting namespace URI if found
5760 *
5761 * Extracts the local name and the URI of a QName value and validates it.
5762 * This one is intended to be used on attribute values that
5763 * should resolve to schema components.
5764 *
5765 * Returns 0, in case the QName is valid, a positive error code
5766 * if not valid and -1 if an internal error occurs.
5767 */
5768static int
5769xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5770				       xmlSchemaPtr schema,
5771				       xmlSchemaBasicItemPtr ownerItem,
5772				       xmlAttrPtr attr,
5773				       const xmlChar *value,
5774				       const xmlChar **uri,
5775				       const xmlChar **local)
5776{
5777    const xmlChar *pref;
5778    xmlNsPtr ns;
5779    int len, ret;
5780
5781    *uri = NULL;
5782    *local = NULL;
5783    ret = xmlValidateQName(value, 1);
5784    if (ret > 0) {
5785	xmlSchemaPSimpleTypeErr(ctxt,
5786	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5787	    ownerItem, (xmlNodePtr) attr,
5788	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5789	    NULL, value, NULL, NULL, NULL);
5790	*local = value;
5791	return (ctxt->err);
5792    } else if (ret < 0)
5793	return (-1);
5794
5795    if (!strchr((char *) value, ':')) {
5796	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5797	if (ns)
5798	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5799	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5800	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5801	    * parser context. */
5802	    /*
5803	    * This one takes care of included schemas with no
5804	    * target namespace.
5805	    */
5806	    *uri = ctxt->targetNamespace;
5807	}
5808	*local = xmlDictLookup(ctxt->dict, value, -1);
5809	return (0);
5810    }
5811    /*
5812    * At this point xmlSplitQName3 has to return a local name.
5813    */
5814    *local = xmlSplitQName3(value, &len);
5815    *local = xmlDictLookup(ctxt->dict, *local, -1);
5816    pref = xmlDictLookup(ctxt->dict, value, len);
5817    ns = xmlSearchNs(attr->doc, attr->parent, pref);
5818    if (ns == NULL) {
5819	xmlSchemaPSimpleTypeErr(ctxt,
5820	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5821	    ownerItem, (xmlNodePtr) attr,
5822	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5823	    "The value '%s' of simple type 'xs:QName' has no "
5824	    "corresponding namespace declaration in scope", value, NULL);
5825	return (ctxt->err);
5826    } else {
5827        *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5828    }
5829    return (0);
5830}
5831
5832/**
5833 * xmlSchemaPValAttrNodeQName:
5834 * @ctxt:  a schema parser context
5835 * @schema: the schema context
5836 * @ownerDes: the designation of the owner element
5837 * @ownerItem: the owner as a schema object
5838 * @attr:  the attribute node
5839 * @local: the resulting local part if found, the attribute value otherwise
5840 * @uri:  the resulting namespace URI if found
5841 *
5842 * Extracts and validates the QName of an attribute value.
5843 * This one is intended to be used on attribute values that
5844 * should resolve to schema components.
5845 *
5846 * Returns 0, in case the QName is valid, a positive error code
5847 * if not valid and -1 if an internal error occurs.
5848 */
5849static int
5850xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5851				       xmlSchemaPtr schema,
5852				       xmlSchemaBasicItemPtr ownerItem,
5853				       xmlAttrPtr attr,
5854				       const xmlChar **uri,
5855				       const xmlChar **local)
5856{
5857    const xmlChar *value;
5858
5859    value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5860    return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5861	ownerItem, attr, value, uri, local));
5862}
5863
5864/**
5865 * xmlSchemaPValAttrQName:
5866 * @ctxt:  a schema parser context
5867 * @schema: the schema context
5868 * @ownerDes: the designation of the parent element
5869 * @ownerItem: the owner as a schema object
5870 * @ownerElem:  the parent node of the attribute
5871 * @name:  the name of the attribute
5872 * @local: the resulting local part if found, the attribute value otherwise
5873 * @uri:  the resulting namespace URI if found
5874 *
5875 * Extracts and validates the QName of an attribute value.
5876 *
5877 * Returns 0, in case the QName is valid, a positive error code
5878 * if not valid and -1 if an internal error occurs.
5879 */
5880static int
5881xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5882				   xmlSchemaPtr schema,
5883				   xmlSchemaBasicItemPtr ownerItem,
5884				   xmlNodePtr ownerElem,
5885				   const char *name,
5886				   const xmlChar **uri,
5887				   const xmlChar **local)
5888{
5889    xmlAttrPtr attr;
5890
5891    attr = xmlSchemaGetPropNode(ownerElem, name);
5892    if (attr == NULL) {
5893	*local = NULL;
5894	*uri = NULL;
5895	return (0);
5896    }
5897    return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5898	ownerItem, attr, uri, local));
5899}
5900
5901/**
5902 * xmlSchemaPValAttrID:
5903 * @ctxt:  a schema parser context
5904 * @schema: the schema context
5905 * @ownerDes: the designation of the parent element
5906 * @ownerItem: the owner as a schema object
5907 * @ownerElem:  the parent node of the attribute
5908 * @name:  the name of the attribute
5909 *
5910 * Extracts and validates the ID of an attribute value.
5911 *
5912 * Returns 0, in case the ID is valid, a positive error code
5913 * if not valid and -1 if an internal error occurs.
5914 */
5915static int
5916xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5917{
5918    int ret;
5919    const xmlChar *value;
5920
5921    if (attr == NULL)
5922	return(0);
5923    value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5924    ret = xmlValidateNCName(value, 1);
5925    if (ret == 0) {
5926	/*
5927	* NOTE: the IDness might have already be declared in the DTD
5928	*/
5929	if (attr->atype != XML_ATTRIBUTE_ID) {
5930	    xmlIDPtr res;
5931	    xmlChar *strip;
5932
5933	    /*
5934	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5935	    * moment.
5936	    */
5937	    strip = xmlSchemaCollapseString(value);
5938	    if (strip != NULL) {
5939		xmlFree((xmlChar *) value);
5940		value = strip;
5941	    }
5942    	    res = xmlAddID(NULL, attr->doc, value, attr);
5943	    if (res == NULL) {
5944		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5945		xmlSchemaPSimpleTypeErr(ctxt,
5946		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5947		    NULL, (xmlNodePtr) attr,
5948		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5949		    NULL, NULL, "Duplicate value '%s' of simple "
5950		    "type 'xs:ID'", value, NULL);
5951	    } else
5952		attr->atype = XML_ATTRIBUTE_ID;
5953	}
5954    } else if (ret > 0) {
5955	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5956	xmlSchemaPSimpleTypeErr(ctxt,
5957	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5958	    NULL, (xmlNodePtr) attr,
5959	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5960	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5961	    "not a valid 'xs:NCName'",
5962	    value, NULL);
5963    }
5964    if (value != NULL)
5965	xmlFree((xmlChar *)value);
5966
5967    return (ret);
5968}
5969
5970static int
5971xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5972		    xmlNodePtr ownerElem,
5973		    const xmlChar *name)
5974{
5975    xmlAttrPtr attr;
5976
5977    attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5978    if (attr == NULL)
5979	return(0);
5980    return(xmlSchemaPValAttrNodeID(ctxt, attr));
5981
5982}
5983
5984/**
5985 * xmlGetMaxOccurs:
5986 * @ctxt:  a schema validation context
5987 * @node:  a subtree containing XML Schema informations
5988 *
5989 * Get the maxOccurs property
5990 *
5991 * Returns the default if not found, or the value
5992 */
5993static int
5994xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5995		int min, int max, int def, const char *expected)
5996{
5997    const xmlChar *val, *cur;
5998    int ret = 0;
5999    xmlAttrPtr attr;
6000
6001    attr = xmlSchemaGetPropNode(node, "maxOccurs");
6002    if (attr == NULL)
6003	return (def);
6004    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6005
6006    if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6007	if (max != UNBOUNDED) {
6008	    xmlSchemaPSimpleTypeErr(ctxt,
6009		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6010		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6011		NULL, (xmlNodePtr) attr, NULL, expected,
6012		val, NULL, NULL, NULL);
6013	    return (def);
6014	} else
6015	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6016    }
6017
6018    cur = val;
6019    while (IS_BLANK_CH(*cur))
6020        cur++;
6021    if (*cur == 0) {
6022        xmlSchemaPSimpleTypeErr(ctxt,
6023	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6024	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6025	    NULL, (xmlNodePtr) attr, NULL, expected,
6026	    val, NULL, NULL, NULL);
6027	return (def);
6028    }
6029    while ((*cur >= '0') && (*cur <= '9')) {
6030        ret = ret * 10 + (*cur - '0');
6031        cur++;
6032    }
6033    while (IS_BLANK_CH(*cur))
6034        cur++;
6035    /*
6036    * TODO: Restrict the maximal value to Integer.
6037    */
6038    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6039	xmlSchemaPSimpleTypeErr(ctxt,
6040	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6041	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6042	    NULL, (xmlNodePtr) attr, NULL, expected,
6043	    val, NULL, NULL, NULL);
6044        return (def);
6045    }
6046    return (ret);
6047}
6048
6049/**
6050 * xmlGetMinOccurs:
6051 * @ctxt:  a schema validation context
6052 * @node:  a subtree containing XML Schema informations
6053 *
6054 * Get the minOccurs property
6055 *
6056 * Returns the default if not found, or the value
6057 */
6058static int
6059xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6060		int min, int max, int def, const char *expected)
6061{
6062    const xmlChar *val, *cur;
6063    int ret = 0;
6064    xmlAttrPtr attr;
6065
6066    attr = xmlSchemaGetPropNode(node, "minOccurs");
6067    if (attr == NULL)
6068	return (def);
6069    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6070    cur = val;
6071    while (IS_BLANK_CH(*cur))
6072        cur++;
6073    if (*cur == 0) {
6074        xmlSchemaPSimpleTypeErr(ctxt,
6075	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6076	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6077	    NULL, (xmlNodePtr) attr, NULL, expected,
6078	    val, NULL, NULL, NULL);
6079        return (def);
6080    }
6081    while ((*cur >= '0') && (*cur <= '9')) {
6082        ret = ret * 10 + (*cur - '0');
6083        cur++;
6084    }
6085    while (IS_BLANK_CH(*cur))
6086        cur++;
6087    /*
6088    * TODO: Restrict the maximal value to Integer.
6089    */
6090    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6091	xmlSchemaPSimpleTypeErr(ctxt,
6092	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6093	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6094	    NULL, (xmlNodePtr) attr, NULL, expected,
6095	    val, NULL, NULL, NULL);
6096        return (def);
6097    }
6098    return (ret);
6099}
6100
6101/**
6102 * xmlSchemaPGetBoolNodeValue:
6103 * @ctxt:  a schema validation context
6104 * @ownerDes:  owner designation
6105 * @ownerItem:  the owner as a schema item
6106 * @node: the node holding the value
6107 *
6108 * Converts a boolean string value into 1 or 0.
6109 *
6110 * Returns 0 or 1.
6111 */
6112static int
6113xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6114			   xmlSchemaBasicItemPtr ownerItem,
6115			   xmlNodePtr node)
6116{
6117    xmlChar *value = NULL;
6118    int res = 0;
6119
6120    value = xmlNodeGetContent(node);
6121    /*
6122    * 3.2.2.1 Lexical representation
6123    * An instance of a datatype that is defined as �boolean�
6124    * can have the following legal literals {true, false, 1, 0}.
6125    */
6126    if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6127        res = 1;
6128    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6129        res = 0;
6130    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6131	res = 1;
6132    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6133        res = 0;
6134    else {
6135        xmlSchemaPSimpleTypeErr(ctxt,
6136	    XML_SCHEMAP_INVALID_BOOLEAN,
6137	    ownerItem, node,
6138	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6139	    NULL, BAD_CAST value,
6140	    NULL, NULL, NULL);
6141    }
6142    if (value != NULL)
6143	xmlFree(value);
6144    return (res);
6145}
6146
6147/**
6148 * xmlGetBooleanProp:
6149 * @ctxt:  a schema validation context
6150 * @node:  a subtree containing XML Schema informations
6151 * @name:  the attribute name
6152 * @def:  the default value
6153 *
6154 * Evaluate if a boolean property is set
6155 *
6156 * Returns the default if not found, 0 if found to be false,
6157 * 1 if found to be true
6158 */
6159static int
6160xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6161		  xmlNodePtr node,
6162                  const char *name, int def)
6163{
6164    const xmlChar *val;
6165
6166    val = xmlSchemaGetProp(ctxt, node, name);
6167    if (val == NULL)
6168        return (def);
6169    /*
6170    * 3.2.2.1 Lexical representation
6171    * An instance of a datatype that is defined as �boolean�
6172    * can have the following legal literals {true, false, 1, 0}.
6173    */
6174    if (xmlStrEqual(val, BAD_CAST "true"))
6175        def = 1;
6176    else if (xmlStrEqual(val, BAD_CAST "false"))
6177        def = 0;
6178    else if (xmlStrEqual(val, BAD_CAST "1"))
6179	def = 1;
6180    else if (xmlStrEqual(val, BAD_CAST "0"))
6181        def = 0;
6182    else {
6183        xmlSchemaPSimpleTypeErr(ctxt,
6184	    XML_SCHEMAP_INVALID_BOOLEAN,
6185	    NULL,
6186	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6187	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6188	    NULL, val, NULL, NULL, NULL);
6189    }
6190    return (def);
6191}
6192
6193/************************************************************************
6194 * 									*
6195 *		Shema extraction from an Infoset			*
6196 * 									*
6197 ************************************************************************/
6198static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6199                                                 ctxt, xmlSchemaPtr schema,
6200                                                 xmlNodePtr node,
6201						 int topLevel);
6202static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6203                                                  ctxt,
6204                                                  xmlSchemaPtr schema,
6205                                                  xmlNodePtr node,
6206						  int topLevel);
6207static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6208                                                  ctxt,
6209                                                  xmlSchemaPtr schema,
6210                                                  xmlNodePtr node,
6211						  xmlSchemaTypeType parentType);
6212static xmlSchemaBasicItemPtr
6213xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6214			     xmlSchemaPtr schema,
6215			     xmlNodePtr node,
6216			     xmlSchemaItemListPtr uses,
6217			     int parentType);
6218static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6219                                           xmlSchemaPtr schema,
6220                                           xmlNodePtr node);
6221static xmlSchemaWildcardPtr
6222xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6223                           xmlSchemaPtr schema, xmlNodePtr node);
6224
6225/**
6226 * xmlSchemaPValAttrNodeValue:
6227 *
6228 * @ctxt:  a schema parser context
6229 * @ownerDes: the designation of the parent element
6230 * @ownerItem: the schema object owner if existent
6231 * @attr:  the schema attribute node being validated
6232 * @value: the value
6233 * @type: the built-in type to be validated against
6234 *
6235 * Validates a value against the given built-in type.
6236 * This one is intended to be used internally for validation
6237 * of schema attribute values during parsing of the schema.
6238 *
6239 * Returns 0 if the value is valid, a positive error code
6240 * number otherwise and -1 in case of an internal or API error.
6241 */
6242static int
6243xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6244			   xmlSchemaBasicItemPtr ownerItem,
6245			   xmlAttrPtr attr,
6246			   const xmlChar *value,
6247			   xmlSchemaTypePtr type)
6248{
6249
6250    int ret = 0;
6251
6252    /*
6253    * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6254    * one is really meant to be used internally, so better not.
6255    */
6256    if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6257	return (-1);
6258    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6259	PERROR_INT("xmlSchemaPValAttrNodeValue",
6260	    "the given type is not a built-in type");
6261	return (-1);
6262    }
6263    switch (type->builtInType) {
6264	case XML_SCHEMAS_NCNAME:
6265	case XML_SCHEMAS_QNAME:
6266	case XML_SCHEMAS_ANYURI:
6267	case XML_SCHEMAS_TOKEN:
6268	case XML_SCHEMAS_LANGUAGE:
6269	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6270		(xmlNodePtr) attr);
6271	    break;
6272	default: {
6273	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6274		"validation using the given type is not supported while "
6275		"parsing a schema");
6276	    return (-1);
6277	}
6278    }
6279    /*
6280    * TODO: Should we use the S4S error codes instead?
6281    */
6282    if (ret < 0) {
6283	PERROR_INT("xmlSchemaPValAttrNodeValue",
6284	    "failed to validate a schema attribute value");
6285	return (-1);
6286    } else if (ret > 0) {
6287	if (WXS_IS_LIST(type))
6288	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6289	else
6290	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6291	xmlSchemaPSimpleTypeErr(pctxt,
6292	    ret, ownerItem, (xmlNodePtr) attr,
6293	    type, NULL, value, NULL, NULL, NULL);
6294    }
6295    return (ret);
6296}
6297
6298/**
6299 * xmlSchemaPValAttrNode:
6300 *
6301 * @ctxt:  a schema parser context
6302 * @ownerDes: the designation of the parent element
6303 * @ownerItem: the schema object owner if existent
6304 * @attr:  the schema attribute node being validated
6305 * @type: the built-in type to be validated against
6306 * @value: the resulting value if any
6307 *
6308 * Extracts and validates a value against the given built-in type.
6309 * This one is intended to be used internally for validation
6310 * of schema attribute values during parsing of the schema.
6311 *
6312 * Returns 0 if the value is valid, a positive error code
6313 * number otherwise and -1 in case of an internal or API error.
6314 */
6315static int
6316xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6317			   xmlSchemaBasicItemPtr ownerItem,
6318			   xmlAttrPtr attr,
6319			   xmlSchemaTypePtr type,
6320			   const xmlChar **value)
6321{
6322    const xmlChar *val;
6323
6324    if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6325	return (-1);
6326
6327    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6328    if (value != NULL)
6329	*value = val;
6330
6331    return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6332	val, type));
6333}
6334
6335/**
6336 * xmlSchemaPValAttr:
6337 *
6338 * @ctxt:  a schema parser context
6339 * @node: the element node of the attribute
6340 * @ownerDes: the designation of the parent element
6341 * @ownerItem: the schema object owner if existent
6342 * @ownerElem: the owner element node
6343 * @name:  the name of the schema attribute node
6344 * @type: the built-in type to be validated against
6345 * @value: the resulting value if any
6346 *
6347 * Extracts and validates a value against the given built-in type.
6348 * This one is intended to be used internally for validation
6349 * of schema attribute values during parsing of the schema.
6350 *
6351 * Returns 0 if the value is valid, a positive error code
6352 * number otherwise and -1 in case of an internal or API error.
6353 */
6354static int
6355xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6356		       xmlSchemaBasicItemPtr ownerItem,
6357		       xmlNodePtr ownerElem,
6358		       const char *name,
6359		       xmlSchemaTypePtr type,
6360		       const xmlChar **value)
6361{
6362    xmlAttrPtr attr;
6363
6364    if ((ctxt == NULL) || (type == NULL)) {
6365	if (value != NULL)
6366	    *value = NULL;
6367	return (-1);
6368    }
6369    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6370	if (value != NULL)
6371	    *value = NULL;
6372	xmlSchemaPErr(ctxt, ownerElem,
6373	    XML_SCHEMAP_INTERNAL,
6374	    "Internal error: xmlSchemaPValAttr, the given "
6375	    "type '%s' is not a built-in type.\n",
6376	    type->name, NULL);
6377	return (-1);
6378    }
6379    attr = xmlSchemaGetPropNode(ownerElem, name);
6380    if (attr == NULL) {
6381	if (value != NULL)
6382	    *value = NULL;
6383	return (0);
6384    }
6385    return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6386	type, value));
6387}
6388
6389static int
6390xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6391		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6392		  xmlNodePtr node,
6393		  xmlAttrPtr attr,
6394		  const xmlChar *namespaceName)
6395{
6396    /* TODO: Pointer comparison instead? */
6397    if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6398	return (0);
6399    if (xmlStrEqual(xmlSchemaNs, namespaceName))
6400	return (0);
6401    /*
6402    * Check if the referenced namespace was <import>ed.
6403    */
6404    if (WXS_BUCKET(pctxt)->relations != NULL) {
6405	xmlSchemaSchemaRelationPtr rel;
6406
6407	rel = WXS_BUCKET(pctxt)->relations;
6408	do {
6409	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6410		xmlStrEqual(namespaceName, rel->importNamespace))
6411		return (0);
6412	    rel = rel->next;
6413	} while (rel != NULL);
6414    }
6415    /*
6416    * No matching <import>ed namespace found.
6417    */
6418    {
6419	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6420
6421	if (namespaceName == NULL)
6422	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6423		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6424		"References from this schema to components in no "
6425		"namespace are not allowed, since not indicated by an "
6426		"import statement", NULL, NULL);
6427	else
6428	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6429		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6430		"References from this schema to components in the "
6431		"namespace '%s' are not allowed, since not indicated by an "
6432		"import statement", namespaceName, NULL);
6433    }
6434    return (XML_SCHEMAP_SRC_RESOLVE);
6435}
6436
6437/**
6438 * xmlSchemaParseLocalAttributes:
6439 * @ctxt:  a schema validation context
6440 * @schema:  the schema being built
6441 * @node:  a subtree containing XML Schema informations
6442 * @type:  the hosting type where the attributes will be anchored
6443 *
6444 * Parses attribute uses and attribute declarations and
6445 * attribute group references.
6446 */
6447static int
6448xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6449                        xmlNodePtr *child, xmlSchemaItemListPtr *list,
6450			int parentType, int *hasRefs)
6451{
6452    void *item;
6453
6454    while ((IS_SCHEMA((*child), "attribute")) ||
6455           (IS_SCHEMA((*child), "attributeGroup"))) {
6456        if (IS_SCHEMA((*child), "attribute")) {
6457	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6458		*list, parentType);
6459        } else {
6460            item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6461	    if ((item != NULL) && (hasRefs != NULL))
6462		*hasRefs = 1;
6463        }
6464	if (item != NULL) {
6465	    if (*list == NULL) {
6466		/* TODO: Customize grow factor. */
6467		*list = xmlSchemaItemListCreate();
6468		if (*list == NULL)
6469		    return(-1);
6470	    }
6471	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6472		return(-1);
6473	}
6474        *child = (*child)->next;
6475    }
6476    return (0);
6477}
6478
6479/**
6480 * xmlSchemaParseAnnotation:
6481 * @ctxt:  a schema validation context
6482 * @schema:  the schema being built
6483 * @node:  a subtree containing XML Schema informations
6484 *
6485 * parse a XML schema Attrribute declaration
6486 * *WARNING* this interface is highly subject to change
6487 *
6488 * Returns -1 in case of error, 0 if the declaration is improper and
6489 *         1 in case of success.
6490 */
6491static xmlSchemaAnnotPtr
6492xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6493{
6494    xmlSchemaAnnotPtr ret;
6495    xmlNodePtr child = NULL;
6496    xmlAttrPtr attr;
6497    int barked = 0;
6498
6499    /*
6500    * INFO: S4S completed.
6501    */
6502    /*
6503    * id = ID
6504    * {any attributes with non-schema namespace . . .}>
6505    * Content: (appinfo | documentation)*
6506    */
6507    if ((ctxt == NULL) || (node == NULL))
6508        return (NULL);
6509    if (needed)
6510	ret = xmlSchemaNewAnnot(ctxt, node);
6511    else
6512	ret = NULL;
6513    attr = node->properties;
6514    while (attr != NULL) {
6515	if (((attr->ns == NULL) &&
6516	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6517	    ((attr->ns != NULL) &&
6518	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6519
6520	    xmlSchemaPIllegalAttrErr(ctxt,
6521		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6522	}
6523	attr = attr->next;
6524    }
6525    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6526    /*
6527    * And now for the children...
6528    */
6529    child = node->children;
6530    while (child != NULL) {
6531	if (IS_SCHEMA(child, "appinfo")) {
6532	    /* TODO: make available the content of "appinfo". */
6533	    /*
6534	    * source = anyURI
6535	    * {any attributes with non-schema namespace . . .}>
6536	    * Content: ({any})*
6537	    */
6538	    attr = child->properties;
6539	    while (attr != NULL) {
6540		if (((attr->ns == NULL) &&
6541		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6542		     ((attr->ns != NULL) &&
6543		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6544
6545		    xmlSchemaPIllegalAttrErr(ctxt,
6546			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6547		}
6548		attr = attr->next;
6549	    }
6550	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6551		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6552	    child = child->next;
6553	} else if (IS_SCHEMA(child, "documentation")) {
6554	    /* TODO: make available the content of "documentation". */
6555	    /*
6556	    * source = anyURI
6557	    * {any attributes with non-schema namespace . . .}>
6558	    * Content: ({any})*
6559	    */
6560	    attr = child->properties;
6561	    while (attr != NULL) {
6562		if (attr->ns == NULL) {
6563		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6564			xmlSchemaPIllegalAttrErr(ctxt,
6565			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6566		    }
6567		} else {
6568		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6569			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6570			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6571
6572			xmlSchemaPIllegalAttrErr(ctxt,
6573			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6574		    }
6575		}
6576		attr = attr->next;
6577	    }
6578	    /*
6579	    * Attribute "xml:lang".
6580	    */
6581	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6582	    if (attr != NULL)
6583		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6584		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6585	    child = child->next;
6586	} else {
6587	    if (!barked)
6588		xmlSchemaPContentErr(ctxt,
6589		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6590		    NULL, node, child, NULL, "(appinfo | documentation)*");
6591	    barked = 1;
6592	    child = child->next;
6593	}
6594    }
6595
6596    return (ret);
6597}
6598
6599/**
6600 * xmlSchemaParseFacet:
6601 * @ctxt:  a schema validation context
6602 * @schema:  the schema being built
6603 * @node:  a subtree containing XML Schema informations
6604 *
6605 * parse a XML schema Facet declaration
6606 * *WARNING* this interface is highly subject to change
6607 *
6608 * Returns the new type structure or NULL in case of error
6609 */
6610static xmlSchemaFacetPtr
6611xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6612                    xmlNodePtr node)
6613{
6614    xmlSchemaFacetPtr facet;
6615    xmlNodePtr child = NULL;
6616    const xmlChar *value;
6617
6618    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6619        return (NULL);
6620
6621    facet = xmlSchemaNewFacet();
6622    if (facet == NULL) {
6623        xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6624        return (NULL);
6625    }
6626    facet->node = node;
6627    value = xmlSchemaGetProp(ctxt, node, "value");
6628    if (value == NULL) {
6629        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6630                       "Facet %s has no value\n", node->name, NULL);
6631        xmlSchemaFreeFacet(facet);
6632        return (NULL);
6633    }
6634    if (IS_SCHEMA(node, "minInclusive")) {
6635        facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6636    } else if (IS_SCHEMA(node, "minExclusive")) {
6637        facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6638    } else if (IS_SCHEMA(node, "maxInclusive")) {
6639        facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6640    } else if (IS_SCHEMA(node, "maxExclusive")) {
6641        facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6642    } else if (IS_SCHEMA(node, "totalDigits")) {
6643        facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6644    } else if (IS_SCHEMA(node, "fractionDigits")) {
6645        facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6646    } else if (IS_SCHEMA(node, "pattern")) {
6647        facet->type = XML_SCHEMA_FACET_PATTERN;
6648    } else if (IS_SCHEMA(node, "enumeration")) {
6649        facet->type = XML_SCHEMA_FACET_ENUMERATION;
6650    } else if (IS_SCHEMA(node, "whiteSpace")) {
6651        facet->type = XML_SCHEMA_FACET_WHITESPACE;
6652    } else if (IS_SCHEMA(node, "length")) {
6653        facet->type = XML_SCHEMA_FACET_LENGTH;
6654    } else if (IS_SCHEMA(node, "maxLength")) {
6655        facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6656    } else if (IS_SCHEMA(node, "minLength")) {
6657        facet->type = XML_SCHEMA_FACET_MINLENGTH;
6658    } else {
6659        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6660                       "Unknown facet type %s\n", node->name, NULL);
6661        xmlSchemaFreeFacet(facet);
6662        return (NULL);
6663    }
6664    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6665    facet->value = value;
6666    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6667	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6668	const xmlChar *fixed;
6669
6670	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6671	if (fixed != NULL) {
6672	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6673		facet->fixed = 1;
6674	}
6675    }
6676    child = node->children;
6677
6678    if (IS_SCHEMA(child, "annotation")) {
6679        facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6680        child = child->next;
6681    }
6682    if (child != NULL) {
6683        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6684                       "Facet %s has unexpected child content\n",
6685                       node->name, NULL);
6686    }
6687    return (facet);
6688}
6689
6690/**
6691 * xmlSchemaParseWildcardNs:
6692 * @ctxt:  a schema parser context
6693 * @wildc:  the wildcard, already created
6694 * @node:  a subtree containing XML Schema informations
6695 *
6696 * Parses the attribute "processContents" and "namespace"
6697 * of a xsd:anyAttribute and xsd:any.
6698 * *WARNING* this interface is highly subject to change
6699 *
6700 * Returns 0 if everything goes fine, a positive error code
6701 * if something is not valid and -1 if an internal error occurs.
6702 */
6703static int
6704xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6705			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6706			 xmlSchemaWildcardPtr wildc,
6707			 xmlNodePtr node)
6708{
6709    const xmlChar *pc, *ns, *dictnsItem;
6710    int ret = 0;
6711    xmlChar *nsItem;
6712    xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6713    xmlAttrPtr attr;
6714
6715    pc = xmlSchemaGetProp(ctxt, node, "processContents");
6716    if ((pc == NULL)
6717        || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6718        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6719    } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6720        wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6721    } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6722        wildc->processContents = XML_SCHEMAS_ANY_LAX;
6723    } else {
6724        xmlSchemaPSimpleTypeErr(ctxt,
6725	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6726	    NULL, node,
6727	    NULL, "(strict | skip | lax)", pc,
6728	    NULL, NULL, NULL);
6729        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6730	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6731    }
6732    /*
6733     * Build the namespace constraints.
6734     */
6735    attr = xmlSchemaGetPropNode(node, "namespace");
6736    ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6737    if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6738	wildc->any = 1;
6739    else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6740	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6741	if (wildc->negNsSet == NULL) {
6742	    return (-1);
6743	}
6744	wildc->negNsSet->value = ctxt->targetNamespace;
6745    } else {
6746	const xmlChar *end, *cur;
6747
6748	cur = ns;
6749	do {
6750	    while (IS_BLANK_CH(*cur))
6751		cur++;
6752	    end = cur;
6753	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6754		end++;
6755	    if (end == cur)
6756		break;
6757	    nsItem = xmlStrndup(cur, end - cur);
6758	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6759		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6760		xmlSchemaPSimpleTypeErr(ctxt,
6761		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6762		    NULL, (xmlNodePtr) attr,
6763		    NULL,
6764		    "((##any | ##other) | List of (xs:anyURI | "
6765		    "(##targetNamespace | ##local)))",
6766		    nsItem, NULL, NULL, NULL);
6767		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6768	    } else {
6769		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6770		    dictnsItem = ctxt->targetNamespace;
6771		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6772		    dictnsItem = NULL;
6773		} else {
6774		    /*
6775		    * Validate the item (anyURI).
6776		    */
6777		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6778			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6779		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6780		}
6781		/*
6782		* Avoid dublicate namespaces.
6783		*/
6784		tmp = wildc->nsSet;
6785		while (tmp != NULL) {
6786		    if (dictnsItem == tmp->value)
6787			break;
6788		    tmp = tmp->next;
6789		}
6790		if (tmp == NULL) {
6791		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6792		    if (tmp == NULL) {
6793			xmlFree(nsItem);
6794			return (-1);
6795		    }
6796		    tmp->value = dictnsItem;
6797		    tmp->next = NULL;
6798		    if (wildc->nsSet == NULL)
6799			wildc->nsSet = tmp;
6800		    else if (lastNs != NULL)
6801			lastNs->next = tmp;
6802		    lastNs = tmp;
6803		}
6804
6805	    }
6806	    xmlFree(nsItem);
6807	    cur = end;
6808	} while (*cur != 0);
6809    }
6810    return (ret);
6811}
6812
6813static int
6814xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6815				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6816				 xmlNodePtr node,
6817				 int minOccurs,
6818				 int maxOccurs) {
6819
6820    if ((maxOccurs == 0) && ( minOccurs == 0))
6821	return (0);
6822    if (maxOccurs != UNBOUNDED) {
6823	/*
6824	* TODO: Maybe we should better not create the particle,
6825	* if min/max is invalid, since it could confuse the build of the
6826	* content model.
6827	*/
6828	/*
6829	* 3.9.6 Schema Component Constraint: Particle Correct
6830	*
6831	*/
6832	if (maxOccurs < 1) {
6833	    /*
6834	    * 2.2 {max occurs} must be greater than or equal to 1.
6835	    */
6836	    xmlSchemaPCustomAttrErr(ctxt,
6837		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6838		NULL, NULL,
6839		xmlSchemaGetPropNode(node, "maxOccurs"),
6840		"The value must be greater than or equal to 1");
6841	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6842	} else if (minOccurs > maxOccurs) {
6843	    /*
6844	    * 2.1 {min occurs} must not be greater than {max occurs}.
6845	    */
6846	    xmlSchemaPCustomAttrErr(ctxt,
6847		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6848		NULL, NULL,
6849		xmlSchemaGetPropNode(node, "minOccurs"),
6850		"The value must not be greater than the value of 'maxOccurs'");
6851	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6852	}
6853    }
6854    return (0);
6855}
6856
6857/**
6858 * xmlSchemaParseAny:
6859 * @ctxt:  a schema validation context
6860 * @schema:  the schema being built
6861 * @node:  a subtree containing XML Schema informations
6862 *
6863 * Parsea a XML schema <any> element. A particle and wildcard
6864 * will be created (except if minOccurs==maxOccurs==0, in this case
6865 * nothing will be created).
6866 * *WARNING* this interface is highly subject to change
6867 *
6868 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6869 */
6870static xmlSchemaParticlePtr
6871xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6872                  xmlNodePtr node)
6873{
6874    xmlSchemaParticlePtr particle;
6875    xmlNodePtr child = NULL;
6876    xmlSchemaWildcardPtr wild;
6877    int min, max;
6878    xmlAttrPtr attr;
6879    xmlSchemaAnnotPtr annot = NULL;
6880
6881    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6882        return (NULL);
6883    /*
6884    * Check for illegal attributes.
6885    */
6886    attr = node->properties;
6887    while (attr != NULL) {
6888	if (attr->ns == NULL) {
6889	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6890		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6891		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6892	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6893		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6894		xmlSchemaPIllegalAttrErr(ctxt,
6895		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6896	    }
6897	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6898	    xmlSchemaPIllegalAttrErr(ctxt,
6899		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6900	}
6901	attr = attr->next;
6902    }
6903    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6904    /*
6905    * minOccurs/maxOccurs.
6906    */
6907    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6908	"(xs:nonNegativeInteger | unbounded)");
6909    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6910	"xs:nonNegativeInteger");
6911    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6912    /*
6913    * Create & parse the wildcard.
6914    */
6915    wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6916    if (wild == NULL)
6917	return (NULL);
6918    xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6919    /*
6920    * And now for the children...
6921    */
6922    child = node->children;
6923    if (IS_SCHEMA(child, "annotation")) {
6924        annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6925        child = child->next;
6926    }
6927    if (child != NULL) {
6928	xmlSchemaPContentErr(ctxt,
6929	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6930	    NULL, node, child,
6931	    NULL, "(annotation?)");
6932    }
6933    /*
6934    * No component if minOccurs==maxOccurs==0.
6935    */
6936    if ((min == 0) && (max == 0)) {
6937	/* Don't free the wildcard, since it's already on the list. */
6938	return (NULL);
6939    }
6940    /*
6941    * Create the particle.
6942    */
6943    particle = xmlSchemaAddParticle(ctxt, node, min, max);
6944    if (particle == NULL)
6945        return (NULL);
6946    particle->annot = annot;
6947    particle->children = (xmlSchemaTreeItemPtr) wild;
6948
6949    return (particle);
6950}
6951
6952/**
6953 * xmlSchemaParseNotation:
6954 * @ctxt:  a schema validation context
6955 * @schema:  the schema being built
6956 * @node:  a subtree containing XML Schema informations
6957 *
6958 * parse a XML schema Notation declaration
6959 *
6960 * Returns the new structure or NULL in case of error
6961 */
6962static xmlSchemaNotationPtr
6963xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6964                       xmlNodePtr node)
6965{
6966    const xmlChar *name;
6967    xmlSchemaNotationPtr ret;
6968    xmlNodePtr child = NULL;
6969
6970    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6971        return (NULL);
6972    name = xmlSchemaGetProp(ctxt, node, "name");
6973    if (name == NULL) {
6974        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6975                       "Notation has no name\n", NULL, NULL);
6976        return (NULL);
6977    }
6978    ret = xmlSchemaAddNotation(ctxt, schema, name,
6979	ctxt->targetNamespace, node);
6980    if (ret == NULL)
6981        return (NULL);
6982    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6983
6984    child = node->children;
6985    if (IS_SCHEMA(child, "annotation")) {
6986        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6987        child = child->next;
6988    }
6989    if (child != NULL) {
6990	xmlSchemaPContentErr(ctxt,
6991	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6992	    NULL, node, child,
6993	    NULL, "(annotation?)");
6994    }
6995
6996    return (ret);
6997}
6998
6999/**
7000 * xmlSchemaParseAnyAttribute:
7001 * @ctxt:  a schema validation context
7002 * @schema:  the schema being built
7003 * @node:  a subtree containing XML Schema informations
7004 *
7005 * parse a XML schema AnyAttrribute declaration
7006 * *WARNING* this interface is highly subject to change
7007 *
7008 * Returns a wildcard or NULL.
7009 */
7010static xmlSchemaWildcardPtr
7011xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7012                           xmlSchemaPtr schema, xmlNodePtr node)
7013{
7014    xmlSchemaWildcardPtr ret;
7015    xmlNodePtr child = NULL;
7016    xmlAttrPtr attr;
7017
7018    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7019        return (NULL);
7020
7021    ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7022	node);
7023    if (ret == NULL) {
7024        return (NULL);
7025    }
7026    /*
7027    * Check for illegal attributes.
7028    */
7029    attr = node->properties;
7030    while (attr != NULL) {
7031	if (attr->ns == NULL) {
7032	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7033	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7034		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7035		xmlSchemaPIllegalAttrErr(ctxt,
7036		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7037	    }
7038	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7039	    xmlSchemaPIllegalAttrErr(ctxt,
7040		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7041	}
7042	attr = attr->next;
7043    }
7044    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7045    /*
7046    * Parse the namespace list.
7047    */
7048    if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7049	return (NULL);
7050    /*
7051    * And now for the children...
7052    */
7053    child = node->children;
7054    if (IS_SCHEMA(child, "annotation")) {
7055        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7056        child = child->next;
7057    }
7058    if (child != NULL) {
7059	xmlSchemaPContentErr(ctxt,
7060	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7061	    NULL, node, child,
7062	    NULL, "(annotation?)");
7063    }
7064
7065    return (ret);
7066}
7067
7068
7069/**
7070 * xmlSchemaParseAttribute:
7071 * @ctxt:  a schema validation context
7072 * @schema:  the schema being built
7073 * @node:  a subtree containing XML Schema informations
7074 *
7075 * parse a XML schema Attrribute declaration
7076 * *WARNING* this interface is highly subject to change
7077 *
7078 * Returns the attribute declaration.
7079 */
7080static xmlSchemaBasicItemPtr
7081xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7082			     xmlSchemaPtr schema,
7083			     xmlNodePtr node,
7084			     xmlSchemaItemListPtr uses,
7085			     int parentType)
7086{
7087    const xmlChar *attrValue, *name = NULL, *ns = NULL;
7088    xmlSchemaAttributeUsePtr use = NULL;
7089    xmlNodePtr child = NULL;
7090    xmlAttrPtr attr;
7091    const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7092    int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7093    int	nberrors, hasForm = 0, defValueType = 0;
7094
7095#define WXS_ATTR_DEF_VAL_DEFAULT 1
7096#define WXS_ATTR_DEF_VAL_FIXED 2
7097
7098    /*
7099     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7100     */
7101
7102    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7103        return (NULL);
7104    attr = xmlSchemaGetPropNode(node, "ref");
7105    if (attr != NULL) {
7106	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7107	    NULL, attr, &tmpNs, &tmpName) != 0) {
7108	    return (NULL);
7109	}
7110	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7111	    return(NULL);
7112	isRef = 1;
7113    }
7114    nberrors = pctxt->nberrors;
7115    /*
7116    * Check for illegal attributes.
7117    */
7118    attr = node->properties;
7119    while (attr != NULL) {
7120	if (attr->ns == NULL) {
7121	    if (isRef) {
7122		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7123		    xmlSchemaPValAttrNodeID(pctxt, attr);
7124		    goto attr_next;
7125		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7126		    goto attr_next;
7127		}
7128	    } else {
7129		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7130		    goto attr_next;
7131		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7132		    xmlSchemaPValAttrNodeID(pctxt, attr);
7133		    goto attr_next;
7134		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7135		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7136			attr, &tmpNs, &tmpName);
7137		    goto attr_next;
7138		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7139		    /*
7140		    * Evaluate the target namespace
7141		    */
7142		    hasForm = 1;
7143		    attrValue = xmlSchemaGetNodeContent(pctxt,
7144			(xmlNodePtr) attr);
7145		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7146			ns = pctxt->targetNamespace;
7147		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7148		    {
7149			xmlSchemaPSimpleTypeErr(pctxt,
7150			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7151			    NULL, (xmlNodePtr) attr,
7152			    NULL, "(qualified | unqualified)",
7153			    attrValue, NULL, NULL, NULL);
7154		    }
7155		    goto attr_next;
7156		}
7157	    }
7158	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7159
7160		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7161		/* TODO: Maybe we need to normalize the value beforehand. */
7162		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7163		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7164		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7165		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7166		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7167		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7168		else {
7169		    xmlSchemaPSimpleTypeErr(pctxt,
7170			XML_SCHEMAP_INVALID_ATTR_USE,
7171			NULL, (xmlNodePtr) attr,
7172			NULL, "(optional | prohibited | required)",
7173			attrValue, NULL, NULL, NULL);
7174		}
7175		goto attr_next;
7176	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7177		/*
7178		* 3.2.3 : 1
7179		* default and fixed must not both be present.
7180		*/
7181		if (defValue) {
7182		    xmlSchemaPMutualExclAttrErr(pctxt,
7183			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7184			NULL, attr, "default", "fixed");
7185		} else {
7186		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7187		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7188		}
7189		goto attr_next;
7190	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7191		/*
7192		* 3.2.3 : 1
7193		* default and fixed must not both be present.
7194		*/
7195		if (defValue) {
7196		    xmlSchemaPMutualExclAttrErr(pctxt,
7197			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7198			NULL, attr, "default", "fixed");
7199		} else {
7200		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7201		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7202		}
7203		goto attr_next;
7204	    }
7205	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7206	    goto attr_next;
7207
7208	xmlSchemaPIllegalAttrErr(pctxt,
7209	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7210
7211attr_next:
7212	attr = attr->next;
7213    }
7214    /*
7215    * 3.2.3 : 2
7216    * If default and use are both present, use must have
7217    * the actual value optional.
7218    */
7219    if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7220	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7221	xmlSchemaPSimpleTypeErr(pctxt,
7222	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7223	    NULL, node, NULL,
7224	    "(optional | prohibited | required)", NULL,
7225	    "The value of the attribute 'use' must be 'optional' "
7226	    "if the attribute 'default' is present",
7227	    NULL, NULL);
7228    }
7229    /*
7230    * We want correct attributes.
7231    */
7232    if (nberrors != pctxt->nberrors)
7233	return(NULL);
7234    if (! isRef) {
7235	xmlSchemaAttributePtr attrDecl;
7236
7237	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7238	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7239	    ns = pctxt->targetNamespace;
7240	/*
7241	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7242	* TODO: Move this to the component layer.
7243	*/
7244	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7245	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7246		XML_SCHEMAP_NO_XSI,
7247		node, NULL,
7248		"The target namespace must not match '%s'",
7249		xmlSchemaInstanceNs, NULL);
7250	}
7251	attr = xmlSchemaGetPropNode(node, "name");
7252	if (attr == NULL) {
7253	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7254		NULL, node, "name", NULL);
7255	    return (NULL);
7256	}
7257	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7258	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7259	    return (NULL);
7260	}
7261	/*
7262	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7263	* TODO: Move this to the component layer.
7264	*/
7265	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7266	    xmlSchemaPSimpleTypeErr(pctxt,
7267		XML_SCHEMAP_NO_XMLNS,
7268		NULL, (xmlNodePtr) attr,
7269		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7270		"The value of the attribute must not match 'xmlns'",
7271		NULL, NULL);
7272	    return (NULL);
7273	}
7274	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7275	    goto check_children;
7276	/*
7277	* Create the attribute use component.
7278	*/
7279	use = xmlSchemaAddAttributeUse(pctxt, node);
7280	if (use == NULL)
7281	    return(NULL);
7282	use->occurs = occurs;
7283	/*
7284	* Create the attribute declaration.
7285	*/
7286	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7287	if (attrDecl == NULL)
7288	    return (NULL);
7289	if (tmpName != NULL) {
7290	    attrDecl->typeName = tmpName;
7291	    attrDecl->typeNs = tmpNs;
7292	}
7293	use->attrDecl = attrDecl;
7294	/*
7295	* Value constraint.
7296	*/
7297	if (defValue != NULL) {
7298	    attrDecl->defValue = defValue;
7299	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7300		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7301	}
7302    } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7303	xmlSchemaQNameRefPtr ref;
7304
7305	/*
7306	* Create the attribute use component.
7307	*/
7308	use = xmlSchemaAddAttributeUse(pctxt, node);
7309	if (use == NULL)
7310	    return(NULL);
7311	/*
7312	* We need to resolve the reference at later stage.
7313	*/
7314	WXS_ADD_PENDING(pctxt, use);
7315	use->occurs = occurs;
7316	/*
7317	* Create a QName reference to the attribute declaration.
7318	*/
7319	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7320	    tmpName, tmpNs);
7321	if (ref == NULL)
7322	    return(NULL);
7323	/*
7324	* Assign the reference. This will be substituted for the
7325	* referenced attribute declaration when the QName is resolved.
7326	*/
7327	use->attrDecl = WXS_ATTR_CAST ref;
7328	/*
7329	* Value constraint.
7330	*/
7331	if (defValue != NULL)
7332	    use->defValue = defValue;
7333	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7334		use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7335    }
7336
7337check_children:
7338    /*
7339    * And now for the children...
7340    */
7341    child = node->children;
7342    if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7343	xmlSchemaAttributeUseProhibPtr prohib;
7344
7345	if (IS_SCHEMA(child, "annotation")) {
7346	    xmlSchemaParseAnnotation(pctxt, child, 0);
7347	    child = child->next;
7348	}
7349	if (child != NULL) {
7350	    xmlSchemaPContentErr(pctxt,
7351		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7352		NULL, node, child, NULL,
7353		"(annotation?)");
7354	}
7355	/*
7356	* Check for pointlessness of attribute prohibitions.
7357	*/
7358	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7359	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7360		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7361		node, NULL,
7362		"Skipping attribute use prohibition, since it is "
7363		"pointless inside an <attributeGroup>",
7364		NULL, NULL, NULL);
7365	    return(NULL);
7366	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7367	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7368		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7369		node, NULL,
7370		"Skipping attribute use prohibition, since it is "
7371		"pointless when extending a type",
7372		NULL, NULL, NULL);
7373	    return(NULL);
7374	}
7375	if (! isRef) {
7376	    tmpName = name;
7377	    tmpNs = ns;
7378	}
7379	/*
7380	* Check for duplicate attribute prohibitions.
7381	*/
7382	if (uses) {
7383	    int i;
7384
7385	    for (i = 0; i < uses->nbItems; i++) {
7386		use = uses->items[i];
7387		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7388		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7389		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7390		{
7391		    xmlChar *str = NULL;
7392
7393		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7394			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7395			node, NULL,
7396			"Skipping duplicate attribute use prohibition '%s'",
7397			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7398			NULL, NULL);
7399		    FREE_AND_NULL(str)
7400		    return(NULL);
7401		}
7402	    }
7403	}
7404	/*
7405	* Create the attribute prohibition helper component.
7406	*/
7407	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7408	if (prohib == NULL)
7409	    return(NULL);
7410	prohib->node = node;
7411	prohib->name = tmpName;
7412	prohib->targetNamespace = tmpNs;
7413	if (isRef) {
7414	    /*
7415	    * We need at least to resolve to the attribute declaration.
7416	    */
7417	    WXS_ADD_PENDING(pctxt, prohib);
7418	}
7419	return(WXS_BASIC_CAST prohib);
7420    } else {
7421	if (IS_SCHEMA(child, "annotation")) {
7422	    /*
7423	    * TODO: Should this go into the attr decl?
7424	    */
7425	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7426	    child = child->next;
7427	}
7428	if (isRef) {
7429	    if (child != NULL) {
7430		if (IS_SCHEMA(child, "simpleType"))
7431		    /*
7432		    * 3.2.3 : 3.2
7433		    * If ref is present, then all of <simpleType>,
7434		    * form and type must be absent.
7435		    */
7436		    xmlSchemaPContentErr(pctxt,
7437			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7438			NULL, node, child, NULL,
7439			"(annotation?)");
7440		else
7441		    xmlSchemaPContentErr(pctxt,
7442			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7443			NULL, node, child, NULL,
7444			"(annotation?)");
7445	    }
7446	} else {
7447	    if (IS_SCHEMA(child, "simpleType")) {
7448		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7449		    /*
7450		    * 3.2.3 : 4
7451		    * type and <simpleType> must not both be present.
7452		    */
7453		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7454			NULL, node, child,
7455			"The attribute 'type' and the <simpleType> child "
7456			"are mutually exclusive", NULL);
7457		} else
7458		    WXS_ATTRUSE_TYPEDEF(use) =
7459			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7460		child = child->next;
7461	    }
7462	    if (child != NULL)
7463		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464		NULL, node, child, NULL,
7465		"(annotation?, simpleType?)");
7466	}
7467    }
7468    return (WXS_BASIC_CAST use);
7469}
7470
7471
7472static xmlSchemaAttributePtr
7473xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7474			      xmlSchemaPtr schema,
7475			      xmlNodePtr node)
7476{
7477    const xmlChar *attrValue;
7478    xmlSchemaAttributePtr ret;
7479    xmlNodePtr child = NULL;
7480    xmlAttrPtr attr;
7481
7482    /*
7483     * Note that the w3c spec assumes the schema to be validated with schema
7484     * for schemas beforehand.
7485     *
7486     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7487     */
7488    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7489        return (NULL);
7490    /*
7491    * 3.2.3 : 3.1
7492    * One of ref or name must be present, but not both
7493    */
7494    attr = xmlSchemaGetPropNode(node, "name");
7495    if (attr == NULL) {
7496	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7497	    NULL, node, "name", NULL);
7498	return (NULL);
7499    }
7500    if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7501	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7502	return (NULL);
7503    }
7504    /*
7505    * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7506    * TODO: Move this to the component layer.
7507    */
7508    if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7509	xmlSchemaPSimpleTypeErr(pctxt,
7510	    XML_SCHEMAP_NO_XMLNS,
7511	    NULL, (xmlNodePtr) attr,
7512	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7513	    "The value of the attribute must not match 'xmlns'",
7514	    NULL, NULL);
7515	return (NULL);
7516    }
7517    /*
7518    * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7519    * TODO: Move this to the component layer.
7520    *       Or better leave it here and add it to the component layer
7521    *       if we have a schema construction API.
7522    */
7523    if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7524	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7525	    XML_SCHEMAP_NO_XSI, node, NULL,
7526	    "The target namespace must not match '%s'",
7527	    xmlSchemaInstanceNs, NULL);
7528    }
7529
7530    ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7531	pctxt->targetNamespace, node, 1);
7532    if (ret == NULL)
7533	return (NULL);
7534    ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7535
7536    /*
7537    * Check for illegal attributes.
7538    */
7539    attr = node->properties;
7540    while (attr != NULL) {
7541	if (attr->ns == NULL) {
7542	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7543		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7544		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7545		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7546		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7547	    {
7548		xmlSchemaPIllegalAttrErr(pctxt,
7549		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7550	    }
7551	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7552	    xmlSchemaPIllegalAttrErr(pctxt,
7553		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7554	}
7555	attr = attr->next;
7556    }
7557    xmlSchemaPValAttrQName(pctxt, schema, NULL,
7558	node, "type", &ret->typeNs, &ret->typeName);
7559
7560    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7561    /*
7562    * Attribute "fixed".
7563    */
7564    ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7565    if (ret->defValue != NULL)
7566	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7567    /*
7568    * Attribute "default".
7569    */
7570    attr = xmlSchemaGetPropNode(node, "default");
7571    if (attr != NULL) {
7572	/*
7573	* 3.2.3 : 1
7574	* default and fixed must not both be present.
7575	*/
7576	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7577	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7578		WXS_BASIC_CAST ret, attr, "default", "fixed");
7579	} else
7580	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7581    }
7582    /*
7583    * And now for the children...
7584    */
7585    child = node->children;
7586    if (IS_SCHEMA(child, "annotation")) {
7587        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7588        child = child->next;
7589    }
7590    if (IS_SCHEMA(child, "simpleType")) {
7591	if (ret->typeName != NULL) {
7592	    /*
7593	    * 3.2.3 : 4
7594	    * type and <simpleType> must not both be present.
7595	    */
7596	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7597		NULL, node, child,
7598		"The attribute 'type' and the <simpleType> child "
7599		"are mutually exclusive", NULL);
7600	} else
7601	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7602	child = child->next;
7603    }
7604    if (child != NULL)
7605	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7606	    NULL, node, child, NULL,
7607	    "(annotation?, simpleType?)");
7608
7609    return (ret);
7610}
7611
7612/**
7613 * xmlSchemaParseAttributeGroupRef:
7614 * @ctxt:  a schema validation context
7615 * @schema:  the schema being built
7616 * @node:  a subtree containing XML Schema informations
7617 *
7618 * Parse an attribute group definition reference.
7619 * Note that a reference to an attribute group does not
7620 * correspond to any component at all.
7621 * *WARNING* this interface is highly subject to change
7622 *
7623 * Returns the attribute group or NULL in case of error.
7624 */
7625static xmlSchemaQNameRefPtr
7626xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7627				xmlSchemaPtr schema,
7628				xmlNodePtr node)
7629{
7630    xmlSchemaQNameRefPtr ret;
7631    xmlNodePtr child = NULL;
7632    xmlAttrPtr attr;
7633    const xmlChar *refNs = NULL, *ref = NULL;
7634
7635    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7636        return (NULL);
7637
7638    attr = xmlSchemaGetPropNode(node, "ref");
7639    if (attr == NULL) {
7640	xmlSchemaPMissingAttrErr(pctxt,
7641	    XML_SCHEMAP_S4S_ATTR_MISSING,
7642	    NULL, node, "ref", NULL);
7643	return (NULL);
7644    }
7645    xmlSchemaPValAttrNodeQName(pctxt, schema,
7646	NULL, attr, &refNs, &ref);
7647    if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7648	return(NULL);
7649
7650    /*
7651    * Check for illegal attributes.
7652    */
7653    attr = node->properties;
7654    while (attr != NULL) {
7655	if (attr->ns == NULL) {
7656	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7657		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7658	    {
7659		xmlSchemaPIllegalAttrErr(pctxt,
7660		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7661	    }
7662	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7663	    xmlSchemaPIllegalAttrErr(pctxt,
7664		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7665	}
7666	attr = attr->next;
7667    }
7668    /* Attribute ID */
7669    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7670
7671    /*
7672    * And now for the children...
7673    */
7674    child = node->children;
7675    if (IS_SCHEMA(child, "annotation")) {
7676	/*
7677	* TODO: We do not have a place to store the annotation, do we?
7678	*/
7679        xmlSchemaParseAnnotation(pctxt, child, 0);
7680        child = child->next;
7681    }
7682    if (child != NULL) {
7683	xmlSchemaPContentErr(pctxt,
7684	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7685	    NULL, node, child, NULL,
7686	    "(annotation?)");
7687    }
7688
7689    /*
7690    * Handle attribute group redefinitions.
7691    */
7692    if (pctxt->isRedefine && pctxt->redef &&
7693	(pctxt->redef->item->type ==
7694	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7695	(ref == pctxt->redef->refName) &&
7696	(refNs == pctxt->redef->refTargetNs))
7697    {
7698	/*
7699	* SPEC src-redefine:
7700	* (7.1) "If it has an <attributeGroup> among its contents
7701	* the �actual value� of whose ref [attribute] is the same
7702	* as the �actual value� of its own name attribute plus
7703	* target namespace, then it must have exactly one such group."
7704	*/
7705	if (pctxt->redefCounter != 0) {
7706	    xmlChar *str = NULL;
7707
7708	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7709		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7710		"The redefining attribute group definition "
7711		"'%s' must not contain more than one "
7712		"reference to the redefined definition",
7713		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7714	    FREE_AND_NULL(str);
7715	    return(NULL);
7716	}
7717	pctxt->redefCounter++;
7718	/*
7719	* URGENT TODO: How to ensure that the reference will not be
7720	* handled by the normal component resolution mechanism?
7721	*/
7722	ret = xmlSchemaNewQNameRef(pctxt,
7723	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7724	if (ret == NULL)
7725	    return(NULL);
7726	ret->node = node;
7727	pctxt->redef->reference = WXS_BASIC_CAST ret;
7728    } else {
7729	/*
7730	* Create a QName-reference helper component. We will substitute this
7731	* component for the attribute uses of the referenced attribute group
7732	* definition.
7733	*/
7734	ret = xmlSchemaNewQNameRef(pctxt,
7735	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7736	if (ret == NULL)
7737	    return(NULL);
7738	ret->node = node;
7739	/* Add to pending items, to be able to resolve the reference. */
7740	WXS_ADD_PENDING(pctxt, ret);
7741    }
7742    return (ret);
7743}
7744
7745/**
7746 * xmlSchemaParseAttributeGroupDefinition:
7747 * @pctxt:  a schema validation context
7748 * @schema:  the schema being built
7749 * @node:  a subtree containing XML Schema informations
7750 *
7751 * parse a XML schema Attribute Group declaration
7752 * *WARNING* this interface is highly subject to change
7753 *
7754 * Returns the attribute group definition or NULL in case of error.
7755 */
7756static xmlSchemaAttributeGroupPtr
7757xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7758				       xmlSchemaPtr schema,
7759				       xmlNodePtr node)
7760{
7761    const xmlChar *name;
7762    xmlSchemaAttributeGroupPtr ret;
7763    xmlNodePtr child = NULL;
7764    xmlAttrPtr attr;
7765    int hasRefs = 0;
7766
7767    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7768        return (NULL);
7769
7770    attr = xmlSchemaGetPropNode(node, "name");
7771    if (attr == NULL) {
7772	xmlSchemaPMissingAttrErr(pctxt,
7773	    XML_SCHEMAP_S4S_ATTR_MISSING,
7774	    NULL, node, "name", NULL);
7775	return (NULL);
7776    }
7777    /*
7778    * The name is crucial, exit if invalid.
7779    */
7780    if (xmlSchemaPValAttrNode(pctxt,
7781	NULL, attr,
7782	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7783	return (NULL);
7784    }
7785    ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7786	name, pctxt->targetNamespace, node);
7787    if (ret == NULL)
7788	return (NULL);
7789    /*
7790    * Check for illegal attributes.
7791    */
7792    attr = node->properties;
7793    while (attr != NULL) {
7794	if (attr->ns == NULL) {
7795	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7796		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7797	    {
7798		xmlSchemaPIllegalAttrErr(pctxt,
7799		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7800	    }
7801	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7802	    xmlSchemaPIllegalAttrErr(pctxt,
7803		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7804	}
7805	attr = attr->next;
7806    }
7807    /* Attribute ID */
7808    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7809    /*
7810    * And now for the children...
7811    */
7812    child = node->children;
7813    if (IS_SCHEMA(child, "annotation")) {
7814        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7815        child = child->next;
7816    }
7817    /*
7818    * Parse contained attribute decls/refs.
7819    */
7820    if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7821	(xmlSchemaItemListPtr *) &(ret->attrUses),
7822	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7823	return(NULL);
7824    if (hasRefs)
7825	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7826    /*
7827    * Parse the attribute wildcard.
7828    */
7829    if (IS_SCHEMA(child, "anyAttribute")) {
7830	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7831	    schema, child);
7832	child = child->next;
7833    }
7834    if (child != NULL) {
7835	xmlSchemaPContentErr(pctxt,
7836	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7837	    NULL, node, child, NULL,
7838	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7839    }
7840    return (ret);
7841}
7842
7843/**
7844 * xmlSchemaPValAttrFormDefault:
7845 * @value:  the value
7846 * @flags: the flags to be modified
7847 * @flagQualified: the specific flag for "qualified"
7848 *
7849 * Returns 0 if the value is valid, 1 otherwise.
7850 */
7851static int
7852xmlSchemaPValAttrFormDefault(const xmlChar *value,
7853			     int *flags,
7854			     int flagQualified)
7855{
7856    if (xmlStrEqual(value, BAD_CAST "qualified")) {
7857	if  ((*flags & flagQualified) == 0)
7858	    *flags |= flagQualified;
7859    } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7860	return (1);
7861
7862    return (0);
7863}
7864
7865/**
7866 * xmlSchemaPValAttrBlockFinal:
7867 * @value:  the value
7868 * @flags: the flags to be modified
7869 * @flagAll: the specific flag for "#all"
7870 * @flagExtension: the specific flag for "extension"
7871 * @flagRestriction: the specific flag for "restriction"
7872 * @flagSubstitution: the specific flag for "substitution"
7873 * @flagList: the specific flag for "list"
7874 * @flagUnion: the specific flag for "union"
7875 *
7876 * Validates the value of the attribute "final" and "block". The value
7877 * is converted into the specified flag values and returned in @flags.
7878 *
7879 * Returns 0 if the value is valid, 1 otherwise.
7880 */
7881
7882static int
7883xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7884			    int *flags,
7885			    int flagAll,
7886			    int flagExtension,
7887			    int flagRestriction,
7888			    int flagSubstitution,
7889			    int flagList,
7890			    int flagUnion)
7891{
7892    int ret = 0;
7893
7894    /*
7895    * TODO: This does not check for dublicate entries.
7896    */
7897    if ((flags == NULL) || (value == NULL))
7898	return (-1);
7899    if (value[0] == 0)
7900	return (0);
7901    if (xmlStrEqual(value, BAD_CAST "#all")) {
7902	if (flagAll != -1)
7903	    *flags |= flagAll;
7904	else {
7905	    if (flagExtension != -1)
7906		*flags |= flagExtension;
7907	    if (flagRestriction != -1)
7908		*flags |= flagRestriction;
7909	    if (flagSubstitution != -1)
7910		*flags |= flagSubstitution;
7911	    if (flagList != -1)
7912		*flags |= flagList;
7913	    if (flagUnion != -1)
7914		*flags |= flagUnion;
7915	}
7916    } else {
7917	const xmlChar *end, *cur = value;
7918	xmlChar *item;
7919
7920	do {
7921	    while (IS_BLANK_CH(*cur))
7922		cur++;
7923	    end = cur;
7924	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7925		end++;
7926	    if (end == cur)
7927		break;
7928	    item = xmlStrndup(cur, end - cur);
7929	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7930		if (flagExtension != -1) {
7931		    if ((*flags & flagExtension) == 0)
7932			*flags |= flagExtension;
7933		} else
7934		    ret = 1;
7935	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7936		if (flagRestriction != -1) {
7937		    if ((*flags & flagRestriction) == 0)
7938			*flags |= flagRestriction;
7939		} else
7940		    ret = 1;
7941	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7942		if (flagSubstitution != -1) {
7943		    if ((*flags & flagSubstitution) == 0)
7944			*flags |= flagSubstitution;
7945		} else
7946		    ret = 1;
7947	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
7948		if (flagList != -1) {
7949		    if ((*flags & flagList) == 0)
7950			*flags |= flagList;
7951		} else
7952		    ret = 1;
7953	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
7954		if (flagUnion != -1) {
7955		    if ((*flags & flagUnion) == 0)
7956			*flags |= flagUnion;
7957		} else
7958		    ret = 1;
7959	    } else
7960		ret = 1;
7961	    if (item != NULL)
7962		xmlFree(item);
7963	    cur = end;
7964	} while ((ret == 0) && (*cur != 0));
7965    }
7966
7967    return (ret);
7968}
7969
7970static int
7971xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7972			     xmlSchemaIDCPtr idc,
7973			     xmlSchemaIDCSelectPtr selector,
7974			     xmlAttrPtr attr,
7975			     int isField)
7976{
7977    xmlNodePtr node;
7978
7979    /*
7980    * c-selector-xpath:
7981    * Schema Component Constraint: Selector Value OK
7982    *
7983    * TODO: 1 The {selector} must be a valid XPath expression, as defined
7984    * in [XPath].
7985    */
7986    if (selector == NULL) {
7987	xmlSchemaPErr(ctxt, idc->node,
7988	    XML_SCHEMAP_INTERNAL,
7989	    "Internal error: xmlSchemaCheckCSelectorXPath, "
7990	    "the selector is not specified.\n", NULL, NULL);
7991	return (-1);
7992    }
7993    if (attr == NULL)
7994	node = idc->node;
7995    else
7996	node = (xmlNodePtr) attr;
7997    if (selector->xpath == NULL) {
7998	xmlSchemaPCustomErr(ctxt,
7999	    /* TODO: Adjust error code. */
8000	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8001	    NULL, node,
8002	    "The XPath expression of the selector is not valid", NULL);
8003	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8004    } else {
8005	const xmlChar **nsArray = NULL;
8006	xmlNsPtr *nsList = NULL;
8007	/*
8008	* Compile the XPath expression.
8009	*/
8010	/*
8011	* TODO: We need the array of in-scope namespaces for compilation.
8012	* TODO: Call xmlPatterncompile with different options for selector/
8013	* field.
8014	*/
8015	if (attr == NULL)
8016	    nsList = NULL;
8017	else
8018	    nsList = xmlGetNsList(attr->doc, attr->parent);
8019	/*
8020	* Build an array of prefixes and namespaces.
8021	*/
8022	if (nsList != NULL) {
8023	    int i, count = 0;
8024
8025	    for (i = 0; nsList[i] != NULL; i++)
8026		count++;
8027
8028	    nsArray = (const xmlChar **) xmlMalloc(
8029		(count * 2 + 1) * sizeof(const xmlChar *));
8030	    if (nsArray == NULL) {
8031		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8032		    NULL);
8033		xmlFree(nsList);
8034		return (-1);
8035	    }
8036	    for (i = 0; i < count; i++) {
8037		nsArray[2 * i] = nsList[i]->href;
8038		nsArray[2 * i + 1] = nsList[i]->prefix;
8039	    }
8040	    nsArray[count * 2] = NULL;
8041	    xmlFree(nsList);
8042	}
8043	/*
8044	* TODO: Differentiate between "selector" and "field".
8045	*/
8046	if (isField)
8047	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8048		NULL, XML_PATTERN_XSFIELD, nsArray);
8049	else
8050	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8051		NULL, XML_PATTERN_XSSEL, nsArray);
8052	if (nsArray != NULL)
8053	    xmlFree((xmlChar **) nsArray);
8054
8055	if (selector->xpathComp == NULL) {
8056	    xmlSchemaPCustomErr(ctxt,
8057		/* TODO: Adjust error code? */
8058		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8059		NULL, node,
8060		"The XPath expression '%s' could not be "
8061		"compiled", selector->xpath);
8062	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8063	}
8064    }
8065    return (0);
8066}
8067
8068#define ADD_ANNOTATION(annot)   \
8069    xmlSchemaAnnotPtr cur = item->annot; \
8070    if (item->annot == NULL) {  \
8071	item->annot = annot;    \
8072	return (annot);         \
8073    }                           \
8074    cur = item->annot;          \
8075    if (cur->next != NULL) {    \
8076	cur = cur->next;	\
8077    }                           \
8078    cur->next = annot;
8079
8080/**
8081 * xmlSchemaAssignAnnotation:
8082 * @item: the schema component
8083 * @annot: the annotation
8084 *
8085 * Adds the annotation to the given schema component.
8086 *
8087 * Returns the given annotaion.
8088 */
8089static xmlSchemaAnnotPtr
8090xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8091		       xmlSchemaAnnotPtr annot)
8092{
8093    if ((annItem == NULL) || (annot == NULL))
8094	return (NULL);
8095    switch (annItem->type) {
8096	case XML_SCHEMA_TYPE_ELEMENT: {
8097		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8098		ADD_ANNOTATION(annot)
8099	    }
8100	    break;
8101	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8102		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8103		ADD_ANNOTATION(annot)
8104	    }
8105	    break;
8106	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8107	case XML_SCHEMA_TYPE_ANY: {
8108		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8109		ADD_ANNOTATION(annot)
8110	    }
8111	    break;
8112	case XML_SCHEMA_TYPE_PARTICLE:
8113	case XML_SCHEMA_TYPE_IDC_KEY:
8114	case XML_SCHEMA_TYPE_IDC_KEYREF:
8115	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8116		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8117		ADD_ANNOTATION(annot)
8118	    }
8119	    break;
8120	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8121		xmlSchemaAttributeGroupPtr item =
8122		    (xmlSchemaAttributeGroupPtr) annItem;
8123		ADD_ANNOTATION(annot)
8124	    }
8125	    break;
8126	case XML_SCHEMA_TYPE_NOTATION: {
8127		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8128		ADD_ANNOTATION(annot)
8129	    }
8130	    break;
8131	case XML_SCHEMA_FACET_MININCLUSIVE:
8132	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8133	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8134	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8135	case XML_SCHEMA_FACET_TOTALDIGITS:
8136	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8137	case XML_SCHEMA_FACET_PATTERN:
8138	case XML_SCHEMA_FACET_ENUMERATION:
8139	case XML_SCHEMA_FACET_WHITESPACE:
8140	case XML_SCHEMA_FACET_LENGTH:
8141	case XML_SCHEMA_FACET_MAXLENGTH:
8142	case XML_SCHEMA_FACET_MINLENGTH: {
8143		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8144		ADD_ANNOTATION(annot)
8145	    }
8146	    break;
8147	case XML_SCHEMA_TYPE_SIMPLE:
8148	case XML_SCHEMA_TYPE_COMPLEX: {
8149		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8150		ADD_ANNOTATION(annot)
8151	    }
8152	    break;
8153	case XML_SCHEMA_TYPE_GROUP: {
8154		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8155		ADD_ANNOTATION(annot)
8156	    }
8157	    break;
8158	case XML_SCHEMA_TYPE_SEQUENCE:
8159	case XML_SCHEMA_TYPE_CHOICE:
8160	case XML_SCHEMA_TYPE_ALL: {
8161		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8162		ADD_ANNOTATION(annot)
8163	    }
8164	    break;
8165	default:
8166	     xmlSchemaPCustomErr(NULL,
8167		XML_SCHEMAP_INTERNAL,
8168		NULL, NULL,
8169		"Internal error: xmlSchemaAddAnnotation, "
8170		"The item is not a annotated schema component", NULL);
8171	     break;
8172    }
8173    return (annot);
8174}
8175
8176/**
8177 * xmlSchemaParseIDCSelectorAndField:
8178 * @ctxt:  a schema validation context
8179 * @schema:  the schema being built
8180 * @node:  a subtree containing XML Schema informations
8181 *
8182 * Parses a XML Schema identity-contraint definition's
8183 * <selector> and <field> elements.
8184 *
8185 * Returns the parsed identity-constraint definition.
8186 */
8187static xmlSchemaIDCSelectPtr
8188xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8189			  xmlSchemaIDCPtr idc,
8190			  xmlNodePtr node,
8191			  int isField)
8192{
8193    xmlSchemaIDCSelectPtr item;
8194    xmlNodePtr child = NULL;
8195    xmlAttrPtr attr;
8196
8197    /*
8198    * Check for illegal attributes.
8199    */
8200    attr = node->properties;
8201    while (attr != NULL) {
8202	if (attr->ns == NULL) {
8203	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8204		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8205		xmlSchemaPIllegalAttrErr(ctxt,
8206		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8207	    }
8208	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8209	    xmlSchemaPIllegalAttrErr(ctxt,
8210		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8211	}
8212	attr = attr->next;
8213    }
8214    /*
8215    * Create the item.
8216    */
8217    item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8218    if (item == NULL) {
8219        xmlSchemaPErrMemory(ctxt,
8220	    "allocating a 'selector' of an identity-constraint definition",
8221	    NULL);
8222        return (NULL);
8223    }
8224    memset(item, 0, sizeof(xmlSchemaIDCSelect));
8225    /*
8226    * Attribute "xpath" (mandatory).
8227    */
8228    attr = xmlSchemaGetPropNode(node, "xpath");
8229    if (attr == NULL) {
8230    	xmlSchemaPMissingAttrErr(ctxt,
8231	    XML_SCHEMAP_S4S_ATTR_MISSING,
8232	    NULL, node,
8233	    "name", NULL);
8234    } else {
8235	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8236	/*
8237	* URGENT TODO: "field"s have an other syntax than "selector"s.
8238	*/
8239
8240	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8241	    isField) == -1) {
8242	    xmlSchemaPErr(ctxt,
8243		(xmlNodePtr) attr,
8244		XML_SCHEMAP_INTERNAL,
8245		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8246		"validating the XPath expression of a IDC selector.\n",
8247		NULL, NULL);
8248	}
8249
8250    }
8251    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8252    /*
8253    * And now for the children...
8254    */
8255    child = node->children;
8256    if (IS_SCHEMA(child, "annotation")) {
8257	/*
8258	* Add the annotation to the parent IDC.
8259	*/
8260	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8261	    xmlSchemaParseAnnotation(ctxt, child, 1));
8262	child = child->next;
8263    }
8264    if (child != NULL) {
8265	xmlSchemaPContentErr(ctxt,
8266	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8267	    NULL, node, child,
8268	    NULL, "(annotation?)");
8269    }
8270
8271    return (item);
8272}
8273
8274/**
8275 * xmlSchemaParseIDC:
8276 * @ctxt:  a schema validation context
8277 * @schema:  the schema being built
8278 * @node:  a subtree containing XML Schema informations
8279 *
8280 * Parses a XML Schema identity-contraint definition.
8281 *
8282 * Returns the parsed identity-constraint definition.
8283 */
8284static xmlSchemaIDCPtr
8285xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8286		  xmlSchemaPtr schema,
8287		  xmlNodePtr node,
8288		  xmlSchemaTypeType idcCategory,
8289		  const xmlChar *targetNamespace)
8290{
8291    xmlSchemaIDCPtr item = NULL;
8292    xmlNodePtr child = NULL;
8293    xmlAttrPtr attr;
8294    const xmlChar *name = NULL;
8295    xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8296
8297    /*
8298    * Check for illegal attributes.
8299    */
8300    attr = node->properties;
8301    while (attr != NULL) {
8302	if (attr->ns == NULL) {
8303	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8304		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8305		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8306		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8307		xmlSchemaPIllegalAttrErr(ctxt,
8308		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8309	    }
8310	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8311	    xmlSchemaPIllegalAttrErr(ctxt,
8312		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8313	}
8314	attr = attr->next;
8315    }
8316    /*
8317    * Attribute "name" (mandatory).
8318    */
8319    attr = xmlSchemaGetPropNode(node, "name");
8320    if (attr == NULL) {
8321	xmlSchemaPMissingAttrErr(ctxt,
8322	    XML_SCHEMAP_S4S_ATTR_MISSING,
8323	    NULL, node,
8324	    "name", NULL);
8325	return (NULL);
8326    } else if (xmlSchemaPValAttrNode(ctxt,
8327	NULL, attr,
8328	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8329	return (NULL);
8330    }
8331    /* Create the component. */
8332    item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8333	idcCategory, node);
8334    if (item == NULL)
8335	return(NULL);
8336
8337    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8338    if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8339	/*
8340	* Attribute "refer" (mandatory).
8341	*/
8342	attr = xmlSchemaGetPropNode(node, "refer");
8343	if (attr == NULL) {
8344	    xmlSchemaPMissingAttrErr(ctxt,
8345		XML_SCHEMAP_S4S_ATTR_MISSING,
8346		NULL, node,
8347		"refer", NULL);
8348	} else {
8349	    /*
8350	    * Create a reference item.
8351	    */
8352	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8353		NULL, NULL);
8354	    if (item->ref == NULL)
8355		return (NULL);
8356	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8357		NULL, attr,
8358		&(item->ref->targetNamespace),
8359		&(item->ref->name));
8360	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8361		item->ref->targetNamespace);
8362	}
8363    }
8364    /*
8365    * And now for the children...
8366    */
8367    child = node->children;
8368    if (IS_SCHEMA(child, "annotation")) {
8369	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8370	child = child->next;
8371    }
8372    if (child == NULL) {
8373	xmlSchemaPContentErr(ctxt,
8374		XML_SCHEMAP_S4S_ELEM_MISSING,
8375		NULL, node, child,
8376		"A child element is missing",
8377		"(annotation?, (selector, field+))");
8378    }
8379    /*
8380    * Child element <selector>.
8381    */
8382    if (IS_SCHEMA(child, "selector")) {
8383	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8384	    item, child, 0);
8385	child = child->next;
8386	/*
8387	* Child elements <field>.
8388	*/
8389	if (IS_SCHEMA(child, "field")) {
8390	    do {
8391		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8392		    item, child, 1);
8393		if (field != NULL) {
8394		    field->index = item->nbFields;
8395		    item->nbFields++;
8396		    if (lastField != NULL)
8397			lastField->next = field;
8398		    else
8399			item->fields = field;
8400		    lastField = field;
8401		}
8402		child = child->next;
8403	    } while (IS_SCHEMA(child, "field"));
8404	} else {
8405	    xmlSchemaPContentErr(ctxt,
8406		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8407		NULL, node, child,
8408		NULL, "(annotation?, (selector, field+))");
8409	}
8410    }
8411    if (child != NULL) {
8412	xmlSchemaPContentErr(ctxt,
8413	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8414	    NULL, node, child,
8415	    NULL, "(annotation?, (selector, field+))");
8416    }
8417
8418    return (item);
8419}
8420
8421/**
8422 * xmlSchemaParseElement:
8423 * @ctxt:  a schema validation context
8424 * @schema:  the schema being built
8425 * @node:  a subtree containing XML Schema informations
8426 * @topLevel: indicates if this is global declaration
8427 *
8428 * Parses a XML schema element declaration.
8429 * *WARNING* this interface is highly subject to change
8430 *
8431 * Returns the element declaration or a particle; NULL in case
8432 * of an error or if the particle has minOccurs==maxOccurs==0.
8433 */
8434static xmlSchemaBasicItemPtr
8435xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8436                      xmlNodePtr node, int *isElemRef, int topLevel)
8437{
8438    xmlSchemaElementPtr decl = NULL;
8439    xmlSchemaParticlePtr particle = NULL;
8440    xmlSchemaAnnotPtr annot = NULL;
8441    xmlNodePtr child = NULL;
8442    xmlAttrPtr attr, nameAttr;
8443    int min, max, isRef = 0;
8444    xmlChar *des = NULL;
8445
8446    /* 3.3.3 Constraints on XML Representations of Element Declarations */
8447    /* TODO: Complete implementation of 3.3.6 */
8448
8449    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8450        return (NULL);
8451
8452    if (isElemRef != NULL)
8453	*isElemRef = 0;
8454    /*
8455    * If we get a "ref" attribute on a local <element> we will assume it's
8456    * a reference - even if there's a "name" attribute; this seems to be more
8457    * robust.
8458    */
8459    nameAttr = xmlSchemaGetPropNode(node, "name");
8460    attr = xmlSchemaGetPropNode(node, "ref");
8461    if ((topLevel) || (attr == NULL)) {
8462	if (nameAttr == NULL) {
8463	    xmlSchemaPMissingAttrErr(ctxt,
8464		XML_SCHEMAP_S4S_ATTR_MISSING,
8465		NULL, node, "name", NULL);
8466	    return (NULL);
8467	}
8468    } else
8469	isRef = 1;
8470
8471    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8472    child = node->children;
8473    if (IS_SCHEMA(child, "annotation")) {
8474	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8475	child = child->next;
8476    }
8477    /*
8478    * Skip particle part if a global declaration.
8479    */
8480    if (topLevel)
8481	goto declaration_part;
8482    /*
8483    * The particle part ==================================================
8484    */
8485    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8486    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8487    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8488    particle = xmlSchemaAddParticle(ctxt, node, min, max);
8489    if (particle == NULL)
8490	goto return_null;
8491
8492    /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8493
8494    if (isRef) {
8495	const xmlChar *refNs = NULL, *ref = NULL;
8496	xmlSchemaQNameRefPtr refer = NULL;
8497	/*
8498	* The reference part =============================================
8499	*/
8500	if (isElemRef != NULL)
8501	    *isElemRef = 1;
8502
8503	xmlSchemaPValAttrNodeQName(ctxt, schema,
8504	    NULL, attr, &refNs, &ref);
8505	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8506	/*
8507	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8508	*/
8509	if (nameAttr != NULL) {
8510	    xmlSchemaPMutualExclAttrErr(ctxt,
8511		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8512	}
8513	/*
8514	* Check for illegal attributes.
8515	*/
8516	attr = node->properties;
8517	while (attr != NULL) {
8518	    if (attr->ns == NULL) {
8519		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8520		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8521		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8522		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8523		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8524		{
8525		    attr = attr->next;
8526		    continue;
8527		} else {
8528		    /* SPEC (3.3.3 : 2.2) */
8529		    xmlSchemaPCustomAttrErr(ctxt,
8530			XML_SCHEMAP_SRC_ELEMENT_2_2,
8531			NULL, NULL, attr,
8532			"Only the attributes 'minOccurs', 'maxOccurs' and "
8533			"'id' are allowed in addition to 'ref'");
8534		    break;
8535		}
8536	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8537		xmlSchemaPIllegalAttrErr(ctxt,
8538		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8539	    }
8540	    attr = attr->next;
8541	}
8542	/*
8543	* No children except <annotation> expected.
8544	*/
8545	if (child != NULL) {
8546	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8547		NULL, node, child, NULL, "(annotation?)");
8548	}
8549	if ((min == 0) && (max == 0))
8550	    goto return_null;
8551	/*
8552	* Create the reference item and attach it to the particle.
8553	*/
8554	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8555	    ref, refNs);
8556	if (refer == NULL)
8557	    goto return_null;
8558	particle->children = (xmlSchemaTreeItemPtr) refer;
8559	particle->annot = annot;
8560	/*
8561	* Add the particle to pending components, since the reference
8562	* need to be resolved.
8563	*/
8564	WXS_ADD_PENDING(ctxt, particle);
8565	return ((xmlSchemaBasicItemPtr) particle);
8566    }
8567    /*
8568    * The declaration part ===============================================
8569    */
8570declaration_part:
8571    {
8572	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8573	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8574
8575	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8576	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8577	    goto return_null;
8578	/*
8579	* Evaluate the target namespace.
8580	*/
8581	if (topLevel) {
8582	    ns = ctxt->targetNamespace;
8583	} else {
8584	    attr = xmlSchemaGetPropNode(node, "form");
8585	    if (attr != NULL) {
8586		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8587		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8588		    ns = ctxt->targetNamespace;
8589		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8590		    xmlSchemaPSimpleTypeErr(ctxt,
8591			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8592			NULL, (xmlNodePtr) attr,
8593			NULL, "(qualified | unqualified)",
8594			attrValue, NULL, NULL, NULL);
8595		}
8596	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8597		ns = ctxt->targetNamespace;
8598	}
8599	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8600	if (decl == NULL) {
8601	    goto return_null;
8602	}
8603	/*
8604	* Check for illegal attributes.
8605	*/
8606	attr = node->properties;
8607	while (attr != NULL) {
8608	    if (attr->ns == NULL) {
8609		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8610		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8611		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8612		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8613		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8614		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8615		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8616		{
8617		    if (topLevel == 0) {
8618			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8619			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8620			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8621			{
8622			    xmlSchemaPIllegalAttrErr(ctxt,
8623				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8624			}
8625		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8626			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8627			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8628
8629			xmlSchemaPIllegalAttrErr(ctxt,
8630			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8631		    }
8632		}
8633	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8634
8635		xmlSchemaPIllegalAttrErr(ctxt,
8636		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8637	    }
8638	    attr = attr->next;
8639	}
8640	/*
8641	* Extract/validate attributes.
8642	*/
8643	if (topLevel) {
8644	    /*
8645	    * Process top attributes of global element declarations here.
8646	    */
8647	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8648	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8649	    xmlSchemaPValAttrQName(ctxt, schema,
8650		NULL, node, "substitutionGroup",
8651		&(decl->substGroupNs), &(decl->substGroup));
8652	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8653		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8654	    /*
8655	    * Attribute "final".
8656	    */
8657	    attr = xmlSchemaGetPropNode(node, "final");
8658	    if (attr == NULL) {
8659		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8660		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8661		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8662		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8663	    } else {
8664		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8665		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8666		    -1,
8667		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8668		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8669		    xmlSchemaPSimpleTypeErr(ctxt,
8670			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8671			NULL, (xmlNodePtr) attr,
8672			NULL, "(#all | List of (extension | restriction))",
8673			attrValue, NULL, NULL, NULL);
8674		}
8675	    }
8676	}
8677	/*
8678	* Attribute "block".
8679	*/
8680	attr = xmlSchemaGetPropNode(node, "block");
8681	if (attr == NULL) {
8682	    /*
8683	    * Apply default "block" values.
8684	    */
8685	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8686		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8687	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8688		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8689	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8690		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8691	} else {
8692	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8693	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8694		-1,
8695		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8696		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8697		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8698		xmlSchemaPSimpleTypeErr(ctxt,
8699		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8700		    NULL, (xmlNodePtr) attr,
8701		    NULL, "(#all | List of (extension | "
8702		    "restriction | substitution))", attrValue,
8703		    NULL, NULL, NULL);
8704	    }
8705	}
8706	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8707	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8708
8709	attr = xmlSchemaGetPropNode(node, "type");
8710	if (attr != NULL) {
8711	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8712		NULL, attr,
8713		&(decl->namedTypeNs), &(decl->namedType));
8714	    xmlSchemaCheckReference(ctxt, schema, node,
8715		attr, decl->namedTypeNs);
8716	}
8717	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8718	attr = xmlSchemaGetPropNode(node, "fixed");
8719	if (attr != NULL) {
8720	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8721	    if (decl->value != NULL) {
8722		/*
8723		* 3.3.3 : 1
8724		* default and fixed must not both be present.
8725		*/
8726		xmlSchemaPMutualExclAttrErr(ctxt,
8727		    XML_SCHEMAP_SRC_ELEMENT_1,
8728		    NULL, attr, "default", "fixed");
8729	    } else {
8730		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8731		decl->value = fixed;
8732	    }
8733	}
8734	/*
8735	* And now for the children...
8736	*/
8737	if (IS_SCHEMA(child, "complexType")) {
8738	    /*
8739	    * 3.3.3 : 3
8740	    * "type" and either <simpleType> or <complexType> are mutually
8741	    * exclusive
8742	    */
8743	    if (decl->namedType != NULL) {
8744		xmlSchemaPContentErr(ctxt,
8745		    XML_SCHEMAP_SRC_ELEMENT_3,
8746		    NULL, node, child,
8747		    "The attribute 'type' and the <complexType> child are "
8748		    "mutually exclusive", NULL);
8749	    } else
8750		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8751	    child = child->next;
8752	} else if (IS_SCHEMA(child, "simpleType")) {
8753	    /*
8754	    * 3.3.3 : 3
8755	    * "type" and either <simpleType> or <complexType> are
8756	    * mutually exclusive
8757	    */
8758	    if (decl->namedType != NULL) {
8759		xmlSchemaPContentErr(ctxt,
8760		    XML_SCHEMAP_SRC_ELEMENT_3,
8761		    NULL, node, child,
8762		    "The attribute 'type' and the <simpleType> child are "
8763		    "mutually exclusive", NULL);
8764	    } else
8765		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8766	    child = child->next;
8767	}
8768	while ((IS_SCHEMA(child, "unique")) ||
8769	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8770	    if (IS_SCHEMA(child, "unique")) {
8771		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8772		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8773	    } else if (IS_SCHEMA(child, "key")) {
8774		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8775		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8776	    } else if (IS_SCHEMA(child, "keyref")) {
8777		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8778		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8779	    }
8780	    if (lastIDC != NULL)
8781		lastIDC->next = curIDC;
8782	    else
8783		decl->idcs = (void *) curIDC;
8784	    lastIDC = curIDC;
8785	    child = child->next;
8786	}
8787	if (child != NULL) {
8788	    xmlSchemaPContentErr(ctxt,
8789		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8790		NULL, node, child,
8791		NULL, "(annotation?, ((simpleType | complexType)?, "
8792		"(unique | key | keyref)*))");
8793	}
8794	decl->annot = annot;
8795    }
8796    /*
8797    * NOTE: Element Declaration Representation OK 4. will be checked at a
8798    * different layer.
8799    */
8800    FREE_AND_NULL(des)
8801    if (topLevel)
8802	return ((xmlSchemaBasicItemPtr) decl);
8803    else {
8804	particle->children = (xmlSchemaTreeItemPtr) decl;
8805	return ((xmlSchemaBasicItemPtr) particle);
8806    }
8807
8808return_null:
8809    FREE_AND_NULL(des);
8810    if (annot != NULL) {
8811	if (particle != NULL)
8812	    particle->annot = NULL;
8813	if (decl != NULL)
8814	    decl->annot = NULL;
8815	xmlSchemaFreeAnnot(annot);
8816    }
8817    return (NULL);
8818}
8819
8820/**
8821 * xmlSchemaParseUnion:
8822 * @ctxt:  a schema validation context
8823 * @schema:  the schema being built
8824 * @node:  a subtree containing XML Schema informations
8825 *
8826 * parse a XML schema Union definition
8827 * *WARNING* this interface is highly subject to change
8828 *
8829 * Returns -1 in case of internal error, 0 in case of success and a positive
8830 * error code otherwise.
8831 */
8832static int
8833xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8834                    xmlNodePtr node)
8835{
8836    xmlSchemaTypePtr type;
8837    xmlNodePtr child = NULL;
8838    xmlAttrPtr attr;
8839    const xmlChar *cur = NULL;
8840
8841    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8842        return (-1);
8843    /* Not a component, don't create it. */
8844    type = ctxt->ctxtType;
8845    /*
8846    * Mark the simple type as being of variety "union".
8847    */
8848    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8849    /*
8850    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8851    * then the �simple ur-type definition�."
8852    */
8853    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8854    /*
8855    * Check for illegal attributes.
8856    */
8857    attr = node->properties;
8858    while (attr != NULL) {
8859	if (attr->ns == NULL) {
8860	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8861		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8862		xmlSchemaPIllegalAttrErr(ctxt,
8863		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8864	    }
8865	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8866	    xmlSchemaPIllegalAttrErr(ctxt,
8867		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8868	}
8869	attr = attr->next;
8870    }
8871    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8872    /*
8873    * Attribute "memberTypes". This is a list of QNames.
8874    * TODO: Check the value to contain anything.
8875    */
8876    attr = xmlSchemaGetPropNode(node, "memberTypes");
8877    if (attr != NULL) {
8878	const xmlChar *end;
8879	xmlChar *tmp;
8880	const xmlChar *localName, *nsName;
8881	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8882	xmlSchemaQNameRefPtr ref;
8883
8884	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8885	type->base = cur;
8886	do {
8887	    while (IS_BLANK_CH(*cur))
8888		cur++;
8889	    end = cur;
8890	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8891		end++;
8892	    if (end == cur)
8893		break;
8894	    tmp = xmlStrndup(cur, end - cur);
8895	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8896		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8897		/*
8898		* Create the member type link.
8899		*/
8900		link = (xmlSchemaTypeLinkPtr)
8901		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8902		if (link == NULL) {
8903		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8904			"allocating a type link", NULL);
8905		    return (-1);
8906		}
8907		link->type = NULL;
8908		link->next = NULL;
8909		if (lastLink == NULL)
8910		    type->memberTypes = link;
8911		else
8912		    lastLink->next = link;
8913		lastLink = link;
8914		/*
8915		* Create a reference item.
8916		*/
8917		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8918		    localName, nsName);
8919		if (ref == NULL) {
8920		    FREE_AND_NULL(tmp)
8921		    return (-1);
8922		}
8923		/*
8924		* Assign the reference to the link, it will be resolved
8925		* later during fixup of the union simple type.
8926		*/
8927		link->type = (xmlSchemaTypePtr) ref;
8928	    }
8929	    FREE_AND_NULL(tmp)
8930	    cur = end;
8931	} while (*cur != 0);
8932
8933    }
8934    /*
8935    * And now for the children...
8936    */
8937    child = node->children;
8938    if (IS_SCHEMA(child, "annotation")) {
8939	/*
8940	* Add the annotation to the simple type ancestor.
8941	*/
8942	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8943	    xmlSchemaParseAnnotation(ctxt, child, 1));
8944        child = child->next;
8945    }
8946    if (IS_SCHEMA(child, "simpleType")) {
8947	xmlSchemaTypePtr subtype, last = NULL;
8948
8949	/*
8950	* Anchor the member types in the "subtypes" field of the
8951	* simple type.
8952	*/
8953	while (IS_SCHEMA(child, "simpleType")) {
8954	    subtype = (xmlSchemaTypePtr)
8955		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8956	    if (subtype != NULL) {
8957		if (last == NULL) {
8958		    type->subtypes = subtype;
8959		    last = subtype;
8960		} else {
8961		    last->next = subtype;
8962		    last = subtype;
8963		}
8964		last->next = NULL;
8965	    }
8966	    child = child->next;
8967	}
8968    }
8969    if (child != NULL) {
8970	xmlSchemaPContentErr(ctxt,
8971	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8972	    NULL, node, child, NULL, "(annotation?, simpleType*)");
8973    }
8974    if ((attr == NULL) && (type->subtypes == NULL)) {
8975	 /*
8976	* src-union-memberTypes-or-simpleTypes
8977	* Either the memberTypes [attribute] of the <union> element must
8978	* be non-empty or there must be at least one simpleType [child].
8979	*/
8980	xmlSchemaPCustomErr(ctxt,
8981	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8982	    NULL, node,
8983	    "Either the attribute 'memberTypes' or "
8984	    "at least one <simpleType> child must be present", NULL);
8985    }
8986    return (0);
8987}
8988
8989/**
8990 * xmlSchemaParseList:
8991 * @ctxt:  a schema validation context
8992 * @schema:  the schema being built
8993 * @node:  a subtree containing XML Schema informations
8994 *
8995 * parse a XML schema List definition
8996 * *WARNING* this interface is highly subject to change
8997 *
8998 * Returns -1 in case of error, 0 if the declaration is improper and
8999 *         1 in case of success.
9000 */
9001static xmlSchemaTypePtr
9002xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9003                   xmlNodePtr node)
9004{
9005    xmlSchemaTypePtr type;
9006    xmlNodePtr child = NULL;
9007    xmlAttrPtr attr;
9008
9009    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9010        return (NULL);
9011    /* Not a component, don't create it. */
9012    type = ctxt->ctxtType;
9013    /*
9014    * Mark the type as being of variety "list".
9015    */
9016    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9017    /*
9018    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9019    * then the �simple ur-type definition�."
9020    */
9021    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9022    /*
9023    * Check for illegal attributes.
9024    */
9025    attr = node->properties;
9026    while (attr != NULL) {
9027	if (attr->ns == NULL) {
9028	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9029		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9030		xmlSchemaPIllegalAttrErr(ctxt,
9031		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9032	    }
9033	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9034	    xmlSchemaPIllegalAttrErr(ctxt,
9035		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9036	}
9037	attr = attr->next;
9038    }
9039
9040    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9041
9042    /*
9043    * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9044    * fields for holding the reference to the itemType.
9045    *
9046    * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9047    * the "ref" fields.
9048    */
9049    xmlSchemaPValAttrQName(ctxt, schema, NULL,
9050	node, "itemType", &(type->baseNs), &(type->base));
9051    /*
9052    * And now for the children...
9053    */
9054    child = node->children;
9055    if (IS_SCHEMA(child, "annotation")) {
9056	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9057	    xmlSchemaParseAnnotation(ctxt, child, 1));
9058        child = child->next;
9059    }
9060    if (IS_SCHEMA(child, "simpleType")) {
9061	/*
9062	* src-list-itemType-or-simpleType
9063	* Either the itemType [attribute] or the <simpleType> [child] of
9064	* the <list> element must be present, but not both.
9065	*/
9066	if (type->base != NULL) {
9067	    xmlSchemaPCustomErr(ctxt,
9068		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9069		NULL, node,
9070		"The attribute 'itemType' and the <simpleType> child "
9071		"are mutually exclusive", NULL);
9072	} else {
9073	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9074	}
9075        child = child->next;
9076    } else if (type->base == NULL) {
9077	xmlSchemaPCustomErr(ctxt,
9078	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9079	    NULL, node,
9080	    "Either the attribute 'itemType' or the <simpleType> child "
9081	    "must be present", NULL);
9082    }
9083    if (child != NULL) {
9084	xmlSchemaPContentErr(ctxt,
9085	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9086	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9087    }
9088    if ((type->base == NULL) &&
9089	(type->subtypes == NULL) &&
9090	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9091	xmlSchemaPCustomErr(ctxt,
9092	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9093	    NULL, node,
9094	    "Either the attribute 'itemType' or the <simpleType> child "
9095	    "must be present", NULL);
9096    }
9097    return (NULL);
9098}
9099
9100/**
9101 * xmlSchemaParseSimpleType:
9102 * @ctxt:  a schema validation context
9103 * @schema:  the schema being built
9104 * @node:  a subtree containing XML Schema informations
9105 *
9106 * parse a XML schema Simple Type definition
9107 * *WARNING* this interface is highly subject to change
9108 *
9109 * Returns -1 in case of error, 0 if the declaration is improper and
9110 * 1 in case of success.
9111 */
9112static xmlSchemaTypePtr
9113xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9114                         xmlNodePtr node, int topLevel)
9115{
9116    xmlSchemaTypePtr type, oldCtxtType;
9117    xmlNodePtr child = NULL;
9118    const xmlChar *attrValue = NULL;
9119    xmlAttrPtr attr;
9120    int hasRestriction = 0;
9121
9122    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9123        return (NULL);
9124
9125    if (topLevel) {
9126	attr = xmlSchemaGetPropNode(node, "name");
9127	if (attr == NULL) {
9128	    xmlSchemaPMissingAttrErr(ctxt,
9129		XML_SCHEMAP_S4S_ATTR_MISSING,
9130		NULL, node,
9131		"name", NULL);
9132	    return (NULL);
9133	} else {
9134	    if (xmlSchemaPValAttrNode(ctxt,
9135		NULL, attr,
9136		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9137		return (NULL);
9138	    /*
9139	    * Skip built-in types.
9140	    */
9141	    if (ctxt->isS4S) {
9142		xmlSchemaTypePtr biType;
9143
9144		if (ctxt->isRedefine) {
9145		    /*
9146		    * REDEFINE: Disallow redefinition of built-in-types.
9147		    * TODO: It seems that the spec does not say anything
9148		    * about this case.
9149		    */
9150		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9151			NULL, node,
9152			"Redefinition of built-in simple types is not "
9153			"supported", NULL);
9154		    return(NULL);
9155		}
9156		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9157		if (biType != NULL)
9158		    return (biType);
9159	    }
9160	}
9161    }
9162    /*
9163    * TargetNamespace:
9164    * SPEC "The �actual value� of the targetNamespace [attribute]
9165    * of the <schema> ancestor element information item if present,
9166    * otherwise �absent�.
9167    */
9168    if (topLevel == 0) {
9169#ifdef ENABLE_NAMED_LOCALS
9170        char buf[40];
9171#endif
9172	/*
9173	* Parse as local simple type definition.
9174	*/
9175#ifdef ENABLE_NAMED_LOCALS
9176        snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9177	type = xmlSchemaAddType(ctxt, schema,
9178	    XML_SCHEMA_TYPE_SIMPLE,
9179	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9180	    ctxt->targetNamespace, node, 0);
9181#else
9182	type = xmlSchemaAddType(ctxt, schema,
9183	    XML_SCHEMA_TYPE_SIMPLE,
9184	    NULL, ctxt->targetNamespace, node, 0);
9185#endif
9186	if (type == NULL)
9187	    return (NULL);
9188	type->type = XML_SCHEMA_TYPE_SIMPLE;
9189	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9190	/*
9191	* Check for illegal attributes.
9192	*/
9193	attr = node->properties;
9194	while (attr != NULL) {
9195	    if (attr->ns == NULL) {
9196		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9197		    xmlSchemaPIllegalAttrErr(ctxt,
9198			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9199		}
9200	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9201		    xmlSchemaPIllegalAttrErr(ctxt,
9202			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9203	    }
9204	    attr = attr->next;
9205	}
9206    } else {
9207	/*
9208	* Parse as global simple type definition.
9209	*
9210	* Note that attrValue is the value of the attribute "name" here.
9211	*/
9212	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9213	    attrValue, ctxt->targetNamespace, node, 1);
9214	if (type == NULL)
9215	    return (NULL);
9216	type->type = XML_SCHEMA_TYPE_SIMPLE;
9217	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9218	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9219	/*
9220	* Check for illegal attributes.
9221	*/
9222	attr = node->properties;
9223	while (attr != NULL) {
9224	    if (attr->ns == NULL) {
9225		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9226		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9227		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9228		    xmlSchemaPIllegalAttrErr(ctxt,
9229			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9230		}
9231	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9232		xmlSchemaPIllegalAttrErr(ctxt,
9233		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9234	    }
9235	    attr = attr->next;
9236	}
9237	/*
9238	* Attribute "final".
9239	*/
9240	attr = xmlSchemaGetPropNode(node, "final");
9241	if (attr == NULL) {
9242	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9243		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9244	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9245		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9246	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9247		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9248	} else {
9249	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9250	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9251		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9252		XML_SCHEMAS_TYPE_FINAL_LIST,
9253		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9254
9255		xmlSchemaPSimpleTypeErr(ctxt,
9256		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9257		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9258		    NULL, "(#all | List of (list | union | restriction)",
9259		    attrValue, NULL, NULL, NULL);
9260	    }
9261	}
9262    }
9263    type->targetNamespace = ctxt->targetNamespace;
9264    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9265    /*
9266    * And now for the children...
9267    */
9268    oldCtxtType = ctxt->ctxtType;
9269
9270    ctxt->ctxtType = type;
9271
9272    child = node->children;
9273    if (IS_SCHEMA(child, "annotation")) {
9274        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9275        child = child->next;
9276    }
9277    if (child == NULL) {
9278	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9279	    NULL, node, child, NULL,
9280	    "(annotation?, (restriction | list | union))");
9281    } else if (IS_SCHEMA(child, "restriction")) {
9282        xmlSchemaParseRestriction(ctxt, schema, child,
9283	    XML_SCHEMA_TYPE_SIMPLE);
9284	hasRestriction = 1;
9285        child = child->next;
9286    } else if (IS_SCHEMA(child, "list")) {
9287        xmlSchemaParseList(ctxt, schema, child);
9288        child = child->next;
9289    } else if (IS_SCHEMA(child, "union")) {
9290        xmlSchemaParseUnion(ctxt, schema, child);
9291        child = child->next;
9292    }
9293    if (child != NULL) {
9294	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9295	    NULL, node, child, NULL,
9296	    "(annotation?, (restriction | list | union))");
9297    }
9298    /*
9299    * REDEFINE: SPEC src-redefine (5)
9300    * "Within the [children], each <simpleType> must have a
9301    * <restriction> among its [children] ... the �actual value� of whose
9302    * base [attribute] must be the same as the �actual value� of its own
9303    * name attribute plus target namespace;"
9304    */
9305    if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9306	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9307	    NULL, node, "This is a redefinition, thus the "
9308	    "<simpleType> must have a <restriction> child", NULL);
9309    }
9310
9311    ctxt->ctxtType = oldCtxtType;
9312    return (type);
9313}
9314
9315/**
9316 * xmlSchemaParseModelGroupDefRef:
9317 * @ctxt:  the parser context
9318 * @schema: the schema being built
9319 * @node:  the node
9320 *
9321 * Parses a reference to a model group definition.
9322 *
9323 * We will return a particle component with a qname-component or
9324 * NULL in case of an error.
9325 */
9326static xmlSchemaTreeItemPtr
9327xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9328			       xmlSchemaPtr schema,
9329			       xmlNodePtr node)
9330{
9331    xmlSchemaParticlePtr item;
9332    xmlNodePtr child = NULL;
9333    xmlAttrPtr attr;
9334    const xmlChar *ref = NULL, *refNs = NULL;
9335    int min, max;
9336
9337    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9338        return (NULL);
9339
9340    attr = xmlSchemaGetPropNode(node, "ref");
9341    if (attr == NULL) {
9342	xmlSchemaPMissingAttrErr(ctxt,
9343	    XML_SCHEMAP_S4S_ATTR_MISSING,
9344	    NULL, node, "ref", NULL);
9345	return (NULL);
9346    } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9347	attr, &refNs, &ref) != 0) {
9348	return (NULL);
9349    }
9350    xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9351    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9352    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9353	"(xs:nonNegativeInteger | unbounded)");
9354    /*
9355    * Check for illegal attributes.
9356    */
9357    attr = node->properties;
9358    while (attr != NULL) {
9359	if (attr->ns == NULL) {
9360	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9361		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9362		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9363		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9364		xmlSchemaPIllegalAttrErr(ctxt,
9365		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9366	    }
9367	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9368	    xmlSchemaPIllegalAttrErr(ctxt,
9369		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9370	}
9371	attr = attr->next;
9372    }
9373    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9374    item = xmlSchemaAddParticle(ctxt, node, min, max);
9375    if (item == NULL)
9376	return (NULL);
9377    /*
9378    * Create a qname-reference and set as the term; it will be substituted
9379    * for the model group after the reference has been resolved.
9380    */
9381    item->children = (xmlSchemaTreeItemPtr)
9382	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9383    xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9384    /*
9385    * And now for the children...
9386    */
9387    child = node->children;
9388    /* TODO: Is annotation even allowed for a model group reference? */
9389    if (IS_SCHEMA(child, "annotation")) {
9390	/*
9391	* TODO: What to do exactly with the annotation?
9392	*/
9393	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9394	child = child->next;
9395    }
9396    if (child != NULL) {
9397	xmlSchemaPContentErr(ctxt,
9398	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9399	    NULL, node, child, NULL,
9400	    "(annotation?)");
9401    }
9402    /*
9403    * Corresponds to no component at all if minOccurs==maxOccurs==0.
9404    */
9405    if ((min == 0) && (max == 0))
9406	return (NULL);
9407
9408    return ((xmlSchemaTreeItemPtr) item);
9409}
9410
9411/**
9412 * xmlSchemaParseModelGroupDefinition:
9413 * @ctxt:  a schema validation context
9414 * @schema:  the schema being built
9415 * @node:  a subtree containing XML Schema informations
9416 *
9417 * Parses a XML schema model group definition.
9418 *
9419 * Note that the contraint src-redefine (6.2) can't be applied until
9420 * references have been resolved. So we will do this at the
9421 * component fixup level.
9422 *
9423 * *WARNING* this interface is highly subject to change
9424 *
9425 * Returns -1 in case of error, 0 if the declaration is improper and
9426 *         1 in case of success.
9427 */
9428static xmlSchemaModelGroupDefPtr
9429xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9430				   xmlSchemaPtr schema,
9431				   xmlNodePtr node)
9432{
9433    xmlSchemaModelGroupDefPtr item;
9434    xmlNodePtr child = NULL;
9435    xmlAttrPtr attr;
9436    const xmlChar *name;
9437
9438    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9439        return (NULL);
9440
9441    attr = xmlSchemaGetPropNode(node, "name");
9442    if (attr == NULL) {
9443	xmlSchemaPMissingAttrErr(ctxt,
9444	    XML_SCHEMAP_S4S_ATTR_MISSING,
9445	    NULL, node,
9446	    "name", NULL);
9447	return (NULL);
9448    } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9449	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9450	return (NULL);
9451    }
9452    item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9453	ctxt->targetNamespace, node);
9454    if (item == NULL)
9455	return (NULL);
9456    /*
9457    * Check for illegal attributes.
9458    */
9459    attr = node->properties;
9460    while (attr != NULL) {
9461	if (attr->ns == NULL) {
9462	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9463		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9464		xmlSchemaPIllegalAttrErr(ctxt,
9465		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9466	    }
9467	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9468	    xmlSchemaPIllegalAttrErr(ctxt,
9469		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9470	}
9471	attr = attr->next;
9472    }
9473    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9474    /*
9475    * And now for the children...
9476    */
9477    child = node->children;
9478    if (IS_SCHEMA(child, "annotation")) {
9479	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9480	child = child->next;
9481    }
9482    if (IS_SCHEMA(child, "all")) {
9483	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9484	    XML_SCHEMA_TYPE_ALL, 0);
9485	child = child->next;
9486    } else if (IS_SCHEMA(child, "choice")) {
9487	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9488	    XML_SCHEMA_TYPE_CHOICE, 0);
9489	child = child->next;
9490    } else if (IS_SCHEMA(child, "sequence")) {
9491	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9492	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9493	child = child->next;
9494    }
9495
9496
9497
9498    if (child != NULL) {
9499	xmlSchemaPContentErr(ctxt,
9500	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9501	    NULL, node, child, NULL,
9502	    "(annotation?, (all | choice | sequence)?)");
9503    }
9504    return (item);
9505}
9506
9507/**
9508 * xmlSchemaCleanupDoc:
9509 * @ctxt:  a schema validation context
9510 * @node:  the root of the document.
9511 *
9512 * removes unwanted nodes in a schemas document tree
9513 */
9514static void
9515xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9516{
9517    xmlNodePtr delete, cur;
9518
9519    if ((ctxt == NULL) || (root == NULL)) return;
9520
9521    /*
9522     * Remove all the blank text nodes
9523     */
9524    delete = NULL;
9525    cur = root;
9526    while (cur != NULL) {
9527        if (delete != NULL) {
9528            xmlUnlinkNode(delete);
9529            xmlFreeNode(delete);
9530            delete = NULL;
9531        }
9532        if (cur->type == XML_TEXT_NODE) {
9533            if (IS_BLANK_NODE(cur)) {
9534                if (xmlNodeGetSpacePreserve(cur) != 1) {
9535                    delete = cur;
9536                }
9537            }
9538        } else if ((cur->type != XML_ELEMENT_NODE) &&
9539                   (cur->type != XML_CDATA_SECTION_NODE)) {
9540            delete = cur;
9541            goto skip_children;
9542        }
9543
9544        /*
9545         * Skip to next node
9546         */
9547        if (cur->children != NULL) {
9548            if ((cur->children->type != XML_ENTITY_DECL) &&
9549                (cur->children->type != XML_ENTITY_REF_NODE) &&
9550                (cur->children->type != XML_ENTITY_NODE)) {
9551                cur = cur->children;
9552                continue;
9553            }
9554        }
9555      skip_children:
9556        if (cur->next != NULL) {
9557            cur = cur->next;
9558            continue;
9559        }
9560
9561        do {
9562            cur = cur->parent;
9563            if (cur == NULL)
9564                break;
9565            if (cur == root) {
9566                cur = NULL;
9567                break;
9568            }
9569            if (cur->next != NULL) {
9570                cur = cur->next;
9571                break;
9572            }
9573        } while (cur != NULL);
9574    }
9575    if (delete != NULL) {
9576        xmlUnlinkNode(delete);
9577        xmlFreeNode(delete);
9578        delete = NULL;
9579    }
9580}
9581
9582
9583static void
9584xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9585{
9586    if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9587	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9588
9589    if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9590	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9591
9592    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9593	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9594    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9595	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9596    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9597	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9598    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9599	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9600
9601    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9602	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9603    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9604	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9605    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9606	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9607}
9608
9609static int
9610xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9611			     xmlSchemaPtr schema,
9612			     xmlNodePtr node)
9613{
9614    xmlAttrPtr attr;
9615    const xmlChar *val;
9616    int res = 0, oldErrs = ctxt->nberrors;
9617
9618    /*
9619    * Those flags should be moved to the parser context flags,
9620    * since they are not visible at the component level. I.e.
9621    * they are used if processing schema *documents* only.
9622    */
9623    res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9624    HFAILURE;
9625
9626    /*
9627    * Since the version is of type xs:token, we won't bother to
9628    * check it.
9629    */
9630    /* REMOVED:
9631    attr = xmlSchemaGetPropNode(node, "version");
9632    if (attr != NULL) {
9633	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9634	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9635	HFAILURE;
9636    }
9637    */
9638    attr = xmlSchemaGetPropNode(node, "targetNamespace");
9639    if (attr != NULL) {
9640	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9641	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9642	HFAILURE;
9643	if (res != 0) {
9644	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9645	    goto exit;
9646	}
9647    }
9648    attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9649    if (attr != NULL) {
9650	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9651	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9652	    XML_SCHEMAS_QUALIF_ELEM);
9653	HFAILURE;
9654	if (res != 0) {
9655	    xmlSchemaPSimpleTypeErr(ctxt,
9656		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9657		NULL, (xmlNodePtr) attr, NULL,
9658		"(qualified | unqualified)", val, NULL, NULL, NULL);
9659	}
9660    }
9661    attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9662    if (attr != NULL) {
9663	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9664	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9665	    XML_SCHEMAS_QUALIF_ATTR);
9666	HFAILURE;
9667	if (res != 0) {
9668	    xmlSchemaPSimpleTypeErr(ctxt,
9669		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9670		NULL, (xmlNodePtr) attr, NULL,
9671		"(qualified | unqualified)", val, NULL, NULL, NULL);
9672	}
9673    }
9674    attr = xmlSchemaGetPropNode(node, "finalDefault");
9675    if (attr != NULL) {
9676	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9677	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9678	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9679	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9680	    -1,
9681	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9682	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9683	HFAILURE;
9684	if (res != 0) {
9685	    xmlSchemaPSimpleTypeErr(ctxt,
9686		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9687		NULL, (xmlNodePtr) attr, NULL,
9688		"(#all | List of (extension | restriction | list | union))",
9689		val, NULL, NULL, NULL);
9690	}
9691    }
9692    attr = xmlSchemaGetPropNode(node, "blockDefault");
9693    if (attr != NULL) {
9694	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9695	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9696	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9697	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9698	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9699	HFAILURE;
9700	if (res != 0) {
9701	    xmlSchemaPSimpleTypeErr(ctxt,
9702		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9703		NULL, (xmlNodePtr) attr, NULL,
9704		"(#all | List of (extension | restriction | substitution))",
9705		val, NULL, NULL, NULL);
9706	}
9707    }
9708
9709exit:
9710    if (oldErrs != ctxt->nberrors)
9711	res = ctxt->err;
9712    return(res);
9713exit_failure:
9714    return(-1);
9715}
9716
9717/**
9718 * xmlSchemaParseSchemaTopLevel:
9719 * @ctxt:  a schema validation context
9720 * @schema:  the schemas
9721 * @nodes:  the list of top level nodes
9722 *
9723 * Returns the internal XML Schema structure built from the resource or
9724 *         NULL in case of error
9725 */
9726static int
9727xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9728                             xmlSchemaPtr schema, xmlNodePtr nodes)
9729{
9730    xmlNodePtr child;
9731    xmlSchemaAnnotPtr annot;
9732    int res = 0, oldErrs, tmpOldErrs;
9733
9734    if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9735        return(-1);
9736
9737    oldErrs = ctxt->nberrors;
9738    child = nodes;
9739    while ((IS_SCHEMA(child, "include")) ||
9740	   (IS_SCHEMA(child, "import")) ||
9741	   (IS_SCHEMA(child, "redefine")) ||
9742	   (IS_SCHEMA(child, "annotation"))) {
9743	if (IS_SCHEMA(child, "annotation")) {
9744	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9745	    if (schema->annot == NULL)
9746		schema->annot = annot;
9747	    else
9748		xmlSchemaFreeAnnot(annot);
9749	} else if (IS_SCHEMA(child, "import")) {
9750	    tmpOldErrs = ctxt->nberrors;
9751	    res = xmlSchemaParseImport(ctxt, schema, child);
9752	    HFAILURE;
9753	    HSTOP(ctxt);
9754	    if (tmpOldErrs != ctxt->nberrors)
9755		goto exit;
9756	} else if (IS_SCHEMA(child, "include")) {
9757	    tmpOldErrs = ctxt->nberrors;
9758	    res = xmlSchemaParseInclude(ctxt, schema, child);
9759	    HFAILURE;
9760	    HSTOP(ctxt);
9761	    if (tmpOldErrs != ctxt->nberrors)
9762		goto exit;
9763	} else if (IS_SCHEMA(child, "redefine")) {
9764	    tmpOldErrs = ctxt->nberrors;
9765	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9766	    HFAILURE;
9767	    HSTOP(ctxt);
9768	    if (tmpOldErrs != ctxt->nberrors)
9769		goto exit;
9770	}
9771	child = child->next;
9772    }
9773    /*
9774    * URGENT TODO: Change the functions to return int results.
9775    * We need especially to catch internal errors.
9776    */
9777    while (child != NULL) {
9778	if (IS_SCHEMA(child, "complexType")) {
9779	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9780	    child = child->next;
9781	} else if (IS_SCHEMA(child, "simpleType")) {
9782	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9783	    child = child->next;
9784	} else if (IS_SCHEMA(child, "element")) {
9785	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9786	    child = child->next;
9787	} else if (IS_SCHEMA(child, "attribute")) {
9788	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9789	    child = child->next;
9790	} else if (IS_SCHEMA(child, "attributeGroup")) {
9791	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9792	    child = child->next;
9793	} else if (IS_SCHEMA(child, "group")) {
9794	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9795	    child = child->next;
9796	} else if (IS_SCHEMA(child, "notation")) {
9797	    xmlSchemaParseNotation(ctxt, schema, child);
9798	    child = child->next;
9799	} else {
9800	    xmlSchemaPContentErr(ctxt,
9801		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9802		NULL, child->parent, child,
9803		NULL, "((include | import | redefine | annotation)*, "
9804		"(((simpleType | complexType | group | attributeGroup) "
9805		"| element | attribute | notation), annotation*)*)");
9806	    child = child->next;
9807	}
9808	while (IS_SCHEMA(child, "annotation")) {
9809	    /*
9810	    * TODO: We should add all annotations.
9811	    */
9812	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9813	    if (schema->annot == NULL)
9814		schema->annot = annot;
9815	    else
9816		xmlSchemaFreeAnnot(annot);
9817	    child = child->next;
9818	}
9819    }
9820exit:
9821    ctxt->ctxtType = NULL;
9822    if (oldErrs != ctxt->nberrors)
9823	res = ctxt->err;
9824    return(res);
9825exit_failure:
9826    return(-1);
9827}
9828
9829static xmlSchemaSchemaRelationPtr
9830xmlSchemaSchemaRelationCreate(void)
9831{
9832    xmlSchemaSchemaRelationPtr ret;
9833
9834    ret = (xmlSchemaSchemaRelationPtr)
9835	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9836    if (ret == NULL) {
9837	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9838	return(NULL);
9839    }
9840    memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9841    return(ret);
9842}
9843
9844#if 0
9845static void
9846xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9847{
9848    xmlFree(rel);
9849}
9850#endif
9851
9852static void
9853xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9854{
9855    xmlSchemaRedefPtr prev;
9856
9857    while (redef != NULL) {
9858	prev = redef;
9859	redef = redef->next;
9860	xmlFree(prev);
9861    }
9862}
9863
9864static void
9865xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9866{
9867    /*
9868    * After the construction context has been freed, there will be
9869    * no schema graph available any more. Only the schema buckets
9870    * will stay alive, which are put into the "schemasImports" and
9871    * "includes" slots of the xmlSchema.
9872    */
9873    if (con->buckets != NULL)
9874	xmlSchemaItemListFree(con->buckets);
9875    if (con->pending != NULL)
9876	xmlSchemaItemListFree(con->pending);
9877    if (con->substGroups != NULL)
9878	xmlHashFree(con->substGroups,
9879	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9880    if (con->redefs != NULL)
9881	xmlSchemaRedefListFree(con->redefs);
9882    if (con->dict != NULL)
9883	xmlDictFree(con->dict);
9884    xmlFree(con);
9885}
9886
9887static xmlSchemaConstructionCtxtPtr
9888xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9889{
9890    xmlSchemaConstructionCtxtPtr ret;
9891
9892    ret = (xmlSchemaConstructionCtxtPtr)
9893	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9894    if (ret == NULL) {
9895        xmlSchemaPErrMemory(NULL,
9896	    "allocating schema construction context", NULL);
9897        return (NULL);
9898    }
9899    memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9900
9901    ret->buckets = xmlSchemaItemListCreate();
9902    if (ret->buckets == NULL) {
9903	xmlSchemaPErrMemory(NULL,
9904	    "allocating list of schema buckets", NULL);
9905	xmlFree(ret);
9906        return (NULL);
9907    }
9908    ret->pending = xmlSchemaItemListCreate();
9909    if (ret->pending == NULL) {
9910	xmlSchemaPErrMemory(NULL,
9911	    "allocating list of pending global components", NULL);
9912	xmlSchemaConstructionCtxtFree(ret);
9913        return (NULL);
9914    }
9915    ret->dict = dict;
9916    xmlDictReference(dict);
9917    return(ret);
9918}
9919
9920static xmlSchemaParserCtxtPtr
9921xmlSchemaParserCtxtCreate(void)
9922{
9923    xmlSchemaParserCtxtPtr ret;
9924
9925    ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9926    if (ret == NULL) {
9927        xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9928                            NULL);
9929        return (NULL);
9930    }
9931    memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9932    ret->type = XML_SCHEMA_CTXT_PARSER;
9933    ret->attrProhibs = xmlSchemaItemListCreate();
9934    if (ret->attrProhibs == NULL) {
9935	xmlFree(ret);
9936	return(NULL);
9937    }
9938    return(ret);
9939}
9940
9941/**
9942 * xmlSchemaNewParserCtxtUseDict:
9943 * @URL:  the location of the schema
9944 * @dict: the dictionary to be used
9945 *
9946 * Create an XML Schemas parse context for that file/resource expected
9947 * to contain an XML Schemas file.
9948 *
9949 * Returns the parser context or NULL in case of error
9950 */
9951static xmlSchemaParserCtxtPtr
9952xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9953{
9954    xmlSchemaParserCtxtPtr ret;
9955
9956    ret = xmlSchemaParserCtxtCreate();
9957    if (ret == NULL)
9958        return (NULL);
9959    ret->dict = dict;
9960    xmlDictReference(dict);
9961    if (URL != NULL)
9962	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9963    return (ret);
9964}
9965
9966static int
9967xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9968{
9969    if (vctxt->pctxt == NULL) {
9970        if (vctxt->schema != NULL)
9971	    vctxt->pctxt =
9972		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9973	else
9974	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9975	if (vctxt->pctxt == NULL) {
9976	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9977		"failed to create a temp. parser context");
9978	    return (-1);
9979	}
9980	/* TODO: Pass user data. */
9981	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9982	    vctxt->warning, vctxt->errCtxt);
9983	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9984	    vctxt->errCtxt);
9985    }
9986    return (0);
9987}
9988
9989/**
9990 * xmlSchemaGetSchemaBucket:
9991 * @pctxt: the schema parser context
9992 * @schemaLocation: the URI of the schema document
9993 *
9994 * Returns a schema bucket if it was already parsed.
9995 *
9996 * Returns a schema bucket if it was already parsed from
9997 *         @schemaLocation, NULL otherwise.
9998 */
9999static xmlSchemaBucketPtr
10000xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10001			    const xmlChar *schemaLocation)
10002{
10003    xmlSchemaBucketPtr cur;
10004    xmlSchemaItemListPtr list;
10005
10006    list = pctxt->constructor->buckets;
10007    if (list->nbItems == 0)
10008	return(NULL);
10009    else {
10010	int i;
10011	for (i = 0; i < list->nbItems; i++) {
10012	    cur = (xmlSchemaBucketPtr) list->items[i];
10013	    /* Pointer comparison! */
10014	    if (cur->schemaLocation == schemaLocation)
10015		return(cur);
10016	}
10017    }
10018    return(NULL);
10019}
10020
10021static xmlSchemaBucketPtr
10022xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10023				     const xmlChar *schemaLocation,
10024				     const xmlChar *targetNamespace)
10025{
10026    xmlSchemaBucketPtr cur;
10027    xmlSchemaItemListPtr list;
10028
10029    list = pctxt->constructor->buckets;
10030    if (list->nbItems == 0)
10031	return(NULL);
10032    else {
10033	int i;
10034	for (i = 0; i < list->nbItems; i++) {
10035	    cur = (xmlSchemaBucketPtr) list->items[i];
10036	    /* Pointer comparison! */
10037	    if ((cur->origTargetNamespace == NULL) &&
10038		(cur->schemaLocation == schemaLocation) &&
10039		(cur->targetNamespace == targetNamespace))
10040		return(cur);
10041	}
10042    }
10043    return(NULL);
10044}
10045
10046
10047#define IS_BAD_SCHEMA_DOC(b) \
10048    (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10049
10050static xmlSchemaBucketPtr
10051xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10052				 const xmlChar *targetNamespace,
10053				 int imported)
10054{
10055    xmlSchemaBucketPtr cur;
10056    xmlSchemaItemListPtr list;
10057
10058    list = pctxt->constructor->buckets;
10059    if (list->nbItems == 0)
10060	return(NULL);
10061    else {
10062	int i;
10063	for (i = 0; i < list->nbItems; i++) {
10064	    cur = (xmlSchemaBucketPtr) list->items[i];
10065	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10066		(cur->origTargetNamespace == targetNamespace) &&
10067		((imported && cur->imported) ||
10068		 ((!imported) && (!cur->imported))))
10069		return(cur);
10070	}
10071    }
10072    return(NULL);
10073}
10074
10075static int
10076xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10077		     xmlSchemaPtr schema,
10078		     xmlSchemaBucketPtr bucket)
10079{
10080    int oldFlags;
10081    xmlDocPtr oldDoc;
10082    xmlNodePtr node;
10083    int ret, oldErrs;
10084    xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10085
10086    /*
10087    * Save old values; reset the *main* schema.
10088    * URGENT TODO: This is not good; move the per-document information
10089    * to the parser. Get rid of passing the main schema to the
10090    * parsing functions.
10091    */
10092    oldFlags = schema->flags;
10093    oldDoc = schema->doc;
10094    if (schema->flags != 0)
10095	xmlSchemaClearSchemaDefaults(schema);
10096    schema->doc = bucket->doc;
10097    pctxt->schema = schema;
10098    /*
10099    * Keep the current target namespace on the parser *not* on the
10100    * main schema.
10101    */
10102    pctxt->targetNamespace = bucket->targetNamespace;
10103    WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10104
10105    if ((bucket->targetNamespace != NULL) &&
10106	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10107	/*
10108	* We are parsing the schema for schemas!
10109	*/
10110	pctxt->isS4S = 1;
10111    }
10112    /* Mark it as parsed, even if parsing fails. */
10113    bucket->parsed++;
10114    /* Compile the schema doc. */
10115    node = xmlDocGetRootElement(bucket->doc);
10116    ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10117    if (ret != 0)
10118	goto exit;
10119    /* An empty schema; just get out. */
10120    if (node->children == NULL)
10121	goto exit;
10122    oldErrs = pctxt->nberrors;
10123    ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10124    if (ret != 0)
10125	goto exit;
10126    /*
10127    * TODO: Not nice, but I'm not 100% sure we will get always an error
10128    * as a result of the obove functions; so better rely on pctxt->err
10129    * as well.
10130    */
10131    if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10132	ret = pctxt->err;
10133	goto exit;
10134    }
10135
10136exit:
10137    WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10138    /* Restore schema values. */
10139    schema->doc = oldDoc;
10140    schema->flags = oldFlags;
10141    return(ret);
10142}
10143
10144static int
10145xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10146		     xmlSchemaPtr schema,
10147		     xmlSchemaBucketPtr bucket)
10148{
10149    xmlSchemaParserCtxtPtr newpctxt;
10150    int res = 0;
10151
10152    if (bucket == NULL)
10153	return(0);
10154    if (bucket->parsed) {
10155	PERROR_INT("xmlSchemaParseNewDoc",
10156	    "reparsing a schema doc");
10157	return(-1);
10158    }
10159    if (bucket->doc == NULL) {
10160	PERROR_INT("xmlSchemaParseNewDoc",
10161	    "parsing a schema doc, but there's no doc");
10162	return(-1);
10163    }
10164    if (pctxt->constructor == NULL) {
10165	PERROR_INT("xmlSchemaParseNewDoc",
10166	    "no constructor");
10167	return(-1);
10168    }
10169    /* Create and init the temporary parser context. */
10170    newpctxt = xmlSchemaNewParserCtxtUseDict(
10171	(const char *) bucket->schemaLocation, pctxt->dict);
10172    if (newpctxt == NULL)
10173	return(-1);
10174    newpctxt->constructor = pctxt->constructor;
10175    /*
10176    * TODO: Can we avoid that the parser knows about the main schema?
10177    * It would be better if he knows about the current schema bucket
10178    * only.
10179    */
10180    newpctxt->schema = schema;
10181    xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10182	pctxt->errCtxt);
10183    xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10184	pctxt->errCtxt);
10185    newpctxt->counter = pctxt->counter;
10186
10187
10188    res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10189
10190    /* Channel back errors and cleanup the temporary parser context. */
10191    if (res != 0)
10192	pctxt->err = res;
10193    pctxt->nberrors += newpctxt->nberrors;
10194    pctxt->counter = newpctxt->counter;
10195    newpctxt->constructor = NULL;
10196    /* Free the parser context. */
10197    xmlSchemaFreeParserCtxt(newpctxt);
10198    return(res);
10199}
10200
10201static void
10202xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10203				xmlSchemaSchemaRelationPtr rel)
10204{
10205    xmlSchemaSchemaRelationPtr cur = bucket->relations;
10206
10207    if (cur == NULL) {
10208	bucket->relations = rel;
10209	return;
10210    }
10211    while (cur->next != NULL)
10212	cur = cur->next;
10213    cur->next = rel;
10214}
10215
10216
10217static const xmlChar *
10218xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10219			  xmlNodePtr ctxtNode)
10220{
10221    /*
10222    * Build an absolue location URI.
10223    */
10224    if (location != NULL) {
10225	if (ctxtNode == NULL)
10226	    return(location);
10227	else {
10228	    xmlChar *base, *URI;
10229	    const xmlChar *ret = NULL;
10230
10231	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10232	    if (base == NULL) {
10233		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10234	    } else {
10235		URI = xmlBuildURI(location, base);
10236		xmlFree(base);
10237	    }
10238	    if (URI != NULL) {
10239		ret = xmlDictLookup(dict, URI, -1);
10240		xmlFree(URI);
10241		return(ret);
10242	    }
10243	}
10244    }
10245    return(NULL);
10246}
10247
10248
10249
10250/**
10251 * xmlSchemaAddSchemaDoc:
10252 * @pctxt:  a schema validation context
10253 * @schema:  the schema being built
10254 * @node:  a subtree containing XML Schema informations
10255 *
10256 * Parse an included (and to-be-redefined) XML schema document.
10257 *
10258 * Returns 0 on success, a positive error code on errors and
10259 *         -1 in case of an internal or API error.
10260 */
10261
10262static int
10263xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10264		int type, /* import or include or redefine */
10265		const xmlChar *schemaLocation,
10266		xmlDocPtr schemaDoc,
10267		const char *schemaBuffer,
10268		int schemaBufferLen,
10269		xmlNodePtr invokingNode,
10270		const xmlChar *sourceTargetNamespace,
10271		const xmlChar *importNamespace,
10272		xmlSchemaBucketPtr *bucket)
10273{
10274    const xmlChar *targetNamespace = NULL;
10275    xmlSchemaSchemaRelationPtr relation = NULL;
10276    xmlDocPtr doc = NULL;
10277    int res = 0, err = 0, located = 0, preserveDoc = 0;
10278    xmlSchemaBucketPtr bkt = NULL;
10279
10280    if (bucket != NULL)
10281	*bucket = NULL;
10282
10283    switch (type) {
10284	case XML_SCHEMA_SCHEMA_IMPORT:
10285	case XML_SCHEMA_SCHEMA_MAIN:
10286	    err = XML_SCHEMAP_SRC_IMPORT;
10287	    break;
10288	case XML_SCHEMA_SCHEMA_INCLUDE:
10289	    err = XML_SCHEMAP_SRC_INCLUDE;
10290	    break;
10291	case XML_SCHEMA_SCHEMA_REDEFINE:
10292	    err = XML_SCHEMAP_SRC_REDEFINE;
10293	    break;
10294    }
10295
10296
10297    /* Special handling for the main schema:
10298    * skip the location and relation logic and just parse the doc.
10299    * We need just a bucket to be returned in this case.
10300    */
10301    if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10302	goto doc_load;
10303
10304    /* Note that we expect the location to be an absulute URI. */
10305    if (schemaLocation != NULL) {
10306	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10307	if ((bkt != NULL) &&
10308	    (pctxt->constructor->bucket == bkt)) {
10309	    /* Report self-imports/inclusions/redefinitions. */
10310
10311	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10312		invokingNode, NULL,
10313		"The schema must not import/include/redefine itself",
10314		NULL, NULL);
10315	    goto exit;
10316	}
10317    }
10318    /*
10319    * Create a relation for the graph of schemas.
10320    */
10321    relation = xmlSchemaSchemaRelationCreate();
10322    if (relation == NULL)
10323	return(-1);
10324    xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10325	relation);
10326    relation->type = type;
10327
10328    /*
10329    * Save the namespace import information.
10330    */
10331    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10332	relation->importNamespace = importNamespace;
10333	if (schemaLocation == NULL) {
10334	    /*
10335	    * No location; this is just an import of the namespace.
10336	    * Note that we don't assign a bucket to the relation
10337	    * in this case.
10338	    */
10339	    goto exit;
10340	}
10341	targetNamespace = importNamespace;
10342    }
10343
10344    /* Did we already fetch the doc? */
10345    if (bkt != NULL) {
10346	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10347	    /*
10348	    * We included/redefined and then try to import a schema,
10349	    * but the new location provided for import was different.
10350	    */
10351	    if (schemaLocation == NULL)
10352		schemaLocation = BAD_CAST "in_memory_buffer";
10353	    if (!xmlStrEqual(schemaLocation,
10354		bkt->schemaLocation)) {
10355		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10356		    invokingNode, NULL,
10357		    "The schema document '%s' cannot be imported, since "
10358		    "it was already included or redefined",
10359		    schemaLocation, NULL);
10360		goto exit;
10361	    }
10362	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10363	    /*
10364	    * We imported and then try to include/redefine a schema,
10365	    * but the new location provided for the include/redefine
10366	    * was different.
10367	    */
10368	    if (schemaLocation == NULL)
10369		schemaLocation = BAD_CAST "in_memory_buffer";
10370	    if (!xmlStrEqual(schemaLocation,
10371		bkt->schemaLocation)) {
10372		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10373		    invokingNode, NULL,
10374		    "The schema document '%s' cannot be included or "
10375		    "redefined, since it was already imported",
10376		    schemaLocation, NULL);
10377		goto exit;
10378	    }
10379	}
10380    }
10381
10382    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10383	/*
10384	* Given that the schemaLocation [attribute] is only a hint, it is open
10385	* to applications to ignore all but the first <import> for a given
10386	* namespace, regardless of the �actual value� of schemaLocation, but
10387	* such a strategy risks missing useful information when new
10388	* schemaLocations are offered.
10389	*
10390	* We will use the first <import> that comes with a location.
10391	* Further <import>s *with* a location, will result in an error.
10392	* TODO: Better would be to just report a warning here, but
10393	* we'll try it this way until someone complains.
10394	*
10395	* Schema Document Location Strategy:
10396	* 3 Based on the namespace name, identify an existing schema document,
10397	* either as a resource which is an XML document or a <schema> element
10398	* information item, in some local schema repository;
10399	* 5 Attempt to resolve the namespace name to locate such a resource.
10400	*
10401	* NOTE: (3) and (5) are not supported.
10402	*/
10403	if (bkt != NULL) {
10404	    relation->bucket = bkt;
10405	    goto exit;
10406	}
10407	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10408	    importNamespace, 1);
10409
10410	if (bkt != NULL) {
10411	    relation->bucket = bkt;
10412	    if (bkt->schemaLocation == NULL) {
10413		/* First given location of the schema; load the doc. */
10414		bkt->schemaLocation = schemaLocation;
10415	    } else {
10416		if (!xmlStrEqual(schemaLocation,
10417		    bkt->schemaLocation)) {
10418		    /*
10419		    * Additional location given; just skip it.
10420		    * URGENT TODO: We should report a warning here.
10421		    * res = XML_SCHEMAP_SRC_IMPORT;
10422		    */
10423		    if (schemaLocation == NULL)
10424			schemaLocation = BAD_CAST "in_memory_buffer";
10425
10426		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10427			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10428			invokingNode, NULL,
10429			"Skipping import of schema located at '%s' for the "
10430			"namespace '%s', since this namespace was already "
10431			"imported with the schema located at '%s'",
10432			schemaLocation, importNamespace, bkt->schemaLocation);
10433		}
10434		goto exit;
10435	    }
10436	}
10437	/*
10438	* No bucket + first location: load the doc and create a
10439	* bucket.
10440	*/
10441    } else {
10442	/* <include> and <redefine> */
10443	if (bkt != NULL) {
10444
10445	    if ((bkt->origTargetNamespace == NULL) &&
10446		(bkt->targetNamespace != sourceTargetNamespace)) {
10447		xmlSchemaBucketPtr chamel;
10448
10449		/*
10450		* Chameleon include/redefine: skip loading only if it was
10451		* aleady build for the targetNamespace of the including
10452		* schema.
10453		*/
10454		/*
10455		* URGENT TODO: If the schema is a chameleon-include then copy
10456		* the components into the including schema and modify the
10457		* targetNamespace of those components, do nothing otherwise.
10458		* NOTE: This is currently worked-around by compiling the
10459		* chameleon for every destinct including targetNamespace; thus
10460		* not performant at the moment.
10461		* TODO: Check when the namespace in wildcards for chameleons
10462		* needs to be converted: before we built wildcard intersections
10463		* or after.
10464		*   Answer: after!
10465		*/
10466		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10467		    schemaLocation, sourceTargetNamespace);
10468		if (chamel != NULL) {
10469		    /* A fitting chameleon was already parsed; NOP. */
10470		    relation->bucket = chamel;
10471		    goto exit;
10472		}
10473		/*
10474		* We need to parse the chameleon again for a different
10475		* targetNamespace.
10476		* CHAMELEON TODO: Optimize this by only parsing the
10477		* chameleon once, and then copying the components to
10478		* the new targetNamespace.
10479		*/
10480		bkt = NULL;
10481	    } else {
10482		relation->bucket = bkt;
10483		goto exit;
10484	    }
10485	}
10486    }
10487    if ((bkt != NULL) && (bkt->doc != NULL)) {
10488	PERROR_INT("xmlSchemaAddSchemaDoc",
10489	    "trying to load a schema doc, but a doc is already "
10490	    "assigned to the schema bucket");
10491	goto exit_failure;
10492    }
10493
10494doc_load:
10495    /*
10496    * Load the document.
10497    */
10498    if (schemaDoc != NULL) {
10499	doc = schemaDoc;
10500	/* Don' free this one, since it was provided by the caller. */
10501	preserveDoc = 1;
10502	/* TODO: Does the context or the doc hold the location? */
10503	if (schemaDoc->URL != NULL)
10504	    schemaLocation = xmlDictLookup(pctxt->dict,
10505		schemaDoc->URL, -1);
10506        else
10507	    schemaLocation = BAD_CAST "in_memory_buffer";
10508    } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10509	xmlParserCtxtPtr parserCtxt;
10510
10511	parserCtxt = xmlNewParserCtxt();
10512	if (parserCtxt == NULL) {
10513	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10514		"allocating a parser context", NULL);
10515	    goto exit_failure;
10516	}
10517	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10518	    /*
10519	    * TODO: Do we have to burden the schema parser dict with all
10520	    * the content of the schema doc?
10521	    */
10522	    xmlDictFree(parserCtxt->dict);
10523	    parserCtxt->dict = pctxt->dict;
10524	    xmlDictReference(parserCtxt->dict);
10525	}
10526	if (schemaLocation != NULL) {
10527	    /* Parse from file. */
10528	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10529		NULL, SCHEMAS_PARSE_OPTIONS);
10530	} else if (schemaBuffer != NULL) {
10531	    /* Parse from memory buffer. */
10532	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10533		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10534	    schemaLocation = BAD_CAST "in_memory_buffer";
10535	    if (doc != NULL)
10536		doc->URL = xmlStrdup(schemaLocation);
10537	}
10538	/*
10539	* For <import>:
10540	* 2.1 The referent is (a fragment of) a resource which is an
10541	* XML document (see clause 1.1), which in turn corresponds to
10542	* a <schema> element information item in a well-formed information
10543	* set, which in turn corresponds to a valid schema.
10544	* TODO: (2.1) fragments of XML documents are not supported.
10545	*
10546	* 2.2 The referent is a <schema> element information item in
10547	* a well-formed information set, which in turn corresponds
10548	* to a valid schema.
10549	* TODO: (2.2) is not supported.
10550	*/
10551	if (doc == NULL) {
10552	    xmlErrorPtr lerr;
10553	    lerr = xmlGetLastError();
10554	    /*
10555	    * Check if this a parser error, or if the document could
10556	    * just not be located.
10557	    * TODO: Try to find specific error codes to react only on
10558	    * localisation failures.
10559	    */
10560	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10561		/*
10562		* We assume a parser error here.
10563		*/
10564		located = 1;
10565		/* TODO: Error code ?? */
10566		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10567		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10568		    invokingNode, NULL,
10569		    "Failed to parse the XML resource '%s'",
10570		    schemaLocation, NULL);
10571	    }
10572	}
10573	xmlFreeParserCtxt(parserCtxt);
10574	if ((doc == NULL) && located)
10575	    goto exit_error;
10576    } else {
10577	xmlSchemaPErr(pctxt, NULL,
10578	    XML_SCHEMAP_NOTHING_TO_PARSE,
10579	    "No information for parsing was provided with the "
10580	    "given schema parser context.\n",
10581	    NULL, NULL);
10582	goto exit_failure;
10583    }
10584    /*
10585    * Preprocess the document.
10586    */
10587    if (doc != NULL) {
10588	xmlNodePtr docElem = NULL;
10589
10590	located = 1;
10591	docElem = xmlDocGetRootElement(doc);
10592	if (docElem == NULL) {
10593	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10594		invokingNode, NULL,
10595		"The document '%s' has no document element",
10596		schemaLocation, NULL);
10597	    goto exit_error;
10598	}
10599	/*
10600	* Remove all the blank text nodes.
10601	*/
10602	xmlSchemaCleanupDoc(pctxt, docElem);
10603	/*
10604	* Check the schema's top level element.
10605	*/
10606	if (!IS_SCHEMA(docElem, "schema")) {
10607	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10608		invokingNode, NULL,
10609		"The XML document '%s' is not a schema document",
10610		schemaLocation, NULL);
10611	    goto exit_error;
10612	}
10613	/*
10614	* Note that we don't apply a type check for the
10615	* targetNamespace value here.
10616	*/
10617	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10618	    "targetNamespace");
10619    }
10620
10621/* after_doc_loading: */
10622    if ((bkt == NULL) && located) {
10623	/* Only create a bucket if the schema was located. */
10624        bkt = xmlSchemaBucketCreate(pctxt, type,
10625	    targetNamespace);
10626	if (bkt == NULL)
10627	    goto exit_failure;
10628    }
10629    if (bkt != NULL) {
10630	bkt->schemaLocation = schemaLocation;
10631	bkt->located = located;
10632	if (doc != NULL) {
10633	    bkt->doc = doc;
10634	    bkt->targetNamespace = targetNamespace;
10635	    bkt->origTargetNamespace = targetNamespace;
10636	    if (preserveDoc)
10637		bkt->preserveDoc = 1;
10638	}
10639	if (WXS_IS_BUCKET_IMPMAIN(type))
10640	    bkt->imported++;
10641	    /*
10642	    * Add it to the graph of schemas.
10643	    */
10644	if (relation != NULL)
10645	    relation->bucket = bkt;
10646    }
10647
10648exit:
10649    /*
10650    * Return the bucket explicitely; this is needed for the
10651    * main schema.
10652    */
10653    if (bucket != NULL)
10654	*bucket = bkt;
10655    return (0);
10656
10657exit_error:
10658    if ((doc != NULL) && (! preserveDoc)) {
10659	xmlFreeDoc(doc);
10660	if (bkt != NULL)
10661	    bkt->doc = NULL;
10662    }
10663    return(pctxt->err);
10664
10665exit_failure:
10666    if ((doc != NULL) && (! preserveDoc)) {
10667	xmlFreeDoc(doc);
10668	if (bkt != NULL)
10669	    bkt->doc = NULL;
10670    }
10671    return (-1);
10672}
10673
10674/**
10675 * xmlSchemaParseImport:
10676 * @ctxt:  a schema validation context
10677 * @schema:  the schema being built
10678 * @node:  a subtree containing XML Schema informations
10679 *
10680 * parse a XML schema Import definition
10681 * *WARNING* this interface is highly subject to change
10682 *
10683 * Returns 0 in case of success, a positive error code if
10684 * not valid and -1 in case of an internal error.
10685 */
10686static int
10687xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10688                     xmlNodePtr node)
10689{
10690    xmlNodePtr child;
10691    const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10692    const xmlChar *thisTargetNamespace;
10693    xmlAttrPtr attr;
10694    int ret = 0;
10695    xmlSchemaBucketPtr bucket = NULL;
10696
10697    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10698        return (-1);
10699
10700    /*
10701    * Check for illegal attributes.
10702    */
10703    attr = node->properties;
10704    while (attr != NULL) {
10705	if (attr->ns == NULL) {
10706	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10707		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10708		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10709		xmlSchemaPIllegalAttrErr(pctxt,
10710		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10711	    }
10712	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10713	    xmlSchemaPIllegalAttrErr(pctxt,
10714		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10715	}
10716	attr = attr->next;
10717    }
10718    /*
10719    * Extract and validate attributes.
10720    */
10721    if (xmlSchemaPValAttr(pctxt, NULL, node,
10722	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10723	&namespaceName) != 0) {
10724	xmlSchemaPSimpleTypeErr(pctxt,
10725	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10726	    NULL, node,
10727	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10728	    NULL, namespaceName, NULL, NULL, NULL);
10729	return (pctxt->err);
10730    }
10731
10732    if (xmlSchemaPValAttr(pctxt, NULL, node,
10733	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10734	&schemaLocation) != 0) {
10735	xmlSchemaPSimpleTypeErr(pctxt,
10736	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10737	    NULL, node,
10738	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10739	    NULL, namespaceName, NULL, NULL, NULL);
10740	return (pctxt->err);
10741    }
10742    /*
10743    * And now for the children...
10744    */
10745    child = node->children;
10746    if (IS_SCHEMA(child, "annotation")) {
10747        /*
10748         * the annotation here is simply discarded ...
10749	 * TODO: really?
10750         */
10751        child = child->next;
10752    }
10753    if (child != NULL) {
10754	xmlSchemaPContentErr(pctxt,
10755	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10756	    NULL, node, child, NULL,
10757	    "(annotation?)");
10758    }
10759    /*
10760    * Apply additional constraints.
10761    *
10762    * Note that it is important to use the original @targetNamespace
10763    * (or none at all), to rule out imports of schemas _with_ a
10764    * @targetNamespace if the importing schema is a chameleon schema
10765    * (with no @targetNamespace).
10766    */
10767    thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10768    if (namespaceName != NULL) {
10769	/*
10770	* 1.1 If the namespace [attribute] is present, then its �actual value�
10771	* must not match the �actual value� of the enclosing <schema>'s
10772	* targetNamespace [attribute].
10773	*/
10774	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10775	    xmlSchemaPCustomErr(pctxt,
10776		XML_SCHEMAP_SRC_IMPORT_1_1,
10777		NULL, node,
10778		"The value of the attribute 'namespace' must not match "
10779		"the target namespace '%s' of the importing schema",
10780		thisTargetNamespace);
10781	    return (pctxt->err);
10782	}
10783    } else {
10784	/*
10785	* 1.2 If the namespace [attribute] is not present, then the enclosing
10786	* <schema> must have a targetNamespace [attribute].
10787	*/
10788	if (thisTargetNamespace == NULL) {
10789	    xmlSchemaPCustomErr(pctxt,
10790		XML_SCHEMAP_SRC_IMPORT_1_2,
10791		NULL, node,
10792		"The attribute 'namespace' must be existent if "
10793		"the importing schema has no target namespace",
10794		NULL);
10795	    return (pctxt->err);
10796	}
10797    }
10798    /*
10799    * Locate and acquire the schema document.
10800    */
10801    if (schemaLocation != NULL)
10802	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10803	    schemaLocation, node);
10804    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10805	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10806	namespaceName, &bucket);
10807
10808    if (ret != 0)
10809	return(ret);
10810
10811    /*
10812    * For <import>: "It is *not* an error for the application
10813    * schema reference strategy to fail."
10814    * So just don't parse if no schema document was found.
10815    * Note that we will get no bucket if the schema could not be
10816    * located or if there was no schemaLocation.
10817    */
10818    if ((bucket == NULL) && (schemaLocation != NULL)) {
10819	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10820	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10821	    node, NULL,
10822	    "Failed to locate a schema at location '%s'. "
10823	    "Skipping the import", schemaLocation, NULL, NULL);
10824    }
10825
10826    if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10827	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10828    }
10829
10830    return (ret);
10831}
10832
10833static int
10834xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10835				     xmlSchemaPtr schema,
10836				     xmlNodePtr node,
10837				     xmlChar **schemaLocation,
10838				     int type)
10839{
10840    xmlAttrPtr attr;
10841
10842    if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10843	(schemaLocation == NULL))
10844        return (-1);
10845
10846    *schemaLocation = NULL;
10847    /*
10848    * Check for illegal attributes.
10849    * Applies for both <include> and <redefine>.
10850    */
10851    attr = node->properties;
10852    while (attr != NULL) {
10853	if (attr->ns == NULL) {
10854	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10855		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10856		xmlSchemaPIllegalAttrErr(pctxt,
10857		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10858	    }
10859	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10860	    xmlSchemaPIllegalAttrErr(pctxt,
10861		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10862	}
10863	attr = attr->next;
10864    }
10865    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10866    /*
10867    * Preliminary step, extract the URI-Reference and make an URI
10868    * from the base.
10869    */
10870    /*
10871    * Attribute "schemaLocation" is mandatory.
10872    */
10873    attr = xmlSchemaGetPropNode(node, "schemaLocation");
10874    if (attr != NULL) {
10875        xmlChar *base = NULL;
10876        xmlChar *uri = NULL;
10877
10878	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10879	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10880	    (const xmlChar **) schemaLocation) != 0)
10881	    goto exit_error;
10882	base = xmlNodeGetBase(node->doc, node);
10883	if (base == NULL) {
10884	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10885	} else {
10886	    uri = xmlBuildURI(*schemaLocation, base);
10887	    xmlFree(base);
10888	}
10889	if (uri == NULL) {
10890	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10891		"could not build an URI from the schemaLocation")
10892	    goto exit_failure;
10893	}
10894	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10895	xmlFree(uri);
10896    } else {
10897	xmlSchemaPMissingAttrErr(pctxt,
10898	    XML_SCHEMAP_S4S_ATTR_MISSING,
10899	    NULL, node, "schemaLocation", NULL);
10900	goto exit_error;
10901    }
10902    /*
10903    * Report self-inclusion and self-redefinition.
10904    */
10905    if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10906	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10907	    xmlSchemaPCustomErr(pctxt,
10908		XML_SCHEMAP_SRC_REDEFINE,
10909		NULL, node,
10910		"The schema document '%s' cannot redefine itself.",
10911		*schemaLocation);
10912	} else {
10913	    xmlSchemaPCustomErr(pctxt,
10914		XML_SCHEMAP_SRC_INCLUDE,
10915		NULL, node,
10916		"The schema document '%s' cannot include itself.",
10917		*schemaLocation);
10918	}
10919	goto exit_error;
10920    }
10921
10922    return(0);
10923exit_error:
10924    return(pctxt->err);
10925exit_failure:
10926    return(-1);
10927}
10928
10929static int
10930xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10931				xmlSchemaPtr schema,
10932				xmlNodePtr node,
10933				int type)
10934{
10935    xmlNodePtr child = NULL;
10936    const xmlChar *schemaLocation = NULL;
10937    int res = 0; /* hasRedefinitions = 0 */
10938    int isChameleon = 0, wasChameleon = 0;
10939    xmlSchemaBucketPtr bucket = NULL;
10940
10941    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10942        return (-1);
10943
10944    /*
10945    * Parse attributes. Note that the returned schemaLocation will
10946    * be already converted to an absolute URI.
10947    */
10948    res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10949	node, (xmlChar **) (&schemaLocation), type);
10950    if (res != 0)
10951	return(res);
10952    /*
10953    * Load and add the schema document.
10954    */
10955    res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10956	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10957    if (res != 0)
10958	return(res);
10959    /*
10960    * If we get no schema bucket back, then this means that the schema
10961    * document could not be located or was broken XML or was not
10962    * a schema document.
10963    */
10964    if ((bucket == NULL) || (bucket->doc == NULL)) {
10965	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10966	    /*
10967	    * WARNING for <include>:
10968	    * We will raise an error if the schema cannot be located
10969	    * for inclusions, since the that was the feedback from the
10970	    * schema people. I.e. the following spec piece will *not* be
10971	    * satisfied:
10972	    * SPEC src-include: "It is not an error for the �actual value� of the
10973	    * schemaLocation [attribute] to fail to resolve it all, in which
10974	    * case no corresponding inclusion is performed.
10975	    * So do we need a warning report here?"
10976	    */
10977	    res = XML_SCHEMAP_SRC_INCLUDE;
10978	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10979		node, NULL,
10980		"Failed to load the document '%s' for inclusion",
10981		schemaLocation, NULL);
10982	} else {
10983	    /*
10984	    * NOTE: This was changed to raise an error even if no redefinitions
10985	    * are specified.
10986	    *
10987	    * SPEC src-redefine (1)
10988	    * "If there are any element information items among the [children]
10989	    * other than <annotation> then the �actual value� of the
10990	    * schemaLocation [attribute] must successfully resolve."
10991	    * TODO: Ask the WG if a the location has always to resolve
10992	    * here as well!
10993	    */
10994	    res = XML_SCHEMAP_SRC_REDEFINE;
10995	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10996		node, NULL,
10997		"Failed to load the document '%s' for redefinition",
10998		schemaLocation, NULL);
10999	}
11000    } else {
11001	/*
11002	* Check targetNamespace sanity before parsing the new schema.
11003	* TODO: Note that we won't check further content if the
11004	* targetNamespace was bad.
11005	*/
11006	if (bucket->origTargetNamespace != NULL) {
11007	    /*
11008	    * SPEC src-include (2.1)
11009	    * "SII has a targetNamespace [attribute], and its �actual
11010	    * value� is identical to the �actual value� of the targetNamespace
11011	    * [attribute] of SII� (which must have such an [attribute])."
11012	    */
11013	    if (pctxt->targetNamespace == NULL) {
11014		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11015		    XML_SCHEMAP_SRC_INCLUDE,
11016		    node, NULL,
11017		    "The target namespace of the included/redefined schema "
11018		    "'%s' has to be absent, since the including/redefining "
11019		    "schema has no target namespace",
11020		    schemaLocation, NULL);
11021		goto exit_error;
11022	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11023		pctxt->targetNamespace)) {
11024		/* TODO: Change error function. */
11025		xmlSchemaPCustomErrExt(pctxt,
11026		    XML_SCHEMAP_SRC_INCLUDE,
11027		    NULL, node,
11028		    "The target namespace '%s' of the included/redefined "
11029		    "schema '%s' differs from '%s' of the "
11030		    "including/redefining schema",
11031		    bucket->origTargetNamespace, schemaLocation,
11032		    pctxt->targetNamespace);
11033		goto exit_error;
11034	    }
11035	} else if (pctxt->targetNamespace != NULL) {
11036	    /*
11037	    * Chameleons: the original target namespace will
11038	    * differ from the resulting namespace.
11039	    */
11040	    isChameleon = 1;
11041	    if (bucket->parsed &&
11042		bucket->origTargetNamespace != NULL) {
11043		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11044		    XML_SCHEMAP_SRC_INCLUDE,
11045		    node, NULL,
11046		    "The target namespace of the included/redefined schema "
11047		    "'%s' has to be absent or the same as the "
11048		    "including/redefining schema's target namespace",
11049		    schemaLocation, NULL);
11050		goto exit_error;
11051	    }
11052	    bucket->targetNamespace = pctxt->targetNamespace;
11053	}
11054    }
11055    /*
11056    * Parse the schema.
11057    */
11058    if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11059	if (isChameleon) {
11060	    /* TODO: Get rid of this flag on the schema itself. */
11061	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11062		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11063	    } else
11064		wasChameleon = 1;
11065	}
11066	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11067	/* Restore chameleon flag. */
11068	if (isChameleon && (!wasChameleon))
11069	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11070    }
11071    /*
11072    * And now for the children...
11073    */
11074    child = node->children;
11075    if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11076	/*
11077	* Parse (simpleType | complexType | group | attributeGroup))*
11078	*/
11079	pctxt->redefined = bucket;
11080	/*
11081	* How to proceed if the redefined schema was not located?
11082	*/
11083	pctxt->isRedefine = 1;
11084	while (IS_SCHEMA(child, "annotation") ||
11085	    IS_SCHEMA(child, "simpleType") ||
11086	    IS_SCHEMA(child, "complexType") ||
11087	    IS_SCHEMA(child, "group") ||
11088	    IS_SCHEMA(child, "attributeGroup")) {
11089	    if (IS_SCHEMA(child, "annotation")) {
11090		/*
11091		* TODO: discard or not?
11092		*/
11093	    } else if (IS_SCHEMA(child, "simpleType")) {
11094		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11095	    } else if (IS_SCHEMA(child, "complexType")) {
11096		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11097		/* hasRedefinitions = 1; */
11098	    } else if (IS_SCHEMA(child, "group")) {
11099		/* hasRedefinitions = 1; */
11100		xmlSchemaParseModelGroupDefinition(pctxt,
11101		    schema, child);
11102	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11103		/* hasRedefinitions = 1; */
11104		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11105		    child);
11106	    }
11107	    child = child->next;
11108	}
11109	pctxt->redefined = NULL;
11110	pctxt->isRedefine = 0;
11111    } else {
11112	if (IS_SCHEMA(child, "annotation")) {
11113	    /*
11114	    * TODO: discard or not?
11115	    */
11116	    child = child->next;
11117	}
11118    }
11119    if (child != NULL) {
11120	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11121	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11122	    xmlSchemaPContentErr(pctxt, res,
11123		NULL, node, child, NULL,
11124		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11125	} else {
11126	     xmlSchemaPContentErr(pctxt, res,
11127		NULL, node, child, NULL,
11128		"(annotation?)");
11129	}
11130    }
11131    return(res);
11132
11133exit_error:
11134    return(pctxt->err);
11135}
11136
11137static int
11138xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11139                       xmlNodePtr node)
11140{
11141    int res;
11142#ifndef ENABLE_REDEFINE
11143    TODO
11144    return(0);
11145#endif
11146    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11147	XML_SCHEMA_SCHEMA_REDEFINE);
11148    if (res != 0)
11149	return(res);
11150    return(0);
11151}
11152
11153static int
11154xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11155                       xmlNodePtr node)
11156{
11157    int res;
11158
11159    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11160	XML_SCHEMA_SCHEMA_INCLUDE);
11161    if (res != 0)
11162	return(res);
11163    return(0);
11164}
11165
11166/**
11167 * xmlSchemaParseModelGroup:
11168 * @ctxt:  a schema validation context
11169 * @schema:  the schema being built
11170 * @node:  a subtree containing XML Schema informations
11171 * @type: the "compositor" type
11172 * @particleNeeded: if a a model group with a particle
11173 *
11174 * parse a XML schema Sequence definition.
11175 * Applies parts of:
11176 *   Schema Representation Constraint:
11177 *     Redefinition Constraints and Semantics (src-redefine)
11178 *     (6.1), (6.1.1), (6.1.2)
11179 *
11180 *   Schema Component Constraint:
11181 *     All Group Limited (cos-all-limited) (2)
11182 *     TODO: Actually this should go to component-level checks,
11183 *     but is done here due to performance. Move it to an other layer
11184 *     is schema construction via an API is implemented.
11185 *
11186 * *WARNING* this interface is highly subject to change
11187 *
11188 * Returns -1 in case of error, 0 if the declaration is improper and
11189 *         1 in case of success.
11190 */
11191static xmlSchemaTreeItemPtr
11192xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11193			 xmlNodePtr node, xmlSchemaTypeType type,
11194			 int withParticle)
11195{
11196    xmlSchemaModelGroupPtr item;
11197    xmlSchemaParticlePtr particle = NULL;
11198    xmlNodePtr child = NULL;
11199    xmlAttrPtr attr;
11200    int min = 1, max = 1, isElemRef, hasRefs = 0;
11201
11202    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11203        return (NULL);
11204    /*
11205    * Create a model group with the given compositor.
11206    */
11207    item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11208    if (item == NULL)
11209	return (NULL);
11210
11211    if (withParticle) {
11212	if (type == XML_SCHEMA_TYPE_ALL) {
11213	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11214	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11215	} else {
11216	    /* choice + sequence */
11217	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11218	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11219		"(xs:nonNegativeInteger | unbounded)");
11220	}
11221	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11222	/*
11223	* Create a particle
11224	*/
11225	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11226	if (particle == NULL)
11227	    return (NULL);
11228	particle->children = (xmlSchemaTreeItemPtr) item;
11229	/*
11230	* Check for illegal attributes.
11231	*/
11232	attr = node->properties;
11233	while (attr != NULL) {
11234	    if (attr->ns == NULL) {
11235		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11236		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11237		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11238		    xmlSchemaPIllegalAttrErr(ctxt,
11239			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11240		}
11241	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11242		xmlSchemaPIllegalAttrErr(ctxt,
11243		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11244	    }
11245	    attr = attr->next;
11246	}
11247    } else {
11248	/*
11249	* Check for illegal attributes.
11250	*/
11251	attr = node->properties;
11252	while (attr != NULL) {
11253	    if (attr->ns == NULL) {
11254		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11255		    xmlSchemaPIllegalAttrErr(ctxt,
11256			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11257		}
11258	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11259		xmlSchemaPIllegalAttrErr(ctxt,
11260		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11261	    }
11262	    attr = attr->next;
11263	}
11264    }
11265
11266    /*
11267    * Extract and validate attributes.
11268    */
11269    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11270    /*
11271    * And now for the children...
11272    */
11273    child = node->children;
11274    if (IS_SCHEMA(child, "annotation")) {
11275        item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11276        child = child->next;
11277    }
11278    if (type == XML_SCHEMA_TYPE_ALL) {
11279	xmlSchemaParticlePtr part, last = NULL;
11280
11281	while (IS_SCHEMA(child, "element")) {
11282	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11283		schema, child, &isElemRef, 0);
11284	    /*
11285	    * SPEC cos-all-limited (2)
11286	    * "The {max occurs} of all the particles in the {particles}
11287	    * of the ('all') group must be 0 or 1.
11288	    */
11289	    if (part != NULL) {
11290		if (isElemRef)
11291		    hasRefs++;
11292		if (part->minOccurs > 1) {
11293		    xmlSchemaPCustomErr(ctxt,
11294			XML_SCHEMAP_COS_ALL_LIMITED,
11295			NULL, child,
11296			"Invalid value for minOccurs (must be 0 or 1)",
11297			NULL);
11298		    /* Reset to 1. */
11299		    part->minOccurs = 1;
11300		}
11301		if (part->maxOccurs > 1) {
11302		    xmlSchemaPCustomErr(ctxt,
11303			XML_SCHEMAP_COS_ALL_LIMITED,
11304			NULL, child,
11305			"Invalid value for maxOccurs (must be 0 or 1)",
11306			NULL);
11307		    /* Reset to 1. */
11308		    part->maxOccurs = 1;
11309		}
11310		if (last == NULL)
11311		    item->children = (xmlSchemaTreeItemPtr) part;
11312		else
11313		    last->next = (xmlSchemaTreeItemPtr) part;
11314		last = part;
11315	    }
11316	    child = child->next;
11317	}
11318	if (child != NULL) {
11319	    xmlSchemaPContentErr(ctxt,
11320		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11321		NULL, node, child, NULL,
11322		"(annotation?, (annotation?, element*)");
11323	}
11324    } else {
11325	/* choice + sequence */
11326	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11327
11328	while ((IS_SCHEMA(child, "element")) ||
11329	    (IS_SCHEMA(child, "group")) ||
11330	    (IS_SCHEMA(child, "any")) ||
11331	    (IS_SCHEMA(child, "choice")) ||
11332	    (IS_SCHEMA(child, "sequence"))) {
11333
11334	    if (IS_SCHEMA(child, "element")) {
11335		part = (xmlSchemaTreeItemPtr)
11336		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11337		if (part && isElemRef)
11338		    hasRefs++;
11339	    } else if (IS_SCHEMA(child, "group")) {
11340		part =
11341		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11342		if (part != NULL)
11343		    hasRefs++;
11344		/*
11345		* Handle redefinitions.
11346		*/
11347		if (ctxt->isRedefine && ctxt->redef &&
11348		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11349		    part && part->children)
11350		{
11351		    if ((xmlSchemaGetQNameRefName(part->children) ==
11352			    ctxt->redef->refName) &&
11353			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11354			    ctxt->redef->refTargetNs))
11355		    {
11356			/*
11357			* SPEC src-redefine:
11358			* (6.1) "If it has a <group> among its contents at
11359			* some level the �actual value� of whose ref
11360			* [attribute] is the same as the �actual value� of
11361			* its own name attribute plus target namespace, then
11362			* all of the following must be true:"
11363			* (6.1.1) "It must have exactly one such group."
11364			*/
11365			if (ctxt->redefCounter != 0) {
11366			    xmlChar *str = NULL;
11367
11368			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11369				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11370				"The redefining model group definition "
11371				"'%s' must not contain more than one "
11372				"reference to the redefined definition",
11373				xmlSchemaFormatQName(&str,
11374				    ctxt->redef->refTargetNs,
11375				    ctxt->redef->refName),
11376				NULL);
11377			    FREE_AND_NULL(str)
11378			    part = NULL;
11379			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11380			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11381			{
11382			    xmlChar *str = NULL;
11383			    /*
11384			    * SPEC src-redefine:
11385			    * (6.1.2) "The �actual value� of both that
11386			    * group's minOccurs and maxOccurs [attribute]
11387			    * must be 1 (or �absent�).
11388			    */
11389			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391				"The redefining model group definition "
11392				"'%s' must not contain a reference to the "
11393				"redefined definition with a "
11394				"maxOccurs/minOccurs other than 1",
11395				xmlSchemaFormatQName(&str,
11396				    ctxt->redef->refTargetNs,
11397				    ctxt->redef->refName),
11398				NULL);
11399			    FREE_AND_NULL(str)
11400			    part = NULL;
11401			}
11402			ctxt->redef->reference = WXS_BASIC_CAST part;
11403			ctxt->redefCounter++;
11404		    }
11405		}
11406	    } else if (IS_SCHEMA(child, "any")) {
11407		part = (xmlSchemaTreeItemPtr)
11408		    xmlSchemaParseAny(ctxt, schema, child);
11409	    } else if (IS_SCHEMA(child, "choice")) {
11410		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11411		    XML_SCHEMA_TYPE_CHOICE, 1);
11412	    } else if (IS_SCHEMA(child, "sequence")) {
11413		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11414		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11415	    }
11416	    if (part != NULL) {
11417		if (last == NULL)
11418		    item->children = part;
11419		else
11420		    last->next = part;
11421		last = part;
11422	    }
11423	    child = child->next;
11424	}
11425	if (child != NULL) {
11426	    xmlSchemaPContentErr(ctxt,
11427		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11428		NULL, node, child, NULL,
11429		"(annotation?, (element | group | choice | sequence | any)*)");
11430	}
11431    }
11432    if ((max == 0) && (min == 0))
11433	return (NULL);
11434    if (hasRefs) {
11435	/*
11436	* We need to resolve references.
11437	*/
11438	WXS_ADD_PENDING(ctxt, item);
11439    }
11440    if (withParticle)
11441	return ((xmlSchemaTreeItemPtr) particle);
11442    else
11443	return ((xmlSchemaTreeItemPtr) item);
11444}
11445
11446/**
11447 * xmlSchemaParseRestriction:
11448 * @ctxt:  a schema validation context
11449 * @schema:  the schema being built
11450 * @node:  a subtree containing XML Schema informations
11451 *
11452 * parse a XML schema Restriction definition
11453 * *WARNING* this interface is highly subject to change
11454 *
11455 * Returns the type definition or NULL in case of error
11456 */
11457static xmlSchemaTypePtr
11458xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11459                          xmlNodePtr node, xmlSchemaTypeType parentType)
11460{
11461    xmlSchemaTypePtr type;
11462    xmlNodePtr child = NULL;
11463    xmlAttrPtr attr;
11464
11465    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11466        return (NULL);
11467    /* Not a component, don't create it. */
11468    type = ctxt->ctxtType;
11469    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11470
11471    /*
11472    * Check for illegal attributes.
11473    */
11474    attr = node->properties;
11475    while (attr != NULL) {
11476	if (attr->ns == NULL) {
11477	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11478		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11479		xmlSchemaPIllegalAttrErr(ctxt,
11480		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11481	    }
11482	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11483	    xmlSchemaPIllegalAttrErr(ctxt,
11484		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11485	}
11486	attr = attr->next;
11487    }
11488    /*
11489    * Extract and validate attributes.
11490    */
11491    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11492    /*
11493    * Attribute
11494    */
11495    /*
11496    * Extract the base type. The "base" attribute is mandatory if inside
11497    * a complex type or if redefining.
11498    *
11499    * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11500    * among its [children]), the simple type definition which is
11501    * the {content type} of the type definition �resolved� to by
11502    * the �actual value� of the base [attribute]"
11503    */
11504    if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11505	&(type->baseNs), &(type->base)) == 0)
11506    {
11507	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11508	    xmlSchemaPMissingAttrErr(ctxt,
11509		XML_SCHEMAP_S4S_ATTR_MISSING,
11510		NULL, node, "base", NULL);
11511	} else if ((ctxt->isRedefine) &&
11512	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11513	{
11514	    if (type->base == NULL) {
11515		xmlSchemaPMissingAttrErr(ctxt,
11516		    XML_SCHEMAP_S4S_ATTR_MISSING,
11517		    NULL, node, "base", NULL);
11518	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11519		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11520	    {
11521		xmlChar *str1 = NULL, *str2 = NULL;
11522		/*
11523		* REDEFINE: SPEC src-redefine (5)
11524		* "Within the [children], each <simpleType> must have a
11525		* <restriction> among its [children] ... the �actual value� of
11526		* whose base [attribute] must be the same as the �actual value�
11527		* of its own name attribute plus target namespace;"
11528		*/
11529		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11530		    NULL, node, "This is a redefinition, but the QName "
11531		    "value '%s' of the 'base' attribute does not match the "
11532		    "type's designation '%s'",
11533		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11534		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11535			type->name), NULL);
11536		FREE_AND_NULL(str1);
11537		FREE_AND_NULL(str2);
11538		/* Avoid confusion and erase the values. */
11539		type->base = NULL;
11540		type->baseNs = NULL;
11541	    }
11542	}
11543    }
11544    /*
11545    * And now for the children...
11546    */
11547    child = node->children;
11548    if (IS_SCHEMA(child, "annotation")) {
11549	/*
11550	* Add the annotation to the simple type ancestor.
11551	*/
11552	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11553	    xmlSchemaParseAnnotation(ctxt, child, 1));
11554        child = child->next;
11555    }
11556    if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11557	/*
11558	* Corresponds to <simpleType><restriction><simpleType>.
11559	*/
11560	if (IS_SCHEMA(child, "simpleType")) {
11561	    if (type->base != NULL) {
11562		/*
11563		* src-restriction-base-or-simpleType
11564		* Either the base [attribute] or the simpleType [child] of the
11565		* <restriction> element must be present, but not both.
11566		*/
11567		xmlSchemaPContentErr(ctxt,
11568		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11569		    NULL, node, child,
11570		    "The attribute 'base' and the <simpleType> child are "
11571		    "mutually exclusive", NULL);
11572	    } else {
11573		type->baseType = (xmlSchemaTypePtr)
11574		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11575	    }
11576	    child = child->next;
11577	} else if (type->base == NULL) {
11578	    xmlSchemaPContentErr(ctxt,
11579		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11580		NULL, node, child,
11581		"Either the attribute 'base' or a <simpleType> child "
11582		"must be present", NULL);
11583	}
11584    } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11585	/*
11586	* Corresponds to <complexType><complexContent><restriction>...
11587	* followed by:
11588	*
11589	* Model groups <all>, <choice> and <sequence>.
11590	*/
11591	if (IS_SCHEMA(child, "all")) {
11592	    type->subtypes = (xmlSchemaTypePtr)
11593		xmlSchemaParseModelGroup(ctxt, schema, child,
11594		    XML_SCHEMA_TYPE_ALL, 1);
11595	    child = child->next;
11596	} else if (IS_SCHEMA(child, "choice")) {
11597	    type->subtypes = (xmlSchemaTypePtr)
11598		xmlSchemaParseModelGroup(ctxt,
11599		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11600	    child = child->next;
11601	} else if (IS_SCHEMA(child, "sequence")) {
11602	    type->subtypes = (xmlSchemaTypePtr)
11603		xmlSchemaParseModelGroup(ctxt, schema, child,
11604		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11605	    child = child->next;
11606	/*
11607	* Model group reference <group>.
11608	*/
11609	} else if (IS_SCHEMA(child, "group")) {
11610	    type->subtypes = (xmlSchemaTypePtr)
11611		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11612	    /*
11613	    * Note that the reference will be resolved in
11614	    * xmlSchemaResolveTypeReferences();
11615	    */
11616	    child = child->next;
11617	}
11618    } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11619	/*
11620	* Corresponds to <complexType><simpleContent><restriction>...
11621	*
11622	* "1.1 the simple type definition corresponding to the <simpleType>
11623	* among the [children] of <restriction> if there is one;"
11624	*/
11625	if (IS_SCHEMA(child, "simpleType")) {
11626	    /*
11627	    * We will store the to-be-restricted simple type in
11628	    * type->contentTypeDef *temporarily*.
11629	    */
11630	    type->contentTypeDef = (xmlSchemaTypePtr)
11631		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11632	    if ( type->contentTypeDef == NULL)
11633		return (NULL);
11634	    child = child->next;
11635	}
11636    }
11637
11638    if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11639	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11640	xmlSchemaFacetPtr facet, lastfacet = NULL;
11641	/*
11642	* Corresponds to <complexType><simpleContent><restriction>...
11643	* <simpleType><restriction>...
11644	*/
11645
11646	/*
11647	* Add the facets to the simple type ancestor.
11648	*/
11649	/*
11650	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11651	* Simple Type Definition Schema Representation Constraint:
11652	* *Single Facet Value*
11653	*/
11654	while ((IS_SCHEMA(child, "minInclusive")) ||
11655	    (IS_SCHEMA(child, "minExclusive")) ||
11656	    (IS_SCHEMA(child, "maxInclusive")) ||
11657	    (IS_SCHEMA(child, "maxExclusive")) ||
11658	    (IS_SCHEMA(child, "totalDigits")) ||
11659	    (IS_SCHEMA(child, "fractionDigits")) ||
11660	    (IS_SCHEMA(child, "pattern")) ||
11661	    (IS_SCHEMA(child, "enumeration")) ||
11662	    (IS_SCHEMA(child, "whiteSpace")) ||
11663	    (IS_SCHEMA(child, "length")) ||
11664	    (IS_SCHEMA(child, "maxLength")) ||
11665	    (IS_SCHEMA(child, "minLength"))) {
11666	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11667	    if (facet != NULL) {
11668		if (lastfacet == NULL)
11669		    type->facets = facet;
11670		else
11671		    lastfacet->next = facet;
11672		lastfacet = facet;
11673		lastfacet->next = NULL;
11674	    }
11675	    child = child->next;
11676	}
11677	/*
11678	* Create links for derivation and validation.
11679	*/
11680	if (type->facets != NULL) {
11681	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11682
11683	    facet = type->facets;
11684	    do {
11685		facetLink = (xmlSchemaFacetLinkPtr)
11686		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11687		if (facetLink == NULL) {
11688		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11689		    xmlFree(facetLink);
11690		    return (NULL);
11691		}
11692		facetLink->facet = facet;
11693		facetLink->next = NULL;
11694		if (lastFacetLink == NULL)
11695		    type->facetSet = facetLink;
11696		else
11697		    lastFacetLink->next = facetLink;
11698		lastFacetLink = facetLink;
11699		facet = facet->next;
11700	    } while (facet != NULL);
11701	}
11702    }
11703    if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11704	/*
11705	* Attribute uses/declarations.
11706	*/
11707	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11708	    (xmlSchemaItemListPtr *) &(type->attrUses),
11709	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11710	    return(NULL);
11711	/*
11712	* Attribute wildcard.
11713	*/
11714	if (IS_SCHEMA(child, "anyAttribute")) {
11715	    type->attributeWildcard =
11716		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11717	    child = child->next;
11718	}
11719    }
11720    if (child != NULL) {
11721	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11722	    xmlSchemaPContentErr(ctxt,
11723		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11724		NULL, node, child, NULL,
11725		"annotation?, (group | all | choice | sequence)?, "
11726		"((attribute | attributeGroup)*, anyAttribute?))");
11727	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11728	     xmlSchemaPContentErr(ctxt,
11729		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11730		NULL, node, child, NULL,
11731		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11732		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11733		"length | minLength | maxLength | enumeration | whiteSpace | "
11734		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11735	} else {
11736	    /* Simple type */
11737	    xmlSchemaPContentErr(ctxt,
11738		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11739		NULL, node, child, NULL,
11740		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11741		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11742		"length | minLength | maxLength | enumeration | whiteSpace | "
11743		"pattern)*))");
11744	}
11745    }
11746    return (NULL);
11747}
11748
11749/**
11750 * xmlSchemaParseExtension:
11751 * @ctxt:  a schema validation context
11752 * @schema:  the schema being built
11753 * @node:  a subtree containing XML Schema informations
11754 *
11755 * Parses an <extension>, which is found inside a
11756 * <simpleContent> or <complexContent>.
11757 * *WARNING* this interface is highly subject to change.
11758 *
11759 * TODO: Returns the type definition or NULL in case of error
11760 */
11761static xmlSchemaTypePtr
11762xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11763                        xmlNodePtr node, xmlSchemaTypeType parentType)
11764{
11765    xmlSchemaTypePtr type;
11766    xmlNodePtr child = NULL;
11767    xmlAttrPtr attr;
11768
11769    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11770        return (NULL);
11771    /* Not a component, don't create it. */
11772    type = ctxt->ctxtType;
11773    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11774
11775    /*
11776    * Check for illegal attributes.
11777    */
11778    attr = node->properties;
11779    while (attr != NULL) {
11780	if (attr->ns == NULL) {
11781	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11782		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11783		xmlSchemaPIllegalAttrErr(ctxt,
11784		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11785	    }
11786	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11787	    xmlSchemaPIllegalAttrErr(ctxt,
11788		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11789	}
11790	attr = attr->next;
11791    }
11792
11793    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11794
11795    /*
11796    * Attribute "base" - mandatory.
11797    */
11798    if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11799	"base", &(type->baseNs), &(type->base)) == 0) &&
11800	(type->base == NULL)) {
11801	xmlSchemaPMissingAttrErr(ctxt,
11802	    XML_SCHEMAP_S4S_ATTR_MISSING,
11803	    NULL, node, "base", NULL);
11804    }
11805    /*
11806    * And now for the children...
11807    */
11808    child = node->children;
11809    if (IS_SCHEMA(child, "annotation")) {
11810	/*
11811	* Add the annotation to the type ancestor.
11812	*/
11813	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11814	    xmlSchemaParseAnnotation(ctxt, child, 1));
11815        child = child->next;
11816    }
11817    if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11818	/*
11819	* Corresponds to <complexType><complexContent><extension>... and:
11820	*
11821	* Model groups <all>, <choice>, <sequence> and <group>.
11822	*/
11823	if (IS_SCHEMA(child, "all")) {
11824	    type->subtypes = (xmlSchemaTypePtr)
11825		xmlSchemaParseModelGroup(ctxt, schema,
11826		    child, XML_SCHEMA_TYPE_ALL, 1);
11827	    child = child->next;
11828	} else if (IS_SCHEMA(child, "choice")) {
11829	    type->subtypes = (xmlSchemaTypePtr)
11830		xmlSchemaParseModelGroup(ctxt, schema,
11831		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11832	    child = child->next;
11833	} else if (IS_SCHEMA(child, "sequence")) {
11834	    type->subtypes = (xmlSchemaTypePtr)
11835		xmlSchemaParseModelGroup(ctxt, schema,
11836		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11837	    child = child->next;
11838	} else if (IS_SCHEMA(child, "group")) {
11839	    type->subtypes = (xmlSchemaTypePtr)
11840		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11841	    /*
11842	    * Note that the reference will be resolved in
11843	    * xmlSchemaResolveTypeReferences();
11844	    */
11845	    child = child->next;
11846	}
11847    }
11848    if (child != NULL) {
11849	/*
11850	* Attribute uses/declarations.
11851	*/
11852	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11853	    (xmlSchemaItemListPtr *) &(type->attrUses),
11854	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11855	    return(NULL);
11856	/*
11857	* Attribute wildcard.
11858	*/
11859	if (IS_SCHEMA(child, "anyAttribute")) {
11860	    ctxt->ctxtType->attributeWildcard =
11861		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11862	    child = child->next;
11863	}
11864    }
11865    if (child != NULL) {
11866	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11867	    /* Complex content extension. */
11868	    xmlSchemaPContentErr(ctxt,
11869		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11870		NULL, node, child, NULL,
11871		"(annotation?, ((group | all | choice | sequence)?, "
11872		"((attribute | attributeGroup)*, anyAttribute?)))");
11873	} else {
11874	    /* Simple content extension. */
11875	    xmlSchemaPContentErr(ctxt,
11876		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11877		NULL, node, child, NULL,
11878		"(annotation?, ((attribute | attributeGroup)*, "
11879		"anyAttribute?))");
11880	}
11881    }
11882    return (NULL);
11883}
11884
11885/**
11886 * xmlSchemaParseSimpleContent:
11887 * @ctxt:  a schema validation context
11888 * @schema:  the schema being built
11889 * @node:  a subtree containing XML Schema informations
11890 *
11891 * parse a XML schema SimpleContent definition
11892 * *WARNING* this interface is highly subject to change
11893 *
11894 * Returns the type definition or NULL in case of error
11895 */
11896static int
11897xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11898                            xmlSchemaPtr schema, xmlNodePtr node,
11899			    int *hasRestrictionOrExtension)
11900{
11901    xmlSchemaTypePtr type;
11902    xmlNodePtr child = NULL;
11903    xmlAttrPtr attr;
11904
11905    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11906	(hasRestrictionOrExtension == NULL))
11907        return (-1);
11908    *hasRestrictionOrExtension = 0;
11909    /* Not a component, don't create it. */
11910    type = ctxt->ctxtType;
11911    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11912    /*
11913    * Check for illegal attributes.
11914    */
11915    attr = node->properties;
11916    while (attr != NULL) {
11917	if (attr->ns == NULL) {
11918	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11919		xmlSchemaPIllegalAttrErr(ctxt,
11920		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11921	    }
11922	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11923	    xmlSchemaPIllegalAttrErr(ctxt,
11924		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11925	}
11926	attr = attr->next;
11927    }
11928
11929    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11930
11931    /*
11932    * And now for the children...
11933    */
11934    child = node->children;
11935    if (IS_SCHEMA(child, "annotation")) {
11936	/*
11937	* Add the annotation to the complex type ancestor.
11938	*/
11939	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11940	    xmlSchemaParseAnnotation(ctxt, child, 1));
11941        child = child->next;
11942    }
11943    if (child == NULL) {
11944	xmlSchemaPContentErr(ctxt,
11945	    XML_SCHEMAP_S4S_ELEM_MISSING,
11946	    NULL, node, NULL, NULL,
11947	    "(annotation?, (restriction | extension))");
11948    }
11949    if (child == NULL) {
11950	xmlSchemaPContentErr(ctxt,
11951	    XML_SCHEMAP_S4S_ELEM_MISSING,
11952	    NULL, node, NULL, NULL,
11953	    "(annotation?, (restriction | extension))");
11954    }
11955    if (IS_SCHEMA(child, "restriction")) {
11956        xmlSchemaParseRestriction(ctxt, schema, child,
11957	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11958	(*hasRestrictionOrExtension) = 1;
11959        child = child->next;
11960    } else if (IS_SCHEMA(child, "extension")) {
11961        xmlSchemaParseExtension(ctxt, schema, child,
11962	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11963	(*hasRestrictionOrExtension) = 1;
11964        child = child->next;
11965    }
11966    if (child != NULL) {
11967	xmlSchemaPContentErr(ctxt,
11968	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11969	    NULL, node, child, NULL,
11970	    "(annotation?, (restriction | extension))");
11971    }
11972    return (0);
11973}
11974
11975/**
11976 * xmlSchemaParseComplexContent:
11977 * @ctxt:  a schema validation context
11978 * @schema:  the schema being built
11979 * @node:  a subtree containing XML Schema informations
11980 *
11981 * parse a XML schema ComplexContent definition
11982 * *WARNING* this interface is highly subject to change
11983 *
11984 * Returns the type definition or NULL in case of error
11985 */
11986static int
11987xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11988                             xmlSchemaPtr schema, xmlNodePtr node,
11989			     int *hasRestrictionOrExtension)
11990{
11991    xmlSchemaTypePtr type;
11992    xmlNodePtr child = NULL;
11993    xmlAttrPtr attr;
11994
11995    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11996	(hasRestrictionOrExtension == NULL))
11997        return (-1);
11998    *hasRestrictionOrExtension = 0;
11999    /* Not a component, don't create it. */
12000    type = ctxt->ctxtType;
12001    /*
12002    * Check for illegal attributes.
12003    */
12004    attr = node->properties;
12005    while (attr != NULL) {
12006	if (attr->ns == NULL) {
12007	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12008		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12009	    {
12010		xmlSchemaPIllegalAttrErr(ctxt,
12011		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12012	    }
12013	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12014	    xmlSchemaPIllegalAttrErr(ctxt,
12015		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12016	}
12017	attr = attr->next;
12018    }
12019
12020    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12021
12022    /*
12023    * Set the 'mixed' on the complex type ancestor.
12024    */
12025    if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12026	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12027	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12028    }
12029    child = node->children;
12030    if (IS_SCHEMA(child, "annotation")) {
12031	/*
12032	* Add the annotation to the complex type ancestor.
12033	*/
12034	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12035	    xmlSchemaParseAnnotation(ctxt, child, 1));
12036        child = child->next;
12037    }
12038    if (child == NULL) {
12039	xmlSchemaPContentErr(ctxt,
12040	    XML_SCHEMAP_S4S_ELEM_MISSING,
12041	    NULL, node, NULL,
12042	    NULL, "(annotation?, (restriction | extension))");
12043    }
12044    if (child == NULL) {
12045	xmlSchemaPContentErr(ctxt,
12046	    XML_SCHEMAP_S4S_ELEM_MISSING,
12047	    NULL, node, NULL,
12048	    NULL, "(annotation?, (restriction | extension))");
12049    }
12050    if (IS_SCHEMA(child, "restriction")) {
12051        xmlSchemaParseRestriction(ctxt, schema, child,
12052	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12053	(*hasRestrictionOrExtension) = 1;
12054        child = child->next;
12055    } else if (IS_SCHEMA(child, "extension")) {
12056        xmlSchemaParseExtension(ctxt, schema, child,
12057	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12058	(*hasRestrictionOrExtension) = 1;
12059        child = child->next;
12060    }
12061    if (child != NULL) {
12062	xmlSchemaPContentErr(ctxt,
12063	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12064	    NULL, node, child,
12065	    NULL, "(annotation?, (restriction | extension))");
12066    }
12067    return (0);
12068}
12069
12070/**
12071 * xmlSchemaParseComplexType:
12072 * @ctxt:  a schema validation context
12073 * @schema:  the schema being built
12074 * @node:  a subtree containing XML Schema informations
12075 *
12076 * parse a XML schema Complex Type definition
12077 * *WARNING* this interface is highly subject to change
12078 *
12079 * Returns the type definition or NULL in case of error
12080 */
12081static xmlSchemaTypePtr
12082xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12083                          xmlNodePtr node, int topLevel)
12084{
12085    xmlSchemaTypePtr type, ctxtType;
12086    xmlNodePtr child = NULL;
12087    const xmlChar *name = NULL;
12088    xmlAttrPtr attr;
12089    const xmlChar *attrValue;
12090#ifdef ENABLE_NAMED_LOCALS
12091    char buf[40];
12092#endif
12093    int final = 0, block = 0, hasRestrictionOrExtension = 0;
12094
12095
12096    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12097        return (NULL);
12098
12099    ctxtType = ctxt->ctxtType;
12100
12101    if (topLevel) {
12102	attr = xmlSchemaGetPropNode(node, "name");
12103	if (attr == NULL) {
12104	    xmlSchemaPMissingAttrErr(ctxt,
12105		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12106	    return (NULL);
12107	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12108	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12109	    return (NULL);
12110	}
12111    }
12112
12113    if (topLevel == 0) {
12114	/*
12115	* Parse as local complex type definition.
12116	*/
12117#ifdef ENABLE_NAMED_LOCALS
12118        snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12119	type = xmlSchemaAddType(ctxt, schema,
12120	    XML_SCHEMA_TYPE_COMPLEX,
12121	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12122	    ctxt->targetNamespace, node, 0);
12123#else
12124	type = xmlSchemaAddType(ctxt, schema,
12125	    XML_SCHEMA_TYPE_COMPLEX,
12126	    NULL, ctxt->targetNamespace, node, 0);
12127#endif
12128	if (type == NULL)
12129	    return (NULL);
12130	name = type->name;
12131	type->node = node;
12132	type->type = XML_SCHEMA_TYPE_COMPLEX;
12133	/*
12134	* TODO: We need the target namespace.
12135	*/
12136    } else {
12137	/*
12138	* Parse as global complex type definition.
12139	*/
12140	type = xmlSchemaAddType(ctxt, schema,
12141	    XML_SCHEMA_TYPE_COMPLEX,
12142	    name, ctxt->targetNamespace, node, 1);
12143	if (type == NULL)
12144	    return (NULL);
12145	type->node = node;
12146	type->type = XML_SCHEMA_TYPE_COMPLEX;
12147	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12148    }
12149    type->targetNamespace = ctxt->targetNamespace;
12150    /*
12151    * Handle attributes.
12152    */
12153    attr = node->properties;
12154    while (attr != NULL) {
12155	if (attr->ns == NULL) {
12156	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12157		/*
12158		* Attribute "id".
12159		*/
12160		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12161	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12162		/*
12163		* Attribute "mixed".
12164		*/
12165		if (xmlSchemaPGetBoolNodeValue(ctxt,
12166			NULL, (xmlNodePtr) attr))
12167		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12168	    } else if (topLevel) {
12169		/*
12170		* Attributes of global complex type definitions.
12171		*/
12172		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12173		    /* Pass. */
12174		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12175		    /*
12176		    * Attribute "abstract".
12177		    */
12178		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12179			    NULL, (xmlNodePtr) attr))
12180			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12181		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12182		    /*
12183		    * Attribute "final".
12184		    */
12185		    attrValue = xmlSchemaGetNodeContent(ctxt,
12186			(xmlNodePtr) attr);
12187		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12188			&(type->flags),
12189			-1,
12190			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12191			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12192			-1, -1, -1) != 0)
12193		    {
12194			xmlSchemaPSimpleTypeErr(ctxt,
12195			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12196			    NULL, (xmlNodePtr) attr, NULL,
12197			    "(#all | List of (extension | restriction))",
12198			    attrValue, NULL, NULL, NULL);
12199		    } else
12200			final = 1;
12201		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12202		    /*
12203		    * Attribute "block".
12204		    */
12205		    attrValue = xmlSchemaGetNodeContent(ctxt,
12206			(xmlNodePtr) attr);
12207		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12208			-1,
12209			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12210			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12211			-1, -1, -1) != 0) {
12212			xmlSchemaPSimpleTypeErr(ctxt,
12213			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12214			    NULL, (xmlNodePtr) attr, NULL,
12215			    "(#all | List of (extension | restriction)) ",
12216			    attrValue, NULL, NULL, NULL);
12217		    } else
12218			block = 1;
12219		} else {
12220			xmlSchemaPIllegalAttrErr(ctxt,
12221			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12222		}
12223	    } else {
12224		xmlSchemaPIllegalAttrErr(ctxt,
12225		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12226	    }
12227	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12228	    xmlSchemaPIllegalAttrErr(ctxt,
12229		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12230	}
12231	attr = attr->next;
12232    }
12233    if (! block) {
12234	/*
12235	* Apply default "block" values.
12236	*/
12237	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12238	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12239	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12240	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12241    }
12242    if (! final) {
12243	/*
12244	* Apply default "block" values.
12245	*/
12246	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12247	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12248	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12249	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12250    }
12251    /*
12252    * And now for the children...
12253    */
12254    child = node->children;
12255    if (IS_SCHEMA(child, "annotation")) {
12256        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12257        child = child->next;
12258    }
12259    ctxt->ctxtType = type;
12260    if (IS_SCHEMA(child, "simpleContent")) {
12261	/*
12262	* <complexType><simpleContent>...
12263	* 3.4.3 : 2.2
12264	* Specifying mixed='true' when the <simpleContent>
12265	* alternative is chosen has no effect
12266	*/
12267	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12268	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12269        xmlSchemaParseSimpleContent(ctxt, schema, child,
12270	    &hasRestrictionOrExtension);
12271        child = child->next;
12272    } else if (IS_SCHEMA(child, "complexContent")) {
12273	/*
12274	* <complexType><complexContent>...
12275	*/
12276	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12277        xmlSchemaParseComplexContent(ctxt, schema, child,
12278	    &hasRestrictionOrExtension);
12279        child = child->next;
12280    } else {
12281	/*
12282	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12283	*
12284	* SPEC
12285	* "...the third alternative (neither <simpleContent> nor
12286	* <complexContent>) is chosen. This case is understood as shorthand
12287	* for complex content restricting the �ur-type definition�, and the
12288	* details of the mappings should be modified as necessary.
12289	*/
12290	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12291	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12292	/*
12293	* Parse model groups.
12294	*/
12295        if (IS_SCHEMA(child, "all")) {
12296            type->subtypes = (xmlSchemaTypePtr)
12297		xmlSchemaParseModelGroup(ctxt, schema, child,
12298		    XML_SCHEMA_TYPE_ALL, 1);
12299            child = child->next;
12300        } else if (IS_SCHEMA(child, "choice")) {
12301            type->subtypes = (xmlSchemaTypePtr)
12302		xmlSchemaParseModelGroup(ctxt, schema, child,
12303		    XML_SCHEMA_TYPE_CHOICE, 1);
12304            child = child->next;
12305        } else if (IS_SCHEMA(child, "sequence")) {
12306            type->subtypes = (xmlSchemaTypePtr)
12307		xmlSchemaParseModelGroup(ctxt, schema, child,
12308		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12309            child = child->next;
12310        } else if (IS_SCHEMA(child, "group")) {
12311            type->subtypes = (xmlSchemaTypePtr)
12312		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12313	    /*
12314	    * Note that the reference will be resolved in
12315	    * xmlSchemaResolveTypeReferences();
12316	    */
12317            child = child->next;
12318        }
12319	/*
12320	* Parse attribute decls/refs.
12321	*/
12322        if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12323	    (xmlSchemaItemListPtr *) &(type->attrUses),
12324	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12325	    return(NULL);
12326	/*
12327	* Parse attribute wildcard.
12328	*/
12329	if (IS_SCHEMA(child, "anyAttribute")) {
12330	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12331	    child = child->next;
12332	}
12333    }
12334    if (child != NULL) {
12335	xmlSchemaPContentErr(ctxt,
12336	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12337	    NULL, node, child,
12338	    NULL, "(annotation?, (simpleContent | complexContent | "
12339	    "((group | all | choice | sequence)?, ((attribute | "
12340	    "attributeGroup)*, anyAttribute?))))");
12341    }
12342    /*
12343    * REDEFINE: SPEC src-redefine (5)
12344    */
12345    if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12346	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12347	    NULL, node, "This is a redefinition, thus the "
12348	    "<complexType> must have a <restriction> or <extension> "
12349	    "grand-child", NULL);
12350    }
12351    ctxt->ctxtType = ctxtType;
12352    return (type);
12353}
12354
12355/************************************************************************
12356 * 									*
12357 * 			Validating using Schemas			*
12358 * 									*
12359 ************************************************************************/
12360
12361/************************************************************************
12362 * 									*
12363 * 			Reading/Writing Schemas				*
12364 * 									*
12365 ************************************************************************/
12366
12367#if 0 /* Will be enabled if it is clear what options are needed. */
12368/**
12369 * xmlSchemaParserCtxtSetOptions:
12370 * @ctxt:	a schema parser context
12371 * @options: a combination of xmlSchemaParserOption
12372 *
12373 * Sets the options to be used during the parse.
12374 *
12375 * Returns 0 in case of success, -1 in case of an
12376 * API error.
12377 */
12378static int
12379xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12380			      int options)
12381
12382{
12383    int i;
12384
12385    if (ctxt == NULL)
12386	return (-1);
12387    /*
12388    * WARNING: Change the start value if adding to the
12389    * xmlSchemaParseOption.
12390    */
12391    for (i = 1; i < (int) sizeof(int) * 8; i++) {
12392        if (options & 1<<i) {
12393	    return (-1);
12394        }
12395    }
12396    ctxt->options = options;
12397    return (0);
12398}
12399
12400/**
12401 * xmlSchemaValidCtxtGetOptions:
12402 * @ctxt: a schema parser context
12403 *
12404 * Returns the option combination of the parser context.
12405 */
12406static int
12407xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12408
12409{
12410    if (ctxt == NULL)
12411	return (-1);
12412    else
12413	return (ctxt->options);
12414}
12415#endif
12416
12417/**
12418 * xmlSchemaNewParserCtxt:
12419 * @URL:  the location of the schema
12420 *
12421 * Create an XML Schemas parse context for that file/resource expected
12422 * to contain an XML Schemas file.
12423 *
12424 * Returns the parser context or NULL in case of error
12425 */
12426xmlSchemaParserCtxtPtr
12427xmlSchemaNewParserCtxt(const char *URL)
12428{
12429    xmlSchemaParserCtxtPtr ret;
12430
12431    if (URL == NULL)
12432        return (NULL);
12433
12434    ret = xmlSchemaParserCtxtCreate();
12435    if (ret == NULL)
12436	return(NULL);
12437    ret->dict = xmlDictCreate();
12438    ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12439    return (ret);
12440}
12441
12442/**
12443 * xmlSchemaNewMemParserCtxt:
12444 * @buffer:  a pointer to a char array containing the schemas
12445 * @size:  the size of the array
12446 *
12447 * Create an XML Schemas parse context for that memory buffer expected
12448 * to contain an XML Schemas file.
12449 *
12450 * Returns the parser context or NULL in case of error
12451 */
12452xmlSchemaParserCtxtPtr
12453xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12454{
12455    xmlSchemaParserCtxtPtr ret;
12456
12457    if ((buffer == NULL) || (size <= 0))
12458        return (NULL);
12459    ret = xmlSchemaParserCtxtCreate();
12460    if (ret == NULL)
12461	return(NULL);
12462    ret->buffer = buffer;
12463    ret->size = size;
12464    ret->dict = xmlDictCreate();
12465    return (ret);
12466}
12467
12468/**
12469 * xmlSchemaNewDocParserCtxt:
12470 * @doc:  a preparsed document tree
12471 *
12472 * Create an XML Schemas parse context for that document.
12473 * NB. The document may be modified during the parsing process.
12474 *
12475 * Returns the parser context or NULL in case of error
12476 */
12477xmlSchemaParserCtxtPtr
12478xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12479{
12480    xmlSchemaParserCtxtPtr ret;
12481
12482    if (doc == NULL)
12483      return (NULL);
12484    ret = xmlSchemaParserCtxtCreate();
12485    if (ret == NULL)
12486	return(NULL);
12487    ret->doc = doc;
12488    ret->dict = xmlDictCreate();
12489    /* The application has responsibility for the document */
12490    ret->preserve = 1;
12491
12492    return (ret);
12493}
12494
12495/**
12496 * xmlSchemaFreeParserCtxt:
12497 * @ctxt:  the schema parser context
12498 *
12499 * Free the resources associated to the schema parser context
12500 */
12501void
12502xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12503{
12504    if (ctxt == NULL)
12505        return;
12506    if (ctxt->doc != NULL && !ctxt->preserve)
12507        xmlFreeDoc(ctxt->doc);
12508    if (ctxt->vctxt != NULL) {
12509	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12510    }
12511    if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12512	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12513	ctxt->constructor = NULL;
12514	ctxt->ownsConstructor = 0;
12515    }
12516    if (ctxt->attrProhibs != NULL)
12517	xmlSchemaItemListFree(ctxt->attrProhibs);
12518    xmlDictFree(ctxt->dict);
12519    xmlFree(ctxt);
12520}
12521
12522/************************************************************************
12523 *									*
12524 *			Building the content models			*
12525 *									*
12526 ************************************************************************/
12527
12528/**
12529 * xmlSchemaBuildContentModelForSubstGroup:
12530 *
12531 * Returns 1 if nillable, 0 otherwise
12532 */
12533static int
12534xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12535	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12536{
12537    xmlAutomataStatePtr start, tmp;
12538    xmlSchemaElementPtr elemDecl, member;
12539    xmlSchemaSubstGroupPtr substGroup;
12540    int i;
12541    int ret = 0;
12542
12543    elemDecl = (xmlSchemaElementPtr) particle->children;
12544    /*
12545    * Wrap the substitution group with a CHOICE.
12546    */
12547    start = pctxt->state;
12548    if (end == NULL)
12549	end = xmlAutomataNewState(pctxt->am);
12550    substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12551    if (substGroup == NULL) {
12552	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12553	    XML_SCHEMAP_INTERNAL,
12554	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12555	    "declaration is marked having a subst. group but none "
12556	    "available.\n", elemDecl->name, NULL);
12557	return(0);
12558    }
12559    if (counter >= 0) {
12560	/*
12561	* NOTE that we put the declaration in, even if it's abstract.
12562	* However, an error will be raised during *validation* if an element
12563	* information item shall be validated against an abstract element
12564	* declaration.
12565	*/
12566	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12567        xmlAutomataNewTransition2(pctxt->am, tmp, end,
12568	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12569	/*
12570	* Add subst. group members.
12571	*/
12572	for (i = 0; i < substGroup->members->nbItems; i++) {
12573	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12574            xmlAutomataNewTransition2(pctxt->am, tmp, end,
12575		               member->name, member->targetNamespace, member);
12576	}
12577    } else if (particle->maxOccurs == 1) {
12578	/*
12579	* NOTE that we put the declaration in, even if it's abstract,
12580	*/
12581	xmlAutomataNewEpsilon(pctxt->am,
12582	    xmlAutomataNewTransition2(pctxt->am,
12583	    start, NULL,
12584	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12585	/*
12586	* Add subst. group members.
12587	*/
12588	for (i = 0; i < substGroup->members->nbItems; i++) {
12589	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12590	    /*
12591	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12592	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12593	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12594	    *  section in xmlSchemaBuildAContentModel() ).
12595	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12596	    *  intended for the above "counter" section originally. I.e.,
12597	    *  check xs:all with subst-groups.
12598	    *
12599	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12600	    *	               member->name, member->targetNamespace,
12601	    *		       1, 1, member);
12602	    */
12603	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12604		member->name, member->targetNamespace, member);
12605	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12606	}
12607    } else {
12608	xmlAutomataStatePtr hop;
12609	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12610	    UNBOUNDED : particle->maxOccurs - 1;
12611	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12612
12613	counter =
12614	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12615	    maxOccurs);
12616	hop = xmlAutomataNewState(pctxt->am);
12617
12618	xmlAutomataNewEpsilon(pctxt->am,
12619	    xmlAutomataNewTransition2(pctxt->am,
12620	    start, NULL,
12621	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12622	    hop);
12623	/*
12624	 * Add subst. group members.
12625	 */
12626	for (i = 0; i < substGroup->members->nbItems; i++) {
12627	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12628	    xmlAutomataNewEpsilon(pctxt->am,
12629		xmlAutomataNewTransition2(pctxt->am,
12630		start, NULL,
12631		member->name, member->targetNamespace, member),
12632		hop);
12633	}
12634	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12635	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12636    }
12637    if (particle->minOccurs == 0) {
12638	xmlAutomataNewEpsilon(pctxt->am, start, end);
12639        ret = 1;
12640    }
12641    pctxt->state = end;
12642    return(ret);
12643}
12644
12645/**
12646 * xmlSchemaBuildContentModelForElement:
12647 *
12648 * Returns 1 if nillable, 0 otherwise
12649 */
12650static int
12651xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12652				     xmlSchemaParticlePtr particle)
12653{
12654    int ret = 0;
12655
12656    if (((xmlSchemaElementPtr) particle->children)->flags &
12657	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12658	/*
12659	* Substitution groups.
12660	*/
12661	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12662    } else {
12663	xmlSchemaElementPtr elemDecl;
12664	xmlAutomataStatePtr start;
12665
12666	elemDecl = (xmlSchemaElementPtr) particle->children;
12667
12668	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12669	    return(0);
12670	if (particle->maxOccurs == 1) {
12671	    start = ctxt->state;
12672	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12673		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12674	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12675	           (particle->minOccurs < 2)) {
12676	    /* Special case. */
12677	    start = ctxt->state;
12678	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12679		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12681		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12682	} else {
12683	    int counter;
12684	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12685			    UNBOUNDED : particle->maxOccurs - 1;
12686	    int minOccurs = particle->minOccurs < 1 ?
12687			    0 : particle->minOccurs - 1;
12688
12689	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12690	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12691	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12692		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12693	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12694	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12695		NULL, counter);
12696	}
12697	if (particle->minOccurs == 0) {
12698	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12699            ret = 1;
12700        }
12701    }
12702    return(ret);
12703}
12704
12705/**
12706 * xmlSchemaBuildAContentModel:
12707 * @ctxt:  the schema parser context
12708 * @particle:  the particle component
12709 * @name:  the complex type's name whose content is being built
12710 *
12711 * Create the automaton for the {content type} of a complex type.
12712 *
12713 * Returns 1 if the content is nillable, 0 otherwise
12714 */
12715static int
12716xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12717			    xmlSchemaParticlePtr particle)
12718{
12719    int ret = 0, tmp2;
12720
12721    if (particle == NULL) {
12722	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12723	return(1);
12724    }
12725    if (particle->children == NULL) {
12726	/*
12727	* Just return in this case. A missing "term" of the particle
12728	* might arise due to an invalid "term" component.
12729	*/
12730	return(1);
12731    }
12732
12733    switch (particle->children->type) {
12734	case XML_SCHEMA_TYPE_ANY: {
12735	    xmlAutomataStatePtr start, end;
12736	    xmlSchemaWildcardPtr wild;
12737	    xmlSchemaWildcardNsPtr ns;
12738
12739	    wild = (xmlSchemaWildcardPtr) particle->children;
12740
12741	    start = pctxt->state;
12742	    end = xmlAutomataNewState(pctxt->am);
12743
12744	    if (particle->maxOccurs == 1) {
12745		if (wild->any == 1) {
12746		    /*
12747		    * We need to add both transitions:
12748		    *
12749		    * 1. the {"*", "*"} for elements in a namespace.
12750		    */
12751		    pctxt->state =
12752			xmlAutomataNewTransition2(pctxt->am,
12753			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12754		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12755		    /*
12756		    * 2. the {"*"} for elements in no namespace.
12757		    */
12758		    pctxt->state =
12759			xmlAutomataNewTransition2(pctxt->am,
12760			start, NULL, BAD_CAST "*", NULL, wild);
12761		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12762
12763		} else if (wild->nsSet != NULL) {
12764		    ns = wild->nsSet;
12765		    do {
12766			pctxt->state = start;
12767			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12768			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12769			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12770			ns = ns->next;
12771		    } while (ns != NULL);
12772
12773		} else if (wild->negNsSet != NULL) {
12774		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12775			start, end, BAD_CAST "*", wild->negNsSet->value,
12776			wild);
12777		}
12778	    } else {
12779		int counter;
12780		xmlAutomataStatePtr hop;
12781		int maxOccurs =
12782		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12783                                           particle->maxOccurs - 1;
12784		int minOccurs =
12785		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12786
12787		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12788		hop = xmlAutomataNewState(pctxt->am);
12789		if (wild->any == 1) {
12790		    pctxt->state =
12791			xmlAutomataNewTransition2(pctxt->am,
12792			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12793		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12794		    pctxt->state =
12795			xmlAutomataNewTransition2(pctxt->am,
12796			start, NULL, BAD_CAST "*", NULL, wild);
12797		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12798		} else if (wild->nsSet != NULL) {
12799		    ns = wild->nsSet;
12800		    do {
12801			pctxt->state =
12802			    xmlAutomataNewTransition2(pctxt->am,
12803				start, NULL, BAD_CAST "*", ns->value, wild);
12804			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12805			ns = ns->next;
12806		    } while (ns != NULL);
12807
12808		} else if (wild->negNsSet != NULL) {
12809		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12810			start, hop, BAD_CAST "*", wild->negNsSet->value,
12811			wild);
12812		}
12813		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12814		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12815	    }
12816	    if (particle->minOccurs == 0) {
12817		xmlAutomataNewEpsilon(pctxt->am, start, end);
12818                ret = 1;
12819	    }
12820	    pctxt->state = end;
12821            break;
12822	}
12823        case XML_SCHEMA_TYPE_ELEMENT:
12824	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12825	    break;
12826        case XML_SCHEMA_TYPE_SEQUENCE:{
12827            xmlSchemaTreeItemPtr sub;
12828
12829            ret = 1;
12830            /*
12831             * If max and min occurances are default (1) then
12832             * simply iterate over the particles of the <sequence>.
12833             */
12834            if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12835                sub = particle->children->children;
12836
12837                while (sub != NULL) {
12838                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
12839                                        (xmlSchemaParticlePtr) sub);
12840                    if (tmp2 != 1) ret = 0;
12841                    sub = sub->next;
12842                }
12843            } else {
12844                xmlAutomataStatePtr oldstate = pctxt->state;
12845
12846                if (particle->maxOccurs >= UNBOUNDED) {
12847                    if (particle->minOccurs > 1) {
12848                        xmlAutomataStatePtr tmp;
12849                        int counter;
12850
12851                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12852                            oldstate, NULL);
12853                        oldstate = pctxt->state;
12854
12855                        counter = xmlAutomataNewCounter(pctxt->am,
12856                            particle->minOccurs - 1, UNBOUNDED);
12857
12858                        sub = particle->children->children;
12859                        while (sub != NULL) {
12860                            tmp2 = xmlSchemaBuildAContentModel(pctxt,
12861                                            (xmlSchemaParticlePtr) sub);
12862                            if (tmp2 != 1) ret = 0;
12863                            sub = sub->next;
12864                        }
12865                        tmp = pctxt->state;
12866                        xmlAutomataNewCountedTrans(pctxt->am, tmp,
12867                                                   oldstate, counter);
12868                        pctxt->state =
12869                            xmlAutomataNewCounterTrans(pctxt->am, tmp,
12870                                                       NULL, counter);
12871                        if (ret == 1)
12872                            xmlAutomataNewEpsilon(pctxt->am,
12873                                                oldstate, pctxt->state);
12874
12875                    } else {
12876                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12877                            oldstate, NULL);
12878                        oldstate = pctxt->state;
12879
12880                        sub = particle->children->children;
12881                        while (sub != NULL) {
12882                            tmp2 = xmlSchemaBuildAContentModel(pctxt,
12883                                        (xmlSchemaParticlePtr) sub);
12884                            if (tmp2 != 1) ret = 0;
12885                            sub = sub->next;
12886                        }
12887                        xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12888                                              oldstate);
12889                        /*
12890                         * epsilon needed to block previous trans from
12891                         * being allowed to enter back from another
12892                         * construct
12893                         */
12894                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12895                                            pctxt->state, NULL);
12896                        if (particle->minOccurs == 0) {
12897                            xmlAutomataNewEpsilon(pctxt->am,
12898                                oldstate, pctxt->state);
12899                            ret = 1;
12900                        }
12901                    }
12902                } else if ((particle->maxOccurs > 1)
12903                           || (particle->minOccurs > 1)) {
12904                    xmlAutomataStatePtr tmp;
12905                    int counter;
12906
12907                    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12908                        oldstate, NULL);
12909                    oldstate = pctxt->state;
12910
12911                    counter = xmlAutomataNewCounter(pctxt->am,
12912                        particle->minOccurs - 1,
12913                        particle->maxOccurs - 1);
12914
12915                    sub = particle->children->children;
12916                    while (sub != NULL) {
12917                        tmp2 = xmlSchemaBuildAContentModel(pctxt,
12918                                        (xmlSchemaParticlePtr) sub);
12919                        if (tmp2 != 1) ret = 0;
12920                        sub = sub->next;
12921                    }
12922                    tmp = pctxt->state;
12923                    xmlAutomataNewCountedTrans(pctxt->am,
12924                        tmp, oldstate, counter);
12925                    pctxt->state =
12926                        xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12927                                                   counter);
12928                    if ((particle->minOccurs == 0) || (ret == 1)) {
12929                        xmlAutomataNewEpsilon(pctxt->am,
12930                                            oldstate, pctxt->state);
12931                        ret = 1;
12932                    }
12933                } else {
12934                    sub = particle->children->children;
12935                    while (sub != NULL) {
12936                        tmp2 = xmlSchemaBuildAContentModel(pctxt,
12937                                        (xmlSchemaParticlePtr) sub);
12938                        if (tmp2 != 1) ret = 0;
12939                        sub = sub->next;
12940                    }
12941                    if (particle->minOccurs == 0) {
12942                        xmlAutomataNewEpsilon(pctxt->am, oldstate,
12943                                              pctxt->state);
12944                        ret = 1;
12945                    }
12946                }
12947            }
12948            break;
12949        }
12950        case XML_SCHEMA_TYPE_CHOICE:{
12951            xmlSchemaTreeItemPtr sub;
12952            xmlAutomataStatePtr start, end;
12953
12954            ret = 0;
12955            start = pctxt->state;
12956            end = xmlAutomataNewState(pctxt->am);
12957
12958            /*
12959             * iterate over the subtypes and remerge the end with an
12960             * epsilon transition
12961             */
12962            if (particle->maxOccurs == 1) {
12963                sub = particle->children->children;
12964                while (sub != NULL) {
12965                    pctxt->state = start;
12966                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
12967                                        (xmlSchemaParticlePtr) sub);
12968                    if (tmp2 == 1) ret = 1;
12969                    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12970                    sub = sub->next;
12971                }
12972            } else {
12973                int counter;
12974                xmlAutomataStatePtr hop, base;
12975                int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12976                    UNBOUNDED : particle->maxOccurs - 1;
12977                int minOccurs =
12978                    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12979
12980                /*
12981                 * use a counter to keep track of the number of transtions
12982                 * which went through the choice.
12983                 */
12984                counter =
12985                    xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12986                hop = xmlAutomataNewState(pctxt->am);
12987                base = xmlAutomataNewState(pctxt->am);
12988
12989                sub = particle->children->children;
12990                while (sub != NULL) {
12991                    pctxt->state = base;
12992                    tmp2 = xmlSchemaBuildAContentModel(pctxt,
12993                                        (xmlSchemaParticlePtr) sub);
12994                    if (tmp2 == 1) ret = 1;
12995                    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12996                    sub = sub->next;
12997                }
12998                xmlAutomataNewEpsilon(pctxt->am, start, base);
12999                xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13000                xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13001                if (ret == 1)
13002                    xmlAutomataNewEpsilon(pctxt->am, base, end);
13003            }
13004            if (particle->minOccurs == 0) {
13005                xmlAutomataNewEpsilon(pctxt->am, start, end);
13006                ret = 1;
13007            }
13008            pctxt->state = end;
13009            break;
13010        }
13011        case XML_SCHEMA_TYPE_ALL:{
13012            xmlAutomataStatePtr start, tmp;
13013            xmlSchemaParticlePtr sub;
13014            xmlSchemaElementPtr elemDecl;
13015
13016            ret = 1;
13017
13018            sub = (xmlSchemaParticlePtr) particle->children->children;
13019            if (sub == NULL)
13020                break;
13021
13022            ret = 0;
13023
13024            start = pctxt->state;
13025            tmp = xmlAutomataNewState(pctxt->am);
13026            xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13027            pctxt->state = tmp;
13028            while (sub != NULL) {
13029                pctxt->state = tmp;
13030
13031                elemDecl = (xmlSchemaElementPtr) sub->children;
13032                if (elemDecl == NULL) {
13033                    PERROR_INT("xmlSchemaBuildAContentModel",
13034                        "<element> particle has no term");
13035                    return(ret);
13036                };
13037                /*
13038                * NOTE: The {max occurs} of all the particles in the
13039                * {particles} of the group must be 0 or 1; this is
13040                * already ensured during the parse of the content of
13041                * <all>.
13042                */
13043                if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13044                    int counter;
13045
13046                    /*
13047                     * This is an abstract group, we need to share
13048                     * the same counter for all the element transitions
13049                     * derived from the group
13050                     */
13051                    counter = xmlAutomataNewCounter(pctxt->am,
13052                                       sub->minOccurs, sub->maxOccurs);
13053                    xmlSchemaBuildContentModelForSubstGroup(pctxt,
13054                                       sub, counter, pctxt->state);
13055                } else {
13056                    if ((sub->minOccurs == 1) &&
13057                        (sub->maxOccurs == 1)) {
13058                        xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13059                                                pctxt->state,
13060                                                elemDecl->name,
13061                                                elemDecl->targetNamespace,
13062                                                1, 1, elemDecl);
13063                    } else if ((sub->minOccurs == 0) &&
13064                        (sub->maxOccurs == 1)) {
13065
13066                        xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13067                                                 pctxt->state,
13068                                                 elemDecl->name,
13069                                                 elemDecl->targetNamespace,
13070                                                 0,
13071                                                 1,
13072                                                 elemDecl);
13073                    }
13074                }
13075                sub = (xmlSchemaParticlePtr) sub->next;
13076            }
13077            pctxt->state =
13078                xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13079            if (particle->minOccurs == 0) {
13080                xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13081                ret = 1;
13082            }
13083            break;
13084        }
13085	case XML_SCHEMA_TYPE_GROUP:
13086	    /*
13087	    * If we hit a model group definition, then this means that
13088	    * it was empty, thus was not substituted for the containing
13089	    * model group. Just do nothing in this case.
13090	    * TODO: But the group should be substituted and not occur at
13091	    * all in the content model at this point. Fix this.
13092	    */
13093            ret = 1;
13094	    break;
13095        default:
13096	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13097		"xmlSchemaBuildAContentModel",
13098		"found unexpected term of type '%s' in content model",
13099		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13100            return(ret);
13101    }
13102    return(ret);
13103}
13104
13105/**
13106 * xmlSchemaBuildContentModel:
13107 * @ctxt:  the schema parser context
13108 * @type:  the complex type definition
13109 * @name:  the element name
13110 *
13111 * Builds the content model of the complex type.
13112 */
13113static void
13114xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13115			   xmlSchemaParserCtxtPtr ctxt)
13116{
13117    if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13118	(type->contModel != NULL) ||
13119	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13120	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13121	return;
13122
13123#ifdef DEBUG_CONTENT
13124    xmlGenericError(xmlGenericErrorContext,
13125                    "Building content model for %s\n", name);
13126#endif
13127    ctxt->am = NULL;
13128    ctxt->am = xmlNewAutomata();
13129    if (ctxt->am == NULL) {
13130        xmlGenericError(xmlGenericErrorContext,
13131	    "Cannot create automata for complex type %s\n", type->name);
13132        return;
13133    }
13134    ctxt->state = xmlAutomataGetInitState(ctxt->am);
13135    /*
13136    * Build the automaton.
13137    */
13138    xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13139    xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13140    type->contModel = xmlAutomataCompile(ctxt->am);
13141    if (type->contModel == NULL) {
13142        xmlSchemaPCustomErr(ctxt,
13143	    XML_SCHEMAP_INTERNAL,
13144	    WXS_BASIC_CAST type, type->node,
13145	    "Failed to compile the content model", NULL);
13146    } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13147        xmlSchemaPCustomErr(ctxt,
13148	    XML_SCHEMAP_NOT_DETERMINISTIC,
13149	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13150	    WXS_BASIC_CAST type, type->node,
13151	    "The content model is not determinist", NULL);
13152    } else {
13153#ifdef DEBUG_CONTENT_REGEXP
13154        xmlGenericError(xmlGenericErrorContext,
13155                        "Content model of %s:\n", type->name);
13156        xmlRegexpPrint(stderr, type->contModel);
13157#endif
13158    }
13159    ctxt->state = NULL;
13160    xmlFreeAutomata(ctxt->am);
13161    ctxt->am = NULL;
13162}
13163
13164/**
13165 * xmlSchemaResolveElementReferences:
13166 * @elem:  the schema element context
13167 * @ctxt:  the schema parser context
13168 *
13169 * Resolves the references of an element declaration
13170 * or particle, which has an element declaration as it's
13171 * term.
13172 */
13173static void
13174xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13175				  xmlSchemaParserCtxtPtr ctxt)
13176{
13177    if ((ctxt == NULL) || (elemDecl == NULL) ||
13178	((elemDecl != NULL) &&
13179	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13180        return;
13181    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13182
13183    if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13184	xmlSchemaTypePtr type;
13185
13186	/* (type definition) ... otherwise the type definition �resolved�
13187	* to by the �actual value� of the type [attribute] ...
13188	*/
13189	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13190	    elemDecl->namedTypeNs);
13191	if (type == NULL) {
13192	    xmlSchemaPResCompAttrErr(ctxt,
13193		XML_SCHEMAP_SRC_RESOLVE,
13194		WXS_BASIC_CAST elemDecl, elemDecl->node,
13195		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13196		XML_SCHEMA_TYPE_BASIC, "type definition");
13197	} else
13198	    elemDecl->subtypes = type;
13199    }
13200    if (elemDecl->substGroup != NULL) {
13201	xmlSchemaElementPtr substHead;
13202
13203	/*
13204	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13205	* substitutionGroup?
13206	*/
13207	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13208	    elemDecl->substGroupNs);
13209	if (substHead == NULL) {
13210	    xmlSchemaPResCompAttrErr(ctxt,
13211		XML_SCHEMAP_SRC_RESOLVE,
13212		WXS_BASIC_CAST elemDecl, NULL,
13213		"substitutionGroup", elemDecl->substGroup,
13214		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13215	} else {
13216	    xmlSchemaResolveElementReferences(substHead, ctxt);
13217	    /*
13218	    * Set the "substitution group affiliation".
13219	    * NOTE that now we use the "refDecl" field for this.
13220	    */
13221	    WXS_SUBST_HEAD(elemDecl) = substHead;
13222	    /*
13223	    * The type definitions is set to:
13224	    * SPEC "...the {type definition} of the element
13225	    * declaration �resolved� to by the �actual value�
13226	    * of the substitutionGroup [attribute], if present"
13227	    */
13228	    if (elemDecl->subtypes == NULL)
13229		elemDecl->subtypes = substHead->subtypes;
13230	}
13231    }
13232    /*
13233    * SPEC "The definition of anyType serves as the default type definition
13234    * for element declarations whose XML representation does not specify one."
13235    */
13236    if ((elemDecl->subtypes == NULL) &&
13237	(elemDecl->namedType == NULL) &&
13238	(elemDecl->substGroup == NULL))
13239	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13240}
13241
13242/**
13243 * xmlSchemaResolveUnionMemberTypes:
13244 * @ctxt:  the schema parser context
13245 * @type:  the schema simple type definition
13246 *
13247 * Checks and builds the "member type definitions" property of the union
13248 * simple type. This handles part (1), part (2) is done in
13249 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13250 *
13251 * Returns -1 in case of an internal error, 0 otherwise.
13252 */
13253static int
13254xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13255				 xmlSchemaTypePtr type)
13256{
13257
13258    xmlSchemaTypeLinkPtr link, lastLink, newLink;
13259    xmlSchemaTypePtr memberType;
13260
13261    /*
13262    * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13263    * define the explicit members as the type definitions �resolved�
13264    * to by the items in the �actual value� of the memberTypes [attribute],
13265    * if any, followed by the type definitions corresponding to the
13266    * <simpleType>s among the [children] of <union>, if any."
13267    */
13268    /*
13269    * Resolve references.
13270    */
13271    link = type->memberTypes;
13272    lastLink = NULL;
13273    while (link != NULL) {
13274	const xmlChar *name, *nsName;
13275
13276	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13277	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13278
13279	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13280	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13281	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13282		WXS_BASIC_CAST type, type->node, "memberTypes",
13283		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13284	    /*
13285	    * Remove the member type link.
13286	    */
13287	    if (lastLink == NULL)
13288		type->memberTypes = link->next;
13289	    else
13290		lastLink->next = link->next;
13291	    newLink = link;
13292	    link = link->next;
13293	    xmlFree(newLink);
13294	} else {
13295	    link->type = memberType;
13296	    lastLink = link;
13297	    link = link->next;
13298	}
13299    }
13300    /*
13301    * Add local simple types,
13302    */
13303    memberType = type->subtypes;
13304    while (memberType != NULL) {
13305	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13306	if (link == NULL) {
13307	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13308	    return (-1);
13309	}
13310	link->type = memberType;
13311	link->next = NULL;
13312	if (lastLink == NULL)
13313	    type->memberTypes = link;
13314	else
13315	    lastLink->next = link;
13316	lastLink = link;
13317	memberType = memberType->next;
13318    }
13319    return (0);
13320}
13321
13322/**
13323 * xmlSchemaIsDerivedFromBuiltInType:
13324 * @ctxt:  the schema parser context
13325 * @type:  the type definition
13326 * @valType: the value type
13327 *
13328 *
13329 * Returns 1 if the type has the given value type, or
13330 * is derived from such a type.
13331 */
13332static int
13333xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13334{
13335    if (type == NULL)
13336	return (0);
13337    if (WXS_IS_COMPLEX(type))
13338	return (0);
13339    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13340	if (type->builtInType == valType)
13341	    return(1);
13342	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13343	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13344	    return (0);
13345	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346    }
13347    return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13348}
13349
13350#if 0
13351/**
13352 * xmlSchemaIsDerivedFromBuiltInType:
13353 * @ctxt:  the schema parser context
13354 * @type:  the type definition
13355 * @valType: the value type
13356 *
13357 *
13358 * Returns 1 if the type has the given value type, or
13359 * is derived from such a type.
13360 */
13361static int
13362xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13363{
13364    if (type == NULL)
13365	return (0);
13366    if (WXS_IS_COMPLEX(type))
13367	return (0);
13368    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13369	if (type->builtInType == valType)
13370	    return(1);
13371	return (0);
13372    } else
13373	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13374
13375    return (0);
13376}
13377
13378static xmlSchemaTypePtr
13379xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13380{
13381    if (type == NULL)
13382	return (NULL);
13383    if (WXS_IS_COMPLEX(type))
13384	return (NULL);
13385    if (type->type == XML_SCHEMA_TYPE_BASIC)
13386	return(type);
13387    return(xmlSchemaQueryBuiltInType(type->subtypes));
13388}
13389#endif
13390
13391/**
13392 * xmlSchemaGetPrimitiveType:
13393 * @type:  the simpleType definition
13394 *
13395 * Returns the primitive type of the given type or
13396 * NULL in case of error.
13397 */
13398static xmlSchemaTypePtr
13399xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13400{
13401
13402    while (type != NULL) {
13403	/*
13404	* Note that anySimpleType is actually not a primitive type
13405	* but we need that here.
13406	*/
13407	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13408	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13409	    return (type);
13410	type = type->baseType;
13411    }
13412
13413    return (NULL);
13414}
13415
13416#if 0
13417/**
13418 * xmlSchemaGetBuiltInTypeAncestor:
13419 * @type:  the simpleType definition
13420 *
13421 * Returns the primitive type of the given type or
13422 * NULL in case of error.
13423 */
13424static xmlSchemaTypePtr
13425xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13426{
13427    if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13428	return (0);
13429    while (type != NULL) {
13430	if (type->type == XML_SCHEMA_TYPE_BASIC)
13431	    return (type);
13432	type = type->baseType;
13433    }
13434
13435    return (NULL);
13436}
13437#endif
13438
13439/**
13440 * xmlSchemaCloneWildcardNsConstraints:
13441 * @ctxt:  the schema parser context
13442 * @dest:  the destination wildcard
13443 * @source: the source wildcard
13444 *
13445 * Clones the namespace constraints of source
13446 * and assignes them to dest.
13447 * Returns -1 on internal error, 0 otherwise.
13448 */
13449static int
13450xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13451				    xmlSchemaWildcardPtr dest,
13452				    xmlSchemaWildcardPtr source)
13453{
13454    xmlSchemaWildcardNsPtr cur, tmp, last;
13455
13456    if ((source == NULL) || (dest == NULL))
13457	return(-1);
13458    dest->any = source->any;
13459    cur = source->nsSet;
13460    last = NULL;
13461    while (cur != NULL) {
13462	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13463	if (tmp == NULL)
13464	    return(-1);
13465	tmp->value = cur->value;
13466	if (last == NULL)
13467	    dest->nsSet = tmp;
13468	else
13469	    last->next = tmp;
13470	last = tmp;
13471	cur = cur->next;
13472    }
13473    if (dest->negNsSet != NULL)
13474	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13475    if (source->negNsSet != NULL) {
13476	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13477	if (dest->negNsSet == NULL)
13478	    return(-1);
13479	dest->negNsSet->value = source->negNsSet->value;
13480    } else
13481	dest->negNsSet = NULL;
13482    return(0);
13483}
13484
13485/**
13486 * xmlSchemaUnionWildcards:
13487 * @ctxt:  the schema parser context
13488 * @completeWild:  the first wildcard
13489 * @curWild: the second wildcard
13490 *
13491 * Unions the namespace constraints of the given wildcards.
13492 * @completeWild will hold the resulting union.
13493 * Returns a positive error code on failure, -1 in case of an
13494 * internal error, 0 otherwise.
13495 */
13496static int
13497xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13498			    xmlSchemaWildcardPtr completeWild,
13499			    xmlSchemaWildcardPtr curWild)
13500{
13501    xmlSchemaWildcardNsPtr cur, curB, tmp;
13502
13503    /*
13504    * 1 If O1 and O2 are the same value, then that value must be the
13505    * value.
13506    */
13507    if ((completeWild->any == curWild->any) &&
13508	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13509	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13510
13511	if ((completeWild->negNsSet == NULL) ||
13512	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13513
13514	    if (completeWild->nsSet != NULL) {
13515		int found = 0;
13516
13517		/*
13518		* Check equality of sets.
13519		*/
13520		cur = completeWild->nsSet;
13521		while (cur != NULL) {
13522		    found = 0;
13523		    curB = curWild->nsSet;
13524		    while (curB != NULL) {
13525			if (cur->value == curB->value) {
13526			    found = 1;
13527			    break;
13528			}
13529			curB = curB->next;
13530		    }
13531		    if (!found)
13532			break;
13533		    cur = cur->next;
13534		}
13535		if (found)
13536		    return(0);
13537	    } else
13538		return(0);
13539	}
13540    }
13541    /*
13542    * 2 If either O1 or O2 is any, then any must be the value
13543    */
13544    if (completeWild->any != curWild->any) {
13545	if (completeWild->any == 0) {
13546	    completeWild->any = 1;
13547	    if (completeWild->nsSet != NULL) {
13548		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13549		completeWild->nsSet = NULL;
13550	    }
13551	    if (completeWild->negNsSet != NULL) {
13552		xmlFree(completeWild->negNsSet);
13553		completeWild->negNsSet = NULL;
13554	    }
13555	}
13556	return (0);
13557    }
13558    /*
13559    * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13560    * then the union of those sets must be the value.
13561    */
13562    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13563	int found;
13564	xmlSchemaWildcardNsPtr start;
13565
13566	cur = curWild->nsSet;
13567	start = completeWild->nsSet;
13568	while (cur != NULL) {
13569	    found = 0;
13570	    curB = start;
13571	    while (curB != NULL) {
13572		if (cur->value == curB->value) {
13573		    found = 1;
13574		    break;
13575		}
13576		curB = curB->next;
13577	    }
13578	    if (!found) {
13579		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13580		if (tmp == NULL)
13581		    return (-1);
13582		tmp->value = cur->value;
13583		tmp->next = completeWild->nsSet;
13584		completeWild->nsSet = tmp;
13585	    }
13586	    cur = cur->next;
13587	}
13588
13589	return(0);
13590    }
13591    /*
13592    * 4 If the two are negations of different values (namespace names
13593    * or �absent�), then a pair of not and �absent� must be the value.
13594    */
13595    if ((completeWild->negNsSet != NULL) &&
13596	(curWild->negNsSet != NULL) &&
13597	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13598	completeWild->negNsSet->value = NULL;
13599
13600	return(0);
13601    }
13602    /*
13603     * 5.
13604     */
13605    if (((completeWild->negNsSet != NULL) &&
13606	(completeWild->negNsSet->value != NULL) &&
13607	(curWild->nsSet != NULL)) ||
13608	((curWild->negNsSet != NULL) &&
13609	(curWild->negNsSet->value != NULL) &&
13610	(completeWild->nsSet != NULL))) {
13611
13612	int nsFound, absentFound = 0;
13613
13614	if (completeWild->nsSet != NULL) {
13615	    cur = completeWild->nsSet;
13616	    curB = curWild->negNsSet;
13617	} else {
13618	    cur = curWild->nsSet;
13619	    curB = completeWild->negNsSet;
13620	}
13621	nsFound = 0;
13622	while (cur != NULL) {
13623	    if (cur->value == NULL)
13624		absentFound = 1;
13625	    else if (cur->value == curB->value)
13626		nsFound = 1;
13627	    if (nsFound && absentFound)
13628		break;
13629	    cur = cur->next;
13630	}
13631
13632	if (nsFound && absentFound) {
13633	    /*
13634	    * 5.1 If the set S includes both the negated namespace
13635	    * name and �absent�, then any must be the value.
13636	    */
13637	    completeWild->any = 1;
13638	    if (completeWild->nsSet != NULL) {
13639		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13640		completeWild->nsSet = NULL;
13641	    }
13642	    if (completeWild->negNsSet != NULL) {
13643		xmlFree(completeWild->negNsSet);
13644		completeWild->negNsSet = NULL;
13645	    }
13646	} else if (nsFound && (!absentFound)) {
13647	    /*
13648	    * 5.2 If the set S includes the negated namespace name
13649	    * but not �absent�, then a pair of not and �absent� must
13650	    * be the value.
13651	    */
13652	    if (completeWild->nsSet != NULL) {
13653		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13654		completeWild->nsSet = NULL;
13655	    }
13656	    if (completeWild->negNsSet == NULL) {
13657		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13658		if (completeWild->negNsSet == NULL)
13659		    return (-1);
13660	    }
13661	    completeWild->negNsSet->value = NULL;
13662	} else if ((!nsFound) && absentFound) {
13663	    /*
13664	    * 5.3 If the set S includes �absent� but not the negated
13665	    * namespace name, then the union is not expressible.
13666	    */
13667	    xmlSchemaPErr(ctxt, completeWild->node,
13668		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13669		"The union of the wilcard is not expressible.\n",
13670		NULL, NULL);
13671	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13672	} else if ((!nsFound) && (!absentFound)) {
13673	    /*
13674	    * 5.4 If the set S does not include either the negated namespace
13675	    * name or �absent�, then whichever of O1 or O2 is a pair of not
13676	    * and a namespace name must be the value.
13677	    */
13678	    if (completeWild->negNsSet == NULL) {
13679		if (completeWild->nsSet != NULL) {
13680		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13681		    completeWild->nsSet = NULL;
13682		}
13683		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13684		if (completeWild->negNsSet == NULL)
13685		    return (-1);
13686		completeWild->negNsSet->value = curWild->negNsSet->value;
13687	    }
13688	}
13689	return (0);
13690    }
13691    /*
13692     * 6.
13693     */
13694    if (((completeWild->negNsSet != NULL) &&
13695	(completeWild->negNsSet->value == NULL) &&
13696	(curWild->nsSet != NULL)) ||
13697	((curWild->negNsSet != NULL) &&
13698	(curWild->negNsSet->value == NULL) &&
13699	(completeWild->nsSet != NULL))) {
13700
13701	if (completeWild->nsSet != NULL) {
13702	    cur = completeWild->nsSet;
13703	} else {
13704	    cur = curWild->nsSet;
13705	}
13706	while (cur != NULL) {
13707	    if (cur->value == NULL) {
13708		/*
13709		* 6.1 If the set S includes �absent�, then any must be the
13710		* value.
13711		*/
13712		completeWild->any = 1;
13713		if (completeWild->nsSet != NULL) {
13714		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13715		    completeWild->nsSet = NULL;
13716		}
13717		if (completeWild->negNsSet != NULL) {
13718		    xmlFree(completeWild->negNsSet);
13719		    completeWild->negNsSet = NULL;
13720		}
13721		return (0);
13722	    }
13723	    cur = cur->next;
13724	}
13725	if (completeWild->negNsSet == NULL) {
13726	    /*
13727	    * 6.2 If the set S does not include �absent�, then a pair of not
13728	    * and �absent� must be the value.
13729	    */
13730	    if (completeWild->nsSet != NULL) {
13731		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13732		completeWild->nsSet = NULL;
13733	    }
13734	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13735	    if (completeWild->negNsSet == NULL)
13736		return (-1);
13737	    completeWild->negNsSet->value = NULL;
13738	}
13739	return (0);
13740    }
13741    return (0);
13742
13743}
13744
13745/**
13746 * xmlSchemaIntersectWildcards:
13747 * @ctxt:  the schema parser context
13748 * @completeWild:  the first wildcard
13749 * @curWild: the second wildcard
13750 *
13751 * Intersects the namespace constraints of the given wildcards.
13752 * @completeWild will hold the resulting intersection.
13753 * Returns a positive error code on failure, -1 in case of an
13754 * internal error, 0 otherwise.
13755 */
13756static int
13757xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13758			    xmlSchemaWildcardPtr completeWild,
13759			    xmlSchemaWildcardPtr curWild)
13760{
13761    xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13762
13763    /*
13764    * 1 If O1 and O2 are the same value, then that value must be the
13765    * value.
13766    */
13767    if ((completeWild->any == curWild->any) &&
13768	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13769	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13770
13771	if ((completeWild->negNsSet == NULL) ||
13772	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13773
13774	    if (completeWild->nsSet != NULL) {
13775		int found = 0;
13776
13777		/*
13778		* Check equality of sets.
13779		*/
13780		cur = completeWild->nsSet;
13781		while (cur != NULL) {
13782		    found = 0;
13783		    curB = curWild->nsSet;
13784		    while (curB != NULL) {
13785			if (cur->value == curB->value) {
13786			    found = 1;
13787			    break;
13788			}
13789			curB = curB->next;
13790		    }
13791		    if (!found)
13792			break;
13793		    cur = cur->next;
13794		}
13795		if (found)
13796		    return(0);
13797	    } else
13798		return(0);
13799	}
13800    }
13801    /*
13802    * 2 If either O1 or O2 is any, then the other must be the value.
13803    */
13804    if ((completeWild->any != curWild->any) && (completeWild->any)) {
13805	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13806	    return(-1);
13807	return(0);
13808    }
13809    /*
13810    * 3 If either O1 or O2 is a pair of not and a value (a namespace
13811    * name or �absent�) and the other is a set of (namespace names or
13812    * �absent�), then that set, minus the negated value if it was in
13813    * the set, minus �absent� if it was in the set, must be the value.
13814    */
13815    if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13816	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13817	const xmlChar *neg;
13818
13819	if (completeWild->nsSet == NULL) {
13820	    neg = completeWild->negNsSet->value;
13821	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13822		return(-1);
13823	} else
13824	    neg = curWild->negNsSet->value;
13825	/*
13826	* Remove absent and negated.
13827	*/
13828	prev = NULL;
13829	cur = completeWild->nsSet;
13830	while (cur != NULL) {
13831	    if (cur->value == NULL) {
13832		if (prev == NULL)
13833		    completeWild->nsSet = cur->next;
13834		else
13835		    prev->next = cur->next;
13836		xmlFree(cur);
13837		break;
13838	    }
13839	    prev = cur;
13840	    cur = cur->next;
13841	}
13842	if (neg != NULL) {
13843	    prev = NULL;
13844	    cur = completeWild->nsSet;
13845	    while (cur != NULL) {
13846		if (cur->value == neg) {
13847		    if (prev == NULL)
13848			completeWild->nsSet = cur->next;
13849		    else
13850			prev->next = cur->next;
13851		    xmlFree(cur);
13852		    break;
13853		}
13854		prev = cur;
13855		cur = cur->next;
13856	    }
13857	}
13858
13859	return(0);
13860    }
13861    /*
13862    * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13863    * then the intersection of those sets must be the value.
13864    */
13865    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13866	int found;
13867
13868	cur = completeWild->nsSet;
13869	prev = NULL;
13870	while (cur != NULL) {
13871	    found = 0;
13872	    curB = curWild->nsSet;
13873	    while (curB != NULL) {
13874		if (cur->value == curB->value) {
13875		    found = 1;
13876		    break;
13877		}
13878		curB = curB->next;
13879	    }
13880	    if (!found) {
13881		if (prev == NULL)
13882		    completeWild->nsSet = cur->next;
13883		else
13884		    prev->next = cur->next;
13885		tmp = cur->next;
13886		xmlFree(cur);
13887		cur = tmp;
13888		continue;
13889	    }
13890	    prev = cur;
13891	    cur = cur->next;
13892	}
13893
13894	return(0);
13895    }
13896    /* 5 If the two are negations of different namespace names,
13897    * then the intersection is not expressible
13898    */
13899    if ((completeWild->negNsSet != NULL) &&
13900	(curWild->negNsSet != NULL) &&
13901	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13902	(completeWild->negNsSet->value != NULL) &&
13903	(curWild->negNsSet->value != NULL)) {
13904
13905	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13906	    "The intersection of the wilcard is not expressible.\n",
13907	    NULL, NULL);
13908	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13909    }
13910    /*
13911    * 6 If the one is a negation of a namespace name and the other
13912    * is a negation of �absent�, then the one which is the negation
13913    * of a namespace name must be the value.
13914    */
13915    if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13916	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13917	(completeWild->negNsSet->value == NULL)) {
13918	completeWild->negNsSet->value =  curWild->negNsSet->value;
13919    }
13920    return(0);
13921}
13922
13923/**
13924 * xmlSchemaIsWildcardNsConstraintSubset:
13925 * @ctxt:  the schema parser context
13926 * @sub:  the first wildcard
13927 * @super: the second wildcard
13928 *
13929 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13930 *
13931 * Returns 0 if the namespace constraint of @sub is an intensional
13932 * subset of @super, 1 otherwise.
13933 */
13934static int
13935xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13936			  xmlSchemaWildcardPtr super)
13937{
13938    /*
13939    * 1 super must be any.
13940    */
13941    if (super->any)
13942	return (0);
13943    /*
13944    * 2.1 sub must be a pair of not and a namespace name or �absent�.
13945    * 2.2 super must be a pair of not and the same value.
13946    */
13947    if ((sub->negNsSet != NULL) &&
13948	(super->negNsSet != NULL) &&
13949	(sub->negNsSet->value == super->negNsSet->value))
13950	return (0);
13951    /*
13952    * 3.1 sub must be a set whose members are either namespace names or �absent�.
13953    */
13954    if (sub->nsSet != NULL) {
13955	/*
13956	* 3.2.1 super must be the same set or a superset thereof.
13957	*/
13958	if (super->nsSet != NULL) {
13959	    xmlSchemaWildcardNsPtr cur, curB;
13960	    int found = 0;
13961
13962	    cur = sub->nsSet;
13963	    while (cur != NULL) {
13964		found = 0;
13965		curB = super->nsSet;
13966		while (curB != NULL) {
13967		    if (cur->value == curB->value) {
13968			found = 1;
13969			break;
13970		    }
13971		    curB = curB->next;
13972		}
13973		if (!found)
13974		    return (1);
13975		cur = cur->next;
13976	    }
13977	    if (found)
13978		return (0);
13979	} else if (super->negNsSet != NULL) {
13980	    xmlSchemaWildcardNsPtr cur;
13981	    /*
13982	    * 3.2.2 super must be a pair of not and a namespace name or
13983	    * �absent� and that value must not be in sub's set.
13984	    */
13985	    cur = sub->nsSet;
13986	    while (cur != NULL) {
13987		if (cur->value == super->negNsSet->value)
13988		    return (1);
13989		cur = cur->next;
13990	    }
13991	    return (0);
13992	}
13993    }
13994    return (1);
13995}
13996
13997static int
13998xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13999				     int *fixed,
14000				     const xmlChar **value,
14001				     xmlSchemaValPtr *val)
14002{
14003    *fixed = 0;
14004    *value = NULL;
14005    if (val != 0)
14006	*val = NULL;
14007
14008    if (attruse->defValue != NULL) {
14009	*value = attruse->defValue;
14010	if (val != NULL)
14011	    *val = attruse->defVal;
14012	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14013	    *fixed = 1;
14014	return(1);
14015    } else if ((attruse->attrDecl != NULL) &&
14016	(attruse->attrDecl->defValue != NULL)) {
14017	*value = attruse->attrDecl->defValue;
14018	if (val != NULL)
14019	    *val = attruse->attrDecl->defVal;
14020	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14021	    *fixed = 1;
14022	return(1);
14023    }
14024    return(0);
14025}
14026/**
14027 * xmlSchemaCheckCVCWildcardNamespace:
14028 * @wild:  the wildcard
14029 * @ns:  the namespace
14030 *
14031 * Validation Rule: Wildcard allows Namespace Name
14032 * (cvc-wildcard-namespace)
14033 *
14034 * Returns 0 if the given namespace matches the wildcard,
14035 * 1 otherwise and -1 on API errors.
14036 */
14037static int
14038xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14039				   const xmlChar* ns)
14040{
14041    if (wild == NULL)
14042	return(-1);
14043
14044    if (wild->any)
14045	return(0);
14046    else if (wild->nsSet != NULL) {
14047	xmlSchemaWildcardNsPtr cur;
14048
14049	cur = wild->nsSet;
14050	while (cur != NULL) {
14051	    if (xmlStrEqual(cur->value, ns))
14052		return(0);
14053	    cur = cur->next;
14054	}
14055    } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14056	(!xmlStrEqual(wild->negNsSet->value, ns)))
14057	return(0);
14058
14059    return(1);
14060}
14061
14062#define XML_SCHEMA_ACTION_DERIVE 0
14063#define XML_SCHEMA_ACTION_REDEFINE 1
14064
14065#define WXS_ACTION_STR(a) \
14066((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14067
14068/*
14069* Schema Component Constraint:
14070*   Derivation Valid (Restriction, Complex)
14071*   derivation-ok-restriction (2) - (4)
14072*
14073* ATTENTION:
14074* In XML Schema 1.1 this will be:
14075* Validation Rule:
14076*     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14077*
14078*/
14079static int
14080xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14081				       int action,
14082				       xmlSchemaBasicItemPtr item,
14083				       xmlSchemaBasicItemPtr baseItem,
14084				       xmlSchemaItemListPtr uses,
14085				       xmlSchemaItemListPtr baseUses,
14086				       xmlSchemaWildcardPtr wild,
14087				       xmlSchemaWildcardPtr baseWild)
14088{
14089    xmlSchemaAttributeUsePtr cur = NULL, bcur;
14090    int i, j, found; /* err = 0; */
14091    const xmlChar *bEffValue;
14092    int effFixed;
14093
14094    if (uses != NULL) {
14095	for (i = 0; i < uses->nbItems; i++) {
14096	    cur = uses->items[i];
14097	    found = 0;
14098	    if (baseUses == NULL)
14099		goto not_found;
14100	    for (j = 0; j < baseUses->nbItems; j++) {
14101		bcur = baseUses->items[j];
14102		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14103			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14104		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14105			WXS_ATTRUSE_DECL_TNS(bcur)))
14106		{
14107		    /*
14108		    * (2.1) "If there is an attribute use in the {attribute
14109		    * uses} of the {base type definition} (call this B) whose
14110		    * {attribute declaration} has the same {name} and {target
14111		    * namespace}, then  all of the following must be true:"
14112		    */
14113		    found = 1;
14114
14115		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14116			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14117		    {
14118			xmlChar *str = NULL;
14119			/*
14120			* (2.1.1) "one of the following must be true:"
14121			* (2.1.1.1) "B's {required} is false."
14122			* (2.1.1.2) "R's {required} is true."
14123			*/
14124			xmlSchemaPAttrUseErr4(pctxt,
14125			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14126			    WXS_ITEM_NODE(item), item, cur,
14127			    "The 'optional' attribute use is inconsistent "
14128			    "with the corresponding 'required' attribute use of "
14129			    "the %s %s",
14130			    WXS_ACTION_STR(action),
14131			    xmlSchemaGetComponentDesignation(&str, baseItem),
14132			    NULL, NULL);
14133			FREE_AND_NULL(str);
14134			/* err = pctxt->err; */
14135		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14136			WXS_ATTRUSE_TYPEDEF(cur),
14137			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14138		    {
14139			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14140
14141			/*
14142			* SPEC (2.1.2) "R's {attribute declaration}'s
14143			* {type definition} must be validly derived from
14144			* B's {type definition} given the empty set as
14145			* defined in Type Derivation OK (Simple) (�3.14.6)."
14146			*/
14147			xmlSchemaPAttrUseErr4(pctxt,
14148			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14149			    WXS_ITEM_NODE(item), item, cur,
14150			    "The attribute declaration's %s "
14151			    "is not validly derived from "
14152			    "the corresponding %s of the "
14153			    "attribute declaration in the %s %s",
14154			    xmlSchemaGetComponentDesignation(&strA,
14155				WXS_ATTRUSE_TYPEDEF(cur)),
14156			    xmlSchemaGetComponentDesignation(&strB,
14157				WXS_ATTRUSE_TYPEDEF(bcur)),
14158			    WXS_ACTION_STR(action),
14159			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14160			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14161			FREE_AND_NULL(strA);
14162			FREE_AND_NULL(strB);
14163			FREE_AND_NULL(strC);
14164			/* err = pctxt->err; */
14165		    } else {
14166			/*
14167			* 2.1.3 [Definition:]  Let the effective value
14168			* constraint of an attribute use be its {value
14169			* constraint}, if present, otherwise its {attribute
14170			* declaration}'s {value constraint} .
14171			*/
14172			xmlSchemaGetEffectiveValueConstraint(bcur,
14173			    &effFixed, &bEffValue, NULL);
14174			/*
14175			* 2.1.3 ... one of the following must be true
14176			*
14177			* 2.1.3.1 B's �effective value constraint� is
14178			* �absent� or default.
14179			*/
14180			if ((bEffValue != NULL) &&
14181			    (effFixed == 1)) {
14182			    const xmlChar *rEffValue = NULL;
14183
14184			    xmlSchemaGetEffectiveValueConstraint(bcur,
14185				&effFixed, &rEffValue, NULL);
14186			    /*
14187			    * 2.1.3.2 R's �effective value constraint� is
14188			    * fixed with the same string as B's.
14189			    * MAYBE TODO: Compare the computed values.
14190			    *       Hmm, it says "same string" so
14191			    *       string-equality might really be sufficient.
14192			    */
14193			    if ((effFixed == 0) ||
14194				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14195			    {
14196				xmlChar *str = NULL;
14197
14198				xmlSchemaPAttrUseErr4(pctxt,
14199				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14200				    WXS_ITEM_NODE(item), item, cur,
14201				    "The effective value constraint of the "
14202				    "attribute use is inconsistent with "
14203				    "its correspondent in the %s %s",
14204				    WXS_ACTION_STR(action),
14205				    xmlSchemaGetComponentDesignation(&str,
14206					baseItem),
14207				    NULL, NULL);
14208				FREE_AND_NULL(str);
14209				/* err = pctxt->err; */
14210			    }
14211			}
14212		    }
14213		    break;
14214		}
14215	    }
14216not_found:
14217	    if (!found) {
14218		/*
14219		* (2.2) "otherwise the {base type definition} must have an
14220		* {attribute wildcard} and the {target namespace} of the
14221		* R's {attribute declaration} must be �valid� with respect
14222		* to that wildcard, as defined in Wildcard allows Namespace
14223		* Name (�3.10.4)."
14224		*/
14225		if ((baseWild == NULL) ||
14226		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14227		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14228		{
14229		    xmlChar *str = NULL;
14230
14231		    xmlSchemaPAttrUseErr4(pctxt,
14232			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14233			WXS_ITEM_NODE(item), item, cur,
14234			"Neither a matching attribute use, "
14235			"nor a matching wildcard exists in the %s %s",
14236			WXS_ACTION_STR(action),
14237			xmlSchemaGetComponentDesignation(&str, baseItem),
14238			NULL, NULL);
14239		    FREE_AND_NULL(str);
14240		    /* err = pctxt->err; */
14241		}
14242	    }
14243	}
14244    }
14245    /*
14246    * SPEC derivation-ok-restriction (3):
14247    * (3) "For each attribute use in the {attribute uses} of the {base type
14248    * definition} whose {required} is true, there must be an attribute
14249    * use with an {attribute declaration} with the same {name} and
14250    * {target namespace} as its {attribute declaration} in the {attribute
14251    * uses} of the complex type definition itself whose {required} is true.
14252    */
14253    if (baseUses != NULL) {
14254	for (j = 0; j < baseUses->nbItems; j++) {
14255	    bcur = baseUses->items[j];
14256	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14257		continue;
14258	    found = 0;
14259	    if (uses != NULL) {
14260		for (i = 0; i < uses->nbItems; i++) {
14261		    cur = uses->items[i];
14262		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14263			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14264			(WXS_ATTRUSE_DECL_TNS(cur) ==
14265			WXS_ATTRUSE_DECL_TNS(bcur))) {
14266			found = 1;
14267			break;
14268		    }
14269		}
14270	    }
14271	    if (!found) {
14272		xmlChar *strA = NULL, *strB = NULL;
14273
14274		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14275		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14276		    NULL, item,
14277		    "A matching attribute use for the "
14278		    "'required' %s of the %s %s is missing",
14279		    xmlSchemaGetComponentDesignation(&strA, bcur),
14280		    WXS_ACTION_STR(action),
14281		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14282		    NULL);
14283		FREE_AND_NULL(strA);
14284		FREE_AND_NULL(strB);
14285	    }
14286	}
14287    }
14288    /*
14289    * derivation-ok-restriction (4)
14290    */
14291    if (wild != NULL) {
14292	/*
14293	* (4) "If there is an {attribute wildcard}, all of the
14294	* following must be true:"
14295	*/
14296	if (baseWild == NULL) {
14297	    xmlChar *str = NULL;
14298
14299	    /*
14300	    * (4.1) "The {base type definition} must also have one."
14301	    */
14302	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14303		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14304		NULL, item,
14305		"The %s has an attribute wildcard, "
14306		"but the %s %s '%s' does not have one",
14307		WXS_ITEM_TYPE_NAME(item),
14308		WXS_ACTION_STR(action),
14309		WXS_ITEM_TYPE_NAME(baseItem),
14310		xmlSchemaGetComponentQName(&str, baseItem));
14311	    FREE_AND_NULL(str);
14312	    return(pctxt->err);
14313	} else if ((baseWild->any == 0) &&
14314		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14315	{
14316	    xmlChar *str = NULL;
14317	    /*
14318	    * (4.2) "The complex type definition's {attribute wildcard}'s
14319	    * {namespace constraint} must be a subset of the {base type
14320	    * definition}'s {attribute wildcard}'s {namespace constraint},
14321	    * as defined by Wildcard Subset (�3.10.6)."
14322	    */
14323	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14324		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14325		NULL, item,
14326		"The attribute wildcard is not a valid "
14327		"subset of the wildcard in the %s %s '%s'",
14328		WXS_ACTION_STR(action),
14329		WXS_ITEM_TYPE_NAME(baseItem),
14330		xmlSchemaGetComponentQName(&str, baseItem),
14331		NULL);
14332	    FREE_AND_NULL(str);
14333	    return(pctxt->err);
14334	}
14335	/* 4.3 Unless the {base type definition} is the �ur-type
14336	* definition�, the complex type definition's {attribute
14337	* wildcard}'s {process contents} must be identical to or
14338	* stronger than the {base type definition}'s {attribute
14339	* wildcard}'s {process contents}, where strict is stronger
14340	* than lax is stronger than skip.
14341	*/
14342	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14343	    (wild->processContents < baseWild->processContents)) {
14344	    xmlChar *str = NULL;
14345	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14346		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14347		NULL, baseItem,
14348		"The {process contents} of the attribute wildcard is "
14349		"weaker than the one in the %s %s '%s'",
14350		WXS_ACTION_STR(action),
14351		WXS_ITEM_TYPE_NAME(baseItem),
14352		xmlSchemaGetComponentQName(&str, baseItem),
14353		NULL);
14354	    FREE_AND_NULL(str)
14355		return(pctxt->err);
14356	}
14357    }
14358    return(0);
14359}
14360
14361
14362static int
14363xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14364				  xmlSchemaBasicItemPtr item,
14365				  xmlSchemaWildcardPtr *completeWild,
14366				  xmlSchemaItemListPtr list,
14367				  xmlSchemaItemListPtr prohibs);
14368/**
14369 * xmlSchemaFixupTypeAttributeUses:
14370 * @ctxt:  the schema parser context
14371 * @type:  the complex type definition
14372 *
14373 *
14374 * Builds the wildcard and the attribute uses on the given complex type.
14375 * Returns -1 if an internal error occurs, 0 otherwise.
14376 *
14377 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14378 * strings, so recheck this if we start to hardcode some schemata, since
14379 * they might not be in the same dict.
14380 * NOTE: It is allowed to "extend" the xs:anyType type.
14381 */
14382static int
14383xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14384				  xmlSchemaTypePtr type)
14385{
14386    xmlSchemaTypePtr baseType = NULL;
14387    xmlSchemaAttributeUsePtr use;
14388    xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14389
14390    if (type->baseType == NULL) {
14391	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14392	    "no base type");
14393        return (-1);
14394    }
14395    baseType = type->baseType;
14396    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14397	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14398	    return(-1);
14399
14400    uses = type->attrUses;
14401    baseUses = baseType->attrUses;
14402    /*
14403    * Expand attribute group references. And build the 'complete'
14404    * wildcard, i.e. intersect multiple wildcards.
14405    * Move attribute prohibitions into a separate list.
14406    */
14407    if (uses != NULL) {
14408	if (WXS_IS_RESTRICTION(type)) {
14409	    /*
14410	    * This one will transfer all attr. prohibitions
14411	    * into pctxt->attrProhibs.
14412	    */
14413	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14414		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14415		pctxt->attrProhibs) == -1)
14416	    {
14417		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14418		"failed to expand attributes");
14419	    }
14420	    if (pctxt->attrProhibs->nbItems != 0)
14421		prohibs = pctxt->attrProhibs;
14422	} else {
14423	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14424		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14425		NULL) == -1)
14426	    {
14427		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14428		"failed to expand attributes");
14429	    }
14430	}
14431    }
14432    /*
14433    * Inherit the attribute uses of the base type.
14434    */
14435    if (baseUses != NULL) {
14436	int i, j;
14437	xmlSchemaAttributeUseProhibPtr pro;
14438
14439	if (WXS_IS_RESTRICTION(type)) {
14440	    int usesCount;
14441	    xmlSchemaAttributeUsePtr tmp;
14442
14443	    if (uses != NULL)
14444		usesCount = uses->nbItems;
14445	    else
14446		usesCount = 0;
14447
14448	    /* Restriction. */
14449	    for (i = 0; i < baseUses->nbItems; i++) {
14450		use = baseUses->items[i];
14451		if (prohibs) {
14452		    /*
14453		    * Filter out prohibited uses.
14454		    */
14455		    for (j = 0; j < prohibs->nbItems; j++) {
14456			pro = prohibs->items[j];
14457			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14458			    (WXS_ATTRUSE_DECL_TNS(use) ==
14459				pro->targetNamespace))
14460			{
14461			    goto inherit_next;
14462			}
14463		    }
14464		}
14465		if (usesCount) {
14466		    /*
14467		    * Filter out existing uses.
14468		    */
14469		    for (j = 0; j < usesCount; j++) {
14470			tmp = uses->items[j];
14471			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14472				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14473			    (WXS_ATTRUSE_DECL_TNS(use) ==
14474				WXS_ATTRUSE_DECL_TNS(tmp)))
14475			{
14476			    goto inherit_next;
14477			}
14478		    }
14479		}
14480		if (uses == NULL) {
14481		    type->attrUses = xmlSchemaItemListCreate();
14482		    if (type->attrUses == NULL)
14483			goto exit_failure;
14484		    uses = type->attrUses;
14485		}
14486		xmlSchemaItemListAddSize(uses, 2, use);
14487inherit_next: {}
14488	    }
14489	} else {
14490	    /* Extension. */
14491	    for (i = 0; i < baseUses->nbItems; i++) {
14492		use = baseUses->items[i];
14493		if (uses == NULL) {
14494		    type->attrUses = xmlSchemaItemListCreate();
14495		    if (type->attrUses == NULL)
14496			goto exit_failure;
14497		    uses = type->attrUses;
14498		}
14499		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14500	    }
14501	}
14502    }
14503    /*
14504    * Shrink attr. uses.
14505    */
14506    if (uses) {
14507	if (uses->nbItems == 0) {
14508	    xmlSchemaItemListFree(uses);
14509	    type->attrUses = NULL;
14510	}
14511	/*
14512	* TODO: We could shrink the size of the array
14513	* to fit the actual number of items.
14514	*/
14515    }
14516    /*
14517    * Compute the complete wildcard.
14518    */
14519    if (WXS_IS_EXTENSION(type)) {
14520	if (baseType->attributeWildcard != NULL) {
14521	    /*
14522	    * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14523	    * the appropriate case among the following:"
14524	    */
14525	    if (type->attributeWildcard != NULL) {
14526		/*
14527		* Union the complete wildcard with the base wildcard.
14528		* SPEC {attribute wildcard}
14529		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14530		* and {annotation} are those of the �complete wildcard�,
14531		* and whose {namespace constraint} is the intensional union
14532		* of the {namespace constraint} of the �complete wildcard�
14533		* and of the �base wildcard�, as defined in Attribute
14534		* Wildcard Union (�3.10.6)."
14535		*/
14536		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537		    baseType->attributeWildcard) == -1)
14538		    goto exit_failure;
14539	    } else {
14540		/*
14541		* (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14542		* then the �base wildcard�."
14543		*/
14544		type->attributeWildcard = baseType->attributeWildcard;
14545	    }
14546	} else {
14547	    /*
14548	    * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14549	    * �complete wildcard"
14550	    * NOOP
14551	    */
14552	}
14553    } else {
14554	/*
14555	* SPEC {attribute wildcard}
14556	* (3.1) "If the <restriction> alternative is chosen, then the
14557	* �complete wildcard�;"
14558	* NOOP
14559	*/
14560    }
14561
14562    return (0);
14563
14564exit_failure:
14565    return(-1);
14566}
14567
14568/**
14569 * xmlSchemaTypeFinalContains:
14570 * @schema:  the schema
14571 * @type:  the type definition
14572 * @final: the final
14573 *
14574 * Evaluates if a type definition contains the given "final".
14575 * This does take "finalDefault" into account as well.
14576 *
14577 * Returns 1 if the type does containt the given "final",
14578 * 0 otherwise.
14579 */
14580static int
14581xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14582{
14583    if (type == NULL)
14584	return (0);
14585    if (type->flags & final)
14586	return (1);
14587    else
14588	return (0);
14589}
14590
14591/**
14592 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14593 * @type:  the Union Simple Type
14594 *
14595 * Returns a list of member types of @type if existing,
14596 * returns NULL otherwise.
14597 */
14598static xmlSchemaTypeLinkPtr
14599xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14600{
14601    while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14602	if (type->memberTypes != NULL)
14603	    return (type->memberTypes);
14604	else
14605	    type = type->baseType;
14606    }
14607    return (NULL);
14608}
14609
14610/**
14611 * xmlSchemaGetParticleTotalRangeMin:
14612 * @particle: the particle
14613 *
14614 * Schema Component Constraint: Effective Total Range
14615 * (all and sequence) + (choice)
14616 *
14617 * Returns the minimun Effective Total Range.
14618 */
14619static int
14620xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14621{
14622    if ((particle->children == NULL) ||
14623	(particle->minOccurs == 0))
14624	return (0);
14625    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14626	int min = -1, cur;
14627	xmlSchemaParticlePtr part =
14628	    (xmlSchemaParticlePtr) particle->children->children;
14629
14630	if (part == NULL)
14631	    return (0);
14632	while (part != NULL) {
14633	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14634		(part->children->type == XML_SCHEMA_TYPE_ANY))
14635		cur = part->minOccurs;
14636	    else
14637		cur = xmlSchemaGetParticleTotalRangeMin(part);
14638	    if (cur == 0)
14639		return (0);
14640	    if ((min > cur) || (min == -1))
14641		min = cur;
14642	    part = (xmlSchemaParticlePtr) part->next;
14643	}
14644	return (particle->minOccurs * min);
14645    } else {
14646	/* <all> and <sequence> */
14647	int sum = 0;
14648	xmlSchemaParticlePtr part =
14649	    (xmlSchemaParticlePtr) particle->children->children;
14650
14651	if (part == NULL)
14652	    return (0);
14653	do {
14654	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14655		(part->children->type == XML_SCHEMA_TYPE_ANY))
14656		sum += part->minOccurs;
14657	    else
14658		sum += xmlSchemaGetParticleTotalRangeMin(part);
14659	    part = (xmlSchemaParticlePtr) part->next;
14660	} while (part != NULL);
14661	return (particle->minOccurs * sum);
14662    }
14663}
14664
14665#if 0
14666/**
14667 * xmlSchemaGetParticleTotalRangeMax:
14668 * @particle: the particle
14669 *
14670 * Schema Component Constraint: Effective Total Range
14671 * (all and sequence) + (choice)
14672 *
14673 * Returns the maximum Effective Total Range.
14674 */
14675static int
14676xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14677{
14678    if ((particle->children == NULL) ||
14679	(particle->children->children == NULL))
14680	return (0);
14681    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14682	int max = -1, cur;
14683	xmlSchemaParticlePtr part =
14684	    (xmlSchemaParticlePtr) particle->children->children;
14685
14686	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14687	    if (part->children == NULL)
14688		continue;
14689	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14690		(part->children->type == XML_SCHEMA_TYPE_ANY))
14691		cur = part->maxOccurs;
14692	    else
14693		cur = xmlSchemaGetParticleTotalRangeMax(part);
14694	    if (cur == UNBOUNDED)
14695		return (UNBOUNDED);
14696	    if ((max < cur) || (max == -1))
14697		max = cur;
14698	}
14699	/* TODO: Handle overflows? */
14700	return (particle->maxOccurs * max);
14701    } else {
14702	/* <all> and <sequence> */
14703	int sum = 0, cur;
14704	xmlSchemaParticlePtr part =
14705	    (xmlSchemaParticlePtr) particle->children->children;
14706
14707	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14708	    if (part->children == NULL)
14709		continue;
14710	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14711		(part->children->type == XML_SCHEMA_TYPE_ANY))
14712		cur = part->maxOccurs;
14713	    else
14714		cur = xmlSchemaGetParticleTotalRangeMax(part);
14715	    if (cur == UNBOUNDED)
14716		return (UNBOUNDED);
14717	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14718		return (UNBOUNDED);
14719	    sum += cur;
14720	}
14721	/* TODO: Handle overflows? */
14722	return (particle->maxOccurs * sum);
14723    }
14724}
14725#endif
14726
14727/**
14728 * xmlSchemaIsParticleEmptiable:
14729 * @particle: the particle
14730 *
14731 * Schema Component Constraint: Particle Emptiable
14732 * Checks whether the given particle is emptiable.
14733 *
14734 * Returns 1 if emptiable, 0 otherwise.
14735 */
14736static int
14737xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14738{
14739    /*
14740    * SPEC (1) "Its {min occurs} is 0."
14741    */
14742    if ((particle == NULL) || (particle->minOccurs == 0) ||
14743	(particle->children == NULL))
14744	return (1);
14745    /*
14746    * SPEC (2) "Its {term} is a group and the minimum part of the
14747    * effective total range of that group, [...] is 0."
14748    */
14749    if (WXS_IS_MODEL_GROUP(particle->children)) {
14750	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14751	    return (1);
14752    }
14753    return (0);
14754}
14755
14756/**
14757 * xmlSchemaCheckCOSSTDerivedOK:
14758 * @actxt: a context
14759 * @type:  the derived simple type definition
14760 * @baseType:  the base type definition
14761 * @subset: the subset of ('restriction', ect.)
14762 *
14763 * Schema Component Constraint:
14764 * Type Derivation OK (Simple) (cos-st-derived-OK)
14765 *
14766 * Checks wheter @type can be validly
14767 * derived from @baseType.
14768 *
14769 * Returns 0 on success, an positive error code otherwise.
14770 */
14771static int
14772xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14773			     xmlSchemaTypePtr type,
14774			     xmlSchemaTypePtr baseType,
14775			     int subset)
14776{
14777    /*
14778    * 1 They are the same type definition.
14779    * TODO: The identy check might have to be more complex than this.
14780    */
14781    if (type == baseType)
14782	return (0);
14783    /*
14784    * 2.1 restriction is not in the subset, or in the {final}
14785    * of its own {base type definition};
14786    *
14787    * NOTE that this will be used also via "xsi:type".
14788    *
14789    * TODO: Revise this, it looks strange. How can the "type"
14790    * not be fixed or *in* fixing?
14791    */
14792    if (WXS_IS_TYPE_NOT_FIXED(type))
14793	if (xmlSchemaTypeFixup(type, actxt) == -1)
14794	    return(-1);
14795    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14796	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14797	    return(-1);
14798    if ((subset & SUBSET_RESTRICTION) ||
14799	(xmlSchemaTypeFinalContains(type->baseType,
14800	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14801	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14802    }
14803    /* 2.2 */
14804    if (type->baseType == baseType) {
14805	/*
14806	* 2.2.1 D's �base type definition� is B.
14807	*/
14808	return (0);
14809    }
14810    /*
14811    * 2.2.2 D's �base type definition� is not the �ur-type definition�
14812    * and is validly derived from B given the subset, as defined by this
14813    * constraint.
14814    */
14815    if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14816	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14817	    baseType, subset) == 0)) {
14818	return (0);
14819    }
14820    /*
14821    * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14822    * definition�.
14823    */
14824    if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14825	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14826	return (0);
14827    }
14828    /*
14829    * 2.2.4 B's {variety} is union and D is validly derived from a type
14830    * definition in B's {member type definitions} given the subset, as
14831    * defined by this constraint.
14832    *
14833    * NOTE: This seems not to involve built-in types, since there is no
14834    * built-in Union Simple Type.
14835    */
14836    if (WXS_IS_UNION(baseType)) {
14837	xmlSchemaTypeLinkPtr cur;
14838
14839	cur = baseType->memberTypes;
14840	while (cur != NULL) {
14841	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14842		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14843		    return(-1);
14844	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14845		    type, cur->type, subset) == 0)
14846	    {
14847		/*
14848		* It just has to be validly derived from at least one
14849		* member-type.
14850		*/
14851		return (0);
14852	    }
14853	    cur = cur->next;
14854	}
14855    }
14856    return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14857}
14858
14859/**
14860 * xmlSchemaCheckTypeDefCircularInternal:
14861 * @pctxt:  the schema parser context
14862 * @ctxtType:  the type definition
14863 * @ancestor: an ancestor of @ctxtType
14864 *
14865 * Checks st-props-correct (2) + ct-props-correct (3).
14866 * Circular type definitions are not allowed.
14867 *
14868 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14869 * circular, 0 otherwise.
14870 */
14871static int
14872xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14873			   xmlSchemaTypePtr ctxtType,
14874			   xmlSchemaTypePtr ancestor)
14875{
14876    int ret;
14877
14878    if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14879	return (0);
14880
14881    if (ctxtType == ancestor) {
14882	xmlSchemaPCustomErr(pctxt,
14883	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14884	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14885	    "The definition is circular", NULL);
14886	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14887    }
14888    if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14889	/*
14890	* Avoid inifinite recursion on circular types not yet checked.
14891	*/
14892	return (0);
14893    }
14894    ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14895    ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14896	ancestor->baseType);
14897    ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14898    return (ret);
14899}
14900
14901/**
14902 * xmlSchemaCheckTypeDefCircular:
14903 * @item:  the complex/simple type definition
14904 * @ctxt:  the parser context
14905 * @name:  the name
14906 *
14907 * Checks for circular type definitions.
14908 */
14909static void
14910xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14911			      xmlSchemaParserCtxtPtr ctxt)
14912{
14913    if ((item == NULL) ||
14914	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14915	(item->baseType == NULL))
14916	return;
14917    xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14918	item->baseType);
14919}
14920
14921/*
14922* Simple Type Definition Representation OK (src-simple-type) 4
14923*
14924* "4 Circular union type definition is disallowed. That is, if the
14925* <union> alternative is chosen, there must not be any entries in the
14926* memberTypes [attribute] at any depth which resolve to the component
14927* corresponding to the <simpleType>."
14928*
14929* Note that this should work on the *representation* of a component,
14930* thus assumes any union types in the member types not being yet
14931* substituted. At this stage we need the variety of the types
14932* to be already computed.
14933*/
14934static int
14935xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14936					xmlSchemaTypePtr ctxType,
14937					xmlSchemaTypeLinkPtr members)
14938{
14939    xmlSchemaTypeLinkPtr member;
14940    xmlSchemaTypePtr memberType;
14941
14942    member = members;
14943    while (member != NULL) {
14944	memberType = member->type;
14945	while ((memberType != NULL) &&
14946	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14947	    if (memberType == ctxType) {
14948		xmlSchemaPCustomErr(pctxt,
14949		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14950		    WXS_BASIC_CAST ctxType, NULL,
14951		    "The union type definition is circular", NULL);
14952		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14953	    }
14954	    if ((WXS_IS_UNION(memberType)) &&
14955		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14956	    {
14957		int res;
14958		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14959		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14960		    ctxType,
14961		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14962		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14963		if (res != 0)
14964		    return(res);
14965	    }
14966	    memberType = memberType->baseType;
14967	}
14968	member = member->next;
14969    }
14970    return(0);
14971}
14972
14973static int
14974xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14975				   xmlSchemaTypePtr type)
14976{
14977    if (! WXS_IS_UNION(type))
14978	return(0);
14979    return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14980	type->memberTypes));
14981}
14982
14983/**
14984 * xmlSchemaResolveTypeReferences:
14985 * @item:  the complex/simple type definition
14986 * @ctxt:  the parser context
14987 * @name:  the name
14988 *
14989 * Resolvese type definition references
14990 */
14991static void
14992xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14993			 xmlSchemaParserCtxtPtr ctxt)
14994{
14995    if (typeDef == NULL)
14996	return;
14997
14998    /*
14999    * Resolve the base type.
15000    */
15001    if (typeDef->baseType == NULL) {
15002	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15003	    typeDef->base, typeDef->baseNs);
15004	if (typeDef->baseType == NULL) {
15005	    xmlSchemaPResCompAttrErr(ctxt,
15006		XML_SCHEMAP_SRC_RESOLVE,
15007		WXS_BASIC_CAST typeDef, typeDef->node,
15008		"base", typeDef->base, typeDef->baseNs,
15009		XML_SCHEMA_TYPE_SIMPLE, NULL);
15010	    return;
15011	}
15012    }
15013    if (WXS_IS_SIMPLE(typeDef)) {
15014	if (WXS_IS_UNION(typeDef)) {
15015	    /*
15016	    * Resolve the memberTypes.
15017	    */
15018	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15019	    return;
15020	} else if (WXS_IS_LIST(typeDef)) {
15021	    /*
15022	    * Resolve the itemType.
15023	    */
15024	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15025
15026		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15027		    typeDef->base, typeDef->baseNs);
15028
15029		if ((typeDef->subtypes == NULL) ||
15030		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15031		{
15032		    typeDef->subtypes = NULL;
15033		    xmlSchemaPResCompAttrErr(ctxt,
15034			XML_SCHEMAP_SRC_RESOLVE,
15035			WXS_BASIC_CAST typeDef, typeDef->node,
15036			"itemType", typeDef->base, typeDef->baseNs,
15037			XML_SCHEMA_TYPE_SIMPLE, NULL);
15038		}
15039	    }
15040	    return;
15041	}
15042    }
15043    /*
15044    * The ball of letters below means, that if we have a particle
15045    * which has a QName-helper component as its {term}, we want
15046    * to resolve it...
15047    */
15048    else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15049	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15050	    XML_SCHEMA_TYPE_PARTICLE) &&
15051	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15052	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15053	    XML_SCHEMA_EXTRA_QNAMEREF))
15054    {
15055	xmlSchemaQNameRefPtr ref =
15056	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15057	xmlSchemaModelGroupDefPtr groupDef;
15058
15059	/*
15060	* URGENT TODO: Test this.
15061	*/
15062	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15063	/*
15064	* Resolve the MG definition reference.
15065	*/
15066	groupDef =
15067	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15068		ref->itemType, ref->name, ref->targetNamespace);
15069	if (groupDef == NULL) {
15070	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15071		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15072		"ref", ref->name, ref->targetNamespace, ref->itemType,
15073		NULL);
15074	    /* Remove the particle. */
15075	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15076	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15077	    /* Remove the particle. */
15078	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15079	else {
15080	    /*
15081	    * Assign the MG definition's {model group} to the
15082	    * particle's {term}.
15083	    */
15084	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15085
15086	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15087		/*
15088		* SPEC cos-all-limited (1.2)
15089		* "1.2 the {term} property of a particle with
15090		* {max occurs}=1 which is part of a pair which constitutes
15091		* the {content type} of a complex type definition."
15092		*/
15093		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15094		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15095			/* TODO: error code */
15096			XML_SCHEMAP_COS_ALL_LIMITED,
15097			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15098			"The particle's {max occurs} must be 1, since the "
15099			"reference resolves to an 'all' model group",
15100			NULL, NULL);
15101		}
15102	    }
15103	}
15104    }
15105}
15106
15107
15108
15109/**
15110 * xmlSchemaCheckSTPropsCorrect:
15111 * @ctxt:  the schema parser context
15112 * @type:  the simple type definition
15113 *
15114 * Checks st-props-correct.
15115 *
15116 * Returns 0 if the properties are correct,
15117 * if not, a positive error code and -1 on internal
15118 * errors.
15119 */
15120static int
15121xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15122			     xmlSchemaTypePtr type)
15123{
15124    xmlSchemaTypePtr baseType = type->baseType;
15125    xmlChar *str = NULL;
15126
15127    /* STATE: error funcs converted. */
15128    /*
15129    * Schema Component Constraint: Simple Type Definition Properties Correct
15130    *
15131    * NOTE: This is somehow redundant, since we actually built a simple type
15132    * to have all the needed information; this acts as an self test.
15133    */
15134    /* Base type: If the datatype has been �derived� by �restriction�
15135    * then the Simple Type Definition component from which it is �derived�,
15136    * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15137    */
15138    if (baseType == NULL) {
15139	/*
15140	* TODO: Think about: "modulo the impact of Missing
15141	* Sub-components (�5.3)."
15142	*/
15143	xmlSchemaPCustomErr(ctxt,
15144	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15145	    WXS_BASIC_CAST type, NULL,
15146	    "No base type existent", NULL);
15147	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15148
15149    }
15150    if (! WXS_IS_SIMPLE(baseType)) {
15151	xmlSchemaPCustomErr(ctxt,
15152	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15153	    WXS_BASIC_CAST type, NULL,
15154	    "The base type '%s' is not a simple type",
15155	    xmlSchemaGetComponentQName(&str, baseType));
15156	FREE_AND_NULL(str)
15157	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15158    }
15159    if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15160	 (WXS_IS_RESTRICTION(type) == 0) &&
15161	 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15162	xmlSchemaPCustomErr(ctxt,
15163	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15164	    WXS_BASIC_CAST type, NULL,
15165	    "A type, derived by list or union, must have "
15166	    "the simple ur-type definition as base type, not '%s'",
15167	    xmlSchemaGetComponentQName(&str, baseType));
15168	FREE_AND_NULL(str)
15169	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15170    }
15171    /*
15172    * Variety: One of {atomic, list, union}.
15173    */
15174    if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15175	(! WXS_IS_LIST(type))) {
15176	xmlSchemaPCustomErr(ctxt,
15177	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15178	    WXS_BASIC_CAST type, NULL,
15179	    "The variety is absent", NULL);
15180	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15181    }
15182    /* TODO: Finish this. Hmm, is this finished? */
15183
15184    /*
15185    * 3 The {final} of the {base type definition} must not contain restriction.
15186    */
15187    if (xmlSchemaTypeFinalContains(baseType,
15188	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15189	xmlSchemaPCustomErr(ctxt,
15190	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15191	    WXS_BASIC_CAST type, NULL,
15192	    "The 'final' of its base type '%s' must not contain "
15193	    "'restriction'",
15194	    xmlSchemaGetComponentQName(&str, baseType));
15195	FREE_AND_NULL(str)
15196	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15197    }
15198
15199    /*
15200    * 2 All simple type definitions must be derived ultimately from the �simple
15201    * ur-type definition (so� circular definitions are disallowed). That is, it
15202    * must be possible to reach a built-in primitive datatype or the �simple
15203    * ur-type definition� by repeatedly following the {base type definition}.
15204    *
15205    * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15206    */
15207    return (0);
15208}
15209
15210/**
15211 * xmlSchemaCheckCOSSTRestricts:
15212 * @ctxt:  the schema parser context
15213 * @type:  the simple type definition
15214 *
15215 * Schema Component Constraint:
15216 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15217
15218 * Checks if the given @type (simpleType) is derived validly by restriction.
15219 * STATUS:
15220 *
15221 * Returns -1 on internal errors, 0 if the type is validly derived,
15222 * a positive error code otherwise.
15223 */
15224static int
15225xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15226			     xmlSchemaTypePtr type)
15227{
15228    xmlChar *str = NULL;
15229
15230    if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15231	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15232	    "given type is not a user-derived simpleType");
15233	return (-1);
15234    }
15235
15236    if (WXS_IS_ATOMIC(type)) {
15237	xmlSchemaTypePtr primitive;
15238	/*
15239	* 1.1 The {base type definition} must be an atomic simple
15240	* type definition or a built-in primitive datatype.
15241	*/
15242	if (! WXS_IS_ATOMIC(type->baseType)) {
15243	    xmlSchemaPCustomErr(pctxt,
15244		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15245		WXS_BASIC_CAST type, NULL,
15246		"The base type '%s' is not an atomic simple type",
15247		xmlSchemaGetComponentQName(&str, type->baseType));
15248	    FREE_AND_NULL(str)
15249	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15250	}
15251	/* 1.2 The {final} of the {base type definition} must not contain
15252	* restriction.
15253	*/
15254	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15255	if (xmlSchemaTypeFinalContains(type->baseType,
15256	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15257	    xmlSchemaPCustomErr(pctxt,
15258		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15259		WXS_BASIC_CAST type, NULL,
15260		"The final of its base type '%s' must not contain 'restriction'",
15261		xmlSchemaGetComponentQName(&str, type->baseType));
15262	    FREE_AND_NULL(str)
15263	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15264	}
15265
15266	/*
15267	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15268	* type definition}, as specified in the appropriate subsection of 3.2
15269	* Primitive datatypes.
15270	*/
15271	if (type->facets != NULL) {
15272	    xmlSchemaFacetPtr facet;
15273	    int ok = 1;
15274
15275	    primitive = xmlSchemaGetPrimitiveType(type);
15276	    if (primitive == NULL) {
15277		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15278		    "failed to get primitive type");
15279		return (-1);
15280	    }
15281	    facet = type->facets;
15282	    do {
15283		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15284		    ok = 0;
15285		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15286			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15287			type, primitive, facet);
15288		}
15289		facet = facet->next;
15290	    } while (facet != NULL);
15291	    if (ok == 0)
15292		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15293	}
15294	/*
15295	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15296	* of the {base type definition} (call this BF),then the DF's {value}
15297	* must be a valid restriction of BF's {value} as defined in
15298	* [XML Schemas: Datatypes]."
15299	*
15300	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15301	* xmlSchemaDeriveAndValidateFacets()
15302	*/
15303    } else if (WXS_IS_LIST(type)) {
15304	xmlSchemaTypePtr itemType = NULL;
15305
15306	itemType = type->subtypes;
15307	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15308	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309		"failed to evaluate the item type");
15310	    return (-1);
15311	}
15312	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15313	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15314	/*
15315	* 2.1 The {item type definition} must have a {variety} of atomic or
15316	* union (in which case all the {member type definitions}
15317	* must be atomic).
15318	*/
15319	if ((! WXS_IS_ATOMIC(itemType)) &&
15320	    (! WXS_IS_UNION(itemType))) {
15321	    xmlSchemaPCustomErr(pctxt,
15322		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15323		WXS_BASIC_CAST type, NULL,
15324		"The item type '%s' does not have a variety of atomic or union",
15325		xmlSchemaGetComponentQName(&str, itemType));
15326	    FREE_AND_NULL(str)
15327	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15328	} else if (WXS_IS_UNION(itemType)) {
15329	    xmlSchemaTypeLinkPtr member;
15330
15331	    member = itemType->memberTypes;
15332	    while (member != NULL) {
15333		if (! WXS_IS_ATOMIC(member->type)) {
15334		    xmlSchemaPCustomErr(pctxt,
15335			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15336			WXS_BASIC_CAST type, NULL,
15337			"The item type is a union type, but the "
15338			"member type '%s' of this item type is not atomic",
15339			xmlSchemaGetComponentQName(&str, member->type));
15340		    FREE_AND_NULL(str)
15341		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15342		}
15343		member = member->next;
15344	    }
15345	}
15346
15347	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15348	    xmlSchemaFacetPtr facet;
15349	    /*
15350	    * This is the case if we have: <simpleType><list ..
15351	    */
15352	    /*
15353	    * 2.3.1
15354	    * 2.3.1.1 The {final} of the {item type definition} must not
15355	    * contain list.
15356	    */
15357	    if (xmlSchemaTypeFinalContains(itemType,
15358		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15359		xmlSchemaPCustomErr(pctxt,
15360		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15361		    WXS_BASIC_CAST type, NULL,
15362		    "The final of its item type '%s' must not contain 'list'",
15363		    xmlSchemaGetComponentQName(&str, itemType));
15364		FREE_AND_NULL(str)
15365		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15366	    }
15367	    /*
15368	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15369	    * facet component.
15370	    * OPTIMIZE TODO: the S4S already disallows any facet
15371	    * to be specified.
15372	    */
15373	    if (type->facets != NULL) {
15374		facet = type->facets;
15375		do {
15376		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15377			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15378			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15379			    type, facet);
15380			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15381		    }
15382		    facet = facet->next;
15383		} while (facet != NULL);
15384	    }
15385	    /*
15386	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15387	    * A �list� datatype can be �derived� from an �atomic� datatype
15388	    * whose �lexical space� allows space (such as string or anyURI)or
15389	    * a �union� datatype any of whose {member type definitions}'s
15390	    * �lexical space� allows space.
15391	    */
15392	} else {
15393	    /*
15394	    * This is the case if we have: <simpleType><restriction ...
15395	    * I.e. the variety of "list" is inherited.
15396	    */
15397	    /*
15398	    * 2.3.2
15399	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15400	    */
15401	    if (! WXS_IS_LIST(type->baseType)) {
15402		xmlSchemaPCustomErr(pctxt,
15403		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15404		    WXS_BASIC_CAST type, NULL,
15405		    "The base type '%s' must be a list type",
15406		    xmlSchemaGetComponentQName(&str, type->baseType));
15407		FREE_AND_NULL(str)
15408		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15409	    }
15410	    /*
15411	    * 2.3.2.2 The {final} of the {base type definition} must not
15412	    * contain restriction.
15413	    */
15414	    if (xmlSchemaTypeFinalContains(type->baseType,
15415		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15416		xmlSchemaPCustomErr(pctxt,
15417		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15418		    WXS_BASIC_CAST type, NULL,
15419		    "The 'final' of the base type '%s' must not contain 'restriction'",
15420		    xmlSchemaGetComponentQName(&str, type->baseType));
15421		FREE_AND_NULL(str)
15422		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15423	    }
15424	    /*
15425	    * 2.3.2.3 The {item type definition} must be validly derived
15426	    * from the {base type definition}'s {item type definition} given
15427	    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15428	    */
15429	    {
15430		xmlSchemaTypePtr baseItemType;
15431
15432		baseItemType = type->baseType->subtypes;
15433		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15434		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15435			"failed to eval the item type of a base type");
15436		    return (-1);
15437		}
15438		if ((itemType != baseItemType) &&
15439		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15440			baseItemType, 0) != 0)) {
15441		    xmlChar *strBIT = NULL, *strBT = NULL;
15442		    xmlSchemaPCustomErrExt(pctxt,
15443			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15444			WXS_BASIC_CAST type, NULL,
15445			"The item type '%s' is not validly derived from "
15446			"the item type '%s' of the base type '%s'",
15447			xmlSchemaGetComponentQName(&str, itemType),
15448			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15449			xmlSchemaGetComponentQName(&strBT, type->baseType));
15450
15451		    FREE_AND_NULL(str)
15452		    FREE_AND_NULL(strBIT)
15453		    FREE_AND_NULL(strBT)
15454		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15455		}
15456	    }
15457
15458	    if (type->facets != NULL) {
15459		xmlSchemaFacetPtr facet;
15460		int ok = 1;
15461		/*
15462		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15463		* and enumeration facet components are allowed among the {facets}.
15464		*/
15465		facet = type->facets;
15466		do {
15467		    switch (facet->type) {
15468			case XML_SCHEMA_FACET_LENGTH:
15469			case XML_SCHEMA_FACET_MINLENGTH:
15470			case XML_SCHEMA_FACET_MAXLENGTH:
15471			case XML_SCHEMA_FACET_WHITESPACE:
15472			    /*
15473			    * TODO: 2.5.1.2 List datatypes
15474			    * The value of �whiteSpace� is fixed to the value collapse.
15475			    */
15476			case XML_SCHEMA_FACET_PATTERN:
15477			case XML_SCHEMA_FACET_ENUMERATION:
15478			    break;
15479			default: {
15480			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15481				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15482				type, facet);
15483			    /*
15484			    * We could return, but it's nicer to report all
15485			    * invalid facets.
15486			    */
15487			    ok = 0;
15488			}
15489		    }
15490		    facet = facet->next;
15491		} while (facet != NULL);
15492		if (ok == 0)
15493		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15494		/*
15495		* SPEC (2.3.2.5) (same as 1.3.2)
15496		*
15497		* NOTE (2.3.2.5) This is currently done in
15498		* xmlSchemaDeriveAndValidateFacets()
15499		*/
15500	    }
15501	}
15502    } else if (WXS_IS_UNION(type)) {
15503	/*
15504	* 3.1 The {member type definitions} must all have {variety} of
15505	* atomic or list.
15506	*/
15507	xmlSchemaTypeLinkPtr member;
15508
15509	member = type->memberTypes;
15510	while (member != NULL) {
15511	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15512		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15513
15514	    if ((! WXS_IS_ATOMIC(member->type)) &&
15515		(! WXS_IS_LIST(member->type))) {
15516		xmlSchemaPCustomErr(pctxt,
15517		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15518		    WXS_BASIC_CAST type, NULL,
15519		    "The member type '%s' is neither an atomic, nor a list type",
15520		    xmlSchemaGetComponentQName(&str, member->type));
15521		FREE_AND_NULL(str)
15522		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15523	    }
15524	    member = member->next;
15525	}
15526	/*
15527	* 3.3.1 If the {base type definition} is the �simple ur-type
15528	* definition�
15529	*/
15530	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15531	    /*
15532	    * 3.3.1.1 All of the {member type definitions} must have a
15533	    * {final} which does not contain union.
15534	    */
15535	    member = type->memberTypes;
15536	    while (member != NULL) {
15537		if (xmlSchemaTypeFinalContains(member->type,
15538		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15539		    xmlSchemaPCustomErr(pctxt,
15540			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15541			WXS_BASIC_CAST type, NULL,
15542			"The 'final' of member type '%s' contains 'union'",
15543			xmlSchemaGetComponentQName(&str, member->type));
15544		    FREE_AND_NULL(str)
15545		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15546		}
15547		member = member->next;
15548	    }
15549	    /*
15550	    * 3.3.1.2 The {facets} must be empty.
15551	    */
15552	    if (type->facetSet != NULL) {
15553		xmlSchemaPCustomErr(pctxt,
15554		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15555		    WXS_BASIC_CAST type, NULL,
15556		    "No facets allowed", NULL);
15557		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15558	    }
15559	} else {
15560	    /*
15561	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15562	    * I.e. the variety of "list" is inherited.
15563	    */
15564	    if (! WXS_IS_UNION(type->baseType)) {
15565		xmlSchemaPCustomErr(pctxt,
15566		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15567		    WXS_BASIC_CAST type, NULL,
15568		    "The base type '%s' is not a union type",
15569		    xmlSchemaGetComponentQName(&str, type->baseType));
15570		FREE_AND_NULL(str)
15571		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15572	    }
15573	    /*
15574	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15575	    */
15576	    if (xmlSchemaTypeFinalContains(type->baseType,
15577		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15578		xmlSchemaPCustomErr(pctxt,
15579		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15580		    WXS_BASIC_CAST type, NULL,
15581		    "The 'final' of its base type '%s' must not contain 'restriction'",
15582		    xmlSchemaGetComponentQName(&str, type->baseType));
15583		FREE_AND_NULL(str)
15584		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15585	    }
15586	    /*
15587	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15588	    * derived from the corresponding type definitions in the {base
15589	    * type definition}'s {member type definitions} given the empty set,
15590	    * as defined in Type Derivation OK (Simple) (�3.14.6).
15591	    */
15592	    {
15593		xmlSchemaTypeLinkPtr baseMember;
15594
15595		/*
15596		* OPTIMIZE: if the type is restricting, it has no local defined
15597		* member types and inherits the member types of the base type;
15598		* thus a check for equality can be skipped.
15599		*/
15600		/*
15601		* Even worse: I cannot see a scenario where a restricting
15602		* union simple type can have other member types as the member
15603		* types of it's base type. This check seems not necessary with
15604		* respect to the derivation process in libxml2.
15605		* But necessary if constructing types with an API.
15606		*/
15607		if (type->memberTypes != NULL) {
15608		    member = type->memberTypes;
15609		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15610		    if ((member == NULL) && (baseMember != NULL)) {
15611			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15612			    "different number of member types in base");
15613		    }
15614		    while (member != NULL) {
15615			if (baseMember == NULL) {
15616			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15617			    "different number of member types in base");
15618			} else if ((member->type != baseMember->type) &&
15619			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15620				member->type, baseMember->type, 0) != 0)) {
15621			    xmlChar *strBMT = NULL, *strBT = NULL;
15622
15623			    xmlSchemaPCustomErrExt(pctxt,
15624				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15625				WXS_BASIC_CAST type, NULL,
15626				"The member type %s is not validly "
15627				"derived from its corresponding member "
15628				"type %s of the base type %s",
15629				xmlSchemaGetComponentQName(&str, member->type),
15630				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15631				xmlSchemaGetComponentQName(&strBT, type->baseType));
15632			    FREE_AND_NULL(str)
15633			    FREE_AND_NULL(strBMT)
15634			    FREE_AND_NULL(strBT)
15635			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15636			}
15637			member = member->next;
15638                        if (baseMember != NULL)
15639                            baseMember = baseMember->next;
15640		    }
15641		}
15642	    }
15643	    /*
15644	    * 3.3.2.4 Only pattern and enumeration facet components are
15645	    * allowed among the {facets}.
15646	    */
15647	    if (type->facets != NULL) {
15648		xmlSchemaFacetPtr facet;
15649		int ok = 1;
15650
15651		facet = type->facets;
15652		do {
15653		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15654			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15655			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15656				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15657				type, facet);
15658			ok = 0;
15659		    }
15660		    facet = facet->next;
15661		} while (facet != NULL);
15662		if (ok == 0)
15663		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15664
15665	    }
15666	    /*
15667	    * SPEC (3.3.2.5) (same as 1.3.2)
15668	    *
15669	    * NOTE (3.3.2.5) This is currently done in
15670	    * xmlSchemaDeriveAndValidateFacets()
15671	    */
15672	}
15673    }
15674
15675    return (0);
15676}
15677
15678/**
15679 * xmlSchemaCheckSRCSimpleType:
15680 * @ctxt:  the schema parser context
15681 * @type:  the simple type definition
15682 *
15683 * Checks crc-simple-type constraints.
15684 *
15685 * Returns 0 if the constraints are satisfied,
15686 * if not a positive error code and -1 on internal
15687 * errors.
15688 */
15689#if 0
15690static int
15691xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15692			    xmlSchemaTypePtr type)
15693{
15694    /*
15695    * src-simple-type.1 The corresponding simple type definition, if any,
15696    * must satisfy the conditions set out in Constraints on Simple Type
15697    * Definition Schema Components (�3.14.6).
15698    */
15699    if (WXS_IS_RESTRICTION(type)) {
15700	/*
15701	* src-simple-type.2 "If the <restriction> alternative is chosen,
15702	* either it must have a base [attribute] or a <simpleType> among its
15703	* [children], but not both."
15704	* NOTE: This is checked in the parse function of <restriction>.
15705	*/
15706	/*
15707	*
15708	*/
15709    } else if (WXS_IS_LIST(type)) {
15710	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15711	* an itemType [attribute] or a <simpleType> among its [children],
15712	* but not both."
15713	*
15714	* NOTE: This is checked in the parse function of <list>.
15715	*/
15716    } else if (WXS_IS_UNION(type)) {
15717	/*
15718	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15719	*/
15720    }
15721    return (0);
15722}
15723#endif
15724
15725static int
15726xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15727{
15728   if (ctxt->vctxt == NULL) {
15729	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15730	if (ctxt->vctxt == NULL) {
15731	    xmlSchemaPErr(ctxt, NULL,
15732		XML_SCHEMAP_INTERNAL,
15733		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15734		"failed to create a temp. validation context.\n",
15735		NULL, NULL);
15736	    return (-1);
15737	}
15738	/* TODO: Pass user data. */
15739	xmlSchemaSetValidErrors(ctxt->vctxt,
15740	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15741	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15742	    ctxt->serror, ctxt->errCtxt);
15743    }
15744    return (0);
15745}
15746
15747static int
15748xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15749			     xmlNodePtr node,
15750			     xmlSchemaTypePtr type,
15751			     const xmlChar *value,
15752			     xmlSchemaValPtr *retVal,
15753			     int fireErrors,
15754			     int normalize,
15755			     int isNormalized);
15756
15757/**
15758 * xmlSchemaParseCheckCOSValidDefault:
15759 * @pctxt:  the schema parser context
15760 * @type:  the simple type definition
15761 * @value: the default value
15762 * @node: an optional node (the holder of the value)
15763 *
15764 * Schema Component Constraint: Element Default Valid (Immediate)
15765 * (cos-valid-default)
15766 * This will be used by the parser only. For the validator there's
15767 * an other version.
15768 *
15769 * Returns 0 if the constraints are satisfied,
15770 * if not, a positive error code and -1 on internal
15771 * errors.
15772 */
15773static int
15774xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15775				   xmlNodePtr node,
15776				   xmlSchemaTypePtr type,
15777				   const xmlChar *value,
15778				   xmlSchemaValPtr *val)
15779{
15780    int ret = 0;
15781
15782    /*
15783    * cos-valid-default:
15784    * Schema Component Constraint: Element Default Valid (Immediate)
15785    * For a string to be a valid default with respect to a type
15786    * definition the appropriate case among the following must be true:
15787    */
15788    if WXS_IS_COMPLEX(type) {
15789	/*
15790	* Complex type.
15791	*
15792	* SPEC (2.1) "its {content type} must be a simple type definition
15793	* or mixed."
15794	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15795	* type}'s particle must be �emptiable� as defined by
15796	* Particle Emptiable (�3.9.6)."
15797	*/
15798	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15799	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15800	    /* NOTE that this covers (2.2.2) as well. */
15801	    xmlSchemaPCustomErr(pctxt,
15802		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15803		WXS_BASIC_CAST type, type->node,
15804		"For a string to be a valid default, the type definition "
15805		"must be a simple type or a complex type with mixed content "
15806		"and a particle emptiable", NULL);
15807	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15808	}
15809    }
15810    /*
15811    * 1 If the type definition is a simple type definition, then the string
15812    * must be �valid� with respect to that definition as defined by String
15813    * Valid (�3.14.4).
15814    *
15815    * AND
15816    *
15817    * 2.2.1 If the {content type} is a simple type definition, then the
15818    * string must be �valid� with respect to that simple type definition
15819    * as defined by String Valid (�3.14.4).
15820    */
15821    if (WXS_IS_SIMPLE(type))
15822	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15823	    type, value, val, 1, 1, 0);
15824    else if (WXS_HAS_SIMPLE_CONTENT(type))
15825	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15826	    type->contentTypeDef, value, val, 1, 1, 0);
15827    else
15828	return (ret);
15829
15830    if (ret < 0) {
15831	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15832	    "calling xmlSchemaVCheckCVCSimpleType()");
15833    }
15834
15835    return (ret);
15836}
15837
15838/**
15839 * xmlSchemaCheckCTPropsCorrect:
15840 * @ctxt:  the schema parser context
15841 * @type:  the complex type definition
15842 *
15843 *.(4.6) Constraints on Complex Type Definition Schema Components
15844 * Schema Component Constraint:
15845 * Complex Type Definition Properties Correct (ct-props-correct)
15846 * STATUS: (seems) complete
15847 *
15848 * Returns 0 if the constraints are satisfied, a positive
15849 * error code if not and -1 if an internal error occured.
15850 */
15851static int
15852xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15853			     xmlSchemaTypePtr type)
15854{
15855    /*
15856    * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15857    *
15858    * SPEC (1) "The values of the properties of a complex type definition must
15859    * be as described in the property tableau in The Complex Type Definition
15860    * Schema Component (�3.4.1), modulo the impact of Missing
15861    * Sub-components (�5.3)."
15862    */
15863    if ((type->baseType != NULL) &&
15864	(WXS_IS_SIMPLE(type->baseType)) &&
15865	(WXS_IS_EXTENSION(type) == 0)) {
15866	/*
15867	* SPEC (2) "If the {base type definition} is a simple type definition,
15868	* the {derivation method} must be extension."
15869	*/
15870	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15871	    XML_SCHEMAP_SRC_CT_1,
15872	    NULL, WXS_BASIC_CAST type,
15873	    "If the base type is a simple type, the derivation method must be "
15874	    "'extension'", NULL, NULL);
15875	return (XML_SCHEMAP_SRC_CT_1);
15876    }
15877    /*
15878    * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15879    * definition�. That is, it must be possible to reach the �ur-type
15880    * definition by repeatedly following the {base type definition}."
15881    *
15882    * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15883    */
15884    /*
15885    * NOTE that (4) and (5) need the following:
15886    *   - attribute uses need to be already inherited (apply attr. prohibitions)
15887    *   - attribute group references need to be expanded already
15888    *   - simple types need to be typefixed already
15889    */
15890    if (type->attrUses &&
15891	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15892    {
15893	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15894	xmlSchemaAttributeUsePtr use, tmp;
15895	int i, j, hasId = 0;
15896
15897	for (i = uses->nbItems -1; i >= 0; i--) {
15898	    use = uses->items[i];
15899
15900	    /*
15901	    * SPEC ct-props-correct
15902	    * (4) "Two distinct attribute declarations in the
15903	    * {attribute uses} must not have identical {name}s and
15904	    * {target namespace}s."
15905	    */
15906	    if (i > 0) {
15907		for (j = i -1; j >= 0; j--) {
15908		    tmp = uses->items[j];
15909		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15910			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15911			(WXS_ATTRUSE_DECL_TNS(use) ==
15912			WXS_ATTRUSE_DECL_TNS(tmp)))
15913		    {
15914			xmlChar *str = NULL;
15915
15916			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15917			    XML_SCHEMAP_AG_PROPS_CORRECT,
15918			    NULL, WXS_BASIC_CAST type,
15919			    "Duplicate %s",
15920			    xmlSchemaGetComponentDesignation(&str, use),
15921			    NULL);
15922			FREE_AND_NULL(str);
15923			/*
15924			* Remove the duplicate.
15925			*/
15926			if (xmlSchemaItemListRemove(uses, i) == -1)
15927			    goto exit_failure;
15928			goto next_use;
15929		    }
15930		}
15931	    }
15932	    /*
15933	    * SPEC ct-props-correct
15934	    * (5) "Two distinct attribute declarations in the
15935	    * {attribute uses} must not have {type definition}s which
15936	    * are or are derived from ID."
15937	    */
15938	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15939		if (xmlSchemaIsDerivedFromBuiltInType(
15940		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15941		{
15942		    if (hasId) {
15943			xmlChar *str = NULL;
15944
15945			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15946			    XML_SCHEMAP_AG_PROPS_CORRECT,
15947			    NULL, WXS_BASIC_CAST type,
15948			    "There must not exist more than one attribute "
15949			    "declaration of type 'xs:ID' "
15950			    "(or derived from 'xs:ID'). The %s violates this "
15951			    "constraint",
15952			    xmlSchemaGetComponentDesignation(&str, use),
15953			    NULL);
15954			FREE_AND_NULL(str);
15955			if (xmlSchemaItemListRemove(uses, i) == -1)
15956			    goto exit_failure;
15957		    }
15958
15959		    hasId = 1;
15960		}
15961	    }
15962next_use: {}
15963	}
15964    }
15965    return (0);
15966exit_failure:
15967    return(-1);
15968}
15969
15970static int
15971xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15972		       xmlSchemaTypePtr typeB)
15973{
15974    /*
15975    * TODO: This should implement component-identity
15976    * in the future.
15977    */
15978    if ((typeA == NULL) || (typeB == NULL))
15979	return (0);
15980    return (typeA == typeB);
15981}
15982
15983/**
15984 * xmlSchemaCheckCOSCTDerivedOK:
15985 * @ctxt:  the schema parser context
15986 * @type:  the to-be derived complex type definition
15987 * @baseType:  the base complex type definition
15988 * @set: the given set
15989 *
15990 * Schema Component Constraint:
15991 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15992 *
15993 * STATUS: completed
15994 *
15995 * Returns 0 if the constraints are satisfied, or 1
15996 * if not.
15997 */
15998static int
15999xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16000			     xmlSchemaTypePtr type,
16001			     xmlSchemaTypePtr baseType,
16002			     int set)
16003{
16004    int equal = xmlSchemaAreEqualTypes(type, baseType);
16005    /* TODO: Error codes. */
16006    /*
16007    * SPEC "For a complex type definition (call it D, for derived)
16008    * to be validly derived from a type definition (call this
16009    * B, for base) given a subset of {extension, restriction}
16010    * all of the following must be true:"
16011    */
16012    if (! equal) {
16013	/*
16014	* SPEC (1) "If B and D are not the same type definition, then the
16015	* {derivation method} of D must not be in the subset."
16016	*/
16017	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16018	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16019	    return (1);
16020    } else {
16021	/*
16022	* SPEC (2.1) "B and D must be the same type definition."
16023	*/
16024	return (0);
16025    }
16026    /*
16027    * SPEC (2.2) "B must be D's {base type definition}."
16028    */
16029    if (type->baseType == baseType)
16030	return (0);
16031    /*
16032    * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
16033    * definition�."
16034    */
16035    if (WXS_IS_ANYTYPE(type->baseType))
16036	return (1);
16037
16038    if (WXS_IS_COMPLEX(type->baseType)) {
16039	/*
16040	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16041	* must be validly derived from B given the subset as defined by this
16042	* constraint."
16043	*/
16044	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16045	    baseType, set));
16046    } else {
16047	/*
16048	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16049	* must be validly derived from B given the subset as defined in Type
16050	* Derivation OK (Simple) (�3.14.6).
16051	*/
16052	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16053	    baseType, set));
16054    }
16055}
16056
16057/**
16058 * xmlSchemaCheckCOSDerivedOK:
16059 * @type:  the derived simple type definition
16060 * @baseType:  the base type definition
16061 *
16062 * Calls:
16063 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16064 *
16065 * Checks wheter @type can be validly derived from @baseType.
16066 *
16067 * Returns 0 on success, an positive error code otherwise.
16068 */
16069static int
16070xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16071			   xmlSchemaTypePtr type,
16072			   xmlSchemaTypePtr baseType,
16073			   int set)
16074{
16075    if (WXS_IS_SIMPLE(type))
16076	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16077    else
16078	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16079}
16080
16081/**
16082 * xmlSchemaCheckCOSCTExtends:
16083 * @ctxt:  the schema parser context
16084 * @type:  the complex type definition
16085 *
16086 * (3.4.6) Constraints on Complex Type Definition Schema Components
16087 * Schema Component Constraint:
16088 * Derivation Valid (Extension) (cos-ct-extends)
16089 *
16090 * STATUS:
16091 *   missing:
16092 *     (1.5)
16093 *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16094 *
16095 * Returns 0 if the constraints are satisfied, a positive
16096 * error code if not and -1 if an internal error occured.
16097 */
16098static int
16099xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16100			   xmlSchemaTypePtr type)
16101{
16102    xmlSchemaTypePtr base = type->baseType;
16103    /*
16104    * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16105    * temporarily only.
16106    */
16107    /*
16108    * SPEC (1) "If the {base type definition} is a complex type definition,
16109    * then all of the following must be true:"
16110    */
16111    if (WXS_IS_COMPLEX(base)) {
16112	/*
16113	* SPEC (1.1) "The {final} of the {base type definition} must not
16114	* contain extension."
16115	*/
16116	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16117	    xmlSchemaPCustomErr(ctxt,
16118		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16119		WXS_BASIC_CAST type, NULL,
16120		"The 'final' of the base type definition "
16121		"contains 'extension'", NULL);
16122	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16123	}
16124
16125	/*
16126	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16127	* since they are automatically satisfied through the
16128	* inheriting mechanism.
16129	* Note that even if redefining components, the inheriting mechanism
16130	* is used.
16131	*/
16132#if 0
16133	/*
16134	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16135	* uses}
16136	* of the complex type definition itself, that is, for every attribute
16137	* use in the {attribute uses} of the {base type definition}, there
16138	* must be an attribute use in the {attribute uses} of the complex
16139	* type definition itself whose {attribute declaration} has the same
16140	* {name}, {target namespace} and {type definition} as its attribute
16141	* declaration"
16142	*/
16143	if (base->attrUses != NULL) {
16144	    int i, j, found;
16145	    xmlSchemaAttributeUsePtr use, buse;
16146
16147	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16148		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16149		found = 0;
16150		if (type->attrUses != NULL) {
16151		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16152		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16153		    {
16154			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16155				WXS_ATTRUSE_DECL_NAME(buse)) &&
16156			    (WXS_ATTRUSE_DECL_TNS(use) ==
16157				WXS_ATTRUSE_DECL_TNS(buse)) &&
16158			    (WXS_ATTRUSE_TYPEDEF(use) ==
16159				WXS_ATTRUSE_TYPEDEF(buse))
16160			{
16161			    found = 1;
16162			    break;
16163			}
16164		    }
16165		}
16166		if (! found) {
16167		    xmlChar *str = NULL;
16168
16169		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16170			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16171			NULL, WXS_BASIC_CAST type,
16172			/*
16173			* TODO: The report does not indicate that also the
16174			* type needs to be the same.
16175			*/
16176			"This type is missing a matching correspondent "
16177			"for its {base type}'s %s in its {attribute uses}",
16178			xmlSchemaGetComponentDesignation(&str,
16179			    buse->children),
16180			NULL);
16181		    FREE_AND_NULL(str)
16182		}
16183	    }
16184	}
16185	/*
16186	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16187	* definition must also have one, and the base type definition's
16188	* {attribute  wildcard}'s {namespace constraint} must be a subset
16189	* of the complex  type definition's {attribute wildcard}'s {namespace
16190	* constraint}, as defined by Wildcard Subset (�3.10.6)."
16191	*/
16192
16193	/*
16194	* MAYBE TODO: Enable if ever needed. But this will be needed only
16195	* if created the type via a schema construction API.
16196	*/
16197	if (base->attributeWildcard != NULL) {
16198	    if (type->attributeWilcard == NULL) {
16199		xmlChar *str = NULL;
16200
16201		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16202		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16203		    NULL, type,
16204		    "The base %s has an attribute wildcard, "
16205		    "but this type is missing an attribute wildcard",
16206		    xmlSchemaGetComponentDesignation(&str, base));
16207		FREE_AND_NULL(str)
16208
16209	    } else if (xmlSchemaCheckCOSNSSubset(
16210		base->attributeWildcard, type->attributeWildcard))
16211	    {
16212		xmlChar *str = NULL;
16213
16214		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16215		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16216		    NULL, type,
16217		    "The attribute wildcard is not a valid "
16218		    "superset of the one in the base %s",
16219		    xmlSchemaGetComponentDesignation(&str, base));
16220		FREE_AND_NULL(str)
16221	    }
16222	}
16223#endif
16224	/*
16225	* SPEC (1.4) "One of the following must be true:"
16226	*/
16227	if ((type->contentTypeDef != NULL) &&
16228	    (type->contentTypeDef == base->contentTypeDef)) {
16229	    /*
16230	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16231	    * and the {content type} of the complex type definition itself
16232	    * must be the same simple type definition"
16233	    * PASS
16234	    */
16235	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16236	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16237	    /*
16238	    * SPEC (1.4.2) "The {content type} of both the {base type
16239	    * definition} and the complex type definition itself must
16240	    * be empty."
16241	    * PASS
16242	    */
16243	} else {
16244	    /*
16245	    * SPEC (1.4.3) "All of the following must be true:"
16246	    */
16247	    if (type->subtypes == NULL) {
16248		/*
16249		* SPEC 1.4.3.1 The {content type} of the complex type
16250		* definition itself must specify a particle.
16251		*/
16252		xmlSchemaPCustomErr(ctxt,
16253		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16254		    WXS_BASIC_CAST type, NULL,
16255		    "The content type must specify a particle", NULL);
16256		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16257	    }
16258	    /*
16259	    * SPEC (1.4.3.2) "One of the following must be true:"
16260	    */
16261	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16262		/*
16263		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16264		* definition} must be empty.
16265		* PASS
16266		*/
16267	    } else {
16268		/*
16269		* SPEC (1.4.3.2.2) "All of the following must be true:"
16270		*/
16271		if ((type->contentType != base->contentType) ||
16272		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16273		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16274		    /*
16275		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16276		    * or both must be element-only."
16277		    */
16278		    xmlSchemaPCustomErr(ctxt,
16279			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16280			WXS_BASIC_CAST type, NULL,
16281			"The content type of both, the type and its base "
16282			"type, must either 'mixed' or 'element-only'", NULL);
16283		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16284		}
16285		/*
16286		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16287		* complex type definition must be a �valid extension�
16288		* of the {base type definition}'s particle, as defined
16289		* in Particle Valid (Extension) (�3.9.6)."
16290		*
16291		* NOTE that we won't check "Particle Valid (Extension)",
16292		* since it is ensured by the derivation process in
16293		* xmlSchemaTypeFixup(). We need to implement this when heading
16294		* for a construction API
16295		* TODO: !! This is needed to be checked if redefining a type !!
16296		*/
16297	    }
16298	    /*
16299	    * URGENT TODO (1.5)
16300	    */
16301	}
16302    } else {
16303	/*
16304	* SPEC (2) "If the {base type definition} is a simple type definition,
16305	* then all of the following must be true:"
16306	*/
16307	if (type->contentTypeDef != base) {
16308	    /*
16309	    * SPEC (2.1) "The {content type} must be the same simple type
16310	    * definition."
16311	    */
16312	    xmlSchemaPCustomErr(ctxt,
16313		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16314		WXS_BASIC_CAST type, NULL,
16315		"The content type must be the simple base type", NULL);
16316	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16317	}
16318	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16319	    /*
16320	    * SPEC (2.2) "The {final} of the {base type definition} must not
16321	    * contain extension"
16322	    * NOTE that this is the same as (1.1).
16323	    */
16324	    xmlSchemaPCustomErr(ctxt,
16325		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16326		WXS_BASIC_CAST type, NULL,
16327		"The 'final' of the base type definition "
16328		"contains 'extension'", NULL);
16329	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16330	}
16331    }
16332    return (0);
16333}
16334
16335/**
16336 * xmlSchemaCheckDerivationOKRestriction:
16337 * @ctxt:  the schema parser context
16338 * @type:  the complex type definition
16339 *
16340 * (3.4.6) Constraints on Complex Type Definition Schema Components
16341 * Schema Component Constraint:
16342 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16343 *
16344 * STATUS:
16345 *   missing:
16346 *     (5.4.2) ???
16347 *
16348 * ATTENTION:
16349 * In XML Schema 1.1 this will be:
16350 * Validation Rule: Checking complex type subsumption
16351 *
16352 * Returns 0 if the constraints are satisfied, a positive
16353 * error code if not and -1 if an internal error occured.
16354 */
16355static int
16356xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16357				      xmlSchemaTypePtr type)
16358{
16359    xmlSchemaTypePtr base;
16360
16361    /*
16362    * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16363    * temporarily only.
16364    */
16365    base = type->baseType;
16366    if (! WXS_IS_COMPLEX(base)) {
16367	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16368	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16369	    type->node, WXS_BASIC_CAST type,
16370	    "The base type must be a complex type", NULL, NULL);
16371	return(ctxt->err);
16372    }
16373    if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16374	/*
16375	* SPEC (1) "The {base type definition} must be a complex type
16376	* definition whose {final} does not contain restriction."
16377	*/
16378	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16379	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16380	    type->node, WXS_BASIC_CAST type,
16381	    "The 'final' of the base type definition "
16382	    "contains 'restriction'", NULL, NULL);
16383	return (ctxt->err);
16384    }
16385    /*
16386    * SPEC (2), (3) and (4)
16387    * Those are handled in a separate function, since the
16388    * same constraints are needed for redefinition of
16389    * attribute groups as well.
16390    */
16391    if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16392	XML_SCHEMA_ACTION_DERIVE,
16393	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16394	type->attrUses, base->attrUses,
16395	type->attributeWildcard,
16396	base->attributeWildcard) == -1)
16397    {
16398	return(-1);
16399    }
16400    /*
16401    * SPEC (5) "One of the following must be true:"
16402    */
16403    if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16404	/*
16405	* SPEC (5.1) "The {base type definition} must be the
16406	* �ur-type definition�."
16407	* PASS
16408	*/
16409    } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16410	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16411	/*
16412	* SPEC (5.2.1) "The {content type} of the complex type definition
16413	* must be a simple type definition"
16414	*
16415	* SPEC (5.2.2) "One of the following must be true:"
16416	*/
16417	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16418	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16419	{
16420	    int err;
16421	    /*
16422	    * SPEC (5.2.2.1) "The {content type} of the {base type
16423	    * definition} must be a simple type definition from which
16424	    * the {content type} is validly derived given the empty
16425	    * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16426	    *
16427	    * ATTENTION TODO: This seems not needed if the type implicitely
16428	    * derived from the base type.
16429	    *
16430	    */
16431	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16432		type->contentTypeDef, base->contentTypeDef, 0);
16433	    if (err != 0) {
16434		xmlChar *strA = NULL, *strB = NULL;
16435
16436		if (err == -1)
16437		    return(-1);
16438		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16439		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16440		    NULL, WXS_BASIC_CAST type,
16441		    "The {content type} %s is not validly derived from the "
16442		    "base type's {content type} %s",
16443		    xmlSchemaGetComponentDesignation(&strA,
16444			type->contentTypeDef),
16445		    xmlSchemaGetComponentDesignation(&strB,
16446			base->contentTypeDef));
16447		FREE_AND_NULL(strA);
16448		FREE_AND_NULL(strB);
16449		return(ctxt->err);
16450	    }
16451	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16452	    (xmlSchemaIsParticleEmptiable(
16453		(xmlSchemaParticlePtr) base->subtypes))) {
16454	    /*
16455	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16456	    * and have a particle which is �emptiable� as defined in
16457	    * Particle Emptiable (�3.9.6)."
16458	    * PASS
16459	    */
16460	} else {
16461	    xmlSchemaPCustomErr(ctxt,
16462		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16463		WXS_BASIC_CAST type, NULL,
16464		"The content type of the base type must be either "
16465		"a simple type or 'mixed' and an emptiable particle", NULL);
16466	    return (ctxt->err);
16467	}
16468    } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16469	/*
16470	* SPEC (5.3.1) "The {content type} of the complex type itself must
16471	* be empty"
16472	*/
16473	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16474	    /*
16475	    * SPEC (5.3.2.1) "The {content type} of the {base type
16476	    * definition} must also be empty."
16477	    * PASS
16478	    */
16479	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16480	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16481	    xmlSchemaIsParticleEmptiable(
16482		(xmlSchemaParticlePtr) base->subtypes)) {
16483	    /*
16484	    * SPEC (5.3.2.2) "The {content type} of the {base type
16485	    * definition} must be elementOnly or mixed and have a particle
16486	    * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16487	    * PASS
16488	    */
16489	} else {
16490	    xmlSchemaPCustomErr(ctxt,
16491		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16492		WXS_BASIC_CAST type, NULL,
16493		"The content type of the base type must be either "
16494		"empty or 'mixed' (or 'elements-only') and an emptiable "
16495		"particle", NULL);
16496	    return (ctxt->err);
16497	}
16498    } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16499	WXS_HAS_MIXED_CONTENT(type)) {
16500	/*
16501	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16502	* itself must be element-only"
16503	*/
16504	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16505	    /*
16506	    * SPEC (5.4.1.2) "The {content type} of the complex type
16507	    * definition itself and of the {base type definition} must be
16508	    * mixed"
16509	    */
16510	    xmlSchemaPCustomErr(ctxt,
16511		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16512		WXS_BASIC_CAST type, NULL,
16513		"If the content type is 'mixed', then the content type of the "
16514		"base type must also be 'mixed'", NULL);
16515	    return (ctxt->err);
16516	}
16517	/*
16518	* SPEC (5.4.2) "The particle of the complex type definition itself
16519	* must be a �valid restriction� of the particle of the {content
16520	* type} of the {base type definition} as defined in Particle Valid
16521	* (Restriction) (�3.9.6).
16522	*
16523	* URGENT TODO: (5.4.2)
16524	*/
16525    } else {
16526	xmlSchemaPCustomErr(ctxt,
16527	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16528	    WXS_BASIC_CAST type, NULL,
16529	    "The type is not a valid restriction of its base type", NULL);
16530	return (ctxt->err);
16531    }
16532    return (0);
16533}
16534
16535/**
16536 * xmlSchemaCheckCTComponent:
16537 * @ctxt:  the schema parser context
16538 * @type:  the complex type definition
16539 *
16540 * (3.4.6) Constraints on Complex Type Definition Schema Components
16541 *
16542 * Returns 0 if the constraints are satisfied, a positive
16543 * error code if not and -1 if an internal error occured.
16544 */
16545static int
16546xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16547			  xmlSchemaTypePtr type)
16548{
16549    int ret;
16550    /*
16551    * Complex Type Definition Properties Correct
16552    */
16553    ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16554    if (ret != 0)
16555	return (ret);
16556    if (WXS_IS_EXTENSION(type))
16557	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16558    else
16559	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16560    return (ret);
16561}
16562
16563/**
16564 * xmlSchemaCheckSRCCT:
16565 * @ctxt:  the schema parser context
16566 * @type:  the complex type definition
16567 *
16568 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16569 * Schema Representation Constraint:
16570 * Complex Type Definition Representation OK (src-ct)
16571 *
16572 * Returns 0 if the constraints are satisfied, a positive
16573 * error code if not and -1 if an internal error occured.
16574 */
16575static int
16576xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16577		    xmlSchemaTypePtr type)
16578{
16579    xmlSchemaTypePtr base;
16580    int ret = 0;
16581
16582    /*
16583    * TODO: Adjust the error codes here, as I used
16584    * XML_SCHEMAP_SRC_CT_1 only yet.
16585    */
16586    base = type->baseType;
16587    if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16588	/*
16589	* 1 If the <complexContent> alternative is chosen, the type definition
16590	* �resolved� to by the �actual value� of the base [attribute]
16591	* must be a complex type definition;
16592	*/
16593	if (! WXS_IS_COMPLEX(base)) {
16594	    xmlChar *str = NULL;
16595	    xmlSchemaPCustomErr(ctxt,
16596		XML_SCHEMAP_SRC_CT_1,
16597		WXS_BASIC_CAST type, type->node,
16598		"If using <complexContent>, the base type is expected to be "
16599		"a complex type. The base type '%s' is a simple type",
16600		xmlSchemaFormatQName(&str, base->targetNamespace,
16601		base->name));
16602	    FREE_AND_NULL(str)
16603	    return (XML_SCHEMAP_SRC_CT_1);
16604	}
16605    } else {
16606	/*
16607	* SPEC
16608	* 2 If the <simpleContent> alternative is chosen, all of the
16609	* following must be true:
16610	* 2.1 The type definition �resolved� to by the �actual value� of the
16611	* base [attribute] must be one of the following:
16612	*/
16613	if (WXS_IS_SIMPLE(base)) {
16614	    if (WXS_IS_EXTENSION(type) == 0) {
16615		xmlChar *str = NULL;
16616		/*
16617		* 2.1.3 only if the <extension> alternative is also
16618		* chosen, a simple type definition.
16619		*/
16620		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16621		xmlSchemaPCustomErr(ctxt,
16622		    XML_SCHEMAP_SRC_CT_1,
16623		    WXS_BASIC_CAST type, NULL,
16624		    "If using <simpleContent> and <restriction>, the base "
16625		    "type must be a complex type. The base type '%s' is "
16626		    "a simple type",
16627		    xmlSchemaFormatQName(&str, base->targetNamespace,
16628			base->name));
16629		FREE_AND_NULL(str)
16630		return (XML_SCHEMAP_SRC_CT_1);
16631	    }
16632	} else {
16633	    /* Base type is a complex type. */
16634	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16635		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16636		/*
16637		* 2.1.1 a complex type definition whose {content type} is a
16638		* simple type definition;
16639		* PASS
16640		*/
16641		if (base->contentTypeDef == NULL) {
16642		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16643			WXS_BASIC_CAST type, NULL,
16644			"Internal error: xmlSchemaCheckSRCCT, "
16645			"'%s', base type has no content type",
16646			type->name);
16647		    return (-1);
16648		}
16649	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16650		(WXS_IS_RESTRICTION(type))) {
16651
16652		/*
16653		* 2.1.2 only if the <restriction> alternative is also
16654		* chosen, a complex type definition whose {content type}
16655		* is mixed and a particle emptiable.
16656		*/
16657		if (! xmlSchemaIsParticleEmptiable(
16658		    (xmlSchemaParticlePtr) base->subtypes)) {
16659		    ret = XML_SCHEMAP_SRC_CT_1;
16660		} else
16661		    /*
16662		    * Attention: at this point the <simpleType> child is in
16663		    * ->contentTypeDef (put there during parsing).
16664		    */
16665		    if (type->contentTypeDef == NULL) {
16666		    xmlChar *str = NULL;
16667		    /*
16668		    * 2.2 If clause 2.1.2 above is satisfied, then there
16669		    * must be a <simpleType> among the [children] of
16670		    * <restriction>.
16671		    */
16672		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16673		    xmlSchemaPCustomErr(ctxt,
16674			XML_SCHEMAP_SRC_CT_1,
16675			WXS_BASIC_CAST type, NULL,
16676			"A <simpleType> is expected among the children "
16677			"of <restriction>, if <simpleContent> is used and "
16678			"the base type '%s' is a complex type",
16679			xmlSchemaFormatQName(&str, base->targetNamespace,
16680			base->name));
16681		    FREE_AND_NULL(str)
16682		    return (XML_SCHEMAP_SRC_CT_1);
16683		}
16684	    } else {
16685		ret = XML_SCHEMAP_SRC_CT_1;
16686	    }
16687	}
16688	if (ret > 0) {
16689	    xmlChar *str = NULL;
16690	    if (WXS_IS_RESTRICTION(type)) {
16691		xmlSchemaPCustomErr(ctxt,
16692		    XML_SCHEMAP_SRC_CT_1,
16693		    WXS_BASIC_CAST type, NULL,
16694		    "If <simpleContent> and <restriction> is used, the "
16695		    "base type must be a simple type or a complex type with "
16696		    "mixed content and particle emptiable. The base type "
16697		    "'%s' is none of those",
16698		    xmlSchemaFormatQName(&str, base->targetNamespace,
16699		    base->name));
16700	    } else {
16701		xmlSchemaPCustomErr(ctxt,
16702		    XML_SCHEMAP_SRC_CT_1,
16703		    WXS_BASIC_CAST type, NULL,
16704		    "If <simpleContent> and <extension> is used, the "
16705		    "base type must be a simple type. The base type '%s' "
16706		    "is a complex type",
16707		    xmlSchemaFormatQName(&str, base->targetNamespace,
16708		    base->name));
16709	    }
16710	    FREE_AND_NULL(str)
16711	}
16712    }
16713    /*
16714    * SPEC (3) "The corresponding complex type definition component must
16715    * satisfy the conditions set out in Constraints on Complex Type
16716    * Definition Schema Components (�3.4.6);"
16717    * NOTE (3) will be done in xmlSchemaTypeFixup().
16718    */
16719    /*
16720    * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16721    * above for {attribute wildcard} is satisfied, the intensional
16722    * intersection must be expressible, as defined in Attribute Wildcard
16723    * Intersection (�3.10.6).
16724    * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16725    */
16726    return (ret);
16727}
16728
16729#ifdef ENABLE_PARTICLE_RESTRICTION
16730/**
16731 * xmlSchemaCheckParticleRangeOK:
16732 * @ctxt:  the schema parser context
16733 * @type:  the complex type definition
16734 *
16735 * (3.9.6) Constraints on Particle Schema Components
16736 * Schema Component Constraint:
16737 * Occurrence Range OK (range-ok)
16738 *
16739 * STATUS: complete
16740 *
16741 * Returns 0 if the constraints are satisfied, a positive
16742 * error code if not and -1 if an internal error occured.
16743 */
16744static int
16745xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16746			      int bmin, int bmax)
16747{
16748    if (rmin < bmin)
16749	return (1);
16750    if ((bmax != UNBOUNDED) &&
16751	(rmax > bmax))
16752	return (1);
16753    return (0);
16754}
16755
16756/**
16757 * xmlSchemaCheckRCaseNameAndTypeOK:
16758 * @ctxt:  the schema parser context
16759 * @r: the restricting element declaration particle
16760 * @b: the base element declaration particle
16761 *
16762 * (3.9.6) Constraints on Particle Schema Components
16763 * Schema Component Constraint:
16764 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16765 * (rcase-NameAndTypeOK)
16766 *
16767 * STATUS:
16768 *   MISSING (3.2.3)
16769 *   CLARIFY: (3.2.2)
16770 *
16771 * Returns 0 if the constraints are satisfied, a positive
16772 * error code if not and -1 if an internal error occured.
16773 */
16774static int
16775xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16776				 xmlSchemaParticlePtr r,
16777				 xmlSchemaParticlePtr b)
16778{
16779    xmlSchemaElementPtr elemR, elemB;
16780
16781    /* TODO: Error codes (rcase-NameAndTypeOK). */
16782    elemR = (xmlSchemaElementPtr) r->children;
16783    elemB = (xmlSchemaElementPtr) b->children;
16784    /*
16785    * SPEC (1) "The declarations' {name}s and {target namespace}s are
16786    * the same."
16787    */
16788    if ((elemR != elemB) &&
16789	((! xmlStrEqual(elemR->name, elemB->name)) ||
16790	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16791	return (1);
16792    /*
16793    * SPEC (2) "R's occurrence range is a valid restriction of B's
16794    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16795    */
16796    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16797	    b->minOccurs, b->maxOccurs) != 0)
16798	return (1);
16799    /*
16800    * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16801    * {scope} are global."
16802    */
16803    if (elemR == elemB)
16804	return (0);
16805    /*
16806    * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16807    */
16808    if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16809	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16810	 return (1);
16811    /*
16812    * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16813    * or is not fixed, or R's declaration's {value constraint} is fixed
16814    * with the same value."
16815    */
16816    if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16817	((elemR->value == NULL) ||
16818	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16819	 /* TODO: Equality of the initial value or normalized or canonical? */
16820	 (! xmlStrEqual(elemR->value, elemB->value))))
16821	 return (1);
16822    /*
16823    * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16824    * definitions} is a subset of B's declaration's {identity-constraint
16825    * definitions}, if any."
16826    */
16827    if (elemB->idcs != NULL) {
16828	/* TODO */
16829    }
16830    /*
16831    * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16832    * superset of B's declaration's {disallowed substitutions}."
16833    */
16834    if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16835	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16836	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16837	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16838	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16839	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16840	 return (1);
16841    /*
16842    * SPEC (3.2.5) "R's {type definition} is validly derived given
16843    * {extension, list, union} from B's {type definition}"
16844    *
16845    * BADSPEC TODO: What's the point of adding "list" and "union" to the
16846    * set, if the corresponding constraints handle "restriction" and
16847    * "extension" only?
16848    *
16849    */
16850    {
16851	int set = 0;
16852
16853	set |= SUBSET_EXTENSION;
16854	set |= SUBSET_LIST;
16855	set |= SUBSET_UNION;
16856	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16857	    elemB->subtypes, set) != 0)
16858	    return (1);
16859    }
16860    return (0);
16861}
16862
16863/**
16864 * xmlSchemaCheckRCaseNSCompat:
16865 * @ctxt:  the schema parser context
16866 * @r: the restricting element declaration particle
16867 * @b: the base wildcard particle
16868 *
16869 * (3.9.6) Constraints on Particle Schema Components
16870 * Schema Component Constraint:
16871 * Particle Derivation OK (Elt:Any -- NSCompat)
16872 * (rcase-NSCompat)
16873 *
16874 * STATUS: complete
16875 *
16876 * Returns 0 if the constraints are satisfied, a positive
16877 * error code if not and -1 if an internal error occured.
16878 */
16879static int
16880xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16881			    xmlSchemaParticlePtr r,
16882			    xmlSchemaParticlePtr b)
16883{
16884    /* TODO:Error codes (rcase-NSCompat). */
16885    /*
16886    * SPEC "For an element declaration particle to be a �valid restriction�
16887    * of a wildcard particle all of the following must be true:"
16888    *
16889    * SPEC (1) "The element declaration's {target namespace} is �valid�
16890    * with respect to the wildcard's {namespace constraint} as defined by
16891    * Wildcard allows Namespace Name (�3.10.4)."
16892    */
16893    if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16894	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16895	return (1);
16896    /*
16897    * SPEC (2) "R's occurrence range is a valid restriction of B's
16898    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16899    */
16900    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16901	    b->minOccurs, b->maxOccurs) != 0)
16902	return (1);
16903
16904    return (0);
16905}
16906
16907/**
16908 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16909 * @ctxt:  the schema parser context
16910 * @r: the restricting element declaration particle
16911 * @b: the base model group particle
16912 *
16913 * (3.9.6) Constraints on Particle Schema Components
16914 * Schema Component Constraint:
16915 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16916 * (rcase-RecurseAsIfGroup)
16917 *
16918 * STATUS: TODO
16919 *
16920 * Returns 0 if the constraints are satisfied, a positive
16921 * error code if not and -1 if an internal error occured.
16922 */
16923static int
16924xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16925				    xmlSchemaParticlePtr r,
16926				    xmlSchemaParticlePtr b)
16927{
16928    /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16929    TODO
16930    return (0);
16931}
16932
16933/**
16934 * xmlSchemaCheckRCaseNSSubset:
16935 * @ctxt:  the schema parser context
16936 * @r: the restricting wildcard particle
16937 * @b: the base wildcard particle
16938 *
16939 * (3.9.6) Constraints on Particle Schema Components
16940 * Schema Component Constraint:
16941 * Particle Derivation OK (Any:Any -- NSSubset)
16942 * (rcase-NSSubset)
16943 *
16944 * STATUS: complete
16945 *
16946 * Returns 0 if the constraints are satisfied, a positive
16947 * error code if not and -1 if an internal error occured.
16948 */
16949static int
16950xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16951				    xmlSchemaParticlePtr r,
16952				    xmlSchemaParticlePtr b,
16953				    int isAnyTypeBase)
16954{
16955    /* TODO: Error codes (rcase-NSSubset). */
16956    /*
16957    * SPEC (1) "R's occurrence range is a valid restriction of B's
16958    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16959    */
16960    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16961	    b->minOccurs, b->maxOccurs))
16962	return (1);
16963    /*
16964    * SPEC (2) "R's {namespace constraint} must be an intensional subset
16965    * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16966    */
16967    if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16968	(xmlSchemaWildcardPtr) b->children))
16969	return (1);
16970    /*
16971    * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16972    * definition�, R's {process contents} must be identical to or stronger
16973    * than B's {process contents}, where strict is stronger than lax is
16974    * stronger than skip."
16975    */
16976    if (! isAnyTypeBase) {
16977	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16978	    ((xmlSchemaWildcardPtr) b->children)->processContents)
16979	    return (1);
16980    }
16981
16982    return (0);
16983}
16984
16985/**
16986 * xmlSchemaCheckCOSParticleRestrict:
16987 * @ctxt:  the schema parser context
16988 * @type:  the complex type definition
16989 *
16990 * (3.9.6) Constraints on Particle Schema Components
16991 * Schema Component Constraint:
16992 * Particle Valid (Restriction) (cos-particle-restrict)
16993 *
16994 * STATUS: TODO
16995 *
16996 * Returns 0 if the constraints are satisfied, a positive
16997 * error code if not and -1 if an internal error occured.
16998 */
16999static int
17000xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17001				  xmlSchemaParticlePtr r,
17002				  xmlSchemaParticlePtr b)
17003{
17004    int ret = 0;
17005
17006    /*part = WXS_TYPE_PARTICLE(type);
17007    basePart = WXS_TYPE_PARTICLE(base);
17008    */
17009
17010    TODO
17011
17012    /*
17013    * SPEC (1) "They are the same particle."
17014    */
17015    if (r == b)
17016	return (0);
17017
17018
17019    return (0);
17020}
17021
17022#if 0
17023/**
17024 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17025 * @ctxt:  the schema parser context
17026 * @r: the model group particle
17027 * @b: the base wildcard particle
17028 *
17029 * (3.9.6) Constraints on Particle Schema Components
17030 * Schema Component Constraint:
17031 * Particle Derivation OK (All/Choice/Sequence:Any --
17032 *                         NSRecurseCheckCardinality)
17033 * (rcase-NSRecurseCheckCardinality)
17034 *
17035 * STATUS: TODO: subst-groups
17036 *
17037 * Returns 0 if the constraints are satisfied, a positive
17038 * error code if not and -1 if an internal error occured.
17039 */
17040static int
17041xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17042					     xmlSchemaParticlePtr r,
17043					     xmlSchemaParticlePtr b)
17044{
17045    xmlSchemaParticlePtr part;
17046    /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17047    if ((r->children == NULL) || (r->children->children == NULL))
17048	return (-1);
17049    /*
17050    * SPEC "For a group particle to be a �valid restriction� of a
17051    * wildcard particle..."
17052    *
17053    * SPEC (1) "Every member of the {particles} of the group is a �valid
17054    * restriction� of the wildcard as defined by
17055    * Particle Valid (Restriction) (�3.9.6)."
17056    */
17057    part = (xmlSchemaParticlePtr) r->children->children;
17058    do {
17059	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17060	    return (1);
17061	part = (xmlSchemaParticlePtr) part->next;
17062    } while (part != NULL);
17063    /*
17064    * SPEC (2) "The effective total range of the group [...] is a
17065    * valid restriction of B's occurrence range as defined by
17066    * Occurrence Range OK (�3.9.6)."
17067    */
17068    if (xmlSchemaCheckParticleRangeOK(
17069	    xmlSchemaGetParticleTotalRangeMin(r),
17070	    xmlSchemaGetParticleTotalRangeMax(r),
17071	    b->minOccurs, b->maxOccurs) != 0)
17072	return (1);
17073    return (0);
17074}
17075#endif
17076
17077/**
17078 * xmlSchemaCheckRCaseRecurse:
17079 * @ctxt:  the schema parser context
17080 * @r: the <all> or <sequence> model group particle
17081 * @b: the base <all> or <sequence> model group particle
17082 *
17083 * (3.9.6) Constraints on Particle Schema Components
17084 * Schema Component Constraint:
17085 * Particle Derivation OK (All:All,Sequence:Sequence --
17086                           Recurse)
17087 * (rcase-Recurse)
17088 *
17089 * STATUS:  ?
17090 * TODO: subst-groups
17091 *
17092 * Returns 0 if the constraints are satisfied, a positive
17093 * error code if not and -1 if an internal error occured.
17094 */
17095static int
17096xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17097			   xmlSchemaParticlePtr r,
17098			   xmlSchemaParticlePtr b)
17099{
17100    /* xmlSchemaParticlePtr part; */
17101    /* TODO: Error codes (rcase-Recurse). */
17102    if ((r->children == NULL) || (b->children == NULL) ||
17103	(r->children->type != b->children->type))
17104	return (-1);
17105    /*
17106    * SPEC "For an all or sequence group particle to be a �valid
17107    * restriction� of another group particle with the same {compositor}..."
17108    *
17109    * SPEC (1) "R's occurrence range is a valid restriction of B's
17110    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17111    */
17112    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17113	    b->minOccurs, b->maxOccurs))
17114	return (1);
17115
17116
17117    return (0);
17118}
17119
17120#endif
17121
17122#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17123    xmlSchemaPCustomErrExt(pctxt,      \
17124	XML_SCHEMAP_INVALID_FACET_VALUE, \
17125	WXS_BASIC_CAST fac1, fac1->node, \
17126	"It is an error for both '%s' and '%s' to be specified on the "\
17127	"same type definition", \
17128	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17129	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17130
17131#define FACET_RESTR_ERR(fac1, msg) \
17132    xmlSchemaPCustomErr(pctxt,      \
17133	XML_SCHEMAP_INVALID_FACET_VALUE, \
17134	WXS_BASIC_CAST fac1, fac1->node, \
17135	msg, NULL);
17136
17137#define FACET_RESTR_FIXED_ERR(fac) \
17138    xmlSchemaPCustomErr(pctxt, \
17139	XML_SCHEMAP_INVALID_FACET_VALUE, \
17140	WXS_BASIC_CAST fac, fac->node, \
17141	"The base type's facet is 'fixed', thus the value must not " \
17142	"differ", NULL);
17143
17144static void
17145xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17146			xmlSchemaFacetPtr facet1,
17147			xmlSchemaFacetPtr facet2,
17148			int lessGreater,
17149			int orEqual,
17150			int ofBase)
17151{
17152    xmlChar *msg = NULL;
17153
17154    msg = xmlStrdup(BAD_CAST "'");
17155    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17156    msg = xmlStrcat(msg, BAD_CAST "' has to be");
17157    if (lessGreater == 0)
17158	msg = xmlStrcat(msg, BAD_CAST " equal to");
17159    if (lessGreater == 1)
17160	msg = xmlStrcat(msg, BAD_CAST " greater than");
17161    else
17162	msg = xmlStrcat(msg, BAD_CAST " less than");
17163
17164    if (orEqual)
17165	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17166    msg = xmlStrcat(msg, BAD_CAST " '");
17167    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17168    if (ofBase)
17169	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17170    else
17171	msg = xmlStrcat(msg, BAD_CAST "'");
17172
17173    xmlSchemaPCustomErr(pctxt,
17174	XML_SCHEMAP_INVALID_FACET_VALUE,
17175	WXS_BASIC_CAST facet1, NULL,
17176	(const char *) msg, NULL);
17177
17178    if (msg != NULL)
17179	xmlFree(msg);
17180}
17181
17182/*
17183* xmlSchemaDeriveAndValidateFacets:
17184*
17185* Schema Component Constraint: Simple Type Restriction (Facets)
17186* (st-restrict-facets)
17187*/
17188static int
17189xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17190				 xmlSchemaTypePtr type)
17191{
17192    xmlSchemaTypePtr base = type->baseType;
17193    xmlSchemaFacetLinkPtr link, cur, last = NULL;
17194    xmlSchemaFacetPtr facet, bfacet,
17195	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17196	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17197	fmininc = NULL, fmaxinc = NULL,
17198	fminexc = NULL, fmaxexc = NULL,
17199	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17200	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17201	bfmininc = NULL, bfmaxinc = NULL,
17202	bfminexc = NULL, bfmaxexc = NULL;
17203    int res; /* err = 0, fixedErr; */
17204
17205    /*
17206    * SPEC st-restrict-facets 1:
17207    * "The {variety} of R is the same as that of B."
17208    */
17209    /*
17210    * SPEC st-restrict-facets 2:
17211    * "If {variety} is atomic, the {primitive type definition}
17212    * of R is the same as that of B."
17213    *
17214    * NOTE: we leave 1 & 2 out for now, since this will be
17215    * satisfied by the derivation process.
17216    * CONSTRUCTION TODO: Maybe needed if using a construction API.
17217    */
17218    /*
17219    * SPEC st-restrict-facets 3:
17220    * "The {facets} of R are the union of S and the {facets}
17221    * of B, eliminating duplicates. To eliminate duplicates,
17222    * when a facet of the same kind occurs in both S and the
17223    * {facets} of B, the one in the {facets} of B is not
17224    * included, with the exception of enumeration and pattern
17225    * facets, for which multiple occurrences with distinct values
17226    * are allowed."
17227    */
17228
17229    if ((type->facetSet == NULL) && (base->facetSet == NULL))
17230	return (0);
17231
17232    last = type->facetSet;
17233    if (last != NULL)
17234	while (last->next != NULL)
17235	    last = last->next;
17236
17237    for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17238	facet = cur->facet;
17239	switch (facet->type) {
17240	    case XML_SCHEMA_FACET_LENGTH:
17241		flength = facet; break;
17242	    case XML_SCHEMA_FACET_MINLENGTH:
17243		fminlen = facet; break;
17244	    case XML_SCHEMA_FACET_MININCLUSIVE:
17245		fmininc = facet; break;
17246	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17247		fminexc = facet; break;
17248	    case XML_SCHEMA_FACET_MAXLENGTH:
17249		fmaxlen = facet; break;
17250	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17251		fmaxinc = facet; break;
17252	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17253		fmaxexc = facet; break;
17254	    case XML_SCHEMA_FACET_TOTALDIGITS:
17255		ftotdig = facet; break;
17256	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17257		ffracdig = facet; break;
17258	    default:
17259		break;
17260	}
17261    }
17262    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17263	facet = cur->facet;
17264	switch (facet->type) {
17265	    case XML_SCHEMA_FACET_LENGTH:
17266		bflength = facet; break;
17267	    case XML_SCHEMA_FACET_MINLENGTH:
17268		bfminlen = facet; break;
17269	    case XML_SCHEMA_FACET_MININCLUSIVE:
17270		bfmininc = facet; break;
17271	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17272		bfminexc = facet; break;
17273	    case XML_SCHEMA_FACET_MAXLENGTH:
17274		bfmaxlen = facet; break;
17275	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17276		bfmaxinc = facet; break;
17277	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17278		bfmaxexc = facet; break;
17279	    case XML_SCHEMA_FACET_TOTALDIGITS:
17280		bftotdig = facet; break;
17281	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17282		bffracdig = facet; break;
17283	    default:
17284		break;
17285	}
17286    }
17287    /*
17288    * length and minLength or maxLength (2.2) + (3.2)
17289    */
17290    if (flength && (fminlen || fmaxlen)) {
17291	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17292	    "either of 'minLength' or 'maxLength' to be specified on "
17293	    "the same type definition")
17294    }
17295    /*
17296    * Mutual exclusions in the same derivation step.
17297    */
17298    if ((fmaxinc) && (fmaxexc)) {
17299	/*
17300	* SCC "maxInclusive and maxExclusive"
17301	*/
17302	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17303    }
17304    if ((fmininc) && (fminexc)) {
17305	/*
17306	* SCC "minInclusive and minExclusive"
17307	*/
17308	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17309    }
17310
17311    if (flength && bflength) {
17312	/*
17313	* SCC "length valid restriction"
17314	* The values have to be equal.
17315	*/
17316	res = xmlSchemaCompareValues(flength->val, bflength->val);
17317	if (res == -2)
17318	    goto internal_error;
17319	if (res != 0)
17320	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17321	if ((res != 0) && (bflength->fixed)) {
17322	    FACET_RESTR_FIXED_ERR(flength)
17323	}
17324
17325    }
17326    if (fminlen && bfminlen) {
17327	/*
17328	* SCC "minLength valid restriction"
17329	* minLength >= BASE minLength
17330	*/
17331	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17332	if (res == -2)
17333	    goto internal_error;
17334	if (res == -1)
17335	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17336	if ((res != 0) && (bfminlen->fixed)) {
17337	    FACET_RESTR_FIXED_ERR(fminlen)
17338	}
17339    }
17340    if (fmaxlen && bfmaxlen) {
17341	/*
17342	* SCC "maxLength valid restriction"
17343	* maxLength <= BASE minLength
17344	*/
17345	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17346	if (res == -2)
17347	    goto internal_error;
17348	if (res == 1)
17349	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17350	if ((res != 0) && (bfmaxlen->fixed)) {
17351	    FACET_RESTR_FIXED_ERR(fmaxlen)
17352	}
17353    }
17354    /*
17355    * SCC "length and minLength or maxLength"
17356    */
17357    if (! flength)
17358	flength = bflength;
17359    if (flength) {
17360	if (! fminlen)
17361	    fminlen = bfminlen;
17362	if (fminlen) {
17363	    /* (1.1) length >= minLength */
17364	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17365	    if (res == -2)
17366		goto internal_error;
17367	    if (res == -1)
17368		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17369	}
17370	if (! fmaxlen)
17371	    fmaxlen = bfmaxlen;
17372	if (fmaxlen) {
17373	    /* (2.1) length <= maxLength */
17374	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17375	    if (res == -2)
17376		goto internal_error;
17377	    if (res == 1)
17378		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17379	}
17380    }
17381    if (fmaxinc) {
17382	/*
17383	* "maxInclusive"
17384	*/
17385	if (fmininc) {
17386	    /* SCC "maxInclusive >= minInclusive" */
17387	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17388	    if (res == -2)
17389		goto internal_error;
17390	    if (res == -1) {
17391		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17392	    }
17393	}
17394	/*
17395	* SCC "maxInclusive valid restriction"
17396	*/
17397	if (bfmaxinc) {
17398	    /* maxInclusive <= BASE maxInclusive */
17399	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17400	    if (res == -2)
17401		goto internal_error;
17402	    if (res == 1)
17403		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17404	    if ((res != 0) && (bfmaxinc->fixed)) {
17405		FACET_RESTR_FIXED_ERR(fmaxinc)
17406	    }
17407	}
17408	if (bfmaxexc) {
17409	    /* maxInclusive < BASE maxExclusive */
17410	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17411	    if (res == -2)
17412		goto internal_error;
17413	    if (res != -1) {
17414		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17415	    }
17416	}
17417	if (bfmininc) {
17418	    /* maxInclusive >= BASE minInclusive */
17419	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17420	    if (res == -2)
17421		goto internal_error;
17422	    if (res == -1) {
17423		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17424	    }
17425	}
17426	if (bfminexc) {
17427	    /* maxInclusive > BASE minExclusive */
17428	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17429	    if (res == -2)
17430		goto internal_error;
17431	    if (res != 1) {
17432		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17433	    }
17434	}
17435    }
17436    if (fmaxexc) {
17437	/*
17438	* "maxExclusive >= minExclusive"
17439	*/
17440	if (fminexc) {
17441	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17442	    if (res == -2)
17443		goto internal_error;
17444	    if (res == -1) {
17445		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17446	    }
17447	}
17448	/*
17449	* "maxExclusive valid restriction"
17450	*/
17451	if (bfmaxexc) {
17452	    /* maxExclusive <= BASE maxExclusive */
17453	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17454	    if (res == -2)
17455		goto internal_error;
17456	    if (res == 1) {
17457		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17458	    }
17459	    if ((res != 0) && (bfmaxexc->fixed)) {
17460		FACET_RESTR_FIXED_ERR(fmaxexc)
17461	    }
17462	}
17463	if (bfmaxinc) {
17464	    /* maxExclusive <= BASE maxInclusive */
17465	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17466	    if (res == -2)
17467		goto internal_error;
17468	    if (res == 1) {
17469		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17470	    }
17471	}
17472	if (bfmininc) {
17473	    /* maxExclusive > BASE minInclusive */
17474	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17475	    if (res == -2)
17476		goto internal_error;
17477	    if (res != 1) {
17478		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17479	    }
17480	}
17481	if (bfminexc) {
17482	    /* maxExclusive > BASE minExclusive */
17483	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17484	    if (res == -2)
17485		goto internal_error;
17486	    if (res != 1) {
17487		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17488	    }
17489	}
17490    }
17491    if (fminexc) {
17492	/*
17493	* "minExclusive < maxInclusive"
17494	*/
17495	if (fmaxinc) {
17496	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17497	    if (res == -2)
17498		goto internal_error;
17499	    if (res != -1) {
17500		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17501	    }
17502	}
17503	/*
17504	* "minExclusive valid restriction"
17505	*/
17506	if (bfminexc) {
17507	    /* minExclusive >= BASE minExclusive */
17508	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17509	    if (res == -2)
17510		goto internal_error;
17511	    if (res == -1) {
17512		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17513	    }
17514	    if ((res != 0) && (bfminexc->fixed)) {
17515		FACET_RESTR_FIXED_ERR(fminexc)
17516	    }
17517	}
17518	if (bfmaxinc) {
17519	    /* minExclusive <= BASE maxInclusive */
17520	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17521	    if (res == -2)
17522		goto internal_error;
17523	    if (res == 1) {
17524		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17525	    }
17526	}
17527	if (bfmininc) {
17528	    /* minExclusive >= BASE minInclusive */
17529	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17530	    if (res == -2)
17531		goto internal_error;
17532	    if (res == -1) {
17533		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17534	    }
17535	}
17536	if (bfmaxexc) {
17537	    /* minExclusive < BASE maxExclusive */
17538	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17539	    if (res == -2)
17540		goto internal_error;
17541	    if (res != -1) {
17542		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17543	    }
17544	}
17545    }
17546    if (fmininc) {
17547	/*
17548	* "minInclusive < maxExclusive"
17549	*/
17550	if (fmaxexc) {
17551	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17552	    if (res == -2)
17553		goto internal_error;
17554	    if (res != -1) {
17555		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17556	    }
17557	}
17558	/*
17559	* "minExclusive valid restriction"
17560	*/
17561	if (bfmininc) {
17562	    /* minInclusive >= BASE minInclusive */
17563	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17564	    if (res == -2)
17565		goto internal_error;
17566	    if (res == -1) {
17567		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17568	    }
17569	    if ((res != 0) && (bfmininc->fixed)) {
17570		FACET_RESTR_FIXED_ERR(fmininc)
17571	    }
17572	}
17573	if (bfmaxinc) {
17574	    /* minInclusive <= BASE maxInclusive */
17575	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17576	    if (res == -2)
17577		goto internal_error;
17578	    if (res == 1) {
17579		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17580	    }
17581	}
17582	if (bfminexc) {
17583	    /* minInclusive > BASE minExclusive */
17584	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17585	    if (res == -2)
17586		goto internal_error;
17587	    if (res != 1)
17588		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17589	}
17590	if (bfmaxexc) {
17591	    /* minInclusive < BASE maxExclusive */
17592	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17593	    if (res == -2)
17594		goto internal_error;
17595	    if (res != -1)
17596		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17597	}
17598    }
17599    if (ftotdig && bftotdig) {
17600	/*
17601	* SCC " totalDigits valid restriction"
17602	* totalDigits <= BASE totalDigits
17603	*/
17604	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17605	if (res == -2)
17606	    goto internal_error;
17607	if (res == 1)
17608	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17609	    -1, 1, 1);
17610	if ((res != 0) && (bftotdig->fixed)) {
17611	    FACET_RESTR_FIXED_ERR(ftotdig)
17612	}
17613    }
17614    if (ffracdig && bffracdig) {
17615	/*
17616	* SCC  "fractionDigits valid restriction"
17617	* fractionDigits <= BASE fractionDigits
17618	*/
17619	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17620	if (res == -2)
17621	    goto internal_error;
17622	if (res == 1)
17623	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17624	    -1, 1, 1);
17625	if ((res != 0) && (bffracdig->fixed)) {
17626	    FACET_RESTR_FIXED_ERR(ffracdig)
17627	}
17628    }
17629    /*
17630    * SCC "fractionDigits less than or equal to totalDigits"
17631    */
17632    if (! ftotdig)
17633	ftotdig = bftotdig;
17634    if (! ffracdig)
17635	ffracdig = bffracdig;
17636    if (ftotdig && ffracdig) {
17637	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17638	if (res == -2)
17639	    goto internal_error;
17640	if (res == 1)
17641	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17642		-1, 1, 0);
17643    }
17644    /*
17645    * *Enumerations* won' be added here, since only the first set
17646    * of enumerations in the ancestor-or-self axis is used
17647    * for validation, plus we need to use the base type of those
17648    * enumerations for whitespace.
17649    *
17650    * *Patterns*: won't be add here, since they are ORed at
17651    * type level and ANDed at ancestor level. This will
17652    * happed during validation by walking the base axis
17653    * of the type.
17654    */
17655    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17656	bfacet = cur->facet;
17657	/*
17658	* Special handling of enumerations and patterns.
17659	* TODO: hmm, they should not appear in the set, so remove this.
17660	*/
17661	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17662	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17663	    continue;
17664	/*
17665	* Search for a duplicate facet in the current type.
17666	*/
17667	link = type->facetSet;
17668	/* err = 0; */
17669	/* fixedErr = 0; */
17670	while (link != NULL) {
17671	    facet = link->facet;
17672	    if (facet->type == bfacet->type) {
17673		switch (facet->type) {
17674		    case XML_SCHEMA_FACET_WHITESPACE:
17675			/*
17676			* The whitespace must be stronger.
17677			*/
17678			if (facet->whitespace < bfacet->whitespace) {
17679			    FACET_RESTR_ERR(facet,
17680				"The 'whitespace' value has to be equal to "
17681				"or stronger than the 'whitespace' value of "
17682				"the base type")
17683			}
17684			if ((bfacet->fixed) &&
17685			    (facet->whitespace != bfacet->whitespace)) {
17686			    FACET_RESTR_FIXED_ERR(facet)
17687			}
17688			break;
17689		    default:
17690			break;
17691		}
17692		/* Duplicate found. */
17693		break;
17694	    }
17695	    link = link->next;
17696	}
17697	/*
17698	* If no duplicate was found: add the base types's facet
17699	* to the set.
17700	*/
17701	if (link == NULL) {
17702	    link = (xmlSchemaFacetLinkPtr)
17703		xmlMalloc(sizeof(xmlSchemaFacetLink));
17704	    if (link == NULL) {
17705		xmlSchemaPErrMemory(pctxt,
17706		    "deriving facets, creating a facet link", NULL);
17707		return (-1);
17708	    }
17709	    link->facet = cur->facet;
17710	    link->next = NULL;
17711	    if (last == NULL)
17712		type->facetSet = link;
17713	    else
17714		last->next = link;
17715	    last = link;
17716	}
17717
17718    }
17719
17720    return (0);
17721internal_error:
17722    PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17723	"an error occured");
17724    return (-1);
17725}
17726
17727static int
17728xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17729					     xmlSchemaTypePtr type)
17730{
17731    xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17732    /*
17733    * The actual value is then formed by replacing any union type
17734    * definition in the �explicit members� with the members of their
17735    * {member type definitions}, in order.
17736    *
17737    * TODO: There's a bug entry at
17738    * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17739    * which indicates that we'll keep the union types the future.
17740    */
17741    link = type->memberTypes;
17742    while (link != NULL) {
17743
17744	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17745	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17746
17747	if (WXS_IS_UNION(link->type)) {
17748	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17749	    if (subLink != NULL) {
17750		link->type = subLink->type;
17751		if (subLink->next != NULL) {
17752		    lastLink = link->next;
17753		    subLink = subLink->next;
17754		    prevLink = link;
17755		    while (subLink != NULL) {
17756			newLink = (xmlSchemaTypeLinkPtr)
17757			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17758			if (newLink == NULL) {
17759			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17760				NULL);
17761			    return (-1);
17762			}
17763			newLink->type = subLink->type;
17764			prevLink->next = newLink;
17765			prevLink = newLink;
17766			newLink->next = lastLink;
17767
17768			subLink = subLink->next;
17769		    }
17770		}
17771	    }
17772	}
17773	link = link->next;
17774    }
17775    return (0);
17776}
17777
17778static void
17779xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17780{
17781    int has = 0, needVal = 0, normVal = 0;
17782
17783    has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17784    if (has) {
17785	needVal = (type->baseType->flags &
17786	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17787	normVal = (type->baseType->flags &
17788	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17789    }
17790    if (type->facets != NULL) {
17791	xmlSchemaFacetPtr fac;
17792
17793	for (fac = type->facets; fac != NULL; fac = fac->next) {
17794	    switch (fac->type) {
17795		case XML_SCHEMA_FACET_WHITESPACE:
17796		    break;
17797		case XML_SCHEMA_FACET_PATTERN:
17798		    normVal = 1;
17799		    has = 1;
17800		    break;
17801		case XML_SCHEMA_FACET_ENUMERATION:
17802		    needVal = 1;
17803		    normVal = 1;
17804		    has = 1;
17805		    break;
17806		default:
17807		    has = 1;
17808		    break;
17809	    }
17810	}
17811    }
17812    if (normVal)
17813	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17814    if (needVal)
17815	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17816    if (has)
17817	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17818
17819    if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17820	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17821	/*
17822	* OPTIMIZE VAL TODO: Some facets need a computed value.
17823	*/
17824	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17825	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17826	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17827	}
17828    }
17829}
17830
17831static int
17832xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17833{
17834
17835
17836    /*
17837    * Evaluate the whitespace-facet value.
17838    */
17839    if (WXS_IS_LIST(type)) {
17840	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17841	return (0);
17842    } else if (WXS_IS_UNION(type))
17843	return (0);
17844
17845    if (type->facetSet != NULL) {
17846	xmlSchemaFacetLinkPtr lin;
17847
17848	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17849	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17850		switch (lin->facet->whitespace) {
17851		case XML_SCHEMAS_FACET_PRESERVE:
17852		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17853		    break;
17854		case XML_SCHEMAS_FACET_REPLACE:
17855		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17856		    break;
17857		case XML_SCHEMAS_FACET_COLLAPSE:
17858		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17859		    break;
17860		default:
17861		    return (-1);
17862		}
17863		return (0);
17864	    }
17865	}
17866    }
17867    /*
17868    * For all �atomic� datatypes other than string (and types �derived�
17869    * by �restriction� from it) the value of whiteSpace is fixed to
17870    * collapse
17871    */
17872    {
17873	xmlSchemaTypePtr anc;
17874
17875	for (anc = type->baseType; anc != NULL &&
17876		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17877		anc = anc->baseType) {
17878
17879	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17880		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17881		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17882
17883		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17884		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17885		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17886
17887		} else
17888		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17889		break;
17890	    }
17891	}
17892    }
17893    return (0);
17894}
17895
17896static int
17897xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17898			  xmlSchemaTypePtr type)
17899{
17900    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17901	return(0);
17902    if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17903	return(0);
17904    type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17905
17906    if (WXS_IS_LIST(type)) {
17907	/*
17908	* Corresponds to <simpleType><list>...
17909	*/
17910	if (type->subtypes == NULL) {
17911	    /*
17912	    * This one is really needed, so get out.
17913	    */
17914	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17915		"list type has no item-type assigned");
17916	    return(-1);
17917	}
17918    } else if (WXS_IS_UNION(type)) {
17919	/*
17920	* Corresponds to <simpleType><union>...
17921	*/
17922	if (type->memberTypes == NULL) {
17923	    /*
17924	    * This one is really needed, so get out.
17925	    */
17926	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17927		"union type has no member-types assigned");
17928	    return(-1);
17929	}
17930    } else {
17931	/*
17932	* Corresponds to <simpleType><restriction>...
17933	*/
17934	if (type->baseType == NULL) {
17935	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17936		"type has no base-type assigned");
17937	    return(-1);
17938	}
17939	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17940	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17941		return(-1);
17942	/*
17943	* Variety
17944	* If the <restriction> alternative is chosen, then the
17945	* {variety} of the {base type definition}.
17946	*/
17947	if (WXS_IS_ATOMIC(type->baseType))
17948	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17949	else if (WXS_IS_LIST(type->baseType)) {
17950	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17951	    /*
17952	    * Inherit the itemType.
17953	    */
17954	    type->subtypes = type->baseType->subtypes;
17955	} else if (WXS_IS_UNION(type->baseType)) {
17956	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17957	    /*
17958	    * NOTE that we won't assign the memberTypes of the base,
17959	    * since this will make trouble when freeing them; we will
17960	    * use a lookup function to access them instead.
17961	    */
17962	}
17963    }
17964    return(0);
17965}
17966
17967#ifdef DEBUG_TYPE
17968static void
17969xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17970		       xmlSchemaTypePtr type)
17971{
17972    if (type->node != NULL) {
17973        xmlGenericError(xmlGenericErrorContext,
17974                        "Type of %s : %s:%d :", name,
17975                        type->node->doc->URL,
17976                        xmlGetLineNo(type->node));
17977    } else {
17978        xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17979    }
17980    if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17981	switch (type->contentType) {
17982	    case XML_SCHEMA_CONTENT_SIMPLE:
17983		xmlGenericError(xmlGenericErrorContext, "simple\n");
17984		break;
17985	    case XML_SCHEMA_CONTENT_ELEMENTS:
17986		xmlGenericError(xmlGenericErrorContext, "elements\n");
17987		break;
17988	    case XML_SCHEMA_CONTENT_UNKNOWN:
17989		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17990		break;
17991	    case XML_SCHEMA_CONTENT_EMPTY:
17992		xmlGenericError(xmlGenericErrorContext, "empty\n");
17993		break;
17994	    case XML_SCHEMA_CONTENT_MIXED:
17995		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17996		    type->subtypes))
17997		    xmlGenericError(xmlGenericErrorContext,
17998			"mixed as emptiable particle\n");
17999		else
18000		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18001		break;
18002		/* Removed, since not used. */
18003		/*
18004		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18005		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18006		break;
18007		*/
18008	    case XML_SCHEMA_CONTENT_BASIC:
18009		xmlGenericError(xmlGenericErrorContext, "basic\n");
18010		break;
18011	    default:
18012		xmlGenericError(xmlGenericErrorContext,
18013		    "not registered !!!\n");
18014		break;
18015	}
18016    }
18017}
18018#endif
18019
18020/*
18021* 3.14.6 Constraints on Simple Type Definition Schema Components
18022*/
18023static int
18024xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18025				 xmlSchemaTypePtr type)
18026{
18027    int res, olderrs = pctxt->nberrors;
18028
18029    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18030	return(-1);
18031
18032    if (! WXS_IS_TYPE_NOT_FIXED(type))
18033	return(0);
18034
18035    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18036    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18037
18038    if (type->baseType == NULL) {
18039	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18040	    "missing baseType");
18041	goto exit_failure;
18042    }
18043    if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18044	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18045    /*
18046    * If a member type of a union is a union itself, we need to substitute
18047    * that member type for its member types.
18048    * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18049    * types in WXS 1.1.
18050    */
18051    if ((type->memberTypes != NULL) &&
18052	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18053	return(-1);
18054    /*
18055    * SPEC src-simple-type 1
18056    * "The corresponding simple type definition, if any, must satisfy
18057    * the conditions set out in Constraints on Simple Type Definition
18058    * Schema Components (�3.14.6)."
18059    */
18060    /*
18061    * Schema Component Constraint: Simple Type Definition Properties Correct
18062    * (st-props-correct)
18063    */
18064    res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18065    HFAILURE HERROR
18066    /*
18067    * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18068    * (cos-st-restricts)
18069    */
18070    res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18071    HFAILURE HERROR
18072    /*
18073    * TODO: Removed the error report, since it got annoying to get an
18074    * extra error report, if anything failed until now.
18075    * Enable this if needed.
18076    *
18077    * xmlSchemaPErr(ctxt, type->node,
18078    *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18079    *    "Simple type '%s' does not satisfy the constraints "
18080    *    "on simple type definitions.\n",
18081    *    type->name, NULL);
18082    */
18083    /*
18084    * Schema Component Constraint: Simple Type Restriction (Facets)
18085    * (st-restrict-facets)
18086    */
18087    res = xmlSchemaCheckFacetValues(type, pctxt);
18088    HFAILURE HERROR
18089    if ((type->facetSet != NULL) ||
18090	(type->baseType->facetSet != NULL)) {
18091	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18092	HFAILURE HERROR
18093    }
18094    /*
18095    * Whitespace value.
18096    */
18097    res = xmlSchemaTypeFixupWhitespace(type);
18098    HFAILURE HERROR
18099    xmlSchemaTypeFixupOptimFacets(type);
18100
18101exit_error:
18102#ifdef DEBUG_TYPE
18103    xmlSchemaDebugFixedType(pctxt, type);
18104#endif
18105    if (olderrs != pctxt->nberrors)
18106	return(pctxt->err);
18107    return(0);
18108
18109exit_failure:
18110#ifdef DEBUG_TYPE
18111    xmlSchemaDebugFixedType(pctxt, type);
18112#endif
18113    return(-1);
18114}
18115
18116static int
18117xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18118			  xmlSchemaTypePtr type)
18119{
18120    int res = 0, olderrs = pctxt->nberrors;
18121    xmlSchemaTypePtr baseType = type->baseType;
18122
18123    if (! WXS_IS_TYPE_NOT_FIXED(type))
18124	return(0);
18125    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18126    if (baseType == NULL) {
18127	PERROR_INT("xmlSchemaFixupComplexType",
18128	    "missing baseType");
18129	goto exit_failure;
18130    }
18131    /*
18132    * Fixup the base type.
18133    */
18134    if (WXS_IS_TYPE_NOT_FIXED(baseType))
18135	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18136    if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18137	/*
18138	* Skip fixup if the base type is invalid.
18139	* TODO: Generate a warning!
18140	*/
18141	return(0);
18142    }
18143    /*
18144    * This basically checks if the base type can be derived.
18145    */
18146    res = xmlSchemaCheckSRCCT(pctxt, type);
18147    HFAILURE HERROR
18148    /*
18149    * Fixup the content type.
18150    */
18151    if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18152	/*
18153	* Corresponds to <complexType><simpleContent>...
18154	*/
18155	if ((WXS_IS_COMPLEX(baseType)) &&
18156	    (baseType->contentTypeDef != NULL) &&
18157	    (WXS_IS_RESTRICTION(type))) {
18158	    xmlSchemaTypePtr contentBase, content;
18159#ifdef ENABLE_NAMED_LOCALS
18160	    char buf[30];
18161	    const xmlChar *tmpname;
18162#endif
18163	    /*
18164	    * SPEC (1) If <restriction> + base type is <complexType>,
18165	    * "whose own {content type} is a simple type..."
18166	    */
18167	    if (type->contentTypeDef != NULL) {
18168		/*
18169		* SPEC (1.1) "the simple type definition corresponding to the
18170		* <simpleType> among the [children] of <restriction> if there
18171		* is one;"
18172		* Note that this "<simpleType> among the [children]" was put
18173		* into ->contentTypeDef during parsing.
18174		*/
18175		contentBase = type->contentTypeDef;
18176		type->contentTypeDef = NULL;
18177	    } else {
18178		/*
18179		* (1.2) "...otherwise (<restriction> has no <simpleType>
18180		* among its [children]), the simple type definition which
18181		* is the {content type} of the ... base type."
18182		*/
18183		contentBase = baseType->contentTypeDef;
18184	    }
18185	    /*
18186	    * SPEC
18187	    * "... a simple type definition which restricts the simple
18188	    * type definition identified in clause 1.1 or clause 1.2
18189	    * with a set of facet components"
18190	    *
18191	    * Create the anonymous simple type, which will be the content
18192	    * type of the complex type.
18193	    */
18194#ifdef ENABLE_NAMED_LOCALS
18195	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18196	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18197	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18198		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18199		type->node, 0);
18200#else
18201	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18202		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18203		type->node, 0);
18204#endif
18205	    if (content == NULL)
18206		goto exit_failure;
18207	    /*
18208	    * We will use the same node as for the <complexType>
18209	    * to have it somehow anchored in the schema doc.
18210	    */
18211	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18212	    content->baseType = contentBase;
18213	    /*
18214	    * Move the facets, previously anchored on the
18215	    * complexType during parsing.
18216	    */
18217	    content->facets = type->facets;
18218	    type->facets = NULL;
18219	    content->facetSet = type->facetSet;
18220	    type->facetSet = NULL;
18221
18222	    type->contentTypeDef = content;
18223	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18224		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18225	    /*
18226	    * Fixup the newly created type. We don't need to check
18227	    * for circularity here.
18228	    */
18229	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18230	    HFAILURE HERROR
18231	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18232	    HFAILURE HERROR
18233
18234	} else if ((WXS_IS_COMPLEX(baseType)) &&
18235	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18236	    (WXS_IS_RESTRICTION(type))) {
18237	    /*
18238	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18239	    * an emptiable particle, then a simple type definition which
18240	    * restricts the <restriction>'s <simpleType> child.
18241	    */
18242	    if ((type->contentTypeDef == NULL) ||
18243		(type->contentTypeDef->baseType == NULL)) {
18244		/*
18245		* TODO: Check if this ever happens.
18246		*/
18247		xmlSchemaPCustomErr(pctxt,
18248		    XML_SCHEMAP_INTERNAL,
18249		    WXS_BASIC_CAST type, NULL,
18250		    "Internal error: xmlSchemaTypeFixup, "
18251		    "complex type '%s': the <simpleContent><restriction> "
18252		    "is missing a <simpleType> child, but was not catched "
18253		    "by xmlSchemaCheckSRCCT()", type->name);
18254		goto exit_failure;
18255	    }
18256	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18257	    /*
18258	    * SPEC (3) If <extension> + base is <complexType> with
18259	    * <simpleType> content, "...then the {content type} of that
18260	    * complex type definition"
18261	    */
18262	    if (baseType->contentTypeDef == NULL) {
18263		/*
18264		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18265		* should have catched this already.
18266		*/
18267		xmlSchemaPCustomErr(pctxt,
18268		    XML_SCHEMAP_INTERNAL,
18269		    WXS_BASIC_CAST type, NULL,
18270		    "Internal error: xmlSchemaTypeFixup, "
18271		    "complex type '%s': the <extension>ed base type is "
18272		    "a complex type with no simple content type",
18273		    type->name);
18274		goto exit_failure;
18275	    }
18276	    type->contentTypeDef = baseType->contentTypeDef;
18277	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18278	    /*
18279	    * SPEC (4) <extension> + base is <simpleType>
18280	    * "... then that simple type definition"
18281	    */
18282	    type->contentTypeDef = baseType;
18283	} else {
18284	    /*
18285	    * TODO: Check if this ever happens.
18286	    */
18287	    xmlSchemaPCustomErr(pctxt,
18288		XML_SCHEMAP_INTERNAL,
18289		WXS_BASIC_CAST type, NULL,
18290		"Internal error: xmlSchemaTypeFixup, "
18291		"complex type '%s' with <simpleContent>: unhandled "
18292		"derivation case", type->name);
18293	    goto exit_failure;
18294	}
18295    } else {
18296	int dummySequence = 0;
18297	xmlSchemaParticlePtr particle =
18298	    (xmlSchemaParticlePtr) type->subtypes;
18299	/*
18300	* Corresponds to <complexType><complexContent>...
18301	*
18302	* NOTE that the effective mixed was already set during parsing of
18303	* <complexType> and <complexContent>; its flag value is
18304	* XML_SCHEMAS_TYPE_MIXED.
18305	*
18306	* Compute the "effective content":
18307	* (2.1.1) + (2.1.2) + (2.1.3)
18308	*/
18309	if ((particle == NULL) ||
18310	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18311	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18312	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18313	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18314	    (particle->minOccurs == 0))) &&
18315	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18316	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18317		/*
18318		* SPEC (2.1.4) "If the �effective mixed� is true, then
18319		* a particle whose properties are as follows:..."
18320		*
18321		* Empty sequence model group with
18322		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18323		* NOTE that we sill assign it the <complexType> node to
18324		* somehow anchor it in the doc.
18325		*/
18326		if ((particle == NULL) ||
18327		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18328		    /*
18329		    * Create the particle.
18330		    */
18331		    particle = xmlSchemaAddParticle(pctxt,
18332			type->node, 1, 1);
18333		    if (particle == NULL)
18334			goto exit_failure;
18335		    /*
18336		    * Create the model group.
18337		    */ /* URGENT TODO: avoid adding to pending items. */
18338		    particle->children = (xmlSchemaTreeItemPtr)
18339			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18340			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18341		    if (particle->children == NULL)
18342			goto exit_failure;
18343
18344		    type->subtypes = (xmlSchemaTypePtr) particle;
18345		}
18346		dummySequence = 1;
18347		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18348	    } else {
18349		/*
18350		* SPEC (2.1.5) "otherwise empty"
18351		*/
18352		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18353	    }
18354	} else {
18355	    /*
18356	    * SPEC (2.2) "otherwise the particle corresponding to the
18357	    * <all>, <choice>, <group> or <sequence> among the
18358	    * [children]."
18359	    */
18360	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18361	}
18362	/*
18363	* Compute the "content type".
18364	*/
18365	if (WXS_IS_RESTRICTION(type)) {
18366	    /*
18367	    * SPEC (3.1) "If <restriction>..."
18368	    * (3.1.1) + (3.1.2) */
18369	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18370		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18371		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18372	    }
18373	} else {
18374	    /*
18375	    * SPEC (3.2) "If <extension>..."
18376	    */
18377	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18378		/*
18379		* SPEC (3.2.1)
18380		* "If the �effective content� is empty, then the
18381		*  {content type} of the [...] base ..."
18382		*/
18383		type->contentType = baseType->contentType;
18384		type->subtypes = baseType->subtypes;
18385		/*
18386		* Fixes bug #347316:
18387		* This is the case when the base type has a simple
18388		* type definition as content.
18389		*/
18390		type->contentTypeDef = baseType->contentTypeDef;
18391		/*
18392		* NOTE that the effective mixed is ignored here.
18393		*/
18394	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18395		/*
18396		* SPEC (3.2.2)
18397		*/
18398		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18399		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18400	    } else {
18401		/*
18402		* SPEC (3.2.3)
18403		*/
18404		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18405		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18406		    /*
18407		    * "A model group whose {compositor} is sequence and whose
18408		    * {particles} are..."
18409		    */
18410		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18411		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18412		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18413			XML_SCHEMA_TYPE_ALL))
18414		{
18415		    /*
18416		    * SPEC cos-all-limited (1)
18417		    */
18418		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18419			/* TODO: error code */
18420			XML_SCHEMAP_COS_ALL_LIMITED,
18421			WXS_ITEM_NODE(type), NULL,
18422			"The type has an 'all' model group in its "
18423			"{content type} and thus cannot be derived from "
18424			"a non-empty type, since this would produce a "
18425			"'sequence' model group containing the 'all' "
18426			"model group; 'all' model groups are not "
18427			"allowed to appear inside other model groups",
18428			NULL, NULL);
18429
18430		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18431		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18432		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18433			XML_SCHEMA_TYPE_ALL))
18434		{
18435		    /*
18436		    * SPEC cos-all-limited (1)
18437		    */
18438		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18439			/* TODO: error code */
18440			XML_SCHEMAP_COS_ALL_LIMITED,
18441			WXS_ITEM_NODE(type), NULL,
18442			"A type cannot be derived by extension from a type "
18443			"which has an 'all' model group in its "
18444			"{content type}, since this would produce a "
18445			"'sequence' model group containing the 'all' "
18446			"model group; 'all' model groups are not "
18447			"allowed to appear inside other model groups",
18448			NULL, NULL);
18449
18450		} else if (! dummySequence) {
18451		    xmlSchemaTreeItemPtr effectiveContent =
18452			(xmlSchemaTreeItemPtr) type->subtypes;
18453		    /*
18454		    * Create the particle.
18455		    */
18456		    particle = xmlSchemaAddParticle(pctxt,
18457			type->node, 1, 1);
18458		    if (particle == NULL)
18459			goto exit_failure;
18460		    /*
18461		    * Create the "sequence" model group.
18462		    */
18463		    particle->children = (xmlSchemaTreeItemPtr)
18464			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18465			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18466		    if (particle->children == NULL)
18467			goto exit_failure;
18468		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18469		    /*
18470		    * SPEC "the particle of the {content type} of
18471		    * the ... base ..."
18472		    * Create a duplicate of the base type's particle
18473		    * and assign its "term" to it.
18474		    */
18475		    particle->children->children =
18476			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18477			type->node,
18478			((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18479			((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18480		    if (particle->children->children == NULL)
18481			goto exit_failure;
18482		    particle = (xmlSchemaParticlePtr)
18483			particle->children->children;
18484		    particle->children =
18485			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18486		    /*
18487		    * SPEC "followed by the �effective content�."
18488		    */
18489		    particle->next = effectiveContent;
18490		    /*
18491		    * This all will result in:
18492		    * new-particle
18493		    *   --> new-sequence(
18494		    *         new-particle
18495		    *           --> base-model,
18496		    *         this-particle
18497		    *	        --> this-model
18498		    *	    )
18499		    */
18500		} else {
18501		    /*
18502		    * This is the case when there is already an empty
18503		    * <sequence> with minOccurs==maxOccurs==1.
18504		    * Just add the base types's content type.
18505		    * NOTE that, although we miss to add an intermediate
18506		    * <sequence>, this should produce no difference to
18507		    * neither the regex compilation of the content model,
18508		    * nor to the complex type contraints.
18509		    */
18510		    particle->children->children =
18511			(xmlSchemaTreeItemPtr) baseType->subtypes;
18512		}
18513	    }
18514	}
18515    }
18516    /*
18517    * Now fixup attribute uses:
18518    *   - expand attr. group references
18519    *     - intersect attribute wildcards
18520    *   - inherit attribute uses of the base type
18521    *   - inherit or union attr. wildcards if extending
18522    *   - apply attr. use prohibitions if restricting
18523    */
18524    res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18525    HFAILURE HERROR
18526    /*
18527    * Apply the complex type component constraints; this will not
18528    * check attributes, since this is done in
18529    * xmlSchemaFixupTypeAttributeUses().
18530    */
18531    res = xmlSchemaCheckCTComponent(pctxt, type);
18532    HFAILURE HERROR
18533
18534#ifdef DEBUG_TYPE
18535    xmlSchemaDebugFixedType(pctxt, type);
18536#endif
18537    if (olderrs != pctxt->nberrors)
18538	return(pctxt->err);
18539    else
18540	return(0);
18541
18542exit_error:
18543    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18544#ifdef DEBUG_TYPE
18545    xmlSchemaDebugFixedType(pctxt, type);
18546#endif
18547    return(pctxt->err);
18548
18549exit_failure:
18550    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18551#ifdef DEBUG_TYPE
18552    xmlSchemaDebugFixedType(pctxt, type);
18553#endif
18554    return(-1);
18555}
18556
18557
18558/**
18559 * xmlSchemaTypeFixup:
18560 * @typeDecl:  the schema type definition
18561 * @ctxt:  the schema parser context
18562 *
18563 * Fixes the content model of the type.
18564 * URGENT TODO: We need an int result!
18565 */
18566static int
18567xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18568                   xmlSchemaAbstractCtxtPtr actxt)
18569{
18570    if (type == NULL)
18571        return(0);
18572    if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18573	AERROR_INT("xmlSchemaTypeFixup",
18574	    "this function needs a parser context");
18575	return(-1);
18576    }
18577    if (! WXS_IS_TYPE_NOT_FIXED(type))
18578	return(0);
18579    if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18580	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18581    else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18582	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18583    return(0);
18584}
18585
18586/**
18587 * xmlSchemaCheckFacet:
18588 * @facet:  the facet
18589 * @typeDecl:  the schema type definition
18590 * @pctxt:  the schema parser context or NULL
18591 * @name: the optional name of the type
18592 *
18593 * Checks and computes the values of facets.
18594 *
18595 * Returns 0 if valid, a positive error code if not valid and
18596 *         -1 in case of an internal or API error.
18597 */
18598int
18599xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18600                    xmlSchemaTypePtr typeDecl,
18601                    xmlSchemaParserCtxtPtr pctxt,
18602		    const xmlChar * name ATTRIBUTE_UNUSED)
18603{
18604    int ret = 0, ctxtGiven;
18605
18606    if ((facet == NULL) || (typeDecl == NULL))
18607        return(-1);
18608    /*
18609    * TODO: will the parser context be given if used from
18610    * the relaxNG module?
18611    */
18612    if (pctxt == NULL)
18613	ctxtGiven = 0;
18614    else
18615	ctxtGiven = 1;
18616
18617    switch (facet->type) {
18618        case XML_SCHEMA_FACET_MININCLUSIVE:
18619        case XML_SCHEMA_FACET_MINEXCLUSIVE:
18620        case XML_SCHEMA_FACET_MAXINCLUSIVE:
18621        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18622	case XML_SCHEMA_FACET_ENUMERATION: {
18623                /*
18624                 * Okay we need to validate the value
18625                 * at that point.
18626                 */
18627		xmlSchemaTypePtr base;
18628
18629		/* 4.3.5.5 Constraints on enumeration Schema Components
18630		* Schema Component Constraint: enumeration valid restriction
18631		* It is an �error� if any member of {value} is not in the
18632		* �value space� of {base type definition}.
18633		*
18634		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18635		* The value �must� be in the
18636		* �value space� of the �base type�.
18637		*/
18638		/*
18639		* This function is intended to deliver a compiled value
18640		* on the facet. In this implementation of XML Schemata the
18641		* type holding a facet, won't be a built-in type.
18642		* Thus to ensure that other API
18643		* calls (relaxng) do work, if the given type is a built-in
18644		* type, we will assume that the given built-in type *is
18645		* already* the base type.
18646		*/
18647		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18648		    base = typeDecl->baseType;
18649		    if (base == NULL) {
18650			PERROR_INT("xmlSchemaCheckFacet",
18651			    "a type user derived type has no base type");
18652			return (-1);
18653		    }
18654		} else
18655		    base = typeDecl;
18656
18657		if (! ctxtGiven) {
18658		    /*
18659		    * A context is needed if called from RelaxNG.
18660		    */
18661		    pctxt = xmlSchemaNewParserCtxt("*");
18662		    if (pctxt == NULL)
18663			return (-1);
18664		}
18665		/*
18666		* NOTE: This call does not check the content nodes,
18667		* since they are not available:
18668		* facet->node is just the node holding the facet
18669		* definition, *not* the attribute holding the *value*
18670		* of the facet.
18671		*/
18672		ret = xmlSchemaVCheckCVCSimpleType(
18673		    ACTXT_CAST pctxt, facet->node, base,
18674		    facet->value, &(facet->val), 1, 1, 0);
18675                if (ret != 0) {
18676		    if (ret < 0) {
18677			/* No error message for RelaxNG. */
18678			if (ctxtGiven) {
18679			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18680				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18681				"Internal error: xmlSchemaCheckFacet, "
18682				"failed to validate the value '%s' of the "
18683				"facet '%s' against the base type",
18684				facet->value, xmlSchemaFacetTypeToString(facet->type));
18685			}
18686			goto internal_error;
18687		    }
18688		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18689		    /* No error message for RelaxNG. */
18690		    if (ctxtGiven) {
18691			xmlChar *str = NULL;
18692
18693			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18694			    ret, facet->node, WXS_BASIC_CAST facet,
18695			    "The value '%s' of the facet does not validate "
18696			    "against the base type '%s'",
18697			    facet->value,
18698			    xmlSchemaFormatQName(&str,
18699				base->targetNamespace, base->name));
18700			FREE_AND_NULL(str);
18701		    }
18702		    goto exit;
18703                } else if (facet->val == NULL) {
18704		    if (ctxtGiven) {
18705			PERROR_INT("xmlSchemaCheckFacet",
18706			    "value was not computed");
18707		    }
18708		    TODO
18709		}
18710                break;
18711            }
18712        case XML_SCHEMA_FACET_PATTERN:
18713            facet->regexp = xmlRegexpCompile(facet->value);
18714            if (facet->regexp == NULL) {
18715		ret = XML_SCHEMAP_REGEXP_INVALID;
18716		/* No error message for RelaxNG. */
18717		if (ctxtGiven) {
18718		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18719			ret, facet->node, WXS_BASIC_CAST typeDecl,
18720			"The value '%s' of the facet 'pattern' is not a "
18721			"valid regular expression",
18722			facet->value, NULL);
18723		}
18724            }
18725            break;
18726        case XML_SCHEMA_FACET_TOTALDIGITS:
18727        case XML_SCHEMA_FACET_FRACTIONDIGITS:
18728        case XML_SCHEMA_FACET_LENGTH:
18729        case XML_SCHEMA_FACET_MAXLENGTH:
18730        case XML_SCHEMA_FACET_MINLENGTH:
18731
18732	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18733		ret = xmlSchemaValidatePredefinedType(
18734		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18735		    facet->value, &(facet->val));
18736	    } else {
18737		ret = xmlSchemaValidatePredefinedType(
18738		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18739		    facet->value, &(facet->val));
18740	    }
18741	    if (ret != 0) {
18742		if (ret < 0) {
18743		    /* No error message for RelaxNG. */
18744		    if (ctxtGiven) {
18745			PERROR_INT("xmlSchemaCheckFacet",
18746			    "validating facet value");
18747		    }
18748		    goto internal_error;
18749		}
18750		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18751		/* No error message for RelaxNG. */
18752		if (ctxtGiven) {
18753		    /* error code */
18754		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18755			ret, facet->node, WXS_BASIC_CAST typeDecl,
18756			"The value '%s' of the facet '%s' is not a valid '%s'",
18757			facet->value,
18758			xmlSchemaFacetTypeToString(facet->type),
18759			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18760			    BAD_CAST "nonNegativeInteger" :
18761			    BAD_CAST "positiveInteger",
18762			NULL);
18763		}
18764	    }
18765	    break;
18766
18767        case XML_SCHEMA_FACET_WHITESPACE:{
18768                if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18769                    facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18770                } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18771                    facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18772                } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18773                    facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18774                } else {
18775		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18776                    /* No error message for RelaxNG. */
18777		    if (ctxtGiven) {
18778			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18779			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18780			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18781			    "The value '%s' of the facet 'whitespace' is not "
18782			    "valid", facet->value, NULL);
18783                    }
18784                }
18785            }
18786        default:
18787            break;
18788    }
18789exit:
18790    if ((! ctxtGiven) && (pctxt != NULL))
18791	xmlSchemaFreeParserCtxt(pctxt);
18792    return (ret);
18793internal_error:
18794    if ((! ctxtGiven) && (pctxt != NULL))
18795	xmlSchemaFreeParserCtxt(pctxt);
18796    return (-1);
18797}
18798
18799/**
18800 * xmlSchemaCheckFacetValues:
18801 * @typeDecl:  the schema type definition
18802 * @ctxt:  the schema parser context
18803 *
18804 * Checks the default values types, especially for facets
18805 */
18806static int
18807xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18808			  xmlSchemaParserCtxtPtr pctxt)
18809{
18810    int res, olderrs = pctxt->nberrors;
18811    const xmlChar *name = typeDecl->name;
18812    /*
18813    * NOTE: It is intended to use the facets list, instead
18814    * of facetSet.
18815    */
18816    if (typeDecl->facets != NULL) {
18817	xmlSchemaFacetPtr facet = typeDecl->facets;
18818
18819	/*
18820	* Temporarily assign the "schema" to the validation context
18821	* of the parser context. This is needed for NOTATION validation.
18822	*/
18823	if (pctxt->vctxt == NULL) {
18824	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18825		return(-1);
18826	}
18827	pctxt->vctxt->schema = pctxt->schema;
18828	while (facet != NULL) {
18829	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18830	    HFAILURE
18831	    facet = facet->next;
18832	}
18833	pctxt->vctxt->schema = NULL;
18834    }
18835    if (olderrs != pctxt->nberrors)
18836	return(pctxt->err);
18837    return(0);
18838exit_failure:
18839    return(-1);
18840}
18841
18842/**
18843 * xmlSchemaGetCircModelGrDefRef:
18844 * @ctxtMGroup: the searched model group
18845 * @selfMGroup: the second searched model group
18846 * @particle: the first particle
18847 *
18848 * This one is intended to be used by
18849 * xmlSchemaCheckGroupDefCircular only.
18850 *
18851 * Returns the particle with the circular model group definition reference,
18852 * otherwise NULL.
18853 */
18854static xmlSchemaTreeItemPtr
18855xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18856			      xmlSchemaTreeItemPtr particle)
18857{
18858    xmlSchemaTreeItemPtr circ = NULL;
18859    xmlSchemaTreeItemPtr term;
18860    xmlSchemaModelGroupDefPtr gdef;
18861
18862    for (; particle != NULL; particle = particle->next) {
18863	term = particle->children;
18864	if (term == NULL)
18865	    continue;
18866	switch (term->type) {
18867	    case XML_SCHEMA_TYPE_GROUP:
18868		gdef = (xmlSchemaModelGroupDefPtr) term;
18869		if (gdef == groupDef)
18870		    return (particle);
18871		/*
18872		* Mark this model group definition to avoid infinite
18873		* recursion on circular references not yet examined.
18874		*/
18875		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18876		    continue;
18877		if (gdef->children != NULL) {
18878		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18879		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18880			gdef->children->children);
18881		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18882		    if (circ != NULL)
18883			return (circ);
18884		}
18885		break;
18886	    case XML_SCHEMA_TYPE_SEQUENCE:
18887	    case XML_SCHEMA_TYPE_CHOICE:
18888	    case XML_SCHEMA_TYPE_ALL:
18889		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18890		if (circ != NULL)
18891		    return (circ);
18892		break;
18893	    default:
18894		break;
18895	}
18896    }
18897    return (NULL);
18898}
18899
18900/**
18901 * xmlSchemaCheckGroupDefCircular:
18902 * @item:  the model group definition
18903 * @ctxt:  the parser context
18904 * @name:  the name
18905 *
18906 * Checks for circular references to model group definitions.
18907 */
18908static void
18909xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18910			       xmlSchemaParserCtxtPtr ctxt)
18911{
18912    /*
18913    * Schema Component Constraint: Model Group Correct
18914    * 2 Circular groups are disallowed. That is, within the {particles}
18915    * of a group there must not be at any depth a particle whose {term}
18916    * is the group itself.
18917    */
18918    if ((item == NULL) ||
18919	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18920	(item->children == NULL))
18921	return;
18922    {
18923	xmlSchemaTreeItemPtr circ;
18924
18925	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18926	if (circ != NULL) {
18927	    xmlChar *str = NULL;
18928	    /*
18929	    * TODO: The error report is not adequate: this constraint
18930	    * is defined for model groups but not definitions, but since
18931	    * there cannot be any circular model groups without a model group
18932	    * definition (if not using a construction API), we check those
18933	    * defintions only.
18934	    */
18935	    xmlSchemaPCustomErr(ctxt,
18936		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18937		NULL, WXS_ITEM_NODE(circ),
18938		"Circular reference to the model group definition '%s' "
18939		"defined", xmlSchemaFormatQName(&str,
18940		    item->targetNamespace, item->name));
18941	    FREE_AND_NULL(str)
18942	    /*
18943	    * NOTE: We will cut the reference to avoid further
18944	    * confusion of the processor. This is a fatal error.
18945	    */
18946	    circ->children = NULL;
18947	}
18948    }
18949}
18950
18951/**
18952 * xmlSchemaModelGroupToModelGroupDefFixup:
18953 * @ctxt:  the parser context
18954 * @mg:  the model group
18955 *
18956 * Assigns the model group of model group definitions to the "term"
18957 * of the referencing particle.
18958 * In xmlSchemaResolveModelGroupParticleReferences the model group
18959 * definitions were assigned to the "term", since needed for the
18960 * circularity check.
18961 *
18962 * Schema Component Constraint:
18963 *     All Group Limited (cos-all-limited) (1.2)
18964 */
18965static void
18966xmlSchemaModelGroupToModelGroupDefFixup(
18967    xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18968    xmlSchemaModelGroupPtr mg)
18969{
18970    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18971
18972    while (particle != NULL) {
18973	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18974	    ((WXS_PARTICLE_TERM(particle))->type !=
18975		XML_SCHEMA_TYPE_GROUP))
18976	{
18977	    particle = WXS_PTC_CAST particle->next;
18978	    continue;
18979	}
18980	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18981	    /*
18982	    * TODO: Remove the particle.
18983	    */
18984	    WXS_PARTICLE_TERM(particle) = NULL;
18985	    particle = WXS_PTC_CAST particle->next;
18986	    continue;
18987	}
18988	/*
18989	* Assign the model group to the {term} of the particle.
18990	*/
18991	WXS_PARTICLE_TERM(particle) =
18992	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18993
18994	particle = WXS_PTC_CAST particle->next;
18995    }
18996}
18997
18998/**
18999 * xmlSchemaCheckAttrGroupCircularRecur:
19000 * @ctxtGr: the searched attribute group
19001 * @attr: the current attribute list to be processed
19002 *
19003 * This one is intended to be used by
19004 * xmlSchemaCheckAttrGroupCircular only.
19005 *
19006 * Returns the circular attribute grou reference, otherwise NULL.
19007 */
19008static xmlSchemaQNameRefPtr
19009xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19010				     xmlSchemaItemListPtr list)
19011{
19012    xmlSchemaAttributeGroupPtr gr;
19013    xmlSchemaQNameRefPtr ref, circ;
19014    int i;
19015    /*
19016    * We will search for an attribute group reference which
19017    * references the context attribute group.
19018    */
19019    for (i = 0; i < list->nbItems; i++) {
19020	ref = list->items[i];
19021	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19022	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19023	    (ref->item != NULL))
19024	{
19025	    gr = WXS_ATTR_GROUP_CAST ref->item;
19026	    if (gr == ctxtGr)
19027		return(ref);
19028	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19029		continue;
19030	    /*
19031	    * Mark as visited to avoid infinite recursion on
19032	    * circular references not yet examined.
19033	    */
19034	    if ((gr->attrUses) &&
19035		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19036	    {
19037		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19038		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19039		    (xmlSchemaItemListPtr) gr->attrUses);
19040		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19041		if (circ != NULL)
19042		    return (circ);
19043	    }
19044
19045	}
19046    }
19047    return (NULL);
19048}
19049
19050/**
19051 * xmlSchemaCheckAttrGroupCircular:
19052 * attrGr:  the attribute group definition
19053 * @ctxt:  the parser context
19054 * @name:  the name
19055 *
19056 * Checks for circular references of attribute groups.
19057 */
19058static int
19059xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19060				xmlSchemaParserCtxtPtr ctxt)
19061{
19062    /*
19063    * Schema Representation Constraint:
19064    * Attribute Group Definition Representation OK
19065    * 3 Circular group reference is disallowed outside <redefine>.
19066    * That is, unless this element information item's parent is
19067    * <redefine>, then among the [children], if any, there must
19068    * not be an <attributeGroup> with ref [attribute] which resolves
19069    * to the component corresponding to this <attributeGroup>. Indirect
19070    * circularity is also ruled out. That is, when QName resolution
19071    * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19072    * any <attributeGroup>s with a ref [attribute] among the [children],
19073    * it must not be the case that a �QName� is encountered at any depth
19074    * which resolves to the component corresponding to this <attributeGroup>.
19075    */
19076    if (attrGr->attrUses == NULL)
19077	return(0);
19078    else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19079	return(0);
19080    else {
19081	xmlSchemaQNameRefPtr circ;
19082
19083	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19084	    (xmlSchemaItemListPtr) attrGr->attrUses);
19085	if (circ != NULL) {
19086	    xmlChar *str = NULL;
19087	    /*
19088	    * TODO: Report the referenced attr group as QName.
19089	    */
19090	    xmlSchemaPCustomErr(ctxt,
19091		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19092		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19093		"Circular reference to the attribute group '%s' "
19094		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19095	    FREE_AND_NULL(str);
19096	    /*
19097	    * NOTE: We will cut the reference to avoid further
19098	    * confusion of the processor.
19099	    * BADSPEC TODO: The spec should define how to process in this case.
19100	    */
19101	    circ->item = NULL;
19102	    return(ctxt->err);
19103	}
19104    }
19105    return(0);
19106}
19107
19108static int
19109xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19110				  xmlSchemaAttributeGroupPtr attrGr);
19111
19112/**
19113 * xmlSchemaExpandAttributeGroupRefs:
19114 * @pctxt: the parser context
19115 * @node: the node of the component holding the attribute uses
19116 * @completeWild: the intersected wildcard to be returned
19117 * @list: the attribute uses
19118 *
19119 * Substitutes contained attribute group references
19120 * for their attribute uses. Wilcards are intersected.
19121 * Attribute use prohibitions are removed from the list
19122 * and returned via the @prohibs list.
19123 * Pointlessness of attr. prohibs, if a matching attr. decl
19124 * is existent a well, are checked.
19125 */
19126static int
19127xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19128				  xmlSchemaBasicItemPtr item,
19129				  xmlSchemaWildcardPtr *completeWild,
19130				  xmlSchemaItemListPtr list,
19131				  xmlSchemaItemListPtr prohibs)
19132{
19133    xmlSchemaAttributeGroupPtr gr;
19134    xmlSchemaAttributeUsePtr use;
19135    xmlSchemaItemListPtr sublist;
19136    int i, j;
19137    int created = (*completeWild == NULL) ? 0 : 1;
19138
19139    if (prohibs)
19140	prohibs->nbItems = 0;
19141
19142    for (i = 0; i < list->nbItems; i++) {
19143	use = list->items[i];
19144
19145	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19146	    if (prohibs == NULL) {
19147		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19148		    "unexpected attr prohibition found");
19149		return(-1);
19150	    }
19151	    /*
19152	    * Remove from attribute uses.
19153	    */
19154	    if (xmlSchemaItemListRemove(list, i) == -1)
19155		return(-1);
19156	    i--;
19157	    /*
19158	    * Note that duplicate prohibitions were already
19159	    * handled at parsing time.
19160	    */
19161	    /*
19162	    * Add to list of prohibitions.
19163	    */
19164	    xmlSchemaItemListAddSize(prohibs, 2, use);
19165	    continue;
19166	}
19167	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19168	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19169	{
19170	    if ((WXS_QNAME_CAST use)->item == NULL)
19171		return(-1);
19172	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19173	    /*
19174	    * Expand the referenced attr. group.
19175	    * TODO: remove this, this is done in a previous step, so
19176	    * already done here.
19177	    */
19178	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19179		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19180		    return(-1);
19181	    }
19182	    /*
19183	    * Build the 'complete' wildcard; i.e. intersect multiple
19184	    * wildcards.
19185	    */
19186	    if (gr->attributeWildcard != NULL) {
19187		if (*completeWild == NULL) {
19188		    *completeWild = gr->attributeWildcard;
19189		} else {
19190		    if (! created) {
19191			xmlSchemaWildcardPtr tmpWild;
19192
19193			 /*
19194			* Copy the first encountered wildcard as context,
19195			* except for the annotation.
19196			*
19197			* Although the complete wildcard might not correspond
19198			* to any node in the schema, we will anchor it on
19199			* the node of the owner component.
19200			*/
19201			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19202			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19203			    WXS_ITEM_NODE(item));
19204			if (tmpWild == NULL)
19205			    return(-1);
19206			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19207			    tmpWild, *completeWild) == -1)
19208			    return (-1);
19209			tmpWild->processContents = (*completeWild)->processContents;
19210			*completeWild = tmpWild;
19211			created = 1;
19212		    }
19213
19214		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19215			gr->attributeWildcard) == -1)
19216			return(-1);
19217		}
19218	    }
19219	    /*
19220	    * Just remove the reference if the referenced group does not
19221	    * contain any attribute uses.
19222	    */
19223	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19224	    if ((sublist == NULL) || sublist->nbItems == 0) {
19225		if (xmlSchemaItemListRemove(list, i) == -1)
19226		    return(-1);
19227		i--;
19228		continue;
19229	    }
19230	    /*
19231	    * Add the attribute uses.
19232	    */
19233	    list->items[i] = sublist->items[0];
19234	    if (sublist->nbItems != 1) {
19235		for (j = 1; j < sublist->nbItems; j++) {
19236		    i++;
19237		    if (xmlSchemaItemListInsert(list,
19238			    sublist->items[j], i) == -1)
19239			return(-1);
19240		}
19241	    }
19242	}
19243
19244    }
19245    /*
19246    * Handle pointless prohibitions of declared attributes.
19247    */
19248    if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19249	xmlSchemaAttributeUseProhibPtr prohib;
19250
19251	for (i = prohibs->nbItems -1; i >= 0; i--) {
19252	    prohib = prohibs->items[i];
19253	    for (j = 0; j < list->nbItems; j++) {
19254		use = list->items[j];
19255
19256		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19257		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19258		{
19259		    xmlChar *str = NULL;
19260
19261		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19262			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19263			prohib->node, NULL,
19264			"Skipping pointless attribute use prohibition "
19265			"'%s', since a corresponding attribute use "
19266			"exists already in the type definition",
19267			xmlSchemaFormatQName(&str,
19268			    prohib->targetNamespace, prohib->name),
19269			NULL, NULL);
19270		    FREE_AND_NULL(str);
19271		    /*
19272		    * Remove the prohibition.
19273		    */
19274		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19275			return(-1);
19276		    break;
19277		}
19278	    }
19279	}
19280    }
19281    return(0);
19282}
19283
19284/**
19285 * xmlSchemaAttributeGroupExpandRefs:
19286 * @pctxt:  the parser context
19287 * @attrGr:  the attribute group definition
19288 *
19289 * Computation of:
19290 * {attribute uses} property
19291 * {attribute wildcard} property
19292 *
19293 * Substitutes contained attribute group references
19294 * for their attribute uses. Wilcards are intersected.
19295 */
19296static int
19297xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19298				  xmlSchemaAttributeGroupPtr attrGr)
19299{
19300    if ((attrGr->attrUses == NULL) ||
19301	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19302	return(0);
19303
19304    attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19305    if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19306	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19307	return(-1);
19308    return(0);
19309}
19310
19311/**
19312 * xmlSchemaAttributeGroupExpandRefs:
19313 * @pctxt:  the parser context
19314 * @attrGr:  the attribute group definition
19315 *
19316 * Substitutes contained attribute group references
19317 * for their attribute uses. Wilcards are intersected.
19318 *
19319 * Schema Component Constraint:
19320 *    Attribute Group Definition Properties Correct (ag-props-correct)
19321 */
19322static int
19323xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19324				  xmlSchemaAttributeGroupPtr attrGr)
19325{
19326    /*
19327    * SPEC ag-props-correct
19328    * (1) "The values of the properties of an attribute group definition
19329    * must be as described in the property tableau in The Attribute
19330    * Group Definition Schema Component (�3.6.1), modulo the impact of
19331    * Missing Sub-components (�5.3);"
19332    */
19333
19334    if ((attrGr->attrUses != NULL) &&
19335	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19336    {
19337	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19338	xmlSchemaAttributeUsePtr use, tmp;
19339	int i, j, hasId = 0;
19340
19341	for (i = uses->nbItems -1; i >= 0; i--) {
19342	    use = uses->items[i];
19343	    /*
19344	    * SPEC ag-props-correct
19345	    * (2) "Two distinct members of the {attribute uses} must not have
19346	    * {attribute declaration}s both of whose {name}s match and whose
19347	    * {target namespace}s are identical."
19348	    */
19349	    if (i > 0) {
19350		for (j = i -1; j >= 0; j--) {
19351		    tmp = uses->items[j];
19352		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19353			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19354			(WXS_ATTRUSE_DECL_TNS(use) ==
19355			WXS_ATTRUSE_DECL_TNS(tmp)))
19356		    {
19357			xmlChar *str = NULL;
19358
19359			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19360			    XML_SCHEMAP_AG_PROPS_CORRECT,
19361			    attrGr->node, WXS_BASIC_CAST attrGr,
19362			    "Duplicate %s",
19363			    xmlSchemaGetComponentDesignation(&str, use),
19364			    NULL);
19365			FREE_AND_NULL(str);
19366			/*
19367			* Remove the duplicate.
19368			*/
19369			if (xmlSchemaItemListRemove(uses, i) == -1)
19370			    return(-1);
19371			goto next_use;
19372		    }
19373		}
19374	    }
19375	    /*
19376	    * SPEC ag-props-correct
19377	    * (3) "Two distinct members of the {attribute uses} must not have
19378	    * {attribute declaration}s both of whose {type definition}s are or
19379	    * are derived from ID."
19380	    * TODO: Does 'derived' include member-types of unions?
19381	    */
19382	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19383		if (xmlSchemaIsDerivedFromBuiltInType(
19384		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19385		{
19386		    if (hasId) {
19387			xmlChar *str = NULL;
19388
19389			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19390			    XML_SCHEMAP_AG_PROPS_CORRECT,
19391			    attrGr->node, WXS_BASIC_CAST attrGr,
19392			    "There must not exist more than one attribute "
19393			    "declaration of type 'xs:ID' "
19394			    "(or derived from 'xs:ID'). The %s violates this "
19395			    "constraint",
19396			    xmlSchemaGetComponentDesignation(&str, use),
19397			    NULL);
19398			FREE_AND_NULL(str);
19399			if (xmlSchemaItemListRemove(uses, i) == -1)
19400			    return(-1);
19401		    }
19402		    hasId = 1;
19403		}
19404	    }
19405next_use: {}
19406	}
19407    }
19408    return(0);
19409}
19410
19411/**
19412 * xmlSchemaResolveAttrGroupReferences:
19413 * @attrgrpDecl:  the schema attribute definition
19414 * @ctxt:  the schema parser context
19415 * @name:  the attribute name
19416 *
19417 * Resolves references to attribute group definitions.
19418 */
19419static int
19420xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19421				    xmlSchemaParserCtxtPtr ctxt)
19422{
19423    xmlSchemaAttributeGroupPtr group;
19424
19425    if (ref->item != NULL)
19426        return(0);
19427    group = xmlSchemaGetAttributeGroup(ctxt->schema,
19428	ref->name,
19429	ref->targetNamespace);
19430    if (group == NULL) {
19431	xmlSchemaPResCompAttrErr(ctxt,
19432	    XML_SCHEMAP_SRC_RESOLVE,
19433	    NULL, ref->node,
19434	    "ref", ref->name, ref->targetNamespace,
19435	    ref->itemType, NULL);
19436	return(ctxt->err);
19437    }
19438    ref->item = WXS_BASIC_CAST group;
19439    return(0);
19440}
19441
19442/**
19443 * xmlSchemaCheckAttrPropsCorrect:
19444 * @item:  an schema attribute declaration/use
19445 * @ctxt:  a schema parser context
19446 * @name:  the name of the attribute
19447 *
19448 *
19449 * Schema Component Constraint:
19450 *    Attribute Declaration Properties Correct (a-props-correct)
19451 *
19452 * Validates the value constraints of an attribute declaration/use.
19453 * NOTE that this needs the simle type definitions to be already
19454 *   builded and checked.
19455 */
19456static int
19457xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19458			       xmlSchemaAttributePtr attr)
19459{
19460
19461    /*
19462    * SPEC a-props-correct (1)
19463    * "The values of the properties of an attribute declaration must
19464    * be as described in the property tableau in The Attribute
19465    * Declaration Schema Component (�3.2.1), modulo the impact of
19466    * Missing Sub-components (�5.3)."
19467    */
19468
19469    if (WXS_ATTR_TYPEDEF(attr) == NULL)
19470	return(0);
19471
19472    if (attr->defValue != NULL) {
19473	int ret;
19474
19475	/*
19476	* SPEC a-props-correct (3)
19477	* "If the {type definition} is or is derived from ID then there
19478	* must not be a {value constraint}."
19479	*/
19480	if (xmlSchemaIsDerivedFromBuiltInType(
19481	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19482	{
19483	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19484		XML_SCHEMAP_A_PROPS_CORRECT_3,
19485		NULL, WXS_BASIC_CAST attr,
19486		"Value constraints are not allowed if the type definition "
19487		"is or is derived from xs:ID",
19488		NULL, NULL);
19489	    return(pctxt->err);
19490	}
19491	/*
19492	* SPEC a-props-correct (2)
19493	* "if there is a {value constraint}, the canonical lexical
19494	* representation of its value must be �valid� with respect
19495	* to the {type definition} as defined in String Valid (�3.14.4)."
19496	* TODO: Don't care about the *cononical* stuff here, this requirement
19497	* will be removed in WXS 1.1 anyway.
19498	*/
19499	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19500	    attr->node, WXS_ATTR_TYPEDEF(attr),
19501	    attr->defValue, &(attr->defVal),
19502	    1, 1, 0);
19503	if (ret != 0) {
19504	    if (ret < 0) {
19505		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19506		    "calling xmlSchemaVCheckCVCSimpleType()");
19507		return(-1);
19508	    }
19509	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19510		XML_SCHEMAP_A_PROPS_CORRECT_2,
19511		NULL, WXS_BASIC_CAST attr,
19512		"The value of the value constraint is not valid",
19513		NULL, NULL);
19514	    return(pctxt->err);
19515	}
19516    }
19517
19518    return(0);
19519}
19520
19521static xmlSchemaElementPtr
19522xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19523				 xmlSchemaElementPtr ancestor)
19524{
19525    xmlSchemaElementPtr ret;
19526
19527    if (WXS_SUBST_HEAD(ancestor) == NULL)
19528	return (NULL);
19529    if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19530	return (ancestor);
19531
19532    if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19533	return (NULL);
19534    WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19535    ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19536	WXS_SUBST_HEAD(ancestor));
19537    WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19538
19539    return (ret);
19540}
19541
19542/**
19543 * xmlSchemaCheckElemPropsCorrect:
19544 * @ctxt:  a schema parser context
19545 * @decl: the element declaration
19546 * @name:  the name of the attribute
19547 *
19548 * Schema Component Constraint:
19549 * Element Declaration Properties Correct (e-props-correct)
19550 *
19551 * STATUS:
19552 *   missing: (6)
19553 */
19554static int
19555xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19556			       xmlSchemaElementPtr elemDecl)
19557{
19558    int ret = 0;
19559    xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19560    /*
19561    * SPEC (1) "The values of the properties of an element declaration
19562    * must be as described in the property tableau in The Element
19563    * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19564    * Sub-components (�5.3)."
19565    */
19566    if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19567	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19568
19569	xmlSchemaCheckElementDeclComponent(head, pctxt);
19570	/*
19571	* SPEC (3) "If there is a non-�absent� {substitution group
19572	* affiliation}, then {scope} must be global."
19573	*/
19574	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19575	    xmlSchemaPCustomErr(pctxt,
19576		XML_SCHEMAP_E_PROPS_CORRECT_3,
19577		WXS_BASIC_CAST elemDecl, NULL,
19578		"Only global element declarations can have a "
19579		"substitution group affiliation", NULL);
19580	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19581	}
19582	/*
19583	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19584	* That is, it must not be possible to return to an element declaration
19585	* by repeatedly following the {substitution group affiliation}
19586	* property."
19587	*/
19588	if (head == elemDecl)
19589	    circ = head;
19590	else if (WXS_SUBST_HEAD(head) != NULL)
19591	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19592	else
19593	    circ = NULL;
19594	if (circ != NULL) {
19595	    xmlChar *strA = NULL, *strB = NULL;
19596
19597	    xmlSchemaPCustomErrExt(pctxt,
19598		XML_SCHEMAP_E_PROPS_CORRECT_6,
19599		WXS_BASIC_CAST circ, NULL,
19600		"The element declaration '%s' defines a circular "
19601		"substitution group to element declaration '%s'",
19602		xmlSchemaGetComponentQName(&strA, circ),
19603		xmlSchemaGetComponentQName(&strB, head),
19604		NULL);
19605	    FREE_AND_NULL(strA)
19606	    FREE_AND_NULL(strB)
19607	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19608	}
19609	/*
19610	* SPEC (4) "If there is a {substitution group affiliation},
19611	* the {type definition}
19612	* of the element declaration must be validly derived from the {type
19613	* definition} of the {substitution group affiliation}, given the value
19614	* of the {substitution group exclusions} of the {substitution group
19615	* affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19616	* (if the {type definition} is complex) or as defined in
19617	* Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19618	* simple)."
19619	*
19620	* NOTE: {substitution group exclusions} means the values of the
19621	* attribute "final".
19622	*/
19623
19624	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19625	    int set = 0;
19626
19627	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19628		set |= SUBSET_EXTENSION;
19629	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19630		set |= SUBSET_RESTRICTION;
19631
19632	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19633		WXS_ELEM_TYPEDEF(head), set) != 0) {
19634		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19635
19636		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19637		xmlSchemaPCustomErrExt(pctxt,
19638		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19639		    WXS_BASIC_CAST elemDecl, NULL,
19640		    "The type definition '%s' was "
19641		    "either rejected by the substitution group "
19642		    "affiliation '%s', or not validly derived from its type "
19643		    "definition '%s'",
19644		    xmlSchemaGetComponentQName(&strA, typeDef),
19645		    xmlSchemaGetComponentQName(&strB, head),
19646		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19647		FREE_AND_NULL(strA)
19648		FREE_AND_NULL(strB)
19649		FREE_AND_NULL(strC)
19650	    }
19651	}
19652    }
19653    /*
19654    * SPEC (5) "If the {type definition} or {type definition}'s
19655    * {content type}
19656    * is or is derived from ID then there must not be a {value constraint}.
19657    * Note: The use of ID as a type definition for elements goes beyond
19658    * XML 1.0, and should be avoided if backwards compatibility is desired"
19659    */
19660    if ((elemDecl->value != NULL) &&
19661	((WXS_IS_SIMPLE(typeDef) &&
19662	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19663	 (WXS_IS_COMPLEX(typeDef) &&
19664	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19665	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19666	    XML_SCHEMAS_ID)))) {
19667
19668	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19669	xmlSchemaPCustomErr(pctxt,
19670	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19671	    WXS_BASIC_CAST elemDecl, NULL,
19672	    "The type definition (or type definition's content type) is or "
19673	    "is derived from ID; value constraints are not allowed in "
19674	    "conjunction with such a type definition", NULL);
19675    } else if (elemDecl->value != NULL) {
19676	int vcret;
19677	xmlNodePtr node = NULL;
19678
19679	/*
19680	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19681	* representation of its value must be �valid� with respect to the
19682	* {type definition} as defined in Element Default Valid (Immediate)
19683	* (�3.3.6)."
19684	*/
19685	if (typeDef == NULL) {
19686	    xmlSchemaPErr(pctxt, elemDecl->node,
19687		XML_SCHEMAP_INTERNAL,
19688		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19689		"type is missing... skipping validation of "
19690		"the value constraint", NULL, NULL);
19691	    return (-1);
19692	}
19693	if (elemDecl->node != NULL) {
19694	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19695		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19696		    BAD_CAST "fixed");
19697	    else
19698		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19699		    BAD_CAST "default");
19700	}
19701	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19702	    typeDef, elemDecl->value, &(elemDecl->defVal));
19703	if (vcret != 0) {
19704	    if (vcret < 0) {
19705		PERROR_INT("xmlSchemaElemCheckValConstr",
19706		    "failed to validate the value constraint of an "
19707		    "element declaration");
19708		return (-1);
19709	    }
19710	    return (vcret);
19711	}
19712    }
19713
19714    return (ret);
19715}
19716
19717/**
19718 * xmlSchemaCheckElemSubstGroup:
19719 * @ctxt:  a schema parser context
19720 * @decl: the element declaration
19721 * @name:  the name of the attribute
19722 *
19723 * Schema Component Constraint:
19724 * Substitution Group (cos-equiv-class)
19725 *
19726 * In Libxml2 the subst. groups will be precomputed, in terms of that
19727 * a list will be built for each subst. group head, holding all direct
19728 * referents to this head.
19729 * NOTE that this function needs:
19730 *   1. circular subst. groups to be checked beforehand
19731 *   2. the declaration's type to be derived from the head's type
19732 *
19733 * STATUS:
19734 *
19735 */
19736static void
19737xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19738			     xmlSchemaElementPtr elemDecl)
19739{
19740    if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19741	/* SPEC (1) "Its {abstract} is false." */
19742	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19743	return;
19744    {
19745	xmlSchemaElementPtr head;
19746	xmlSchemaTypePtr headType, type;
19747	int set, methSet;
19748	/*
19749	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19750	* {disallowed substitutions} as the blocking constraint, as defined in
19751	* Substitution Group OK (Transitive) (�3.3.6)."
19752	*/
19753	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19754	    head = WXS_SUBST_HEAD(head)) {
19755	    set = 0;
19756	    methSet = 0;
19757	    /*
19758	    * The blocking constraints.
19759	    */
19760	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19761		continue;
19762	    headType = head->subtypes;
19763	    type = elemDecl->subtypes;
19764	    if (headType == type)
19765		goto add_member;
19766	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19767		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19768	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19769		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19770	    /*
19771	    * SPEC: Substitution Group OK (Transitive) (2.3)
19772	    * "The set of all {derivation method}s involved in the
19773	    * derivation of D's {type definition} from C's {type definition}
19774	    * does not intersect with the union of the blocking constraint,
19775	    * C's {prohibited substitutions} (if C is complex, otherwise the
19776	    * empty set) and the {prohibited substitutions} (respectively the
19777	    * empty set) of any intermediate {type definition}s in the
19778	    * derivation of D's {type definition} from C's {type definition}."
19779	    */
19780	    /*
19781	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19782	    * subst.head axis, the methSet does not need to be computed for
19783	    * the full depth over and over.
19784	    */
19785	    /*
19786	    * The set of all {derivation method}s involved in the derivation
19787	    */
19788	    while ((type != NULL) && (type != headType)) {
19789		if ((WXS_IS_EXTENSION(type)) &&
19790		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19791		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19792
19793		if (WXS_IS_RESTRICTION(type) &&
19794		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19795		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19796
19797		type = type->baseType;
19798	    }
19799	    /*
19800	    * The {prohibited substitutions} of all intermediate types +
19801	    * the head's type.
19802	    */
19803	    type = elemDecl->subtypes->baseType;
19804	    while (type != NULL) {
19805		if (WXS_IS_COMPLEX(type)) {
19806		    if ((type->flags &
19807			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19808			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19809		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19810		    if ((type->flags &
19811			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19812			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19813		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19814		} else
19815		    break;
19816		if (type == headType)
19817		    break;
19818		type = type->baseType;
19819	    }
19820	    if ((set != 0) &&
19821		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19822		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19823		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19824		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19825		continue;
19826	    }
19827add_member:
19828	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19829	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19830		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19831	}
19832    }
19833}
19834
19835#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19836/**
19837 * xmlSchemaCheckElementDeclComponent
19838 * @pctxt: the schema parser context
19839 * @ctxtComponent: the context component (an element declaration)
19840 * @ctxtParticle: the first particle of the context component
19841 * @searchParticle: the element declaration particle to be analysed
19842 *
19843 * Schema Component Constraint: Element Declarations Consistent
19844 */
19845static int
19846xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19847				    xmlSchemaBasicItemPtr ctxtComponent,
19848				    xmlSchemaParticlePtr ctxtParticle,
19849				    xmlSchemaParticlePtr searchParticle,
19850				    xmlSchemaParticlePtr curParticle,
19851				    int search)
19852{
19853    return(0);
19854
19855    int ret = 0;
19856    xmlSchemaParticlePtr cur = curParticle;
19857    if (curParticle == NULL) {
19858	return(0);
19859    }
19860    if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19861	/*
19862	* Just return in this case. A missing "term" of the particle
19863	* might arise due to an invalid "term" component.
19864	*/
19865	return(0);
19866    }
19867    while (cur != NULL) {
19868	switch (WXS_PARTICLE_TERM(cur)->type) {
19869	    case XML_SCHEMA_TYPE_ANY:
19870		break;
19871	    case XML_SCHEMA_TYPE_ELEMENT:
19872		if (search == 0) {
19873		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19874			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19875		    if (ret != 0)
19876			return(ret);
19877		} else {
19878		    xmlSchemaElementPtr elem =
19879			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19880		    /*
19881		    * SPEC Element Declarations Consistent:
19882		    * "If the {particles} contains, either directly,
19883		    * indirectly (that is, within the {particles} of a
19884		    * contained model group, recursively) or �implicitly�
19885		    * two or more element declaration particles with
19886		    * the same {name} and {target namespace}, then
19887		    * all their type definitions must be the same
19888		    * top-level definition [...]"
19889		    */
19890		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19891			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19892			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19893			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19894		    {
19895			xmlChar *strA = NULL, *strB = NULL;
19896
19897			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19898			    /* TODO: error code */
19899			    XML_SCHEMAP_COS_NONAMBIG,
19900			    WXS_ITEM_NODE(cur), NULL,
19901			    "In the content model of %s, there are multiple "
19902			    "element declarations for '%s' with different "
19903			    "type definitions",
19904			    xmlSchemaGetComponentDesignation(&strA,
19905				ctxtComponent),
19906			    xmlSchemaFormatQName(&strB,
19907				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19908				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19909			FREE_AND_NULL(strA);
19910			FREE_AND_NULL(strB);
19911			return(XML_SCHEMAP_COS_NONAMBIG);
19912		    }
19913		}
19914		break;
19915	    case XML_SCHEMA_TYPE_SEQUENCE: {
19916		break;
19917		}
19918	    case XML_SCHEMA_TYPE_CHOICE:{
19919		/*
19920		xmlSchemaTreeItemPtr sub;
19921
19922		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19923		while (sub != NULL) {
19924		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19925			ctxtParticle, ctxtElem);
19926		    if (ret != 0)
19927			return(ret);
19928		    sub = sub->next;
19929		}
19930		*/
19931		break;
19932		}
19933	    case XML_SCHEMA_TYPE_ALL:
19934		break;
19935	    case XML_SCHEMA_TYPE_GROUP:
19936		break;
19937	    default:
19938		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19939		    "xmlSchemaCheckElementDeclConsistent",
19940		    "found unexpected term of type '%s' in content model",
19941		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19942		return(-1);
19943	}
19944	cur = (xmlSchemaParticlePtr) cur->next;
19945    }
19946
19947exit:
19948    return(ret);
19949}
19950#endif
19951
19952/**
19953 * xmlSchemaCheckElementDeclComponent
19954 * @item:  an schema element declaration/particle
19955 * @ctxt:  a schema parser context
19956 * @name:  the name of the attribute
19957 *
19958 * Validates the value constraints of an element declaration.
19959 * Adds substitution group members.
19960 */
19961static void
19962xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19963				   xmlSchemaParserCtxtPtr ctxt)
19964{
19965    if (elemDecl == NULL)
19966	return;
19967    if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19968	return;
19969    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19970    if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19971	/*
19972	* Adds substitution group members.
19973	*/
19974	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19975    }
19976}
19977
19978/**
19979 * xmlSchemaResolveModelGroupParticleReferences:
19980 * @particle:  a particle component
19981 * @ctxt:  a parser context
19982 *
19983 * Resolves references of a model group's {particles} to
19984 * model group definitions and to element declarations.
19985 */
19986static void
19987xmlSchemaResolveModelGroupParticleReferences(
19988    xmlSchemaParserCtxtPtr ctxt,
19989    xmlSchemaModelGroupPtr mg)
19990{
19991    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19992    xmlSchemaQNameRefPtr ref;
19993    xmlSchemaBasicItemPtr refItem;
19994
19995    /*
19996    * URGENT TODO: Test this.
19997    */
19998    while (particle != NULL) {
19999	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20000	    ((WXS_PARTICLE_TERM(particle))->type !=
20001		XML_SCHEMA_EXTRA_QNAMEREF))
20002	{
20003	    goto next_particle;
20004	}
20005	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20006	/*
20007	* Resolve the reference.
20008	* NULL the {term} by default.
20009	*/
20010	particle->children = NULL;
20011
20012	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20013	    ref->itemType, ref->name, ref->targetNamespace);
20014	if (refItem == NULL) {
20015	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20016		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20017		ref->targetNamespace, ref->itemType, NULL);
20018	    /* TODO: remove the particle. */
20019	    goto next_particle;
20020	}
20021	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20022	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20023		/* TODO: remove the particle. */
20024		goto next_particle;
20025	    /*
20026	    * NOTE that we will assign the model group definition
20027	    * itself to the "term" of the particle. This will ease
20028	    * the check for circular model group definitions. After
20029	    * that the "term" will be assigned the model group of the
20030	    * model group definition.
20031	    */
20032	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20033		    XML_SCHEMA_TYPE_ALL) {
20034		/*
20035		* SPEC cos-all-limited (1)
20036		* SPEC cos-all-limited (1.2)
20037		* "It appears only as the value of one or both of the
20038		* following properties:"
20039		* (1.1) "the {model group} property of a model group
20040		*        definition."
20041		* (1.2) "the {term} property of a particle [... of] the "
20042		* {content type} of a complex type definition."
20043		*/
20044		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20045		    /* TODO: error code */
20046		    XML_SCHEMAP_COS_ALL_LIMITED,
20047		    WXS_ITEM_NODE(particle), NULL,
20048		    "A model group definition is referenced, but "
20049		    "it contains an 'all' model group, which "
20050		    "cannot be contained by model groups",
20051		    NULL, NULL);
20052		/* TODO: remove the particle. */
20053		goto next_particle;
20054	    }
20055	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20056	} else {
20057	    /*
20058	    * TODO: Are referenced element declarations the only
20059	    * other components we expect here?
20060	    */
20061	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20062	}
20063next_particle:
20064	particle = WXS_PTC_CAST particle->next;
20065    }
20066}
20067
20068static int
20069xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20070		       xmlSchemaValPtr y)
20071{
20072    xmlSchemaTypePtr tx, ty, ptx, pty;
20073    int ret;
20074
20075    while (x != NULL) {
20076	/* Same types. */
20077	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20078	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20079	ptx = xmlSchemaGetPrimitiveType(tx);
20080	pty = xmlSchemaGetPrimitiveType(ty);
20081	/*
20082	* (1) if a datatype T' is �derived� by �restriction� from an
20083	* atomic datatype T then the �value space� of T' is a subset of
20084	* the �value space� of T. */
20085	/*
20086	* (2) if datatypes T' and T'' are �derived� by �restriction�
20087	* from a common atomic ancestor T then the �value space�s of T'
20088	* and T'' may overlap.
20089	*/
20090	if (ptx != pty)
20091	    return(0);
20092	/*
20093	* We assume computed values to be normalized, so do a fast
20094	* string comparison for string based types.
20095	*/
20096	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20097	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20098	    if (! xmlStrEqual(
20099		xmlSchemaValueGetAsString(x),
20100		xmlSchemaValueGetAsString(y)))
20101		return (0);
20102	} else {
20103	    ret = xmlSchemaCompareValuesWhtsp(
20104		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20105		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20106	    if (ret == -2)
20107		return(-1);
20108	    if (ret != 0)
20109		return(0);
20110	}
20111	/*
20112	* Lists.
20113	*/
20114	x = xmlSchemaValueGetNext(x);
20115	if (x != NULL) {
20116	    y = xmlSchemaValueGetNext(y);
20117	    if (y == NULL)
20118		return (0);
20119	} else if (xmlSchemaValueGetNext(y) != NULL)
20120	    return (0);
20121	else
20122	    return (1);
20123    }
20124    return (0);
20125}
20126
20127/**
20128 * xmlSchemaResolveAttrUseReferences:
20129 * @item:  an attribute use
20130 * @ctxt:  a parser context
20131 *
20132 * Resolves the referenced attribute declaration.
20133 */
20134static int
20135xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20136				  xmlSchemaParserCtxtPtr ctxt)
20137{
20138    if ((ctxt == NULL) || (ause == NULL))
20139	return(-1);
20140    if ((ause->attrDecl == NULL) ||
20141	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20142	return(0);
20143
20144    {
20145	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20146
20147	/*
20148	* TODO: Evaluate, what errors could occur if the declaration is not
20149	* found.
20150	*/
20151	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20152	    ref->name, ref->targetNamespace);
20153        if (ause->attrDecl == NULL) {
20154	    xmlSchemaPResCompAttrErr(ctxt,
20155	    	XML_SCHEMAP_SRC_RESOLVE,
20156		WXS_BASIC_CAST ause, ause->node,
20157		"ref", ref->name, ref->targetNamespace,
20158		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20159            return(ctxt->err);;
20160        }
20161    }
20162    return(0);
20163}
20164
20165/**
20166 * xmlSchemaCheckAttrUsePropsCorrect:
20167 * @ctxt:  a parser context
20168 * @use:  an attribute use
20169 *
20170 * Schema Component Constraint:
20171 * Attribute Use Correct (au-props-correct)
20172 *
20173 */
20174static int
20175xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20176			     xmlSchemaAttributeUsePtr use)
20177{
20178    if ((ctxt == NULL) || (use == NULL))
20179	return(-1);
20180    if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20181	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20182	return(0);
20183
20184    /*
20185    * SPEC au-props-correct (1)
20186    * "The values of the properties of an attribute use must be as
20187    * described in the property tableau in The Attribute Use Schema
20188    * Component (�3.5.1), modulo the impact of Missing
20189    * Sub-components (�5.3)."
20190    */
20191
20192    if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20193	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20194        ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20195    {
20196	xmlSchemaPCustomErr(ctxt,
20197	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20198	    WXS_BASIC_CAST use, NULL,
20199	    "The attribute declaration has a 'fixed' value constraint "
20200	    ", thus the attribute use must also have a 'fixed' value "
20201	    "constraint",
20202	    NULL);
20203	return(ctxt->err);
20204    }
20205    /*
20206    * Compute and check the value constraint's value.
20207    */
20208    if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20209	int ret;
20210	/*
20211	* TODO: The spec seems to be missing a check of the
20212	* value constraint of the attribute use. We will do it here.
20213	*/
20214	/*
20215	* SPEC a-props-correct (3)
20216	*/
20217	if (xmlSchemaIsDerivedFromBuiltInType(
20218	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20219	{
20220	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20221		XML_SCHEMAP_AU_PROPS_CORRECT,
20222		NULL, WXS_BASIC_CAST use,
20223		"Value constraints are not allowed if the type definition "
20224		"is or is derived from xs:ID",
20225		NULL, NULL);
20226	    return(ctxt->err);
20227	}
20228
20229	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20230	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20231	    use->defValue, &(use->defVal),
20232	    1, 1, 0);
20233	if (ret != 0) {
20234	    if (ret < 0) {
20235		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20236		    "calling xmlSchemaVCheckCVCSimpleType()");
20237		return(-1);
20238	    }
20239	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20240		XML_SCHEMAP_AU_PROPS_CORRECT,
20241		NULL, WXS_BASIC_CAST use,
20242		"The value of the value constraint is not valid",
20243		NULL, NULL);
20244	    return(ctxt->err);
20245	}
20246    }
20247    /*
20248    * SPEC au-props-correct (2)
20249    * "If the {attribute declaration} has a fixed
20250    * {value constraint}, then if the attribute use itself has a
20251    * {value constraint}, it must also be fixed and its value must match
20252    * that of the {attribute declaration}'s {value constraint}."
20253    */
20254    if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20255	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20256    {
20257	if (! xmlSchemaAreValuesEqual(use->defVal,
20258		(WXS_ATTRUSE_DECL(use))->defVal))
20259	{
20260	    xmlSchemaPCustomErr(ctxt,
20261		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20262		WXS_BASIC_CAST use, NULL,
20263		"The 'fixed' value constraint of the attribute use "
20264		"must match the attribute declaration's value "
20265		"constraint '%s'",
20266		(WXS_ATTRUSE_DECL(use))->defValue);
20267	}
20268	return(ctxt->err);
20269    }
20270    return(0);
20271}
20272
20273
20274
20275
20276/**
20277 * xmlSchemaResolveAttrTypeReferences:
20278 * @item:  an attribute declaration
20279 * @ctxt:  a parser context
20280 *
20281 * Resolves the referenced type definition component.
20282 */
20283static int
20284xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20285				   xmlSchemaParserCtxtPtr ctxt)
20286{
20287    /*
20288    * The simple type definition corresponding to the <simpleType> element
20289    * information item in the [children], if present, otherwise the simple
20290    * type definition �resolved� to by the �actual value� of the type
20291    * [attribute], if present, otherwise the �simple ur-type definition�.
20292    */
20293    if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20294	return(0);
20295    item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20296    if (item->subtypes != NULL)
20297        return(0);
20298    if (item->typeName != NULL) {
20299        xmlSchemaTypePtr type;
20300
20301	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20302	    item->typeNs);
20303	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20304	    xmlSchemaPResCompAttrErr(ctxt,
20305		XML_SCHEMAP_SRC_RESOLVE,
20306		WXS_BASIC_CAST item, item->node,
20307		"type", item->typeName, item->typeNs,
20308		XML_SCHEMA_TYPE_SIMPLE, NULL);
20309	    return(ctxt->err);
20310	} else
20311	    item->subtypes = type;
20312
20313    } else {
20314	/*
20315	* The type defaults to the xs:anySimpleType.
20316	*/
20317	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20318    }
20319    return(0);
20320}
20321
20322/**
20323 * xmlSchemaResolveIDCKeyReferences:
20324 * @idc:  the identity-constraint definition
20325 * @ctxt:  the schema parser context
20326 * @name:  the attribute name
20327 *
20328 * Resolve keyRef references to key/unique IDCs.
20329 * Schema Component Constraint:
20330 *   Identity-constraint Definition Properties Correct (c-props-correct)
20331 */
20332static int
20333xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20334			  xmlSchemaParserCtxtPtr pctxt)
20335{
20336    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20337        return(0);
20338    if (idc->ref->name != NULL) {
20339	idc->ref->item = (xmlSchemaBasicItemPtr)
20340	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20341		idc->ref->targetNamespace);
20342        if (idc->ref->item == NULL) {
20343	    /*
20344	    * TODO: It is actually not an error to fail to resolve
20345	    * at this stage. BUT we need to be that strict!
20346	    */
20347	    xmlSchemaPResCompAttrErr(pctxt,
20348		XML_SCHEMAP_SRC_RESOLVE,
20349		WXS_BASIC_CAST idc, idc->node,
20350		"refer", idc->ref->name,
20351		idc->ref->targetNamespace,
20352		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20353            return(pctxt->err);
20354	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20355	    /*
20356	    * SPEC c-props-correct (1)
20357	    */
20358	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20359		XML_SCHEMAP_C_PROPS_CORRECT,
20360		NULL, WXS_BASIC_CAST idc,
20361		"The keyref references a keyref",
20362		NULL, NULL);
20363	    idc->ref->item = NULL;
20364	    return(pctxt->err);
20365	} else {
20366	    if (idc->nbFields !=
20367		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20368		xmlChar *str = NULL;
20369		xmlSchemaIDCPtr refer;
20370
20371		refer = (xmlSchemaIDCPtr) idc->ref->item;
20372		/*
20373		* SPEC c-props-correct(2)
20374		* "If the {identity-constraint category} is keyref,
20375		* the cardinality of the {fields} must equal that of
20376		* the {fields} of the {referenced key}.
20377		*/
20378		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20379		    XML_SCHEMAP_C_PROPS_CORRECT,
20380		    NULL, WXS_BASIC_CAST idc,
20381		    "The cardinality of the keyref differs from the "
20382		    "cardinality of the referenced key/unique '%s'",
20383		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20384			refer->name),
20385		    NULL);
20386		FREE_AND_NULL(str)
20387		return(pctxt->err);
20388	    }
20389	}
20390    }
20391    return(0);
20392}
20393
20394static int
20395xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20396				       xmlSchemaParserCtxtPtr pctxt)
20397{
20398    if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20399	prohib->targetNamespace) == NULL) {
20400
20401	xmlSchemaPResCompAttrErr(pctxt,
20402	    XML_SCHEMAP_SRC_RESOLVE,
20403	    NULL, prohib->node,
20404	    "ref", prohib->name, prohib->targetNamespace,
20405	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20406	return(XML_SCHEMAP_SRC_RESOLVE);
20407    }
20408    return(0);
20409}
20410
20411#define WXS_REDEFINED_TYPE(c) \
20412(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20413
20414#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20415(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20416
20417#define WXS_REDEFINED_ATTR_GROUP(c) \
20418(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20419
20420static int
20421xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20422{
20423    int err = 0;
20424    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20425    xmlSchemaBasicItemPtr prev, item;
20426    int wasRedefined;
20427
20428    if (redef == NULL)
20429	return(0);
20430
20431    do {
20432	item = redef->item;
20433	/*
20434	* First try to locate the redefined component in the
20435	* schema graph starting with the redefined schema.
20436	* NOTE: According to this schema bug entry:
20437	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20438	*   it's not clear if the referenced component needs to originate
20439	*   from the <redefine>d schema _document_ or the schema; the latter
20440	*   would include all imported and included sub-schemas of the
20441	*   <redefine>d schema. Currenlty we latter approach is used.
20442	*   SUPPLEMENT: It seems that the WG moves towards the latter
20443	*   approach, so we are doing it right.
20444	*
20445	*/
20446	prev = xmlSchemaFindRedefCompInGraph(
20447	    redef->targetBucket, item->type,
20448	    redef->refName, redef->refTargetNs);
20449	if (prev == NULL) {
20450	    xmlChar *str = NULL;
20451	    xmlNodePtr node;
20452
20453	    /*
20454	    * SPEC src-redefine:
20455	    * (6.2.1) "The �actual value� of its own name attribute plus
20456	    * target namespace must successfully �resolve� to a model
20457	    * group definition in I."
20458	    * (7.2.1) "The �actual value� of its own name attribute plus
20459	    * target namespace must successfully �resolve� to an attribute
20460	    * group definition in I."
20461
20462	    *
20463	    * Note that, if we are redefining with the use of references
20464	    * to components, the spec assumes the src-resolve to be used;
20465	    * but this won't assure that we search only *inside* the
20466	    * redefined schema.
20467	    */
20468	    if (redef->reference)
20469		node = WXS_ITEM_NODE(redef->reference);
20470	    else
20471		node = WXS_ITEM_NODE(item);
20472	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20473		/*
20474		* TODO: error code.
20475		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20476		* reference kind.
20477		*/
20478		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20479		"The %s '%s' to be redefined could not be found in "
20480		"the redefined schema",
20481		WXS_ITEM_TYPE_NAME(item),
20482		xmlSchemaFormatQName(&str, redef->refTargetNs,
20483		    redef->refName));
20484	    FREE_AND_NULL(str);
20485	    err = pctxt->err;
20486	    redef = redef->next;
20487	    continue;
20488	}
20489	/*
20490	* TODO: Obtaining and setting the redefinition state is really
20491	* clumsy.
20492	*/
20493	wasRedefined = 0;
20494	switch (item->type) {
20495	    case XML_SCHEMA_TYPE_COMPLEX:
20496	    case XML_SCHEMA_TYPE_SIMPLE:
20497		if ((WXS_TYPE_CAST prev)->flags &
20498		    XML_SCHEMAS_TYPE_REDEFINED)
20499		{
20500		    wasRedefined = 1;
20501		    break;
20502		}
20503		/* Mark it as redefined. */
20504		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20505		/*
20506		* Assign the redefined type to the
20507		* base type of the redefining type.
20508		* TODO: How
20509		*/
20510		((xmlSchemaTypePtr) item)->baseType =
20511		    (xmlSchemaTypePtr) prev;
20512		break;
20513	    case XML_SCHEMA_TYPE_GROUP:
20514		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20515		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20516		{
20517		    wasRedefined = 1;
20518		    break;
20519		}
20520		/* Mark it as redefined. */
20521		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20522		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20523		if (redef->reference != NULL) {
20524		    /*
20525		    * Overwrite the QName-reference with the
20526		    * referenced model group def.
20527		    */
20528		    (WXS_PTC_CAST redef->reference)->children =
20529			WXS_TREE_CAST prev;
20530		}
20531		redef->target = prev;
20532		break;
20533	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20534		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20535		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20536		{
20537		    wasRedefined = 1;
20538		    break;
20539		}
20540		(WXS_ATTR_GROUP_CAST prev)->flags |=
20541		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20542		if (redef->reference != NULL) {
20543		    /*
20544		    * Assign the redefined attribute group to the
20545		    * QName-reference component.
20546		    * This is the easy case, since we will just
20547		    * expand the redefined group.
20548		    */
20549		    (WXS_QNAME_CAST redef->reference)->item = prev;
20550		    redef->target = NULL;
20551		} else {
20552		    /*
20553		    * This is the complicated case: we need
20554		    * to apply src-redefine (7.2.2) at a later
20555		    * stage, i.e. when attribute group references
20556		    * have beed expanded and simple types have
20557		    * beed fixed.
20558		    */
20559		    redef->target = prev;
20560		}
20561		break;
20562	    default:
20563		PERROR_INT("xmlSchemaResolveRedefReferences",
20564		    "Unexpected redefined component type");
20565		return(-1);
20566	}
20567	if (wasRedefined) {
20568	    xmlChar *str = NULL;
20569	    xmlNodePtr node;
20570
20571	    if (redef->reference)
20572		node = WXS_ITEM_NODE(redef->reference);
20573	    else
20574		node = WXS_ITEM_NODE(redef->item);
20575
20576	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20577		/* TODO: error code. */
20578		XML_SCHEMAP_SRC_REDEFINE,
20579		node, NULL,
20580		"The referenced %s was already redefined. Multiple "
20581		"redefinition of the same component is not supported",
20582		xmlSchemaGetComponentDesignation(&str, prev),
20583		NULL);
20584	    FREE_AND_NULL(str)
20585	    err = pctxt->err;
20586	    redef = redef->next;
20587	    continue;
20588	}
20589	redef = redef->next;
20590    } while (redef != NULL);
20591
20592    return(err);
20593}
20594
20595static int
20596xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20597{
20598    int err = 0;
20599    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20600    xmlSchemaBasicItemPtr item;
20601
20602    if (redef == NULL)
20603	return(0);
20604
20605    do {
20606	if (redef->target == NULL) {
20607	    redef = redef->next;
20608	    continue;
20609	}
20610	item = redef->item;
20611
20612	switch (item->type) {
20613	    case XML_SCHEMA_TYPE_SIMPLE:
20614	    case XML_SCHEMA_TYPE_COMPLEX:
20615		/*
20616		* Since the spec wants the {name} of the redefined
20617		* type to be 'absent', we'll NULL it.
20618		*/
20619		(WXS_TYPE_CAST redef->target)->name = NULL;
20620
20621		/*
20622		* TODO: Seems like there's nothing more to do. The normal
20623		* inheritance mechanism is used. But not 100% sure.
20624		*/
20625		break;
20626	    case XML_SCHEMA_TYPE_GROUP:
20627		/*
20628		* URGENT TODO:
20629		* SPEC src-redefine:
20630		* (6.2.2) "The {model group} of the model group definition
20631		* which corresponds to it per XML Representation of Model
20632		* Group Definition Schema Components (�3.7.2) must be a
20633		* �valid restriction� of the {model group} of that model
20634		* group definition in I, as defined in Particle Valid
20635		* (Restriction) (�3.9.6)."
20636		*/
20637		break;
20638	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20639		/*
20640		* SPEC src-redefine:
20641		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20642		* the attribute group definition which corresponds to it
20643		* per XML Representation of Attribute Group Definition Schema
20644		* Components (�3.6.2) must be �valid restrictions� of the
20645		* {attribute uses} and {attribute wildcard} of that attribute
20646		* group definition in I, as defined in clause 2, clause 3 and
20647		* clause 4 of Derivation Valid (Restriction, Complex)
20648		* (�3.4.6) (where references to the base type definition are
20649		* understood as references to the attribute group definition
20650		* in I)."
20651		*/
20652		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20653		    XML_SCHEMA_ACTION_REDEFINE,
20654		    item, redef->target,
20655		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20656		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20657		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20658		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20659		if (err == -1)
20660		    return(-1);
20661		break;
20662	    default:
20663		break;
20664	}
20665	redef = redef->next;
20666    } while (redef != NULL);
20667    return(0);
20668}
20669
20670
20671static int
20672xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20673		       xmlSchemaBucketPtr bucket)
20674{
20675    xmlSchemaBasicItemPtr item;
20676    int err;
20677    xmlHashTablePtr *table;
20678    const xmlChar *name;
20679    int i;
20680
20681#define WXS_GET_GLOBAL_HASH(c, slot) { \
20682    if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20683	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20684    else \
20685	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20686
20687    /*
20688    * Add global components to the schema's hash tables.
20689    * This is the place where duplicate components will be
20690    * detected.
20691    * TODO: I think normally we should support imports of the
20692    *   same namespace from multiple locations. We don't do currently,
20693    *   but if we do then according to:
20694    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20695    *   we would need, if imported directly, to import redefined
20696    *   components as well to be able to catch clashing components.
20697    *   (I hope I'll still know what this means after some months :-()
20698    */
20699    if (bucket == NULL)
20700	return(-1);
20701    if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20702	return(0);
20703    bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20704
20705    for (i = 0; i < bucket->globals->nbItems; i++) {
20706	item = bucket->globals->items[i];
20707	table = NULL;
20708	switch (item->type) {
20709	    case XML_SCHEMA_TYPE_COMPLEX:
20710	    case XML_SCHEMA_TYPE_SIMPLE:
20711		if (WXS_REDEFINED_TYPE(item))
20712		    continue;
20713		name = (WXS_TYPE_CAST item)->name;
20714		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20715		break;
20716	    case XML_SCHEMA_TYPE_ELEMENT:
20717		name = (WXS_ELEM_CAST item)->name;
20718		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20719		break;
20720	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20721		name = (WXS_ATTR_CAST item)->name;
20722		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20723		break;
20724	    case XML_SCHEMA_TYPE_GROUP:
20725		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20726		    continue;
20727		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20728		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20729		break;
20730	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20731		if (WXS_REDEFINED_ATTR_GROUP(item))
20732		    continue;
20733		name = (WXS_ATTR_GROUP_CAST item)->name;
20734		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20735		break;
20736	    case XML_SCHEMA_TYPE_IDC_KEY:
20737	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20738	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20739		name = (WXS_IDC_CAST item)->name;
20740		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20741		break;
20742	    case XML_SCHEMA_TYPE_NOTATION:
20743		name = ((xmlSchemaNotationPtr) item)->name;
20744		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20745		break;
20746	    default:
20747		PERROR_INT("xmlSchemaAddComponents",
20748		    "Unexpected global component type");
20749		continue;
20750	}
20751	if (*table == NULL) {
20752	    *table = xmlHashCreateDict(10, pctxt->dict);
20753	    if (*table == NULL) {
20754		PERROR_INT("xmlSchemaAddComponents",
20755		    "failed to create a component hash table");
20756		return(-1);
20757	    }
20758	}
20759	err = xmlHashAddEntry(*table, name, item);
20760	if (err != 0) {
20761	    xmlChar *str = NULL;
20762
20763	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20764		XML_SCHEMAP_REDEFINED_TYPE,
20765		WXS_ITEM_NODE(item),
20766		WXS_BASIC_CAST item,
20767		"A global %s '%s' does already exist",
20768		WXS_ITEM_TYPE_NAME(item),
20769		xmlSchemaGetComponentQName(&str, item));
20770	    FREE_AND_NULL(str);
20771	}
20772    }
20773    /*
20774    * Process imported/included schemas.
20775    */
20776    if (bucket->relations != NULL) {
20777	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20778	do {
20779	    if ((rel->bucket != NULL) &&
20780		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20781		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20782		    return(-1);
20783	    }
20784	    rel = rel->next;
20785	} while (rel != NULL);
20786    }
20787    return(0);
20788}
20789
20790static int
20791xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20792			 xmlSchemaBucketPtr rootBucket)
20793{
20794    xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20795    xmlSchemaTreeItemPtr item, *items;
20796    int nbItems, i, ret = 0;
20797    xmlSchemaBucketPtr oldbucket = con->bucket;
20798    xmlSchemaElementPtr elemDecl;
20799
20800#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20801
20802    if ((con->pending == NULL) ||
20803	(con->pending->nbItems == 0))
20804	return(0);
20805
20806    /*
20807    * Since xmlSchemaFixupComplexType() will create new particles
20808    * (local components), and those particle components need a bucket
20809    * on the constructor, we'll assure here that the constructor has
20810    * a bucket.
20811    * TODO: Think about storing locals _only_ on the main bucket.
20812    */
20813    if (con->bucket == NULL)
20814	con->bucket = rootBucket;
20815
20816    /* TODO:
20817    * SPEC (src-redefine):
20818    * (6.2) "If it has no such self-reference, then all of the
20819    * following must be true:"
20820
20821    * (6.2.2) The {model group} of the model group definition which
20822    * corresponds to it per XML Representation of Model Group
20823    * Definition Schema Components (�3.7.2) must be a �valid
20824    * restriction� of the {model group} of that model group definition
20825    * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20826    */
20827    xmlSchemaCheckSRCRedefineFirst(pctxt);
20828
20829    /*
20830    * Add global components to the schemata's hash tables.
20831    */
20832    xmlSchemaAddComponents(pctxt, rootBucket);
20833
20834    pctxt->ctxtType = NULL;
20835    items = (xmlSchemaTreeItemPtr *) con->pending->items;
20836    nbItems = con->pending->nbItems;
20837    /*
20838    * Now that we have parsed *all* the schema document(s) and converted
20839    * them to schema components, we can resolve references, apply component
20840    * constraints, create the FSA from the content model, etc.
20841    */
20842    /*
20843    * Resolve references of..
20844    *
20845    * 1. element declarations:
20846    *   - the type definition
20847    *   - the substitution group affiliation
20848    * 2. simple/complex types:
20849    *   - the base type definition
20850    *   - the memberTypes of union types
20851    *   - the itemType of list types
20852    * 3. attributes declarations and attribute uses:
20853    *   - the type definition
20854    *   - if an attribute use, then the attribute declaration
20855    * 4. attribute group references:
20856    *   - the attribute group definition
20857    * 5. particles:
20858    *   - the term of the particle (e.g. a model group)
20859    * 6. IDC key-references:
20860    *   - the referenced IDC 'key' or 'unique' definition
20861    * 7. Attribute prohibitions which had a "ref" attribute.
20862    */
20863    for (i = 0; i < nbItems; i++) {
20864	item = items[i];
20865	switch (item->type) {
20866	    case XML_SCHEMA_TYPE_ELEMENT:
20867		xmlSchemaResolveElementReferences(
20868		    (xmlSchemaElementPtr) item, pctxt);
20869		FIXHFAILURE;
20870		break;
20871	    case XML_SCHEMA_TYPE_COMPLEX:
20872	    case XML_SCHEMA_TYPE_SIMPLE:
20873		xmlSchemaResolveTypeReferences(
20874		    (xmlSchemaTypePtr) item, pctxt);
20875		FIXHFAILURE;
20876		break;
20877	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20878		xmlSchemaResolveAttrTypeReferences(
20879		    (xmlSchemaAttributePtr) item, pctxt);
20880		FIXHFAILURE;
20881		break;
20882	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20883		xmlSchemaResolveAttrUseReferences(
20884		    (xmlSchemaAttributeUsePtr) item, pctxt);
20885		FIXHFAILURE;
20886		break;
20887	    case XML_SCHEMA_EXTRA_QNAMEREF:
20888		if ((WXS_QNAME_CAST item)->itemType ==
20889		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20890		{
20891		    xmlSchemaResolveAttrGroupReferences(
20892			WXS_QNAME_CAST item, pctxt);
20893		}
20894		FIXHFAILURE;
20895		break;
20896	    case XML_SCHEMA_TYPE_SEQUENCE:
20897	    case XML_SCHEMA_TYPE_CHOICE:
20898	    case XML_SCHEMA_TYPE_ALL:
20899		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20900		    WXS_MODEL_GROUP_CAST item);
20901		FIXHFAILURE;
20902		break;
20903	    case XML_SCHEMA_TYPE_IDC_KEY:
20904	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20905	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20906		xmlSchemaResolveIDCKeyReferences(
20907		    (xmlSchemaIDCPtr) item, pctxt);
20908		FIXHFAILURE;
20909		break;
20910	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20911		/*
20912		* Handle attribue prohibition which had a
20913		* "ref" attribute.
20914		*/
20915		xmlSchemaResolveAttrUseProhibReferences(
20916		    WXS_ATTR_PROHIB_CAST item, pctxt);
20917		FIXHFAILURE;
20918		break;
20919	    default:
20920		break;
20921	}
20922    }
20923    if (pctxt->nberrors != 0)
20924	goto exit_error;
20925
20926    /*
20927    * Now that all references are resolved we
20928    * can check for circularity of...
20929    * 1. the base axis of type definitions
20930    * 2. nested model group definitions
20931    * 3. nested attribute group definitions
20932    * TODO: check for circual substitution groups.
20933    */
20934    for (i = 0; i < nbItems; i++) {
20935	item = items[i];
20936	/*
20937	* Let's better stop on the first error here.
20938	*/
20939	switch (item->type) {
20940	    case XML_SCHEMA_TYPE_COMPLEX:
20941	    case XML_SCHEMA_TYPE_SIMPLE:
20942		xmlSchemaCheckTypeDefCircular(
20943		    (xmlSchemaTypePtr) item, pctxt);
20944		FIXHFAILURE;
20945		if (pctxt->nberrors != 0)
20946		    goto exit_error;
20947		break;
20948	    case XML_SCHEMA_TYPE_GROUP:
20949		xmlSchemaCheckGroupDefCircular(
20950		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20951		FIXHFAILURE;
20952		if (pctxt->nberrors != 0)
20953		    goto exit_error;
20954		break;
20955	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20956		xmlSchemaCheckAttrGroupCircular(
20957		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20958		FIXHFAILURE;
20959		if (pctxt->nberrors != 0)
20960		    goto exit_error;
20961		break;
20962	    default:
20963		break;
20964	}
20965    }
20966    if (pctxt->nberrors != 0)
20967	goto exit_error;
20968    /*
20969    * Model group definition references:
20970    * Such a reference is reflected by a particle at the component
20971    * level. Until now the 'term' of such particles pointed
20972    * to the model group definition; this was done, in order to
20973    * ease circularity checks. Now we need to set the 'term' of
20974    * such particles to the model group of the model group definition.
20975    */
20976    for (i = 0; i < nbItems; i++) {
20977	item = items[i];
20978	switch (item->type) {
20979	    case XML_SCHEMA_TYPE_SEQUENCE:
20980	    case XML_SCHEMA_TYPE_CHOICE:
20981		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20982		    WXS_MODEL_GROUP_CAST item);
20983		break;
20984	    default:
20985		break;
20986	}
20987    }
20988    if (pctxt->nberrors != 0)
20989	goto exit_error;
20990    /*
20991    * Expand attribute group references of attribute group definitions.
20992    */
20993    for (i = 0; i < nbItems; i++) {
20994	item = items[i];
20995	switch (item->type) {
20996            case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20997		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20998		    WXS_ATTR_GROUP_HAS_REFS(item))
20999		{
21000		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21001			WXS_ATTR_GROUP_CAST item);
21002		    FIXHFAILURE;
21003		}
21004		break;
21005	    default:
21006		break;
21007	}
21008    }
21009    if (pctxt->nberrors != 0)
21010	goto exit_error;
21011    /*
21012    * First compute the variety of simple types. This is needed as
21013    * a seperate step, since otherwise we won't be able to detect
21014    * circular union types in all cases.
21015    */
21016    for (i = 0; i < nbItems; i++) {
21017	item = items[i];
21018	switch (item->type) {
21019            case XML_SCHEMA_TYPE_SIMPLE:
21020		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21021		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21022			(xmlSchemaTypePtr) item);
21023		    FIXHFAILURE;
21024		}
21025		break;
21026	    default:
21027		break;
21028	}
21029    }
21030    if (pctxt->nberrors != 0)
21031	goto exit_error;
21032    /*
21033    * Detect circular union types. Note that this needs the variety to
21034    * be already computed.
21035    */
21036    for (i = 0; i < nbItems; i++) {
21037	item = items[i];
21038	switch (item->type) {
21039            case XML_SCHEMA_TYPE_SIMPLE:
21040		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21041		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21042			(xmlSchemaTypePtr) item);
21043		    FIXHFAILURE;
21044		}
21045		break;
21046	    default:
21047		break;
21048	}
21049    }
21050    if (pctxt->nberrors != 0)
21051	goto exit_error;
21052
21053    /*
21054    * Do the complete type fixup for simple types.
21055    */
21056    for (i = 0; i < nbItems; i++) {
21057	item = items[i];
21058	switch (item->type) {
21059            case XML_SCHEMA_TYPE_SIMPLE:
21060		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21061		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21062		    FIXHFAILURE;
21063		}
21064		break;
21065	    default:
21066		break;
21067	}
21068    }
21069    if (pctxt->nberrors != 0)
21070	goto exit_error;
21071    /*
21072    * At this point we need build and check all simple types.
21073    */
21074    /*
21075    * Apply contraints for attribute declarations.
21076    */
21077    for (i = 0; i < nbItems; i++) {
21078	item = items[i];
21079	switch (item->type) {
21080	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21081		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21082		FIXHFAILURE;
21083		break;
21084	    default:
21085		break;
21086	}
21087    }
21088    if (pctxt->nberrors != 0)
21089	goto exit_error;
21090    /*
21091    * Apply constraints for attribute uses.
21092    */
21093    for (i = 0; i < nbItems; i++) {
21094	item = items[i];
21095	switch (item->type) {
21096	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21097		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21098		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21099			WXS_ATTR_USE_CAST item);
21100		    FIXHFAILURE;
21101		}
21102		break;
21103	    default:
21104		break;
21105	}
21106    }
21107    if (pctxt->nberrors != 0)
21108	goto exit_error;
21109
21110    /*
21111    * Apply constraints for attribute group definitions.
21112    */
21113    for (i = 0; i < nbItems; i++) {
21114	item = items[i];
21115	switch (item->type) {
21116	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21117	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21118		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21119	    {
21120		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21121		FIXHFAILURE;
21122	    }
21123	    break;
21124	default:
21125	    break;
21126	}
21127    }
21128    if (pctxt->nberrors != 0)
21129	goto exit_error;
21130
21131    /*
21132    * Apply constraints for redefinitions.
21133    */
21134    if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21135	xmlSchemaCheckSRCRedefineSecond(pctxt);
21136    if (pctxt->nberrors != 0)
21137	goto exit_error;
21138
21139    /*
21140    * Complex types are builded and checked.
21141    */
21142    for (i = 0; i < nbItems; i++) {
21143	item = con->pending->items[i];
21144	switch (item->type) {
21145	    case XML_SCHEMA_TYPE_COMPLEX:
21146		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21147		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21148		    FIXHFAILURE;
21149		}
21150		break;
21151	    default:
21152		break;
21153	}
21154    }
21155    if (pctxt->nberrors != 0)
21156	goto exit_error;
21157
21158    /*
21159    * The list could have changed, since xmlSchemaFixupComplexType()
21160    * will create particles and model groups in some cases.
21161    */
21162    items = (xmlSchemaTreeItemPtr *) con->pending->items;
21163    nbItems = con->pending->nbItems;
21164
21165    /*
21166    * Apply some constraints for element declarations.
21167    */
21168    for (i = 0; i < nbItems; i++) {
21169	item = items[i];
21170	switch (item->type) {
21171	    case XML_SCHEMA_TYPE_ELEMENT:
21172		elemDecl = (xmlSchemaElementPtr) item;
21173
21174		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21175		{
21176		    xmlSchemaCheckElementDeclComponent(
21177			(xmlSchemaElementPtr) elemDecl, pctxt);
21178		    FIXHFAILURE;
21179		}
21180
21181#ifdef WXS_ELEM_DECL_CONS_ENABLED
21182		/*
21183		* Schema Component Constraint: Element Declarations Consistent
21184		* Apply this constraint to local types of element declarations.
21185		*/
21186		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21187		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21188		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21189		{
21190		    xmlSchemaCheckElementDeclConsistent(pctxt,
21191			WXS_BASIC_CAST elemDecl,
21192			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21193			NULL, NULL, 0);
21194		}
21195#endif
21196		break;
21197	    default:
21198		break;
21199	}
21200    }
21201    if (pctxt->nberrors != 0)
21202	goto exit_error;
21203
21204    /*
21205    * Finally we can build the automaton from the content model of
21206    * complex types.
21207    */
21208
21209    for (i = 0; i < nbItems; i++) {
21210	item = items[i];
21211	switch (item->type) {
21212	    case XML_SCHEMA_TYPE_COMPLEX:
21213		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21214		/* FIXHFAILURE; */
21215		break;
21216	    default:
21217		break;
21218	}
21219    }
21220    if (pctxt->nberrors != 0)
21221	goto exit_error;
21222    /*
21223    * URGENT TODO: cos-element-consistent
21224    */
21225    goto exit;
21226
21227exit_error:
21228    ret = pctxt->err;
21229    goto exit;
21230
21231exit_failure:
21232    ret = -1;
21233
21234exit:
21235    /*
21236    * Reset the constructor. This is needed for XSI acquisition, since
21237    * those items will be processed over and over again for every XSI
21238    * if not cleared here.
21239    */
21240    con->bucket = oldbucket;
21241    con->pending->nbItems = 0;
21242    if (con->substGroups != NULL) {
21243	xmlHashFree(con->substGroups,
21244	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21245	con->substGroups = NULL;
21246    }
21247    if (con->redefs != NULL) {
21248	xmlSchemaRedefListFree(con->redefs);
21249	con->redefs = NULL;
21250    }
21251    return(ret);
21252}
21253/**
21254 * xmlSchemaParse:
21255 * @ctxt:  a schema validation context
21256 *
21257 * parse a schema definition resource and build an internal
21258 * XML Shema struture which can be used to validate instances.
21259 *
21260 * Returns the internal XML Schema structure built from the resource or
21261 *         NULL in case of error
21262 */
21263xmlSchemaPtr
21264xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21265{
21266    xmlSchemaPtr mainSchema = NULL;
21267    xmlSchemaBucketPtr bucket = NULL;
21268    int res;
21269
21270    /*
21271    * This one is used if the schema to be parsed was specified via
21272    * the API; i.e. not automatically by the validated instance document.
21273    */
21274
21275    xmlSchemaInitTypes();
21276
21277    if (ctxt == NULL)
21278        return (NULL);
21279
21280    /* TODO: Init the context. Is this all we need?*/
21281    ctxt->nberrors = 0;
21282    ctxt->err = 0;
21283    ctxt->counter = 0;
21284
21285    /* Create the *main* schema. */
21286    mainSchema = xmlSchemaNewSchema(ctxt);
21287    if (mainSchema == NULL)
21288	goto exit_failure;
21289    /*
21290    * Create the schema constructor.
21291    */
21292    if (ctxt->constructor == NULL) {
21293	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21294	if (ctxt->constructor == NULL)
21295	    return(NULL);
21296	/* Take ownership of the constructor to be able to free it. */
21297	ctxt->ownsConstructor = 1;
21298    }
21299    ctxt->constructor->mainSchema = mainSchema;
21300    /*
21301    * Locate and add the schema document.
21302    */
21303    res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21304	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21305	NULL, NULL, &bucket);
21306    if (res == -1)
21307	goto exit_failure;
21308    if (res != 0)
21309	goto exit;
21310
21311    if (bucket == NULL) {
21312	/* TODO: Error code, actually we failed to *locate* the schema. */
21313	if (ctxt->URL)
21314	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21315		NULL, NULL,
21316		"Failed to locate the main schema resource at '%s'",
21317		ctxt->URL, NULL);
21318	else
21319	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21320		NULL, NULL,
21321		"Failed to locate the main schema resource",
21322		    NULL, NULL);
21323	goto exit;
21324    }
21325    /* Then do the parsing for good. */
21326    if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21327	goto exit_failure;
21328    if (ctxt->nberrors != 0)
21329	goto exit;
21330
21331    mainSchema->doc = bucket->doc;
21332    mainSchema->preserve = ctxt->preserve;
21333
21334    ctxt->schema = mainSchema;
21335
21336    if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21337	goto exit_failure;
21338
21339    /*
21340    * TODO: This is not nice, since we cannot distinguish from the
21341    * result if there was an internal error or not.
21342    */
21343exit:
21344    if (ctxt->nberrors != 0) {
21345	if (mainSchema) {
21346	    xmlSchemaFree(mainSchema);
21347	    mainSchema = NULL;
21348	}
21349	if (ctxt->constructor) {
21350	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21351	    ctxt->constructor = NULL;
21352	    ctxt->ownsConstructor = 0;
21353	}
21354    }
21355    ctxt->schema = NULL;
21356    return(mainSchema);
21357exit_failure:
21358    /*
21359    * Quite verbose, but should catch internal errors, which were
21360    * not communitated.
21361    */
21362    if (mainSchema) {
21363        xmlSchemaFree(mainSchema);
21364	mainSchema = NULL;
21365    }
21366    if (ctxt->constructor) {
21367	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21368	ctxt->constructor = NULL;
21369	ctxt->ownsConstructor = 0;
21370    }
21371    PERROR_INT2("xmlSchemaParse",
21372	"An internal error occured");
21373    ctxt->schema = NULL;
21374    return(NULL);
21375}
21376
21377/**
21378 * xmlSchemaSetParserErrors:
21379 * @ctxt:  a schema validation context
21380 * @err:  the error callback
21381 * @warn:  the warning callback
21382 * @ctx:  contextual data for the callbacks
21383 *
21384 * Set the callback functions used to handle errors for a validation context
21385 */
21386void
21387xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21388                         xmlSchemaValidityErrorFunc err,
21389                         xmlSchemaValidityWarningFunc warn, void *ctx)
21390{
21391    if (ctxt == NULL)
21392        return;
21393    ctxt->error = err;
21394    ctxt->warning = warn;
21395    ctxt->errCtxt = ctx;
21396    if (ctxt->vctxt != NULL)
21397	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21398}
21399
21400/**
21401 * xmlSchemaSetParserStructuredErrors:
21402 * @ctxt:  a schema parser context
21403 * @serror:  the structured error function
21404 * @ctx: the functions context
21405 *
21406 * Set the structured error callback
21407 */
21408void
21409xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21410				   xmlStructuredErrorFunc serror,
21411				   void *ctx)
21412{
21413    if (ctxt == NULL)
21414	return;
21415    ctxt->serror = serror;
21416    ctxt->errCtxt = ctx;
21417    if (ctxt->vctxt != NULL)
21418	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21419}
21420
21421/**
21422 * xmlSchemaGetParserErrors:
21423 * @ctxt:  a XMl-Schema parser context
21424 * @err: the error callback result
21425 * @warn: the warning callback result
21426 * @ctx: contextual data for the callbacks result
21427 *
21428 * Get the callback information used to handle errors for a parser context
21429 *
21430 * Returns -1 in case of failure, 0 otherwise
21431 */
21432int
21433xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21434			 xmlSchemaValidityErrorFunc * err,
21435			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21436{
21437	if (ctxt == NULL)
21438		return(-1);
21439	if (err != NULL)
21440		*err = ctxt->error;
21441	if (warn != NULL)
21442		*warn = ctxt->warning;
21443	if (ctx != NULL)
21444		*ctx = ctxt->errCtxt;
21445	return(0);
21446}
21447
21448/**
21449 * xmlSchemaFacetTypeToString:
21450 * @type:  the facet type
21451 *
21452 * Convert the xmlSchemaTypeType to a char string.
21453 *
21454 * Returns the char string representation of the facet type if the
21455 *     type is a facet and an "Internal Error" string otherwise.
21456 */
21457static const xmlChar *
21458xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21459{
21460    switch (type) {
21461        case XML_SCHEMA_FACET_PATTERN:
21462            return (BAD_CAST "pattern");
21463        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21464            return (BAD_CAST "maxExclusive");
21465        case XML_SCHEMA_FACET_MAXINCLUSIVE:
21466            return (BAD_CAST "maxInclusive");
21467        case XML_SCHEMA_FACET_MINEXCLUSIVE:
21468            return (BAD_CAST "minExclusive");
21469        case XML_SCHEMA_FACET_MININCLUSIVE:
21470            return (BAD_CAST "minInclusive");
21471        case XML_SCHEMA_FACET_WHITESPACE:
21472            return (BAD_CAST "whiteSpace");
21473        case XML_SCHEMA_FACET_ENUMERATION:
21474            return (BAD_CAST "enumeration");
21475        case XML_SCHEMA_FACET_LENGTH:
21476            return (BAD_CAST "length");
21477        case XML_SCHEMA_FACET_MAXLENGTH:
21478            return (BAD_CAST "maxLength");
21479        case XML_SCHEMA_FACET_MINLENGTH:
21480            return (BAD_CAST "minLength");
21481        case XML_SCHEMA_FACET_TOTALDIGITS:
21482            return (BAD_CAST "totalDigits");
21483        case XML_SCHEMA_FACET_FRACTIONDIGITS:
21484            return (BAD_CAST "fractionDigits");
21485        default:
21486            break;
21487    }
21488    return (BAD_CAST "Internal Error");
21489}
21490
21491static xmlSchemaWhitespaceValueType
21492xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21493{
21494    /*
21495    * The normalization type can be changed only for types which are derived
21496    * from xsd:string.
21497    */
21498    if (type->type == XML_SCHEMA_TYPE_BASIC) {
21499	/*
21500	* Note that we assume a whitespace of preserve for anySimpleType.
21501	*/
21502	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21503	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21504	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21505	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21506	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21507	else {
21508	    /*
21509	    * For all �atomic� datatypes other than string (and types �derived�
21510	    * by �restriction� from it) the value of whiteSpace is fixed to
21511	    * collapse
21512	    * Note that this includes built-in list datatypes.
21513	    */
21514	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21515	}
21516    } else if (WXS_IS_LIST(type)) {
21517	/*
21518	* For list types the facet "whiteSpace" is fixed to "collapse".
21519	*/
21520	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21521    } else if (WXS_IS_UNION(type)) {
21522	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21523    } else if (WXS_IS_ATOMIC(type)) {
21524	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21525	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21526	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21527	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21528	else
21529	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21530    }
21531    return (-1);
21532}
21533
21534/************************************************************************
21535 * 									*
21536 * 			Simple type validation				*
21537 * 									*
21538 ************************************************************************/
21539
21540
21541/************************************************************************
21542 * 									*
21543 * 			DOM Validation code				*
21544 * 									*
21545 ************************************************************************/
21546
21547/**
21548 * xmlSchemaAssembleByLocation:
21549 * @pctxt:  a schema parser context
21550 * @vctxt:  a schema validation context
21551 * @schema: the existing schema
21552 * @node: the node that fired the assembling
21553 * @nsName: the namespace name of the new schema
21554 * @location: the location of the schema
21555 *
21556 * Expands an existing schema by an additional schema.
21557 *
21558 * Returns 0 if the new schema is correct, a positive error code
21559 * number otherwise and -1 in case of an internal or API error.
21560 */
21561static int
21562xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21563			    xmlSchemaPtr schema,
21564			    xmlNodePtr node,
21565			    const xmlChar *nsName,
21566			    const xmlChar *location)
21567{
21568    int ret = 0;
21569    xmlSchemaParserCtxtPtr pctxt;
21570    xmlSchemaBucketPtr bucket = NULL;
21571
21572    if ((vctxt == NULL) || (schema == NULL))
21573	return (-1);
21574
21575    if (vctxt->pctxt == NULL) {
21576	VERROR_INT("xmlSchemaAssembleByLocation",
21577	    "no parser context available");
21578	return(-1);
21579    }
21580    pctxt = vctxt->pctxt;
21581    if (pctxt->constructor == NULL) {
21582	PERROR_INT("xmlSchemaAssembleByLocation",
21583	    "no constructor");
21584	return(-1);
21585    }
21586    /*
21587    * Acquire the schema document.
21588    */
21589    location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21590	location, node);
21591    /*
21592    * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21593    * the process will automatically change this to
21594    * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21595    */
21596    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21597	location, NULL, NULL, 0, node, NULL, nsName,
21598	&bucket);
21599    if (ret != 0)
21600	return(ret);
21601    if (bucket == NULL) {
21602	/*
21603	* Generate a warning that the document could not be located.
21604	*/
21605	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21606	    node, NULL,
21607	    "The document at location '%s' could not be acquired",
21608	    location, NULL, NULL);
21609	return(ret);
21610    }
21611    /*
21612    * The first located schema will be handled as if all other
21613    * schemas imported by XSI were imported by this first schema.
21614    */
21615    if ((bucket != NULL) &&
21616	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21617	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21618    /*
21619    * TODO: Is this handled like an import? I.e. is it not an error
21620    * if the schema cannot be located?
21621    */
21622    if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21623	return(0);
21624    /*
21625    * We will reuse the parser context for every schema imported
21626    * directly via XSI. So reset the context.
21627    */
21628    pctxt->nberrors = 0;
21629    pctxt->err = 0;
21630    pctxt->doc = bucket->doc;
21631
21632    ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21633    if (ret == -1) {
21634	pctxt->doc = NULL;
21635	goto exit_failure;
21636    }
21637    /* Paranoid error channelling. */
21638    if ((ret == 0) && (pctxt->nberrors != 0))
21639	ret = pctxt->err;
21640    if (pctxt->nberrors == 0) {
21641	/*
21642	* Only bother to fixup pending components, if there was
21643	* no error yet.
21644	* For every XSI acquired schema (and its sub-schemata) we will
21645	* fixup the components.
21646	*/
21647	xmlSchemaFixupComponents(pctxt, bucket);
21648	ret = pctxt->err;
21649	/*
21650	* Not nice, but we need somehow to channel the schema parser
21651	* error to the validation context.
21652	*/
21653	if ((ret != 0) && (vctxt->err == 0))
21654	    vctxt->err = ret;
21655	vctxt->nberrors += pctxt->nberrors;
21656    } else {
21657	/* Add to validation error sum. */
21658	vctxt->nberrors += pctxt->nberrors;
21659    }
21660    pctxt->doc = NULL;
21661    return(ret);
21662exit_failure:
21663    pctxt->doc = NULL;
21664    return (-1);
21665}
21666
21667static xmlSchemaAttrInfoPtr
21668xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21669			 int metaType)
21670{
21671    if (vctxt->nbAttrInfos == 0)
21672	return (NULL);
21673    {
21674	int i;
21675	xmlSchemaAttrInfoPtr iattr;
21676
21677	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21678	    iattr = vctxt->attrInfos[i];
21679	    if (iattr->metaType == metaType)
21680		return (iattr);
21681	}
21682
21683    }
21684    return (NULL);
21685}
21686
21687/**
21688 * xmlSchemaAssembleByXSI:
21689 * @vctxt:  a schema validation context
21690 *
21691 * Expands an existing schema by an additional schema using
21692 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21693 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21694 * must be set to 1.
21695 *
21696 * Returns 0 if the new schema is correct, a positive error code
21697 * number otherwise and -1 in case of an internal or API error.
21698 */
21699static int
21700xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21701{
21702    const xmlChar *cur, *end;
21703    const xmlChar *nsname = NULL, *location;
21704    int count = 0;
21705    int ret = 0;
21706    xmlSchemaAttrInfoPtr iattr;
21707
21708    /*
21709    * Parse the value; we will assume an even number of values
21710    * to be given (this is how Xerces and XSV work).
21711    *
21712    * URGENT TODO: !! This needs to work for both
21713    * @noNamespaceSchemaLocation AND @schemaLocation on the same
21714    * element !!
21715    */
21716    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21717	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21718    if (iattr == NULL)
21719	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21720	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21721    if (iattr == NULL)
21722	return (0);
21723    cur = iattr->value;
21724    do {
21725	/*
21726	* TODO: Move the string parsing mechanism away from here.
21727	*/
21728	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21729	    /*
21730	    * Get the namespace name.
21731	    */
21732	    while (IS_BLANK_CH(*cur))
21733		cur++;
21734	    end = cur;
21735	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21736		end++;
21737	    if (end == cur)
21738		break;
21739	    count++; /* TODO: Don't use the schema's dict. */
21740	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21741	    cur = end;
21742	}
21743	/*
21744	* Get the URI.
21745	*/
21746	while (IS_BLANK_CH(*cur))
21747	    cur++;
21748	end = cur;
21749	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21750	    end++;
21751	if (end == cur) {
21752	    if (iattr->metaType ==
21753		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21754	    {
21755		/*
21756		* If using @schemaLocation then tuples are expected.
21757		* I.e. the namespace name *and* the document's URI.
21758		*/
21759		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21760		    iattr->node, NULL,
21761		    "The value must consist of tuples: the target namespace "
21762		    "name and the document's URI", NULL, NULL, NULL);
21763	    }
21764	    break;
21765	}
21766	count++; /* TODO: Don't use the schema's dict. */
21767	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21768	cur = end;
21769	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21770	    iattr->node, nsname, location);
21771	if (ret == -1) {
21772	    VERROR_INT("xmlSchemaAssembleByXSI",
21773		"assembling schemata");
21774	    return (-1);
21775	}
21776    } while (*cur != 0);
21777    return (ret);
21778}
21779
21780static const xmlChar *
21781xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21782			 const xmlChar *prefix)
21783{
21784    if (vctxt->sax != NULL) {
21785	int i, j;
21786	xmlSchemaNodeInfoPtr inode;
21787
21788	for (i = vctxt->depth; i >= 0; i--) {
21789	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21790		inode = vctxt->elemInfos[i];
21791		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21792		    if (((prefix == NULL) &&
21793			    (inode->nsBindings[j] == NULL)) ||
21794			((prefix != NULL) && xmlStrEqual(prefix,
21795			    inode->nsBindings[j]))) {
21796
21797			/*
21798			* Note that the namespace bindings are already
21799			* in a string dict.
21800			*/
21801			return (inode->nsBindings[j+1]);
21802		    }
21803		}
21804	    }
21805	}
21806	return (NULL);
21807#ifdef LIBXML_READER_ENABLED
21808    } else if (vctxt->reader != NULL) {
21809	xmlChar *nsName;
21810
21811	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21812	if (nsName != NULL) {
21813	    const xmlChar *ret;
21814
21815	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21816	    xmlFree(nsName);
21817	    return (ret);
21818	} else
21819	    return (NULL);
21820#endif
21821    } else {
21822	xmlNsPtr ns;
21823
21824	if ((vctxt->inode->node == NULL) ||
21825	    (vctxt->inode->node->doc == NULL)) {
21826	    VERROR_INT("xmlSchemaLookupNamespace",
21827		"no node or node's doc avaliable");
21828	    return (NULL);
21829	}
21830	ns = xmlSearchNs(vctxt->inode->node->doc,
21831	    vctxt->inode->node, prefix);
21832	if (ns != NULL)
21833	    return (ns->href);
21834	return (NULL);
21835    }
21836}
21837
21838/*
21839* This one works on the schema of the validation context.
21840*/
21841static int
21842xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21843			  xmlSchemaPtr schema,
21844			  xmlNodePtr node,
21845			  const xmlChar *value,
21846			  xmlSchemaValPtr *val,
21847			  int valNeeded)
21848{
21849    int ret;
21850
21851    if (vctxt && (vctxt->schema == NULL)) {
21852	VERROR_INT("xmlSchemaValidateNotation",
21853	    "a schema is needed on the validation context");
21854	return (-1);
21855    }
21856    ret = xmlValidateQName(value, 1);
21857    if (ret != 0)
21858	return (ret);
21859    {
21860	xmlChar *localName = NULL;
21861	xmlChar *prefix = NULL;
21862
21863	localName = xmlSplitQName2(value, &prefix);
21864	if (prefix != NULL) {
21865	    const xmlChar *nsName = NULL;
21866
21867	    if (vctxt != NULL)
21868		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21869	    else if (node != NULL) {
21870		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21871		if (ns != NULL)
21872		    nsName = ns->href;
21873	    } else {
21874		xmlFree(prefix);
21875		xmlFree(localName);
21876		return (1);
21877	    }
21878	    if (nsName == NULL) {
21879		xmlFree(prefix);
21880		xmlFree(localName);
21881		return (1);
21882	    }
21883	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21884		if ((valNeeded) && (val != NULL)) {
21885		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21886						       xmlStrdup(nsName));
21887		    if (*val == NULL)
21888			ret = -1;
21889		}
21890	    } else
21891		ret = 1;
21892	    xmlFree(prefix);
21893	    xmlFree(localName);
21894	} else {
21895	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21896		if (valNeeded && (val != NULL)) {
21897		    (*val) = xmlSchemaNewNOTATIONValue(
21898			BAD_CAST xmlStrdup(value), NULL);
21899		    if (*val == NULL)
21900			ret = -1;
21901		}
21902	    } else
21903		return (1);
21904	}
21905    }
21906    return (ret);
21907}
21908
21909static int
21910xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21911		       const xmlChar* lname,
21912		       const xmlChar* nsname)
21913{
21914    int i;
21915
21916    lname = xmlDictLookup(vctxt->dict, lname, -1);
21917    if (lname == NULL)
21918	return(-1);
21919    if (nsname != NULL) {
21920	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21921	if (nsname == NULL)
21922	    return(-1);
21923    }
21924    for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21925	if ((vctxt->nodeQNames->items [i] == lname) &&
21926	    (vctxt->nodeQNames->items[i +1] == nsname))
21927	    /* Already there */
21928	    return(i);
21929    }
21930    /* Add new entry. */
21931    i = vctxt->nodeQNames->nbItems;
21932    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21933    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21934    return(i);
21935}
21936
21937/************************************************************************
21938 * 									*
21939 *  Validation of identity-constraints (IDC)                            *
21940 * 									*
21941 ************************************************************************/
21942
21943/**
21944 * xmlSchemaAugmentIDC:
21945 * @idcDef: the IDC definition
21946 *
21947 * Creates an augmented IDC definition item.
21948 *
21949 * Returns the item, or NULL on internal errors.
21950 */
21951static void
21952xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21953		    xmlSchemaValidCtxtPtr vctxt)
21954{
21955    xmlSchemaIDCAugPtr aidc;
21956
21957    aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21958    if (aidc == NULL) {
21959	xmlSchemaVErrMemory(vctxt,
21960	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21961	    NULL);
21962	return;
21963    }
21964    aidc->keyrefDepth = -1;
21965    aidc->def = idcDef;
21966    aidc->next = NULL;
21967    if (vctxt->aidcs == NULL)
21968	vctxt->aidcs = aidc;
21969    else {
21970	aidc->next = vctxt->aidcs;
21971	vctxt->aidcs = aidc;
21972    }
21973    /*
21974    * Save if we have keyrefs at all.
21975    */
21976    if ((vctxt->hasKeyrefs == 0) &&
21977	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21978	vctxt->hasKeyrefs = 1;
21979}
21980
21981/**
21982 * xmlSchemaAugmentImportedIDC:
21983 * @imported: the imported schema
21984 *
21985 * Creates an augmented IDC definition for the imported schema.
21986 */
21987static void
21988xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21989    if (imported->schema->idcDef != NULL) {
21990	    xmlHashScan(imported->schema->idcDef ,
21991	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21992    }
21993}
21994
21995/**
21996 * xmlSchemaIDCNewBinding:
21997 * @idcDef: the IDC definition of this binding
21998 *
21999 * Creates a new IDC binding.
22000 *
22001 * Returns the new IDC binding, NULL on internal errors.
22002 */
22003static xmlSchemaPSVIIDCBindingPtr
22004xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22005{
22006    xmlSchemaPSVIIDCBindingPtr ret;
22007
22008    ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22009	    sizeof(xmlSchemaPSVIIDCBinding));
22010    if (ret == NULL) {
22011	xmlSchemaVErrMemory(NULL,
22012	    "allocating a PSVI IDC binding item", NULL);
22013	return (NULL);
22014    }
22015    memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22016    ret->definition = idcDef;
22017    return (ret);
22018}
22019
22020/**
22021 * xmlSchemaIDCStoreNodeTableItem:
22022 * @vctxt: the WXS validation context
22023 * @item: the IDC node table item
22024 *
22025 * The validation context is used to store IDC node table items.
22026 * They are stored to avoid copying them if IDC node-tables are merged
22027 * with corresponding parent IDC node-tables (bubbling).
22028 *
22029 * Returns 0 if succeeded, -1 on internal errors.
22030 */
22031static int
22032xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22033			       xmlSchemaPSVIIDCNodePtr item)
22034{
22035    /*
22036    * Add to gobal list.
22037    */
22038    if (vctxt->idcNodes == NULL) {
22039	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22040	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22041	if (vctxt->idcNodes == NULL) {
22042	    xmlSchemaVErrMemory(vctxt,
22043		"allocating the IDC node table item list", NULL);
22044	    return (-1);
22045	}
22046	vctxt->sizeIdcNodes = 20;
22047    } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22048	vctxt->sizeIdcNodes *= 2;
22049	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22050	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22051	    sizeof(xmlSchemaPSVIIDCNodePtr));
22052	if (vctxt->idcNodes == NULL) {
22053	    xmlSchemaVErrMemory(vctxt,
22054		"re-allocating the IDC node table item list", NULL);
22055	    return (-1);
22056	}
22057    }
22058    vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22059
22060    return (0);
22061}
22062
22063/**
22064 * xmlSchemaIDCStoreKey:
22065 * @vctxt: the WXS validation context
22066 * @item: the IDC key
22067 *
22068 * The validation context is used to store an IDC key.
22069 *
22070 * Returns 0 if succeeded, -1 on internal errors.
22071 */
22072static int
22073xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22074		     xmlSchemaPSVIIDCKeyPtr key)
22075{
22076    /*
22077    * Add to gobal list.
22078    */
22079    if (vctxt->idcKeys == NULL) {
22080	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22081	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22082	if (vctxt->idcKeys == NULL) {
22083	    xmlSchemaVErrMemory(vctxt,
22084		"allocating the IDC key storage list", NULL);
22085	    return (-1);
22086	}
22087	vctxt->sizeIdcKeys = 40;
22088    } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22089	vctxt->sizeIdcKeys *= 2;
22090	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22091	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22092	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22093	if (vctxt->idcKeys == NULL) {
22094	    xmlSchemaVErrMemory(vctxt,
22095		"re-allocating the IDC key storage list", NULL);
22096	    return (-1);
22097	}
22098    }
22099    vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22100
22101    return (0);
22102}
22103
22104/**
22105 * xmlSchemaIDCAppendNodeTableItem:
22106 * @bind: the IDC binding
22107 * @ntItem: the node-table item
22108 *
22109 * Appends the IDC node-table item to the binding.
22110 *
22111 * Returns 0 on success and -1 on internal errors.
22112 */
22113static int
22114xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22115				xmlSchemaPSVIIDCNodePtr ntItem)
22116{
22117    if (bind->nodeTable == NULL) {
22118	bind->sizeNodes = 10;
22119	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22120	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22121	if (bind->nodeTable == NULL) {
22122	    xmlSchemaVErrMemory(NULL,
22123		"allocating an array of IDC node-table items", NULL);
22124	    return(-1);
22125	}
22126    } else if (bind->sizeNodes <= bind->nbNodes) {
22127	bind->sizeNodes *= 2;
22128	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22129	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22130		sizeof(xmlSchemaPSVIIDCNodePtr));
22131	if (bind->nodeTable == NULL) {
22132	    xmlSchemaVErrMemory(NULL,
22133		"re-allocating an array of IDC node-table items", NULL);
22134	    return(-1);
22135	}
22136    }
22137    bind->nodeTable[bind->nbNodes++] = ntItem;
22138    return(0);
22139}
22140
22141/**
22142 * xmlSchemaIDCAcquireBinding:
22143 * @vctxt: the WXS validation context
22144 * @matcher: the IDC matcher
22145 *
22146 * Looks up an PSVI IDC binding, for the IDC definition and
22147 * of the given matcher. If none found, a new one is created
22148 * and added to the IDC table.
22149 *
22150 * Returns an IDC binding or NULL on internal errors.
22151 */
22152static xmlSchemaPSVIIDCBindingPtr
22153xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22154			  xmlSchemaIDCMatcherPtr matcher)
22155{
22156    xmlSchemaNodeInfoPtr ielem;
22157
22158    ielem = vctxt->elemInfos[matcher->depth];
22159
22160    if (ielem->idcTable == NULL) {
22161	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22162	if (ielem->idcTable == NULL)
22163	    return (NULL);
22164	return(ielem->idcTable);
22165    } else {
22166	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22167
22168	bind = ielem->idcTable;
22169	do {
22170	    if (bind->definition == matcher->aidc->def)
22171		return(bind);
22172	    if (bind->next == NULL) {
22173		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22174		if (bind->next == NULL)
22175		    return (NULL);
22176		return(bind->next);
22177	    }
22178	    bind = bind->next;
22179	} while (bind != NULL);
22180    }
22181    return (NULL);
22182}
22183
22184static xmlSchemaItemListPtr
22185xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22186			     xmlSchemaIDCMatcherPtr matcher)
22187{
22188    if (matcher->targets == NULL)
22189	matcher->targets = xmlSchemaItemListCreate();
22190    return(matcher->targets);
22191}
22192
22193/**
22194 * xmlSchemaIDCFreeKey:
22195 * @key: the IDC key
22196 *
22197 * Frees an IDC key together with its compiled value.
22198 */
22199static void
22200xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22201{
22202    if (key->val != NULL)
22203	xmlSchemaFreeValue(key->val);
22204    xmlFree(key);
22205}
22206
22207/**
22208 * xmlSchemaIDCFreeBinding:
22209 *
22210 * Frees an IDC binding. Note that the node table-items
22211 * are not freed.
22212 */
22213static void
22214xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22215{
22216    if (bind->nodeTable != NULL)
22217	xmlFree(bind->nodeTable);
22218    if (bind->dupls != NULL)
22219	xmlSchemaItemListFree(bind->dupls);
22220    xmlFree(bind);
22221}
22222
22223/**
22224 * xmlSchemaIDCFreeIDCTable:
22225 * @bind: the first IDC binding in the list
22226 *
22227 * Frees an IDC table, i.e. all the IDC bindings in the list.
22228 */
22229static void
22230xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22231{
22232    xmlSchemaPSVIIDCBindingPtr prev;
22233
22234    while (bind != NULL) {
22235	prev = bind;
22236	bind = bind->next;
22237	xmlSchemaIDCFreeBinding(prev);
22238    }
22239}
22240
22241/**
22242 * xmlSchemaIDCFreeMatcherList:
22243 * @matcher: the first IDC matcher in the list
22244 *
22245 * Frees a list of IDC matchers.
22246 */
22247static void
22248xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22249{
22250    xmlSchemaIDCMatcherPtr next;
22251
22252    while (matcher != NULL) {
22253	next = matcher->next;
22254	if (matcher->keySeqs != NULL) {
22255	    int i;
22256	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22257		if (matcher->keySeqs[i] != NULL)
22258		    xmlFree(matcher->keySeqs[i]);
22259	    xmlFree(matcher->keySeqs);
22260	}
22261	if (matcher->targets != NULL) {
22262	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22263		int i;
22264		xmlSchemaPSVIIDCNodePtr idcNode;
22265		/*
22266		* Node-table items for keyrefs are not stored globally
22267		* to the validation context, since they are not bubbled.
22268		* We need to free them here.
22269		*/
22270		for (i = 0; i < matcher->targets->nbItems; i++) {
22271		    idcNode =
22272			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22273		    xmlFree(idcNode->keys);
22274		    xmlFree(idcNode);
22275		}
22276	    }
22277	    xmlSchemaItemListFree(matcher->targets);
22278	}
22279	xmlFree(matcher);
22280	matcher = next;
22281    }
22282}
22283
22284/**
22285 * xmlSchemaIDCReleaseMatcherList:
22286 * @vctxt: the WXS validation context
22287 * @matcher: the first IDC matcher in the list
22288 *
22289 * Caches a list of IDC matchers for reuse.
22290 */
22291static void
22292xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22293			       xmlSchemaIDCMatcherPtr matcher)
22294{
22295    xmlSchemaIDCMatcherPtr next;
22296
22297    while (matcher != NULL) {
22298	next = matcher->next;
22299	if (matcher->keySeqs != NULL) {
22300	    int i;
22301	    /*
22302	    * Don't free the array, but only the content.
22303	    */
22304	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22305		if (matcher->keySeqs[i] != NULL) {
22306		    xmlFree(matcher->keySeqs[i]);
22307		    matcher->keySeqs[i] = NULL;
22308		}
22309	}
22310	if (matcher->targets) {
22311	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22312		int i;
22313		xmlSchemaPSVIIDCNodePtr idcNode;
22314		/*
22315		* Node-table items for keyrefs are not stored globally
22316		* to the validation context, since they are not bubbled.
22317		* We need to free them here.
22318		*/
22319		for (i = 0; i < matcher->targets->nbItems; i++) {
22320		    idcNode =
22321			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22322		    xmlFree(idcNode->keys);
22323		    xmlFree(idcNode);
22324		}
22325	    }
22326	    xmlSchemaItemListFree(matcher->targets);
22327	    matcher->targets = NULL;
22328	}
22329	matcher->next = NULL;
22330	/*
22331	* Cache the matcher.
22332	*/
22333	if (vctxt->idcMatcherCache != NULL)
22334	    matcher->nextCached = vctxt->idcMatcherCache;
22335	vctxt->idcMatcherCache = matcher;
22336
22337	matcher = next;
22338    }
22339}
22340
22341/**
22342 * xmlSchemaIDCAddStateObject:
22343 * @vctxt: the WXS validation context
22344 * @matcher: the IDC matcher
22345 * @sel: the XPath information
22346 * @parent: the parent "selector" state object if any
22347 * @type: "selector" or "field"
22348 *
22349 * Creates/reuses and activates state objects for the given
22350 * XPath information; if the XPath expression consists of unions,
22351 * multiple state objects are created for every unioned expression.
22352 *
22353 * Returns 0 on success and -1 on internal errors.
22354 */
22355static int
22356xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22357			xmlSchemaIDCMatcherPtr matcher,
22358			xmlSchemaIDCSelectPtr sel,
22359			int type)
22360{
22361    xmlSchemaIDCStateObjPtr sto;
22362
22363    /*
22364    * Reuse the state objects from the pool.
22365    */
22366    if (vctxt->xpathStatePool != NULL) {
22367	sto = vctxt->xpathStatePool;
22368	vctxt->xpathStatePool = sto->next;
22369	sto->next = NULL;
22370    } else {
22371	/*
22372	* Create a new state object.
22373	*/
22374	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22375	if (sto == NULL) {
22376	    xmlSchemaVErrMemory(NULL,
22377		"allocating an IDC state object", NULL);
22378	    return (-1);
22379	}
22380	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22381    }
22382    /*
22383    * Add to global list.
22384    */
22385    if (vctxt->xpathStates != NULL)
22386	sto->next = vctxt->xpathStates;
22387    vctxt->xpathStates = sto;
22388
22389    /*
22390    * Free the old xpath validation context.
22391    */
22392    if (sto->xpathCtxt != NULL)
22393	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22394
22395    /*
22396    * Create a new XPath (pattern) validation context.
22397    */
22398    sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22399	(xmlPatternPtr) sel->xpathComp);
22400    if (sto->xpathCtxt == NULL) {
22401	VERROR_INT("xmlSchemaIDCAddStateObject",
22402	    "failed to create an XPath validation context");
22403	return (-1);
22404    }
22405    sto->type = type;
22406    sto->depth = vctxt->depth;
22407    sto->matcher = matcher;
22408    sto->sel = sel;
22409    sto->nbHistory = 0;
22410
22411#ifdef DEBUG_IDC
22412    xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22413	sto->sel->xpath);
22414#endif
22415    return (0);
22416}
22417
22418/**
22419 * xmlSchemaXPathEvaluate:
22420 * @vctxt: the WXS validation context
22421 * @nodeType: the nodeType of the current node
22422 *
22423 * Evaluates all active XPath state objects.
22424 *
22425 * Returns the number of IC "field" state objects which resolved to
22426 * this node, 0 if none resolved and -1 on internal errors.
22427 */
22428static int
22429xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22430		       xmlElementType nodeType)
22431{
22432    xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22433    int res, resolved = 0, depth = vctxt->depth;
22434
22435    if (vctxt->xpathStates == NULL)
22436	return (0);
22437
22438    if (nodeType == XML_ATTRIBUTE_NODE)
22439	depth++;
22440#ifdef DEBUG_IDC
22441    {
22442	xmlChar *str = NULL;
22443	xmlGenericError(xmlGenericErrorContext,
22444	    "IDC: EVAL on %s, depth %d, type %d\n",
22445	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22446		vctxt->inode->localName), depth, nodeType);
22447	FREE_AND_NULL(str)
22448    }
22449#endif
22450    /*
22451    * Process all active XPath state objects.
22452    */
22453    first = vctxt->xpathStates;
22454    sto = first;
22455    while (sto != head) {
22456#ifdef DEBUG_IDC
22457	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22458	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22459		sto->matcher->aidc->def->name, sto->sel->xpath);
22460	else
22461	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22462		sto->matcher->aidc->def->name, sto->sel->xpath);
22463#endif
22464	if (nodeType == XML_ELEMENT_NODE)
22465	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22466		vctxt->inode->localName, vctxt->inode->nsName);
22467	else
22468	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22469		vctxt->inode->localName, vctxt->inode->nsName);
22470
22471	if (res == -1) {
22472	    VERROR_INT("xmlSchemaXPathEvaluate",
22473		"calling xmlStreamPush()");
22474	    return (-1);
22475	}
22476	if (res == 0)
22477	    goto next_sto;
22478	/*
22479	* Full match.
22480	*/
22481#ifdef DEBUG_IDC
22482	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22483	    "MATCH\n");
22484#endif
22485	/*
22486	* Register a match in the state object history.
22487	*/
22488	if (sto->history == NULL) {
22489	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22490	    if (sto->history == NULL) {
22491		xmlSchemaVErrMemory(NULL,
22492		    "allocating the state object history", NULL);
22493		return(-1);
22494	    }
22495	    sto->sizeHistory = 5;
22496	} else if (sto->sizeHistory <= sto->nbHistory) {
22497	    sto->sizeHistory *= 2;
22498	    sto->history = (int *) xmlRealloc(sto->history,
22499		sto->sizeHistory * sizeof(int));
22500	    if (sto->history == NULL) {
22501		xmlSchemaVErrMemory(NULL,
22502		    "re-allocating the state object history", NULL);
22503		return(-1);
22504	    }
22505	}
22506	sto->history[sto->nbHistory++] = depth;
22507
22508#ifdef DEBUG_IDC
22509	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22510	    vctxt->depth);
22511#endif
22512
22513	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22514	    xmlSchemaIDCSelectPtr sel;
22515	    /*
22516	    * Activate state objects for the IDC fields of
22517	    * the IDC selector.
22518	    */
22519#ifdef DEBUG_IDC
22520	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22521		"activating field states\n");
22522#endif
22523	    sel = sto->matcher->aidc->def->fields;
22524	    while (sel != NULL) {
22525		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22526		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22527		    return (-1);
22528		sel = sel->next;
22529	    }
22530	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22531	    /*
22532	    * An IDC key node was found by the IDC field.
22533	    */
22534#ifdef DEBUG_IDC
22535	    xmlGenericError(xmlGenericErrorContext,
22536		"IDC:     key found\n");
22537#endif
22538	    /*
22539	    * Notify that the character value of this node is
22540	    * needed.
22541	    */
22542	    if (resolved == 0) {
22543		if ((vctxt->inode->flags &
22544		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22545		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22546	    }
22547	    resolved++;
22548	}
22549next_sto:
22550	if (sto->next == NULL) {
22551	    /*
22552	    * Evaluate field state objects created on this node as well.
22553	    */
22554	    head = first;
22555	    sto = vctxt->xpathStates;
22556	} else
22557	    sto = sto->next;
22558    }
22559    return (resolved);
22560}
22561
22562static const xmlChar *
22563xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22564			      xmlChar **buf,
22565			      xmlSchemaPSVIIDCKeyPtr *seq,
22566			      int count)
22567{
22568    int i, res;
22569    xmlChar *value = NULL;
22570
22571    *buf = xmlStrdup(BAD_CAST "[");
22572    for (i = 0; i < count; i++) {
22573	*buf = xmlStrcat(*buf, BAD_CAST "'");
22574	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22575	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22576	    &value);
22577	if (res == 0)
22578	    *buf = xmlStrcat(*buf, BAD_CAST value);
22579	else {
22580	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22581		"failed to compute a canonical value");
22582	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22583	}
22584	if (i < count -1)
22585	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22586	else
22587	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22588	if (value != NULL) {
22589	    xmlFree(value);
22590	    value = NULL;
22591	}
22592    }
22593    *buf = xmlStrcat(*buf, BAD_CAST "]");
22594
22595    return (BAD_CAST *buf);
22596}
22597
22598/**
22599 * xmlSchemaXPathPop:
22600 * @vctxt: the WXS validation context
22601 *
22602 * Pops all XPath states.
22603 *
22604 * Returns 0 on success and -1 on internal errors.
22605 */
22606static int
22607xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22608{
22609    xmlSchemaIDCStateObjPtr sto;
22610    int res;
22611
22612    if (vctxt->xpathStates == NULL)
22613	return(0);
22614    sto = vctxt->xpathStates;
22615    do {
22616	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22617	if (res == -1)
22618	    return (-1);
22619	sto = sto->next;
22620    } while (sto != NULL);
22621    return(0);
22622}
22623
22624/**
22625 * xmlSchemaXPathProcessHistory:
22626 * @vctxt: the WXS validation context
22627 * @type: the simple/complex type of the current node if any at all
22628 * @val: the precompiled value
22629 *
22630 * Processes and pops the history items of the IDC state objects.
22631 * IDC key-sequences are validated/created on IDC bindings.
22632 *
22633 * Returns 0 on success and -1 on internal errors.
22634 */
22635static int
22636xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22637			     int depth)
22638{
22639    xmlSchemaIDCStateObjPtr sto, nextsto;
22640    int res, matchDepth;
22641    xmlSchemaPSVIIDCKeyPtr key = NULL;
22642    xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22643
22644    if (vctxt->xpathStates == NULL)
22645	return (0);
22646    sto = vctxt->xpathStates;
22647
22648#ifdef DEBUG_IDC
22649    {
22650	xmlChar *str = NULL;
22651	xmlGenericError(xmlGenericErrorContext,
22652	    "IDC: BACK on %s, depth %d\n",
22653	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22654		vctxt->inode->localName), vctxt->depth);
22655	FREE_AND_NULL(str)
22656    }
22657#endif
22658    /*
22659    * Evaluate the state objects.
22660    */
22661    while (sto != NULL) {
22662	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22663	if (res == -1) {
22664	    VERROR_INT("xmlSchemaXPathProcessHistory",
22665		"calling xmlStreamPop()");
22666	    return (-1);
22667	}
22668#ifdef DEBUG_IDC
22669	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22670	    sto->sel->xpath);
22671#endif
22672	if (sto->nbHistory == 0)
22673	    goto deregister_check;
22674
22675	matchDepth = sto->history[sto->nbHistory -1];
22676
22677	/*
22678	* Only matches at the current depth are of interest.
22679	*/
22680	if (matchDepth != depth) {
22681	    sto = sto->next;
22682	    continue;
22683	}
22684	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22685	    /*
22686	    * NOTE: According to
22687	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22688	    *   ... the simple-content of complex types is also allowed.
22689	    */
22690
22691	    if (WXS_IS_COMPLEX(type)) {
22692		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22693		    /*
22694		    * Sanity check for complex types with simple content.
22695		    */
22696		    simpleType = type->contentTypeDef;
22697		    if (simpleType == NULL) {
22698			VERROR_INT("xmlSchemaXPathProcessHistory",
22699			    "field resolves to a CT with simple content "
22700			    "but the CT is missing the ST definition");
22701			return (-1);
22702		    }
22703		} else
22704		    simpleType = NULL;
22705	    } else
22706		simpleType = type;
22707	    if (simpleType == NULL) {
22708		xmlChar *str = NULL;
22709
22710		/*
22711		* Not qualified if the field resolves to a node of non
22712		* simple type.
22713		*/
22714		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22715		    XML_SCHEMAV_CVC_IDC, NULL,
22716		    WXS_BASIC_CAST sto->matcher->aidc->def,
22717		    "The XPath '%s' of a field of %s does evaluate to a node of "
22718		    "non-simple type",
22719		    sto->sel->xpath,
22720		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22721		FREE_AND_NULL(str);
22722		sto->nbHistory--;
22723		goto deregister_check;
22724	    }
22725
22726	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22727		/*
22728		* Failed to provide the normalized value; maybe
22729		* the value was invalid.
22730		*/
22731		VERROR(XML_SCHEMAV_CVC_IDC,
22732		    WXS_BASIC_CAST sto->matcher->aidc->def,
22733		    "Warning: No precomputed value available, the value "
22734		    "was either invalid or something strange happend");
22735		sto->nbHistory--;
22736		goto deregister_check;
22737	    } else {
22738		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22739		xmlSchemaPSVIIDCKeyPtr *keySeq;
22740		int pos, idx;
22741
22742		/*
22743		* The key will be anchored on the matcher's list of
22744		* key-sequences. The position in this list is determined
22745		* by the target node's depth relative to the matcher's
22746		* depth of creation (i.e. the depth of the scope element).
22747		*
22748		* Element        Depth    Pos   List-entries
22749		* <scope>          0              NULL
22750		*   <bar>          1              NULL
22751		*     <target/>    2       2      target
22752		*   <bar>
22753                * </scope>
22754		*
22755		* The size of the list is only dependant on the depth of
22756		* the tree.
22757		* An entry will be NULLed in selector_leave, i.e. when
22758		* we hit the target's
22759		*/
22760		pos = sto->depth - matcher->depth;
22761		idx = sto->sel->index;
22762
22763		/*
22764		* Create/grow the array of key-sequences.
22765		*/
22766		if (matcher->keySeqs == NULL) {
22767		    if (pos > 9)
22768			matcher->sizeKeySeqs = pos * 2;
22769		    else
22770			matcher->sizeKeySeqs = 10;
22771		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22772			xmlMalloc(matcher->sizeKeySeqs *
22773			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22774		    if (matcher->keySeqs == NULL) {
22775			xmlSchemaVErrMemory(NULL,
22776			    "allocating an array of key-sequences",
22777			    NULL);
22778			return(-1);
22779		    }
22780		    memset(matcher->keySeqs, 0,
22781			matcher->sizeKeySeqs *
22782			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22783		} else if (pos >= matcher->sizeKeySeqs) {
22784		    int i = matcher->sizeKeySeqs;
22785
22786		    matcher->sizeKeySeqs *= 2;
22787		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22788			xmlRealloc(matcher->keySeqs,
22789			matcher->sizeKeySeqs *
22790			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22791		    if (matcher->keySeqs == NULL) {
22792			xmlSchemaVErrMemory(NULL,
22793			    "reallocating an array of key-sequences",
22794			    NULL);
22795			return (-1);
22796		    }
22797		    /*
22798		    * The array needs to be NULLed.
22799		    * TODO: Use memset?
22800		    */
22801		    for (; i < matcher->sizeKeySeqs; i++)
22802			matcher->keySeqs[i] = NULL;
22803		}
22804
22805		/*
22806		* Get/create the key-sequence.
22807		*/
22808		keySeq = matcher->keySeqs[pos];
22809		if (keySeq == NULL) {
22810		    goto create_sequence;
22811		} else if (keySeq[idx] != NULL) {
22812		    xmlChar *str = NULL;
22813		    /*
22814		    * cvc-identity-constraint:
22815		    * 3 For each node in the �target node set� all
22816		    * of the {fields}, with that node as the context
22817		    * node, evaluate to either an empty node-set or
22818		    * a node-set with exactly one member, which must
22819		    * have a simple type.
22820		    *
22821		    * The key was already set; report an error.
22822		    */
22823		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22824			XML_SCHEMAV_CVC_IDC, NULL,
22825			WXS_BASIC_CAST matcher->aidc->def,
22826			"The XPath '%s' of a field of %s evaluates to a "
22827			"node-set with more than one member",
22828			sto->sel->xpath,
22829			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22830		    FREE_AND_NULL(str);
22831		    sto->nbHistory--;
22832		    goto deregister_check;
22833		} else
22834		    goto create_key;
22835
22836create_sequence:
22837		/*
22838		* Create a key-sequence.
22839		*/
22840		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22841		    matcher->aidc->def->nbFields *
22842		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22843		if (keySeq == NULL) {
22844		    xmlSchemaVErrMemory(NULL,
22845			"allocating an IDC key-sequence", NULL);
22846		    return(-1);
22847		}
22848		memset(keySeq, 0, matcher->aidc->def->nbFields *
22849		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22850		matcher->keySeqs[pos] = keySeq;
22851create_key:
22852		/*
22853		* Create a key once per node only.
22854		*/
22855		if (key == NULL) {
22856		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22857			sizeof(xmlSchemaPSVIIDCKey));
22858		    if (key == NULL) {
22859			xmlSchemaVErrMemory(NULL,
22860			    "allocating a IDC key", NULL);
22861			xmlFree(keySeq);
22862			matcher->keySeqs[pos] = NULL;
22863			return(-1);
22864		    }
22865		    /*
22866		    * Consume the compiled value.
22867		    */
22868		    key->type = simpleType;
22869		    key->val = vctxt->inode->val;
22870		    vctxt->inode->val = NULL;
22871		    /*
22872		    * Store the key in a global list.
22873		    */
22874		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22875			xmlSchemaIDCFreeKey(key);
22876			return (-1);
22877		    }
22878		}
22879		keySeq[idx] = key;
22880	    }
22881	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22882
22883	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22884	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22885	    xmlSchemaPSVIIDCNodePtr ntItem;
22886	    xmlSchemaIDCMatcherPtr matcher;
22887	    xmlSchemaIDCPtr idc;
22888	    xmlSchemaItemListPtr targets;
22889	    int pos, i, j, nbKeys;
22890	    /*
22891	    * Here we have the following scenario:
22892	    * An IDC 'selector' state object resolved to a target node,
22893	    * during the time this target node was in the
22894	    * ancestor-or-self axis, the 'field' state object(s) looked
22895	    * out for matching nodes to create a key-sequence for this
22896	    * target node. Now we are back to this target node and need
22897	    * to put the key-sequence, together with the target node
22898	    * itself, into the node-table of the corresponding IDC
22899	    * binding.
22900	    */
22901	    matcher = sto->matcher;
22902	    idc = matcher->aidc->def;
22903	    nbKeys = idc->nbFields;
22904	    pos = depth - matcher->depth;
22905	    /*
22906	    * Check if the matcher has any key-sequences at all, plus
22907	    * if it has a key-sequence for the current target node.
22908	    */
22909	    if ((matcher->keySeqs == NULL) ||
22910		(matcher->sizeKeySeqs <= pos)) {
22911		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22912		    goto selector_key_error;
22913		else
22914		    goto selector_leave;
22915	    }
22916
22917	    keySeq = &(matcher->keySeqs[pos]);
22918	    if (*keySeq == NULL) {
22919		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22920		    goto selector_key_error;
22921		else
22922		    goto selector_leave;
22923	    }
22924
22925	    for (i = 0; i < nbKeys; i++) {
22926		if ((*keySeq)[i] == NULL) {
22927		    /*
22928		    * Not qualified, if not all fields did resolve.
22929		    */
22930		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22931			/*
22932			* All fields of a "key" IDC must resolve.
22933			*/
22934			goto selector_key_error;
22935		    }
22936		    goto selector_leave;
22937		}
22938	    }
22939	    /*
22940	    * All fields did resolve.
22941	    */
22942
22943	    /*
22944	    * 4.1 If the {identity-constraint category} is unique(/key),
22945	    * then no two members of the �qualified node set� have
22946	    * �key-sequences� whose members are pairwise equal, as
22947	    * defined by Equal in [XML Schemas: Datatypes].
22948	    *
22949	    * Get the IDC binding from the matcher and check for
22950	    * duplicate key-sequences.
22951	    */
22952#if 0
22953	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22954#endif
22955	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22956	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22957		(targets->nbItems != 0)) {
22958		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22959
22960		i = 0;
22961		res = 0;
22962		/*
22963		* Compare the key-sequences, key by key.
22964		*/
22965		do {
22966		    bkeySeq =
22967			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22968		    for (j = 0; j < nbKeys; j++) {
22969			ckey = (*keySeq)[j];
22970			bkey = bkeySeq[j];
22971			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22972			if (res == -1) {
22973			    return (-1);
22974			} else if (res == 0) {
22975			    /*
22976			    * One of the keys differs, so the key-sequence
22977			    * won't be equal; get out.
22978			    */
22979			    break;
22980			}
22981		    }
22982		    if (res == 1) {
22983			/*
22984			* Duplicate key-sequence found.
22985			*/
22986			break;
22987		    }
22988		    i++;
22989		} while (i < targets->nbItems);
22990		if (i != targets->nbItems) {
22991		    xmlChar *str = NULL, *strB = NULL;
22992		    /*
22993		    * TODO: Try to report the key-sequence.
22994		    */
22995		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22996			XML_SCHEMAV_CVC_IDC, NULL,
22997			WXS_BASIC_CAST idc,
22998			"Duplicate key-sequence %s in %s",
22999			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23000			    (*keySeq), nbKeys),
23001			xmlSchemaGetIDCDesignation(&strB, idc));
23002		    FREE_AND_NULL(str);
23003		    FREE_AND_NULL(strB);
23004		    goto selector_leave;
23005		}
23006	    }
23007	    /*
23008	    * Add a node-table item to the IDC binding.
23009	    */
23010	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23011		sizeof(xmlSchemaPSVIIDCNode));
23012	    if (ntItem == NULL) {
23013		xmlSchemaVErrMemory(NULL,
23014		    "allocating an IDC node-table item", NULL);
23015		xmlFree(*keySeq);
23016		*keySeq = NULL;
23017		return(-1);
23018	    }
23019	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23020
23021	    /*
23022	    * Store the node-table item in a global list.
23023	    */
23024	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23025		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23026		    xmlFree(ntItem);
23027		    xmlFree(*keySeq);
23028		    *keySeq = NULL;
23029		    return (-1);
23030		}
23031		ntItem->nodeQNameID = -1;
23032	    } else {
23033		/*
23034		* Save a cached QName for this node on the IDC node, to be
23035		* able to report it, even if the node is not saved.
23036		*/
23037		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23038		    vctxt->inode->localName, vctxt->inode->nsName);
23039		if (ntItem->nodeQNameID == -1) {
23040		    xmlFree(ntItem);
23041		    xmlFree(*keySeq);
23042		    *keySeq = NULL;
23043		    return (-1);
23044		}
23045	    }
23046	    /*
23047	    * Init the node-table item: Save the node, position and
23048	    * consume the key-sequence.
23049	    */
23050	    ntItem->node = vctxt->node;
23051	    ntItem->nodeLine = vctxt->inode->nodeLine;
23052	    ntItem->keys = *keySeq;
23053	    *keySeq = NULL;
23054#if 0
23055	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23056#endif
23057	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23058		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23059		    /*
23060		    * Free the item, since keyref items won't be
23061		    * put on a global list.
23062		    */
23063		    xmlFree(ntItem->keys);
23064		    xmlFree(ntItem);
23065		}
23066		return (-1);
23067	    }
23068
23069	    goto selector_leave;
23070selector_key_error:
23071	    {
23072		xmlChar *str = NULL;
23073		/*
23074		* 4.2.1 (KEY) The �target node set� and the
23075		* �qualified node set� are equal, that is, every
23076		* member of the �target node set� is also a member
23077		* of the �qualified node set� and vice versa.
23078		*/
23079		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23080		    XML_SCHEMAV_CVC_IDC, NULL,
23081		    WXS_BASIC_CAST idc,
23082		    "Not all fields of %s evaluate to a node",
23083		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23084		FREE_AND_NULL(str);
23085	    }
23086selector_leave:
23087	    /*
23088	    * Free the key-sequence if not added to the IDC table.
23089	    */
23090	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23091		xmlFree(*keySeq);
23092		*keySeq = NULL;
23093	    }
23094	} /* if selector */
23095
23096	sto->nbHistory--;
23097
23098deregister_check:
23099	/*
23100	* Deregister state objects if they reach the depth of creation.
23101	*/
23102	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23103#ifdef DEBUG_IDC
23104	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23105		sto->sel->xpath);
23106#endif
23107	    if (vctxt->xpathStates != sto) {
23108		VERROR_INT("xmlSchemaXPathProcessHistory",
23109		    "The state object to be removed is not the first "
23110		    "in the list");
23111	    }
23112	    nextsto = sto->next;
23113	    /*
23114	    * Unlink from the list of active XPath state objects.
23115	    */
23116	    vctxt->xpathStates = sto->next;
23117	    sto->next = vctxt->xpathStatePool;
23118	    /*
23119	    * Link it to the pool of reusable state objects.
23120	    */
23121	    vctxt->xpathStatePool = sto;
23122	    sto = nextsto;
23123	} else
23124	    sto = sto->next;
23125    } /* while (sto != NULL) */
23126    return (0);
23127}
23128
23129/**
23130 * xmlSchemaIDCRegisterMatchers:
23131 * @vctxt: the WXS validation context
23132 * @elemDecl: the element declaration
23133 *
23134 * Creates helper objects to evaluate IDC selectors/fields
23135 * successively.
23136 *
23137 * Returns 0 if OK and -1 on internal errors.
23138 */
23139static int
23140xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23141			     xmlSchemaElementPtr elemDecl)
23142{
23143    xmlSchemaIDCMatcherPtr matcher, last = NULL;
23144    xmlSchemaIDCPtr idc, refIdc;
23145    xmlSchemaIDCAugPtr aidc;
23146
23147    idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23148    if (idc == NULL)
23149	return (0);
23150
23151#ifdef DEBUG_IDC
23152    {
23153	xmlChar *str = NULL;
23154	xmlGenericError(xmlGenericErrorContext,
23155	    "IDC: REGISTER on %s, depth %d\n",
23156	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23157		vctxt->inode->localName), vctxt->depth);
23158	FREE_AND_NULL(str)
23159    }
23160#endif
23161    if (vctxt->inode->idcMatchers != NULL) {
23162	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23163	    "The chain of IDC matchers is expected to be empty");
23164	return (-1);
23165    }
23166    do {
23167	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23168	    /*
23169	    * Since IDCs bubbles are expensive we need to know the
23170	    * depth at which the bubbles should stop; this will be
23171	    * the depth of the top-most keyref IDC. If no keyref
23172	    * references a key/unique IDC, the keyrefDepth will
23173	    * be -1, indicating that no bubbles are needed.
23174	    */
23175	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23176	    if (refIdc != NULL) {
23177		/*
23178		* Remember that we have keyrefs on this node.
23179		*/
23180		vctxt->inode->hasKeyrefs = 1;
23181		/*
23182		* Lookup the referenced augmented IDC info.
23183		*/
23184		aidc = vctxt->aidcs;
23185		while (aidc != NULL) {
23186		    if (aidc->def == refIdc)
23187			break;
23188		    aidc = aidc->next;
23189		}
23190		if (aidc == NULL) {
23191		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23192			"Could not find an augmented IDC item for an IDC "
23193			"definition");
23194		    return (-1);
23195		}
23196		if ((aidc->keyrefDepth == -1) ||
23197		    (vctxt->depth < aidc->keyrefDepth))
23198		    aidc->keyrefDepth = vctxt->depth;
23199	    }
23200	}
23201	/*
23202	* Lookup the augmented IDC item for the IDC definition.
23203	*/
23204	aidc = vctxt->aidcs;
23205	while (aidc != NULL) {
23206	    if (aidc->def == idc)
23207		break;
23208	    aidc = aidc->next;
23209	}
23210	if (aidc == NULL) {
23211	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23212		"Could not find an augmented IDC item for an IDC definition");
23213	    return (-1);
23214	}
23215	/*
23216	* Create an IDC matcher for every IDC definition.
23217	*/
23218	if (vctxt->idcMatcherCache != NULL) {
23219	    /*
23220	    * Reuse a cached matcher.
23221	    */
23222	    matcher = vctxt->idcMatcherCache;
23223	    vctxt->idcMatcherCache = matcher->nextCached;
23224	    matcher->nextCached = NULL;
23225	} else {
23226	    matcher = (xmlSchemaIDCMatcherPtr)
23227		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23228	    if (matcher == NULL) {
23229		xmlSchemaVErrMemory(vctxt,
23230		    "allocating an IDC matcher", NULL);
23231		return (-1);
23232	    }
23233	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23234	}
23235	if (last == NULL)
23236	    vctxt->inode->idcMatchers = matcher;
23237	else
23238	    last->next = matcher;
23239	last = matcher;
23240
23241	matcher->type = IDC_MATCHER;
23242	matcher->depth = vctxt->depth;
23243	matcher->aidc = aidc;
23244	matcher->idcType = aidc->def->type;
23245#ifdef DEBUG_IDC
23246	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23247#endif
23248	/*
23249	* Init the automaton state object.
23250	*/
23251	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23252	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23253	    return (-1);
23254
23255	idc = idc->next;
23256    } while (idc != NULL);
23257    return (0);
23258}
23259
23260static int
23261xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23262			   xmlSchemaNodeInfoPtr ielem)
23263{
23264    xmlSchemaPSVIIDCBindingPtr bind;
23265    int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23266    xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23267    xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23268
23269    xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23270    /* vctxt->createIDCNodeTables */
23271    while (matcher != NULL) {
23272	/*
23273	* Skip keyref IDCs and empty IDC target-lists.
23274	*/
23275	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23276	    WXS_ILIST_IS_EMPTY(matcher->targets))
23277	{
23278	    matcher = matcher->next;
23279	    continue;
23280	}
23281	/*
23282	* If we _want_ the IDC node-table to be created in any case
23283	* then do so. Otherwise create them only if keyrefs need them.
23284	*/
23285	if ((! vctxt->createIDCNodeTables) &&
23286	    ((matcher->aidc->keyrefDepth == -1) ||
23287	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23288	{
23289	    matcher = matcher->next;
23290	    continue;
23291	}
23292	/*
23293	* Get/create the IDC binding on this element for the IDC definition.
23294	*/
23295	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23296
23297	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23298	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23299	    nbDupls = bind->dupls->nbItems;
23300	} else {
23301	    dupls = NULL;
23302	    nbDupls = 0;
23303	}
23304	if (bind->nodeTable != NULL) {
23305	    nbNodeTable = bind->nbNodes;
23306	} else {
23307	    nbNodeTable = 0;
23308	}
23309
23310	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23311	    /*
23312	    * Transfer all IDC target-nodes to the IDC node-table.
23313	    */
23314	    bind->nodeTable =
23315		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23316	    bind->sizeNodes = matcher->targets->sizeItems;
23317	    bind->nbNodes = matcher->targets->nbItems;
23318
23319	    matcher->targets->items = NULL;
23320	    matcher->targets->sizeItems = 0;
23321	    matcher->targets->nbItems = 0;
23322	} else {
23323	    /*
23324	    * Compare the key-sequences and add to the IDC node-table.
23325	    */
23326	    nbTargets = matcher->targets->nbItems;
23327	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23328	    nbFields = matcher->aidc->def->nbFields;
23329	    i = 0;
23330	    do {
23331		keys = targets[i]->keys;
23332		if (nbDupls) {
23333		    /*
23334		    * Search in already found duplicates first.
23335		    */
23336		    j = 0;
23337		    do {
23338			if (nbFields == 1) {
23339			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23340				dupls[j]->keys[0]->val);
23341			    if (res == -1)
23342				goto internal_error;
23343			    if (res == 1) {
23344				/*
23345				* Equal key-sequence.
23346				*/
23347				goto next_target;
23348			    }
23349			} else {
23350			    res = 0;
23351			    ntkeys = dupls[j]->keys;
23352			    for (k = 0; k < nbFields; k++) {
23353				res = xmlSchemaAreValuesEqual(keys[k]->val,
23354				    ntkeys[k]->val);
23355				if (res == -1)
23356				    goto internal_error;
23357				if (res == 0) {
23358				    /*
23359				    * One of the keys differs.
23360				    */
23361				    break;
23362				}
23363			    }
23364			    if (res == 1) {
23365				/*
23366				* Equal key-sequence found.
23367				*/
23368				goto next_target;
23369			    }
23370			}
23371			j++;
23372		    } while (j < nbDupls);
23373		}
23374		if (nbNodeTable) {
23375		    j = 0;
23376		    do {
23377			if (nbFields == 1) {
23378			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23379				bind->nodeTable[j]->keys[0]->val);
23380			    if (res == -1)
23381				goto internal_error;
23382			    if (res == 0) {
23383				/*
23384				* The key-sequence differs.
23385				*/
23386				goto next_node_table_entry;
23387			    }
23388			} else {
23389			    res = 0;
23390			    ntkeys = bind->nodeTable[j]->keys;
23391			    for (k = 0; k < nbFields; k++) {
23392				res = xmlSchemaAreValuesEqual(keys[k]->val,
23393				    ntkeys[k]->val);
23394				if (res == -1)
23395				    goto internal_error;
23396				if (res == 0) {
23397				    /*
23398				    * One of the keys differs.
23399				    */
23400				    goto next_node_table_entry;
23401				}
23402			    }
23403			}
23404			/*
23405			* Add the duplicate to the list of duplicates.
23406			*/
23407			if (bind->dupls == NULL) {
23408			    bind->dupls = xmlSchemaItemListCreate();
23409			    if (bind->dupls == NULL)
23410				goto internal_error;
23411			}
23412			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23413			    goto internal_error;
23414			/*
23415			* Remove the duplicate entry from the IDC node-table.
23416			*/
23417			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23418			bind->nbNodes--;
23419
23420			goto next_target;
23421
23422next_node_table_entry:
23423			j++;
23424		    } while (j < nbNodeTable);
23425		}
23426		/*
23427		* If everything is fine, then add the IDC target-node to
23428		* the IDC node-table.
23429		*/
23430		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23431		    goto internal_error;
23432
23433next_target:
23434		i++;
23435	    } while (i < nbTargets);
23436	}
23437	matcher = matcher->next;
23438    }
23439    return(0);
23440
23441internal_error:
23442    return(-1);
23443}
23444
23445/**
23446 * xmlSchemaBubbleIDCNodeTables:
23447 * @depth: the current tree depth
23448 *
23449 * Merges IDC bindings of an element at @depth into the corresponding IDC
23450 * bindings of its parent element. If a duplicate note-table entry is found,
23451 * both, the parent node-table entry and child entry are discarded from the
23452 * node-table of the parent.
23453 *
23454 * Returns 0 if OK and -1 on internal errors.
23455 */
23456static int
23457xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23458{
23459    xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23460    xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23461    xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23462    xmlSchemaIDCAugPtr aidc;
23463    int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23464
23465    bind = vctxt->inode->idcTable;
23466    if (bind == NULL) {
23467	/* Fine, no table, no bubbles. */
23468	return (0);
23469    }
23470
23471    parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23472    /*
23473    * Walk all bindings; create new or add to existing bindings.
23474    * Remove duplicate key-sequences.
23475    */
23476    while (bind != NULL) {
23477
23478	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23479	    goto next_binding;
23480	/*
23481	* Check if the key/unique IDC table needs to be bubbled.
23482	*/
23483	if (! vctxt->createIDCNodeTables) {
23484	    aidc = vctxt->aidcs;
23485	    do {
23486		if (aidc->def == bind->definition) {
23487		    if ((aidc->keyrefDepth == -1) ||
23488			(aidc->keyrefDepth >= vctxt->depth)) {
23489			goto next_binding;
23490		    }
23491		    break;
23492		}
23493		aidc = aidc->next;
23494	    } while (aidc != NULL);
23495	}
23496
23497	if (parTable != NULL)
23498	    parBind = *parTable;
23499	/*
23500	* Search a matching parent binding for the
23501	* IDC definition.
23502	*/
23503	while (parBind != NULL) {
23504	    if (parBind->definition == bind->definition)
23505		break;
23506	    parBind = parBind->next;
23507	}
23508
23509	if (parBind != NULL) {
23510	    /*
23511	    * Compare every node-table entry of the child node,
23512	    * i.e. the key-sequence within, ...
23513	    */
23514	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23515
23516	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23517		oldDupls = parBind->dupls->nbItems;
23518		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23519	    } else {
23520		dupls = NULL;
23521		oldDupls = 0;
23522	    }
23523
23524	    parNodes = parBind->nodeTable;
23525	    nbFields = bind->definition->nbFields;
23526
23527	    for (i = 0; i < bind->nbNodes; i++) {
23528		node = bind->nodeTable[i];
23529		if (node == NULL)
23530		    continue;
23531		/*
23532		* ...with every key-sequence of the parent node, already
23533		* evaluated to be a duplicate key-sequence.
23534		*/
23535		if (oldDupls) {
23536		    j = 0;
23537		    while (j < oldDupls) {
23538			if (nbFields == 1) {
23539			    ret = xmlSchemaAreValuesEqual(
23540				node->keys[0]->val,
23541				dupls[j]->keys[0]->val);
23542			    if (ret == -1)
23543				goto internal_error;
23544			    if (ret == 0) {
23545				j++;
23546				continue;
23547			    }
23548			} else {
23549			    parNode = dupls[j];
23550			    for (k = 0; k < nbFields; k++) {
23551				ret = xmlSchemaAreValuesEqual(
23552				    node->keys[k]->val,
23553				    parNode->keys[k]->val);
23554				if (ret == -1)
23555				    goto internal_error;
23556				if (ret == 0)
23557				    break;
23558			    }
23559			}
23560			if (ret == 1)
23561			    /* Duplicate found. */
23562			    break;
23563			j++;
23564		    }
23565		    if (j != oldDupls) {
23566			/* Duplicate found. Skip this entry. */
23567			continue;
23568		    }
23569		}
23570		/*
23571		* ... and with every key-sequence of the parent node.
23572		*/
23573		if (oldNum) {
23574		    j = 0;
23575		    while (j < oldNum) {
23576			parNode = parNodes[j];
23577			if (nbFields == 1) {
23578			    ret = xmlSchemaAreValuesEqual(
23579				node->keys[0]->val,
23580				parNode->keys[0]->val);
23581			    if (ret == -1)
23582				goto internal_error;
23583			    if (ret == 0) {
23584				j++;
23585				continue;
23586			    }
23587			} else {
23588			    for (k = 0; k < nbFields; k++) {
23589				ret = xmlSchemaAreValuesEqual(
23590				    node->keys[k]->val,
23591				    parNode->keys[k]->val);
23592				if (ret == -1)
23593				    goto internal_error;
23594				if (ret == 0)
23595				    break;
23596			    }
23597			}
23598			if (ret == 1)
23599			    /* Duplicate found. */
23600			    break;
23601			j++;
23602		    }
23603		    if (j != oldNum) {
23604			/*
23605			* Handle duplicates. Move the duplicate in
23606			* the parent's node-table to the list of
23607			* duplicates.
23608			*/
23609			oldNum--;
23610			parBind->nbNodes--;
23611			/*
23612			* Move last old item to pos of duplicate.
23613			*/
23614			parNodes[j] = parNodes[oldNum];
23615
23616			if (parBind->nbNodes != oldNum) {
23617			    /*
23618			    * If new items exist, move last new item to
23619			    * last of old items.
23620			    */
23621			    parNodes[oldNum] =
23622				parNodes[parBind->nbNodes];
23623			}
23624			if (parBind->dupls == NULL) {
23625			    parBind->dupls = xmlSchemaItemListCreate();
23626			    if (parBind->dupls == NULL)
23627				goto internal_error;
23628			}
23629			xmlSchemaItemListAdd(parBind->dupls, parNode);
23630		    } else {
23631			/*
23632			* Add the node-table entry (node and key-sequence) of
23633			* the child node to the node table of the parent node.
23634			*/
23635			if (parBind->nodeTable == NULL) {
23636			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23637				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23638			    if (parBind->nodeTable == NULL) {
23639				xmlSchemaVErrMemory(NULL,
23640				    "allocating IDC list of node-table items", NULL);
23641				goto internal_error;
23642			    }
23643			    parBind->sizeNodes = 1;
23644			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23645			    parBind->sizeNodes *= 2;
23646			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23647				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23648				sizeof(xmlSchemaPSVIIDCNodePtr));
23649			    if (parBind->nodeTable == NULL) {
23650				xmlSchemaVErrMemory(NULL,
23651				    "re-allocating IDC list of node-table items", NULL);
23652				goto internal_error;
23653			    }
23654			}
23655			parNodes = parBind->nodeTable;
23656			/*
23657			* Append the new node-table entry to the 'new node-table
23658			* entries' section.
23659			*/
23660			parNodes[parBind->nbNodes++] = node;
23661		    }
23662
23663		}
23664
23665	    }
23666	} else {
23667	    /*
23668	    * No binding for the IDC was found: create a new one and
23669	    * copy all node-tables.
23670	    */
23671	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23672	    if (parBind == NULL)
23673		goto internal_error;
23674
23675	    /*
23676	    * TODO: Hmm, how to optimize the initial number of
23677	    * allocated entries?
23678	    */
23679	    if (bind->nbNodes != 0) {
23680		/*
23681		* Add all IDC node-table entries.
23682		*/
23683		if (! vctxt->psviExposeIDCNodeTables) {
23684		    /*
23685		    * Just move the entries.
23686		    * NOTE: this is quite save here, since
23687		    * all the keyref lookups have already been
23688		    * performed.
23689		    */
23690		    parBind->nodeTable = bind->nodeTable;
23691		    bind->nodeTable = NULL;
23692		    parBind->sizeNodes = bind->sizeNodes;
23693		    bind->sizeNodes = 0;
23694		    parBind->nbNodes = bind->nbNodes;
23695		    bind->nbNodes = 0;
23696		} else {
23697		    /*
23698		    * Copy the entries.
23699		    */
23700		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23701			xmlMalloc(bind->nbNodes *
23702			sizeof(xmlSchemaPSVIIDCNodePtr));
23703		    if (parBind->nodeTable == NULL) {
23704			xmlSchemaVErrMemory(NULL,
23705			    "allocating an array of IDC node-table "
23706			    "items", NULL);
23707			xmlSchemaIDCFreeBinding(parBind);
23708			goto internal_error;
23709		    }
23710		    parBind->sizeNodes = bind->nbNodes;
23711		    parBind->nbNodes = bind->nbNodes;
23712		    memcpy(parBind->nodeTable, bind->nodeTable,
23713			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23714		}
23715	    }
23716	    if (bind->dupls) {
23717		/*
23718		* Move the duplicates.
23719		*/
23720		if (parBind->dupls != NULL)
23721		    xmlSchemaItemListFree(parBind->dupls);
23722		parBind->dupls = bind->dupls;
23723		bind->dupls = NULL;
23724	    }
23725            if (parTable != NULL) {
23726                if (*parTable == NULL)
23727                    *parTable = parBind;
23728                else {
23729                    parBind->next = *parTable;
23730                    *parTable = parBind;
23731                }
23732            }
23733	}
23734
23735next_binding:
23736	bind = bind->next;
23737    }
23738    return (0);
23739
23740internal_error:
23741    return(-1);
23742}
23743
23744/**
23745 * xmlSchemaCheckCVCIDCKeyRef:
23746 * @vctxt: the WXS validation context
23747 * @elemDecl: the element declaration
23748 *
23749 * Check the cvc-idc-keyref constraints.
23750 */
23751static int
23752xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23753{
23754    xmlSchemaIDCMatcherPtr matcher;
23755    xmlSchemaPSVIIDCBindingPtr bind;
23756
23757    matcher = vctxt->inode->idcMatchers;
23758    /*
23759    * Find a keyref.
23760    */
23761    while (matcher != NULL) {
23762	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23763	    matcher->targets &&
23764	    matcher->targets->nbItems)
23765	{
23766	    int i, j, k, res, nbFields, hasDupls;
23767	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23768	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23769
23770	    nbFields = matcher->aidc->def->nbFields;
23771
23772	    /*
23773	    * Find the IDC node-table for the referenced IDC key/unique.
23774	    */
23775	    bind = vctxt->inode->idcTable;
23776	    while (bind != NULL) {
23777		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23778		    bind->definition)
23779		    break;
23780		bind = bind->next;
23781	    }
23782	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23783	    /*
23784	    * Search for a matching key-sequences.
23785	    */
23786	    for (i = 0; i < matcher->targets->nbItems; i++) {
23787		res = 0;
23788		refNode = matcher->targets->items[i];
23789		if (bind != NULL) {
23790		    refKeys = refNode->keys;
23791		    for (j = 0; j < bind->nbNodes; j++) {
23792			keys = bind->nodeTable[j]->keys;
23793			for (k = 0; k < nbFields; k++) {
23794			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23795				refKeys[k]->val);
23796			    if (res == 0)
23797				break;
23798			    else if (res == -1) {
23799				return (-1);
23800			    }
23801			}
23802			if (res == 1) {
23803			    /*
23804			    * Match found.
23805			    */
23806			    break;
23807			}
23808		    }
23809		    if ((res == 0) && hasDupls) {
23810			/*
23811			* Search in duplicates
23812			*/
23813			for (j = 0; j < bind->dupls->nbItems; j++) {
23814			    keys = ((xmlSchemaPSVIIDCNodePtr)
23815				bind->dupls->items[j])->keys;
23816			    for (k = 0; k < nbFields; k++) {
23817				res = xmlSchemaAreValuesEqual(keys[k]->val,
23818				    refKeys[k]->val);
23819				if (res == 0)
23820				    break;
23821				else if (res == -1) {
23822				    return (-1);
23823				}
23824			    }
23825			    if (res == 1) {
23826				/*
23827				* Match in duplicates found.
23828				*/
23829				xmlChar *str = NULL, *strB = NULL;
23830				xmlSchemaKeyrefErr(vctxt,
23831				    XML_SCHEMAV_CVC_IDC, refNode,
23832				    (xmlSchemaTypePtr) matcher->aidc->def,
23833				    "More than one match found for "
23834				    "key-sequence %s of keyref '%s'",
23835				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23836					refNode->keys, nbFields),
23837				    xmlSchemaGetComponentQName(&strB,
23838					matcher->aidc->def));
23839				FREE_AND_NULL(str);
23840				FREE_AND_NULL(strB);
23841				break;
23842			    }
23843			}
23844		    }
23845		}
23846
23847		if (res == 0) {
23848		    xmlChar *str = NULL, *strB = NULL;
23849		    xmlSchemaKeyrefErr(vctxt,
23850			XML_SCHEMAV_CVC_IDC, refNode,
23851			(xmlSchemaTypePtr) matcher->aidc->def,
23852			"No match found for key-sequence %s of keyref '%s'",
23853			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23854			    refNode->keys, nbFields),
23855			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23856		    FREE_AND_NULL(str);
23857		    FREE_AND_NULL(strB);
23858		}
23859	    }
23860	}
23861	matcher = matcher->next;
23862    }
23863    /* TODO: Return an error if any error encountered. */
23864    return (0);
23865}
23866
23867/************************************************************************
23868 * 									*
23869 * 			XML Reader validation code                      *
23870 * 									*
23871 ************************************************************************/
23872
23873static xmlSchemaAttrInfoPtr
23874xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23875{
23876    xmlSchemaAttrInfoPtr iattr;
23877    /*
23878    * Grow/create list of attribute infos.
23879    */
23880    if (vctxt->attrInfos == NULL) {
23881	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23882	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23883	vctxt->sizeAttrInfos = 1;
23884	if (vctxt->attrInfos == NULL) {
23885	    xmlSchemaVErrMemory(vctxt,
23886		"allocating attribute info list", NULL);
23887	    return (NULL);
23888	}
23889    } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23890	vctxt->sizeAttrInfos++;
23891	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23892	    xmlRealloc(vctxt->attrInfos,
23893		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23894	if (vctxt->attrInfos == NULL) {
23895	    xmlSchemaVErrMemory(vctxt,
23896		"re-allocating attribute info list", NULL);
23897	    return (NULL);
23898	}
23899    } else {
23900	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23901	if (iattr->localName != NULL) {
23902	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23903		"attr info not cleared");
23904	    return (NULL);
23905	}
23906	iattr->nodeType = XML_ATTRIBUTE_NODE;
23907	return (iattr);
23908    }
23909    /*
23910    * Create an attribute info.
23911    */
23912    iattr = (xmlSchemaAttrInfoPtr)
23913	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23914    if (iattr == NULL) {
23915	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23916	return (NULL);
23917    }
23918    memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23919    iattr->nodeType = XML_ATTRIBUTE_NODE;
23920    vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23921
23922    return (iattr);
23923}
23924
23925static int
23926xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23927			xmlNodePtr attrNode,
23928			int nodeLine,
23929			const xmlChar *localName,
23930			const xmlChar *nsName,
23931			int ownedNames,
23932			xmlChar *value,
23933			int ownedValue)
23934{
23935    xmlSchemaAttrInfoPtr attr;
23936
23937    attr = xmlSchemaGetFreshAttrInfo(vctxt);
23938    if (attr == NULL) {
23939	VERROR_INT("xmlSchemaPushAttribute",
23940	    "calling xmlSchemaGetFreshAttrInfo()");
23941	return (-1);
23942    }
23943    attr->node = attrNode;
23944    attr->nodeLine = nodeLine;
23945    attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23946    attr->localName = localName;
23947    attr->nsName = nsName;
23948    if (ownedNames)
23949	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23950    /*
23951    * Evaluate if it's an XSI attribute.
23952    */
23953    if (nsName != NULL) {
23954	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23955	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23956		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23957	    }
23958	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23959	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23960		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23961	    }
23962	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23963	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23964		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23965	    }
23966	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23967	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23968		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23969	    }
23970	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23971	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23972	}
23973    }
23974    attr->value = value;
23975    if (ownedValue)
23976	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23977    if (attr->metaType != 0)
23978	attr->state = XML_SCHEMAS_ATTR_META;
23979    return (0);
23980}
23981
23982/**
23983 * xmlSchemaClearElemInfo:
23984 * @vctxt: the WXS validation context
23985 * @ielem: the element information item
23986 */
23987static void
23988xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23989		       xmlSchemaNodeInfoPtr ielem)
23990{
23991    ielem->hasKeyrefs = 0;
23992    ielem->appliedXPath = 0;
23993    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23994	FREE_AND_NULL(ielem->localName);
23995	FREE_AND_NULL(ielem->nsName);
23996    } else {
23997	ielem->localName = NULL;
23998	ielem->nsName = NULL;
23999    }
24000    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24001	FREE_AND_NULL(ielem->value);
24002    } else {
24003	ielem->value = NULL;
24004    }
24005    if (ielem->val != NULL) {
24006	/*
24007	* PSVI TODO: Be careful not to free it when the value is
24008	* exposed via PSVI.
24009	*/
24010	xmlSchemaFreeValue(ielem->val);
24011	ielem->val = NULL;
24012    }
24013    if (ielem->idcMatchers != NULL) {
24014	/*
24015	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24016	*   Does it work?
24017	*/
24018	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24019#if 0
24020	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24021#endif
24022	ielem->idcMatchers = NULL;
24023    }
24024    if (ielem->idcTable != NULL) {
24025	/*
24026	* OPTIMIZE TODO: Use a pool of IDC tables??.
24027	*/
24028	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24029	ielem->idcTable = NULL;
24030    }
24031    if (ielem->regexCtxt != NULL) {
24032	xmlRegFreeExecCtxt(ielem->regexCtxt);
24033	ielem->regexCtxt = NULL;
24034    }
24035    if (ielem->nsBindings != NULL) {
24036	xmlFree((xmlChar **)ielem->nsBindings);
24037	ielem->nsBindings = NULL;
24038	ielem->nbNsBindings = 0;
24039	ielem->sizeNsBindings = 0;
24040    }
24041}
24042
24043/**
24044 * xmlSchemaGetFreshElemInfo:
24045 * @vctxt: the schema validation context
24046 *
24047 * Creates/reuses and initializes the element info item for
24048 * the currect tree depth.
24049 *
24050 * Returns the element info item or NULL on API or internal errors.
24051 */
24052static xmlSchemaNodeInfoPtr
24053xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24054{
24055    xmlSchemaNodeInfoPtr info = NULL;
24056
24057    if (vctxt->depth > vctxt->sizeElemInfos) {
24058	VERROR_INT("xmlSchemaGetFreshElemInfo",
24059	    "inconsistent depth encountered");
24060	return (NULL);
24061    }
24062    if (vctxt->elemInfos == NULL) {
24063	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24064	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24065	if (vctxt->elemInfos == NULL) {
24066	    xmlSchemaVErrMemory(vctxt,
24067		"allocating the element info array", NULL);
24068	    return (NULL);
24069	}
24070	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24071	vctxt->sizeElemInfos = 10;
24072    } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24073	int i = vctxt->sizeElemInfos;
24074
24075	vctxt->sizeElemInfos *= 2;
24076	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24077	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24078	    sizeof(xmlSchemaNodeInfoPtr));
24079	if (vctxt->elemInfos == NULL) {
24080	    xmlSchemaVErrMemory(vctxt,
24081		"re-allocating the element info array", NULL);
24082	    return (NULL);
24083	}
24084	/*
24085	* We need the new memory to be NULLed.
24086	* TODO: Use memset instead?
24087	*/
24088	for (; i < vctxt->sizeElemInfos; i++)
24089	    vctxt->elemInfos[i] = NULL;
24090    } else
24091	info = vctxt->elemInfos[vctxt->depth];
24092
24093    if (info == NULL) {
24094	info = (xmlSchemaNodeInfoPtr)
24095	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24096	if (info == NULL) {
24097	    xmlSchemaVErrMemory(vctxt,
24098		"allocating an element info", NULL);
24099	    return (NULL);
24100	}
24101	vctxt->elemInfos[vctxt->depth] = info;
24102    } else {
24103	if (info->localName != NULL) {
24104	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24105		"elem info has not been cleared");
24106	    return (NULL);
24107	}
24108    }
24109    memset(info, 0, sizeof(xmlSchemaNodeInfo));
24110    info->nodeType = XML_ELEMENT_NODE;
24111    info->depth = vctxt->depth;
24112
24113    return (info);
24114}
24115
24116#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24117#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24118#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24119
24120static int
24121xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24122			xmlNodePtr node,
24123			xmlSchemaTypePtr type,
24124			xmlSchemaValType valType,
24125			const xmlChar * value,
24126			xmlSchemaValPtr val,
24127			unsigned long length,
24128			int fireErrors)
24129{
24130    int ret, error = 0;
24131
24132    xmlSchemaTypePtr tmpType;
24133    xmlSchemaFacetLinkPtr facetLink;
24134    xmlSchemaFacetPtr facet;
24135    unsigned long len = 0;
24136    xmlSchemaWhitespaceValueType ws;
24137
24138    /*
24139    * In Libxml2, derived built-in types have currently no explicit facets.
24140    */
24141    if (type->type == XML_SCHEMA_TYPE_BASIC)
24142	return (0);
24143
24144    /*
24145    * NOTE: Do not jump away, if the facetSet of the given type is
24146    * empty: until now, "pattern" and "enumeration" facets of the
24147    * *base types* need to be checked as well.
24148    */
24149    if (type->facetSet == NULL)
24150	goto pattern_and_enum;
24151
24152    if (! WXS_IS_ATOMIC(type)) {
24153	if (WXS_IS_LIST(type))
24154	    goto WXS_IS_LIST;
24155	else
24156	    goto pattern_and_enum;
24157    }
24158    /*
24159    * Whitespace handling is only of importance for string-based
24160    * types.
24161    */
24162    tmpType = xmlSchemaGetPrimitiveType(type);
24163    if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24164	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24165	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24166    } else
24167	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24168    /*
24169    * If the value was not computed (for string or
24170    * anySimpleType based types), then use the provided
24171    * type.
24172    */
24173    if (val == NULL)
24174	valType = valType;
24175    else
24176	valType = xmlSchemaGetValType(val);
24177
24178    ret = 0;
24179    for (facetLink = type->facetSet; facetLink != NULL;
24180	facetLink = facetLink->next) {
24181	/*
24182	* Skip the pattern "whiteSpace": it is used to
24183	* format the character content beforehand.
24184	*/
24185	switch (facetLink->facet->type) {
24186	    case XML_SCHEMA_FACET_WHITESPACE:
24187	    case XML_SCHEMA_FACET_PATTERN:
24188	    case XML_SCHEMA_FACET_ENUMERATION:
24189		continue;
24190	    case XML_SCHEMA_FACET_LENGTH:
24191	    case XML_SCHEMA_FACET_MINLENGTH:
24192	    case XML_SCHEMA_FACET_MAXLENGTH:
24193		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24194		    valType, value, val, &len, ws);
24195		break;
24196	    default:
24197		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24198		    valType, value, val, ws);
24199		break;
24200	}
24201	if (ret < 0) {
24202	    AERROR_INT("xmlSchemaValidateFacets",
24203		"validating against a atomic type facet");
24204	    return (-1);
24205	} else if (ret > 0) {
24206	    if (fireErrors)
24207		xmlSchemaFacetErr(actxt, ret, node,
24208		value, len, type, facetLink->facet, NULL, NULL, NULL);
24209	    else
24210		return (ret);
24211	    if (error == 0)
24212		error = ret;
24213	}
24214	ret = 0;
24215    }
24216
24217WXS_IS_LIST:
24218    if (! WXS_IS_LIST(type))
24219	goto pattern_and_enum;
24220    /*
24221    * "length", "minLength" and "maxLength" of list types.
24222    */
24223    ret = 0;
24224    for (facetLink = type->facetSet; facetLink != NULL;
24225	facetLink = facetLink->next) {
24226
24227	switch (facetLink->facet->type) {
24228	    case XML_SCHEMA_FACET_LENGTH:
24229	    case XML_SCHEMA_FACET_MINLENGTH:
24230	    case XML_SCHEMA_FACET_MAXLENGTH:
24231		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24232		    value, length, NULL);
24233		break;
24234	    default:
24235		continue;
24236	}
24237	if (ret < 0) {
24238	    AERROR_INT("xmlSchemaValidateFacets",
24239		"validating against a list type facet");
24240	    return (-1);
24241	} else if (ret > 0) {
24242	    if (fireErrors)
24243		xmlSchemaFacetErr(actxt, ret, node,
24244		value, length, type, facetLink->facet, NULL, NULL, NULL);
24245	    else
24246		return (ret);
24247	    if (error == 0)
24248		error = ret;
24249	}
24250	ret = 0;
24251    }
24252
24253pattern_and_enum:
24254    if (error >= 0) {
24255	int found = 0;
24256	/*
24257	* Process enumerations. Facet values are in the value space
24258	* of the defining type's base type. This seems to be a bug in the
24259	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24260	* Only the first set of enumerations in the ancestor-or-self axis
24261	* is used for validation.
24262	*/
24263	ret = 0;
24264	tmpType = type;
24265	do {
24266	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24267		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24268		    continue;
24269		found = 1;
24270		ret = xmlSchemaAreValuesEqual(facet->val, val);
24271		if (ret == 1)
24272		    break;
24273		else if (ret < 0) {
24274		    AERROR_INT("xmlSchemaValidateFacets",
24275			"validating against an enumeration facet");
24276		    return (-1);
24277		}
24278	    }
24279	    if (ret != 0)
24280		break;
24281	    /*
24282	    * Break on the first set of enumerations. Any additional
24283	    *  enumerations which might be existent on the ancestors
24284	    *  of the current type are restricted by this set; thus
24285	    *  *must* *not* be taken into account.
24286	    */
24287	    if (found)
24288		break;
24289	    tmpType = tmpType->baseType;
24290	} while ((tmpType != NULL) &&
24291	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24292	if (found && (ret == 0)) {
24293	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24294	    if (fireErrors) {
24295		xmlSchemaFacetErr(actxt, ret, node,
24296		    value, 0, type, NULL, NULL, NULL, NULL);
24297	    } else
24298		return (ret);
24299	    if (error == 0)
24300		error = ret;
24301	}
24302    }
24303
24304    if (error >= 0) {
24305	int found;
24306	/*
24307	* Process patters. Pattern facets are ORed at type level
24308	* and ANDed if derived. Walk the base type axis.
24309	*/
24310	tmpType = type;
24311	facet = NULL;
24312	do {
24313	    found = 0;
24314	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24315		facetLink = facetLink->next) {
24316		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24317		    continue;
24318		found = 1;
24319		/*
24320		* NOTE that for patterns, @value needs to be the
24321		* normalized vaule.
24322		*/
24323		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24324		if (ret == 1)
24325		    break;
24326		else if (ret < 0) {
24327		    AERROR_INT("xmlSchemaValidateFacets",
24328			"validating against a pattern facet");
24329		    return (-1);
24330		} else {
24331		    /*
24332		    * Save the last non-validating facet.
24333		    */
24334		    facet = facetLink->facet;
24335		}
24336	    }
24337	    if (found && (ret != 1)) {
24338		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24339		if (fireErrors) {
24340		    xmlSchemaFacetErr(actxt, ret, node,
24341			value, 0, type, facet, NULL, NULL, NULL);
24342		} else
24343		    return (ret);
24344		if (error == 0)
24345		    error = ret;
24346		break;
24347	    }
24348	    tmpType = tmpType->baseType;
24349	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24350    }
24351
24352    return (error);
24353}
24354
24355static xmlChar *
24356xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24357			const xmlChar *value)
24358{
24359    switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24360	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24361	    return (xmlSchemaCollapseString(value));
24362	case XML_SCHEMA_WHITESPACE_REPLACE:
24363	    return (xmlSchemaWhiteSpaceReplace(value));
24364	default:
24365	    return (NULL);
24366    }
24367}
24368
24369static int
24370xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24371		       const xmlChar *value,
24372		       xmlSchemaValPtr *val,
24373		       int valNeeded)
24374{
24375    int ret;
24376    const xmlChar *nsName;
24377    xmlChar *local, *prefix = NULL;
24378
24379    ret = xmlValidateQName(value, 1);
24380    if (ret != 0) {
24381	if (ret == -1) {
24382	    VERROR_INT("xmlSchemaValidateQName",
24383		"calling xmlValidateQName()");
24384	    return (-1);
24385	}
24386	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24387    }
24388    /*
24389    * NOTE: xmlSplitQName2 will always return a duplicated
24390    * strings.
24391    */
24392    local = xmlSplitQName2(value, &prefix);
24393    if (local == NULL)
24394	local = xmlStrdup(value);
24395    /*
24396    * OPTIMIZE TODO: Use flags for:
24397    *  - is there any namespace binding?
24398    *  - is there a default namespace?
24399    */
24400    nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24401
24402    if (prefix != NULL) {
24403	xmlFree(prefix);
24404	/*
24405	* A namespace must be found if the prefix is
24406	* NOT NULL.
24407	*/
24408	if (nsName == NULL) {
24409	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24410	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24411		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24412		"The QName value '%s' has no "
24413		"corresponding namespace declaration in "
24414		"scope", value, NULL);
24415	    if (local != NULL)
24416		xmlFree(local);
24417	    return (ret);
24418	}
24419    }
24420    if (valNeeded && val) {
24421	if (nsName != NULL)
24422	    *val = xmlSchemaNewQNameValue(
24423		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24424	else
24425	    *val = xmlSchemaNewQNameValue(NULL,
24426		BAD_CAST local);
24427    } else
24428	xmlFree(local);
24429    return (0);
24430}
24431
24432/*
24433* cvc-simple-type
24434*/
24435static int
24436xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24437			     xmlNodePtr node,
24438			     xmlSchemaTypePtr type,
24439			     const xmlChar *value,
24440			     xmlSchemaValPtr *retVal,
24441			     int fireErrors,
24442			     int normalize,
24443			     int isNormalized)
24444{
24445    int ret = 0, valNeeded = (retVal) ? 1 : 0;
24446    xmlSchemaValPtr val = NULL;
24447    /* xmlSchemaWhitespaceValueType ws; */
24448    xmlChar *normValue = NULL;
24449
24450#define NORMALIZE(atype) \
24451    if ((! isNormalized) && \
24452    (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24453	normValue = xmlSchemaNormalizeValue(atype, value); \
24454	if (normValue != NULL) \
24455	    value = normValue; \
24456	isNormalized = 1; \
24457    }
24458
24459    if ((retVal != NULL) && (*retVal != NULL)) {
24460	xmlSchemaFreeValue(*retVal);
24461	*retVal = NULL;
24462    }
24463    /*
24464    * 3.14.4 Simple Type Definition Validation Rules
24465    * Validation Rule: String Valid
24466    */
24467    /*
24468    * 1 It is schema-valid with respect to that definition as defined
24469    * by Datatype Valid in [XML Schemas: Datatypes].
24470    */
24471    /*
24472    * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24473    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24474    * the string must be a �declared entity name�.
24475    */
24476    /*
24477    * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24478    * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24479    * then every whitespace-delimited substring of the string must be a �declared
24480    * entity name�.
24481    */
24482    /*
24483    * 2.3 otherwise no further condition applies.
24484    */
24485    if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24486	valNeeded = 1;
24487    if (value == NULL)
24488	value = BAD_CAST "";
24489    if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24490	xmlSchemaTypePtr biType; /* The built-in type. */
24491	/*
24492	* SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24493	* a literal in the �lexical space� of {base type definition}"
24494	*/
24495	/*
24496	* Whitespace-normalize.
24497	*/
24498	NORMALIZE(type);
24499	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24500	    /*
24501	    * Get the built-in type.
24502	    */
24503	    biType = type->baseType;
24504	    while ((biType != NULL) &&
24505		(biType->type != XML_SCHEMA_TYPE_BASIC))
24506		biType = biType->baseType;
24507
24508	    if (biType == NULL) {
24509		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24510		    "could not get the built-in type");
24511		goto internal_error;
24512	    }
24513	} else
24514	    biType = type;
24515	/*
24516	* NOTATIONs need to be processed here, since they need
24517	* to lookup in the hashtable of NOTATION declarations of the schema.
24518	*/
24519	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24520	    switch (biType->builtInType) {
24521		case XML_SCHEMAS_NOTATION:
24522		    ret = xmlSchemaValidateNotation(
24523			(xmlSchemaValidCtxtPtr) actxt,
24524			((xmlSchemaValidCtxtPtr) actxt)->schema,
24525			NULL, value, &val, valNeeded);
24526		    break;
24527		case XML_SCHEMAS_QNAME:
24528		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24529			value, &val, valNeeded);
24530		    break;
24531		default:
24532		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24533		    if (valNeeded)
24534			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24535			    value, &val, node);
24536		    else
24537			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24538			    value, NULL, node);
24539		    break;
24540	    }
24541	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24542	    switch (biType->builtInType) {
24543		case XML_SCHEMAS_NOTATION:
24544		    ret = xmlSchemaValidateNotation(NULL,
24545			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24546			value, &val, valNeeded);
24547		    break;
24548		default:
24549		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24550		    if (valNeeded)
24551			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24552			    value, &val, node);
24553		    else
24554			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24555			    value, NULL, node);
24556		    break;
24557	    }
24558	} else {
24559	    /*
24560	    * Validation via a public API is not implemented yet.
24561	    */
24562	    TODO
24563	    goto internal_error;
24564	}
24565	if (ret != 0) {
24566	    if (ret < 0) {
24567		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24568		    "validating against a built-in type");
24569		goto internal_error;
24570	    }
24571	    if (WXS_IS_LIST(type))
24572		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24573	    else
24574		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24575	}
24576	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24577	    /*
24578	    * Check facets.
24579	    */
24580	    ret = xmlSchemaValidateFacets(actxt, node, type,
24581		(xmlSchemaValType) biType->builtInType, value, val,
24582		0, fireErrors);
24583	    if (ret != 0) {
24584		if (ret < 0) {
24585		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24586			"validating facets of atomic simple type");
24587		    goto internal_error;
24588		}
24589		if (WXS_IS_LIST(type))
24590		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24591		else
24592		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24593	    }
24594	}
24595	if (fireErrors && (ret > 0))
24596	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24597    } else if (WXS_IS_LIST(type)) {
24598
24599	xmlSchemaTypePtr itemType;
24600	const xmlChar *cur, *end;
24601	xmlChar *tmpValue = NULL;
24602	unsigned long len = 0;
24603	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24604	/* 1.2.2 if {variety} is �list� then the string must be a sequence
24605	* of white space separated tokens, each of which �match�es a literal
24606	* in the �lexical space� of {item type definition}
24607	*/
24608	/*
24609	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24610	* the list type has an enum or pattern facet.
24611	*/
24612	NORMALIZE(type);
24613	/*
24614	* VAL TODO: Optimize validation of empty values.
24615	* VAL TODO: We do not have computed values for lists.
24616	*/
24617	itemType = WXS_LIST_ITEMTYPE(type);
24618	cur = value;
24619	do {
24620	    while (IS_BLANK_CH(*cur))
24621		cur++;
24622	    end = cur;
24623	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24624		end++;
24625	    if (end == cur)
24626		break;
24627	    tmpValue = xmlStrndup(cur, end - cur);
24628	    len++;
24629
24630	    if (valNeeded)
24631		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24632		    tmpValue, &curVal, fireErrors, 0, 1);
24633	    else
24634		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24635		    tmpValue, NULL, fireErrors, 0, 1);
24636	    FREE_AND_NULL(tmpValue);
24637	    if (curVal != NULL) {
24638		/*
24639		* Add to list of computed values.
24640		*/
24641		if (val == NULL)
24642		    val = curVal;
24643		else
24644		    xmlSchemaValueAppend(prevVal, curVal);
24645		prevVal = curVal;
24646		curVal = NULL;
24647	    }
24648	    if (ret != 0) {
24649		if (ret < 0) {
24650		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24651			"validating an item of list simple type");
24652		    goto internal_error;
24653		}
24654		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24655		break;
24656	    }
24657	    cur = end;
24658	} while (*cur != 0);
24659	FREE_AND_NULL(tmpValue);
24660	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24661	    /*
24662	    * Apply facets (pattern, enumeration).
24663	    */
24664	    ret = xmlSchemaValidateFacets(actxt, node, type,
24665		XML_SCHEMAS_UNKNOWN, value, val,
24666		len, fireErrors);
24667	    if (ret != 0) {
24668		if (ret < 0) {
24669		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24670			"validating facets of list simple type");
24671		    goto internal_error;
24672		}
24673		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24674	    }
24675	}
24676	if (fireErrors && (ret > 0)) {
24677	    /*
24678	    * Report the normalized value.
24679	    */
24680	    normalize = 1;
24681	    NORMALIZE(type);
24682	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24683	}
24684    } else if (WXS_IS_UNION(type)) {
24685	xmlSchemaTypeLinkPtr memberLink;
24686	/*
24687	* TODO: For all datatypes �derived� by �union�  whiteSpace does
24688	* not apply directly; however, the normalization behavior of �union�
24689	* types is controlled by the value of whiteSpace on that one of the
24690	* �memberTypes� against which the �union� is successfully validated.
24691	*
24692	* This means that the value is normalized by the first validating
24693	* member type, then the facets of the union type are applied. This
24694	* needs changing of the value!
24695	*/
24696
24697	/*
24698	* 1.2.3 if {variety} is �union� then the string must �match� a
24699	* literal in the �lexical space� of at least one member of
24700	* {member type definitions}
24701	*/
24702	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24703	if (memberLink == NULL) {
24704	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24705		"union simple type has no member types");
24706	    goto internal_error;
24707	}
24708	/*
24709	* Always normalize union type values, since we currently
24710	* cannot store the whitespace information with the value
24711	* itself; otherwise a later value-comparison would be
24712	* not possible.
24713	*/
24714	while (memberLink != NULL) {
24715	    if (valNeeded)
24716		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24717		    memberLink->type, value, &val, 0, 1, 0);
24718	    else
24719		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24720		    memberLink->type, value, NULL, 0, 1, 0);
24721	    if (ret <= 0)
24722		break;
24723	    memberLink = memberLink->next;
24724	}
24725	if (ret != 0) {
24726	    if (ret < 0) {
24727		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24728		    "validating members of union simple type");
24729		goto internal_error;
24730	    }
24731	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24732	}
24733	/*
24734	* Apply facets (pattern, enumeration).
24735	*/
24736	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24737	    /*
24738	    * The normalization behavior of �union� types is controlled by
24739	    * the value of whiteSpace on that one of the �memberTypes�
24740	    * against which the �union� is successfully validated.
24741	    */
24742	    NORMALIZE(memberLink->type);
24743	    ret = xmlSchemaValidateFacets(actxt, node, type,
24744		XML_SCHEMAS_UNKNOWN, value, val,
24745		0, fireErrors);
24746	    if (ret != 0) {
24747		if (ret < 0) {
24748		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24749			"validating facets of union simple type");
24750		    goto internal_error;
24751		}
24752		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24753	    }
24754	}
24755	if (fireErrors && (ret > 0))
24756	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24757    }
24758
24759    if (normValue != NULL)
24760	xmlFree(normValue);
24761    if (ret == 0) {
24762	if (retVal != NULL)
24763	    *retVal = val;
24764	else if (val != NULL)
24765	    xmlSchemaFreeValue(val);
24766    } else if (val != NULL)
24767	xmlSchemaFreeValue(val);
24768    return (ret);
24769internal_error:
24770    if (normValue != NULL)
24771	xmlFree(normValue);
24772    if (val != NULL)
24773	xmlSchemaFreeValue(val);
24774    return (-1);
24775}
24776
24777static int
24778xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24779			   const xmlChar *value,
24780			   const xmlChar **nsName,
24781			   const xmlChar **localName)
24782{
24783    int ret = 0;
24784
24785    if ((nsName == NULL) || (localName == NULL))
24786	return (-1);
24787    *nsName = NULL;
24788    *localName = NULL;
24789
24790    ret = xmlValidateQName(value, 1);
24791    if (ret == -1)
24792	return (-1);
24793    if (ret > 0) {
24794	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24795	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24796	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24797	return (1);
24798    }
24799    {
24800	xmlChar *local = NULL;
24801	xmlChar *prefix;
24802
24803	/*
24804	* NOTE: xmlSplitQName2 will return a duplicated
24805	* string.
24806	*/
24807	local = xmlSplitQName2(value, &prefix);
24808	if (local == NULL)
24809	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24810	else {
24811	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24812	    xmlFree(local);
24813	}
24814
24815	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24816
24817	if (prefix != NULL) {
24818	    xmlFree(prefix);
24819	    /*
24820	    * A namespace must be found if the prefix is NOT NULL.
24821	    */
24822	    if (*nsName == NULL) {
24823		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24824		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24825		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24826		    "The QName value '%s' has no "
24827		    "corresponding namespace declaration in scope",
24828		    value, NULL);
24829		return (2);
24830	    }
24831	}
24832    }
24833    return (0);
24834}
24835
24836static int
24837xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24838			xmlSchemaAttrInfoPtr iattr,
24839			xmlSchemaTypePtr *localType,
24840			xmlSchemaElementPtr elemDecl)
24841{
24842    int ret = 0;
24843    /*
24844    * cvc-elt (3.3.4) : (4)
24845    * AND
24846    * Schema-Validity Assessment (Element) (cvc-assess-elt)
24847    *   (1.2.1.2.1) - (1.2.1.2.4)
24848    * Handle 'xsi:type'.
24849    */
24850    if (localType == NULL)
24851	return (-1);
24852    *localType = NULL;
24853    if (iattr == NULL)
24854	return (0);
24855    else {
24856	const xmlChar *nsName = NULL, *local = NULL;
24857	/*
24858	* TODO: We should report a *warning* that the type was overriden
24859	* by the instance.
24860	*/
24861	ACTIVATE_ATTRIBUTE(iattr);
24862	/*
24863	* (cvc-elt) (3.3.4) : (4.1)
24864	* (cvc-assess-elt) (1.2.1.2.2)
24865	*/
24866	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24867	    &nsName, &local);
24868	if (ret != 0) {
24869	    if (ret < 0) {
24870		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24871		    "calling xmlSchemaQNameExpand() to validate the "
24872		    "attribute 'xsi:type'");
24873		goto internal_error;
24874	    }
24875	    goto exit;
24876	}
24877	/*
24878	* (cvc-elt) (3.3.4) : (4.2)
24879	* (cvc-assess-elt) (1.2.1.2.3)
24880	*/
24881	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24882	if (*localType == NULL) {
24883	    xmlChar *str = NULL;
24884
24885	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24886		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24887		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24888		"The QName value '%s' of the xsi:type attribute does not "
24889		"resolve to a type definition",
24890		xmlSchemaFormatQName(&str, nsName, local), NULL);
24891	    FREE_AND_NULL(str);
24892	    ret = vctxt->err;
24893	    goto exit;
24894	}
24895	if (elemDecl != NULL) {
24896	    int set = 0;
24897
24898	    /*
24899	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24900	    * "The �local type definition� must be validly
24901	    * derived from the {type definition} given the union of
24902	    * the {disallowed substitutions} and the {type definition}'s
24903	    * {prohibited substitutions}, as defined in
24904	    * Type Derivation OK (Complex) (�3.4.6)
24905	    * (if it is a complex type definition),
24906	    * or given {disallowed substitutions} as defined in Type
24907	    * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24908	    * definition)."
24909	    *
24910	    * {disallowed substitutions}: the "block" on the element decl.
24911	    * {prohibited substitutions}: the "block" on the type def.
24912	    */
24913	    /*
24914	    * OPTIMIZE TODO: We could map types already evaluated
24915	    * to be validly derived from other types to avoid checking
24916	    * this over and over for the same types.
24917	    */
24918	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24919		(elemDecl->subtypes->flags &
24920		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24921		set |= SUBSET_EXTENSION;
24922
24923	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24924		(elemDecl->subtypes->flags &
24925		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24926		set |= SUBSET_RESTRICTION;
24927
24928	    /*
24929	    * REMOVED and CHANGED since this produced a parser context
24930	    * which adds to the string dict of the schema. So this would
24931	    * change the schema and we don't want this. We don't need
24932	    * the parser context anymore.
24933	    *
24934	    * if ((vctxt->pctxt == NULL) &&
24935	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24936	    *	    return (-1);
24937	    */
24938
24939	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24940		elemDecl->subtypes, set) != 0) {
24941		xmlChar *str = NULL;
24942
24943		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24944		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24945		    "The type definition '%s', specified by xsi:type, is "
24946		    "blocked or not validly derived from the type definition "
24947		    "of the element declaration",
24948		    xmlSchemaFormatQName(&str,
24949			(*localType)->targetNamespace,
24950			(*localType)->name),
24951		    NULL);
24952		FREE_AND_NULL(str);
24953		ret = vctxt->err;
24954		*localType = NULL;
24955	    }
24956	}
24957    }
24958exit:
24959    ACTIVATE_ELEM;
24960    return (ret);
24961internal_error:
24962    ACTIVATE_ELEM;
24963    return (-1);
24964}
24965
24966static int
24967xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24968{
24969    xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24970    xmlSchemaTypePtr actualType;
24971
24972    /*
24973    * cvc-elt (3.3.4) : 1
24974    */
24975    if (elemDecl == NULL) {
24976	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24977	    "No matching declaration available");
24978        return (vctxt->err);
24979    }
24980    actualType = WXS_ELEM_TYPEDEF(elemDecl);
24981    /*
24982    * cvc-elt (3.3.4) : 2
24983    */
24984    if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24985	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24986	    "The element declaration is abstract");
24987        return (vctxt->err);
24988    }
24989    if (actualType == NULL) {
24990    	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24991    	    "The type definition is absent");
24992    	return (XML_SCHEMAV_CVC_TYPE_1);
24993    }
24994    if (vctxt->nbAttrInfos != 0) {
24995	int ret;
24996	xmlSchemaAttrInfoPtr iattr;
24997	/*
24998	* cvc-elt (3.3.4) : 3
24999	* Handle 'xsi:nil'.
25000	*/
25001	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25002	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25003	if (iattr) {
25004	    ACTIVATE_ATTRIBUTE(iattr);
25005	    /*
25006	    * Validate the value.
25007	    */
25008	    ret = xmlSchemaVCheckCVCSimpleType(
25009		ACTXT_CAST vctxt, NULL,
25010		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25011		iattr->value, &(iattr->val), 1, 0, 0);
25012	    ACTIVATE_ELEM;
25013	    if (ret < 0) {
25014		VERROR_INT("xmlSchemaValidateElemDecl",
25015		    "calling xmlSchemaVCheckCVCSimpleType() to "
25016		    "validate the attribute 'xsi:nil'");
25017		return (-1);
25018	    }
25019	    if (ret == 0) {
25020		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25021		    /*
25022		    * cvc-elt (3.3.4) : 3.1
25023		    */
25024		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25025			"The element is not 'nillable'");
25026		    /* Does not return an error on purpose. */
25027		} else {
25028		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25029			/*
25030			* cvc-elt (3.3.4) : 3.2.2
25031			*/
25032			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25033			    (elemDecl->value != NULL)) {
25034			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25035				"The element cannot be 'nilled' because "
25036				"there is a fixed value constraint defined "
25037				"for it");
25038			     /* Does not return an error on purpose. */
25039			} else
25040			    vctxt->inode->flags |=
25041				XML_SCHEMA_ELEM_INFO_NILLED;
25042		    }
25043		}
25044	    }
25045	}
25046	/*
25047	* cvc-elt (3.3.4) : 4
25048	* Handle 'xsi:type'.
25049	*/
25050	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25051	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25052	if (iattr) {
25053	    xmlSchemaTypePtr localType = NULL;
25054
25055	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25056		elemDecl);
25057	    if (ret != 0) {
25058		if (ret == -1) {
25059		    VERROR_INT("xmlSchemaValidateElemDecl",
25060			"calling xmlSchemaProcessXSIType() to "
25061			"process the attribute 'xsi:type'");
25062		    return (-1);
25063		}
25064		/* Does not return an error on purpose. */
25065	    }
25066	    if (localType != NULL) {
25067		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25068		actualType = localType;
25069	    }
25070	}
25071    }
25072    /*
25073    * IDC: Register identity-constraint XPath matchers.
25074    */
25075    if ((elemDecl->idcs != NULL) &&
25076	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25077	    return (-1);
25078    /*
25079    * No actual type definition.
25080    */
25081    if (actualType == NULL) {
25082    	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25083    	    "The type definition is absent");
25084    	return (XML_SCHEMAV_CVC_TYPE_1);
25085    }
25086    /*
25087    * Remember the actual type definition.
25088    */
25089    vctxt->inode->typeDef = actualType;
25090
25091    return (0);
25092}
25093
25094static int
25095xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25096{
25097    xmlSchemaAttrInfoPtr iattr;
25098    int ret = 0, i;
25099
25100    /*
25101    * SPEC cvc-type (3.1.1)
25102    * "The attributes of must be empty, excepting those whose namespace
25103    * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25104    * whose local name is one of type, nil, schemaLocation or
25105    * noNamespaceSchemaLocation."
25106    */
25107    if (vctxt->nbAttrInfos == 0)
25108	return (0);
25109    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25110	iattr = vctxt->attrInfos[i];
25111	if (! iattr->metaType) {
25112	    ACTIVATE_ATTRIBUTE(iattr)
25113	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25114		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25115	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25116        }
25117    }
25118    ACTIVATE_ELEM
25119    return (ret);
25120}
25121
25122/*
25123* Cleanup currently used attribute infos.
25124*/
25125static void
25126xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25127{
25128    int i;
25129    xmlSchemaAttrInfoPtr attr;
25130
25131    if (vctxt->nbAttrInfos == 0)
25132	return;
25133    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25134	attr = vctxt->attrInfos[i];
25135	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25136	    if (attr->localName != NULL)
25137		xmlFree((xmlChar *) attr->localName);
25138	    if (attr->nsName != NULL)
25139		xmlFree((xmlChar *) attr->nsName);
25140	}
25141	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25142	    if (attr->value != NULL)
25143		xmlFree((xmlChar *) attr->value);
25144	}
25145	if (attr->val != NULL) {
25146	    xmlSchemaFreeValue(attr->val);
25147	    attr->val = NULL;
25148	}
25149	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25150    }
25151    vctxt->nbAttrInfos = 0;
25152}
25153
25154/*
25155* 3.4.4 Complex Type Definition Validation Rules
25156*   Element Locally Valid (Complex Type) (cvc-complex-type)
25157* 3.2.4 Attribute Declaration Validation Rules
25158*   Validation Rule: Attribute Locally Valid (cvc-attribute)
25159*   Attribute Locally Valid (Use) (cvc-au)
25160*
25161* Only "assessed" attribute information items will be visible to
25162* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25163*/
25164static int
25165xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25166{
25167    xmlSchemaTypePtr type = vctxt->inode->typeDef;
25168    xmlSchemaItemListPtr attrUseList;
25169    xmlSchemaAttributeUsePtr attrUse = NULL;
25170    xmlSchemaAttributePtr attrDecl = NULL;
25171    xmlSchemaAttrInfoPtr iattr, tmpiattr;
25172    int i, j, found, nbAttrs, nbUses;
25173    int xpathRes = 0, res, wildIDs = 0, fixed;
25174    xmlNodePtr defAttrOwnerElem = NULL;
25175
25176    /*
25177    * SPEC (cvc-attribute)
25178    * (1) "The declaration must not be �absent� (see Missing
25179    * Sub-components (�5.3) for how this can fail to be
25180    * the case)."
25181    * (2) "Its {type definition} must not be absent."
25182    *
25183    * NOTE (1) + (2): This is not handled here, since we currently do not
25184    * allow validation against schemas which have missing sub-components.
25185    *
25186    * SPEC (cvc-complex-type)
25187    * (3) "For each attribute information item in the element information
25188    * item's [attributes] excepting those whose [namespace name] is
25189    * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25190    * [local name] is one of type, nil, schemaLocation or
25191    * noNamespaceSchemaLocation, the appropriate case among the following
25192    * must be true:
25193    *
25194    */
25195    attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25196    /*
25197    * @nbAttrs is the number of attributes present in the instance.
25198    */
25199    nbAttrs = vctxt->nbAttrInfos;
25200    if (attrUseList != NULL)
25201	nbUses = attrUseList->nbItems;
25202    else
25203	nbUses = 0;
25204    for (i = 0; i < nbUses; i++) {
25205        found = 0;
25206	attrUse = attrUseList->items[i];
25207	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25208        for (j = 0; j < nbAttrs; j++) {
25209	    iattr = vctxt->attrInfos[j];
25210	    /*
25211	    * SPEC (cvc-complex-type) (3)
25212	    * Skip meta attributes.
25213	    */
25214	    if (iattr->metaType)
25215		continue;
25216	    if (iattr->localName[0] != attrDecl->name[0])
25217		continue;
25218	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25219		continue;
25220	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25221		continue;
25222	    found = 1;
25223	    /*
25224	    * SPEC (cvc-complex-type)
25225	    * (3.1) "If there is among the {attribute uses} an attribute
25226	    * use with an {attribute declaration} whose {name} matches
25227	    * the attribute information item's [local name] and whose
25228	    * {target namespace} is identical to the attribute information
25229	    * item's [namespace name] (where an �absent� {target namespace}
25230	    * is taken to be identical to a [namespace name] with no value),
25231	    * then the attribute information must be �valid� with respect
25232	    * to that attribute use as per Attribute Locally Valid (Use)
25233	    * (�3.5.4). In this case the {attribute declaration} of that
25234	    * attribute use is the �context-determined declaration� for the
25235	    * attribute information item with respect to Schema-Validity
25236	    * Assessment (Attribute) (�3.2.4) and
25237	    * Assessment Outcome (Attribute) (�3.2.5).
25238	    */
25239	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25240	    iattr->use = attrUse;
25241	    /*
25242	    * Context-determined declaration.
25243	    */
25244	    iattr->decl = attrDecl;
25245	    iattr->typeDef = attrDecl->subtypes;
25246	    break;
25247	}
25248
25249	if (found)
25250	    continue;
25251
25252	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25253	    /*
25254	    * Handle non-existent, required attributes.
25255	    *
25256	    * SPEC (cvc-complex-type)
25257	    * (4) "The {attribute declaration} of each attribute use in
25258	    * the {attribute uses} whose {required} is true matches one
25259	    * of the attribute information items in the element information
25260	    * item's [attributes] as per clause 3.1 above."
25261	    */
25262	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25263	    if (tmpiattr == NULL) {
25264		VERROR_INT(
25265		    "xmlSchemaVAttributesComplex",
25266		    "calling xmlSchemaGetFreshAttrInfo()");
25267		return (-1);
25268	    }
25269	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25270	    tmpiattr->use = attrUse;
25271	    tmpiattr->decl = attrDecl;
25272	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25273	    ((attrUse->defValue != NULL) ||
25274	     (attrDecl->defValue != NULL))) {
25275	    /*
25276	    * Handle non-existent, optional, default/fixed attributes.
25277	    */
25278	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25279	    if (tmpiattr == NULL) {
25280		VERROR_INT(
25281		    "xmlSchemaVAttributesComplex",
25282		    "calling xmlSchemaGetFreshAttrInfo()");
25283		return (-1);
25284	    }
25285	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25286	    tmpiattr->use = attrUse;
25287	    tmpiattr->decl = attrDecl;
25288	    tmpiattr->typeDef = attrDecl->subtypes;
25289	    tmpiattr->localName = attrDecl->name;
25290	    tmpiattr->nsName = attrDecl->targetNamespace;
25291	}
25292    }
25293
25294    if (vctxt->nbAttrInfos == 0)
25295	return (0);
25296    /*
25297    * Validate against the wildcard.
25298    */
25299    if (type->attributeWildcard != NULL) {
25300	/*
25301	* SPEC (cvc-complex-type)
25302	* (3.2.1) "There must be an {attribute wildcard}."
25303	*/
25304	for (i = 0; i < nbAttrs; i++) {
25305	    iattr = vctxt->attrInfos[i];
25306	    /*
25307	    * SPEC (cvc-complex-type) (3)
25308	    * Skip meta attributes.
25309	    */
25310	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25311		continue;
25312	    /*
25313	    * SPEC (cvc-complex-type)
25314	    * (3.2.2) "The attribute information item must be �valid� with
25315	    * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25316	    *
25317	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25318	    * "... its [namespace name] must be �valid� with respect to
25319	    * the wildcard constraint, as defined in Wildcard allows
25320	    * Namespace Name (�3.10.4)."
25321	    */
25322	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25323		    iattr->nsName) == 0) {
25324		/*
25325		* Handle processContents.
25326		*
25327		* SPEC (cvc-wildcard):
25328		* processContents | context-determined declaration:
25329		* "strict"          "mustFind"
25330		* "lax"             "none"
25331		* "skip"            "skip"
25332		*/
25333		if (type->attributeWildcard->processContents ==
25334		    XML_SCHEMAS_ANY_SKIP) {
25335		     /*
25336		    * context-determined declaration = "skip"
25337		    *
25338		    * SPEC PSVI Assessment Outcome (Attribute)
25339		    * [validity] = "notKnown"
25340		    * [validation attempted] = "none"
25341		    */
25342		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25343		    continue;
25344		}
25345		/*
25346		* Find an attribute declaration.
25347		*/
25348		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25349		    iattr->localName, iattr->nsName);
25350		if (iattr->decl != NULL) {
25351		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25352		    /*
25353		    * SPEC (cvc-complex-type)
25354		    * (5) "Let [Definition:]  the wild IDs be the set of
25355		    * all attribute information item to which clause 3.2
25356		    * applied and whose �validation� resulted in a
25357		    * �context-determined declaration� of mustFind or no
25358		    * �context-determined declaration� at all, and whose
25359		    * [local name] and [namespace name] resolve (as
25360		    * defined by QName resolution (Instance) (�3.15.4)) to
25361		    * an attribute declaration whose {type definition} is
25362		    * or is derived from ID. Then all of the following
25363		    * must be true:"
25364		    */
25365		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25366		    if (xmlSchemaIsDerivedFromBuiltInType(
25367			iattr->typeDef, XML_SCHEMAS_ID)) {
25368			/*
25369			* SPEC (5.1) "There must be no more than one
25370			* item in �wild IDs�."
25371			*/
25372			if (wildIDs != 0) {
25373			    /* VAL TODO */
25374			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25375			    TODO
25376			    continue;
25377			}
25378			wildIDs++;
25379			/*
25380			* SPEC (cvc-complex-type)
25381			* (5.2) "If �wild IDs� is non-empty, there must not
25382			* be any attribute uses among the {attribute uses}
25383			* whose {attribute declaration}'s {type definition}
25384			* is or is derived from ID."
25385			*/
25386                        if (attrUseList != NULL) {
25387                            for (j = 0; j < attrUseList->nbItems; j++) {
25388                                if (xmlSchemaIsDerivedFromBuiltInType(
25389                                    WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25390                                    XML_SCHEMAS_ID)) {
25391                                    /* URGENT VAL TODO: implement */
25392                            iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25393                                    TODO
25394                                    break;
25395                                }
25396                            }
25397                        }
25398		    }
25399		} else if (type->attributeWildcard->processContents ==
25400		    XML_SCHEMAS_ANY_LAX) {
25401		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25402		    /*
25403		    * SPEC PSVI Assessment Outcome (Attribute)
25404		    * [validity] = "notKnown"
25405		    * [validation attempted] = "none"
25406		    */
25407		} else {
25408		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25409		}
25410	    }
25411	}
25412    }
25413
25414    if (vctxt->nbAttrInfos == 0)
25415	return (0);
25416
25417    /*
25418    * Get the owner element; needed for creation of default attributes.
25419    * This fixes bug #341337, reported by David Grohmann.
25420    */
25421    if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25422	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25423	if (ielem && ielem->node && ielem->node->doc)
25424	    defAttrOwnerElem = ielem->node;
25425    }
25426    /*
25427    * Validate values, create default attributes, evaluate IDCs.
25428    */
25429    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25430	iattr = vctxt->attrInfos[i];
25431	/*
25432	* VAL TODO: Note that we won't try to resolve IDCs to
25433	* "lax" and "skip" validated attributes. Check what to
25434	* do in this case.
25435	*/
25436	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25437	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25438	    continue;
25439	/*
25440	* VAL TODO: What to do if the type definition is missing?
25441	*/
25442	if (iattr->typeDef == NULL) {
25443	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25444	    continue;
25445	}
25446
25447	ACTIVATE_ATTRIBUTE(iattr);
25448	fixed = 0;
25449	xpathRes = 0;
25450
25451	if (vctxt->xpathStates != NULL) {
25452	    /*
25453	    * Evaluate IDCs.
25454	    */
25455	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25456		XML_ATTRIBUTE_NODE);
25457	    if (xpathRes == -1) {
25458		VERROR_INT("xmlSchemaVAttributesComplex",
25459		    "calling xmlSchemaXPathEvaluate()");
25460		goto internal_error;
25461	    }
25462	}
25463
25464	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25465	    /*
25466	    * Default/fixed attributes.
25467	    * We need the value only if we need to resolve IDCs or
25468	    * will create default attributes.
25469	    */
25470	    if ((xpathRes) || (defAttrOwnerElem)) {
25471		if (iattr->use->defValue != NULL) {
25472		    iattr->value = (xmlChar *) iattr->use->defValue;
25473		    iattr->val = iattr->use->defVal;
25474		} else {
25475		    iattr->value = (xmlChar *) iattr->decl->defValue;
25476		    iattr->val = iattr->decl->defVal;
25477		}
25478		/*
25479		* IDCs will consume the precomputed default value,
25480		* so we need to clone it.
25481		*/
25482		if (iattr->val == NULL) {
25483		    VERROR_INT("xmlSchemaVAttributesComplex",
25484			"default/fixed value on an attribute use was "
25485			"not precomputed");
25486		    goto internal_error;
25487		}
25488		iattr->val = xmlSchemaCopyValue(iattr->val);
25489		if (iattr->val == NULL) {
25490		    VERROR_INT("xmlSchemaVAttributesComplex",
25491			"calling xmlSchemaCopyValue()");
25492		    goto internal_error;
25493		}
25494	    }
25495	    /*
25496	    * PSVI: Add the default attribute to the current element.
25497	    * VAL TODO: Should we use the *normalized* value? This currently
25498	    *   uses the *initial* value.
25499	    */
25500
25501	    if (defAttrOwnerElem) {
25502		xmlChar *normValue;
25503		const xmlChar *value;
25504
25505		value = iattr->value;
25506		/*
25507		* Normalize the value.
25508		*/
25509		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25510		    iattr->value);
25511		if (normValue != NULL)
25512		    value = BAD_CAST normValue;
25513
25514		if (iattr->nsName == NULL) {
25515		    if (xmlNewProp(defAttrOwnerElem,
25516			iattr->localName, value) == NULL) {
25517			VERROR_INT("xmlSchemaVAttributesComplex",
25518			    "callling xmlNewProp()");
25519			if (normValue != NULL)
25520			    xmlFree(normValue);
25521			goto internal_error;
25522		    }
25523		} else {
25524		    xmlNsPtr ns;
25525
25526		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25527			defAttrOwnerElem, iattr->nsName);
25528		    if (ns == NULL) {
25529			xmlChar prefix[12];
25530			int counter = 0;
25531
25532			/*
25533			* Create a namespace declaration on the validation
25534			* root node if no namespace declaration is in scope.
25535			*/
25536			do {
25537			    snprintf((char *) prefix, 12, "p%d", counter++);
25538			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25539				defAttrOwnerElem, BAD_CAST prefix);
25540			    if (counter > 1000) {
25541				VERROR_INT(
25542				    "xmlSchemaVAttributesComplex",
25543				    "could not compute a ns prefix for a "
25544				    "default/fixed attribute");
25545				if (normValue != NULL)
25546				    xmlFree(normValue);
25547				goto internal_error;
25548			    }
25549			} while (ns != NULL);
25550			ns = xmlNewNs(vctxt->validationRoot,
25551			    iattr->nsName, BAD_CAST prefix);
25552		    }
25553		    /*
25554		    * TODO:
25555		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25556		    * If we have QNames: do we need to ensure there's a
25557		    * prefix defined for the QName?
25558		    */
25559		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25560		}
25561		if (normValue != NULL)
25562		    xmlFree(normValue);
25563	    }
25564	    /*
25565	    * Go directly to IDC evaluation.
25566	    */
25567	    goto eval_idcs;
25568	}
25569	/*
25570	* Validate the value.
25571	*/
25572	if (vctxt->value != NULL) {
25573	    /*
25574	    * Free last computed value; just for safety reasons.
25575	    */
25576	    xmlSchemaFreeValue(vctxt->value);
25577	    vctxt->value = NULL;
25578	}
25579	/*
25580	* Note that the attribute *use* can be unavailable, if
25581	* the attribute was a wild attribute.
25582	*/
25583	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25584	    ((iattr->use != NULL) &&
25585	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25586	    fixed = 1;
25587	else
25588	    fixed = 0;
25589	/*
25590	* SPEC (cvc-attribute)
25591	* (3) "The item's �normalized value� must be locally �valid�
25592	* with respect to that {type definition} as per
25593	* String Valid (�3.14.4)."
25594	*
25595	* VAL TODO: Do we already have the
25596	* "normalized attribute value" here?
25597	*/
25598	if (xpathRes || fixed) {
25599	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25600	    /*
25601	    * Request a computed value.
25602	    */
25603	    res = xmlSchemaVCheckCVCSimpleType(
25604		ACTXT_CAST vctxt,
25605		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25606		1, 1, 0);
25607	} else {
25608	    res = xmlSchemaVCheckCVCSimpleType(
25609		ACTXT_CAST vctxt,
25610		iattr->node, iattr->typeDef, iattr->value, NULL,
25611		1, 0, 0);
25612	}
25613
25614	if (res != 0) {
25615	    if (res == -1) {
25616		VERROR_INT("xmlSchemaVAttributesComplex",
25617		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25618		goto internal_error;
25619	    }
25620	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25621	    /*
25622	    * SPEC PSVI Assessment Outcome (Attribute)
25623	    * [validity] = "invalid"
25624	    */
25625	    goto eval_idcs;
25626	}
25627
25628	if (fixed) {
25629	    /*
25630	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25631	    * "For an attribute information item to be�valid�
25632	    * with respect to an attribute use its *normalized*
25633	    * value� must match the *canonical* lexical
25634	    * representation of the attribute use's {value
25635	    * constraint}value, if it is present and fixed."
25636	    *
25637	    * VAL TODO: The requirement for the *canonical* value
25638	    * will be removed in XML Schema 1.1.
25639	    */
25640	    /*
25641	    * SPEC Attribute Locally Valid (cvc-attribute)
25642	    * (4) "The item's *actual* value� must match the *value* of
25643	    * the {value constraint}, if it is present and fixed."
25644	    */
25645	    if (iattr->val == NULL) {
25646		/* VAL TODO: A value was not precomputed. */
25647		TODO
25648		goto eval_idcs;
25649	    }
25650	    if ((iattr->use != NULL) &&
25651		(iattr->use->defValue != NULL)) {
25652		if (iattr->use->defVal == NULL) {
25653		    /* VAL TODO: A default value was not precomputed. */
25654		    TODO
25655		    goto eval_idcs;
25656		}
25657		iattr->vcValue = iattr->use->defValue;
25658		/*
25659		if (xmlSchemaCompareValuesWhtsp(attr->val,
25660		    (xmlSchemaWhitespaceValueType) ws,
25661		    attr->use->defVal,
25662		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25663		*/
25664		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25665		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25666	    } else {
25667		if (iattr->decl->defVal == NULL) {
25668		    /* VAL TODO: A default value was not precomputed. */
25669		    TODO
25670		    goto eval_idcs;
25671		}
25672		iattr->vcValue = iattr->decl->defValue;
25673		/*
25674		if (xmlSchemaCompareValuesWhtsp(attr->val,
25675		    (xmlSchemaWhitespaceValueType) ws,
25676		    attrDecl->defVal,
25677		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25678		*/
25679		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25680		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25681	    }
25682	    /*
25683	    * [validity] = "valid"
25684	    */
25685	}
25686eval_idcs:
25687	/*
25688	* Evaluate IDCs.
25689	*/
25690	if (xpathRes) {
25691	    if (xmlSchemaXPathProcessHistory(vctxt,
25692		vctxt->depth +1) == -1) {
25693		VERROR_INT("xmlSchemaVAttributesComplex",
25694		    "calling xmlSchemaXPathEvaluate()");
25695		goto internal_error;
25696	    }
25697	} else if (vctxt->xpathStates != NULL)
25698	    xmlSchemaXPathPop(vctxt);
25699    }
25700
25701    /*
25702    * Report errors.
25703    */
25704    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25705	iattr = vctxt->attrInfos[i];
25706	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25707	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25708	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25709	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25710	    continue;
25711	ACTIVATE_ATTRIBUTE(iattr);
25712	switch (iattr->state) {
25713	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25714		    xmlChar *str = NULL;
25715		    ACTIVATE_ELEM;
25716		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25717			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25718			"The attribute '%s' is required but missing",
25719			xmlSchemaFormatQName(&str,
25720			    iattr->decl->targetNamespace,
25721			    iattr->decl->name),
25722			NULL);
25723		    FREE_AND_NULL(str)
25724		    break;
25725		}
25726	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25727		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25728		    "The type definition is absent");
25729		break;
25730	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25731		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25732		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25733		    "The value '%s' does not match the fixed "
25734		    "value constraint '%s'",
25735		    iattr->value, iattr->vcValue);
25736		break;
25737	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25738		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25739		    "No matching global attribute declaration available, but "
25740		    "demanded by the strict wildcard");
25741		break;
25742	    case XML_SCHEMAS_ATTR_UNKNOWN:
25743		if (iattr->metaType)
25744		    break;
25745		/*
25746		* MAYBE VAL TODO: One might report different error messages
25747		* for the following errors.
25748		*/
25749		if (type->attributeWildcard == NULL) {
25750		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25751			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25752		} else {
25753		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25754			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25755		}
25756		break;
25757	    default:
25758		break;
25759	}
25760    }
25761
25762    ACTIVATE_ELEM;
25763    return (0);
25764internal_error:
25765    ACTIVATE_ELEM;
25766    return (-1);
25767}
25768
25769static int
25770xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25771			      int *skip)
25772{
25773    xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25774    /*
25775    * The namespace of the element was already identified to be
25776    * matching the wildcard.
25777    */
25778    if ((skip == NULL) || (wild == NULL) ||
25779	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25780	VERROR_INT("xmlSchemaValidateElemWildcard",
25781	    "bad arguments");
25782	return (-1);
25783    }
25784    *skip = 0;
25785    if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25786	/*
25787	* URGENT VAL TODO: Either we need to position the stream to the
25788	* next sibling, or walk the whole subtree.
25789	*/
25790	*skip = 1;
25791	return (0);
25792    }
25793    {
25794	xmlSchemaElementPtr decl = NULL;
25795
25796	decl = xmlSchemaGetElem(vctxt->schema,
25797	    vctxt->inode->localName, vctxt->inode->nsName);
25798	if (decl != NULL) {
25799	    vctxt->inode->decl = decl;
25800	    return (0);
25801	}
25802    }
25803    if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25804	/* VAL TODO: Change to proper error code. */
25805	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25806	    "No matching global element declaration available, but "
25807	    "demanded by the strict wildcard");
25808	return (vctxt->err);
25809    }
25810    if (vctxt->nbAttrInfos != 0) {
25811	xmlSchemaAttrInfoPtr iattr;
25812	/*
25813	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25814	* (1.2.1.2.1) - (1.2.1.2.3 )
25815	*
25816	* Use the xsi:type attribute for the type definition.
25817	*/
25818	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25819	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25820	if (iattr != NULL) {
25821	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25822		&(vctxt->inode->typeDef), NULL) == -1) {
25823		VERROR_INT("xmlSchemaValidateElemWildcard",
25824		    "calling xmlSchemaProcessXSIType() to "
25825		    "process the attribute 'xsi:nil'");
25826		return (-1);
25827	    }
25828	    /*
25829	    * Don't return an error on purpose.
25830	    */
25831	    return (0);
25832	}
25833    }
25834    /*
25835    * SPEC Validation Rule: Schema-Validity Assessment (Element)
25836    *
25837    * Fallback to "anyType".
25838    */
25839    vctxt->inode->typeDef =
25840	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25841    return (0);
25842}
25843
25844/*
25845* xmlSchemaCheckCOSValidDefault:
25846*
25847* This will be called if: not nilled, no content and a default/fixed
25848* value is provided.
25849*/
25850
25851static int
25852xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25853			      const xmlChar *value,
25854			      xmlSchemaValPtr *val)
25855{
25856    int ret = 0;
25857    xmlSchemaNodeInfoPtr inode = vctxt->inode;
25858
25859    /*
25860    * cos-valid-default:
25861    * Schema Component Constraint: Element Default Valid (Immediate)
25862    * For a string to be a valid default with respect to a type
25863    * definition the appropriate case among the following must be true:
25864    */
25865    if WXS_IS_COMPLEX(inode->typeDef) {
25866	/*
25867	* Complex type.
25868	*
25869	* SPEC (2.1) "its {content type} must be a simple type definition
25870	* or mixed."
25871	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25872	* type}'s particle must be �emptiable� as defined by
25873	* Particle Emptiable (�3.9.6)."
25874	*/
25875	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25876	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25877	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25878	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25879	    /* NOTE that this covers (2.2.2) as well. */
25880	    VERROR(ret, NULL,
25881		"For a string to be a valid default, the type definition "
25882		"must be a simple type or a complex type with simple content "
25883		"or mixed content and a particle emptiable");
25884	    return(ret);
25885	}
25886    }
25887    /*
25888    * 1 If the type definition is a simple type definition, then the string
25889    * must be �valid� with respect to that definition as defined by String
25890    * Valid (�3.14.4).
25891    *
25892    * AND
25893    *
25894    * 2.2.1 If the {content type} is a simple type definition, then the
25895    * string must be �valid� with respect to that simple type definition
25896    * as defined by String Valid (�3.14.4).
25897    */
25898    if (WXS_IS_SIMPLE(inode->typeDef)) {
25899
25900	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25901	    NULL, inode->typeDef, value, val, 1, 1, 0);
25902
25903    } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25904
25905	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25906	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25907    }
25908    if (ret < 0) {
25909	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25910	    "calling xmlSchemaVCheckCVCSimpleType()");
25911    }
25912    return (ret);
25913}
25914
25915static void
25916xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25917			       const xmlChar * name ATTRIBUTE_UNUSED,
25918			       xmlSchemaElementPtr item,
25919			       xmlSchemaNodeInfoPtr inode)
25920{
25921    inode->decl = item;
25922#ifdef DEBUG_CONTENT
25923    {
25924	xmlChar *str = NULL;
25925
25926	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25927	    xmlGenericError(xmlGenericErrorContext,
25928		"AUTOMATON callback for '%s' [declaration]\n",
25929		xmlSchemaFormatQName(&str,
25930		inode->localName, inode->nsName));
25931	} else {
25932	    xmlGenericError(xmlGenericErrorContext,
25933		    "AUTOMATON callback for '%s' [wildcard]\n",
25934		    xmlSchemaFormatQName(&str,
25935		    inode->localName, inode->nsName));
25936
25937	}
25938	FREE_AND_NULL(str)
25939    }
25940#endif
25941}
25942
25943static int
25944xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25945{
25946    vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25947    if (vctxt->inode == NULL) {
25948	VERROR_INT("xmlSchemaValidatorPushElem",
25949	    "calling xmlSchemaGetFreshElemInfo()");
25950	return (-1);
25951    }
25952    vctxt->nbAttrInfos = 0;
25953    return (0);
25954}
25955
25956static int
25957xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25958			     xmlSchemaNodeInfoPtr inode,
25959			     xmlSchemaTypePtr type,
25960			     const xmlChar *value)
25961{
25962    if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25963	return (xmlSchemaVCheckCVCSimpleType(
25964	    ACTXT_CAST vctxt, NULL,
25965	    type, value, &(inode->val), 1, 1, 0));
25966    else
25967	return (xmlSchemaVCheckCVCSimpleType(
25968	    ACTXT_CAST vctxt, NULL,
25969	    type, value, NULL, 1, 0, 0));
25970}
25971
25972
25973
25974/*
25975* Process END of element.
25976*/
25977static int
25978xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25979{
25980    int ret = 0;
25981    xmlSchemaNodeInfoPtr inode = vctxt->inode;
25982
25983    if (vctxt->nbAttrInfos != 0)
25984	xmlSchemaClearAttrInfos(vctxt);
25985    if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25986	/*
25987	* This element was not expected;
25988	* we will not validate child elements of broken parents.
25989	* Skip validation of all content of the parent.
25990	*/
25991	vctxt->skipDepth = vctxt->depth -1;
25992	goto end_elem;
25993    }
25994    if ((inode->typeDef == NULL) ||
25995	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25996	/*
25997	* 1. the type definition might be missing if the element was
25998	*    error prone
25999	* 2. it might be abstract.
26000	*/
26001	goto end_elem;
26002    }
26003    /*
26004    * Check the content model.
26005    */
26006    if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26007	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26008
26009	/*
26010	* Workaround for "anyType".
26011	*/
26012	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26013	    goto character_content;
26014
26015	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26016	    xmlChar *values[10];
26017	    int terminal, nbval = 10, nbneg;
26018
26019	    if (inode->regexCtxt == NULL) {
26020		/*
26021		* Create the regex context.
26022		*/
26023		inode->regexCtxt =
26024		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26025		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26026		    vctxt);
26027		if (inode->regexCtxt == NULL) {
26028		    VERROR_INT("xmlSchemaValidatorPopElem",
26029			"failed to create a regex context");
26030		    goto internal_error;
26031		}
26032#ifdef DEBUG_AUTOMATA
26033		xmlGenericError(xmlGenericErrorContext,
26034		    "AUTOMATON create on '%s'\n", inode->localName);
26035#endif
26036	    }
26037	    /*
26038	    * Get hold of the still expected content, since a further
26039	    * call to xmlRegExecPushString() will loose this information.
26040	    */
26041	    xmlRegExecNextValues(inode->regexCtxt,
26042		&nbval, &nbneg, &values[0], &terminal);
26043	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26044	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26045		/*
26046		* Still missing something.
26047		*/
26048		ret = 1;
26049		inode->flags |=
26050		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26051		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26052		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26053		    "Missing child element(s)",
26054		    nbval, nbneg, values);
26055#ifdef DEBUG_AUTOMATA
26056		xmlGenericError(xmlGenericErrorContext,
26057		    "AUTOMATON missing ERROR on '%s'\n",
26058		    inode->localName);
26059#endif
26060	    } else {
26061		/*
26062		* Content model is satisfied.
26063		*/
26064		ret = 0;
26065#ifdef DEBUG_AUTOMATA
26066		xmlGenericError(xmlGenericErrorContext,
26067		    "AUTOMATON succeeded on '%s'\n",
26068		    inode->localName);
26069#endif
26070	    }
26071
26072	}
26073    }
26074    if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26075	goto end_elem;
26076
26077character_content:
26078
26079    if (vctxt->value != NULL) {
26080	xmlSchemaFreeValue(vctxt->value);
26081	vctxt->value = NULL;
26082    }
26083    /*
26084    * Check character content.
26085    */
26086    if (inode->decl == NULL) {
26087	/*
26088	* Speedup if no declaration exists.
26089	*/
26090	if (WXS_IS_SIMPLE(inode->typeDef)) {
26091	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26092		inode, inode->typeDef, inode->value);
26093	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26094	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26095		inode, inode->typeDef->contentTypeDef,
26096		inode->value);
26097	}
26098	if (ret < 0) {
26099	    VERROR_INT("xmlSchemaValidatorPopElem",
26100		"calling xmlSchemaVCheckCVCSimpleType()");
26101	    goto internal_error;
26102	}
26103	goto end_elem;
26104    }
26105    /*
26106    * cvc-elt (3.3.4) : 5
26107    * The appropriate case among the following must be true:
26108    */
26109    /*
26110    * cvc-elt (3.3.4) : 5.1
26111    * If the declaration has a {value constraint},
26112    * the item has neither element nor character [children] and
26113    * clause 3.2 has not applied, then all of the following must be true:
26114    */
26115    if ((inode->decl->value != NULL) &&
26116	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26117	(! INODE_NILLED(inode))) {
26118	/*
26119	* cvc-elt (3.3.4) : 5.1.1
26120	* If the �actual type definition� is a �local type definition�
26121	* then the canonical lexical representation of the {value constraint}
26122	* value must be a valid default for the �actual type definition� as
26123	* defined in Element Default Valid (Immediate) (�3.3.6).
26124	*/
26125	/*
26126	* NOTE: 'local' above means types acquired by xsi:type.
26127	* NOTE: Although the *canonical* value is stated, it is not
26128	* relevant if canonical or not. Additionally XML Schema 1.1
26129	* will removed this requirement as well.
26130	*/
26131	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26132
26133	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26134		inode->decl->value, &(inode->val));
26135	    if (ret != 0) {
26136		if (ret < 0) {
26137		    VERROR_INT("xmlSchemaValidatorPopElem",
26138			"calling xmlSchemaCheckCOSValidDefault()");
26139		    goto internal_error;
26140		}
26141		goto end_elem;
26142	    }
26143	    /*
26144	    * Stop here, to avoid redundant validation of the value
26145	    * (see following).
26146	    */
26147	    goto default_psvi;
26148	}
26149	/*
26150	* cvc-elt (3.3.4) : 5.1.2
26151	* The element information item with the canonical lexical
26152	* representation of the {value constraint} value used as its
26153	* �normalized value� must be �valid� with respect to the
26154	* �actual type definition� as defined by Element Locally Valid (Type)
26155	* (�3.3.4).
26156	*/
26157	if (WXS_IS_SIMPLE(inode->typeDef)) {
26158	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26159		inode, inode->typeDef, inode->decl->value);
26160	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26161	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26162		inode, inode->typeDef->contentTypeDef,
26163		inode->decl->value);
26164	}
26165	if (ret != 0) {
26166	    if (ret < 0) {
26167		VERROR_INT("xmlSchemaValidatorPopElem",
26168		    "calling xmlSchemaVCheckCVCSimpleType()");
26169		goto internal_error;
26170	    }
26171	    goto end_elem;
26172	}
26173
26174default_psvi:
26175	/*
26176	* PSVI: Create a text node on the instance element.
26177	*/
26178	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26179	    (inode->node != NULL)) {
26180	    xmlNodePtr textChild;
26181	    xmlChar *normValue;
26182	    /*
26183	    * VAL TODO: Normalize the value.
26184	    */
26185	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26186		inode->decl->value);
26187	    if (normValue != NULL) {
26188		textChild = xmlNewText(BAD_CAST normValue);
26189		xmlFree(normValue);
26190	    } else
26191		textChild = xmlNewText(inode->decl->value);
26192	    if (textChild == NULL) {
26193		VERROR_INT("xmlSchemaValidatorPopElem",
26194		    "calling xmlNewText()");
26195		goto internal_error;
26196	    } else
26197		xmlAddChild(inode->node, textChild);
26198	}
26199
26200    } else if (! INODE_NILLED(inode)) {
26201	/*
26202	* 5.2.1 The element information item must be �valid� with respect
26203	* to the �actual type definition� as defined by Element Locally
26204	* Valid (Type) (�3.3.4).
26205	*/
26206	if (WXS_IS_SIMPLE(inode->typeDef)) {
26207	     /*
26208	    * SPEC (cvc-type) (3.1)
26209	    * "If the type definition is a simple type definition, ..."
26210	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26211	    * (Element) (�3.3.4) did not apply, then the �normalized value�
26212	    * must be �valid� with respect to the type definition as defined
26213	    * by String Valid (�3.14.4).
26214	    */
26215	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26216		    inode, inode->typeDef, inode->value);
26217	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26218	    /*
26219	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26220	    * definition, then the element information item must be
26221	    * �valid� with respect to the type definition as per
26222	    * Element Locally Valid (Complex Type) (�3.4.4);"
26223	    *
26224	    * SPEC (cvc-complex-type) (2.2)
26225	    * "If the {content type} is a simple type definition, ...
26226	    * the �normalized value� of the element information item is
26227	    * �valid� with respect to that simple type definition as
26228	    * defined by String Valid (�3.14.4)."
26229	    */
26230	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26231		inode, inode->typeDef->contentTypeDef, inode->value);
26232	}
26233	if (ret != 0) {
26234	    if (ret < 0) {
26235		VERROR_INT("xmlSchemaValidatorPopElem",
26236		    "calling xmlSchemaVCheckCVCSimpleType()");
26237		goto internal_error;
26238	    }
26239	    goto end_elem;
26240	}
26241	/*
26242	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26243	* not applied, all of the following must be true:
26244	*/
26245	if ((inode->decl->value != NULL) &&
26246	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26247
26248	    /*
26249	    * TODO: We will need a computed value, when comparison is
26250	    * done on computed values.
26251	    */
26252	    /*
26253	    * 5.2.2.1 The element information item must have no element
26254	    * information item [children].
26255	    */
26256	    if (inode->flags &
26257		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26258		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26259		VERROR(ret, NULL,
26260		    "The content must not containt element nodes since "
26261		    "there is a fixed value constraint");
26262		goto end_elem;
26263	    } else {
26264		/*
26265		* 5.2.2.2 The appropriate case among the following must
26266		* be true:
26267		*/
26268		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26269		    /*
26270		    * 5.2.2.2.1 If the {content type} of the �actual type
26271		    * definition� is mixed, then the *initial value* of the
26272		    * item must match the canonical lexical representation
26273		    * of the {value constraint} value.
26274		    *
26275		    * ... the *initial value* of an element information
26276		    * item is the string composed of, in order, the
26277		    * [character code] of each character information item in
26278		    * the [children] of that element information item.
26279		    */
26280		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26281			/*
26282			* VAL TODO: Report invalid & expected values as well.
26283			* VAL TODO: Implement the canonical stuff.
26284			*/
26285			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26286			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26287			    ret, NULL, NULL,
26288			    "The initial value '%s' does not match the fixed "
26289			    "value constraint '%s'",
26290			    inode->value, inode->decl->value);
26291			goto end_elem;
26292		    }
26293		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26294		    /*
26295		    * 5.2.2.2.2 If the {content type} of the �actual type
26296		    * definition� is a simple type definition, then the
26297		    * *actual value* of the item must match the canonical
26298		    * lexical representation of the {value constraint} value.
26299		    */
26300		    /*
26301		    * VAL TODO: *actual value* is the normalized value, impl.
26302		    *           this.
26303		    * VAL TODO: Report invalid & expected values as well.
26304		    * VAL TODO: Implement a comparison with the computed values.
26305		    */
26306		    if (! xmlStrEqual(inode->value,
26307			    inode->decl->value)) {
26308			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26309			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26310			    ret, NULL, NULL,
26311			    "The actual value '%s' does not match the fixed "
26312			    "value constraint '%s'",
26313			    inode->value,
26314			    inode->decl->value);
26315			goto end_elem;
26316		    }
26317		}
26318	    }
26319	}
26320    }
26321
26322end_elem:
26323    if (vctxt->depth < 0) {
26324	/* TODO: raise error? */
26325	return (0);
26326    }
26327    if (vctxt->depth == vctxt->skipDepth)
26328	vctxt->skipDepth = -1;
26329    /*
26330    * Evaluate the history of XPath state objects.
26331    */
26332    if (inode->appliedXPath &&
26333	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26334	goto internal_error;
26335    /*
26336    * MAYBE TODO:
26337    * SPEC (6) "The element information item must be �valid� with
26338    * respect to each of the {identity-constraint definitions} as per
26339    * Identity-constraint Satisfied (�3.11.4)."
26340    */
26341    /*
26342    * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26343    *   need to be built in any case.
26344    *   We will currently build IDC node-tables and bubble them only if
26345    *   keyrefs do exist.
26346    */
26347
26348    /*
26349    * Add the current IDC target-nodes to the IDC node-tables.
26350    */
26351    if ((inode->idcMatchers != NULL) &&
26352	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26353    {
26354	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26355	    goto internal_error;
26356    }
26357    /*
26358    * Validate IDC keyrefs.
26359    */
26360    if (vctxt->inode->hasKeyrefs)
26361	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26362	    goto internal_error;
26363    /*
26364    * Merge/free the IDC table.
26365    */
26366    if (inode->idcTable != NULL) {
26367#ifdef DEBUG_IDC_NODE_TABLE
26368	xmlSchemaDebugDumpIDCTable(stdout,
26369	    inode->nsName,
26370	    inode->localName,
26371	    inode->idcTable);
26372#endif
26373	if ((vctxt->depth > 0) &&
26374	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26375	{
26376	    /*
26377	    * Merge the IDC node table with the table of the parent node.
26378	    */
26379	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26380		goto internal_error;
26381	}
26382    }
26383    /*
26384    * Clear the current ielem.
26385    * VAL TODO: Don't free the PSVI IDC tables if they are
26386    * requested for the PSVI.
26387    */
26388    xmlSchemaClearElemInfo(vctxt, inode);
26389    /*
26390    * Skip further processing if we are on the validation root.
26391    */
26392    if (vctxt->depth == 0) {
26393	vctxt->depth--;
26394	vctxt->inode = NULL;
26395	return (0);
26396    }
26397    /*
26398    * Reset the keyrefDepth if needed.
26399    */
26400    if (vctxt->aidcs != NULL) {
26401	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26402	do {
26403	    if (aidc->keyrefDepth == vctxt->depth) {
26404		/*
26405		* A 'keyrefDepth' of a key/unique IDC matches the current
26406		* depth, this means that we are leaving the scope of the
26407		* top-most keyref IDC which refers to this IDC.
26408		*/
26409		aidc->keyrefDepth = -1;
26410	    }
26411	    aidc = aidc->next;
26412	} while (aidc != NULL);
26413    }
26414    vctxt->depth--;
26415    vctxt->inode = vctxt->elemInfos[vctxt->depth];
26416    /*
26417    * VAL TODO: 7 If the element information item is the �validation root�, it must be
26418    * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26419    */
26420    return (ret);
26421
26422internal_error:
26423    vctxt->err = -1;
26424    return (-1);
26425}
26426
26427/*
26428* 3.4.4 Complex Type Definition Validation Rules
26429* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26430*/
26431static int
26432xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26433{
26434    xmlSchemaNodeInfoPtr pielem;
26435    xmlSchemaTypePtr ptype;
26436    int ret = 0;
26437
26438    if (vctxt->depth <= 0) {
26439	VERROR_INT("xmlSchemaValidateChildElem",
26440	    "not intended for the validation root");
26441	return (-1);
26442    }
26443    pielem = vctxt->elemInfos[vctxt->depth -1];
26444    if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26445	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26446    /*
26447    * Handle 'nilled' elements.
26448    */
26449    if (INODE_NILLED(pielem)) {
26450	/*
26451	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26452	*/
26453	ACTIVATE_PARENT_ELEM;
26454	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26455	VERROR(ret, NULL,
26456	    "Neither character nor element content is allowed, "
26457	    "because the element was 'nilled'");
26458	ACTIVATE_ELEM;
26459	goto unexpected_elem;
26460    }
26461
26462    ptype = pielem->typeDef;
26463
26464    if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26465	/*
26466	* Workaround for "anyType": we have currently no content model
26467	* assigned for "anyType", so handle it explicitely.
26468	* "anyType" has an unbounded, lax "any" wildcard.
26469	*/
26470	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26471	    vctxt->inode->localName,
26472	    vctxt->inode->nsName);
26473
26474	if (vctxt->inode->decl == NULL) {
26475	    xmlSchemaAttrInfoPtr iattr;
26476	    /*
26477	    * Process "xsi:type".
26478	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26479	    */
26480	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26481		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26482	    if (iattr != NULL) {
26483		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26484		    &(vctxt->inode->typeDef), NULL);
26485		if (ret != 0) {
26486		    if (ret == -1) {
26487			VERROR_INT("xmlSchemaValidateChildElem",
26488			    "calling xmlSchemaProcessXSIType() to "
26489			    "process the attribute 'xsi:nil'");
26490			return (-1);
26491		    }
26492		    return (ret);
26493		}
26494	    } else {
26495		 /*
26496		 * Fallback to "anyType".
26497		 *
26498		 * SPEC (cvc-assess-elt)
26499		 * "If the item cannot be �strictly assessed�, [...]
26500		 * an element information item's schema validity may be laxly
26501		 * assessed if its �context-determined declaration� is not
26502		 * skip by �validating� with respect to the �ur-type
26503		 * definition� as per Element Locally Valid (Type) (�3.3.4)."
26504		*/
26505		vctxt->inode->typeDef =
26506		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26507	    }
26508	}
26509	return (0);
26510    }
26511
26512    switch (ptype->contentType) {
26513	case XML_SCHEMA_CONTENT_EMPTY:
26514	    /*
26515	    * SPEC (2.1) "If the {content type} is empty, then the
26516	    * element information item has no character or element
26517	    * information item [children]."
26518	    */
26519	    ACTIVATE_PARENT_ELEM
26520	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26521	    VERROR(ret, NULL,
26522		"Element content is not allowed, "
26523		"because the content type is empty");
26524	    ACTIVATE_ELEM
26525	    goto unexpected_elem;
26526	    break;
26527
26528	case XML_SCHEMA_CONTENT_MIXED:
26529        case XML_SCHEMA_CONTENT_ELEMENTS: {
26530	    xmlRegExecCtxtPtr regexCtxt;
26531	    xmlChar *values[10];
26532	    int terminal, nbval = 10, nbneg;
26533
26534	    /* VAL TODO: Optimized "anyType" validation.*/
26535
26536	    if (ptype->contModel == NULL) {
26537		VERROR_INT("xmlSchemaValidateChildElem",
26538		    "type has elem content but no content model");
26539		return (-1);
26540	    }
26541	    /*
26542	    * Safety belf for evaluation if the cont. model was already
26543	    * examined to be invalid.
26544	    */
26545	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26546		VERROR_INT("xmlSchemaValidateChildElem",
26547		    "validating elem, but elem content is already invalid");
26548		return (-1);
26549	    }
26550
26551	    regexCtxt = pielem->regexCtxt;
26552	    if (regexCtxt == NULL) {
26553		/*
26554		* Create the regex context.
26555		*/
26556		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26557		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26558		    vctxt);
26559		if (regexCtxt == NULL) {
26560		    VERROR_INT("xmlSchemaValidateChildElem",
26561			"failed to create a regex context");
26562		    return (-1);
26563		}
26564		pielem->regexCtxt = regexCtxt;
26565#ifdef DEBUG_AUTOMATA
26566		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26567		    pielem->localName);
26568#endif
26569	    }
26570
26571	    /*
26572	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26573	    * then the sequence of the element information item's
26574	    * element information item [children], if any, taken in
26575	    * order, is �valid� with respect to the {content type}'s
26576	    * particle, as defined in Element Sequence Locally Valid
26577	    * (Particle) (�3.9.4)."
26578	    */
26579	    ret = xmlRegExecPushString2(regexCtxt,
26580		vctxt->inode->localName,
26581		vctxt->inode->nsName,
26582		vctxt->inode);
26583#ifdef DEBUG_AUTOMATA
26584	    if (ret < 0)
26585		xmlGenericError(xmlGenericErrorContext,
26586		"AUTOMATON push ERROR for '%s' on '%s'\n",
26587		vctxt->inode->localName, pielem->localName);
26588	    else
26589		xmlGenericError(xmlGenericErrorContext,
26590		"AUTOMATON push OK for '%s' on '%s'\n",
26591		vctxt->inode->localName, pielem->localName);
26592#endif
26593	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26594		VERROR_INT("xmlSchemaValidateChildElem",
26595		    "calling xmlRegExecPushString2()");
26596		return (-1);
26597	    }
26598	    if (ret < 0) {
26599		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26600		    &values[0], &terminal);
26601		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26602		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26603		    "This element is not expected",
26604		    nbval, nbneg, values);
26605		ret = vctxt->err;
26606		goto unexpected_elem;
26607	    } else
26608		ret = 0;
26609	}
26610	    break;
26611	case XML_SCHEMA_CONTENT_SIMPLE:
26612	case XML_SCHEMA_CONTENT_BASIC:
26613	    ACTIVATE_PARENT_ELEM
26614	    if (WXS_IS_COMPLEX(ptype)) {
26615		/*
26616		* SPEC (cvc-complex-type) (2.2)
26617		* "If the {content type} is a simple type definition, then
26618		* the element information item has no element information
26619		* item [children], ..."
26620		*/
26621		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26622		VERROR(ret, NULL, "Element content is not allowed, "
26623		    "because the content type is a simple type definition");
26624	    } else {
26625		/*
26626		* SPEC (cvc-type) (3.1.2) "The element information item must
26627		* have no element information item [children]."
26628		*/
26629		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26630		VERROR(ret, NULL, "Element content is not allowed, "
26631		    "because the type definition is simple");
26632	    }
26633	    ACTIVATE_ELEM
26634	    ret = vctxt->err;
26635	    goto unexpected_elem;
26636	    break;
26637
26638	default:
26639	    break;
26640    }
26641    return (ret);
26642unexpected_elem:
26643    /*
26644    * Pop this element and set the skipDepth to skip
26645    * all further content of the parent element.
26646    */
26647    vctxt->skipDepth = vctxt->depth;
26648    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26649    pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26650    return (ret);
26651}
26652
26653#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26654#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26655#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26656
26657static int
26658xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26659		  int nodeType, const xmlChar *value, int len,
26660		  int mode, int *consumed)
26661{
26662    /*
26663    * Unfortunately we have to duplicate the text sometimes.
26664    * OPTIMIZE: Maybe we could skip it, if:
26665    *   1. content type is simple
26666    *   2. whitespace is "collapse"
26667    *   3. it consists of whitespace only
26668    *
26669    * Process character content.
26670    */
26671    if (consumed != NULL)
26672	*consumed = 0;
26673    if (INODE_NILLED(vctxt->inode)) {
26674	/*
26675	* SPEC cvc-elt (3.3.4 - 3.2.1)
26676	* "The element information item must have no character or
26677	* element information item [children]."
26678	*/
26679	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26680	    "Neither character nor element content is allowed "
26681	    "because the element is 'nilled'");
26682	return (vctxt->err);
26683    }
26684    /*
26685    * SPEC (2.1) "If the {content type} is empty, then the
26686    * element information item has no character or element
26687    * information item [children]."
26688    */
26689    if (vctxt->inode->typeDef->contentType ==
26690	    XML_SCHEMA_CONTENT_EMPTY) {
26691	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26692	    "Character content is not allowed, "
26693	    "because the content type is empty");
26694	return (vctxt->err);
26695    }
26696
26697    if (vctxt->inode->typeDef->contentType ==
26698	    XML_SCHEMA_CONTENT_ELEMENTS) {
26699	if ((nodeType != XML_TEXT_NODE) ||
26700	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26701	    /*
26702	    * SPEC cvc-complex-type (2.3)
26703	    * "If the {content type} is element-only, then the
26704	    * element information item has no character information
26705	    * item [children] other than those whose [character
26706	    * code] is defined as a white space in [XML 1.0 (Second
26707	    * Edition)]."
26708	    */
26709	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26710		"Character content other than whitespace is not allowed "
26711		"because the content type is 'element-only'");
26712	    return (vctxt->err);
26713	}
26714	return (0);
26715    }
26716
26717    if ((value == NULL) || (value[0] == 0))
26718	return (0);
26719    /*
26720    * Save the value.
26721    * NOTE that even if the content type is *mixed*, we need the
26722    * *initial value* for default/fixed value constraints.
26723    */
26724    if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26725	((vctxt->inode->decl == NULL) ||
26726	(vctxt->inode->decl->value == NULL)))
26727	return (0);
26728
26729    if (vctxt->inode->value == NULL) {
26730	/*
26731	* Set the value.
26732	*/
26733	switch (mode) {
26734	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26735		/*
26736		* When working on a tree.
26737		*/
26738		vctxt->inode->value = value;
26739		break;
26740	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26741		/*
26742		* When working with the reader.
26743		* The value will be freed by the element info.
26744		*/
26745		vctxt->inode->value = value;
26746		if (consumed != NULL)
26747		    *consumed = 1;
26748		vctxt->inode->flags |=
26749		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26750		break;
26751	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26752		/*
26753		* When working with SAX.
26754		* The value will be freed by the element info.
26755		*/
26756		if (len != -1)
26757		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26758		else
26759		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26760		vctxt->inode->flags |=
26761		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26762		break;
26763	    default:
26764		break;
26765	}
26766    } else {
26767	if (len < 0)
26768	    len = xmlStrlen(value);
26769	/*
26770	* Concat the value.
26771	*/
26772	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26773	    vctxt->inode->value = BAD_CAST xmlStrncat(
26774		(xmlChar *) vctxt->inode->value, value, len);
26775	} else {
26776	    vctxt->inode->value =
26777		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26778	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26779	}
26780    }
26781
26782    return (0);
26783}
26784
26785static int
26786xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26787{
26788    int ret = 0;
26789
26790    if ((vctxt->skipDepth != -1) &&
26791	(vctxt->depth >= vctxt->skipDepth)) {
26792	VERROR_INT("xmlSchemaValidateElem",
26793	    "in skip-state");
26794	goto internal_error;
26795    }
26796    if (vctxt->xsiAssemble) {
26797	/*
26798	* We will stop validation if there was an error during
26799	* dynamic schema construction.
26800	* Note that we simply set @skipDepth to 0, this could
26801	* mean that a streaming document via SAX would be
26802	* still read to the end but it won't be validated any more.
26803	* TODO: If we are sure how to stop the validation at once
26804	*   for all input scenarios, then this should be changed to
26805	*   instantly stop the validation.
26806	*/
26807	ret = xmlSchemaAssembleByXSI(vctxt);
26808	if (ret != 0) {
26809	    if (ret == -1)
26810		goto internal_error;
26811	    vctxt->skipDepth = 0;
26812	    return(ret);
26813	}
26814    }
26815    if (vctxt->depth > 0) {
26816	/*
26817	* Validate this element against the content model
26818	* of the parent.
26819	*/
26820	ret = xmlSchemaValidateChildElem(vctxt);
26821	if (ret != 0) {
26822	    if (ret < 0) {
26823		VERROR_INT("xmlSchemaValidateElem",
26824		    "calling xmlSchemaStreamValidateChildElement()");
26825		goto internal_error;
26826	    }
26827	    goto exit;
26828	}
26829	if (vctxt->depth == vctxt->skipDepth)
26830	    goto exit;
26831	if ((vctxt->inode->decl == NULL) &&
26832	    (vctxt->inode->typeDef == NULL)) {
26833	    VERROR_INT("xmlSchemaValidateElem",
26834		"the child element was valid but neither the "
26835		"declaration nor the type was set");
26836	    goto internal_error;
26837	}
26838    } else {
26839	/*
26840	* Get the declaration of the validation root.
26841	*/
26842	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26843	    vctxt->inode->localName,
26844	    vctxt->inode->nsName);
26845	if (vctxt->inode->decl == NULL) {
26846	    ret = XML_SCHEMAV_CVC_ELT_1;
26847	    VERROR(ret, NULL,
26848		"No matching global declaration available "
26849		"for the validation root");
26850	    goto exit;
26851	}
26852    }
26853
26854    if (vctxt->inode->decl == NULL)
26855	goto type_validation;
26856
26857    if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26858	int skip;
26859	/*
26860	* Wildcards.
26861	*/
26862	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26863	if (ret != 0) {
26864	    if (ret < 0) {
26865		VERROR_INT("xmlSchemaValidateElem",
26866		    "calling xmlSchemaValidateElemWildcard()");
26867		goto internal_error;
26868	    }
26869	    goto exit;
26870	}
26871	if (skip) {
26872	    vctxt->skipDepth = vctxt->depth;
26873	    goto exit;
26874	}
26875	/*
26876	* The declaration might be set by the wildcard validation,
26877	* when the processContents is "lax" or "strict".
26878	*/
26879	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26880	    /*
26881	    * Clear the "decl" field to not confuse further processing.
26882	    */
26883	    vctxt->inode->decl = NULL;
26884	    goto type_validation;
26885	}
26886    }
26887    /*
26888    * Validate against the declaration.
26889    */
26890    ret = xmlSchemaValidateElemDecl(vctxt);
26891    if (ret != 0) {
26892	if (ret < 0) {
26893	    VERROR_INT("xmlSchemaValidateElem",
26894		"calling xmlSchemaValidateElemDecl()");
26895	    goto internal_error;
26896	}
26897	goto exit;
26898    }
26899    /*
26900    * Validate against the type definition.
26901    */
26902type_validation:
26903
26904    if (vctxt->inode->typeDef == NULL) {
26905	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26906	ret = XML_SCHEMAV_CVC_TYPE_1;
26907    	VERROR(ret, NULL,
26908    	    "The type definition is absent");
26909	goto exit;
26910    }
26911    if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26912	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26913	ret = XML_SCHEMAV_CVC_TYPE_2;
26914    	    VERROR(ret, NULL,
26915    	    "The type definition is abstract");
26916	goto exit;
26917    }
26918    /*
26919    * Evaluate IDCs. Do it here, since new IDC matchers are registered
26920    * during validation against the declaration. This must be done
26921    * _before_ attribute validation.
26922    */
26923    if (vctxt->xpathStates != NULL) {
26924	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26925	vctxt->inode->appliedXPath = 1;
26926	if (ret == -1) {
26927	    VERROR_INT("xmlSchemaValidateElem",
26928		"calling xmlSchemaXPathEvaluate()");
26929	    goto internal_error;
26930	}
26931    }
26932    /*
26933    * Validate attributes.
26934    */
26935    if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26936	if ((vctxt->nbAttrInfos != 0) ||
26937	    (vctxt->inode->typeDef->attrUses != NULL)) {
26938
26939	    ret = xmlSchemaVAttributesComplex(vctxt);
26940	}
26941    } else if (vctxt->nbAttrInfos != 0) {
26942
26943	ret = xmlSchemaVAttributesSimple(vctxt);
26944    }
26945    /*
26946    * Clear registered attributes.
26947    */
26948    if (vctxt->nbAttrInfos != 0)
26949	xmlSchemaClearAttrInfos(vctxt);
26950    if (ret == -1) {
26951	VERROR_INT("xmlSchemaValidateElem",
26952	    "calling attributes validation");
26953	goto internal_error;
26954    }
26955    /*
26956    * Don't return an error if attributes are invalid on purpose.
26957    */
26958    ret = 0;
26959
26960exit:
26961    if (ret != 0)
26962	vctxt->skipDepth = vctxt->depth;
26963    return (ret);
26964internal_error:
26965    return (-1);
26966}
26967
26968#ifdef XML_SCHEMA_READER_ENABLED
26969static int
26970xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26971{
26972    const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26973    int depth, nodeType, ret = 0, consumed;
26974    xmlSchemaNodeInfoPtr ielem;
26975
26976    vctxt->depth = -1;
26977    ret = xmlTextReaderRead(vctxt->reader);
26978    /*
26979    * Move to the document element.
26980    */
26981    while (ret == 1) {
26982	nodeType = xmlTextReaderNodeType(vctxt->reader);
26983	if (nodeType == XML_ELEMENT_NODE)
26984	    goto root_found;
26985	ret = xmlTextReaderRead(vctxt->reader);
26986    }
26987    goto exit;
26988
26989root_found:
26990
26991    do {
26992	depth = xmlTextReaderDepth(vctxt->reader);
26993	nodeType = xmlTextReaderNodeType(vctxt->reader);
26994
26995	if (nodeType == XML_ELEMENT_NODE) {
26996
26997	    vctxt->depth++;
26998	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26999		VERROR_INT("xmlSchemaVReaderWalk",
27000		    "calling xmlSchemaValidatorPushElem()");
27001		goto internal_error;
27002	    }
27003	    ielem = vctxt->inode;
27004	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27005	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27006	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27007	    /*
27008	    * Is the element empty?
27009	    */
27010	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27011	    if (ret == -1) {
27012		VERROR_INT("xmlSchemaVReaderWalk",
27013		    "calling xmlTextReaderIsEmptyElement()");
27014		goto internal_error;
27015	    }
27016	    if (ret) {
27017		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27018	    }
27019	    /*
27020	    * Register attributes.
27021	    */
27022	    vctxt->nbAttrInfos = 0;
27023	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27024	    if (ret == -1) {
27025		VERROR_INT("xmlSchemaVReaderWalk",
27026		    "calling xmlTextReaderMoveToFirstAttribute()");
27027		goto internal_error;
27028	    }
27029	    if (ret == 1) {
27030		do {
27031		    /*
27032		    * VAL TODO: How do we know that the reader works on a
27033		    * node tree, to be able to pass a node here?
27034		    */
27035		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27036			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27037			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27038			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27039
27040			VERROR_INT("xmlSchemaVReaderWalk",
27041			    "calling xmlSchemaValidatorPushAttribute()");
27042			goto internal_error;
27043		    }
27044		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27045		    if (ret == -1) {
27046			VERROR_INT("xmlSchemaVReaderWalk",
27047			    "calling xmlTextReaderMoveToFirstAttribute()");
27048			goto internal_error;
27049		    }
27050		} while (ret == 1);
27051		/*
27052		* Back to element position.
27053		*/
27054		ret = xmlTextReaderMoveToElement(vctxt->reader);
27055		if (ret == -1) {
27056		    VERROR_INT("xmlSchemaVReaderWalk",
27057			"calling xmlTextReaderMoveToElement()");
27058		    goto internal_error;
27059		}
27060	    }
27061	    /*
27062	    * Validate the element.
27063	    */
27064	    ret= xmlSchemaValidateElem(vctxt);
27065	    if (ret != 0) {
27066		if (ret == -1) {
27067		    VERROR_INT("xmlSchemaVReaderWalk",
27068			"calling xmlSchemaValidateElem()");
27069		    goto internal_error;
27070		}
27071		goto exit;
27072	    }
27073	    if (vctxt->depth == vctxt->skipDepth) {
27074		int curDepth;
27075		/*
27076		* Skip all content.
27077		*/
27078		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27079		    ret = xmlTextReaderRead(vctxt->reader);
27080		    curDepth = xmlTextReaderDepth(vctxt->reader);
27081		    while ((ret == 1) && (curDepth != depth)) {
27082			ret = xmlTextReaderRead(vctxt->reader);
27083			curDepth = xmlTextReaderDepth(vctxt->reader);
27084		    }
27085		    if (ret < 0) {
27086			/*
27087			* VAL TODO: A reader error occured; what to do here?
27088			*/
27089			ret = 1;
27090			goto exit;
27091		    }
27092		}
27093		goto leave_elem;
27094	    }
27095	    /*
27096	    * READER VAL TODO: Is an END_ELEM really never called
27097	    * if the elem is empty?
27098	    */
27099	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27100		goto leave_elem;
27101	} else if (nodeType == END_ELEM) {
27102	    /*
27103	    * Process END of element.
27104	    */
27105leave_elem:
27106	    ret = xmlSchemaValidatorPopElem(vctxt);
27107	    if (ret != 0) {
27108		if (ret < 0) {
27109		    VERROR_INT("xmlSchemaVReaderWalk",
27110			"calling xmlSchemaValidatorPopElem()");
27111		    goto internal_error;
27112		}
27113		goto exit;
27114	    }
27115	    if (vctxt->depth >= 0)
27116		ielem = vctxt->inode;
27117	    else
27118		ielem = NULL;
27119	} else if ((nodeType == XML_TEXT_NODE) ||
27120	    (nodeType == XML_CDATA_SECTION_NODE) ||
27121	    (nodeType == WHTSP) ||
27122	    (nodeType == SIGN_WHTSP)) {
27123	    /*
27124	    * Process character content.
27125	    */
27126	    xmlChar *value;
27127
27128	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27129		nodeType = XML_TEXT_NODE;
27130
27131	    value = xmlTextReaderValue(vctxt->reader);
27132	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27133		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27134	    if (! consumed)
27135		xmlFree(value);
27136	    if (ret == -1) {
27137		VERROR_INT("xmlSchemaVReaderWalk",
27138		    "calling xmlSchemaVPushText()");
27139		goto internal_error;
27140	    }
27141	} else if ((nodeType == XML_ENTITY_NODE) ||
27142	    (nodeType == XML_ENTITY_REF_NODE)) {
27143	    /*
27144	    * VAL TODO: What to do with entities?
27145	    */
27146	    TODO
27147	}
27148	/*
27149	* Read next node.
27150	*/
27151	ret = xmlTextReaderRead(vctxt->reader);
27152    } while (ret == 1);
27153
27154exit:
27155    return (ret);
27156internal_error:
27157    return (-1);
27158}
27159#endif
27160
27161/************************************************************************
27162 * 									*
27163 * 			SAX validation handlers				*
27164 * 									*
27165 ************************************************************************/
27166
27167/*
27168* Process text content.
27169*/
27170static void
27171xmlSchemaSAXHandleText(void *ctx,
27172		       const xmlChar * ch,
27173		       int len)
27174{
27175    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27176
27177    if (vctxt->depth < 0)
27178	return;
27179    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27180	return;
27181    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27182	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27183    if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27184	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27185	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27186	    "calling xmlSchemaVPushText()");
27187	vctxt->err = -1;
27188	xmlStopParser(vctxt->parserCtxt);
27189    }
27190}
27191
27192/*
27193* Process CDATA content.
27194*/
27195static void
27196xmlSchemaSAXHandleCDataSection(void *ctx,
27197			     const xmlChar * ch,
27198			     int len)
27199{
27200    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27201
27202    if (vctxt->depth < 0)
27203	return;
27204    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27205	return;
27206    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27207	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27208    if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27209	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27210	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27211	    "calling xmlSchemaVPushText()");
27212	vctxt->err = -1;
27213	xmlStopParser(vctxt->parserCtxt);
27214    }
27215}
27216
27217static void
27218xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27219			    const xmlChar * name ATTRIBUTE_UNUSED)
27220{
27221    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27222
27223    if (vctxt->depth < 0)
27224	return;
27225    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27226	return;
27227    /* SAX VAL TODO: What to do here? */
27228    TODO
27229}
27230
27231static void
27232xmlSchemaSAXHandleStartElementNs(void *ctx,
27233				 const xmlChar * localname,
27234				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27235				 const xmlChar * URI,
27236				 int nb_namespaces,
27237				 const xmlChar ** namespaces,
27238				 int nb_attributes,
27239				 int nb_defaulted ATTRIBUTE_UNUSED,
27240				 const xmlChar ** attributes)
27241{
27242    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27243    int ret;
27244    xmlSchemaNodeInfoPtr ielem;
27245    int i, j;
27246
27247    /*
27248    * SAX VAL TODO: What to do with nb_defaulted?
27249    */
27250    /*
27251    * Skip elements if inside a "skip" wildcard or invalid.
27252    */
27253    vctxt->depth++;
27254    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27255	return;
27256    /*
27257    * Push the element.
27258    */
27259    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27260	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27261	    "calling xmlSchemaValidatorPushElem()");
27262	goto internal_error;
27263    }
27264    ielem = vctxt->inode;
27265    /*
27266    * TODO: Is this OK?
27267    */
27268    ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27269    ielem->localName = localname;
27270    ielem->nsName = URI;
27271    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27272    /*
27273    * Register namespaces on the elem info.
27274    */
27275    if (nb_namespaces != 0) {
27276	/*
27277	* Although the parser builds its own namespace list,
27278	* we have no access to it, so we'll use an own one.
27279	*/
27280        for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27281	    /*
27282	    * Store prefix and namespace name.
27283	    */
27284	    if (ielem->nsBindings == NULL) {
27285		ielem->nsBindings =
27286		    (const xmlChar **) xmlMalloc(10 *
27287			sizeof(const xmlChar *));
27288		if (ielem->nsBindings == NULL) {
27289		    xmlSchemaVErrMemory(vctxt,
27290			"allocating namespace bindings for SAX validation",
27291			NULL);
27292		    goto internal_error;
27293		}
27294		ielem->nbNsBindings = 0;
27295		ielem->sizeNsBindings = 5;
27296	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27297		ielem->sizeNsBindings *= 2;
27298		ielem->nsBindings =
27299		    (const xmlChar **) xmlRealloc(
27300			(void *) ielem->nsBindings,
27301			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27302		if (ielem->nsBindings == NULL) {
27303		    xmlSchemaVErrMemory(vctxt,
27304			"re-allocating namespace bindings for SAX validation",
27305			NULL);
27306		    goto internal_error;
27307		}
27308	    }
27309
27310	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27311	    if (namespaces[j+1][0] == 0) {
27312		/*
27313		* Handle xmlns="".
27314		*/
27315		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27316	    } else
27317		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27318		    namespaces[j+1];
27319	    ielem->nbNsBindings++;
27320	}
27321    }
27322    /*
27323    * Register attributes.
27324    * SAX VAL TODO: We are not adding namespace declaration
27325    * attributes yet.
27326    */
27327    if (nb_attributes != 0) {
27328	xmlChar *value;
27329
27330        for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27331	    /*
27332	    * Duplicate the value.
27333	    */
27334	    value = xmlStrndup(attributes[j+3],
27335		attributes[j+4] - attributes[j+3]);
27336	    /*
27337	    * TODO: Set the node line.
27338	    */
27339	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27340		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27341		value, 1);
27342	    if (ret == -1) {
27343		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27344		    "calling xmlSchemaValidatorPushAttribute()");
27345		goto internal_error;
27346	    }
27347	}
27348    }
27349    /*
27350    * Validate the element.
27351    */
27352    ret = xmlSchemaValidateElem(vctxt);
27353    if (ret != 0) {
27354	if (ret == -1) {
27355	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27356		"calling xmlSchemaValidateElem()");
27357	    goto internal_error;
27358	}
27359	goto exit;
27360    }
27361
27362exit:
27363    return;
27364internal_error:
27365    vctxt->err = -1;
27366    xmlStopParser(vctxt->parserCtxt);
27367    return;
27368}
27369
27370static void
27371xmlSchemaSAXHandleEndElementNs(void *ctx,
27372			       const xmlChar * localname ATTRIBUTE_UNUSED,
27373			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27374			       const xmlChar * URI ATTRIBUTE_UNUSED)
27375{
27376    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27377    int res;
27378
27379    /*
27380    * Skip elements if inside a "skip" wildcard or if invalid.
27381    */
27382    if (vctxt->skipDepth != -1) {
27383	if (vctxt->depth > vctxt->skipDepth) {
27384	    vctxt->depth--;
27385	    return;
27386	} else
27387	    vctxt->skipDepth = -1;
27388    }
27389    /*
27390    * SAX VAL TODO: Just a temporary check.
27391    */
27392    if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27393	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27394	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27395	    "elem pop mismatch");
27396    }
27397    res = xmlSchemaValidatorPopElem(vctxt);
27398    if (res != 0) {
27399	if (res < 0) {
27400	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27401		"calling xmlSchemaValidatorPopElem()");
27402	    goto internal_error;
27403	}
27404	goto exit;
27405    }
27406exit:
27407    return;
27408internal_error:
27409    vctxt->err = -1;
27410    xmlStopParser(vctxt->parserCtxt);
27411    return;
27412}
27413
27414/************************************************************************
27415 * 									*
27416 * 			Validation interfaces				*
27417 * 									*
27418 ************************************************************************/
27419
27420/**
27421 * xmlSchemaNewValidCtxt:
27422 * @schema:  a precompiled XML Schemas
27423 *
27424 * Create an XML Schemas validation context based on the given schema.
27425 *
27426 * Returns the validation context or NULL in case of error
27427 */
27428xmlSchemaValidCtxtPtr
27429xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27430{
27431    xmlSchemaValidCtxtPtr ret;
27432
27433    ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27434    if (ret == NULL) {
27435        xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27436        return (NULL);
27437    }
27438    memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27439    ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27440    ret->dict = xmlDictCreate();
27441    ret->nodeQNames = xmlSchemaItemListCreate();
27442    ret->schema = schema;
27443    return (ret);
27444}
27445
27446/**
27447 * xmlSchemaClearValidCtxt:
27448 * @ctxt: the schema validation context
27449 *
27450 * Free the resources associated to the schema validation context;
27451 * leaves some fields alive intended for reuse of the context.
27452 */
27453static void
27454xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27455{
27456    if (vctxt == NULL)
27457        return;
27458
27459    /*
27460    * TODO: Should we clear the flags?
27461    *   Might be problematic if one reuses the context
27462    *   and assumes that the options remain the same.
27463    */
27464    vctxt->flags = 0;
27465    vctxt->validationRoot = NULL;
27466    vctxt->doc = NULL;
27467#ifdef LIBXML_READER_ENABLED
27468    vctxt->reader = NULL;
27469#endif
27470    vctxt->hasKeyrefs = 0;
27471
27472    if (vctxt->value != NULL) {
27473        xmlSchemaFreeValue(vctxt->value);
27474	vctxt->value = NULL;
27475    }
27476    /*
27477    * Augmented IDC information.
27478    */
27479    if (vctxt->aidcs != NULL) {
27480	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27481	do {
27482	    next = cur->next;
27483	    xmlFree(cur);
27484	    cur = next;
27485	} while (cur != NULL);
27486	vctxt->aidcs = NULL;
27487    }
27488    if (vctxt->idcMatcherCache != NULL) {
27489	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27490
27491	while (matcher) {
27492	    tmp = matcher;
27493	    matcher = matcher->nextCached;
27494	    xmlSchemaIDCFreeMatcherList(tmp);
27495	}
27496	vctxt->idcMatcherCache = NULL;
27497    }
27498
27499
27500    if (vctxt->idcNodes != NULL) {
27501	int i;
27502	xmlSchemaPSVIIDCNodePtr item;
27503
27504	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27505	    item = vctxt->idcNodes[i];
27506	    xmlFree(item->keys);
27507	    xmlFree(item);
27508	}
27509	xmlFree(vctxt->idcNodes);
27510	vctxt->idcNodes = NULL;
27511	vctxt->nbIdcNodes = 0;
27512	vctxt->sizeIdcNodes = 0;
27513    }
27514    /*
27515    * Note that we won't delete the XPath state pool here.
27516    */
27517    if (vctxt->xpathStates != NULL) {
27518	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27519	vctxt->xpathStates = NULL;
27520    }
27521    /*
27522    * Attribute info.
27523    */
27524    if (vctxt->nbAttrInfos != 0) {
27525	xmlSchemaClearAttrInfos(vctxt);
27526    }
27527    /*
27528    * Element info.
27529    */
27530    if (vctxt->elemInfos != NULL) {
27531	int i;
27532	xmlSchemaNodeInfoPtr ei;
27533
27534	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27535	    ei = vctxt->elemInfos[i];
27536	    if (ei == NULL)
27537		break;
27538	    xmlSchemaClearElemInfo(vctxt, ei);
27539	}
27540    }
27541    xmlSchemaItemListClear(vctxt->nodeQNames);
27542    /* Recreate the dict. */
27543    xmlDictFree(vctxt->dict);
27544    /*
27545    * TODO: Is is save to recreate it? Do we have a scenario
27546    * where the user provides the dict?
27547    */
27548    vctxt->dict = xmlDictCreate();
27549}
27550
27551/**
27552 * xmlSchemaFreeValidCtxt:
27553 * @ctxt:  the schema validation context
27554 *
27555 * Free the resources associated to the schema validation context
27556 */
27557void
27558xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27559{
27560    if (ctxt == NULL)
27561        return;
27562    if (ctxt->value != NULL)
27563        xmlSchemaFreeValue(ctxt->value);
27564    if (ctxt->pctxt != NULL)
27565	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27566    if (ctxt->idcNodes != NULL) {
27567	int i;
27568	xmlSchemaPSVIIDCNodePtr item;
27569
27570	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27571	    item = ctxt->idcNodes[i];
27572	    xmlFree(item->keys);
27573	    xmlFree(item);
27574	}
27575	xmlFree(ctxt->idcNodes);
27576    }
27577    if (ctxt->idcKeys != NULL) {
27578	int i;
27579	for (i = 0; i < ctxt->nbIdcKeys; i++)
27580	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27581	xmlFree(ctxt->idcKeys);
27582    }
27583
27584    if (ctxt->xpathStates != NULL) {
27585	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27586	ctxt->xpathStates = NULL;
27587    }
27588    if (ctxt->xpathStatePool != NULL) {
27589	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27590	ctxt->xpathStatePool = NULL;
27591    }
27592
27593    /*
27594    * Augmented IDC information.
27595    */
27596    if (ctxt->aidcs != NULL) {
27597	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27598	do {
27599	    next = cur->next;
27600	    xmlFree(cur);
27601	    cur = next;
27602	} while (cur != NULL);
27603    }
27604    if (ctxt->attrInfos != NULL) {
27605	int i;
27606	xmlSchemaAttrInfoPtr attr;
27607
27608	/* Just a paranoid call to the cleanup. */
27609	if (ctxt->nbAttrInfos != 0)
27610	    xmlSchemaClearAttrInfos(ctxt);
27611	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27612	    attr = ctxt->attrInfos[i];
27613	    xmlFree(attr);
27614	}
27615	xmlFree(ctxt->attrInfos);
27616    }
27617    if (ctxt->elemInfos != NULL) {
27618	int i;
27619	xmlSchemaNodeInfoPtr ei;
27620
27621	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27622	    ei = ctxt->elemInfos[i];
27623	    if (ei == NULL)
27624		break;
27625	    xmlSchemaClearElemInfo(ctxt, ei);
27626	    xmlFree(ei);
27627	}
27628	xmlFree(ctxt->elemInfos);
27629    }
27630    if (ctxt->nodeQNames != NULL)
27631	xmlSchemaItemListFree(ctxt->nodeQNames);
27632    if (ctxt->dict != NULL)
27633	xmlDictFree(ctxt->dict);
27634    xmlFree(ctxt);
27635}
27636
27637/**
27638 * xmlSchemaIsValid:
27639 * @ctxt: the schema validation context
27640 *
27641 * Check if any error was detected during validation.
27642 *
27643 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27644 *         of internal error.
27645 */
27646int
27647xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27648{
27649    if (ctxt == NULL)
27650        return(-1);
27651    return(ctxt->err == 0);
27652}
27653
27654/**
27655 * xmlSchemaSetValidErrors:
27656 * @ctxt:  a schema validation context
27657 * @err:  the error function
27658 * @warn: the warning function
27659 * @ctx: the functions context
27660 *
27661 * Set the error and warning callback informations
27662 */
27663void
27664xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27665                        xmlSchemaValidityErrorFunc err,
27666                        xmlSchemaValidityWarningFunc warn, void *ctx)
27667{
27668    if (ctxt == NULL)
27669        return;
27670    ctxt->error = err;
27671    ctxt->warning = warn;
27672    ctxt->errCtxt = ctx;
27673    if (ctxt->pctxt != NULL)
27674	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27675}
27676
27677/**
27678 * xmlSchemaSetValidStructuredErrors:
27679 * @ctxt:  a schema validation context
27680 * @serror:  the structured error function
27681 * @ctx: the functions context
27682 *
27683 * Set the structured error callback
27684 */
27685void
27686xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27687				  xmlStructuredErrorFunc serror, void *ctx)
27688{
27689    if (ctxt == NULL)
27690        return;
27691	ctxt->serror = serror;
27692    ctxt->error = NULL;
27693    ctxt->warning = NULL;
27694    ctxt->errCtxt = ctx;
27695    if (ctxt->pctxt != NULL)
27696	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27697}
27698
27699/**
27700 * xmlSchemaGetValidErrors:
27701 * @ctxt: a XML-Schema validation context
27702 * @err: the error function result
27703 * @warn: the warning function result
27704 * @ctx: the functions context result
27705 *
27706 * Get the error and warning callback informations
27707 *
27708 * Returns -1 in case of error and 0 otherwise
27709 */
27710int
27711xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27712			xmlSchemaValidityErrorFunc * err,
27713			xmlSchemaValidityWarningFunc * warn, void **ctx)
27714{
27715	if (ctxt == NULL)
27716		return (-1);
27717	if (err != NULL)
27718		*err = ctxt->error;
27719	if (warn != NULL)
27720		*warn = ctxt->warning;
27721	if (ctx != NULL)
27722		*ctx = ctxt->errCtxt;
27723	return (0);
27724}
27725
27726
27727/**
27728 * xmlSchemaSetValidOptions:
27729 * @ctxt:	a schema validation context
27730 * @options: a combination of xmlSchemaValidOption
27731 *
27732 * Sets the options to be used during the validation.
27733 *
27734 * Returns 0 in case of success, -1 in case of an
27735 * API error.
27736 */
27737int
27738xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27739			 int options)
27740
27741{
27742    int i;
27743
27744    if (ctxt == NULL)
27745	return (-1);
27746    /*
27747    * WARNING: Change the start value if adding to the
27748    * xmlSchemaValidOption.
27749    * TODO: Is there an other, more easy to maintain,
27750    * way?
27751    */
27752    for (i = 1; i < (int) sizeof(int) * 8; i++) {
27753        if (options & 1<<i)
27754	    return (-1);
27755    }
27756    ctxt->options = options;
27757    return (0);
27758}
27759
27760/**
27761 * xmlSchemaValidCtxtGetOptions:
27762 * @ctxt: a schema validation context
27763 *
27764 * Get the validation context options.
27765 *
27766 * Returns the option combination or -1 on error.
27767 */
27768int
27769xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27770
27771{
27772    if (ctxt == NULL)
27773	return (-1);
27774    else
27775	return (ctxt->options);
27776}
27777
27778static int
27779xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27780{
27781    xmlAttrPtr attr;
27782    int ret = 0;
27783    xmlSchemaNodeInfoPtr ielem = NULL;
27784    xmlNodePtr node, valRoot;
27785    const xmlChar *nsName;
27786
27787    /* DOC VAL TODO: Move this to the start function. */
27788    valRoot = xmlDocGetRootElement(vctxt->doc);
27789    if (valRoot == NULL) {
27790	/* VAL TODO: Error code? */
27791	VERROR(1, NULL, "The document has no document element");
27792	return (1);
27793    }
27794    vctxt->depth = -1;
27795    vctxt->validationRoot = valRoot;
27796    node = valRoot;
27797    while (node != NULL) {
27798	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27799	    goto next_sibling;
27800	if (node->type == XML_ELEMENT_NODE) {
27801
27802	    /*
27803	    * Init the node-info.
27804	    */
27805	    vctxt->depth++;
27806	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27807		goto internal_error;
27808	    ielem = vctxt->inode;
27809	    ielem->node = node;
27810	    ielem->nodeLine = node->line;
27811	    ielem->localName = node->name;
27812	    if (node->ns != NULL)
27813		ielem->nsName = node->ns->href;
27814	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27815	    /*
27816	    * Register attributes.
27817	    * DOC VAL TODO: We do not register namespace declaration
27818	    * attributes yet.
27819	    */
27820	    vctxt->nbAttrInfos = 0;
27821	    if (node->properties != NULL) {
27822		attr = node->properties;
27823		do {
27824		    if (attr->ns != NULL)
27825			nsName = attr->ns->href;
27826		    else
27827			nsName = NULL;
27828		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27829			(xmlNodePtr) attr,
27830			/*
27831			* Note that we give it the line number of the
27832			* parent element.
27833			*/
27834			ielem->nodeLine,
27835			attr->name, nsName, 0,
27836			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27837		    if (ret == -1) {
27838			VERROR_INT("xmlSchemaDocWalk",
27839			    "calling xmlSchemaValidatorPushAttribute()");
27840			goto internal_error;
27841		    }
27842		    attr = attr->next;
27843		} while (attr);
27844	    }
27845	    /*
27846	    * Validate the element.
27847	    */
27848	    ret = xmlSchemaValidateElem(vctxt);
27849	    if (ret != 0) {
27850		if (ret == -1) {
27851		    VERROR_INT("xmlSchemaDocWalk",
27852			"calling xmlSchemaValidateElem()");
27853		    goto internal_error;
27854		}
27855		/*
27856		* Don't stop validation; just skip the content
27857		* of this element.
27858		*/
27859		goto leave_node;
27860	    }
27861	    if ((vctxt->skipDepth != -1) &&
27862		(vctxt->depth >= vctxt->skipDepth))
27863		goto leave_node;
27864	} else if ((node->type == XML_TEXT_NODE) ||
27865	    (node->type == XML_CDATA_SECTION_NODE)) {
27866	    /*
27867	    * Process character content.
27868	    */
27869	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27870		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27871	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27872		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27873	    if (ret < 0) {
27874		VERROR_INT("xmlSchemaVDocWalk",
27875		    "calling xmlSchemaVPushText()");
27876		goto internal_error;
27877	    }
27878	    /*
27879	    * DOC VAL TODO: Should we skip further validation of the
27880	    * element content here?
27881	    */
27882	} else if ((node->type == XML_ENTITY_NODE) ||
27883	    (node->type == XML_ENTITY_REF_NODE)) {
27884	    /*
27885	    * DOC VAL TODO: What to do with entities?
27886	    */
27887	    VERROR_INT("xmlSchemaVDocWalk",
27888		"there is at least one entity reference in the node-tree "
27889		"currently being validated. Processing of entities with "
27890		"this XML Schema processor is not supported (yet). Please "
27891		"substitute entities before validation.");
27892	    goto internal_error;
27893	} else {
27894	    goto leave_node;
27895	    /*
27896	    * DOC VAL TODO: XInclude nodes, etc.
27897	    */
27898	}
27899	/*
27900	* Walk the doc.
27901	*/
27902	if (node->children != NULL) {
27903	    node = node->children;
27904	    continue;
27905	}
27906leave_node:
27907	if (node->type == XML_ELEMENT_NODE) {
27908	    /*
27909	    * Leaving the scope of an element.
27910	    */
27911	    if (node != vctxt->inode->node) {
27912		VERROR_INT("xmlSchemaVDocWalk",
27913		    "element position mismatch");
27914		goto internal_error;
27915	    }
27916	    ret = xmlSchemaValidatorPopElem(vctxt);
27917	    if (ret != 0) {
27918		if (ret < 0) {
27919		    VERROR_INT("xmlSchemaVDocWalk",
27920			"calling xmlSchemaValidatorPopElem()");
27921		    goto internal_error;
27922		}
27923	    }
27924	    if (node == valRoot)
27925		goto exit;
27926	}
27927next_sibling:
27928	if (node->next != NULL)
27929	    node = node->next;
27930	else {
27931	    node = node->parent;
27932	    goto leave_node;
27933	}
27934    }
27935
27936exit:
27937    return (ret);
27938internal_error:
27939    return (-1);
27940}
27941
27942static int
27943xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27944    /*
27945    * Some initialization.
27946    */
27947    vctxt->err = 0;
27948    vctxt->nberrors = 0;
27949    vctxt->depth = -1;
27950    vctxt->skipDepth = -1;
27951    vctxt->xsiAssemble = 0;
27952    vctxt->hasKeyrefs = 0;
27953#ifdef ENABLE_IDC_NODE_TABLES_TEST
27954    vctxt->createIDCNodeTables = 1;
27955#else
27956    vctxt->createIDCNodeTables = 0;
27957#endif
27958    /*
27959    * Create a schema + parser if necessary.
27960    */
27961    if (vctxt->schema == NULL) {
27962	xmlSchemaParserCtxtPtr pctxt;
27963
27964	vctxt->xsiAssemble = 1;
27965	/*
27966	* If not schema was given then we will create a schema
27967	* dynamically using XSI schema locations.
27968	*
27969	* Create the schema parser context.
27970	*/
27971	if ((vctxt->pctxt == NULL) &&
27972	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27973	   return (-1);
27974	pctxt = vctxt->pctxt;
27975	pctxt->xsiAssemble = 1;
27976	/*
27977	* Create the schema.
27978	*/
27979	vctxt->schema = xmlSchemaNewSchema(pctxt);
27980	if (vctxt->schema == NULL)
27981	    return (-1);
27982	/*
27983	* Create the schema construction context.
27984	*/
27985	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27986	if (pctxt->constructor == NULL)
27987	    return(-1);
27988	pctxt->constructor->mainSchema = vctxt->schema;
27989	/*
27990	* Take ownership of the constructor to be able to free it.
27991	*/
27992	pctxt->ownsConstructor = 1;
27993    }
27994    /*
27995    * Augment the IDC definitions for the main schema and all imported ones
27996    * NOTE: main schema if the first in the imported list
27997    */
27998    xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
27999
28000    return(0);
28001}
28002
28003static void
28004xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28005    if (vctxt->xsiAssemble) {
28006	if (vctxt->schema != NULL) {
28007	    xmlSchemaFree(vctxt->schema);
28008	    vctxt->schema = NULL;
28009	}
28010    }
28011    xmlSchemaClearValidCtxt(vctxt);
28012}
28013
28014static int
28015xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28016{
28017    int ret = 0;
28018
28019    if (xmlSchemaPreRun(vctxt) < 0)
28020        return(-1);
28021
28022    if (vctxt->doc != NULL) {
28023	/*
28024	 * Tree validation.
28025	 */
28026	ret = xmlSchemaVDocWalk(vctxt);
28027#ifdef LIBXML_READER_ENABLED
28028    } else if (vctxt->reader != NULL) {
28029	/*
28030	 * XML Reader validation.
28031	 */
28032#ifdef XML_SCHEMA_READER_ENABLED
28033	ret = xmlSchemaVReaderWalk(vctxt);
28034#endif
28035#endif
28036    } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28037	/*
28038	 * SAX validation.
28039	 */
28040	ret = xmlParseDocument(vctxt->parserCtxt);
28041    } else {
28042	VERROR_INT("xmlSchemaVStart",
28043	    "no instance to validate");
28044	ret = -1;
28045    }
28046
28047    xmlSchemaPostRun(vctxt);
28048    if (ret == 0)
28049	ret = vctxt->err;
28050    return (ret);
28051}
28052
28053/**
28054 * xmlSchemaValidateOneElement:
28055 * @ctxt:  a schema validation context
28056 * @elem:  an element node
28057 *
28058 * Validate a branch of a tree, starting with the given @elem.
28059 *
28060 * Returns 0 if the element and its subtree is valid, a positive error
28061 * code number otherwise and -1 in case of an internal or API error.
28062 */
28063int
28064xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28065{
28066    if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28067	return (-1);
28068
28069    if (ctxt->schema == NULL)
28070	return (-1);
28071
28072    ctxt->doc = elem->doc;
28073    ctxt->node = elem;
28074    ctxt->validationRoot = elem;
28075    return(xmlSchemaVStart(ctxt));
28076}
28077
28078/**
28079 * xmlSchemaValidateDoc:
28080 * @ctxt:  a schema validation context
28081 * @doc:  a parsed document tree
28082 *
28083 * Validate a document tree in memory.
28084 *
28085 * Returns 0 if the document is schemas valid, a positive error code
28086 *     number otherwise and -1 in case of internal or API error.
28087 */
28088int
28089xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28090{
28091    if ((ctxt == NULL) || (doc == NULL))
28092        return (-1);
28093
28094    ctxt->doc = doc;
28095    ctxt->node = xmlDocGetRootElement(doc);
28096    if (ctxt->node == NULL) {
28097        xmlSchemaCustomErr(ACTXT_CAST ctxt,
28098	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28099	    (xmlNodePtr) doc, NULL,
28100	    "The document has no document element", NULL, NULL);
28101        return (ctxt->err);
28102    }
28103    ctxt->validationRoot = ctxt->node;
28104    return (xmlSchemaVStart(ctxt));
28105}
28106
28107
28108/************************************************************************
28109 * 									*
28110 * 		Function and data for SAX streaming API			*
28111 * 									*
28112 ************************************************************************/
28113typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28114typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28115
28116struct _xmlSchemaSplitSAXData {
28117    xmlSAXHandlerPtr      user_sax;
28118    void                 *user_data;
28119    xmlSchemaValidCtxtPtr ctxt;
28120    xmlSAXHandlerPtr      schemas_sax;
28121};
28122
28123#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28124
28125struct _xmlSchemaSAXPlug {
28126    unsigned int magic;
28127
28128    /* the original callbacks informations */
28129    xmlSAXHandlerPtr     *user_sax_ptr;
28130    xmlSAXHandlerPtr      user_sax;
28131    void                **user_data_ptr;
28132    void                 *user_data;
28133
28134    /* the block plugged back and validation informations */
28135    xmlSAXHandler         schemas_sax;
28136    xmlSchemaValidCtxtPtr ctxt;
28137};
28138
28139/* All those functions just bounces to the user provided SAX handlers */
28140static void
28141internalSubsetSplit(void *ctx, const xmlChar *name,
28142	       const xmlChar *ExternalID, const xmlChar *SystemID)
28143{
28144    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28145    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28146        (ctxt->user_sax->internalSubset != NULL))
28147	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28148	                               SystemID);
28149}
28150
28151static int
28152isStandaloneSplit(void *ctx)
28153{
28154    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28155    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28156        (ctxt->user_sax->isStandalone != NULL))
28157	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28158    return(0);
28159}
28160
28161static int
28162hasInternalSubsetSplit(void *ctx)
28163{
28164    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28165    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28166        (ctxt->user_sax->hasInternalSubset != NULL))
28167	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28168    return(0);
28169}
28170
28171static int
28172hasExternalSubsetSplit(void *ctx)
28173{
28174    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28175    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28176        (ctxt->user_sax->hasExternalSubset != NULL))
28177	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28178    return(0);
28179}
28180
28181static void
28182externalSubsetSplit(void *ctx, const xmlChar *name,
28183	       const xmlChar *ExternalID, const xmlChar *SystemID)
28184{
28185    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28186    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28187        (ctxt->user_sax->externalSubset != NULL))
28188	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28189	                               SystemID);
28190}
28191
28192static xmlParserInputPtr
28193resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28194{
28195    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28196    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28197        (ctxt->user_sax->resolveEntity != NULL))
28198	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28199	                                     systemId));
28200    return(NULL);
28201}
28202
28203static xmlEntityPtr
28204getEntitySplit(void *ctx, const xmlChar *name)
28205{
28206    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28207    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28208        (ctxt->user_sax->getEntity != NULL))
28209	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28210    return(NULL);
28211}
28212
28213static xmlEntityPtr
28214getParameterEntitySplit(void *ctx, const xmlChar *name)
28215{
28216    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28217    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28218        (ctxt->user_sax->getParameterEntity != NULL))
28219	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28220    return(NULL);
28221}
28222
28223
28224static void
28225entityDeclSplit(void *ctx, const xmlChar *name, int type,
28226          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28227{
28228    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28229    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28230        (ctxt->user_sax->entityDecl != NULL))
28231	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28232	                           systemId, content);
28233}
28234
28235static void
28236attributeDeclSplit(void *ctx, const xmlChar * elem,
28237                   const xmlChar * name, int type, int def,
28238                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
28239{
28240    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28241    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28242        (ctxt->user_sax->attributeDecl != NULL)) {
28243	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28244	                              def, defaultValue, tree);
28245    } else {
28246	xmlFreeEnumeration(tree);
28247    }
28248}
28249
28250static void
28251elementDeclSplit(void *ctx, const xmlChar *name, int type,
28252	    xmlElementContentPtr content)
28253{
28254    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28255    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28256        (ctxt->user_sax->elementDecl != NULL))
28257	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28258}
28259
28260static void
28261notationDeclSplit(void *ctx, const xmlChar *name,
28262	     const xmlChar *publicId, const xmlChar *systemId)
28263{
28264    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28265    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28266        (ctxt->user_sax->notationDecl != NULL))
28267	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28268	                             systemId);
28269}
28270
28271static void
28272unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28273		   const xmlChar *publicId, const xmlChar *systemId,
28274		   const xmlChar *notationName)
28275{
28276    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28277    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28278        (ctxt->user_sax->unparsedEntityDecl != NULL))
28279	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28280	                                   systemId, notationName);
28281}
28282
28283static void
28284setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28285{
28286    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28287    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28288        (ctxt->user_sax->setDocumentLocator != NULL))
28289	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28290}
28291
28292static void
28293startDocumentSplit(void *ctx)
28294{
28295    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28296    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28297        (ctxt->user_sax->startDocument != NULL))
28298	ctxt->user_sax->startDocument(ctxt->user_data);
28299}
28300
28301static void
28302endDocumentSplit(void *ctx)
28303{
28304    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28305    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28306        (ctxt->user_sax->endDocument != NULL))
28307	ctxt->user_sax->endDocument(ctxt->user_data);
28308}
28309
28310static void
28311processingInstructionSplit(void *ctx, const xmlChar *target,
28312                      const xmlChar *data)
28313{
28314    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28315    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28316        (ctxt->user_sax->processingInstruction != NULL))
28317	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28318}
28319
28320static void
28321commentSplit(void *ctx, const xmlChar *value)
28322{
28323    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28324    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28325        (ctxt->user_sax->comment != NULL))
28326	ctxt->user_sax->comment(ctxt->user_data, value);
28327}
28328
28329/*
28330 * Varargs error callbacks to the user application, harder ...
28331 */
28332
28333static void XMLCDECL
28334warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28335    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28336    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28337        (ctxt->user_sax->warning != NULL)) {
28338	TODO
28339    }
28340}
28341static void XMLCDECL
28342errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28343    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28344    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28345        (ctxt->user_sax->error != NULL)) {
28346	TODO
28347    }
28348}
28349static void XMLCDECL
28350fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28351    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28352    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28353        (ctxt->user_sax->fatalError != NULL)) {
28354	TODO
28355    }
28356}
28357
28358/*
28359 * Those are function where both the user handler and the schemas handler
28360 * need to be called.
28361 */
28362static void
28363charactersSplit(void *ctx, const xmlChar *ch, int len)
28364{
28365    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28366    if (ctxt == NULL)
28367        return;
28368    if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28369	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28370    if (ctxt->ctxt != NULL)
28371	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28372}
28373
28374static void
28375ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28376{
28377    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28378    if (ctxt == NULL)
28379        return;
28380    if ((ctxt->user_sax != NULL) &&
28381        (ctxt->user_sax->ignorableWhitespace != NULL))
28382	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28383    if (ctxt->ctxt != NULL)
28384	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28385}
28386
28387static void
28388cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28389{
28390    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28391    if (ctxt == NULL)
28392        return;
28393    if ((ctxt->user_sax != NULL) &&
28394        (ctxt->user_sax->cdataBlock != NULL))
28395	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28396    if (ctxt->ctxt != NULL)
28397	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28398}
28399
28400static void
28401referenceSplit(void *ctx, const xmlChar *name)
28402{
28403    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28404    if (ctxt == NULL)
28405        return;
28406    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28407        (ctxt->user_sax->reference != NULL))
28408	ctxt->user_sax->reference(ctxt->user_data, name);
28409    if (ctxt->ctxt != NULL)
28410        xmlSchemaSAXHandleReference(ctxt->user_data, name);
28411}
28412
28413static void
28414startElementNsSplit(void *ctx, const xmlChar * localname,
28415		    const xmlChar * prefix, const xmlChar * URI,
28416		    int nb_namespaces, const xmlChar ** namespaces,
28417		    int nb_attributes, int nb_defaulted,
28418		    const xmlChar ** attributes) {
28419    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28420    if (ctxt == NULL)
28421        return;
28422    if ((ctxt->user_sax != NULL) &&
28423        (ctxt->user_sax->startElementNs != NULL))
28424	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28425	                               URI, nb_namespaces, namespaces,
28426				       nb_attributes, nb_defaulted,
28427				       attributes);
28428    if (ctxt->ctxt != NULL)
28429	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28430	                                 URI, nb_namespaces, namespaces,
28431					 nb_attributes, nb_defaulted,
28432					 attributes);
28433}
28434
28435static void
28436endElementNsSplit(void *ctx, const xmlChar * localname,
28437		    const xmlChar * prefix, const xmlChar * URI) {
28438    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28439    if (ctxt == NULL)
28440        return;
28441    if ((ctxt->user_sax != NULL) &&
28442        (ctxt->user_sax->endElementNs != NULL))
28443	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28444    if (ctxt->ctxt != NULL)
28445	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28446}
28447
28448/**
28449 * xmlSchemaSAXPlug:
28450 * @ctxt:  a schema validation context
28451 * @sax:  a pointer to the original xmlSAXHandlerPtr
28452 * @user_data:  a pointer to the original SAX user data pointer
28453 *
28454 * Plug a SAX based validation layer in a SAX parsing event flow.
28455 * The original @saxptr and @dataptr data are replaced by new pointers
28456 * but the calls to the original will be maintained.
28457 *
28458 * Returns a pointer to a data structure needed to unplug the validation layer
28459 *         or NULL in case of errors.
28460 */
28461xmlSchemaSAXPlugPtr
28462xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28463		 xmlSAXHandlerPtr *sax, void **user_data)
28464{
28465    xmlSchemaSAXPlugPtr ret;
28466    xmlSAXHandlerPtr old_sax;
28467
28468    if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28469        return(NULL);
28470
28471    /*
28472     * We only allow to plug into SAX2 event streams
28473     */
28474    old_sax = *sax;
28475    if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28476        return(NULL);
28477    if ((old_sax != NULL) &&
28478        (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28479        ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28480        return(NULL);
28481
28482    /*
28483     * everything seems right allocate the local data needed for that layer
28484     */
28485    ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28486    if (ret == NULL) {
28487        return(NULL);
28488    }
28489    memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28490    ret->magic = XML_SAX_PLUG_MAGIC;
28491    ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28492    ret->ctxt = ctxt;
28493    ret->user_sax_ptr = sax;
28494    ret->user_sax = old_sax;
28495    if (old_sax == NULL) {
28496        /*
28497	 * go direct, no need for the split block and functions.
28498	 */
28499	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28500	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28501	/*
28502	 * Note that we use the same text-function for both, to prevent
28503	 * the parser from testing for ignorable whitespace.
28504	 */
28505	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28506	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28507
28508	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28509	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28510
28511	ret->user_data = ctxt;
28512	*user_data = ctxt;
28513    } else {
28514       /*
28515        * for each callback unused by Schemas initialize it to the Split
28516	* routine only if non NULL in the user block, this can speed up
28517	* things at the SAX level.
28518	*/
28519        if (old_sax->internalSubset != NULL)
28520            ret->schemas_sax.internalSubset = internalSubsetSplit;
28521        if (old_sax->isStandalone != NULL)
28522            ret->schemas_sax.isStandalone = isStandaloneSplit;
28523        if (old_sax->hasInternalSubset != NULL)
28524            ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28525        if (old_sax->hasExternalSubset != NULL)
28526            ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28527        if (old_sax->resolveEntity != NULL)
28528            ret->schemas_sax.resolveEntity = resolveEntitySplit;
28529        if (old_sax->getEntity != NULL)
28530            ret->schemas_sax.getEntity = getEntitySplit;
28531        if (old_sax->entityDecl != NULL)
28532            ret->schemas_sax.entityDecl = entityDeclSplit;
28533        if (old_sax->notationDecl != NULL)
28534            ret->schemas_sax.notationDecl = notationDeclSplit;
28535        if (old_sax->attributeDecl != NULL)
28536            ret->schemas_sax.attributeDecl = attributeDeclSplit;
28537        if (old_sax->elementDecl != NULL)
28538            ret->schemas_sax.elementDecl = elementDeclSplit;
28539        if (old_sax->unparsedEntityDecl != NULL)
28540            ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28541        if (old_sax->setDocumentLocator != NULL)
28542            ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28543        if (old_sax->startDocument != NULL)
28544            ret->schemas_sax.startDocument = startDocumentSplit;
28545        if (old_sax->endDocument != NULL)
28546            ret->schemas_sax.endDocument = endDocumentSplit;
28547        if (old_sax->processingInstruction != NULL)
28548            ret->schemas_sax.processingInstruction = processingInstructionSplit;
28549        if (old_sax->comment != NULL)
28550            ret->schemas_sax.comment = commentSplit;
28551        if (old_sax->warning != NULL)
28552            ret->schemas_sax.warning = warningSplit;
28553        if (old_sax->error != NULL)
28554            ret->schemas_sax.error = errorSplit;
28555        if (old_sax->fatalError != NULL)
28556            ret->schemas_sax.fatalError = fatalErrorSplit;
28557        if (old_sax->getParameterEntity != NULL)
28558            ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28559        if (old_sax->externalSubset != NULL)
28560            ret->schemas_sax.externalSubset = externalSubsetSplit;
28561
28562	/*
28563	 * the 6 schemas callback have to go to the splitter functions
28564	 * Note that we use the same text-function for ignorableWhitespace
28565	 * if possible, to prevent the parser from testing for ignorable
28566	 * whitespace.
28567	 */
28568        ret->schemas_sax.characters = charactersSplit;
28569	if ((old_sax->ignorableWhitespace != NULL) &&
28570	    (old_sax->ignorableWhitespace != old_sax->characters))
28571	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28572	else
28573	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28574        ret->schemas_sax.cdataBlock = cdataBlockSplit;
28575        ret->schemas_sax.reference = referenceSplit;
28576        ret->schemas_sax.startElementNs = startElementNsSplit;
28577        ret->schemas_sax.endElementNs = endElementNsSplit;
28578
28579	ret->user_data_ptr = user_data;
28580	ret->user_data = *user_data;
28581	*user_data = ret;
28582    }
28583
28584    /*
28585     * plug the pointers back.
28586     */
28587    *sax = &(ret->schemas_sax);
28588    ctxt->sax = *sax;
28589    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28590    xmlSchemaPreRun(ctxt);
28591    return(ret);
28592}
28593
28594/**
28595 * xmlSchemaSAXUnplug:
28596 * @plug:  a data structure returned by xmlSchemaSAXPlug
28597 *
28598 * Unplug a SAX based validation layer in a SAX parsing event flow.
28599 * The original pointers used in the call are restored.
28600 *
28601 * Returns 0 in case of success and -1 in case of failure.
28602 */
28603int
28604xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28605{
28606    xmlSAXHandlerPtr *sax;
28607    void **user_data;
28608
28609    if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28610        return(-1);
28611    plug->magic = 0;
28612
28613    xmlSchemaPostRun(plug->ctxt);
28614    /* restore the data */
28615    sax = plug->user_sax_ptr;
28616    *sax = plug->user_sax;
28617    if (plug->user_sax != NULL) {
28618	user_data = plug->user_data_ptr;
28619	*user_data = plug->user_data;
28620    }
28621
28622    /* free and return */
28623    xmlFree(plug);
28624    return(0);
28625}
28626
28627/**
28628 * xmlSchemaValidateStream:
28629 * @ctxt:  a schema validation context
28630 * @input:  the input to use for reading the data
28631 * @enc:  an optional encoding information
28632 * @sax:  a SAX handler for the resulting events
28633 * @user_data:  the context to provide to the SAX handler.
28634 *
28635 * Validate an input based on a flow of SAX event from the parser
28636 * and forward the events to the @sax handler with the provided @user_data
28637 * the user provided @sax handler must be a SAX2 one.
28638 *
28639 * Returns 0 if the document is schemas valid, a positive error code
28640 *     number otherwise and -1 in case of internal or API error.
28641 */
28642int
28643xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28644                        xmlParserInputBufferPtr input, xmlCharEncoding enc,
28645                        xmlSAXHandlerPtr sax, void *user_data)
28646{
28647    xmlSchemaSAXPlugPtr plug = NULL;
28648    xmlSAXHandlerPtr old_sax = NULL;
28649    xmlParserCtxtPtr pctxt = NULL;
28650    xmlParserInputPtr inputStream = NULL;
28651    int ret;
28652
28653    if ((ctxt == NULL) || (input == NULL))
28654        return (-1);
28655
28656    /*
28657     * prepare the parser
28658     */
28659    pctxt = xmlNewParserCtxt();
28660    if (pctxt == NULL)
28661        return (-1);
28662    old_sax = pctxt->sax;
28663    pctxt->sax = sax;
28664    pctxt->userData = user_data;
28665#if 0
28666    if (options)
28667        xmlCtxtUseOptions(pctxt, options);
28668#endif
28669    pctxt->linenumbers = 1;
28670
28671    inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28672    if (inputStream == NULL) {
28673        ret = -1;
28674	goto done;
28675    }
28676    inputPush(pctxt, inputStream);
28677    ctxt->parserCtxt = pctxt;
28678    ctxt->input = input;
28679
28680    /*
28681     * Plug the validation and launch the parsing
28682     */
28683    plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28684    if (plug == NULL) {
28685        ret = -1;
28686	goto done;
28687    }
28688    ctxt->input = input;
28689    ctxt->enc = enc;
28690    ctxt->sax = pctxt->sax;
28691    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28692    ret = xmlSchemaVStart(ctxt);
28693
28694    if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28695	ret = ctxt->parserCtxt->errNo;
28696	if (ret == 0)
28697	    ret = 1;
28698    }
28699
28700done:
28701    ctxt->parserCtxt = NULL;
28702    ctxt->sax = NULL;
28703    ctxt->input = NULL;
28704    if (plug != NULL) {
28705        xmlSchemaSAXUnplug(plug);
28706    }
28707    /* cleanup */
28708    if (pctxt != NULL) {
28709	pctxt->sax = old_sax;
28710	xmlFreeParserCtxt(pctxt);
28711    }
28712    return (ret);
28713}
28714
28715/**
28716 * xmlSchemaValidateFile:
28717 * @ctxt: a schema validation context
28718 * @filename: the URI of the instance
28719 * @options: a future set of options, currently unused
28720 *
28721 * Do a schemas validation of the given resource, it will use the
28722 * SAX streamable validation internally.
28723 *
28724 * Returns 0 if the document is valid, a positive error code
28725 *     number otherwise and -1 in case of an internal or API error.
28726 */
28727int
28728xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28729                      const char * filename,
28730		      int options ATTRIBUTE_UNUSED)
28731{
28732    int ret;
28733    xmlParserInputBufferPtr input;
28734
28735    if ((ctxt == NULL) || (filename == NULL))
28736        return (-1);
28737
28738    input = xmlParserInputBufferCreateFilename(filename,
28739	XML_CHAR_ENCODING_NONE);
28740    if (input == NULL)
28741	return (-1);
28742    ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28743	NULL, NULL);
28744    return (ret);
28745}
28746
28747/**
28748 * xmlSchemaValidCtxtGetParserCtxt:
28749 * @ctxt: a schema validation context
28750 *
28751 * allow access to the parser context of the schema validation context
28752 *
28753 * Returns the parser context of the schema validation context or NULL
28754 *         in case of error.
28755 */
28756xmlParserCtxtPtr
28757xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28758{
28759    if (ctxt == NULL)
28760        return(NULL);
28761    return (ctxt->parserCtxt);
28762}
28763
28764#define bottom_xmlschemas
28765#include "elfgcchack.h"
28766#endif /* LIBXML_SCHEMAS_ENABLED */
28767