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#ifdef DEBUG_IDC
88 #ifndef DEBUG_IDC_NODE_TABLE
89  #define DEBUG_IDC_NODE_TABLE
90 #endif
91#endif
92
93/* #define ENABLE_PARTICLE_RESTRICTION 1 */
94
95#define ENABLE_REDEFINE
96
97/* #define ENABLE_NAMED_LOCALS */
98
99/* #define ENABLE_IDC_NODE_TABLES_TEST */
100
101#define DUMP_CONTENT_MODEL
102
103#ifdef LIBXML_READER_ENABLED
104/* #define XML_SCHEMA_READER_ENABLED */
105#endif
106
107#define UNBOUNDED (1 << 30)
108#define TODO 								\
109    xmlGenericError(xmlGenericErrorContext,				\
110	    "Unimplemented block at %s:%d\n",				\
111            __FILE__, __LINE__);
112
113#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
114
115/*
116 * The XML Schemas namespaces
117 */
118static const xmlChar *xmlSchemaNs = (const xmlChar *)
119    "http://www.w3.org/2001/XMLSchema";
120
121static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
122    "http://www.w3.org/2001/XMLSchema-instance";
123
124static const xmlChar *xmlNamespaceNs = (const xmlChar *)
125    "http://www.w3.org/2000/xmlns/";
126
127/*
128* Come casting macros.
129*/
130#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
131#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
132#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
133#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
134#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
135#define WXS_PTC_CAST (xmlSchemaParticlePtr)
136#define WXS_TYPE_CAST (xmlSchemaTypePtr)
137#define WXS_ELEM_CAST (xmlSchemaElementPtr)
138#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
139#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
140#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
141#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
142#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
143#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
144#define WXS_IDC_CAST (xmlSchemaIDCPtr)
145#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
146#define WXS_LIST_CAST (xmlSchemaItemListPtr)
147
148/*
149* Macros to query common properties of components.
150*/
151#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
152
153#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
154/*
155* Macros for element declarations.
156*/
157#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
158
159#define WXS_SUBST_HEAD(item) (item)->refDecl
160/*
161* Macros for attribute declarations.
162*/
163#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
164/*
165* Macros for attribute uses.
166*/
167#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
168
169#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
170
171#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
172
173#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
174/*
175* Macros for attribute groups.
176*/
177#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
178#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
179/*
180* Macros for particles.
181*/
182#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
183
184#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
185
186#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
187/*
188* Macros for model groups definitions.
189*/
190#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
191/*
192* Macros for model groups.
193*/
194#define WXS_IS_MODEL_GROUP(i) \
195    (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
196     ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
197     ((i)->type == XML_SCHEMA_TYPE_ALL))
198
199#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
200/*
201* Macros for schema buckets.
202*/
203#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
204    ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
205
206#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
207    ((t) == XML_SCHEMA_SCHEMA_IMPORT))
208
209#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
210
211#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
212/*
213* Macros for complex/simple types.
214*/
215#define WXS_IS_ANYTYPE(i) \
216     (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
217      ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
218
219#define WXS_IS_COMPLEX(i) \
220    (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
221     ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
222
223#define WXS_IS_SIMPLE(item) \
224    ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
225     ((item->type == XML_SCHEMA_TYPE_BASIC) && \
226      (item->builtInType != XML_SCHEMAS_ANYTYPE)))
227
228#define WXS_IS_ANY_SIMPLE_TYPE(i) \
229    (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
230      ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
231
232#define WXS_IS_RESTRICTION(t) \
233    ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
234
235#define WXS_IS_EXTENSION(t) \
236    ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
237
238#define WXS_IS_TYPE_NOT_FIXED(i) \
239    (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
240     (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
241
242#define WXS_IS_TYPE_NOT_FIXED_1(item) \
243    (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
244     (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
245/*
246* Macros for exclusively for complex types.
247*/
248#define WXS_HAS_COMPLEX_CONTENT(item) \
249    ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
250     (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
251     (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
252
253#define WXS_HAS_SIMPLE_CONTENT(item) \
254    ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
255     (item->contentType == XML_SCHEMA_CONTENT_BASIC))
256
257#define WXS_HAS_MIXED_CONTENT(item) \
258    (item->contentType == XML_SCHEMA_CONTENT_MIXED)
259
260#define WXS_EMPTIABLE(t) \
261    (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
262
263#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
264
265#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
266
267#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
268/*
269* Macros for exclusively for simple types.
270*/
271#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
272
273#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
274
275#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
276
277#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
278/*
279* Misc parser context macros.
280*/
281#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
282
283#define WXS_HAS_BUCKETS(ctx) \
284( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
285(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
286
287#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
288
289#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
290
291#define WXS_SCHEMA(ctx) (ctx)->schema
292
293#define WXS_ADD_LOCAL(ctx, item) \
294    xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
295
296#define WXS_ADD_GLOBAL(ctx, item) \
297    xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
298
299#define WXS_ADD_PENDING(ctx, item) \
300    xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
301/*
302* xmlSchemaItemList macros.
303*/
304#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
305/*
306* Misc macros.
307*/
308#define IS_SCHEMA(node, type) \
309   ((node != NULL) && (node->ns != NULL) && \
310    (xmlStrEqual(node->name, (const xmlChar *) type)) && \
311    (xmlStrEqual(node->ns->href, xmlSchemaNs)))
312
313#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
314
315/*
316* Since we put the default/fixed values into the dict, we can
317* use pointer comparison for those values.
318* REMOVED: (xmlStrEqual((v1), (v2)))
319*/
320#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
321
322#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
323
324#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
325
326#define HFAILURE if (res == -1) goto exit_failure;
327
328#define HERROR if (res != 0) goto exit_error;
329
330#define HSTOP(ctx) if ((ctx)->stop) goto exit;
331/*
332* Some flags used for various schema constraints.
333*/
334#define SUBSET_RESTRICTION  1<<0
335#define SUBSET_EXTENSION    1<<1
336#define SUBSET_SUBSTITUTION 1<<2
337#define SUBSET_LIST         1<<3
338#define SUBSET_UNION        1<<4
339
340typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
341typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
342
343typedef struct _xmlSchemaItemList xmlSchemaItemList;
344typedef xmlSchemaItemList *xmlSchemaItemListPtr;
345struct _xmlSchemaItemList {
346    void **items;  /* used for dynamic addition of schemata */
347    int nbItems; /* used for dynamic addition of schemata */
348    int sizeItems; /* used for dynamic addition of schemata */
349};
350
351#define XML_SCHEMA_CTXT_PARSER 1
352#define XML_SCHEMA_CTXT_VALIDATOR 2
353
354typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
355typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
356struct _xmlSchemaAbstractCtxt {
357    int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
358};
359
360typedef struct _xmlSchemaBucket xmlSchemaBucket;
361typedef xmlSchemaBucket *xmlSchemaBucketPtr;
362
363#define XML_SCHEMA_SCHEMA_MAIN 0
364#define XML_SCHEMA_SCHEMA_IMPORT 1
365#define XML_SCHEMA_SCHEMA_INCLUDE 2
366#define XML_SCHEMA_SCHEMA_REDEFINE 3
367
368/**
369 * xmlSchemaSchemaRelation:
370 *
371 * Used to create a graph of schema relationships.
372 */
373typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
374typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
375struct _xmlSchemaSchemaRelation {
376    xmlSchemaSchemaRelationPtr next;
377    int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
378    const xmlChar *importNamespace;
379    xmlSchemaBucketPtr bucket;
380};
381
382#define XML_SCHEMA_BUCKET_MARKED 1<<0
383#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
384
385struct _xmlSchemaBucket {
386    int type;
387    int flags;
388    const xmlChar *schemaLocation;
389    const xmlChar *origTargetNamespace;
390    const xmlChar *targetNamespace;
391    xmlDocPtr doc;
392    xmlSchemaSchemaRelationPtr relations;
393    int located;
394    int parsed;
395    int imported;
396    int preserveDoc;
397    xmlSchemaItemListPtr globals; /* Global components. */
398    xmlSchemaItemListPtr locals; /* Local components. */
399};
400
401/**
402 * xmlSchemaImport:
403 * (extends xmlSchemaBucket)
404 *
405 * Reflects a schema. Holds some information
406 * about the schema and its toplevel components. Duplicate
407 * toplevel components are not checked at this level.
408 */
409typedef struct _xmlSchemaImport xmlSchemaImport;
410typedef xmlSchemaImport *xmlSchemaImportPtr;
411struct _xmlSchemaImport {
412    int type; /* Main OR import OR include. */
413    int flags;
414    const xmlChar *schemaLocation; /* The URI of the schema document. */
415    /* For chameleon includes, @origTargetNamespace will be NULL */
416    const xmlChar *origTargetNamespace;
417    /*
418    * For chameleon includes, @targetNamespace will be the
419    * targetNamespace of the including schema.
420    */
421    const xmlChar *targetNamespace;
422    xmlDocPtr doc; /* The schema node-tree. */
423    /* @relations will hold any included/imported/redefined schemas. */
424    xmlSchemaSchemaRelationPtr relations;
425    int located;
426    int parsed;
427    int imported;
428    int preserveDoc;
429    xmlSchemaItemListPtr globals;
430    xmlSchemaItemListPtr locals;
431    /* The imported schema. */
432    xmlSchemaPtr schema;
433};
434
435/*
436* (extends xmlSchemaBucket)
437*/
438typedef struct _xmlSchemaInclude xmlSchemaInclude;
439typedef xmlSchemaInclude *xmlSchemaIncludePtr;
440struct _xmlSchemaInclude {
441    int type;
442    int flags;
443    const xmlChar *schemaLocation;
444    const xmlChar *origTargetNamespace;
445    const xmlChar *targetNamespace;
446    xmlDocPtr doc;
447    xmlSchemaSchemaRelationPtr relations;
448    int located;
449    int parsed;
450    int imported;
451    int preserveDoc;
452    xmlSchemaItemListPtr globals; /* Global components. */
453    xmlSchemaItemListPtr locals; /* Local components. */
454
455    /* The owning main or import schema bucket. */
456    xmlSchemaImportPtr ownerImport;
457};
458
459/**
460 * xmlSchemaBasicItem:
461 *
462 * The abstract base type for schema components.
463 */
464typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
465typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
466struct _xmlSchemaBasicItem {
467    xmlSchemaTypeType type;
468};
469
470/**
471 * xmlSchemaAnnotItem:
472 *
473 * The abstract base type for annotated schema components.
474 * (Extends xmlSchemaBasicItem)
475 */
476typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
477typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
478struct _xmlSchemaAnnotItem {
479    xmlSchemaTypeType type;
480    xmlSchemaAnnotPtr annot;
481};
482
483/**
484 * xmlSchemaTreeItem:
485 *
486 * The abstract base type for tree-like structured schema components.
487 * (Extends xmlSchemaAnnotItem)
488 */
489typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
490typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
491struct _xmlSchemaTreeItem {
492    xmlSchemaTypeType type;
493    xmlSchemaAnnotPtr annot;
494    xmlSchemaTreeItemPtr next;
495    xmlSchemaTreeItemPtr children;
496};
497
498
499#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
500/**
501 * xmlSchemaAttributeUsePtr:
502 *
503 * The abstract base type for tree-like structured schema components.
504 * (Extends xmlSchemaTreeItem)
505 */
506typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
507typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
508struct _xmlSchemaAttributeUse {
509    xmlSchemaTypeType type;
510    xmlSchemaAnnotPtr annot;
511    xmlSchemaAttributeUsePtr next; /* The next attr. use. */
512    /*
513    * The attr. decl. OR a QName-ref. to an attr. decl. OR
514    * a QName-ref. to an attribute group definition.
515    */
516    xmlSchemaAttributePtr attrDecl;
517
518    int flags;
519    xmlNodePtr node;
520    int occurs; /* required, optional */
521    const xmlChar * defValue;
522    xmlSchemaValPtr defVal;
523};
524
525/**
526 * xmlSchemaAttributeUseProhibPtr:
527 *
528 * A helper component to reflect attribute prohibitions.
529 * (Extends xmlSchemaBasicItem)
530 */
531typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
532typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
533struct _xmlSchemaAttributeUseProhib {
534    xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
535    xmlNodePtr node;
536    const xmlChar *name;
537    const xmlChar *targetNamespace;
538    int isRef;
539};
540
541/**
542 * xmlSchemaRedef:
543 */
544typedef struct _xmlSchemaRedef xmlSchemaRedef;
545typedef xmlSchemaRedef *xmlSchemaRedefPtr;
546struct _xmlSchemaRedef {
547    xmlSchemaRedefPtr next;
548    xmlSchemaBasicItemPtr item; /* The redefining component. */
549    xmlSchemaBasicItemPtr reference; /* The referencing component. */
550    xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
551    const xmlChar *refName; /* The name of the to-be-redefined component. */
552    const xmlChar *refTargetNs; /* The target namespace of the
553                                   to-be-redefined comp. */
554    xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
555};
556
557/**
558 * xmlSchemaConstructionCtxt:
559 */
560typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
561typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
562struct _xmlSchemaConstructionCtxt {
563    xmlSchemaPtr mainSchema; /* The main schema. */
564    xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
565    xmlDictPtr dict;
566    xmlSchemaItemListPtr buckets; /* List of schema buckets. */
567    /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
568    xmlSchemaBucketPtr bucket; /* The current schema bucket */
569    xmlSchemaItemListPtr pending; /* All Components of all schemas that
570                                     need to be fixed. */
571    xmlHashTablePtr substGroups;
572    xmlSchemaRedefPtr redefs;
573    xmlSchemaRedefPtr lastRedef;
574};
575
576#define XML_SCHEMAS_PARSE_ERROR		1
577#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
578
579struct _xmlSchemaParserCtxt {
580    int type;
581    void *errCtxt;             /* user specific error context */
582    xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
583    xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
584    int err;
585    int nberrors;
586    xmlStructuredErrorFunc serror;
587
588    xmlSchemaConstructionCtxtPtr constructor;
589    int ownsConstructor; /* TODO: Move this to parser *flags*. */
590
591    /* xmlSchemaPtr topschema;	*/
592    /* xmlHashTablePtr namespaces;  */
593
594    xmlSchemaPtr schema;        /* The main schema in use */
595    int counter;
596
597    const xmlChar *URL;
598    xmlDocPtr doc;
599    int preserve;		/* Whether the doc should be freed  */
600
601    const char *buffer;
602    int size;
603
604    /*
605     * Used to build complex element content models
606     */
607    xmlAutomataPtr am;
608    xmlAutomataStatePtr start;
609    xmlAutomataStatePtr end;
610    xmlAutomataStatePtr state;
611
612    xmlDictPtr dict;		/* dictionnary for interned string names */
613    xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
614    int options;
615    xmlSchemaValidCtxtPtr vctxt;
616    int isS4S;
617    int isRedefine;
618    int xsiAssemble;
619    int stop; /* If the parser should stop; i.e. a critical error. */
620    const xmlChar *targetNamespace;
621    xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
622
623    xmlSchemaRedefPtr redef; /* Used for redefinitions. */
624    int redefCounter; /* Used for redefinitions. */
625    xmlSchemaItemListPtr attrProhibs;
626};
627
628/**
629 * xmlSchemaQNameRef:
630 *
631 * A component reference item (not a schema component)
632 * (Extends xmlSchemaBasicItem)
633 */
634typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
635typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
636struct _xmlSchemaQNameRef {
637    xmlSchemaTypeType type;
638    xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
639    xmlSchemaTypeType itemType;
640    const xmlChar *name;
641    const xmlChar *targetNamespace;
642    xmlNodePtr node;
643};
644
645/**
646 * xmlSchemaParticle:
647 *
648 * A particle component.
649 * (Extends xmlSchemaTreeItem)
650 */
651typedef struct _xmlSchemaParticle xmlSchemaParticle;
652typedef xmlSchemaParticle *xmlSchemaParticlePtr;
653struct _xmlSchemaParticle {
654    xmlSchemaTypeType type;
655    xmlSchemaAnnotPtr annot;
656    xmlSchemaTreeItemPtr next; /* next particle */
657    xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
658	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
659        etc.) */
660    int minOccurs;
661    int maxOccurs;
662    xmlNodePtr node;
663};
664
665/**
666 * xmlSchemaModelGroup:
667 *
668 * A model group component.
669 * (Extends xmlSchemaTreeItem)
670 */
671typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
672typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
673struct _xmlSchemaModelGroup {
674    xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
675    xmlSchemaAnnotPtr annot;
676    xmlSchemaTreeItemPtr next; /* not used */
677    xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
678    xmlNodePtr node;
679};
680
681#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
682#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
683/**
684 * xmlSchemaModelGroupDef:
685 *
686 * A model group definition component.
687 * (Extends xmlSchemaTreeItem)
688 */
689typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
690typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
691struct _xmlSchemaModelGroupDef {
692    xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
693    xmlSchemaAnnotPtr annot;
694    xmlSchemaTreeItemPtr next; /* not used */
695    xmlSchemaTreeItemPtr children; /* the "model group" */
696    const xmlChar *name;
697    const xmlChar *targetNamespace;
698    xmlNodePtr node;
699    int flags;
700};
701
702typedef struct _xmlSchemaIDC xmlSchemaIDC;
703typedef xmlSchemaIDC *xmlSchemaIDCPtr;
704
705/**
706 * xmlSchemaIDCSelect:
707 *
708 * The identity-constraint "field" and "selector" item, holding the
709 * XPath expression.
710 */
711typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
712typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
713struct _xmlSchemaIDCSelect {
714    xmlSchemaIDCSelectPtr next;
715    xmlSchemaIDCPtr idc;
716    int index; /* an index position if significant for IDC key-sequences */
717    const xmlChar *xpath; /* the XPath expression */
718    void *xpathComp; /* the compiled XPath expression */
719};
720
721/**
722 * xmlSchemaIDC:
723 *
724 * The identity-constraint definition component.
725 * (Extends xmlSchemaAnnotItem)
726 */
727
728struct _xmlSchemaIDC {
729    xmlSchemaTypeType type;
730    xmlSchemaAnnotPtr annot;
731    xmlSchemaIDCPtr next;
732    xmlNodePtr node;
733    const xmlChar *name;
734    const xmlChar *targetNamespace;
735    xmlSchemaIDCSelectPtr selector;
736    xmlSchemaIDCSelectPtr fields;
737    int nbFields;
738    xmlSchemaQNameRefPtr ref;
739};
740
741/**
742 * xmlSchemaIDCAug:
743 *
744 * The augmented IDC information used for validation.
745 */
746typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
747typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
748struct _xmlSchemaIDCAug {
749    xmlSchemaIDCAugPtr next; /* next in a list */
750    xmlSchemaIDCPtr def; /* the IDC definition */
751    int keyrefDepth; /* the lowest tree level to which IDC
752                        tables need to be bubbled upwards */
753};
754
755/**
756 * xmlSchemaPSVIIDCKeySequence:
757 *
758 * The key sequence of a node table item.
759 */
760typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
761typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
762struct _xmlSchemaPSVIIDCKey {
763    xmlSchemaTypePtr type;
764    xmlSchemaValPtr val;
765};
766
767/**
768 * xmlSchemaPSVIIDCNode:
769 *
770 * The node table item of a node table.
771 */
772typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
773typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
774struct _xmlSchemaPSVIIDCNode {
775    xmlNodePtr node;
776    xmlSchemaPSVIIDCKeyPtr *keys;
777    int nodeLine;
778    int nodeQNameID;
779
780};
781
782/**
783 * xmlSchemaPSVIIDCBinding:
784 *
785 * The identity-constraint binding item of the [identity-constraint table].
786 */
787typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
788typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
789struct _xmlSchemaPSVIIDCBinding {
790    xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
791    xmlSchemaIDCPtr definition; /* the IDC definition */
792    xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
793    int nbNodes; /* number of entries in the node table */
794    int sizeNodes; /* size of the node table */
795    xmlSchemaItemListPtr dupls;
796};
797
798
799#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
800#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
801
802#define XPATH_STATE_OBJ_MATCHES -2
803#define XPATH_STATE_OBJ_BLOCKED -3
804
805typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
806typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
807
808/**
809 * xmlSchemaIDCStateObj:
810 *
811 * The state object used to evaluate XPath expressions.
812 */
813typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
814typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
815struct _xmlSchemaIDCStateObj {
816    int type;
817    xmlSchemaIDCStateObjPtr next; /* next if in a list */
818    int depth; /* depth of creation */
819    int *history; /* list of (depth, state-id) tuples */
820    int nbHistory;
821    int sizeHistory;
822    xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
823                                       matcher */
824    xmlSchemaIDCSelectPtr sel;
825    void *xpathCtxt;
826};
827
828#define IDC_MATCHER 0
829
830/**
831 * xmlSchemaIDCMatcher:
832 *
833 * Used to evaluate IDC selectors (and fields).
834 */
835struct _xmlSchemaIDCMatcher {
836    int type;
837    int depth; /* the tree depth at creation time */
838    xmlSchemaIDCMatcherPtr next; /* next in the list */
839    xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
840    int idcType;
841    xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
842                                         elements */
843    int sizeKeySeqs;
844    int targetDepth;
845    xmlSchemaItemListPtr targets; /* list of target-node
846                                     (xmlSchemaPSVIIDCNodePtr) entries */
847};
848
849/*
850* Element info flags.
851*/
852#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
853#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
854#define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2
855#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3
856
857#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
858#define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
859#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
860
861#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
862#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
863#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
864#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
865
866/**
867 * xmlSchemaNodeInfo:
868 *
869 * Holds information of an element node.
870 */
871struct _xmlSchemaNodeInfo {
872    int nodeType;
873    xmlNodePtr node;
874    int nodeLine;
875    const xmlChar *localName;
876    const xmlChar *nsName;
877    const xmlChar *value;
878    xmlSchemaValPtr val; /* the pre-computed value if any */
879    xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
880
881    int flags; /* combination of node info flags */
882
883    int valNeeded;
884    int normVal;
885
886    xmlSchemaElementPtr decl; /* the element/attribute declaration */
887    int depth;
888    xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
889                                            for the scope element*/
890    xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
891                                           element */
892    xmlRegExecCtxtPtr regexCtxt;
893
894    const xmlChar **nsBindings; /* Namespace bindings on this element */
895    int nbNsBindings;
896    int sizeNsBindings;
897
898    int hasKeyrefs;
899    int appliedXPath; /* Indicates that an XPath has been applied. */
900};
901
902#define XML_SCHEMAS_ATTR_UNKNOWN 1
903#define XML_SCHEMAS_ATTR_ASSESSED 2
904#define XML_SCHEMAS_ATTR_PROHIBITED 3
905#define XML_SCHEMAS_ATTR_ERR_MISSING 4
906#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
907#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
908#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
909#define XML_SCHEMAS_ATTR_DEFAULT 8
910#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
911#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
912#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
913#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
914#define XML_SCHEMAS_ATTR_WILD_SKIP 13
915#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
916#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
917#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
918#define XML_SCHEMAS_ATTR_META 17
919/*
920* @metaType values of xmlSchemaAttrInfo.
921*/
922#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
923#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
924#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
925#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
926#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
927
928typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
929typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
930struct _xmlSchemaAttrInfo {
931    int nodeType;
932    xmlNodePtr node;
933    int nodeLine;
934    const xmlChar *localName;
935    const xmlChar *nsName;
936    const xmlChar *value;
937    xmlSchemaValPtr val; /* the pre-computed value if any */
938    xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
939    int flags; /* combination of node info flags */
940
941    xmlSchemaAttributePtr decl; /* the attribute declaration */
942    xmlSchemaAttributeUsePtr use;  /* the attribute use */
943    int state;
944    int metaType;
945    const xmlChar *vcValue; /* the value constraint value */
946    xmlSchemaNodeInfoPtr parent;
947};
948
949
950#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
951/**
952 * xmlSchemaValidCtxt:
953 *
954 * A Schemas validation context
955 */
956struct _xmlSchemaValidCtxt {
957    int type;
958    void *errCtxt;             /* user specific data block */
959    xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
960    xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
961    xmlStructuredErrorFunc serror;
962
963    xmlSchemaPtr schema;        /* The schema in use */
964    xmlDocPtr doc;
965    xmlParserInputBufferPtr input;
966    xmlCharEncoding enc;
967    xmlSAXHandlerPtr sax;
968    xmlParserCtxtPtr parserCtxt;
969    void *user_data; /* TODO: What is this for? */
970
971    int err;
972    int nberrors;
973
974    xmlNodePtr node;
975    xmlNodePtr cur;
976    /* xmlSchemaTypePtr type; */
977
978    xmlRegExecCtxtPtr regexp;
979    xmlSchemaValPtr value;
980
981    int valueWS;
982    int options;
983    xmlNodePtr validationRoot;
984    xmlSchemaParserCtxtPtr pctxt;
985    int xsiAssemble;
986
987    int depth;
988    xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
989    int sizeElemInfos;
990    xmlSchemaNodeInfoPtr inode; /* the current element information */
991
992    xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
993
994    xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
995    xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
996
997    xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
998    int nbIdcNodes;
999    int sizeIdcNodes;
1000
1001    xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1002    int nbIdcKeys;
1003    int sizeIdcKeys;
1004
1005    int flags;
1006
1007    xmlDictPtr dict;
1008
1009#ifdef LIBXML_READER_ENABLED
1010    xmlTextReaderPtr reader;
1011#endif
1012
1013    xmlSchemaAttrInfoPtr *attrInfos;
1014    int nbAttrInfos;
1015    int sizeAttrInfos;
1016
1017    int skipDepth;
1018    xmlSchemaItemListPtr nodeQNames;
1019    int hasKeyrefs;
1020    int createIDCNodeTables;
1021    int psviExposeIDCNodeTables;
1022};
1023
1024/**
1025 * xmlSchemaSubstGroup:
1026 *
1027 *
1028 */
1029typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1030typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1031struct _xmlSchemaSubstGroup {
1032    xmlSchemaElementPtr head;
1033    xmlSchemaItemListPtr members;
1034};
1035
1036/************************************************************************
1037 * 									*
1038 * 			Some predeclarations				*
1039 * 									*
1040 ************************************************************************/
1041
1042static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1043                                 xmlSchemaPtr schema,
1044                                 xmlNodePtr node);
1045static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1046                                 xmlSchemaPtr schema,
1047                                 xmlNodePtr node);
1048static int
1049xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1050                   xmlSchemaAbstractCtxtPtr ctxt);
1051static const xmlChar *
1052xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1053static int
1054xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1055                     xmlNodePtr node);
1056static int
1057xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1058                       xmlSchemaParserCtxtPtr ctxt);
1059static void
1060xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1061static xmlSchemaWhitespaceValueType
1062xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1063static xmlSchemaTreeItemPtr
1064xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1065			 xmlNodePtr node, xmlSchemaTypeType type,
1066			 int withParticle);
1067static const xmlChar *
1068xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1069static xmlSchemaTypeLinkPtr
1070xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1071static void
1072xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1073		     const char *funcName,
1074		     const char *message);
1075static int
1076xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1077			     xmlSchemaTypePtr type,
1078			     xmlSchemaTypePtr baseType,
1079			     int subset);
1080static void
1081xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1082				   xmlSchemaParserCtxtPtr ctxt);
1083static void
1084xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1085static xmlSchemaQNameRefPtr
1086xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1087				xmlSchemaPtr schema,
1088				xmlNodePtr node);
1089
1090/************************************************************************
1091 *									*
1092 * 			Helper functions			        *
1093 *									*
1094 ************************************************************************/
1095
1096/**
1097 * xmlSchemaItemTypeToStr:
1098 * @type: the type of the schema item
1099 *
1100 * Returns the component name of a schema item.
1101 */
1102static const xmlChar *
1103xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1104{
1105    switch (type) {
1106	case XML_SCHEMA_TYPE_BASIC:
1107	    return(BAD_CAST "simple type definition");
1108	case XML_SCHEMA_TYPE_SIMPLE:
1109	    return(BAD_CAST "simple type definition");
1110	case XML_SCHEMA_TYPE_COMPLEX:
1111	    return(BAD_CAST "complex type definition");
1112	case XML_SCHEMA_TYPE_ELEMENT:
1113	    return(BAD_CAST "element declaration");
1114	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1115	    return(BAD_CAST "attribute use");
1116	case XML_SCHEMA_TYPE_ATTRIBUTE:
1117	    return(BAD_CAST "attribute declaration");
1118	case XML_SCHEMA_TYPE_GROUP:
1119	    return(BAD_CAST "model group definition");
1120	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1121	    return(BAD_CAST "attribute group definition");
1122	case XML_SCHEMA_TYPE_NOTATION:
1123	    return(BAD_CAST "notation declaration");
1124	case XML_SCHEMA_TYPE_SEQUENCE:
1125	    return(BAD_CAST "model group (sequence)");
1126	case XML_SCHEMA_TYPE_CHOICE:
1127	    return(BAD_CAST "model group (choice)");
1128	case XML_SCHEMA_TYPE_ALL:
1129	    return(BAD_CAST "model group (all)");
1130	case XML_SCHEMA_TYPE_PARTICLE:
1131	    return(BAD_CAST "particle");
1132	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1133	    return(BAD_CAST "unique identity-constraint");
1134	    /* return(BAD_CAST "IDC (unique)"); */
1135	case XML_SCHEMA_TYPE_IDC_KEY:
1136	    return(BAD_CAST "key identity-constraint");
1137	    /* return(BAD_CAST "IDC (key)"); */
1138	case XML_SCHEMA_TYPE_IDC_KEYREF:
1139	    return(BAD_CAST "keyref identity-constraint");
1140	    /* return(BAD_CAST "IDC (keyref)"); */
1141	case XML_SCHEMA_TYPE_ANY:
1142	    return(BAD_CAST "wildcard (any)");
1143	case XML_SCHEMA_EXTRA_QNAMEREF:
1144	    return(BAD_CAST "[helper component] QName reference");
1145	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1146	    return(BAD_CAST "[helper component] attribute use prohibition");
1147	default:
1148	    return(BAD_CAST "Not a schema component");
1149    }
1150}
1151
1152/**
1153 * xmlSchemaGetComponentTypeStr:
1154 * @type: the type of the schema item
1155 *
1156 * Returns the component name of a schema item.
1157 */
1158static const xmlChar *
1159xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1160{
1161    switch (item->type) {
1162	case XML_SCHEMA_TYPE_BASIC:
1163	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1164		return(BAD_CAST "complex type definition");
1165	    else
1166		return(BAD_CAST "simple type definition");
1167	default:
1168	    return(xmlSchemaItemTypeToStr(item->type));
1169    }
1170}
1171
1172/**
1173 * xmlSchemaGetComponentNode:
1174 * @item: a schema component
1175 *
1176 * Returns node associated with the schema component.
1177 * NOTE that such a node need not be available; plus, a component's
1178 * node need not to reflect the component directly, since there is no
1179 * one-to-one relationship between the XML Schema representation and
1180 * the component representation.
1181 */
1182static xmlNodePtr
1183xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1184{
1185    switch (item->type) {
1186	case XML_SCHEMA_TYPE_ELEMENT:
1187	    return (((xmlSchemaElementPtr) item)->node);
1188	case XML_SCHEMA_TYPE_ATTRIBUTE:
1189	    return (((xmlSchemaAttributePtr) item)->node);
1190	case XML_SCHEMA_TYPE_COMPLEX:
1191	case XML_SCHEMA_TYPE_SIMPLE:
1192	    return (((xmlSchemaTypePtr) item)->node);
1193	case XML_SCHEMA_TYPE_ANY:
1194	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1195	    return (((xmlSchemaWildcardPtr) item)->node);
1196	case XML_SCHEMA_TYPE_PARTICLE:
1197	    return (((xmlSchemaParticlePtr) item)->node);
1198	case XML_SCHEMA_TYPE_SEQUENCE:
1199	case XML_SCHEMA_TYPE_CHOICE:
1200	case XML_SCHEMA_TYPE_ALL:
1201	    return (((xmlSchemaModelGroupPtr) item)->node);
1202	case XML_SCHEMA_TYPE_GROUP:
1203	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1204	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1205	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1206	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1207	case XML_SCHEMA_TYPE_IDC_KEY:
1208	case XML_SCHEMA_TYPE_IDC_KEYREF:
1209	    return (((xmlSchemaIDCPtr) item)->node);
1210	case XML_SCHEMA_EXTRA_QNAMEREF:
1211	    return(((xmlSchemaQNameRefPtr) item)->node);
1212	/* TODO: What to do with NOTATIONs?
1213	case XML_SCHEMA_TYPE_NOTATION:
1214	    return (((xmlSchemaNotationPtr) item)->node);
1215	*/
1216	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1217	    return (((xmlSchemaAttributeUsePtr) item)->node);
1218	default:
1219	    return (NULL);
1220    }
1221}
1222
1223#if 0
1224/**
1225 * xmlSchemaGetNextComponent:
1226 * @item: a schema component
1227 *
1228 * Returns the next sibling of the schema component.
1229 */
1230static xmlSchemaBasicItemPtr
1231xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1232{
1233    switch (item->type) {
1234	case XML_SCHEMA_TYPE_ELEMENT:
1235	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1236	case XML_SCHEMA_TYPE_ATTRIBUTE:
1237	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1238	case XML_SCHEMA_TYPE_COMPLEX:
1239	case XML_SCHEMA_TYPE_SIMPLE:
1240	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1241	case XML_SCHEMA_TYPE_ANY:
1242	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1243	    return (NULL);
1244	case XML_SCHEMA_TYPE_PARTICLE:
1245	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1246	case XML_SCHEMA_TYPE_SEQUENCE:
1247	case XML_SCHEMA_TYPE_CHOICE:
1248	case XML_SCHEMA_TYPE_ALL:
1249	    return (NULL);
1250	case XML_SCHEMA_TYPE_GROUP:
1251	    return (NULL);
1252	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1253	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1254	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1255	case XML_SCHEMA_TYPE_IDC_KEY:
1256	case XML_SCHEMA_TYPE_IDC_KEYREF:
1257	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1258	default:
1259	    return (NULL);
1260    }
1261}
1262#endif
1263
1264
1265/**
1266 * xmlSchemaFormatQName:
1267 * @buf: the string buffer
1268 * @namespaceName:  the namespace name
1269 * @localName: the local name
1270 *
1271 * Returns the given QName in the format "{namespaceName}localName" or
1272 * just "localName" if @namespaceName is NULL.
1273 *
1274 * Returns the localName if @namespaceName is NULL, a formatted
1275 * string otherwise.
1276 */
1277static const xmlChar*
1278xmlSchemaFormatQName(xmlChar **buf,
1279		     const xmlChar *namespaceName,
1280		     const xmlChar *localName)
1281{
1282    FREE_AND_NULL(*buf)
1283    if (namespaceName != NULL) {
1284	*buf = xmlStrdup(BAD_CAST "{");
1285	*buf = xmlStrcat(*buf, namespaceName);
1286	*buf = xmlStrcat(*buf, BAD_CAST "}");
1287    }
1288    if (localName != NULL) {
1289	if (namespaceName == NULL)
1290	    return(localName);
1291	*buf = xmlStrcat(*buf, localName);
1292    } else {
1293	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1294    }
1295    return ((const xmlChar *) *buf);
1296}
1297
1298static const xmlChar*
1299xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1300{
1301    if (ns != NULL)
1302	return (xmlSchemaFormatQName(buf, ns->href, localName));
1303    else
1304	return (xmlSchemaFormatQName(buf, NULL, localName));
1305}
1306
1307static const xmlChar *
1308xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1309{
1310    switch (item->type) {
1311	case XML_SCHEMA_TYPE_ELEMENT:
1312	    return (((xmlSchemaElementPtr) item)->name);
1313	case XML_SCHEMA_TYPE_ATTRIBUTE:
1314	    return (((xmlSchemaAttributePtr) item)->name);
1315	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1316	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1317	case XML_SCHEMA_TYPE_BASIC:
1318	case XML_SCHEMA_TYPE_SIMPLE:
1319	case XML_SCHEMA_TYPE_COMPLEX:
1320	    return (((xmlSchemaTypePtr) item)->name);
1321	case XML_SCHEMA_TYPE_GROUP:
1322	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1323	case XML_SCHEMA_TYPE_IDC_KEY:
1324	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1325	case XML_SCHEMA_TYPE_IDC_KEYREF:
1326	    return (((xmlSchemaIDCPtr) item)->name);
1327	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1328	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1329		return(xmlSchemaGetComponentName(
1330		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1331	    } else
1332		return(NULL);
1333	case XML_SCHEMA_EXTRA_QNAMEREF:
1334	    return (((xmlSchemaQNameRefPtr) item)->name);
1335	case XML_SCHEMA_TYPE_NOTATION:
1336	    return (((xmlSchemaNotationPtr) item)->name);
1337	default:
1338	    /*
1339	    * Other components cannot have names.
1340	    */
1341	    break;
1342    }
1343    return (NULL);
1344}
1345
1346#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1347#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1348/*
1349static const xmlChar *
1350xmlSchemaGetQNameRefName(void *ref)
1351{
1352    return(((xmlSchemaQNameRefPtr) ref)->name);
1353}
1354
1355static const xmlChar *
1356xmlSchemaGetQNameRefTargetNs(void *ref)
1357{
1358    return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1359}
1360*/
1361
1362static const xmlChar *
1363xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1364{
1365    switch (item->type) {
1366	case XML_SCHEMA_TYPE_ELEMENT:
1367	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1368	case XML_SCHEMA_TYPE_ATTRIBUTE:
1369	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1370	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1371	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1372	case XML_SCHEMA_TYPE_BASIC:
1373	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1374	case XML_SCHEMA_TYPE_SIMPLE:
1375	case XML_SCHEMA_TYPE_COMPLEX:
1376	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1377	case XML_SCHEMA_TYPE_GROUP:
1378	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1379	case XML_SCHEMA_TYPE_IDC_KEY:
1380	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1381	case XML_SCHEMA_TYPE_IDC_KEYREF:
1382	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1383	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1384	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1385		return(xmlSchemaGetComponentTargetNs(
1386		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1387	    }
1388	    /* TODO: Will returning NULL break something? */
1389	    break;
1390	case XML_SCHEMA_EXTRA_QNAMEREF:
1391	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1392	case XML_SCHEMA_TYPE_NOTATION:
1393	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1394	default:
1395	    /*
1396	    * Other components cannot have names.
1397	    */
1398	    break;
1399    }
1400    return (NULL);
1401}
1402
1403static const xmlChar*
1404xmlSchemaGetComponentQName(xmlChar **buf,
1405			   void *item)
1406{
1407    return (xmlSchemaFormatQName(buf,
1408	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1409	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1410}
1411
1412static const xmlChar*
1413xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1414{
1415    xmlChar *str = NULL;
1416
1417    *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1418    *buf = xmlStrcat(*buf, BAD_CAST " '");
1419    *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1420	(xmlSchemaBasicItemPtr) item));
1421    *buf = xmlStrcat(*buf, BAD_CAST "'");
1422    FREE_AND_NULL(str);
1423    return(*buf);
1424}
1425
1426static const xmlChar*
1427xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1428{
1429    return(xmlSchemaGetComponentDesignation(buf, idc));
1430}
1431
1432/**
1433 * xmlSchemaWildcardPCToString:
1434 * @pc: the type of processContents
1435 *
1436 * Returns a string representation of the type of
1437 * processContents.
1438 */
1439static const xmlChar *
1440xmlSchemaWildcardPCToString(int pc)
1441{
1442    switch (pc) {
1443	case XML_SCHEMAS_ANY_SKIP:
1444	    return (BAD_CAST "skip");
1445	case XML_SCHEMAS_ANY_LAX:
1446	    return (BAD_CAST "lax");
1447	case XML_SCHEMAS_ANY_STRICT:
1448	    return (BAD_CAST "strict");
1449	default:
1450	    return (BAD_CAST "invalid process contents");
1451    }
1452}
1453
1454/**
1455 * xmlSchemaGetCanonValueWhtspExt:
1456 * @val: the precomputed value
1457 * @retValue: the returned value
1458 * @ws: the whitespace type of the value
1459 *
1460 * Get a the cononical representation of the value.
1461 * The caller has to free the returned retValue.
1462 *
1463 * Returns 0 if the value could be built and -1 in case of
1464 *         API errors or if the value type is not supported yet.
1465 */
1466static int
1467xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1468			       xmlSchemaWhitespaceValueType ws,
1469			       xmlChar **retValue)
1470{
1471    int list;
1472    xmlSchemaValType valType;
1473    const xmlChar *value, *value2 = NULL;
1474
1475
1476    if ((retValue == NULL) || (val == NULL))
1477	return (-1);
1478    list = xmlSchemaValueGetNext(val) ? 1 : 0;
1479    *retValue = NULL;
1480    do {
1481	value = NULL;
1482	valType = xmlSchemaGetValType(val);
1483	switch (valType) {
1484	    case XML_SCHEMAS_STRING:
1485	    case XML_SCHEMAS_NORMSTRING:
1486	    case XML_SCHEMAS_ANYSIMPLETYPE:
1487		value = xmlSchemaValueGetAsString(val);
1488		if (value != NULL) {
1489		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1490			value2 = xmlSchemaCollapseString(value);
1491		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1492			value2 = xmlSchemaWhiteSpaceReplace(value);
1493		    if (value2 != NULL)
1494			value = value2;
1495		}
1496		break;
1497	    default:
1498		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1499		    if (value2 != NULL)
1500			xmlFree((xmlChar *) value2);
1501		    goto internal_error;
1502		}
1503		value = value2;
1504	}
1505	if (*retValue == NULL)
1506	    if (value == NULL) {
1507		if (! list)
1508		    *retValue = xmlStrdup(BAD_CAST "");
1509	    } else
1510		*retValue = xmlStrdup(value);
1511	else if (value != NULL) {
1512	    /* List. */
1513	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1514	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1515	}
1516	FREE_AND_NULL(value2)
1517	val = xmlSchemaValueGetNext(val);
1518    } while (val != NULL);
1519
1520    return (0);
1521internal_error:
1522    if (*retValue != NULL)
1523	xmlFree((xmlChar *) (*retValue));
1524    if (value2 != NULL)
1525	xmlFree((xmlChar *) value2);
1526    return (-1);
1527}
1528
1529/**
1530 * xmlSchemaFormatItemForReport:
1531 * @buf: the string buffer
1532 * @itemDes: the designation of the item
1533 * @itemName: the name of the item
1534 * @item: the item as an object
1535 * @itemNode: the node of the item
1536 * @local: the local name
1537 * @parsing: if the function is used during the parse
1538 *
1539 * Returns a representation of the given item used
1540 * for error reports.
1541 *
1542 * The following order is used to build the resulting
1543 * designation if the arguments are not NULL:
1544 * 1a. If itemDes not NULL -> itemDes
1545 * 1b. If (itemDes not NULL) and (itemName not NULL)
1546 *     -> itemDes + itemName
1547 * 2. If the preceding was NULL and (item not NULL) -> item
1548 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1549 *
1550 * If the itemNode is an attribute node, the name of the attribute
1551 * will be appended to the result.
1552 *
1553 * Returns the formatted string and sets @buf to the resulting value.
1554 */
1555static xmlChar*
1556xmlSchemaFormatItemForReport(xmlChar **buf,
1557		     const xmlChar *itemDes,
1558		     xmlSchemaBasicItemPtr item,
1559		     xmlNodePtr itemNode)
1560{
1561    xmlChar *str = NULL;
1562    int named = 1;
1563
1564    if (*buf != NULL) {
1565	xmlFree(*buf);
1566	*buf = NULL;
1567    }
1568
1569    if (itemDes != NULL) {
1570	*buf = xmlStrdup(itemDes);
1571    } else if (item != NULL) {
1572	switch (item->type) {
1573	case XML_SCHEMA_TYPE_BASIC: {
1574	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1575
1576	    if (WXS_IS_ATOMIC(type))
1577		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1578	    else if (WXS_IS_LIST(type))
1579		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1580	    else if (WXS_IS_UNION(type))
1581		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1582	    else
1583		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1584	    *buf = xmlStrcat(*buf, type->name);
1585	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1586	    }
1587	    break;
1588	case XML_SCHEMA_TYPE_SIMPLE: {
1589	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1590
1591	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1592		*buf = xmlStrdup(BAD_CAST"");
1593	    } else {
1594		*buf = xmlStrdup(BAD_CAST "local ");
1595	    }
1596	    if (WXS_IS_ATOMIC(type))
1597		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1598	    else if (WXS_IS_LIST(type))
1599		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1600	    else if (WXS_IS_UNION(type))
1601		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1602	    else
1603		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1604	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1605		*buf = xmlStrcat(*buf, BAD_CAST " '");
1606		*buf = xmlStrcat(*buf, type->name);
1607		*buf = xmlStrcat(*buf, BAD_CAST "'");
1608	    }
1609	    }
1610	    break;
1611	case XML_SCHEMA_TYPE_COMPLEX: {
1612	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1613
1614	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1615		*buf = xmlStrdup(BAD_CAST "");
1616	    else
1617		*buf = xmlStrdup(BAD_CAST "local ");
1618	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1619	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1620		*buf = xmlStrcat(*buf, BAD_CAST " '");
1621		*buf = xmlStrcat(*buf, type->name);
1622		*buf = xmlStrcat(*buf, BAD_CAST "'");
1623	    }
1624	    }
1625	    break;
1626	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1627		xmlSchemaAttributeUsePtr ause;
1628
1629		ause = WXS_ATTR_USE_CAST item;
1630		*buf = xmlStrdup(BAD_CAST "attribute use ");
1631		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1632		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1633		    *buf = xmlStrcat(*buf,
1634			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1635		    FREE_AND_NULL(str)
1636			*buf = xmlStrcat(*buf, BAD_CAST "'");
1637		} else {
1638		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1639		}
1640	    }
1641	    break;
1642	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1643		xmlSchemaAttributePtr attr;
1644
1645		attr = (xmlSchemaAttributePtr) item;
1646		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1647		*buf = xmlStrcat(*buf, BAD_CAST " '");
1648		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1649		    attr->targetNamespace, attr->name));
1650		FREE_AND_NULL(str)
1651		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1652	    }
1653	    break;
1654	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1655	    xmlSchemaGetComponentDesignation(buf, item);
1656	    break;
1657	case XML_SCHEMA_TYPE_ELEMENT: {
1658		xmlSchemaElementPtr elem;
1659
1660		elem = (xmlSchemaElementPtr) item;
1661		*buf = xmlStrdup(BAD_CAST "element decl.");
1662		*buf = xmlStrcat(*buf, BAD_CAST " '");
1663		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1664		    elem->targetNamespace, elem->name));
1665		*buf = xmlStrcat(*buf, BAD_CAST "'");
1666	    }
1667	    break;
1668	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1669	case XML_SCHEMA_TYPE_IDC_KEY:
1670	case XML_SCHEMA_TYPE_IDC_KEYREF:
1671	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1672		*buf = xmlStrdup(BAD_CAST "unique '");
1673	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1674		*buf = xmlStrdup(BAD_CAST "key '");
1675	    else
1676		*buf = xmlStrdup(BAD_CAST "keyRef '");
1677	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1678	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1679	    break;
1680	case XML_SCHEMA_TYPE_ANY:
1681	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1682	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1683		    ((xmlSchemaWildcardPtr) item)->processContents));
1684	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1685	    break;
1686	case XML_SCHEMA_FACET_MININCLUSIVE:
1687	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1688	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1689	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1690	case XML_SCHEMA_FACET_TOTALDIGITS:
1691	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1692	case XML_SCHEMA_FACET_PATTERN:
1693	case XML_SCHEMA_FACET_ENUMERATION:
1694	case XML_SCHEMA_FACET_WHITESPACE:
1695	case XML_SCHEMA_FACET_LENGTH:
1696	case XML_SCHEMA_FACET_MAXLENGTH:
1697	case XML_SCHEMA_FACET_MINLENGTH:
1698	    *buf = xmlStrdup(BAD_CAST "facet '");
1699	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1700	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1701	    break;
1702	case XML_SCHEMA_TYPE_GROUP: {
1703		*buf = xmlStrdup(BAD_CAST "model group def.");
1704		*buf = xmlStrcat(*buf, BAD_CAST " '");
1705		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1706		*buf = xmlStrcat(*buf, BAD_CAST "'");
1707		FREE_AND_NULL(str)
1708	    }
1709	    break;
1710	case XML_SCHEMA_TYPE_SEQUENCE:
1711	case XML_SCHEMA_TYPE_CHOICE:
1712	case XML_SCHEMA_TYPE_ALL:
1713	case XML_SCHEMA_TYPE_PARTICLE:
1714	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1715	    break;
1716	case XML_SCHEMA_TYPE_NOTATION: {
1717		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1718		*buf = xmlStrcat(*buf, BAD_CAST " '");
1719		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1720		*buf = xmlStrcat(*buf, BAD_CAST "'");
1721		FREE_AND_NULL(str);
1722	    }
1723	default:
1724	    named = 0;
1725	}
1726    } else
1727	named = 0;
1728
1729    if ((named == 0) && (itemNode != NULL)) {
1730	xmlNodePtr elem;
1731
1732	if (itemNode->type == XML_ATTRIBUTE_NODE)
1733	    elem = itemNode->parent;
1734	else
1735	    elem = itemNode;
1736	*buf = xmlStrdup(BAD_CAST "Element '");
1737	if (elem->ns != NULL) {
1738	    *buf = xmlStrcat(*buf,
1739		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1740	    FREE_AND_NULL(str)
1741	} else
1742	    *buf = xmlStrcat(*buf, elem->name);
1743	*buf = xmlStrcat(*buf, BAD_CAST "'");
1744
1745    }
1746    if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1747	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1748	if (itemNode->ns != NULL) {
1749	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1750		itemNode->ns->href, itemNode->name));
1751	    FREE_AND_NULL(str)
1752	} else
1753	    *buf = xmlStrcat(*buf, itemNode->name);
1754	*buf = xmlStrcat(*buf, BAD_CAST "'");
1755    }
1756    FREE_AND_NULL(str)
1757
1758    return (*buf);
1759}
1760
1761/**
1762 * xmlSchemaFormatFacetEnumSet:
1763 * @buf: the string buffer
1764 * @type: the type holding the enumeration facets
1765 *
1766 * Builds a string consisting of all enumeration elements.
1767 *
1768 * Returns a string of all enumeration elements.
1769 */
1770static const xmlChar *
1771xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1772			    xmlChar **buf, xmlSchemaTypePtr type)
1773{
1774    xmlSchemaFacetPtr facet;
1775    xmlSchemaWhitespaceValueType ws;
1776    xmlChar *value = NULL;
1777    int res, found = 0;
1778
1779    if (*buf != NULL)
1780	xmlFree(*buf);
1781    *buf = NULL;
1782
1783    do {
1784	/*
1785	* Use the whitespace type of the base type.
1786	*/
1787	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1788	for (facet = type->facets; facet != NULL; facet = facet->next) {
1789	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1790		continue;
1791	    found = 1;
1792	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1793		ws, &value);
1794	    if (res == -1) {
1795		xmlSchemaInternalErr(actxt,
1796		    "xmlSchemaFormatFacetEnumSet",
1797		    "compute the canonical lexical representation");
1798		if (*buf != NULL)
1799		    xmlFree(*buf);
1800		*buf = NULL;
1801		return (NULL);
1802	    }
1803	    if (*buf == NULL)
1804		*buf = xmlStrdup(BAD_CAST "'");
1805	    else
1806		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1807	    *buf = xmlStrcat(*buf, BAD_CAST value);
1808	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1809	    if (value != NULL) {
1810		xmlFree((xmlChar *)value);
1811		value = NULL;
1812	    }
1813	}
1814	/*
1815	* The enumeration facet of a type restricts the enumeration
1816	* facet of the ancestor type; i.e., such restricted enumerations
1817	* do not belong to the set of the given type. Thus we break
1818	* on the first found enumeration.
1819	*/
1820	if (found)
1821	    break;
1822	type = type->baseType;
1823    } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1824
1825    return ((const xmlChar *) *buf);
1826}
1827
1828/************************************************************************
1829 *									*
1830 * 			Error functions				        *
1831 *									*
1832 ************************************************************************/
1833
1834#if 0
1835static void
1836xmlSchemaErrMemory(const char *msg)
1837{
1838    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1839                     msg);
1840}
1841#endif
1842
1843static void
1844xmlSchemaPSimpleErr(const char *msg)
1845{
1846    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1847                     msg);
1848}
1849
1850/**
1851 * xmlSchemaPErrMemory:
1852 * @node: a context node
1853 * @extra:  extra informations
1854 *
1855 * Handle an out of memory condition
1856 */
1857static void
1858xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1859                    const char *extra, xmlNodePtr node)
1860{
1861    if (ctxt != NULL)
1862        ctxt->nberrors++;
1863    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1864                     extra);
1865}
1866
1867/**
1868 * xmlSchemaPErr:
1869 * @ctxt: the parsing context
1870 * @node: the context node
1871 * @error: the error code
1872 * @msg: the error message
1873 * @str1: extra data
1874 * @str2: extra data
1875 *
1876 * Handle a parser error
1877 */
1878static void
1879xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1880              const char *msg, const xmlChar * str1, const xmlChar * str2)
1881{
1882    xmlGenericErrorFunc channel = NULL;
1883    xmlStructuredErrorFunc schannel = NULL;
1884    void *data = NULL;
1885
1886    if (ctxt != NULL) {
1887        ctxt->nberrors++;
1888	ctxt->err = error;
1889        channel = ctxt->error;
1890        data = ctxt->errCtxt;
1891	schannel = ctxt->serror;
1892    }
1893    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1894                    error, XML_ERR_ERROR, NULL, 0,
1895                    (const char *) str1, (const char *) str2, NULL, 0, 0,
1896                    msg, str1, str2);
1897}
1898
1899/**
1900 * xmlSchemaPErr2:
1901 * @ctxt: the parsing context
1902 * @node: the context node
1903 * @node: the current child
1904 * @error: the error code
1905 * @msg: the error message
1906 * @str1: extra data
1907 * @str2: extra data
1908 *
1909 * Handle a parser error
1910 */
1911static void
1912xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1913               xmlNodePtr child, int error,
1914               const char *msg, const xmlChar * str1, const xmlChar * str2)
1915{
1916    if (child != NULL)
1917        xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1918    else
1919        xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1920}
1921
1922
1923/**
1924 * xmlSchemaPErrExt:
1925 * @ctxt: the parsing context
1926 * @node: the context node
1927 * @error: the error code
1928 * @strData1: extra data
1929 * @strData2: extra data
1930 * @strData3: extra data
1931 * @msg: the message
1932 * @str1:  extra parameter for the message display
1933 * @str2:  extra parameter for the message display
1934 * @str3:  extra parameter for the message display
1935 * @str4:  extra parameter for the message display
1936 * @str5:  extra parameter for the message display
1937 *
1938 * Handle a parser error
1939 */
1940static void
1941xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1942		const xmlChar * strData1, const xmlChar * strData2,
1943		const xmlChar * strData3, const char *msg, const xmlChar * str1,
1944		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1945		const xmlChar * str5)
1946{
1947
1948    xmlGenericErrorFunc channel = NULL;
1949    xmlStructuredErrorFunc schannel = NULL;
1950    void *data = NULL;
1951
1952    if (ctxt != NULL) {
1953        ctxt->nberrors++;
1954	ctxt->err = error;
1955        channel = ctxt->error;
1956        data = ctxt->errCtxt;
1957	schannel = ctxt->serror;
1958    }
1959    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1960                    error, XML_ERR_ERROR, NULL, 0,
1961                    (const char *) strData1, (const char *) strData2,
1962		    (const char *) strData3, 0, 0, msg, str1, str2,
1963		    str3, str4, str5);
1964}
1965
1966/************************************************************************
1967 *									*
1968 * 			Allround error functions			*
1969 *									*
1970 ************************************************************************/
1971
1972/**
1973 * xmlSchemaVTypeErrMemory:
1974 * @node: a context node
1975 * @extra:  extra informations
1976 *
1977 * Handle an out of memory condition
1978 */
1979static void
1980xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1981                    const char *extra, xmlNodePtr node)
1982{
1983    if (ctxt != NULL) {
1984        ctxt->nberrors++;
1985        ctxt->err = XML_SCHEMAV_INTERNAL;
1986    }
1987    __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1988                     extra);
1989}
1990
1991static void
1992xmlSchemaPSimpleInternalErr(xmlNodePtr node,
1993			    const char *msg, const xmlChar *str)
1994{
1995     __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
1996	 msg, (const char *) str);
1997}
1998
1999#define WXS_ERROR_TYPE_ERROR 1
2000#define WXS_ERROR_TYPE_WARNING 2
2001/**
2002 * xmlSchemaErr3:
2003 * @ctxt: the validation context
2004 * @node: the context node
2005 * @error: the error code
2006 * @msg: the error message
2007 * @str1: extra data
2008 * @str2: extra data
2009 * @str3: extra data
2010 *
2011 * Handle a validation error
2012 */
2013static void
2014xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2015		  xmlErrorLevel errorLevel,
2016		  int error, xmlNodePtr node, int line, const char *msg,
2017		  const xmlChar *str1, const xmlChar *str2,
2018		  const xmlChar *str3, const xmlChar *str4)
2019{
2020    xmlStructuredErrorFunc schannel = NULL;
2021    xmlGenericErrorFunc channel = NULL;
2022    void *data = NULL;
2023
2024    if (ctxt != NULL) {
2025	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2026	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2027	    const char *file = NULL;
2028	    if (errorLevel != XML_ERR_WARNING) {
2029		vctxt->nberrors++;
2030		vctxt->err = error;
2031		channel = vctxt->error;
2032	    } else {
2033		channel = vctxt->warning;
2034	    }
2035	    schannel = vctxt->serror;
2036	    data = vctxt->errCtxt;
2037
2038	    /*
2039	    * Error node. If we specify a line number, then
2040	    * do not channel any node to the error function.
2041	    */
2042	    if (line == 0) {
2043		if ((node == NULL) &&
2044		    (vctxt->depth >= 0) &&
2045		    (vctxt->inode != NULL)) {
2046		    node = vctxt->inode->node;
2047		}
2048		/*
2049		* Get filename and line if no node-tree.
2050		*/
2051		if ((node == NULL) &&
2052		    (vctxt->parserCtxt != NULL) &&
2053		    (vctxt->parserCtxt->input != NULL)) {
2054		    file = vctxt->parserCtxt->input->filename;
2055		    line = vctxt->parserCtxt->input->line;
2056		}
2057	    } else {
2058		/*
2059		* Override the given node's (if any) position
2060		* and channel only the given line number.
2061		*/
2062		node = NULL;
2063		/*
2064		* Get filename.
2065		*/
2066		if (vctxt->doc != NULL)
2067		    file = (const char *) vctxt->doc->URL;
2068		else if ((vctxt->parserCtxt != NULL) &&
2069		    (vctxt->parserCtxt->input != NULL))
2070		    file = vctxt->parserCtxt->input->filename;
2071	    }
2072	    __xmlRaiseError(schannel, channel, data, ctxt,
2073		node, XML_FROM_SCHEMASV,
2074		error, errorLevel, file, line,
2075		(const char *) str1, (const char *) str2,
2076		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2077
2078	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2079	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2080	    if (errorLevel != XML_ERR_WARNING) {
2081		pctxt->nberrors++;
2082		pctxt->err = error;
2083		channel = pctxt->error;
2084	    } else {
2085		channel = pctxt->warning;
2086	    }
2087	    schannel = pctxt->serror;
2088	    data = pctxt->errCtxt;
2089	    __xmlRaiseError(schannel, channel, data, ctxt,
2090		node, XML_FROM_SCHEMASP, error,
2091		errorLevel, NULL, 0,
2092		(const char *) str1, (const char *) str2,
2093		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2094	} else {
2095	    TODO
2096	}
2097    }
2098}
2099
2100/**
2101 * xmlSchemaErr3:
2102 * @ctxt: the validation context
2103 * @node: the context node
2104 * @error: the error code
2105 * @msg: the error message
2106 * @str1: extra data
2107 * @str2: extra data
2108 * @str3: extra data
2109 *
2110 * Handle a validation error
2111 */
2112static void
2113xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2114	      int error, xmlNodePtr node, const char *msg,
2115	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2116{
2117    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2118	msg, str1, str2, str3, NULL);
2119}
2120
2121static void
2122xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2123	      int error, xmlNodePtr node, const char *msg,
2124	      const xmlChar *str1, const xmlChar *str2,
2125	      const xmlChar *str3, const xmlChar *str4)
2126{
2127    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2128	msg, str1, str2, str3, str4);
2129}
2130
2131static void
2132xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2133	     int error, xmlNodePtr node, const char *msg,
2134	     const xmlChar *str1, const xmlChar *str2)
2135{
2136    xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2137}
2138
2139static xmlChar *
2140xmlSchemaFormatNodeForError(xmlChar ** msg,
2141			    xmlSchemaAbstractCtxtPtr actxt,
2142			    xmlNodePtr node)
2143{
2144    xmlChar *str = NULL;
2145
2146    *msg = NULL;
2147    if ((node != NULL) &&
2148	(node->type != XML_ELEMENT_NODE) &&
2149	(node->type != XML_ATTRIBUTE_NODE))
2150    {
2151	/*
2152	* Don't try to format other nodes than element and
2153	* attribute nodes.
2154	* Play save and return an empty string.
2155	*/
2156	*msg = xmlStrdup(BAD_CAST "");
2157	return(*msg);
2158    }
2159    if (node != NULL) {
2160	/*
2161	* Work on tree nodes.
2162	*/
2163	if (node->type == XML_ATTRIBUTE_NODE) {
2164	    xmlNodePtr elem = node->parent;
2165
2166	    *msg = xmlStrdup(BAD_CAST "Element '");
2167	    if (elem->ns != NULL)
2168		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2169		    elem->ns->href, elem->name));
2170	    else
2171		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2172		    NULL, elem->name));
2173	    FREE_AND_NULL(str);
2174	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2175	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2176	} else {
2177	    *msg = xmlStrdup(BAD_CAST "Element '");
2178	}
2179	if (node->ns != NULL)
2180	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2181	    node->ns->href, node->name));
2182	else
2183	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2184	    NULL, node->name));
2185	FREE_AND_NULL(str);
2186	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2187    } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2188	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2189	/*
2190	* Work on node infos.
2191	*/
2192	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2193	    xmlSchemaNodeInfoPtr ielem =
2194		vctxt->elemInfos[vctxt->depth];
2195
2196	    *msg = xmlStrdup(BAD_CAST "Element '");
2197	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2198		ielem->nsName, ielem->localName));
2199	    FREE_AND_NULL(str);
2200	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2201	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2202	} else {
2203	    *msg = xmlStrdup(BAD_CAST "Element '");
2204	}
2205	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2206	    vctxt->inode->nsName, vctxt->inode->localName));
2207	FREE_AND_NULL(str);
2208	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2209    } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2210	/*
2211	* Hmm, no node while parsing?
2212	* Return an empty string, in case NULL will break something.
2213	*/
2214	*msg = xmlStrdup(BAD_CAST "");
2215    } else {
2216	TODO
2217	return (NULL);
2218    }
2219    /*
2220    * VAL TODO: The output of the given schema component is currently
2221    * disabled.
2222    */
2223#if 0
2224    if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2225	*msg = xmlStrcat(*msg, BAD_CAST " [");
2226	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2227	    NULL, type, NULL, 0));
2228	FREE_AND_NULL(str)
2229	*msg = xmlStrcat(*msg, BAD_CAST "]");
2230    }
2231#endif
2232    return (*msg);
2233}
2234
2235static void
2236xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2237		     const char *funcName,
2238		     const char *message,
2239		     const xmlChar *str1,
2240		     const xmlChar *str2)
2241{
2242    xmlChar *msg = NULL;
2243
2244    if (actxt == NULL)
2245        return;
2246    msg = xmlStrdup(BAD_CAST "Internal error: ");
2247    msg = xmlStrcat(msg, BAD_CAST funcName);
2248    msg = xmlStrcat(msg, BAD_CAST ", ");
2249    msg = xmlStrcat(msg, BAD_CAST message);
2250    msg = xmlStrcat(msg, BAD_CAST ".\n");
2251
2252    if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2253	xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2254	    (const char *) msg, str1, str2);
2255
2256    else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2257	xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2258	    (const char *) msg, str1, str2);
2259
2260    FREE_AND_NULL(msg)
2261}
2262
2263static void
2264xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2265		     const char *funcName,
2266		     const char *message)
2267{
2268    xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2269}
2270
2271#if 0
2272static void
2273xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2274		     const char *funcName,
2275		     const char *message,
2276		     const xmlChar *str1,
2277		     const xmlChar *str2)
2278{
2279    xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2280	str1, str2);
2281}
2282#endif
2283
2284static void
2285xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2286		   xmlParserErrors error,
2287		   xmlNodePtr node,
2288		   xmlSchemaBasicItemPtr item,
2289		   const char *message,
2290		   const xmlChar *str1, const xmlChar *str2,
2291		   const xmlChar *str3, const xmlChar *str4)
2292{
2293    xmlChar *msg = NULL;
2294
2295    if ((node == NULL) && (item != NULL) &&
2296	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2297	node = WXS_ITEM_NODE(item);
2298	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2299	msg = xmlStrcat(msg, BAD_CAST ": ");
2300    } else
2301	xmlSchemaFormatNodeForError(&msg, actxt, node);
2302    msg = xmlStrcat(msg, (const xmlChar *) message);
2303    msg = xmlStrcat(msg, BAD_CAST ".\n");
2304    xmlSchemaErr4(actxt, error, node,
2305	(const char *) msg, str1, str2, str3, str4);
2306    FREE_AND_NULL(msg)
2307}
2308
2309static void
2310xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2311		   xmlParserErrors error,
2312		   xmlNodePtr node,
2313		   xmlSchemaBasicItemPtr item,
2314		   const char *message,
2315		   const xmlChar *str1,
2316		   const xmlChar *str2)
2317{
2318    xmlSchemaCustomErr4(actxt, error, node, item,
2319	message, str1, str2, NULL, NULL);
2320}
2321
2322
2323
2324static void
2325xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2326		   xmlParserErrors error,
2327		   xmlNodePtr node,
2328		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2329		   const char *message,
2330		   const xmlChar *str1,
2331		   const xmlChar *str2,
2332		   const xmlChar *str3)
2333{
2334    xmlChar *msg = NULL;
2335
2336    xmlSchemaFormatNodeForError(&msg, actxt, node);
2337    msg = xmlStrcat(msg, (const xmlChar *) message);
2338    msg = xmlStrcat(msg, BAD_CAST ".\n");
2339
2340    /* URGENT TODO: Set the error code to something sane. */
2341    xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2342	(const char *) msg, str1, str2, str3, NULL);
2343
2344    FREE_AND_NULL(msg)
2345}
2346
2347
2348
2349static void
2350xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2351		   xmlParserErrors error,
2352		   xmlSchemaPSVIIDCNodePtr idcNode,
2353		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2354		   const char *message,
2355		   const xmlChar *str1,
2356		   const xmlChar *str2)
2357{
2358    xmlChar *msg = NULL, *qname = NULL;
2359
2360    msg = xmlStrdup(BAD_CAST "Element '%s': ");
2361    msg = xmlStrcat(msg, (const xmlChar *) message);
2362    msg = xmlStrcat(msg, BAD_CAST ".\n");
2363    xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2364	error, NULL, idcNode->nodeLine, (const char *) msg,
2365	xmlSchemaFormatQName(&qname,
2366	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2367	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2368	str1, str2, NULL);
2369    FREE_AND_NULL(qname);
2370    FREE_AND_NULL(msg);
2371}
2372
2373static int
2374xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2375			   xmlNodePtr node)
2376{
2377    if (node != NULL)
2378	return (node->type);
2379    if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2380	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2381	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2382    return (-1);
2383}
2384
2385static int
2386xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2387{
2388    switch (item->type) {
2389	case XML_SCHEMA_TYPE_COMPLEX:
2390	case XML_SCHEMA_TYPE_SIMPLE:
2391	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2392		return(1);
2393	    break;
2394	case XML_SCHEMA_TYPE_GROUP:
2395	    return (1);
2396	case XML_SCHEMA_TYPE_ELEMENT:
2397	    if ( ((xmlSchemaElementPtr) item)->flags &
2398		XML_SCHEMAS_ELEM_GLOBAL)
2399		return(1);
2400	    break;
2401	case XML_SCHEMA_TYPE_ATTRIBUTE:
2402	    if ( ((xmlSchemaAttributePtr) item)->flags &
2403		XML_SCHEMAS_ATTR_GLOBAL)
2404		return(1);
2405	    break;
2406	/* Note that attribute groups are always global. */
2407	default:
2408	    return(1);
2409    }
2410    return (0);
2411}
2412
2413static void
2414xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2415		       xmlParserErrors error,
2416		       xmlNodePtr node,
2417		       const xmlChar *value,
2418		       xmlSchemaTypePtr type,
2419		       int displayValue)
2420{
2421    xmlChar *msg = NULL;
2422
2423    xmlSchemaFormatNodeForError(&msg, actxt, node);
2424
2425    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2426	    XML_ATTRIBUTE_NODE))
2427	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2428    else
2429	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2430	    "value of ");
2431
2432    if (! xmlSchemaIsGlobalItem(type))
2433	msg = xmlStrcat(msg, BAD_CAST "the local ");
2434    else
2435	msg = xmlStrcat(msg, BAD_CAST "the ");
2436
2437    if (WXS_IS_ATOMIC(type))
2438	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2439    else if (WXS_IS_LIST(type))
2440	msg = xmlStrcat(msg, BAD_CAST "list type");
2441    else if (WXS_IS_UNION(type))
2442	msg = xmlStrcat(msg, BAD_CAST "union type");
2443
2444    if (xmlSchemaIsGlobalItem(type)) {
2445	xmlChar *str = NULL;
2446	msg = xmlStrcat(msg, BAD_CAST " '");
2447	if (type->builtInType != 0) {
2448	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2449	    msg = xmlStrcat(msg, type->name);
2450	} else
2451	    msg = xmlStrcat(msg,
2452		xmlSchemaFormatQName(&str,
2453		    type->targetNamespace, type->name));
2454	msg = xmlStrcat(msg, BAD_CAST "'");
2455	FREE_AND_NULL(str);
2456    }
2457    msg = xmlStrcat(msg, BAD_CAST ".\n");
2458    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2459	    XML_ATTRIBUTE_NODE))
2460	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2461    else
2462	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2463    FREE_AND_NULL(msg)
2464}
2465
2466static const xmlChar *
2467xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2468			      xmlSchemaNodeInfoPtr ni,
2469			      xmlNodePtr node)
2470{
2471    if (node != NULL) {
2472	if (node->ns != NULL)
2473	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2474	else
2475	    return (xmlSchemaFormatQName(str, NULL, node->name));
2476    } else if (ni != NULL)
2477	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2478    return (NULL);
2479}
2480
2481static void
2482xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2483			xmlParserErrors error,
2484			xmlSchemaAttrInfoPtr ni,
2485			xmlNodePtr node)
2486{
2487    xmlChar *msg = NULL, *str = NULL;
2488
2489    xmlSchemaFormatNodeForError(&msg, actxt, node);
2490    msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2491    xmlSchemaErr(actxt, error, node, (const char *) msg,
2492	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2493	NULL);
2494    FREE_AND_NULL(str)
2495    FREE_AND_NULL(msg)
2496}
2497
2498static void
2499xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2500		        xmlParserErrors error,
2501		        xmlNodePtr node,
2502			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2503			const char *message,
2504			int nbval,
2505			int nbneg,
2506			xmlChar **values)
2507{
2508    xmlChar *str = NULL, *msg = NULL;
2509    xmlChar *localName, *nsName;
2510    const xmlChar *cur, *end;
2511    int i;
2512
2513    xmlSchemaFormatNodeForError(&msg, actxt, node);
2514    msg = xmlStrcat(msg, (const xmlChar *) message);
2515    msg = xmlStrcat(msg, BAD_CAST ".");
2516    /*
2517    * Note that is does not make sense to report that we have a
2518    * wildcard here, since the wildcard might be unfolded into
2519    * multiple transitions.
2520    */
2521    if (nbval + nbneg > 0) {
2522	if (nbval + nbneg > 1) {
2523	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2524	} else
2525	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2526	nsName = NULL;
2527
2528	for (i = 0; i < nbval + nbneg; i++) {
2529	    cur = values[i];
2530	    if (cur == NULL)
2531	        continue;
2532	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2533	        (cur[3] == ' ')) {
2534		cur += 4;
2535		str = xmlStrcat(str, BAD_CAST "##other");
2536	    }
2537	    /*
2538	    * Get the local name.
2539	    */
2540	    localName = NULL;
2541
2542	    end = cur;
2543	    if (*end == '*') {
2544		localName = xmlStrdup(BAD_CAST "*");
2545		end++;
2546	    } else {
2547		while ((*end != 0) && (*end != '|'))
2548		    end++;
2549		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2550	    }
2551	    if (*end != 0) {
2552		end++;
2553		/*
2554		* Skip "*|*" if they come with negated expressions, since
2555		* they represent the same negated wildcard.
2556		*/
2557		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2558		    /*
2559		    * Get the namespace name.
2560		    */
2561		    cur = end;
2562		    if (*end == '*') {
2563			nsName = xmlStrdup(BAD_CAST "{*}");
2564		    } else {
2565			while (*end != 0)
2566			    end++;
2567
2568			if (i >= nbval)
2569			    nsName = xmlStrdup(BAD_CAST "{##other:");
2570			else
2571			    nsName = xmlStrdup(BAD_CAST "{");
2572
2573			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2574			nsName = xmlStrcat(nsName, BAD_CAST "}");
2575		    }
2576		    str = xmlStrcat(str, BAD_CAST nsName);
2577		    FREE_AND_NULL(nsName)
2578		} else {
2579		    FREE_AND_NULL(localName);
2580		    continue;
2581		}
2582	    }
2583	    str = xmlStrcat(str, BAD_CAST localName);
2584	    FREE_AND_NULL(localName);
2585
2586	    if (i < nbval + nbneg -1)
2587		str = xmlStrcat(str, BAD_CAST ", ");
2588	}
2589	str = xmlStrcat(str, BAD_CAST " ).\n");
2590	msg = xmlStrcat(msg, BAD_CAST str);
2591	FREE_AND_NULL(str)
2592    } else
2593      msg = xmlStrcat(msg, BAD_CAST "\n");
2594    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2595    xmlFree(msg);
2596}
2597
2598static void
2599xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2600		  xmlParserErrors error,
2601		  xmlNodePtr node,
2602		  const xmlChar *value,
2603		  unsigned long length,
2604		  xmlSchemaTypePtr type,
2605		  xmlSchemaFacetPtr facet,
2606		  const char *message,
2607		  const xmlChar *str1,
2608		  const xmlChar *str2)
2609{
2610    xmlChar *str = NULL, *msg = NULL;
2611    xmlSchemaTypeType facetType;
2612    int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2613
2614    xmlSchemaFormatNodeForError(&msg, actxt, node);
2615    if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2616	facetType = XML_SCHEMA_FACET_ENUMERATION;
2617	/*
2618	* If enumerations are validated, one must not expect the
2619	* facet to be given.
2620	*/
2621    } else
2622	facetType = facet->type;
2623    msg = xmlStrcat(msg, BAD_CAST "[");
2624    msg = xmlStrcat(msg, BAD_CAST "facet '");
2625    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2626    msg = xmlStrcat(msg, BAD_CAST "'] ");
2627    if (message == NULL) {
2628	/*
2629	* Use a default message.
2630	*/
2631	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2632	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2633	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2634
2635	    char len[25], actLen[25];
2636
2637	    /* FIXME, TODO: What is the max expected string length of the
2638	    * this value?
2639	    */
2640	    if (nodeType == XML_ATTRIBUTE_NODE)
2641		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2642	    else
2643		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2644
2645	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2646	    snprintf(actLen, 24, "%lu", length);
2647
2648	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2649		msg = xmlStrcat(msg,
2650		BAD_CAST "this differs from the allowed length of '%s'.\n");
2651	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2652		msg = xmlStrcat(msg,
2653		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2654	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2655		msg = xmlStrcat(msg,
2656		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2657
2658	    if (nodeType == XML_ATTRIBUTE_NODE)
2659		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2660		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2661	    else
2662		xmlSchemaErr(actxt, error, node, (const char *) msg,
2663		    (const xmlChar *) actLen, (const xmlChar *) len);
2664
2665	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2666	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2667		"of the set {%s}.\n");
2668	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2669		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2670	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2671	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2672		"by the pattern '%s'.\n");
2673	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2674		facet->value);
2675	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2676	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2677		"minimum value allowed ('%s').\n");
2678	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2679		facet->value);
2680	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2681	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2682		"maximum value allowed ('%s').\n");
2683	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2684		facet->value);
2685	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2686	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2687		"'%s'.\n");
2688	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2689		facet->value);
2690	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2691	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2692		"'%s'.\n");
2693	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2694		facet->value);
2695	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2696	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2697		"digits than are allowed ('%s').\n");
2698	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2699		facet->value);
2700	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2701	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2702		"digits than are allowed ('%s').\n");
2703	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2704		facet->value);
2705	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2706	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2707	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2708	} else {
2709	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2710	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2711	}
2712    } else {
2713	msg = xmlStrcat(msg, (const xmlChar *) message);
2714	msg = xmlStrcat(msg, BAD_CAST ".\n");
2715	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2716    }
2717    FREE_AND_NULL(str)
2718    xmlFree(msg);
2719}
2720
2721#define VERROR(err, type, msg) \
2722    xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2723
2724#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2725
2726#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2727#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2728
2729#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2730
2731
2732/**
2733 * xmlSchemaPMissingAttrErr:
2734 * @ctxt: the schema validation context
2735 * @ownerDes: the designation of  the owner
2736 * @ownerName: the name of the owner
2737 * @ownerItem: the owner as a schema object
2738 * @ownerElem: the owner as an element node
2739 * @node: the parent element node of the missing attribute node
2740 * @type: the corresponding type of the attribute node
2741 *
2742 * Reports an illegal attribute.
2743 */
2744static void
2745xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2746			 xmlParserErrors error,
2747			 xmlSchemaBasicItemPtr ownerItem,
2748			 xmlNodePtr ownerElem,
2749			 const char *name,
2750			 const char *message)
2751{
2752    xmlChar *des = NULL;
2753
2754    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2755
2756    if (message != NULL)
2757	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2758    else
2759	xmlSchemaPErr(ctxt, ownerElem, error,
2760	    "%s: The attribute '%s' is required but missing.\n",
2761	    BAD_CAST des, BAD_CAST name);
2762    FREE_AND_NULL(des);
2763}
2764
2765
2766/**
2767 * xmlSchemaPResCompAttrErr:
2768 * @ctxt: the schema validation context
2769 * @error: the error code
2770 * @ownerDes: the designation of  the owner
2771 * @ownerItem: the owner as a schema object
2772 * @ownerElem: the owner as an element node
2773 * @name: the name of the attribute holding the QName
2774 * @refName: the referenced local name
2775 * @refURI: the referenced namespace URI
2776 * @message: optional message
2777 *
2778 * Used to report QName attribute values that failed to resolve
2779 * to schema components.
2780 */
2781static void
2782xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2783			 xmlParserErrors error,
2784			 xmlSchemaBasicItemPtr ownerItem,
2785			 xmlNodePtr ownerElem,
2786			 const char *name,
2787			 const xmlChar *refName,
2788			 const xmlChar *refURI,
2789			 xmlSchemaTypeType refType,
2790			 const char *refTypeStr)
2791{
2792    xmlChar *des = NULL, *strA = NULL;
2793
2794    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2795    if (refTypeStr == NULL)
2796	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2797	xmlSchemaPErrExt(ctxt, ownerElem, error,
2798	    NULL, NULL, NULL,
2799	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2800	    "%s.\n", BAD_CAST des, BAD_CAST name,
2801	    xmlSchemaFormatQName(&strA, refURI, refName),
2802	    BAD_CAST refTypeStr, NULL);
2803    FREE_AND_NULL(des)
2804    FREE_AND_NULL(strA)
2805}
2806
2807/**
2808 * xmlSchemaPCustomAttrErr:
2809 * @ctxt: the schema parser context
2810 * @error: the error code
2811 * @ownerDes: the designation of the owner
2812 * @ownerItem: the owner as a schema object
2813 * @attr: the illegal attribute node
2814 *
2815 * Reports an illegal attribute during the parse.
2816 */
2817static void
2818xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2819			xmlParserErrors error,
2820			xmlChar **ownerDes,
2821			xmlSchemaBasicItemPtr ownerItem,
2822			xmlAttrPtr attr,
2823			const char *msg)
2824{
2825    xmlChar *des = NULL;
2826
2827    if (ownerDes == NULL)
2828	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2829    else if (*ownerDes == NULL) {
2830	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2831	des = *ownerDes;
2832    } else
2833	des = *ownerDes;
2834    if (attr == NULL) {
2835	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2836	    "%s, attribute '%s': %s.\n",
2837	    BAD_CAST des, (const xmlChar *) "Unknown",
2838	    (const xmlChar *) msg, NULL, NULL);
2839    } else {
2840	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2841	    "%s, attribute '%s': %s.\n",
2842	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2843    }
2844    if (ownerDes == NULL)
2845	FREE_AND_NULL(des);
2846}
2847
2848/**
2849 * xmlSchemaPIllegalAttrErr:
2850 * @ctxt: the schema parser context
2851 * @error: the error code
2852 * @ownerDes: the designation of the attribute's owner
2853 * @ownerItem: the attribute's owner item
2854 * @attr: the illegal attribute node
2855 *
2856 * Reports an illegal attribute during the parse.
2857 */
2858static void
2859xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2860			 xmlParserErrors error,
2861			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2862			 xmlAttrPtr attr)
2863{
2864    xmlChar *strA = NULL, *strB = NULL;
2865
2866    xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2867    xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2868	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2869	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2870	NULL, NULL);
2871    FREE_AND_NULL(strA);
2872    FREE_AND_NULL(strB);
2873}
2874
2875/**
2876 * xmlSchemaPCustomErr:
2877 * @ctxt: the schema parser context
2878 * @error: the error code
2879 * @itemDes: the designation of the schema item
2880 * @item: the schema item
2881 * @itemElem: the node of the schema item
2882 * @message: the error message
2883 * @str1: an optional param for the error message
2884 * @str2: an optional param for the error message
2885 * @str3: an optional param for the error message
2886 *
2887 * Reports an error during parsing.
2888 */
2889static void
2890xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2891		    xmlParserErrors error,
2892		    xmlSchemaBasicItemPtr item,
2893		    xmlNodePtr itemElem,
2894		    const char *message,
2895		    const xmlChar *str1,
2896		    const xmlChar *str2,
2897		    const xmlChar *str3)
2898{
2899    xmlChar *des = NULL, *msg = NULL;
2900
2901    xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2902    msg = xmlStrdup(BAD_CAST "%s: ");
2903    msg = xmlStrcat(msg, (const xmlChar *) message);
2904    msg = xmlStrcat(msg, BAD_CAST ".\n");
2905    if ((itemElem == NULL) && (item != NULL))
2906	itemElem = WXS_ITEM_NODE(item);
2907    xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2908	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2909    FREE_AND_NULL(des);
2910    FREE_AND_NULL(msg);
2911}
2912
2913/**
2914 * xmlSchemaPCustomErr:
2915 * @ctxt: the schema parser context
2916 * @error: the error code
2917 * @itemDes: the designation of the schema item
2918 * @item: the schema item
2919 * @itemElem: the node of the schema item
2920 * @message: the error message
2921 * @str1: the optional param for the error message
2922 *
2923 * Reports an error during parsing.
2924 */
2925static void
2926xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2927		    xmlParserErrors error,
2928		    xmlSchemaBasicItemPtr item,
2929		    xmlNodePtr itemElem,
2930		    const char *message,
2931		    const xmlChar *str1)
2932{
2933    xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2934	str1, NULL, NULL);
2935}
2936
2937/**
2938 * xmlSchemaPAttrUseErr:
2939 * @ctxt: the schema parser context
2940 * @error: the error code
2941 * @itemDes: the designation of the schema type
2942 * @item: the schema type
2943 * @itemElem: the node of the schema type
2944 * @attr: the invalid schema attribute
2945 * @message: the error message
2946 * @str1: the optional param for the error message
2947 *
2948 * Reports an attribute use error during parsing.
2949 */
2950static void
2951xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2952		    xmlParserErrors error,
2953		    xmlNodePtr node,
2954		    xmlSchemaBasicItemPtr ownerItem,
2955		    const xmlSchemaAttributeUsePtr attruse,
2956		    const char *message,
2957		    const xmlChar *str1, const xmlChar *str2,
2958		    const xmlChar *str3,const xmlChar *str4)
2959{
2960    xmlChar *str = NULL, *msg = NULL;
2961
2962    xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2963    msg = xmlStrcat(msg, BAD_CAST ", ");
2964    msg = xmlStrcat(msg,
2965	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2966	WXS_BASIC_CAST attruse, NULL));
2967    FREE_AND_NULL(str);
2968    msg = xmlStrcat(msg, BAD_CAST ": ");
2969    msg = xmlStrcat(msg, (const xmlChar *) message);
2970    msg = xmlStrcat(msg, BAD_CAST ".\n");
2971    xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2972	(const char *) msg, str1, str2, str3, str4);
2973    xmlFree(msg);
2974}
2975
2976/**
2977 * xmlSchemaPIllegalFacetAtomicErr:
2978 * @ctxt: the schema parser context
2979 * @error: the error code
2980 * @type: the schema type
2981 * @baseType: the base type of type
2982 * @facet: the illegal facet
2983 *
2984 * Reports an illegal facet for atomic simple types.
2985 */
2986static void
2987xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2988			  xmlParserErrors error,
2989			  xmlSchemaTypePtr type,
2990			  xmlSchemaTypePtr baseType,
2991			  xmlSchemaFacetPtr facet)
2992{
2993    xmlChar *des = NULL, *strT = NULL;
2994
2995    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
2996    xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
2997	"%s: The facet '%s' is not allowed on types derived from the "
2998	"type %s.\n",
2999	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3000	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3001	NULL, NULL);
3002    FREE_AND_NULL(des);
3003    FREE_AND_NULL(strT);
3004}
3005
3006/**
3007 * xmlSchemaPIllegalFacetListUnionErr:
3008 * @ctxt: the schema parser context
3009 * @error: the error code
3010 * @itemDes: the designation of the schema item involved
3011 * @item: the schema item involved
3012 * @facet: the illegal facet
3013 *
3014 * Reports an illegal facet for <list> and <union>.
3015 */
3016static void
3017xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3018			  xmlParserErrors error,
3019			  xmlSchemaTypePtr type,
3020			  xmlSchemaFacetPtr facet)
3021{
3022    xmlChar *des = NULL;
3023
3024    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3025	type->node);
3026    xmlSchemaPErr(ctxt, type->node, error,
3027	"%s: The facet '%s' is not allowed.\n",
3028	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3029    FREE_AND_NULL(des);
3030}
3031
3032/**
3033 * xmlSchemaPMutualExclAttrErr:
3034 * @ctxt: the schema validation context
3035 * @error: the error code
3036 * @elemDes: the designation of the parent element node
3037 * @attr: the bad attribute node
3038 * @type: the corresponding type of the attribute node
3039 *
3040 * Reports an illegal attribute.
3041 */
3042static void
3043xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3044			 xmlParserErrors error,
3045			 xmlSchemaBasicItemPtr ownerItem,
3046			 xmlAttrPtr attr,
3047			 const char *name1,
3048			 const char *name2)
3049{
3050    xmlChar *des = NULL;
3051
3052    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3053    xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3054	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3055	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3056    FREE_AND_NULL(des);
3057}
3058
3059/**
3060 * xmlSchemaPSimpleTypeErr:
3061 * @ctxt:  the schema validation context
3062 * @error: the error code
3063 * @type: the type specifier
3064 * @ownerDes: the designation of the owner
3065 * @ownerItem: the schema object if existent
3066 * @node: the validated node
3067 * @value: the validated value
3068 *
3069 * Reports a simple type validation error.
3070 * TODO: Should this report the value of an element as well?
3071 */
3072static void
3073xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3074			xmlParserErrors error,
3075			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3076			xmlNodePtr node,
3077			xmlSchemaTypePtr type,
3078			const char *expected,
3079			const xmlChar *value,
3080			const char *message,
3081			const xmlChar *str1,
3082			const xmlChar *str2)
3083{
3084    xmlChar *msg = NULL;
3085
3086    xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3087    if (message == NULL) {
3088	/*
3089	* Use default messages.
3090	*/
3091	if (type != NULL) {
3092	    if (node->type == XML_ATTRIBUTE_NODE)
3093		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3094	    else
3095		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3096		"valid value of ");
3097	    if (! xmlSchemaIsGlobalItem(type))
3098		msg = xmlStrcat(msg, BAD_CAST "the local ");
3099	    else
3100		msg = xmlStrcat(msg, BAD_CAST "the ");
3101
3102	    if (WXS_IS_ATOMIC(type))
3103		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3104	    else if (WXS_IS_LIST(type))
3105		msg = xmlStrcat(msg, BAD_CAST "list type");
3106	    else if (WXS_IS_UNION(type))
3107		msg = xmlStrcat(msg, BAD_CAST "union type");
3108
3109	    if (xmlSchemaIsGlobalItem(type)) {
3110		xmlChar *str = NULL;
3111		msg = xmlStrcat(msg, BAD_CAST " '");
3112		if (type->builtInType != 0) {
3113		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3114		    msg = xmlStrcat(msg, type->name);
3115		} else
3116		    msg = xmlStrcat(msg,
3117			xmlSchemaFormatQName(&str,
3118			    type->targetNamespace, type->name));
3119		msg = xmlStrcat(msg, BAD_CAST "'.");
3120		FREE_AND_NULL(str);
3121	    }
3122	} else {
3123	    if (node->type == XML_ATTRIBUTE_NODE)
3124		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3125	    else
3126		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3127		"valid.");
3128	}
3129	if (expected) {
3130	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3131	    msg = xmlStrcat(msg, BAD_CAST expected);
3132	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3133	} else
3134	    msg = xmlStrcat(msg, BAD_CAST "\n");
3135	if (node->type == XML_ATTRIBUTE_NODE)
3136	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3137	else
3138	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3139    } else {
3140	msg = xmlStrcat(msg, BAD_CAST message);
3141	msg = xmlStrcat(msg, BAD_CAST ".\n");
3142	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3143	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3144    }
3145    /* Cleanup. */
3146    FREE_AND_NULL(msg)
3147}
3148
3149/**
3150 * xmlSchemaPContentErr:
3151 * @ctxt: the schema parser context
3152 * @error: the error code
3153 * @onwerDes: the designation of the holder of the content
3154 * @ownerItem: the owner item of the holder of the content
3155 * @ownerElem: the node of the holder of the content
3156 * @child: the invalid child node
3157 * @message: the optional error message
3158 * @content: the optional string describing the correct content
3159 *
3160 * Reports an error concerning the content of a schema element.
3161 */
3162static void
3163xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3164		     xmlParserErrors error,
3165		     xmlSchemaBasicItemPtr ownerItem,
3166		     xmlNodePtr ownerElem,
3167		     xmlNodePtr child,
3168		     const char *message,
3169		     const char *content)
3170{
3171    xmlChar *des = NULL;
3172
3173    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3174    if (message != NULL)
3175	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3176	    "%s: %s.\n",
3177	    BAD_CAST des, BAD_CAST message);
3178    else {
3179	if (content != NULL) {
3180	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3181		"%s: The content is not valid. Expected is %s.\n",
3182		BAD_CAST des, BAD_CAST content);
3183	} else {
3184	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3185		"%s: The content is not valid.\n",
3186		BAD_CAST des, NULL);
3187	}
3188    }
3189    FREE_AND_NULL(des)
3190}
3191
3192/************************************************************************
3193 * 									*
3194 * 			Streamable error functions                      *
3195 * 									*
3196 ************************************************************************/
3197
3198
3199
3200
3201/************************************************************************
3202 * 									*
3203 * 			Validation helper functions			*
3204 * 									*
3205 ************************************************************************/
3206
3207
3208/************************************************************************
3209 * 									*
3210 * 			Allocation functions				*
3211 * 									*
3212 ************************************************************************/
3213
3214/**
3215 * xmlSchemaNewSchemaForParserCtxt:
3216 * @ctxt:  a schema validation context
3217 *
3218 * Allocate a new Schema structure.
3219 *
3220 * Returns the newly allocated structure or NULL in case or error
3221 */
3222static xmlSchemaPtr
3223xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3224{
3225    xmlSchemaPtr ret;
3226
3227    ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3228    if (ret == NULL) {
3229        xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3230        return (NULL);
3231    }
3232    memset(ret, 0, sizeof(xmlSchema));
3233    ret->dict = ctxt->dict;
3234    xmlDictReference(ret->dict);
3235
3236    return (ret);
3237}
3238
3239/**
3240 * xmlSchemaNewFacet:
3241 *
3242 * Allocate a new Facet structure.
3243 *
3244 * Returns the newly allocated structure or NULL in case or error
3245 */
3246xmlSchemaFacetPtr
3247xmlSchemaNewFacet(void)
3248{
3249    xmlSchemaFacetPtr ret;
3250
3251    ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3252    if (ret == NULL) {
3253        return (NULL);
3254    }
3255    memset(ret, 0, sizeof(xmlSchemaFacet));
3256
3257    return (ret);
3258}
3259
3260/**
3261 * xmlSchemaNewAnnot:
3262 * @ctxt:  a schema validation context
3263 * @node:  a node
3264 *
3265 * Allocate a new annotation structure.
3266 *
3267 * Returns the newly allocated structure or NULL in case or error
3268 */
3269static xmlSchemaAnnotPtr
3270xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3271{
3272    xmlSchemaAnnotPtr ret;
3273
3274    ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3275    if (ret == NULL) {
3276        xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3277        return (NULL);
3278    }
3279    memset(ret, 0, sizeof(xmlSchemaAnnot));
3280    ret->content = node;
3281    return (ret);
3282}
3283
3284static xmlSchemaItemListPtr
3285xmlSchemaItemListCreate(void)
3286{
3287    xmlSchemaItemListPtr ret;
3288
3289    ret = xmlMalloc(sizeof(xmlSchemaItemList));
3290    if (ret == NULL) {
3291	xmlSchemaPErrMemory(NULL,
3292	    "allocating an item list structure", NULL);
3293	return (NULL);
3294    }
3295    memset(ret, 0, sizeof(xmlSchemaItemList));
3296    return (ret);
3297}
3298
3299static void
3300xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3301{
3302    if (list->items != NULL) {
3303	xmlFree(list->items);
3304	list->items = NULL;
3305    }
3306    list->nbItems = 0;
3307    list->sizeItems = 0;
3308}
3309
3310static int
3311xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3312{
3313    if (list->items == NULL) {
3314	list->items = (void **) xmlMalloc(
3315	    20 * sizeof(void *));
3316	if (list->items == NULL) {
3317	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3318	    return(-1);
3319	}
3320	list->sizeItems = 20;
3321    } else if (list->sizeItems <= list->nbItems) {
3322	list->sizeItems *= 2;
3323	list->items = (void **) xmlRealloc(list->items,
3324	    list->sizeItems * sizeof(void *));
3325	if (list->items == NULL) {
3326	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3327	    list->sizeItems = 0;
3328	    return(-1);
3329	}
3330    }
3331    list->items[list->nbItems++] = item;
3332    return(0);
3333}
3334
3335static int
3336xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3337			 int initialSize,
3338			 void *item)
3339{
3340    if (list->items == NULL) {
3341	if (initialSize <= 0)
3342	    initialSize = 1;
3343	list->items = (void **) xmlMalloc(
3344	    initialSize * sizeof(void *));
3345	if (list->items == NULL) {
3346	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3347	    return(-1);
3348	}
3349	list->sizeItems = initialSize;
3350    } else if (list->sizeItems <= list->nbItems) {
3351	list->sizeItems *= 2;
3352	list->items = (void **) xmlRealloc(list->items,
3353	    list->sizeItems * sizeof(void *));
3354	if (list->items == NULL) {
3355	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3356	    list->sizeItems = 0;
3357	    return(-1);
3358	}
3359    }
3360    list->items[list->nbItems++] = item;
3361    return(0);
3362}
3363
3364static int
3365xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3366{
3367    if (list->items == NULL) {
3368	list->items = (void **) xmlMalloc(
3369	    20 * sizeof(void *));
3370	if (list->items == NULL) {
3371	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3372	    return(-1);
3373	}
3374	list->sizeItems = 20;
3375    } else if (list->sizeItems <= list->nbItems) {
3376	list->sizeItems *= 2;
3377	list->items = (void **) xmlRealloc(list->items,
3378	    list->sizeItems * sizeof(void *));
3379	if (list->items == NULL) {
3380	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3381	    list->sizeItems = 0;
3382	    return(-1);
3383	}
3384    }
3385    /*
3386    * Just append if the index is greater/equal than the item count.
3387    */
3388    if (idx >= list->nbItems) {
3389	list->items[list->nbItems++] = item;
3390    } else {
3391	int i;
3392	for (i = list->nbItems; i > idx; i--)
3393	    list->items[i] = list->items[i-1];
3394	list->items[idx] = item;
3395	list->nbItems++;
3396    }
3397    return(0);
3398}
3399
3400#if 0 /* enable if ever needed */
3401static int
3402xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3403			    int initialSize,
3404			    void *item,
3405			    int idx)
3406{
3407    if (list->items == NULL) {
3408	if (initialSize <= 0)
3409	    initialSize = 1;
3410	list->items = (void **) xmlMalloc(
3411	    initialSize * sizeof(void *));
3412	if (list->items == NULL) {
3413	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3414	    return(-1);
3415	}
3416	list->sizeItems = initialSize;
3417    } else if (list->sizeItems <= list->nbItems) {
3418	list->sizeItems *= 2;
3419	list->items = (void **) xmlRealloc(list->items,
3420	    list->sizeItems * sizeof(void *));
3421	if (list->items == NULL) {
3422	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3423	    list->sizeItems = 0;
3424	    return(-1);
3425	}
3426    }
3427    /*
3428    * Just append if the index is greater/equal than the item count.
3429    */
3430    if (idx >= list->nbItems) {
3431	list->items[list->nbItems++] = item;
3432    } else {
3433	int i;
3434	for (i = list->nbItems; i > idx; i--)
3435	    list->items[i] = list->items[i-1];
3436	list->items[idx] = item;
3437	list->nbItems++;
3438    }
3439    return(0);
3440}
3441#endif
3442
3443static int
3444xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3445{
3446    int i;
3447    if ((list->items == NULL) || (idx >= list->nbItems)) {
3448	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3449	    "index error.\n");
3450	return(-1);
3451    }
3452
3453    if (list->nbItems == 1) {
3454	/* TODO: Really free the list? */
3455	xmlFree(list->items);
3456	list->items = NULL;
3457	list->nbItems = 0;
3458	list->sizeItems = 0;
3459    } else if (list->nbItems -1 == idx) {
3460	list->nbItems--;
3461    } else {
3462	for (i = idx; i < list->nbItems -1; i++)
3463	    list->items[i] = list->items[i+1];
3464	list->nbItems--;
3465    }
3466    return(0);
3467}
3468
3469/**
3470 * xmlSchemaItemListFree:
3471 * @annot:  a schema type structure
3472 *
3473 * Deallocate a annotation structure
3474 */
3475static void
3476xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3477{
3478    if (list == NULL)
3479	return;
3480    if (list->items != NULL)
3481	xmlFree(list->items);
3482    xmlFree(list);
3483}
3484
3485static void
3486xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3487{
3488    if (bucket == NULL)
3489	return;
3490    if (bucket->globals != NULL) {
3491	xmlSchemaComponentListFree(bucket->globals);
3492	xmlSchemaItemListFree(bucket->globals);
3493    }
3494    if (bucket->locals != NULL) {
3495	xmlSchemaComponentListFree(bucket->locals);
3496	xmlSchemaItemListFree(bucket->locals);
3497    }
3498    if (bucket->relations != NULL) {
3499	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3500	do {
3501	    prev = cur;
3502	    cur = cur->next;
3503	    xmlFree(prev);
3504	} while (cur != NULL);
3505    }
3506    if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3507	xmlFreeDoc(bucket->doc);
3508    }
3509    if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3510	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3511	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3512    }
3513    xmlFree(bucket);
3514}
3515
3516static xmlSchemaBucketPtr
3517xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3518			 int type, const xmlChar *targetNamespace)
3519{
3520    xmlSchemaBucketPtr ret;
3521    int size;
3522    xmlSchemaPtr mainSchema;
3523
3524    if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3525	PERROR_INT("xmlSchemaBucketCreate",
3526	    "no main schema on constructor");
3527	return(NULL);
3528    }
3529    mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3530    /* Create the schema bucket. */
3531    if (WXS_IS_BUCKET_INCREDEF(type))
3532	size = sizeof(xmlSchemaInclude);
3533    else
3534	size = sizeof(xmlSchemaImport);
3535    ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3536    if (ret == NULL) {
3537	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3538	return(NULL);
3539    }
3540    memset(ret, 0, size);
3541    ret->targetNamespace = targetNamespace;
3542    ret->type = type;
3543    ret->globals = xmlSchemaItemListCreate();
3544    if (ret->globals == NULL) {
3545	xmlFree(ret);
3546	return(NULL);
3547    }
3548    ret->locals = xmlSchemaItemListCreate();
3549    if (ret->locals == NULL) {
3550	xmlFree(ret);
3551	return(NULL);
3552    }
3553    /*
3554    * The following will assure that only the first bucket is marked as
3555    * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3556    * For each following import buckets an xmlSchema will be created.
3557    * An xmlSchema will be created for every distinct targetNamespace.
3558    * We assign the targetNamespace to the schemata here.
3559    */
3560    if (! WXS_HAS_BUCKETS(pctxt)) {
3561	if (WXS_IS_BUCKET_INCREDEF(type)) {
3562	    PERROR_INT("xmlSchemaBucketCreate",
3563		"first bucket but it's an include or redefine");
3564	    xmlSchemaBucketFree(ret);
3565	    return(NULL);
3566	}
3567	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3568	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3569	/* Point to the *main* schema. */
3570	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3571	WXS_IMPBUCKET(ret)->schema = mainSchema;
3572	/*
3573	* Ensure that the main schema gets a targetNamespace.
3574	*/
3575	mainSchema->targetNamespace = targetNamespace;
3576    } else {
3577	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3578	    PERROR_INT("xmlSchemaBucketCreate",
3579		"main bucket but it's not the first one");
3580	    xmlSchemaBucketFree(ret);
3581	    return(NULL);
3582	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3583	    /*
3584	    * Create a schema for imports and assign the
3585	    * targetNamespace.
3586	    */
3587	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3588	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3589		xmlSchemaBucketFree(ret);
3590		return(NULL);
3591	    }
3592	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3593	}
3594    }
3595    if (WXS_IS_BUCKET_IMPMAIN(type)) {
3596	int res;
3597	/*
3598	* Imports go into the "schemasImports" slot of the main *schema*.
3599	* Note that we create an import entry for the main schema as well; i.e.,
3600	* even if there's only one schema, we'll get an import.
3601	*/
3602	if (mainSchema->schemasImports == NULL) {
3603	    mainSchema->schemasImports = xmlHashCreateDict(5,
3604		WXS_CONSTRUCTOR(pctxt)->dict);
3605	    if (mainSchema->schemasImports == NULL) {
3606		xmlSchemaBucketFree(ret);
3607		return(NULL);
3608	    }
3609	}
3610	if (targetNamespace == NULL)
3611	    res = xmlHashAddEntry(mainSchema->schemasImports,
3612		XML_SCHEMAS_NO_NAMESPACE, ret);
3613	else
3614	    res = xmlHashAddEntry(mainSchema->schemasImports,
3615		targetNamespace, ret);
3616	if (res != 0) {
3617	    PERROR_INT("xmlSchemaBucketCreate",
3618		"failed to add the schema bucket to the hash");
3619	    xmlSchemaBucketFree(ret);
3620	    return(NULL);
3621	}
3622    } else {
3623	/* Set the @ownerImport of an include bucket. */
3624	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3625	    WXS_INCBUCKET(ret)->ownerImport =
3626		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3627	else
3628	    WXS_INCBUCKET(ret)->ownerImport =
3629		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3630
3631	/* Includes got into the "includes" slot of the *main* schema. */
3632	if (mainSchema->includes == NULL) {
3633	    mainSchema->includes = xmlSchemaItemListCreate();
3634	    if (mainSchema->includes == NULL) {
3635		xmlSchemaBucketFree(ret);
3636		return(NULL);
3637	    }
3638	}
3639	xmlSchemaItemListAdd(mainSchema->includes, ret);
3640    }
3641    /*
3642    * Add to list of all buckets; this is used for lookup
3643    * during schema construction time only.
3644    */
3645    if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3646	return(NULL);
3647    return(ret);
3648}
3649
3650static int
3651xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3652{
3653    if (*list == NULL) {
3654	*list = xmlSchemaItemListCreate();
3655	if (*list == NULL)
3656	    return(-1);
3657    }
3658    xmlSchemaItemListAddSize(*list, initialSize, item);
3659    return(0);
3660}
3661
3662/**
3663 * xmlSchemaFreeAnnot:
3664 * @annot:  a schema type structure
3665 *
3666 * Deallocate a annotation structure
3667 */
3668static void
3669xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3670{
3671    if (annot == NULL)
3672        return;
3673    if (annot->next == NULL) {
3674	xmlFree(annot);
3675    } else {
3676	xmlSchemaAnnotPtr prev;
3677
3678	do {
3679	    prev = annot;
3680	    annot = annot->next;
3681	    xmlFree(prev);
3682	} while (annot != NULL);
3683    }
3684}
3685
3686/**
3687 * xmlSchemaFreeNotation:
3688 * @schema:  a schema notation structure
3689 *
3690 * Deallocate a Schema Notation structure.
3691 */
3692static void
3693xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3694{
3695    if (nota == NULL)
3696        return;
3697    xmlFree(nota);
3698}
3699
3700/**
3701 * xmlSchemaFreeAttribute:
3702 * @attr:  an attribute declaration
3703 *
3704 * Deallocates an attribute declaration structure.
3705 */
3706static void
3707xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3708{
3709    if (attr == NULL)
3710        return;
3711    if (attr->annot != NULL)
3712	xmlSchemaFreeAnnot(attr->annot);
3713    if (attr->defVal != NULL)
3714	xmlSchemaFreeValue(attr->defVal);
3715    xmlFree(attr);
3716}
3717
3718/**
3719 * xmlSchemaFreeAttributeUse:
3720 * @use:  an attribute use
3721 *
3722 * Deallocates an attribute use structure.
3723 */
3724static void
3725xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3726{
3727    if (use == NULL)
3728        return;
3729    if (use->annot != NULL)
3730	xmlSchemaFreeAnnot(use->annot);
3731    if (use->defVal != NULL)
3732	xmlSchemaFreeValue(use->defVal);
3733    xmlFree(use);
3734}
3735
3736/**
3737 * xmlSchemaFreeAttributeUseProhib:
3738 * @prohib:  an attribute use prohibition
3739 *
3740 * Deallocates an attribute use structure.
3741 */
3742static void
3743xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3744{
3745    if (prohib == NULL)
3746        return;
3747    xmlFree(prohib);
3748}
3749
3750/**
3751 * xmlSchemaFreeWildcardNsSet:
3752 * set:  a schema wildcard namespace
3753 *
3754 * Deallocates a list of wildcard constraint structures.
3755 */
3756static void
3757xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3758{
3759    xmlSchemaWildcardNsPtr next;
3760
3761    while (set != NULL) {
3762	next = set->next;
3763	xmlFree(set);
3764	set = next;
3765    }
3766}
3767
3768/**
3769 * xmlSchemaFreeWildcard:
3770 * @wildcard:  a wildcard structure
3771 *
3772 * Deallocates a wildcard structure.
3773 */
3774void
3775xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3776{
3777    if (wildcard == NULL)
3778        return;
3779    if (wildcard->annot != NULL)
3780        xmlSchemaFreeAnnot(wildcard->annot);
3781    if (wildcard->nsSet != NULL)
3782	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3783    if (wildcard->negNsSet != NULL)
3784	xmlFree(wildcard->negNsSet);
3785    xmlFree(wildcard);
3786}
3787
3788/**
3789 * xmlSchemaFreeAttributeGroup:
3790 * @schema:  a schema attribute group structure
3791 *
3792 * Deallocate a Schema Attribute Group structure.
3793 */
3794static void
3795xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3796{
3797    if (attrGr == NULL)
3798        return;
3799    if (attrGr->annot != NULL)
3800        xmlSchemaFreeAnnot(attrGr->annot);
3801    if (attrGr->attrUses != NULL)
3802	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3803    xmlFree(attrGr);
3804}
3805
3806/**
3807 * xmlSchemaFreeQNameRef:
3808 * @item: a QName reference structure
3809 *
3810 * Deallocatea a QName reference structure.
3811 */
3812static void
3813xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3814{
3815    xmlFree(item);
3816}
3817
3818/**
3819 * xmlSchemaFreeTypeLinkList:
3820 * @alink: a type link
3821 *
3822 * Deallocate a list of types.
3823 */
3824static void
3825xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3826{
3827    xmlSchemaTypeLinkPtr next;
3828
3829    while (link != NULL) {
3830	next = link->next;
3831	xmlFree(link);
3832	link = next;
3833    }
3834}
3835
3836static void
3837xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3838{
3839    xmlSchemaIDCStateObjPtr next;
3840    while (sto != NULL) {
3841	next = sto->next;
3842	if (sto->history != NULL)
3843	    xmlFree(sto->history);
3844	if (sto->xpathCtxt != NULL)
3845	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3846	xmlFree(sto);
3847	sto = next;
3848    }
3849}
3850
3851/**
3852 * xmlSchemaFreeIDC:
3853 * @idc: a identity-constraint definition
3854 *
3855 * Deallocates an identity-constraint definition.
3856 */
3857static void
3858xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3859{
3860    xmlSchemaIDCSelectPtr cur, prev;
3861
3862    if (idcDef == NULL)
3863	return;
3864    if (idcDef->annot != NULL)
3865        xmlSchemaFreeAnnot(idcDef->annot);
3866    /* Selector */
3867    if (idcDef->selector != NULL) {
3868	if (idcDef->selector->xpathComp != NULL)
3869	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3870	xmlFree(idcDef->selector);
3871    }
3872    /* Fields */
3873    if (idcDef->fields != NULL) {
3874	cur = idcDef->fields;
3875	do {
3876	    prev = cur;
3877	    cur = cur->next;
3878	    if (prev->xpathComp != NULL)
3879		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3880	    xmlFree(prev);
3881	} while (cur != NULL);
3882    }
3883    xmlFree(idcDef);
3884}
3885
3886/**
3887 * xmlSchemaFreeElement:
3888 * @schema:  a schema element structure
3889 *
3890 * Deallocate a Schema Element structure.
3891 */
3892static void
3893xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3894{
3895    if (elem == NULL)
3896        return;
3897    if (elem->annot != NULL)
3898        xmlSchemaFreeAnnot(elem->annot);
3899    if (elem->contModel != NULL)
3900        xmlRegFreeRegexp(elem->contModel);
3901    if (elem->defVal != NULL)
3902	xmlSchemaFreeValue(elem->defVal);
3903    xmlFree(elem);
3904}
3905
3906/**
3907 * xmlSchemaFreeFacet:
3908 * @facet:  a schema facet structure
3909 *
3910 * Deallocate a Schema Facet structure.
3911 */
3912void
3913xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3914{
3915    if (facet == NULL)
3916        return;
3917    if (facet->val != NULL)
3918        xmlSchemaFreeValue(facet->val);
3919    if (facet->regexp != NULL)
3920        xmlRegFreeRegexp(facet->regexp);
3921    if (facet->annot != NULL)
3922        xmlSchemaFreeAnnot(facet->annot);
3923    xmlFree(facet);
3924}
3925
3926/**
3927 * xmlSchemaFreeType:
3928 * @type:  a schema type structure
3929 *
3930 * Deallocate a Schema Type structure.
3931 */
3932void
3933xmlSchemaFreeType(xmlSchemaTypePtr type)
3934{
3935    if (type == NULL)
3936        return;
3937    if (type->annot != NULL)
3938        xmlSchemaFreeAnnot(type->annot);
3939    if (type->facets != NULL) {
3940        xmlSchemaFacetPtr facet, next;
3941
3942        facet = type->facets;
3943        while (facet != NULL) {
3944            next = facet->next;
3945            xmlSchemaFreeFacet(facet);
3946            facet = next;
3947        }
3948    }
3949    if (type->attrUses != NULL)
3950	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3951    if (type->memberTypes != NULL)
3952	xmlSchemaFreeTypeLinkList(type->memberTypes);
3953    if (type->facetSet != NULL) {
3954	xmlSchemaFacetLinkPtr next, link;
3955
3956	link = type->facetSet;
3957	do {
3958	    next = link->next;
3959	    xmlFree(link);
3960	    link = next;
3961	} while (link != NULL);
3962    }
3963    if (type->contModel != NULL)
3964        xmlRegFreeRegexp(type->contModel);
3965    xmlFree(type);
3966}
3967
3968/**
3969 * xmlSchemaFreeModelGroupDef:
3970 * @item:  a schema model group definition
3971 *
3972 * Deallocates a schema model group definition.
3973 */
3974static void
3975xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3976{
3977    if (item->annot != NULL)
3978	xmlSchemaFreeAnnot(item->annot);
3979    xmlFree(item);
3980}
3981
3982/**
3983 * xmlSchemaFreeModelGroup:
3984 * @item:  a schema model group
3985 *
3986 * Deallocates a schema model group structure.
3987 */
3988static void
3989xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3990{
3991    if (item->annot != NULL)
3992	xmlSchemaFreeAnnot(item->annot);
3993    xmlFree(item);
3994}
3995
3996static void
3997xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3998{
3999    if ((list == NULL) || (list->nbItems == 0))
4000	return;
4001    {
4002	xmlSchemaTreeItemPtr item;
4003	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4004	int i;
4005
4006	for (i = 0; i < list->nbItems; i++) {
4007	    item = items[i];
4008	    if (item == NULL)
4009		continue;
4010	    switch (item->type) {
4011		case XML_SCHEMA_TYPE_SIMPLE:
4012		case XML_SCHEMA_TYPE_COMPLEX:
4013		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4014		    break;
4015		case XML_SCHEMA_TYPE_ATTRIBUTE:
4016		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4017		    break;
4018		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4019		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4020		    break;
4021		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4022		    xmlSchemaFreeAttributeUseProhib(
4023			(xmlSchemaAttributeUseProhibPtr) item);
4024		    break;
4025		case XML_SCHEMA_TYPE_ELEMENT:
4026		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4027		    break;
4028		case XML_SCHEMA_TYPE_PARTICLE:
4029		    if (item->annot != NULL)
4030			xmlSchemaFreeAnnot(item->annot);
4031		    xmlFree(item);
4032		    break;
4033		case XML_SCHEMA_TYPE_SEQUENCE:
4034		case XML_SCHEMA_TYPE_CHOICE:
4035		case XML_SCHEMA_TYPE_ALL:
4036		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4037		    break;
4038		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4039		    xmlSchemaFreeAttributeGroup(
4040			(xmlSchemaAttributeGroupPtr) item);
4041		    break;
4042		case XML_SCHEMA_TYPE_GROUP:
4043		    xmlSchemaFreeModelGroupDef(
4044			(xmlSchemaModelGroupDefPtr) item);
4045		    break;
4046		case XML_SCHEMA_TYPE_ANY:
4047		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4048		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4049		    break;
4050		case XML_SCHEMA_TYPE_IDC_KEY:
4051		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4052		case XML_SCHEMA_TYPE_IDC_KEYREF:
4053		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4054		    break;
4055		case XML_SCHEMA_TYPE_NOTATION:
4056		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4057		    break;
4058		case XML_SCHEMA_EXTRA_QNAMEREF:
4059		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4060		    break;
4061		default: {
4062		    /* TODO: This should never be hit. */
4063		    xmlSchemaPSimpleInternalErr(NULL,
4064			"Internal error: xmlSchemaComponentListFree, "
4065			"unexpected component type '%s'\n",
4066			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4067			 }
4068		    break;
4069	    }
4070	}
4071	list->nbItems = 0;
4072    }
4073}
4074
4075/**
4076 * xmlSchemaFree:
4077 * @schema:  a schema structure
4078 *
4079 * Deallocate a Schema structure.
4080 */
4081void
4082xmlSchemaFree(xmlSchemaPtr schema)
4083{
4084    if (schema == NULL)
4085        return;
4086    /* @volatiles is not used anymore :-/ */
4087    if (schema->volatiles != NULL)
4088	TODO
4089    /*
4090    * Note that those slots are not responsible for freeing
4091    * schema components anymore; this will now be done by
4092    * the schema buckets.
4093    */
4094    if (schema->notaDecl != NULL)
4095        xmlHashFree(schema->notaDecl, NULL);
4096    if (schema->attrDecl != NULL)
4097        xmlHashFree(schema->attrDecl, NULL);
4098    if (schema->attrgrpDecl != NULL)
4099        xmlHashFree(schema->attrgrpDecl, NULL);
4100    if (schema->elemDecl != NULL)
4101        xmlHashFree(schema->elemDecl, NULL);
4102    if (schema->typeDecl != NULL)
4103        xmlHashFree(schema->typeDecl, NULL);
4104    if (schema->groupDecl != NULL)
4105        xmlHashFree(schema->groupDecl, NULL);
4106    if (schema->idcDef != NULL)
4107        xmlHashFree(schema->idcDef, NULL);
4108
4109    if (schema->schemasImports != NULL)
4110	xmlHashFree(schema->schemasImports,
4111		    (xmlHashDeallocator) xmlSchemaBucketFree);
4112    if (schema->includes != NULL) {
4113	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4114	int i;
4115	for (i = 0; i < list->nbItems; i++) {
4116	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4117	}
4118	xmlSchemaItemListFree(list);
4119    }
4120    if (schema->annot != NULL)
4121        xmlSchemaFreeAnnot(schema->annot);
4122    /* Never free the doc here, since this will be done by the buckets. */
4123
4124    xmlDictFree(schema->dict);
4125    xmlFree(schema);
4126}
4127
4128/************************************************************************
4129 * 									*
4130 * 			Debug functions					*
4131 * 									*
4132 ************************************************************************/
4133
4134#ifdef LIBXML_OUTPUT_ENABLED
4135
4136static void
4137xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4138
4139/**
4140 * xmlSchemaElementDump:
4141 * @elem:  an element
4142 * @output:  the file output
4143 *
4144 * Dump the element
4145 */
4146static void
4147xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4148                     const xmlChar * name ATTRIBUTE_UNUSED,
4149		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4150                     const xmlChar * context ATTRIBUTE_UNUSED)
4151{
4152    if (elem == NULL)
4153        return;
4154
4155
4156    fprintf(output, "Element");
4157    if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4158	fprintf(output, " (global)");
4159    fprintf(output, ": '%s' ", elem->name);
4160    if (namespace != NULL)
4161	fprintf(output, "ns '%s'", namespace);
4162    fprintf(output, "\n");
4163#if 0
4164    if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4165	fprintf(output, "  min %d ", elem->minOccurs);
4166        if (elem->maxOccurs >= UNBOUNDED)
4167            fprintf(output, "max: unbounded\n");
4168        else if (elem->maxOccurs != 1)
4169            fprintf(output, "max: %d\n", elem->maxOccurs);
4170        else
4171            fprintf(output, "\n");
4172    }
4173#endif
4174    /*
4175    * Misc other properties.
4176    */
4177    if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4178	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4179	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4180	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4181	fprintf(output, "  props: ");
4182	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4183	    fprintf(output, "[fixed] ");
4184	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4185	    fprintf(output, "[default] ");
4186	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4187	    fprintf(output, "[abstract] ");
4188	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4189	    fprintf(output, "[nillable] ");
4190	fprintf(output, "\n");
4191    }
4192    /*
4193    * Default/fixed value.
4194    */
4195    if (elem->value != NULL)
4196	fprintf(output, "  value: '%s'\n", elem->value);
4197    /*
4198    * Type.
4199    */
4200    if (elem->namedType != NULL) {
4201	fprintf(output, "  type: '%s' ", elem->namedType);
4202	if (elem->namedTypeNs != NULL)
4203	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4204	else
4205	    fprintf(output, "\n");
4206    } else if (elem->subtypes != NULL) {
4207	/*
4208	* Dump local types.
4209	*/
4210	xmlSchemaTypeDump(elem->subtypes, output);
4211    }
4212    /*
4213    * Substitution group.
4214    */
4215    if (elem->substGroup != NULL) {
4216	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4217	if (elem->substGroupNs != NULL)
4218	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4219	else
4220	    fprintf(output, "\n");
4221    }
4222}
4223
4224/**
4225 * xmlSchemaAnnotDump:
4226 * @output:  the file output
4227 * @annot:  a annotation
4228 *
4229 * Dump the annotation
4230 */
4231static void
4232xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4233{
4234    xmlChar *content;
4235
4236    if (annot == NULL)
4237        return;
4238
4239    content = xmlNodeGetContent(annot->content);
4240    if (content != NULL) {
4241        fprintf(output, "  Annot: %s\n", content);
4242        xmlFree(content);
4243    } else
4244        fprintf(output, "  Annot: empty\n");
4245}
4246
4247/**
4248 * xmlSchemaContentModelDump:
4249 * @particle: the schema particle
4250 * @output: the file output
4251 * @depth: the depth used for intentation
4252 *
4253 * Dump a SchemaType structure
4254 */
4255static void
4256xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4257{
4258    xmlChar *str = NULL;
4259    xmlSchemaTreeItemPtr term;
4260    char shift[100];
4261    int i;
4262
4263    if (particle == NULL)
4264	return;
4265    for (i = 0;((i < depth) && (i < 25));i++)
4266        shift[2 * i] = shift[2 * i + 1] = ' ';
4267    shift[2 * i] = shift[2 * i + 1] = 0;
4268    fprintf(output, shift);
4269    if (particle->children == NULL) {
4270	fprintf(output, "MISSING particle term\n");
4271	return;
4272    }
4273    term = particle->children;
4274    if (term == NULL) {
4275	fprintf(output, "(NULL)");
4276    } else {
4277	switch (term->type) {
4278	    case XML_SCHEMA_TYPE_ELEMENT:
4279		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4280		    ((xmlSchemaElementPtr)term)->targetNamespace,
4281		    ((xmlSchemaElementPtr)term)->name));
4282		FREE_AND_NULL(str);
4283		break;
4284	    case XML_SCHEMA_TYPE_SEQUENCE:
4285		fprintf(output, "SEQUENCE");
4286		break;
4287	    case XML_SCHEMA_TYPE_CHOICE:
4288		fprintf(output, "CHOICE");
4289		break;
4290	    case XML_SCHEMA_TYPE_ALL:
4291		fprintf(output, "ALL");
4292		break;
4293	    case XML_SCHEMA_TYPE_ANY:
4294		fprintf(output, "ANY");
4295		break;
4296	    default:
4297		fprintf(output, "UNKNOWN\n");
4298		return;
4299	}
4300    }
4301    if (particle->minOccurs != 1)
4302	fprintf(output, " min: %d", particle->minOccurs);
4303    if (particle->maxOccurs >= UNBOUNDED)
4304	fprintf(output, " max: unbounded");
4305    else if (particle->maxOccurs != 1)
4306	fprintf(output, " max: %d", particle->maxOccurs);
4307    fprintf(output, "\n");
4308    if (term &&
4309	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4310	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4311	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4312	 (term->children != NULL)) {
4313	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4314	    output, depth +1);
4315    }
4316    if (particle->next != NULL)
4317	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4318		output, depth);
4319}
4320
4321/**
4322 * xmlSchemaAttrUsesDump:
4323 * @uses:  attribute uses list
4324 * @output:  the file output
4325 *
4326 * Dumps a list of attribute use components.
4327 */
4328static void
4329xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4330{
4331    xmlSchemaAttributeUsePtr use;
4332    xmlSchemaAttributeUseProhibPtr prohib;
4333    xmlSchemaQNameRefPtr ref;
4334    const xmlChar *name, *tns;
4335    xmlChar *str = NULL;
4336    int i;
4337
4338    if ((uses == NULL) || (uses->nbItems == 0))
4339        return;
4340
4341    fprintf(output, "  attributes:\n");
4342    for (i = 0; i < uses->nbItems; i++) {
4343	use = uses->items[i];
4344	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4345	    fprintf(output, "  [prohibition] ");
4346	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4347	    name = prohib->name;
4348	    tns = prohib->targetNamespace;
4349	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4350	    fprintf(output, "  [reference] ");
4351	    ref = (xmlSchemaQNameRefPtr) use;
4352	    name = ref->name;
4353	    tns = ref->targetNamespace;
4354	} else {
4355	    fprintf(output, "  [use] ");
4356	    name = WXS_ATTRUSE_DECL_NAME(use);
4357	    tns = WXS_ATTRUSE_DECL_TNS(use);
4358	}
4359	fprintf(output, "'%s'\n",
4360	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4361	FREE_AND_NULL(str);
4362    }
4363}
4364
4365/**
4366 * xmlSchemaTypeDump:
4367 * @output:  the file output
4368 * @type:  a type structure
4369 *
4370 * Dump a SchemaType structure
4371 */
4372static void
4373xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4374{
4375    if (type == NULL) {
4376        fprintf(output, "Type: NULL\n");
4377        return;
4378    }
4379    fprintf(output, "Type: ");
4380    if (type->name != NULL)
4381        fprintf(output, "'%s' ", type->name);
4382    else
4383        fprintf(output, "(no name) ");
4384    if (type->targetNamespace != NULL)
4385	fprintf(output, "ns '%s' ", type->targetNamespace);
4386    switch (type->type) {
4387        case XML_SCHEMA_TYPE_BASIC:
4388            fprintf(output, "[basic] ");
4389            break;
4390        case XML_SCHEMA_TYPE_SIMPLE:
4391            fprintf(output, "[simple] ");
4392            break;
4393        case XML_SCHEMA_TYPE_COMPLEX:
4394            fprintf(output, "[complex] ");
4395            break;
4396        case XML_SCHEMA_TYPE_SEQUENCE:
4397            fprintf(output, "[sequence] ");
4398            break;
4399        case XML_SCHEMA_TYPE_CHOICE:
4400            fprintf(output, "[choice] ");
4401            break;
4402        case XML_SCHEMA_TYPE_ALL:
4403            fprintf(output, "[all] ");
4404            break;
4405        case XML_SCHEMA_TYPE_UR:
4406            fprintf(output, "[ur] ");
4407            break;
4408        case XML_SCHEMA_TYPE_RESTRICTION:
4409            fprintf(output, "[restriction] ");
4410            break;
4411        case XML_SCHEMA_TYPE_EXTENSION:
4412            fprintf(output, "[extension] ");
4413            break;
4414        default:
4415            fprintf(output, "[unknown type %d] ", type->type);
4416            break;
4417    }
4418    fprintf(output, "content: ");
4419    switch (type->contentType) {
4420        case XML_SCHEMA_CONTENT_UNKNOWN:
4421            fprintf(output, "[unknown] ");
4422            break;
4423        case XML_SCHEMA_CONTENT_EMPTY:
4424            fprintf(output, "[empty] ");
4425            break;
4426        case XML_SCHEMA_CONTENT_ELEMENTS:
4427            fprintf(output, "[element] ");
4428            break;
4429        case XML_SCHEMA_CONTENT_MIXED:
4430            fprintf(output, "[mixed] ");
4431            break;
4432        case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4433	/* not used. */
4434            break;
4435        case XML_SCHEMA_CONTENT_BASIC:
4436            fprintf(output, "[basic] ");
4437            break;
4438        case XML_SCHEMA_CONTENT_SIMPLE:
4439            fprintf(output, "[simple] ");
4440            break;
4441        case XML_SCHEMA_CONTENT_ANY:
4442            fprintf(output, "[any] ");
4443            break;
4444    }
4445    fprintf(output, "\n");
4446    if (type->base != NULL) {
4447        fprintf(output, "  base type: '%s'", type->base);
4448	if (type->baseNs != NULL)
4449	    fprintf(output, " ns '%s'\n", type->baseNs);
4450	else
4451	    fprintf(output, "\n");
4452    }
4453    if (type->attrUses != NULL)
4454	xmlSchemaAttrUsesDump(type->attrUses, output);
4455    if (type->annot != NULL)
4456        xmlSchemaAnnotDump(output, type->annot);
4457#ifdef DUMP_CONTENT_MODEL
4458    if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4459	(type->subtypes != NULL)) {
4460	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4461	    output, 1);
4462    }
4463#endif
4464}
4465
4466/**
4467 * xmlSchemaDump:
4468 * @output:  the file output
4469 * @schema:  a schema structure
4470 *
4471 * Dump a Schema structure.
4472 */
4473void
4474xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4475{
4476    if (output == NULL)
4477        return;
4478    if (schema == NULL) {
4479        fprintf(output, "Schemas: NULL\n");
4480        return;
4481    }
4482    fprintf(output, "Schemas: ");
4483    if (schema->name != NULL)
4484        fprintf(output, "%s, ", schema->name);
4485    else
4486        fprintf(output, "no name, ");
4487    if (schema->targetNamespace != NULL)
4488        fprintf(output, "%s", (const char *) schema->targetNamespace);
4489    else
4490        fprintf(output, "no target namespace");
4491    fprintf(output, "\n");
4492    if (schema->annot != NULL)
4493        xmlSchemaAnnotDump(output, schema->annot);
4494    xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4495                output);
4496    xmlHashScanFull(schema->elemDecl,
4497                    (xmlHashScannerFull) xmlSchemaElementDump, output);
4498}
4499
4500#ifdef DEBUG_IDC_NODE_TABLE
4501/**
4502 * xmlSchemaDebugDumpIDCTable:
4503 * @vctxt: the WXS validation context
4504 *
4505 * Displays the current IDC table for debug purposes.
4506 */
4507static void
4508xmlSchemaDebugDumpIDCTable(FILE * output,
4509			   const xmlChar *namespaceName,
4510			   const xmlChar *localName,
4511			   xmlSchemaPSVIIDCBindingPtr bind)
4512{
4513    xmlChar *str = NULL;
4514    const xmlChar *value;
4515    xmlSchemaPSVIIDCNodePtr tab;
4516    xmlSchemaPSVIIDCKeyPtr key;
4517    int i, j, res;
4518
4519    fprintf(output, "IDC: TABLES on '%s'\n",
4520	xmlSchemaFormatQName(&str, namespaceName, localName));
4521    FREE_AND_NULL(str)
4522
4523    if (bind == NULL)
4524	return;
4525    do {
4526	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4527	    xmlSchemaGetComponentQName(&str,
4528		bind->definition), bind->nbNodes);
4529	FREE_AND_NULL(str)
4530	for (i = 0; i < bind->nbNodes; i++) {
4531	    tab = bind->nodeTable[i];
4532	    fprintf(output, "         ( ");
4533	    for (j = 0; j < bind->definition->nbFields; j++) {
4534		key = tab->keys[j];
4535		if ((key != NULL) && (key->val != NULL)) {
4536		    res = xmlSchemaGetCanonValue(key->val, &value);
4537		    if (res >= 0)
4538			fprintf(output, "'%s' ", value);
4539		    else
4540			fprintf(output, "CANON-VALUE-FAILED ");
4541		    if (res == 0)
4542			FREE_AND_NULL(value)
4543		} else if (key != NULL)
4544		    fprintf(output, "(no val), ");
4545		else
4546		    fprintf(output, "(key missing), ");
4547	    }
4548	    fprintf(output, ")\n");
4549	}
4550	if (bind->dupls && bind->dupls->nbItems) {
4551	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4552	    for (i = 0; i < bind->dupls->nbItems; i++) {
4553		tab = bind->dupls->items[i];
4554		fprintf(output, "         ( ");
4555		for (j = 0; j < bind->definition->nbFields; j++) {
4556		    key = tab->keys[j];
4557		    if ((key != NULL) && (key->val != NULL)) {
4558			res = xmlSchemaGetCanonValue(key->val, &value);
4559			if (res >= 0)
4560			    fprintf(output, "'%s' ", value);
4561			else
4562			    fprintf(output, "CANON-VALUE-FAILED ");
4563			if (res == 0)
4564			    FREE_AND_NULL(value)
4565		    } else if (key != NULL)
4566		    fprintf(output, "(no val), ");
4567			else
4568			    fprintf(output, "(key missing), ");
4569		}
4570		fprintf(output, ")\n");
4571	    }
4572	}
4573	bind = bind->next;
4574    } while (bind != NULL);
4575}
4576#endif /* DEBUG_IDC */
4577#endif /* LIBXML_OUTPUT_ENABLED */
4578
4579/************************************************************************
4580 *									*
4581 * 			Utilities					*
4582 *									*
4583 ************************************************************************/
4584
4585/**
4586 * xmlSchemaGetPropNode:
4587 * @node: the element node
4588 * @name: the name of the attribute
4589 *
4590 * Seeks an attribute with a name of @name in
4591 * no namespace.
4592 *
4593 * Returns the attribute or NULL if not present.
4594 */
4595static xmlAttrPtr
4596xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4597{
4598    xmlAttrPtr prop;
4599
4600    if ((node == NULL) || (name == NULL))
4601	return(NULL);
4602    prop = node->properties;
4603    while (prop != NULL) {
4604        if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4605	    return(prop);
4606	prop = prop->next;
4607    }
4608    return (NULL);
4609}
4610
4611/**
4612 * xmlSchemaGetPropNodeNs:
4613 * @node: the element node
4614 * @uri: the uri
4615 * @name: the name of the attribute
4616 *
4617 * Seeks an attribute with a local name of @name and
4618 * a namespace URI of @uri.
4619 *
4620 * Returns the attribute or NULL if not present.
4621 */
4622static xmlAttrPtr
4623xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4624{
4625    xmlAttrPtr prop;
4626
4627    if ((node == NULL) || (name == NULL))
4628	return(NULL);
4629    prop = node->properties;
4630    while (prop != NULL) {
4631	if ((prop->ns != NULL) &&
4632	    xmlStrEqual(prop->name, BAD_CAST name) &&
4633	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4634	    return(prop);
4635	prop = prop->next;
4636    }
4637    return (NULL);
4638}
4639
4640static const xmlChar *
4641xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4642{
4643    xmlChar *val;
4644    const xmlChar *ret;
4645
4646    val = xmlNodeGetContent(node);
4647    if (val == NULL)
4648	val = xmlStrdup((xmlChar *)"");
4649    ret = xmlDictLookup(ctxt->dict, val, -1);
4650    xmlFree(val);
4651    return(ret);
4652}
4653
4654static const xmlChar *
4655xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4656{
4657    return((const xmlChar*) xmlNodeGetContent(node));
4658}
4659
4660/**
4661 * xmlSchemaGetProp:
4662 * @ctxt: the parser context
4663 * @node: the node
4664 * @name: the property name
4665 *
4666 * Read a attribute value and internalize the string
4667 *
4668 * Returns the string or NULL if not present.
4669 */
4670static const xmlChar *
4671xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4672                 const char *name)
4673{
4674    xmlChar *val;
4675    const xmlChar *ret;
4676
4677    val = xmlGetNoNsProp(node, BAD_CAST name);
4678    if (val == NULL)
4679        return(NULL);
4680    ret = xmlDictLookup(ctxt->dict, val, -1);
4681    xmlFree(val);
4682    return(ret);
4683}
4684
4685/************************************************************************
4686 * 									*
4687 * 			Parsing functions				*
4688 * 									*
4689 ************************************************************************/
4690
4691#define WXS_FIND_GLOBAL_ITEM(slot)			\
4692    if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4693	ret = xmlHashLookup(schema->slot, name); \
4694	if (ret != NULL) goto exit; \
4695    } \
4696    if (xmlHashSize(schema->schemasImports) > 1) { \
4697	xmlSchemaImportPtr import; \
4698	if (nsName == NULL) \
4699	    import = xmlHashLookup(schema->schemasImports, \
4700		XML_SCHEMAS_NO_NAMESPACE); \
4701	else \
4702	    import = xmlHashLookup(schema->schemasImports, nsName); \
4703	if (import == NULL) \
4704	    goto exit; \
4705	ret = xmlHashLookup(import->schema->slot, name); \
4706    }
4707
4708/**
4709 * xmlSchemaGetElem:
4710 * @schema:  the schema context
4711 * @name:  the element name
4712 * @ns:  the element namespace
4713 *
4714 * Lookup a global element declaration in the schema.
4715 *
4716 * Returns the element declaration or NULL if not found.
4717 */
4718static xmlSchemaElementPtr
4719xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4720                 const xmlChar * nsName)
4721{
4722    xmlSchemaElementPtr ret = NULL;
4723
4724    if ((name == NULL) || (schema == NULL))
4725        return(NULL);
4726    if (schema != NULL) {
4727	WXS_FIND_GLOBAL_ITEM(elemDecl)
4728    }
4729exit:
4730#ifdef DEBUG
4731    if (ret == NULL) {
4732        if (nsName == NULL)
4733            fprintf(stderr, "Unable to lookup element decl. %s", name);
4734        else
4735            fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4736                    nsName);
4737    }
4738#endif
4739    return (ret);
4740}
4741
4742/**
4743 * xmlSchemaGetType:
4744 * @schema:  the main schema
4745 * @name:  the type's name
4746 * nsName:  the type's namespace
4747 *
4748 * Lookup a type in the schemas or the predefined types
4749 *
4750 * Returns the group definition or NULL if not found.
4751 */
4752static xmlSchemaTypePtr
4753xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4754                 const xmlChar * nsName)
4755{
4756    xmlSchemaTypePtr ret = NULL;
4757
4758    if (name == NULL)
4759        return (NULL);
4760    /* First try the built-in types. */
4761    if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4762	ret = xmlSchemaGetPredefinedType(name, nsName);
4763	if (ret != NULL)
4764	    goto exit;
4765	/*
4766	* Note that we try the parsed schemas as well here
4767	* since one might have parsed the S4S, which contain more
4768	* than the built-in types.
4769	* TODO: Can we optimize this?
4770	*/
4771    }
4772    if (schema != NULL) {
4773	WXS_FIND_GLOBAL_ITEM(typeDecl)
4774    }
4775exit:
4776
4777#ifdef DEBUG
4778    if (ret == NULL) {
4779        if (nsName == NULL)
4780            fprintf(stderr, "Unable to lookup type %s", name);
4781        else
4782            fprintf(stderr, "Unable to lookup type %s:%s", name,
4783                    nsName);
4784    }
4785#endif
4786    return (ret);
4787}
4788
4789/**
4790 * xmlSchemaGetAttributeDecl:
4791 * @schema:  the context of the schema
4792 * @name:  the name of the attribute
4793 * @ns:  the target namespace of the attribute
4794 *
4795 * Lookup a an attribute in the schema or imported schemas
4796 *
4797 * Returns the attribute declaration or NULL if not found.
4798 */
4799static xmlSchemaAttributePtr
4800xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4801                 const xmlChar * nsName)
4802{
4803    xmlSchemaAttributePtr ret = NULL;
4804
4805    if ((name == NULL) || (schema == NULL))
4806        return (NULL);
4807    if (schema != NULL) {
4808	WXS_FIND_GLOBAL_ITEM(attrDecl)
4809    }
4810exit:
4811#ifdef DEBUG
4812    if (ret == NULL) {
4813        if (nsName == NULL)
4814            fprintf(stderr, "Unable to lookup attribute %s", name);
4815        else
4816            fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4817                    nsName);
4818    }
4819#endif
4820    return (ret);
4821}
4822
4823/**
4824 * xmlSchemaGetAttributeGroup:
4825 * @schema:  the context of the schema
4826 * @name:  the name of the attribute group
4827 * @ns:  the target namespace of the attribute group
4828 *
4829 * Lookup a an attribute group in the schema or imported schemas
4830 *
4831 * Returns the attribute group definition or NULL if not found.
4832 */
4833static xmlSchemaAttributeGroupPtr
4834xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4835                 const xmlChar * nsName)
4836{
4837    xmlSchemaAttributeGroupPtr ret = NULL;
4838
4839    if ((name == NULL) || (schema == NULL))
4840        return (NULL);
4841    if (schema != NULL) {
4842	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4843    }
4844exit:
4845    /* TODO:
4846    if ((ret != NULL) && (ret->redef != NULL)) {
4847	* Return the last redefinition. *
4848	ret = ret->redef;
4849    }
4850    */
4851#ifdef DEBUG
4852    if (ret == NULL) {
4853        if (nsName == NULL)
4854            fprintf(stderr, "Unable to lookup attribute group %s", name);
4855        else
4856            fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4857                    nsName);
4858    }
4859#endif
4860    return (ret);
4861}
4862
4863/**
4864 * xmlSchemaGetGroup:
4865 * @schema:  the context of the schema
4866 * @name:  the name of the group
4867 * @ns:  the target namespace of the group
4868 *
4869 * Lookup a group in the schema or imported schemas
4870 *
4871 * Returns the group definition or NULL if not found.
4872 */
4873static xmlSchemaModelGroupDefPtr
4874xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4875                 const xmlChar * nsName)
4876{
4877    xmlSchemaModelGroupDefPtr ret = NULL;
4878
4879    if ((name == NULL) || (schema == NULL))
4880        return (NULL);
4881    if (schema != NULL) {
4882	WXS_FIND_GLOBAL_ITEM(groupDecl)
4883    }
4884exit:
4885
4886#ifdef DEBUG
4887    if (ret == NULL) {
4888        if (nsName == NULL)
4889            fprintf(stderr, "Unable to lookup group %s", name);
4890        else
4891            fprintf(stderr, "Unable to lookup group %s:%s", name,
4892                    nsName);
4893    }
4894#endif
4895    return (ret);
4896}
4897
4898static xmlSchemaNotationPtr
4899xmlSchemaGetNotation(xmlSchemaPtr schema,
4900		     const xmlChar *name,
4901		     const xmlChar *nsName)
4902{
4903    xmlSchemaNotationPtr ret = NULL;
4904
4905    if ((name == NULL) || (schema == NULL))
4906        return (NULL);
4907    if (schema != NULL) {
4908	WXS_FIND_GLOBAL_ITEM(notaDecl)
4909    }
4910exit:
4911    return (ret);
4912}
4913
4914static xmlSchemaIDCPtr
4915xmlSchemaGetIDC(xmlSchemaPtr schema,
4916		const xmlChar *name,
4917		const xmlChar *nsName)
4918{
4919    xmlSchemaIDCPtr ret = NULL;
4920
4921    if ((name == NULL) || (schema == NULL))
4922        return (NULL);
4923    if (schema != NULL) {
4924	WXS_FIND_GLOBAL_ITEM(idcDef)
4925    }
4926exit:
4927    return (ret);
4928}
4929
4930/**
4931 * xmlSchemaGetNamedComponent:
4932 * @schema:  the schema
4933 * @name:  the name of the group
4934 * @ns:  the target namespace of the group
4935 *
4936 * Lookup a group in the schema or imported schemas
4937 *
4938 * Returns the group definition or NULL if not found.
4939 */
4940static xmlSchemaBasicItemPtr
4941xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4942			   xmlSchemaTypeType itemType,
4943			   const xmlChar *name,
4944			   const xmlChar *targetNs)
4945{
4946    switch (itemType) {
4947	case XML_SCHEMA_TYPE_GROUP:
4948	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4949		name, targetNs));
4950	case XML_SCHEMA_TYPE_ELEMENT:
4951	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4952		name, targetNs));
4953	default:
4954	    TODO
4955	    return (NULL);
4956    }
4957}
4958
4959/************************************************************************
4960 * 									*
4961 * 			Parsing functions				*
4962 * 									*
4963 ************************************************************************/
4964
4965#define IS_BLANK_NODE(n)						\
4966    (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4967
4968/**
4969 * xmlSchemaIsBlank:
4970 * @str:  a string
4971 * @len: the length of the string or -1
4972 *
4973 * Check if a string is ignorable
4974 *
4975 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4976 */
4977static int
4978xmlSchemaIsBlank(xmlChar * str, int len)
4979{
4980    if (str == NULL)
4981        return (1);
4982    if (len < 0) {
4983	while (*str != 0) {
4984	    if (!(IS_BLANK_CH(*str)))
4985		return (0);
4986	    str++;
4987	}
4988    } else while ((*str != 0) && (len != 0)) {
4989	if (!(IS_BLANK_CH(*str)))
4990	    return (0);
4991	str++;
4992	len--;
4993    }
4994
4995    return (1);
4996}
4997
4998#define WXS_COMP_NAME(c, t) ((t) (c))->name
4999#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5000/*
5001* xmlSchemaFindRedefCompInGraph:
5002* ATTENTION TODO: This uses pointer comp. for strings.
5003*/
5004static xmlSchemaBasicItemPtr
5005xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5006			      xmlSchemaTypeType type,
5007			      const xmlChar *name,
5008			      const xmlChar *nsName)
5009{
5010    xmlSchemaBasicItemPtr ret;
5011    int i;
5012
5013    if ((bucket == NULL) || (name == NULL))
5014	return(NULL);
5015    if ((bucket->globals == NULL) ||
5016	(bucket->globals->nbItems == 0))
5017	goto subschemas;
5018    /*
5019    * Search in global components.
5020    */
5021    for (i = 0; i < bucket->globals->nbItems; i++) {
5022	ret = bucket->globals->items[i];
5023	if (ret->type == type) {
5024	    switch (type) {
5025		case XML_SCHEMA_TYPE_COMPLEX:
5026		case XML_SCHEMA_TYPE_SIMPLE:
5027		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5028			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5029			nsName))
5030		    {
5031			return(ret);
5032		    }
5033		    break;
5034		case XML_SCHEMA_TYPE_GROUP:
5035		    if ((WXS_COMP_NAME(ret,
5036			    xmlSchemaModelGroupDefPtr) == name) &&
5037			(WXS_COMP_TNS(ret,
5038			    xmlSchemaModelGroupDefPtr) == nsName))
5039		    {
5040			return(ret);
5041		    }
5042		    break;
5043		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5044		    if ((WXS_COMP_NAME(ret,
5045			    xmlSchemaAttributeGroupPtr) == name) &&
5046			(WXS_COMP_TNS(ret,
5047			    xmlSchemaAttributeGroupPtr) == nsName))
5048		    {
5049			return(ret);
5050		    }
5051		    break;
5052		default:
5053		    /* Should not be hit. */
5054		    return(NULL);
5055	    }
5056	}
5057    }
5058subschemas:
5059    /*
5060    * Process imported/included schemas.
5061    */
5062    if (bucket->relations != NULL) {
5063	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5064
5065	/*
5066	* TODO: Marking the bucket will not avoid multiple searches
5067	* in the same schema, but avoids at least circularity.
5068	*/
5069	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5070	do {
5071	    if ((rel->bucket != NULL) &&
5072		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5073		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5074		    type, name, nsName);
5075		if (ret != NULL)
5076		    return(ret);
5077	    }
5078	    rel = rel->next;
5079	} while (rel != NULL);
5080	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5081    }
5082    return(NULL);
5083}
5084
5085/**
5086 * xmlSchemaAddNotation:
5087 * @ctxt:  a schema parser context
5088 * @schema:  the schema being built
5089 * @name:  the item name
5090 *
5091 * Add an XML schema annotation declaration
5092 * *WARNING* this interface is highly subject to change
5093 *
5094 * Returns the new struture or NULL in case of error
5095 */
5096static xmlSchemaNotationPtr
5097xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5098                     const xmlChar *name, const xmlChar *nsName,
5099		     xmlNodePtr node ATTRIBUTE_UNUSED)
5100{
5101    xmlSchemaNotationPtr ret = NULL;
5102
5103    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5104        return (NULL);
5105
5106    ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5107    if (ret == NULL) {
5108        xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5109        return (NULL);
5110    }
5111    memset(ret, 0, sizeof(xmlSchemaNotation));
5112    ret->type = XML_SCHEMA_TYPE_NOTATION;
5113    ret->name = name;
5114    ret->targetNamespace = nsName;
5115    /* TODO: do we need the node to be set?
5116    * ret->node = node;*/
5117    WXS_ADD_GLOBAL(ctxt, ret);
5118    return (ret);
5119}
5120
5121/**
5122 * xmlSchemaAddAttribute:
5123 * @ctxt:  a schema parser context
5124 * @schema:  the schema being built
5125 * @name:  the item name
5126 * @namespace:  the namespace
5127 *
5128 * Add an XML schema Attrribute declaration
5129 * *WARNING* this interface is highly subject to change
5130 *
5131 * Returns the new struture or NULL in case of error
5132 */
5133static xmlSchemaAttributePtr
5134xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5135                      const xmlChar * name, const xmlChar * nsName,
5136		      xmlNodePtr node, int topLevel)
5137{
5138    xmlSchemaAttributePtr ret = NULL;
5139
5140    if ((ctxt == NULL) || (schema == NULL))
5141        return (NULL);
5142
5143    ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5144    if (ret == NULL) {
5145        xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5146        return (NULL);
5147    }
5148    memset(ret, 0, sizeof(xmlSchemaAttribute));
5149    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5150    ret->node = node;
5151    ret->name = name;
5152    ret->targetNamespace = nsName;
5153
5154    if (topLevel)
5155	WXS_ADD_GLOBAL(ctxt, ret);
5156    else
5157	WXS_ADD_LOCAL(ctxt, ret);
5158    WXS_ADD_PENDING(ctxt, ret);
5159    return (ret);
5160}
5161
5162/**
5163 * xmlSchemaAddAttributeUse:
5164 * @ctxt:  a schema parser context
5165 * @schema:  the schema being built
5166 * @name:  the item name
5167 * @namespace:  the namespace
5168 *
5169 * Add an XML schema Attrribute declaration
5170 * *WARNING* this interface is highly subject to change
5171 *
5172 * Returns the new struture or NULL in case of error
5173 */
5174static xmlSchemaAttributeUsePtr
5175xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5176			 xmlNodePtr node)
5177{
5178    xmlSchemaAttributeUsePtr ret = NULL;
5179
5180    if (pctxt == NULL)
5181        return (NULL);
5182
5183    ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5184    if (ret == NULL) {
5185        xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5186        return (NULL);
5187    }
5188    memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5189    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5190    ret->node = node;
5191
5192    WXS_ADD_LOCAL(pctxt, ret);
5193    return (ret);
5194}
5195
5196/*
5197* xmlSchemaAddRedef:
5198*
5199* Adds a redefinition information. This is used at a later stage to:
5200* resolve references to the redefined components and to check constraints.
5201*/
5202static xmlSchemaRedefPtr
5203xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5204		  xmlSchemaBucketPtr targetBucket,
5205		  void *item,
5206		  const xmlChar *refName,
5207		  const xmlChar *refTargetNs)
5208{
5209    xmlSchemaRedefPtr ret;
5210
5211    ret = (xmlSchemaRedefPtr)
5212	xmlMalloc(sizeof(xmlSchemaRedef));
5213    if (ret == NULL) {
5214	xmlSchemaPErrMemory(pctxt,
5215	    "allocating redefinition info", NULL);
5216	return (NULL);
5217    }
5218    memset(ret, 0, sizeof(xmlSchemaRedef));
5219    ret->item = item;
5220    ret->targetBucket = targetBucket;
5221    ret->refName = refName;
5222    ret->refTargetNs = refTargetNs;
5223    if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5224	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5225    else
5226	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5227    WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5228
5229    return (ret);
5230}
5231
5232/**
5233 * xmlSchemaAddAttributeGroupDefinition:
5234 * @ctxt:  a schema parser context
5235 * @schema:  the schema being built
5236 * @name:  the item name
5237 * @nsName:  the target namespace
5238 * @node: the corresponding node
5239 *
5240 * Add an XML schema Attrribute Group definition.
5241 *
5242 * Returns the new struture or NULL in case of error
5243 */
5244static xmlSchemaAttributeGroupPtr
5245xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5246                           xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5247			   const xmlChar *name,
5248			   const xmlChar *nsName,
5249			   xmlNodePtr node)
5250{
5251    xmlSchemaAttributeGroupPtr ret = NULL;
5252
5253    if ((pctxt == NULL) || (name == NULL))
5254        return (NULL);
5255
5256    ret = (xmlSchemaAttributeGroupPtr)
5257        xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5258    if (ret == NULL) {
5259	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5260	return (NULL);
5261    }
5262    memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5263    ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5264    ret->name = name;
5265    ret->targetNamespace = nsName;
5266    ret->node = node;
5267
5268    /* TODO: Remove the flag. */
5269    ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5270    if (pctxt->isRedefine) {
5271	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5272	    ret, name, nsName);
5273	if (pctxt->redef == NULL) {
5274	    xmlFree(ret);
5275	    return(NULL);
5276	}
5277	pctxt->redefCounter = 0;
5278    }
5279    WXS_ADD_GLOBAL(pctxt, ret);
5280    WXS_ADD_PENDING(pctxt, ret);
5281    return (ret);
5282}
5283
5284/**
5285 * xmlSchemaAddElement:
5286 * @ctxt:  a schema parser context
5287 * @schema:  the schema being built
5288 * @name:  the type name
5289 * @namespace:  the type namespace
5290 *
5291 * Add an XML schema Element declaration
5292 * *WARNING* this interface is highly subject to change
5293 *
5294 * Returns the new struture or NULL in case of error
5295 */
5296static xmlSchemaElementPtr
5297xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5298                    const xmlChar * name, const xmlChar * nsName,
5299		    xmlNodePtr node, int topLevel)
5300{
5301    xmlSchemaElementPtr ret = NULL;
5302
5303    if ((ctxt == NULL) || (name == NULL))
5304        return (NULL);
5305
5306    ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5307    if (ret == NULL) {
5308        xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5309        return (NULL);
5310    }
5311    memset(ret, 0, sizeof(xmlSchemaElement));
5312    ret->type = XML_SCHEMA_TYPE_ELEMENT;
5313    ret->name = name;
5314    ret->targetNamespace = nsName;
5315    ret->node = node;
5316
5317    if (topLevel)
5318	WXS_ADD_GLOBAL(ctxt, ret);
5319    else
5320	WXS_ADD_LOCAL(ctxt, ret);
5321    WXS_ADD_PENDING(ctxt, ret);
5322    return (ret);
5323}
5324
5325/**
5326 * xmlSchemaAddType:
5327 * @ctxt:  a schema parser context
5328 * @schema:  the schema being built
5329 * @name:  the item name
5330 * @namespace:  the namespace
5331 *
5332 * Add an XML schema item
5333 * *WARNING* this interface is highly subject to change
5334 *
5335 * Returns the new struture or NULL in case of error
5336 */
5337static xmlSchemaTypePtr
5338xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5339		 xmlSchemaTypeType type,
5340                 const xmlChar * name, const xmlChar * nsName,
5341		 xmlNodePtr node, int topLevel)
5342{
5343    xmlSchemaTypePtr ret = NULL;
5344
5345    if ((ctxt == NULL) || (schema == NULL))
5346        return (NULL);
5347
5348    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5349    if (ret == NULL) {
5350        xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5351        return (NULL);
5352    }
5353    memset(ret, 0, sizeof(xmlSchemaType));
5354    ret->type = type;
5355    ret->name = name;
5356    ret->targetNamespace = nsName;
5357    ret->node = node;
5358    if (topLevel) {
5359	if (ctxt->isRedefine) {
5360	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5361		ret, name, nsName);
5362	    if (ctxt->redef == NULL) {
5363		xmlFree(ret);
5364		return(NULL);
5365	    }
5366	    ctxt->redefCounter = 0;
5367	}
5368	WXS_ADD_GLOBAL(ctxt, ret);
5369    } else
5370	WXS_ADD_LOCAL(ctxt, ret);
5371    WXS_ADD_PENDING(ctxt, ret);
5372    return (ret);
5373}
5374
5375static xmlSchemaQNameRefPtr
5376xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5377		     xmlSchemaTypeType refType,
5378		     const xmlChar *refName,
5379		     const xmlChar *refNs)
5380{
5381    xmlSchemaQNameRefPtr ret;
5382
5383    ret = (xmlSchemaQNameRefPtr)
5384	xmlMalloc(sizeof(xmlSchemaQNameRef));
5385    if (ret == NULL) {
5386	xmlSchemaPErrMemory(pctxt,
5387	    "allocating QName reference item", NULL);
5388	return (NULL);
5389    }
5390    ret->node = NULL;
5391    ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5392    ret->name = refName;
5393    ret->targetNamespace = refNs;
5394    ret->item = NULL;
5395    ret->itemType = refType;
5396    /*
5397    * Store the reference item in the schema.
5398    */
5399    WXS_ADD_LOCAL(pctxt, ret);
5400    return (ret);
5401}
5402
5403static xmlSchemaAttributeUseProhibPtr
5404xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5405{
5406    xmlSchemaAttributeUseProhibPtr ret;
5407
5408    ret = (xmlSchemaAttributeUseProhibPtr)
5409	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5410    if (ret == NULL) {
5411	xmlSchemaPErrMemory(pctxt,
5412	    "allocating attribute use prohibition", NULL);
5413	return (NULL);
5414    }
5415    memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5416    ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5417    WXS_ADD_LOCAL(pctxt, ret);
5418    return (ret);
5419}
5420
5421
5422/**
5423 * xmlSchemaAddModelGroup:
5424 * @ctxt:  a schema parser context
5425 * @schema:  the schema being built
5426 * @type: the "compositor" type of the model group
5427 * @node: the node in the schema doc
5428 *
5429 * Adds a schema model group
5430 * *WARNING* this interface is highly subject to change
5431 *
5432 * Returns the new struture or NULL in case of error
5433 */
5434static xmlSchemaModelGroupPtr
5435xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5436		       xmlSchemaPtr schema,
5437		       xmlSchemaTypeType type,
5438		       xmlNodePtr node)
5439{
5440    xmlSchemaModelGroupPtr ret = NULL;
5441
5442    if ((ctxt == NULL) || (schema == NULL))
5443        return (NULL);
5444
5445    ret = (xmlSchemaModelGroupPtr)
5446	xmlMalloc(sizeof(xmlSchemaModelGroup));
5447    if (ret == NULL) {
5448	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5449	    NULL);
5450	return (NULL);
5451    }
5452    memset(ret, 0, sizeof(xmlSchemaModelGroup));
5453    ret->type = type;
5454    ret->node = node;
5455    WXS_ADD_LOCAL(ctxt, ret);
5456    if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5457	(type == XML_SCHEMA_TYPE_CHOICE))
5458	WXS_ADD_PENDING(ctxt, ret);
5459    return (ret);
5460}
5461
5462
5463/**
5464 * xmlSchemaAddParticle:
5465 * @ctxt:  a schema parser context
5466 * @schema:  the schema being built
5467 * @node: the corresponding node in the schema doc
5468 * @min: the minOccurs
5469 * @max: the maxOccurs
5470 *
5471 * Adds an XML schema particle component.
5472 * *WARNING* this interface is highly subject to change
5473 *
5474 * Returns the new struture or NULL in case of error
5475 */
5476static xmlSchemaParticlePtr
5477xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5478		     xmlNodePtr node, int min, int max)
5479{
5480    xmlSchemaParticlePtr ret = NULL;
5481    if (ctxt == NULL)
5482        return (NULL);
5483
5484#ifdef DEBUG
5485    fprintf(stderr, "Adding particle component\n");
5486#endif
5487    ret = (xmlSchemaParticlePtr)
5488	xmlMalloc(sizeof(xmlSchemaParticle));
5489    if (ret == NULL) {
5490	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5491	    NULL);
5492	return (NULL);
5493    }
5494    ret->type = XML_SCHEMA_TYPE_PARTICLE;
5495    ret->annot = NULL;
5496    ret->node = node;
5497    ret->minOccurs = min;
5498    ret->maxOccurs = max;
5499    ret->next = NULL;
5500    ret->children = NULL;
5501
5502    WXS_ADD_LOCAL(ctxt, ret);
5503    /*
5504    * Note that addition to pending components will be done locally
5505    * to the specific parsing function, since the most particles
5506    * need not to be fixed up (i.e. the reference to be resolved).
5507    * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5508    */
5509    return (ret);
5510}
5511
5512/**
5513 * xmlSchemaAddModelGroupDefinition:
5514 * @ctxt:  a schema validation context
5515 * @schema:  the schema being built
5516 * @name:  the group name
5517 *
5518 * Add an XML schema Group definition
5519 *
5520 * Returns the new struture or NULL in case of error
5521 */
5522static xmlSchemaModelGroupDefPtr
5523xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5524				 xmlSchemaPtr schema,
5525				 const xmlChar *name,
5526				 const xmlChar *nsName,
5527				 xmlNodePtr node)
5528{
5529    xmlSchemaModelGroupDefPtr ret = NULL;
5530
5531    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5532        return (NULL);
5533
5534    ret = (xmlSchemaModelGroupDefPtr)
5535	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5536    if (ret == NULL) {
5537        xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5538        return (NULL);
5539    }
5540    memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5541    ret->name = name;
5542    ret->type = XML_SCHEMA_TYPE_GROUP;
5543    ret->node = node;
5544    ret->targetNamespace = nsName;
5545
5546    if (ctxt->isRedefine) {
5547	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5548	    ret, name, nsName);
5549	if (ctxt->redef == NULL) {
5550	    xmlFree(ret);
5551	    return(NULL);
5552	}
5553	ctxt->redefCounter = 0;
5554    }
5555    WXS_ADD_GLOBAL(ctxt, ret);
5556    WXS_ADD_PENDING(ctxt, ret);
5557    return (ret);
5558}
5559
5560/**
5561 * xmlSchemaNewWildcardNs:
5562 * @ctxt:  a schema validation context
5563 *
5564 * Creates a new wildcard namespace constraint.
5565 *
5566 * Returns the new struture or NULL in case of error
5567 */
5568static xmlSchemaWildcardNsPtr
5569xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5570{
5571    xmlSchemaWildcardNsPtr ret;
5572
5573    ret = (xmlSchemaWildcardNsPtr)
5574	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5575    if (ret == NULL) {
5576	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5577	return (NULL);
5578    }
5579    ret->value = NULL;
5580    ret->next = NULL;
5581    return (ret);
5582}
5583
5584static xmlSchemaIDCPtr
5585xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5586                  const xmlChar *name, const xmlChar *nsName,
5587		  int category, xmlNodePtr node)
5588{
5589    xmlSchemaIDCPtr ret = NULL;
5590
5591    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5592        return (NULL);
5593
5594    ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5595    if (ret == NULL) {
5596        xmlSchemaPErrMemory(ctxt,
5597	    "allocating an identity-constraint definition", NULL);
5598        return (NULL);
5599    }
5600    memset(ret, 0, sizeof(xmlSchemaIDC));
5601    /* The target namespace of the parent element declaration. */
5602    ret->targetNamespace = nsName;
5603    ret->name = name;
5604    ret->type = category;
5605    ret->node = node;
5606
5607    WXS_ADD_GLOBAL(ctxt, ret);
5608    /*
5609    * Only keyrefs need to be fixup up.
5610    */
5611    if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5612	WXS_ADD_PENDING(ctxt, ret);
5613    return (ret);
5614}
5615
5616/**
5617 * xmlSchemaAddWildcard:
5618 * @ctxt:  a schema validation context
5619 * @schema: a schema
5620 *
5621 * Adds a wildcard.
5622 * It corresponds to a xsd:anyAttribute and xsd:any.
5623 *
5624 * Returns the new struture or NULL in case of error
5625 */
5626static xmlSchemaWildcardPtr
5627xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5628		     xmlSchemaTypeType type, xmlNodePtr node)
5629{
5630    xmlSchemaWildcardPtr ret = NULL;
5631
5632    if ((ctxt == NULL) || (schema == NULL))
5633        return (NULL);
5634
5635    ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5636    if (ret == NULL) {
5637        xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5638        return (NULL);
5639    }
5640    memset(ret, 0, sizeof(xmlSchemaWildcard));
5641    ret->type = type;
5642    ret->node = node;
5643    WXS_ADD_LOCAL(ctxt, ret);
5644    return (ret);
5645}
5646
5647static void
5648xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5649{
5650    if (group == NULL)
5651	return;
5652    if (group->members != NULL)
5653	xmlSchemaItemListFree(group->members);
5654    xmlFree(group);
5655}
5656
5657static xmlSchemaSubstGroupPtr
5658xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5659		       xmlSchemaElementPtr head)
5660{
5661    xmlSchemaSubstGroupPtr ret;
5662
5663    /* Init subst group hash. */
5664    if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5665	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5666	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5667	    return(NULL);
5668    }
5669    /* Create a new substitution group. */
5670    ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5671    if (ret == NULL) {
5672	xmlSchemaPErrMemory(NULL,
5673	    "allocating a substitution group container", NULL);
5674	return(NULL);
5675    }
5676    memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5677    ret->head = head;
5678    /* Create list of members. */
5679    ret->members = xmlSchemaItemListCreate();
5680    if (ret->members == NULL) {
5681	xmlSchemaSubstGroupFree(ret);
5682	return(NULL);
5683    }
5684    /* Add subst group to hash. */
5685    if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5686	head->name, head->targetNamespace, ret) != 0) {
5687	PERROR_INT("xmlSchemaSubstGroupAdd",
5688	    "failed to add a new substitution container");
5689	xmlSchemaSubstGroupFree(ret);
5690	return(NULL);
5691    }
5692    return(ret);
5693}
5694
5695static xmlSchemaSubstGroupPtr
5696xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5697		       xmlSchemaElementPtr head)
5698{
5699    if (WXS_SUBST_GROUPS(pctxt) == NULL)
5700	return(NULL);
5701    return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5702	head->name, head->targetNamespace));
5703
5704}
5705
5706/**
5707 * xmlSchemaAddElementSubstitutionMember:
5708 * @pctxt:  a schema parser context
5709 * @head:  the head of the substitution group
5710 * @member: the new member of the substitution group
5711 *
5712 * Allocate a new annotation structure.
5713 *
5714 * Returns the newly allocated structure or NULL in case or error
5715 */
5716static int
5717xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5718				      xmlSchemaElementPtr head,
5719				      xmlSchemaElementPtr member)
5720{
5721    xmlSchemaSubstGroupPtr substGroup = NULL;
5722
5723    if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5724	return (-1);
5725
5726    substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5727    if (substGroup == NULL)
5728	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5729    if (substGroup == NULL)
5730	return(-1);
5731    if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5732	return(-1);
5733    return(0);
5734}
5735
5736/************************************************************************
5737 * 									*
5738 *		Utilities for parsing					*
5739 * 									*
5740 ************************************************************************/
5741
5742/**
5743 * xmlSchemaPValAttrNodeQNameValue:
5744 * @ctxt:  a schema parser context
5745 * @schema: the schema context
5746 * @ownerDes: the designation of the parent element
5747 * @ownerItem: the parent as a schema object
5748 * @value:  the QName value
5749 * @local: the resulting local part if found, the attribute value otherwise
5750 * @uri:  the resulting namespace URI if found
5751 *
5752 * Extracts the local name and the URI of a QName value and validates it.
5753 * This one is intended to be used on attribute values that
5754 * should resolve to schema components.
5755 *
5756 * Returns 0, in case the QName is valid, a positive error code
5757 * if not valid and -1 if an internal error occurs.
5758 */
5759static int
5760xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5761				       xmlSchemaPtr schema,
5762				       xmlSchemaBasicItemPtr ownerItem,
5763				       xmlAttrPtr attr,
5764				       const xmlChar *value,
5765				       const xmlChar **uri,
5766				       const xmlChar **local)
5767{
5768    const xmlChar *pref;
5769    xmlNsPtr ns;
5770    int len, ret;
5771
5772    *uri = NULL;
5773    *local = NULL;
5774    ret = xmlValidateQName(value, 1);
5775    if (ret > 0) {
5776	xmlSchemaPSimpleTypeErr(ctxt,
5777	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5778	    ownerItem, (xmlNodePtr) attr,
5779	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5780	    NULL, value, NULL, NULL, NULL);
5781	*local = value;
5782	return (ctxt->err);
5783    } else if (ret < 0)
5784	return (-1);
5785
5786    if (!strchr((char *) value, ':')) {
5787	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5788	if (ns)
5789	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5790	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5791	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5792	    * parser context. */
5793	    /*
5794	    * This one takes care of included schemas with no
5795	    * target namespace.
5796	    */
5797	    *uri = ctxt->targetNamespace;
5798	}
5799	*local = xmlDictLookup(ctxt->dict, value, -1);
5800	return (0);
5801    }
5802    /*
5803    * At this point xmlSplitQName3 has to return a local name.
5804    */
5805    *local = xmlSplitQName3(value, &len);
5806    *local = xmlDictLookup(ctxt->dict, *local, -1);
5807    pref = xmlDictLookup(ctxt->dict, value, len);
5808    ns = xmlSearchNs(attr->doc, attr->parent, pref);
5809    if (ns == NULL) {
5810	xmlSchemaPSimpleTypeErr(ctxt,
5811	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5812	    ownerItem, (xmlNodePtr) attr,
5813	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5814	    "The value '%s' of simple type 'xs:QName' has no "
5815	    "corresponding namespace declaration in scope", value, NULL);
5816	return (ctxt->err);
5817    } else {
5818        *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5819    }
5820    return (0);
5821}
5822
5823/**
5824 * xmlSchemaPValAttrNodeQName:
5825 * @ctxt:  a schema parser context
5826 * @schema: the schema context
5827 * @ownerDes: the designation of the owner element
5828 * @ownerItem: the owner as a schema object
5829 * @attr:  the attribute node
5830 * @local: the resulting local part if found, the attribute value otherwise
5831 * @uri:  the resulting namespace URI if found
5832 *
5833 * Extracts and validates the QName of an attribute value.
5834 * This one is intended to be used on attribute values that
5835 * should resolve to schema components.
5836 *
5837 * Returns 0, in case the QName is valid, a positive error code
5838 * if not valid and -1 if an internal error occurs.
5839 */
5840static int
5841xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5842				       xmlSchemaPtr schema,
5843				       xmlSchemaBasicItemPtr ownerItem,
5844				       xmlAttrPtr attr,
5845				       const xmlChar **uri,
5846				       const xmlChar **local)
5847{
5848    const xmlChar *value;
5849
5850    value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5851    return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5852	ownerItem, attr, value, uri, local));
5853}
5854
5855/**
5856 * xmlSchemaPValAttrQName:
5857 * @ctxt:  a schema parser context
5858 * @schema: the schema context
5859 * @ownerDes: the designation of the parent element
5860 * @ownerItem: the owner as a schema object
5861 * @ownerElem:  the parent node of the attribute
5862 * @name:  the name of the attribute
5863 * @local: the resulting local part if found, the attribute value otherwise
5864 * @uri:  the resulting namespace URI if found
5865 *
5866 * Extracts and validates the QName of an attribute value.
5867 *
5868 * Returns 0, in case the QName is valid, a positive error code
5869 * if not valid and -1 if an internal error occurs.
5870 */
5871static int
5872xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5873				   xmlSchemaPtr schema,
5874				   xmlSchemaBasicItemPtr ownerItem,
5875				   xmlNodePtr ownerElem,
5876				   const char *name,
5877				   const xmlChar **uri,
5878				   const xmlChar **local)
5879{
5880    xmlAttrPtr attr;
5881
5882    attr = xmlSchemaGetPropNode(ownerElem, name);
5883    if (attr == NULL) {
5884	*local = NULL;
5885	*uri = NULL;
5886	return (0);
5887    }
5888    return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5889	ownerItem, attr, uri, local));
5890}
5891
5892/**
5893 * xmlSchemaPValAttrID:
5894 * @ctxt:  a schema parser context
5895 * @schema: the schema context
5896 * @ownerDes: the designation of the parent element
5897 * @ownerItem: the owner as a schema object
5898 * @ownerElem:  the parent node of the attribute
5899 * @name:  the name of the attribute
5900 *
5901 * Extracts and validates the ID of an attribute value.
5902 *
5903 * Returns 0, in case the ID is valid, a positive error code
5904 * if not valid and -1 if an internal error occurs.
5905 */
5906static int
5907xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5908{
5909    int ret;
5910    const xmlChar *value;
5911
5912    if (attr == NULL)
5913	return(0);
5914    value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5915    ret = xmlValidateNCName(value, 1);
5916    if (ret == 0) {
5917	/*
5918	* NOTE: the IDness might have already be declared in the DTD
5919	*/
5920	if (attr->atype != XML_ATTRIBUTE_ID) {
5921	    xmlIDPtr res;
5922	    xmlChar *strip;
5923
5924	    /*
5925	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5926	    * moment.
5927	    */
5928	    strip = xmlSchemaCollapseString(value);
5929	    if (strip != NULL) {
5930		xmlFree((xmlChar *) value);
5931		value = strip;
5932	    }
5933    	    res = xmlAddID(NULL, attr->doc, value, attr);
5934	    if (res == NULL) {
5935		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5936		xmlSchemaPSimpleTypeErr(ctxt,
5937		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5938		    NULL, (xmlNodePtr) attr,
5939		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5940		    NULL, NULL, "Duplicate value '%s' of simple "
5941		    "type 'xs:ID'", value, NULL);
5942	    } else
5943		attr->atype = XML_ATTRIBUTE_ID;
5944	}
5945    } else if (ret > 0) {
5946	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5947	xmlSchemaPSimpleTypeErr(ctxt,
5948	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5949	    NULL, (xmlNodePtr) attr,
5950	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5951	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5952	    "not a valid 'xs:NCName'",
5953	    value, NULL);
5954    }
5955    if (value != NULL)
5956	xmlFree((xmlChar *)value);
5957
5958    return (ret);
5959}
5960
5961static int
5962xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5963		    xmlNodePtr ownerElem,
5964		    const xmlChar *name)
5965{
5966    xmlAttrPtr attr;
5967
5968    attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5969    if (attr == NULL)
5970	return(0);
5971    return(xmlSchemaPValAttrNodeID(ctxt, attr));
5972
5973}
5974
5975/**
5976 * xmlGetMaxOccurs:
5977 * @ctxt:  a schema validation context
5978 * @node:  a subtree containing XML Schema informations
5979 *
5980 * Get the maxOccurs property
5981 *
5982 * Returns the default if not found, or the value
5983 */
5984static int
5985xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5986		int min, int max, int def, const char *expected)
5987{
5988    const xmlChar *val, *cur;
5989    int ret = 0;
5990    xmlAttrPtr attr;
5991
5992    attr = xmlSchemaGetPropNode(node, "maxOccurs");
5993    if (attr == NULL)
5994	return (def);
5995    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5996
5997    if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
5998	if (max != UNBOUNDED) {
5999	    xmlSchemaPSimpleTypeErr(ctxt,
6000		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6001		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6002		NULL, (xmlNodePtr) attr, NULL, expected,
6003		val, NULL, NULL, NULL);
6004	    return (def);
6005	} else
6006	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6007    }
6008
6009    cur = val;
6010    while (IS_BLANK_CH(*cur))
6011        cur++;
6012    if (*cur == 0) {
6013        xmlSchemaPSimpleTypeErr(ctxt,
6014	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6015	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6016	    NULL, (xmlNodePtr) attr, NULL, expected,
6017	    val, NULL, NULL, NULL);
6018	return (def);
6019    }
6020    while ((*cur >= '0') && (*cur <= '9')) {
6021        ret = ret * 10 + (*cur - '0');
6022        cur++;
6023    }
6024    while (IS_BLANK_CH(*cur))
6025        cur++;
6026    /*
6027    * TODO: Restrict the maximal value to Integer.
6028    */
6029    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6030	xmlSchemaPSimpleTypeErr(ctxt,
6031	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6032	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6033	    NULL, (xmlNodePtr) attr, NULL, expected,
6034	    val, NULL, NULL, NULL);
6035        return (def);
6036    }
6037    return (ret);
6038}
6039
6040/**
6041 * xmlGetMinOccurs:
6042 * @ctxt:  a schema validation context
6043 * @node:  a subtree containing XML Schema informations
6044 *
6045 * Get the minOccurs property
6046 *
6047 * Returns the default if not found, or the value
6048 */
6049static int
6050xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6051		int min, int max, int def, const char *expected)
6052{
6053    const xmlChar *val, *cur;
6054    int ret = 0;
6055    xmlAttrPtr attr;
6056
6057    attr = xmlSchemaGetPropNode(node, "minOccurs");
6058    if (attr == NULL)
6059	return (def);
6060    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6061    cur = val;
6062    while (IS_BLANK_CH(*cur))
6063        cur++;
6064    if (*cur == 0) {
6065        xmlSchemaPSimpleTypeErr(ctxt,
6066	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6067	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6068	    NULL, (xmlNodePtr) attr, NULL, expected,
6069	    val, NULL, NULL, NULL);
6070        return (def);
6071    }
6072    while ((*cur >= '0') && (*cur <= '9')) {
6073        ret = ret * 10 + (*cur - '0');
6074        cur++;
6075    }
6076    while (IS_BLANK_CH(*cur))
6077        cur++;
6078    /*
6079    * TODO: Restrict the maximal value to Integer.
6080    */
6081    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6082	xmlSchemaPSimpleTypeErr(ctxt,
6083	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6084	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6085	    NULL, (xmlNodePtr) attr, NULL, expected,
6086	    val, NULL, NULL, NULL);
6087        return (def);
6088    }
6089    return (ret);
6090}
6091
6092/**
6093 * xmlSchemaPGetBoolNodeValue:
6094 * @ctxt:  a schema validation context
6095 * @ownerDes:  owner designation
6096 * @ownerItem:  the owner as a schema item
6097 * @node: the node holding the value
6098 *
6099 * Converts a boolean string value into 1 or 0.
6100 *
6101 * Returns 0 or 1.
6102 */
6103static int
6104xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6105			   xmlSchemaBasicItemPtr ownerItem,
6106			   xmlNodePtr node)
6107{
6108    xmlChar *value = NULL;
6109    int res = 0;
6110
6111    value = xmlNodeGetContent(node);
6112    /*
6113    * 3.2.2.1 Lexical representation
6114    * An instance of a datatype that is defined as �boolean�
6115    * can have the following legal literals {true, false, 1, 0}.
6116    */
6117    if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6118        res = 1;
6119    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6120        res = 0;
6121    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6122	res = 1;
6123    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6124        res = 0;
6125    else {
6126        xmlSchemaPSimpleTypeErr(ctxt,
6127	    XML_SCHEMAP_INVALID_BOOLEAN,
6128	    ownerItem, node,
6129	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6130	    NULL, BAD_CAST value,
6131	    NULL, NULL, NULL);
6132    }
6133    if (value != NULL)
6134	xmlFree(value);
6135    return (res);
6136}
6137
6138/**
6139 * xmlGetBooleanProp:
6140 * @ctxt:  a schema validation context
6141 * @node:  a subtree containing XML Schema informations
6142 * @name:  the attribute name
6143 * @def:  the default value
6144 *
6145 * Evaluate if a boolean property is set
6146 *
6147 * Returns the default if not found, 0 if found to be false,
6148 * 1 if found to be true
6149 */
6150static int
6151xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6152		  xmlNodePtr node,
6153                  const char *name, int def)
6154{
6155    const xmlChar *val;
6156
6157    val = xmlSchemaGetProp(ctxt, node, name);
6158    if (val == NULL)
6159        return (def);
6160    /*
6161    * 3.2.2.1 Lexical representation
6162    * An instance of a datatype that is defined as �boolean�
6163    * can have the following legal literals {true, false, 1, 0}.
6164    */
6165    if (xmlStrEqual(val, BAD_CAST "true"))
6166        def = 1;
6167    else if (xmlStrEqual(val, BAD_CAST "false"))
6168        def = 0;
6169    else if (xmlStrEqual(val, BAD_CAST "1"))
6170	def = 1;
6171    else if (xmlStrEqual(val, BAD_CAST "0"))
6172        def = 0;
6173    else {
6174        xmlSchemaPSimpleTypeErr(ctxt,
6175	    XML_SCHEMAP_INVALID_BOOLEAN,
6176	    NULL,
6177	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6178	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6179	    NULL, val, NULL, NULL, NULL);
6180    }
6181    return (def);
6182}
6183
6184/************************************************************************
6185 * 									*
6186 *		Shema extraction from an Infoset			*
6187 * 									*
6188 ************************************************************************/
6189static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6190                                                 ctxt, xmlSchemaPtr schema,
6191                                                 xmlNodePtr node,
6192						 int topLevel);
6193static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6194                                                  ctxt,
6195                                                  xmlSchemaPtr schema,
6196                                                  xmlNodePtr node,
6197						  int topLevel);
6198static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6199                                                  ctxt,
6200                                                  xmlSchemaPtr schema,
6201                                                  xmlNodePtr node,
6202						  xmlSchemaTypeType parentType);
6203static xmlSchemaBasicItemPtr
6204xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6205			     xmlSchemaPtr schema,
6206			     xmlNodePtr node,
6207			     xmlSchemaItemListPtr uses,
6208			     int parentType);
6209static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6210                                           xmlSchemaPtr schema,
6211                                           xmlNodePtr node);
6212static xmlSchemaWildcardPtr
6213xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6214                           xmlSchemaPtr schema, xmlNodePtr node);
6215
6216/**
6217 * xmlSchemaPValAttrNodeValue:
6218 *
6219 * @ctxt:  a schema parser context
6220 * @ownerDes: the designation of the parent element
6221 * @ownerItem: the schema object owner if existent
6222 * @attr:  the schema attribute node being validated
6223 * @value: the value
6224 * @type: the built-in type to be validated against
6225 *
6226 * Validates a value against the given built-in type.
6227 * This one is intended to be used internally for validation
6228 * of schema attribute values during parsing of the schema.
6229 *
6230 * Returns 0 if the value is valid, a positive error code
6231 * number otherwise and -1 in case of an internal or API error.
6232 */
6233static int
6234xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6235			   xmlSchemaBasicItemPtr ownerItem,
6236			   xmlAttrPtr attr,
6237			   const xmlChar *value,
6238			   xmlSchemaTypePtr type)
6239{
6240
6241    int ret = 0;
6242
6243    /*
6244    * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6245    * one is really meant to be used internally, so better not.
6246    */
6247    if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6248	return (-1);
6249    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6250	PERROR_INT("xmlSchemaPValAttrNodeValue",
6251	    "the given type is not a built-in type");
6252	return (-1);
6253    }
6254    switch (type->builtInType) {
6255	case XML_SCHEMAS_NCNAME:
6256	case XML_SCHEMAS_QNAME:
6257	case XML_SCHEMAS_ANYURI:
6258	case XML_SCHEMAS_TOKEN:
6259	case XML_SCHEMAS_LANGUAGE:
6260	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6261		(xmlNodePtr) attr);
6262	    break;
6263	default: {
6264	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6265		"validation using the given type is not supported while "
6266		"parsing a schema");
6267	    return (-1);
6268	}
6269    }
6270    /*
6271    * TODO: Should we use the S4S error codes instead?
6272    */
6273    if (ret < 0) {
6274	PERROR_INT("xmlSchemaPValAttrNodeValue",
6275	    "failed to validate a schema attribute value");
6276	return (-1);
6277    } else if (ret > 0) {
6278	if (WXS_IS_LIST(type))
6279	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6280	else
6281	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6282	xmlSchemaPSimpleTypeErr(pctxt,
6283	    ret, ownerItem, (xmlNodePtr) attr,
6284	    type, NULL, value, NULL, NULL, NULL);
6285    }
6286    return (ret);
6287}
6288
6289/**
6290 * xmlSchemaPValAttrNode:
6291 *
6292 * @ctxt:  a schema parser context
6293 * @ownerDes: the designation of the parent element
6294 * @ownerItem: the schema object owner if existent
6295 * @attr:  the schema attribute node being validated
6296 * @type: the built-in type to be validated against
6297 * @value: the resulting value if any
6298 *
6299 * Extracts and validates a value against the given built-in type.
6300 * This one is intended to be used internally for validation
6301 * of schema attribute values during parsing of the schema.
6302 *
6303 * Returns 0 if the value is valid, a positive error code
6304 * number otherwise and -1 in case of an internal or API error.
6305 */
6306static int
6307xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6308			   xmlSchemaBasicItemPtr ownerItem,
6309			   xmlAttrPtr attr,
6310			   xmlSchemaTypePtr type,
6311			   const xmlChar **value)
6312{
6313    const xmlChar *val;
6314
6315    if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6316	return (-1);
6317
6318    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6319    if (value != NULL)
6320	*value = val;
6321
6322    return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6323	val, type));
6324}
6325
6326/**
6327 * xmlSchemaPValAttr:
6328 *
6329 * @ctxt:  a schema parser context
6330 * @node: the element node of the attribute
6331 * @ownerDes: the designation of the parent element
6332 * @ownerItem: the schema object owner if existent
6333 * @ownerElem: the owner element node
6334 * @name:  the name of the schema attribute node
6335 * @type: the built-in type to be validated against
6336 * @value: the resulting value if any
6337 *
6338 * Extracts and validates a value against the given built-in type.
6339 * This one is intended to be used internally for validation
6340 * of schema attribute values during parsing of the schema.
6341 *
6342 * Returns 0 if the value is valid, a positive error code
6343 * number otherwise and -1 in case of an internal or API error.
6344 */
6345static int
6346xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6347		       xmlSchemaBasicItemPtr ownerItem,
6348		       xmlNodePtr ownerElem,
6349		       const char *name,
6350		       xmlSchemaTypePtr type,
6351		       const xmlChar **value)
6352{
6353    xmlAttrPtr attr;
6354
6355    if ((ctxt == NULL) || (type == NULL)) {
6356	if (value != NULL)
6357	    *value = NULL;
6358	return (-1);
6359    }
6360    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6361	if (value != NULL)
6362	    *value = NULL;
6363	xmlSchemaPErr(ctxt, ownerElem,
6364	    XML_SCHEMAP_INTERNAL,
6365	    "Internal error: xmlSchemaPValAttr, the given "
6366	    "type '%s' is not a built-in type.\n",
6367	    type->name, NULL);
6368	return (-1);
6369    }
6370    attr = xmlSchemaGetPropNode(ownerElem, name);
6371    if (attr == NULL) {
6372	if (value != NULL)
6373	    *value = NULL;
6374	return (0);
6375    }
6376    return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6377	type, value));
6378}
6379
6380static int
6381xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6382		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6383		  xmlNodePtr node,
6384		  xmlAttrPtr attr,
6385		  const xmlChar *namespaceName)
6386{
6387    /* TODO: Pointer comparison instead? */
6388    if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6389	return (0);
6390    if (xmlStrEqual(xmlSchemaNs, namespaceName))
6391	return (0);
6392    /*
6393    * Check if the referenced namespace was <import>ed.
6394    */
6395    if (WXS_BUCKET(pctxt)->relations != NULL) {
6396	xmlSchemaSchemaRelationPtr rel;
6397
6398	rel = WXS_BUCKET(pctxt)->relations;
6399	do {
6400	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6401		xmlStrEqual(namespaceName, rel->importNamespace))
6402		return (0);
6403	    rel = rel->next;
6404	} while (rel != NULL);
6405    }
6406    /*
6407    * No matching <import>ed namespace found.
6408    */
6409    {
6410	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6411
6412	if (namespaceName == NULL)
6413	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6414		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6415		"References from this schema to components in no "
6416		"namespace are not allowed, since not indicated by an "
6417		"import statement", NULL, NULL);
6418	else
6419	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6420		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6421		"References from this schema to components in the "
6422		"namespace '%s' are not allowed, since not indicated by an "
6423		"import statement", namespaceName, NULL);
6424    }
6425    return (XML_SCHEMAP_SRC_RESOLVE);
6426}
6427
6428/**
6429 * xmlSchemaParseLocalAttributes:
6430 * @ctxt:  a schema validation context
6431 * @schema:  the schema being built
6432 * @node:  a subtree containing XML Schema informations
6433 * @type:  the hosting type where the attributes will be anchored
6434 *
6435 * Parses attribute uses and attribute declarations and
6436 * attribute group references.
6437 */
6438static int
6439xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6440                        xmlNodePtr *child, xmlSchemaItemListPtr *list,
6441			int parentType, int *hasRefs)
6442{
6443    void *item;
6444
6445    while ((IS_SCHEMA((*child), "attribute")) ||
6446           (IS_SCHEMA((*child), "attributeGroup"))) {
6447        if (IS_SCHEMA((*child), "attribute")) {
6448	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6449		*list, parentType);
6450        } else {
6451            item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6452	    if ((item != NULL) && (hasRefs != NULL))
6453		*hasRefs = 1;
6454        }
6455	if (item != NULL) {
6456	    if (*list == NULL) {
6457		/* TODO: Customize grow factor. */
6458		*list = xmlSchemaItemListCreate();
6459		if (*list == NULL)
6460		    return(-1);
6461	    }
6462	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6463		return(-1);
6464	}
6465        *child = (*child)->next;
6466    }
6467    return (0);
6468}
6469
6470/**
6471 * xmlSchemaParseAnnotation:
6472 * @ctxt:  a schema validation context
6473 * @schema:  the schema being built
6474 * @node:  a subtree containing XML Schema informations
6475 *
6476 * parse a XML schema Attrribute declaration
6477 * *WARNING* this interface is highly subject to change
6478 *
6479 * Returns -1 in case of error, 0 if the declaration is improper and
6480 *         1 in case of success.
6481 */
6482static xmlSchemaAnnotPtr
6483xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6484{
6485    xmlSchemaAnnotPtr ret;
6486    xmlNodePtr child = NULL;
6487    xmlAttrPtr attr;
6488    int barked = 0;
6489
6490    /*
6491    * INFO: S4S completed.
6492    */
6493    /*
6494    * id = ID
6495    * {any attributes with non-schema namespace . . .}>
6496    * Content: (appinfo | documentation)*
6497    */
6498    if ((ctxt == NULL) || (node == NULL))
6499        return (NULL);
6500    if (needed)
6501	ret = xmlSchemaNewAnnot(ctxt, node);
6502    else
6503	ret = NULL;
6504    attr = node->properties;
6505    while (attr != NULL) {
6506	if (((attr->ns == NULL) &&
6507	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6508	    ((attr->ns != NULL) &&
6509	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6510
6511	    xmlSchemaPIllegalAttrErr(ctxt,
6512		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6513	}
6514	attr = attr->next;
6515    }
6516    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6517    /*
6518    * And now for the children...
6519    */
6520    child = node->children;
6521    while (child != NULL) {
6522	if (IS_SCHEMA(child, "appinfo")) {
6523	    /* TODO: make available the content of "appinfo". */
6524	    /*
6525	    * source = anyURI
6526	    * {any attributes with non-schema namespace . . .}>
6527	    * Content: ({any})*
6528	    */
6529	    attr = child->properties;
6530	    while (attr != NULL) {
6531		if (((attr->ns == NULL) &&
6532		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6533		     ((attr->ns != NULL) &&
6534		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6535
6536		    xmlSchemaPIllegalAttrErr(ctxt,
6537			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6538		}
6539		attr = attr->next;
6540	    }
6541	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6542		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6543	    child = child->next;
6544	} else if (IS_SCHEMA(child, "documentation")) {
6545	    /* TODO: make available the content of "documentation". */
6546	    /*
6547	    * source = anyURI
6548	    * {any attributes with non-schema namespace . . .}>
6549	    * Content: ({any})*
6550	    */
6551	    attr = child->properties;
6552	    while (attr != NULL) {
6553		if (attr->ns == NULL) {
6554		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6555			xmlSchemaPIllegalAttrErr(ctxt,
6556			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6557		    }
6558		} else {
6559		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6560			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6561			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6562
6563			xmlSchemaPIllegalAttrErr(ctxt,
6564			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6565		    }
6566		}
6567		attr = attr->next;
6568	    }
6569	    /*
6570	    * Attribute "xml:lang".
6571	    */
6572	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6573	    if (attr != NULL)
6574		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6575		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6576	    child = child->next;
6577	} else {
6578	    if (!barked)
6579		xmlSchemaPContentErr(ctxt,
6580		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6581		    NULL, node, child, NULL, "(appinfo | documentation)*");
6582	    barked = 1;
6583	    child = child->next;
6584	}
6585    }
6586
6587    return (ret);
6588}
6589
6590/**
6591 * xmlSchemaParseFacet:
6592 * @ctxt:  a schema validation context
6593 * @schema:  the schema being built
6594 * @node:  a subtree containing XML Schema informations
6595 *
6596 * parse a XML schema Facet declaration
6597 * *WARNING* this interface is highly subject to change
6598 *
6599 * Returns the new type structure or NULL in case of error
6600 */
6601static xmlSchemaFacetPtr
6602xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6603                    xmlNodePtr node)
6604{
6605    xmlSchemaFacetPtr facet;
6606    xmlNodePtr child = NULL;
6607    const xmlChar *value;
6608
6609    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6610        return (NULL);
6611
6612    facet = xmlSchemaNewFacet();
6613    if (facet == NULL) {
6614        xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6615        return (NULL);
6616    }
6617    facet->node = node;
6618    value = xmlSchemaGetProp(ctxt, node, "value");
6619    if (value == NULL) {
6620        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6621                       "Facet %s has no value\n", node->name, NULL);
6622        xmlSchemaFreeFacet(facet);
6623        return (NULL);
6624    }
6625    if (IS_SCHEMA(node, "minInclusive")) {
6626        facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6627    } else if (IS_SCHEMA(node, "minExclusive")) {
6628        facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6629    } else if (IS_SCHEMA(node, "maxInclusive")) {
6630        facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6631    } else if (IS_SCHEMA(node, "maxExclusive")) {
6632        facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6633    } else if (IS_SCHEMA(node, "totalDigits")) {
6634        facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6635    } else if (IS_SCHEMA(node, "fractionDigits")) {
6636        facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6637    } else if (IS_SCHEMA(node, "pattern")) {
6638        facet->type = XML_SCHEMA_FACET_PATTERN;
6639    } else if (IS_SCHEMA(node, "enumeration")) {
6640        facet->type = XML_SCHEMA_FACET_ENUMERATION;
6641    } else if (IS_SCHEMA(node, "whiteSpace")) {
6642        facet->type = XML_SCHEMA_FACET_WHITESPACE;
6643    } else if (IS_SCHEMA(node, "length")) {
6644        facet->type = XML_SCHEMA_FACET_LENGTH;
6645    } else if (IS_SCHEMA(node, "maxLength")) {
6646        facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6647    } else if (IS_SCHEMA(node, "minLength")) {
6648        facet->type = XML_SCHEMA_FACET_MINLENGTH;
6649    } else {
6650        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6651                       "Unknown facet type %s\n", node->name, NULL);
6652        xmlSchemaFreeFacet(facet);
6653        return (NULL);
6654    }
6655    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6656    facet->value = value;
6657    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6658	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6659	const xmlChar *fixed;
6660
6661	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6662	if (fixed != NULL) {
6663	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6664		facet->fixed = 1;
6665	}
6666    }
6667    child = node->children;
6668
6669    if (IS_SCHEMA(child, "annotation")) {
6670        facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6671        child = child->next;
6672    }
6673    if (child != NULL) {
6674        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6675                       "Facet %s has unexpected child content\n",
6676                       node->name, NULL);
6677    }
6678    return (facet);
6679}
6680
6681/**
6682 * xmlSchemaParseWildcardNs:
6683 * @ctxt:  a schema parser context
6684 * @wildc:  the wildcard, already created
6685 * @node:  a subtree containing XML Schema informations
6686 *
6687 * Parses the attribute "processContents" and "namespace"
6688 * of a xsd:anyAttribute and xsd:any.
6689 * *WARNING* this interface is highly subject to change
6690 *
6691 * Returns 0 if everything goes fine, a positive error code
6692 * if something is not valid and -1 if an internal error occurs.
6693 */
6694static int
6695xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6696			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6697			 xmlSchemaWildcardPtr wildc,
6698			 xmlNodePtr node)
6699{
6700    const xmlChar *pc, *ns, *dictnsItem;
6701    int ret = 0;
6702    xmlChar *nsItem;
6703    xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6704    xmlAttrPtr attr;
6705
6706    pc = xmlSchemaGetProp(ctxt, node, "processContents");
6707    if ((pc == NULL)
6708        || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6709        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6710    } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6711        wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6712    } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6713        wildc->processContents = XML_SCHEMAS_ANY_LAX;
6714    } else {
6715        xmlSchemaPSimpleTypeErr(ctxt,
6716	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6717	    NULL, node,
6718	    NULL, "(strict | skip | lax)", pc,
6719	    NULL, NULL, NULL);
6720        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6721	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6722    }
6723    /*
6724     * Build the namespace constraints.
6725     */
6726    attr = xmlSchemaGetPropNode(node, "namespace");
6727    ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6728    if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6729	wildc->any = 1;
6730    else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6731	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6732	if (wildc->negNsSet == NULL) {
6733	    return (-1);
6734	}
6735	wildc->negNsSet->value = ctxt->targetNamespace;
6736    } else {
6737	const xmlChar *end, *cur;
6738
6739	cur = ns;
6740	do {
6741	    while (IS_BLANK_CH(*cur))
6742		cur++;
6743	    end = cur;
6744	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6745		end++;
6746	    if (end == cur)
6747		break;
6748	    nsItem = xmlStrndup(cur, end - cur);
6749	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6750		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6751		xmlSchemaPSimpleTypeErr(ctxt,
6752		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6753		    NULL, (xmlNodePtr) attr,
6754		    NULL,
6755		    "((##any | ##other) | List of (xs:anyURI | "
6756		    "(##targetNamespace | ##local)))",
6757		    nsItem, NULL, NULL, NULL);
6758		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6759	    } else {
6760		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6761		    dictnsItem = ctxt->targetNamespace;
6762		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6763		    dictnsItem = NULL;
6764		} else {
6765		    /*
6766		    * Validate the item (anyURI).
6767		    */
6768		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6769			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6770		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6771		}
6772		/*
6773		* Avoid dublicate namespaces.
6774		*/
6775		tmp = wildc->nsSet;
6776		while (tmp != NULL) {
6777		    if (dictnsItem == tmp->value)
6778			break;
6779		    tmp = tmp->next;
6780		}
6781		if (tmp == NULL) {
6782		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6783		    if (tmp == NULL) {
6784			xmlFree(nsItem);
6785			return (-1);
6786		    }
6787		    tmp->value = dictnsItem;
6788		    tmp->next = NULL;
6789		    if (wildc->nsSet == NULL)
6790			wildc->nsSet = tmp;
6791		    else
6792			lastNs->next = tmp;
6793		    lastNs = tmp;
6794		}
6795
6796	    }
6797	    xmlFree(nsItem);
6798	    cur = end;
6799	} while (*cur != 0);
6800    }
6801    return (ret);
6802}
6803
6804static int
6805xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6806				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6807				 xmlNodePtr node,
6808				 int minOccurs,
6809				 int maxOccurs) {
6810
6811    if ((maxOccurs == 0) && ( minOccurs == 0))
6812	return (0);
6813    if (maxOccurs != UNBOUNDED) {
6814	/*
6815	* TODO: Maybe we should better not create the particle,
6816	* if min/max is invalid, since it could confuse the build of the
6817	* content model.
6818	*/
6819	/*
6820	* 3.9.6 Schema Component Constraint: Particle Correct
6821	*
6822	*/
6823	if (maxOccurs < 1) {
6824	    /*
6825	    * 2.2 {max occurs} must be greater than or equal to 1.
6826	    */
6827	    xmlSchemaPCustomAttrErr(ctxt,
6828		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6829		NULL, NULL,
6830		xmlSchemaGetPropNode(node, "maxOccurs"),
6831		"The value must be greater than or equal to 1");
6832	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6833	} else if (minOccurs > maxOccurs) {
6834	    /*
6835	    * 2.1 {min occurs} must not be greater than {max occurs}.
6836	    */
6837	    xmlSchemaPCustomAttrErr(ctxt,
6838		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6839		NULL, NULL,
6840		xmlSchemaGetPropNode(node, "minOccurs"),
6841		"The value must not be greater than the value of 'maxOccurs'");
6842	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6843	}
6844    }
6845    return (0);
6846}
6847
6848/**
6849 * xmlSchemaParseAny:
6850 * @ctxt:  a schema validation context
6851 * @schema:  the schema being built
6852 * @node:  a subtree containing XML Schema informations
6853 *
6854 * Parsea a XML schema <any> element. A particle and wildcard
6855 * will be created (except if minOccurs==maxOccurs==0, in this case
6856 * nothing will be created).
6857 * *WARNING* this interface is highly subject to change
6858 *
6859 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6860 */
6861static xmlSchemaParticlePtr
6862xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6863                  xmlNodePtr node)
6864{
6865    xmlSchemaParticlePtr particle;
6866    xmlNodePtr child = NULL;
6867    xmlSchemaWildcardPtr wild;
6868    int min, max;
6869    xmlAttrPtr attr;
6870    xmlSchemaAnnotPtr annot = NULL;
6871
6872    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6873        return (NULL);
6874    /*
6875    * Check for illegal attributes.
6876    */
6877    attr = node->properties;
6878    while (attr != NULL) {
6879	if (attr->ns == NULL) {
6880	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6881		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6882		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6883	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6884		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6885		xmlSchemaPIllegalAttrErr(ctxt,
6886		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6887	    }
6888	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6889	    xmlSchemaPIllegalAttrErr(ctxt,
6890		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6891	}
6892	attr = attr->next;
6893    }
6894    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6895    /*
6896    * minOccurs/maxOccurs.
6897    */
6898    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6899	"(xs:nonNegativeInteger | unbounded)");
6900    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6901	"xs:nonNegativeInteger");
6902    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6903    /*
6904    * Create & parse the wildcard.
6905    */
6906    wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6907    if (wild == NULL)
6908	return (NULL);
6909    xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6910    /*
6911    * And now for the children...
6912    */
6913    child = node->children;
6914    if (IS_SCHEMA(child, "annotation")) {
6915        annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6916        child = child->next;
6917    }
6918    if (child != NULL) {
6919	xmlSchemaPContentErr(ctxt,
6920	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6921	    NULL, node, child,
6922	    NULL, "(annotation?)");
6923    }
6924    /*
6925    * No component if minOccurs==maxOccurs==0.
6926    */
6927    if ((min == 0) && (max == 0)) {
6928	/* Don't free the wildcard, since it's already on the list. */
6929	return (NULL);
6930    }
6931    /*
6932    * Create the particle.
6933    */
6934    particle = xmlSchemaAddParticle(ctxt, node, min, max);
6935    if (particle == NULL)
6936        return (NULL);
6937    particle->annot = annot;
6938    particle->children = (xmlSchemaTreeItemPtr) wild;
6939
6940    return (particle);
6941}
6942
6943/**
6944 * xmlSchemaParseNotation:
6945 * @ctxt:  a schema validation context
6946 * @schema:  the schema being built
6947 * @node:  a subtree containing XML Schema informations
6948 *
6949 * parse a XML schema Notation declaration
6950 *
6951 * Returns the new structure or NULL in case of error
6952 */
6953static xmlSchemaNotationPtr
6954xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6955                       xmlNodePtr node)
6956{
6957    const xmlChar *name;
6958    xmlSchemaNotationPtr ret;
6959    xmlNodePtr child = NULL;
6960
6961    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6962        return (NULL);
6963    name = xmlSchemaGetProp(ctxt, node, "name");
6964    if (name == NULL) {
6965        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6966                       "Notation has no name\n", NULL, NULL);
6967        return (NULL);
6968    }
6969    ret = xmlSchemaAddNotation(ctxt, schema, name,
6970	ctxt->targetNamespace, node);
6971    if (ret == NULL)
6972        return (NULL);
6973    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6974
6975    child = node->children;
6976    if (IS_SCHEMA(child, "annotation")) {
6977        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6978        child = child->next;
6979    }
6980    if (child != NULL) {
6981	xmlSchemaPContentErr(ctxt,
6982	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6983	    NULL, node, child,
6984	    NULL, "(annotation?)");
6985    }
6986
6987    return (ret);
6988}
6989
6990/**
6991 * xmlSchemaParseAnyAttribute:
6992 * @ctxt:  a schema validation context
6993 * @schema:  the schema being built
6994 * @node:  a subtree containing XML Schema informations
6995 *
6996 * parse a XML schema AnyAttrribute declaration
6997 * *WARNING* this interface is highly subject to change
6998 *
6999 * Returns a wildcard or NULL.
7000 */
7001static xmlSchemaWildcardPtr
7002xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7003                           xmlSchemaPtr schema, xmlNodePtr node)
7004{
7005    xmlSchemaWildcardPtr ret;
7006    xmlNodePtr child = NULL;
7007    xmlAttrPtr attr;
7008
7009    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7010        return (NULL);
7011
7012    ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7013	node);
7014    if (ret == NULL) {
7015        return (NULL);
7016    }
7017    /*
7018    * Check for illegal attributes.
7019    */
7020    attr = node->properties;
7021    while (attr != NULL) {
7022	if (attr->ns == NULL) {
7023	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7024	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7025		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7026		xmlSchemaPIllegalAttrErr(ctxt,
7027		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7028	    }
7029	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7030	    xmlSchemaPIllegalAttrErr(ctxt,
7031		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7032	}
7033	attr = attr->next;
7034    }
7035    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7036    /*
7037    * Parse the namespace list.
7038    */
7039    if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7040	return (NULL);
7041    /*
7042    * And now for the children...
7043    */
7044    child = node->children;
7045    if (IS_SCHEMA(child, "annotation")) {
7046        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7047        child = child->next;
7048    }
7049    if (child != NULL) {
7050	xmlSchemaPContentErr(ctxt,
7051	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7052	    NULL, node, child,
7053	    NULL, "(annotation?)");
7054    }
7055
7056    return (ret);
7057}
7058
7059
7060/**
7061 * xmlSchemaParseAttribute:
7062 * @ctxt:  a schema validation context
7063 * @schema:  the schema being built
7064 * @node:  a subtree containing XML Schema informations
7065 *
7066 * parse a XML schema Attrribute declaration
7067 * *WARNING* this interface is highly subject to change
7068 *
7069 * Returns the attribute declaration.
7070 */
7071static xmlSchemaBasicItemPtr
7072xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7073			     xmlSchemaPtr schema,
7074			     xmlNodePtr node,
7075			     xmlSchemaItemListPtr uses,
7076			     int parentType)
7077{
7078    const xmlChar *attrValue, *name = NULL, *ns = NULL;
7079    xmlSchemaAttributeUsePtr use = NULL;
7080    xmlNodePtr child = NULL;
7081    xmlAttrPtr attr;
7082    const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7083    int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7084    int	nberrors, hasForm = 0, defValueType = 0;
7085
7086#define WXS_ATTR_DEF_VAL_DEFAULT 1
7087#define WXS_ATTR_DEF_VAL_FIXED 2
7088
7089    /*
7090     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7091     */
7092
7093    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7094        return (NULL);
7095    attr = xmlSchemaGetPropNode(node, "ref");
7096    if (attr != NULL) {
7097	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7098	    NULL, attr, &tmpNs, &tmpName) != 0) {
7099	    return (NULL);
7100	}
7101	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7102	    return(NULL);
7103	isRef = 1;
7104    }
7105    nberrors = pctxt->nberrors;
7106    /*
7107    * Check for illegal attributes.
7108    */
7109    attr = node->properties;
7110    while (attr != NULL) {
7111	if (attr->ns == NULL) {
7112	    if (isRef) {
7113		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7114		    xmlSchemaPValAttrNodeID(pctxt, attr);
7115		    goto attr_next;
7116		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7117		    goto attr_next;
7118		}
7119	    } else {
7120		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7121		    goto attr_next;
7122		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7123		    xmlSchemaPValAttrNodeID(pctxt, attr);
7124		    goto attr_next;
7125		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7126		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7127			attr, &tmpNs, &tmpName);
7128		    goto attr_next;
7129		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7130		    /*
7131		    * Evaluate the target namespace
7132		    */
7133		    hasForm = 1;
7134		    attrValue = xmlSchemaGetNodeContent(pctxt,
7135			(xmlNodePtr) attr);
7136		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7137			ns = pctxt->targetNamespace;
7138		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7139		    {
7140			xmlSchemaPSimpleTypeErr(pctxt,
7141			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7142			    NULL, (xmlNodePtr) attr,
7143			    NULL, "(qualified | unqualified)",
7144			    attrValue, NULL, NULL, NULL);
7145		    }
7146		    goto attr_next;
7147		}
7148	    }
7149	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7150
7151		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7152		/* TODO: Maybe we need to normalize the value beforehand. */
7153		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7154		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7155		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7156		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7157		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7158		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7159		else {
7160		    xmlSchemaPSimpleTypeErr(pctxt,
7161			XML_SCHEMAP_INVALID_ATTR_USE,
7162			NULL, (xmlNodePtr) attr,
7163			NULL, "(optional | prohibited | required)",
7164			attrValue, NULL, NULL, NULL);
7165		}
7166		goto attr_next;
7167	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7168		/*
7169		* 3.2.3 : 1
7170		* default and fixed must not both be present.
7171		*/
7172		if (defValue) {
7173		    xmlSchemaPMutualExclAttrErr(pctxt,
7174			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7175			NULL, attr, "default", "fixed");
7176		} else {
7177		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7178		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7179		}
7180		goto attr_next;
7181	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7182		/*
7183		* 3.2.3 : 1
7184		* default and fixed must not both be present.
7185		*/
7186		if (defValue) {
7187		    xmlSchemaPMutualExclAttrErr(pctxt,
7188			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7189			NULL, attr, "default", "fixed");
7190		} else {
7191		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7192		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7193		}
7194		goto attr_next;
7195	    }
7196	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7197	    goto attr_next;
7198
7199	xmlSchemaPIllegalAttrErr(pctxt,
7200	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7201
7202attr_next:
7203	attr = attr->next;
7204    }
7205    /*
7206    * 3.2.3 : 2
7207    * If default and use are both present, use must have
7208    * the actual value optional.
7209    */
7210    if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7211	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7212	xmlSchemaPSimpleTypeErr(pctxt,
7213	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7214	    NULL, node, NULL,
7215	    "(optional | prohibited | required)", NULL,
7216	    "The value of the attribute 'use' must be 'optional' "
7217	    "if the attribute 'default' is present",
7218	    NULL, NULL);
7219    }
7220    /*
7221    * We want correct attributes.
7222    */
7223    if (nberrors != pctxt->nberrors)
7224	return(NULL);
7225    if (! isRef) {
7226	xmlSchemaAttributePtr attrDecl;
7227
7228	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7229	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7230	    ns = pctxt->targetNamespace;
7231	/*
7232	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7233	* TODO: Move this to the component layer.
7234	*/
7235	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7236	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7237		XML_SCHEMAP_NO_XSI,
7238		node, NULL,
7239		"The target namespace must not match '%s'",
7240		xmlSchemaInstanceNs, NULL);
7241	}
7242	attr = xmlSchemaGetPropNode(node, "name");
7243	if (attr == NULL) {
7244	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7245		NULL, node, "name", NULL);
7246	    return (NULL);
7247	}
7248	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7249	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7250	    return (NULL);
7251	}
7252	/*
7253	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7254	* TODO: Move this to the component layer.
7255	*/
7256	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7257	    xmlSchemaPSimpleTypeErr(pctxt,
7258		XML_SCHEMAP_NO_XMLNS,
7259		NULL, (xmlNodePtr) attr,
7260		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7261		"The value of the attribute must not match 'xmlns'",
7262		NULL, NULL);
7263	    return (NULL);
7264	}
7265	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7266	    goto check_children;
7267	/*
7268	* Create the attribute use component.
7269	*/
7270	use = xmlSchemaAddAttributeUse(pctxt, node);
7271	if (use == NULL)
7272	    return(NULL);
7273	use->occurs = occurs;
7274	/*
7275	* Create the attribute declaration.
7276	*/
7277	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7278	if (attrDecl == NULL)
7279	    return (NULL);
7280	if (tmpName != NULL) {
7281	    attrDecl->typeName = tmpName;
7282	    attrDecl->typeNs = tmpNs;
7283	}
7284	use->attrDecl = attrDecl;
7285	/*
7286	* Value constraint.
7287	*/
7288	if (defValue != NULL) {
7289	    attrDecl->defValue = defValue;
7290	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7291		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7292	}
7293    } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7294	xmlSchemaQNameRefPtr ref;
7295
7296	/*
7297	* Create the attribute use component.
7298	*/
7299	use = xmlSchemaAddAttributeUse(pctxt, node);
7300	if (use == NULL)
7301	    return(NULL);
7302	/*
7303	* We need to resolve the reference at later stage.
7304	*/
7305	WXS_ADD_PENDING(pctxt, use);
7306	use->occurs = occurs;
7307	/*
7308	* Create a QName reference to the attribute declaration.
7309	*/
7310	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7311	    tmpName, tmpNs);
7312	if (ref == NULL)
7313	    return(NULL);
7314	/*
7315	* Assign the reference. This will be substituted for the
7316	* referenced attribute declaration when the QName is resolved.
7317	*/
7318	use->attrDecl = WXS_ATTR_CAST ref;
7319	/*
7320	* Value constraint.
7321	*/
7322	if (defValue != NULL)
7323	    use->defValue = defValue;
7324	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7325		use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7326    }
7327
7328check_children:
7329    /*
7330    * And now for the children...
7331    */
7332    child = node->children;
7333    if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7334	xmlSchemaAttributeUseProhibPtr prohib;
7335
7336	if (IS_SCHEMA(child, "annotation")) {
7337	    xmlSchemaParseAnnotation(pctxt, child, 0);
7338	    child = child->next;
7339	}
7340	if (child != NULL) {
7341	    xmlSchemaPContentErr(pctxt,
7342		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7343		NULL, node, child, NULL,
7344		"(annotation?)");
7345	}
7346	/*
7347	* Check for pointlessness of attribute prohibitions.
7348	*/
7349	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7350	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7351		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7352		node, NULL,
7353		"Skipping attribute use prohibition, since it is "
7354		"pointless inside an <attributeGroup>",
7355		NULL, NULL, NULL);
7356	    return(NULL);
7357	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7358	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7359		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7360		node, NULL,
7361		"Skipping attribute use prohibition, since it is "
7362		"pointless when extending a type",
7363		NULL, NULL, NULL);
7364	    return(NULL);
7365	}
7366	if (! isRef) {
7367	    tmpName = name;
7368	    tmpNs = ns;
7369	}
7370	/*
7371	* Check for duplicate attribute prohibitions.
7372	*/
7373	if (uses) {
7374	    int i;
7375
7376	    for (i = 0; i < uses->nbItems; i++) {
7377		use = uses->items[i];
7378		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7379		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7380		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7381		{
7382		    xmlChar *str = NULL;
7383
7384		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7385			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7386			node, NULL,
7387			"Skipping duplicate attribute use prohibition '%s'",
7388			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7389			NULL, NULL);
7390		    FREE_AND_NULL(str)
7391		    return(NULL);
7392		}
7393	    }
7394	}
7395	/*
7396	* Create the attribute prohibition helper component.
7397	*/
7398	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7399	if (prohib == NULL)
7400	    return(NULL);
7401	prohib->node = node;
7402	prohib->name = tmpName;
7403	prohib->targetNamespace = tmpNs;
7404	if (isRef) {
7405	    /*
7406	    * We need at least to resolve to the attribute declaration.
7407	    */
7408	    WXS_ADD_PENDING(pctxt, prohib);
7409	}
7410	return(WXS_BASIC_CAST prohib);
7411    } else {
7412	if (IS_SCHEMA(child, "annotation")) {
7413	    /*
7414	    * TODO: Should this go into the attr decl?
7415	    */
7416	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7417	    child = child->next;
7418	}
7419	if (isRef) {
7420	    if (child != NULL) {
7421		if (IS_SCHEMA(child, "simpleType"))
7422		    /*
7423		    * 3.2.3 : 3.2
7424		    * If ref is present, then all of <simpleType>,
7425		    * form and type must be absent.
7426		    */
7427		    xmlSchemaPContentErr(pctxt,
7428			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7429			NULL, node, child, NULL,
7430			"(annotation?)");
7431		else
7432		    xmlSchemaPContentErr(pctxt,
7433			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7434			NULL, node, child, NULL,
7435			"(annotation?)");
7436	    }
7437	} else {
7438	    if (IS_SCHEMA(child, "simpleType")) {
7439		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7440		    /*
7441		    * 3.2.3 : 4
7442		    * type and <simpleType> must not both be present.
7443		    */
7444		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7445			NULL, node, child,
7446			"The attribute 'type' and the <simpleType> child "
7447			"are mutually exclusive", NULL);
7448		} else
7449		    WXS_ATTRUSE_TYPEDEF(use) =
7450			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7451		child = child->next;
7452	    }
7453	    if (child != NULL)
7454		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7455		NULL, node, child, NULL,
7456		"(annotation?, simpleType?)");
7457	}
7458    }
7459    return (WXS_BASIC_CAST use);
7460}
7461
7462
7463static xmlSchemaAttributePtr
7464xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7465			      xmlSchemaPtr schema,
7466			      xmlNodePtr node)
7467{
7468    const xmlChar *attrValue;
7469    xmlSchemaAttributePtr ret;
7470    xmlNodePtr child = NULL;
7471    xmlAttrPtr attr;
7472
7473    /*
7474     * Note that the w3c spec assumes the schema to be validated with schema
7475     * for schemas beforehand.
7476     *
7477     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7478     */
7479    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7480        return (NULL);
7481    /*
7482    * 3.2.3 : 3.1
7483    * One of ref or name must be present, but not both
7484    */
7485    attr = xmlSchemaGetPropNode(node, "name");
7486    if (attr == NULL) {
7487	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7488	    NULL, node, "name", NULL);
7489	return (NULL);
7490    }
7491    if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7492	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7493	return (NULL);
7494    }
7495    /*
7496    * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7497    * TODO: Move this to the component layer.
7498    */
7499    if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7500	xmlSchemaPSimpleTypeErr(pctxt,
7501	    XML_SCHEMAP_NO_XMLNS,
7502	    NULL, (xmlNodePtr) attr,
7503	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7504	    "The value of the attribute must not match 'xmlns'",
7505	    NULL, NULL);
7506	return (NULL);
7507    }
7508    /*
7509    * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7510    * TODO: Move this to the component layer.
7511    *       Or better leave it here and add it to the component layer
7512    *       if we have a schema construction API.
7513    */
7514    if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7515	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7516	    XML_SCHEMAP_NO_XSI, node, NULL,
7517	    "The target namespace must not match '%s'",
7518	    xmlSchemaInstanceNs, NULL);
7519    }
7520
7521    ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7522	pctxt->targetNamespace, node, 1);
7523    if (ret == NULL)
7524	return (NULL);
7525    ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7526
7527    /*
7528    * Check for illegal attributes.
7529    */
7530    attr = node->properties;
7531    while (attr != NULL) {
7532	if (attr->ns == NULL) {
7533	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7534		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7535		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7536		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7537		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7538	    {
7539		xmlSchemaPIllegalAttrErr(pctxt,
7540		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7541	    }
7542	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7543	    xmlSchemaPIllegalAttrErr(pctxt,
7544		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7545	}
7546	attr = attr->next;
7547    }
7548    xmlSchemaPValAttrQName(pctxt, schema, NULL,
7549	node, "type", &ret->typeNs, &ret->typeName);
7550
7551    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7552    /*
7553    * Attribute "fixed".
7554    */
7555    ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7556    if (ret->defValue != NULL)
7557	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7558    /*
7559    * Attribute "default".
7560    */
7561    attr = xmlSchemaGetPropNode(node, "default");
7562    if (attr != NULL) {
7563	/*
7564	* 3.2.3 : 1
7565	* default and fixed must not both be present.
7566	*/
7567	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7568	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7569		WXS_BASIC_CAST ret, attr, "default", "fixed");
7570	} else
7571	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7572    }
7573    /*
7574    * And now for the children...
7575    */
7576    child = node->children;
7577    if (IS_SCHEMA(child, "annotation")) {
7578        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7579        child = child->next;
7580    }
7581    if (IS_SCHEMA(child, "simpleType")) {
7582	if (ret->typeName != NULL) {
7583	    /*
7584	    * 3.2.3 : 4
7585	    * type and <simpleType> must not both be present.
7586	    */
7587	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7588		NULL, node, child,
7589		"The attribute 'type' and the <simpleType> child "
7590		"are mutually exclusive", NULL);
7591	} else
7592	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7593	child = child->next;
7594    }
7595    if (child != NULL)
7596	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7597	    NULL, node, child, NULL,
7598	    "(annotation?, simpleType?)");
7599
7600    return (ret);
7601}
7602
7603/**
7604 * xmlSchemaParseAttributeGroupRef:
7605 * @ctxt:  a schema validation context
7606 * @schema:  the schema being built
7607 * @node:  a subtree containing XML Schema informations
7608 *
7609 * Parse an attribute group definition reference.
7610 * Note that a reference to an attribute group does not
7611 * correspond to any component at all.
7612 * *WARNING* this interface is highly subject to change
7613 *
7614 * Returns the attribute group or NULL in case of error.
7615 */
7616static xmlSchemaQNameRefPtr
7617xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7618				xmlSchemaPtr schema,
7619				xmlNodePtr node)
7620{
7621    xmlSchemaQNameRefPtr ret;
7622    xmlNodePtr child = NULL;
7623    xmlAttrPtr attr;
7624    const xmlChar *refNs = NULL, *ref = NULL;
7625
7626    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7627        return (NULL);
7628
7629    attr = xmlSchemaGetPropNode(node, "ref");
7630    if (attr == NULL) {
7631	xmlSchemaPMissingAttrErr(pctxt,
7632	    XML_SCHEMAP_S4S_ATTR_MISSING,
7633	    NULL, node, "ref", NULL);
7634	return (NULL);
7635    }
7636    xmlSchemaPValAttrNodeQName(pctxt, schema,
7637	NULL, attr, &refNs, &ref);
7638    if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7639	return(NULL);
7640
7641    /*
7642    * Check for illegal attributes.
7643    */
7644    attr = node->properties;
7645    while (attr != NULL) {
7646	if (attr->ns == NULL) {
7647	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7648		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7649	    {
7650		xmlSchemaPIllegalAttrErr(pctxt,
7651		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7652	    }
7653	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7654	    xmlSchemaPIllegalAttrErr(pctxt,
7655		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7656	}
7657	attr = attr->next;
7658    }
7659    /* Attribute ID */
7660    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7661
7662    /*
7663    * And now for the children...
7664    */
7665    child = node->children;
7666    if (IS_SCHEMA(child, "annotation")) {
7667	/*
7668	* TODO: We do not have a place to store the annotation, do we?
7669	*/
7670        xmlSchemaParseAnnotation(pctxt, child, 0);
7671        child = child->next;
7672    }
7673    if (child != NULL) {
7674	xmlSchemaPContentErr(pctxt,
7675	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7676	    NULL, node, child, NULL,
7677	    "(annotation?)");
7678    }
7679
7680    /*
7681    * Handle attribute group redefinitions.
7682    */
7683    if (pctxt->isRedefine && pctxt->redef &&
7684	(pctxt->redef->item->type ==
7685	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7686	(ref == pctxt->redef->refName) &&
7687	(refNs == pctxt->redef->refTargetNs))
7688    {
7689	/*
7690	* SPEC src-redefine:
7691	* (7.1) "If it has an <attributeGroup> among its contents
7692	* the �actual value� of whose ref [attribute] is the same
7693	* as the �actual value� of its own name attribute plus
7694	* target namespace, then it must have exactly one such group."
7695	*/
7696	if (pctxt->redefCounter != 0) {
7697	    xmlChar *str = NULL;
7698
7699	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7700		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7701		"The redefining attribute group definition "
7702		"'%s' must not contain more than one "
7703		"reference to the redefined definition",
7704		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7705	    FREE_AND_NULL(str);
7706	    return(NULL);
7707	}
7708	pctxt->redefCounter++;
7709	/*
7710	* URGENT TODO: How to ensure that the reference will not be
7711	* handled by the normal component resolution mechanism?
7712	*/
7713	ret = xmlSchemaNewQNameRef(pctxt,
7714	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7715	if (ret == NULL)
7716	    return(NULL);
7717	ret->node = node;
7718	pctxt->redef->reference = WXS_BASIC_CAST ret;
7719    } else {
7720	/*
7721	* Create a QName-reference helper component. We will substitute this
7722	* component for the attribute uses of the referenced attribute group
7723	* definition.
7724	*/
7725	ret = xmlSchemaNewQNameRef(pctxt,
7726	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7727	if (ret == NULL)
7728	    return(NULL);
7729	ret->node = node;
7730	/* Add to pending items, to be able to resolve the reference. */
7731	WXS_ADD_PENDING(pctxt, ret);
7732    }
7733    return (ret);
7734}
7735
7736/**
7737 * xmlSchemaParseAttributeGroupDefinition:
7738 * @pctxt:  a schema validation context
7739 * @schema:  the schema being built
7740 * @node:  a subtree containing XML Schema informations
7741 *
7742 * parse a XML schema Attribute Group declaration
7743 * *WARNING* this interface is highly subject to change
7744 *
7745 * Returns the attribute group definition or NULL in case of error.
7746 */
7747static xmlSchemaAttributeGroupPtr
7748xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7749				       xmlSchemaPtr schema,
7750				       xmlNodePtr node)
7751{
7752    const xmlChar *name;
7753    xmlSchemaAttributeGroupPtr ret;
7754    xmlNodePtr child = NULL;
7755    xmlAttrPtr attr;
7756    int hasRefs = 0;
7757
7758    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7759        return (NULL);
7760
7761    attr = xmlSchemaGetPropNode(node, "name");
7762    if (attr == NULL) {
7763	xmlSchemaPMissingAttrErr(pctxt,
7764	    XML_SCHEMAP_S4S_ATTR_MISSING,
7765	    NULL, node, "name", NULL);
7766	return (NULL);
7767    }
7768    /*
7769    * The name is crucial, exit if invalid.
7770    */
7771    if (xmlSchemaPValAttrNode(pctxt,
7772	NULL, attr,
7773	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7774	return (NULL);
7775    }
7776    ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7777	name, pctxt->targetNamespace, node);
7778    if (ret == NULL)
7779	return (NULL);
7780    /*
7781    * Check for illegal attributes.
7782    */
7783    attr = node->properties;
7784    while (attr != NULL) {
7785	if (attr->ns == NULL) {
7786	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7787		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7788	    {
7789		xmlSchemaPIllegalAttrErr(pctxt,
7790		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7791	    }
7792	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7793	    xmlSchemaPIllegalAttrErr(pctxt,
7794		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7795	}
7796	attr = attr->next;
7797    }
7798    /* Attribute ID */
7799    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7800    /*
7801    * And now for the children...
7802    */
7803    child = node->children;
7804    if (IS_SCHEMA(child, "annotation")) {
7805        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7806        child = child->next;
7807    }
7808    /*
7809    * Parse contained attribute decls/refs.
7810    */
7811    if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7812	(xmlSchemaItemListPtr *) &(ret->attrUses),
7813	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7814	return(NULL);
7815    if (hasRefs)
7816	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7817    /*
7818    * Parse the attribute wildcard.
7819    */
7820    if (IS_SCHEMA(child, "anyAttribute")) {
7821	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7822	    schema, child);
7823	child = child->next;
7824    }
7825    if (child != NULL) {
7826	xmlSchemaPContentErr(pctxt,
7827	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7828	    NULL, node, child, NULL,
7829	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7830    }
7831    return (ret);
7832}
7833
7834/**
7835 * xmlSchemaPValAttrFormDefault:
7836 * @value:  the value
7837 * @flags: the flags to be modified
7838 * @flagQualified: the specific flag for "qualified"
7839 *
7840 * Returns 0 if the value is valid, 1 otherwise.
7841 */
7842static int
7843xmlSchemaPValAttrFormDefault(const xmlChar *value,
7844			     int *flags,
7845			     int flagQualified)
7846{
7847    if (xmlStrEqual(value, BAD_CAST "qualified")) {
7848	if  ((*flags & flagQualified) == 0)
7849	    *flags |= flagQualified;
7850    } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7851	return (1);
7852
7853    return (0);
7854}
7855
7856/**
7857 * xmlSchemaPValAttrBlockFinal:
7858 * @value:  the value
7859 * @flags: the flags to be modified
7860 * @flagAll: the specific flag for "#all"
7861 * @flagExtension: the specific flag for "extension"
7862 * @flagRestriction: the specific flag for "restriction"
7863 * @flagSubstitution: the specific flag for "substitution"
7864 * @flagList: the specific flag for "list"
7865 * @flagUnion: the specific flag for "union"
7866 *
7867 * Validates the value of the attribute "final" and "block". The value
7868 * is converted into the specified flag values and returned in @flags.
7869 *
7870 * Returns 0 if the value is valid, 1 otherwise.
7871 */
7872
7873static int
7874xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7875			    int *flags,
7876			    int flagAll,
7877			    int flagExtension,
7878			    int flagRestriction,
7879			    int flagSubstitution,
7880			    int flagList,
7881			    int flagUnion)
7882{
7883    int ret = 0;
7884
7885    /*
7886    * TODO: This does not check for dublicate entries.
7887    */
7888    if ((flags == NULL) || (value == NULL))
7889	return (-1);
7890    if (value[0] == 0)
7891	return (0);
7892    if (xmlStrEqual(value, BAD_CAST "#all")) {
7893	if (flagAll != -1)
7894	    *flags |= flagAll;
7895	else {
7896	    if (flagExtension != -1)
7897		*flags |= flagExtension;
7898	    if (flagRestriction != -1)
7899		*flags |= flagRestriction;
7900	    if (flagSubstitution != -1)
7901		*flags |= flagSubstitution;
7902	    if (flagList != -1)
7903		*flags |= flagList;
7904	    if (flagUnion != -1)
7905		*flags |= flagUnion;
7906	}
7907    } else {
7908	const xmlChar *end, *cur = value;
7909	xmlChar *item;
7910
7911	do {
7912	    while (IS_BLANK_CH(*cur))
7913		cur++;
7914	    end = cur;
7915	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7916		end++;
7917	    if (end == cur)
7918		break;
7919	    item = xmlStrndup(cur, end - cur);
7920	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7921		if (flagExtension != -1) {
7922		    if ((*flags & flagExtension) == 0)
7923			*flags |= flagExtension;
7924		} else
7925		    ret = 1;
7926	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7927		if (flagRestriction != -1) {
7928		    if ((*flags & flagRestriction) == 0)
7929			*flags |= flagRestriction;
7930		} else
7931		    ret = 1;
7932	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7933		if (flagSubstitution != -1) {
7934		    if ((*flags & flagSubstitution) == 0)
7935			*flags |= flagSubstitution;
7936		} else
7937		    ret = 1;
7938	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
7939		if (flagList != -1) {
7940		    if ((*flags & flagList) == 0)
7941			*flags |= flagList;
7942		} else
7943		    ret = 1;
7944	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
7945		if (flagUnion != -1) {
7946		    if ((*flags & flagUnion) == 0)
7947			*flags |= flagUnion;
7948		} else
7949		    ret = 1;
7950	    } else
7951		ret = 1;
7952	    if (item != NULL)
7953		xmlFree(item);
7954	    cur = end;
7955	} while ((ret == 0) && (*cur != 0));
7956    }
7957
7958    return (ret);
7959}
7960
7961static int
7962xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7963			     xmlSchemaIDCPtr idc,
7964			     xmlSchemaIDCSelectPtr selector,
7965			     xmlAttrPtr attr,
7966			     int isField)
7967{
7968    xmlNodePtr node;
7969
7970    /*
7971    * c-selector-xpath:
7972    * Schema Component Constraint: Selector Value OK
7973    *
7974    * TODO: 1 The {selector} must be a valid XPath expression, as defined
7975    * in [XPath].
7976    */
7977    if (selector == NULL) {
7978	xmlSchemaPErr(ctxt, idc->node,
7979	    XML_SCHEMAP_INTERNAL,
7980	    "Internal error: xmlSchemaCheckCSelectorXPath, "
7981	    "the selector is not specified.\n", NULL, NULL);
7982	return (-1);
7983    }
7984    if (attr == NULL)
7985	node = idc->node;
7986    else
7987	node = (xmlNodePtr) attr;
7988    if (selector->xpath == NULL) {
7989	xmlSchemaPCustomErr(ctxt,
7990	    /* TODO: Adjust error code. */
7991	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7992	    NULL, node,
7993	    "The XPath expression of the selector is not valid", NULL);
7994	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7995    } else {
7996	const xmlChar **nsArray = NULL;
7997	xmlNsPtr *nsList = NULL;
7998	/*
7999	* Compile the XPath expression.
8000	*/
8001	/*
8002	* TODO: We need the array of in-scope namespaces for compilation.
8003	* TODO: Call xmlPatterncompile with different options for selector/
8004	* field.
8005	*/
8006	if (attr == NULL)
8007	    nsList = NULL;
8008	else
8009	    nsList = xmlGetNsList(attr->doc, attr->parent);
8010	/*
8011	* Build an array of prefixes and namespaces.
8012	*/
8013	if (nsList != NULL) {
8014	    int i, count = 0;
8015
8016	    for (i = 0; nsList[i] != NULL; i++)
8017		count++;
8018
8019	    nsArray = (const xmlChar **) xmlMalloc(
8020		(count * 2 + 1) * sizeof(const xmlChar *));
8021	    if (nsArray == NULL) {
8022		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8023		    NULL);
8024		xmlFree(nsList);
8025		return (-1);
8026	    }
8027	    for (i = 0; i < count; i++) {
8028		nsArray[2 * i] = nsList[i]->href;
8029		nsArray[2 * i + 1] = nsList[i]->prefix;
8030	    }
8031	    nsArray[count * 2] = NULL;
8032	    xmlFree(nsList);
8033	}
8034	/*
8035	* TODO: Differentiate between "selector" and "field".
8036	*/
8037	if (isField)
8038	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8039		NULL, XML_PATTERN_XSFIELD, nsArray);
8040	else
8041	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8042		NULL, XML_PATTERN_XSSEL, nsArray);
8043	if (nsArray != NULL)
8044	    xmlFree((xmlChar **) nsArray);
8045
8046	if (selector->xpathComp == NULL) {
8047	    xmlSchemaPCustomErr(ctxt,
8048		/* TODO: Adjust error code? */
8049		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8050		NULL, node,
8051		"The XPath expression '%s' could not be "
8052		"compiled", selector->xpath);
8053	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8054	}
8055    }
8056    return (0);
8057}
8058
8059#define ADD_ANNOTATION(annot)   \
8060    xmlSchemaAnnotPtr cur = item->annot; \
8061    if (item->annot == NULL) {  \
8062	item->annot = annot;    \
8063	return (annot);         \
8064    }                           \
8065    cur = item->annot;          \
8066    if (cur->next != NULL) {    \
8067	cur = cur->next;	\
8068    }                           \
8069    cur->next = annot;
8070
8071/**
8072 * xmlSchemaAssignAnnotation:
8073 * @item: the schema component
8074 * @annot: the annotation
8075 *
8076 * Adds the annotation to the given schema component.
8077 *
8078 * Returns the given annotaion.
8079 */
8080static xmlSchemaAnnotPtr
8081xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8082		       xmlSchemaAnnotPtr annot)
8083{
8084    if ((annItem == NULL) || (annot == NULL))
8085	return (NULL);
8086    switch (annItem->type) {
8087	case XML_SCHEMA_TYPE_ELEMENT: {
8088		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8089		ADD_ANNOTATION(annot)
8090	    }
8091	    break;
8092	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8093		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8094		ADD_ANNOTATION(annot)
8095	    }
8096	    break;
8097	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8098	case XML_SCHEMA_TYPE_ANY: {
8099		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8100		ADD_ANNOTATION(annot)
8101	    }
8102	    break;
8103	case XML_SCHEMA_TYPE_PARTICLE:
8104	case XML_SCHEMA_TYPE_IDC_KEY:
8105	case XML_SCHEMA_TYPE_IDC_KEYREF:
8106	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8107		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8108		ADD_ANNOTATION(annot)
8109	    }
8110	    break;
8111	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8112		xmlSchemaAttributeGroupPtr item =
8113		    (xmlSchemaAttributeGroupPtr) annItem;
8114		ADD_ANNOTATION(annot)
8115	    }
8116	    break;
8117	case XML_SCHEMA_TYPE_NOTATION: {
8118		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8119		ADD_ANNOTATION(annot)
8120	    }
8121	    break;
8122	case XML_SCHEMA_FACET_MININCLUSIVE:
8123	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8124	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8125	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8126	case XML_SCHEMA_FACET_TOTALDIGITS:
8127	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8128	case XML_SCHEMA_FACET_PATTERN:
8129	case XML_SCHEMA_FACET_ENUMERATION:
8130	case XML_SCHEMA_FACET_WHITESPACE:
8131	case XML_SCHEMA_FACET_LENGTH:
8132	case XML_SCHEMA_FACET_MAXLENGTH:
8133	case XML_SCHEMA_FACET_MINLENGTH: {
8134		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8135		ADD_ANNOTATION(annot)
8136	    }
8137	    break;
8138	case XML_SCHEMA_TYPE_SIMPLE:
8139	case XML_SCHEMA_TYPE_COMPLEX: {
8140		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8141		ADD_ANNOTATION(annot)
8142	    }
8143	    break;
8144	case XML_SCHEMA_TYPE_GROUP: {
8145		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8146		ADD_ANNOTATION(annot)
8147	    }
8148	    break;
8149	case XML_SCHEMA_TYPE_SEQUENCE:
8150	case XML_SCHEMA_TYPE_CHOICE:
8151	case XML_SCHEMA_TYPE_ALL: {
8152		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8153		ADD_ANNOTATION(annot)
8154	    }
8155	    break;
8156	default:
8157	     xmlSchemaPCustomErr(NULL,
8158		XML_SCHEMAP_INTERNAL,
8159		NULL, NULL,
8160		"Internal error: xmlSchemaAddAnnotation, "
8161		"The item is not a annotated schema component", NULL);
8162	     break;
8163    }
8164    return (annot);
8165}
8166
8167/**
8168 * xmlSchemaParseIDCSelectorAndField:
8169 * @ctxt:  a schema validation context
8170 * @schema:  the schema being built
8171 * @node:  a subtree containing XML Schema informations
8172 *
8173 * Parses a XML Schema identity-contraint definition's
8174 * <selector> and <field> elements.
8175 *
8176 * Returns the parsed identity-constraint definition.
8177 */
8178static xmlSchemaIDCSelectPtr
8179xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8180			  xmlSchemaIDCPtr idc,
8181			  xmlNodePtr node,
8182			  int isField)
8183{
8184    xmlSchemaIDCSelectPtr item;
8185    xmlNodePtr child = NULL;
8186    xmlAttrPtr attr;
8187
8188    /*
8189    * Check for illegal attributes.
8190    */
8191    attr = node->properties;
8192    while (attr != NULL) {
8193	if (attr->ns == NULL) {
8194	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8195		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8196		xmlSchemaPIllegalAttrErr(ctxt,
8197		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8198	    }
8199	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8200	    xmlSchemaPIllegalAttrErr(ctxt,
8201		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8202	}
8203	attr = attr->next;
8204    }
8205    /*
8206    * Create the item.
8207    */
8208    item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8209    if (item == NULL) {
8210        xmlSchemaPErrMemory(ctxt,
8211	    "allocating a 'selector' of an identity-constraint definition",
8212	    NULL);
8213        return (NULL);
8214    }
8215    memset(item, 0, sizeof(xmlSchemaIDCSelect));
8216    /*
8217    * Attribute "xpath" (mandatory).
8218    */
8219    attr = xmlSchemaGetPropNode(node, "xpath");
8220    if (attr == NULL) {
8221    	xmlSchemaPMissingAttrErr(ctxt,
8222	    XML_SCHEMAP_S4S_ATTR_MISSING,
8223	    NULL, node,
8224	    "name", NULL);
8225    } else {
8226	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8227	/*
8228	* URGENT TODO: "field"s have an other syntax than "selector"s.
8229	*/
8230
8231	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8232	    isField) == -1) {
8233	    xmlSchemaPErr(ctxt,
8234		(xmlNodePtr) attr,
8235		XML_SCHEMAP_INTERNAL,
8236		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8237		"validating the XPath expression of a IDC selector.\n",
8238		NULL, NULL);
8239	}
8240
8241    }
8242    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8243    /*
8244    * And now for the children...
8245    */
8246    child = node->children;
8247    if (IS_SCHEMA(child, "annotation")) {
8248	/*
8249	* Add the annotation to the parent IDC.
8250	*/
8251	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8252	    xmlSchemaParseAnnotation(ctxt, child, 1));
8253	child = child->next;
8254    }
8255    if (child != NULL) {
8256	xmlSchemaPContentErr(ctxt,
8257	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8258	    NULL, node, child,
8259	    NULL, "(annotation?)");
8260    }
8261
8262    return (item);
8263}
8264
8265/**
8266 * xmlSchemaParseIDC:
8267 * @ctxt:  a schema validation context
8268 * @schema:  the schema being built
8269 * @node:  a subtree containing XML Schema informations
8270 *
8271 * Parses a XML Schema identity-contraint definition.
8272 *
8273 * Returns the parsed identity-constraint definition.
8274 */
8275static xmlSchemaIDCPtr
8276xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8277		  xmlSchemaPtr schema,
8278		  xmlNodePtr node,
8279		  xmlSchemaTypeType idcCategory,
8280		  const xmlChar *targetNamespace)
8281{
8282    xmlSchemaIDCPtr item = NULL;
8283    xmlNodePtr child = NULL;
8284    xmlAttrPtr attr;
8285    const xmlChar *name = NULL;
8286    xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8287
8288    /*
8289    * Check for illegal attributes.
8290    */
8291    attr = node->properties;
8292    while (attr != NULL) {
8293	if (attr->ns == NULL) {
8294	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8295		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8296		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8297		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8298		xmlSchemaPIllegalAttrErr(ctxt,
8299		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8300	    }
8301	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8302	    xmlSchemaPIllegalAttrErr(ctxt,
8303		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8304	}
8305	attr = attr->next;
8306    }
8307    /*
8308    * Attribute "name" (mandatory).
8309    */
8310    attr = xmlSchemaGetPropNode(node, "name");
8311    if (attr == NULL) {
8312	xmlSchemaPMissingAttrErr(ctxt,
8313	    XML_SCHEMAP_S4S_ATTR_MISSING,
8314	    NULL, node,
8315	    "name", NULL);
8316	return (NULL);
8317    } else if (xmlSchemaPValAttrNode(ctxt,
8318	NULL, attr,
8319	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8320	return (NULL);
8321    }
8322    /* Create the component. */
8323    item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8324	idcCategory, node);
8325    if (item == NULL)
8326	return(NULL);
8327
8328    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8329    if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8330	/*
8331	* Attribute "refer" (mandatory).
8332	*/
8333	attr = xmlSchemaGetPropNode(node, "refer");
8334	if (attr == NULL) {
8335	    xmlSchemaPMissingAttrErr(ctxt,
8336		XML_SCHEMAP_S4S_ATTR_MISSING,
8337		NULL, node,
8338		"refer", NULL);
8339	} else {
8340	    /*
8341	    * Create a reference item.
8342	    */
8343	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8344		NULL, NULL);
8345	    if (item->ref == NULL)
8346		return (NULL);
8347	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8348		NULL, attr,
8349		&(item->ref->targetNamespace),
8350		&(item->ref->name));
8351	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8352		item->ref->targetNamespace);
8353	}
8354    }
8355    /*
8356    * And now for the children...
8357    */
8358    child = node->children;
8359    if (IS_SCHEMA(child, "annotation")) {
8360	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8361	child = child->next;
8362    }
8363    if (child == NULL) {
8364	xmlSchemaPContentErr(ctxt,
8365		XML_SCHEMAP_S4S_ELEM_MISSING,
8366		NULL, node, child,
8367		"A child element is missing",
8368		"(annotation?, (selector, field+))");
8369    }
8370    /*
8371    * Child element <selector>.
8372    */
8373    if (IS_SCHEMA(child, "selector")) {
8374	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8375	    item, child, 0);
8376	child = child->next;
8377	/*
8378	* Child elements <field>.
8379	*/
8380	if (IS_SCHEMA(child, "field")) {
8381	    do {
8382		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8383		    item, child, 1);
8384		if (field != NULL) {
8385		    field->index = item->nbFields;
8386		    item->nbFields++;
8387		    if (lastField != NULL)
8388			lastField->next = field;
8389		    else
8390			item->fields = field;
8391		    lastField = field;
8392		}
8393		child = child->next;
8394	    } while (IS_SCHEMA(child, "field"));
8395	} else {
8396	    xmlSchemaPContentErr(ctxt,
8397		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8398		NULL, node, child,
8399		NULL, "(annotation?, (selector, field+))");
8400	}
8401    }
8402    if (child != NULL) {
8403	xmlSchemaPContentErr(ctxt,
8404	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8405	    NULL, node, child,
8406	    NULL, "(annotation?, (selector, field+))");
8407    }
8408
8409    return (item);
8410}
8411
8412/**
8413 * xmlSchemaParseElement:
8414 * @ctxt:  a schema validation context
8415 * @schema:  the schema being built
8416 * @node:  a subtree containing XML Schema informations
8417 * @topLevel: indicates if this is global declaration
8418 *
8419 * Parses a XML schema element declaration.
8420 * *WARNING* this interface is highly subject to change
8421 *
8422 * Returns the element declaration or a particle; NULL in case
8423 * of an error or if the particle has minOccurs==maxOccurs==0.
8424 */
8425static xmlSchemaBasicItemPtr
8426xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8427                      xmlNodePtr node, int *isElemRef, int topLevel)
8428{
8429    xmlSchemaElementPtr decl = NULL;
8430    xmlSchemaParticlePtr particle = NULL;
8431    xmlSchemaAnnotPtr annot = NULL;
8432    xmlNodePtr child = NULL;
8433    xmlAttrPtr attr, nameAttr;
8434    int min, max, isRef = 0;
8435    xmlChar *des = NULL;
8436
8437    /* 3.3.3 Constraints on XML Representations of Element Declarations */
8438    /* TODO: Complete implementation of 3.3.6 */
8439
8440    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8441        return (NULL);
8442
8443    if (isElemRef != NULL)
8444	*isElemRef = 0;
8445    /*
8446    * If we get a "ref" attribute on a local <element> we will assume it's
8447    * a reference - even if there's a "name" attribute; this seems to be more
8448    * robust.
8449    */
8450    nameAttr = xmlSchemaGetPropNode(node, "name");
8451    attr = xmlSchemaGetPropNode(node, "ref");
8452    if ((topLevel) || (attr == NULL)) {
8453	if (nameAttr == NULL) {
8454	    xmlSchemaPMissingAttrErr(ctxt,
8455		XML_SCHEMAP_S4S_ATTR_MISSING,
8456		NULL, node, "name", NULL);
8457	    return (NULL);
8458	}
8459    } else
8460	isRef = 1;
8461
8462    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8463    child = node->children;
8464    if (IS_SCHEMA(child, "annotation")) {
8465	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8466	child = child->next;
8467    }
8468    /*
8469    * Skip particle part if a global declaration.
8470    */
8471    if (topLevel)
8472	goto declaration_part;
8473    /*
8474    * The particle part ==================================================
8475    */
8476    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8477    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8478    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8479    particle = xmlSchemaAddParticle(ctxt, node, min, max);
8480    if (particle == NULL)
8481	goto return_null;
8482
8483    /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8484
8485    if (isRef) {
8486	const xmlChar *refNs = NULL, *ref = NULL;
8487	xmlSchemaQNameRefPtr refer = NULL;
8488	/*
8489	* The reference part =============================================
8490	*/
8491	if (isElemRef != NULL)
8492	    *isElemRef = 1;
8493
8494	xmlSchemaPValAttrNodeQName(ctxt, schema,
8495	    NULL, attr, &refNs, &ref);
8496	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8497	/*
8498	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8499	*/
8500	if (nameAttr != NULL) {
8501	    xmlSchemaPMutualExclAttrErr(ctxt,
8502		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8503	}
8504	/*
8505	* Check for illegal attributes.
8506	*/
8507	attr = node->properties;
8508	while (attr != NULL) {
8509	    if (attr->ns == NULL) {
8510		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8511		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8512		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8513		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8514		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8515		{
8516		    attr = attr->next;
8517		    continue;
8518		} else {
8519		    /* SPEC (3.3.3 : 2.2) */
8520		    xmlSchemaPCustomAttrErr(ctxt,
8521			XML_SCHEMAP_SRC_ELEMENT_2_2,
8522			NULL, NULL, attr,
8523			"Only the attributes 'minOccurs', 'maxOccurs' and "
8524			"'id' are allowed in addition to 'ref'");
8525		    break;
8526		}
8527	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8528		xmlSchemaPIllegalAttrErr(ctxt,
8529		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8530	    }
8531	    attr = attr->next;
8532	}
8533	/*
8534	* No children except <annotation> expected.
8535	*/
8536	if (child != NULL) {
8537	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8538		NULL, node, child, NULL, "(annotation?)");
8539	}
8540	if ((min == 0) && (max == 0))
8541	    goto return_null;
8542	/*
8543	* Create the reference item and attach it to the particle.
8544	*/
8545	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8546	    ref, refNs);
8547	if (refer == NULL)
8548	    goto return_null;
8549	particle->children = (xmlSchemaTreeItemPtr) refer;
8550	particle->annot = annot;
8551	/*
8552	* Add the particle to pending components, since the reference
8553	* need to be resolved.
8554	*/
8555	WXS_ADD_PENDING(ctxt, particle);
8556	return ((xmlSchemaBasicItemPtr) particle);
8557    }
8558    /*
8559    * The declaration part ===============================================
8560    */
8561declaration_part:
8562    {
8563	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8564	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8565
8566	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8567	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8568	    goto return_null;
8569	/*
8570	* Evaluate the target namespace.
8571	*/
8572	if (topLevel) {
8573	    ns = ctxt->targetNamespace;
8574	} else {
8575	    attr = xmlSchemaGetPropNode(node, "form");
8576	    if (attr != NULL) {
8577		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8578		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8579		    ns = ctxt->targetNamespace;
8580		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8581		    xmlSchemaPSimpleTypeErr(ctxt,
8582			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8583			NULL, (xmlNodePtr) attr,
8584			NULL, "(qualified | unqualified)",
8585			attrValue, NULL, NULL, NULL);
8586		}
8587	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8588		ns = ctxt->targetNamespace;
8589	}
8590	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8591	if (decl == NULL) {
8592	    goto return_null;
8593	}
8594	/*
8595	* Check for illegal attributes.
8596	*/
8597	attr = node->properties;
8598	while (attr != NULL) {
8599	    if (attr->ns == NULL) {
8600		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8601		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8602		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8603		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8604		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8605		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8606		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8607		{
8608		    if (topLevel == 0) {
8609			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8610			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8611			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8612			{
8613			    xmlSchemaPIllegalAttrErr(ctxt,
8614				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8615			}
8616		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8617			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8618			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8619
8620			xmlSchemaPIllegalAttrErr(ctxt,
8621			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8622		    }
8623		}
8624	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8625
8626		xmlSchemaPIllegalAttrErr(ctxt,
8627		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8628	    }
8629	    attr = attr->next;
8630	}
8631	/*
8632	* Extract/validate attributes.
8633	*/
8634	if (topLevel) {
8635	    /*
8636	    * Process top attributes of global element declarations here.
8637	    */
8638	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8639	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8640	    xmlSchemaPValAttrQName(ctxt, schema,
8641		NULL, node, "substitutionGroup",
8642		&(decl->substGroupNs), &(decl->substGroup));
8643	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8644		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8645	    /*
8646	    * Attribute "final".
8647	    */
8648	    attr = xmlSchemaGetPropNode(node, "final");
8649	    if (attr == NULL) {
8650		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8651		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8652		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8653		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8654	    } else {
8655		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8656		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8657		    -1,
8658		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8659		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8660		    xmlSchemaPSimpleTypeErr(ctxt,
8661			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8662			NULL, (xmlNodePtr) attr,
8663			NULL, "(#all | List of (extension | restriction))",
8664			attrValue, NULL, NULL, NULL);
8665		}
8666	    }
8667	}
8668	/*
8669	* Attribute "block".
8670	*/
8671	attr = xmlSchemaGetPropNode(node, "block");
8672	if (attr == NULL) {
8673	    /*
8674	    * Apply default "block" values.
8675	    */
8676	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8677		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8678	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8679		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8680	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8681		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8682	} else {
8683	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8684	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8685		-1,
8686		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8687		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8688		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8689		xmlSchemaPSimpleTypeErr(ctxt,
8690		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8691		    NULL, (xmlNodePtr) attr,
8692		    NULL, "(#all | List of (extension | "
8693		    "restriction | substitution))", attrValue,
8694		    NULL, NULL, NULL);
8695	    }
8696	}
8697	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8698	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8699
8700	attr = xmlSchemaGetPropNode(node, "type");
8701	if (attr != NULL) {
8702	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8703		NULL, attr,
8704		&(decl->namedTypeNs), &(decl->namedType));
8705	    xmlSchemaCheckReference(ctxt, schema, node,
8706		attr, decl->namedTypeNs);
8707	}
8708	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8709	attr = xmlSchemaGetPropNode(node, "fixed");
8710	if (attr != NULL) {
8711	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8712	    if (decl->value != NULL) {
8713		/*
8714		* 3.3.3 : 1
8715		* default and fixed must not both be present.
8716		*/
8717		xmlSchemaPMutualExclAttrErr(ctxt,
8718		    XML_SCHEMAP_SRC_ELEMENT_1,
8719		    NULL, attr, "default", "fixed");
8720	    } else {
8721		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8722		decl->value = fixed;
8723	    }
8724	}
8725	/*
8726	* And now for the children...
8727	*/
8728	if (IS_SCHEMA(child, "complexType")) {
8729	    /*
8730	    * 3.3.3 : 3
8731	    * "type" and either <simpleType> or <complexType> are mutually
8732	    * exclusive
8733	    */
8734	    if (decl->namedType != NULL) {
8735		xmlSchemaPContentErr(ctxt,
8736		    XML_SCHEMAP_SRC_ELEMENT_3,
8737		    NULL, node, child,
8738		    "The attribute 'type' and the <complexType> child are "
8739		    "mutually exclusive", NULL);
8740	    } else
8741		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8742	    child = child->next;
8743	} else if (IS_SCHEMA(child, "simpleType")) {
8744	    /*
8745	    * 3.3.3 : 3
8746	    * "type" and either <simpleType> or <complexType> are
8747	    * mutually exclusive
8748	    */
8749	    if (decl->namedType != NULL) {
8750		xmlSchemaPContentErr(ctxt,
8751		    XML_SCHEMAP_SRC_ELEMENT_3,
8752		    NULL, node, child,
8753		    "The attribute 'type' and the <simpleType> child are "
8754		    "mutually exclusive", NULL);
8755	    } else
8756		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8757	    child = child->next;
8758	}
8759	while ((IS_SCHEMA(child, "unique")) ||
8760	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8761	    if (IS_SCHEMA(child, "unique")) {
8762		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8763		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8764	    } else if (IS_SCHEMA(child, "key")) {
8765		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8766		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8767	    } else if (IS_SCHEMA(child, "keyref")) {
8768		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8769		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8770	    }
8771	    if (lastIDC != NULL)
8772		lastIDC->next = curIDC;
8773	    else
8774		decl->idcs = (void *) curIDC;
8775	    lastIDC = curIDC;
8776	    child = child->next;
8777	}
8778	if (child != NULL) {
8779	    xmlSchemaPContentErr(ctxt,
8780		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8781		NULL, node, child,
8782		NULL, "(annotation?, ((simpleType | complexType)?, "
8783		"(unique | key | keyref)*))");
8784	}
8785	decl->annot = annot;
8786    }
8787    /*
8788    * NOTE: Element Declaration Representation OK 4. will be checked at a
8789    * different layer.
8790    */
8791    FREE_AND_NULL(des)
8792    if (topLevel)
8793	return ((xmlSchemaBasicItemPtr) decl);
8794    else {
8795	particle->children = (xmlSchemaTreeItemPtr) decl;
8796	return ((xmlSchemaBasicItemPtr) particle);
8797    }
8798
8799return_null:
8800    FREE_AND_NULL(des);
8801    if (annot != NULL) {
8802	if (particle != NULL)
8803	    particle->annot = NULL;
8804	if (decl != NULL)
8805	    decl->annot = NULL;
8806	xmlSchemaFreeAnnot(annot);
8807    }
8808    return (NULL);
8809}
8810
8811/**
8812 * xmlSchemaParseUnion:
8813 * @ctxt:  a schema validation context
8814 * @schema:  the schema being built
8815 * @node:  a subtree containing XML Schema informations
8816 *
8817 * parse a XML schema Union definition
8818 * *WARNING* this interface is highly subject to change
8819 *
8820 * Returns -1 in case of internal error, 0 in case of success and a positive
8821 * error code otherwise.
8822 */
8823static int
8824xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8825                    xmlNodePtr node)
8826{
8827    xmlSchemaTypePtr type;
8828    xmlNodePtr child = NULL;
8829    xmlAttrPtr attr;
8830    const xmlChar *cur = NULL;
8831
8832    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8833        return (-1);
8834    /* Not a component, don't create it. */
8835    type = ctxt->ctxtType;
8836    /*
8837    * Mark the simple type as being of variety "union".
8838    */
8839    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8840    /*
8841    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8842    * then the �simple ur-type definition�."
8843    */
8844    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8845    /*
8846    * Check for illegal attributes.
8847    */
8848    attr = node->properties;
8849    while (attr != NULL) {
8850	if (attr->ns == NULL) {
8851	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8852		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8853		xmlSchemaPIllegalAttrErr(ctxt,
8854		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8855	    }
8856	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8857	    xmlSchemaPIllegalAttrErr(ctxt,
8858		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8859	}
8860	attr = attr->next;
8861    }
8862    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8863    /*
8864    * Attribute "memberTypes". This is a list of QNames.
8865    * TODO: Check the value to contain anything.
8866    */
8867    attr = xmlSchemaGetPropNode(node, "memberTypes");
8868    if (attr != NULL) {
8869	const xmlChar *end;
8870	xmlChar *tmp;
8871	const xmlChar *localName, *nsName;
8872	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8873	xmlSchemaQNameRefPtr ref;
8874
8875	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8876	type->base = cur;
8877	do {
8878	    while (IS_BLANK_CH(*cur))
8879		cur++;
8880	    end = cur;
8881	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8882		end++;
8883	    if (end == cur)
8884		break;
8885	    tmp = xmlStrndup(cur, end - cur);
8886	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8887		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8888		/*
8889		* Create the member type link.
8890		*/
8891		link = (xmlSchemaTypeLinkPtr)
8892		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8893		if (link == NULL) {
8894		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8895			"allocating a type link", NULL);
8896		    return (-1);
8897		}
8898		link->type = NULL;
8899		link->next = NULL;
8900		if (lastLink == NULL)
8901		    type->memberTypes = link;
8902		else
8903		    lastLink->next = link;
8904		lastLink = link;
8905		/*
8906		* Create a reference item.
8907		*/
8908		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8909		    localName, nsName);
8910		if (ref == NULL) {
8911		    FREE_AND_NULL(tmp)
8912		    return (-1);
8913		}
8914		/*
8915		* Assign the reference to the link, it will be resolved
8916		* later during fixup of the union simple type.
8917		*/
8918		link->type = (xmlSchemaTypePtr) ref;
8919	    }
8920	    FREE_AND_NULL(tmp)
8921	    cur = end;
8922	} while (*cur != 0);
8923
8924    }
8925    /*
8926    * And now for the children...
8927    */
8928    child = node->children;
8929    if (IS_SCHEMA(child, "annotation")) {
8930	/*
8931	* Add the annotation to the simple type ancestor.
8932	*/
8933	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8934	    xmlSchemaParseAnnotation(ctxt, child, 1));
8935        child = child->next;
8936    }
8937    if (IS_SCHEMA(child, "simpleType")) {
8938	xmlSchemaTypePtr subtype, last = NULL;
8939
8940	/*
8941	* Anchor the member types in the "subtypes" field of the
8942	* simple type.
8943	*/
8944	while (IS_SCHEMA(child, "simpleType")) {
8945	    subtype = (xmlSchemaTypePtr)
8946		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8947	    if (subtype != NULL) {
8948		if (last == NULL) {
8949		    type->subtypes = subtype;
8950		    last = subtype;
8951		} else {
8952		    last->next = subtype;
8953		    last = subtype;
8954		}
8955		last->next = NULL;
8956	    }
8957	    child = child->next;
8958	}
8959    }
8960    if (child != NULL) {
8961	xmlSchemaPContentErr(ctxt,
8962	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8963	    NULL, node, child, NULL, "(annotation?, simpleType*)");
8964    }
8965    if ((attr == NULL) && (type->subtypes == NULL)) {
8966	 /*
8967	* src-union-memberTypes-or-simpleTypes
8968	* Either the memberTypes [attribute] of the <union> element must
8969	* be non-empty or there must be at least one simpleType [child].
8970	*/
8971	xmlSchemaPCustomErr(ctxt,
8972	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8973	    NULL, node,
8974	    "Either the attribute 'memberTypes' or "
8975	    "at least one <simpleType> child must be present", NULL);
8976    }
8977    return (0);
8978}
8979
8980/**
8981 * xmlSchemaParseList:
8982 * @ctxt:  a schema validation context
8983 * @schema:  the schema being built
8984 * @node:  a subtree containing XML Schema informations
8985 *
8986 * parse a XML schema List definition
8987 * *WARNING* this interface is highly subject to change
8988 *
8989 * Returns -1 in case of error, 0 if the declaration is improper and
8990 *         1 in case of success.
8991 */
8992static xmlSchemaTypePtr
8993xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8994                   xmlNodePtr node)
8995{
8996    xmlSchemaTypePtr type;
8997    xmlNodePtr child = NULL;
8998    xmlAttrPtr attr;
8999
9000    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9001        return (NULL);
9002    /* Not a component, don't create it. */
9003    type = ctxt->ctxtType;
9004    /*
9005    * Mark the type as being of variety "list".
9006    */
9007    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9008    /*
9009    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9010    * then the �simple ur-type definition�."
9011    */
9012    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9013    /*
9014    * Check for illegal attributes.
9015    */
9016    attr = node->properties;
9017    while (attr != NULL) {
9018	if (attr->ns == NULL) {
9019	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9020		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9021		xmlSchemaPIllegalAttrErr(ctxt,
9022		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9023	    }
9024	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9025	    xmlSchemaPIllegalAttrErr(ctxt,
9026		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9027	}
9028	attr = attr->next;
9029    }
9030
9031    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9032
9033    /*
9034    * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9035    * fields for holding the reference to the itemType.
9036    *
9037    * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9038    * the "ref" fields.
9039    */
9040    xmlSchemaPValAttrQName(ctxt, schema, NULL,
9041	node, "itemType", &(type->baseNs), &(type->base));
9042    /*
9043    * And now for the children...
9044    */
9045    child = node->children;
9046    if (IS_SCHEMA(child, "annotation")) {
9047	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9048	    xmlSchemaParseAnnotation(ctxt, child, 1));
9049        child = child->next;
9050    }
9051    if (IS_SCHEMA(child, "simpleType")) {
9052	/*
9053	* src-list-itemType-or-simpleType
9054	* Either the itemType [attribute] or the <simpleType> [child] of
9055	* the <list> element must be present, but not both.
9056	*/
9057	if (type->base != NULL) {
9058	    xmlSchemaPCustomErr(ctxt,
9059		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9060		NULL, node,
9061		"The attribute 'itemType' and the <simpleType> child "
9062		"are mutually exclusive", NULL);
9063	} else {
9064	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9065	}
9066        child = child->next;
9067    } else if (type->base == NULL) {
9068	xmlSchemaPCustomErr(ctxt,
9069	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9070	    NULL, node,
9071	    "Either the attribute 'itemType' or the <simpleType> child "
9072	    "must be present", NULL);
9073    }
9074    if (child != NULL) {
9075	xmlSchemaPContentErr(ctxt,
9076	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9077	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9078    }
9079    if ((type->base == NULL) &&
9080	(type->subtypes == NULL) &&
9081	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9082	xmlSchemaPCustomErr(ctxt,
9083	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9084	    NULL, node,
9085	    "Either the attribute 'itemType' or the <simpleType> child "
9086	    "must be present", NULL);
9087    }
9088    return (NULL);
9089}
9090
9091/**
9092 * xmlSchemaParseSimpleType:
9093 * @ctxt:  a schema validation context
9094 * @schema:  the schema being built
9095 * @node:  a subtree containing XML Schema informations
9096 *
9097 * parse a XML schema Simple Type definition
9098 * *WARNING* this interface is highly subject to change
9099 *
9100 * Returns -1 in case of error, 0 if the declaration is improper and
9101 * 1 in case of success.
9102 */
9103static xmlSchemaTypePtr
9104xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9105                         xmlNodePtr node, int topLevel)
9106{
9107    xmlSchemaTypePtr type, oldCtxtType;
9108    xmlNodePtr child = NULL;
9109    const xmlChar *attrValue = NULL;
9110    xmlAttrPtr attr;
9111    int hasRestriction = 0;
9112
9113    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9114        return (NULL);
9115
9116    if (topLevel) {
9117	attr = xmlSchemaGetPropNode(node, "name");
9118	if (attr == NULL) {
9119	    xmlSchemaPMissingAttrErr(ctxt,
9120		XML_SCHEMAP_S4S_ATTR_MISSING,
9121		NULL, node,
9122		"name", NULL);
9123	    return (NULL);
9124	} else {
9125	    if (xmlSchemaPValAttrNode(ctxt,
9126		NULL, attr,
9127		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9128		return (NULL);
9129	    /*
9130	    * Skip built-in types.
9131	    */
9132	    if (ctxt->isS4S) {
9133		xmlSchemaTypePtr biType;
9134
9135		if (ctxt->isRedefine) {
9136		    /*
9137		    * REDEFINE: Disallow redefinition of built-in-types.
9138		    * TODO: It seems that the spec does not say anything
9139		    * about this case.
9140		    */
9141		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9142			NULL, node,
9143			"Redefinition of built-in simple types is not "
9144			"supported", NULL);
9145		    return(NULL);
9146		}
9147		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9148		if (biType != NULL)
9149		    return (biType);
9150	    }
9151	}
9152    }
9153    /*
9154    * TargetNamespace:
9155    * SPEC "The �actual value� of the targetNamespace [attribute]
9156    * of the <schema> ancestor element information item if present,
9157    * otherwise �absent�.
9158    */
9159    if (topLevel == 0) {
9160#ifdef ENABLE_NAMED_LOCALS
9161        char buf[40];
9162#endif
9163	/*
9164	* Parse as local simple type definition.
9165	*/
9166#ifdef ENABLE_NAMED_LOCALS
9167        snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9168	type = xmlSchemaAddType(ctxt, schema,
9169	    XML_SCHEMA_TYPE_SIMPLE,
9170	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9171	    ctxt->targetNamespace, node, 0);
9172#else
9173	type = xmlSchemaAddType(ctxt, schema,
9174	    XML_SCHEMA_TYPE_SIMPLE,
9175	    NULL, ctxt->targetNamespace, node, 0);
9176#endif
9177	if (type == NULL)
9178	    return (NULL);
9179	type->type = XML_SCHEMA_TYPE_SIMPLE;
9180	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9181	/*
9182	* Check for illegal attributes.
9183	*/
9184	attr = node->properties;
9185	while (attr != NULL) {
9186	    if (attr->ns == NULL) {
9187		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9188		    xmlSchemaPIllegalAttrErr(ctxt,
9189			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9190		}
9191	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9192		    xmlSchemaPIllegalAttrErr(ctxt,
9193			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9194	    }
9195	    attr = attr->next;
9196	}
9197    } else {
9198	/*
9199	* Parse as global simple type definition.
9200	*
9201	* Note that attrValue is the value of the attribute "name" here.
9202	*/
9203	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9204	    attrValue, ctxt->targetNamespace, node, 1);
9205	if (type == NULL)
9206	    return (NULL);
9207	type->type = XML_SCHEMA_TYPE_SIMPLE;
9208	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9209	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9210	/*
9211	* Check for illegal attributes.
9212	*/
9213	attr = node->properties;
9214	while (attr != NULL) {
9215	    if (attr->ns == NULL) {
9216		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9217		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9218		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9219		    xmlSchemaPIllegalAttrErr(ctxt,
9220			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9221		}
9222	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9223		xmlSchemaPIllegalAttrErr(ctxt,
9224		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9225	    }
9226	    attr = attr->next;
9227	}
9228	/*
9229	* Attribute "final".
9230	*/
9231	attr = xmlSchemaGetPropNode(node, "final");
9232	if (attr == NULL) {
9233	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9234		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9235	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9236		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9237	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9238		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9239	} else {
9240	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9241	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9242		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9243		XML_SCHEMAS_TYPE_FINAL_LIST,
9244		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9245
9246		xmlSchemaPSimpleTypeErr(ctxt,
9247		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9248		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9249		    NULL, "(#all | List of (list | union | restriction)",
9250		    attrValue, NULL, NULL, NULL);
9251	    }
9252	}
9253    }
9254    type->targetNamespace = ctxt->targetNamespace;
9255    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9256    /*
9257    * And now for the children...
9258    */
9259    oldCtxtType = ctxt->ctxtType;
9260
9261    ctxt->ctxtType = type;
9262
9263    child = node->children;
9264    if (IS_SCHEMA(child, "annotation")) {
9265        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9266        child = child->next;
9267    }
9268    if (child == NULL) {
9269	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9270	    NULL, node, child, NULL,
9271	    "(annotation?, (restriction | list | union))");
9272    } else if (IS_SCHEMA(child, "restriction")) {
9273        xmlSchemaParseRestriction(ctxt, schema, child,
9274	    XML_SCHEMA_TYPE_SIMPLE);
9275	hasRestriction = 1;
9276        child = child->next;
9277    } else if (IS_SCHEMA(child, "list")) {
9278        xmlSchemaParseList(ctxt, schema, child);
9279        child = child->next;
9280    } else if (IS_SCHEMA(child, "union")) {
9281        xmlSchemaParseUnion(ctxt, schema, child);
9282        child = child->next;
9283    }
9284    if (child != NULL) {
9285	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9286	    NULL, node, child, NULL,
9287	    "(annotation?, (restriction | list | union))");
9288    }
9289    /*
9290    * REDEFINE: SPEC src-redefine (5)
9291    * "Within the [children], each <simpleType> must have a
9292    * <restriction> among its [children] ... the �actual value� of whose
9293    * base [attribute] must be the same as the �actual value� of its own
9294    * name attribute plus target namespace;"
9295    */
9296    if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9297	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9298	    NULL, node, "This is a redefinition, thus the "
9299	    "<simpleType> must have a <restriction> child", NULL);
9300    }
9301
9302    ctxt->ctxtType = oldCtxtType;
9303    return (type);
9304}
9305
9306/**
9307 * xmlSchemaParseModelGroupDefRef:
9308 * @ctxt:  the parser context
9309 * @schema: the schema being built
9310 * @node:  the node
9311 *
9312 * Parses a reference to a model group definition.
9313 *
9314 * We will return a particle component with a qname-component or
9315 * NULL in case of an error.
9316 */
9317static xmlSchemaTreeItemPtr
9318xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9319			       xmlSchemaPtr schema,
9320			       xmlNodePtr node)
9321{
9322    xmlSchemaParticlePtr item;
9323    xmlNodePtr child = NULL;
9324    xmlAttrPtr attr;
9325    const xmlChar *ref = NULL, *refNs = NULL;
9326    int min, max;
9327
9328    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9329        return (NULL);
9330
9331    attr = xmlSchemaGetPropNode(node, "ref");
9332    if (attr == NULL) {
9333	xmlSchemaPMissingAttrErr(ctxt,
9334	    XML_SCHEMAP_S4S_ATTR_MISSING,
9335	    NULL, node, "ref", NULL);
9336	return (NULL);
9337    } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9338	attr, &refNs, &ref) != 0) {
9339	return (NULL);
9340    }
9341    xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9342    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9343    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9344	"(xs:nonNegativeInteger | unbounded)");
9345    /*
9346    * Check for illegal attributes.
9347    */
9348    attr = node->properties;
9349    while (attr != NULL) {
9350	if (attr->ns == NULL) {
9351	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9352		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9353		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9354		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9355		xmlSchemaPIllegalAttrErr(ctxt,
9356		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9357	    }
9358	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9359	    xmlSchemaPIllegalAttrErr(ctxt,
9360		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9361	}
9362	attr = attr->next;
9363    }
9364    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9365    item = xmlSchemaAddParticle(ctxt, node, min, max);
9366    if (item == NULL)
9367	return (NULL);
9368    /*
9369    * Create a qname-reference and set as the term; it will be substituted
9370    * for the model group after the reference has been resolved.
9371    */
9372    item->children = (xmlSchemaTreeItemPtr)
9373	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9374    xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9375    /*
9376    * And now for the children...
9377    */
9378    child = node->children;
9379    /* TODO: Is annotation even allowed for a model group reference? */
9380    if (IS_SCHEMA(child, "annotation")) {
9381	/*
9382	* TODO: What to do exactly with the annotation?
9383	*/
9384	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9385	child = child->next;
9386    }
9387    if (child != NULL) {
9388	xmlSchemaPContentErr(ctxt,
9389	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9390	    NULL, node, child, NULL,
9391	    "(annotation?)");
9392    }
9393    /*
9394    * Corresponds to no component at all if minOccurs==maxOccurs==0.
9395    */
9396    if ((min == 0) && (max == 0))
9397	return (NULL);
9398
9399    return ((xmlSchemaTreeItemPtr) item);
9400}
9401
9402/**
9403 * xmlSchemaParseModelGroupDefinition:
9404 * @ctxt:  a schema validation context
9405 * @schema:  the schema being built
9406 * @node:  a subtree containing XML Schema informations
9407 *
9408 * Parses a XML schema model group definition.
9409 *
9410 * Note that the contraint src-redefine (6.2) can't be applied until
9411 * references have been resolved. So we will do this at the
9412 * component fixup level.
9413 *
9414 * *WARNING* this interface is highly subject to change
9415 *
9416 * Returns -1 in case of error, 0 if the declaration is improper and
9417 *         1 in case of success.
9418 */
9419static xmlSchemaModelGroupDefPtr
9420xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9421				   xmlSchemaPtr schema,
9422				   xmlNodePtr node)
9423{
9424    xmlSchemaModelGroupDefPtr item;
9425    xmlNodePtr child = NULL;
9426    xmlAttrPtr attr;
9427    const xmlChar *name;
9428
9429    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9430        return (NULL);
9431
9432    attr = xmlSchemaGetPropNode(node, "name");
9433    if (attr == NULL) {
9434	xmlSchemaPMissingAttrErr(ctxt,
9435	    XML_SCHEMAP_S4S_ATTR_MISSING,
9436	    NULL, node,
9437	    "name", NULL);
9438	return (NULL);
9439    } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9440	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9441	return (NULL);
9442    }
9443    item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9444	ctxt->targetNamespace, node);
9445    if (item == NULL)
9446	return (NULL);
9447    /*
9448    * Check for illegal attributes.
9449    */
9450    attr = node->properties;
9451    while (attr != NULL) {
9452	if (attr->ns == NULL) {
9453	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9454		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9455		xmlSchemaPIllegalAttrErr(ctxt,
9456		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9457	    }
9458	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9459	    xmlSchemaPIllegalAttrErr(ctxt,
9460		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9461	}
9462	attr = attr->next;
9463    }
9464    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9465    /*
9466    * And now for the children...
9467    */
9468    child = node->children;
9469    if (IS_SCHEMA(child, "annotation")) {
9470	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9471	child = child->next;
9472    }
9473    if (IS_SCHEMA(child, "all")) {
9474	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9475	    XML_SCHEMA_TYPE_ALL, 0);
9476	child = child->next;
9477    } else if (IS_SCHEMA(child, "choice")) {
9478	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9479	    XML_SCHEMA_TYPE_CHOICE, 0);
9480	child = child->next;
9481    } else if (IS_SCHEMA(child, "sequence")) {
9482	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9483	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9484	child = child->next;
9485    }
9486
9487
9488
9489    if (child != NULL) {
9490	xmlSchemaPContentErr(ctxt,
9491	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9492	    NULL, node, child, NULL,
9493	    "(annotation?, (all | choice | sequence)?)");
9494    }
9495    return (item);
9496}
9497
9498/**
9499 * xmlSchemaCleanupDoc:
9500 * @ctxt:  a schema validation context
9501 * @node:  the root of the document.
9502 *
9503 * removes unwanted nodes in a schemas document tree
9504 */
9505static void
9506xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9507{
9508    xmlNodePtr delete, cur;
9509
9510    if ((ctxt == NULL) || (root == NULL)) return;
9511
9512    /*
9513     * Remove all the blank text nodes
9514     */
9515    delete = NULL;
9516    cur = root;
9517    while (cur != NULL) {
9518        if (delete != NULL) {
9519            xmlUnlinkNode(delete);
9520            xmlFreeNode(delete);
9521            delete = NULL;
9522        }
9523        if (cur->type == XML_TEXT_NODE) {
9524            if (IS_BLANK_NODE(cur)) {
9525                if (xmlNodeGetSpacePreserve(cur) != 1) {
9526                    delete = cur;
9527                }
9528            }
9529        } else if ((cur->type != XML_ELEMENT_NODE) &&
9530                   (cur->type != XML_CDATA_SECTION_NODE)) {
9531            delete = cur;
9532            goto skip_children;
9533        }
9534
9535        /*
9536         * Skip to next node
9537         */
9538        if (cur->children != NULL) {
9539            if ((cur->children->type != XML_ENTITY_DECL) &&
9540                (cur->children->type != XML_ENTITY_REF_NODE) &&
9541                (cur->children->type != XML_ENTITY_NODE)) {
9542                cur = cur->children;
9543                continue;
9544            }
9545        }
9546      skip_children:
9547        if (cur->next != NULL) {
9548            cur = cur->next;
9549            continue;
9550        }
9551
9552        do {
9553            cur = cur->parent;
9554            if (cur == NULL)
9555                break;
9556            if (cur == root) {
9557                cur = NULL;
9558                break;
9559            }
9560            if (cur->next != NULL) {
9561                cur = cur->next;
9562                break;
9563            }
9564        } while (cur != NULL);
9565    }
9566    if (delete != NULL) {
9567        xmlUnlinkNode(delete);
9568        xmlFreeNode(delete);
9569        delete = NULL;
9570    }
9571}
9572
9573
9574static void
9575xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9576{
9577    if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9578	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9579
9580    if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9581	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9582
9583    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9584	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9585    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9586	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9587    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9588	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9589    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9590	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9591
9592    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9593	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9594    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9595	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9596    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9597	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9598}
9599
9600static int
9601xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9602			     xmlSchemaPtr schema,
9603			     xmlNodePtr node)
9604{
9605    xmlAttrPtr attr;
9606    const xmlChar *val;
9607    int res = 0, oldErrs = ctxt->nberrors;
9608
9609    /*
9610    * Those flags should be moved to the parser context flags,
9611    * since they are not visible at the component level. I.e.
9612    * they are used if processing schema *documents* only.
9613    */
9614    res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9615    HFAILURE;
9616
9617    /*
9618    * Since the version is of type xs:token, we won't bother to
9619    * check it.
9620    */
9621    /* REMOVED:
9622    attr = xmlSchemaGetPropNode(node, "version");
9623    if (attr != NULL) {
9624	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9625	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9626	HFAILURE;
9627    }
9628    */
9629    attr = xmlSchemaGetPropNode(node, "targetNamespace");
9630    if (attr != NULL) {
9631	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9632	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9633	HFAILURE;
9634	if (res != 0) {
9635	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9636	    goto exit;
9637	}
9638    }
9639    attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9640    if (attr != NULL) {
9641	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9642	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9643	    XML_SCHEMAS_QUALIF_ELEM);
9644	HFAILURE;
9645	if (res != 0) {
9646	    xmlSchemaPSimpleTypeErr(ctxt,
9647		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9648		NULL, (xmlNodePtr) attr, NULL,
9649		"(qualified | unqualified)", val, NULL, NULL, NULL);
9650	}
9651    }
9652    attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9653    if (attr != NULL) {
9654	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9655	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9656	    XML_SCHEMAS_QUALIF_ATTR);
9657	HFAILURE;
9658	if (res != 0) {
9659	    xmlSchemaPSimpleTypeErr(ctxt,
9660		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9661		NULL, (xmlNodePtr) attr, NULL,
9662		"(qualified | unqualified)", val, NULL, NULL, NULL);
9663	}
9664    }
9665    attr = xmlSchemaGetPropNode(node, "finalDefault");
9666    if (attr != NULL) {
9667	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9668	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9669	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9670	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9671	    -1,
9672	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9673	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9674	HFAILURE;
9675	if (res != 0) {
9676	    xmlSchemaPSimpleTypeErr(ctxt,
9677		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9678		NULL, (xmlNodePtr) attr, NULL,
9679		"(#all | List of (extension | restriction | list | union))",
9680		val, NULL, NULL, NULL);
9681	}
9682    }
9683    attr = xmlSchemaGetPropNode(node, "blockDefault");
9684    if (attr != NULL) {
9685	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9686	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9687	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9688	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9689	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9690	HFAILURE;
9691	if (res != 0) {
9692	    xmlSchemaPSimpleTypeErr(ctxt,
9693		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9694		NULL, (xmlNodePtr) attr, NULL,
9695		"(#all | List of (extension | restriction | substitution))",
9696		val, NULL, NULL, NULL);
9697	}
9698    }
9699
9700exit:
9701    if (oldErrs != ctxt->nberrors)
9702	res = ctxt->err;
9703    return(res);
9704exit_failure:
9705    return(-1);
9706}
9707
9708/**
9709 * xmlSchemaParseSchemaTopLevel:
9710 * @ctxt:  a schema validation context
9711 * @schema:  the schemas
9712 * @nodes:  the list of top level nodes
9713 *
9714 * Returns the internal XML Schema structure built from the resource or
9715 *         NULL in case of error
9716 */
9717static int
9718xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9719                             xmlSchemaPtr schema, xmlNodePtr nodes)
9720{
9721    xmlNodePtr child;
9722    xmlSchemaAnnotPtr annot;
9723    int res = 0, oldErrs, tmpOldErrs;
9724
9725    if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9726        return(-1);
9727
9728    oldErrs = ctxt->nberrors;
9729    child = nodes;
9730    while ((IS_SCHEMA(child, "include")) ||
9731	   (IS_SCHEMA(child, "import")) ||
9732	   (IS_SCHEMA(child, "redefine")) ||
9733	   (IS_SCHEMA(child, "annotation"))) {
9734	if (IS_SCHEMA(child, "annotation")) {
9735	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9736	    if (schema->annot == NULL)
9737		schema->annot = annot;
9738	    else
9739		xmlSchemaFreeAnnot(annot);
9740	} else if (IS_SCHEMA(child, "import")) {
9741	    tmpOldErrs = ctxt->nberrors;
9742	    res = xmlSchemaParseImport(ctxt, schema, child);
9743	    HFAILURE;
9744	    HSTOP(ctxt);
9745	    if (tmpOldErrs != ctxt->nberrors)
9746		goto exit;
9747	} else if (IS_SCHEMA(child, "include")) {
9748	    tmpOldErrs = ctxt->nberrors;
9749	    res = xmlSchemaParseInclude(ctxt, schema, child);
9750	    HFAILURE;
9751	    HSTOP(ctxt);
9752	    if (tmpOldErrs != ctxt->nberrors)
9753		goto exit;
9754	} else if (IS_SCHEMA(child, "redefine")) {
9755	    tmpOldErrs = ctxt->nberrors;
9756	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9757	    HFAILURE;
9758	    HSTOP(ctxt);
9759	    if (tmpOldErrs != ctxt->nberrors)
9760		goto exit;
9761	}
9762	child = child->next;
9763    }
9764    /*
9765    * URGENT TODO: Change the functions to return int results.
9766    * We need especially to catch internal errors.
9767    */
9768    while (child != NULL) {
9769	if (IS_SCHEMA(child, "complexType")) {
9770	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9771	    child = child->next;
9772	} else if (IS_SCHEMA(child, "simpleType")) {
9773	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9774	    child = child->next;
9775	} else if (IS_SCHEMA(child, "element")) {
9776	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9777	    child = child->next;
9778	} else if (IS_SCHEMA(child, "attribute")) {
9779	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9780	    child = child->next;
9781	} else if (IS_SCHEMA(child, "attributeGroup")) {
9782	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9783	    child = child->next;
9784	} else if (IS_SCHEMA(child, "group")) {
9785	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9786	    child = child->next;
9787	} else if (IS_SCHEMA(child, "notation")) {
9788	    xmlSchemaParseNotation(ctxt, schema, child);
9789	    child = child->next;
9790	} else {
9791	    xmlSchemaPContentErr(ctxt,
9792		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9793		NULL, child->parent, child,
9794		NULL, "((include | import | redefine | annotation)*, "
9795		"(((simpleType | complexType | group | attributeGroup) "
9796		"| element | attribute | notation), annotation*)*)");
9797	    child = child->next;
9798	}
9799	while (IS_SCHEMA(child, "annotation")) {
9800	    /*
9801	    * TODO: We should add all annotations.
9802	    */
9803	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9804	    if (schema->annot == NULL)
9805		schema->annot = annot;
9806	    else
9807		xmlSchemaFreeAnnot(annot);
9808	    child = child->next;
9809	}
9810    }
9811exit:
9812    ctxt->ctxtType = NULL;
9813    if (oldErrs != ctxt->nberrors)
9814	res = ctxt->err;
9815    return(res);
9816exit_failure:
9817    return(-1);
9818}
9819
9820static xmlSchemaSchemaRelationPtr
9821xmlSchemaSchemaRelationCreate(void)
9822{
9823    xmlSchemaSchemaRelationPtr ret;
9824
9825    ret = (xmlSchemaSchemaRelationPtr)
9826	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9827    if (ret == NULL) {
9828	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9829	return(NULL);
9830    }
9831    memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9832    return(ret);
9833}
9834
9835#if 0
9836static void
9837xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9838{
9839    xmlFree(rel);
9840}
9841#endif
9842
9843static void
9844xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9845{
9846    xmlSchemaRedefPtr prev;
9847
9848    while (redef != NULL) {
9849	prev = redef;
9850	redef = redef->next;
9851	xmlFree(prev);
9852    }
9853}
9854
9855static void
9856xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9857{
9858    /*
9859    * After the construction context has been freed, there will be
9860    * no schema graph available any more. Only the schema buckets
9861    * will stay alive, which are put into the "schemasImports" and
9862    * "includes" slots of the xmlSchema.
9863    */
9864    if (con->buckets != NULL)
9865	xmlSchemaItemListFree(con->buckets);
9866    if (con->pending != NULL)
9867	xmlSchemaItemListFree(con->pending);
9868    if (con->substGroups != NULL)
9869	xmlHashFree(con->substGroups,
9870	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9871    if (con->redefs != NULL)
9872	xmlSchemaRedefListFree(con->redefs);
9873    if (con->dict != NULL)
9874	xmlDictFree(con->dict);
9875    xmlFree(con);
9876}
9877
9878static xmlSchemaConstructionCtxtPtr
9879xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9880{
9881    xmlSchemaConstructionCtxtPtr ret;
9882
9883    ret = (xmlSchemaConstructionCtxtPtr)
9884	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9885    if (ret == NULL) {
9886        xmlSchemaPErrMemory(NULL,
9887	    "allocating schema construction context", NULL);
9888        return (NULL);
9889    }
9890    memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9891
9892    ret->buckets = xmlSchemaItemListCreate();
9893    if (ret->buckets == NULL) {
9894	xmlSchemaPErrMemory(NULL,
9895	    "allocating list of schema buckets", NULL);
9896	xmlFree(ret);
9897        return (NULL);
9898    }
9899    ret->pending = xmlSchemaItemListCreate();
9900    if (ret->pending == NULL) {
9901	xmlSchemaPErrMemory(NULL,
9902	    "allocating list of pending global components", NULL);
9903	xmlSchemaConstructionCtxtFree(ret);
9904        return (NULL);
9905    }
9906    ret->dict = dict;
9907    xmlDictReference(dict);
9908    return(ret);
9909}
9910
9911static xmlSchemaParserCtxtPtr
9912xmlSchemaParserCtxtCreate(void)
9913{
9914    xmlSchemaParserCtxtPtr ret;
9915
9916    ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9917    if (ret == NULL) {
9918        xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9919                            NULL);
9920        return (NULL);
9921    }
9922    memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9923    ret->type = XML_SCHEMA_CTXT_PARSER;
9924    ret->attrProhibs = xmlSchemaItemListCreate();
9925    if (ret->attrProhibs == NULL) {
9926	xmlFree(ret);
9927	return(NULL);
9928    }
9929    return(ret);
9930}
9931
9932/**
9933 * xmlSchemaNewParserCtxtUseDict:
9934 * @URL:  the location of the schema
9935 * @dict: the dictionary to be used
9936 *
9937 * Create an XML Schemas parse context for that file/resource expected
9938 * to contain an XML Schemas file.
9939 *
9940 * Returns the parser context or NULL in case of error
9941 */
9942static xmlSchemaParserCtxtPtr
9943xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9944{
9945    xmlSchemaParserCtxtPtr ret;
9946
9947    ret = xmlSchemaParserCtxtCreate();
9948    if (ret == NULL)
9949        return (NULL);
9950    ret->dict = dict;
9951    xmlDictReference(dict);
9952    if (URL != NULL)
9953	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9954    return (ret);
9955}
9956
9957static int
9958xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9959{
9960    if (vctxt->pctxt == NULL) {
9961        if (vctxt->schema != NULL)
9962	    vctxt->pctxt =
9963		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9964	else
9965	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9966	if (vctxt->pctxt == NULL) {
9967	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9968		"failed to create a temp. parser context");
9969	    return (-1);
9970	}
9971	/* TODO: Pass user data. */
9972	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9973	    vctxt->warning, vctxt->errCtxt);
9974	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9975	    vctxt->errCtxt);
9976    }
9977    return (0);
9978}
9979
9980/**
9981 * xmlSchemaGetSchemaBucket:
9982 * @pctxt: the schema parser context
9983 * @schemaLocation: the URI of the schema document
9984 *
9985 * Returns a schema bucket if it was already parsed.
9986 *
9987 * Returns a schema bucket if it was already parsed from
9988 *         @schemaLocation, NULL otherwise.
9989 */
9990static xmlSchemaBucketPtr
9991xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9992			    const xmlChar *schemaLocation)
9993{
9994    xmlSchemaBucketPtr cur;
9995    xmlSchemaItemListPtr list;
9996
9997    list = pctxt->constructor->buckets;
9998    if (list->nbItems == 0)
9999	return(NULL);
10000    else {
10001	int i;
10002	for (i = 0; i < list->nbItems; i++) {
10003	    cur = (xmlSchemaBucketPtr) list->items[i];
10004	    /* Pointer comparison! */
10005	    if (cur->schemaLocation == schemaLocation)
10006		return(cur);
10007	}
10008    }
10009    return(NULL);
10010}
10011
10012static xmlSchemaBucketPtr
10013xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10014				     const xmlChar *schemaLocation,
10015				     const xmlChar *targetNamespace)
10016{
10017    xmlSchemaBucketPtr cur;
10018    xmlSchemaItemListPtr list;
10019
10020    list = pctxt->constructor->buckets;
10021    if (list->nbItems == 0)
10022	return(NULL);
10023    else {
10024	int i;
10025	for (i = 0; i < list->nbItems; i++) {
10026	    cur = (xmlSchemaBucketPtr) list->items[i];
10027	    /* Pointer comparison! */
10028	    if ((cur->origTargetNamespace == NULL) &&
10029		(cur->schemaLocation == schemaLocation) &&
10030		(cur->targetNamespace == targetNamespace))
10031		return(cur);
10032	}
10033    }
10034    return(NULL);
10035}
10036
10037
10038#define IS_BAD_SCHEMA_DOC(b) \
10039    (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10040
10041static xmlSchemaBucketPtr
10042xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10043				 const xmlChar *targetNamespace,
10044				 int imported)
10045{
10046    xmlSchemaBucketPtr cur;
10047    xmlSchemaItemListPtr list;
10048
10049    list = pctxt->constructor->buckets;
10050    if (list->nbItems == 0)
10051	return(NULL);
10052    else {
10053	int i;
10054	for (i = 0; i < list->nbItems; i++) {
10055	    cur = (xmlSchemaBucketPtr) list->items[i];
10056	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10057		(cur->origTargetNamespace == targetNamespace) &&
10058		((imported && cur->imported) ||
10059		 ((!imported) && (!cur->imported))))
10060		return(cur);
10061	}
10062    }
10063    return(NULL);
10064}
10065
10066static int
10067xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10068		     xmlSchemaPtr schema,
10069		     xmlSchemaBucketPtr bucket)
10070{
10071    int oldFlags;
10072    xmlDocPtr oldDoc;
10073    xmlNodePtr node;
10074    int ret, oldErrs;
10075    xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10076
10077    /*
10078    * Save old values; reset the *main* schema.
10079    * URGENT TODO: This is not good; move the per-document information
10080    * to the parser. Get rid of passing the main schema to the
10081    * parsing functions.
10082    */
10083    oldFlags = schema->flags;
10084    oldDoc = schema->doc;
10085    if (schema->flags != 0)
10086	xmlSchemaClearSchemaDefaults(schema);
10087    schema->doc = bucket->doc;
10088    pctxt->schema = schema;
10089    /*
10090    * Keep the current target namespace on the parser *not* on the
10091    * main schema.
10092    */
10093    pctxt->targetNamespace = bucket->targetNamespace;
10094    WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10095
10096    if ((bucket->targetNamespace != NULL) &&
10097	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10098	/*
10099	* We are parsing the schema for schemas!
10100	*/
10101	pctxt->isS4S = 1;
10102    }
10103    /* Mark it as parsed, even if parsing fails. */
10104    bucket->parsed++;
10105    /* Compile the schema doc. */
10106    node = xmlDocGetRootElement(bucket->doc);
10107    ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10108    if (ret != 0)
10109	goto exit;
10110    /* An empty schema; just get out. */
10111    if (node->children == NULL)
10112	goto exit;
10113    oldErrs = pctxt->nberrors;
10114    ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10115    if (ret != 0)
10116	goto exit;
10117    /*
10118    * TODO: Not nice, but I'm not 100% sure we will get always an error
10119    * as a result of the obove functions; so better rely on pctxt->err
10120    * as well.
10121    */
10122    if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10123	ret = pctxt->err;
10124	goto exit;
10125    }
10126
10127exit:
10128    WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10129    /* Restore schema values. */
10130    schema->doc = oldDoc;
10131    schema->flags = oldFlags;
10132    return(ret);
10133}
10134
10135static int
10136xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10137		     xmlSchemaPtr schema,
10138		     xmlSchemaBucketPtr bucket)
10139{
10140    xmlSchemaParserCtxtPtr newpctxt;
10141    int res = 0;
10142
10143    if (bucket == NULL)
10144	return(0);
10145    if (bucket->parsed) {
10146	PERROR_INT("xmlSchemaParseNewDoc",
10147	    "reparsing a schema doc");
10148	return(-1);
10149    }
10150    if (bucket->doc == NULL) {
10151	PERROR_INT("xmlSchemaParseNewDoc",
10152	    "parsing a schema doc, but there's no doc");
10153	return(-1);
10154    }
10155    if (pctxt->constructor == NULL) {
10156	PERROR_INT("xmlSchemaParseNewDoc",
10157	    "no constructor");
10158	return(-1);
10159    }
10160    /* Create and init the temporary parser context. */
10161    newpctxt = xmlSchemaNewParserCtxtUseDict(
10162	(const char *) bucket->schemaLocation, pctxt->dict);
10163    if (newpctxt == NULL)
10164	return(-1);
10165    newpctxt->constructor = pctxt->constructor;
10166    /*
10167    * TODO: Can we avoid that the parser knows about the main schema?
10168    * It would be better if he knows about the current schema bucket
10169    * only.
10170    */
10171    newpctxt->schema = schema;
10172    xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10173	pctxt->errCtxt);
10174    xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10175	pctxt->errCtxt);
10176    newpctxt->counter = pctxt->counter;
10177
10178
10179    res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10180
10181    /* Channel back errors and cleanup the temporary parser context. */
10182    if (res != 0)
10183	pctxt->err = res;
10184    pctxt->nberrors += newpctxt->nberrors;
10185    pctxt->counter = newpctxt->counter;
10186    newpctxt->constructor = NULL;
10187    /* Free the parser context. */
10188    xmlSchemaFreeParserCtxt(newpctxt);
10189    return(res);
10190}
10191
10192static void
10193xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10194				xmlSchemaSchemaRelationPtr rel)
10195{
10196    xmlSchemaSchemaRelationPtr cur = bucket->relations;
10197
10198    if (cur == NULL) {
10199	bucket->relations = rel;
10200	return;
10201    }
10202    while (cur->next != NULL)
10203	cur = cur->next;
10204    cur->next = rel;
10205}
10206
10207
10208static const xmlChar *
10209xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10210			  xmlNodePtr ctxtNode)
10211{
10212    /*
10213    * Build an absolue location URI.
10214    */
10215    if (location != NULL) {
10216	if (ctxtNode == NULL)
10217	    return(location);
10218	else {
10219	    xmlChar *base, *URI;
10220	    const xmlChar *ret = NULL;
10221
10222	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10223	    if (base == NULL) {
10224		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10225	    } else {
10226		URI = xmlBuildURI(location, base);
10227		xmlFree(base);
10228	    }
10229	    if (URI != NULL) {
10230		ret = xmlDictLookup(dict, URI, -1);
10231		xmlFree(URI);
10232		return(ret);
10233	    }
10234	}
10235    }
10236    return(NULL);
10237}
10238
10239
10240
10241/**
10242 * xmlSchemaAddSchemaDoc:
10243 * @pctxt:  a schema validation context
10244 * @schema:  the schema being built
10245 * @node:  a subtree containing XML Schema informations
10246 *
10247 * Parse an included (and to-be-redefined) XML schema document.
10248 *
10249 * Returns 0 on success, a positive error code on errors and
10250 *         -1 in case of an internal or API error.
10251 */
10252
10253static int
10254xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10255		int type, /* import or include or redefine */
10256		const xmlChar *schemaLocation,
10257		xmlDocPtr schemaDoc,
10258		const char *schemaBuffer,
10259		int schemaBufferLen,
10260		xmlNodePtr invokingNode,
10261		const xmlChar *sourceTargetNamespace,
10262		const xmlChar *importNamespace,
10263		xmlSchemaBucketPtr *bucket)
10264{
10265    const xmlChar *targetNamespace = NULL;
10266    xmlSchemaSchemaRelationPtr relation = NULL;
10267    xmlDocPtr doc = NULL;
10268    int res = 0, err = 0, located = 0, preserveDoc = 0;
10269    xmlSchemaBucketPtr bkt = NULL;
10270
10271    if (bucket != NULL)
10272	*bucket = NULL;
10273
10274    switch (type) {
10275	case XML_SCHEMA_SCHEMA_IMPORT:
10276	case XML_SCHEMA_SCHEMA_MAIN:
10277	    err = XML_SCHEMAP_SRC_IMPORT;
10278	    break;
10279	case XML_SCHEMA_SCHEMA_INCLUDE:
10280	    err = XML_SCHEMAP_SRC_INCLUDE;
10281	    break;
10282	case XML_SCHEMA_SCHEMA_REDEFINE:
10283	    err = XML_SCHEMAP_SRC_REDEFINE;
10284	    break;
10285    }
10286
10287
10288    /* Special handling for the main schema:
10289    * skip the location and relation logic and just parse the doc.
10290    * We need just a bucket to be returned in this case.
10291    */
10292    if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10293	goto doc_load;
10294
10295    /* Note that we expect the location to be an absulute URI. */
10296    if (schemaLocation != NULL) {
10297	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10298	if ((bkt != NULL) &&
10299	    (pctxt->constructor->bucket == bkt)) {
10300	    /* Report self-imports/inclusions/redefinitions. */
10301
10302	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10303		invokingNode, NULL,
10304		"The schema must not import/include/redefine itself",
10305		NULL, NULL);
10306	    goto exit;
10307	}
10308    }
10309    /*
10310    * Create a relation for the graph of schemas.
10311    */
10312    relation = xmlSchemaSchemaRelationCreate();
10313    if (relation == NULL)
10314	return(-1);
10315    xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10316	relation);
10317    relation->type = type;
10318
10319    /*
10320    * Save the namespace import information.
10321    */
10322    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10323	relation->importNamespace = importNamespace;
10324	if (schemaLocation == NULL) {
10325	    /*
10326	    * No location; this is just an import of the namespace.
10327	    * Note that we don't assign a bucket to the relation
10328	    * in this case.
10329	    */
10330	    goto exit;
10331	}
10332	targetNamespace = importNamespace;
10333    }
10334
10335    /* Did we already fetch the doc? */
10336    if (bkt != NULL) {
10337	/* TODO: The following nasty cases will produce an error. */
10338	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10339	    /* We included/redefined and then try to import a schema. */
10340	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10341		invokingNode, NULL,
10342		"The schema document '%s' cannot be imported, since "
10343		"it was already included or redefined",
10344		schemaLocation, NULL);
10345	    goto exit;
10346	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10347	    /* We imported and then try to include/redefine a schema. */
10348	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10349		invokingNode, NULL,
10350		"The schema document '%s' cannot be included or "
10351		"redefined, since it was already imported",
10352		schemaLocation, NULL);
10353	    goto exit;
10354	}
10355    }
10356
10357    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10358	/*
10359	* Given that the schemaLocation [attribute] is only a hint, it is open
10360	* to applications to ignore all but the first <import> for a given
10361	* namespace, regardless of the �actual value� of schemaLocation, but
10362	* such a strategy risks missing useful information when new
10363	* schemaLocations are offered.
10364	*
10365	* We will use the first <import> that comes with a location.
10366	* Further <import>s *with* a location, will result in an error.
10367	* TODO: Better would be to just report a warning here, but
10368	* we'll try it this way until someone complains.
10369	*
10370	* Schema Document Location Strategy:
10371	* 3 Based on the namespace name, identify an existing schema document,
10372	* either as a resource which is an XML document or a <schema> element
10373	* information item, in some local schema repository;
10374	* 5 Attempt to resolve the namespace name to locate such a resource.
10375	*
10376	* NOTE: (3) and (5) are not supported.
10377	*/
10378	if (bkt != NULL) {
10379	    relation->bucket = bkt;
10380	    goto exit;
10381	}
10382	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10383	    importNamespace, 1);
10384
10385	if (bkt != NULL) {
10386	    relation->bucket = bkt;
10387	    if (bkt->schemaLocation == NULL) {
10388		/* First given location of the schema; load the doc. */
10389		bkt->schemaLocation = schemaLocation;
10390	    } else {
10391		if (!xmlStrEqual(schemaLocation,
10392		    bkt->schemaLocation)) {
10393		    /*
10394		    * Additional location given; just skip it.
10395		    * URGENT TODO: We should report a warning here.
10396		    * res = XML_SCHEMAP_SRC_IMPORT;
10397		    */
10398		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10399			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10400			invokingNode, NULL,
10401			"Skipping import of schema located at '%s' for the "
10402			"namespace '%s', since this namespace was already "
10403			"imported with the schema located at '%s'",
10404			schemaLocation, importNamespace, bkt->schemaLocation);
10405		}
10406		goto exit;
10407	    }
10408	}
10409	/*
10410	* No bucket + first location: load the doc and create a
10411	* bucket.
10412	*/
10413    } else {
10414	/* <include> and <redefine> */
10415	if (bkt != NULL) {
10416
10417	    if ((bkt->origTargetNamespace == NULL) &&
10418		(bkt->targetNamespace != sourceTargetNamespace)) {
10419		xmlSchemaBucketPtr chamel;
10420
10421		/*
10422		* Chameleon include/redefine: skip loading only if it was
10423		* aleady build for the targetNamespace of the including
10424		* schema.
10425		*/
10426		/*
10427		* URGENT TODO: If the schema is a chameleon-include then copy
10428		* the components into the including schema and modify the
10429		* targetNamespace of those components, do nothing otherwise.
10430		* NOTE: This is currently worked-around by compiling the
10431		* chameleon for every destinct including targetNamespace; thus
10432		* not performant at the moment.
10433		* TODO: Check when the namespace in wildcards for chameleons
10434		* needs to be converted: before we built wildcard intersections
10435		* or after.
10436		*   Answer: after!
10437		*/
10438		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10439		    schemaLocation, sourceTargetNamespace);
10440		if (chamel != NULL) {
10441		    /* A fitting chameleon was already parsed; NOP. */
10442		    relation->bucket = chamel;
10443		    goto exit;
10444		}
10445		/*
10446		* We need to parse the chameleon again for a different
10447		* targetNamespace.
10448		* CHAMELEON TODO: Optimize this by only parsing the
10449		* chameleon once, and then copying the components to
10450		* the new targetNamespace.
10451		*/
10452		bkt = NULL;
10453	    } else {
10454		relation->bucket = bkt;
10455		goto exit;
10456	    }
10457	}
10458    }
10459    if ((bkt != NULL) && (bkt->doc != NULL)) {
10460	PERROR_INT("xmlSchemaAddSchemaDoc",
10461	    "trying to load a schema doc, but a doc is already "
10462	    "assigned to the schema bucket");
10463	goto exit_failure;
10464    }
10465
10466doc_load:
10467    /*
10468    * Load the document.
10469    */
10470    if (schemaDoc != NULL) {
10471	doc = schemaDoc;
10472	/* Don' free this one, since it was provided by the caller. */
10473	preserveDoc = 1;
10474	/* TODO: Does the context or the doc hold the location? */
10475	if (schemaDoc->URL != NULL)
10476	    schemaLocation = xmlDictLookup(pctxt->dict,
10477		schemaDoc->URL, -1);
10478
10479    } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10480	xmlParserCtxtPtr parserCtxt;
10481
10482	parserCtxt = xmlNewParserCtxt();
10483	if (parserCtxt == NULL) {
10484	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10485		"allocating a parser context", NULL);
10486	    goto exit_failure;
10487	}
10488	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10489	    /*
10490	    * TODO: Do we have to burden the schema parser dict with all
10491	    * the content of the schema doc?
10492	    */
10493	    xmlDictFree(parserCtxt->dict);
10494	    parserCtxt->dict = pctxt->dict;
10495	    xmlDictReference(parserCtxt->dict);
10496	}
10497	if (schemaLocation != NULL) {
10498	    /* Parse from file. */
10499	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10500		NULL, SCHEMAS_PARSE_OPTIONS);
10501	} else if (schemaBuffer != NULL) {
10502	    /* Parse from memory buffer. */
10503	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10504		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10505	    schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10506	    if (doc != NULL)
10507		doc->URL = schemaLocation;
10508	}
10509	/*
10510	* For <import>:
10511	* 2.1 The referent is (a fragment of) a resource which is an
10512	* XML document (see clause 1.1), which in turn corresponds to
10513	* a <schema> element information item in a well-formed information
10514	* set, which in turn corresponds to a valid schema.
10515	* TODO: (2.1) fragments of XML documents are not supported.
10516	*
10517	* 2.2 The referent is a <schema> element information item in
10518	* a well-formed information set, which in turn corresponds
10519	* to a valid schema.
10520	* TODO: (2.2) is not supported.
10521	*/
10522	if (doc == NULL) {
10523	    xmlErrorPtr lerr;
10524	    lerr = xmlGetLastError();
10525	    /*
10526	    * Check if this a parser error, or if the document could
10527	    * just not be located.
10528	    * TODO: Try to find specific error codes to react only on
10529	    * localisation failures.
10530	    */
10531	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10532		/*
10533		* We assume a parser error here.
10534		*/
10535		located = 1;
10536		/* TODO: Error code ?? */
10537		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10538		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10539		    invokingNode, NULL,
10540		    "Failed to parse the XML resource '%s'",
10541		    schemaLocation, NULL);
10542	    }
10543	}
10544	xmlFreeParserCtxt(parserCtxt);
10545	if ((doc == NULL) && located)
10546	    goto exit_error;
10547    } else {
10548	xmlSchemaPErr(pctxt, NULL,
10549	    XML_SCHEMAP_NOTHING_TO_PARSE,
10550	    "No information for parsing was provided with the "
10551	    "given schema parser context.\n",
10552	    NULL, NULL);
10553	goto exit_failure;
10554    }
10555    /*
10556    * Preprocess the document.
10557    */
10558    if (doc != NULL) {
10559	xmlNodePtr docElem = NULL;
10560
10561	located = 1;
10562	docElem = xmlDocGetRootElement(doc);
10563	if (docElem == NULL) {
10564	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10565		invokingNode, NULL,
10566		"The document '%s' has no document element",
10567		schemaLocation, NULL);
10568	    goto exit_error;
10569	}
10570	/*
10571	* Remove all the blank text nodes.
10572	*/
10573	xmlSchemaCleanupDoc(pctxt, docElem);
10574	/*
10575	* Check the schema's top level element.
10576	*/
10577	if (!IS_SCHEMA(docElem, "schema")) {
10578	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10579		invokingNode, NULL,
10580		"The XML document '%s' is not a schema document",
10581		schemaLocation, NULL);
10582	    goto exit_error;
10583	}
10584	/*
10585	* Note that we don't apply a type check for the
10586	* targetNamespace value here.
10587	*/
10588	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10589	    "targetNamespace");
10590    }
10591
10592/* after_doc_loading: */
10593    if ((bkt == NULL) && located) {
10594	/* Only create a bucket if the schema was located. */
10595        bkt = xmlSchemaBucketCreate(pctxt, type,
10596	    targetNamespace);
10597	if (bkt == NULL)
10598	    goto exit_failure;
10599    }
10600    if (bkt != NULL) {
10601	bkt->schemaLocation = schemaLocation;
10602	bkt->located = located;
10603	if (doc != NULL) {
10604	    bkt->doc = doc;
10605	    bkt->targetNamespace = targetNamespace;
10606	    bkt->origTargetNamespace = targetNamespace;
10607	    if (preserveDoc)
10608		bkt->preserveDoc = 1;
10609	}
10610	if (WXS_IS_BUCKET_IMPMAIN(type))
10611	    bkt->imported++;
10612	    /*
10613	    * Add it to the graph of schemas.
10614	    */
10615	if (relation != NULL)
10616	    relation->bucket = bkt;
10617    }
10618
10619exit:
10620    /*
10621    * Return the bucket explicitely; this is needed for the
10622    * main schema.
10623    */
10624    if (bucket != NULL)
10625	*bucket = bkt;
10626    return (0);
10627
10628exit_error:
10629    if ((doc != NULL) && (! preserveDoc)) {
10630	xmlFreeDoc(doc);
10631	if (bkt != NULL)
10632	    bkt->doc = NULL;
10633    }
10634    return(pctxt->err);
10635
10636exit_failure:
10637    if ((doc != NULL) && (! preserveDoc)) {
10638	xmlFreeDoc(doc);
10639	if (bkt != NULL)
10640	    bkt->doc = NULL;
10641    }
10642    return (-1);
10643}
10644
10645/**
10646 * xmlSchemaParseImport:
10647 * @ctxt:  a schema validation context
10648 * @schema:  the schema being built
10649 * @node:  a subtree containing XML Schema informations
10650 *
10651 * parse a XML schema Import definition
10652 * *WARNING* this interface is highly subject to change
10653 *
10654 * Returns 0 in case of success, a positive error code if
10655 * not valid and -1 in case of an internal error.
10656 */
10657static int
10658xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10659                     xmlNodePtr node)
10660{
10661    xmlNodePtr child;
10662    const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10663    const xmlChar *thisTargetNamespace;
10664    xmlAttrPtr attr;
10665    int ret = 0;
10666    xmlSchemaBucketPtr bucket = NULL;
10667
10668    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10669        return (-1);
10670
10671    /*
10672    * Check for illegal attributes.
10673    */
10674    attr = node->properties;
10675    while (attr != NULL) {
10676	if (attr->ns == NULL) {
10677	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10678		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10679		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10680		xmlSchemaPIllegalAttrErr(pctxt,
10681		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10682	    }
10683	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10684	    xmlSchemaPIllegalAttrErr(pctxt,
10685		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10686	}
10687	attr = attr->next;
10688    }
10689    /*
10690    * Extract and validate attributes.
10691    */
10692    if (xmlSchemaPValAttr(pctxt, NULL, node,
10693	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10694	&namespaceName) != 0) {
10695	xmlSchemaPSimpleTypeErr(pctxt,
10696	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10697	    NULL, node,
10698	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10699	    NULL, namespaceName, NULL, NULL, NULL);
10700	return (pctxt->err);
10701    }
10702
10703    if (xmlSchemaPValAttr(pctxt, NULL, node,
10704	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10705	&schemaLocation) != 0) {
10706	xmlSchemaPSimpleTypeErr(pctxt,
10707	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10708	    NULL, node,
10709	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10710	    NULL, namespaceName, NULL, NULL, NULL);
10711	return (pctxt->err);
10712    }
10713    /*
10714    * And now for the children...
10715    */
10716    child = node->children;
10717    if (IS_SCHEMA(child, "annotation")) {
10718        /*
10719         * the annotation here is simply discarded ...
10720	 * TODO: really?
10721         */
10722        child = child->next;
10723    }
10724    if (child != NULL) {
10725	xmlSchemaPContentErr(pctxt,
10726	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10727	    NULL, node, child, NULL,
10728	    "(annotation?)");
10729    }
10730    /*
10731    * Apply additional constraints.
10732    *
10733    * Note that it is important to use the original @targetNamespace
10734    * (or none at all), to rule out imports of schemas _with_ a
10735    * @targetNamespace if the importing schema is a chameleon schema
10736    * (with no @targetNamespace).
10737    */
10738    thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10739    if (namespaceName != NULL) {
10740	/*
10741	* 1.1 If the namespace [attribute] is present, then its �actual value�
10742	* must not match the �actual value� of the enclosing <schema>'s
10743	* targetNamespace [attribute].
10744	*/
10745	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10746	    xmlSchemaPCustomErr(pctxt,
10747		XML_SCHEMAP_SRC_IMPORT_1_1,
10748		NULL, node,
10749		"The value of the attribute 'namespace' must not match "
10750		"the target namespace '%s' of the importing schema",
10751		thisTargetNamespace);
10752	    return (pctxt->err);
10753	}
10754    } else {
10755	/*
10756	* 1.2 If the namespace [attribute] is not present, then the enclosing
10757	* <schema> must have a targetNamespace [attribute].
10758	*/
10759	if (thisTargetNamespace == NULL) {
10760	    xmlSchemaPCustomErr(pctxt,
10761		XML_SCHEMAP_SRC_IMPORT_1_2,
10762		NULL, node,
10763		"The attribute 'namespace' must be existent if "
10764		"the importing schema has no target namespace",
10765		NULL);
10766	    return (pctxt->err);
10767	}
10768    }
10769    /*
10770    * Locate and acquire the schema document.
10771    */
10772    if (schemaLocation != NULL)
10773	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10774	    schemaLocation, node);
10775    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10776	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10777	namespaceName, &bucket);
10778
10779    if (ret != 0)
10780	return(ret);
10781
10782    /*
10783    * For <import>: "It is *not* an error for the application
10784    * schema reference strategy to fail."
10785    * So just don't parse if no schema document was found.
10786    * Note that we will get no bucket if the schema could not be
10787    * located or if there was no schemaLocation.
10788    */
10789    if ((bucket == NULL) && (schemaLocation != NULL)) {
10790	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10791	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10792	    node, NULL,
10793	    "Failed to locate a schema at location '%s'. "
10794	    "Skipping the import", schemaLocation, NULL, NULL);
10795    }
10796
10797    if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10798	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10799    }
10800
10801    return (ret);
10802}
10803
10804static int
10805xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10806				     xmlSchemaPtr schema,
10807				     xmlNodePtr node,
10808				     xmlChar **schemaLocation,
10809				     int type)
10810{
10811    xmlAttrPtr attr;
10812
10813    if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10814	(schemaLocation == NULL))
10815        return (-1);
10816
10817    *schemaLocation = NULL;
10818    /*
10819    * Check for illegal attributes.
10820    * Applies for both <include> and <redefine>.
10821    */
10822    attr = node->properties;
10823    while (attr != NULL) {
10824	if (attr->ns == NULL) {
10825	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10826		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10827		xmlSchemaPIllegalAttrErr(pctxt,
10828		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10829	    }
10830	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10831	    xmlSchemaPIllegalAttrErr(pctxt,
10832		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10833	}
10834	attr = attr->next;
10835    }
10836    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10837    /*
10838    * Preliminary step, extract the URI-Reference and make an URI
10839    * from the base.
10840    */
10841    /*
10842    * Attribute "schemaLocation" is mandatory.
10843    */
10844    attr = xmlSchemaGetPropNode(node, "schemaLocation");
10845    if (attr != NULL) {
10846        xmlChar *base = NULL;
10847        xmlChar *uri = NULL;
10848
10849	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10850	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10851	    (const xmlChar **) schemaLocation) != 0)
10852	    goto exit_error;
10853	base = xmlNodeGetBase(node->doc, node);
10854	if (base == NULL) {
10855	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10856	} else {
10857	    uri = xmlBuildURI(*schemaLocation, base);
10858	    xmlFree(base);
10859	}
10860	if (uri == NULL) {
10861	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10862		"could not build an URI from the schemaLocation")
10863	    goto exit_failure;
10864	}
10865	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10866	xmlFree(uri);
10867    } else {
10868	xmlSchemaPMissingAttrErr(pctxt,
10869	    XML_SCHEMAP_S4S_ATTR_MISSING,
10870	    NULL, node, "schemaLocation", NULL);
10871	goto exit_error;
10872    }
10873    /*
10874    * Report self-inclusion and self-redefinition.
10875    */
10876    if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10877	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10878	    xmlSchemaPCustomErr(pctxt,
10879		XML_SCHEMAP_SRC_REDEFINE,
10880		NULL, node,
10881		"The schema document '%s' cannot redefine itself.",
10882		*schemaLocation);
10883	} else {
10884	    xmlSchemaPCustomErr(pctxt,
10885		XML_SCHEMAP_SRC_INCLUDE,
10886		NULL, node,
10887		"The schema document '%s' cannot include itself.",
10888		*schemaLocation);
10889	}
10890	goto exit_error;
10891    }
10892
10893    return(0);
10894exit_error:
10895    return(pctxt->err);
10896exit_failure:
10897    return(-1);
10898}
10899
10900static int
10901xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10902				xmlSchemaPtr schema,
10903				xmlNodePtr node,
10904				int type)
10905{
10906    xmlNodePtr child = NULL;
10907    const xmlChar *schemaLocation = NULL;
10908    int res = 0; /* hasRedefinitions = 0 */
10909    int isChameleon = 0, wasChameleon = 0;
10910    xmlSchemaBucketPtr bucket = NULL;
10911
10912    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10913        return (-1);
10914
10915    /*
10916    * Parse attributes. Note that the returned schemaLocation will
10917    * be already converted to an absolute URI.
10918    */
10919    res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10920	node, (xmlChar **) (&schemaLocation), type);
10921    if (res != 0)
10922	return(res);
10923    /*
10924    * Load and add the schema document.
10925    */
10926    res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10927	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10928    if (res != 0)
10929	return(res);
10930    /*
10931    * If we get no schema bucket back, then this means that the schema
10932    * document could not be located or was broken XML or was not
10933    * a schema document.
10934    */
10935    if ((bucket == NULL) || (bucket->doc == NULL)) {
10936	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10937	    /*
10938	    * WARNING for <include>:
10939	    * We will raise an error if the schema cannot be located
10940	    * for inclusions, since the that was the feedback from the
10941	    * schema people. I.e. the following spec piece will *not* be
10942	    * satisfied:
10943	    * SPEC src-include: "It is not an error for the �actual value� of the
10944	    * schemaLocation [attribute] to fail to resolve it all, in which
10945	    * case no corresponding inclusion is performed.
10946	    * So do we need a warning report here?"
10947	    */
10948	    res = XML_SCHEMAP_SRC_INCLUDE;
10949	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10950		node, NULL,
10951		"Failed to load the document '%s' for inclusion",
10952		schemaLocation, NULL);
10953	} else {
10954	    /*
10955	    * NOTE: This was changed to raise an error even if no redefinitions
10956	    * are specified.
10957	    *
10958	    * SPEC src-redefine (1)
10959	    * "If there are any element information items among the [children]
10960	    * other than <annotation> then the �actual value� of the
10961	    * schemaLocation [attribute] must successfully resolve."
10962	    * TODO: Ask the WG if a the location has always to resolve
10963	    * here as well!
10964	    */
10965	    res = XML_SCHEMAP_SRC_REDEFINE;
10966	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10967		node, NULL,
10968		"Failed to load the document '%s' for redefinition",
10969		schemaLocation, NULL);
10970	}
10971    } else {
10972	/*
10973	* Check targetNamespace sanity before parsing the new schema.
10974	* TODO: Note that we won't check further content if the
10975	* targetNamespace was bad.
10976	*/
10977	if (bucket->origTargetNamespace != NULL) {
10978	    /*
10979	    * SPEC src-include (2.1)
10980	    * "SII has a targetNamespace [attribute], and its �actual
10981	    * value� is identical to the �actual value� of the targetNamespace
10982	    * [attribute] of SII� (which must have such an [attribute])."
10983	    */
10984	    if (pctxt->targetNamespace == NULL) {
10985		xmlSchemaCustomErr(ACTXT_CAST pctxt,
10986		    XML_SCHEMAP_SRC_INCLUDE,
10987		    node, NULL,
10988		    "The target namespace of the included/redefined schema "
10989		    "'%s' has to be absent, since the including/redefining "
10990		    "schema has no target namespace",
10991		    schemaLocation, NULL);
10992		goto exit_error;
10993	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
10994		pctxt->targetNamespace)) {
10995		/* TODO: Change error function. */
10996		xmlSchemaPCustomErrExt(pctxt,
10997		    XML_SCHEMAP_SRC_INCLUDE,
10998		    NULL, node,
10999		    "The target namespace '%s' of the included/redefined "
11000		    "schema '%s' differs from '%s' of the "
11001		    "including/redefining schema",
11002		    bucket->origTargetNamespace, schemaLocation,
11003		    pctxt->targetNamespace);
11004		goto exit_error;
11005	    }
11006	} else if (pctxt->targetNamespace != NULL) {
11007	    /*
11008	    * Chameleons: the original target namespace will
11009	    * differ from the resulting namespace.
11010	    */
11011	    isChameleon = 1;
11012	    if (bucket->parsed &&
11013		(bucket->targetNamespace != pctxt->targetNamespace)) {
11014		/*
11015		* This is a sanity check, I dunno yet if this can happen.
11016		*/
11017		PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11018		    "trying to use an already parsed schema for a "
11019		    "different targetNamespace");
11020		return(-1);
11021	    }
11022	    bucket->targetNamespace = pctxt->targetNamespace;
11023	}
11024    }
11025    /*
11026    * Parse the schema.
11027    */
11028    if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11029	if (isChameleon) {
11030	    /* TODO: Get rid of this flag on the schema itself. */
11031	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11032		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11033	    } else
11034		wasChameleon = 1;
11035	}
11036	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11037	/* Restore chameleon flag. */
11038	if (isChameleon && (!wasChameleon))
11039	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11040    }
11041    /*
11042    * And now for the children...
11043    */
11044    child = node->children;
11045    if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11046	/*
11047	* Parse (simpleType | complexType | group | attributeGroup))*
11048	*/
11049	pctxt->redefined = bucket;
11050	/*
11051	* How to proceed if the redefined schema was not located?
11052	*/
11053	pctxt->isRedefine = 1;
11054	while (IS_SCHEMA(child, "annotation") ||
11055	    IS_SCHEMA(child, "simpleType") ||
11056	    IS_SCHEMA(child, "complexType") ||
11057	    IS_SCHEMA(child, "group") ||
11058	    IS_SCHEMA(child, "attributeGroup")) {
11059	    if (IS_SCHEMA(child, "annotation")) {
11060		/*
11061		* TODO: discard or not?
11062		*/
11063	    } else if (IS_SCHEMA(child, "simpleType")) {
11064		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11065	    } else if (IS_SCHEMA(child, "complexType")) {
11066		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11067		/* hasRedefinitions = 1; */
11068	    } else if (IS_SCHEMA(child, "group")) {
11069		/* hasRedefinitions = 1; */
11070		xmlSchemaParseModelGroupDefinition(pctxt,
11071		    schema, child);
11072	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11073		/* hasRedefinitions = 1; */
11074		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11075		    child);
11076	    }
11077	    child = child->next;
11078	}
11079	pctxt->redefined = NULL;
11080	pctxt->isRedefine = 0;
11081    } else {
11082	if (IS_SCHEMA(child, "annotation")) {
11083	    /*
11084	    * TODO: discard or not?
11085	    */
11086	    child = child->next;
11087	}
11088    }
11089    if (child != NULL) {
11090	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11091	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11092	    xmlSchemaPContentErr(pctxt, res,
11093		NULL, node, child, NULL,
11094		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11095	} else {
11096	     xmlSchemaPContentErr(pctxt, res,
11097		NULL, node, child, NULL,
11098		"(annotation?)");
11099	}
11100    }
11101    return(res);
11102
11103exit_error:
11104    return(pctxt->err);
11105}
11106
11107static int
11108xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11109                       xmlNodePtr node)
11110{
11111    int res;
11112#ifndef ENABLE_REDEFINE
11113    TODO
11114    return(0);
11115#endif
11116    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11117	XML_SCHEMA_SCHEMA_REDEFINE);
11118    if (res != 0)
11119	return(res);
11120    return(0);
11121}
11122
11123static int
11124xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11125                       xmlNodePtr node)
11126{
11127    int res;
11128
11129    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11130	XML_SCHEMA_SCHEMA_INCLUDE);
11131    if (res != 0)
11132	return(res);
11133    return(0);
11134}
11135
11136/**
11137 * xmlSchemaParseModelGroup:
11138 * @ctxt:  a schema validation context
11139 * @schema:  the schema being built
11140 * @node:  a subtree containing XML Schema informations
11141 * @type: the "compositor" type
11142 * @particleNeeded: if a a model group with a particle
11143 *
11144 * parse a XML schema Sequence definition.
11145 * Applies parts of:
11146 *   Schema Representation Constraint:
11147 *     Redefinition Constraints and Semantics (src-redefine)
11148 *     (6.1), (6.1.1), (6.1.2)
11149 *
11150 *   Schema Component Constraint:
11151 *     All Group Limited (cos-all-limited) (2)
11152 *     TODO: Actually this should go to component-level checks,
11153 *     but is done here due to performance. Move it to an other layer
11154 *     is schema construction via an API is implemented.
11155 *
11156 * *WARNING* this interface is highly subject to change
11157 *
11158 * Returns -1 in case of error, 0 if the declaration is improper and
11159 *         1 in case of success.
11160 */
11161static xmlSchemaTreeItemPtr
11162xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11163			 xmlNodePtr node, xmlSchemaTypeType type,
11164			 int withParticle)
11165{
11166    xmlSchemaModelGroupPtr item;
11167    xmlSchemaParticlePtr particle = NULL;
11168    xmlNodePtr child = NULL;
11169    xmlAttrPtr attr;
11170    int min = 1, max = 1, isElemRef, hasRefs = 0;
11171
11172    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11173        return (NULL);
11174    /*
11175    * Create a model group with the given compositor.
11176    */
11177    item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11178    if (item == NULL)
11179	return (NULL);
11180
11181    if (withParticle) {
11182	if (type == XML_SCHEMA_TYPE_ALL) {
11183	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11184	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11185	} else {
11186	    /* choice + sequence */
11187	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11188	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11189		"(xs:nonNegativeInteger | unbounded)");
11190	}
11191	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11192	/*
11193	* Create a particle
11194	*/
11195	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11196	if (particle == NULL)
11197	    return (NULL);
11198	particle->children = (xmlSchemaTreeItemPtr) item;
11199	/*
11200	* Check for illegal attributes.
11201	*/
11202	attr = node->properties;
11203	while (attr != NULL) {
11204	    if (attr->ns == NULL) {
11205		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11206		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11207		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11208		    xmlSchemaPIllegalAttrErr(ctxt,
11209			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11210		}
11211	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11212		xmlSchemaPIllegalAttrErr(ctxt,
11213		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11214	    }
11215	    attr = attr->next;
11216	}
11217    } else {
11218	/*
11219	* Check for illegal attributes.
11220	*/
11221	attr = node->properties;
11222	while (attr != NULL) {
11223	    if (attr->ns == NULL) {
11224		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11225		    xmlSchemaPIllegalAttrErr(ctxt,
11226			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11227		}
11228	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11229		xmlSchemaPIllegalAttrErr(ctxt,
11230		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11231	    }
11232	    attr = attr->next;
11233	}
11234    }
11235
11236    /*
11237    * Extract and validate attributes.
11238    */
11239    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11240    /*
11241    * And now for the children...
11242    */
11243    child = node->children;
11244    if (IS_SCHEMA(child, "annotation")) {
11245        item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11246        child = child->next;
11247    }
11248    if (type == XML_SCHEMA_TYPE_ALL) {
11249	xmlSchemaParticlePtr part, last = NULL;
11250
11251	while (IS_SCHEMA(child, "element")) {
11252	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11253		schema, child, &isElemRef, 0);
11254	    /*
11255	    * SPEC cos-all-limited (2)
11256	    * "The {max occurs} of all the particles in the {particles}
11257	    * of the ('all') group must be 0 or 1.
11258	    */
11259	    if (part != NULL) {
11260		if (isElemRef)
11261		    hasRefs++;
11262		if (part->minOccurs > 1) {
11263		    xmlSchemaPCustomErr(ctxt,
11264			XML_SCHEMAP_COS_ALL_LIMITED,
11265			NULL, child,
11266			"Invalid value for minOccurs (must be 0 or 1)",
11267			NULL);
11268		    /* Reset to 1. */
11269		    part->minOccurs = 1;
11270		}
11271		if (part->maxOccurs > 1) {
11272		    xmlSchemaPCustomErr(ctxt,
11273			XML_SCHEMAP_COS_ALL_LIMITED,
11274			NULL, child,
11275			"Invalid value for maxOccurs (must be 0 or 1)",
11276			NULL);
11277		    /* Reset to 1. */
11278		    part->maxOccurs = 1;
11279		}
11280		if (last == NULL)
11281		    item->children = (xmlSchemaTreeItemPtr) part;
11282		else
11283		    last->next = (xmlSchemaTreeItemPtr) part;
11284		last = part;
11285	    }
11286	    child = child->next;
11287	}
11288	if (child != NULL) {
11289	    xmlSchemaPContentErr(ctxt,
11290		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11291		NULL, node, child, NULL,
11292		"(annotation?, (annotation?, element*)");
11293	}
11294    } else {
11295	/* choice + sequence */
11296	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11297
11298	while ((IS_SCHEMA(child, "element")) ||
11299	    (IS_SCHEMA(child, "group")) ||
11300	    (IS_SCHEMA(child, "any")) ||
11301	    (IS_SCHEMA(child, "choice")) ||
11302	    (IS_SCHEMA(child, "sequence"))) {
11303
11304	    if (IS_SCHEMA(child, "element")) {
11305		part = (xmlSchemaTreeItemPtr)
11306		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11307		if (part && isElemRef)
11308		    hasRefs++;
11309	    } else if (IS_SCHEMA(child, "group")) {
11310		part =
11311		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11312		if (part != NULL)
11313		    hasRefs++;
11314		/*
11315		* Handle redefinitions.
11316		*/
11317		if (ctxt->isRedefine && ctxt->redef &&
11318		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11319		    part && part->children)
11320		{
11321		    if ((xmlSchemaGetQNameRefName(part->children) ==
11322			    ctxt->redef->refName) &&
11323			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11324			    ctxt->redef->refTargetNs))
11325		    {
11326			/*
11327			* SPEC src-redefine:
11328			* (6.1) "If it has a <group> among its contents at
11329			* some level the �actual value� of whose ref
11330			* [attribute] is the same as the �actual value� of
11331			* its own name attribute plus target namespace, then
11332			* all of the following must be true:"
11333			* (6.1.1) "It must have exactly one such group."
11334			*/
11335			if (ctxt->redefCounter != 0) {
11336			    xmlChar *str = NULL;
11337
11338			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11339				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11340				"The redefining model group definition "
11341				"'%s' must not contain more than one "
11342				"reference to the redefined definition",
11343				xmlSchemaFormatQName(&str,
11344				    ctxt->redef->refTargetNs,
11345				    ctxt->redef->refName),
11346				NULL);
11347			    FREE_AND_NULL(str)
11348			    part = NULL;
11349			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11350			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11351			{
11352			    xmlChar *str = NULL;
11353			    /*
11354			    * SPEC src-redefine:
11355			    * (6.1.2) "The �actual value� of both that
11356			    * group's minOccurs and maxOccurs [attribute]
11357			    * must be 1 (or �absent�).
11358			    */
11359			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11360				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11361				"The redefining model group definition "
11362				"'%s' must not contain a reference to the "
11363				"redefined definition with a "
11364				"maxOccurs/minOccurs other than 1",
11365				xmlSchemaFormatQName(&str,
11366				    ctxt->redef->refTargetNs,
11367				    ctxt->redef->refName),
11368				NULL);
11369			    FREE_AND_NULL(str)
11370			    part = NULL;
11371			}
11372			ctxt->redef->reference = WXS_BASIC_CAST part;
11373			ctxt->redefCounter++;
11374		    }
11375		}
11376	    } else if (IS_SCHEMA(child, "any")) {
11377		part = (xmlSchemaTreeItemPtr)
11378		    xmlSchemaParseAny(ctxt, schema, child);
11379	    } else if (IS_SCHEMA(child, "choice")) {
11380		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11381		    XML_SCHEMA_TYPE_CHOICE, 1);
11382	    } else if (IS_SCHEMA(child, "sequence")) {
11383		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11384		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11385	    }
11386	    if (part != NULL) {
11387		if (last == NULL)
11388		    item->children = part;
11389		else
11390		    last->next = part;
11391		last = part;
11392	    }
11393	    child = child->next;
11394	}
11395	if (child != NULL) {
11396	    xmlSchemaPContentErr(ctxt,
11397		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11398		NULL, node, child, NULL,
11399		"(annotation?, (element | group | choice | sequence | any)*)");
11400	}
11401    }
11402    if ((max == 0) && (min == 0))
11403	return (NULL);
11404    if (hasRefs) {
11405	/*
11406	* We need to resolve references.
11407	*/
11408	WXS_ADD_PENDING(ctxt, item);
11409    }
11410    if (withParticle)
11411	return ((xmlSchemaTreeItemPtr) particle);
11412    else
11413	return ((xmlSchemaTreeItemPtr) item);
11414}
11415
11416/**
11417 * xmlSchemaParseRestriction:
11418 * @ctxt:  a schema validation context
11419 * @schema:  the schema being built
11420 * @node:  a subtree containing XML Schema informations
11421 *
11422 * parse a XML schema Restriction definition
11423 * *WARNING* this interface is highly subject to change
11424 *
11425 * Returns the type definition or NULL in case of error
11426 */
11427static xmlSchemaTypePtr
11428xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11429                          xmlNodePtr node, xmlSchemaTypeType parentType)
11430{
11431    xmlSchemaTypePtr type;
11432    xmlNodePtr child = NULL;
11433    xmlAttrPtr attr;
11434
11435    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11436        return (NULL);
11437    /* Not a component, don't create it. */
11438    type = ctxt->ctxtType;
11439    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11440
11441    /*
11442    * Check for illegal attributes.
11443    */
11444    attr = node->properties;
11445    while (attr != NULL) {
11446	if (attr->ns == NULL) {
11447	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11448		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11449		xmlSchemaPIllegalAttrErr(ctxt,
11450		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11451	    }
11452	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11453	    xmlSchemaPIllegalAttrErr(ctxt,
11454		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11455	}
11456	attr = attr->next;
11457    }
11458    /*
11459    * Extract and validate attributes.
11460    */
11461    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11462    /*
11463    * Attribute
11464    */
11465    /*
11466    * Extract the base type. The "base" attribute is mandatory if inside
11467    * a complex type or if redefining.
11468    *
11469    * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11470    * among its [children]), the simple type definition which is
11471    * the {content type} of the type definition �resolved� to by
11472    * the �actual value� of the base [attribute]"
11473    */
11474    if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11475	&(type->baseNs), &(type->base)) == 0)
11476    {
11477	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11478	    xmlSchemaPMissingAttrErr(ctxt,
11479		XML_SCHEMAP_S4S_ATTR_MISSING,
11480		NULL, node, "base", NULL);
11481	} else if ((ctxt->isRedefine) &&
11482	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11483	{
11484	    if (type->base == NULL) {
11485		xmlSchemaPMissingAttrErr(ctxt,
11486		    XML_SCHEMAP_S4S_ATTR_MISSING,
11487		    NULL, node, "base", NULL);
11488	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11489		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11490	    {
11491		xmlChar *str1 = NULL, *str2 = NULL;
11492		/*
11493		* REDEFINE: SPEC src-redefine (5)
11494		* "Within the [children], each <simpleType> must have a
11495		* <restriction> among its [children] ... the �actual value� of
11496		* whose base [attribute] must be the same as the �actual value�
11497		* of its own name attribute plus target namespace;"
11498		*/
11499		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11500		    NULL, node, "This is a redefinition, but the QName "
11501		    "value '%s' of the 'base' attribute does not match the "
11502		    "type's designation '%s'",
11503		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11504		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11505			type->name), NULL);
11506		FREE_AND_NULL(str1);
11507		FREE_AND_NULL(str2);
11508		/* Avoid confusion and erase the values. */
11509		type->base = NULL;
11510		type->baseNs = NULL;
11511	    }
11512	}
11513    }
11514    /*
11515    * And now for the children...
11516    */
11517    child = node->children;
11518    if (IS_SCHEMA(child, "annotation")) {
11519	/*
11520	* Add the annotation to the simple type ancestor.
11521	*/
11522	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11523	    xmlSchemaParseAnnotation(ctxt, child, 1));
11524        child = child->next;
11525    }
11526    if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11527	/*
11528	* Corresponds to <simpleType><restriction><simpleType>.
11529	*/
11530	if (IS_SCHEMA(child, "simpleType")) {
11531	    if (type->base != NULL) {
11532		/*
11533		* src-restriction-base-or-simpleType
11534		* Either the base [attribute] or the simpleType [child] of the
11535		* <restriction> element must be present, but not both.
11536		*/
11537		xmlSchemaPContentErr(ctxt,
11538		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11539		    NULL, node, child,
11540		    "The attribute 'base' and the <simpleType> child are "
11541		    "mutually exclusive", NULL);
11542	    } else {
11543		type->baseType = (xmlSchemaTypePtr)
11544		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11545	    }
11546	    child = child->next;
11547	} else if (type->base == NULL) {
11548	    xmlSchemaPContentErr(ctxt,
11549		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11550		NULL, node, child,
11551		"Either the attribute 'base' or a <simpleType> child "
11552		"must be present", NULL);
11553	}
11554    } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11555	/*
11556	* Corresponds to <complexType><complexContent><restriction>...
11557	* followed by:
11558	*
11559	* Model groups <all>, <choice> and <sequence>.
11560	*/
11561	if (IS_SCHEMA(child, "all")) {
11562	    type->subtypes = (xmlSchemaTypePtr)
11563		xmlSchemaParseModelGroup(ctxt, schema, child,
11564		    XML_SCHEMA_TYPE_ALL, 1);
11565	    child = child->next;
11566	} else if (IS_SCHEMA(child, "choice")) {
11567	    type->subtypes = (xmlSchemaTypePtr)
11568		xmlSchemaParseModelGroup(ctxt,
11569		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11570	    child = child->next;
11571	} else if (IS_SCHEMA(child, "sequence")) {
11572	    type->subtypes = (xmlSchemaTypePtr)
11573		xmlSchemaParseModelGroup(ctxt, schema, child,
11574		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11575	    child = child->next;
11576	/*
11577	* Model group reference <group>.
11578	*/
11579	} else if (IS_SCHEMA(child, "group")) {
11580	    type->subtypes = (xmlSchemaTypePtr)
11581		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11582	    /*
11583	    * Note that the reference will be resolved in
11584	    * xmlSchemaResolveTypeReferences();
11585	    */
11586	    child = child->next;
11587	}
11588    } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11589	/*
11590	* Corresponds to <complexType><simpleContent><restriction>...
11591	*
11592	* "1.1 the simple type definition corresponding to the <simpleType>
11593	* among the [children] of <restriction> if there is one;"
11594	*/
11595	if (IS_SCHEMA(child, "simpleType")) {
11596	    /*
11597	    * We will store the to-be-restricted simple type in
11598	    * type->contentTypeDef *temporarily*.
11599	    */
11600	    type->contentTypeDef = (xmlSchemaTypePtr)
11601		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11602	    if ( type->contentTypeDef == NULL)
11603		return (NULL);
11604	    child = child->next;
11605	}
11606    }
11607
11608    if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11609	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11610	xmlSchemaFacetPtr facet, lastfacet = NULL;
11611	/*
11612	* Corresponds to <complexType><simpleContent><restriction>...
11613	* <simpleType><restriction>...
11614	*/
11615
11616	/*
11617	* Add the facets to the simple type ancestor.
11618	*/
11619	/*
11620	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11621	* Simple Type Definition Schema Representation Constraint:
11622	* *Single Facet Value*
11623	*/
11624	while ((IS_SCHEMA(child, "minInclusive")) ||
11625	    (IS_SCHEMA(child, "minExclusive")) ||
11626	    (IS_SCHEMA(child, "maxInclusive")) ||
11627	    (IS_SCHEMA(child, "maxExclusive")) ||
11628	    (IS_SCHEMA(child, "totalDigits")) ||
11629	    (IS_SCHEMA(child, "fractionDigits")) ||
11630	    (IS_SCHEMA(child, "pattern")) ||
11631	    (IS_SCHEMA(child, "enumeration")) ||
11632	    (IS_SCHEMA(child, "whiteSpace")) ||
11633	    (IS_SCHEMA(child, "length")) ||
11634	    (IS_SCHEMA(child, "maxLength")) ||
11635	    (IS_SCHEMA(child, "minLength"))) {
11636	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11637	    if (facet != NULL) {
11638		if (lastfacet == NULL)
11639		    type->facets = facet;
11640		else
11641		    lastfacet->next = facet;
11642		lastfacet = facet;
11643		lastfacet->next = NULL;
11644	    }
11645	    child = child->next;
11646	}
11647	/*
11648	* Create links for derivation and validation.
11649	*/
11650	if (type->facets != NULL) {
11651	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11652
11653	    facet = type->facets;
11654	    do {
11655		facetLink = (xmlSchemaFacetLinkPtr)
11656		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11657		if (facetLink == NULL) {
11658		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11659		    xmlFree(facetLink);
11660		    return (NULL);
11661		}
11662		facetLink->facet = facet;
11663		facetLink->next = NULL;
11664		if (lastFacetLink == NULL)
11665		    type->facetSet = facetLink;
11666		else
11667		    lastFacetLink->next = facetLink;
11668		lastFacetLink = facetLink;
11669		facet = facet->next;
11670	    } while (facet != NULL);
11671	}
11672    }
11673    if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11674	/*
11675	* Attribute uses/declarations.
11676	*/
11677	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11678	    (xmlSchemaItemListPtr *) &(type->attrUses),
11679	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11680	    return(NULL);
11681	/*
11682	* Attribute wildcard.
11683	*/
11684	if (IS_SCHEMA(child, "anyAttribute")) {
11685	    type->attributeWildcard =
11686		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11687	    child = child->next;
11688	}
11689    }
11690    if (child != NULL) {
11691	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11692	    xmlSchemaPContentErr(ctxt,
11693		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11694		NULL, node, child, NULL,
11695		"annotation?, (group | all | choice | sequence)?, "
11696		"((attribute | attributeGroup)*, anyAttribute?))");
11697	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11698	     xmlSchemaPContentErr(ctxt,
11699		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11700		NULL, node, child, NULL,
11701		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11702		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11703		"length | minLength | maxLength | enumeration | whiteSpace | "
11704		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11705	} else {
11706	    /* Simple type */
11707	    xmlSchemaPContentErr(ctxt,
11708		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11709		NULL, node, child, NULL,
11710		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11711		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11712		"length | minLength | maxLength | enumeration | whiteSpace | "
11713		"pattern)*))");
11714	}
11715    }
11716    return (NULL);
11717}
11718
11719/**
11720 * xmlSchemaParseExtension:
11721 * @ctxt:  a schema validation context
11722 * @schema:  the schema being built
11723 * @node:  a subtree containing XML Schema informations
11724 *
11725 * Parses an <extension>, which is found inside a
11726 * <simpleContent> or <complexContent>.
11727 * *WARNING* this interface is highly subject to change.
11728 *
11729 * TODO: Returns the type definition or NULL in case of error
11730 */
11731static xmlSchemaTypePtr
11732xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11733                        xmlNodePtr node, xmlSchemaTypeType parentType)
11734{
11735    xmlSchemaTypePtr type;
11736    xmlNodePtr child = NULL;
11737    xmlAttrPtr attr;
11738
11739    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11740        return (NULL);
11741    /* Not a component, don't create it. */
11742    type = ctxt->ctxtType;
11743    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11744
11745    /*
11746    * Check for illegal attributes.
11747    */
11748    attr = node->properties;
11749    while (attr != NULL) {
11750	if (attr->ns == NULL) {
11751	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11752		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11753		xmlSchemaPIllegalAttrErr(ctxt,
11754		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11755	    }
11756	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11757	    xmlSchemaPIllegalAttrErr(ctxt,
11758		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11759	}
11760	attr = attr->next;
11761    }
11762
11763    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11764
11765    /*
11766    * Attribute "base" - mandatory.
11767    */
11768    if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11769	"base", &(type->baseNs), &(type->base)) == 0) &&
11770	(type->base == NULL)) {
11771	xmlSchemaPMissingAttrErr(ctxt,
11772	    XML_SCHEMAP_S4S_ATTR_MISSING,
11773	    NULL, node, "base", NULL);
11774    }
11775    /*
11776    * And now for the children...
11777    */
11778    child = node->children;
11779    if (IS_SCHEMA(child, "annotation")) {
11780	/*
11781	* Add the annotation to the type ancestor.
11782	*/
11783	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11784	    xmlSchemaParseAnnotation(ctxt, child, 1));
11785        child = child->next;
11786    }
11787    if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11788	/*
11789	* Corresponds to <complexType><complexContent><extension>... and:
11790	*
11791	* Model groups <all>, <choice>, <sequence> and <group>.
11792	*/
11793	if (IS_SCHEMA(child, "all")) {
11794	    type->subtypes = (xmlSchemaTypePtr)
11795		xmlSchemaParseModelGroup(ctxt, schema,
11796		    child, XML_SCHEMA_TYPE_ALL, 1);
11797	    child = child->next;
11798	} else if (IS_SCHEMA(child, "choice")) {
11799	    type->subtypes = (xmlSchemaTypePtr)
11800		xmlSchemaParseModelGroup(ctxt, schema,
11801		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11802	    child = child->next;
11803	} else if (IS_SCHEMA(child, "sequence")) {
11804	    type->subtypes = (xmlSchemaTypePtr)
11805		xmlSchemaParseModelGroup(ctxt, schema,
11806		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11807	    child = child->next;
11808	} else if (IS_SCHEMA(child, "group")) {
11809	    type->subtypes = (xmlSchemaTypePtr)
11810		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11811	    /*
11812	    * Note that the reference will be resolved in
11813	    * xmlSchemaResolveTypeReferences();
11814	    */
11815	    child = child->next;
11816	}
11817    }
11818    if (child != NULL) {
11819	/*
11820	* Attribute uses/declarations.
11821	*/
11822	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11823	    (xmlSchemaItemListPtr *) &(type->attrUses),
11824	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11825	    return(NULL);
11826	/*
11827	* Attribute wildcard.
11828	*/
11829	if (IS_SCHEMA(child, "anyAttribute")) {
11830	    ctxt->ctxtType->attributeWildcard =
11831		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11832	    child = child->next;
11833	}
11834    }
11835    if (child != NULL) {
11836	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11837	    /* Complex content extension. */
11838	    xmlSchemaPContentErr(ctxt,
11839		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11840		NULL, node, child, NULL,
11841		"(annotation?, ((group | all | choice | sequence)?, "
11842		"((attribute | attributeGroup)*, anyAttribute?)))");
11843	} else {
11844	    /* Simple content extension. */
11845	    xmlSchemaPContentErr(ctxt,
11846		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11847		NULL, node, child, NULL,
11848		"(annotation?, ((attribute | attributeGroup)*, "
11849		"anyAttribute?))");
11850	}
11851    }
11852    return (NULL);
11853}
11854
11855/**
11856 * xmlSchemaParseSimpleContent:
11857 * @ctxt:  a schema validation context
11858 * @schema:  the schema being built
11859 * @node:  a subtree containing XML Schema informations
11860 *
11861 * parse a XML schema SimpleContent definition
11862 * *WARNING* this interface is highly subject to change
11863 *
11864 * Returns the type definition or NULL in case of error
11865 */
11866static int
11867xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11868                            xmlSchemaPtr schema, xmlNodePtr node,
11869			    int *hasRestrictionOrExtension)
11870{
11871    xmlSchemaTypePtr type;
11872    xmlNodePtr child = NULL;
11873    xmlAttrPtr attr;
11874
11875    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11876	(hasRestrictionOrExtension == NULL))
11877        return (-1);
11878    *hasRestrictionOrExtension = 0;
11879    /* Not a component, don't create it. */
11880    type = ctxt->ctxtType;
11881    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11882    /*
11883    * Check for illegal attributes.
11884    */
11885    attr = node->properties;
11886    while (attr != NULL) {
11887	if (attr->ns == NULL) {
11888	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11889		xmlSchemaPIllegalAttrErr(ctxt,
11890		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11891	    }
11892	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11893	    xmlSchemaPIllegalAttrErr(ctxt,
11894		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11895	}
11896	attr = attr->next;
11897    }
11898
11899    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11900
11901    /*
11902    * And now for the children...
11903    */
11904    child = node->children;
11905    if (IS_SCHEMA(child, "annotation")) {
11906	/*
11907	* Add the annotation to the complex type ancestor.
11908	*/
11909	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11910	    xmlSchemaParseAnnotation(ctxt, child, 1));
11911        child = child->next;
11912    }
11913    if (child == NULL) {
11914	xmlSchemaPContentErr(ctxt,
11915	    XML_SCHEMAP_S4S_ELEM_MISSING,
11916	    NULL, node, NULL, NULL,
11917	    "(annotation?, (restriction | extension))");
11918    }
11919    if (child == NULL) {
11920	xmlSchemaPContentErr(ctxt,
11921	    XML_SCHEMAP_S4S_ELEM_MISSING,
11922	    NULL, node, NULL, NULL,
11923	    "(annotation?, (restriction | extension))");
11924    }
11925    if (IS_SCHEMA(child, "restriction")) {
11926        xmlSchemaParseRestriction(ctxt, schema, child,
11927	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11928	(*hasRestrictionOrExtension) = 1;
11929        child = child->next;
11930    } else if (IS_SCHEMA(child, "extension")) {
11931        xmlSchemaParseExtension(ctxt, schema, child,
11932	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11933	(*hasRestrictionOrExtension) = 1;
11934        child = child->next;
11935    }
11936    if (child != NULL) {
11937	xmlSchemaPContentErr(ctxt,
11938	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11939	    NULL, node, child, NULL,
11940	    "(annotation?, (restriction | extension))");
11941    }
11942    return (0);
11943}
11944
11945/**
11946 * xmlSchemaParseComplexContent:
11947 * @ctxt:  a schema validation context
11948 * @schema:  the schema being built
11949 * @node:  a subtree containing XML Schema informations
11950 *
11951 * parse a XML schema ComplexContent definition
11952 * *WARNING* this interface is highly subject to change
11953 *
11954 * Returns the type definition or NULL in case of error
11955 */
11956static int
11957xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11958                             xmlSchemaPtr schema, xmlNodePtr node,
11959			     int *hasRestrictionOrExtension)
11960{
11961    xmlSchemaTypePtr type;
11962    xmlNodePtr child = NULL;
11963    xmlAttrPtr attr;
11964
11965    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11966	(hasRestrictionOrExtension == NULL))
11967        return (-1);
11968    *hasRestrictionOrExtension = 0;
11969    /* Not a component, don't create it. */
11970    type = ctxt->ctxtType;
11971    /*
11972    * Check for illegal attributes.
11973    */
11974    attr = node->properties;
11975    while (attr != NULL) {
11976	if (attr->ns == NULL) {
11977	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11978		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
11979	    {
11980		xmlSchemaPIllegalAttrErr(ctxt,
11981		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11982	    }
11983	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11984	    xmlSchemaPIllegalAttrErr(ctxt,
11985		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11986	}
11987	attr = attr->next;
11988    }
11989
11990    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11991
11992    /*
11993    * Set the 'mixed' on the complex type ancestor.
11994    */
11995    if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
11996	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11997	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
11998    }
11999    child = node->children;
12000    if (IS_SCHEMA(child, "annotation")) {
12001	/*
12002	* Add the annotation to the complex type ancestor.
12003	*/
12004	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12005	    xmlSchemaParseAnnotation(ctxt, child, 1));
12006        child = child->next;
12007    }
12008    if (child == NULL) {
12009	xmlSchemaPContentErr(ctxt,
12010	    XML_SCHEMAP_S4S_ELEM_MISSING,
12011	    NULL, node, NULL,
12012	    NULL, "(annotation?, (restriction | extension))");
12013    }
12014    if (child == NULL) {
12015	xmlSchemaPContentErr(ctxt,
12016	    XML_SCHEMAP_S4S_ELEM_MISSING,
12017	    NULL, node, NULL,
12018	    NULL, "(annotation?, (restriction | extension))");
12019    }
12020    if (IS_SCHEMA(child, "restriction")) {
12021        xmlSchemaParseRestriction(ctxt, schema, child,
12022	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12023	(*hasRestrictionOrExtension) = 1;
12024        child = child->next;
12025    } else if (IS_SCHEMA(child, "extension")) {
12026        xmlSchemaParseExtension(ctxt, schema, child,
12027	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12028	(*hasRestrictionOrExtension) = 1;
12029        child = child->next;
12030    }
12031    if (child != NULL) {
12032	xmlSchemaPContentErr(ctxt,
12033	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12034	    NULL, node, child,
12035	    NULL, "(annotation?, (restriction | extension))");
12036    }
12037    return (0);
12038}
12039
12040/**
12041 * xmlSchemaParseComplexType:
12042 * @ctxt:  a schema validation context
12043 * @schema:  the schema being built
12044 * @node:  a subtree containing XML Schema informations
12045 *
12046 * parse a XML schema Complex Type definition
12047 * *WARNING* this interface is highly subject to change
12048 *
12049 * Returns the type definition or NULL in case of error
12050 */
12051static xmlSchemaTypePtr
12052xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12053                          xmlNodePtr node, int topLevel)
12054{
12055    xmlSchemaTypePtr type, ctxtType;
12056    xmlNodePtr child = NULL;
12057    const xmlChar *name = NULL;
12058    xmlAttrPtr attr;
12059    const xmlChar *attrValue;
12060#ifdef ENABLE_NAMED_LOCALS
12061    char buf[40];
12062#endif
12063    int final = 0, block = 0, hasRestrictionOrExtension = 0;
12064
12065
12066    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12067        return (NULL);
12068
12069    ctxtType = ctxt->ctxtType;
12070
12071    if (topLevel) {
12072	attr = xmlSchemaGetPropNode(node, "name");
12073	if (attr == NULL) {
12074	    xmlSchemaPMissingAttrErr(ctxt,
12075		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12076	    return (NULL);
12077	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12078	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12079	    return (NULL);
12080	}
12081    }
12082
12083    if (topLevel == 0) {
12084	/*
12085	* Parse as local complex type definition.
12086	*/
12087#ifdef ENABLE_NAMED_LOCALS
12088        snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12089	type = xmlSchemaAddType(ctxt, schema,
12090	    XML_SCHEMA_TYPE_COMPLEX,
12091	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12092	    ctxt->targetNamespace, node, 0);
12093#else
12094	type = xmlSchemaAddType(ctxt, schema,
12095	    XML_SCHEMA_TYPE_COMPLEX,
12096	    NULL, ctxt->targetNamespace, node, 0);
12097#endif
12098	if (type == NULL)
12099	    return (NULL);
12100	name = type->name;
12101	type->node = node;
12102	type->type = XML_SCHEMA_TYPE_COMPLEX;
12103	/*
12104	* TODO: We need the target namespace.
12105	*/
12106    } else {
12107	/*
12108	* Parse as global complex type definition.
12109	*/
12110	type = xmlSchemaAddType(ctxt, schema,
12111	    XML_SCHEMA_TYPE_COMPLEX,
12112	    name, ctxt->targetNamespace, node, 1);
12113	if (type == NULL)
12114	    return (NULL);
12115	type->node = node;
12116	type->type = XML_SCHEMA_TYPE_COMPLEX;
12117	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12118    }
12119    type->targetNamespace = ctxt->targetNamespace;
12120    /*
12121    * Handle attributes.
12122    */
12123    attr = node->properties;
12124    while (attr != NULL) {
12125	if (attr->ns == NULL) {
12126	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12127		/*
12128		* Attribute "id".
12129		*/
12130		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12131	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12132		/*
12133		* Attribute "mixed".
12134		*/
12135		if (xmlSchemaPGetBoolNodeValue(ctxt,
12136			NULL, (xmlNodePtr) attr))
12137		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12138	    } else if (topLevel) {
12139		/*
12140		* Attributes of global complex type definitions.
12141		*/
12142		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12143		    /* Pass. */
12144		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12145		    /*
12146		    * Attribute "abstract".
12147		    */
12148		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12149			    NULL, (xmlNodePtr) attr))
12150			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12151		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12152		    /*
12153		    * Attribute "final".
12154		    */
12155		    attrValue = xmlSchemaGetNodeContent(ctxt,
12156			(xmlNodePtr) attr);
12157		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12158			&(type->flags),
12159			-1,
12160			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12161			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12162			-1, -1, -1) != 0)
12163		    {
12164			xmlSchemaPSimpleTypeErr(ctxt,
12165			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12166			    NULL, (xmlNodePtr) attr, NULL,
12167			    "(#all | List of (extension | restriction))",
12168			    attrValue, NULL, NULL, NULL);
12169		    } else
12170			final = 1;
12171		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12172		    /*
12173		    * Attribute "block".
12174		    */
12175		    attrValue = xmlSchemaGetNodeContent(ctxt,
12176			(xmlNodePtr) attr);
12177		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12178			-1,
12179			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12180			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12181			-1, -1, -1) != 0) {
12182			xmlSchemaPSimpleTypeErr(ctxt,
12183			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12184			    NULL, (xmlNodePtr) attr, NULL,
12185			    "(#all | List of (extension | restriction)) ",
12186			    attrValue, NULL, NULL, NULL);
12187		    } else
12188			block = 1;
12189		} else {
12190			xmlSchemaPIllegalAttrErr(ctxt,
12191			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12192		}
12193	    } else {
12194		xmlSchemaPIllegalAttrErr(ctxt,
12195		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12196	    }
12197	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12198	    xmlSchemaPIllegalAttrErr(ctxt,
12199		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12200	}
12201	attr = attr->next;
12202    }
12203    if (! block) {
12204	/*
12205	* Apply default "block" values.
12206	*/
12207	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12208	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12209	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12210	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12211    }
12212    if (! final) {
12213	/*
12214	* Apply default "block" values.
12215	*/
12216	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12217	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12218	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12219	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12220    }
12221    /*
12222    * And now for the children...
12223    */
12224    child = node->children;
12225    if (IS_SCHEMA(child, "annotation")) {
12226        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12227        child = child->next;
12228    }
12229    ctxt->ctxtType = type;
12230    if (IS_SCHEMA(child, "simpleContent")) {
12231	/*
12232	* <complexType><simpleContent>...
12233	* 3.4.3 : 2.2
12234	* Specifying mixed='true' when the <simpleContent>
12235	* alternative is chosen has no effect
12236	*/
12237	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12238	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12239        xmlSchemaParseSimpleContent(ctxt, schema, child,
12240	    &hasRestrictionOrExtension);
12241        child = child->next;
12242    } else if (IS_SCHEMA(child, "complexContent")) {
12243	/*
12244	* <complexType><complexContent>...
12245	*/
12246	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12247        xmlSchemaParseComplexContent(ctxt, schema, child,
12248	    &hasRestrictionOrExtension);
12249        child = child->next;
12250    } else {
12251	/*
12252	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12253	*
12254	* SPEC
12255	* "...the third alternative (neither <simpleContent> nor
12256	* <complexContent>) is chosen. This case is understood as shorthand
12257	* for complex content restricting the �ur-type definition�, and the
12258	* details of the mappings should be modified as necessary.
12259	*/
12260	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12261	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12262	/*
12263	* Parse model groups.
12264	*/
12265        if (IS_SCHEMA(child, "all")) {
12266            type->subtypes = (xmlSchemaTypePtr)
12267		xmlSchemaParseModelGroup(ctxt, schema, child,
12268		    XML_SCHEMA_TYPE_ALL, 1);
12269            child = child->next;
12270        } else if (IS_SCHEMA(child, "choice")) {
12271            type->subtypes = (xmlSchemaTypePtr)
12272		xmlSchemaParseModelGroup(ctxt, schema, child,
12273		    XML_SCHEMA_TYPE_CHOICE, 1);
12274            child = child->next;
12275        } else if (IS_SCHEMA(child, "sequence")) {
12276            type->subtypes = (xmlSchemaTypePtr)
12277		xmlSchemaParseModelGroup(ctxt, schema, child,
12278		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12279            child = child->next;
12280        } else if (IS_SCHEMA(child, "group")) {
12281            type->subtypes = (xmlSchemaTypePtr)
12282		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12283	    /*
12284	    * Note that the reference will be resolved in
12285	    * xmlSchemaResolveTypeReferences();
12286	    */
12287            child = child->next;
12288        }
12289	/*
12290	* Parse attribute decls/refs.
12291	*/
12292        if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12293	    (xmlSchemaItemListPtr *) &(type->attrUses),
12294	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12295	    return(NULL);
12296	/*
12297	* Parse attribute wildcard.
12298	*/
12299	if (IS_SCHEMA(child, "anyAttribute")) {
12300	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12301	    child = child->next;
12302	}
12303    }
12304    if (child != NULL) {
12305	xmlSchemaPContentErr(ctxt,
12306	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12307	    NULL, node, child,
12308	    NULL, "(annotation?, (simpleContent | complexContent | "
12309	    "((group | all | choice | sequence)?, ((attribute | "
12310	    "attributeGroup)*, anyAttribute?))))");
12311    }
12312    /*
12313    * REDEFINE: SPEC src-redefine (5)
12314    */
12315    if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12316	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12317	    NULL, node, "This is a redefinition, thus the "
12318	    "<complexType> must have a <restriction> or <extension> "
12319	    "grand-child", NULL);
12320    }
12321    ctxt->ctxtType = ctxtType;
12322    return (type);
12323}
12324
12325/************************************************************************
12326 * 									*
12327 * 			Validating using Schemas			*
12328 * 									*
12329 ************************************************************************/
12330
12331/************************************************************************
12332 * 									*
12333 * 			Reading/Writing Schemas				*
12334 * 									*
12335 ************************************************************************/
12336
12337#if 0 /* Will be enabled if it is clear what options are needed. */
12338/**
12339 * xmlSchemaParserCtxtSetOptions:
12340 * @ctxt:	a schema parser context
12341 * @options: a combination of xmlSchemaParserOption
12342 *
12343 * Sets the options to be used during the parse.
12344 *
12345 * Returns 0 in case of success, -1 in case of an
12346 * API error.
12347 */
12348static int
12349xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12350			      int options)
12351
12352{
12353    int i;
12354
12355    if (ctxt == NULL)
12356	return (-1);
12357    /*
12358    * WARNING: Change the start value if adding to the
12359    * xmlSchemaParseOption.
12360    */
12361    for (i = 1; i < (int) sizeof(int) * 8; i++) {
12362        if (options & 1<<i) {
12363	    return (-1);
12364        }
12365    }
12366    ctxt->options = options;
12367    return (0);
12368}
12369
12370/**
12371 * xmlSchemaValidCtxtGetOptions:
12372 * @ctxt: a schema parser context
12373 *
12374 * Returns the option combination of the parser context.
12375 */
12376static int
12377xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12378
12379{
12380    if (ctxt == NULL)
12381	return (-1);
12382    else
12383	return (ctxt->options);
12384}
12385#endif
12386
12387/**
12388 * xmlSchemaNewParserCtxt:
12389 * @URL:  the location of the schema
12390 *
12391 * Create an XML Schemas parse context for that file/resource expected
12392 * to contain an XML Schemas file.
12393 *
12394 * Returns the parser context or NULL in case of error
12395 */
12396xmlSchemaParserCtxtPtr
12397xmlSchemaNewParserCtxt(const char *URL)
12398{
12399    xmlSchemaParserCtxtPtr ret;
12400
12401    if (URL == NULL)
12402        return (NULL);
12403
12404    ret = xmlSchemaParserCtxtCreate();
12405    if (ret == NULL)
12406	return(NULL);
12407    ret->dict = xmlDictCreate();
12408    ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12409    return (ret);
12410}
12411
12412/**
12413 * xmlSchemaNewMemParserCtxt:
12414 * @buffer:  a pointer to a char array containing the schemas
12415 * @size:  the size of the array
12416 *
12417 * Create an XML Schemas parse context for that memory buffer expected
12418 * to contain an XML Schemas file.
12419 *
12420 * Returns the parser context or NULL in case of error
12421 */
12422xmlSchemaParserCtxtPtr
12423xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12424{
12425    xmlSchemaParserCtxtPtr ret;
12426
12427    if ((buffer == NULL) || (size <= 0))
12428        return (NULL);
12429    ret = xmlSchemaParserCtxtCreate();
12430    if (ret == NULL)
12431	return(NULL);
12432    ret->buffer = buffer;
12433    ret->size = size;
12434    ret->dict = xmlDictCreate();
12435    return (ret);
12436}
12437
12438/**
12439 * xmlSchemaNewDocParserCtxt:
12440 * @doc:  a preparsed document tree
12441 *
12442 * Create an XML Schemas parse context for that document.
12443 * NB. The document may be modified during the parsing process.
12444 *
12445 * Returns the parser context or NULL in case of error
12446 */
12447xmlSchemaParserCtxtPtr
12448xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12449{
12450    xmlSchemaParserCtxtPtr ret;
12451
12452    if (doc == NULL)
12453      return (NULL);
12454    ret = xmlSchemaParserCtxtCreate();
12455    if (ret == NULL)
12456	return(NULL);
12457    ret->doc = doc;
12458    ret->dict = xmlDictCreate();
12459    /* The application has responsibility for the document */
12460    ret->preserve = 1;
12461
12462    return (ret);
12463}
12464
12465/**
12466 * xmlSchemaFreeParserCtxt:
12467 * @ctxt:  the schema parser context
12468 *
12469 * Free the resources associated to the schema parser context
12470 */
12471void
12472xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12473{
12474    if (ctxt == NULL)
12475        return;
12476    if (ctxt->doc != NULL && !ctxt->preserve)
12477        xmlFreeDoc(ctxt->doc);
12478    if (ctxt->vctxt != NULL) {
12479	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12480    }
12481    if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12482	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12483	ctxt->constructor = NULL;
12484	ctxt->ownsConstructor = 0;
12485    }
12486    if (ctxt->attrProhibs != NULL)
12487	xmlSchemaItemListFree(ctxt->attrProhibs);
12488    xmlDictFree(ctxt->dict);
12489    xmlFree(ctxt);
12490}
12491
12492/************************************************************************
12493 *									*
12494 *			Building the content models			*
12495 *									*
12496 ************************************************************************/
12497
12498static void
12499xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12500	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12501{
12502    xmlAutomataStatePtr start, tmp;
12503    xmlSchemaElementPtr elemDecl, member;
12504    xmlSchemaSubstGroupPtr substGroup;
12505    int i;
12506
12507    elemDecl = (xmlSchemaElementPtr) particle->children;
12508    /*
12509    * Wrap the substitution group with a CHOICE.
12510    */
12511    start = pctxt->state;
12512    if (end == NULL)
12513	end = xmlAutomataNewState(pctxt->am);
12514    substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12515    if (substGroup == NULL) {
12516	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12517	    XML_SCHEMAP_INTERNAL,
12518	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12519	    "declaration is marked having a subst. group but none "
12520	    "available.\n", elemDecl->name, NULL);
12521	return;
12522    }
12523    if (counter >= 0) {
12524	/*
12525	* NOTE that we put the declaration in, even if it's abstract.
12526	* However, an error will be raised during *validation* if an element
12527	* information item shall be validated against an abstract element
12528	* declaration.
12529	*/
12530	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12531        xmlAutomataNewTransition2(pctxt->am, tmp, end,
12532	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12533	/*
12534	* Add subst. group members.
12535	*/
12536	for (i = 0; i < substGroup->members->nbItems; i++) {
12537	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12538            xmlAutomataNewTransition2(pctxt->am, tmp, end,
12539		               member->name, member->targetNamespace, member);
12540	}
12541    } else if (particle->maxOccurs == 1) {
12542	/*
12543	* NOTE that we put the declaration in, even if it's abstract,
12544	*/
12545	xmlAutomataNewEpsilon(pctxt->am,
12546	    xmlAutomataNewTransition2(pctxt->am,
12547	    start, NULL,
12548	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12549	/*
12550	* Add subst. group members.
12551	*/
12552	for (i = 0; i < substGroup->members->nbItems; i++) {
12553	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12554	    /*
12555	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12556	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12557	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12558	    *  section in xmlSchemaBuildAContentModel() ).
12559	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12560	    *  intended for the above "counter" section originally. I.e.,
12561	    *  check xs:all with subst-groups.
12562	    *
12563	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12564	    *	               member->name, member->targetNamespace,
12565	    *		       1, 1, member);
12566	    */
12567	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12568		member->name, member->targetNamespace, member);
12569	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12570	}
12571    } else {
12572	xmlAutomataStatePtr hop;
12573	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12574	    UNBOUNDED : particle->maxOccurs - 1;
12575	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12576
12577	counter =
12578	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12579	    maxOccurs);
12580	hop = xmlAutomataNewState(pctxt->am);
12581
12582	xmlAutomataNewEpsilon(pctxt->am,
12583	    xmlAutomataNewTransition2(pctxt->am,
12584	    start, NULL,
12585	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12586	    hop);
12587	/*
12588	 * Add subst. group members.
12589	 */
12590	for (i = 0; i < substGroup->members->nbItems; i++) {
12591	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12592	    xmlAutomataNewEpsilon(pctxt->am,
12593		xmlAutomataNewTransition2(pctxt->am,
12594		start, NULL,
12595		member->name, member->targetNamespace, member),
12596		hop);
12597	}
12598	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12599	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12600    }
12601    if (particle->minOccurs == 0)
12602	xmlAutomataNewEpsilon(pctxt->am, start, end);
12603    pctxt->state = end;
12604}
12605
12606static void
12607xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12608				     xmlSchemaParticlePtr particle)
12609{
12610    if (((xmlSchemaElementPtr) particle->children)->flags &
12611	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12612	/*
12613	* Substitution groups.
12614	*/
12615	xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12616    } else {
12617	xmlSchemaElementPtr elemDecl;
12618	xmlAutomataStatePtr start;
12619
12620	elemDecl = (xmlSchemaElementPtr) particle->children;
12621
12622	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12623	    return;
12624	if (particle->maxOccurs == 1) {
12625	    start = ctxt->state;
12626	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12627		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12628	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12629	           (particle->minOccurs < 2)) {
12630	    /* Special case. */
12631	    start = ctxt->state;
12632	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12633		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12634	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12635		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12636	} else {
12637	    int counter;
12638	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12639			    UNBOUNDED : particle->maxOccurs - 1;
12640	    int minOccurs = particle->minOccurs < 1 ?
12641			    0 : particle->minOccurs - 1;
12642
12643	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12644	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12645	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12646		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12647	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12648	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12649		NULL, counter);
12650	}
12651	if (particle->minOccurs == 0)
12652	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12653    }
12654}
12655
12656/**
12657 * xmlSchemaBuildAContentModel:
12658 * @ctxt:  the schema parser context
12659 * @particle:  the particle component
12660 * @name:  the complex type's name whose content is being built
12661 *
12662 * Create the automaton for the {content type} of a complex type.
12663 *
12664 */
12665static void
12666xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12667			    xmlSchemaParticlePtr particle)
12668{
12669    if (particle == NULL) {
12670	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12671	return;
12672    }
12673    if (particle->children == NULL) {
12674	/*
12675	* Just return in this case. A missing "term" of the particle
12676	* might arise due to an invalid "term" component.
12677	*/
12678	return;
12679    }
12680
12681    switch (particle->children->type) {
12682	case XML_SCHEMA_TYPE_ANY: {
12683	    xmlAutomataStatePtr start, end;
12684	    xmlSchemaWildcardPtr wild;
12685	    xmlSchemaWildcardNsPtr ns;
12686
12687	    wild = (xmlSchemaWildcardPtr) particle->children;
12688
12689	    start = pctxt->state;
12690	    end = xmlAutomataNewState(pctxt->am);
12691
12692	    if (particle->maxOccurs == 1) {
12693		if (wild->any == 1) {
12694		    /*
12695		    * We need to add both transitions:
12696		    *
12697		    * 1. the {"*", "*"} for elements in a namespace.
12698		    */
12699		    pctxt->state =
12700			xmlAutomataNewTransition2(pctxt->am,
12701			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12702		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12703		    /*
12704		    * 2. the {"*"} for elements in no namespace.
12705		    */
12706		    pctxt->state =
12707			xmlAutomataNewTransition2(pctxt->am,
12708			start, NULL, BAD_CAST "*", NULL, wild);
12709		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12710
12711		} else if (wild->nsSet != NULL) {
12712		    ns = wild->nsSet;
12713		    do {
12714			pctxt->state = start;
12715			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12716			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12717			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12718			ns = ns->next;
12719		    } while (ns != NULL);
12720
12721		} else if (wild->negNsSet != NULL) {
12722		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12723			start, end, BAD_CAST "*", wild->negNsSet->value,
12724			wild);
12725		}
12726	    } else {
12727		int counter;
12728		xmlAutomataStatePtr hop;
12729		int maxOccurs =
12730		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
12731		int minOccurs =
12732		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12733
12734		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12735		hop = xmlAutomataNewState(pctxt->am);
12736		if (wild->any == 1) {
12737		    pctxt->state =
12738			xmlAutomataNewTransition2(pctxt->am,
12739			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12740		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12741		    pctxt->state =
12742			xmlAutomataNewTransition2(pctxt->am,
12743			start, NULL, BAD_CAST "*", NULL, wild);
12744		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12745		} else if (wild->nsSet != NULL) {
12746		    ns = wild->nsSet;
12747		    do {
12748			pctxt->state =
12749			    xmlAutomataNewTransition2(pctxt->am,
12750				start, NULL, BAD_CAST "*", ns->value, wild);
12751			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12752			ns = ns->next;
12753		    } while (ns != NULL);
12754
12755		} else if (wild->negNsSet != NULL) {
12756		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12757			start, hop, BAD_CAST "*", wild->negNsSet->value,
12758			wild);
12759		}
12760		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12761		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12762	    }
12763	    if (particle->minOccurs == 0) {
12764		xmlAutomataNewEpsilon(pctxt->am, start, end);
12765	    }
12766	    pctxt->state = end;
12767            break;
12768	}
12769        case XML_SCHEMA_TYPE_ELEMENT:
12770	    xmlSchemaBuildContentModelForElement(pctxt, particle);
12771	    break;
12772        case XML_SCHEMA_TYPE_SEQUENCE:{
12773                xmlSchemaTreeItemPtr sub;
12774
12775                /*
12776                 * If max and min occurances are default (1) then
12777                 * simply iterate over the particles of the <sequence>.
12778                 */
12779                if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12780                    sub = particle->children->children;
12781                    while (sub != NULL) {
12782                        xmlSchemaBuildAContentModel(pctxt,
12783			    (xmlSchemaParticlePtr) sub);
12784                        sub = sub->next;
12785                    }
12786                } else {
12787                    xmlAutomataStatePtr oldstate = pctxt->state;
12788
12789                    if (particle->maxOccurs >= UNBOUNDED) {
12790                        if (particle->minOccurs > 1) {
12791                            xmlAutomataStatePtr tmp;
12792                            int counter;
12793
12794                            pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12795				oldstate, NULL);
12796                            oldstate = pctxt->state;
12797
12798                            counter = xmlAutomataNewCounter(pctxt->am,
12799				particle->minOccurs - 1, UNBOUNDED);
12800
12801                            sub = particle->children->children;
12802                            while (sub != NULL) {
12803                                xmlSchemaBuildAContentModel(pctxt,
12804				    (xmlSchemaParticlePtr) sub);
12805                                sub = sub->next;
12806                            }
12807                            tmp = pctxt->state;
12808                            xmlAutomataNewCountedTrans(pctxt->am, tmp,
12809                                                       oldstate, counter);
12810                            pctxt->state =
12811                                xmlAutomataNewCounterTrans(pctxt->am, tmp,
12812                                                           NULL, counter);
12813
12814                        } else {
12815                            pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12816				oldstate, NULL);
12817                            oldstate = pctxt->state;
12818
12819			    sub = particle->children->children;
12820                            while (sub != NULL) {
12821                                xmlSchemaBuildAContentModel(pctxt,
12822				    (xmlSchemaParticlePtr) sub);
12823                                sub = sub->next;
12824                            }
12825                            xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12826                                                  oldstate);
12827			    /*
12828			     * epsilon needed to block previous trans from
12829			     * being allowed to enter back from another
12830			     * construct
12831			     */
12832			    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12833						pctxt->state, NULL);
12834                            if (particle->minOccurs == 0) {
12835                                xmlAutomataNewEpsilon(pctxt->am,
12836				    oldstate, pctxt->state);
12837                            }
12838                        }
12839                    } else if ((particle->maxOccurs > 1)
12840                               || (particle->minOccurs > 1)) {
12841                        xmlAutomataStatePtr tmp;
12842                        int counter;
12843
12844                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12845			    oldstate, NULL);
12846                        oldstate = pctxt->state;
12847
12848                        counter = xmlAutomataNewCounter(pctxt->am,
12849			    particle->minOccurs - 1,
12850			    particle->maxOccurs - 1);
12851
12852                        sub = particle->children->children;
12853                        while (sub != NULL) {
12854                            xmlSchemaBuildAContentModel(pctxt,
12855				(xmlSchemaParticlePtr) sub);
12856                            sub = sub->next;
12857                        }
12858                        tmp = pctxt->state;
12859                        xmlAutomataNewCountedTrans(pctxt->am,
12860			    tmp, oldstate, counter);
12861                        pctxt->state =
12862                            xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12863                                                       counter);
12864                        if (particle->minOccurs == 0) {
12865                            xmlAutomataNewEpsilon(pctxt->am,
12866				oldstate, pctxt->state);
12867                        }
12868                    } else {
12869                        sub = particle->children->children;
12870                        while (sub != NULL) {
12871                            xmlSchemaBuildAContentModel(pctxt,
12872				(xmlSchemaParticlePtr) sub);
12873                            sub = sub->next;
12874                        }
12875                        if (particle->minOccurs == 0) {
12876                            xmlAutomataNewEpsilon(pctxt->am, oldstate,
12877                                                  pctxt->state);
12878                        }
12879                    }
12880                }
12881                break;
12882            }
12883        case XML_SCHEMA_TYPE_CHOICE:{
12884                xmlSchemaTreeItemPtr sub;
12885                xmlAutomataStatePtr start, end;
12886
12887                start = pctxt->state;
12888                end = xmlAutomataNewState(pctxt->am);
12889
12890                /*
12891                 * iterate over the subtypes and remerge the end with an
12892                 * epsilon transition
12893                 */
12894                if (particle->maxOccurs == 1) {
12895		    sub = particle->children->children;
12896                    while (sub != NULL) {
12897                        pctxt->state = start;
12898                        xmlSchemaBuildAContentModel(pctxt,
12899			    (xmlSchemaParticlePtr) sub);
12900                        xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12901                        sub = sub->next;
12902                    }
12903                } else {
12904                    int counter;
12905                    xmlAutomataStatePtr hop, base;
12906                    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12907                        UNBOUNDED : particle->maxOccurs - 1;
12908                    int minOccurs =
12909                        particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12910
12911                    /*
12912                     * use a counter to keep track of the number of transtions
12913                     * which went through the choice.
12914                     */
12915                    counter =
12916                        xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12917                    hop = xmlAutomataNewState(pctxt->am);
12918                    base = xmlAutomataNewState(pctxt->am);
12919
12920		    sub = particle->children->children;
12921                    while (sub != NULL) {
12922                        pctxt->state = base;
12923                        xmlSchemaBuildAContentModel(pctxt,
12924			    (xmlSchemaParticlePtr) sub);
12925                        xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12926                        sub = sub->next;
12927                    }
12928                    xmlAutomataNewEpsilon(pctxt->am, start, base);
12929		    xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12930                    xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12931                }
12932                if (particle->minOccurs == 0) {
12933                    xmlAutomataNewEpsilon(pctxt->am, start, end);
12934                }
12935                pctxt->state = end;
12936                break;
12937            }
12938        case XML_SCHEMA_TYPE_ALL:{
12939                xmlAutomataStatePtr start;
12940		xmlSchemaParticlePtr sub;
12941		xmlSchemaElementPtr elemDecl;
12942                int lax;
12943
12944		sub = (xmlSchemaParticlePtr) particle->children->children;
12945                if (sub == NULL)
12946                    break;
12947                start = pctxt->state;
12948                while (sub != NULL) {
12949                    pctxt->state = start;
12950
12951		    elemDecl = (xmlSchemaElementPtr) sub->children;
12952		    if (elemDecl == NULL) {
12953			PERROR_INT("xmlSchemaBuildAContentModel",
12954			    "<element> particle has no term");
12955			return;
12956		    };
12957		    /*
12958		    * NOTE: The {max occurs} of all the particles in the
12959		    * {particles} of the group must be 0 or 1; this is
12960		    * already ensured during the parse of the content of
12961		    * <all>.
12962		    */
12963		    if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12964			int counter;
12965
12966		        /*
12967			 * This is an abstract group, we need to share
12968			 * the same counter for all the element transitions
12969			 * derived from the group
12970			 */
12971			counter = xmlAutomataNewCounter(pctxt->am,
12972			                   sub->minOccurs, sub->maxOccurs);
12973			xmlSchemaBuildContentModelForSubstGroup(pctxt,
12974					   sub, counter, pctxt->state);
12975		    } else {
12976			if ((sub->minOccurs == 1) &&
12977			    (sub->maxOccurs == 1)) {
12978			    xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12979						    pctxt->state,
12980						    elemDecl->name,
12981						    elemDecl->targetNamespace,
12982						    1, 1, elemDecl);
12983			} else if ((sub->minOccurs == 0) &&
12984			    (sub->maxOccurs == 1)) {
12985
12986			    xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12987						     pctxt->state,
12988						     elemDecl->name,
12989						     elemDecl->targetNamespace,
12990						     0,
12991						     1,
12992						     elemDecl);
12993			}
12994		    }
12995                    sub = (xmlSchemaParticlePtr) sub->next;
12996                }
12997                lax = particle->minOccurs == 0;
12998                pctxt->state =
12999                    xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
13000                break;
13001            }
13002	case XML_SCHEMA_TYPE_GROUP:
13003	    /*
13004	    * If we hit a model group definition, then this means that
13005	    * it was empty, thus was not substituted for the containing
13006	    * model group. Just do nothing in this case.
13007	    * TODO: But the group should be substituted and not occur at
13008	    * all in the content model at this point. Fix this.
13009	    */
13010	    break;
13011        default:
13012	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13013		"xmlSchemaBuildAContentModel",
13014		"found unexpected term of type '%s' in content model",
13015		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13016            return;
13017    }
13018}
13019
13020/**
13021 * xmlSchemaBuildContentModel:
13022 * @ctxt:  the schema parser context
13023 * @type:  the complex type definition
13024 * @name:  the element name
13025 *
13026 * Builds the content model of the complex type.
13027 */
13028static void
13029xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13030			   xmlSchemaParserCtxtPtr ctxt)
13031{
13032    if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13033	(type->contModel != NULL) ||
13034	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13035	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13036	return;
13037
13038#ifdef DEBUG_CONTENT
13039    xmlGenericError(xmlGenericErrorContext,
13040                    "Building content model for %s\n", name);
13041#endif
13042    ctxt->am = NULL;
13043    ctxt->am = xmlNewAutomata();
13044    if (ctxt->am == NULL) {
13045        xmlGenericError(xmlGenericErrorContext,
13046	    "Cannot create automata for complex type %s\n", type->name);
13047        return;
13048    }
13049    ctxt->state = xmlAutomataGetInitState(ctxt->am);
13050    /*
13051    * Build the automaton.
13052    */
13053    xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13054    xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13055    type->contModel = xmlAutomataCompile(ctxt->am);
13056    if (type->contModel == NULL) {
13057        xmlSchemaPCustomErr(ctxt,
13058	    XML_SCHEMAP_INTERNAL,
13059	    WXS_BASIC_CAST type, type->node,
13060	    "Failed to compile the content model", NULL);
13061    } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13062        xmlSchemaPCustomErr(ctxt,
13063	    XML_SCHEMAP_NOT_DETERMINISTIC,
13064	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13065	    WXS_BASIC_CAST type, type->node,
13066	    "The content model is not determinist", NULL);
13067    } else {
13068#ifdef DEBUG_CONTENT_REGEXP
13069        xmlGenericError(xmlGenericErrorContext,
13070                        "Content model of %s:\n", type->name);
13071        xmlRegexpPrint(stderr, type->contModel);
13072#endif
13073    }
13074    ctxt->state = NULL;
13075    xmlFreeAutomata(ctxt->am);
13076    ctxt->am = NULL;
13077}
13078
13079/**
13080 * xmlSchemaResolveElementReferences:
13081 * @elem:  the schema element context
13082 * @ctxt:  the schema parser context
13083 *
13084 * Resolves the references of an element declaration
13085 * or particle, which has an element declaration as it's
13086 * term.
13087 */
13088static void
13089xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13090				  xmlSchemaParserCtxtPtr ctxt)
13091{
13092    if ((ctxt == NULL) || (elemDecl == NULL) ||
13093	((elemDecl != NULL) &&
13094	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13095        return;
13096    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13097
13098    if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13099	xmlSchemaTypePtr type;
13100
13101	/* (type definition) ... otherwise the type definition �resolved�
13102	* to by the �actual value� of the type [attribute] ...
13103	*/
13104	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13105	    elemDecl->namedTypeNs);
13106	if (type == NULL) {
13107	    xmlSchemaPResCompAttrErr(ctxt,
13108		XML_SCHEMAP_SRC_RESOLVE,
13109		WXS_BASIC_CAST elemDecl, elemDecl->node,
13110		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13111		XML_SCHEMA_TYPE_BASIC, "type definition");
13112	} else
13113	    elemDecl->subtypes = type;
13114    }
13115    if (elemDecl->substGroup != NULL) {
13116	xmlSchemaElementPtr substHead;
13117
13118	/*
13119	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13120	* substitutionGroup?
13121	*/
13122	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13123	    elemDecl->substGroupNs);
13124	if (substHead == NULL) {
13125	    xmlSchemaPResCompAttrErr(ctxt,
13126		XML_SCHEMAP_SRC_RESOLVE,
13127		WXS_BASIC_CAST elemDecl, NULL,
13128		"substitutionGroup", elemDecl->substGroup,
13129		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13130	} else {
13131	    xmlSchemaResolveElementReferences(substHead, ctxt);
13132	    /*
13133	    * Set the "substitution group affiliation".
13134	    * NOTE that now we use the "refDecl" field for this.
13135	    */
13136	    WXS_SUBST_HEAD(elemDecl) = substHead;
13137	    /*
13138	    * The type definitions is set to:
13139	    * SPEC "...the {type definition} of the element
13140	    * declaration �resolved� to by the �actual value�
13141	    * of the substitutionGroup [attribute], if present"
13142	    */
13143	    if (elemDecl->subtypes == NULL)
13144		elemDecl->subtypes = substHead->subtypes;
13145	}
13146    }
13147    /*
13148    * SPEC "The definition of anyType serves as the default type definition
13149    * for element declarations whose XML representation does not specify one."
13150    */
13151    if ((elemDecl->subtypes == NULL) &&
13152	(elemDecl->namedType == NULL) &&
13153	(elemDecl->substGroup == NULL))
13154	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13155}
13156
13157/**
13158 * xmlSchemaResolveUnionMemberTypes:
13159 * @ctxt:  the schema parser context
13160 * @type:  the schema simple type definition
13161 *
13162 * Checks and builds the "member type definitions" property of the union
13163 * simple type. This handles part (1), part (2) is done in
13164 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13165 *
13166 * Returns -1 in case of an internal error, 0 otherwise.
13167 */
13168static int
13169xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13170				 xmlSchemaTypePtr type)
13171{
13172
13173    xmlSchemaTypeLinkPtr link, lastLink, newLink;
13174    xmlSchemaTypePtr memberType;
13175
13176    /*
13177    * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13178    * define the explicit members as the type definitions �resolved�
13179    * to by the items in the �actual value� of the memberTypes [attribute],
13180    * if any, followed by the type definitions corresponding to the
13181    * <simpleType>s among the [children] of <union>, if any."
13182    */
13183    /*
13184    * Resolve references.
13185    */
13186    link = type->memberTypes;
13187    lastLink = NULL;
13188    while (link != NULL) {
13189	const xmlChar *name, *nsName;
13190
13191	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13192	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13193
13194	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13195	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13196	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13197		WXS_BASIC_CAST type, type->node, "memberTypes",
13198		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13199	    /*
13200	    * Remove the member type link.
13201	    */
13202	    if (lastLink == NULL)
13203		type->memberTypes = link->next;
13204	    else
13205		lastLink->next = link->next;
13206	    newLink = link;
13207	    link = link->next;
13208	    xmlFree(newLink);
13209	} else {
13210	    link->type = memberType;
13211	    lastLink = link;
13212	    link = link->next;
13213	}
13214    }
13215    /*
13216    * Add local simple types,
13217    */
13218    memberType = type->subtypes;
13219    while (memberType != NULL) {
13220	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13221	if (link == NULL) {
13222	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13223	    return (-1);
13224	}
13225	link->type = memberType;
13226	link->next = NULL;
13227	if (lastLink == NULL)
13228	    type->memberTypes = link;
13229	else
13230	    lastLink->next = link;
13231	lastLink = link;
13232	memberType = memberType->next;
13233    }
13234    return (0);
13235}
13236
13237/**
13238 * xmlSchemaIsDerivedFromBuiltInType:
13239 * @ctxt:  the schema parser context
13240 * @type:  the type definition
13241 * @valType: the value type
13242 *
13243 *
13244 * Returns 1 if the type has the given value type, or
13245 * is derived from such a type.
13246 */
13247static int
13248xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13249{
13250    if (type == NULL)
13251	return (0);
13252    if (WXS_IS_COMPLEX(type))
13253	return (0);
13254    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13255	if (type->builtInType == valType)
13256	    return(1);
13257	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13258	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13259	    return (0);
13260	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13261    }
13262    return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13263}
13264
13265#if 0
13266/**
13267 * xmlSchemaIsDerivedFromBuiltInType:
13268 * @ctxt:  the schema parser context
13269 * @type:  the type definition
13270 * @valType: the value type
13271 *
13272 *
13273 * Returns 1 if the type has the given value type, or
13274 * is derived from such a type.
13275 */
13276static int
13277xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13278{
13279    if (type == NULL)
13280	return (0);
13281    if (WXS_IS_COMPLEX(type))
13282	return (0);
13283    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13284	if (type->builtInType == valType)
13285	    return(1);
13286	return (0);
13287    } else
13288	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13289
13290    return (0);
13291}
13292#endif
13293
13294static xmlSchemaTypePtr
13295xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13296{
13297    if (type == NULL)
13298	return (NULL);
13299    if (WXS_IS_COMPLEX(type))
13300	return (NULL);
13301    if (type->type == XML_SCHEMA_TYPE_BASIC)
13302	return(type);
13303    return(xmlSchemaQueryBuiltInType(type->subtypes));
13304}
13305
13306/**
13307 * xmlSchemaGetPrimitiveType:
13308 * @type:  the simpleType definition
13309 *
13310 * Returns the primitive type of the given type or
13311 * NULL in case of error.
13312 */
13313static xmlSchemaTypePtr
13314xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13315{
13316
13317    while (type != NULL) {
13318	/*
13319	* Note that anySimpleType is actually not a primitive type
13320	* but we need that here.
13321	*/
13322	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13323	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13324	    return (type);
13325	type = type->baseType;
13326    }
13327
13328    return (NULL);
13329}
13330
13331#if 0
13332/**
13333 * xmlSchemaGetBuiltInTypeAncestor:
13334 * @type:  the simpleType definition
13335 *
13336 * Returns the primitive type of the given type or
13337 * NULL in case of error.
13338 */
13339static xmlSchemaTypePtr
13340xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13341{
13342    if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13343	return (0);
13344    while (type != NULL) {
13345	if (type->type == XML_SCHEMA_TYPE_BASIC)
13346	    return (type);
13347	type = type->baseType;
13348    }
13349
13350    return (NULL);
13351}
13352#endif
13353
13354/**
13355 * xmlSchemaCloneWildcardNsConstraints:
13356 * @ctxt:  the schema parser context
13357 * @dest:  the destination wildcard
13358 * @source: the source wildcard
13359 *
13360 * Clones the namespace constraints of source
13361 * and assignes them to dest.
13362 * Returns -1 on internal error, 0 otherwise.
13363 */
13364static int
13365xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13366				    xmlSchemaWildcardPtr dest,
13367				    xmlSchemaWildcardPtr source)
13368{
13369    xmlSchemaWildcardNsPtr cur, tmp, last;
13370
13371    if ((source == NULL) || (dest == NULL))
13372	return(-1);
13373    dest->any = source->any;
13374    cur = source->nsSet;
13375    last = NULL;
13376    while (cur != NULL) {
13377	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13378	if (tmp == NULL)
13379	    return(-1);
13380	tmp->value = cur->value;
13381	if (last == NULL)
13382	    dest->nsSet = tmp;
13383	else
13384	    last->next = tmp;
13385	last = tmp;
13386	cur = cur->next;
13387    }
13388    if (dest->negNsSet != NULL)
13389	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13390    if (source->negNsSet != NULL) {
13391	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13392	if (dest->negNsSet == NULL)
13393	    return(-1);
13394	dest->negNsSet->value = source->negNsSet->value;
13395    } else
13396	dest->negNsSet = NULL;
13397    return(0);
13398}
13399
13400/**
13401 * xmlSchemaUnionWildcards:
13402 * @ctxt:  the schema parser context
13403 * @completeWild:  the first wildcard
13404 * @curWild: the second wildcard
13405 *
13406 * Unions the namespace constraints of the given wildcards.
13407 * @completeWild will hold the resulting union.
13408 * Returns a positive error code on failure, -1 in case of an
13409 * internal error, 0 otherwise.
13410 */
13411static int
13412xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13413			    xmlSchemaWildcardPtr completeWild,
13414			    xmlSchemaWildcardPtr curWild)
13415{
13416    xmlSchemaWildcardNsPtr cur, curB, tmp;
13417
13418    /*
13419    * 1 If O1 and O2 are the same value, then that value must be the
13420    * value.
13421    */
13422    if ((completeWild->any == curWild->any) &&
13423	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13424	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13425
13426	if ((completeWild->negNsSet == NULL) ||
13427	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13428
13429	    if (completeWild->nsSet != NULL) {
13430		int found = 0;
13431
13432		/*
13433		* Check equality of sets.
13434		*/
13435		cur = completeWild->nsSet;
13436		while (cur != NULL) {
13437		    found = 0;
13438		    curB = curWild->nsSet;
13439		    while (curB != NULL) {
13440			if (cur->value == curB->value) {
13441			    found = 1;
13442			    break;
13443			}
13444			curB = curB->next;
13445		    }
13446		    if (!found)
13447			break;
13448		    cur = cur->next;
13449		}
13450		if (found)
13451		    return(0);
13452	    } else
13453		return(0);
13454	}
13455    }
13456    /*
13457    * 2 If either O1 or O2 is any, then any must be the value
13458    */
13459    if (completeWild->any != curWild->any) {
13460	if (completeWild->any == 0) {
13461	    completeWild->any = 1;
13462	    if (completeWild->nsSet != NULL) {
13463		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13464		completeWild->nsSet = NULL;
13465	    }
13466	    if (completeWild->negNsSet != NULL) {
13467		xmlFree(completeWild->negNsSet);
13468		completeWild->negNsSet = NULL;
13469	    }
13470	}
13471	return (0);
13472    }
13473    /*
13474    * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13475    * then the union of those sets must be the value.
13476    */
13477    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13478	int found;
13479	xmlSchemaWildcardNsPtr start;
13480
13481	cur = curWild->nsSet;
13482	start = completeWild->nsSet;
13483	while (cur != NULL) {
13484	    found = 0;
13485	    curB = start;
13486	    while (curB != NULL) {
13487		if (cur->value == curB->value) {
13488		    found = 1;
13489		    break;
13490		}
13491		curB = curB->next;
13492	    }
13493	    if (!found) {
13494		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13495		if (tmp == NULL)
13496		    return (-1);
13497		tmp->value = cur->value;
13498		tmp->next = completeWild->nsSet;
13499		completeWild->nsSet = tmp;
13500	    }
13501	    cur = cur->next;
13502	}
13503
13504	return(0);
13505    }
13506    /*
13507    * 4 If the two are negations of different values (namespace names
13508    * or �absent�), then a pair of not and �absent� must be the value.
13509    */
13510    if ((completeWild->negNsSet != NULL) &&
13511	(curWild->negNsSet != NULL) &&
13512	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13513	completeWild->negNsSet->value = NULL;
13514
13515	return(0);
13516    }
13517    /*
13518     * 5.
13519     */
13520    if (((completeWild->negNsSet != NULL) &&
13521	(completeWild->negNsSet->value != NULL) &&
13522	(curWild->nsSet != NULL)) ||
13523	((curWild->negNsSet != NULL) &&
13524	(curWild->negNsSet->value != NULL) &&
13525	(completeWild->nsSet != NULL))) {
13526
13527	int nsFound, absentFound = 0;
13528
13529	if (completeWild->nsSet != NULL) {
13530	    cur = completeWild->nsSet;
13531	    curB = curWild->negNsSet;
13532	} else {
13533	    cur = curWild->nsSet;
13534	    curB = completeWild->negNsSet;
13535	}
13536	nsFound = 0;
13537	while (cur != NULL) {
13538	    if (cur->value == NULL)
13539		absentFound = 1;
13540	    else if (cur->value == curB->value)
13541		nsFound = 1;
13542	    if (nsFound && absentFound)
13543		break;
13544	    cur = cur->next;
13545	}
13546
13547	if (nsFound && absentFound) {
13548	    /*
13549	    * 5.1 If the set S includes both the negated namespace
13550	    * name and �absent�, then any must be the value.
13551	    */
13552	    completeWild->any = 1;
13553	    if (completeWild->nsSet != NULL) {
13554		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13555		completeWild->nsSet = NULL;
13556	    }
13557	    if (completeWild->negNsSet != NULL) {
13558		xmlFree(completeWild->negNsSet);
13559		completeWild->negNsSet = NULL;
13560	    }
13561	} else if (nsFound && (!absentFound)) {
13562	    /*
13563	    * 5.2 If the set S includes the negated namespace name
13564	    * but not �absent�, then a pair of not and �absent� must
13565	    * be the value.
13566	    */
13567	    if (completeWild->nsSet != NULL) {
13568		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13569		completeWild->nsSet = NULL;
13570	    }
13571	    if (completeWild->negNsSet == NULL) {
13572		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13573		if (completeWild->negNsSet == NULL)
13574		    return (-1);
13575	    }
13576	    completeWild->negNsSet->value = NULL;
13577	} else if ((!nsFound) && absentFound) {
13578	    /*
13579	    * 5.3 If the set S includes �absent� but not the negated
13580	    * namespace name, then the union is not expressible.
13581	    */
13582	    xmlSchemaPErr(ctxt, completeWild->node,
13583		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13584		"The union of the wilcard is not expressible.\n",
13585		NULL, NULL);
13586	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13587	} else if ((!nsFound) && (!absentFound)) {
13588	    /*
13589	    * 5.4 If the set S does not include either the negated namespace
13590	    * name or �absent�, then whichever of O1 or O2 is a pair of not
13591	    * and a namespace name must be the value.
13592	    */
13593	    if (completeWild->negNsSet == NULL) {
13594		if (completeWild->nsSet != NULL) {
13595		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13596		    completeWild->nsSet = NULL;
13597		}
13598		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13599		if (completeWild->negNsSet == NULL)
13600		    return (-1);
13601		completeWild->negNsSet->value = curWild->negNsSet->value;
13602	    }
13603	}
13604	return (0);
13605    }
13606    /*
13607     * 6.
13608     */
13609    if (((completeWild->negNsSet != NULL) &&
13610	(completeWild->negNsSet->value == NULL) &&
13611	(curWild->nsSet != NULL)) ||
13612	((curWild->negNsSet != NULL) &&
13613	(curWild->negNsSet->value == NULL) &&
13614	(completeWild->nsSet != NULL))) {
13615
13616	if (completeWild->nsSet != NULL) {
13617	    cur = completeWild->nsSet;
13618	} else {
13619	    cur = curWild->nsSet;
13620	}
13621	while (cur != NULL) {
13622	    if (cur->value == NULL) {
13623		/*
13624		* 6.1 If the set S includes �absent�, then any must be the
13625		* value.
13626		*/
13627		completeWild->any = 1;
13628		if (completeWild->nsSet != NULL) {
13629		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13630		    completeWild->nsSet = NULL;
13631		}
13632		if (completeWild->negNsSet != NULL) {
13633		    xmlFree(completeWild->negNsSet);
13634		    completeWild->negNsSet = NULL;
13635		}
13636		return (0);
13637	    }
13638	    cur = cur->next;
13639	}
13640	if (completeWild->negNsSet == NULL) {
13641	    /*
13642	    * 6.2 If the set S does not include �absent�, then a pair of not
13643	    * and �absent� must be the value.
13644	    */
13645	    if (completeWild->nsSet != NULL) {
13646		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13647		completeWild->nsSet = NULL;
13648	    }
13649	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13650	    if (completeWild->negNsSet == NULL)
13651		return (-1);
13652	    completeWild->negNsSet->value = NULL;
13653	}
13654	return (0);
13655    }
13656    return (0);
13657
13658}
13659
13660/**
13661 * xmlSchemaIntersectWildcards:
13662 * @ctxt:  the schema parser context
13663 * @completeWild:  the first wildcard
13664 * @curWild: the second wildcard
13665 *
13666 * Intersects the namespace constraints of the given wildcards.
13667 * @completeWild will hold the resulting intersection.
13668 * Returns a positive error code on failure, -1 in case of an
13669 * internal error, 0 otherwise.
13670 */
13671static int
13672xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13673			    xmlSchemaWildcardPtr completeWild,
13674			    xmlSchemaWildcardPtr curWild)
13675{
13676    xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13677
13678    /*
13679    * 1 If O1 and O2 are the same value, then that value must be the
13680    * value.
13681    */
13682    if ((completeWild->any == curWild->any) &&
13683	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13684	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13685
13686	if ((completeWild->negNsSet == NULL) ||
13687	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13688
13689	    if (completeWild->nsSet != NULL) {
13690		int found = 0;
13691
13692		/*
13693		* Check equality of sets.
13694		*/
13695		cur = completeWild->nsSet;
13696		while (cur != NULL) {
13697		    found = 0;
13698		    curB = curWild->nsSet;
13699		    while (curB != NULL) {
13700			if (cur->value == curB->value) {
13701			    found = 1;
13702			    break;
13703			}
13704			curB = curB->next;
13705		    }
13706		    if (!found)
13707			break;
13708		    cur = cur->next;
13709		}
13710		if (found)
13711		    return(0);
13712	    } else
13713		return(0);
13714	}
13715    }
13716    /*
13717    * 2 If either O1 or O2 is any, then the other must be the value.
13718    */
13719    if ((completeWild->any != curWild->any) && (completeWild->any)) {
13720	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13721	    return(-1);
13722	return(0);
13723    }
13724    /*
13725    * 3 If either O1 or O2 is a pair of not and a value (a namespace
13726    * name or �absent�) and the other is a set of (namespace names or
13727    * �absent�), then that set, minus the negated value if it was in
13728    * the set, minus �absent� if it was in the set, must be the value.
13729    */
13730    if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13731	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13732	const xmlChar *neg;
13733
13734	if (completeWild->nsSet == NULL) {
13735	    neg = completeWild->negNsSet->value;
13736	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13737		return(-1);
13738	} else
13739	    neg = curWild->negNsSet->value;
13740	/*
13741	* Remove absent and negated.
13742	*/
13743	prev = NULL;
13744	cur = completeWild->nsSet;
13745	while (cur != NULL) {
13746	    if (cur->value == NULL) {
13747		if (prev == NULL)
13748		    completeWild->nsSet = cur->next;
13749		else
13750		    prev->next = cur->next;
13751		xmlFree(cur);
13752		break;
13753	    }
13754	    prev = cur;
13755	    cur = cur->next;
13756	}
13757	if (neg != NULL) {
13758	    prev = NULL;
13759	    cur = completeWild->nsSet;
13760	    while (cur != NULL) {
13761		if (cur->value == neg) {
13762		    if (prev == NULL)
13763			completeWild->nsSet = cur->next;
13764		    else
13765			prev->next = cur->next;
13766		    xmlFree(cur);
13767		    break;
13768		}
13769		prev = cur;
13770		cur = cur->next;
13771	    }
13772	}
13773
13774	return(0);
13775    }
13776    /*
13777    * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13778    * then the intersection of those sets must be the value.
13779    */
13780    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13781	int found;
13782
13783	cur = completeWild->nsSet;
13784	prev = NULL;
13785	while (cur != NULL) {
13786	    found = 0;
13787	    curB = curWild->nsSet;
13788	    while (curB != NULL) {
13789		if (cur->value == curB->value) {
13790		    found = 1;
13791		    break;
13792		}
13793		curB = curB->next;
13794	    }
13795	    if (!found) {
13796		if (prev == NULL)
13797		    completeWild->nsSet = cur->next;
13798		else
13799		    prev->next = cur->next;
13800		tmp = cur->next;
13801		xmlFree(cur);
13802		cur = tmp;
13803		continue;
13804	    }
13805	    prev = cur;
13806	    cur = cur->next;
13807	}
13808
13809	return(0);
13810    }
13811    /* 5 If the two are negations of different namespace names,
13812    * then the intersection is not expressible
13813    */
13814    if ((completeWild->negNsSet != NULL) &&
13815	(curWild->negNsSet != NULL) &&
13816	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13817	(completeWild->negNsSet->value != NULL) &&
13818	(curWild->negNsSet->value != NULL)) {
13819
13820	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13821	    "The intersection of the wilcard is not expressible.\n",
13822	    NULL, NULL);
13823	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13824    }
13825    /*
13826    * 6 If the one is a negation of a namespace name and the other
13827    * is a negation of �absent�, then the one which is the negation
13828    * of a namespace name must be the value.
13829    */
13830    if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13831	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13832	(completeWild->negNsSet->value == NULL)) {
13833	completeWild->negNsSet->value =  curWild->negNsSet->value;
13834    }
13835    return(0);
13836}
13837
13838/**
13839 * xmlSchemaIsWildcardNsConstraintSubset:
13840 * @ctxt:  the schema parser context
13841 * @sub:  the first wildcard
13842 * @super: the second wildcard
13843 *
13844 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13845 *
13846 * Returns 0 if the namespace constraint of @sub is an intensional
13847 * subset of @super, 1 otherwise.
13848 */
13849static int
13850xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13851			  xmlSchemaWildcardPtr super)
13852{
13853    /*
13854    * 1 super must be any.
13855    */
13856    if (super->any)
13857	return (0);
13858    /*
13859    * 2.1 sub must be a pair of not and a namespace name or �absent�.
13860    * 2.2 super must be a pair of not and the same value.
13861    */
13862    if ((sub->negNsSet != NULL) &&
13863	(super->negNsSet != NULL) &&
13864	(sub->negNsSet->value == sub->negNsSet->value))
13865	return (0);
13866    /*
13867    * 3.1 sub must be a set whose members are either namespace names or �absent�.
13868    */
13869    if (sub->nsSet != NULL) {
13870	/*
13871	* 3.2.1 super must be the same set or a superset thereof.
13872	*/
13873	if (super->nsSet != NULL) {
13874	    xmlSchemaWildcardNsPtr cur, curB;
13875	    int found = 0;
13876
13877	    cur = sub->nsSet;
13878	    while (cur != NULL) {
13879		found = 0;
13880		curB = super->nsSet;
13881		while (curB != NULL) {
13882		    if (cur->value == curB->value) {
13883			found = 1;
13884			break;
13885		    }
13886		    curB = curB->next;
13887		}
13888		if (!found)
13889		    return (1);
13890		cur = cur->next;
13891	    }
13892	    if (found)
13893		return (0);
13894	} else if (super->negNsSet != NULL) {
13895	    xmlSchemaWildcardNsPtr cur;
13896	    /*
13897	    * 3.2.2 super must be a pair of not and a namespace name or
13898	    * �absent� and that value must not be in sub's set.
13899	    */
13900	    cur = sub->nsSet;
13901	    while (cur != NULL) {
13902		if (cur->value == super->negNsSet->value)
13903		    return (1);
13904		cur = cur->next;
13905	    }
13906	    return (0);
13907	}
13908    }
13909    return (1);
13910}
13911
13912static int
13913xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13914				     int *fixed,
13915				     const xmlChar **value,
13916				     xmlSchemaValPtr *val)
13917{
13918    *fixed = 0;
13919    *value = NULL;
13920    if (val != 0)
13921	*val = NULL;
13922
13923    if (attruse->defValue != NULL) {
13924	*value = attruse->defValue;
13925	if (val != NULL)
13926	    *val = attruse->defVal;
13927	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
13928	    *fixed = 1;
13929	return(1);
13930    } else if ((attruse->attrDecl != NULL) &&
13931	(attruse->attrDecl->defValue != NULL)) {
13932	*value = attruse->attrDecl->defValue;
13933	if (val != NULL)
13934	    *val = attruse->attrDecl->defVal;
13935	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
13936	    *fixed = 1;
13937	return(1);
13938    }
13939    return(0);
13940}
13941/**
13942 * xmlSchemaCheckCVCWildcardNamespace:
13943 * @wild:  the wildcard
13944 * @ns:  the namespace
13945 *
13946 * Validation Rule: Wildcard allows Namespace Name
13947 * (cvc-wildcard-namespace)
13948 *
13949 * Returns 0 if the given namespace matches the wildcard,
13950 * 1 otherwise and -1 on API errors.
13951 */
13952static int
13953xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13954				   const xmlChar* ns)
13955{
13956    if (wild == NULL)
13957	return(-1);
13958
13959    if (wild->any)
13960	return(0);
13961    else if (wild->nsSet != NULL) {
13962	xmlSchemaWildcardNsPtr cur;
13963
13964	cur = wild->nsSet;
13965	while (cur != NULL) {
13966	    if (xmlStrEqual(cur->value, ns))
13967		return(0);
13968	    cur = cur->next;
13969	}
13970    } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
13971	(!xmlStrEqual(wild->negNsSet->value, ns)))
13972	return(0);
13973
13974    return(1);
13975}
13976
13977#define XML_SCHEMA_ACTION_DERIVE 0
13978#define XML_SCHEMA_ACTION_REDEFINE 1
13979
13980#define WXS_ACTION_STR(a) \
13981((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13982
13983/*
13984* Schema Component Constraint:
13985*   Derivation Valid (Restriction, Complex)
13986*   derivation-ok-restriction (2) - (4)
13987*
13988* ATTENTION:
13989* In XML Schema 1.1 this will be:
13990* Validation Rule:
13991*     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
13992*
13993*/
13994static int
13995xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
13996				       int action,
13997				       xmlSchemaBasicItemPtr item,
13998				       xmlSchemaBasicItemPtr baseItem,
13999				       xmlSchemaItemListPtr uses,
14000				       xmlSchemaItemListPtr baseUses,
14001				       xmlSchemaWildcardPtr wild,
14002				       xmlSchemaWildcardPtr baseWild)
14003{
14004    xmlSchemaAttributeUsePtr cur = NULL, bcur;
14005    int i, j, found; /* err = 0; */
14006    const xmlChar *bEffValue;
14007    int effFixed;
14008
14009    if (uses != NULL) {
14010	for (i = 0; i < uses->nbItems; i++) {
14011	    cur = uses->items[i];
14012	    found = 0;
14013	    if (baseUses == NULL)
14014		goto not_found;
14015	    for (j = 0; j < baseUses->nbItems; j++) {
14016		bcur = baseUses->items[j];
14017		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14018			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14019		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14020			WXS_ATTRUSE_DECL_TNS(bcur)))
14021		{
14022		    /*
14023		    * (2.1) "If there is an attribute use in the {attribute
14024		    * uses} of the {base type definition} (call this B) whose
14025		    * {attribute declaration} has the same {name} and {target
14026		    * namespace}, then  all of the following must be true:"
14027		    */
14028		    found = 1;
14029
14030		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14031			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14032		    {
14033			xmlChar *str = NULL;
14034			/*
14035			* (2.1.1) "one of the following must be true:"
14036			* (2.1.1.1) "B's {required} is false."
14037			* (2.1.1.2) "R's {required} is true."
14038			*/
14039			xmlSchemaPAttrUseErr4(pctxt,
14040			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14041			    WXS_ITEM_NODE(item), item, cur,
14042			    "The 'optional' attribute use is inconsistent "
14043			    "with the corresponding 'required' attribute use of "
14044			    "the %s %s",
14045			    WXS_ACTION_STR(action),
14046			    xmlSchemaGetComponentDesignation(&str, baseItem),
14047			    NULL, NULL);
14048			FREE_AND_NULL(str);
14049			/* err = pctxt->err; */
14050		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14051			WXS_ATTRUSE_TYPEDEF(cur),
14052			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14053		    {
14054			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14055
14056			/*
14057			* SPEC (2.1.2) "R's {attribute declaration}'s
14058			* {type definition} must be validly derived from
14059			* B's {type definition} given the empty set as
14060			* defined in Type Derivation OK (Simple) (�3.14.6)."
14061			*/
14062			xmlSchemaPAttrUseErr4(pctxt,
14063			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14064			    WXS_ITEM_NODE(item), item, cur,
14065			    "The attribute declaration's %s "
14066			    "is not validly derived from "
14067			    "the corresponding %s of the "
14068			    "attribute declaration in the %s %s",
14069			    xmlSchemaGetComponentDesignation(&strA,
14070				WXS_ATTRUSE_TYPEDEF(cur)),
14071			    xmlSchemaGetComponentDesignation(&strB,
14072				WXS_ATTRUSE_TYPEDEF(bcur)),
14073			    WXS_ACTION_STR(action),
14074			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14075			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14076			FREE_AND_NULL(strA);
14077			FREE_AND_NULL(strB);
14078			FREE_AND_NULL(strC);
14079			/* err = pctxt->err; */
14080		    } else {
14081			/*
14082			* 2.1.3 [Definition:]  Let the effective value
14083			* constraint of an attribute use be its {value
14084			* constraint}, if present, otherwise its {attribute
14085			* declaration}'s {value constraint} .
14086			*/
14087			xmlSchemaGetEffectiveValueConstraint(bcur,
14088			    &effFixed, &bEffValue, NULL);
14089			/*
14090			* 2.1.3 ... one of the following must be true
14091			*
14092			* 2.1.3.1 B's �effective value constraint� is
14093			* �absent� or default.
14094			*/
14095			if ((bEffValue != NULL) &&
14096			    (effFixed == 1)) {
14097			    const xmlChar *rEffValue = NULL;
14098
14099			    xmlSchemaGetEffectiveValueConstraint(bcur,
14100				&effFixed, &rEffValue, NULL);
14101			    /*
14102			    * 2.1.3.2 R's �effective value constraint� is
14103			    * fixed with the same string as B's.
14104			    * MAYBE TODO: Compare the computed values.
14105			    *       Hmm, it says "same string" so
14106			    *       string-equality might really be sufficient.
14107			    */
14108			    if ((effFixed == 0) ||
14109				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14110			    {
14111				xmlChar *str = NULL;
14112
14113				xmlSchemaPAttrUseErr4(pctxt,
14114				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14115				    WXS_ITEM_NODE(item), item, cur,
14116				    "The effective value constraint of the "
14117				    "attribute use is inconsistent with "
14118				    "its correspondent in the %s %s",
14119				    WXS_ACTION_STR(action),
14120				    xmlSchemaGetComponentDesignation(&str,
14121					baseItem),
14122				    NULL, NULL);
14123				FREE_AND_NULL(str);
14124				/* err = pctxt->err; */
14125			    }
14126			}
14127		    }
14128		    break;
14129		}
14130	    }
14131not_found:
14132	    if (!found) {
14133		/*
14134		* (2.2) "otherwise the {base type definition} must have an
14135		* {attribute wildcard} and the {target namespace} of the
14136		* R's {attribute declaration} must be �valid� with respect
14137		* to that wildcard, as defined in Wildcard allows Namespace
14138		* Name (�3.10.4)."
14139		*/
14140		if ((baseWild == NULL) ||
14141		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14142		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14143		{
14144		    xmlChar *str = NULL;
14145
14146		    xmlSchemaPAttrUseErr4(pctxt,
14147			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14148			WXS_ITEM_NODE(item), item, cur,
14149			"Neither a matching attribute use, "
14150			"nor a matching wildcard exists in the %s %s",
14151			WXS_ACTION_STR(action),
14152			xmlSchemaGetComponentDesignation(&str, baseItem),
14153			NULL, NULL);
14154		    FREE_AND_NULL(str);
14155		    /* err = pctxt->err; */
14156		}
14157	    }
14158	}
14159    }
14160    /*
14161    * SPEC derivation-ok-restriction (3):
14162    * (3) "For each attribute use in the {attribute uses} of the {base type
14163    * definition} whose {required} is true, there must be an attribute
14164    * use with an {attribute declaration} with the same {name} and
14165    * {target namespace} as its {attribute declaration} in the {attribute
14166    * uses} of the complex type definition itself whose {required} is true.
14167    */
14168    if (baseUses != NULL) {
14169	for (j = 0; j < baseUses->nbItems; j++) {
14170	    bcur = baseUses->items[j];
14171	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14172		continue;
14173	    found = 0;
14174	    if (uses != NULL) {
14175		for (i = 0; i < uses->nbItems; i++) {
14176		    cur = uses->items[i];
14177		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14178			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14179			(WXS_ATTRUSE_DECL_TNS(cur) ==
14180			WXS_ATTRUSE_DECL_TNS(bcur))) {
14181			found = 1;
14182			break;
14183		    }
14184		}
14185	    }
14186	    if (!found) {
14187		xmlChar *strA = NULL, *strB = NULL;
14188
14189		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14190		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14191		    NULL, item,
14192		    "A matching attribute use for the "
14193		    "'required' %s of the %s %s is missing",
14194		    xmlSchemaGetComponentDesignation(&strA, bcur),
14195		    WXS_ACTION_STR(action),
14196		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14197		    NULL);
14198		FREE_AND_NULL(strA);
14199		FREE_AND_NULL(strB);
14200	    }
14201	}
14202    }
14203    /*
14204    * derivation-ok-restriction (4)
14205    */
14206    if (wild != NULL) {
14207	/*
14208	* (4) "If there is an {attribute wildcard}, all of the
14209	* following must be true:"
14210	*/
14211	if (baseWild == NULL) {
14212	    xmlChar *str = NULL;
14213
14214	    /*
14215	    * (4.1) "The {base type definition} must also have one."
14216	    */
14217	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14218		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14219		NULL, item,
14220		"The %s has an attribute wildcard, "
14221		"but the %s %s '%s' does not have one",
14222		WXS_ITEM_TYPE_NAME(item),
14223		WXS_ACTION_STR(action),
14224		WXS_ITEM_TYPE_NAME(baseItem),
14225		xmlSchemaGetComponentQName(&str, baseItem));
14226	    FREE_AND_NULL(str);
14227	    return(pctxt->err);
14228	} else if ((baseWild->any == 0) &&
14229		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14230	{
14231	    xmlChar *str = NULL;
14232	    /*
14233	    * (4.2) "The complex type definition's {attribute wildcard}'s
14234	    * {namespace constraint} must be a subset of the {base type
14235	    * definition}'s {attribute wildcard}'s {namespace constraint},
14236	    * as defined by Wildcard Subset (�3.10.6)."
14237	    */
14238	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14239		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14240		NULL, item,
14241		"The attribute wildcard is not a valid "
14242		"subset of the wildcard in the %s %s '%s'",
14243		WXS_ACTION_STR(action),
14244		WXS_ITEM_TYPE_NAME(baseItem),
14245		xmlSchemaGetComponentQName(&str, baseItem),
14246		NULL);
14247	    FREE_AND_NULL(str);
14248	    return(pctxt->err);
14249	}
14250	/* 4.3 Unless the {base type definition} is the �ur-type
14251	* definition�, the complex type definition's {attribute
14252	* wildcard}'s {process contents} must be identical to or
14253	* stronger than the {base type definition}'s {attribute
14254	* wildcard}'s {process contents}, where strict is stronger
14255	* than lax is stronger than skip.
14256	*/
14257	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14258	    (wild->processContents < baseWild->processContents)) {
14259	    xmlChar *str = NULL;
14260	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14261		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14262		NULL, baseItem,
14263		"The {process contents} of the attribute wildcard is "
14264		"weaker than the one in the %s %s '%s'",
14265		WXS_ACTION_STR(action),
14266		WXS_ITEM_TYPE_NAME(baseItem),
14267		xmlSchemaGetComponentQName(&str, baseItem),
14268		NULL);
14269	    FREE_AND_NULL(str)
14270		return(pctxt->err);
14271	}
14272    }
14273    return(0);
14274}
14275
14276
14277static int
14278xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14279				  xmlSchemaBasicItemPtr item,
14280				  xmlSchemaWildcardPtr *completeWild,
14281				  xmlSchemaItemListPtr list,
14282				  xmlSchemaItemListPtr prohibs);
14283/**
14284 * xmlSchemaFixupTypeAttributeUses:
14285 * @ctxt:  the schema parser context
14286 * @type:  the complex type definition
14287 *
14288 *
14289 * Builds the wildcard and the attribute uses on the given complex type.
14290 * Returns -1 if an internal error occurs, 0 otherwise.
14291 *
14292 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14293 * strings, so recheck this if we start to hardcode some schemata, since
14294 * they might not be in the same dict.
14295 * NOTE: It is allowed to "extend" the xs:anyType type.
14296 */
14297static int
14298xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14299				  xmlSchemaTypePtr type)
14300{
14301    xmlSchemaTypePtr baseType = NULL;
14302    xmlSchemaAttributeUsePtr use;
14303    xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14304
14305    if (type->baseType == NULL) {
14306	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14307	    "no base type");
14308        return (-1);
14309    }
14310    baseType = type->baseType;
14311    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14312	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14313	    return(-1);
14314
14315    uses = type->attrUses;
14316    baseUses = baseType->attrUses;
14317    /*
14318    * Expand attribute group references. And build the 'complete'
14319    * wildcard, i.e. intersect multiple wildcards.
14320    * Move attribute prohibitions into a separate list.
14321    */
14322    if (uses != NULL) {
14323	if (WXS_IS_RESTRICTION(type)) {
14324	    /*
14325	    * This one will transfer all attr. prohibitions
14326	    * into pctxt->attrProhibs.
14327	    */
14328	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14329		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14330		pctxt->attrProhibs) == -1)
14331	    {
14332		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14333		"failed to expand attributes");
14334	    }
14335	    if (pctxt->attrProhibs->nbItems != 0)
14336		prohibs = pctxt->attrProhibs;
14337	} else {
14338	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14339		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14340		NULL) == -1)
14341	    {
14342		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14343		"failed to expand attributes");
14344	    }
14345	}
14346    }
14347    /*
14348    * Inherit the attribute uses of the base type.
14349    */
14350    if (baseUses != NULL) {
14351	int i, j;
14352	xmlSchemaAttributeUseProhibPtr pro;
14353
14354	if (WXS_IS_RESTRICTION(type)) {
14355	    int usesCount;
14356	    xmlSchemaAttributeUsePtr tmp;
14357
14358	    if (uses != NULL)
14359		usesCount = uses->nbItems;
14360	    else
14361		usesCount = 0;
14362
14363	    /* Restriction. */
14364	    for (i = 0; i < baseUses->nbItems; i++) {
14365		use = baseUses->items[i];
14366		if (prohibs) {
14367		    /*
14368		    * Filter out prohibited uses.
14369		    */
14370		    for (j = 0; j < prohibs->nbItems; j++) {
14371			pro = prohibs->items[j];
14372			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14373			    (WXS_ATTRUSE_DECL_TNS(use) ==
14374				pro->targetNamespace))
14375			{
14376			    goto inherit_next;
14377			}
14378		    }
14379		}
14380		if (usesCount) {
14381		    /*
14382		    * Filter out existing uses.
14383		    */
14384		    for (j = 0; j < usesCount; j++) {
14385			tmp = uses->items[j];
14386			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14387				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14388			    (WXS_ATTRUSE_DECL_TNS(use) ==
14389				WXS_ATTRUSE_DECL_TNS(tmp)))
14390			{
14391			    goto inherit_next;
14392			}
14393		    }
14394		}
14395		if (uses == NULL) {
14396		    type->attrUses = xmlSchemaItemListCreate();
14397		    if (type->attrUses == NULL)
14398			goto exit_failure;
14399		    uses = type->attrUses;
14400		}
14401		xmlSchemaItemListAddSize(uses, 2, use);
14402inherit_next: {}
14403	    }
14404	} else {
14405	    /* Extension. */
14406	    for (i = 0; i < baseUses->nbItems; i++) {
14407		use = baseUses->items[i];
14408		if (uses == NULL) {
14409		    type->attrUses = xmlSchemaItemListCreate();
14410		    if (type->attrUses == NULL)
14411			goto exit_failure;
14412		    uses = type->attrUses;
14413		}
14414		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14415	    }
14416	}
14417    }
14418    /*
14419    * Shrink attr. uses.
14420    */
14421    if (uses) {
14422	if (uses->nbItems == 0) {
14423	    xmlSchemaItemListFree(uses);
14424	    type->attrUses = NULL;
14425	}
14426	/*
14427	* TODO: We could shrink the size of the array
14428	* to fit the actual number of items.
14429	*/
14430    }
14431    /*
14432    * Compute the complete wildcard.
14433    */
14434    if (WXS_IS_EXTENSION(type)) {
14435	if (baseType->attributeWildcard != NULL) {
14436	    /*
14437	    * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14438	    * the appropriate case among the following:"
14439	    */
14440	    if (type->attributeWildcard != NULL) {
14441		/*
14442		* Union the complete wildcard with the base wildcard.
14443		* SPEC {attribute wildcard}
14444		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14445		* and {annotation} are those of the �complete wildcard�,
14446		* and whose {namespace constraint} is the intensional union
14447		* of the {namespace constraint} of the �complete wildcard�
14448		* and of the �base wildcard�, as defined in Attribute
14449		* Wildcard Union (�3.10.6)."
14450		*/
14451		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14452		    baseType->attributeWildcard) == -1)
14453		    goto exit_failure;
14454	    } else {
14455		/*
14456		* (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14457		* then the �base wildcard�."
14458		*/
14459		type->attributeWildcard = baseType->attributeWildcard;
14460	    }
14461	} else {
14462	    /*
14463	    * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14464	    * �complete wildcard"
14465	    * NOOP
14466	    */
14467	}
14468    } else {
14469	/*
14470	* SPEC {attribute wildcard}
14471	* (3.1) "If the <restriction> alternative is chosen, then the
14472	* �complete wildcard�;"
14473	* NOOP
14474	*/
14475    }
14476
14477    return (0);
14478
14479exit_failure:
14480    return(-1);
14481}
14482
14483/**
14484 * xmlSchemaTypeFinalContains:
14485 * @schema:  the schema
14486 * @type:  the type definition
14487 * @final: the final
14488 *
14489 * Evaluates if a type definition contains the given "final".
14490 * This does take "finalDefault" into account as well.
14491 *
14492 * Returns 1 if the type does containt the given "final",
14493 * 0 otherwise.
14494 */
14495static int
14496xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14497{
14498    if (type == NULL)
14499	return (0);
14500    if (type->flags & final)
14501	return (1);
14502    else
14503	return (0);
14504}
14505
14506/**
14507 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14508 * @type:  the Union Simple Type
14509 *
14510 * Returns a list of member types of @type if existing,
14511 * returns NULL otherwise.
14512 */
14513static xmlSchemaTypeLinkPtr
14514xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14515{
14516    while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14517	if (type->memberTypes != NULL)
14518	    return (type->memberTypes);
14519	else
14520	    type = type->baseType;
14521    }
14522    return (NULL);
14523}
14524
14525/**
14526 * xmlSchemaGetParticleTotalRangeMin:
14527 * @particle: the particle
14528 *
14529 * Schema Component Constraint: Effective Total Range
14530 * (all and sequence) + (choice)
14531 *
14532 * Returns the minimun Effective Total Range.
14533 */
14534static int
14535xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14536{
14537    if ((particle->children == NULL) ||
14538	(particle->minOccurs == 0))
14539	return (0);
14540    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14541	int min = -1, cur;
14542	xmlSchemaParticlePtr part =
14543	    (xmlSchemaParticlePtr) particle->children->children;
14544
14545	if (part == NULL)
14546	    return (0);
14547	while (part != NULL) {
14548	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14549		(part->children->type == XML_SCHEMA_TYPE_ANY))
14550		cur = part->minOccurs;
14551	    else
14552		cur = xmlSchemaGetParticleTotalRangeMin(part);
14553	    if (cur == 0)
14554		return (0);
14555	    if ((min > cur) || (min == -1))
14556		min = cur;
14557	    part = (xmlSchemaParticlePtr) part->next;
14558	}
14559	return (particle->minOccurs * min);
14560    } else {
14561	/* <all> and <sequence> */
14562	int sum = 0;
14563	xmlSchemaParticlePtr part =
14564	    (xmlSchemaParticlePtr) particle->children->children;
14565
14566	if (part == NULL)
14567	    return (0);
14568	do {
14569	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14570		(part->children->type == XML_SCHEMA_TYPE_ANY))
14571		sum += part->minOccurs;
14572	    else
14573		sum += xmlSchemaGetParticleTotalRangeMin(part);
14574	    part = (xmlSchemaParticlePtr) part->next;
14575	} while (part != NULL);
14576	return (particle->minOccurs * sum);
14577    }
14578}
14579
14580/**
14581 * xmlSchemaGetParticleTotalRangeMax:
14582 * @particle: the particle
14583 *
14584 * Schema Component Constraint: Effective Total Range
14585 * (all and sequence) + (choice)
14586 *
14587 * Returns the maximum Effective Total Range.
14588 */
14589static int
14590xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14591{
14592    if ((particle->children == NULL) ||
14593	(particle->children->children == NULL))
14594	return (0);
14595    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14596	int max = -1, cur;
14597	xmlSchemaParticlePtr part =
14598	    (xmlSchemaParticlePtr) particle->children->children;
14599
14600	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14601	    if (part->children == NULL)
14602		continue;
14603	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14604		(part->children->type == XML_SCHEMA_TYPE_ANY))
14605		cur = part->maxOccurs;
14606	    else
14607		cur = xmlSchemaGetParticleTotalRangeMax(part);
14608	    if (cur == UNBOUNDED)
14609		return (UNBOUNDED);
14610	    if ((max < cur) || (max == -1))
14611		max = cur;
14612	}
14613	/* TODO: Handle overflows? */
14614	return (particle->maxOccurs * max);
14615    } else {
14616	/* <all> and <sequence> */
14617	int sum = 0, cur;
14618	xmlSchemaParticlePtr part =
14619	    (xmlSchemaParticlePtr) particle->children->children;
14620
14621	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14622	    if (part->children == NULL)
14623		continue;
14624	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14625		(part->children->type == XML_SCHEMA_TYPE_ANY))
14626		cur = part->maxOccurs;
14627	    else
14628		cur = xmlSchemaGetParticleTotalRangeMax(part);
14629	    if (cur == UNBOUNDED)
14630		return (UNBOUNDED);
14631	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14632		return (UNBOUNDED);
14633	    sum += cur;
14634	}
14635	/* TODO: Handle overflows? */
14636	return (particle->maxOccurs * sum);
14637    }
14638}
14639
14640/**
14641 * xmlSchemaIsParticleEmptiable:
14642 * @particle: the particle
14643 *
14644 * Schema Component Constraint: Particle Emptiable
14645 * Checks whether the given particle is emptiable.
14646 *
14647 * Returns 1 if emptiable, 0 otherwise.
14648 */
14649static int
14650xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14651{
14652    /*
14653    * SPEC (1) "Its {min occurs} is 0."
14654    */
14655    if ((particle == NULL) || (particle->minOccurs == 0) ||
14656	(particle->children == NULL))
14657	return (1);
14658    /*
14659    * SPEC (2) "Its {term} is a group and the minimum part of the
14660    * effective total range of that group, [...] is 0."
14661    */
14662    if (WXS_IS_MODEL_GROUP(particle->children)) {
14663	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14664	    return (1);
14665    }
14666    return (0);
14667}
14668
14669/**
14670 * xmlSchemaCheckCOSSTDerivedOK:
14671 * @actxt: a context
14672 * @type:  the derived simple type definition
14673 * @baseType:  the base type definition
14674 * @subset: the subset of ('restriction', ect.)
14675 *
14676 * Schema Component Constraint:
14677 * Type Derivation OK (Simple) (cos-st-derived-OK)
14678 *
14679 * Checks wheter @type can be validly
14680 * derived from @baseType.
14681 *
14682 * Returns 0 on success, an positive error code otherwise.
14683 */
14684static int
14685xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14686			     xmlSchemaTypePtr type,
14687			     xmlSchemaTypePtr baseType,
14688			     int subset)
14689{
14690    /*
14691    * 1 They are the same type definition.
14692    * TODO: The identy check might have to be more complex than this.
14693    */
14694    if (type == baseType)
14695	return (0);
14696    /*
14697    * 2.1 restriction is not in the subset, or in the {final}
14698    * of its own {base type definition};
14699    *
14700    * NOTE that this will be used also via "xsi:type".
14701    *
14702    * TODO: Revise this, it looks strange. How can the "type"
14703    * not be fixed or *in* fixing?
14704    */
14705    if (WXS_IS_TYPE_NOT_FIXED(type))
14706	if (xmlSchemaTypeFixup(type, actxt) == -1)
14707	    return(-1);
14708    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14709	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14710	    return(-1);
14711    if ((subset & SUBSET_RESTRICTION) ||
14712	(xmlSchemaTypeFinalContains(type->baseType,
14713	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14714	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14715    }
14716    /* 2.2 */
14717    if (type->baseType == baseType) {
14718	/*
14719	* 2.2.1 D's �base type definition� is B.
14720	*/
14721	return (0);
14722    }
14723    /*
14724    * 2.2.2 D's �base type definition� is not the �ur-type definition�
14725    * and is validly derived from B given the subset, as defined by this
14726    * constraint.
14727    */
14728    if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14729	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14730	    baseType, subset) == 0)) {
14731	return (0);
14732    }
14733    /*
14734    * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14735    * definition�.
14736    */
14737    if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14738	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14739	return (0);
14740    }
14741    /*
14742    * 2.2.4 B's {variety} is union and D is validly derived from a type
14743    * definition in B's {member type definitions} given the subset, as
14744    * defined by this constraint.
14745    *
14746    * NOTE: This seems not to involve built-in types, since there is no
14747    * built-in Union Simple Type.
14748    */
14749    if (WXS_IS_UNION(baseType)) {
14750	xmlSchemaTypeLinkPtr cur;
14751
14752	cur = baseType->memberTypes;
14753	while (cur != NULL) {
14754	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14755		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14756		    return(-1);
14757	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14758		    type, cur->type, subset) == 0)
14759	    {
14760		/*
14761		* It just has to be validly derived from at least one
14762		* member-type.
14763		*/
14764		return (0);
14765	    }
14766	    cur = cur->next;
14767	}
14768    }
14769    return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14770}
14771
14772/**
14773 * xmlSchemaCheckTypeDefCircularInternal:
14774 * @pctxt:  the schema parser context
14775 * @ctxtType:  the type definition
14776 * @ancestor: an ancestor of @ctxtType
14777 *
14778 * Checks st-props-correct (2) + ct-props-correct (3).
14779 * Circular type definitions are not allowed.
14780 *
14781 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14782 * circular, 0 otherwise.
14783 */
14784static int
14785xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14786			   xmlSchemaTypePtr ctxtType,
14787			   xmlSchemaTypePtr ancestor)
14788{
14789    int ret;
14790
14791    if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14792	return (0);
14793
14794    if (ctxtType == ancestor) {
14795	xmlSchemaPCustomErr(pctxt,
14796	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14797	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14798	    "The definition is circular", NULL);
14799	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14800    }
14801    if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14802	/*
14803	* Avoid inifinite recursion on circular types not yet checked.
14804	*/
14805	return (0);
14806    }
14807    ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14808    ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14809	ancestor->baseType);
14810    ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14811    return (ret);
14812}
14813
14814/**
14815 * xmlSchemaCheckTypeDefCircular:
14816 * @item:  the complex/simple type definition
14817 * @ctxt:  the parser context
14818 * @name:  the name
14819 *
14820 * Checks for circular type definitions.
14821 */
14822static void
14823xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14824			      xmlSchemaParserCtxtPtr ctxt)
14825{
14826    if ((item == NULL) ||
14827	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14828	(item->baseType == NULL))
14829	return;
14830    xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14831	item->baseType);
14832}
14833
14834/*
14835* Simple Type Definition Representation OK (src-simple-type) 4
14836*
14837* "4 Circular union type definition is disallowed. That is, if the
14838* <union> alternative is chosen, there must not be any entries in the
14839* memberTypes [attribute] at any depth which resolve to the component
14840* corresponding to the <simpleType>."
14841*
14842* Note that this should work on the *representation* of a component,
14843* thus assumes any union types in the member types not being yet
14844* substituted. At this stage we need the variety of the types
14845* to be already computed.
14846*/
14847static int
14848xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14849					xmlSchemaTypePtr ctxType,
14850					xmlSchemaTypeLinkPtr members)
14851{
14852    xmlSchemaTypeLinkPtr member;
14853    xmlSchemaTypePtr memberType;
14854
14855    member = members;
14856    while (member != NULL) {
14857	memberType = member->type;
14858	while ((memberType != NULL) &&
14859	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14860	    if (memberType == ctxType) {
14861		xmlSchemaPCustomErr(pctxt,
14862		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14863		    WXS_BASIC_CAST ctxType, NULL,
14864		    "The union type definition is circular", NULL);
14865		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14866	    }
14867	    if ((WXS_IS_UNION(memberType)) &&
14868		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14869	    {
14870		int res;
14871		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14872		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14873		    ctxType,
14874		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14875		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14876		if (res != 0)
14877		    return(res);
14878	    }
14879	    memberType = memberType->baseType;
14880	}
14881	member = member->next;
14882    }
14883    return(0);
14884}
14885
14886static int
14887xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14888				   xmlSchemaTypePtr type)
14889{
14890    if (! WXS_IS_UNION(type))
14891	return(0);
14892    return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14893	type->memberTypes));
14894}
14895
14896/**
14897 * xmlSchemaResolveTypeReferences:
14898 * @item:  the complex/simple type definition
14899 * @ctxt:  the parser context
14900 * @name:  the name
14901 *
14902 * Resolvese type definition references
14903 */
14904static void
14905xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14906			 xmlSchemaParserCtxtPtr ctxt)
14907{
14908    if (typeDef == NULL)
14909	return;
14910
14911    /*
14912    * Resolve the base type.
14913    */
14914    if (typeDef->baseType == NULL) {
14915	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14916	    typeDef->base, typeDef->baseNs);
14917	if (typeDef->baseType == NULL) {
14918	    xmlSchemaPResCompAttrErr(ctxt,
14919		XML_SCHEMAP_SRC_RESOLVE,
14920		WXS_BASIC_CAST typeDef, typeDef->node,
14921		"base", typeDef->base, typeDef->baseNs,
14922		XML_SCHEMA_TYPE_SIMPLE, NULL);
14923	    return;
14924	}
14925    }
14926    if (WXS_IS_SIMPLE(typeDef)) {
14927	if (WXS_IS_UNION(typeDef)) {
14928	    /*
14929	    * Resolve the memberTypes.
14930	    */
14931	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14932	    return;
14933	} else if (WXS_IS_LIST(typeDef)) {
14934	    /*
14935	    * Resolve the itemType.
14936	    */
14937	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14938
14939		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
14940		    typeDef->base, typeDef->baseNs);
14941
14942		if ((typeDef->subtypes == NULL) ||
14943		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
14944		{
14945		    typeDef->subtypes = NULL;
14946		    xmlSchemaPResCompAttrErr(ctxt,
14947			XML_SCHEMAP_SRC_RESOLVE,
14948			WXS_BASIC_CAST typeDef, typeDef->node,
14949			"itemType", typeDef->base, typeDef->baseNs,
14950			XML_SCHEMA_TYPE_SIMPLE, NULL);
14951		}
14952	    }
14953	    return;
14954	}
14955    }
14956    /*
14957    * The ball of letters below means, that if we have a particle
14958    * which has a QName-helper component as its {term}, we want
14959    * to resolve it...
14960    */
14961    else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14962	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14963	    XML_SCHEMA_TYPE_PARTICLE) &&
14964	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14965	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14966	    XML_SCHEMA_EXTRA_QNAMEREF))
14967    {
14968	xmlSchemaQNameRefPtr ref =
14969	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14970	xmlSchemaModelGroupDefPtr groupDef;
14971
14972	/*
14973	* URGENT TODO: Test this.
14974	*/
14975	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14976	/*
14977	* Resolve the MG definition reference.
14978	*/
14979	groupDef =
14980	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14981		ref->itemType, ref->name, ref->targetNamespace);
14982	if (groupDef == NULL) {
14983	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14984		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14985		"ref", ref->name, ref->targetNamespace, ref->itemType,
14986		NULL);
14987	    /* Remove the particle. */
14988	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14989	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14990	    /* Remove the particle. */
14991	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14992	else {
14993	    /*
14994	    * Assign the MG definition's {model group} to the
14995	    * particle's {term}.
14996	    */
14997	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
14998
14999	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15000		/*
15001		* SPEC cos-all-limited (1.2)
15002		* "1.2 the {term} property of a particle with
15003		* {max occurs}=1 which is part of a pair which constitutes
15004		* the {content type} of a complex type definition."
15005		*/
15006		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15007		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15008			/* TODO: error code */
15009			XML_SCHEMAP_COS_ALL_LIMITED,
15010			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15011			"The particle's {max occurs} must be 1, since the "
15012			"reference resolves to an 'all' model group",
15013			NULL, NULL);
15014		}
15015	    }
15016	}
15017    }
15018}
15019
15020
15021
15022/**
15023 * xmlSchemaCheckSTPropsCorrect:
15024 * @ctxt:  the schema parser context
15025 * @type:  the simple type definition
15026 *
15027 * Checks st-props-correct.
15028 *
15029 * Returns 0 if the properties are correct,
15030 * if not, a positive error code and -1 on internal
15031 * errors.
15032 */
15033static int
15034xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15035			     xmlSchemaTypePtr type)
15036{
15037    xmlSchemaTypePtr baseType = type->baseType;
15038    xmlChar *str = NULL;
15039
15040    /* STATE: error funcs converted. */
15041    /*
15042    * Schema Component Constraint: Simple Type Definition Properties Correct
15043    *
15044    * NOTE: This is somehow redundant, since we actually built a simple type
15045    * to have all the needed information; this acts as an self test.
15046    */
15047    /* Base type: If the datatype has been �derived� by �restriction�
15048    * then the Simple Type Definition component from which it is �derived�,
15049    * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15050    */
15051    if (baseType == NULL) {
15052	/*
15053	* TODO: Think about: "modulo the impact of Missing
15054	* Sub-components (�5.3)."
15055	*/
15056	xmlSchemaPCustomErr(ctxt,
15057	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15058	    WXS_BASIC_CAST type, NULL,
15059	    "No base type existent", NULL);
15060	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15061
15062    }
15063    if (! WXS_IS_SIMPLE(baseType)) {
15064	xmlSchemaPCustomErr(ctxt,
15065	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15066	    WXS_BASIC_CAST type, NULL,
15067	    "The base type '%s' is not a simple type",
15068	    xmlSchemaGetComponentQName(&str, baseType));
15069	FREE_AND_NULL(str)
15070	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15071    }
15072    if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15073	 (WXS_IS_RESTRICTION(type) == 0) &&
15074	 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15075	xmlSchemaPCustomErr(ctxt,
15076	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15077	    WXS_BASIC_CAST type, NULL,
15078	    "A type, derived by list or union, must have"
15079	    "the simple ur-type definition as base type, not '%s'",
15080	    xmlSchemaGetComponentQName(&str, baseType));
15081	FREE_AND_NULL(str)
15082	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15083    }
15084    /*
15085    * Variety: One of {atomic, list, union}.
15086    */
15087    if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15088	(! WXS_IS_LIST(type))) {
15089	xmlSchemaPCustomErr(ctxt,
15090	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15091	    WXS_BASIC_CAST type, NULL,
15092	    "The variety is absent", NULL);
15093	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15094    }
15095    /* TODO: Finish this. Hmm, is this finished? */
15096
15097    /*
15098    * 3 The {final} of the {base type definition} must not contain restriction.
15099    */
15100    if (xmlSchemaTypeFinalContains(baseType,
15101	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15102	xmlSchemaPCustomErr(ctxt,
15103	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15104	    WXS_BASIC_CAST type, NULL,
15105	    "The 'final' of its base type '%s' must not contain "
15106	    "'restriction'",
15107	    xmlSchemaGetComponentQName(&str, baseType));
15108	FREE_AND_NULL(str)
15109	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15110    }
15111
15112    /*
15113    * 2 All simple type definitions must be derived ultimately from the �simple
15114    * ur-type definition (so� circular definitions are disallowed). That is, it
15115    * must be possible to reach a built-in primitive datatype or the �simple
15116    * ur-type definition� by repeatedly following the {base type definition}.
15117    *
15118    * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15119    */
15120    return (0);
15121}
15122
15123/**
15124 * xmlSchemaCheckCOSSTRestricts:
15125 * @ctxt:  the schema parser context
15126 * @type:  the simple type definition
15127 *
15128 * Schema Component Constraint:
15129 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15130
15131 * Checks if the given @type (simpleType) is derived validly by restriction.
15132 * STATUS:
15133 *
15134 * Returns -1 on internal errors, 0 if the type is validly derived,
15135 * a positive error code otherwise.
15136 */
15137static int
15138xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15139			     xmlSchemaTypePtr type)
15140{
15141    xmlChar *str = NULL;
15142
15143    if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15144	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15145	    "given type is not a user-derived simpleType");
15146	return (-1);
15147    }
15148
15149    if (WXS_IS_ATOMIC(type)) {
15150	xmlSchemaTypePtr primitive;
15151	/*
15152	* 1.1 The {base type definition} must be an atomic simple
15153	* type definition or a built-in primitive datatype.
15154	*/
15155	if (! WXS_IS_ATOMIC(type->baseType)) {
15156	    xmlSchemaPCustomErr(pctxt,
15157		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15158		WXS_BASIC_CAST type, NULL,
15159		"The base type '%s' is not an atomic simple type",
15160		xmlSchemaGetComponentQName(&str, type->baseType));
15161	    FREE_AND_NULL(str)
15162	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15163	}
15164	/* 1.2 The {final} of the {base type definition} must not contain
15165	* restriction.
15166	*/
15167	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15168	if (xmlSchemaTypeFinalContains(type->baseType,
15169	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15170	    xmlSchemaPCustomErr(pctxt,
15171		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15172		WXS_BASIC_CAST type, NULL,
15173		"The final of its base type '%s' must not contain 'restriction'",
15174		xmlSchemaGetComponentQName(&str, type->baseType));
15175	    FREE_AND_NULL(str)
15176	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15177	}
15178
15179	/*
15180	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15181	* type definition}, as specified in the appropriate subsection of 3.2
15182	* Primitive datatypes.
15183	*/
15184	if (type->facets != NULL) {
15185	    xmlSchemaFacetPtr facet;
15186	    int ok = 1;
15187
15188	    primitive = xmlSchemaGetPrimitiveType(type);
15189	    if (primitive == NULL) {
15190		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15191		    "failed to get primitive type");
15192		return (-1);
15193	    }
15194	    facet = type->facets;
15195	    do {
15196		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15197		    ok = 0;
15198		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15199			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15200			type, primitive, facet);
15201		}
15202		facet = facet->next;
15203	    } while (facet != NULL);
15204	    if (ok == 0)
15205		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15206	}
15207	/*
15208	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15209	* of the {base type definition} (call this BF),then the DF's {value}
15210	* must be a valid restriction of BF's {value} as defined in
15211	* [XML Schemas: Datatypes]."
15212	*
15213	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15214	* xmlSchemaDeriveAndValidateFacets()
15215	*/
15216    } else if (WXS_IS_LIST(type)) {
15217	xmlSchemaTypePtr itemType = NULL;
15218
15219	itemType = type->subtypes;
15220	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15221	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15222		"failed to evaluate the item type");
15223	    return (-1);
15224	}
15225	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15226	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15227	/*
15228	* 2.1 The {item type definition} must have a {variety} of atomic or
15229	* union (in which case all the {member type definitions}
15230	* must be atomic).
15231	*/
15232	if ((! WXS_IS_ATOMIC(itemType)) &&
15233	    (! WXS_IS_UNION(itemType))) {
15234	    xmlSchemaPCustomErr(pctxt,
15235		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15236		WXS_BASIC_CAST type, NULL,
15237		"The item type '%s' does not have a variety of atomic or union",
15238		xmlSchemaGetComponentQName(&str, itemType));
15239	    FREE_AND_NULL(str)
15240	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15241	} else if (WXS_IS_UNION(itemType)) {
15242	    xmlSchemaTypeLinkPtr member;
15243
15244	    member = itemType->memberTypes;
15245	    while (member != NULL) {
15246		if (! WXS_IS_ATOMIC(member->type)) {
15247		    xmlSchemaPCustomErr(pctxt,
15248			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15249			WXS_BASIC_CAST type, NULL,
15250			"The item type is a union type, but the "
15251			"member type '%s' of this item type is not atomic",
15252			xmlSchemaGetComponentQName(&str, member->type));
15253		    FREE_AND_NULL(str)
15254		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15255		}
15256		member = member->next;
15257	    }
15258	}
15259
15260	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15261	    xmlSchemaFacetPtr facet;
15262	    /*
15263	    * This is the case if we have: <simpleType><list ..
15264	    */
15265	    /*
15266	    * 2.3.1
15267	    * 2.3.1.1 The {final} of the {item type definition} must not
15268	    * contain list.
15269	    */
15270	    if (xmlSchemaTypeFinalContains(itemType,
15271		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15272		xmlSchemaPCustomErr(pctxt,
15273		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15274		    WXS_BASIC_CAST type, NULL,
15275		    "The final of its item type '%s' must not contain 'list'",
15276		    xmlSchemaGetComponentQName(&str, itemType));
15277		FREE_AND_NULL(str)
15278		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15279	    }
15280	    /*
15281	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15282	    * facet component.
15283	    * OPTIMIZE TODO: the S4S already disallows any facet
15284	    * to be specified.
15285	    */
15286	    if (type->facets != NULL) {
15287		facet = type->facets;
15288		do {
15289		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15290			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15291			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15292			    type, facet);
15293			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15294		    }
15295		    facet = facet->next;
15296		} while (facet != NULL);
15297	    }
15298	    /*
15299	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15300	    * A �list� datatype can be �derived� from an �atomic� datatype
15301	    * whose �lexical space� allows space (such as string or anyURI)or
15302	    * a �union� datatype any of whose {member type definitions}'s
15303	    * �lexical space� allows space.
15304	    */
15305	} else {
15306	    /*
15307	    * This is the case if we have: <simpleType><restriction ...
15308	    * I.e. the variety of "list" is inherited.
15309	    */
15310	    /*
15311	    * 2.3.2
15312	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15313	    */
15314	    if (! WXS_IS_LIST(type->baseType)) {
15315		xmlSchemaPCustomErr(pctxt,
15316		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15317		    WXS_BASIC_CAST type, NULL,
15318		    "The base type '%s' must be a list type",
15319		    xmlSchemaGetComponentQName(&str, type->baseType));
15320		FREE_AND_NULL(str)
15321		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15322	    }
15323	    /*
15324	    * 2.3.2.2 The {final} of the {base type definition} must not
15325	    * contain restriction.
15326	    */
15327	    if (xmlSchemaTypeFinalContains(type->baseType,
15328		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15329		xmlSchemaPCustomErr(pctxt,
15330		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15331		    WXS_BASIC_CAST type, NULL,
15332		    "The 'final' of the base type '%s' must not contain 'restriction'",
15333		    xmlSchemaGetComponentQName(&str, type->baseType));
15334		FREE_AND_NULL(str)
15335		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15336	    }
15337	    /*
15338	    * 2.3.2.3 The {item type definition} must be validly derived
15339	    * from the {base type definition}'s {item type definition} given
15340	    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15341	    */
15342	    {
15343		xmlSchemaTypePtr baseItemType;
15344
15345		baseItemType = type->baseType->subtypes;
15346		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15347		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15348			"failed to eval the item type of a base type");
15349		    return (-1);
15350		}
15351		if ((itemType != baseItemType) &&
15352		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15353			baseItemType, 0) != 0)) {
15354		    xmlChar *strBIT = NULL, *strBT = NULL;
15355		    xmlSchemaPCustomErrExt(pctxt,
15356			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15357			WXS_BASIC_CAST type, NULL,
15358			"The item type '%s' is not validly derived from "
15359			"the item type '%s' of the base type '%s'",
15360			xmlSchemaGetComponentQName(&str, itemType),
15361			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15362			xmlSchemaGetComponentQName(&strBT, type->baseType));
15363
15364		    FREE_AND_NULL(str)
15365		    FREE_AND_NULL(strBIT)
15366		    FREE_AND_NULL(strBT)
15367		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15368		}
15369	    }
15370
15371	    if (type->facets != NULL) {
15372		xmlSchemaFacetPtr facet;
15373		int ok = 1;
15374		/*
15375		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15376		* and enumeration facet components are allowed among the {facets}.
15377		*/
15378		facet = type->facets;
15379		do {
15380		    switch (facet->type) {
15381			case XML_SCHEMA_FACET_LENGTH:
15382			case XML_SCHEMA_FACET_MINLENGTH:
15383			case XML_SCHEMA_FACET_MAXLENGTH:
15384			case XML_SCHEMA_FACET_WHITESPACE:
15385			    /*
15386			    * TODO: 2.5.1.2 List datatypes
15387			    * The value of �whiteSpace� is fixed to the value collapse.
15388			    */
15389			case XML_SCHEMA_FACET_PATTERN:
15390			case XML_SCHEMA_FACET_ENUMERATION:
15391			    break;
15392			default: {
15393			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15394				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15395				type, facet);
15396			    /*
15397			    * We could return, but it's nicer to report all
15398			    * invalid facets.
15399			    */
15400			    ok = 0;
15401			}
15402		    }
15403		    facet = facet->next;
15404		} while (facet != NULL);
15405		if (ok == 0)
15406		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15407		/*
15408		* SPEC (2.3.2.5) (same as 1.3.2)
15409		*
15410		* NOTE (2.3.2.5) This is currently done in
15411		* xmlSchemaDeriveAndValidateFacets()
15412		*/
15413	    }
15414	}
15415    } else if (WXS_IS_UNION(type)) {
15416	/*
15417	* 3.1 The {member type definitions} must all have {variety} of
15418	* atomic or list.
15419	*/
15420	xmlSchemaTypeLinkPtr member;
15421
15422	member = type->memberTypes;
15423	while (member != NULL) {
15424	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15425		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15426
15427	    if ((! WXS_IS_ATOMIC(member->type)) &&
15428		(! WXS_IS_LIST(member->type))) {
15429		xmlSchemaPCustomErr(pctxt,
15430		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15431		    WXS_BASIC_CAST type, NULL,
15432		    "The member type '%s' is neither an atomic, nor a list type",
15433		    xmlSchemaGetComponentQName(&str, member->type));
15434		FREE_AND_NULL(str)
15435		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15436	    }
15437	    member = member->next;
15438	}
15439	/*
15440	* 3.3.1 If the {base type definition} is the �simple ur-type
15441	* definition�
15442	*/
15443	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15444	    /*
15445	    * 3.3.1.1 All of the {member type definitions} must have a
15446	    * {final} which does not contain union.
15447	    */
15448	    member = type->memberTypes;
15449	    while (member != NULL) {
15450		if (xmlSchemaTypeFinalContains(member->type,
15451		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15452		    xmlSchemaPCustomErr(pctxt,
15453			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15454			WXS_BASIC_CAST type, NULL,
15455			"The 'final' of member type '%s' contains 'union'",
15456			xmlSchemaGetComponentQName(&str, member->type));
15457		    FREE_AND_NULL(str)
15458		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15459		}
15460		member = member->next;
15461	    }
15462	    /*
15463	    * 3.3.1.2 The {facets} must be empty.
15464	    */
15465	    if (type->facetSet != NULL) {
15466		xmlSchemaPCustomErr(pctxt,
15467		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15468		    WXS_BASIC_CAST type, NULL,
15469		    "No facets allowed", NULL);
15470		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15471	    }
15472	} else {
15473	    /*
15474	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15475	    * I.e. the variety of "list" is inherited.
15476	    */
15477	    if (! WXS_IS_UNION(type->baseType)) {
15478		xmlSchemaPCustomErr(pctxt,
15479		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15480		    WXS_BASIC_CAST type, NULL,
15481		    "The base type '%s' is not a union type",
15482		    xmlSchemaGetComponentQName(&str, type->baseType));
15483		FREE_AND_NULL(str)
15484		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15485	    }
15486	    /*
15487	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15488	    */
15489	    if (xmlSchemaTypeFinalContains(type->baseType,
15490		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15491		xmlSchemaPCustomErr(pctxt,
15492		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15493		    WXS_BASIC_CAST type, NULL,
15494		    "The 'final' of its base type '%s' must not contain 'restriction'",
15495		    xmlSchemaGetComponentQName(&str, type->baseType));
15496		FREE_AND_NULL(str)
15497		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15498	    }
15499	    /*
15500	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15501	    * derived from the corresponding type definitions in the {base
15502	    * type definition}'s {member type definitions} given the empty set,
15503	    * as defined in Type Derivation OK (Simple) (�3.14.6).
15504	    */
15505	    {
15506		xmlSchemaTypeLinkPtr baseMember;
15507
15508		/*
15509		* OPTIMIZE: if the type is restricting, it has no local defined
15510		* member types and inherits the member types of the base type;
15511		* thus a check for equality can be skipped.
15512		*/
15513		/*
15514		* Even worse: I cannot see a scenario where a restricting
15515		* union simple type can have other member types as the member
15516		* types of it's base type. This check seems not necessary with
15517		* respect to the derivation process in libxml2.
15518		* But necessary if constructing types with an API.
15519		*/
15520		if (type->memberTypes != NULL) {
15521		    member = type->memberTypes;
15522		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15523		    if ((member == NULL) && (baseMember != NULL)) {
15524			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15525			    "different number of member types in base");
15526		    }
15527		    while (member != NULL) {
15528			if (baseMember == NULL) {
15529			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15530			    "different number of member types in base");
15531			} else if ((member->type != baseMember->type) &&
15532			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15533				member->type, baseMember->type, 0) != 0)) {
15534			    xmlChar *strBMT = NULL, *strBT = NULL;
15535
15536			    xmlSchemaPCustomErrExt(pctxt,
15537				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15538				WXS_BASIC_CAST type, NULL,
15539				"The member type %s is not validly "
15540				"derived from its corresponding member "
15541				"type %s of the base type %s",
15542				xmlSchemaGetComponentQName(&str, member->type),
15543				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15544				xmlSchemaGetComponentQName(&strBT, type->baseType));
15545			    FREE_AND_NULL(str)
15546			    FREE_AND_NULL(strBMT)
15547			    FREE_AND_NULL(strBT)
15548			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15549			}
15550			member = member->next;
15551			baseMember = baseMember->next;
15552		    }
15553		}
15554	    }
15555	    /*
15556	    * 3.3.2.4 Only pattern and enumeration facet components are
15557	    * allowed among the {facets}.
15558	    */
15559	    if (type->facets != NULL) {
15560		xmlSchemaFacetPtr facet;
15561		int ok = 1;
15562
15563		facet = type->facets;
15564		do {
15565		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15566			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15567			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15568				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15569				type, facet);
15570			ok = 0;
15571		    }
15572		    facet = facet->next;
15573		} while (facet != NULL);
15574		if (ok == 0)
15575		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15576
15577	    }
15578	    /*
15579	    * SPEC (3.3.2.5) (same as 1.3.2)
15580	    *
15581	    * NOTE (3.3.2.5) This is currently done in
15582	    * xmlSchemaDeriveAndValidateFacets()
15583	    */
15584	}
15585    }
15586
15587    return (0);
15588}
15589
15590/**
15591 * xmlSchemaCheckSRCSimpleType:
15592 * @ctxt:  the schema parser context
15593 * @type:  the simple type definition
15594 *
15595 * Checks crc-simple-type constraints.
15596 *
15597 * Returns 0 if the constraints are satisfied,
15598 * if not a positive error code and -1 on internal
15599 * errors.
15600 */
15601#if 0
15602static int
15603xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15604			    xmlSchemaTypePtr type)
15605{
15606    /*
15607    * src-simple-type.1 The corresponding simple type definition, if any,
15608    * must satisfy the conditions set out in Constraints on Simple Type
15609    * Definition Schema Components (�3.14.6).
15610    */
15611    if (WXS_IS_RESTRICTION(type)) {
15612	/*
15613	* src-simple-type.2 "If the <restriction> alternative is chosen,
15614	* either it must have a base [attribute] or a <simpleType> among its
15615	* [children], but not both."
15616	* NOTE: This is checked in the parse function of <restriction>.
15617	*/
15618	/*
15619	*
15620	*/
15621    } else if (WXS_IS_LIST(type)) {
15622	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15623	* an itemType [attribute] or a <simpleType> among its [children],
15624	* but not both."
15625	*
15626	* NOTE: This is checked in the parse function of <list>.
15627	*/
15628    } else if (WXS_IS_UNION(type)) {
15629	/*
15630	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15631	*/
15632    }
15633    return (0);
15634}
15635#endif
15636
15637static int
15638xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15639{
15640   if (ctxt->vctxt == NULL) {
15641	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15642	if (ctxt->vctxt == NULL) {
15643	    xmlSchemaPErr(ctxt, NULL,
15644		XML_SCHEMAP_INTERNAL,
15645		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15646		"failed to create a temp. validation context.\n",
15647		NULL, NULL);
15648	    return (-1);
15649	}
15650	/* TODO: Pass user data. */
15651	xmlSchemaSetValidErrors(ctxt->vctxt,
15652	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15653	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15654	    ctxt->serror, ctxt->errCtxt);
15655    }
15656    return (0);
15657}
15658
15659static int
15660xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15661			     xmlNodePtr node,
15662			     xmlSchemaTypePtr type,
15663			     const xmlChar *value,
15664			     xmlSchemaValPtr *retVal,
15665			     int fireErrors,
15666			     int normalize,
15667			     int isNormalized);
15668
15669/**
15670 * xmlSchemaParseCheckCOSValidDefault:
15671 * @pctxt:  the schema parser context
15672 * @type:  the simple type definition
15673 * @value: the default value
15674 * @node: an optional node (the holder of the value)
15675 *
15676 * Schema Component Constraint: Element Default Valid (Immediate)
15677 * (cos-valid-default)
15678 * This will be used by the parser only. For the validator there's
15679 * an other version.
15680 *
15681 * Returns 0 if the constraints are satisfied,
15682 * if not, a positive error code and -1 on internal
15683 * errors.
15684 */
15685static int
15686xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15687				   xmlNodePtr node,
15688				   xmlSchemaTypePtr type,
15689				   const xmlChar *value,
15690				   xmlSchemaValPtr *val)
15691{
15692    int ret = 0;
15693
15694    /*
15695    * cos-valid-default:
15696    * Schema Component Constraint: Element Default Valid (Immediate)
15697    * For a string to be a valid default with respect to a type
15698    * definition the appropriate case among the following must be true:
15699    */
15700    if WXS_IS_COMPLEX(type) {
15701	/*
15702	* Complex type.
15703	*
15704	* SPEC (2.1) "its {content type} must be a simple type definition
15705	* or mixed."
15706	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15707	* type}'s particle must be �emptiable� as defined by
15708	* Particle Emptiable (�3.9.6)."
15709	*/
15710	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15711	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15712	    /* NOTE that this covers (2.2.2) as well. */
15713	    xmlSchemaPCustomErr(pctxt,
15714		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15715		WXS_BASIC_CAST type, type->node,
15716		"For a string to be a valid default, the type definition "
15717		"must be a simple type or a complex type with mixed content "
15718		"and a particle emptiable", NULL);
15719	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15720	}
15721    }
15722    /*
15723    * 1 If the type definition is a simple type definition, then the string
15724    * must be �valid� with respect to that definition as defined by String
15725    * Valid (�3.14.4).
15726    *
15727    * AND
15728    *
15729    * 2.2.1 If the {content type} is a simple type definition, then the
15730    * string must be �valid� with respect to that simple type definition
15731    * as defined by String Valid (�3.14.4).
15732    */
15733    if (WXS_IS_SIMPLE(type))
15734	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15735	    type, value, val, 1, 1, 0);
15736    else if (WXS_HAS_SIMPLE_CONTENT(type))
15737	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15738	    type->contentTypeDef, value, val, 1, 1, 0);
15739    else
15740	return (ret);
15741
15742    if (ret < 0) {
15743	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15744	    "calling xmlSchemaVCheckCVCSimpleType()");
15745    }
15746
15747    return (ret);
15748}
15749
15750/**
15751 * xmlSchemaCheckCTPropsCorrect:
15752 * @ctxt:  the schema parser context
15753 * @type:  the complex type definition
15754 *
15755 *.(4.6) Constraints on Complex Type Definition Schema Components
15756 * Schema Component Constraint:
15757 * Complex Type Definition Properties Correct (ct-props-correct)
15758 * STATUS: (seems) complete
15759 *
15760 * Returns 0 if the constraints are satisfied, a positive
15761 * error code if not and -1 if an internal error occured.
15762 */
15763static int
15764xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15765			     xmlSchemaTypePtr type)
15766{
15767    /*
15768    * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15769    *
15770    * SPEC (1) "The values of the properties of a complex type definition must
15771    * be as described in the property tableau in The Complex Type Definition
15772    * Schema Component (�3.4.1), modulo the impact of Missing
15773    * Sub-components (�5.3)."
15774    */
15775    if ((type->baseType != NULL) &&
15776	(WXS_IS_SIMPLE(type->baseType)) &&
15777	(WXS_IS_EXTENSION(type) == 0)) {
15778	/*
15779	* SPEC (2) "If the {base type definition} is a simple type definition,
15780	* the {derivation method} must be extension."
15781	*/
15782	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15783	    XML_SCHEMAP_SRC_CT_1,
15784	    NULL, WXS_BASIC_CAST type,
15785	    "If the base type is a simple type, the derivation method must be "
15786	    "'extension'", NULL, NULL);
15787	return (XML_SCHEMAP_SRC_CT_1);
15788    }
15789    /*
15790    * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15791    * definition�. That is, it must be possible to reach the �ur-type
15792    * definition by repeatedly following the {base type definition}."
15793    *
15794    * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15795    */
15796    /*
15797    * NOTE that (4) and (5) need the following:
15798    *   - attribute uses need to be already inherited (apply attr. prohibitions)
15799    *   - attribute group references need to be expanded already
15800    *   - simple types need to be typefixed already
15801    */
15802    if (type->attrUses &&
15803	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15804    {
15805	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15806	xmlSchemaAttributeUsePtr use, tmp;
15807	int i, j, hasId = 0;
15808
15809	for (i = uses->nbItems -1; i >= 0; i--) {
15810	    use = uses->items[i];
15811
15812	    /*
15813	    * SPEC ct-props-correct
15814	    * (4) "Two distinct attribute declarations in the
15815	    * {attribute uses} must not have identical {name}s and
15816	    * {target namespace}s."
15817	    */
15818	    if (i > 0) {
15819		for (j = i -1; j >= 0; j--) {
15820		    tmp = uses->items[j];
15821		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15822			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15823			(WXS_ATTRUSE_DECL_TNS(use) ==
15824			WXS_ATTRUSE_DECL_TNS(tmp)))
15825		    {
15826			xmlChar *str = NULL;
15827
15828			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15829			    XML_SCHEMAP_AG_PROPS_CORRECT,
15830			    NULL, WXS_BASIC_CAST type,
15831			    "Duplicate %s",
15832			    xmlSchemaGetComponentDesignation(&str, use),
15833			    NULL);
15834			FREE_AND_NULL(str);
15835			/*
15836			* Remove the duplicate.
15837			*/
15838			if (xmlSchemaItemListRemove(uses, i) == -1)
15839			    goto exit_failure;
15840			goto next_use;
15841		    }
15842		}
15843	    }
15844	    /*
15845	    * SPEC ct-props-correct
15846	    * (5) "Two distinct attribute declarations in the
15847	    * {attribute uses} must not have {type definition}s which
15848	    * are or are derived from ID."
15849	    */
15850	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15851		if (xmlSchemaIsDerivedFromBuiltInType(
15852		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15853		{
15854		    if (hasId) {
15855			xmlChar *str = NULL;
15856
15857			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15858			    XML_SCHEMAP_AG_PROPS_CORRECT,
15859			    NULL, WXS_BASIC_CAST type,
15860			    "There must not exist more than one attribute "
15861			    "declaration of type 'xs:ID' "
15862			    "(or derived from 'xs:ID'). The %s violates this "
15863			    "constraint",
15864			    xmlSchemaGetComponentDesignation(&str, use),
15865			    NULL);
15866			FREE_AND_NULL(str);
15867			if (xmlSchemaItemListRemove(uses, i) == -1)
15868			    goto exit_failure;
15869		    }
15870
15871		    hasId = 1;
15872		}
15873	    }
15874next_use: {}
15875	}
15876    }
15877    return (0);
15878exit_failure:
15879    return(-1);
15880}
15881
15882static int
15883xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15884		       xmlSchemaTypePtr typeB)
15885{
15886    /*
15887    * TODO: This should implement component-identity
15888    * in the future.
15889    */
15890    if ((typeA == NULL) || (typeB == NULL))
15891	return (0);
15892    return (typeA == typeB);
15893}
15894
15895/**
15896 * xmlSchemaCheckCOSCTDerivedOK:
15897 * @ctxt:  the schema parser context
15898 * @type:  the to-be derived complex type definition
15899 * @baseType:  the base complex type definition
15900 * @set: the given set
15901 *
15902 * Schema Component Constraint:
15903 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15904 *
15905 * STATUS: completed
15906 *
15907 * Returns 0 if the constraints are satisfied, or 1
15908 * if not.
15909 */
15910static int
15911xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
15912			     xmlSchemaTypePtr type,
15913			     xmlSchemaTypePtr baseType,
15914			     int set)
15915{
15916    int equal = xmlSchemaAreEqualTypes(type, baseType);
15917    /* TODO: Error codes. */
15918    /*
15919    * SPEC "For a complex type definition (call it D, for derived)
15920    * to be validly derived from a type definition (call this
15921    * B, for base) given a subset of {extension, restriction}
15922    * all of the following must be true:"
15923    */
15924    if (! equal) {
15925	/*
15926	* SPEC (1) "If B and D are not the same type definition, then the
15927	* {derivation method} of D must not be in the subset."
15928	*/
15929	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15930	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
15931	    return (1);
15932    } else {
15933	/*
15934	* SPEC (2.1) "B and D must be the same type definition."
15935	*/
15936	return (0);
15937    }
15938    /*
15939    * SPEC (2.2) "B must be D's {base type definition}."
15940    */
15941    if (type->baseType == baseType)
15942	return (0);
15943    /*
15944    * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
15945    * definition�."
15946    */
15947    if (WXS_IS_ANYTYPE(type->baseType))
15948	return (1);
15949
15950    if (WXS_IS_COMPLEX(type->baseType)) {
15951	/*
15952	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15953	* must be validly derived from B given the subset as defined by this
15954	* constraint."
15955	*/
15956	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
15957	    baseType, set));
15958    } else {
15959	/*
15960	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15961	* must be validly derived from B given the subset as defined in Type
15962	* Derivation OK (Simple) (�3.14.6).
15963	*/
15964	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
15965	    baseType, set));
15966    }
15967}
15968
15969/**
15970 * xmlSchemaCheckCOSDerivedOK:
15971 * @type:  the derived simple type definition
15972 * @baseType:  the base type definition
15973 *
15974 * Calls:
15975 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
15976 *
15977 * Checks wheter @type can be validly derived from @baseType.
15978 *
15979 * Returns 0 on success, an positive error code otherwise.
15980 */
15981static int
15982xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
15983			   xmlSchemaTypePtr type,
15984			   xmlSchemaTypePtr baseType,
15985			   int set)
15986{
15987    if (WXS_IS_SIMPLE(type))
15988	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
15989    else
15990	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
15991}
15992
15993/**
15994 * xmlSchemaCheckCOSCTExtends:
15995 * @ctxt:  the schema parser context
15996 * @type:  the complex type definition
15997 *
15998 * (3.4.6) Constraints on Complex Type Definition Schema Components
15999 * Schema Component Constraint:
16000 * Derivation Valid (Extension) (cos-ct-extends)
16001 *
16002 * STATUS:
16003 *   missing:
16004 *     (1.5)
16005 *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16006 *
16007 * Returns 0 if the constraints are satisfied, a positive
16008 * error code if not and -1 if an internal error occured.
16009 */
16010static int
16011xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16012			   xmlSchemaTypePtr type)
16013{
16014    xmlSchemaTypePtr base = type->baseType;
16015    /*
16016    * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16017    * temporarily only.
16018    */
16019    /*
16020    * SPEC (1) "If the {base type definition} is a complex type definition,
16021    * then all of the following must be true:"
16022    */
16023    if (WXS_IS_COMPLEX(base)) {
16024	/*
16025	* SPEC (1.1) "The {final} of the {base type definition} must not
16026	* contain extension."
16027	*/
16028	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16029	    xmlSchemaPCustomErr(ctxt,
16030		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16031		WXS_BASIC_CAST type, NULL,
16032		"The 'final' of the base type definition "
16033		"contains 'extension'", NULL);
16034	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16035	}
16036
16037	/*
16038	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16039	* since they are automatically satisfied through the
16040	* inheriting mechanism.
16041	* Note that even if redefining components, the inheriting mechanism
16042	* is used.
16043	*/
16044#if 0
16045	/*
16046	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16047	* uses}
16048	* of the complex type definition itself, that is, for every attribute
16049	* use in the {attribute uses} of the {base type definition}, there
16050	* must be an attribute use in the {attribute uses} of the complex
16051	* type definition itself whose {attribute declaration} has the same
16052	* {name}, {target namespace} and {type definition} as its attribute
16053	* declaration"
16054	*/
16055	if (base->attrUses != NULL) {
16056	    int i, j, found;
16057	    xmlSchemaAttributeUsePtr use, buse;
16058
16059	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16060		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16061		found = 0;
16062		if (type->attrUses != NULL) {
16063		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16064		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16065		    {
16066			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16067				WXS_ATTRUSE_DECL_NAME(buse)) &&
16068			    (WXS_ATTRUSE_DECL_TNS(use) ==
16069				WXS_ATTRUSE_DECL_TNS(buse)) &&
16070			    (WXS_ATTRUSE_TYPEDEF(use) ==
16071				WXS_ATTRUSE_TYPEDEF(buse))
16072			{
16073			    found = 1;
16074			    break;
16075			}
16076		    }
16077		}
16078		if (! found) {
16079		    xmlChar *str = NULL;
16080
16081		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16082			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16083			NULL, WXS_BASIC_CAST type,
16084			/*
16085			* TODO: The report does not indicate that also the
16086			* type needs to be the same.
16087			*/
16088			"This type is missing a matching correspondent "
16089			"for its {base type}'s %s in its {attribute uses}",
16090			xmlSchemaGetComponentDesignation(&str,
16091			    buse->children),
16092			NULL);
16093		    FREE_AND_NULL(str)
16094		}
16095	    }
16096	}
16097	/*
16098	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16099	* definition must also have one, and the base type definition's
16100	* {attribute  wildcard}'s {namespace constraint} must be a subset
16101	* of the complex  type definition's {attribute wildcard}'s {namespace
16102	* constraint}, as defined by Wildcard Subset (�3.10.6)."
16103	*/
16104
16105	/*
16106	* MAYBE TODO: Enable if ever needed. But this will be needed only
16107	* if created the type via a schema construction API.
16108	*/
16109	if (base->attributeWildcard != NULL) {
16110	    if (type->attributeWilcard == NULL) {
16111		xmlChar *str = NULL;
16112
16113		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16114		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16115		    NULL, type,
16116		    "The base %s has an attribute wildcard, "
16117		    "but this type is missing an attribute wildcard",
16118		    xmlSchemaGetComponentDesignation(&str, base));
16119		FREE_AND_NULL(str)
16120
16121	    } else if (xmlSchemaCheckCOSNSSubset(
16122		base->attributeWildcard, type->attributeWildcard))
16123	    {
16124		xmlChar *str = NULL;
16125
16126		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16127		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16128		    NULL, type,
16129		    "The attribute wildcard is not a valid "
16130		    "superset of the one in the base %s",
16131		    xmlSchemaGetComponentDesignation(&str, base));
16132		FREE_AND_NULL(str)
16133	    }
16134	}
16135#endif
16136	/*
16137	* SPEC (1.4) "One of the following must be true:"
16138	*/
16139	if ((type->contentTypeDef != NULL) &&
16140	    (type->contentTypeDef == base->contentTypeDef)) {
16141	    /*
16142	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16143	    * and the {content type} of the complex type definition itself
16144	    * must be the same simple type definition"
16145	    * PASS
16146	    */
16147	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16148	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16149	    /*
16150	    * SPEC (1.4.2) "The {content type} of both the {base type
16151	    * definition} and the complex type definition itself must
16152	    * be empty."
16153	    * PASS
16154	    */
16155	} else {
16156	    /*
16157	    * SPEC (1.4.3) "All of the following must be true:"
16158	    */
16159	    if (type->subtypes == NULL) {
16160		/*
16161		* SPEC 1.4.3.1 The {content type} of the complex type
16162		* definition itself must specify a particle.
16163		*/
16164		xmlSchemaPCustomErr(ctxt,
16165		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16166		    WXS_BASIC_CAST type, NULL,
16167		    "The content type must specify a particle", NULL);
16168		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16169	    }
16170	    /*
16171	    * SPEC (1.4.3.2) "One of the following must be true:"
16172	    */
16173	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16174		/*
16175		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16176		* definition} must be empty.
16177		* PASS
16178		*/
16179	    } else {
16180		/*
16181		* SPEC (1.4.3.2.2) "All of the following must be true:"
16182		*/
16183		if ((type->contentType != base->contentType) ||
16184		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16185		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16186		    /*
16187		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16188		    * or both must be element-only."
16189		    */
16190		    xmlSchemaPCustomErr(ctxt,
16191			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16192			WXS_BASIC_CAST type, NULL,
16193			"The content type of both, the type and its base "
16194			"type, must either 'mixed' or 'element-only'", NULL);
16195		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16196		}
16197		/*
16198		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16199		* complex type definition must be a �valid extension�
16200		* of the {base type definition}'s particle, as defined
16201		* in Particle Valid (Extension) (�3.9.6)."
16202		*
16203		* NOTE that we won't check "Particle Valid (Extension)",
16204		* since it is ensured by the derivation process in
16205		* xmlSchemaTypeFixup(). We need to implement this when heading
16206		* for a construction API
16207		* TODO: !! This is needed to be checked if redefining a type !!
16208		*/
16209	    }
16210	    /*
16211	    * URGENT TODO (1.5)
16212	    */
16213	}
16214    } else {
16215	/*
16216	* SPEC (2) "If the {base type definition} is a simple type definition,
16217	* then all of the following must be true:"
16218	*/
16219	if (type->contentTypeDef != base) {
16220	    /*
16221	    * SPEC (2.1) "The {content type} must be the same simple type
16222	    * definition."
16223	    */
16224	    xmlSchemaPCustomErr(ctxt,
16225		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16226		WXS_BASIC_CAST type, NULL,
16227		"The content type must be the simple base type", NULL);
16228	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16229	}
16230	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16231	    /*
16232	    * SPEC (2.2) "The {final} of the {base type definition} must not
16233	    * contain extension"
16234	    * NOTE that this is the same as (1.1).
16235	    */
16236	    xmlSchemaPCustomErr(ctxt,
16237		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16238		WXS_BASIC_CAST type, NULL,
16239		"The 'final' of the base type definition "
16240		"contains 'extension'", NULL);
16241	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16242	}
16243    }
16244    return (0);
16245}
16246
16247/**
16248 * xmlSchemaCheckDerivationOKRestriction:
16249 * @ctxt:  the schema parser context
16250 * @type:  the complex type definition
16251 *
16252 * (3.4.6) Constraints on Complex Type Definition Schema Components
16253 * Schema Component Constraint:
16254 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16255 *
16256 * STATUS:
16257 *   missing:
16258 *     (5.4.2) ???
16259 *
16260 * ATTENTION:
16261 * In XML Schema 1.1 this will be:
16262 * Validation Rule: Checking complex type subsumption
16263 *
16264 * Returns 0 if the constraints are satisfied, a positive
16265 * error code if not and -1 if an internal error occured.
16266 */
16267static int
16268xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16269				      xmlSchemaTypePtr type)
16270{
16271    xmlSchemaTypePtr base;
16272
16273    /*
16274    * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16275    * temporarily only.
16276    */
16277    base = type->baseType;
16278    if (! WXS_IS_COMPLEX(base)) {
16279	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16280	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16281	    type->node, WXS_BASIC_CAST type,
16282	    "The base type must be a complex type", NULL, NULL);
16283	return(ctxt->err);
16284    }
16285    if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16286	/*
16287	* SPEC (1) "The {base type definition} must be a complex type
16288	* definition whose {final} does not contain restriction."
16289	*/
16290	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16291	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16292	    type->node, WXS_BASIC_CAST type,
16293	    "The 'final' of the base type definition "
16294	    "contains 'restriction'", NULL, NULL);
16295	return (ctxt->err);
16296    }
16297    /*
16298    * SPEC (2), (3) and (4)
16299    * Those are handled in a separate function, since the
16300    * same constraints are needed for redefinition of
16301    * attribute groups as well.
16302    */
16303    if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16304	XML_SCHEMA_ACTION_DERIVE,
16305	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16306	type->attrUses, base->attrUses,
16307	type->attributeWildcard,
16308	base->attributeWildcard) == -1)
16309    {
16310	return(-1);
16311    }
16312    /*
16313    * SPEC (5) "One of the following must be true:"
16314    */
16315    if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16316	/*
16317	* SPEC (5.1) "The {base type definition} must be the
16318	* �ur-type definition�."
16319	* PASS
16320	*/
16321    } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16322	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16323	/*
16324	* SPEC (5.2.1) "The {content type} of the complex type definition
16325	* must be a simple type definition"
16326	*
16327	* SPEC (5.2.2) "One of the following must be true:"
16328	*/
16329	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16330	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16331	{
16332	    int err;
16333	    /*
16334	    * SPEC (5.2.2.1) "The {content type} of the {base type
16335	    * definition} must be a simple type definition from which
16336	    * the {content type} is validly derived given the empty
16337	    * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16338	    *
16339	    * ATTENTION TODO: This seems not needed if the type implicitely
16340	    * derived from the base type.
16341	    *
16342	    */
16343	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16344		type->contentTypeDef, base->contentTypeDef, 0);
16345	    if (err != 0) {
16346		xmlChar *strA = NULL, *strB = NULL;
16347
16348		if (err == -1)
16349		    return(-1);
16350		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16351		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16352		    NULL, WXS_BASIC_CAST type,
16353		    "The {content type} %s is not validly derived from the "
16354		    "base type's {content type} %s",
16355		    xmlSchemaGetComponentDesignation(&strA,
16356			type->contentTypeDef),
16357		    xmlSchemaGetComponentDesignation(&strB,
16358			base->contentTypeDef));
16359		FREE_AND_NULL(strA);
16360		FREE_AND_NULL(strB);
16361		return(ctxt->err);
16362	    }
16363	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16364	    (xmlSchemaIsParticleEmptiable(
16365		(xmlSchemaParticlePtr) base->subtypes))) {
16366	    /*
16367	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16368	    * and have a particle which is �emptiable� as defined in
16369	    * Particle Emptiable (�3.9.6)."
16370	    * PASS
16371	    */
16372	} else {
16373	    xmlSchemaPCustomErr(ctxt,
16374		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16375		WXS_BASIC_CAST type, NULL,
16376		"The content type of the base type must be either "
16377		"a simple type or 'mixed' and an emptiable particle", NULL);
16378	    return (ctxt->err);
16379	}
16380    } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16381	/*
16382	* SPEC (5.3.1) "The {content type} of the complex type itself must
16383	* be empty"
16384	*/
16385	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16386	    /*
16387	    * SPEC (5.3.2.1) "The {content type} of the {base type
16388	    * definition} must also be empty."
16389	    * PASS
16390	    */
16391	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16392	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16393	    xmlSchemaIsParticleEmptiable(
16394		(xmlSchemaParticlePtr) base->subtypes)) {
16395	    /*
16396	    * SPEC (5.3.2.2) "The {content type} of the {base type
16397	    * definition} must be elementOnly or mixed and have a particle
16398	    * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16399	    * PASS
16400	    */
16401	} else {
16402	    xmlSchemaPCustomErr(ctxt,
16403		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16404		WXS_BASIC_CAST type, NULL,
16405		"The content type of the base type must be either "
16406		"empty or 'mixed' (or 'elements-only') and an emptiable "
16407		"particle", NULL);
16408	    return (ctxt->err);
16409	}
16410    } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16411	WXS_HAS_MIXED_CONTENT(type)) {
16412	/*
16413	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16414	* itself must be element-only"
16415	*/
16416	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16417	    /*
16418	    * SPEC (5.4.1.2) "The {content type} of the complex type
16419	    * definition itself and of the {base type definition} must be
16420	    * mixed"
16421	    */
16422	    xmlSchemaPCustomErr(ctxt,
16423		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16424		WXS_BASIC_CAST type, NULL,
16425		"If the content type is 'mixed', then the content type of the "
16426		"base type must also be 'mixed'", NULL);
16427	    return (ctxt->err);
16428	}
16429	/*
16430	* SPEC (5.4.2) "The particle of the complex type definition itself
16431	* must be a �valid restriction� of the particle of the {content
16432	* type} of the {base type definition} as defined in Particle Valid
16433	* (Restriction) (�3.9.6).
16434	*
16435	* URGENT TODO: (5.4.2)
16436	*/
16437    } else {
16438	xmlSchemaPCustomErr(ctxt,
16439	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16440	    WXS_BASIC_CAST type, NULL,
16441	    "The type is not a valid restriction of its base type", NULL);
16442	return (ctxt->err);
16443    }
16444    return (0);
16445}
16446
16447/**
16448 * xmlSchemaCheckCTComponent:
16449 * @ctxt:  the schema parser context
16450 * @type:  the complex type definition
16451 *
16452 * (3.4.6) Constraints on Complex Type Definition Schema Components
16453 *
16454 * Returns 0 if the constraints are satisfied, a positive
16455 * error code if not and -1 if an internal error occured.
16456 */
16457static int
16458xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16459			  xmlSchemaTypePtr type)
16460{
16461    int ret;
16462    /*
16463    * Complex Type Definition Properties Correct
16464    */
16465    ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16466    if (ret != 0)
16467	return (ret);
16468    if (WXS_IS_EXTENSION(type))
16469	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16470    else
16471	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16472    return (ret);
16473}
16474
16475/**
16476 * xmlSchemaCheckSRCCT:
16477 * @ctxt:  the schema parser context
16478 * @type:  the complex type definition
16479 *
16480 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16481 * Schema Representation Constraint:
16482 * Complex Type Definition Representation OK (src-ct)
16483 *
16484 * Returns 0 if the constraints are satisfied, a positive
16485 * error code if not and -1 if an internal error occured.
16486 */
16487static int
16488xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16489		    xmlSchemaTypePtr type)
16490{
16491    xmlSchemaTypePtr base;
16492    int ret = 0;
16493
16494    /*
16495    * TODO: Adjust the error codes here, as I used
16496    * XML_SCHEMAP_SRC_CT_1 only yet.
16497    */
16498    base = type->baseType;
16499    if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16500	/*
16501	* 1 If the <complexContent> alternative is chosen, the type definition
16502	* �resolved� to by the �actual value� of the base [attribute]
16503	* must be a complex type definition;
16504	*/
16505	if (! WXS_IS_COMPLEX(base)) {
16506	    xmlChar *str = NULL;
16507	    xmlSchemaPCustomErr(ctxt,
16508		XML_SCHEMAP_SRC_CT_1,
16509		WXS_BASIC_CAST type, type->node,
16510		"If using <complexContent>, the base type is expected to be "
16511		"a complex type. The base type '%s' is a simple type",
16512		xmlSchemaFormatQName(&str, base->targetNamespace,
16513		base->name));
16514	    FREE_AND_NULL(str)
16515	    return (XML_SCHEMAP_SRC_CT_1);
16516	}
16517    } else {
16518	/*
16519	* SPEC
16520	* 2 If the <simpleContent> alternative is chosen, all of the
16521	* following must be true:
16522	* 2.1 The type definition �resolved� to by the �actual value� of the
16523	* base [attribute] must be one of the following:
16524	*/
16525	if (WXS_IS_SIMPLE(base)) {
16526	    if (WXS_IS_EXTENSION(type) == 0) {
16527		xmlChar *str = NULL;
16528		/*
16529		* 2.1.3 only if the <extension> alternative is also
16530		* chosen, a simple type definition.
16531		*/
16532		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16533		xmlSchemaPCustomErr(ctxt,
16534		    XML_SCHEMAP_SRC_CT_1,
16535		    WXS_BASIC_CAST type, NULL,
16536		    "If using <simpleContent> and <restriction>, the base "
16537		    "type must be a complex type. The base type '%s' is "
16538		    "a simple type",
16539		    xmlSchemaFormatQName(&str, base->targetNamespace,
16540			base->name));
16541		FREE_AND_NULL(str)
16542		return (XML_SCHEMAP_SRC_CT_1);
16543	    }
16544	} else {
16545	    /* Base type is a complex type. */
16546	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16547		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16548		/*
16549		* 2.1.1 a complex type definition whose {content type} is a
16550		* simple type definition;
16551		* PASS
16552		*/
16553		if (base->contentTypeDef == NULL) {
16554		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16555			WXS_BASIC_CAST type, NULL,
16556			"Internal error: xmlSchemaCheckSRCCT, "
16557			"'%s', base type has no content type",
16558			type->name);
16559		    return (-1);
16560		}
16561	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16562		(WXS_IS_RESTRICTION(type))) {
16563
16564		/*
16565		* 2.1.2 only if the <restriction> alternative is also
16566		* chosen, a complex type definition whose {content type}
16567		* is mixed and a particle emptiable.
16568		*/
16569		if (! xmlSchemaIsParticleEmptiable(
16570		    (xmlSchemaParticlePtr) base->subtypes)) {
16571		    ret = XML_SCHEMAP_SRC_CT_1;
16572		} else
16573		    /*
16574		    * Attention: at this point the <simpleType> child is in
16575		    * ->contentTypeDef (put there during parsing).
16576		    */
16577		    if (type->contentTypeDef == NULL) {
16578		    xmlChar *str = NULL;
16579		    /*
16580		    * 2.2 If clause 2.1.2 above is satisfied, then there
16581		    * must be a <simpleType> among the [children] of
16582		    * <restriction>.
16583		    */
16584		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16585		    xmlSchemaPCustomErr(ctxt,
16586			XML_SCHEMAP_SRC_CT_1,
16587			WXS_BASIC_CAST type, NULL,
16588			"A <simpleType> is expected among the children "
16589			"of <restriction>, if <simpleContent> is used and "
16590			"the base type '%s' is a complex type",
16591			xmlSchemaFormatQName(&str, base->targetNamespace,
16592			base->name));
16593		    FREE_AND_NULL(str)
16594		    return (XML_SCHEMAP_SRC_CT_1);
16595		}
16596	    } else {
16597		ret = XML_SCHEMAP_SRC_CT_1;
16598	    }
16599	}
16600	if (ret > 0) {
16601	    xmlChar *str = NULL;
16602	    if (WXS_IS_RESTRICTION(type)) {
16603		xmlSchemaPCustomErr(ctxt,
16604		    XML_SCHEMAP_SRC_CT_1,
16605		    WXS_BASIC_CAST type, NULL,
16606		    "If <simpleContent> and <restriction> is used, the "
16607		    "base type must be a simple type or a complex type with "
16608		    "mixed content and particle emptiable. The base type "
16609		    "'%s' is none of those",
16610		    xmlSchemaFormatQName(&str, base->targetNamespace,
16611		    base->name));
16612	    } else {
16613		xmlSchemaPCustomErr(ctxt,
16614		    XML_SCHEMAP_SRC_CT_1,
16615		    WXS_BASIC_CAST type, NULL,
16616		    "If <simpleContent> and <extension> is used, the "
16617		    "base type must be a simple type. The base type '%s' "
16618		    "is a complex type",
16619		    xmlSchemaFormatQName(&str, base->targetNamespace,
16620		    base->name));
16621	    }
16622	    FREE_AND_NULL(str)
16623	}
16624    }
16625    /*
16626    * SPEC (3) "The corresponding complex type definition component must
16627    * satisfy the conditions set out in Constraints on Complex Type
16628    * Definition Schema Components (�3.4.6);"
16629    * NOTE (3) will be done in xmlSchemaTypeFixup().
16630    */
16631    /*
16632    * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16633    * above for {attribute wildcard} is satisfied, the intensional
16634    * intersection must be expressible, as defined in Attribute Wildcard
16635    * Intersection (�3.10.6).
16636    * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16637    */
16638    return (ret);
16639}
16640
16641#ifdef ENABLE_PARTICLE_RESTRICTION
16642/**
16643 * xmlSchemaCheckParticleRangeOK:
16644 * @ctxt:  the schema parser context
16645 * @type:  the complex type definition
16646 *
16647 * (3.9.6) Constraints on Particle Schema Components
16648 * Schema Component Constraint:
16649 * Occurrence Range OK (range-ok)
16650 *
16651 * STATUS: complete
16652 *
16653 * Returns 0 if the constraints are satisfied, a positive
16654 * error code if not and -1 if an internal error occured.
16655 */
16656static int
16657xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16658			      int bmin, int bmax)
16659{
16660    if (rmin < bmin)
16661	return (1);
16662    if ((bmax != UNBOUNDED) &&
16663	(rmax > bmax))
16664	return (1);
16665    return (0);
16666}
16667
16668/**
16669 * xmlSchemaCheckRCaseNameAndTypeOK:
16670 * @ctxt:  the schema parser context
16671 * @r: the restricting element declaration particle
16672 * @b: the base element declaration particle
16673 *
16674 * (3.9.6) Constraints on Particle Schema Components
16675 * Schema Component Constraint:
16676 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16677 * (rcase-NameAndTypeOK)
16678 *
16679 * STATUS:
16680 *   MISSING (3.2.3)
16681 *   CLARIFY: (3.2.2)
16682 *
16683 * Returns 0 if the constraints are satisfied, a positive
16684 * error code if not and -1 if an internal error occured.
16685 */
16686static int
16687xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16688				 xmlSchemaParticlePtr r,
16689				 xmlSchemaParticlePtr b)
16690{
16691    xmlSchemaElementPtr elemR, elemB;
16692
16693    /* TODO: Error codes (rcase-NameAndTypeOK). */
16694    elemR = (xmlSchemaElementPtr) r->children;
16695    elemB = (xmlSchemaElementPtr) b->children;
16696    /*
16697    * SPEC (1) "The declarations' {name}s and {target namespace}s are
16698    * the same."
16699    */
16700    if ((elemR != elemB) &&
16701	((! xmlStrEqual(elemR->name, elemB->name)) ||
16702	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16703	return (1);
16704    /*
16705    * SPEC (2) "R's occurrence range is a valid restriction of B's
16706    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16707    */
16708    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16709	    b->minOccurs, b->maxOccurs) != 0)
16710	return (1);
16711    /*
16712    * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16713    * {scope} are global."
16714    */
16715    if (elemR == elemB)
16716	return (0);
16717    /*
16718    * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16719    */
16720    if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16721	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16722	 return (1);
16723    /*
16724    * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16725    * or is not fixed, or R's declaration's {value constraint} is fixed
16726    * with the same value."
16727    */
16728    if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16729	((elemR->value == NULL) ||
16730	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16731	 /* TODO: Equality of the initial value or normalized or canonical? */
16732	 (! xmlStrEqual(elemR->value, elemB->value))))
16733	 return (1);
16734    /*
16735    * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16736    * definitions} is a subset of B's declaration's {identity-constraint
16737    * definitions}, if any."
16738    */
16739    if (elemB->idcs != NULL) {
16740	/* TODO */
16741    }
16742    /*
16743    * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16744    * superset of B's declaration's {disallowed substitutions}."
16745    */
16746    if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16747	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16748	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16749	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16750	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16751	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16752	 return (1);
16753    /*
16754    * SPEC (3.2.5) "R's {type definition} is validly derived given
16755    * {extension, list, union} from B's {type definition}"
16756    *
16757    * BADSPEC TODO: What's the point of adding "list" and "union" to the
16758    * set, if the corresponding constraints handle "restriction" and
16759    * "extension" only?
16760    *
16761    */
16762    {
16763	int set = 0;
16764
16765	set |= SUBSET_EXTENSION;
16766	set |= SUBSET_LIST;
16767	set |= SUBSET_UNION;
16768	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16769	    elemB->subtypes, set) != 0)
16770	    return (1);
16771    }
16772    return (0);
16773}
16774
16775/**
16776 * xmlSchemaCheckRCaseNSCompat:
16777 * @ctxt:  the schema parser context
16778 * @r: the restricting element declaration particle
16779 * @b: the base wildcard particle
16780 *
16781 * (3.9.6) Constraints on Particle Schema Components
16782 * Schema Component Constraint:
16783 * Particle Derivation OK (Elt:Any -- NSCompat)
16784 * (rcase-NSCompat)
16785 *
16786 * STATUS: complete
16787 *
16788 * Returns 0 if the constraints are satisfied, a positive
16789 * error code if not and -1 if an internal error occured.
16790 */
16791static int
16792xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16793			    xmlSchemaParticlePtr r,
16794			    xmlSchemaParticlePtr b)
16795{
16796    /* TODO:Error codes (rcase-NSCompat). */
16797    /*
16798    * SPEC "For an element declaration particle to be a �valid restriction�
16799    * of a wildcard particle all of the following must be true:"
16800    *
16801    * SPEC (1) "The element declaration's {target namespace} is �valid�
16802    * with respect to the wildcard's {namespace constraint} as defined by
16803    * Wildcard allows Namespace Name (�3.10.4)."
16804    */
16805    if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16806	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16807	return (1);
16808    /*
16809    * SPEC (2) "R's occurrence range is a valid restriction of B's
16810    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16811    */
16812    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16813	    b->minOccurs, b->maxOccurs) != 0)
16814	return (1);
16815
16816    return (0);
16817}
16818
16819/**
16820 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16821 * @ctxt:  the schema parser context
16822 * @r: the restricting element declaration particle
16823 * @b: the base model group particle
16824 *
16825 * (3.9.6) Constraints on Particle Schema Components
16826 * Schema Component Constraint:
16827 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16828 * (rcase-RecurseAsIfGroup)
16829 *
16830 * STATUS: TODO
16831 *
16832 * Returns 0 if the constraints are satisfied, a positive
16833 * error code if not and -1 if an internal error occured.
16834 */
16835static int
16836xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16837				    xmlSchemaParticlePtr r,
16838				    xmlSchemaParticlePtr b)
16839{
16840    /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16841    TODO
16842    return (0);
16843}
16844
16845/**
16846 * xmlSchemaCheckRCaseNSSubset:
16847 * @ctxt:  the schema parser context
16848 * @r: the restricting wildcard particle
16849 * @b: the base wildcard particle
16850 *
16851 * (3.9.6) Constraints on Particle Schema Components
16852 * Schema Component Constraint:
16853 * Particle Derivation OK (Any:Any -- NSSubset)
16854 * (rcase-NSSubset)
16855 *
16856 * STATUS: complete
16857 *
16858 * Returns 0 if the constraints are satisfied, a positive
16859 * error code if not and -1 if an internal error occured.
16860 */
16861static int
16862xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16863				    xmlSchemaParticlePtr r,
16864				    xmlSchemaParticlePtr b,
16865				    int isAnyTypeBase)
16866{
16867    /* TODO: Error codes (rcase-NSSubset). */
16868    /*
16869    * SPEC (1) "R's occurrence range is a valid restriction of B's
16870    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16871    */
16872    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16873	    b->minOccurs, b->maxOccurs))
16874	return (1);
16875    /*
16876    * SPEC (2) "R's {namespace constraint} must be an intensional subset
16877    * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16878    */
16879    if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16880	(xmlSchemaWildcardPtr) b->children))
16881	return (1);
16882    /*
16883    * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16884    * definition�, R's {process contents} must be identical to or stronger
16885    * than B's {process contents}, where strict is stronger than lax is
16886    * stronger than skip."
16887    */
16888    if (! isAnyTypeBase) {
16889	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16890	    ((xmlSchemaWildcardPtr) b->children)->processContents)
16891	    return (1);
16892    }
16893
16894    return (0);
16895}
16896
16897/**
16898 * xmlSchemaCheckCOSParticleRestrict:
16899 * @ctxt:  the schema parser context
16900 * @type:  the complex type definition
16901 *
16902 * (3.9.6) Constraints on Particle Schema Components
16903 * Schema Component Constraint:
16904 * Particle Valid (Restriction) (cos-particle-restrict)
16905 *
16906 * STATUS: TODO
16907 *
16908 * Returns 0 if the constraints are satisfied, a positive
16909 * error code if not and -1 if an internal error occured.
16910 */
16911static int
16912xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16913				  xmlSchemaParticlePtr r,
16914				  xmlSchemaParticlePtr b)
16915{
16916    int ret = 0;
16917
16918    /*part = WXS_TYPE_PARTICLE(type);
16919    basePart = WXS_TYPE_PARTICLE(base);
16920    */
16921
16922    TODO
16923
16924    /*
16925    * SPEC (1) "They are the same particle."
16926    */
16927    if (r == b)
16928	return (0);
16929
16930
16931    return (0);
16932}
16933
16934/**
16935 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16936 * @ctxt:  the schema parser context
16937 * @r: the model group particle
16938 * @b: the base wildcard particle
16939 *
16940 * (3.9.6) Constraints on Particle Schema Components
16941 * Schema Component Constraint:
16942 * Particle Derivation OK (All/Choice/Sequence:Any --
16943 *                         NSRecurseCheckCardinality)
16944 * (rcase-NSRecurseCheckCardinality)
16945 *
16946 * STATUS: TODO: subst-groups
16947 *
16948 * Returns 0 if the constraints are satisfied, a positive
16949 * error code if not and -1 if an internal error occured.
16950 */
16951static int
16952xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16953					     xmlSchemaParticlePtr r,
16954					     xmlSchemaParticlePtr b)
16955{
16956    xmlSchemaParticlePtr part;
16957    /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16958    if ((r->children == NULL) || (r->children->children == NULL))
16959	return (-1);
16960    /*
16961    * SPEC "For a group particle to be a �valid restriction� of a
16962    * wildcard particle..."
16963    *
16964    * SPEC (1) "Every member of the {particles} of the group is a �valid
16965    * restriction� of the wildcard as defined by
16966    * Particle Valid (Restriction) (�3.9.6)."
16967    */
16968    part = (xmlSchemaParticlePtr) r->children->children;
16969    do {
16970	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16971	    return (1);
16972	part = (xmlSchemaParticlePtr) part->next;
16973    } while (part != NULL);
16974    /*
16975    * SPEC (2) "The effective total range of the group [...] is a
16976    * valid restriction of B's occurrence range as defined by
16977    * Occurrence Range OK (�3.9.6)."
16978    */
16979    if (xmlSchemaCheckParticleRangeOK(
16980	    xmlSchemaGetParticleTotalRangeMin(r),
16981	    xmlSchemaGetParticleTotalRangeMax(r),
16982	    b->minOccurs, b->maxOccurs) != 0)
16983	return (1);
16984    return (0);
16985}
16986
16987/**
16988 * xmlSchemaCheckRCaseRecurse:
16989 * @ctxt:  the schema parser context
16990 * @r: the <all> or <sequence> model group particle
16991 * @b: the base <all> or <sequence> model group particle
16992 *
16993 * (3.9.6) Constraints on Particle Schema Components
16994 * Schema Component Constraint:
16995 * Particle Derivation OK (All:All,Sequence:Sequence --
16996                           Recurse)
16997 * (rcase-Recurse)
16998 *
16999 * STATUS:  ?
17000 * TODO: subst-groups
17001 *
17002 * Returns 0 if the constraints are satisfied, a positive
17003 * error code if not and -1 if an internal error occured.
17004 */
17005static int
17006xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17007			   xmlSchemaParticlePtr r,
17008			   xmlSchemaParticlePtr b)
17009{
17010    /* xmlSchemaParticlePtr part; */
17011    /* TODO: Error codes (rcase-Recurse). */
17012    if ((r->children == NULL) || (b->children == NULL) ||
17013	(r->children->type != b->children->type))
17014	return (-1);
17015    /*
17016    * SPEC "For an all or sequence group particle to be a �valid
17017    * restriction� of another group particle with the same {compositor}..."
17018    *
17019    * SPEC (1) "R's occurrence range is a valid restriction of B's
17020    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17021    */
17022    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17023	    b->minOccurs, b->maxOccurs))
17024	return (1);
17025
17026
17027    return (0);
17028}
17029
17030#endif
17031
17032#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17033    xmlSchemaPCustomErrExt(pctxt,      \
17034	XML_SCHEMAP_INVALID_FACET_VALUE, \
17035	WXS_BASIC_CAST fac1, fac1->node, \
17036	"It is an error for both '%s' and '%s' to be specified on the "\
17037	"same type definition", \
17038	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17039	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17040
17041#define FACET_RESTR_ERR(fac1, msg) \
17042    xmlSchemaPCustomErr(pctxt,      \
17043	XML_SCHEMAP_INVALID_FACET_VALUE, \
17044	WXS_BASIC_CAST fac1, fac1->node, \
17045	msg, NULL);
17046
17047#define FACET_RESTR_FIXED_ERR(fac) \
17048    xmlSchemaPCustomErr(pctxt, \
17049	XML_SCHEMAP_INVALID_FACET_VALUE, \
17050	WXS_BASIC_CAST fac, fac->node, \
17051	"The base type's facet is 'fixed', thus the value must not " \
17052	"differ", NULL);
17053
17054static void
17055xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17056			xmlSchemaFacetPtr facet1,
17057			xmlSchemaFacetPtr facet2,
17058			int lessGreater,
17059			int orEqual,
17060			int ofBase)
17061{
17062    xmlChar *msg = NULL;
17063
17064    msg = xmlStrdup(BAD_CAST "'");
17065    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17066    msg = xmlStrcat(msg, BAD_CAST "' has to be");
17067    if (lessGreater == 0)
17068	msg = xmlStrcat(msg, BAD_CAST " equal to");
17069    if (lessGreater == 1)
17070	msg = xmlStrcat(msg, BAD_CAST " greater than");
17071    else
17072	msg = xmlStrcat(msg, BAD_CAST " less than");
17073
17074    if (orEqual)
17075	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17076    msg = xmlStrcat(msg, BAD_CAST " '");
17077    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17078    if (ofBase)
17079	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17080    else
17081	msg = xmlStrcat(msg, BAD_CAST "'");
17082
17083    xmlSchemaPCustomErr(pctxt,
17084	XML_SCHEMAP_INVALID_FACET_VALUE,
17085	WXS_BASIC_CAST facet1, NULL,
17086	(const char *) msg, NULL);
17087
17088    if (msg != NULL)
17089	xmlFree(msg);
17090}
17091
17092/*
17093* xmlSchemaDeriveAndValidateFacets:
17094*
17095* Schema Component Constraint: Simple Type Restriction (Facets)
17096* (st-restrict-facets)
17097*/
17098static int
17099xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17100				 xmlSchemaTypePtr type)
17101{
17102    xmlSchemaTypePtr base = type->baseType;
17103    xmlSchemaFacetLinkPtr link, cur, last = NULL;
17104    xmlSchemaFacetPtr facet, bfacet,
17105	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17106	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17107	fmininc = NULL, fmaxinc = NULL,
17108	fminexc = NULL, fmaxexc = NULL,
17109	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17110	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17111	bfmininc = NULL, bfmaxinc = NULL,
17112	bfminexc = NULL, bfmaxexc = NULL;
17113    int res; /* err = 0, fixedErr; */
17114
17115    /*
17116    * SPEC st-restrict-facets 1:
17117    * "The {variety} of R is the same as that of B."
17118    */
17119    /*
17120    * SPEC st-restrict-facets 2:
17121    * "If {variety} is atomic, the {primitive type definition}
17122    * of R is the same as that of B."
17123    *
17124    * NOTE: we leave 1 & 2 out for now, since this will be
17125    * satisfied by the derivation process.
17126    * CONSTRUCTION TODO: Maybe needed if using a construction API.
17127    */
17128    /*
17129    * SPEC st-restrict-facets 3:
17130    * "The {facets} of R are the union of S and the {facets}
17131    * of B, eliminating duplicates. To eliminate duplicates,
17132    * when a facet of the same kind occurs in both S and the
17133    * {facets} of B, the one in the {facets} of B is not
17134    * included, with the exception of enumeration and pattern
17135    * facets, for which multiple occurrences with distinct values
17136    * are allowed."
17137    */
17138
17139    if ((type->facetSet == NULL) && (base->facetSet == NULL))
17140	return (0);
17141
17142    last = type->facetSet;
17143    if (last != NULL)
17144	while (last->next != NULL)
17145	    last = last->next;
17146
17147    for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17148	facet = cur->facet;
17149	switch (facet->type) {
17150	    case XML_SCHEMA_FACET_LENGTH:
17151		flength = facet; break;
17152	    case XML_SCHEMA_FACET_MINLENGTH:
17153		fminlen = facet; break;
17154	    case XML_SCHEMA_FACET_MININCLUSIVE:
17155		fmininc = facet; break;
17156	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17157		fminexc = facet; break;
17158	    case XML_SCHEMA_FACET_MAXLENGTH:
17159		fmaxlen = facet; break;
17160	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17161		fmaxinc = facet; break;
17162	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17163		fmaxexc = facet; break;
17164	    case XML_SCHEMA_FACET_TOTALDIGITS:
17165		ftotdig = facet; break;
17166	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17167		ffracdig = facet; break;
17168	    default:
17169		break;
17170	}
17171    }
17172    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17173	facet = cur->facet;
17174	switch (facet->type) {
17175	    case XML_SCHEMA_FACET_LENGTH:
17176		bflength = facet; break;
17177	    case XML_SCHEMA_FACET_MINLENGTH:
17178		bfminlen = facet; break;
17179	    case XML_SCHEMA_FACET_MININCLUSIVE:
17180		bfmininc = facet; break;
17181	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17182		bfminexc = facet; break;
17183	    case XML_SCHEMA_FACET_MAXLENGTH:
17184		bfmaxlen = facet; break;
17185	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17186		bfmaxinc = facet; break;
17187	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17188		bfmaxexc = facet; break;
17189	    case XML_SCHEMA_FACET_TOTALDIGITS:
17190		bftotdig = facet; break;
17191	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17192		bffracdig = facet; break;
17193	    default:
17194		break;
17195	}
17196    }
17197    /*
17198    * length and minLength or maxLength (2.2) + (3.2)
17199    */
17200    if (flength && (fminlen || fmaxlen)) {
17201	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17202	    "either of 'minLength' or 'maxLength' to be specified on "
17203	    "the same type definition")
17204    }
17205    /*
17206    * Mutual exclusions in the same derivation step.
17207    */
17208    if ((fmaxinc) && (fmaxexc)) {
17209	/*
17210	* SCC "maxInclusive and maxExclusive"
17211	*/
17212	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17213    }
17214    if ((fmininc) && (fminexc)) {
17215	/*
17216	* SCC "minInclusive and minExclusive"
17217	*/
17218	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17219    }
17220
17221    if (flength && bflength) {
17222	/*
17223	* SCC "length valid restriction"
17224	* The values have to be equal.
17225	*/
17226	res = xmlSchemaCompareValues(flength->val, bflength->val);
17227	if (res == -2)
17228	    goto internal_error;
17229	if (res != 0)
17230	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17231	if ((res != 0) && (bflength->fixed)) {
17232	    FACET_RESTR_FIXED_ERR(flength)
17233	}
17234
17235    }
17236    if (fminlen && bfminlen) {
17237	/*
17238	* SCC "minLength valid restriction"
17239	* minLength >= BASE minLength
17240	*/
17241	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17242	if (res == -2)
17243	    goto internal_error;
17244	if (res == -1)
17245	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17246	if ((res != 0) && (bfminlen->fixed)) {
17247	    FACET_RESTR_FIXED_ERR(fminlen)
17248	}
17249    }
17250    if (fmaxlen && bfmaxlen) {
17251	/*
17252	* SCC "maxLength valid restriction"
17253	* maxLength <= BASE minLength
17254	*/
17255	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17256	if (res == -2)
17257	    goto internal_error;
17258	if (res == 1)
17259	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17260	if ((res != 0) && (bfmaxlen->fixed)) {
17261	    FACET_RESTR_FIXED_ERR(fmaxlen)
17262	}
17263    }
17264    /*
17265    * SCC "length and minLength or maxLength"
17266    */
17267    if (! flength)
17268	flength = bflength;
17269    if (flength) {
17270	if (! fminlen)
17271	    flength = bflength;
17272	if (fminlen) {
17273	    /* (1.1) length >= minLength */
17274	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17275	    if (res == -2)
17276		goto internal_error;
17277	    if (res == -1)
17278		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17279	}
17280	if (! fmaxlen)
17281	    fmaxlen = bfmaxlen;
17282	if (fmaxlen) {
17283	    /* (2.1) length <= maxLength */
17284	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17285	    if (res == -2)
17286		goto internal_error;
17287	    if (res == 1)
17288		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17289	}
17290    }
17291    if (fmaxinc) {
17292	/*
17293	* "maxInclusive"
17294	*/
17295	if (fmininc) {
17296	    /* SCC "maxInclusive >= minInclusive" */
17297	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17298	    if (res == -2)
17299		goto internal_error;
17300	    if (res == -1) {
17301		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17302	    }
17303	}
17304	/*
17305	* SCC "maxInclusive valid restriction"
17306	*/
17307	if (bfmaxinc) {
17308	    /* maxInclusive <= BASE maxInclusive */
17309	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17310	    if (res == -2)
17311		goto internal_error;
17312	    if (res == 1)
17313		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17314	    if ((res != 0) && (bfmaxinc->fixed)) {
17315		FACET_RESTR_FIXED_ERR(fmaxinc)
17316	    }
17317	}
17318	if (bfmaxexc) {
17319	    /* maxInclusive < BASE maxExclusive */
17320	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17321	    if (res == -2)
17322		goto internal_error;
17323	    if (res != -1) {
17324		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17325	    }
17326	}
17327	if (bfmininc) {
17328	    /* maxInclusive >= BASE minInclusive */
17329	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17330	    if (res == -2)
17331		goto internal_error;
17332	    if (res == -1) {
17333		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17334	    }
17335	}
17336	if (bfminexc) {
17337	    /* maxInclusive > BASE minExclusive */
17338	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17339	    if (res == -2)
17340		goto internal_error;
17341	    if (res != 1) {
17342		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17343	    }
17344	}
17345    }
17346    if (fmaxexc) {
17347	/*
17348	* "maxExclusive >= minExclusive"
17349	*/
17350	if (fminexc) {
17351	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17352	    if (res == -2)
17353		goto internal_error;
17354	    if (res == -1) {
17355		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17356	    }
17357	}
17358	/*
17359	* "maxExclusive valid restriction"
17360	*/
17361	if (bfmaxexc) {
17362	    /* maxExclusive <= BASE maxExclusive */
17363	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17364	    if (res == -2)
17365		goto internal_error;
17366	    if (res == 1) {
17367		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17368	    }
17369	    if ((res != 0) && (bfmaxexc->fixed)) {
17370		FACET_RESTR_FIXED_ERR(fmaxexc)
17371	    }
17372	}
17373	if (bfmaxinc) {
17374	    /* maxExclusive <= BASE maxInclusive */
17375	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17376	    if (res == -2)
17377		goto internal_error;
17378	    if (res == 1) {
17379		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17380	    }
17381	}
17382	if (bfmininc) {
17383	    /* maxExclusive > BASE minInclusive */
17384	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17385	    if (res == -2)
17386		goto internal_error;
17387	    if (res != 1) {
17388		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17389	    }
17390	}
17391	if (bfminexc) {
17392	    /* maxExclusive > BASE minExclusive */
17393	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17394	    if (res == -2)
17395		goto internal_error;
17396	    if (res != 1) {
17397		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17398	    }
17399	}
17400    }
17401    if (fminexc) {
17402	/*
17403	* "minExclusive < maxInclusive"
17404	*/
17405	if (fmaxinc) {
17406	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17407	    if (res == -2)
17408		goto internal_error;
17409	    if (res != -1) {
17410		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17411	    }
17412	}
17413	/*
17414	* "minExclusive valid restriction"
17415	*/
17416	if (bfminexc) {
17417	    /* minExclusive >= BASE minExclusive */
17418	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17419	    if (res == -2)
17420		goto internal_error;
17421	    if (res == -1) {
17422		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17423	    }
17424	    if ((res != 0) && (bfminexc->fixed)) {
17425		FACET_RESTR_FIXED_ERR(fminexc)
17426	    }
17427	}
17428	if (bfmaxinc) {
17429	    /* minExclusive <= BASE maxInclusive */
17430	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17431	    if (res == -2)
17432		goto internal_error;
17433	    if (res == 1) {
17434		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17435	    }
17436	}
17437	if (bfmininc) {
17438	    /* minExclusive >= BASE minInclusive */
17439	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17440	    if (res == -2)
17441		goto internal_error;
17442	    if (res == -1) {
17443		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17444	    }
17445	}
17446	if (bfmaxexc) {
17447	    /* minExclusive < BASE maxExclusive */
17448	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17449	    if (res == -2)
17450		goto internal_error;
17451	    if (res != -1) {
17452		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17453	    }
17454	}
17455    }
17456    if (fmininc) {
17457	/*
17458	* "minInclusive < maxExclusive"
17459	*/
17460	if (fmaxexc) {
17461	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17462	    if (res == -2)
17463		goto internal_error;
17464	    if (res != -1) {
17465		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17466	    }
17467	}
17468	/*
17469	* "minExclusive valid restriction"
17470	*/
17471	if (bfmininc) {
17472	    /* minInclusive >= BASE minInclusive */
17473	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17474	    if (res == -2)
17475		goto internal_error;
17476	    if (res == -1) {
17477		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17478	    }
17479	    if ((res != 0) && (bfmininc->fixed)) {
17480		FACET_RESTR_FIXED_ERR(fmininc)
17481	    }
17482	}
17483	if (bfmaxinc) {
17484	    /* minInclusive <= BASE maxInclusive */
17485	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17486	    if (res == -2)
17487		goto internal_error;
17488	    if (res == 1) {
17489		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17490	    }
17491	}
17492	if (bfminexc) {
17493	    /* minInclusive > BASE minExclusive */
17494	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17495	    if (res == -2)
17496		goto internal_error;
17497	    if (res != 1)
17498		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17499	}
17500	if (bfmaxexc) {
17501	    /* minInclusive < BASE maxExclusive */
17502	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17503	    if (res == -2)
17504		goto internal_error;
17505	    if (res != -1)
17506		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17507	}
17508    }
17509    if (ftotdig && bftotdig) {
17510	/*
17511	* SCC " totalDigits valid restriction"
17512	* totalDigits <= BASE totalDigits
17513	*/
17514	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17515	if (res == -2)
17516	    goto internal_error;
17517	if (res == 1)
17518	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17519	    -1, 1, 1);
17520	if ((res != 0) && (bftotdig->fixed)) {
17521	    FACET_RESTR_FIXED_ERR(ftotdig)
17522	}
17523    }
17524    if (ffracdig && bffracdig) {
17525	/*
17526	* SCC  "fractionDigits valid restriction"
17527	* fractionDigits <= BASE fractionDigits
17528	*/
17529	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17530	if (res == -2)
17531	    goto internal_error;
17532	if (res == 1)
17533	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17534	    -1, 1, 1);
17535	if ((res != 0) && (bffracdig->fixed)) {
17536	    FACET_RESTR_FIXED_ERR(ffracdig)
17537	}
17538    }
17539    /*
17540    * SCC "fractionDigits less than or equal to totalDigits"
17541    */
17542    if (! ftotdig)
17543	ftotdig = bftotdig;
17544    if (! ffracdig)
17545	ffracdig = bffracdig;
17546    if (ftotdig && ffracdig) {
17547	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17548	if (res == -2)
17549	    goto internal_error;
17550	if (res == 1)
17551	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17552		-1, 1, 0);
17553    }
17554    /*
17555    * *Enumerations* won' be added here, since only the first set
17556    * of enumerations in the ancestor-or-self axis is used
17557    * for validation, plus we need to use the base type of those
17558    * enumerations for whitespace.
17559    *
17560    * *Patterns*: won't be add here, since they are ORed at
17561    * type level and ANDed at ancestor level. This will
17562    * happed during validation by walking the base axis
17563    * of the type.
17564    */
17565    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17566	bfacet = cur->facet;
17567	/*
17568	* Special handling of enumerations and patterns.
17569	* TODO: hmm, they should not appear in the set, so remove this.
17570	*/
17571	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17572	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17573	    continue;
17574	/*
17575	* Search for a duplicate facet in the current type.
17576	*/
17577	link = type->facetSet;
17578	/* err = 0; */
17579	/* fixedErr = 0; */
17580	while (link != NULL) {
17581	    facet = link->facet;
17582	    if (facet->type == bfacet->type) {
17583		switch (facet->type) {
17584		    case XML_SCHEMA_FACET_WHITESPACE:
17585			/*
17586			* The whitespace must be stronger.
17587			*/
17588			if (facet->whitespace < bfacet->whitespace) {
17589			    FACET_RESTR_ERR(flength,
17590				"The 'whitespace' value has to be equal to "
17591				"or stronger than the 'whitespace' value of "
17592				"the base type")
17593			}
17594			if ((bfacet->fixed) &&
17595			    (facet->whitespace != bfacet->whitespace)) {
17596			    FACET_RESTR_FIXED_ERR(facet)
17597			}
17598			break;
17599		    default:
17600			break;
17601		}
17602		/* Duplicate found. */
17603		break;
17604	    }
17605	    link = link->next;
17606	}
17607	/*
17608	* If no duplicate was found: add the base types's facet
17609	* to the set.
17610	*/
17611	if (link == NULL) {
17612	    link = (xmlSchemaFacetLinkPtr)
17613		xmlMalloc(sizeof(xmlSchemaFacetLink));
17614	    if (link == NULL) {
17615		xmlSchemaPErrMemory(pctxt,
17616		    "deriving facets, creating a facet link", NULL);
17617		return (-1);
17618	    }
17619	    link->facet = cur->facet;
17620	    link->next = NULL;
17621	    if (last == NULL)
17622		type->facetSet = link;
17623	    else
17624		last->next = link;
17625	    last = link;
17626	}
17627
17628    }
17629
17630    return (0);
17631internal_error:
17632    PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17633	"an error occured");
17634    return (-1);
17635}
17636
17637static int
17638xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17639					     xmlSchemaTypePtr type)
17640{
17641    xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17642    /*
17643    * The actual value is then formed by replacing any union type
17644    * definition in the �explicit members� with the members of their
17645    * {member type definitions}, in order.
17646    *
17647    * TODO: There's a bug entry at
17648    * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17649    * which indicates that we'll keep the union types the future.
17650    */
17651    link = type->memberTypes;
17652    while (link != NULL) {
17653
17654	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17655	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17656
17657	if (WXS_IS_UNION(link->type)) {
17658	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17659	    if (subLink != NULL) {
17660		link->type = subLink->type;
17661		if (subLink->next != NULL) {
17662		    lastLink = link->next;
17663		    subLink = subLink->next;
17664		    prevLink = link;
17665		    while (subLink != NULL) {
17666			newLink = (xmlSchemaTypeLinkPtr)
17667			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17668			if (newLink == NULL) {
17669			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17670				NULL);
17671			    return (-1);
17672			}
17673			newLink->type = subLink->type;
17674			prevLink->next = newLink;
17675			prevLink = newLink;
17676			newLink->next = lastLink;
17677
17678			subLink = subLink->next;
17679		    }
17680		}
17681	    }
17682	}
17683	link = link->next;
17684    }
17685    return (0);
17686}
17687
17688static void
17689xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17690{
17691    int has = 0, needVal = 0, normVal = 0;
17692
17693    has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17694    if (has) {
17695	needVal = (type->baseType->flags &
17696	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17697	normVal = (type->baseType->flags &
17698	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17699    }
17700    if (type->facets != NULL) {
17701	xmlSchemaFacetPtr fac;
17702
17703	for (fac = type->facets; fac != NULL; fac = fac->next) {
17704	    switch (fac->type) {
17705		case XML_SCHEMA_FACET_WHITESPACE:
17706		    break;
17707		case XML_SCHEMA_FACET_PATTERN:
17708		    normVal = 1;
17709		    has = 1;
17710		    break;
17711		case XML_SCHEMA_FACET_ENUMERATION:
17712		    needVal = 1;
17713		    normVal = 1;
17714		    has = 1;
17715		    break;
17716		default:
17717		    has = 1;
17718		    break;
17719	    }
17720	}
17721    }
17722    if (normVal)
17723	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17724    if (needVal)
17725	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17726    if (has)
17727	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17728
17729    if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17730	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17731	/*
17732	* OPTIMIZE VAL TODO: Some facets need a computed value.
17733	*/
17734	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17735	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17736	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17737	}
17738    }
17739}
17740
17741static int
17742xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17743{
17744
17745
17746    /*
17747    * Evaluate the whitespace-facet value.
17748    */
17749    if (WXS_IS_LIST(type)) {
17750	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17751	return (0);
17752    } else if (WXS_IS_UNION(type))
17753	return (0);
17754
17755    if (type->facetSet != NULL) {
17756	xmlSchemaFacetLinkPtr lin;
17757
17758	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17759	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17760		switch (lin->facet->whitespace) {
17761		case XML_SCHEMAS_FACET_PRESERVE:
17762		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17763		    break;
17764		case XML_SCHEMAS_FACET_REPLACE:
17765		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17766		    break;
17767		case XML_SCHEMAS_FACET_COLLAPSE:
17768		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17769		    break;
17770		default:
17771		    return (-1);
17772		}
17773		return (0);
17774	    }
17775	}
17776    }
17777    /*
17778    * For all �atomic� datatypes other than string (and types �derived�
17779    * by �restriction� from it) the value of whiteSpace is fixed to
17780    * collapse
17781    */
17782    {
17783	xmlSchemaTypePtr anc;
17784
17785	for (anc = type->baseType; anc != NULL &&
17786		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17787		anc = anc->baseType) {
17788
17789	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17790		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17791		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17792
17793		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17794		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17795		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17796
17797		} else
17798		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17799		break;
17800	    }
17801	}
17802    }
17803    return (0);
17804}
17805
17806static int
17807xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17808			  xmlSchemaTypePtr type)
17809{
17810    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17811	return(0);
17812    if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17813	return(0);
17814    type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17815
17816    if (WXS_IS_LIST(type)) {
17817	/*
17818	* Corresponds to <simpleType><list>...
17819	*/
17820	if (type->subtypes == NULL) {
17821	    /*
17822	    * This one is really needed, so get out.
17823	    */
17824	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17825		"list type has no item-type assigned");
17826	    return(-1);
17827	}
17828    } else if (WXS_IS_UNION(type)) {
17829	/*
17830	* Corresponds to <simpleType><union>...
17831	*/
17832	if (type->memberTypes == NULL) {
17833	    /*
17834	    * This one is really needed, so get out.
17835	    */
17836	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17837		"union type has no member-types assigned");
17838	    return(-1);
17839	}
17840    } else {
17841	/*
17842	* Corresponds to <simpleType><restriction>...
17843	*/
17844	if (type->baseType == NULL) {
17845	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17846		"type has no base-type assigned");
17847	    return(-1);
17848	}
17849	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17850	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17851		return(-1);
17852	/*
17853	* Variety
17854	* If the <restriction> alternative is chosen, then the
17855	* {variety} of the {base type definition}.
17856	*/
17857	if (WXS_IS_ATOMIC(type->baseType))
17858	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17859	else if (WXS_IS_LIST(type->baseType)) {
17860	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17861	    /*
17862	    * Inherit the itemType.
17863	    */
17864	    type->subtypes = type->baseType->subtypes;
17865	} else if (WXS_IS_UNION(type->baseType)) {
17866	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17867	    /*
17868	    * NOTE that we won't assign the memberTypes of the base,
17869	    * since this will make trouble when freeing them; we will
17870	    * use a lookup function to access them instead.
17871	    */
17872	}
17873    }
17874    return(0);
17875}
17876
17877#ifdef DEBUG_TYPE
17878static void
17879xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17880		       xmlSchemaTypePtr type)
17881{
17882    if (type->node != NULL) {
17883        xmlGenericError(xmlGenericErrorContext,
17884                        "Type of %s : %s:%d :", name,
17885                        type->node->doc->URL,
17886                        xmlGetLineNo(type->node));
17887    } else {
17888        xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17889    }
17890    if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17891	switch (type->contentType) {
17892	    case XML_SCHEMA_CONTENT_SIMPLE:
17893		xmlGenericError(xmlGenericErrorContext, "simple\n");
17894		break;
17895	    case XML_SCHEMA_CONTENT_ELEMENTS:
17896		xmlGenericError(xmlGenericErrorContext, "elements\n");
17897		break;
17898	    case XML_SCHEMA_CONTENT_UNKNOWN:
17899		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17900		break;
17901	    case XML_SCHEMA_CONTENT_EMPTY:
17902		xmlGenericError(xmlGenericErrorContext, "empty\n");
17903		break;
17904	    case XML_SCHEMA_CONTENT_MIXED:
17905		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17906		    type->subtypes))
17907		    xmlGenericError(xmlGenericErrorContext,
17908			"mixed as emptiable particle\n");
17909		else
17910		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
17911		break;
17912		/* Removed, since not used. */
17913		/*
17914		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17915		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17916		break;
17917		*/
17918	    case XML_SCHEMA_CONTENT_BASIC:
17919		xmlGenericError(xmlGenericErrorContext, "basic\n");
17920		break;
17921	    default:
17922		xmlGenericError(xmlGenericErrorContext,
17923		    "not registered !!!\n");
17924		break;
17925	}
17926    }
17927}
17928#endif
17929
17930/*
17931* 3.14.6 Constraints on Simple Type Definition Schema Components
17932*/
17933static int
17934xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17935				 xmlSchemaTypePtr type)
17936{
17937    int res, olderrs = pctxt->nberrors;
17938
17939    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17940	return(-1);
17941
17942    if (! WXS_IS_TYPE_NOT_FIXED(type))
17943	return(0);
17944
17945    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17946    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17947
17948    if (type->baseType == NULL) {
17949	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17950	    "missing baseType");
17951	goto exit_failure;
17952    }
17953    if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
17954	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
17955    /*
17956    * If a member type of a union is a union itself, we need to substitute
17957    * that member type for its member types.
17958    * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17959    * types in WXS 1.1.
17960    */
17961    if ((type->memberTypes != NULL) &&
17962	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17963	return(-1);
17964    /*
17965    * SPEC src-simple-type 1
17966    * "The corresponding simple type definition, if any, must satisfy
17967    * the conditions set out in Constraints on Simple Type Definition
17968    * Schema Components (�3.14.6)."
17969    */
17970    /*
17971    * Schema Component Constraint: Simple Type Definition Properties Correct
17972    * (st-props-correct)
17973    */
17974    res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17975    HFAILURE HERROR
17976    /*
17977    * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17978    * (cos-st-restricts)
17979    */
17980    res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17981    HFAILURE HERROR
17982    /*
17983    * TODO: Removed the error report, since it got annoying to get an
17984    * extra error report, if anything failed until now.
17985    * Enable this if needed.
17986    *
17987    * xmlSchemaPErr(ctxt, type->node,
17988    *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17989    *    "Simple type '%s' does not satisfy the constraints "
17990    *    "on simple type definitions.\n",
17991    *    type->name, NULL);
17992    */
17993    /*
17994    * Schema Component Constraint: Simple Type Restriction (Facets)
17995    * (st-restrict-facets)
17996    */
17997    res = xmlSchemaCheckFacetValues(type, pctxt);
17998    HFAILURE HERROR
17999    if ((type->facetSet != NULL) ||
18000	(type->baseType->facetSet != NULL)) {
18001	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18002	HFAILURE HERROR
18003    }
18004    /*
18005    * Whitespace value.
18006    */
18007    res = xmlSchemaTypeFixupWhitespace(type);
18008    HFAILURE HERROR
18009    xmlSchemaTypeFixupOptimFacets(type);
18010
18011exit_error:
18012#ifdef DEBUG_TYPE
18013    xmlSchemaDebugFixedType(pctxt, type);
18014#endif
18015    if (olderrs != pctxt->nberrors)
18016	return(pctxt->err);
18017    return(0);
18018
18019exit_failure:
18020#ifdef DEBUG_TYPE
18021    xmlSchemaDebugFixedType(pctxt, type);
18022#endif
18023    return(-1);
18024}
18025
18026static int
18027xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18028			  xmlSchemaTypePtr type)
18029{
18030    int res = 0, olderrs = pctxt->nberrors;
18031    xmlSchemaTypePtr baseType = type->baseType;
18032
18033    if (! WXS_IS_TYPE_NOT_FIXED(type))
18034	return(0);
18035    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18036    if (baseType == NULL) {
18037	PERROR_INT("xmlSchemaFixupComplexType",
18038	    "missing baseType");
18039	goto exit_failure;
18040    }
18041    /*
18042    * Fixup the base type.
18043    */
18044    if (WXS_IS_TYPE_NOT_FIXED(baseType))
18045	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18046    if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18047	/*
18048	* Skip fixup if the base type is invalid.
18049	* TODO: Generate a warning!
18050	*/
18051	return(0);
18052    }
18053    /*
18054    * This basically checks if the base type can be derived.
18055    */
18056    res = xmlSchemaCheckSRCCT(pctxt, type);
18057    HFAILURE HERROR
18058    /*
18059    * Fixup the content type.
18060    */
18061    if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18062	/*
18063	* Corresponds to <complexType><simpleContent>...
18064	*/
18065	if ((WXS_IS_COMPLEX(baseType)) &&
18066	    (baseType->contentTypeDef != NULL) &&
18067	    (WXS_IS_RESTRICTION(type))) {
18068	    xmlSchemaTypePtr contentBase, content;
18069#ifdef ENABLE_NAMED_LOCALS
18070	    char buf[30];
18071	    const xmlChar *tmpname;
18072#endif
18073	    /*
18074	    * SPEC (1) If <restriction> + base type is <complexType>,
18075	    * "whose own {content type} is a simple type..."
18076	    */
18077	    if (type->contentTypeDef != NULL) {
18078		/*
18079		* SPEC (1.1) "the simple type definition corresponding to the
18080		* <simpleType> among the [children] of <restriction> if there
18081		* is one;"
18082		* Note that this "<simpleType> among the [children]" was put
18083		* into ->contentTypeDef during parsing.
18084		*/
18085		contentBase = type->contentTypeDef;
18086		type->contentTypeDef = NULL;
18087	    } else {
18088		/*
18089		* (1.2) "...otherwise (<restriction> has no <simpleType>
18090		* among its [children]), the simple type definition which
18091		* is the {content type} of the ... base type."
18092		*/
18093		contentBase = baseType->contentTypeDef;
18094	    }
18095	    /*
18096	    * SPEC
18097	    * "... a simple type definition which restricts the simple
18098	    * type definition identified in clause 1.1 or clause 1.2
18099	    * with a set of facet components"
18100	    *
18101	    * Create the anonymous simple type, which will be the content
18102	    * type of the complex type.
18103	    */
18104#ifdef ENABLE_NAMED_LOCALS
18105	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18106	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18107	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18108		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18109		type->node, 0);
18110#else
18111	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18112		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18113		type->node, 0);
18114#endif
18115	    if (content == NULL)
18116		goto exit_failure;
18117	    /*
18118	    * We will use the same node as for the <complexType>
18119	    * to have it somehow anchored in the schema doc.
18120	    */
18121	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18122	    content->baseType = contentBase;
18123	    /*
18124	    * Move the facets, previously anchored on the
18125	    * complexType during parsing.
18126	    */
18127	    content->facets = type->facets;
18128	    type->facets = NULL;
18129	    content->facetSet = type->facetSet;
18130	    type->facetSet = NULL;
18131
18132	    type->contentTypeDef = content;
18133	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18134		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18135	    /*
18136	    * Fixup the newly created type. We don't need to check
18137	    * for circularity here.
18138	    */
18139	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18140	    HFAILURE HERROR
18141	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18142	    HFAILURE HERROR
18143
18144	} else if ((WXS_IS_COMPLEX(baseType)) &&
18145	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18146	    (WXS_IS_RESTRICTION(type))) {
18147	    /*
18148	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18149	    * an emptiable particle, then a simple type definition which
18150	    * restricts the <restriction>'s <simpleType> child.
18151	    */
18152	    if ((type->contentTypeDef == NULL) ||
18153		(type->contentTypeDef->baseType == NULL)) {
18154		/*
18155		* TODO: Check if this ever happens.
18156		*/
18157		xmlSchemaPCustomErr(pctxt,
18158		    XML_SCHEMAP_INTERNAL,
18159		    WXS_BASIC_CAST type, NULL,
18160		    "Internal error: xmlSchemaTypeFixup, "
18161		    "complex type '%s': the <simpleContent><restriction> "
18162		    "is missing a <simpleType> child, but was not catched "
18163		    "by xmlSchemaCheckSRCCT()", type->name);
18164		goto exit_failure;
18165	    }
18166	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18167	    /*
18168	    * SPEC (3) If <extension> + base is <complexType> with
18169	    * <simpleType> content, "...then the {content type} of that
18170	    * complex type definition"
18171	    */
18172	    if (baseType->contentTypeDef == NULL) {
18173		/*
18174		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18175		* should have catched this already.
18176		*/
18177		xmlSchemaPCustomErr(pctxt,
18178		    XML_SCHEMAP_INTERNAL,
18179		    WXS_BASIC_CAST type, NULL,
18180		    "Internal error: xmlSchemaTypeFixup, "
18181		    "complex type '%s': the <extension>ed base type is "
18182		    "a complex type with no simple content type",
18183		    type->name);
18184		goto exit_failure;
18185	    }
18186	    type->contentTypeDef = baseType->contentTypeDef;
18187	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18188	    /*
18189	    * SPEC (4) <extension> + base is <simpleType>
18190	    * "... then that simple type definition"
18191	    */
18192	    type->contentTypeDef = baseType;
18193	} else {
18194	    /*
18195	    * TODO: Check if this ever happens.
18196	    */
18197	    xmlSchemaPCustomErr(pctxt,
18198		XML_SCHEMAP_INTERNAL,
18199		WXS_BASIC_CAST type, NULL,
18200		"Internal error: xmlSchemaTypeFixup, "
18201		"complex type '%s' with <simpleContent>: unhandled "
18202		"derivation case", type->name);
18203	    goto exit_failure;
18204	}
18205    } else {
18206	int dummySequence = 0;
18207	xmlSchemaParticlePtr particle =
18208	    (xmlSchemaParticlePtr) type->subtypes;
18209	/*
18210	* Corresponds to <complexType><complexContent>...
18211	*
18212	* NOTE that the effective mixed was already set during parsing of
18213	* <complexType> and <complexContent>; its flag value is
18214	* XML_SCHEMAS_TYPE_MIXED.
18215	*
18216	* Compute the "effective content":
18217	* (2.1.1) + (2.1.2) + (2.1.3)
18218	*/
18219	if ((particle == NULL) ||
18220	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18221	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18222	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18223	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18224	    (particle->minOccurs == 0))) &&
18225	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18226	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18227		/*
18228		* SPEC (2.1.4) "If the �effective mixed� is true, then
18229		* a particle whose properties are as follows:..."
18230		*
18231		* Empty sequence model group with
18232		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18233		* NOTE that we sill assign it the <complexType> node to
18234		* somehow anchor it in the doc.
18235		*/
18236		if ((particle == NULL) ||
18237		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18238		    /*
18239		    * Create the particle.
18240		    */
18241		    particle = xmlSchemaAddParticle(pctxt,
18242			type->node, 1, 1);
18243		    if (particle == NULL)
18244			goto exit_failure;
18245		    /*
18246		    * Create the model group.
18247		    */ /* URGENT TODO: avoid adding to pending items. */
18248		    particle->children = (xmlSchemaTreeItemPtr)
18249			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18250			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18251		    if (particle->children == NULL)
18252			goto exit_failure;
18253
18254		    type->subtypes = (xmlSchemaTypePtr) particle;
18255		}
18256		dummySequence = 1;
18257		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18258	    } else {
18259		/*
18260		* SPEC (2.1.5) "otherwise empty"
18261		*/
18262		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18263	    }
18264	} else {
18265	    /*
18266	    * SPEC (2.2) "otherwise the particle corresponding to the
18267	    * <all>, <choice>, <group> or <sequence> among the
18268	    * [children]."
18269	    */
18270	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18271	}
18272	/*
18273	* Compute the "content type".
18274	*/
18275	if (WXS_IS_RESTRICTION(type)) {
18276	    /*
18277	    * SPEC (3.1) "If <restriction>..."
18278	    * (3.1.1) + (3.1.2) */
18279	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18280		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18281		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18282	    }
18283	} else {
18284	    /*
18285	    * SPEC (3.2) "If <extension>..."
18286	    */
18287	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18288		/*
18289		* SPEC (3.2.1)
18290		*/
18291		type->contentType = baseType->contentType;
18292		type->subtypes = baseType->subtypes;
18293		/*
18294		* NOTE that the effective mixed is ignored here.
18295		*/
18296	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18297		/*
18298		* SPEC (3.2.2)
18299		*/
18300		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18301		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18302	    } else {
18303		/*
18304		* SPEC (3.2.3)
18305		*/
18306		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18307		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18308		    /*
18309		    * "A model group whose {compositor} is sequence and whose
18310		    * {particles} are..."
18311		    */
18312		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18313		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18314		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18315			XML_SCHEMA_TYPE_ALL))
18316		{
18317		    /*
18318		    * SPEC cos-all-limited (1)
18319		    */
18320		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18321			/* TODO: error code */
18322			XML_SCHEMAP_COS_ALL_LIMITED,
18323			WXS_ITEM_NODE(type), NULL,
18324			"The type has an 'all' model group in its "
18325			"{content type} and thus cannot be derived from "
18326			"a non-empty type, since this would produce a "
18327			"'sequence' model group containing the 'all' "
18328			"model group; 'all' model groups are not "
18329			"allowed to appear inside other model groups",
18330			NULL, NULL);
18331
18332		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18333		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18334		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18335			XML_SCHEMA_TYPE_ALL))
18336		{
18337		    /*
18338		    * SPEC cos-all-limited (1)
18339		    */
18340		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18341			/* TODO: error code */
18342			XML_SCHEMAP_COS_ALL_LIMITED,
18343			WXS_ITEM_NODE(type), NULL,
18344			"A type cannot be derived by extension from a type "
18345			"which has an 'all' model group in its "
18346			"{content type}, since this would produce a "
18347			"'sequence' model group containing the 'all' "
18348			"model group; 'all' model groups are not "
18349			"allowed to appear inside other model groups",
18350			NULL, NULL);
18351
18352		} else if (! dummySequence) {
18353		    xmlSchemaTreeItemPtr effectiveContent =
18354			(xmlSchemaTreeItemPtr) type->subtypes;
18355		    /*
18356		    * Create the particle.
18357		    */
18358		    particle = xmlSchemaAddParticle(pctxt,
18359			type->node, 1, 1);
18360		    if (particle == NULL)
18361			goto exit_failure;
18362		    /*
18363		    * Create the "sequence" model group.
18364		    */
18365		    particle->children = (xmlSchemaTreeItemPtr)
18366			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18367			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18368		    if (particle->children == NULL)
18369			goto exit_failure;
18370		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18371		    /*
18372		    * SPEC "the particle of the {content type} of
18373		    * the ... base ..."
18374		    * Create a duplicate of the base type's particle
18375		    * and assign its "term" to it.
18376		    */
18377		    particle->children->children =
18378			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18379			type->node,
18380			((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18381			((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18382		    if (particle->children->children == NULL)
18383			goto exit_failure;
18384		    particle = (xmlSchemaParticlePtr)
18385			particle->children->children;
18386		    particle->children =
18387			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18388		    /*
18389		    * SPEC "followed by the �effective content�."
18390		    */
18391		    particle->next = effectiveContent;
18392		    /*
18393		    * This all will result in:
18394		    * new-particle
18395		    *   --> new-sequence(
18396		    *         new-particle
18397		    *           --> base-model,
18398		    *         this-particle
18399		    *	        --> this-model
18400		    *	    )
18401		    */
18402		} else {
18403		    /*
18404		    * This is the case when there is already an empty
18405		    * <sequence> with minOccurs==maxOccurs==1.
18406		    * Just add the base types's content type.
18407		    * NOTE that, although we miss to add an intermediate
18408		    * <sequence>, this should produce no difference to
18409		    * neither the regex compilation of the content model,
18410		    * nor to the complex type contraints.
18411		    */
18412		    particle->children->children =
18413			(xmlSchemaTreeItemPtr) baseType->subtypes;
18414		}
18415	    }
18416	}
18417    }
18418    /*
18419    * Now fixup attribute uses:
18420    *   - expand attr. group references
18421    *     - intersect attribute wildcards
18422    *   - inherit attribute uses of the base type
18423    *   - inherit or union attr. wildcards if extending
18424    *   - apply attr. use prohibitions if restricting
18425    */
18426    res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18427    HFAILURE HERROR
18428    /*
18429    * Apply the complex type component constraints; this will not
18430    * check attributes, since this is done in
18431    * xmlSchemaFixupTypeAttributeUses().
18432    */
18433    res = xmlSchemaCheckCTComponent(pctxt, type);
18434    HFAILURE HERROR
18435
18436#ifdef DEBUG_TYPE
18437    xmlSchemaDebugFixedType(pctxt, type);
18438#endif
18439    if (olderrs != pctxt->nberrors)
18440	return(pctxt->err);
18441    else
18442	return(0);
18443
18444exit_error:
18445    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18446#ifdef DEBUG_TYPE
18447    xmlSchemaDebugFixedType(pctxt, type);
18448#endif
18449    return(pctxt->err);
18450
18451exit_failure:
18452    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18453#ifdef DEBUG_TYPE
18454    xmlSchemaDebugFixedType(pctxt, type);
18455#endif
18456    return(-1);
18457}
18458
18459
18460/**
18461 * xmlSchemaTypeFixup:
18462 * @typeDecl:  the schema type definition
18463 * @ctxt:  the schema parser context
18464 *
18465 * Fixes the content model of the type.
18466 * URGENT TODO: We need an int result!
18467 */
18468static int
18469xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18470                   xmlSchemaAbstractCtxtPtr actxt)
18471{
18472    if (type == NULL)
18473        return(0);
18474    if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18475	AERROR_INT("xmlSchemaTypeFixup",
18476	    "this function needs a parser context");
18477	return(-1);
18478    }
18479    if (! WXS_IS_TYPE_NOT_FIXED(type))
18480	return(0);
18481    if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18482	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18483    else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18484	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18485    return(0);
18486}
18487
18488/**
18489 * xmlSchemaCheckFacet:
18490 * @facet:  the facet
18491 * @typeDecl:  the schema type definition
18492 * @pctxt:  the schema parser context or NULL
18493 * @name: the optional name of the type
18494 *
18495 * Checks and computes the values of facets.
18496 *
18497 * Returns 0 if valid, a positive error code if not valid and
18498 *         -1 in case of an internal or API error.
18499 */
18500int
18501xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18502                    xmlSchemaTypePtr typeDecl,
18503                    xmlSchemaParserCtxtPtr pctxt,
18504		    const xmlChar * name ATTRIBUTE_UNUSED)
18505{
18506    int ret = 0, ctxtGiven;
18507
18508    if ((facet == NULL) || (typeDecl == NULL))
18509        return(-1);
18510    /*
18511    * TODO: will the parser context be given if used from
18512    * the relaxNG module?
18513    */
18514    if (pctxt == NULL)
18515	ctxtGiven = 0;
18516    else
18517	ctxtGiven = 1;
18518
18519    switch (facet->type) {
18520        case XML_SCHEMA_FACET_MININCLUSIVE:
18521        case XML_SCHEMA_FACET_MINEXCLUSIVE:
18522        case XML_SCHEMA_FACET_MAXINCLUSIVE:
18523        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18524	case XML_SCHEMA_FACET_ENUMERATION: {
18525                /*
18526                 * Okay we need to validate the value
18527                 * at that point.
18528                 */
18529		xmlSchemaTypePtr base;
18530
18531		/* 4.3.5.5 Constraints on enumeration Schema Components
18532		* Schema Component Constraint: enumeration valid restriction
18533		* It is an �error� if any member of {value} is not in the
18534		* �value space� of {base type definition}.
18535		*
18536		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18537		* The value �must� be in the
18538		* �value space� of the �base type�.
18539		*/
18540		/*
18541		* This function is intended to deliver a compiled value
18542		* on the facet. In this implementation of XML Schemata the
18543		* type holding a facet, won't be a built-in type.
18544		* Thus to ensure that other API
18545		* calls (relaxng) do work, if the given type is a built-in
18546		* type, we will assume that the given built-in type *is
18547		* already* the base type.
18548		*/
18549		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18550		    base = typeDecl->baseType;
18551		    if (base == NULL) {
18552			PERROR_INT("xmlSchemaCheckFacet",
18553			    "a type user derived type has no base type");
18554			return (-1);
18555		    }
18556		} else
18557		    base = typeDecl;
18558
18559		if (! ctxtGiven) {
18560		    /*
18561		    * A context is needed if called from RelaxNG.
18562		    */
18563		    pctxt = xmlSchemaNewParserCtxt("*");
18564		    if (pctxt == NULL)
18565			return (-1);
18566		}
18567		/*
18568		* NOTE: This call does not check the content nodes,
18569		* since they are not available:
18570		* facet->node is just the node holding the facet
18571		* definition, *not* the attribute holding the *value*
18572		* of the facet.
18573		*/
18574		ret = xmlSchemaVCheckCVCSimpleType(
18575		    ACTXT_CAST pctxt, facet->node, base,
18576		    facet->value, &(facet->val), 1, 1, 0);
18577                if (ret != 0) {
18578		    if (ret < 0) {
18579			/* No error message for RelaxNG. */
18580			if (ctxtGiven) {
18581			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18582				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18583				"Internal error: xmlSchemaCheckFacet, "
18584				"failed to validate the value '%s' of the "
18585				"facet '%s' against the base type",
18586				facet->value, xmlSchemaFacetTypeToString(facet->type));
18587			}
18588			goto internal_error;
18589		    }
18590		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18591		    /* No error message for RelaxNG. */
18592		    if (ctxtGiven) {
18593			xmlChar *str = NULL;
18594
18595			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18596			    ret, facet->node, WXS_BASIC_CAST facet,
18597			    "The value '%s' of the facet does not validate "
18598			    "against the base type '%s'",
18599			    facet->value,
18600			    xmlSchemaFormatQName(&str,
18601				base->targetNamespace, base->name));
18602			FREE_AND_NULL(str);
18603		    }
18604		    goto exit;
18605                } else if (facet->val == NULL) {
18606		    if (ctxtGiven) {
18607			PERROR_INT("xmlSchemaCheckFacet",
18608			    "value was not computed");
18609		    }
18610		    TODO
18611		}
18612                break;
18613            }
18614        case XML_SCHEMA_FACET_PATTERN:
18615            facet->regexp = xmlRegexpCompile(facet->value);
18616            if (facet->regexp == NULL) {
18617		ret = XML_SCHEMAP_REGEXP_INVALID;
18618		/* No error message for RelaxNG. */
18619		if (ctxtGiven) {
18620		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18621			ret, facet->node, WXS_BASIC_CAST typeDecl,
18622			"The value '%s' of the facet 'pattern' is not a "
18623			"valid regular expression",
18624			facet->value, NULL);
18625		}
18626            }
18627            break;
18628        case XML_SCHEMA_FACET_TOTALDIGITS:
18629        case XML_SCHEMA_FACET_FRACTIONDIGITS:
18630        case XML_SCHEMA_FACET_LENGTH:
18631        case XML_SCHEMA_FACET_MAXLENGTH:
18632        case XML_SCHEMA_FACET_MINLENGTH:
18633
18634	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18635		ret = xmlSchemaValidatePredefinedType(
18636		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18637		    facet->value, &(facet->val));
18638	    } else {
18639		ret = xmlSchemaValidatePredefinedType(
18640		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18641		    facet->value, &(facet->val));
18642	    }
18643	    if (ret != 0) {
18644		if (ret < 0) {
18645		    /* No error message for RelaxNG. */
18646		    if (ctxtGiven) {
18647			PERROR_INT("xmlSchemaCheckFacet",
18648			    "validating facet value");
18649		    }
18650		    goto internal_error;
18651		}
18652		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18653		/* No error message for RelaxNG. */
18654		if (ctxtGiven) {
18655		    /* error code */
18656		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18657			ret, facet->node, WXS_BASIC_CAST typeDecl,
18658			"The value '%s' of the facet '%s' is not a valid '%s'",
18659			facet->value,
18660			xmlSchemaFacetTypeToString(facet->type),
18661			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18662			    BAD_CAST "nonNegativeInteger" :
18663			    BAD_CAST "positiveInteger",
18664			NULL);
18665		}
18666	    }
18667	    break;
18668
18669        case XML_SCHEMA_FACET_WHITESPACE:{
18670                if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18671                    facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18672                } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18673                    facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18674                } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18675                    facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18676                } else {
18677		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18678                    /* No error message for RelaxNG. */
18679		    if (ctxtGiven) {
18680			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18681			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18682			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18683			    "The value '%s' of the facet 'whitespace' is not "
18684			    "valid", facet->value, NULL);
18685                    }
18686                }
18687            }
18688        default:
18689            break;
18690    }
18691exit:
18692    if ((! ctxtGiven) && (pctxt != NULL))
18693	xmlSchemaFreeParserCtxt(pctxt);
18694    return (ret);
18695internal_error:
18696    if ((! ctxtGiven) && (pctxt != NULL))
18697	xmlSchemaFreeParserCtxt(pctxt);
18698    return (-1);
18699}
18700
18701/**
18702 * xmlSchemaCheckFacetValues:
18703 * @typeDecl:  the schema type definition
18704 * @ctxt:  the schema parser context
18705 *
18706 * Checks the default values types, especially for facets
18707 */
18708static int
18709xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18710			  xmlSchemaParserCtxtPtr pctxt)
18711{
18712    int res, olderrs = pctxt->nberrors;
18713    const xmlChar *name = typeDecl->name;
18714    /*
18715    * NOTE: It is intended to use the facets list, instead
18716    * of facetSet.
18717    */
18718    if (typeDecl->facets != NULL) {
18719	xmlSchemaFacetPtr facet = typeDecl->facets;
18720
18721	/*
18722	* Temporarily assign the "schema" to the validation context
18723	* of the parser context. This is needed for NOTATION validation.
18724	*/
18725	if (pctxt->vctxt == NULL) {
18726	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18727		return(-1);
18728	}
18729	pctxt->vctxt->schema = pctxt->schema;
18730	while (facet != NULL) {
18731	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18732	    HFAILURE
18733	    facet = facet->next;
18734	}
18735	pctxt->vctxt->schema = NULL;
18736    }
18737    if (olderrs != pctxt->nberrors)
18738	return(pctxt->err);
18739    return(0);
18740exit_failure:
18741    return(-1);
18742}
18743
18744/**
18745 * xmlSchemaGetCircModelGrDefRef:
18746 * @ctxtMGroup: the searched model group
18747 * @selfMGroup: the second searched model group
18748 * @particle: the first particle
18749 *
18750 * This one is intended to be used by
18751 * xmlSchemaCheckGroupDefCircular only.
18752 *
18753 * Returns the particle with the circular model group definition reference,
18754 * otherwise NULL.
18755 */
18756static xmlSchemaTreeItemPtr
18757xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18758			      xmlSchemaTreeItemPtr particle)
18759{
18760    xmlSchemaTreeItemPtr circ = NULL;
18761    xmlSchemaTreeItemPtr term;
18762    xmlSchemaModelGroupDefPtr gdef;
18763
18764    for (; particle != NULL; particle = particle->next) {
18765	term = particle->children;
18766	if (term == NULL)
18767	    continue;
18768	switch (term->type) {
18769	    case XML_SCHEMA_TYPE_GROUP:
18770		gdef = (xmlSchemaModelGroupDefPtr) term;
18771		if (gdef == groupDef)
18772		    return (particle);
18773		/*
18774		* Mark this model group definition to avoid infinite
18775		* recursion on circular references not yet examined.
18776		*/
18777		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18778		    continue;
18779		if (gdef->children != NULL) {
18780		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18781		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18782			gdef->children->children);
18783		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18784		    if (circ != NULL)
18785			return (circ);
18786		}
18787		break;
18788	    case XML_SCHEMA_TYPE_SEQUENCE:
18789	    case XML_SCHEMA_TYPE_CHOICE:
18790	    case XML_SCHEMA_TYPE_ALL:
18791		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18792		if (circ != NULL)
18793		    return (circ);
18794		break;
18795	    default:
18796		break;
18797	}
18798    }
18799    return (NULL);
18800}
18801
18802/**
18803 * xmlSchemaCheckGroupDefCircular:
18804 * @item:  the model group definition
18805 * @ctxt:  the parser context
18806 * @name:  the name
18807 *
18808 * Checks for circular references to model group definitions.
18809 */
18810static void
18811xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18812			       xmlSchemaParserCtxtPtr ctxt)
18813{
18814    /*
18815    * Schema Component Constraint: Model Group Correct
18816    * 2 Circular groups are disallowed. That is, within the {particles}
18817    * of a group there must not be at any depth a particle whose {term}
18818    * is the group itself.
18819    */
18820    if ((item == NULL) ||
18821	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18822	(item->children == NULL))
18823	return;
18824    {
18825	xmlSchemaTreeItemPtr circ;
18826
18827	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18828	if (circ != NULL) {
18829	    xmlChar *str = NULL;
18830	    /*
18831	    * TODO: The error report is not adequate: this constraint
18832	    * is defined for model groups but not definitions, but since
18833	    * there cannot be any circular model groups without a model group
18834	    * definition (if not using a construction API), we check those
18835	    * defintions only.
18836	    */
18837	    xmlSchemaPCustomErr(ctxt,
18838		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18839		NULL, WXS_ITEM_NODE(circ),
18840		"Circular reference to the model group definition '%s' "
18841		"defined", xmlSchemaFormatQName(&str,
18842		    item->targetNamespace, item->name));
18843	    FREE_AND_NULL(str)
18844	    /*
18845	    * NOTE: We will cut the reference to avoid further
18846	    * confusion of the processor. This is a fatal error.
18847	    */
18848	    circ->children = NULL;
18849	}
18850    }
18851}
18852
18853/**
18854 * xmlSchemaModelGroupToModelGroupDefFixup:
18855 * @ctxt:  the parser context
18856 * @mg:  the model group
18857 *
18858 * Assigns the model group of model group definitions to the "term"
18859 * of the referencing particle.
18860 * In xmlSchemaResolveModelGroupParticleReferences the model group
18861 * definitions were assigned to the "term", since needed for the
18862 * circularity check.
18863 *
18864 * Schema Component Constraint:
18865 *     All Group Limited (cos-all-limited) (1.2)
18866 */
18867static void
18868xmlSchemaModelGroupToModelGroupDefFixup(
18869    xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18870    xmlSchemaModelGroupPtr mg)
18871{
18872    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18873
18874    while (particle != NULL) {
18875	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18876	    ((WXS_PARTICLE_TERM(particle))->type !=
18877		XML_SCHEMA_TYPE_GROUP))
18878	{
18879	    particle = WXS_PTC_CAST particle->next;
18880	    continue;
18881	}
18882	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18883	    /*
18884	    * TODO: Remove the particle.
18885	    */
18886	    WXS_PARTICLE_TERM(particle) = NULL;
18887	    particle = WXS_PTC_CAST particle->next;
18888	    continue;
18889	}
18890	/*
18891	* Assign the model group to the {term} of the particle.
18892	*/
18893	WXS_PARTICLE_TERM(particle) =
18894	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18895
18896	particle = WXS_PTC_CAST particle->next;
18897    }
18898}
18899
18900/**
18901 * xmlSchemaCheckAttrGroupCircularRecur:
18902 * @ctxtGr: the searched attribute group
18903 * @attr: the current attribute list to be processed
18904 *
18905 * This one is intended to be used by
18906 * xmlSchemaCheckAttrGroupCircular only.
18907 *
18908 * Returns the circular attribute grou reference, otherwise NULL.
18909 */
18910static xmlSchemaQNameRefPtr
18911xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18912				     xmlSchemaItemListPtr list)
18913{
18914    xmlSchemaAttributeGroupPtr gr;
18915    xmlSchemaQNameRefPtr ref, circ;
18916    int i;
18917    /*
18918    * We will search for an attribute group reference which
18919    * references the context attribute group.
18920    */
18921    for (i = 0; i < list->nbItems; i++) {
18922	ref = list->items[i];
18923	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18924	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18925	    (ref->item != NULL))
18926	{
18927	    gr = WXS_ATTR_GROUP_CAST ref->item;
18928	    if (gr == ctxtGr)
18929		return(ref);
18930	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18931		continue;
18932	    /*
18933	    * Mark as visited to avoid infinite recursion on
18934	    * circular references not yet examined.
18935	    */
18936	    if ((gr->attrUses) &&
18937		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18938	    {
18939		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18940		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18941		    (xmlSchemaItemListPtr) gr->attrUses);
18942		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18943		if (circ != NULL)
18944		    return (circ);
18945	    }
18946
18947	}
18948    }
18949    return (NULL);
18950}
18951
18952/**
18953 * xmlSchemaCheckAttrGroupCircular:
18954 * attrGr:  the attribute group definition
18955 * @ctxt:  the parser context
18956 * @name:  the name
18957 *
18958 * Checks for circular references of attribute groups.
18959 */
18960static int
18961xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
18962				xmlSchemaParserCtxtPtr ctxt)
18963{
18964    /*
18965    * Schema Representation Constraint:
18966    * Attribute Group Definition Representation OK
18967    * 3 Circular group reference is disallowed outside <redefine>.
18968    * That is, unless this element information item's parent is
18969    * <redefine>, then among the [children], if any, there must
18970    * not be an <attributeGroup> with ref [attribute] which resolves
18971    * to the component corresponding to this <attributeGroup>. Indirect
18972    * circularity is also ruled out. That is, when QName resolution
18973    * (Schema Document) (�3.15.3) is applied to a �QName� arising from
18974    * any <attributeGroup>s with a ref [attribute] among the [children],
18975    * it must not be the case that a �QName� is encountered at any depth
18976    * which resolves to the component corresponding to this <attributeGroup>.
18977    */
18978    if (attrGr->attrUses == NULL)
18979	return(0);
18980    else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18981	return(0);
18982    else {
18983	xmlSchemaQNameRefPtr circ;
18984
18985	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
18986	    (xmlSchemaItemListPtr) attrGr->attrUses);
18987	if (circ != NULL) {
18988	    xmlChar *str = NULL;
18989	    /*
18990	    * TODO: Report the referenced attr group as QName.
18991	    */
18992	    xmlSchemaPCustomErr(ctxt,
18993		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
18994		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
18995		"Circular reference to the attribute group '%s' "
18996		"defined", xmlSchemaGetComponentQName(&str, attrGr));
18997	    FREE_AND_NULL(str);
18998	    /*
18999	    * NOTE: We will cut the reference to avoid further
19000	    * confusion of the processor.
19001	    * BADSPEC TODO: The spec should define how to process in this case.
19002	    */
19003	    circ->item = NULL;
19004	    return(ctxt->err);
19005	}
19006    }
19007    return(0);
19008}
19009
19010static int
19011xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19012				  xmlSchemaAttributeGroupPtr attrGr);
19013
19014/**
19015 * xmlSchemaExpandAttributeGroupRefs:
19016 * @pctxt: the parser context
19017 * @node: the node of the component holding the attribute uses
19018 * @completeWild: the intersected wildcard to be returned
19019 * @list: the attribute uses
19020 *
19021 * Substitutes contained attribute group references
19022 * for their attribute uses. Wilcards are intersected.
19023 * Attribute use prohibitions are removed from the list
19024 * and returned via the @prohibs list.
19025 * Pointlessness of attr. prohibs, if a matching attr. decl
19026 * is existent a well, are checked.
19027 */
19028static int
19029xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19030				  xmlSchemaBasicItemPtr item,
19031				  xmlSchemaWildcardPtr *completeWild,
19032				  xmlSchemaItemListPtr list,
19033				  xmlSchemaItemListPtr prohibs)
19034{
19035    xmlSchemaAttributeGroupPtr gr;
19036    xmlSchemaAttributeUsePtr use;
19037    xmlSchemaItemListPtr sublist;
19038    int i, j;
19039    int created = (*completeWild == NULL) ? 0 : 1;
19040
19041    if (prohibs)
19042	prohibs->nbItems = 0;
19043
19044    for (i = 0; i < list->nbItems; i++) {
19045	use = list->items[i];
19046
19047	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19048	    if (prohibs == NULL) {
19049		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19050		    "unexpected attr prohibition found");
19051		return(-1);
19052	    }
19053	    /*
19054	    * Remove from attribute uses.
19055	    */
19056	    if (xmlSchemaItemListRemove(list, i) == -1)
19057		return(-1);
19058	    i--;
19059	    /*
19060	    * Note that duplicate prohibitions were already
19061	    * handled at parsing time.
19062	    */
19063	    /*
19064	    * Add to list of prohibitions.
19065	    */
19066	    xmlSchemaItemListAddSize(prohibs, 2, use);
19067	    continue;
19068	}
19069	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19070	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19071	{
19072	    if ((WXS_QNAME_CAST use)->item == NULL)
19073		return(-1);
19074	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19075	    /*
19076	    * Expand the referenced attr. group.
19077	    * TODO: remove this, this is done in a previous step, so
19078	    * already done here.
19079	    */
19080	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19081		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19082		    return(-1);
19083	    }
19084	    /*
19085	    * Build the 'complete' wildcard; i.e. intersect multiple
19086	    * wildcards.
19087	    */
19088	    if (gr->attributeWildcard != NULL) {
19089		if (*completeWild == NULL) {
19090		    *completeWild = gr->attributeWildcard;
19091		} else {
19092		    if (! created) {
19093			xmlSchemaWildcardPtr tmpWild;
19094
19095			 /*
19096			* Copy the first encountered wildcard as context,
19097			* except for the annotation.
19098			*
19099			* Although the complete wildcard might not correspond
19100			* to any node in the schema, we will anchor it on
19101			* the node of the owner component.
19102			*/
19103			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19104			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19105			    WXS_ITEM_NODE(item));
19106			if (tmpWild == NULL)
19107			    return(-1);
19108			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19109			    tmpWild, *completeWild) == -1)
19110			    return (-1);
19111			tmpWild->processContents = (*completeWild)->processContents;
19112			*completeWild = tmpWild;
19113			created = 1;
19114		    }
19115
19116		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19117			gr->attributeWildcard) == -1)
19118			return(-1);
19119		}
19120	    }
19121	    /*
19122	    * Just remove the reference if the referenced group does not
19123	    * contain any attribute uses.
19124	    */
19125	    if (gr->attrUses == NULL) {
19126		if (xmlSchemaItemListRemove(list, i) == -1)
19127		    return(-1);
19128		i--;
19129		continue;
19130	    }
19131	    /*
19132	    * Add the attribute uses.
19133	    */
19134	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19135	    if (sublist->nbItems != 0) {
19136		list->items[i] = sublist->items[0];
19137		if (sublist->nbItems != 1) {
19138		    for (j = 1; j < sublist->nbItems; j++) {
19139			i++;
19140			if (xmlSchemaItemListInsert(list,
19141				sublist->items[j], i) == -1)
19142			    return(-1);
19143		    }
19144		}
19145	    }
19146	}
19147
19148    }
19149    /*
19150    * Handle pointless prohibitions of declared attributes.
19151    */
19152    if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19153	xmlSchemaAttributeUseProhibPtr prohib;
19154
19155	for (i = prohibs->nbItems -1; i >= 0; i--) {
19156	    prohib = prohibs->items[i];
19157	    for (j = 0; j < list->nbItems; j++) {
19158		use = list->items[j];
19159
19160		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19161		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19162		{
19163		    xmlChar *str = NULL;
19164
19165		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19166			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19167			prohib->node, NULL,
19168			"Skipping pointless attribute use prohibition "
19169			"'%s', since a corresponding attribute use "
19170			"exists already in the type definition",
19171			xmlSchemaFormatQName(&str,
19172			    prohib->targetNamespace, prohib->name),
19173			NULL, NULL);
19174		    FREE_AND_NULL(str);
19175		    /*
19176		    * Remove the prohibition.
19177		    */
19178		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19179			return(-1);
19180		    break;
19181		}
19182	    }
19183	}
19184    }
19185    return(0);
19186}
19187
19188/**
19189 * xmlSchemaAttributeGroupExpandRefs:
19190 * @pctxt:  the parser context
19191 * @attrGr:  the attribute group definition
19192 *
19193 * Computation of:
19194 * {attribute uses} property
19195 * {attribute wildcard} property
19196 *
19197 * Substitutes contained attribute group references
19198 * for their attribute uses. Wilcards are intersected.
19199 */
19200static int
19201xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19202				  xmlSchemaAttributeGroupPtr attrGr)
19203{
19204    if ((attrGr->attrUses == NULL) ||
19205	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19206	return(0);
19207
19208    attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19209    if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19210	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19211	return(-1);
19212    return(0);
19213}
19214
19215/**
19216 * xmlSchemaAttributeGroupExpandRefs:
19217 * @pctxt:  the parser context
19218 * @attrGr:  the attribute group definition
19219 *
19220 * Substitutes contained attribute group references
19221 * for their attribute uses. Wilcards are intersected.
19222 *
19223 * Schema Component Constraint:
19224 *    Attribute Group Definition Properties Correct (ag-props-correct)
19225 */
19226static int
19227xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19228				  xmlSchemaAttributeGroupPtr attrGr)
19229{
19230    /*
19231    * SPEC ag-props-correct
19232    * (1) "The values of the properties of an attribute group definition
19233    * must be as described in the property tableau in The Attribute
19234    * Group Definition Schema Component (�3.6.1), modulo the impact of
19235    * Missing Sub-components (�5.3);"
19236    */
19237
19238    if ((attrGr->attrUses != NULL) &&
19239	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19240    {
19241	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19242	xmlSchemaAttributeUsePtr use, tmp;
19243	int i, j, hasId = 0;
19244
19245	for (i = uses->nbItems -1; i >= 0; i--) {
19246	    use = uses->items[i];
19247	    /*
19248	    * SPEC ag-props-correct
19249	    * (2) "Two distinct members of the {attribute uses} must not have
19250	    * {attribute declaration}s both of whose {name}s match and whose
19251	    * {target namespace}s are identical."
19252	    */
19253	    if (i > 0) {
19254		for (j = i -1; j >= 0; j--) {
19255		    tmp = uses->items[j];
19256		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19257			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19258			(WXS_ATTRUSE_DECL_TNS(use) ==
19259			WXS_ATTRUSE_DECL_TNS(tmp)))
19260		    {
19261			xmlChar *str = NULL;
19262
19263			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19264			    XML_SCHEMAP_AG_PROPS_CORRECT,
19265			    attrGr->node, WXS_BASIC_CAST attrGr,
19266			    "Duplicate %s",
19267			    xmlSchemaGetComponentDesignation(&str, use),
19268			    NULL);
19269			FREE_AND_NULL(str);
19270			/*
19271			* Remove the duplicate.
19272			*/
19273			if (xmlSchemaItemListRemove(uses, i) == -1)
19274			    return(-1);
19275			goto next_use;
19276		    }
19277		}
19278	    }
19279	    /*
19280	    * SPEC ag-props-correct
19281	    * (3) "Two distinct members of the {attribute uses} must not have
19282	    * {attribute declaration}s both of whose {type definition}s are or
19283	    * are derived from ID."
19284	    * TODO: Does 'derived' include member-types of unions?
19285	    */
19286	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19287		if (xmlSchemaIsDerivedFromBuiltInType(
19288		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19289		{
19290		    if (hasId) {
19291			xmlChar *str = NULL;
19292
19293			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19294			    XML_SCHEMAP_AG_PROPS_CORRECT,
19295			    attrGr->node, WXS_BASIC_CAST attrGr,
19296			    "There must not exist more than one attribute "
19297			    "declaration of type 'xs:ID' "
19298			    "(or derived from 'xs:ID'). The %s violates this "
19299			    "constraint",
19300			    xmlSchemaGetComponentDesignation(&str, use),
19301			    NULL);
19302			FREE_AND_NULL(str);
19303			if (xmlSchemaItemListRemove(uses, i) == -1)
19304			    return(-1);
19305		    }
19306		    hasId = 1;
19307		}
19308	    }
19309next_use: {}
19310	}
19311    }
19312    return(0);
19313}
19314
19315/**
19316 * xmlSchemaResolveAttrGroupReferences:
19317 * @attrgrpDecl:  the schema attribute definition
19318 * @ctxt:  the schema parser context
19319 * @name:  the attribute name
19320 *
19321 * Resolves references to attribute group definitions.
19322 */
19323static int
19324xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19325				    xmlSchemaParserCtxtPtr ctxt)
19326{
19327    xmlSchemaAttributeGroupPtr group;
19328
19329    if (ref->item != NULL)
19330        return(0);
19331    group = xmlSchemaGetAttributeGroup(ctxt->schema,
19332	ref->name,
19333	ref->targetNamespace);
19334    if (group == NULL) {
19335	xmlSchemaPResCompAttrErr(ctxt,
19336	    XML_SCHEMAP_SRC_RESOLVE,
19337	    NULL, ref->node,
19338	    "ref", ref->name, ref->targetNamespace,
19339	    ref->itemType, NULL);
19340	return(ctxt->err);
19341    }
19342    ref->item = WXS_BASIC_CAST group;
19343    return(0);
19344}
19345
19346/**
19347 * xmlSchemaCheckAttrPropsCorrect:
19348 * @item:  an schema attribute declaration/use
19349 * @ctxt:  a schema parser context
19350 * @name:  the name of the attribute
19351 *
19352 *
19353 * Schema Component Constraint:
19354 *    Attribute Declaration Properties Correct (a-props-correct)
19355 *
19356 * Validates the value constraints of an attribute declaration/use.
19357 * NOTE that this needs the simle type definitions to be already
19358 *   builded and checked.
19359 */
19360static int
19361xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19362			       xmlSchemaAttributePtr attr)
19363{
19364
19365    /*
19366    * SPEC a-props-correct (1)
19367    * "The values of the properties of an attribute declaration must
19368    * be as described in the property tableau in The Attribute
19369    * Declaration Schema Component (�3.2.1), modulo the impact of
19370    * Missing Sub-components (�5.3)."
19371    */
19372
19373    if (WXS_ATTR_TYPEDEF(attr) == NULL)
19374	return(0);
19375
19376    if (attr->defValue != NULL) {
19377	int ret;
19378
19379	/*
19380	* SPEC a-props-correct (3)
19381	* "If the {type definition} is or is derived from ID then there
19382	* must not be a {value constraint}."
19383	*/
19384	if (xmlSchemaIsDerivedFromBuiltInType(
19385	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19386	{
19387	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19388		XML_SCHEMAP_A_PROPS_CORRECT_3,
19389		NULL, WXS_BASIC_CAST attr,
19390		"Value constraints are not allowed if the type definition "
19391		"is or is derived from xs:ID",
19392		NULL, NULL);
19393	    return(pctxt->err);
19394	}
19395	/*
19396	* SPEC a-props-correct (2)
19397	* "if there is a {value constraint}, the canonical lexical
19398	* representation of its value must be �valid� with respect
19399	* to the {type definition} as defined in String Valid (�3.14.4)."
19400	* TODO: Don't care about the *cononical* stuff here, this requirement
19401	* will be removed in WXS 1.1 anyway.
19402	*/
19403	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19404	    attr->node, WXS_ATTR_TYPEDEF(attr),
19405	    attr->defValue, &(attr->defVal),
19406	    1, 1, 0);
19407	if (ret != 0) {
19408	    if (ret < 0) {
19409		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19410		    "calling xmlSchemaVCheckCVCSimpleType()");
19411		return(-1);
19412	    }
19413	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19414		XML_SCHEMAP_A_PROPS_CORRECT_2,
19415		NULL, WXS_BASIC_CAST attr,
19416		"The value of the value constraint is not valid",
19417		NULL, NULL);
19418	    return(pctxt->err);
19419	}
19420    }
19421
19422    return(0);
19423}
19424
19425static xmlSchemaElementPtr
19426xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19427				 xmlSchemaElementPtr ancestor)
19428{
19429    xmlSchemaElementPtr ret;
19430
19431    if (WXS_SUBST_HEAD(ancestor) == NULL)
19432	return (NULL);
19433    if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19434	return (ancestor);
19435
19436    if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19437	return (NULL);
19438    WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19439    ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19440	WXS_SUBST_HEAD(ancestor));
19441    WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19442
19443    return (ret);
19444}
19445
19446/**
19447 * xmlSchemaCheckElemPropsCorrect:
19448 * @ctxt:  a schema parser context
19449 * @decl: the element declaration
19450 * @name:  the name of the attribute
19451 *
19452 * Schema Component Constraint:
19453 * Element Declaration Properties Correct (e-props-correct)
19454 *
19455 * STATUS:
19456 *   missing: (6)
19457 */
19458static int
19459xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19460			       xmlSchemaElementPtr elemDecl)
19461{
19462    int ret = 0;
19463    xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19464    /*
19465    * SPEC (1) "The values of the properties of an element declaration
19466    * must be as described in the property tableau in The Element
19467    * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19468    * Sub-components (�5.3)."
19469    */
19470    if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19471	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19472
19473	xmlSchemaCheckElementDeclComponent(head, pctxt);
19474	/*
19475	* SPEC (3) "If there is a non-�absent� {substitution group
19476	* affiliation}, then {scope} must be global."
19477	*/
19478	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19479	    xmlSchemaPCustomErr(pctxt,
19480		XML_SCHEMAP_E_PROPS_CORRECT_3,
19481		WXS_BASIC_CAST elemDecl, NULL,
19482		"Only global element declarations can have a "
19483		"substitution group affiliation", NULL);
19484	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19485	}
19486	/*
19487	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19488	* That is, it must not be possible to return to an element declaration
19489	* by repeatedly following the {substitution group affiliation}
19490	* property."
19491	*/
19492	if (head == elemDecl)
19493	    circ = head;
19494	else if (WXS_SUBST_HEAD(head) != NULL)
19495	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19496	else
19497	    circ = NULL;
19498	if (circ != NULL) {
19499	    xmlChar *strA = NULL, *strB = NULL;
19500
19501	    xmlSchemaPCustomErrExt(pctxt,
19502		XML_SCHEMAP_E_PROPS_CORRECT_6,
19503		WXS_BASIC_CAST circ, NULL,
19504		"The element declaration '%s' defines a circular "
19505		"substitution group to element declaration '%s'",
19506		xmlSchemaGetComponentQName(&strA, circ),
19507		xmlSchemaGetComponentQName(&strB, head),
19508		NULL);
19509	    FREE_AND_NULL(strA)
19510	    FREE_AND_NULL(strB)
19511	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19512	}
19513	/*
19514	* SPEC (4) "If there is a {substitution group affiliation},
19515	* the {type definition}
19516	* of the element declaration must be validly derived from the {type
19517	* definition} of the {substitution group affiliation}, given the value
19518	* of the {substitution group exclusions} of the {substitution group
19519	* affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19520	* (if the {type definition} is complex) or as defined in
19521	* Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19522	* simple)."
19523	*
19524	* NOTE: {substitution group exclusions} means the values of the
19525	* attribute "final".
19526	*/
19527
19528	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19529	    int set = 0;
19530
19531	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19532		set |= SUBSET_EXTENSION;
19533	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19534		set |= SUBSET_RESTRICTION;
19535
19536	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19537		WXS_ELEM_TYPEDEF(head), set) != 0) {
19538		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19539
19540		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19541		xmlSchemaPCustomErrExt(pctxt,
19542		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19543		    WXS_BASIC_CAST elemDecl, NULL,
19544		    "The type definition '%s' was "
19545		    "either rejected by the substitution group "
19546		    "affiliation '%s', or not validly derived from its type "
19547		    "definition '%s'",
19548		    xmlSchemaGetComponentQName(&strA, typeDef),
19549		    xmlSchemaGetComponentQName(&strB, head),
19550		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19551		FREE_AND_NULL(strA)
19552		FREE_AND_NULL(strB)
19553		FREE_AND_NULL(strC)
19554	    }
19555	}
19556    }
19557    /*
19558    * SPEC (5) "If the {type definition} or {type definition}'s
19559    * {content type}
19560    * is or is derived from ID then there must not be a {value constraint}.
19561    * Note: The use of ID as a type definition for elements goes beyond
19562    * XML 1.0, and should be avoided if backwards compatibility is desired"
19563    */
19564    if ((elemDecl->value != NULL) &&
19565	((WXS_IS_SIMPLE(typeDef) &&
19566	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19567	 (WXS_IS_COMPLEX(typeDef) &&
19568	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19569	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19570	    XML_SCHEMAS_ID)))) {
19571
19572	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19573	xmlSchemaPCustomErr(pctxt,
19574	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19575	    WXS_BASIC_CAST elemDecl, NULL,
19576	    "The type definition (or type definition's content type) is or "
19577	    "is derived from ID; value constraints are not allowed in "
19578	    "conjunction with such a type definition", NULL);
19579    } else if (elemDecl->value != NULL) {
19580	int vcret;
19581	xmlNodePtr node = NULL;
19582
19583	/*
19584	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19585	* representation of its value must be �valid� with respect to the
19586	* {type definition} as defined in Element Default Valid (Immediate)
19587	* (�3.3.6)."
19588	*/
19589	if (typeDef == NULL) {
19590	    xmlSchemaPErr(pctxt, elemDecl->node,
19591		XML_SCHEMAP_INTERNAL,
19592		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19593		"type is missing... skipping validation of "
19594		"the value constraint", NULL, NULL);
19595	    return (-1);
19596	}
19597	if (elemDecl->node != NULL) {
19598	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19599		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19600		    BAD_CAST "fixed");
19601	    else
19602		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19603		    BAD_CAST "default");
19604	}
19605	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19606	    typeDef, elemDecl->value, &(elemDecl->defVal));
19607	if (vcret != 0) {
19608	    if (vcret < 0) {
19609		PERROR_INT("xmlSchemaElemCheckValConstr",
19610		    "failed to validate the value constraint of an "
19611		    "element declaration");
19612		return (-1);
19613	    }
19614	    return (vcret);
19615	}
19616    }
19617
19618    return (ret);
19619}
19620
19621/**
19622 * xmlSchemaCheckElemSubstGroup:
19623 * @ctxt:  a schema parser context
19624 * @decl: the element declaration
19625 * @name:  the name of the attribute
19626 *
19627 * Schema Component Constraint:
19628 * Substitution Group (cos-equiv-class)
19629 *
19630 * In Libxml2 the subst. groups will be precomputed, in terms of that
19631 * a list will be built for each subst. group head, holding all direct
19632 * referents to this head.
19633 * NOTE that this function needs:
19634 *   1. circular subst. groups to be checked beforehand
19635 *   2. the declaration's type to be derived from the head's type
19636 *
19637 * STATUS:
19638 *
19639 */
19640static void
19641xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19642			     xmlSchemaElementPtr elemDecl)
19643{
19644    if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19645	/* SPEC (1) "Its {abstract} is false." */
19646	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19647	return;
19648    {
19649	xmlSchemaElementPtr head;
19650	xmlSchemaTypePtr headType, type;
19651	int set, methSet;
19652	/*
19653	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19654	* {disallowed substitutions} as the blocking constraint, as defined in
19655	* Substitution Group OK (Transitive) (�3.3.6)."
19656	*/
19657	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19658	    head = WXS_SUBST_HEAD(head)) {
19659	    set = 0;
19660	    methSet = 0;
19661	    /*
19662	    * The blocking constraints.
19663	    */
19664	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19665		continue;
19666	    headType = head->subtypes;
19667	    type = elemDecl->subtypes;
19668	    if (headType == type)
19669		goto add_member;
19670	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19671		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19672	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19673		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19674	    /*
19675	    * SPEC: Substitution Group OK (Transitive) (2.3)
19676	    * "The set of all {derivation method}s involved in the
19677	    * derivation of D's {type definition} from C's {type definition}
19678	    * does not intersect with the union of the blocking constraint,
19679	    * C's {prohibited substitutions} (if C is complex, otherwise the
19680	    * empty set) and the {prohibited substitutions} (respectively the
19681	    * empty set) of any intermediate {type definition}s in the
19682	    * derivation of D's {type definition} from C's {type definition}."
19683	    */
19684	    /*
19685	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19686	    * subst.head axis, the methSet does not need to be computed for
19687	    * the full depth over and over.
19688	    */
19689	    /*
19690	    * The set of all {derivation method}s involved in the derivation
19691	    */
19692	    while ((type != NULL) && (type != headType)) {
19693		if ((WXS_IS_EXTENSION(type)) &&
19694		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19695		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19696
19697		if (WXS_IS_RESTRICTION(type) &&
19698		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19699		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19700
19701		type = type->baseType;
19702	    }
19703	    /*
19704	    * The {prohibited substitutions} of all intermediate types +
19705	    * the head's type.
19706	    */
19707	    type = elemDecl->subtypes->baseType;
19708	    while (type != NULL) {
19709		if (WXS_IS_COMPLEX(type)) {
19710		    if ((type->flags &
19711			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19712			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19713		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19714		    if ((type->flags &
19715			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19716			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19717		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19718		} else
19719		    break;
19720		if (type == headType)
19721		    break;
19722		type = type->baseType;
19723	    }
19724	    if ((set != 0) &&
19725		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19726		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19727		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19728		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19729		continue;
19730	    }
19731add_member:
19732	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19733	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19734		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19735	}
19736    }
19737}
19738
19739/**
19740 * xmlSchemaCheckElementDeclComponent
19741 * @item:  an schema element declaration/particle
19742 * @ctxt:  a schema parser context
19743 * @name:  the name of the attribute
19744 *
19745 * Validates the value constraints of an element declaration.
19746 *
19747 * Fixes finish doing the computations on the element declarations.
19748 */
19749static void
19750xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19751				   xmlSchemaParserCtxtPtr ctxt)
19752{
19753    if (elemDecl == NULL)
19754	return;
19755    if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19756	return;
19757    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19758    if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
19759	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19760}
19761
19762/**
19763 * xmlSchemaResolveModelGroupParticleReferences:
19764 * @particle:  a particle component
19765 * @ctxt:  a parser context
19766 *
19767 * Resolves references of a model group's {particles} to
19768 * model group definitions and to element declarations.
19769 */
19770static void
19771xmlSchemaResolveModelGroupParticleReferences(
19772    xmlSchemaParserCtxtPtr ctxt,
19773    xmlSchemaModelGroupPtr mg)
19774{
19775    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19776    xmlSchemaQNameRefPtr ref;
19777    xmlSchemaBasicItemPtr refItem;
19778
19779    /*
19780    * URGENT TODO: Test this.
19781    */
19782    while (particle != NULL) {
19783	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19784	    ((WXS_PARTICLE_TERM(particle))->type !=
19785		XML_SCHEMA_EXTRA_QNAMEREF))
19786	{
19787	    goto next_particle;
19788	}
19789	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19790	/*
19791	* Resolve the reference.
19792	* NULL the {term} by default.
19793	*/
19794	particle->children = NULL;
19795
19796	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19797	    ref->itemType, ref->name, ref->targetNamespace);
19798	if (refItem == NULL) {
19799	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19800		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19801		ref->targetNamespace, ref->itemType, NULL);
19802	    /* TODO: remove the particle. */
19803	    goto next_particle;
19804	}
19805	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19806	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19807		/* TODO: remove the particle. */
19808		goto next_particle;
19809	    /*
19810	    * NOTE that we will assign the model group definition
19811	    * itself to the "term" of the particle. This will ease
19812	    * the check for circular model group definitions. After
19813	    * that the "term" will be assigned the model group of the
19814	    * model group definition.
19815	    */
19816	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19817		    XML_SCHEMA_TYPE_ALL) {
19818		/*
19819		* SPEC cos-all-limited (1)
19820		* SPEC cos-all-limited (1.2)
19821		* "It appears only as the value of one or both of the
19822		* following properties:"
19823		* (1.1) "the {model group} property of a model group
19824		*        definition."
19825		* (1.2) "the {term} property of a particle [... of] the "
19826		* {content type} of a complex type definition."
19827		*/
19828		xmlSchemaCustomErr(ACTXT_CAST ctxt,
19829		    /* TODO: error code */
19830		    XML_SCHEMAP_COS_ALL_LIMITED,
19831		    WXS_ITEM_NODE(particle), NULL,
19832		    "A model group definition is referenced, but "
19833		    "it contains an 'all' model group, which "
19834		    "cannot be contained by model groups",
19835		    NULL, NULL);
19836		/* TODO: remove the particle. */
19837		goto next_particle;
19838	    }
19839	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19840	} else {
19841	    /*
19842	    * TODO: Are referenced element declarations the only
19843	    * other components we expect here?
19844	    */
19845	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19846	}
19847next_particle:
19848	particle = WXS_PTC_CAST particle->next;
19849    }
19850}
19851
19852static int
19853xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19854		       xmlSchemaValPtr y)
19855{
19856    xmlSchemaTypePtr tx, ty, ptx, pty;
19857    int ret;
19858
19859    while (x != NULL) {
19860	/* Same types. */
19861	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19862	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
19863	ptx = xmlSchemaGetPrimitiveType(tx);
19864	pty = xmlSchemaGetPrimitiveType(ty);
19865	/*
19866	* (1) if a datatype T' is �derived� by �restriction� from an
19867	* atomic datatype T then the �value space� of T' is a subset of
19868	* the �value space� of T. */
19869	/*
19870	* (2) if datatypes T' and T'' are �derived� by �restriction�
19871	* from a common atomic ancestor T then the �value space�s of T'
19872	* and T'' may overlap.
19873	*/
19874	if (ptx != pty)
19875	    return(0);
19876	/*
19877	* We assume computed values to be normalized, so do a fast
19878	* string comparison for string based types.
19879	*/
19880	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
19881	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
19882	    if (! xmlStrEqual(
19883		xmlSchemaValueGetAsString(x),
19884		xmlSchemaValueGetAsString(y)))
19885		return (0);
19886	} else {
19887	    ret = xmlSchemaCompareValuesWhtsp(
19888		x, XML_SCHEMA_WHITESPACE_PRESERVE,
19889		y, XML_SCHEMA_WHITESPACE_PRESERVE);
19890	    if (ret == -2)
19891		return(-1);
19892	    if (ret != 0)
19893		return(0);
19894	}
19895	/*
19896	* Lists.
19897	*/
19898	x = xmlSchemaValueGetNext(x);
19899	if (x != NULL) {
19900	    y = xmlSchemaValueGetNext(y);
19901	    if (y == NULL)
19902		return (0);
19903	} else if (xmlSchemaValueGetNext(y) != NULL)
19904	    return (0);
19905	else
19906	    return (1);
19907    }
19908    return (0);
19909}
19910
19911/**
19912 * xmlSchemaResolveAttrUseReferences:
19913 * @item:  an attribute use
19914 * @ctxt:  a parser context
19915 *
19916 * Resolves the referenced attribute declaration.
19917 */
19918static int
19919xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
19920				  xmlSchemaParserCtxtPtr ctxt)
19921{
19922    if ((ctxt == NULL) || (ause == NULL))
19923	return(-1);
19924    if ((ause->attrDecl == NULL) ||
19925	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
19926	return(0);
19927
19928    {
19929	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
19930
19931	/*
19932	* TODO: Evaluate, what errors could occur if the declaration is not
19933	* found.
19934	*/
19935	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
19936	    ref->name, ref->targetNamespace);
19937        if (ause->attrDecl == NULL) {
19938	    xmlSchemaPResCompAttrErr(ctxt,
19939	    	XML_SCHEMAP_SRC_RESOLVE,
19940		WXS_BASIC_CAST ause, ause->node,
19941		"ref", ref->name, ref->targetNamespace,
19942		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
19943            return(ctxt->err);;
19944        }
19945    }
19946    return(0);
19947}
19948
19949/**
19950 * xmlSchemaCheckAttrUsePropsCorrect:
19951 * @ctxt:  a parser context
19952 * @use:  an attribute use
19953 *
19954 * Schema Component Constraint:
19955 * Attribute Use Correct (au-props-correct)
19956 *
19957 */
19958static int
19959xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
19960			     xmlSchemaAttributeUsePtr use)
19961{
19962    if ((ctxt == NULL) || (use == NULL))
19963	return(-1);
19964    if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
19965	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
19966	return(0);
19967
19968    /*
19969    * SPEC au-props-correct (1)
19970    * "The values of the properties of an attribute use must be as
19971    * described in the property tableau in The Attribute Use Schema
19972    * Component (�3.5.1), modulo the impact of Missing
19973    * Sub-components (�5.3)."
19974    */
19975
19976    if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
19977	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
19978        ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
19979    {
19980	xmlSchemaPCustomErr(ctxt,
19981	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
19982	    WXS_BASIC_CAST use, NULL,
19983	    "The attribute declaration has a 'fixed' value constraint "
19984	    ", thus the attribute use must also have a 'fixed' value "
19985	    "constraint",
19986	    NULL);
19987	return(ctxt->err);
19988    }
19989    /*
19990    * Compute and check the value constraint's value.
19991    */
19992    if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
19993	int ret;
19994	/*
19995	* TODO: The spec seems to be missing a check of the
19996	* value constraint of the attribute use. We will do it here.
19997	*/
19998	/*
19999	* SPEC a-props-correct (3)
20000	*/
20001	if (xmlSchemaIsDerivedFromBuiltInType(
20002	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20003	{
20004	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20005		XML_SCHEMAP_AU_PROPS_CORRECT,
20006		NULL, WXS_BASIC_CAST use,
20007		"Value constraints are not allowed if the type definition "
20008		"is or is derived from xs:ID",
20009		NULL, NULL);
20010	    return(ctxt->err);
20011	}
20012
20013	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20014	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20015	    use->defValue, &(use->defVal),
20016	    1, 1, 0);
20017	if (ret != 0) {
20018	    if (ret < 0) {
20019		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20020		    "calling xmlSchemaVCheckCVCSimpleType()");
20021		return(-1);
20022	    }
20023	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20024		XML_SCHEMAP_AU_PROPS_CORRECT,
20025		NULL, WXS_BASIC_CAST use,
20026		"The value of the value constraint is not valid",
20027		NULL, NULL);
20028	    return(ctxt->err);
20029	}
20030    }
20031    /*
20032    * SPEC au-props-correct (2)
20033    * "If the {attribute declaration} has a fixed
20034    * {value constraint}, then if the attribute use itself has a
20035    * {value constraint}, it must also be fixed and its value must match
20036    * that of the {attribute declaration}'s {value constraint}."
20037    */
20038    if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20039	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20040    {
20041	if (! xmlSchemaAreValuesEqual(use->defVal,
20042		(WXS_ATTRUSE_DECL(use))->defVal))
20043	{
20044	    xmlSchemaPCustomErr(ctxt,
20045		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20046		WXS_BASIC_CAST use, NULL,
20047		"The 'fixed' value constraint of the attribute use "
20048		"must match the attribute declaration's value "
20049		"constraint '%s'",
20050		(WXS_ATTRUSE_DECL(use))->defValue);
20051	}
20052	return(ctxt->err);
20053    }
20054    return(0);
20055}
20056
20057
20058
20059
20060/**
20061 * xmlSchemaResolveAttrTypeReferences:
20062 * @item:  an attribute declaration
20063 * @ctxt:  a parser context
20064 *
20065 * Resolves the referenced type definition component.
20066 */
20067static int
20068xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20069				   xmlSchemaParserCtxtPtr ctxt)
20070{
20071    /*
20072    * The simple type definition corresponding to the <simpleType> element
20073    * information item in the [children], if present, otherwise the simple
20074    * type definition �resolved� to by the �actual value� of the type
20075    * [attribute], if present, otherwise the �simple ur-type definition�.
20076    */
20077    if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20078	return(0);
20079    item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20080    if (item->subtypes != NULL)
20081        return(0);
20082    if (item->typeName != NULL) {
20083        xmlSchemaTypePtr type;
20084
20085	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20086	    item->typeNs);
20087	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20088	    xmlSchemaPResCompAttrErr(ctxt,
20089		XML_SCHEMAP_SRC_RESOLVE,
20090		WXS_BASIC_CAST item, item->node,
20091		"type", item->typeName, item->typeNs,
20092		XML_SCHEMA_TYPE_SIMPLE, NULL);
20093	    return(ctxt->err);
20094	} else
20095	    item->subtypes = type;
20096
20097    } else {
20098	/*
20099	* The type defaults to the xs:anySimpleType.
20100	*/
20101	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20102    }
20103    return(0);
20104}
20105
20106/**
20107 * xmlSchemaResolveIDCKeyReferences:
20108 * @idc:  the identity-constraint definition
20109 * @ctxt:  the schema parser context
20110 * @name:  the attribute name
20111 *
20112 * Resolve keyRef references to key/unique IDCs.
20113 * Schema Component Constraint:
20114 *   Identity-constraint Definition Properties Correct (c-props-correct)
20115 */
20116static int
20117xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20118			  xmlSchemaParserCtxtPtr pctxt)
20119{
20120    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20121        return(0);
20122    if (idc->ref->name != NULL) {
20123	idc->ref->item = (xmlSchemaBasicItemPtr)
20124	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20125		idc->ref->targetNamespace);
20126        if (idc->ref->item == NULL) {
20127	    /*
20128	    * TODO: It is actually not an error to fail to resolve
20129	    * at this stage. BUT we need to be that strict!
20130	    */
20131	    xmlSchemaPResCompAttrErr(pctxt,
20132		XML_SCHEMAP_SRC_RESOLVE,
20133		WXS_BASIC_CAST idc, idc->node,
20134		"refer", idc->ref->name,
20135		idc->ref->targetNamespace,
20136		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20137            return(pctxt->err);
20138	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20139	    /*
20140	    * SPEC c-props-correct (1)
20141	    */
20142	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20143		XML_SCHEMAP_C_PROPS_CORRECT,
20144		NULL, WXS_BASIC_CAST idc,
20145		"The keyref references a keyref",
20146		NULL, NULL);
20147	    idc->ref->item = NULL;
20148	    return(pctxt->err);
20149	} else {
20150	    if (idc->nbFields !=
20151		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20152		xmlChar *str = NULL;
20153		xmlSchemaIDCPtr refer;
20154
20155		refer = (xmlSchemaIDCPtr) idc->ref->item;
20156		/*
20157		* SPEC c-props-correct(2)
20158		* "If the {identity-constraint category} is keyref,
20159		* the cardinality of the {fields} must equal that of
20160		* the {fields} of the {referenced key}.
20161		*/
20162		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20163		    XML_SCHEMAP_C_PROPS_CORRECT,
20164		    NULL, WXS_BASIC_CAST idc,
20165		    "The cardinality of the keyref differs from the "
20166		    "cardinality of the referenced key/unique '%s'",
20167		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20168			refer->name),
20169		    NULL);
20170		FREE_AND_NULL(str)
20171		return(pctxt->err);
20172	    }
20173	}
20174    }
20175    return(0);
20176}
20177
20178static int
20179xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20180				       xmlSchemaParserCtxtPtr pctxt)
20181{
20182    if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20183	prohib->targetNamespace) == NULL) {
20184
20185	xmlSchemaPResCompAttrErr(pctxt,
20186	    XML_SCHEMAP_SRC_RESOLVE,
20187	    NULL, prohib->node,
20188	    "ref", prohib->name, prohib->targetNamespace,
20189	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20190	return(XML_SCHEMAP_SRC_RESOLVE);
20191    }
20192    return(0);
20193}
20194
20195#define WXS_REDEFINED_TYPE(c) \
20196(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20197
20198#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20199(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20200
20201#define WXS_REDEFINED_ATTR_GROUP(c) \
20202(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20203
20204static int
20205xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20206{
20207    int err = 0;
20208    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20209    xmlSchemaBasicItemPtr prev, item;
20210    int wasRedefined;
20211
20212    if (redef == NULL)
20213	return(0);
20214
20215    do {
20216	item = redef->item;
20217	/*
20218	* First try to locate the redefined component in the
20219	* schema graph starting with the redefined schema.
20220	* NOTE: According to this schema bug entry:
20221	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20222	*   it's not clear if the referenced component needs to originate
20223	*   from the <redefine>d schema _document_ or the schema; the latter
20224	*   would include all imported and included sub-schemas of the
20225	*   <redefine>d schema. Currenlty we latter approach is used.
20226	*   SUPPLEMENT: It seems that the WG moves towards the latter
20227	*   approach, so we are doing it right.
20228	*
20229	*/
20230	prev = xmlSchemaFindRedefCompInGraph(
20231	    redef->targetBucket, item->type,
20232	    redef->refName, redef->refTargetNs);
20233	if (prev == NULL) {
20234	    xmlChar *str = NULL;
20235	    xmlNodePtr node;
20236
20237	    /*
20238	    * SPEC src-redefine:
20239	    * (6.2.1) "The �actual value� of its own name attribute plus
20240	    * target namespace must successfully �resolve� to a model
20241	    * group definition in I."
20242	    * (7.2.1) "The �actual value� of its own name attribute plus
20243	    * target namespace must successfully �resolve� to an attribute
20244	    * group definition in I."
20245
20246	    *
20247	    * Note that, if we are redefining with the use of references
20248	    * to components, the spec assumes the src-resolve to be used;
20249	    * but this won't assure that we search only *inside* the
20250	    * redefined schema.
20251	    */
20252	    if (redef->reference)
20253		node = WXS_ITEM_NODE(redef->reference);
20254	    else
20255		node = WXS_ITEM_NODE(item);
20256	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20257		/*
20258		* TODO: error code.
20259		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20260		* reference kind.
20261		*/
20262		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20263		"The %s '%s' to be redefined could not be found in "
20264		"the redefined schema",
20265		WXS_ITEM_TYPE_NAME(item),
20266		xmlSchemaFormatQName(&str, redef->refTargetNs,
20267		    redef->refName));
20268	    FREE_AND_NULL(str);
20269	    err = pctxt->err;
20270	    redef = redef->next;
20271	    continue;
20272	}
20273	/*
20274	* TODO: Obtaining and setting the redefinition state is really
20275	* clumsy.
20276	*/
20277	wasRedefined = 0;
20278	switch (item->type) {
20279	    case XML_SCHEMA_TYPE_COMPLEX:
20280	    case XML_SCHEMA_TYPE_SIMPLE:
20281		if ((WXS_TYPE_CAST prev)->flags &
20282		    XML_SCHEMAS_TYPE_REDEFINED)
20283		{
20284		    wasRedefined = 1;
20285		    break;
20286		}
20287		/* Mark it as redefined. */
20288		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20289		/*
20290		* Assign the redefined type to the
20291		* base type of the redefining type.
20292		* TODO: How
20293		*/
20294		((xmlSchemaTypePtr) item)->baseType =
20295		    (xmlSchemaTypePtr) prev;
20296		break;
20297	    case XML_SCHEMA_TYPE_GROUP:
20298		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20299		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20300		{
20301		    wasRedefined = 1;
20302		    break;
20303		}
20304		/* Mark it as redefined. */
20305		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20306		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20307		if (redef->reference != NULL) {
20308		    /*
20309		    * Overwrite the QName-reference with the
20310		    * referenced model group def.
20311		    */
20312		    (WXS_PTC_CAST redef->reference)->children =
20313			WXS_TREE_CAST prev;
20314		}
20315		redef->target = prev;
20316		break;
20317	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20318		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20319		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20320		{
20321		    wasRedefined = 1;
20322		    break;
20323		}
20324		(WXS_ATTR_GROUP_CAST prev)->flags |=
20325		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20326		if (redef->reference != NULL) {
20327		    /*
20328		    * Assign the redefined attribute group to the
20329		    * QName-reference component.
20330		    * This is the easy case, since we will just
20331		    * expand the redefined group.
20332		    */
20333		    (WXS_QNAME_CAST redef->reference)->item = prev;
20334		    redef->target = NULL;
20335		} else {
20336		    /*
20337		    * This is the complicated case: we need
20338		    * to apply src-redefine (7.2.2) at a later
20339		    * stage, i.e. when attribute group references
20340		    * have beed expanded and simple types have
20341		    * beed fixed.
20342		    */
20343		    redef->target = prev;
20344		}
20345		break;
20346	    default:
20347		PERROR_INT("xmlSchemaResolveRedefReferences",
20348		    "Unexpected redefined component type");
20349		return(-1);
20350	}
20351	if (wasRedefined) {
20352	    xmlChar *str = NULL;
20353	    xmlNodePtr node;
20354
20355	    if (redef->reference)
20356		node = WXS_ITEM_NODE(redef->reference);
20357	    else
20358		node = WXS_ITEM_NODE(redef->item);
20359
20360	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20361		/* TODO: error code. */
20362		XML_SCHEMAP_SRC_REDEFINE,
20363		node, NULL,
20364		"The referenced %s was already redefined. Multiple "
20365		"redefinition of the same component is not supported",
20366		xmlSchemaGetComponentDesignation(&str, prev),
20367		NULL);
20368	    FREE_AND_NULL(str)
20369	    err = pctxt->err;
20370	    redef = redef->next;
20371	    continue;
20372	}
20373	redef = redef->next;
20374    } while (redef != NULL);
20375
20376    return(err);
20377}
20378
20379static int
20380xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20381{
20382    int err = 0;
20383    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20384    xmlSchemaBasicItemPtr item;
20385
20386    if (redef == NULL)
20387	return(0);
20388
20389    do {
20390	if (redef->target == NULL) {
20391	    redef = redef->next;
20392	    continue;
20393	}
20394	item = redef->item;
20395
20396	switch (item->type) {
20397	    case XML_SCHEMA_TYPE_SIMPLE:
20398	    case XML_SCHEMA_TYPE_COMPLEX:
20399		/*
20400		* Since the spec wants the {name} of the redefined
20401		* type to be 'absent', we'll NULL it.
20402		*/
20403		(WXS_TYPE_CAST redef->target)->name = NULL;
20404
20405		/*
20406		* TODO: Seems like there's nothing more to do. The normal
20407		* inheritance mechanism is used. But not 100% sure.
20408		*/
20409		break;
20410	    case XML_SCHEMA_TYPE_GROUP:
20411		/*
20412		* URGENT TODO:
20413		* SPEC src-redefine:
20414		* (6.2.2) "The {model group} of the model group definition
20415		* which corresponds to it per XML Representation of Model
20416		* Group Definition Schema Components (�3.7.2) must be a
20417		* �valid restriction� of the {model group} of that model
20418		* group definition in I, as defined in Particle Valid
20419		* (Restriction) (�3.9.6)."
20420		*/
20421		break;
20422	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20423		/*
20424		* SPEC src-redefine:
20425		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20426		* the attribute group definition which corresponds to it
20427		* per XML Representation of Attribute Group Definition Schema
20428		* Components (�3.6.2) must be �valid restrictions� of the
20429		* {attribute uses} and {attribute wildcard} of that attribute
20430		* group definition in I, as defined in clause 2, clause 3 and
20431		* clause 4 of Derivation Valid (Restriction, Complex)
20432		* (�3.4.6) (where references to the base type definition are
20433		* understood as references to the attribute group definition
20434		* in I)."
20435		*/
20436		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20437		    XML_SCHEMA_ACTION_REDEFINE,
20438		    item, redef->target,
20439		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20440		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20441		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20442		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20443		if (err == -1)
20444		    return(-1);
20445		break;
20446	    default:
20447		break;
20448	}
20449	redef = redef->next;
20450    } while (redef != NULL);
20451    return(0);
20452}
20453
20454
20455static int
20456xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20457		       xmlSchemaBucketPtr bucket)
20458{
20459    xmlSchemaBasicItemPtr item;
20460    int err;
20461    xmlHashTablePtr *table;
20462    const xmlChar *name;
20463    int i;
20464
20465#define WXS_GET_GLOBAL_HASH(c, slot) { \
20466    if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20467	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20468    else \
20469	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20470
20471    /*
20472    * Add global components to the schema's hash tables.
20473    * This is the place where duplicate components will be
20474    * detected.
20475    * TODO: I think normally we should support imports of the
20476    *   same namespace from multiple locations. We don't do currently,
20477    *   but if we do then according to:
20478    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20479    *   we would need, if imported directly, to import redefined
20480    *   components as well to be able to catch clashing components.
20481    *   (I hope I'll still know what this means after some months :-()
20482    */
20483    if (bucket == NULL)
20484	return(-1);
20485    if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20486	return(0);
20487    bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20488
20489    for (i = 0; i < bucket->globals->nbItems; i++) {
20490	item = bucket->globals->items[i];
20491	table = NULL;
20492	switch (item->type) {
20493	    case XML_SCHEMA_TYPE_COMPLEX:
20494	    case XML_SCHEMA_TYPE_SIMPLE:
20495		if (WXS_REDEFINED_TYPE(item))
20496		    continue;
20497		name = (WXS_TYPE_CAST item)->name;
20498		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20499		break;
20500	    case XML_SCHEMA_TYPE_ELEMENT:
20501		name = (WXS_ELEM_CAST item)->name;
20502		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20503		break;
20504	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20505		name = (WXS_ATTR_CAST item)->name;
20506		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20507		break;
20508	    case XML_SCHEMA_TYPE_GROUP:
20509		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20510		    continue;
20511		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20512		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20513		break;
20514	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20515		if (WXS_REDEFINED_ATTR_GROUP(item))
20516		    continue;
20517		name = (WXS_ATTR_GROUP_CAST item)->name;
20518		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20519		break;
20520	    case XML_SCHEMA_TYPE_IDC_KEY:
20521	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20522	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20523		name = (WXS_IDC_CAST item)->name;
20524		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20525		break;
20526	    case XML_SCHEMA_TYPE_NOTATION:
20527		name = ((xmlSchemaNotationPtr) item)->name;
20528		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20529		break;
20530	    default:
20531		PERROR_INT("xmlSchemaAddComponents",
20532		    "Unexpected global component type");
20533		continue;
20534	}
20535	if (*table == NULL) {
20536	    *table = xmlHashCreateDict(10, pctxt->dict);
20537	    if (*table == NULL) {
20538		PERROR_INT("xmlSchemaAddComponents",
20539		    "failed to create a component hash table");
20540		return(-1);
20541	    }
20542	}
20543	err = xmlHashAddEntry(*table, name, item);
20544	if (err != 0) {
20545	    xmlChar *str = NULL;
20546
20547	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20548		XML_SCHEMAP_REDEFINED_TYPE,
20549		WXS_ITEM_NODE(item),
20550		WXS_BASIC_CAST item,
20551		"A global %s '%s' does already exist",
20552		WXS_ITEM_TYPE_NAME(item),
20553		xmlSchemaGetComponentQName(&str, item));
20554	    FREE_AND_NULL(str);
20555	}
20556    }
20557    /*
20558    * Process imported/included schemas.
20559    */
20560    if (bucket->relations != NULL) {
20561	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20562	do {
20563	    if ((rel->bucket != NULL) &&
20564		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20565		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20566		    return(-1);
20567	    }
20568	    rel = rel->next;
20569	} while (rel != NULL);
20570    }
20571    return(0);
20572}
20573
20574static int
20575xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20576			 xmlSchemaBucketPtr rootBucket)
20577{
20578    xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20579    xmlSchemaTreeItemPtr item, *items;
20580    int nbItems, i, ret = 0;
20581    xmlSchemaBucketPtr oldbucket = con->bucket;
20582
20583#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20584
20585    if ((con->pending == NULL) ||
20586	(con->pending->nbItems == 0))
20587	return(0);
20588
20589    /*
20590    * Since xmlSchemaFixupComplexType() will create new particles
20591    * (local components), and those particle components need a bucket
20592    * on the constructor, we'll assure here that the constructor has
20593    * a bucket.
20594    * TODO: Think about storing locals _only_ on the main bucket.
20595    */
20596    if (con->bucket == NULL)
20597	con->bucket = rootBucket;
20598
20599    /* TODO:
20600    * SPEC (src-redefine):
20601    * (6.2) "If it has no such self-reference, then all of the
20602    * following must be true:"
20603
20604    * (6.2.2) The {model group} of the model group definition which
20605    * corresponds to it per XML Representation of Model Group
20606    * Definition Schema Components (�3.7.2) must be a �valid
20607    * restriction� of the {model group} of that model group definition
20608    * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20609    */
20610    xmlSchemaCheckSRCRedefineFirst(pctxt);
20611
20612    /*
20613    * Add global components to the schemata's hash tables.
20614    */
20615    xmlSchemaAddComponents(pctxt, rootBucket);
20616
20617    pctxt->ctxtType = NULL;
20618    items = (xmlSchemaTreeItemPtr *) con->pending->items;
20619    nbItems = con->pending->nbItems;
20620    /*
20621    * Now that we have parsed *all* the schema document(s) and converted
20622    * them to schema components, we can resolve references, apply component
20623    * constraints, create the FSA from the content model, etc.
20624    */
20625    /*
20626    * Resolve references of..
20627    *
20628    * 1. element declarations:
20629    *   - the type definition
20630    *   - the substitution group affiliation
20631    * 2. simple/complex types:
20632    *   - the base type definition
20633    *   - the memberTypes of union types
20634    *   - the itemType of list types
20635    * 3. attributes declarations and attribute uses:
20636    *   - the type definition
20637    *   - if an attribute use, then the attribute declaration
20638    * 4. attribute group references:
20639    *   - the attribute group definition
20640    * 5. particles:
20641    *   - the term of the particle (e.g. a model group)
20642    * 6. IDC key-references:
20643    *   - the referenced IDC 'key' or 'unique' definition
20644    * 7. Attribute prohibitions which had a "ref" attribute.
20645    */
20646    for (i = 0; i < nbItems; i++) {
20647	item = items[i];
20648	switch (item->type) {
20649	    case XML_SCHEMA_TYPE_ELEMENT:
20650		xmlSchemaResolveElementReferences(
20651		    (xmlSchemaElementPtr) item, pctxt);
20652		FIXHFAILURE;
20653		break;
20654	    case XML_SCHEMA_TYPE_COMPLEX:
20655	    case XML_SCHEMA_TYPE_SIMPLE:
20656		xmlSchemaResolveTypeReferences(
20657		    (xmlSchemaTypePtr) item, pctxt);
20658		FIXHFAILURE;
20659		break;
20660	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20661		xmlSchemaResolveAttrTypeReferences(
20662		    (xmlSchemaAttributePtr) item, pctxt);
20663		FIXHFAILURE;
20664		break;
20665	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20666		xmlSchemaResolveAttrUseReferences(
20667		    (xmlSchemaAttributeUsePtr) item, pctxt);
20668		FIXHFAILURE;
20669		break;
20670	    case XML_SCHEMA_EXTRA_QNAMEREF:
20671		if ((WXS_QNAME_CAST item)->itemType ==
20672		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20673		{
20674		    xmlSchemaResolveAttrGroupReferences(
20675			WXS_QNAME_CAST item, pctxt);
20676		}
20677		FIXHFAILURE;
20678		break;
20679	    case XML_SCHEMA_TYPE_SEQUENCE:
20680	    case XML_SCHEMA_TYPE_CHOICE:
20681	    case XML_SCHEMA_TYPE_ALL:
20682		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20683		    WXS_MODEL_GROUP_CAST item);
20684		FIXHFAILURE;
20685		break;
20686	    case XML_SCHEMA_TYPE_IDC_KEY:
20687	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20688	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20689		xmlSchemaResolveIDCKeyReferences(
20690		    (xmlSchemaIDCPtr) item, pctxt);
20691		FIXHFAILURE;
20692		break;
20693	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20694		/*
20695		* Handle attribue prohibition which had a
20696		* "ref" attribute.
20697		*/
20698		xmlSchemaResolveAttrUseProhibReferences(
20699		    WXS_ATTR_PROHIB_CAST item, pctxt);
20700		FIXHFAILURE;
20701		break;
20702	    default:
20703		break;
20704	}
20705    }
20706    if (pctxt->nberrors != 0)
20707	goto exit_error;
20708
20709    /*
20710    * Now that all references are resolved we
20711    * can check for circularity of...
20712    * 1. the base axis of type definitions
20713    * 2. nested model group definitions
20714    * 3. nested attribute group definitions
20715    * TODO: check for circual substitution groups.
20716    */
20717    for (i = 0; i < nbItems; i++) {
20718	item = items[i];
20719	/*
20720	* Let's better stop on the first error here.
20721	*/
20722	switch (item->type) {
20723	    case XML_SCHEMA_TYPE_COMPLEX:
20724	    case XML_SCHEMA_TYPE_SIMPLE:
20725		xmlSchemaCheckTypeDefCircular(
20726		    (xmlSchemaTypePtr) item, pctxt);
20727		FIXHFAILURE;
20728		if (pctxt->nberrors != 0)
20729		    goto exit_error;
20730		break;
20731	    case XML_SCHEMA_TYPE_GROUP:
20732		xmlSchemaCheckGroupDefCircular(
20733		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20734		FIXHFAILURE;
20735		if (pctxt->nberrors != 0)
20736		    goto exit_error;
20737		break;
20738	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20739		xmlSchemaCheckAttrGroupCircular(
20740		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20741		FIXHFAILURE;
20742		if (pctxt->nberrors != 0)
20743		    goto exit_error;
20744		break;
20745	    default:
20746		break;
20747	}
20748    }
20749    if (pctxt->nberrors != 0)
20750	goto exit_error;
20751    /*
20752    * Model group definition references:
20753    * Such a reference is reflected by a particle at the component
20754    * level. Until now the 'term' of such particles pointed
20755    * to the model group definition; this was done, in order to
20756    * ease circularity checks. Now we need to set the 'term' of
20757    * such particles to the model group of the model group definition.
20758    */
20759    for (i = 0; i < nbItems; i++) {
20760	item = items[i];
20761	switch (item->type) {
20762	    case XML_SCHEMA_TYPE_SEQUENCE:
20763	    case XML_SCHEMA_TYPE_CHOICE:
20764		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20765		    WXS_MODEL_GROUP_CAST item);
20766		break;
20767	    default:
20768		break;
20769	}
20770    }
20771    if (pctxt->nberrors != 0)
20772	goto exit_error;
20773    /*
20774    * Expand attribute group references of attribute group definitions.
20775    */
20776    for (i = 0; i < nbItems; i++) {
20777	item = items[i];
20778	switch (item->type) {
20779            case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20780		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20781		    WXS_ATTR_GROUP_HAS_REFS(item))
20782		{
20783		    xmlSchemaAttributeGroupExpandRefs(pctxt,
20784			WXS_ATTR_GROUP_CAST item);
20785		    FIXHFAILURE;
20786		}
20787		break;
20788	    default:
20789		break;
20790	}
20791    }
20792    if (pctxt->nberrors != 0)
20793	goto exit_error;
20794    /*
20795    * First compute the variety of simple types. This is needed as
20796    * a seperate step, since otherwise we won't be able to detect
20797    * circular union types in all cases.
20798    */
20799    for (i = 0; i < nbItems; i++) {
20800	item = items[i];
20801	switch (item->type) {
20802            case XML_SCHEMA_TYPE_SIMPLE:
20803		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20804		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
20805			(xmlSchemaTypePtr) item);
20806		    FIXHFAILURE;
20807		}
20808		break;
20809	    default:
20810		break;
20811	}
20812    }
20813    if (pctxt->nberrors != 0)
20814	goto exit_error;
20815    /*
20816    * Detect circular union types. Note that this needs the variety to
20817    * be already computed.
20818    */
20819    for (i = 0; i < nbItems; i++) {
20820	item = items[i];
20821	switch (item->type) {
20822            case XML_SCHEMA_TYPE_SIMPLE:
20823		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20824		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
20825			(xmlSchemaTypePtr) item);
20826		    FIXHFAILURE;
20827		}
20828		break;
20829	    default:
20830		break;
20831	}
20832    }
20833    if (pctxt->nberrors != 0)
20834	goto exit_error;
20835
20836    /*
20837    * Do the complete type fixup for simple types.
20838    */
20839    for (i = 0; i < nbItems; i++) {
20840	item = items[i];
20841	switch (item->type) {
20842            case XML_SCHEMA_TYPE_SIMPLE:
20843		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20844		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20845		    FIXHFAILURE;
20846		}
20847		break;
20848	    default:
20849		break;
20850	}
20851    }
20852    if (pctxt->nberrors != 0)
20853	goto exit_error;
20854    /*
20855    * At this point we need all simple types to be builded and checked.
20856    */
20857    /*
20858    * Apply contraints for attribute declarations.
20859    */
20860    for (i = 0; i < nbItems; i++) {
20861	item = items[i];
20862	switch (item->type) {
20863	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20864		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
20865		FIXHFAILURE;
20866		break;
20867	    default:
20868		break;
20869	}
20870    }
20871    if (pctxt->nberrors != 0)
20872	goto exit_error;
20873    /*
20874    * Apply constraints for attribute uses.
20875    */
20876    for (i = 0; i < nbItems; i++) {
20877	item = items[i];
20878	switch (item->type) {
20879	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20880		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
20881		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
20882			WXS_ATTR_USE_CAST item);
20883		    FIXHFAILURE;
20884		}
20885		break;
20886	    default:
20887		break;
20888	}
20889    }
20890    if (pctxt->nberrors != 0)
20891	goto exit_error;
20892
20893    /*
20894    * Apply constraints for attribute group definitions.
20895    */
20896    for (i = 0; i < nbItems; i++) {
20897	item = items[i];
20898	switch (item->type) {
20899	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20900	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
20901		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
20902	    {
20903		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
20904		FIXHFAILURE;
20905	    }
20906	    break;
20907	default:
20908	    break;
20909	}
20910    }
20911    if (pctxt->nberrors != 0)
20912	goto exit_error;
20913
20914    /*
20915    * Apply constraints for redefinitions.
20916    */
20917    if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
20918	xmlSchemaCheckSRCRedefineSecond(pctxt);
20919    if (pctxt->nberrors != 0)
20920	goto exit_error;
20921
20922    /*
20923    * Fixup complex types.
20924    */
20925    for (i = 0; i < nbItems; i++) {
20926	item = con->pending->items[i];
20927	switch (item->type) {
20928	    case XML_SCHEMA_TYPE_COMPLEX:
20929		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20930		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
20931		    FIXHFAILURE;
20932		}
20933		break;
20934	    default:
20935		break;
20936	}
20937    }
20938    if (pctxt->nberrors != 0)
20939	goto exit_error;
20940
20941    /*
20942    * The list could have changed, since xmlSchemaFixupComplexType()
20943    * will create particles and model groups in some cases.
20944    */
20945    items = (xmlSchemaTreeItemPtr *) con->pending->items;
20946    nbItems = con->pending->nbItems;
20947
20948    /*
20949    * At this point all complex types need to be builded and checked.
20950    */
20951    /*
20952    * Apply some constraints for element declarations.
20953    */
20954    for (i = 0; i < nbItems; i++) {
20955	item = items[i];
20956	switch (item->type) {
20957	    case XML_SCHEMA_TYPE_ELEMENT:
20958
20959		if ((((xmlSchemaElementPtr) item)->flags &
20960		    XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
20961		    xmlSchemaCheckElementDeclComponent(
20962			(xmlSchemaElementPtr) item, pctxt);
20963		    FIXHFAILURE;
20964		}
20965		break;
20966	    default:
20967		break;
20968	}
20969    }
20970    if (pctxt->nberrors != 0)
20971	goto exit_error;
20972    /*
20973    * Finally we can build the automaton from the content model of
20974    * complex types.
20975    */
20976
20977    for (i = 0; i < nbItems; i++) {
20978	item = items[i];
20979	switch (item->type) {
20980	    case XML_SCHEMA_TYPE_COMPLEX:
20981		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
20982		/* FIXHFAILURE; */
20983		break;
20984	    default:
20985		break;
20986	}
20987    }
20988    if (pctxt->nberrors != 0)
20989	goto exit_error;
20990    /*
20991    * URGENT TODO: cos-element-consistent
20992    */
20993    goto exit;
20994
20995exit_error:
20996    ret = pctxt->err;
20997    goto exit;
20998
20999exit_failure:
21000    ret = -1;
21001
21002exit:
21003    /*
21004    * Reset the constructor. This is needed for XSI acquisition, since
21005    * those items will be processed over and over again for every XSI
21006    * if not cleared here.
21007    */
21008    con->bucket = oldbucket;
21009    con->pending->nbItems = 0;
21010    if (con->substGroups != NULL) {
21011	xmlHashFree(con->substGroups,
21012	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21013	con->substGroups = NULL;
21014    }
21015    if (con->redefs != NULL) {
21016	xmlSchemaRedefListFree(con->redefs);
21017	con->redefs = NULL;
21018    }
21019    return(ret);
21020}
21021/**
21022 * xmlSchemaParse:
21023 * @ctxt:  a schema validation context
21024 *
21025 * parse a schema definition resource and build an internal
21026 * XML Shema struture which can be used to validate instances.
21027 *
21028 * Returns the internal XML Schema structure built from the resource or
21029 *         NULL in case of error
21030 */
21031xmlSchemaPtr
21032xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21033{
21034    xmlSchemaPtr mainSchema = NULL;
21035    xmlSchemaBucketPtr bucket = NULL;
21036    int res;
21037
21038    /*
21039    * This one is used if the schema to be parsed was specified via
21040    * the API; i.e. not automatically by the validated instance document.
21041    */
21042
21043    xmlSchemaInitTypes();
21044
21045    if (ctxt == NULL)
21046        return (NULL);
21047
21048    /* TODO: Init the context. Is this all we need?*/
21049    ctxt->nberrors = 0;
21050    ctxt->err = 0;
21051    ctxt->counter = 0;
21052
21053    /* Create the *main* schema. */
21054    mainSchema = xmlSchemaNewSchema(ctxt);
21055    if (mainSchema == NULL)
21056	goto exit_failure;
21057    /*
21058    * Create the schema constructor.
21059    */
21060    if (ctxt->constructor == NULL) {
21061	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21062	if (ctxt->constructor == NULL)
21063	    return(NULL);
21064	/* Take ownership of the constructor to be able to free it. */
21065	ctxt->ownsConstructor = 1;
21066    }
21067    ctxt->constructor->mainSchema = mainSchema;
21068    /*
21069    * Locate and add the schema document.
21070    */
21071    res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21072	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21073	NULL, NULL, &bucket);
21074    if (res == -1)
21075	goto exit_failure;
21076    if (res != 0)
21077	goto exit;
21078
21079    if (bucket == NULL) {
21080	/* TODO: Error code, actually we failed to *locate* the schema. */
21081	if (ctxt->URL)
21082	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21083		NULL, NULL,
21084		"Failed to locate the main schema resource at '%s'",
21085		ctxt->URL, NULL);
21086	else
21087	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21088		NULL, NULL,
21089		"Failed to locate the main schema resource",
21090		    NULL, NULL);
21091	goto exit;
21092    }
21093    /* Then do the parsing for good. */
21094    if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21095	goto exit_failure;
21096    if (ctxt->nberrors != 0)
21097	goto exit;
21098
21099    mainSchema->doc = bucket->doc;
21100    mainSchema->preserve = ctxt->preserve;
21101
21102    ctxt->schema = mainSchema;
21103
21104    if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21105	goto exit_failure;
21106
21107    /*
21108    * TODO: This is not nice, since we cannot distinguish from the
21109    * result if there was an internal error or not.
21110    */
21111exit:
21112    if (ctxt->nberrors != 0) {
21113	if (mainSchema) {
21114	    xmlSchemaFree(mainSchema);
21115	    mainSchema = NULL;
21116	}
21117	if (ctxt->constructor) {
21118	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21119	    ctxt->constructor = NULL;
21120	    ctxt->ownsConstructor = 0;
21121	}
21122    }
21123    ctxt->schema = NULL;
21124    return(mainSchema);
21125exit_failure:
21126    /*
21127    * Quite verbose, but should catch internal errors, which were
21128    * not communitated.
21129    */
21130    if (mainSchema) {
21131        xmlSchemaFree(mainSchema);
21132	mainSchema = NULL;
21133    }
21134    if (ctxt->constructor) {
21135	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21136	ctxt->constructor = NULL;
21137	ctxt->ownsConstructor = 0;
21138    }
21139    PERROR_INT2("xmlSchemaParse",
21140	"An internal error occured");
21141    ctxt->schema = NULL;
21142    return(NULL);
21143}
21144
21145/**
21146 * xmlSchemaSetParserErrors:
21147 * @ctxt:  a schema validation context
21148 * @err:  the error callback
21149 * @warn:  the warning callback
21150 * @ctx:  contextual data for the callbacks
21151 *
21152 * Set the callback functions used to handle errors for a validation context
21153 */
21154void
21155xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21156                         xmlSchemaValidityErrorFunc err,
21157                         xmlSchemaValidityWarningFunc warn, void *ctx)
21158{
21159    if (ctxt == NULL)
21160        return;
21161    ctxt->error = err;
21162    ctxt->warning = warn;
21163    ctxt->errCtxt = ctx;
21164    if (ctxt->vctxt != NULL)
21165	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21166}
21167
21168/**
21169 * xmlSchemaSetParserStructuredErrors:
21170 * @ctxt:  a schema parser context
21171 * @serror:  the structured error function
21172 * @ctx: the functions context
21173 *
21174 * Set the structured error callback
21175 */
21176void
21177xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21178				   xmlStructuredErrorFunc serror,
21179				   void *ctx)
21180{
21181    if (ctxt == NULL)
21182	return;
21183    ctxt->serror = serror;
21184    ctxt->errCtxt = ctx;
21185    if (ctxt->vctxt != NULL)
21186	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21187}
21188
21189/**
21190 * xmlSchemaGetParserErrors:
21191 * @ctxt:  a XMl-Schema parser context
21192 * @err: the error callback result
21193 * @warn: the warning callback result
21194 * @ctx: contextual data for the callbacks result
21195 *
21196 * Get the callback information used to handle errors for a parser context
21197 *
21198 * Returns -1 in case of failure, 0 otherwise
21199 */
21200int
21201xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21202			 xmlSchemaValidityErrorFunc * err,
21203			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21204{
21205	if (ctxt == NULL)
21206		return(-1);
21207	if (err != NULL)
21208		*err = ctxt->error;
21209	if (warn != NULL)
21210		*warn = ctxt->warning;
21211	if (ctx != NULL)
21212		*ctx = ctxt->errCtxt;
21213	return(0);
21214}
21215
21216/**
21217 * xmlSchemaFacetTypeToString:
21218 * @type:  the facet type
21219 *
21220 * Convert the xmlSchemaTypeType to a char string.
21221 *
21222 * Returns the char string representation of the facet type if the
21223 *     type is a facet and an "Internal Error" string otherwise.
21224 */
21225static const xmlChar *
21226xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21227{
21228    switch (type) {
21229        case XML_SCHEMA_FACET_PATTERN:
21230            return (BAD_CAST "pattern");
21231        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21232            return (BAD_CAST "maxExclusive");
21233        case XML_SCHEMA_FACET_MAXINCLUSIVE:
21234            return (BAD_CAST "maxInclusive");
21235        case XML_SCHEMA_FACET_MINEXCLUSIVE:
21236            return (BAD_CAST "minExclusive");
21237        case XML_SCHEMA_FACET_MININCLUSIVE:
21238            return (BAD_CAST "minInclusive");
21239        case XML_SCHEMA_FACET_WHITESPACE:
21240            return (BAD_CAST "whiteSpace");
21241        case XML_SCHEMA_FACET_ENUMERATION:
21242            return (BAD_CAST "enumeration");
21243        case XML_SCHEMA_FACET_LENGTH:
21244            return (BAD_CAST "length");
21245        case XML_SCHEMA_FACET_MAXLENGTH:
21246            return (BAD_CAST "maxLength");
21247        case XML_SCHEMA_FACET_MINLENGTH:
21248            return (BAD_CAST "minLength");
21249        case XML_SCHEMA_FACET_TOTALDIGITS:
21250            return (BAD_CAST "totalDigits");
21251        case XML_SCHEMA_FACET_FRACTIONDIGITS:
21252            return (BAD_CAST "fractionDigits");
21253        default:
21254            break;
21255    }
21256    return (BAD_CAST "Internal Error");
21257}
21258
21259static xmlSchemaWhitespaceValueType
21260xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21261{
21262    /*
21263    * The normalization type can be changed only for types which are derived
21264    * from xsd:string.
21265    */
21266    if (type->type == XML_SCHEMA_TYPE_BASIC) {
21267	/*
21268	* Note that we assume a whitespace of preserve for anySimpleType.
21269	*/
21270	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21271	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21272	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21273	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21274	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21275	else {
21276	    /*
21277	    * For all �atomic� datatypes other than string (and types �derived�
21278	    * by �restriction� from it) the value of whiteSpace is fixed to
21279	    * collapse
21280	    * Note that this includes built-in list datatypes.
21281	    */
21282	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21283	}
21284    } else if (WXS_IS_LIST(type)) {
21285	/*
21286	* For list types the facet "whiteSpace" is fixed to "collapse".
21287	*/
21288	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21289    } else if (WXS_IS_UNION(type)) {
21290	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21291    } else if (WXS_IS_ATOMIC(type)) {
21292	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21293	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21294	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21295	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21296	else
21297	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21298    }
21299    return (-1);
21300}
21301
21302/************************************************************************
21303 * 									*
21304 * 			Simple type validation				*
21305 * 									*
21306 ************************************************************************/
21307
21308
21309/************************************************************************
21310 * 									*
21311 * 			DOM Validation code				*
21312 * 									*
21313 ************************************************************************/
21314
21315/**
21316 * xmlSchemaAssembleByLocation:
21317 * @pctxt:  a schema parser context
21318 * @vctxt:  a schema validation context
21319 * @schema: the existing schema
21320 * @node: the node that fired the assembling
21321 * @nsName: the namespace name of the new schema
21322 * @location: the location of the schema
21323 *
21324 * Expands an existing schema by an additional schema.
21325 *
21326 * Returns 0 if the new schema is correct, a positive error code
21327 * number otherwise and -1 in case of an internal or API error.
21328 */
21329static int
21330xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21331			    xmlSchemaPtr schema,
21332			    xmlNodePtr node,
21333			    const xmlChar *nsName,
21334			    const xmlChar *location)
21335{
21336    int ret = 0;
21337    xmlSchemaParserCtxtPtr pctxt;
21338    xmlSchemaBucketPtr bucket = NULL;
21339
21340    if ((vctxt == NULL) || (schema == NULL))
21341	return (-1);
21342
21343    if (vctxt->pctxt == NULL) {
21344	VERROR_INT("xmlSchemaAssembleByLocation",
21345	    "no parser context available");
21346	return(-1);
21347    }
21348    pctxt = vctxt->pctxt;
21349    if (pctxt->constructor == NULL) {
21350	PERROR_INT("xmlSchemaAssembleByLocation",
21351	    "no constructor");
21352	return(-1);
21353    }
21354    /*
21355    * Acquire the schema document.
21356    */
21357    location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21358	location, node);
21359    /*
21360    * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21361    * the process will automatically change this to
21362    * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21363    */
21364    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21365	location, NULL, NULL, 0, node, NULL, nsName,
21366	&bucket);
21367    if (ret != 0)
21368	return(ret);
21369    if (bucket == NULL) {
21370	/*
21371	* Generate a warning that the document could not be located.
21372	*/
21373	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21374	    node, NULL,
21375	    "The document at location '%s' could not be acquired",
21376	    location, NULL, NULL);
21377	return(ret);
21378    }
21379    /*
21380    * The first located schema will be handled as if all other
21381    * schemas imported by XSI were imported by this first schema.
21382    */
21383    if ((bucket != NULL) &&
21384	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21385	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21386    /*
21387    * TODO: Is this handled like an import? I.e. is it not an error
21388    * if the schema cannot be located?
21389    */
21390    if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21391	return(0);
21392    /*
21393    * We will reuse the parser context for every schema imported
21394    * directly via XSI. So reset the context.
21395    */
21396    pctxt->nberrors = 0;
21397    pctxt->err = 0;
21398    pctxt->doc = bucket->doc;
21399
21400    ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21401    if (ret == -1) {
21402	pctxt->doc = NULL;
21403	goto exit_failure;
21404    }
21405    /* Paranoid error channelling. */
21406    if ((ret == 0) && (pctxt->nberrors != 0))
21407	ret = pctxt->err;
21408    if (pctxt->nberrors == 0) {
21409	/*
21410	* Only bother to fixup pending components, if there was
21411	* no error yet.
21412	* For every XSI acquired schema (and its sub-schemata) we will
21413	* fixup the components.
21414	*/
21415	xmlSchemaFixupComponents(pctxt, bucket);
21416	ret = pctxt->err;
21417	/*
21418	* Not nice, but we need somehow to channel the schema parser
21419	* error to the validation context.
21420	*/
21421	if ((ret != 0) && (vctxt->err == 0))
21422	    vctxt->err = ret;
21423	vctxt->nberrors += pctxt->nberrors;
21424    } else {
21425	/* Add to validation error sum. */
21426	vctxt->nberrors += pctxt->nberrors;
21427    }
21428    pctxt->doc = NULL;
21429    return(ret);
21430exit_failure:
21431    pctxt->doc = NULL;
21432    return (-1);
21433}
21434
21435static xmlSchemaAttrInfoPtr
21436xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21437			 int metaType)
21438{
21439    if (vctxt->nbAttrInfos == 0)
21440	return (NULL);
21441    {
21442	int i;
21443	xmlSchemaAttrInfoPtr iattr;
21444
21445	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21446	    iattr = vctxt->attrInfos[i];
21447	    if (iattr->metaType == metaType)
21448		return (iattr);
21449	}
21450
21451    }
21452    return (NULL);
21453}
21454
21455/**
21456 * xmlSchemaAssembleByXSI:
21457 * @vctxt:  a schema validation context
21458 *
21459 * Expands an existing schema by an additional schema using
21460 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21461 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21462 * must be set to 1.
21463 *
21464 * Returns 0 if the new schema is correct, a positive error code
21465 * number otherwise and -1 in case of an internal or API error.
21466 */
21467static int
21468xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21469{
21470    const xmlChar *cur, *end;
21471    const xmlChar *nsname = NULL, *location;
21472    int count = 0;
21473    int ret = 0;
21474    xmlSchemaAttrInfoPtr iattr;
21475
21476    /*
21477    * Parse the value; we will assume an even number of values
21478    * to be given (this is how Xerces and XSV work).
21479    *
21480    * URGENT TODO: !! This needs to work for both
21481    * @noNamespaceSchemaLocation AND @schemaLocation on the same
21482    * element !!
21483    */
21484    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21485	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21486    if (iattr == NULL)
21487	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21488	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21489    if (iattr == NULL)
21490	return (0);
21491    cur = iattr->value;
21492    do {
21493	/*
21494	* TODO: Move the string parsing mechanism away from here.
21495	*/
21496	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21497	    /*
21498	    * Get the namespace name.
21499	    */
21500	    while (IS_BLANK_CH(*cur))
21501		cur++;
21502	    end = cur;
21503	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21504		end++;
21505	    if (end == cur)
21506		break;
21507	    count++; /* TODO: Don't use the schema's dict. */
21508	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21509	    cur = end;
21510	}
21511	/*
21512	* Get the URI.
21513	*/
21514	while (IS_BLANK_CH(*cur))
21515	    cur++;
21516	end = cur;
21517	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21518	    end++;
21519	if (end == cur) {
21520	    if (iattr->metaType ==
21521		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21522	    {
21523		/*
21524		* If using @schemaLocation then tuples are expected.
21525		* I.e. the namespace name *and* the document's URI.
21526		*/
21527		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21528		    iattr->node, NULL,
21529		    "The value must consist of tuples: the target namespace "
21530		    "name and the document's URI", NULL, NULL, NULL);
21531	    }
21532	    break;
21533	}
21534	count++; /* TODO: Don't use the schema's dict. */
21535	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21536	cur = end;
21537	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21538	    iattr->node, nsname, location);
21539	if (ret == -1) {
21540	    VERROR_INT("xmlSchemaAssembleByXSI",
21541		"assembling schemata");
21542	    return (-1);
21543	}
21544    } while (*cur != 0);
21545    return (ret);
21546}
21547
21548static const xmlChar *
21549xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21550			 const xmlChar *prefix)
21551{
21552    if (vctxt->sax != NULL) {
21553	int i, j;
21554	xmlSchemaNodeInfoPtr inode;
21555
21556	for (i = vctxt->depth; i >= 0; i--) {
21557	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21558		inode = vctxt->elemInfos[i];
21559		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21560		    if (((prefix == NULL) &&
21561			    (inode->nsBindings[j] == NULL)) ||
21562			((prefix != NULL) && xmlStrEqual(prefix,
21563			    inode->nsBindings[j]))) {
21564
21565			/*
21566			* Note that the namespace bindings are already
21567			* in a string dict.
21568			*/
21569			return (inode->nsBindings[j+1]);
21570		    }
21571		}
21572	    }
21573	}
21574	return (NULL);
21575#ifdef LIBXML_WRITER_ENABLED
21576    } else if (vctxt->reader != NULL) {
21577	xmlChar *nsName;
21578
21579	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21580	if (nsName != NULL) {
21581	    const xmlChar *ret;
21582
21583	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21584	    xmlFree(nsName);
21585	    return (ret);
21586	} else
21587	    return (NULL);
21588#endif
21589    } else {
21590	xmlNsPtr ns;
21591
21592	if ((vctxt->inode->node == NULL) ||
21593	    (vctxt->inode->node->doc == NULL)) {
21594	    VERROR_INT("xmlSchemaLookupNamespace",
21595		"no node or node's doc avaliable");
21596	    return (NULL);
21597	}
21598	ns = xmlSearchNs(vctxt->inode->node->doc,
21599	    vctxt->inode->node, prefix);
21600	if (ns != NULL)
21601	    return (ns->href);
21602	return (NULL);
21603    }
21604}
21605
21606/*
21607* This one works on the schema of the validation context.
21608*/
21609static int
21610xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21611			  xmlSchemaPtr schema,
21612			  xmlNodePtr node,
21613			  const xmlChar *value,
21614			  xmlSchemaValPtr *val,
21615			  int valNeeded)
21616{
21617    int ret;
21618
21619    if (vctxt && (vctxt->schema == NULL)) {
21620	VERROR_INT("xmlSchemaValidateNotation",
21621	    "a schema is needed on the validation context");
21622	return (-1);
21623    }
21624    ret = xmlValidateQName(value, 1);
21625    if (ret != 0)
21626	return (ret);
21627    {
21628	xmlChar *localName = NULL;
21629	xmlChar *prefix = NULL;
21630
21631	localName = xmlSplitQName2(value, &prefix);
21632	if (prefix != NULL) {
21633	    const xmlChar *nsName = NULL;
21634
21635	    if (vctxt != NULL)
21636		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21637	    else if (node != NULL) {
21638		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21639		if (ns != NULL)
21640		    nsName = ns->href;
21641	    } else {
21642		xmlFree(prefix);
21643		xmlFree(localName);
21644		return (1);
21645	    }
21646	    if (nsName == NULL) {
21647		xmlFree(prefix);
21648		xmlFree(localName);
21649		return (1);
21650	    }
21651	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21652		if (valNeeded && (val != NULL)) {
21653		    (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21654			BAD_CAST xmlStrdup(nsName));
21655		    if (*val == NULL)
21656			ret = -1;
21657		}
21658	    } else
21659		ret = 1;
21660	    xmlFree(prefix);
21661	    xmlFree(localName);
21662	} else {
21663	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21664		if (valNeeded && (val != NULL)) {
21665		    (*val) = xmlSchemaNewNOTATIONValue(
21666			BAD_CAST xmlStrdup(value), NULL);
21667		    if (*val == NULL)
21668			ret = -1;
21669		}
21670	    } else
21671		return (1);
21672	}
21673    }
21674    return (ret);
21675}
21676
21677static int
21678xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21679		       const xmlChar* lname,
21680		       const xmlChar* nsname)
21681{
21682    int i;
21683
21684    lname = xmlDictLookup(vctxt->dict, lname, -1);
21685    if (lname == NULL)
21686	return(-1);
21687    if (nsname != NULL) {
21688	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21689	if (nsname == NULL)
21690	    return(-1);
21691    }
21692    for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21693	if ((vctxt->nodeQNames->items [i] == lname) &&
21694	    (vctxt->nodeQNames->items[i +1] == nsname))
21695	    /* Already there */
21696	    return(i);
21697    }
21698    /* Add new entry. */
21699    i = vctxt->nodeQNames->nbItems;
21700    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21701    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21702    return(i);
21703}
21704
21705/************************************************************************
21706 * 									*
21707 *  Validation of identity-constraints (IDC)                            *
21708 * 									*
21709 ************************************************************************/
21710
21711/**
21712 * xmlSchemaAugmentIDC:
21713 * @idcDef: the IDC definition
21714 *
21715 * Creates an augmented IDC definition item.
21716 *
21717 * Returns the item, or NULL on internal errors.
21718 */
21719static void
21720xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21721		    xmlSchemaValidCtxtPtr vctxt)
21722{
21723    xmlSchemaIDCAugPtr aidc;
21724
21725    aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21726    if (aidc == NULL) {
21727	xmlSchemaVErrMemory(vctxt,
21728	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21729	    NULL);
21730	return;
21731    }
21732    aidc->keyrefDepth = -1;
21733    aidc->def = idcDef;
21734    aidc->next = NULL;
21735    if (vctxt->aidcs == NULL)
21736	vctxt->aidcs = aidc;
21737    else {
21738	aidc->next = vctxt->aidcs;
21739	vctxt->aidcs = aidc;
21740    }
21741    /*
21742    * Save if we have keyrefs at all.
21743    */
21744    if ((vctxt->hasKeyrefs == 0) &&
21745	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21746	vctxt->hasKeyrefs = 1;
21747}
21748
21749/**
21750 * xmlSchemaIDCNewBinding:
21751 * @idcDef: the IDC definition of this binding
21752 *
21753 * Creates a new IDC binding.
21754 *
21755 * Returns the new IDC binding, NULL on internal errors.
21756 */
21757static xmlSchemaPSVIIDCBindingPtr
21758xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21759{
21760    xmlSchemaPSVIIDCBindingPtr ret;
21761
21762    ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21763	    sizeof(xmlSchemaPSVIIDCBinding));
21764    if (ret == NULL) {
21765	xmlSchemaVErrMemory(NULL,
21766	    "allocating a PSVI IDC binding item", NULL);
21767	return (NULL);
21768    }
21769    memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21770    ret->definition = idcDef;
21771    return (ret);
21772}
21773
21774/**
21775 * xmlSchemaIDCStoreNodeTableItem:
21776 * @vctxt: the WXS validation context
21777 * @item: the IDC node table item
21778 *
21779 * The validation context is used to store IDC node table items.
21780 * They are stored to avoid copying them if IDC node-tables are merged
21781 * with corresponding parent IDC node-tables (bubbling).
21782 *
21783 * Returns 0 if succeeded, -1 on internal errors.
21784 */
21785static int
21786xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
21787			       xmlSchemaPSVIIDCNodePtr item)
21788{
21789    /*
21790    * Add to gobal list.
21791    */
21792    if (vctxt->idcNodes == NULL) {
21793	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21794	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21795	if (vctxt->idcNodes == NULL) {
21796	    xmlSchemaVErrMemory(vctxt,
21797		"allocating the IDC node table item list", NULL);
21798	    return (-1);
21799	}
21800	vctxt->sizeIdcNodes = 20;
21801    } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21802	vctxt->sizeIdcNodes *= 2;
21803	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21804	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
21805	    sizeof(xmlSchemaPSVIIDCNodePtr));
21806	if (vctxt->idcNodes == NULL) {
21807	    xmlSchemaVErrMemory(vctxt,
21808		"re-allocating the IDC node table item list", NULL);
21809	    return (-1);
21810	}
21811    }
21812    vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
21813
21814    return (0);
21815}
21816
21817/**
21818 * xmlSchemaIDCStoreKey:
21819 * @vctxt: the WXS validation context
21820 * @item: the IDC key
21821 *
21822 * The validation context is used to store an IDC key.
21823 *
21824 * Returns 0 if succeeded, -1 on internal errors.
21825 */
21826static int
21827xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
21828		     xmlSchemaPSVIIDCKeyPtr key)
21829{
21830    /*
21831    * Add to gobal list.
21832    */
21833    if (vctxt->idcKeys == NULL) {
21834	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21835	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21836	if (vctxt->idcKeys == NULL) {
21837	    xmlSchemaVErrMemory(vctxt,
21838		"allocating the IDC key storage list", NULL);
21839	    return (-1);
21840	}
21841	vctxt->sizeIdcKeys = 40;
21842    } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21843	vctxt->sizeIdcKeys *= 2;
21844	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21845	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
21846	    sizeof(xmlSchemaPSVIIDCKeyPtr));
21847	if (vctxt->idcKeys == NULL) {
21848	    xmlSchemaVErrMemory(vctxt,
21849		"re-allocating the IDC key storage list", NULL);
21850	    return (-1);
21851	}
21852    }
21853    vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
21854
21855    return (0);
21856}
21857
21858/**
21859 * xmlSchemaIDCAppendNodeTableItem:
21860 * @bind: the IDC binding
21861 * @ntItem: the node-table item
21862 *
21863 * Appends the IDC node-table item to the binding.
21864 *
21865 * Returns 0 on success and -1 on internal errors.
21866 */
21867static int
21868xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
21869				xmlSchemaPSVIIDCNodePtr ntItem)
21870{
21871    if (bind->nodeTable == NULL) {
21872	bind->sizeNodes = 10;
21873	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21874	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
21875	if (bind->nodeTable == NULL) {
21876	    xmlSchemaVErrMemory(NULL,
21877		"allocating an array of IDC node-table items", NULL);
21878	    return(-1);
21879	}
21880    } else if (bind->sizeNodes <= bind->nbNodes) {
21881	bind->sizeNodes *= 2;
21882	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
21883	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
21884		sizeof(xmlSchemaPSVIIDCNodePtr));
21885	if (bind->nodeTable == NULL) {
21886	    xmlSchemaVErrMemory(NULL,
21887		"re-allocating an array of IDC node-table items", NULL);
21888	    return(-1);
21889	}
21890    }
21891    bind->nodeTable[bind->nbNodes++] = ntItem;
21892    return(0);
21893}
21894
21895/**
21896 * xmlSchemaIDCAcquireBinding:
21897 * @vctxt: the WXS validation context
21898 * @matcher: the IDC matcher
21899 *
21900 * Looks up an PSVI IDC binding, for the IDC definition and
21901 * of the given matcher. If none found, a new one is created
21902 * and added to the IDC table.
21903 *
21904 * Returns an IDC binding or NULL on internal errors.
21905 */
21906static xmlSchemaPSVIIDCBindingPtr
21907xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
21908			  xmlSchemaIDCMatcherPtr matcher)
21909{
21910    xmlSchemaNodeInfoPtr ielem;
21911
21912    ielem = vctxt->elemInfos[matcher->depth];
21913
21914    if (ielem->idcTable == NULL) {
21915	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
21916	if (ielem->idcTable == NULL)
21917	    return (NULL);
21918	return(ielem->idcTable);
21919    } else {
21920	xmlSchemaPSVIIDCBindingPtr bind = NULL;
21921
21922	bind = ielem->idcTable;
21923	do {
21924	    if (bind->definition == matcher->aidc->def)
21925		return(bind);
21926	    if (bind->next == NULL) {
21927		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
21928		if (bind->next == NULL)
21929		    return (NULL);
21930		return(bind->next);
21931	    }
21932	    bind = bind->next;
21933	} while (bind != NULL);
21934    }
21935    return (NULL);
21936}
21937
21938static xmlSchemaItemListPtr
21939xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21940			     xmlSchemaIDCMatcherPtr matcher)
21941{
21942    if (matcher->targets == NULL)
21943	matcher->targets = xmlSchemaItemListCreate();
21944    return(matcher->targets);
21945}
21946
21947/**
21948 * xmlSchemaIDCFreeKey:
21949 * @key: the IDC key
21950 *
21951 * Frees an IDC key together with its compiled value.
21952 */
21953static void
21954xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
21955{
21956    if (key->val != NULL)
21957	xmlSchemaFreeValue(key->val);
21958    xmlFree(key);
21959}
21960
21961/**
21962 * xmlSchemaIDCFreeBinding:
21963 *
21964 * Frees an IDC binding. Note that the node table-items
21965 * are not freed.
21966 */
21967static void
21968xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
21969{
21970    if (bind->nodeTable != NULL)
21971	xmlFree(bind->nodeTable);
21972    if (bind->dupls != NULL)
21973	xmlSchemaItemListFree(bind->dupls);
21974    xmlFree(bind);
21975}
21976
21977/**
21978 * xmlSchemaIDCFreeIDCTable:
21979 * @bind: the first IDC binding in the list
21980 *
21981 * Frees an IDC table, i.e. all the IDC bindings in the list.
21982 */
21983static void
21984xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
21985{
21986    xmlSchemaPSVIIDCBindingPtr prev;
21987
21988    while (bind != NULL) {
21989	prev = bind;
21990	bind = bind->next;
21991	xmlSchemaIDCFreeBinding(prev);
21992    }
21993}
21994
21995/**
21996 * xmlSchemaIDCFreeMatcherList:
21997 * @matcher: the first IDC matcher in the list
21998 *
21999 * Frees a list of IDC matchers.
22000 */
22001static void
22002xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22003{
22004    xmlSchemaIDCMatcherPtr next;
22005
22006    while (matcher != NULL) {
22007	next = matcher->next;
22008	if (matcher->keySeqs != NULL) {
22009	    int i;
22010	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22011		if (matcher->keySeqs[i] != NULL)
22012		    xmlFree(matcher->keySeqs[i]);
22013	    xmlFree(matcher->keySeqs);
22014	}
22015	if (matcher->targets != NULL) {
22016	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22017		int i;
22018		xmlSchemaPSVIIDCNodePtr idcNode;
22019		/*
22020		* Node-table items for keyrefs are not stored globally
22021		* to the validation context, since they are not bubbled.
22022		* We need to free them here.
22023		*/
22024		for (i = 0; i < matcher->targets->nbItems; i++) {
22025		    idcNode =
22026			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22027		    xmlFree(idcNode->keys);
22028		    xmlFree(idcNode);
22029		}
22030	    }
22031	    xmlSchemaItemListFree(matcher->targets);
22032	}
22033	xmlFree(matcher);
22034	matcher = next;
22035    }
22036}
22037
22038/**
22039 * xmlSchemaIDCAddStateObject:
22040 * @vctxt: the WXS validation context
22041 * @matcher: the IDC matcher
22042 * @sel: the XPath information
22043 * @parent: the parent "selector" state object if any
22044 * @type: "selector" or "field"
22045 *
22046 * Creates/reuses and activates state objects for the given
22047 * XPath information; if the XPath expression consists of unions,
22048 * multiple state objects are created for every unioned expression.
22049 *
22050 * Returns 0 on success and -1 on internal errors.
22051 */
22052static int
22053xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22054			xmlSchemaIDCMatcherPtr matcher,
22055			xmlSchemaIDCSelectPtr sel,
22056			int type)
22057{
22058    xmlSchemaIDCStateObjPtr sto;
22059
22060    /*
22061    * Reuse the state objects from the pool.
22062    */
22063    if (vctxt->xpathStatePool != NULL) {
22064	sto = vctxt->xpathStatePool;
22065	vctxt->xpathStatePool = sto->next;
22066	sto->next = NULL;
22067    } else {
22068	/*
22069	* Create a new state object.
22070	*/
22071	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22072	if (sto == NULL) {
22073	    xmlSchemaVErrMemory(NULL,
22074		"allocating an IDC state object", NULL);
22075	    return (-1);
22076	}
22077	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22078    }
22079    /*
22080    * Add to global list.
22081    */
22082    if (vctxt->xpathStates != NULL)
22083	sto->next = vctxt->xpathStates;
22084    vctxt->xpathStates = sto;
22085
22086    /*
22087    * Free the old xpath validation context.
22088    */
22089    if (sto->xpathCtxt != NULL)
22090	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22091
22092    /*
22093    * Create a new XPath (pattern) validation context.
22094    */
22095    sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22096	(xmlPatternPtr) sel->xpathComp);
22097    if (sto->xpathCtxt == NULL) {
22098	VERROR_INT("xmlSchemaIDCAddStateObject",
22099	    "failed to create an XPath validation context");
22100	return (-1);
22101    }
22102    sto->type = type;
22103    sto->depth = vctxt->depth;
22104    sto->matcher = matcher;
22105    sto->sel = sel;
22106    sto->nbHistory = 0;
22107
22108#ifdef DEBUG_IDC
22109    xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22110	sto->sel->xpath);
22111#endif
22112    return (0);
22113}
22114
22115/**
22116 * xmlSchemaXPathEvaluate:
22117 * @vctxt: the WXS validation context
22118 * @nodeType: the nodeType of the current node
22119 *
22120 * Evaluates all active XPath state objects.
22121 *
22122 * Returns the number of IC "field" state objects which resolved to
22123 * this node, 0 if none resolved and -1 on internal errors.
22124 */
22125static int
22126xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22127		       xmlElementType nodeType)
22128{
22129    xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22130    int res, resolved = 0, depth = vctxt->depth;
22131
22132    if (vctxt->xpathStates == NULL)
22133	return (0);
22134
22135    if (nodeType == XML_ATTRIBUTE_NODE)
22136	depth++;
22137#ifdef DEBUG_IDC
22138    {
22139	xmlChar *str = NULL;
22140	xmlGenericError(xmlGenericErrorContext,
22141	    "IDC: EVAL on %s, depth %d, type %d\n",
22142	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22143		vctxt->inode->localName), depth, nodeType);
22144	FREE_AND_NULL(str)
22145    }
22146#endif
22147    /*
22148    * Process all active XPath state objects.
22149    */
22150    first = vctxt->xpathStates;
22151    sto = first;
22152    while (sto != head) {
22153#ifdef DEBUG_IDC
22154	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22155	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22156		sto->matcher->aidc->def->name, sto->sel->xpath);
22157	else
22158	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22159		sto->matcher->aidc->def->name, sto->sel->xpath);
22160#endif
22161	if (nodeType == XML_ELEMENT_NODE)
22162	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22163		vctxt->inode->localName, vctxt->inode->nsName);
22164	else
22165	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22166		vctxt->inode->localName, vctxt->inode->nsName);
22167
22168	if (res == -1) {
22169	    VERROR_INT("xmlSchemaXPathEvaluate",
22170		"calling xmlStreamPush()");
22171	    return (-1);
22172	}
22173	if (res == 0)
22174	    goto next_sto;
22175	/*
22176	* Full match.
22177	*/
22178#ifdef DEBUG_IDC
22179	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22180	    "MATCH\n");
22181#endif
22182	/*
22183	* Register a match in the state object history.
22184	*/
22185	if (sto->history == NULL) {
22186	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22187	    if (sto->history == NULL) {
22188		xmlSchemaVErrMemory(NULL,
22189		    "allocating the state object history", NULL);
22190		return(-1);
22191	    }
22192	    sto->sizeHistory = 10;
22193	} else if (sto->sizeHistory <= sto->nbHistory) {
22194	    sto->sizeHistory *= 2;
22195	    sto->history = (int *) xmlRealloc(sto->history,
22196		sto->sizeHistory * sizeof(int));
22197	    if (sto->history == NULL) {
22198		xmlSchemaVErrMemory(NULL,
22199		    "re-allocating the state object history", NULL);
22200		return(-1);
22201	    }
22202	}
22203	sto->history[sto->nbHistory++] = depth;
22204
22205#ifdef DEBUG_IDC
22206	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22207	    vctxt->depth);
22208#endif
22209
22210	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22211	    xmlSchemaIDCSelectPtr sel;
22212	    /*
22213	    * Activate state objects for the IDC fields of
22214	    * the IDC selector.
22215	    */
22216#ifdef DEBUG_IDC
22217	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22218		"activating field states\n");
22219#endif
22220	    sel = sto->matcher->aidc->def->fields;
22221	    while (sel != NULL) {
22222		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22223		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22224		    return (-1);
22225		sel = sel->next;
22226	    }
22227	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22228	    /*
22229	    * An IDC key node was found by the IDC field.
22230	    */
22231#ifdef DEBUG_IDC
22232	    xmlGenericError(xmlGenericErrorContext,
22233		"IDC:     key found\n");
22234#endif
22235	    /*
22236	    * Notify that the character value of this node is
22237	    * needed.
22238	    */
22239	    if (resolved == 0) {
22240		if ((vctxt->inode->flags &
22241		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22242		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22243	    }
22244	    resolved++;
22245	}
22246next_sto:
22247	if (sto->next == NULL) {
22248	    /*
22249	    * Evaluate field state objects created on this node as well.
22250	    */
22251	    head = first;
22252	    sto = vctxt->xpathStates;
22253	} else
22254	    sto = sto->next;
22255    }
22256    return (resolved);
22257}
22258
22259static const xmlChar *
22260xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22261			      xmlChar **buf,
22262			      xmlSchemaPSVIIDCKeyPtr *seq,
22263			      int count)
22264{
22265    int i, res;
22266    xmlChar *value = NULL;
22267
22268    *buf = xmlStrdup(BAD_CAST "[");
22269    for (i = 0; i < count; i++) {
22270	*buf = xmlStrcat(*buf, BAD_CAST "'");
22271	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22272	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22273	    &value);
22274	if (res == 0)
22275	    *buf = xmlStrcat(*buf, BAD_CAST value);
22276	else {
22277	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22278		"failed to compute a canonical value");
22279	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22280	}
22281	if (i < count -1)
22282	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22283	else
22284	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22285	if (value != NULL) {
22286	    xmlFree(value);
22287	    value = NULL;
22288	}
22289    }
22290    *buf = xmlStrcat(*buf, BAD_CAST "]");
22291
22292    return (BAD_CAST *buf);
22293}
22294
22295/**
22296 * xmlSchemaXPathPop:
22297 * @vctxt: the WXS validation context
22298 *
22299 * Pops all XPath states.
22300 *
22301 * Returns 0 on success and -1 on internal errors.
22302 */
22303static int
22304xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22305{
22306    xmlSchemaIDCStateObjPtr sto;
22307    int res;
22308
22309    if (vctxt->xpathStates == NULL)
22310	return(0);
22311    sto = vctxt->xpathStates;
22312    do {
22313	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22314	if (res == -1)
22315	    return (-1);
22316	sto = sto->next;
22317    } while (sto != NULL);
22318    return(0);
22319}
22320
22321/**
22322 * xmlSchemaXPathProcessHistory:
22323 * @vctxt: the WXS validation context
22324 * @type: the simple/complex type of the current node if any at all
22325 * @val: the precompiled value
22326 *
22327 * Processes and pops the history items of the IDC state objects.
22328 * IDC key-sequences are validated/created on IDC bindings.
22329 *
22330 * Returns 0 on success and -1 on internal errors.
22331 */
22332static int
22333xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22334			     int depth)
22335{
22336    xmlSchemaIDCStateObjPtr sto, nextsto;
22337    int res, matchDepth;
22338    xmlSchemaPSVIIDCKeyPtr key = NULL;
22339    xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22340
22341    if (vctxt->xpathStates == NULL)
22342	return (0);
22343    sto = vctxt->xpathStates;
22344
22345#ifdef DEBUG_IDC
22346    {
22347	xmlChar *str = NULL;
22348	xmlGenericError(xmlGenericErrorContext,
22349	    "IDC: BACK on %s, depth %d\n",
22350	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22351		vctxt->inode->localName), vctxt->depth);
22352	FREE_AND_NULL(str)
22353    }
22354#endif
22355    /*
22356    * Evaluate the state objects.
22357    */
22358    while (sto != NULL) {
22359	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22360	if (res == -1) {
22361	    VERROR_INT("xmlSchemaXPathProcessHistory",
22362		"calling xmlStreamPop()");
22363	    return (-1);
22364	}
22365#ifdef DEBUG_IDC
22366	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22367	    sto->sel->xpath);
22368#endif
22369	if (sto->nbHistory == 0)
22370	    goto deregister_check;
22371
22372	matchDepth = sto->history[sto->nbHistory -1];
22373
22374	/*
22375	* Only matches at the current depth are of interest.
22376	*/
22377	if (matchDepth != depth) {
22378	    sto = sto->next;
22379	    continue;
22380	}
22381	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22382	    /*
22383	    * NOTE: According to
22384	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22385	    *   ... the simple-content of complex types is also allowed.
22386	    */
22387
22388	    if (WXS_IS_COMPLEX(type)) {
22389		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22390		    /*
22391		    * Sanity check for complex types with simple content.
22392		    */
22393		    simpleType = type->contentTypeDef;
22394		    if (simpleType == NULL) {
22395			VERROR_INT("xmlSchemaXPathProcessHistory",
22396			    "field resolves to a CT with simple content "
22397			    "but the CT is missing the ST definition");
22398			return (-1);
22399		    }
22400		} else
22401		    simpleType = NULL;
22402	    } else
22403		simpleType = type;
22404	    if (simpleType == NULL) {
22405		xmlChar *str = NULL;
22406
22407		/*
22408		* Not qualified if the field resolves to a node of non
22409		* simple type.
22410		*/
22411		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22412		    XML_SCHEMAV_CVC_IDC, NULL,
22413		    WXS_BASIC_CAST sto->matcher->aidc->def,
22414		    "The XPath '%s' of a field of %s does evaluate to a node of "
22415		    "non-simple type",
22416		    sto->sel->xpath,
22417		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22418		FREE_AND_NULL(str);
22419		sto->nbHistory--;
22420		goto deregister_check;
22421	    }
22422
22423	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22424		/*
22425		* Failed to provide the normalized value; maybe
22426		* the value was invalid.
22427		*/
22428		VERROR(XML_SCHEMAV_CVC_IDC,
22429		    WXS_BASIC_CAST sto->matcher->aidc->def,
22430		    "Warning: No precomputed value available, the value "
22431		    "was either invalid or something strange happend");
22432		sto->nbHistory--;
22433		goto deregister_check;
22434	    } else {
22435		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22436		xmlSchemaPSVIIDCKeyPtr *keySeq;
22437		int pos, idx;
22438
22439		/*
22440		* The key will be anchored on the matcher's list of
22441		* key-sequences. The position in this list is determined
22442		* by the target node's depth relative to the matcher's
22443		* depth of creation (i.e. the depth of the scope element).
22444		*
22445		* Element        Depth    Pos   List-entries
22446		* <scope>          0              NULL
22447		*   <bar>          1              NULL
22448		*     <target/>    2       2      target
22449		*   <bar>
22450                * </scope>
22451		*
22452		* The size of the list is only dependant on the depth of
22453		* the tree.
22454		* An entry will be NULLed in selector_leave, i.e. when
22455		* we hit the target's
22456		*/
22457		pos = sto->depth - matcher->depth;
22458		idx = sto->sel->index;
22459
22460		/*
22461		* Create/grow the array of key-sequences.
22462		*/
22463		if (matcher->keySeqs == NULL) {
22464		    if (pos > 9)
22465			matcher->sizeKeySeqs = pos * 2;
22466		    else
22467			matcher->sizeKeySeqs = 10;
22468		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22469			xmlMalloc(matcher->sizeKeySeqs *
22470			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22471		    if (matcher->keySeqs == NULL) {
22472			xmlSchemaVErrMemory(NULL,
22473			    "allocating an array of key-sequences",
22474			    NULL);
22475			return(-1);
22476		    }
22477		    memset(matcher->keySeqs, 0,
22478			matcher->sizeKeySeqs *
22479			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22480		} else if (pos >= matcher->sizeKeySeqs) {
22481		    int i = matcher->sizeKeySeqs;
22482
22483		    matcher->sizeKeySeqs *= 2;
22484		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22485			xmlRealloc(matcher->keySeqs,
22486			matcher->sizeKeySeqs *
22487			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22488		    if (matcher->keySeqs == NULL) {
22489			xmlSchemaVErrMemory(NULL,
22490			    "reallocating an array of key-sequences",
22491			    NULL);
22492			return (-1);
22493		    }
22494		    /*
22495		    * The array needs to be NULLed.
22496		    * TODO: Use memset?
22497		    */
22498		    for (; i < matcher->sizeKeySeqs; i++)
22499			matcher->keySeqs[i] = NULL;
22500		}
22501
22502		/*
22503		* Get/create the key-sequence.
22504		*/
22505		keySeq = matcher->keySeqs[pos];
22506		if (keySeq == NULL) {
22507		    goto create_sequence;
22508		} else if (keySeq[idx] != NULL) {
22509		    xmlChar *str = NULL;
22510		    /*
22511		    * cvc-identity-constraint:
22512		    * 3 For each node in the �target node set� all
22513		    * of the {fields}, with that node as the context
22514		    * node, evaluate to either an empty node-set or
22515		    * a node-set with exactly one member, which must
22516		    * have a simple type.
22517		    *
22518		    * The key was already set; report an error.
22519		    */
22520		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22521			XML_SCHEMAV_CVC_IDC, NULL,
22522			WXS_BASIC_CAST matcher->aidc->def,
22523			"The XPath '%s' of a field of %s evaluates to a "
22524			"node-set with more than one member",
22525			sto->sel->xpath,
22526			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22527		    FREE_AND_NULL(str);
22528		    sto->nbHistory--;
22529		    goto deregister_check;
22530		} else
22531		    goto create_key;
22532
22533create_sequence:
22534		/*
22535		* Create a key-sequence.
22536		*/
22537		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22538		    matcher->aidc->def->nbFields *
22539		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22540		if (keySeq == NULL) {
22541		    xmlSchemaVErrMemory(NULL,
22542			"allocating an IDC key-sequence", NULL);
22543		    return(-1);
22544		}
22545		memset(keySeq, 0, matcher->aidc->def->nbFields *
22546		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22547		matcher->keySeqs[pos] = keySeq;
22548create_key:
22549		/*
22550		* Create a key once per node only.
22551		*/
22552		if (key == NULL) {
22553		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22554			sizeof(xmlSchemaPSVIIDCKey));
22555		    if (key == NULL) {
22556			xmlSchemaVErrMemory(NULL,
22557			    "allocating a IDC key", NULL);
22558			xmlFree(keySeq);
22559			matcher->keySeqs[pos] = NULL;
22560			return(-1);
22561		    }
22562		    /*
22563		    * Consume the compiled value.
22564		    */
22565		    key->type = simpleType;
22566		    key->val = vctxt->inode->val;
22567		    vctxt->inode->val = NULL;
22568		    /*
22569		    * Store the key in a global list.
22570		    */
22571		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22572			xmlSchemaIDCFreeKey(key);
22573			return (-1);
22574		    }
22575		}
22576		keySeq[idx] = key;
22577	    }
22578	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22579
22580	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22581	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22582	    xmlSchemaPSVIIDCNodePtr ntItem;
22583	    xmlSchemaIDCMatcherPtr matcher;
22584	    xmlSchemaIDCPtr idc;
22585	    xmlSchemaItemListPtr targets;
22586	    int pos, i, j, nbKeys;
22587	    /*
22588	    * Here we have the following scenario:
22589	    * An IDC 'selector' state object resolved to a target node,
22590	    * during the time this target node was in the
22591	    * ancestor-or-self axis, the 'field' state object(s) looked
22592	    * out for matching nodes to create a key-sequence for this
22593	    * target node. Now we are back to this target node and need
22594	    * to put the key-sequence, together with the target node
22595	    * itself, into the node-table of the corresponding IDC
22596	    * binding.
22597	    */
22598	    matcher = sto->matcher;
22599	    idc = matcher->aidc->def;
22600	    nbKeys = idc->nbFields;
22601	    pos = depth - matcher->depth;
22602	    /*
22603	    * Check if the matcher has any key-sequences at all, plus
22604	    * if it has a key-sequence for the current target node.
22605	    */
22606	    if ((matcher->keySeqs == NULL) ||
22607		(matcher->sizeKeySeqs <= pos)) {
22608		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22609		    goto selector_key_error;
22610		else
22611		    goto selector_leave;
22612	    }
22613
22614	    keySeq = &(matcher->keySeqs[pos]);
22615	    if (*keySeq == NULL) {
22616		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22617		    goto selector_key_error;
22618		else
22619		    goto selector_leave;
22620	    }
22621
22622	    for (i = 0; i < nbKeys; i++) {
22623		if ((*keySeq)[i] == NULL) {
22624		    /*
22625		    * Not qualified, if not all fields did resolve.
22626		    */
22627		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22628			/*
22629			* All fields of a "key" IDC must resolve.
22630			*/
22631			goto selector_key_error;
22632		    }
22633		    goto selector_leave;
22634		}
22635	    }
22636	    /*
22637	    * All fields did resolve.
22638	    */
22639
22640	    /*
22641	    * 4.1 If the {identity-constraint category} is unique(/key),
22642	    * then no two members of the �qualified node set� have
22643	    * �key-sequences� whose members are pairwise equal, as
22644	    * defined by Equal in [XML Schemas: Datatypes].
22645	    *
22646	    * Get the IDC binding from the matcher and check for
22647	    * duplicate key-sequences.
22648	    */
22649#if 0
22650	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22651#endif
22652	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22653	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22654		(targets->nbItems != 0)) {
22655		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22656
22657		i = 0;
22658		res = 0;
22659		/*
22660		* Compare the key-sequences, key by key.
22661		*/
22662		do {
22663		    bkeySeq =
22664			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22665		    for (j = 0; j < nbKeys; j++) {
22666			ckey = (*keySeq)[j];
22667			bkey = bkeySeq[j];
22668			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22669			if (res == -1) {
22670			    return (-1);
22671			} else if (res == 0) {
22672			    /*
22673			    * One of the keys differs, so the key-sequence
22674			    * won't be equal; get out.
22675			    */
22676			    break;
22677			}
22678		    }
22679		    if (res == 1) {
22680			/*
22681			* Duplicate key-sequence found.
22682			*/
22683			break;
22684		    }
22685		    i++;
22686		} while (i < targets->nbItems);
22687		if (i != targets->nbItems) {
22688		    xmlChar *str = NULL, *strB = NULL;
22689		    /*
22690		    * TODO: Try to report the key-sequence.
22691		    */
22692		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22693			XML_SCHEMAV_CVC_IDC, NULL,
22694			WXS_BASIC_CAST idc,
22695			"Duplicate key-sequence %s in %s",
22696			xmlSchemaFormatIDCKeySequence(vctxt, &str,
22697			    (*keySeq), nbKeys),
22698			xmlSchemaGetIDCDesignation(&strB, idc));
22699		    FREE_AND_NULL(str);
22700		    FREE_AND_NULL(strB);
22701		    goto selector_leave;
22702		}
22703	    }
22704	    /*
22705	    * Add a node-table item to the IDC binding.
22706	    */
22707	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22708		sizeof(xmlSchemaPSVIIDCNode));
22709	    if (ntItem == NULL) {
22710		xmlSchemaVErrMemory(NULL,
22711		    "allocating an IDC node-table item", NULL);
22712		xmlFree(*keySeq);
22713		*keySeq = NULL;
22714		return(-1);
22715	    }
22716	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22717
22718	    /*
22719	    * Store the node-table item in a global list.
22720	    */
22721	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22722		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22723		    xmlFree(ntItem);
22724		    xmlFree(*keySeq);
22725		    *keySeq = NULL;
22726		    return (-1);
22727		}
22728		ntItem->nodeQNameID = -1;
22729	    } else {
22730		/*
22731		* Save a cached QName for this node on the IDC node, to be
22732		* able to report it, even if the node is not saved.
22733		*/
22734		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22735		    vctxt->inode->localName, vctxt->inode->nsName);
22736		if (ntItem->nodeQNameID == -1) {
22737		    xmlFree(ntItem);
22738		    xmlFree(*keySeq);
22739		    *keySeq = NULL;
22740		    return (-1);
22741		}
22742	    }
22743	    /*
22744	    * Init the node-table item: Save the node, position and
22745	    * consume the key-sequence.
22746	    */
22747	    ntItem->node = vctxt->node;
22748	    ntItem->nodeLine = vctxt->inode->nodeLine;
22749	    ntItem->keys = *keySeq;
22750	    *keySeq = NULL;
22751#if 0
22752	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22753#endif
22754	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
22755		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22756		    /*
22757		    * Free the item, since keyref items won't be
22758		    * put on a global list.
22759		    */
22760		    xmlFree(ntItem->keys);
22761		    xmlFree(ntItem);
22762		}
22763		return (-1);
22764	    }
22765
22766	    goto selector_leave;
22767selector_key_error:
22768	    {
22769		xmlChar *str = NULL;
22770		/*
22771		* 4.2.1 (KEY) The �target node set� and the
22772		* �qualified node set� are equal, that is, every
22773		* member of the �target node set� is also a member
22774		* of the �qualified node set� and vice versa.
22775		*/
22776		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22777		    XML_SCHEMAV_CVC_IDC, NULL,
22778		    WXS_BASIC_CAST idc,
22779		    "Not all fields of %s evaluate to a node",
22780		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
22781		FREE_AND_NULL(str);
22782	    }
22783selector_leave:
22784	    /*
22785	    * Free the key-sequence if not added to the IDC table.
22786	    */
22787	    if ((keySeq != NULL) && (*keySeq != NULL)) {
22788		xmlFree(*keySeq);
22789		*keySeq = NULL;
22790	    }
22791	} /* if selector */
22792
22793	sto->nbHistory--;
22794
22795deregister_check:
22796	/*
22797	* Deregister state objects if they reach the depth of creation.
22798	*/
22799	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
22800#ifdef DEBUG_IDC
22801	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
22802		sto->sel->xpath);
22803#endif
22804	    if (vctxt->xpathStates != sto) {
22805		VERROR_INT("xmlSchemaXPathProcessHistory",
22806		    "The state object to be removed is not the first "
22807		    "in the list");
22808	    }
22809	    nextsto = sto->next;
22810	    /*
22811	    * Unlink from the list of active XPath state objects.
22812	    */
22813	    vctxt->xpathStates = sto->next;
22814	    sto->next = vctxt->xpathStatePool;
22815	    /*
22816	    * Link it to the pool of reusable state objects.
22817	    */
22818	    vctxt->xpathStatePool = sto;
22819	    sto = nextsto;
22820	} else
22821	    sto = sto->next;
22822    } /* while (sto != NULL) */
22823    return (0);
22824}
22825
22826/**
22827 * xmlSchemaIDCRegisterMatchers:
22828 * @vctxt: the WXS validation context
22829 * @elemDecl: the element declaration
22830 *
22831 * Creates helper objects to evaluate IDC selectors/fields
22832 * successively.
22833 *
22834 * Returns 0 if OK and -1 on internal errors.
22835 */
22836static int
22837xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
22838			     xmlSchemaElementPtr elemDecl)
22839{
22840    xmlSchemaIDCMatcherPtr matcher, last = NULL;
22841    xmlSchemaIDCPtr idc, refIdc;
22842    xmlSchemaIDCAugPtr aidc;
22843
22844    idc = (xmlSchemaIDCPtr) elemDecl->idcs;
22845    if (idc == NULL)
22846	return (0);
22847
22848#ifdef DEBUG_IDC
22849    {
22850	xmlChar *str = NULL;
22851	xmlGenericError(xmlGenericErrorContext,
22852	    "IDC: REGISTER on %s, depth %d\n",
22853	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22854		vctxt->inode->localName), vctxt->depth);
22855	FREE_AND_NULL(str)
22856    }
22857#endif
22858    if (vctxt->inode->idcMatchers != NULL) {
22859	VERROR_INT("xmlSchemaIDCRegisterMatchers",
22860	    "The chain of IDC matchers is expected to be empty");
22861	return (-1);
22862    }
22863    do {
22864	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22865	    /*
22866	    * Since IDCs bubbles are expensive we need to know the
22867	    * depth at which the bubbles should stop; this will be
22868	    * the depth of the top-most keyref IDC. If no keyref
22869	    * references a key/unique IDC, the keyrefDepth will
22870	    * be -1, indicating that no bubbles are needed.
22871	    */
22872	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
22873	    if (refIdc != NULL) {
22874		/*
22875		* Remember that we have keyrefs on this node.
22876		*/
22877		vctxt->inode->hasKeyrefs = 1;
22878		/*
22879		* Lookup the referenced augmented IDC info.
22880		*/
22881		aidc = vctxt->aidcs;
22882		while (aidc != NULL) {
22883		    if (aidc->def == refIdc)
22884			break;
22885		    aidc = aidc->next;
22886		}
22887		if (aidc == NULL) {
22888		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
22889			"Could not find an augmented IDC item for an IDC "
22890			"definition");
22891		    return (-1);
22892		}
22893		if ((aidc->keyrefDepth == -1) ||
22894		    (vctxt->depth < aidc->keyrefDepth))
22895		    aidc->keyrefDepth = vctxt->depth;
22896	    }
22897	}
22898	/*
22899	* Lookup the augmented IDC item for the IDC definition.
22900	*/
22901	aidc = vctxt->aidcs;
22902	while (aidc != NULL) {
22903	    if (aidc->def == idc)
22904		break;
22905	    aidc = aidc->next;
22906	}
22907	if (aidc == NULL) {
22908	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
22909		"Could not find an augmented IDC item for an IDC definition");
22910	    return (-1);
22911	}
22912	/*
22913	* Create an IDC matcher for every IDC definition.
22914	*/
22915	matcher = (xmlSchemaIDCMatcherPtr)
22916	    xmlMalloc(sizeof(xmlSchemaIDCMatcher));
22917	if (matcher == NULL) {
22918	    xmlSchemaVErrMemory(vctxt,
22919		"allocating an IDC matcher", NULL);
22920	    return (-1);
22921	}
22922	memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
22923	if (last == NULL)
22924	    vctxt->inode->idcMatchers = matcher;
22925	else
22926	    last->next = matcher;
22927	last = matcher;
22928
22929	matcher->type = IDC_MATCHER;
22930	matcher->depth = vctxt->depth;
22931	matcher->aidc = aidc;
22932	matcher->idcType = aidc->def->type;
22933#ifdef DEBUG_IDC
22934	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
22935#endif
22936	/*
22937	* Init the automaton state object.
22938	*/
22939	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
22940	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
22941	    return (-1);
22942
22943	idc = idc->next;
22944    } while (idc != NULL);
22945    return (0);
22946}
22947
22948static int
22949xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
22950			   xmlSchemaNodeInfoPtr ielem)
22951{
22952    xmlSchemaPSVIIDCBindingPtr bind;
22953    int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
22954    xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
22955    xmlSchemaPSVIIDCNodePtr *targets, *dupls;
22956
22957    xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
22958    /* vctxt->createIDCNodeTables */
22959    while (matcher != NULL) {
22960	/*
22961	* Skip keyref IDCs and empty IDC target-lists.
22962	*/
22963	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
22964	    WXS_ILIST_IS_EMPTY(matcher->targets))
22965	{
22966	    matcher = matcher->next;
22967	    continue;
22968	}
22969	/*
22970	* If we _want_ the IDC node-table to be created in any case
22971	* then do so. Otherwise create them only if keyrefs need them.
22972	*/
22973	if ((! vctxt->createIDCNodeTables) &&
22974	    ((matcher->aidc->keyrefDepth == -1) ||
22975	     (matcher->aidc->keyrefDepth > vctxt->depth)))
22976	{
22977	    matcher = matcher->next;
22978	    continue;
22979	}
22980	/*
22981	* Get/create the IDC binding on this element for the IDC definition.
22982	*/
22983	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22984
22985	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
22986	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
22987	    nbDupls = bind->dupls->nbItems;
22988	} else {
22989	    dupls = NULL;
22990	    nbDupls = 0;
22991	}
22992	if (bind->nodeTable != NULL) {
22993	    nbNodeTable = bind->nbNodes;
22994	} else {
22995	    nbNodeTable = 0;
22996	}
22997
22998	if ((nbNodeTable == 0) && (nbDupls == 0)) {
22999	    /*
23000	    * Transfer all IDC target-nodes to the IDC node-table.
23001	    */
23002	    bind->nodeTable =
23003		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23004	    bind->sizeNodes = matcher->targets->sizeItems;
23005	    bind->nbNodes = matcher->targets->nbItems;
23006
23007	    matcher->targets->items = NULL;
23008	    matcher->targets->sizeItems = 0;
23009	    matcher->targets->nbItems = 0;
23010	} else {
23011	    /*
23012	    * Compare the key-sequences and add to the IDC node-table.
23013	    */
23014	    nbTargets = matcher->targets->nbItems;
23015	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23016	    nbFields = matcher->aidc->def->nbFields;
23017	    i = 0;
23018	    do {
23019		keys = targets[i]->keys;
23020		if (nbDupls) {
23021		    /*
23022		    * Search in already found duplicates first.
23023		    */
23024		    j = 0;
23025		    do {
23026			if (nbFields == 1) {
23027			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23028				dupls[j]->keys[0]->val);
23029			    if (res == -1)
23030				goto internal_error;
23031			    if (res == 1) {
23032				/*
23033				* Equal key-sequence.
23034				*/
23035				goto next_target;
23036			    }
23037			} else {
23038			    res = 0;
23039			    ntkeys = dupls[j]->keys;
23040			    for (k = 0; k < nbFields; k++) {
23041				res = xmlSchemaAreValuesEqual(keys[k]->val,
23042				    ntkeys[k]->val);
23043				if (res == -1)
23044				    goto internal_error;
23045				if (res == 0) {
23046				    /*
23047				    * One of the keys differs.
23048				    */
23049				    break;
23050				}
23051			    }
23052			    if (res == 1) {
23053				/*
23054				* Equal key-sequence found.
23055				*/
23056				goto next_target;
23057			    }
23058			}
23059			j++;
23060		    } while (j < nbDupls);
23061		}
23062		if (nbNodeTable) {
23063		    j = 0;
23064		    do {
23065			if (nbFields == 1) {
23066			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23067				bind->nodeTable[j]->keys[0]->val);
23068			    if (res == -1)
23069				goto internal_error;
23070			    if (res == 0) {
23071				/*
23072				* The key-sequence differs.
23073				*/
23074				goto next_node_table_entry;
23075			    }
23076			} else {
23077			    res = 0;
23078			    ntkeys = bind->nodeTable[j]->keys;
23079			    for (k = 0; k < nbFields; k++) {
23080				res = xmlSchemaAreValuesEqual(keys[k]->val,
23081				    ntkeys[k]->val);
23082				if (res == -1)
23083				    goto internal_error;
23084				if (res == 0) {
23085				    /*
23086				    * One of the keys differs.
23087				    */
23088				    goto next_node_table_entry;
23089				}
23090			    }
23091			}
23092			/*
23093			* Add the duplicate to the list of duplicates.
23094			*/
23095			if (bind->dupls == NULL) {
23096			    bind->dupls = xmlSchemaItemListCreate();
23097			    if (bind->dupls == NULL)
23098				goto internal_error;
23099			}
23100			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23101			    goto internal_error;
23102			/*
23103			* Remove the duplicate entry from the IDC node-table.
23104			*/
23105			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23106			bind->nbNodes--;
23107
23108			goto next_target;
23109
23110next_node_table_entry:
23111			j++;
23112		    } while (j < nbNodeTable);
23113		}
23114		/*
23115		* If everything is fine, then add the IDC target-node to
23116		* the IDC node-table.
23117		*/
23118		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23119		    goto internal_error;
23120
23121next_target:
23122		i++;
23123	    } while (i < nbTargets);
23124	}
23125	matcher = matcher->next;
23126    }
23127    return(0);
23128
23129internal_error:
23130    return(-1);
23131}
23132
23133/**
23134 * xmlSchemaBubbleIDCNodeTables:
23135 * @depth: the current tree depth
23136 *
23137 * Merges IDC bindings of an element at @depth into the corresponding IDC
23138 * bindings of its parent element. If a duplicate note-table entry is found,
23139 * both, the parent node-table entry and child entry are discarded from the
23140 * node-table of the parent.
23141 *
23142 * Returns 0 if OK and -1 on internal errors.
23143 */
23144static int
23145xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23146{
23147    xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23148    xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23149    xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23150    xmlSchemaIDCAugPtr aidc;
23151    int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23152
23153    bind = vctxt->inode->idcTable;
23154    if (bind == NULL) {
23155	/* Fine, no table, no bubbles. */
23156	return (0);
23157    }
23158
23159    parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23160    /*
23161    * Walk all bindings; create new or add to existing bindings.
23162    * Remove duplicate key-sequences.
23163    */
23164    while (bind != NULL) {
23165
23166	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23167	    goto next_binding;
23168	/*
23169	* Check if the key/unique IDC table needs to be bubbled.
23170	*/
23171	if (! vctxt->createIDCNodeTables) {
23172	    aidc = vctxt->aidcs;
23173	    do {
23174		if (aidc->def == bind->definition) {
23175		    if ((aidc->keyrefDepth == -1) ||
23176			(aidc->keyrefDepth >= vctxt->depth)) {
23177			goto next_binding;
23178		    }
23179		    break;
23180		}
23181		aidc = aidc->next;
23182	    } while (aidc != NULL);
23183	}
23184
23185	if (parTable != NULL)
23186	    parBind = *parTable;
23187	/*
23188	* Search a matching parent binding for the
23189	* IDC definition.
23190	*/
23191	while (parBind != NULL) {
23192	    if (parBind->definition == bind->definition)
23193		break;
23194	    parBind = parBind->next;
23195	}
23196
23197	if (parBind != NULL) {
23198	    /*
23199	    * Compare every node-table entry of the child node,
23200	    * i.e. the key-sequence within, ...
23201	    */
23202	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23203
23204	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23205		oldDupls = parBind->dupls->nbItems;
23206		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23207	    } else {
23208		dupls = NULL;
23209		oldDupls = 0;
23210	    }
23211
23212	    parNodes = parBind->nodeTable;
23213	    nbFields = bind->definition->nbFields;
23214
23215	    for (i = 0; i < bind->nbNodes; i++) {
23216		node = bind->nodeTable[i];
23217		if (node == NULL)
23218		    continue;
23219		/*
23220		* ...with every key-sequence of the parent node, already
23221		* evaluated to be a duplicate key-sequence.
23222		*/
23223		if (oldDupls) {
23224		    j = 0;
23225		    while (j < oldDupls) {
23226			if (nbFields == 1) {
23227			    ret = xmlSchemaAreValuesEqual(
23228				node->keys[0]->val,
23229				dupls[j]->keys[0]->val);
23230			    if (ret == -1)
23231				goto internal_error;
23232			    if (ret == 0) {
23233				j++;
23234				continue;
23235			    }
23236			} else {
23237			    parNode = dupls[j];
23238			    for (k = 0; k < nbFields; k++) {
23239				ret = xmlSchemaAreValuesEqual(
23240				    node->keys[k]->val,
23241				    parNode->keys[k]->val);
23242				if (ret == -1)
23243				    goto internal_error;
23244				if (ret == 0)
23245				    break;
23246			    }
23247			}
23248			if (ret == 1)
23249			    /* Duplicate found. */
23250			    break;
23251			j++;
23252		    }
23253		    if (j != oldDupls) {
23254			/* Duplicate found. Skip this entry. */
23255			continue;
23256		    }
23257		}
23258		/*
23259		* ... and with every key-sequence of the parent node.
23260		*/
23261		if (oldNum) {
23262		    j = 0;
23263		    while (j < oldNum) {
23264			parNode = parNodes[j];
23265			if (nbFields == 1) {
23266			    ret = xmlSchemaAreValuesEqual(
23267				node->keys[0]->val,
23268				parNode->keys[0]->val);
23269			    if (ret == -1)
23270				goto internal_error;
23271			    if (ret == 0) {
23272				j++;
23273				continue;
23274			    }
23275			} else {
23276			    for (k = 0; k < nbFields; k++) {
23277				ret = xmlSchemaAreValuesEqual(
23278				    node->keys[k]->val,
23279				    parNode->keys[k]->val);
23280				if (ret == -1)
23281				    goto internal_error;
23282				if (ret == 0)
23283				    break;
23284			    }
23285			}
23286			if (ret == 1)
23287			    /* Duplicate found. */
23288			    break;
23289			j++;
23290		    }
23291		    if (j != oldNum) {
23292			/*
23293			* Handle duplicates. Move the duplicate in
23294			* the parent's node-table to the list of
23295			* duplicates.
23296			*/
23297			oldNum--;
23298			parBind->nbNodes--;
23299			/*
23300			* Move last old item to pos of duplicate.
23301			*/
23302			parNodes[j] = parNodes[oldNum];
23303
23304			if (parBind->nbNodes != oldNum) {
23305			    /*
23306			    * If new items exist, move last new item to
23307			    * last of old items.
23308			    */
23309			    parNodes[oldNum] =
23310				parNodes[parBind->nbNodes];
23311			}
23312			if (parBind->dupls == NULL) {
23313			    parBind->dupls = xmlSchemaItemListCreate();
23314			    if (parBind->dupls == NULL)
23315				goto internal_error;
23316			}
23317			xmlSchemaItemListAdd(parBind->dupls, parNode);
23318		    } else {
23319			/*
23320			* Add the node-table entry (node and key-sequence) of
23321			* the child node to the node table of the parent node.
23322			*/
23323			if (parBind->nodeTable == NULL) {
23324			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23325				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23326			    if (parBind->nodeTable == NULL) {
23327				xmlSchemaVErrMemory(NULL,
23328				    "allocating IDC list of node-table items", NULL);
23329				goto internal_error;
23330			    }
23331			    parBind->sizeNodes = 1;
23332			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23333			    parBind->sizeNodes *= 2;
23334			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23335				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23336				sizeof(xmlSchemaPSVIIDCNodePtr));
23337			    if (parBind->nodeTable == NULL) {
23338				xmlSchemaVErrMemory(NULL,
23339				    "re-allocating IDC list of node-table items", NULL);
23340				goto internal_error;
23341			    }
23342			}
23343			parNodes = parBind->nodeTable;
23344			/*
23345			* Append the new node-table entry to the 'new node-table
23346			* entries' section.
23347			*/
23348			parNodes[parBind->nbNodes++] = node;
23349		    }
23350
23351		}
23352
23353	    }
23354	} else {
23355	    /*
23356	    * No binding for the IDC was found: create a new one and
23357	    * copy all node-tables.
23358	    */
23359	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23360	    if (parBind == NULL)
23361		goto internal_error;
23362
23363	    /*
23364	    * TODO: Hmm, how to optimize the initial number of
23365	    * allocated entries?
23366	    */
23367	    if (bind->nbNodes != 0) {
23368		/*
23369		* Add all IDC node-table entries.
23370		*/
23371		if (! vctxt->psviExposeIDCNodeTables) {
23372		    /*
23373		    * Just move the entries.
23374		    * NOTE: this is quite save here, since
23375		    * all the keyref lookups have already been
23376		    * performed.
23377		    */
23378		    parBind->nodeTable = bind->nodeTable;
23379		    bind->nodeTable = NULL;
23380		    parBind->sizeNodes = bind->sizeNodes;
23381		    bind->sizeNodes = 0;
23382		    parBind->nbNodes = bind->nbNodes;
23383		    bind->nbNodes = 0;
23384		} else {
23385		    /*
23386		    * Copy the entries.
23387		    */
23388		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23389			xmlMalloc(bind->nbNodes *
23390			sizeof(xmlSchemaPSVIIDCNodePtr));
23391		    if (parBind->nodeTable == NULL) {
23392			xmlSchemaVErrMemory(NULL,
23393			    "allocating an array of IDC node-table "
23394			    "items", NULL);
23395			xmlSchemaIDCFreeBinding(parBind);
23396			goto internal_error;
23397		    }
23398		    parBind->sizeNodes = bind->nbNodes;
23399		    parBind->nbNodes = bind->nbNodes;
23400		    memcpy(parBind->nodeTable, bind->nodeTable,
23401			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23402		}
23403	    }
23404	    if (bind->dupls) {
23405		/*
23406		* Move the duplicates.
23407		*/
23408		if (parBind->dupls != NULL)
23409		    xmlSchemaItemListFree(parBind->dupls);
23410		parBind->dupls = bind->dupls;
23411		bind->dupls = NULL;
23412	    }
23413	    if (*parTable == NULL)
23414		*parTable = parBind;
23415	    else {
23416		parBind->next = *parTable;
23417		*parTable = parBind;
23418	    }
23419	}
23420
23421next_binding:
23422	bind = bind->next;
23423    }
23424    return (0);
23425
23426internal_error:
23427    return(-1);
23428}
23429
23430/**
23431 * xmlSchemaCheckCVCIDCKeyRef:
23432 * @vctxt: the WXS validation context
23433 * @elemDecl: the element declaration
23434 *
23435 * Check the cvc-idc-keyref constraints.
23436 */
23437static int
23438xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23439{
23440    xmlSchemaIDCMatcherPtr matcher;
23441    xmlSchemaPSVIIDCBindingPtr bind;
23442
23443    matcher = vctxt->inode->idcMatchers;
23444    /*
23445    * Find a keyref.
23446    */
23447    while (matcher != NULL) {
23448	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23449	    matcher->targets &&
23450	    matcher->targets->nbItems)
23451	{
23452	    int i, j, k, res, nbFields, hasDupls;
23453	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23454	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23455
23456	    nbFields = matcher->aidc->def->nbFields;
23457
23458	    /*
23459	    * Find the IDC node-table for the referenced IDC key/unique.
23460	    */
23461	    bind = vctxt->inode->idcTable;
23462	    while (bind != NULL) {
23463		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23464		    bind->definition)
23465		    break;
23466		bind = bind->next;
23467	    }
23468	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23469	    /*
23470	    * Search for a matching key-sequences.
23471	    */
23472	    for (i = 0; i < matcher->targets->nbItems; i++) {
23473		res = 0;
23474		refNode = matcher->targets->items[i];
23475		if (bind != NULL) {
23476		    refKeys = refNode->keys;
23477		    for (j = 0; j < bind->nbNodes; j++) {
23478			keys = bind->nodeTable[j]->keys;
23479			for (k = 0; k < nbFields; k++) {
23480			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23481				refKeys[k]->val);
23482			    if (res == 0)
23483				break;
23484			    else if (res == -1) {
23485				return (-1);
23486			    }
23487			}
23488			if (res == 1) {
23489			    /*
23490			    * Match found.
23491			    */
23492			    break;
23493			}
23494		    }
23495		    if ((res == 0) && hasDupls) {
23496			/*
23497			* Search in duplicates
23498			*/
23499			for (j = 0; j < bind->dupls->nbItems; j++) {
23500			    keys = ((xmlSchemaPSVIIDCNodePtr)
23501				bind->dupls->items[j])->keys;
23502			    for (k = 0; k < nbFields; k++) {
23503				res = xmlSchemaAreValuesEqual(keys[k]->val,
23504				    refKeys[k]->val);
23505				if (res == 0)
23506				    break;
23507				else if (res == -1) {
23508				    return (-1);
23509				}
23510			    }
23511			    if (res == 1) {
23512				/*
23513				* Match in duplicates found.
23514				*/
23515				xmlChar *str = NULL, *strB = NULL;
23516				xmlSchemaKeyrefErr(vctxt,
23517				    XML_SCHEMAV_CVC_IDC, refNode,
23518				    (xmlSchemaTypePtr) matcher->aidc->def,
23519				    "More than one match found for "
23520				    "key-sequence %s of keyref '%s'",
23521				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23522					refNode->keys, nbFields),
23523				    xmlSchemaGetComponentQName(&strB,
23524					matcher->aidc->def));
23525				FREE_AND_NULL(str);
23526				FREE_AND_NULL(strB);
23527				break;
23528			    }
23529			}
23530		    }
23531		}
23532
23533		if (res == 0) {
23534		    xmlChar *str = NULL, *strB = NULL;
23535		    xmlSchemaKeyrefErr(vctxt,
23536			XML_SCHEMAV_CVC_IDC, refNode,
23537			(xmlSchemaTypePtr) matcher->aidc->def,
23538			"No match found for key-sequence %s of keyref '%s'",
23539			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23540			    refNode->keys, nbFields),
23541			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23542		    FREE_AND_NULL(str);
23543		    FREE_AND_NULL(strB);
23544		}
23545	    }
23546	}
23547	matcher = matcher->next;
23548    }
23549    /* TODO: Return an error if any error encountered. */
23550    return (0);
23551}
23552
23553/************************************************************************
23554 * 									*
23555 * 			XML Reader validation code                      *
23556 * 									*
23557 ************************************************************************/
23558
23559static xmlSchemaAttrInfoPtr
23560xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23561{
23562    xmlSchemaAttrInfoPtr iattr;
23563    /*
23564    * Grow/create list of attribute infos.
23565    */
23566    if (vctxt->attrInfos == NULL) {
23567	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23568	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23569	vctxt->sizeAttrInfos = 1;
23570	if (vctxt->attrInfos == NULL) {
23571	    xmlSchemaVErrMemory(vctxt,
23572		"allocating attribute info list", NULL);
23573	    return (NULL);
23574	}
23575    } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23576	vctxt->sizeAttrInfos++;
23577	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23578	    xmlRealloc(vctxt->attrInfos,
23579		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23580	if (vctxt->attrInfos == NULL) {
23581	    xmlSchemaVErrMemory(vctxt,
23582		"re-allocating attribute info list", NULL);
23583	    return (NULL);
23584	}
23585    } else {
23586	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23587	if (iattr->localName != NULL) {
23588	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23589		"attr info not cleared");
23590	    return (NULL);
23591	}
23592	iattr->nodeType = XML_ATTRIBUTE_NODE;
23593	return (iattr);
23594    }
23595    /*
23596    * Create an attribute info.
23597    */
23598    iattr = (xmlSchemaAttrInfoPtr)
23599	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23600    if (iattr == NULL) {
23601	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23602	return (NULL);
23603    }
23604    memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23605    iattr->nodeType = XML_ATTRIBUTE_NODE;
23606    vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23607
23608    return (iattr);
23609}
23610
23611static int
23612xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23613			xmlNodePtr attrNode,
23614			int nodeLine,
23615			const xmlChar *localName,
23616			const xmlChar *nsName,
23617			int ownedNames,
23618			xmlChar *value,
23619			int ownedValue)
23620{
23621    xmlSchemaAttrInfoPtr attr;
23622
23623    attr = xmlSchemaGetFreshAttrInfo(vctxt);
23624    if (attr == NULL) {
23625	VERROR_INT("xmlSchemaPushAttribute",
23626	    "calling xmlSchemaGetFreshAttrInfo()");
23627	return (-1);
23628    }
23629    attr->node = attrNode;
23630    attr->nodeLine = nodeLine;
23631    attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23632    attr->localName = localName;
23633    attr->nsName = nsName;
23634    if (ownedNames)
23635	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23636    /*
23637    * Evaluate if it's an XSI attribute.
23638    */
23639    if (nsName != NULL) {
23640	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23641	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23642		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23643	    }
23644	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23645	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23646		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23647	    }
23648	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23649	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23650		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23651	    }
23652	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23653	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23654		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23655	    }
23656	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23657	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23658	}
23659    }
23660    attr->value = value;
23661    if (ownedValue)
23662	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23663    if (attr->metaType != 0)
23664	attr->state = XML_SCHEMAS_ATTR_META;
23665    return (0);
23666}
23667
23668static void
23669xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
23670{
23671    ielem->hasKeyrefs = 0;
23672    ielem->appliedXPath = 0;
23673    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23674	FREE_AND_NULL(ielem->localName);
23675	FREE_AND_NULL(ielem->nsName);
23676    } else {
23677	ielem->localName = NULL;
23678	ielem->nsName = NULL;
23679    }
23680    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23681	FREE_AND_NULL(ielem->value);
23682    } else {
23683	ielem->value = NULL;
23684    }
23685    if (ielem->val != NULL) {
23686	/*
23687	* PSVI TODO: Be careful not to free it when the value is
23688	* exposed via PSVI.
23689	*/
23690	xmlSchemaFreeValue(ielem->val);
23691	ielem->val = NULL;
23692    }
23693    if (ielem->idcMatchers != NULL) {
23694	/*
23695	* URGENT OPTIMIZE TODO: Use a pool of IDC matchers.
23696	*/
23697	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23698	ielem->idcMatchers = NULL;
23699    }
23700    if (ielem->idcTable != NULL) {
23701	/*
23702	* OPTIMIZE TODO: Use a pool of IDC tables??.
23703	*/
23704	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23705	ielem->idcTable = NULL;
23706    }
23707    if (ielem->regexCtxt != NULL) {
23708	xmlRegFreeExecCtxt(ielem->regexCtxt);
23709	ielem->regexCtxt = NULL;
23710    }
23711    if (ielem->nsBindings != NULL) {
23712	xmlFree((xmlChar **)ielem->nsBindings);
23713	ielem->nsBindings = NULL;
23714	ielem->nbNsBindings = 0;
23715	ielem->sizeNsBindings = 0;
23716    }
23717}
23718
23719/**
23720 * xmlSchemaGetFreshElemInfo:
23721 * @vctxt: the schema validation context
23722 *
23723 * Creates/reuses and initializes the element info item for
23724 * the currect tree depth.
23725 *
23726 * Returns the element info item or NULL on API or internal errors.
23727 */
23728static xmlSchemaNodeInfoPtr
23729xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
23730{
23731    xmlSchemaNodeInfoPtr info = NULL;
23732
23733    if (vctxt->depth > vctxt->sizeElemInfos) {
23734	VERROR_INT("xmlSchemaGetFreshElemInfo",
23735	    "inconsistent depth encountered");
23736	return (NULL);
23737    }
23738    if (vctxt->elemInfos == NULL) {
23739	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23740	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23741	if (vctxt->elemInfos == NULL) {
23742	    xmlSchemaVErrMemory(vctxt,
23743		"allocating the element info array", NULL);
23744	    return (NULL);
23745	}
23746	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23747	vctxt->sizeElemInfos = 10;
23748    } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23749	int i = vctxt->sizeElemInfos;
23750
23751	vctxt->sizeElemInfos *= 2;
23752	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23753	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23754	    sizeof(xmlSchemaNodeInfoPtr));
23755	if (vctxt->elemInfos == NULL) {
23756	    xmlSchemaVErrMemory(vctxt,
23757		"re-allocating the element info array", NULL);
23758	    return (NULL);
23759	}
23760	/*
23761	* We need the new memory to be NULLed.
23762	* TODO: Use memset instead?
23763	*/
23764	for (; i < vctxt->sizeElemInfos; i++)
23765	    vctxt->elemInfos[i] = NULL;
23766    } else
23767	info = vctxt->elemInfos[vctxt->depth];
23768
23769    if (info == NULL) {
23770	info = (xmlSchemaNodeInfoPtr)
23771	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
23772	if (info == NULL) {
23773	    xmlSchemaVErrMemory(vctxt,
23774		"allocating an element info", NULL);
23775	    return (NULL);
23776	}
23777	vctxt->elemInfos[vctxt->depth] = info;
23778    } else {
23779	if (info->localName != NULL) {
23780	    VERROR_INT("xmlSchemaGetFreshElemInfo",
23781		"elem info has not been cleared");
23782	    return (NULL);
23783	}
23784    }
23785    memset(info, 0, sizeof(xmlSchemaNodeInfo));
23786    info->nodeType = XML_ELEMENT_NODE;
23787    info->depth = vctxt->depth;
23788
23789    return (info);
23790}
23791
23792#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
23793#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
23794#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
23795
23796static int
23797xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
23798			xmlNodePtr node,
23799			xmlSchemaTypePtr type,
23800			xmlSchemaValType valType,
23801			const xmlChar * value,
23802			xmlSchemaValPtr val,
23803			unsigned long length,
23804			int fireErrors)
23805{
23806    int ret, error = 0;
23807
23808    xmlSchemaTypePtr tmpType;
23809    xmlSchemaFacetLinkPtr facetLink;
23810    xmlSchemaFacetPtr facet;
23811    unsigned long len = 0;
23812    xmlSchemaWhitespaceValueType ws;
23813
23814    /*
23815    * In Libxml2, derived built-in types have currently no explicit facets.
23816    */
23817    if (type->type == XML_SCHEMA_TYPE_BASIC)
23818	return (0);
23819
23820    /*
23821    * NOTE: Do not jump away, if the facetSet of the given type is
23822    * empty: until now, "pattern" and "enumeration" facets of the
23823    * *base types* need to be checked as well.
23824    */
23825    if (type->facetSet == NULL)
23826	goto pattern_and_enum;
23827
23828    if (! WXS_IS_ATOMIC(type)) {
23829	if (WXS_IS_LIST(type))
23830	    goto WXS_IS_LIST;
23831	else
23832	    goto pattern_and_enum;
23833    }
23834    /*
23835    * Whitespace handling is only of importance for string-based
23836    * types.
23837    */
23838    tmpType = xmlSchemaGetPrimitiveType(type);
23839    if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
23840	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
23841	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
23842    } else
23843	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
23844    /*
23845    * If the value was not computed (for string or
23846    * anySimpleType based types), then use the provided
23847    * type.
23848    */
23849    if (val == NULL)
23850	valType = valType;
23851    else
23852	valType = xmlSchemaGetValType(val);
23853
23854    ret = 0;
23855    for (facetLink = type->facetSet; facetLink != NULL;
23856	facetLink = facetLink->next) {
23857	/*
23858	* Skip the pattern "whiteSpace": it is used to
23859	* format the character content beforehand.
23860	*/
23861	switch (facetLink->facet->type) {
23862	    case XML_SCHEMA_FACET_WHITESPACE:
23863	    case XML_SCHEMA_FACET_PATTERN:
23864	    case XML_SCHEMA_FACET_ENUMERATION:
23865		continue;
23866	    case XML_SCHEMA_FACET_LENGTH:
23867	    case XML_SCHEMA_FACET_MINLENGTH:
23868	    case XML_SCHEMA_FACET_MAXLENGTH:
23869		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
23870		    valType, value, val, &len, ws);
23871		break;
23872	    default:
23873		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
23874		    valType, value, val, ws);
23875		break;
23876	}
23877	if (ret < 0) {
23878	    AERROR_INT("xmlSchemaValidateFacets",
23879		"validating against a atomic type facet");
23880	    return (-1);
23881	} else if (ret > 0) {
23882	    if (fireErrors)
23883		xmlSchemaFacetErr(actxt, ret, node,
23884		value, len, type, facetLink->facet, NULL, NULL, NULL);
23885	    else
23886		return (ret);
23887	    if (error == 0)
23888		error = ret;
23889	}
23890	ret = 0;
23891    }
23892
23893WXS_IS_LIST:
23894    if (! WXS_IS_LIST(type))
23895	goto pattern_and_enum;
23896    /*
23897    * "length", "minLength" and "maxLength" of list types.
23898    */
23899    ret = 0;
23900    for (facetLink = type->facetSet; facetLink != NULL;
23901	facetLink = facetLink->next) {
23902
23903	switch (facetLink->facet->type) {
23904	    case XML_SCHEMA_FACET_LENGTH:
23905	    case XML_SCHEMA_FACET_MINLENGTH:
23906	    case XML_SCHEMA_FACET_MAXLENGTH:
23907		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
23908		    value, length, NULL);
23909		break;
23910	    default:
23911		continue;
23912	}
23913	if (ret < 0) {
23914	    AERROR_INT("xmlSchemaValidateFacets",
23915		"validating against a list type facet");
23916	    return (-1);
23917	} else if (ret > 0) {
23918	    if (fireErrors)
23919		xmlSchemaFacetErr(actxt, ret, node,
23920		value, length, type, facetLink->facet, NULL, NULL, NULL);
23921	    else
23922		return (ret);
23923	    if (error == 0)
23924		error = ret;
23925	}
23926	ret = 0;
23927    }
23928
23929pattern_and_enum:
23930    if (error >= 0) {
23931	int found = 0;
23932	/*
23933	* Process enumerations. Facet values are in the value space
23934	* of the defining type's base type. This seems to be a bug in the
23935	* XML Schema 1.0 spec. Use the whitespace type of the base type.
23936	* Only the first set of enumerations in the ancestor-or-self axis
23937	* is used for validation.
23938	*/
23939	ret = 0;
23940	tmpType = type;
23941	do {
23942	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
23943		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
23944		    continue;
23945		found = 1;
23946		ret = xmlSchemaAreValuesEqual(facet->val, val);
23947		if (ret == 1)
23948		    break;
23949		else if (ret < 0) {
23950		    AERROR_INT("xmlSchemaValidateFacets",
23951			"validating against an enumeration facet");
23952		    return (-1);
23953		}
23954	    }
23955	    if (ret != 0)
23956		break;
23957	    /*
23958	    * Break on the first set of enumerations. Any additional
23959	    *  enumerations which might be existent on the ancestors
23960	    *  of the current type are restricted by this set; thus
23961	    *  *must* *not* be taken into account.
23962	    */
23963	    if (found)
23964		break;
23965	    tmpType = tmpType->baseType;
23966	} while ((tmpType != NULL) &&
23967	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
23968	if (found && (ret == 0)) {
23969	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
23970	    if (fireErrors) {
23971		xmlSchemaFacetErr(actxt, ret, node,
23972		    value, 0, type, NULL, NULL, NULL, NULL);
23973	    } else
23974		return (ret);
23975	    if (error == 0)
23976		error = ret;
23977	}
23978    }
23979
23980    if (error >= 0) {
23981	int found;
23982	/*
23983	* Process patters. Pattern facets are ORed at type level
23984	* and ANDed if derived. Walk the base type axis.
23985	*/
23986	tmpType = type;
23987	facet = NULL;
23988	do {
23989	    found = 0;
23990	    for (facetLink = tmpType->facetSet; facetLink != NULL;
23991		facetLink = facetLink->next) {
23992		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
23993		    continue;
23994		found = 1;
23995		/*
23996		* NOTE that for patterns, @value needs to be the
23997		* normalized vaule.
23998		*/
23999		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24000		if (ret == 1)
24001		    break;
24002		else if (ret < 0) {
24003		    AERROR_INT("xmlSchemaValidateFacets",
24004			"validating against a pattern facet");
24005		    return (-1);
24006		} else {
24007		    /*
24008		    * Save the last non-validating facet.
24009		    */
24010		    facet = facetLink->facet;
24011		}
24012	    }
24013	    if (found && (ret != 1)) {
24014		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24015		if (fireErrors) {
24016		    xmlSchemaFacetErr(actxt, ret, node,
24017			value, 0, type, facet, NULL, NULL, NULL);
24018		} else
24019		    return (ret);
24020		if (error == 0)
24021		    error = ret;
24022		break;
24023	    }
24024	    tmpType = tmpType->baseType;
24025	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24026    }
24027
24028    return (error);
24029}
24030
24031static xmlChar *
24032xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24033			const xmlChar *value)
24034{
24035    switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24036	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24037	    return (xmlSchemaCollapseString(value));
24038	case XML_SCHEMA_WHITESPACE_REPLACE:
24039	    return (xmlSchemaWhiteSpaceReplace(value));
24040	default:
24041	    return (NULL);
24042    }
24043}
24044
24045static int
24046xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24047		       const xmlChar *value,
24048		       xmlSchemaValPtr *val,
24049		       int valNeeded)
24050{
24051    int ret;
24052    const xmlChar *nsName;
24053    xmlChar *local, *prefix = NULL;
24054
24055    ret = xmlValidateQName(value, 1);
24056    if (ret != 0) {
24057	if (ret == -1) {
24058	    VERROR_INT("xmlSchemaValidateQName",
24059		"calling xmlValidateQName()");
24060	    return (-1);
24061	}
24062	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24063    }
24064    /*
24065    * NOTE: xmlSplitQName2 will always return a duplicated
24066    * strings.
24067    */
24068    local = xmlSplitQName2(value, &prefix);
24069    if (local == NULL)
24070	local = xmlStrdup(value);
24071    /*
24072    * OPTIMIZE TODO: Use flags for:
24073    *  - is there any namespace binding?
24074    *  - is there a default namespace?
24075    */
24076    nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24077
24078    if (prefix != NULL) {
24079	xmlFree(prefix);
24080	/*
24081	* A namespace must be found if the prefix is
24082	* NOT NULL.
24083	*/
24084	if (nsName == NULL) {
24085	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24086	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24087		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24088		"The QName value '%s' has no "
24089		"corresponding namespace declaration in "
24090		"scope", value, NULL);
24091	    if (local != NULL)
24092		xmlFree(local);
24093	    return (ret);
24094	}
24095    }
24096    if (valNeeded && val) {
24097	if (nsName != NULL)
24098	    *val = xmlSchemaNewQNameValue(
24099		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24100	else
24101	    *val = xmlSchemaNewQNameValue(NULL,
24102		BAD_CAST local);
24103    } else
24104	xmlFree(local);
24105    return (0);
24106}
24107
24108/*
24109* cvc-simple-type
24110*/
24111static int
24112xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24113			     xmlNodePtr node,
24114			     xmlSchemaTypePtr type,
24115			     const xmlChar *value,
24116			     xmlSchemaValPtr *retVal,
24117			     int fireErrors,
24118			     int normalize,
24119			     int isNormalized)
24120{
24121    int ret = 0, valNeeded = (retVal) ? 1 : 0;
24122    xmlSchemaValPtr val = NULL;
24123    /* xmlSchemaWhitespaceValueType ws; */
24124    xmlChar *normValue = NULL;
24125
24126#define NORMALIZE(atype) \
24127    if ((! isNormalized) && \
24128    (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24129	normValue = xmlSchemaNormalizeValue(atype, value); \
24130	if (normValue != NULL) \
24131	    value = normValue; \
24132	isNormalized = 1; \
24133    }
24134
24135    if ((retVal != NULL) && (*retVal != NULL)) {
24136	xmlSchemaFreeValue(*retVal);
24137	*retVal = NULL;
24138    }
24139    /*
24140    * 3.14.4 Simple Type Definition Validation Rules
24141    * Validation Rule: String Valid
24142    */
24143    /*
24144    * 1 It is schema-valid with respect to that definition as defined
24145    * by Datatype Valid in [XML Schemas: Datatypes].
24146    */
24147    /*
24148    * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24149    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24150    * the string must be a �declared entity name�.
24151    */
24152    /*
24153    * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24154    * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24155    * then every whitespace-delimited substring of the string must be a �declared
24156    * entity name�.
24157    */
24158    /*
24159    * 2.3 otherwise no further condition applies.
24160    */
24161    if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24162	valNeeded = 1;
24163    if (value == NULL)
24164	value = BAD_CAST "";
24165    if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24166	xmlSchemaTypePtr biType; /* The built-in type. */
24167	/*
24168	* SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24169	* a literal in the �lexical space� of {base type definition}"
24170	*/
24171	/*
24172	* Whitespace-normalize.
24173	*/
24174	NORMALIZE(type);
24175	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24176	    /*
24177	    * Get the built-in type.
24178	    */
24179	    biType = type->baseType;
24180	    while ((biType != NULL) &&
24181		(biType->type != XML_SCHEMA_TYPE_BASIC))
24182		biType = biType->baseType;
24183
24184	    if (biType == NULL) {
24185		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24186		    "could not get the built-in type");
24187		goto internal_error;
24188	    }
24189	} else
24190	    biType = type;
24191	/*
24192	* NOTATIONs need to be processed here, since they need
24193	* to lookup in the hashtable of NOTATION declarations of the schema.
24194	*/
24195	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24196	    switch (biType->builtInType) {
24197		case XML_SCHEMAS_NOTATION:
24198		    ret = xmlSchemaValidateNotation(
24199			(xmlSchemaValidCtxtPtr) actxt,
24200			((xmlSchemaValidCtxtPtr) actxt)->schema,
24201			NULL, value, &val, valNeeded);
24202		    break;
24203		case XML_SCHEMAS_QNAME:
24204		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24205			value, &val, valNeeded);
24206		    break;
24207		default:
24208		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24209		    if (valNeeded)
24210			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24211			    value, &val, NULL);
24212		    else
24213			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24214			    value, NULL, NULL);
24215		    break;
24216	    }
24217	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24218	    switch (biType->builtInType) {
24219		case XML_SCHEMAS_NOTATION:
24220		    ret = xmlSchemaValidateNotation(NULL,
24221			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24222			value, &val, valNeeded);
24223		    break;
24224		default:
24225		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24226		    if (valNeeded)
24227			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24228			    value, &val, node);
24229		    else
24230			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24231			    value, NULL, node);
24232		    break;
24233	    }
24234	} else {
24235	    /*
24236	    * Validation via a public API is not implemented yet.
24237	    */
24238	    TODO
24239	    goto internal_error;
24240	}
24241	if (ret != 0) {
24242	    if (ret < 0) {
24243		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24244		    "validating against a built-in type");
24245		goto internal_error;
24246	    }
24247	    if (WXS_IS_LIST(type))
24248		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24249	    else
24250		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24251	}
24252	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24253	    /*
24254	    * Check facets.
24255	    */
24256	    ret = xmlSchemaValidateFacets(actxt, node, type,
24257		(xmlSchemaValType) biType->builtInType, value, val,
24258		0, fireErrors);
24259	    if (ret != 0) {
24260		if (ret < 0) {
24261		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24262			"validating facets of atomic simple type");
24263		    goto internal_error;
24264		}
24265		if (WXS_IS_LIST(type))
24266		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24267		else
24268		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24269	    }
24270	}
24271	if (fireErrors && (ret > 0))
24272	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24273    } else if (WXS_IS_LIST(type)) {
24274
24275	xmlSchemaTypePtr itemType;
24276	const xmlChar *cur, *end;
24277	xmlChar *tmpValue = NULL;
24278	unsigned long len = 0;
24279	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24280	/* 1.2.2 if {variety} is �list� then the string must be a sequence
24281	* of white space separated tokens, each of which �match�es a literal
24282	* in the �lexical space� of {item type definition}
24283	*/
24284	/*
24285	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24286	* the list type has an enum or pattern facet.
24287	*/
24288	NORMALIZE(type);
24289	/*
24290	* VAL TODO: Optimize validation of empty values.
24291	* VAL TODO: We do not have computed values for lists.
24292	*/
24293	itemType = WXS_LIST_ITEMTYPE(type);
24294	cur = value;
24295	do {
24296	    while (IS_BLANK_CH(*cur))
24297		cur++;
24298	    end = cur;
24299	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24300		end++;
24301	    if (end == cur)
24302		break;
24303	    tmpValue = xmlStrndup(cur, end - cur);
24304	    len++;
24305
24306	    if (valNeeded)
24307		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24308		    tmpValue, &curVal, fireErrors, 0, 1);
24309	    else
24310		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24311		    tmpValue, NULL, fireErrors, 0, 1);
24312	    FREE_AND_NULL(tmpValue);
24313	    if (curVal != NULL) {
24314		/*
24315		* Add to list of computed values.
24316		*/
24317		if (val == NULL)
24318		    val = curVal;
24319		else
24320		    xmlSchemaValueAppend(prevVal, curVal);
24321		prevVal = curVal;
24322		curVal = NULL;
24323	    }
24324	    if (ret != 0) {
24325		if (ret < 0) {
24326		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24327			"validating an item of list simple type");
24328		    goto internal_error;
24329		}
24330		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24331		break;
24332	    }
24333	    cur = end;
24334	} while (*cur != 0);
24335	FREE_AND_NULL(tmpValue);
24336	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24337	    /*
24338	    * Apply facets (pattern, enumeration).
24339	    */
24340	    ret = xmlSchemaValidateFacets(actxt, node, type,
24341		XML_SCHEMAS_UNKNOWN, value, val,
24342		len, fireErrors);
24343	    if (ret != 0) {
24344		if (ret < 0) {
24345		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24346			"validating facets of list simple type");
24347		    goto internal_error;
24348		}
24349		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24350	    }
24351	}
24352	if (fireErrors && (ret > 0)) {
24353	    /*
24354	    * Report the normalized value.
24355	    */
24356	    normalize = 1;
24357	    NORMALIZE(type);
24358	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24359	}
24360    } else if (WXS_IS_UNION(type)) {
24361	xmlSchemaTypeLinkPtr memberLink;
24362	/*
24363	* TODO: For all datatypes �derived� by �union�  whiteSpace does
24364	* not apply directly; however, the normalization behavior of �union�
24365	* types is controlled by the value of whiteSpace on that one of the
24366	* �memberTypes� against which the �union� is successfully validated.
24367	*
24368	* This means that the value is normalized by the first validating
24369	* member type, then the facets of the union type are applied. This
24370	* needs changing of the value!
24371	*/
24372
24373	/*
24374	* 1.2.3 if {variety} is �union� then the string must �match� a
24375	* literal in the �lexical space� of at least one member of
24376	* {member type definitions}
24377	*/
24378	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24379	if (memberLink == NULL) {
24380	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24381		"union simple type has no member types");
24382	    goto internal_error;
24383	}
24384	/*
24385	* Always normalize union type values, since we currently
24386	* cannot store the whitespace information with the value
24387	* itself; otherwise a later value-comparison would be
24388	* not possible.
24389	*/
24390	while (memberLink != NULL) {
24391	    if (valNeeded)
24392		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24393		    memberLink->type, value, &val, 0, 1, 0);
24394	    else
24395		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24396		    memberLink->type, value, NULL, 0, 1, 0);
24397	    if (ret <= 0)
24398		break;
24399	    memberLink = memberLink->next;
24400	}
24401	if (ret != 0) {
24402	    if (ret < 0) {
24403		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24404		    "validating members of union simple type");
24405		goto internal_error;
24406	    }
24407	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24408	}
24409	/*
24410	* Apply facets (pattern, enumeration).
24411	*/
24412	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24413	    /*
24414	    * The normalization behavior of �union� types is controlled by
24415	    * the value of whiteSpace on that one of the �memberTypes�
24416	    * against which the �union� is successfully validated.
24417	    */
24418	    NORMALIZE(memberLink->type);
24419	    ret = xmlSchemaValidateFacets(actxt, node, type,
24420		XML_SCHEMAS_UNKNOWN, value, val,
24421		0, fireErrors);
24422	    if (ret != 0) {
24423		if (ret < 0) {
24424		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24425			"validating facets of union simple type");
24426		    goto internal_error;
24427		}
24428		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24429	    }
24430	}
24431	if (fireErrors && (ret > 0))
24432	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24433    }
24434
24435    if (normValue != NULL)
24436	xmlFree(normValue);
24437    if (ret == 0) {
24438	if (retVal != NULL)
24439	    *retVal = val;
24440	else if (val != NULL)
24441	    xmlSchemaFreeValue(val);
24442    } else if (val != NULL)
24443	xmlSchemaFreeValue(val);
24444    return (ret);
24445internal_error:
24446    if (normValue != NULL)
24447	xmlFree(normValue);
24448    if (val != NULL)
24449	xmlSchemaFreeValue(val);
24450    return (-1);
24451}
24452
24453static int
24454xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24455			   const xmlChar *value,
24456			   const xmlChar **nsName,
24457			   const xmlChar **localName)
24458{
24459    int ret = 0;
24460
24461    if ((nsName == NULL) || (localName == NULL))
24462	return (-1);
24463    *nsName = NULL;
24464    *localName = NULL;
24465
24466    ret = xmlValidateQName(value, 1);
24467    if (ret == -1)
24468	return (-1);
24469    if (ret > 0) {
24470	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24471	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24472	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24473	return (1);
24474    }
24475    {
24476	xmlChar *local = NULL;
24477	xmlChar *prefix;
24478
24479	/*
24480	* NOTE: xmlSplitQName2 will return a duplicated
24481	* string.
24482	*/
24483	local = xmlSplitQName2(value, &prefix);
24484	if (local == NULL)
24485	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24486	else {
24487	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24488	    xmlFree(local);
24489	}
24490
24491	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24492
24493	if (prefix != NULL) {
24494	    xmlFree(prefix);
24495	    /*
24496	    * A namespace must be found if the prefix is NOT NULL.
24497	    */
24498	    if (*nsName == NULL) {
24499		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24500		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24501		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24502		    "The QName value '%s' has no "
24503		    "corresponding namespace declaration in scope",
24504		    value, NULL);
24505		return (2);
24506	    }
24507	}
24508    }
24509    return (0);
24510}
24511
24512static int
24513xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24514			xmlSchemaAttrInfoPtr iattr,
24515			xmlSchemaTypePtr *localType,
24516			xmlSchemaElementPtr elemDecl)
24517{
24518    int ret = 0;
24519    /*
24520    * cvc-elt (3.3.4) : (4)
24521    * AND
24522    * Schema-Validity Assessment (Element) (cvc-assess-elt)
24523    *   (1.2.1.2.1) - (1.2.1.2.4)
24524    * Handle 'xsi:type'.
24525    */
24526    if (localType == NULL)
24527	return (-1);
24528    *localType = NULL;
24529    if (iattr == NULL)
24530	return (0);
24531    else {
24532	const xmlChar *nsName = NULL, *local = NULL;
24533	/*
24534	* TODO: We should report a *warning* that the type was overriden
24535	* by the instance.
24536	*/
24537	ACTIVATE_ATTRIBUTE(iattr);
24538	/*
24539	* (cvc-elt) (3.3.4) : (4.1)
24540	* (cvc-assess-elt) (1.2.1.2.2)
24541	*/
24542	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24543	    &nsName, &local);
24544	if (ret != 0) {
24545	    if (ret < 0) {
24546		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24547		    "calling xmlSchemaQNameExpand() to validate the "
24548		    "attribute 'xsi:type'");
24549		goto internal_error;
24550	    }
24551	    goto exit;
24552	}
24553	/*
24554	* (cvc-elt) (3.3.4) : (4.2)
24555	* (cvc-assess-elt) (1.2.1.2.3)
24556	*/
24557	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24558	if (*localType == NULL) {
24559	    xmlChar *str = NULL;
24560
24561	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24562		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24563		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24564		"The QName value '%s' of the xsi:type attribute does not "
24565		"resolve to a type definition",
24566		xmlSchemaFormatQName(&str, nsName, local), NULL);
24567	    FREE_AND_NULL(str);
24568	    ret = vctxt->err;
24569	    goto exit;
24570	}
24571	if (elemDecl != NULL) {
24572	    int set = 0;
24573
24574	    /*
24575	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24576	    * "The �local type definition� must be validly
24577	    * derived from the {type definition} given the union of
24578	    * the {disallowed substitutions} and the {type definition}'s
24579	    * {prohibited substitutions}, as defined in
24580	    * Type Derivation OK (Complex) (�3.4.6)
24581	    * (if it is a complex type definition),
24582	    * or given {disallowed substitutions} as defined in Type
24583	    * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24584	    * definition)."
24585	    *
24586	    * {disallowed substitutions}: the "block" on the element decl.
24587	    * {prohibited substitutions}: the "block" on the type def.
24588	    */
24589	    /*
24590	    * OPTIMIZE TODO: We could map types already evaluated
24591	    * to be validly derived from other types to avoid checking
24592	    * this over and over for the same types.
24593	    */
24594	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24595		(elemDecl->subtypes->flags &
24596		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24597		set |= SUBSET_EXTENSION;
24598
24599	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24600		(elemDecl->subtypes->flags &
24601		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24602		set |= SUBSET_RESTRICTION;
24603
24604	    /*
24605	    * REMOVED and CHANGED since this produced a parser context
24606	    * which adds to the string dict of the schema. So this would
24607	    * change the schema and we don't want this. We don't need
24608	    * the parser context anymore.
24609	    *
24610	    * if ((vctxt->pctxt == NULL) &&
24611	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24612	    *	    return (-1);
24613	    */
24614
24615	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24616		elemDecl->subtypes, set) != 0) {
24617		xmlChar *str = NULL;
24618
24619		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24620		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24621		    "The type definition '%s', specified by xsi:type, is "
24622		    "blocked or not validly derived from the type definition "
24623		    "of the element declaration",
24624		    xmlSchemaFormatQName(&str,
24625			(*localType)->targetNamespace,
24626			(*localType)->name),
24627		    NULL);
24628		FREE_AND_NULL(str);
24629		ret = vctxt->err;
24630		*localType = NULL;
24631	    }
24632	}
24633    }
24634exit:
24635    ACTIVATE_ELEM;
24636    return (ret);
24637internal_error:
24638    ACTIVATE_ELEM;
24639    return (-1);
24640}
24641
24642static int
24643xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24644{
24645    xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24646    xmlSchemaTypePtr actualType;
24647
24648    /*
24649    * cvc-elt (3.3.4) : 1
24650    */
24651    if (elemDecl == NULL) {
24652	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24653	    "No matching declaration available");
24654        return (vctxt->err);
24655    }
24656    actualType = WXS_ELEM_TYPEDEF(elemDecl);
24657    /*
24658    * cvc-elt (3.3.4) : 2
24659    */
24660    if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24661	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24662	    "The element declaration is abstract");
24663        return (vctxt->err);
24664    }
24665    if (actualType == NULL) {
24666    	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24667    	    "The type definition is absent");
24668    	return (XML_SCHEMAV_CVC_TYPE_1);
24669    }
24670    if (vctxt->nbAttrInfos != 0) {
24671	int ret;
24672	xmlSchemaAttrInfoPtr iattr;
24673	/*
24674	* cvc-elt (3.3.4) : 3
24675	* Handle 'xsi:nil'.
24676	*/
24677	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24678	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24679	if (iattr) {
24680	    ACTIVATE_ATTRIBUTE(iattr);
24681	    /*
24682	    * Validate the value.
24683	    */
24684	    ret = xmlSchemaVCheckCVCSimpleType(
24685		ACTXT_CAST vctxt, NULL,
24686		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24687		iattr->value, &(iattr->val), 1, 0, 0);
24688	    ACTIVATE_ELEM;
24689	    if (ret < 0) {
24690		VERROR_INT("xmlSchemaValidateElemDecl",
24691		    "calling xmlSchemaVCheckCVCSimpleType() to "
24692		    "validate the attribute 'xsi:nil'");
24693		return (-1);
24694	    }
24695	    if (ret == 0) {
24696		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24697		    /*
24698		    * cvc-elt (3.3.4) : 3.1
24699		    */
24700		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24701			"The element is not 'nillable'");
24702		    /* Does not return an error on purpose. */
24703		} else {
24704		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24705			/*
24706			* cvc-elt (3.3.4) : 3.2.2
24707			*/
24708			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24709			    (elemDecl->value != NULL)) {
24710			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24711				"The element cannot be 'nilled' because "
24712				"there is a fixed value constraint defined "
24713				"for it");
24714			     /* Does not return an error on purpose. */
24715			} else
24716			    vctxt->inode->flags |=
24717				XML_SCHEMA_ELEM_INFO_NILLED;
24718		    }
24719		}
24720	    }
24721	}
24722	/*
24723	* cvc-elt (3.3.4) : 4
24724	* Handle 'xsi:type'.
24725	*/
24726	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24727	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24728	if (iattr) {
24729	    xmlSchemaTypePtr localType = NULL;
24730
24731	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24732		elemDecl);
24733	    if (ret != 0) {
24734		if (ret == -1) {
24735		    VERROR_INT("xmlSchemaValidateElemDecl",
24736			"calling xmlSchemaProcessXSIType() to "
24737			"process the attribute 'xsi:type'");
24738		    return (-1);
24739		}
24740		/* Does not return an error on purpose. */
24741	    }
24742	    if (localType != NULL) {
24743		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24744		actualType = localType;
24745	    }
24746	}
24747    }
24748    /*
24749    * IDC: Register identity-constraint XPath matchers.
24750    */
24751    if ((elemDecl->idcs != NULL) &&
24752	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24753	    return (-1);
24754    /*
24755    * No actual type definition.
24756    */
24757    if (actualType == NULL) {
24758    	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24759    	    "The type definition is absent");
24760    	return (XML_SCHEMAV_CVC_TYPE_1);
24761    }
24762    /*
24763    * Remember the actual type definition.
24764    */
24765    vctxt->inode->typeDef = actualType;
24766
24767    return (0);
24768}
24769
24770static int
24771xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
24772{
24773    xmlSchemaAttrInfoPtr iattr;
24774    int ret = 0, i;
24775
24776    /*
24777    * SPEC cvc-type (3.1.1)
24778    * "The attributes of must be empty, excepting those whose namespace
24779    * name is identical to http://www.w3.org/2001/XMLSchema-instance and
24780    * whose local name is one of type, nil, schemaLocation or
24781    * noNamespaceSchemaLocation."
24782    */
24783    if (vctxt->nbAttrInfos == 0)
24784	return (0);
24785    for (i = 0; i < vctxt->nbAttrInfos; i++) {
24786	iattr = vctxt->attrInfos[i];
24787	if (! iattr->metaType) {
24788	    ACTIVATE_ATTRIBUTE(iattr)
24789	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
24790		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
24791	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
24792        }
24793    }
24794    ACTIVATE_ELEM
24795    return (ret);
24796}
24797
24798/*
24799* Cleanup currently used attribute infos.
24800*/
24801static void
24802xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
24803{
24804    int i;
24805    xmlSchemaAttrInfoPtr attr;
24806
24807    if (vctxt->nbAttrInfos == 0)
24808	return;
24809    for (i = 0; i < vctxt->nbAttrInfos; i++) {
24810	attr = vctxt->attrInfos[i];
24811	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24812	    if (attr->localName != NULL)
24813		xmlFree((xmlChar *) attr->localName);
24814	    if (attr->nsName != NULL)
24815		xmlFree((xmlChar *) attr->nsName);
24816	}
24817	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24818	    if (attr->value != NULL)
24819		xmlFree((xmlChar *) attr->value);
24820	}
24821	if (attr->val != NULL) {
24822	    xmlSchemaFreeValue(attr->val);
24823	    attr->val = NULL;
24824	}
24825	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
24826    }
24827    vctxt->nbAttrInfos = 0;
24828}
24829
24830/*
24831* 3.4.4 Complex Type Definition Validation Rules
24832*   Element Locally Valid (Complex Type) (cvc-complex-type)
24833* 3.2.4 Attribute Declaration Validation Rules
24834*   Validation Rule: Attribute Locally Valid (cvc-attribute)
24835*   Attribute Locally Valid (Use) (cvc-au)
24836*
24837* Only "assessed" attribute information items will be visible to
24838* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
24839*/
24840static int
24841xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
24842{
24843    xmlSchemaTypePtr type = vctxt->inode->typeDef;
24844    xmlSchemaItemListPtr attrUseList;
24845    xmlSchemaAttributeUsePtr attrUse = NULL;
24846    xmlSchemaAttributePtr attrDecl = NULL;
24847    xmlSchemaAttrInfoPtr iattr, tmpiattr;
24848    int i, j, found, nbAttrs, nbUses;
24849    int xpathRes = 0, res, wildIDs = 0, fixed;
24850    xmlNodePtr defAttrOwnerElem = NULL;
24851
24852    /*
24853    * SPEC (cvc-attribute)
24854    * (1) "The declaration must not be �absent� (see Missing
24855    * Sub-components (�5.3) for how this can fail to be
24856    * the case)."
24857    * (2) "Its {type definition} must not be absent."
24858    *
24859    * NOTE (1) + (2): This is not handled here, since we currently do not
24860    * allow validation against schemas which have missing sub-components.
24861    *
24862    * SPEC (cvc-complex-type)
24863    * (3) "For each attribute information item in the element information
24864    * item's [attributes] excepting those whose [namespace name] is
24865    * identical to http://www.w3.org/2001/XMLSchema-instance and whose
24866    * [local name] is one of type, nil, schemaLocation or
24867    * noNamespaceSchemaLocation, the appropriate case among the following
24868    * must be true:
24869    *
24870    */
24871    attrUseList = (xmlSchemaItemListPtr) type->attrUses;
24872    /*
24873    * @nbAttrs is the number of attributes present in the instance.
24874    */
24875    nbAttrs = vctxt->nbAttrInfos;
24876    if (attrUseList != NULL)
24877	nbUses = attrUseList->nbItems;
24878    else
24879	nbUses = 0;
24880    for (i = 0; i < nbUses; i++) {
24881        found = 0;
24882	attrUse = attrUseList->items[i];
24883	attrDecl = WXS_ATTRUSE_DECL(attrUse);
24884        for (j = 0; j < nbAttrs; j++) {
24885	    iattr = vctxt->attrInfos[j];
24886	    /*
24887	    * SPEC (cvc-complex-type) (3)
24888	    * Skip meta attributes.
24889	    */
24890	    if (iattr->metaType)
24891		continue;
24892	    if (iattr->localName[0] != attrDecl->name[0])
24893		continue;
24894	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
24895		continue;
24896	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
24897		continue;
24898	    found = 1;
24899	    /*
24900	    * SPEC (cvc-complex-type)
24901	    * (3.1) "If there is among the {attribute uses} an attribute
24902	    * use with an {attribute declaration} whose {name} matches
24903	    * the attribute information item's [local name] and whose
24904	    * {target namespace} is identical to the attribute information
24905	    * item's [namespace name] (where an �absent� {target namespace}
24906	    * is taken to be identical to a [namespace name] with no value),
24907	    * then the attribute information must be �valid� with respect
24908	    * to that attribute use as per Attribute Locally Valid (Use)
24909	    * (�3.5.4). In this case the {attribute declaration} of that
24910	    * attribute use is the �context-determined declaration� for the
24911	    * attribute information item with respect to Schema-Validity
24912	    * Assessment (Attribute) (�3.2.4) and
24913	    * Assessment Outcome (Attribute) (�3.2.5).
24914	    */
24915	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
24916	    iattr->use = attrUse;
24917	    /*
24918	    * Context-determined declaration.
24919	    */
24920	    iattr->decl = attrDecl;
24921	    iattr->typeDef = attrDecl->subtypes;
24922	    break;
24923	}
24924
24925	if (found)
24926	    continue;
24927
24928	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
24929	    /*
24930	    * Handle non-existent, required attributes.
24931	    *
24932	    * SPEC (cvc-complex-type)
24933	    * (4) "The {attribute declaration} of each attribute use in
24934	    * the {attribute uses} whose {required} is true matches one
24935	    * of the attribute information items in the element information
24936	    * item's [attributes] as per clause 3.1 above."
24937	    */
24938	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24939	    if (tmpiattr == NULL) {
24940		VERROR_INT(
24941		    "xmlSchemaVAttributesComplex",
24942		    "calling xmlSchemaGetFreshAttrInfo()");
24943		return (-1);
24944	    }
24945	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
24946	    tmpiattr->use = attrUse;
24947	    tmpiattr->decl = attrDecl;
24948	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
24949	    ((attrUse->defValue != NULL) ||
24950	     (attrDecl->defValue != NULL))) {
24951	    /*
24952	    * Handle non-existent, optional, default/fixed attributes.
24953	    */
24954	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
24955	    if (tmpiattr == NULL) {
24956		VERROR_INT(
24957		    "xmlSchemaVAttributesComplex",
24958		    "calling xmlSchemaGetFreshAttrInfo()");
24959		return (-1);
24960	    }
24961	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
24962	    tmpiattr->use = attrUse;
24963	    tmpiattr->decl = attrDecl;
24964	    tmpiattr->typeDef = attrDecl->subtypes;
24965	    tmpiattr->localName = attrDecl->name;
24966	    tmpiattr->nsName = attrDecl->targetNamespace;
24967	}
24968    }
24969
24970    if (vctxt->nbAttrInfos == 0)
24971	return (0);
24972    nbUses = vctxt->nbAttrInfos;
24973    /*
24974    * Validate against the wildcard.
24975    */
24976    if (type->attributeWildcard != NULL) {
24977	/*
24978	* SPEC (cvc-complex-type)
24979	* (3.2.1) "There must be an {attribute wildcard}."
24980	*/
24981	for (i = 0; i < nbAttrs; i++) {
24982	    iattr = vctxt->attrInfos[i];
24983	    /*
24984	    * SPEC (cvc-complex-type) (3)
24985	    * Skip meta attributes.
24986	    */
24987	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
24988		continue;
24989	    /*
24990	    * SPEC (cvc-complex-type)
24991	    * (3.2.2) "The attribute information item must be �valid� with
24992	    * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
24993	    *
24994	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
24995	    * "... its [namespace name] must be �valid� with respect to
24996	    * the wildcard constraint, as defined in Wildcard allows
24997	    * Namespace Name (�3.10.4)."
24998	    */
24999	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25000		    iattr->nsName) == 0) {
25001		/*
25002		* Handle processContents.
25003		*
25004		* SPEC (cvc-wildcard):
25005		* processContents | context-determined declaration:
25006		* "strict"          "mustFind"
25007		* "lax"             "none"
25008		* "skip"            "skip"
25009		*/
25010		if (type->attributeWildcard->processContents ==
25011		    XML_SCHEMAS_ANY_SKIP) {
25012		     /*
25013		    * context-determined declaration = "skip"
25014		    *
25015		    * SPEC PSVI Assessment Outcome (Attribute)
25016		    * [validity] = "notKnown"
25017		    * [validation attempted] = "none"
25018		    */
25019		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25020		    continue;
25021		}
25022		/*
25023		* Find an attribute declaration.
25024		*/
25025		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25026		    iattr->localName, iattr->nsName);
25027		if (iattr->decl != NULL) {
25028		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25029		    /*
25030		    * SPEC (cvc-complex-type)
25031		    * (5) "Let [Definition:]  the wild IDs be the set of
25032		    * all attribute information item to which clause 3.2
25033		    * applied and whose �validation� resulted in a
25034		    * �context-determined declaration� of mustFind or no
25035		    * �context-determined declaration� at all, and whose
25036		    * [local name] and [namespace name] resolve (as
25037		    * defined by QName resolution (Instance) (�3.15.4)) to
25038		    * an attribute declaration whose {type definition} is
25039		    * or is derived from ID. Then all of the following
25040		    * must be true:"
25041		    */
25042		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25043		    if (xmlSchemaIsDerivedFromBuiltInType(
25044			iattr->typeDef, XML_SCHEMAS_ID)) {
25045			/*
25046			* SPEC (5.1) "There must be no more than one
25047			* item in �wild IDs�."
25048			*/
25049			if (wildIDs != 0) {
25050			    /* VAL TODO */
25051			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25052			    TODO
25053			    continue;
25054			}
25055			wildIDs++;
25056			/*
25057			* SPEC (cvc-complex-type)
25058			* (5.2) "If �wild IDs� is non-empty, there must not
25059			* be any attribute uses among the {attribute uses}
25060			* whose {attribute declaration}'s {type definition}
25061			* is or is derived from ID."
25062			*/
25063			for (j = 0; j < attrUseList->nbItems; j++) {
25064			    if (xmlSchemaIsDerivedFromBuiltInType(
25065				WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25066				XML_SCHEMAS_ID)) {
25067				/* URGENT VAL TODO: implement */
25068				iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25069				TODO
25070				break;
25071			    }
25072			}
25073		    }
25074		} else if (type->attributeWildcard->processContents ==
25075		    XML_SCHEMAS_ANY_LAX) {
25076		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25077		    /*
25078		    * SPEC PSVI Assessment Outcome (Attribute)
25079		    * [validity] = "notKnown"
25080		    * [validation attempted] = "none"
25081		    */
25082		} else {
25083		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25084		}
25085	    }
25086	}
25087    }
25088
25089    if (vctxt->nbAttrInfos == 0)
25090	return (0);
25091
25092    /*
25093    * Get the owner element; needed for creation of default attributes.
25094    * This fixes bug #341337, reported by David Grohmann.
25095    */
25096    if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25097	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25098	if (ielem && ielem->node && ielem->node->doc)
25099	    defAttrOwnerElem = ielem->node;
25100    }
25101    /*
25102    * Validate values, create default attributes, evaluate IDCs.
25103    */
25104    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25105	iattr = vctxt->attrInfos[i];
25106	/*
25107	* VAL TODO: Note that we won't try to resolve IDCs to
25108	* "lax" and "skip" validated attributes. Check what to
25109	* do in this case.
25110	*/
25111	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25112	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25113	    continue;
25114	/*
25115	* VAL TODO: What to do if the type definition is missing?
25116	*/
25117	if (iattr->typeDef == NULL) {
25118	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25119	    continue;
25120	}
25121
25122	ACTIVATE_ATTRIBUTE(iattr);
25123	fixed = 0;
25124	xpathRes = 0;
25125
25126	if (vctxt->xpathStates != NULL) {
25127	    /*
25128	    * Evaluate IDCs.
25129	    */
25130	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25131		XML_ATTRIBUTE_NODE);
25132	    if (xpathRes == -1) {
25133		VERROR_INT("xmlSchemaVAttributesComplex",
25134		    "calling xmlSchemaXPathEvaluate()");
25135		goto internal_error;
25136	    }
25137	}
25138
25139	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25140	    /*
25141	    * Default/fixed attributes.
25142	    * We need the value only if we need to resolve IDCs or
25143	    * will create default attributes.
25144	    */
25145	    if ((xpathRes) || (defAttrOwnerElem)) {
25146		if (iattr->use->defValue != NULL) {
25147		    iattr->value = (xmlChar *) iattr->use->defValue;
25148		    iattr->val = iattr->use->defVal;
25149		} else {
25150		    iattr->value = (xmlChar *) iattr->decl->defValue;
25151		    iattr->val = iattr->decl->defVal;
25152		}
25153		/*
25154		* IDCs will consume the precomputed default value,
25155		* so we need to clone it.
25156		*/
25157		if (iattr->val == NULL) {
25158		    VERROR_INT("xmlSchemaVAttributesComplex",
25159			"default/fixed value on an attribute use was "
25160			"not precomputed");
25161		    goto internal_error;
25162		}
25163		iattr->val = xmlSchemaCopyValue(iattr->val);
25164		if (iattr->val == NULL) {
25165		    VERROR_INT("xmlSchemaVAttributesComplex",
25166			"calling xmlSchemaCopyValue()");
25167		    goto internal_error;
25168		}
25169	    }
25170	    /*
25171	    * PSVI: Add the default attribute to the current element.
25172	    * VAL TODO: Should we use the *normalized* value? This currently
25173	    *   uses the *initial* value.
25174	    */
25175
25176	    if (defAttrOwnerElem) {
25177		xmlChar *normValue;
25178		const xmlChar *value;
25179
25180		value = iattr->value;
25181		/*
25182		* Normalize the value.
25183		*/
25184		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25185		    iattr->value);
25186		if (normValue != NULL)
25187		    value = BAD_CAST normValue;
25188
25189		if (iattr->nsName == NULL) {
25190		    if (xmlNewProp(defAttrOwnerElem,
25191			iattr->localName, value) == NULL) {
25192			VERROR_INT("xmlSchemaVAttributesComplex",
25193			    "callling xmlNewProp()");
25194			if (normValue != NULL)
25195			    xmlFree(normValue);
25196			goto internal_error;
25197		    }
25198		} else {
25199		    xmlNsPtr ns;
25200
25201		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25202			defAttrOwnerElem, iattr->nsName);
25203		    if (ns == NULL) {
25204			xmlChar prefix[12];
25205			int counter = 0;
25206
25207			/*
25208			* Create a namespace declaration on the validation
25209			* root node if no namespace declaration is in scope.
25210			*/
25211			do {
25212			    snprintf((char *) prefix, 12, "p%d", counter++);
25213			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25214				defAttrOwnerElem, BAD_CAST prefix);
25215			    if (counter > 1000) {
25216				VERROR_INT(
25217				    "xmlSchemaVAttributesComplex",
25218				    "could not compute a ns prefix for a "
25219				    "default/fixed attribute");
25220				if (normValue != NULL)
25221				    xmlFree(normValue);
25222				goto internal_error;
25223			    }
25224			} while (ns != NULL);
25225			ns = xmlNewNs(vctxt->validationRoot,
25226			    iattr->nsName, BAD_CAST prefix);
25227		    }
25228		    /*
25229		    * TODO:
25230		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25231		    * If we have QNames: do we need to ensure there's a
25232		    * prefix defined for the QName?
25233		    */
25234		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25235		}
25236		if (normValue != NULL)
25237		    xmlFree(normValue);
25238	    }
25239	    /*
25240	    * Go directly to IDC evaluation.
25241	    */
25242	    goto eval_idcs;
25243	}
25244	/*
25245	* Validate the value.
25246	*/
25247	if (vctxt->value != NULL) {
25248	    /*
25249	    * Free last computed value; just for safety reasons.
25250	    */
25251	    xmlSchemaFreeValue(vctxt->value);
25252	    vctxt->value = NULL;
25253	}
25254	/*
25255	* Note that the attribute *use* can be unavailable, if
25256	* the attribute was a wild attribute.
25257	*/
25258	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25259	    ((iattr->use != NULL) &&
25260	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25261	    fixed = 1;
25262	else
25263	    fixed = 0;
25264	/*
25265	* SPEC (cvc-attribute)
25266	* (3) "The item's �normalized value� must be locally �valid�
25267	* with respect to that {type definition} as per
25268	* String Valid (�3.14.4)."
25269	*
25270	* VAL TODO: Do we already have the
25271	* "normalized attribute value" here?
25272	*/
25273	if (xpathRes || fixed) {
25274	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25275	    /*
25276	    * Request a computed value.
25277	    */
25278	    res = xmlSchemaVCheckCVCSimpleType(
25279		ACTXT_CAST vctxt,
25280		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25281		1, 1, 0);
25282	} else {
25283	    res = xmlSchemaVCheckCVCSimpleType(
25284		ACTXT_CAST vctxt,
25285		iattr->node, iattr->typeDef, iattr->value, NULL,
25286		1, 0, 0);
25287	}
25288
25289	if (res != 0) {
25290	    if (res == -1) {
25291		VERROR_INT("xmlSchemaVAttributesComplex",
25292		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25293		goto internal_error;
25294	    }
25295	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25296	    /*
25297	    * SPEC PSVI Assessment Outcome (Attribute)
25298	    * [validity] = "invalid"
25299	    */
25300	    goto eval_idcs;
25301	}
25302
25303	if (fixed) {
25304	    /*
25305	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25306	    * "For an attribute information item to be�valid�
25307	    * with respect to an attribute use its *normalized*
25308	    * value� must match the *canonical* lexical
25309	    * representation of the attribute use's {value
25310	    * constraint}value, if it is present and fixed."
25311	    *
25312	    * VAL TODO: The requirement for the *canonical* value
25313	    * will be removed in XML Schema 1.1.
25314	    */
25315	    /*
25316	    * SPEC Attribute Locally Valid (cvc-attribute)
25317	    * (4) "The item's *actual* value� must match the *value* of
25318	    * the {value constraint}, if it is present and fixed."
25319	    */
25320	    if (iattr->val == NULL) {
25321		/* VAL TODO: A value was not precomputed. */
25322		TODO
25323		goto eval_idcs;
25324	    }
25325	    if ((iattr->use != NULL) &&
25326		(iattr->use->defValue != NULL)) {
25327		if (iattr->use->defVal == NULL) {
25328		    /* VAL TODO: A default value was not precomputed. */
25329		    TODO
25330		    goto eval_idcs;
25331		}
25332		iattr->vcValue = iattr->use->defValue;
25333		/*
25334		if (xmlSchemaCompareValuesWhtsp(attr->val,
25335		    (xmlSchemaWhitespaceValueType) ws,
25336		    attr->use->defVal,
25337		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25338		*/
25339		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25340		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25341	    } else {
25342		if (iattr->decl->defVal == NULL) {
25343		    /* VAL TODO: A default value was not precomputed. */
25344		    TODO
25345		    goto eval_idcs;
25346		}
25347		iattr->vcValue = iattr->decl->defValue;
25348		/*
25349		if (xmlSchemaCompareValuesWhtsp(attr->val,
25350		    (xmlSchemaWhitespaceValueType) ws,
25351		    attrDecl->defVal,
25352		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25353		*/
25354		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25355		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25356	    }
25357	    /*
25358	    * [validity] = "valid"
25359	    */
25360	}
25361eval_idcs:
25362	/*
25363	* Evaluate IDCs.
25364	*/
25365	if (xpathRes) {
25366	    if (xmlSchemaXPathProcessHistory(vctxt,
25367		vctxt->depth +1) == -1) {
25368		VERROR_INT("xmlSchemaVAttributesComplex",
25369		    "calling xmlSchemaXPathEvaluate()");
25370		goto internal_error;
25371	    }
25372	} else if (vctxt->xpathStates != NULL)
25373	    xmlSchemaXPathPop(vctxt);
25374    }
25375
25376    /*
25377    * Report errors.
25378    */
25379    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25380	iattr = vctxt->attrInfos[i];
25381	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25382	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25383	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25384	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25385	    continue;
25386	ACTIVATE_ATTRIBUTE(iattr);
25387	switch (iattr->state) {
25388	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25389		    xmlChar *str = NULL;
25390		    ACTIVATE_ELEM;
25391		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25392			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25393			"The attribute '%s' is required but missing",
25394			xmlSchemaFormatQName(&str,
25395			    iattr->decl->targetNamespace,
25396			    iattr->decl->name),
25397			NULL);
25398		    FREE_AND_NULL(str)
25399		    break;
25400		}
25401	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25402		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25403		    "The type definition is absent");
25404		break;
25405	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25406		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25407		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25408		    "The value '%s' does not match the fixed "
25409		    "value constraint '%s'",
25410		    iattr->value, iattr->vcValue);
25411		break;
25412	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25413		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25414		    "No matching global attribute declaration available, but "
25415		    "demanded by the strict wildcard");
25416		break;
25417	    case XML_SCHEMAS_ATTR_UNKNOWN:
25418		if (iattr->metaType)
25419		    break;
25420		/*
25421		* MAYBE VAL TODO: One might report different error messages
25422		* for the following errors.
25423		*/
25424		if (type->attributeWildcard == NULL) {
25425		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25426			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25427		} else {
25428		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25429			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25430		}
25431		break;
25432	    default:
25433		break;
25434	}
25435    }
25436
25437    ACTIVATE_ELEM;
25438    return (0);
25439internal_error:
25440    ACTIVATE_ELEM;
25441    return (-1);
25442}
25443
25444static int
25445xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25446			      int *skip)
25447{
25448    xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25449    /*
25450    * The namespace of the element was already identified to be
25451    * matching the wildcard.
25452    */
25453    if ((skip == NULL) || (wild == NULL) ||
25454	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25455	VERROR_INT("xmlSchemaValidateElemWildcard",
25456	    "bad arguments");
25457	return (-1);
25458    }
25459    *skip = 0;
25460    if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25461	/*
25462	* URGENT VAL TODO: Either we need to position the stream to the
25463	* next sibling, or walk the whole subtree.
25464	*/
25465	*skip = 1;
25466	return (0);
25467    }
25468    {
25469	xmlSchemaElementPtr decl = NULL;
25470
25471	decl = xmlSchemaGetElem(vctxt->schema,
25472	    vctxt->inode->localName, vctxt->inode->nsName);
25473	if (decl != NULL) {
25474	    vctxt->inode->decl = decl;
25475	    return (0);
25476	}
25477    }
25478    if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25479	/* VAL TODO: Change to proper error code. */
25480	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25481	    "No matching global element declaration available, but "
25482	    "demanded by the strict wildcard");
25483	return (vctxt->err);
25484    }
25485    if (vctxt->nbAttrInfos != 0) {
25486	xmlSchemaAttrInfoPtr iattr;
25487	/*
25488	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25489	* (1.2.1.2.1) - (1.2.1.2.3 )
25490	*
25491	* Use the xsi:type attribute for the type definition.
25492	*/
25493	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25494	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25495	if (iattr != NULL) {
25496	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25497		&(vctxt->inode->typeDef), NULL) == -1) {
25498		VERROR_INT("xmlSchemaValidateElemWildcard",
25499		    "calling xmlSchemaProcessXSIType() to "
25500		    "process the attribute 'xsi:nil'");
25501		return (-1);
25502	    }
25503	    /*
25504	    * Don't return an error on purpose.
25505	    */
25506	    return (0);
25507	}
25508    }
25509    /*
25510    * SPEC Validation Rule: Schema-Validity Assessment (Element)
25511    *
25512    * Fallback to "anyType".
25513    */
25514    vctxt->inode->typeDef =
25515	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25516    return (0);
25517}
25518
25519/*
25520* xmlSchemaCheckCOSValidDefault:
25521*
25522* This will be called if: not nilled, no content and a default/fixed
25523* value is provided.
25524*/
25525
25526static int
25527xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25528			      const xmlChar *value,
25529			      xmlSchemaValPtr *val)
25530{
25531    int ret = 0;
25532    xmlSchemaNodeInfoPtr inode = vctxt->inode;
25533
25534    /*
25535    * cos-valid-default:
25536    * Schema Component Constraint: Element Default Valid (Immediate)
25537    * For a string to be a valid default with respect to a type
25538    * definition the appropriate case among the following must be true:
25539    */
25540    if WXS_IS_COMPLEX(inode->typeDef) {
25541	/*
25542	* Complex type.
25543	*
25544	* SPEC (2.1) "its {content type} must be a simple type definition
25545	* or mixed."
25546	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25547	* type}'s particle must be �emptiable� as defined by
25548	* Particle Emptiable (�3.9.6)."
25549	*/
25550	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25551	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25552	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25553	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25554	    /* NOTE that this covers (2.2.2) as well. */
25555	    VERROR(ret, NULL,
25556		"For a string to be a valid default, the type definition "
25557		"must be a simple type or a complex type with simple content "
25558		"or mixed content and a particle emptiable");
25559	    return(ret);
25560	}
25561    }
25562    /*
25563    * 1 If the type definition is a simple type definition, then the string
25564    * must be �valid� with respect to that definition as defined by String
25565    * Valid (�3.14.4).
25566    *
25567    * AND
25568    *
25569    * 2.2.1 If the {content type} is a simple type definition, then the
25570    * string must be �valid� with respect to that simple type definition
25571    * as defined by String Valid (�3.14.4).
25572    */
25573    if (WXS_IS_SIMPLE(inode->typeDef)) {
25574
25575	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25576	    NULL, inode->typeDef, value, val, 1, 1, 0);
25577
25578    } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25579
25580	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25581	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25582    }
25583    if (ret < 0) {
25584	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25585	    "calling xmlSchemaVCheckCVCSimpleType()");
25586    }
25587    return (ret);
25588}
25589
25590static void
25591xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25592			       const xmlChar * name ATTRIBUTE_UNUSED,
25593			       xmlSchemaElementPtr item,
25594			       xmlSchemaNodeInfoPtr inode)
25595{
25596    inode->decl = item;
25597#ifdef DEBUG_CONTENT
25598    {
25599	xmlChar *str = NULL;
25600
25601	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25602	    xmlGenericError(xmlGenericErrorContext,
25603		"AUTOMATON callback for '%s' [declaration]\n",
25604		xmlSchemaFormatQName(&str,
25605		inode->localName, inode->nsName));
25606	} else {
25607	    xmlGenericError(xmlGenericErrorContext,
25608		    "AUTOMATON callback for '%s' [wildcard]\n",
25609		    xmlSchemaFormatQName(&str,
25610		    inode->localName, inode->nsName));
25611
25612	}
25613	FREE_AND_NULL(str)
25614    }
25615#endif
25616}
25617
25618static int
25619xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25620{
25621    vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25622    if (vctxt->inode == NULL) {
25623	VERROR_INT("xmlSchemaValidatorPushElem",
25624	    "calling xmlSchemaGetFreshElemInfo()");
25625	return (-1);
25626    }
25627    vctxt->nbAttrInfos = 0;
25628    return (0);
25629}
25630
25631static int
25632xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25633			     xmlSchemaNodeInfoPtr inode,
25634			     xmlSchemaTypePtr type,
25635			     const xmlChar *value)
25636{
25637    if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25638	return (xmlSchemaVCheckCVCSimpleType(
25639	    ACTXT_CAST vctxt, NULL,
25640	    type, value, &(inode->val), 1, 1, 0));
25641    else
25642	return (xmlSchemaVCheckCVCSimpleType(
25643	    ACTXT_CAST vctxt, NULL,
25644	    type, value, NULL, 1, 0, 0));
25645}
25646
25647
25648
25649/*
25650* Process END of element.
25651*/
25652static int
25653xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25654{
25655    int ret = 0;
25656    xmlSchemaNodeInfoPtr inode = vctxt->inode;
25657
25658    if (vctxt->nbAttrInfos != 0)
25659	xmlSchemaClearAttrInfos(vctxt);
25660    if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25661	/*
25662	* This element was not expected;
25663	* we will not validate child elements of broken parents.
25664	* Skip validation of all content of the parent.
25665	*/
25666	vctxt->skipDepth = vctxt->depth -1;
25667	goto end_elem;
25668    }
25669    if ((inode->typeDef == NULL) ||
25670	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25671	/*
25672	* 1. the type definition might be missing if the element was
25673	*    error prone
25674	* 2. it might be abstract.
25675	*/
25676	goto end_elem;
25677    }
25678    /*
25679    * Check the content model.
25680    */
25681    if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25682	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25683
25684	/*
25685	* Workaround for "anyType".
25686	*/
25687	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25688	    goto character_content;
25689
25690	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25691	    xmlChar *values[10];
25692	    int terminal, nbval = 10, nbneg;
25693
25694	    if (inode->regexCtxt == NULL) {
25695		/*
25696		* Create the regex context.
25697		*/
25698		inode->regexCtxt =
25699		    xmlRegNewExecCtxt(inode->typeDef->contModel,
25700		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25701		    vctxt);
25702		if (inode->regexCtxt == NULL) {
25703		    VERROR_INT("xmlSchemaValidatorPopElem",
25704			"failed to create a regex context");
25705		    goto internal_error;
25706		}
25707#ifdef DEBUG_AUTOMATA
25708		xmlGenericError(xmlGenericErrorContext,
25709		    "AUTOMATON create on '%s'\n", inode->localName);
25710#endif
25711	    }
25712	    /*
25713	    * Get hold of the still expected content, since a further
25714	    * call to xmlRegExecPushString() will loose this information.
25715	    */
25716	    xmlRegExecNextValues(inode->regexCtxt,
25717		&nbval, &nbneg, &values[0], &terminal);
25718	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25719	    if (ret <= 0) {
25720		/*
25721		* Still missing something.
25722		*/
25723		ret = 1;
25724		inode->flags |=
25725		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
25726		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
25727		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25728		    "Missing child element(s)",
25729		    nbval, nbneg, values);
25730#ifdef DEBUG_AUTOMATA
25731		xmlGenericError(xmlGenericErrorContext,
25732		    "AUTOMATON missing ERROR on '%s'\n",
25733		    inode->localName);
25734#endif
25735	    } else {
25736		/*
25737		* Content model is satisfied.
25738		*/
25739		ret = 0;
25740#ifdef DEBUG_AUTOMATA
25741		xmlGenericError(xmlGenericErrorContext,
25742		    "AUTOMATON succeeded on '%s'\n",
25743		    inode->localName);
25744#endif
25745	    }
25746
25747	}
25748    }
25749    if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25750	goto end_elem;
25751
25752character_content:
25753
25754    if (vctxt->value != NULL) {
25755	xmlSchemaFreeValue(vctxt->value);
25756	vctxt->value = NULL;
25757    }
25758    /*
25759    * Check character content.
25760    */
25761    if (inode->decl == NULL) {
25762	/*
25763	* Speedup if no declaration exists.
25764	*/
25765	if (WXS_IS_SIMPLE(inode->typeDef)) {
25766	    ret = xmlSchemaVCheckINodeDataType(vctxt,
25767		inode, inode->typeDef, inode->value);
25768	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25769	    ret = xmlSchemaVCheckINodeDataType(vctxt,
25770		inode, inode->typeDef->contentTypeDef,
25771		inode->value);
25772	}
25773	if (ret < 0) {
25774	    VERROR_INT("xmlSchemaValidatorPopElem",
25775		"calling xmlSchemaVCheckCVCSimpleType()");
25776	    goto internal_error;
25777	}
25778	goto end_elem;
25779    }
25780    /*
25781    * cvc-elt (3.3.4) : 5
25782    * The appropriate case among the following must be true:
25783    */
25784    /*
25785    * cvc-elt (3.3.4) : 5.1
25786    * If the declaration has a {value constraint},
25787    * the item has neither element nor character [children] and
25788    * clause 3.2 has not applied, then all of the following must be true:
25789    */
25790    if ((inode->decl->value != NULL) &&
25791	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
25792	(! INODE_NILLED(inode))) {
25793	/*
25794	* cvc-elt (3.3.4) : 5.1.1
25795	* If the �actual type definition� is a �local type definition�
25796	* then the canonical lexical representation of the {value constraint}
25797	* value must be a valid default for the �actual type definition� as
25798	* defined in Element Default Valid (Immediate) (�3.3.6).
25799	*/
25800	/*
25801	* NOTE: 'local' above means types acquired by xsi:type.
25802	* NOTE: Although the *canonical* value is stated, it is not
25803	* relevant if canonical or not. Additionally XML Schema 1.1
25804	* will removed this requirement as well.
25805	*/
25806	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
25807
25808	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
25809		inode->decl->value, &(inode->val));
25810	    if (ret != 0) {
25811		if (ret < 0) {
25812		    VERROR_INT("xmlSchemaValidatorPopElem",
25813			"calling xmlSchemaCheckCOSValidDefault()");
25814		    goto internal_error;
25815		}
25816		goto end_elem;
25817	    }
25818	    /*
25819	    * Stop here, to avoid redundant validation of the value
25820	    * (see following).
25821	    */
25822	    goto default_psvi;
25823	}
25824	/*
25825	* cvc-elt (3.3.4) : 5.1.2
25826	* The element information item with the canonical lexical
25827	* representation of the {value constraint} value used as its
25828	* �normalized value� must be �valid� with respect to the
25829	* �actual type definition� as defined by Element Locally Valid (Type)
25830	* (�3.3.4).
25831	*/
25832	if (WXS_IS_SIMPLE(inode->typeDef)) {
25833	    ret = xmlSchemaVCheckINodeDataType(vctxt,
25834		inode, inode->typeDef, inode->decl->value);
25835	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25836	    ret = xmlSchemaVCheckINodeDataType(vctxt,
25837		inode, inode->typeDef->contentTypeDef,
25838		inode->decl->value);
25839	}
25840	if (ret != 0) {
25841	    if (ret < 0) {
25842		VERROR_INT("xmlSchemaValidatorPopElem",
25843		    "calling xmlSchemaVCheckCVCSimpleType()");
25844		goto internal_error;
25845	    }
25846	    goto end_elem;
25847	}
25848
25849default_psvi:
25850	/*
25851	* PSVI: Create a text node on the instance element.
25852	*/
25853	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
25854	    (inode->node != NULL)) {
25855	    xmlNodePtr textChild;
25856	    xmlChar *normValue;
25857	    /*
25858	    * VAL TODO: Normalize the value.
25859	    */
25860	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
25861		inode->decl->value);
25862	    if (normValue != NULL) {
25863		textChild = xmlNewText(BAD_CAST normValue);
25864		xmlFree(normValue);
25865	    } else
25866		textChild = xmlNewText(inode->decl->value);
25867	    if (textChild == NULL) {
25868		VERROR_INT("xmlSchemaValidatorPopElem",
25869		    "calling xmlNewText()");
25870		goto internal_error;
25871	    } else
25872		xmlAddChild(inode->node, textChild);
25873	}
25874
25875    } else if (! INODE_NILLED(inode)) {
25876	/*
25877	* 5.2.1 The element information item must be �valid� with respect
25878	* to the �actual type definition� as defined by Element Locally
25879	* Valid (Type) (�3.3.4).
25880	*/
25881	if (WXS_IS_SIMPLE(inode->typeDef)) {
25882	     /*
25883	    * SPEC (cvc-type) (3.1)
25884	    * "If the type definition is a simple type definition, ..."
25885	    * (3.1.3) "If clause 3.2 of Element Locally Valid
25886	    * (Element) (�3.3.4) did not apply, then the �normalized value�
25887	    * must be �valid� with respect to the type definition as defined
25888	    * by String Valid (�3.14.4).
25889	    */
25890	    ret = xmlSchemaVCheckINodeDataType(vctxt,
25891		    inode, inode->typeDef, inode->value);
25892	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25893	    /*
25894	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
25895	    * definition, then the element information item must be
25896	    * �valid� with respect to the type definition as per
25897	    * Element Locally Valid (Complex Type) (�3.4.4);"
25898	    *
25899	    * SPEC (cvc-complex-type) (2.2)
25900	    * "If the {content type} is a simple type definition, ...
25901	    * the �normalized value� of the element information item is
25902	    * �valid� with respect to that simple type definition as
25903	    * defined by String Valid (�3.14.4)."
25904	    */
25905	    ret = xmlSchemaVCheckINodeDataType(vctxt,
25906		inode, inode->typeDef->contentTypeDef, inode->value);
25907	}
25908	if (ret != 0) {
25909	    if (ret < 0) {
25910		VERROR_INT("xmlSchemaValidatorPopElem",
25911		    "calling xmlSchemaVCheckCVCSimpleType()");
25912		goto internal_error;
25913	    }
25914	    goto end_elem;
25915	}
25916	/*
25917	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
25918	* not applied, all of the following must be true:
25919	*/
25920	if ((inode->decl->value != NULL) &&
25921	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
25922
25923	    /*
25924	    * TODO: We will need a computed value, when comparison is
25925	    * done on computed values.
25926	    */
25927	    /*
25928	    * 5.2.2.1 The element information item must have no element
25929	    * information item [children].
25930	    */
25931	    if (inode->flags &
25932		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
25933		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
25934		VERROR(ret, NULL,
25935		    "The content must not containt element nodes since "
25936		    "there is a fixed value constraint");
25937		goto end_elem;
25938	    } else {
25939		/*
25940		* 5.2.2.2 The appropriate case among the following must
25941		* be true:
25942		*/
25943		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
25944		    /*
25945		    * 5.2.2.2.1 If the {content type} of the �actual type
25946		    * definition� is mixed, then the *initial value* of the
25947		    * item must match the canonical lexical representation
25948		    * of the {value constraint} value.
25949		    *
25950		    * ... the *initial value* of an element information
25951		    * item is the string composed of, in order, the
25952		    * [character code] of each character information item in
25953		    * the [children] of that element information item.
25954		    */
25955		    if (! xmlStrEqual(inode->value, inode->decl->value)){
25956			/*
25957			* VAL TODO: Report invalid & expected values as well.
25958			* VAL TODO: Implement the canonical stuff.
25959			*/
25960			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
25961			xmlSchemaCustomErr(ACTXT_CAST vctxt,
25962			    ret, NULL, NULL,
25963			    "The initial value '%s' does not match the fixed "
25964			    "value constraint '%s'",
25965			    inode->value, inode->decl->value);
25966			goto end_elem;
25967		    }
25968		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25969		    /*
25970		    * 5.2.2.2.2 If the {content type} of the �actual type
25971		    * definition� is a simple type definition, then the
25972		    * *actual value* of the item must match the canonical
25973		    * lexical representation of the {value constraint} value.
25974		    */
25975		    /*
25976		    * VAL TODO: *actual value* is the normalized value, impl.
25977		    *           this.
25978		    * VAL TODO: Report invalid & expected values as well.
25979		    * VAL TODO: Implement a comparison with the computed values.
25980		    */
25981		    if (! xmlStrEqual(inode->value,
25982			    inode->decl->value)) {
25983			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
25984			xmlSchemaCustomErr(ACTXT_CAST vctxt,
25985			    ret, NULL, NULL,
25986			    "The actual value '%s' does not match the fixed "
25987			    "value constraint '%s'",
25988			    inode->value,
25989			    inode->decl->value);
25990			goto end_elem;
25991		    }
25992		}
25993	    }
25994	}
25995    }
25996
25997end_elem:
25998    if (vctxt->depth < 0) {
25999	/* TODO: raise error? */
26000	return (0);
26001    }
26002    if (vctxt->depth == vctxt->skipDepth)
26003	vctxt->skipDepth = -1;
26004    /*
26005    * Evaluate the history of XPath state objects.
26006    */
26007    if (inode->appliedXPath &&
26008	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26009	goto internal_error;
26010    /*
26011    * MAYBE TODO:
26012    * SPEC (6) "The element information item must be �valid� with
26013    * respect to each of the {identity-constraint definitions} as per
26014    * Identity-constraint Satisfied (�3.11.4)."
26015    */
26016    /*
26017    * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26018    *   need to be built in any case.
26019    *   We will currently build IDC node-tables and bubble them only if
26020    *   keyrefs do exist.
26021    */
26022
26023    /*
26024    * Add the current IDC target-nodes to the IDC node-tables.
26025    */
26026    if ((inode->idcMatchers != NULL) &&
26027	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26028    {
26029	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26030	    goto internal_error;
26031    }
26032    /*
26033    * Validate IDC keyrefs.
26034    */
26035    if (vctxt->inode->hasKeyrefs)
26036	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26037	    goto internal_error;
26038    /*
26039    * Merge/free the IDC table.
26040    */
26041    if (inode->idcTable != NULL) {
26042#ifdef DEBUG_IDC_NODE_TABLE
26043	xmlSchemaDebugDumpIDCTable(stdout,
26044	    inode->nsName,
26045	    inode->localName,
26046	    inode->idcTable);
26047#endif
26048	if ((vctxt->depth > 0) &&
26049	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26050	{
26051	    /*
26052	    * Merge the IDC node table with the table of the parent node.
26053	    */
26054	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26055		goto internal_error;
26056	}
26057    }
26058    /*
26059    * Clear the current ielem.
26060    * VAL TODO: Don't free the PSVI IDC tables if they are
26061    * requested for the PSVI.
26062    */
26063    xmlSchemaClearElemInfo(inode);
26064    /*
26065    * Skip further processing if we are on the validation root.
26066    */
26067    if (vctxt->depth == 0) {
26068	vctxt->depth--;
26069	vctxt->inode = NULL;
26070	return (0);
26071    }
26072    /*
26073    * Reset the keyrefDepth if needed.
26074    */
26075    if (vctxt->aidcs != NULL) {
26076	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26077	do {
26078	    if (aidc->keyrefDepth == vctxt->depth) {
26079		/*
26080		* A 'keyrefDepth' of a key/unique IDC matches the current
26081		* depth, this means that we are leaving the scope of the
26082		* top-most keyref IDC which refers to this IDC.
26083		*/
26084		aidc->keyrefDepth = -1;
26085	    }
26086	    aidc = aidc->next;
26087	} while (aidc != NULL);
26088    }
26089    vctxt->depth--;
26090    vctxt->inode = vctxt->elemInfos[vctxt->depth];
26091    /*
26092    * VAL TODO: 7 If the element information item is the �validation root�, it must be
26093    * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26094    */
26095    return (ret);
26096
26097internal_error:
26098    vctxt->err = -1;
26099    return (-1);
26100}
26101
26102/*
26103* 3.4.4 Complex Type Definition Validation Rules
26104* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26105*/
26106static int
26107xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26108{
26109    xmlSchemaNodeInfoPtr pielem;
26110    xmlSchemaTypePtr ptype;
26111    int ret = 0;
26112
26113    if (vctxt->depth <= 0) {
26114	VERROR_INT("xmlSchemaValidateChildElem",
26115	    "not intended for the validation root");
26116	return (-1);
26117    }
26118    pielem = vctxt->elemInfos[vctxt->depth -1];
26119    if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26120	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26121    /*
26122    * Handle 'nilled' elements.
26123    */
26124    if (INODE_NILLED(pielem)) {
26125	/*
26126	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26127	*/
26128	ACTIVATE_PARENT_ELEM;
26129	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26130	VERROR(ret, NULL,
26131	    "Neither character nor element content is allowed, "
26132	    "because the element was 'nilled'");
26133	ACTIVATE_ELEM;
26134	goto unexpected_elem;
26135    }
26136
26137    ptype = pielem->typeDef;
26138
26139    if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26140	/*
26141	* Workaround for "anyType": we have currently no content model
26142	* assigned for "anyType", so handle it explicitely.
26143	* "anyType" has an unbounded, lax "any" wildcard.
26144	*/
26145	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26146	    vctxt->inode->localName,
26147	    vctxt->inode->nsName);
26148
26149	if (vctxt->inode->decl == NULL) {
26150	    xmlSchemaAttrInfoPtr iattr;
26151	    /*
26152	    * Process "xsi:type".
26153	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26154	    */
26155	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26156		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26157	    if (iattr != NULL) {
26158		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26159		    &(vctxt->inode->typeDef), NULL);
26160		if (ret != 0) {
26161		    if (ret == -1) {
26162			VERROR_INT("xmlSchemaValidateChildElem",
26163			    "calling xmlSchemaProcessXSIType() to "
26164			    "process the attribute 'xsi:nil'");
26165			return (-1);
26166		    }
26167		    return (ret);
26168		}
26169	    } else {
26170		 /*
26171		 * Fallback to "anyType".
26172		 *
26173		 * SPEC (cvc-assess-elt)
26174		 * "If the item cannot be �strictly assessed�, [...]
26175		 * an element information item's schema validity may be laxly
26176		 * assessed if its �context-determined declaration� is not
26177		 * skip by �validating� with respect to the �ur-type
26178		 * definition� as per Element Locally Valid (Type) (�3.3.4)."
26179		*/
26180		vctxt->inode->typeDef =
26181		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26182	    }
26183	}
26184	return (0);
26185    }
26186
26187    switch (ptype->contentType) {
26188	case XML_SCHEMA_CONTENT_EMPTY:
26189	    /*
26190	    * SPEC (2.1) "If the {content type} is empty, then the
26191	    * element information item has no character or element
26192	    * information item [children]."
26193	    */
26194	    ACTIVATE_PARENT_ELEM
26195	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26196	    VERROR(ret, NULL,
26197		"Element content is not allowed, "
26198		"because the content type is empty");
26199	    ACTIVATE_ELEM
26200	    goto unexpected_elem;
26201	    break;
26202
26203	case XML_SCHEMA_CONTENT_MIXED:
26204        case XML_SCHEMA_CONTENT_ELEMENTS: {
26205	    xmlRegExecCtxtPtr regexCtxt;
26206	    xmlChar *values[10];
26207	    int terminal, nbval = 10, nbneg;
26208
26209	    /* VAL TODO: Optimized "anyType" validation.*/
26210
26211	    if (ptype->contModel == NULL) {
26212		VERROR_INT("xmlSchemaValidateChildElem",
26213		    "type has elem content but no content model");
26214		return (-1);
26215	    }
26216	    /*
26217	    * Safety belf for evaluation if the cont. model was already
26218	    * examined to be invalid.
26219	    */
26220	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26221		VERROR_INT("xmlSchemaValidateChildElem",
26222		    "validating elem, but elem content is already invalid");
26223		return (-1);
26224	    }
26225
26226	    regexCtxt = pielem->regexCtxt;
26227	    if (regexCtxt == NULL) {
26228		/*
26229		* Create the regex context.
26230		*/
26231		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26232		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26233		    vctxt);
26234		if (regexCtxt == NULL) {
26235		    VERROR_INT("xmlSchemaValidateChildElem",
26236			"failed to create a regex context");
26237		    return (-1);
26238		}
26239		pielem->regexCtxt = regexCtxt;
26240#ifdef DEBUG_AUTOMATA
26241		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26242		    pielem->localName);
26243#endif
26244	    }
26245
26246	    /*
26247	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26248	    * then the sequence of the element information item's
26249	    * element information item [children], if any, taken in
26250	    * order, is �valid� with respect to the {content type}'s
26251	    * particle, as defined in Element Sequence Locally Valid
26252	    * (Particle) (�3.9.4)."
26253	    */
26254	    ret = xmlRegExecPushString2(regexCtxt,
26255		vctxt->inode->localName,
26256		vctxt->inode->nsName,
26257		vctxt->inode);
26258#ifdef DEBUG_AUTOMATA
26259	    if (ret < 0)
26260		xmlGenericError(xmlGenericErrorContext,
26261		"AUTOMATON push ERROR for '%s' on '%s'\n",
26262		vctxt->inode->localName, pielem->localName);
26263	    else
26264		xmlGenericError(xmlGenericErrorContext,
26265		"AUTOMATON push OK for '%s' on '%s'\n",
26266		vctxt->inode->localName, pielem->localName);
26267#endif
26268	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26269		VERROR_INT("xmlSchemaValidateChildElem",
26270		    "calling xmlRegExecPushString2()");
26271		return (-1);
26272	    }
26273	    if (ret < 0) {
26274		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26275		    &values[0], &terminal);
26276		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26277		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26278		    "This element is not expected",
26279		    nbval, nbneg, values);
26280		ret = vctxt->err;
26281		goto unexpected_elem;
26282	    } else
26283		ret = 0;
26284	}
26285	    break;
26286	case XML_SCHEMA_CONTENT_SIMPLE:
26287	case XML_SCHEMA_CONTENT_BASIC:
26288	    ACTIVATE_PARENT_ELEM
26289	    if (WXS_IS_COMPLEX(ptype)) {
26290		/*
26291		* SPEC (cvc-complex-type) (2.2)
26292		* "If the {content type} is a simple type definition, then
26293		* the element information item has no element information
26294		* item [children], ..."
26295		*/
26296		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26297		VERROR(ret, NULL, "Element content is not allowed, "
26298		    "because the content type is a simple type definition");
26299	    } else {
26300		/*
26301		* SPEC (cvc-type) (3.1.2) "The element information item must
26302		* have no element information item [children]."
26303		*/
26304		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26305		VERROR(ret, NULL, "Element content is not allowed, "
26306		    "because the type definition is simple");
26307	    }
26308	    ACTIVATE_ELEM
26309	    ret = vctxt->err;
26310	    goto unexpected_elem;
26311	    break;
26312
26313	default:
26314	    break;
26315    }
26316    return (ret);
26317unexpected_elem:
26318    /*
26319    * Pop this element and set the skipDepth to skip
26320    * all further content of the parent element.
26321    */
26322    vctxt->skipDepth = vctxt->depth;
26323    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26324    pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26325    return (ret);
26326}
26327
26328#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26329#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26330#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26331
26332static int
26333xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26334		  int nodeType, const xmlChar *value, int len,
26335		  int mode, int *consumed)
26336{
26337    /*
26338    * Unfortunately we have to duplicate the text sometimes.
26339    * OPTIMIZE: Maybe we could skip it, if:
26340    *   1. content type is simple
26341    *   2. whitespace is "collapse"
26342    *   3. it consists of whitespace only
26343    *
26344    * Process character content.
26345    */
26346    if (consumed != NULL)
26347	*consumed = 0;
26348    if (INODE_NILLED(vctxt->inode)) {
26349	/*
26350	* SPEC cvc-elt (3.3.4 - 3.2.1)
26351	* "The element information item must have no character or
26352	* element information item [children]."
26353	*/
26354	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26355	    "Neither character nor element content is allowed "
26356	    "because the element is 'nilled'");
26357	return (vctxt->err);
26358    }
26359    /*
26360    * SPEC (2.1) "If the {content type} is empty, then the
26361    * element information item has no character or element
26362    * information item [children]."
26363    */
26364    if (vctxt->inode->typeDef->contentType ==
26365	    XML_SCHEMA_CONTENT_EMPTY) {
26366	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26367	    "Character content is not allowed, "
26368	    "because the content type is empty");
26369	return (vctxt->err);
26370    }
26371
26372    if (vctxt->inode->typeDef->contentType ==
26373	    XML_SCHEMA_CONTENT_ELEMENTS) {
26374	if ((nodeType != XML_TEXT_NODE) ||
26375	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26376	    /*
26377	    * SPEC cvc-complex-type (2.3)
26378	    * "If the {content type} is element-only, then the
26379	    * element information item has no character information
26380	    * item [children] other than those whose [character
26381	    * code] is defined as a white space in [XML 1.0 (Second
26382	    * Edition)]."
26383	    */
26384	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26385		"Character content other than whitespace is not allowed "
26386		"because the content type is 'element-only'");
26387	    return (vctxt->err);
26388	}
26389	return (0);
26390    }
26391
26392    if ((value == NULL) || (value[0] == 0))
26393	return (0);
26394    /*
26395    * Save the value.
26396    * NOTE that even if the content type is *mixed*, we need the
26397    * *initial value* for default/fixed value constraints.
26398    */
26399    if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26400	((vctxt->inode->decl == NULL) ||
26401	(vctxt->inode->decl->value == NULL)))
26402	return (0);
26403
26404    if (vctxt->inode->value == NULL) {
26405	/*
26406	* Set the value.
26407	*/
26408	switch (mode) {
26409	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26410		/*
26411		* When working on a tree.
26412		*/
26413		vctxt->inode->value = value;
26414		break;
26415	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26416		/*
26417		* When working with the reader.
26418		* The value will be freed by the element info.
26419		*/
26420		vctxt->inode->value = value;
26421		if (consumed != NULL)
26422		    *consumed = 1;
26423		vctxt->inode->flags |=
26424		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26425		break;
26426	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26427		/*
26428		* When working with SAX.
26429		* The value will be freed by the element info.
26430		*/
26431		if (len != -1)
26432		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26433		else
26434		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26435		vctxt->inode->flags |=
26436		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26437		break;
26438	    default:
26439		break;
26440	}
26441    } else {
26442	if (len < 0)
26443	    len = xmlStrlen(value);
26444	/*
26445	* Concat the value.
26446	*/
26447	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26448	    vctxt->inode->value = BAD_CAST xmlStrncat(
26449		(xmlChar *) vctxt->inode->value, value, len);
26450	} else {
26451	    vctxt->inode->value =
26452		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26453	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26454	}
26455    }
26456
26457    return (0);
26458}
26459
26460static int
26461xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26462{
26463    int ret = 0;
26464
26465    if ((vctxt->skipDepth != -1) &&
26466	(vctxt->depth >= vctxt->skipDepth)) {
26467	VERROR_INT("xmlSchemaValidateElem",
26468	    "in skip-state");
26469	goto internal_error;
26470    }
26471    if (vctxt->xsiAssemble) {
26472	/*
26473	* We will stop validation if there was an error during
26474	* dynamic schema construction.
26475	* Note that we simply set @skipDepth to 0, this could
26476	* mean that a streaming document via SAX would be
26477	* still read to the end but it won't be validated any more.
26478	* TODO: If we are sure how to stop the validation at once
26479	*   for all input scenarios, then this should be changed to
26480	*   instantly stop the validation.
26481	*/
26482	ret = xmlSchemaAssembleByXSI(vctxt);
26483	if (ret != 0) {
26484	    if (ret == -1)
26485		goto internal_error;
26486	    vctxt->skipDepth = 0;
26487	    return(ret);
26488	}
26489    }
26490    if (vctxt->depth > 0) {
26491	/*
26492	* Validate this element against the content model
26493	* of the parent.
26494	*/
26495	ret = xmlSchemaValidateChildElem(vctxt);
26496	if (ret != 0) {
26497	    if (ret < 0) {
26498		VERROR_INT("xmlSchemaValidateElem",
26499		    "calling xmlSchemaStreamValidateChildElement()");
26500		goto internal_error;
26501	    }
26502	    goto exit;
26503	}
26504	if (vctxt->depth == vctxt->skipDepth)
26505	    goto exit;
26506	if ((vctxt->inode->decl == NULL) &&
26507	    (vctxt->inode->typeDef == NULL)) {
26508	    VERROR_INT("xmlSchemaValidateElem",
26509		"the child element was valid but neither the "
26510		"declaration nor the type was set");
26511	    goto internal_error;
26512	}
26513    } else {
26514	/*
26515	* Get the declaration of the validation root.
26516	*/
26517	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26518	    vctxt->inode->localName,
26519	    vctxt->inode->nsName);
26520	if (vctxt->inode->decl == NULL) {
26521	    ret = XML_SCHEMAV_CVC_ELT_1;
26522	    VERROR(ret, NULL,
26523		"No matching global declaration available "
26524		"for the validation root");
26525	    goto exit;
26526	}
26527    }
26528
26529    if (vctxt->inode->decl == NULL)
26530	goto type_validation;
26531
26532    if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26533	int skip;
26534	/*
26535	* Wildcards.
26536	*/
26537	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26538	if (ret != 0) {
26539	    if (ret < 0) {
26540		VERROR_INT("xmlSchemaValidateElem",
26541		    "calling xmlSchemaValidateElemWildcard()");
26542		goto internal_error;
26543	    }
26544	    goto exit;
26545	}
26546	if (skip) {
26547	    vctxt->skipDepth = vctxt->depth;
26548	    goto exit;
26549	}
26550	/*
26551	* The declaration might be set by the wildcard validation,
26552	* when the processContents is "lax" or "strict".
26553	*/
26554	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26555	    /*
26556	    * Clear the "decl" field to not confuse further processing.
26557	    */
26558	    vctxt->inode->decl = NULL;
26559	    goto type_validation;
26560	}
26561    }
26562    /*
26563    * Validate against the declaration.
26564    */
26565    ret = xmlSchemaValidateElemDecl(vctxt);
26566    if (ret != 0) {
26567	if (ret < 0) {
26568	    VERROR_INT("xmlSchemaValidateElem",
26569		"calling xmlSchemaValidateElemDecl()");
26570	    goto internal_error;
26571	}
26572	goto exit;
26573    }
26574    /*
26575    * Validate against the type definition.
26576    */
26577type_validation:
26578
26579    if (vctxt->inode->typeDef == NULL) {
26580	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26581	ret = XML_SCHEMAV_CVC_TYPE_1;
26582    	VERROR(ret, NULL,
26583    	    "The type definition is absent");
26584	goto exit;
26585    }
26586    if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26587	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26588	ret = XML_SCHEMAV_CVC_TYPE_2;
26589    	    VERROR(ret, NULL,
26590    	    "The type definition is abstract");
26591	goto exit;
26592    }
26593    /*
26594    * Evaluate IDCs. Do it here, since new IDC matchers are registered
26595    * during validation against the declaration. This must be done
26596    * _before_ attribute validation.
26597    */
26598    if (vctxt->xpathStates != NULL) {
26599	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26600	vctxt->inode->appliedXPath = 1;
26601	if (ret == -1) {
26602	    VERROR_INT("xmlSchemaValidateElem",
26603		"calling xmlSchemaXPathEvaluate()");
26604	    goto internal_error;
26605	}
26606    }
26607    /*
26608    * Validate attributes.
26609    */
26610    if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26611	if ((vctxt->nbAttrInfos != 0) ||
26612	    (vctxt->inode->typeDef->attrUses != NULL)) {
26613
26614	    ret = xmlSchemaVAttributesComplex(vctxt);
26615	}
26616    } else if (vctxt->nbAttrInfos != 0) {
26617
26618	ret = xmlSchemaVAttributesSimple(vctxt);
26619    }
26620    /*
26621    * Clear registered attributes.
26622    */
26623    if (vctxt->nbAttrInfos != 0)
26624	xmlSchemaClearAttrInfos(vctxt);
26625    if (ret == -1) {
26626	VERROR_INT("xmlSchemaValidateElem",
26627	    "calling attributes validation");
26628	goto internal_error;
26629    }
26630    /*
26631    * Don't return an error if attributes are invalid on purpose.
26632    */
26633    ret = 0;
26634
26635exit:
26636    if (ret != 0)
26637	vctxt->skipDepth = vctxt->depth;
26638    return (ret);
26639internal_error:
26640    return (-1);
26641}
26642
26643#ifdef XML_SCHEMA_READER_ENABLED
26644static int
26645xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26646{
26647    const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26648    int depth, nodeType, ret = 0, consumed;
26649    xmlSchemaNodeInfoPtr ielem;
26650
26651    vctxt->depth = -1;
26652    ret = xmlTextReaderRead(vctxt->reader);
26653    /*
26654    * Move to the document element.
26655    */
26656    while (ret == 1) {
26657	nodeType = xmlTextReaderNodeType(vctxt->reader);
26658	if (nodeType == XML_ELEMENT_NODE)
26659	    goto root_found;
26660	ret = xmlTextReaderRead(vctxt->reader);
26661    }
26662    goto exit;
26663
26664root_found:
26665
26666    do {
26667	depth = xmlTextReaderDepth(vctxt->reader);
26668	nodeType = xmlTextReaderNodeType(vctxt->reader);
26669
26670	if (nodeType == XML_ELEMENT_NODE) {
26671
26672	    vctxt->depth++;
26673	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26674		VERROR_INT("xmlSchemaVReaderWalk",
26675		    "calling xmlSchemaValidatorPushElem()");
26676		goto internal_error;
26677	    }
26678	    ielem = vctxt->inode;
26679	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26680	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26681	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26682	    /*
26683	    * Is the element empty?
26684	    */
26685	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26686	    if (ret == -1) {
26687		VERROR_INT("xmlSchemaVReaderWalk",
26688		    "calling xmlTextReaderIsEmptyElement()");
26689		goto internal_error;
26690	    }
26691	    if (ret) {
26692		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26693	    }
26694	    /*
26695	    * Register attributes.
26696	    */
26697	    vctxt->nbAttrInfos = 0;
26698	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26699	    if (ret == -1) {
26700		VERROR_INT("xmlSchemaVReaderWalk",
26701		    "calling xmlTextReaderMoveToFirstAttribute()");
26702		goto internal_error;
26703	    }
26704	    if (ret == 1) {
26705		do {
26706		    /*
26707		    * VAL TODO: How do we know that the reader works on a
26708		    * node tree, to be able to pass a node here?
26709		    */
26710		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26711			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26712			xmlTextReaderNamespaceUri(vctxt->reader), 1,
26713			xmlTextReaderValue(vctxt->reader), 1) == -1) {
26714
26715			VERROR_INT("xmlSchemaVReaderWalk",
26716			    "calling xmlSchemaValidatorPushAttribute()");
26717			goto internal_error;
26718		    }
26719		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26720		    if (ret == -1) {
26721			VERROR_INT("xmlSchemaVReaderWalk",
26722			    "calling xmlTextReaderMoveToFirstAttribute()");
26723			goto internal_error;
26724		    }
26725		} while (ret == 1);
26726		/*
26727		* Back to element position.
26728		*/
26729		ret = xmlTextReaderMoveToElement(vctxt->reader);
26730		if (ret == -1) {
26731		    VERROR_INT("xmlSchemaVReaderWalk",
26732			"calling xmlTextReaderMoveToElement()");
26733		    goto internal_error;
26734		}
26735	    }
26736	    /*
26737	    * Validate the element.
26738	    */
26739	    ret= xmlSchemaValidateElem(vctxt);
26740	    if (ret != 0) {
26741		if (ret == -1) {
26742		    VERROR_INT("xmlSchemaVReaderWalk",
26743			"calling xmlSchemaValidateElem()");
26744		    goto internal_error;
26745		}
26746		goto exit;
26747	    }
26748	    if (vctxt->depth == vctxt->skipDepth) {
26749		int curDepth;
26750		/*
26751		* Skip all content.
26752		*/
26753		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26754		    ret = xmlTextReaderRead(vctxt->reader);
26755		    curDepth = xmlTextReaderDepth(vctxt->reader);
26756		    while ((ret == 1) && (curDepth != depth)) {
26757			ret = xmlTextReaderRead(vctxt->reader);
26758			curDepth = xmlTextReaderDepth(vctxt->reader);
26759		    }
26760		    if (ret < 0) {
26761			/*
26762			* VAL TODO: A reader error occured; what to do here?
26763			*/
26764			ret = 1;
26765			goto exit;
26766		    }
26767		}
26768		goto leave_elem;
26769	    }
26770	    /*
26771	    * READER VAL TODO: Is an END_ELEM really never called
26772	    * if the elem is empty?
26773	    */
26774	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26775		goto leave_elem;
26776	} else if (nodeType == END_ELEM) {
26777	    /*
26778	    * Process END of element.
26779	    */
26780leave_elem:
26781	    ret = xmlSchemaValidatorPopElem(vctxt);
26782	    if (ret != 0) {
26783		if (ret < 0) {
26784		    VERROR_INT("xmlSchemaVReaderWalk",
26785			"calling xmlSchemaValidatorPopElem()");
26786		    goto internal_error;
26787		}
26788		goto exit;
26789	    }
26790	    if (vctxt->depth >= 0)
26791		ielem = vctxt->inode;
26792	    else
26793		ielem = NULL;
26794	} else if ((nodeType == XML_TEXT_NODE) ||
26795	    (nodeType == XML_CDATA_SECTION_NODE) ||
26796	    (nodeType == WHTSP) ||
26797	    (nodeType == SIGN_WHTSP)) {
26798	    /*
26799	    * Process character content.
26800	    */
26801	    xmlChar *value;
26802
26803	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
26804		nodeType = XML_TEXT_NODE;
26805
26806	    value = xmlTextReaderValue(vctxt->reader);
26807	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
26808		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
26809	    if (! consumed)
26810		xmlFree(value);
26811	    if (ret == -1) {
26812		VERROR_INT("xmlSchemaVReaderWalk",
26813		    "calling xmlSchemaVPushText()");
26814		goto internal_error;
26815	    }
26816	} else if ((nodeType == XML_ENTITY_NODE) ||
26817	    (nodeType == XML_ENTITY_REF_NODE)) {
26818	    /*
26819	    * VAL TODO: What to do with entities?
26820	    */
26821	    TODO
26822	}
26823	/*
26824	* Read next node.
26825	*/
26826	ret = xmlTextReaderRead(vctxt->reader);
26827    } while (ret == 1);
26828
26829exit:
26830    return (ret);
26831internal_error:
26832    return (-1);
26833}
26834#endif
26835
26836/************************************************************************
26837 * 									*
26838 * 			SAX validation handlers				*
26839 * 									*
26840 ************************************************************************/
26841
26842/*
26843* Process text content.
26844*/
26845static void
26846xmlSchemaSAXHandleText(void *ctx,
26847		       const xmlChar * ch,
26848		       int len)
26849{
26850    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26851
26852    if (vctxt->depth < 0)
26853	return;
26854    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26855	return;
26856    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26857	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26858    if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
26859	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26860	VERROR_INT("xmlSchemaSAXHandleCDataSection",
26861	    "calling xmlSchemaVPushText()");
26862	vctxt->err = -1;
26863	xmlStopParser(vctxt->parserCtxt);
26864    }
26865}
26866
26867/*
26868* Process CDATA content.
26869*/
26870static void
26871xmlSchemaSAXHandleCDataSection(void *ctx,
26872			     const xmlChar * ch,
26873			     int len)
26874{
26875    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26876
26877    if (vctxt->depth < 0)
26878	return;
26879    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26880	return;
26881    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26882	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26883    if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
26884	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
26885	VERROR_INT("xmlSchemaSAXHandleCDataSection",
26886	    "calling xmlSchemaVPushText()");
26887	vctxt->err = -1;
26888	xmlStopParser(vctxt->parserCtxt);
26889    }
26890}
26891
26892static void
26893xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
26894			    const xmlChar * name ATTRIBUTE_UNUSED)
26895{
26896    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26897
26898    if (vctxt->depth < 0)
26899	return;
26900    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26901	return;
26902    /* SAX VAL TODO: What to do here? */
26903    TODO
26904}
26905
26906static void
26907xmlSchemaSAXHandleStartElementNs(void *ctx,
26908				 const xmlChar * localname,
26909				 const xmlChar * prefix ATTRIBUTE_UNUSED,
26910				 const xmlChar * URI,
26911				 int nb_namespaces,
26912				 const xmlChar ** namespaces,
26913				 int nb_attributes,
26914				 int nb_defaulted ATTRIBUTE_UNUSED,
26915				 const xmlChar ** attributes)
26916{
26917    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
26918    int ret;
26919    xmlSchemaNodeInfoPtr ielem;
26920    int i, j;
26921
26922    /*
26923    * SAX VAL TODO: What to do with nb_defaulted?
26924    */
26925    /*
26926    * Skip elements if inside a "skip" wildcard or invalid.
26927    */
26928    vctxt->depth++;
26929    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
26930	return;
26931    /*
26932    * Push the element.
26933    */
26934    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26935	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
26936	    "calling xmlSchemaValidatorPushElem()");
26937	goto internal_error;
26938    }
26939    ielem = vctxt->inode;
26940    /*
26941    * TODO: Is this OK?
26942    */
26943    ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
26944    ielem->localName = localname;
26945    ielem->nsName = URI;
26946    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26947    /*
26948    * Register namespaces on the elem info.
26949    */
26950    if (nb_namespaces != 0) {
26951	/*
26952	* Although the parser builds its own namespace list,
26953	* we have no access to it, so we'll use an own one.
26954	*/
26955        for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
26956	    /*
26957	    * Store prefix and namespace name.
26958	    */
26959	    if (ielem->nsBindings == NULL) {
26960		ielem->nsBindings =
26961		    (const xmlChar **) xmlMalloc(10 *
26962			sizeof(const xmlChar *));
26963		if (ielem->nsBindings == NULL) {
26964		    xmlSchemaVErrMemory(vctxt,
26965			"allocating namespace bindings for SAX validation",
26966			NULL);
26967		    goto internal_error;
26968		}
26969		ielem->nbNsBindings = 0;
26970		ielem->sizeNsBindings = 5;
26971	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
26972		ielem->sizeNsBindings *= 2;
26973		ielem->nsBindings =
26974		    (const xmlChar **) xmlRealloc(
26975			(void *) ielem->nsBindings,
26976			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
26977		if (ielem->nsBindings == NULL) {
26978		    xmlSchemaVErrMemory(vctxt,
26979			"re-allocating namespace bindings for SAX validation",
26980			NULL);
26981		    goto internal_error;
26982		}
26983	    }
26984
26985	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
26986	    if (namespaces[j+1][0] == 0) {
26987		/*
26988		* Handle xmlns="".
26989		*/
26990		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
26991	    } else
26992		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
26993		    namespaces[j+1];
26994	    ielem->nbNsBindings++;
26995	}
26996    }
26997    /*
26998    * Register attributes.
26999    * SAX VAL TODO: We are not adding namespace declaration
27000    * attributes yet.
27001    */
27002    if (nb_attributes != 0) {
27003	xmlChar *value;
27004
27005        for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27006	    /*
27007	    * Duplicate the value.
27008	    */
27009	    value = xmlStrndup(attributes[j+3],
27010		attributes[j+4] - attributes[j+3]);
27011	    /*
27012	    * TODO: Set the node line.
27013	    */
27014	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27015		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27016		value, 1);
27017	    if (ret == -1) {
27018		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27019		    "calling xmlSchemaValidatorPushAttribute()");
27020		goto internal_error;
27021	    }
27022	}
27023    }
27024    /*
27025    * Validate the element.
27026    */
27027    ret = xmlSchemaValidateElem(vctxt);
27028    if (ret != 0) {
27029	if (ret == -1) {
27030	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27031		"calling xmlSchemaValidateElem()");
27032	    goto internal_error;
27033	}
27034	goto exit;
27035    }
27036
27037exit:
27038    return;
27039internal_error:
27040    vctxt->err = -1;
27041    xmlStopParser(vctxt->parserCtxt);
27042    return;
27043}
27044
27045static void
27046xmlSchemaSAXHandleEndElementNs(void *ctx,
27047			       const xmlChar * localname ATTRIBUTE_UNUSED,
27048			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27049			       const xmlChar * URI ATTRIBUTE_UNUSED)
27050{
27051    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27052    int res;
27053
27054    /*
27055    * Skip elements if inside a "skip" wildcard or if invalid.
27056    */
27057    if (vctxt->skipDepth != -1) {
27058	if (vctxt->depth > vctxt->skipDepth) {
27059	    vctxt->depth--;
27060	    return;
27061	} else
27062	    vctxt->skipDepth = -1;
27063    }
27064    /*
27065    * SAX VAL TODO: Just a temporary check.
27066    */
27067    if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27068	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27069	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27070	    "elem pop mismatch");
27071    }
27072    res = xmlSchemaValidatorPopElem(vctxt);
27073    if (res != 0) {
27074	if (res < 0) {
27075	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27076		"calling xmlSchemaValidatorPopElem()");
27077	    goto internal_error;
27078	}
27079	goto exit;
27080    }
27081exit:
27082    return;
27083internal_error:
27084    vctxt->err = -1;
27085    xmlStopParser(vctxt->parserCtxt);
27086    return;
27087}
27088
27089/************************************************************************
27090 * 									*
27091 * 			Validation interfaces				*
27092 * 									*
27093 ************************************************************************/
27094
27095/**
27096 * xmlSchemaNewValidCtxt:
27097 * @schema:  a precompiled XML Schemas
27098 *
27099 * Create an XML Schemas validation context based on the given schema.
27100 *
27101 * Returns the validation context or NULL in case of error
27102 */
27103xmlSchemaValidCtxtPtr
27104xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27105{
27106    xmlSchemaValidCtxtPtr ret;
27107
27108    ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27109    if (ret == NULL) {
27110        xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27111        return (NULL);
27112    }
27113    memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27114    ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27115    ret->dict = xmlDictCreate();
27116    ret->nodeQNames = xmlSchemaItemListCreate();
27117    ret->schema = schema;
27118    return (ret);
27119}
27120
27121/**
27122 * xmlSchemaClearValidCtxt:
27123 * @ctxt: the schema validation context
27124 *
27125 * Free the resources associated to the schema validation context;
27126 * leaves some fields alive intended for reuse of the context.
27127 */
27128static void
27129xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27130{
27131    if (vctxt == NULL)
27132        return;
27133
27134    /*
27135    * TODO: Should we clear the flags?
27136    *   Might be problematic if one reuses the context
27137    *   and assumes that the options remain the same.
27138    */
27139    vctxt->flags = 0;
27140    vctxt->validationRoot = NULL;
27141    vctxt->doc = NULL;
27142#ifdef LIBXML_READER_ENABLED
27143    vctxt->reader = NULL;
27144#endif
27145    vctxt->hasKeyrefs = 0;
27146
27147    if (vctxt->value != NULL) {
27148        xmlSchemaFreeValue(vctxt->value);
27149	vctxt->value = NULL;
27150    }
27151    /*
27152    * Augmented IDC information.
27153    */
27154    if (vctxt->aidcs != NULL) {
27155	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27156	do {
27157	    next = cur->next;
27158	    xmlFree(cur);
27159	    cur = next;
27160	} while (cur != NULL);
27161	vctxt->aidcs = NULL;
27162    }
27163    if (vctxt->idcNodes != NULL) {
27164	int i;
27165	xmlSchemaPSVIIDCNodePtr item;
27166
27167	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27168	    item = vctxt->idcNodes[i];
27169	    xmlFree(item->keys);
27170	    xmlFree(item);
27171	}
27172	xmlFree(vctxt->idcNodes);
27173	vctxt->idcNodes = NULL;
27174    }
27175    /*
27176    * Note that we won't delete the XPath state pool here.
27177    */
27178    if (vctxt->xpathStates != NULL) {
27179	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27180	vctxt->xpathStates = NULL;
27181    }
27182    /*
27183    * Attribute info.
27184    */
27185    if (vctxt->nbAttrInfos != 0) {
27186	xmlSchemaClearAttrInfos(vctxt);
27187    }
27188    /*
27189    * Element info.
27190    */
27191    if (vctxt->elemInfos != NULL) {
27192	int i;
27193	xmlSchemaNodeInfoPtr ei;
27194
27195	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27196	    ei = vctxt->elemInfos[i];
27197	    if (ei == NULL)
27198		break;
27199	    xmlSchemaClearElemInfo(ei);
27200	}
27201    }
27202    xmlSchemaItemListClear(vctxt->nodeQNames);
27203    /* Recreate the dict. */
27204    xmlDictFree(vctxt->dict);
27205    /*
27206    * TODO: Is is save to recreate it? Do we have a scenario
27207    * where the user provides the dict?
27208    */
27209    vctxt->dict = xmlDictCreate();
27210}
27211
27212/**
27213 * xmlSchemaFreeValidCtxt:
27214 * @ctxt:  the schema validation context
27215 *
27216 * Free the resources associated to the schema validation context
27217 */
27218void
27219xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27220{
27221    if (ctxt == NULL)
27222        return;
27223    if (ctxt->value != NULL)
27224        xmlSchemaFreeValue(ctxt->value);
27225    if (ctxt->pctxt != NULL)
27226	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27227    if (ctxt->idcNodes != NULL) {
27228	int i;
27229	xmlSchemaPSVIIDCNodePtr item;
27230
27231	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27232	    item = ctxt->idcNodes[i];
27233	    xmlFree(item->keys);
27234	    xmlFree(item);
27235	}
27236	xmlFree(ctxt->idcNodes);
27237    }
27238    if (ctxt->idcKeys != NULL) {
27239	int i;
27240	for (i = 0; i < ctxt->nbIdcKeys; i++)
27241	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27242	xmlFree(ctxt->idcKeys);
27243    }
27244
27245    if (ctxt->xpathStates != NULL)
27246	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27247    if (ctxt->xpathStatePool != NULL)
27248	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27249
27250    /*
27251    * Augmented IDC information.
27252    */
27253    if (ctxt->aidcs != NULL) {
27254	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27255	do {
27256	    next = cur->next;
27257	    xmlFree(cur);
27258	    cur = next;
27259	} while (cur != NULL);
27260    }
27261    if (ctxt->attrInfos != NULL) {
27262	int i;
27263	xmlSchemaAttrInfoPtr attr;
27264
27265	/* Just a paranoid call to the cleanup. */
27266	if (ctxt->nbAttrInfos != 0)
27267	    xmlSchemaClearAttrInfos(ctxt);
27268	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27269	    attr = ctxt->attrInfos[i];
27270	    xmlFree(attr);
27271	}
27272	xmlFree(ctxt->attrInfos);
27273    }
27274    if (ctxt->elemInfos != NULL) {
27275	int i;
27276	xmlSchemaNodeInfoPtr ei;
27277
27278	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27279	    ei = ctxt->elemInfos[i];
27280	    if (ei == NULL)
27281		break;
27282	    xmlSchemaClearElemInfo(ei);
27283	    xmlFree(ei);
27284	}
27285	xmlFree(ctxt->elemInfos);
27286    }
27287    if (ctxt->nodeQNames != NULL)
27288	xmlSchemaItemListFree(ctxt->nodeQNames);
27289    if (ctxt->dict != NULL)
27290	xmlDictFree(ctxt->dict);
27291    xmlFree(ctxt);
27292}
27293
27294/**
27295 * xmlSchemaIsValid:
27296 * @ctxt: the schema validation context
27297 *
27298 * Check if any error was detected during validation.
27299 *
27300 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27301 *         of internal error.
27302 */
27303int
27304xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27305{
27306    if (ctxt == NULL)
27307        return(-1);
27308    return(ctxt->err == 0);
27309}
27310
27311/**
27312 * xmlSchemaSetValidErrors:
27313 * @ctxt:  a schema validation context
27314 * @err:  the error function
27315 * @warn: the warning function
27316 * @ctx: the functions context
27317 *
27318 * Set the error and warning callback informations
27319 */
27320void
27321xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27322                        xmlSchemaValidityErrorFunc err,
27323                        xmlSchemaValidityWarningFunc warn, void *ctx)
27324{
27325    if (ctxt == NULL)
27326        return;
27327    ctxt->error = err;
27328    ctxt->warning = warn;
27329    ctxt->errCtxt = ctx;
27330    if (ctxt->pctxt != NULL)
27331	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27332}
27333
27334/**
27335 * xmlSchemaSetValidStructuredErrors:
27336 * @ctxt:  a schema validation context
27337 * @serror:  the structured error function
27338 * @ctx: the functions context
27339 *
27340 * Set the structured error callback
27341 */
27342void
27343xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27344				  xmlStructuredErrorFunc serror, void *ctx)
27345{
27346    if (ctxt == NULL)
27347        return;
27348	ctxt->serror = serror;
27349    ctxt->error = NULL;
27350    ctxt->warning = NULL;
27351    ctxt->errCtxt = ctx;
27352    if (ctxt->pctxt != NULL)
27353	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27354}
27355
27356/**
27357 * xmlSchemaGetValidErrors:
27358 * @ctxt:	a XML-Schema validation context
27359 * @err: the error function result
27360 * @warn: the warning function result
27361 * @ctx: the functions context result
27362 *
27363 * Get the error and warning callback informations
27364 *
27365 * Returns -1 in case of error and 0 otherwise
27366 */
27367int
27368xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27369			xmlSchemaValidityErrorFunc * err,
27370			xmlSchemaValidityWarningFunc * warn, void **ctx)
27371{
27372	if (ctxt == NULL)
27373		return (-1);
27374	if (err != NULL)
27375		*err = ctxt->error;
27376	if (warn != NULL)
27377		*warn = ctxt->warning;
27378	if (ctx != NULL)
27379		*ctx = ctxt->errCtxt;
27380	return (0);
27381}
27382
27383
27384/**
27385 * xmlSchemaSetValidOptions:
27386 * @ctxt:	a schema validation context
27387 * @options: a combination of xmlSchemaValidOption
27388 *
27389 * Sets the options to be used during the validation.
27390 *
27391 * Returns 0 in case of success, -1 in case of an
27392 * API error.
27393 */
27394int
27395xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27396			 int options)
27397
27398{
27399    int i;
27400
27401    if (ctxt == NULL)
27402	return (-1);
27403    /*
27404    * WARNING: Change the start value if adding to the
27405    * xmlSchemaValidOption.
27406    * TODO: Is there an other, more easy to maintain,
27407    * way?
27408    */
27409    for (i = 1; i < (int) sizeof(int) * 8; i++) {
27410        if (options & 1<<i)
27411	    return (-1);
27412    }
27413    ctxt->options = options;
27414    return (0);
27415}
27416
27417/**
27418 * xmlSchemaValidCtxtGetOptions:
27419 * @ctxt:	a schema validation context
27420 *
27421 * Get the validation context options.
27422 *
27423 * Returns the option combination or -1 on error.
27424 */
27425int
27426xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27427
27428{
27429    if (ctxt == NULL)
27430	return (-1);
27431    else
27432	return (ctxt->options);
27433}
27434
27435static int
27436xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27437{
27438    xmlAttrPtr attr;
27439    int ret = 0;
27440    xmlSchemaNodeInfoPtr ielem = NULL;
27441    xmlNodePtr node, valRoot;
27442    const xmlChar *nsName;
27443
27444    /* DOC VAL TODO: Move this to the start function. */
27445    valRoot = xmlDocGetRootElement(vctxt->doc);
27446    if (valRoot == NULL) {
27447	/* VAL TODO: Error code? */
27448	VERROR(1, NULL, "The document has no document element");
27449	return (1);
27450    }
27451    vctxt->depth = -1;
27452    vctxt->validationRoot = valRoot;
27453    node = valRoot;
27454    while (node != NULL) {
27455	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27456	    goto next_sibling;
27457	if (node->type == XML_ELEMENT_NODE) {
27458
27459	    /*
27460	    * Init the node-info.
27461	    */
27462	    vctxt->depth++;
27463	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27464		goto internal_error;
27465	    ielem = vctxt->inode;
27466	    ielem->node = node;
27467	    ielem->nodeLine = node->line;
27468	    ielem->localName = node->name;
27469	    if (node->ns != NULL)
27470		ielem->nsName = node->ns->href;
27471	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27472	    /*
27473	    * Register attributes.
27474	    * DOC VAL TODO: We do not register namespace declaration
27475	    * attributes yet.
27476	    */
27477	    vctxt->nbAttrInfos = 0;
27478	    if (node->properties != NULL) {
27479		attr = node->properties;
27480		do {
27481		    if (attr->ns != NULL)
27482			nsName = attr->ns->href;
27483		    else
27484			nsName = NULL;
27485		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27486			(xmlNodePtr) attr,
27487			/*
27488			* Note that we give it the line number of the
27489			* parent element.
27490			*/
27491			ielem->nodeLine,
27492			attr->name, nsName, 0,
27493			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27494		    if (ret == -1) {
27495			VERROR_INT("xmlSchemaDocWalk",
27496			    "calling xmlSchemaValidatorPushAttribute()");
27497			goto internal_error;
27498		    }
27499		    attr = attr->next;
27500		} while (attr);
27501	    }
27502	    /*
27503	    * Validate the element.
27504	    */
27505	    ret = xmlSchemaValidateElem(vctxt);
27506	    if (ret != 0) {
27507		if (ret == -1) {
27508		    VERROR_INT("xmlSchemaDocWalk",
27509			"calling xmlSchemaValidateElem()");
27510		    goto internal_error;
27511		}
27512		/*
27513		* Don't stop validation; just skip the content
27514		* of this element.
27515		*/
27516		goto leave_node;
27517	    }
27518	    if ((vctxt->skipDepth != -1) &&
27519		(vctxt->depth >= vctxt->skipDepth))
27520		goto leave_node;
27521	} else if ((node->type == XML_TEXT_NODE) ||
27522	    (node->type == XML_CDATA_SECTION_NODE)) {
27523	    /*
27524	    * Process character content.
27525	    */
27526	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27527		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27528	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27529		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27530	    if (ret < 0) {
27531		VERROR_INT("xmlSchemaVDocWalk",
27532		    "calling xmlSchemaVPushText()");
27533		goto internal_error;
27534	    }
27535	    /*
27536	    * DOC VAL TODO: Should we skip further validation of the
27537	    * element content here?
27538	    */
27539	} else if ((node->type == XML_ENTITY_NODE) ||
27540	    (node->type == XML_ENTITY_REF_NODE)) {
27541	    /*
27542	    * DOC VAL TODO: What to do with entities?
27543	    */
27544	    VERROR_INT("xmlSchemaVDocWalk",
27545		"there is at least one entity reference in the node-tree "
27546		"currently being validated. Processing of entities with "
27547		"this XML Schema processor is not supported (yet). Please "
27548		"substitute entities before validation.");
27549	    goto internal_error;
27550	} else {
27551	    goto leave_node;
27552	    /*
27553	    * DOC VAL TODO: XInclude nodes, etc.
27554	    */
27555	}
27556	/*
27557	* Walk the doc.
27558	*/
27559	if (node->children != NULL) {
27560	    node = node->children;
27561	    continue;
27562	}
27563leave_node:
27564	if (node->type == XML_ELEMENT_NODE) {
27565	    /*
27566	    * Leaving the scope of an element.
27567	    */
27568	    if (node != vctxt->inode->node) {
27569		VERROR_INT("xmlSchemaVDocWalk",
27570		    "element position mismatch");
27571		goto internal_error;
27572	    }
27573	    ret = xmlSchemaValidatorPopElem(vctxt);
27574	    if (ret != 0) {
27575		if (ret < 0) {
27576		    VERROR_INT("xmlSchemaVDocWalk",
27577			"calling xmlSchemaValidatorPopElem()");
27578		    goto internal_error;
27579		}
27580	    }
27581	    if (node == valRoot)
27582		goto exit;
27583	}
27584next_sibling:
27585	if (node->next != NULL)
27586	    node = node->next;
27587	else {
27588	    node = node->parent;
27589	    goto leave_node;
27590	}
27591    }
27592
27593exit:
27594    return (ret);
27595internal_error:
27596    return (-1);
27597}
27598
27599static int
27600xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27601    /*
27602    * Some initialization.
27603    */
27604    vctxt->err = 0;
27605    vctxt->nberrors = 0;
27606    vctxt->depth = -1;
27607    vctxt->skipDepth = -1;
27608    vctxt->xsiAssemble = 0;
27609    vctxt->hasKeyrefs = 0;
27610#ifdef ENABLE_IDC_NODE_TABLES_TEST
27611    vctxt->createIDCNodeTables = 1;
27612#else
27613    vctxt->createIDCNodeTables = 0;
27614#endif
27615    /*
27616    * Create a schema + parser if necessary.
27617    */
27618    if (vctxt->schema == NULL) {
27619	xmlSchemaParserCtxtPtr pctxt;
27620
27621	vctxt->xsiAssemble = 1;
27622	/*
27623	* If not schema was given then we will create a schema
27624	* dynamically using XSI schema locations.
27625	*
27626	* Create the schema parser context.
27627	*/
27628	if ((vctxt->pctxt == NULL) &&
27629	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27630	   return (-1);
27631	pctxt = vctxt->pctxt;
27632	pctxt->xsiAssemble = 1;
27633	/*
27634	* Create the schema.
27635	*/
27636	vctxt->schema = xmlSchemaNewSchema(pctxt);
27637	if (vctxt->schema == NULL)
27638	    return (-1);
27639	/*
27640	* Create the schema construction context.
27641	*/
27642	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27643	if (pctxt->constructor == NULL)
27644	    return(-1);
27645	pctxt->constructor->mainSchema = vctxt->schema;
27646	/*
27647	* Take ownership of the constructor to be able to free it.
27648	*/
27649	pctxt->ownsConstructor = 1;
27650    }
27651    /*
27652    * Augment the IDC definitions.
27653    */
27654    if (vctxt->schema->idcDef != NULL) {
27655	xmlHashScan(vctxt->schema->idcDef,
27656	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27657    }
27658    return(0);
27659}
27660
27661static void
27662xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
27663    if (vctxt->xsiAssemble) {
27664	if (vctxt->schema != NULL) {
27665	    xmlSchemaFree(vctxt->schema);
27666	    vctxt->schema = NULL;
27667	}
27668    }
27669    xmlSchemaClearValidCtxt(vctxt);
27670}
27671
27672static int
27673xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27674{
27675    int ret = 0;
27676
27677    if (xmlSchemaPreRun(vctxt) < 0)
27678        return(-1);
27679
27680    if (vctxt->doc != NULL) {
27681	/*
27682	 * Tree validation.
27683	 */
27684	ret = xmlSchemaVDocWalk(vctxt);
27685#ifdef LIBXML_READER_ENABLED
27686    } else if (vctxt->reader != NULL) {
27687	/*
27688	 * XML Reader validation.
27689	 */
27690#ifdef XML_SCHEMA_READER_ENABLED
27691	ret = xmlSchemaVReaderWalk(vctxt);
27692#endif
27693#endif
27694    } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27695	/*
27696	 * SAX validation.
27697	 */
27698	ret = xmlParseDocument(vctxt->parserCtxt);
27699    } else {
27700	VERROR_INT("xmlSchemaVStart",
27701	    "no instance to validate");
27702	ret = -1;
27703    }
27704
27705    xmlSchemaPostRun(vctxt);
27706    if (ret == 0)
27707	ret = vctxt->err;
27708    return (ret);
27709}
27710
27711/**
27712 * xmlSchemaValidateOneElement:
27713 * @ctxt:  a schema validation context
27714 * @elem:  an element node
27715 *
27716 * Validate a branch of a tree, starting with the given @elem.
27717 *
27718 * Returns 0 if the element and its subtree is valid, a positive error
27719 * code number otherwise and -1 in case of an internal or API error.
27720 */
27721int
27722xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27723{
27724    if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27725	return (-1);
27726
27727    if (ctxt->schema == NULL)
27728	return (-1);
27729
27730    ctxt->doc = elem->doc;
27731    ctxt->node = elem;
27732    ctxt->validationRoot = elem;
27733    return(xmlSchemaVStart(ctxt));
27734}
27735
27736/**
27737 * xmlSchemaValidateDoc:
27738 * @ctxt:  a schema validation context
27739 * @doc:  a parsed document tree
27740 *
27741 * Validate a document tree in memory.
27742 *
27743 * Returns 0 if the document is schemas valid, a positive error code
27744 *     number otherwise and -1 in case of internal or API error.
27745 */
27746int
27747xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27748{
27749    if ((ctxt == NULL) || (doc == NULL))
27750        return (-1);
27751
27752    ctxt->doc = doc;
27753    ctxt->node = xmlDocGetRootElement(doc);
27754    if (ctxt->node == NULL) {
27755        xmlSchemaCustomErr(ACTXT_CAST ctxt,
27756	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
27757	    (xmlNodePtr) doc, NULL,
27758	    "The document has no document element", NULL, NULL);
27759        return (ctxt->err);
27760    }
27761    ctxt->validationRoot = ctxt->node;
27762    return (xmlSchemaVStart(ctxt));
27763}
27764
27765
27766/************************************************************************
27767 * 									*
27768 * 		Function and data for SAX streaming API			*
27769 * 									*
27770 ************************************************************************/
27771typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
27772typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
27773
27774struct _xmlSchemaSplitSAXData {
27775    xmlSAXHandlerPtr      user_sax;
27776    void                 *user_data;
27777    xmlSchemaValidCtxtPtr ctxt;
27778    xmlSAXHandlerPtr      schemas_sax;
27779};
27780
27781#define XML_SAX_PLUG_MAGIC 0xdc43ba21
27782
27783struct _xmlSchemaSAXPlug {
27784    unsigned int magic;
27785
27786    /* the original callbacks informations */
27787    xmlSAXHandlerPtr     *user_sax_ptr;
27788    xmlSAXHandlerPtr      user_sax;
27789    void                **user_data_ptr;
27790    void                 *user_data;
27791
27792    /* the block plugged back and validation informations */
27793    xmlSAXHandler         schemas_sax;
27794    xmlSchemaValidCtxtPtr ctxt;
27795};
27796
27797/* All those functions just bounces to the user provided SAX handlers */
27798static void
27799internalSubsetSplit(void *ctx, const xmlChar *name,
27800	       const xmlChar *ExternalID, const xmlChar *SystemID)
27801{
27802    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27803    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27804        (ctxt->user_sax->internalSubset != NULL))
27805	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27806	                               SystemID);
27807}
27808
27809static int
27810isStandaloneSplit(void *ctx)
27811{
27812    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27813    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27814        (ctxt->user_sax->isStandalone != NULL))
27815	return(ctxt->user_sax->isStandalone(ctxt->user_data));
27816    return(0);
27817}
27818
27819static int
27820hasInternalSubsetSplit(void *ctx)
27821{
27822    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27823    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27824        (ctxt->user_sax->hasInternalSubset != NULL))
27825	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
27826    return(0);
27827}
27828
27829static int
27830hasExternalSubsetSplit(void *ctx)
27831{
27832    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27833    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27834        (ctxt->user_sax->hasExternalSubset != NULL))
27835	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
27836    return(0);
27837}
27838
27839static void
27840externalSubsetSplit(void *ctx, const xmlChar *name,
27841	       const xmlChar *ExternalID, const xmlChar *SystemID)
27842{
27843    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27844    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27845        (ctxt->user_sax->internalSubset != NULL))
27846	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
27847	                               SystemID);
27848}
27849
27850static xmlParserInputPtr
27851resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
27852{
27853    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27854    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27855        (ctxt->user_sax->resolveEntity != NULL))
27856	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
27857	                                     systemId));
27858    return(NULL);
27859}
27860
27861static xmlEntityPtr
27862getEntitySplit(void *ctx, const xmlChar *name)
27863{
27864    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27865    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27866        (ctxt->user_sax->getEntity != NULL))
27867	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
27868    return(NULL);
27869}
27870
27871static xmlEntityPtr
27872getParameterEntitySplit(void *ctx, const xmlChar *name)
27873{
27874    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27875    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27876        (ctxt->user_sax->getParameterEntity != NULL))
27877	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
27878    return(NULL);
27879}
27880
27881
27882static void
27883entityDeclSplit(void *ctx, const xmlChar *name, int type,
27884          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
27885{
27886    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27887    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27888        (ctxt->user_sax->entityDecl != NULL))
27889	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
27890	                           systemId, content);
27891}
27892
27893static void
27894attributeDeclSplit(void *ctx, const xmlChar * elem,
27895                   const xmlChar * name, int type, int def,
27896                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
27897{
27898    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27899    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27900        (ctxt->user_sax->attributeDecl != NULL)) {
27901	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
27902	                              def, defaultValue, tree);
27903    } else {
27904	xmlFreeEnumeration(tree);
27905    }
27906}
27907
27908static void
27909elementDeclSplit(void *ctx, const xmlChar *name, int type,
27910	    xmlElementContentPtr content)
27911{
27912    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27913    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27914        (ctxt->user_sax->elementDecl != NULL))
27915	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
27916}
27917
27918static void
27919notationDeclSplit(void *ctx, const xmlChar *name,
27920	     const xmlChar *publicId, const xmlChar *systemId)
27921{
27922    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27923    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27924        (ctxt->user_sax->notationDecl != NULL))
27925	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
27926	                             systemId);
27927}
27928
27929static void
27930unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
27931		   const xmlChar *publicId, const xmlChar *systemId,
27932		   const xmlChar *notationName)
27933{
27934    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27935    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27936        (ctxt->user_sax->unparsedEntityDecl != NULL))
27937	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
27938	                                   systemId, notationName);
27939}
27940
27941static void
27942setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
27943{
27944    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27945    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27946        (ctxt->user_sax->setDocumentLocator != NULL))
27947	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
27948}
27949
27950static void
27951startDocumentSplit(void *ctx)
27952{
27953    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27954    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27955        (ctxt->user_sax->startDocument != NULL))
27956	ctxt->user_sax->startDocument(ctxt->user_data);
27957}
27958
27959static void
27960endDocumentSplit(void *ctx)
27961{
27962    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27963    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27964        (ctxt->user_sax->endDocument != NULL))
27965	ctxt->user_sax->endDocument(ctxt->user_data);
27966}
27967
27968static void
27969processingInstructionSplit(void *ctx, const xmlChar *target,
27970                      const xmlChar *data)
27971{
27972    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27973    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27974        (ctxt->user_sax->processingInstruction != NULL))
27975	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
27976}
27977
27978static void
27979commentSplit(void *ctx, const xmlChar *value)
27980{
27981    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27982    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27983        (ctxt->user_sax->comment != NULL))
27984	ctxt->user_sax->comment(ctxt->user_data, value);
27985}
27986
27987/*
27988 * Varargs error callbacks to the user application, harder ...
27989 */
27990
27991static void XMLCDECL
27992warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
27993    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
27994    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
27995        (ctxt->user_sax->warning != NULL)) {
27996	TODO
27997    }
27998}
27999static void XMLCDECL
28000errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28001    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28002    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28003        (ctxt->user_sax->error != NULL)) {
28004	TODO
28005    }
28006}
28007static void XMLCDECL
28008fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28009    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28010    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28011        (ctxt->user_sax->fatalError != NULL)) {
28012	TODO
28013    }
28014}
28015
28016/*
28017 * Those are function where both the user handler and the schemas handler
28018 * need to be called.
28019 */
28020static void
28021charactersSplit(void *ctx, const xmlChar *ch, int len)
28022{
28023    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28024    if (ctxt == NULL)
28025        return;
28026    if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28027	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28028    if (ctxt->ctxt != NULL)
28029	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28030}
28031
28032static void
28033ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28034{
28035    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28036    if (ctxt == NULL)
28037        return;
28038    if ((ctxt->user_sax != NULL) &&
28039        (ctxt->user_sax->ignorableWhitespace != NULL))
28040	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28041    if (ctxt->ctxt != NULL)
28042	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28043}
28044
28045static void
28046cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28047{
28048    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28049    if (ctxt == NULL)
28050        return;
28051    if ((ctxt->user_sax != NULL) &&
28052        (ctxt->user_sax->ignorableWhitespace != NULL))
28053	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
28054    if (ctxt->ctxt != NULL)
28055	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28056}
28057
28058static void
28059referenceSplit(void *ctx, const xmlChar *name)
28060{
28061    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28062    if (ctxt == NULL)
28063        return;
28064    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28065        (ctxt->user_sax->reference != NULL))
28066	ctxt->user_sax->reference(ctxt->user_data, name);
28067    if (ctxt->ctxt != NULL)
28068        xmlSchemaSAXHandleReference(ctxt->user_data, name);
28069}
28070
28071static void
28072startElementNsSplit(void *ctx, const xmlChar * localname,
28073		    const xmlChar * prefix, const xmlChar * URI,
28074		    int nb_namespaces, const xmlChar ** namespaces,
28075		    int nb_attributes, int nb_defaulted,
28076		    const xmlChar ** attributes) {
28077    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28078    if (ctxt == NULL)
28079        return;
28080    if ((ctxt->user_sax != NULL) &&
28081        (ctxt->user_sax->startElementNs != NULL))
28082	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28083	                               URI, nb_namespaces, namespaces,
28084				       nb_attributes, nb_defaulted,
28085				       attributes);
28086    if (ctxt->ctxt != NULL)
28087	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28088	                                 URI, nb_namespaces, namespaces,
28089					 nb_attributes, nb_defaulted,
28090					 attributes);
28091}
28092
28093static void
28094endElementNsSplit(void *ctx, const xmlChar * localname,
28095		    const xmlChar * prefix, const xmlChar * URI) {
28096    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28097    if (ctxt == NULL)
28098        return;
28099    if ((ctxt->user_sax != NULL) &&
28100        (ctxt->user_sax->endElementNs != NULL))
28101	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28102    if (ctxt->ctxt != NULL)
28103	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28104}
28105
28106/**
28107 * xmlSchemaSAXPlug:
28108 * @ctxt:  a schema validation context
28109 * @sax:  a pointer to the original xmlSAXHandlerPtr
28110 * @user_data:  a pointer to the original SAX user data pointer
28111 *
28112 * Plug a SAX based validation layer in a SAX parsing event flow.
28113 * The original @saxptr and @dataptr data are replaced by new pointers
28114 * but the calls to the original will be maintained.
28115 *
28116 * Returns a pointer to a data structure needed to unplug the validation layer
28117 *         or NULL in case of errors.
28118 */
28119xmlSchemaSAXPlugPtr
28120xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28121		 xmlSAXHandlerPtr *sax, void **user_data)
28122{
28123    xmlSchemaSAXPlugPtr ret;
28124    xmlSAXHandlerPtr old_sax;
28125
28126    if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28127        return(NULL);
28128
28129    /*
28130     * We only allow to plug into SAX2 event streams
28131     */
28132    old_sax = *sax;
28133    if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28134        return(NULL);
28135    if ((old_sax != NULL) &&
28136        (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28137        ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28138        return(NULL);
28139
28140    /*
28141     * everything seems right allocate the local data needed for that layer
28142     */
28143    ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28144    if (ret == NULL) {
28145        return(NULL);
28146    }
28147    memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28148    ret->magic = XML_SAX_PLUG_MAGIC;
28149    ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28150    ret->ctxt = ctxt;
28151    ret->user_sax_ptr = sax;
28152    ret->user_sax = old_sax;
28153    if (old_sax == NULL) {
28154        /*
28155	 * go direct, no need for the split block and functions.
28156	 */
28157	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28158	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28159	/*
28160	 * Note that we use the same text-function for both, to prevent
28161	 * the parser from testing for ignorable whitespace.
28162	 */
28163	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28164	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28165
28166	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28167	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28168
28169	ret->user_data = ctxt;
28170	*user_data = ctxt;
28171    } else {
28172       /*
28173        * for each callback unused by Schemas initialize it to the Split
28174	* routine only if non NULL in the user block, this can speed up
28175	* things at the SAX level.
28176	*/
28177        if (old_sax->internalSubset != NULL)
28178            ret->schemas_sax.internalSubset = internalSubsetSplit;
28179        if (old_sax->isStandalone != NULL)
28180            ret->schemas_sax.isStandalone = isStandaloneSplit;
28181        if (old_sax->hasInternalSubset != NULL)
28182            ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28183        if (old_sax->hasExternalSubset != NULL)
28184            ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28185        if (old_sax->resolveEntity != NULL)
28186            ret->schemas_sax.resolveEntity = resolveEntitySplit;
28187        if (old_sax->getEntity != NULL)
28188            ret->schemas_sax.getEntity = getEntitySplit;
28189        if (old_sax->entityDecl != NULL)
28190            ret->schemas_sax.entityDecl = entityDeclSplit;
28191        if (old_sax->notationDecl != NULL)
28192            ret->schemas_sax.notationDecl = notationDeclSplit;
28193        if (old_sax->attributeDecl != NULL)
28194            ret->schemas_sax.attributeDecl = attributeDeclSplit;
28195        if (old_sax->elementDecl != NULL)
28196            ret->schemas_sax.elementDecl = elementDeclSplit;
28197        if (old_sax->unparsedEntityDecl != NULL)
28198            ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28199        if (old_sax->setDocumentLocator != NULL)
28200            ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28201        if (old_sax->startDocument != NULL)
28202            ret->schemas_sax.startDocument = startDocumentSplit;
28203        if (old_sax->endDocument != NULL)
28204            ret->schemas_sax.endDocument = endDocumentSplit;
28205        if (old_sax->processingInstruction != NULL)
28206            ret->schemas_sax.processingInstruction = processingInstructionSplit;
28207        if (old_sax->comment != NULL)
28208            ret->schemas_sax.comment = commentSplit;
28209        if (old_sax->warning != NULL)
28210            ret->schemas_sax.warning = warningSplit;
28211        if (old_sax->error != NULL)
28212            ret->schemas_sax.error = errorSplit;
28213        if (old_sax->fatalError != NULL)
28214            ret->schemas_sax.fatalError = fatalErrorSplit;
28215        if (old_sax->getParameterEntity != NULL)
28216            ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28217        if (old_sax->externalSubset != NULL)
28218            ret->schemas_sax.externalSubset = externalSubsetSplit;
28219
28220	/*
28221	 * the 6 schemas callback have to go to the splitter functions
28222	 * Note that we use the same text-function for ignorableWhitespace
28223	 * if possible, to prevent the parser from testing for ignorable
28224	 * whitespace.
28225	 */
28226        ret->schemas_sax.characters = charactersSplit;
28227	if ((old_sax->ignorableWhitespace != NULL) &&
28228	    (old_sax->ignorableWhitespace != old_sax->characters))
28229	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28230	else
28231	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28232        ret->schemas_sax.cdataBlock = cdataBlockSplit;
28233        ret->schemas_sax.reference = referenceSplit;
28234        ret->schemas_sax.startElementNs = startElementNsSplit;
28235        ret->schemas_sax.endElementNs = endElementNsSplit;
28236
28237	ret->user_data_ptr = user_data;
28238	ret->user_data = *user_data;
28239	*user_data = ret;
28240    }
28241
28242    /*
28243     * plug the pointers back.
28244     */
28245    *sax = &(ret->schemas_sax);
28246    ctxt->sax = *sax;
28247    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28248    xmlSchemaPreRun(ctxt);
28249    return(ret);
28250}
28251
28252/**
28253 * xmlSchemaSAXUnplug:
28254 * @plug:  a data structure returned by xmlSchemaSAXPlug
28255 *
28256 * Unplug a SAX based validation layer in a SAX parsing event flow.
28257 * The original pointers used in the call are restored.
28258 *
28259 * Returns 0 in case of success and -1 in case of failure.
28260 */
28261int
28262xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28263{
28264    xmlSAXHandlerPtr *sax;
28265    void **user_data;
28266
28267    if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28268        return(-1);
28269    plug->magic = 0;
28270
28271    xmlSchemaPostRun(plug->ctxt);
28272    /* restore the data */
28273    sax = plug->user_sax_ptr;
28274    *sax = plug->user_sax;
28275    if (plug->user_sax != NULL) {
28276	user_data = plug->user_data_ptr;
28277	*user_data = plug->user_data;
28278    }
28279
28280    /* free and return */
28281    xmlFree(plug);
28282    return(0);
28283}
28284
28285/**
28286 * xmlSchemaValidateStream:
28287 * @ctxt:  a schema validation context
28288 * @input:  the input to use for reading the data
28289 * @enc:  an optional encoding information
28290 * @sax:  a SAX handler for the resulting events
28291 * @user_data:  the context to provide to the SAX handler.
28292 *
28293 * Validate an input based on a flow of SAX event from the parser
28294 * and forward the events to the @sax handler with the provided @user_data
28295 * the user provided @sax handler must be a SAX2 one.
28296 *
28297 * Returns 0 if the document is schemas valid, a positive error code
28298 *     number otherwise and -1 in case of internal or API error.
28299 */
28300int
28301xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28302                        xmlParserInputBufferPtr input, xmlCharEncoding enc,
28303                        xmlSAXHandlerPtr sax, void *user_data)
28304{
28305    xmlSchemaSAXPlugPtr plug = NULL;
28306    xmlSAXHandlerPtr old_sax = NULL;
28307    xmlParserCtxtPtr pctxt = NULL;
28308    xmlParserInputPtr inputStream = NULL;
28309    int ret;
28310
28311    if ((ctxt == NULL) || (input == NULL))
28312        return (-1);
28313
28314    /*
28315     * prepare the parser
28316     */
28317    pctxt = xmlNewParserCtxt();
28318    if (pctxt == NULL)
28319        return (-1);
28320    old_sax = pctxt->sax;
28321    pctxt->sax = sax;
28322    pctxt->userData = user_data;
28323#if 0
28324    if (options)
28325        xmlCtxtUseOptions(pctxt, options);
28326#endif
28327    pctxt->linenumbers = 1;
28328
28329    inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28330    if (inputStream == NULL) {
28331        ret = -1;
28332	goto done;
28333    }
28334    inputPush(pctxt, inputStream);
28335    ctxt->parserCtxt = pctxt;
28336    ctxt->input = input;
28337
28338    /*
28339     * Plug the validation and launch the parsing
28340     */
28341    plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28342    if (plug == NULL) {
28343        ret = -1;
28344	goto done;
28345    }
28346    ctxt->input = input;
28347    ctxt->enc = enc;
28348    ctxt->sax = pctxt->sax;
28349    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28350    ret = xmlSchemaVStart(ctxt);
28351
28352    if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28353	ret = ctxt->parserCtxt->errNo;
28354	if (ret == 0)
28355	    ret = 1;
28356    }
28357
28358done:
28359    ctxt->parserCtxt = NULL;
28360    ctxt->sax = NULL;
28361    ctxt->input = NULL;
28362    if (plug != NULL) {
28363        xmlSchemaSAXUnplug(plug);
28364    }
28365    /* cleanup */
28366    if (pctxt != NULL) {
28367	pctxt->sax = old_sax;
28368	xmlFreeParserCtxt(pctxt);
28369    }
28370    return (ret);
28371}
28372
28373/**
28374 * xmlSchemaValidateFile:
28375 * @ctxt: a schema validation context
28376 * @filename: the URI of the instance
28377 * @options: a future set of options, currently unused
28378 *
28379 * Do a schemas validation of the given resource, it will use the
28380 * SAX streamable validation internally.
28381 *
28382 * Returns 0 if the document is valid, a positive error code
28383 *     number otherwise and -1 in case of an internal or API error.
28384 */
28385int
28386xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28387                      const char * filename,
28388		      int options ATTRIBUTE_UNUSED)
28389{
28390    int ret;
28391    xmlParserInputBufferPtr input;
28392
28393    if ((ctxt == NULL) || (filename == NULL))
28394        return (-1);
28395
28396    input = xmlParserInputBufferCreateFilename(filename,
28397	XML_CHAR_ENCODING_NONE);
28398    if (input == NULL)
28399	return (-1);
28400    ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28401	NULL, NULL);
28402    return (ret);
28403}
28404
28405#define bottom_xmlschemas
28406#include "elfgcchack.h"
28407#endif /* LIBXML_SCHEMAS_ENABLED */
28408