• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gnulib-local/lib/libxml/
1/*
2 * schemas.c : implementation of the XML Schema handling and
3 *             schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
10/*
11 * TODO:
12 *   - when types are redefined in includes, check that all
13 *     types in the redef list are equal
14 *     -> need a type equality operation.
15 *   - if we don't intend to use the schema for schemas, we
16 *     need to validate all schema attributes (ref, type, name)
17 *     against their types.
18 *   - Eliminate item creation for: ??
19 *
20 * URGENT TODO:
21 *   - For xsi-driven schema acquisition, augment the IDCs after every
22 *     acquisition episode (xmlSchemaAugmentIDC).
23 *
24 * NOTES:
25 *   - Elimated item creation for: <restriction>, <extension>,
26 *     <simpleContent>, <complexContent>, <list>, <union>
27 *
28 * PROBLEMS:
29 *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30 *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31 *     XPath will have trouble to resolve to this namespace, since not known.
32 *
33 *
34 * CONSTRAINTS:
35 *
36 * Schema Component Constraint:
37 *   All Group Limited (cos-all-limited)
38 *   Status: complete
39 *   (1.2)
40 *     In xmlSchemaGroupDefReferenceTermFixup() and
41 *   (2)
42 *     In xmlSchemaParseModelGroup()
43 *     TODO: Actually this should go to component-level checks,
44 *     but is done here due to performance. Move it to an other layer
45 *     is schema construction via an API is implemented.
46 */
47#define IN_LIBXML
48#include "libxml.h"
49
50#ifdef LIBXML_SCHEMAS_ENABLED
51
52#include <string.h>
53#include <libxml/xmlmemory.h>
54#include <libxml/parser.h>
55#include <libxml/parserInternals.h>
56#include <libxml/hash.h>
57#include <libxml/uri.h>
58#include <libxml/xmlschemas.h>
59#include <libxml/schemasInternals.h>
60#include <libxml/xmlschemastypes.h>
61#include <libxml/xmlautomata.h>
62#include <libxml/xmlregexp.h>
63#include <libxml/dict.h>
64#include <libxml/encoding.h>
65#include <libxml/xmlIO.h>
66#ifdef LIBXML_PATTERN_ENABLED
67#include <libxml/pattern.h>
68#endif
69#ifdef LIBXML_READER_ENABLED
70#include <libxml/xmlreader.h>
71#endif
72
73/* #define DEBUG 1 */
74
75/* #define DEBUG_CONTENT 1 */
76
77/* #define DEBUG_TYPE 1 */
78
79/* #define DEBUG_CONTENT_REGEXP 1 */
80
81/* #define DEBUG_AUTOMATA 1 */
82
83/* #define DEBUG_IDC */
84
85/* #define DEBUG_IDC_NODE_TABLE */
86
87/* #define WXS_ELEM_DECL_CONS_ENABLED */
88
89#ifdef DEBUG_IDC
90 #ifndef DEBUG_IDC_NODE_TABLE
91  #define DEBUG_IDC_NODE_TABLE
92 #endif
93#endif
94
95/* #define ENABLE_PARTICLE_RESTRICTION 1 */
96
97#define ENABLE_REDEFINE
98
99/* #define ENABLE_NAMED_LOCALS */
100
101/* #define ENABLE_IDC_NODE_TABLES_TEST */
102
103#define DUMP_CONTENT_MODEL
104
105#ifdef LIBXML_READER_ENABLED
106/* #define XML_SCHEMA_READER_ENABLED */
107#endif
108
109#define UNBOUNDED (1 << 30)
110#define TODO 								\
111    xmlGenericError(xmlGenericErrorContext,				\
112	    "Unimplemented block at %s:%d\n",				\
113            __FILE__, __LINE__);
114
115#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
116
117/*
118 * The XML Schemas namespaces
119 */
120static const xmlChar *xmlSchemaNs = (const xmlChar *)
121    "http://www.w3.org/2001/XMLSchema";
122
123static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124    "http://www.w3.org/2001/XMLSchema-instance";
125
126static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127    "http://www.w3.org/2000/xmlns/";
128
129/*
130* Come casting macros.
131*/
132#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
133#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
134#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
135#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
136#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
137#define WXS_PTC_CAST (xmlSchemaParticlePtr)
138#define WXS_TYPE_CAST (xmlSchemaTypePtr)
139#define WXS_ELEM_CAST (xmlSchemaElementPtr)
140#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
141#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
142#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
143#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
144#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
145#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
146#define WXS_IDC_CAST (xmlSchemaIDCPtr)
147#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
148#define WXS_LIST_CAST (xmlSchemaItemListPtr)
149
150/*
151* Macros to query common properties of components.
152*/
153#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
154
155#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
156/*
157* Macros for element declarations.
158*/
159#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
160
161#define WXS_SUBST_HEAD(item) (item)->refDecl
162/*
163* Macros for attribute declarations.
164*/
165#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
166/*
167* Macros for attribute uses.
168*/
169#define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
170
171#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
172
173#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
174
175#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
176/*
177* Macros for attribute groups.
178*/
179#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
180#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
181/*
182* Macros for particles.
183*/
184#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
185
186#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
187
188#define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
189
190#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
191/*
192* Macros for model groups definitions.
193*/
194#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
195/*
196* Macros for model groups.
197*/
198#define WXS_IS_MODEL_GROUP(i) \
199    (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
200     ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
201     ((i)->type == XML_SCHEMA_TYPE_ALL))
202
203#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
204/*
205* Macros for schema buckets.
206*/
207#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
208    ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
209
210#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
211    ((t) == XML_SCHEMA_SCHEMA_IMPORT))
212
213#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
214
215#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
216/*
217* Macros for complex/simple types.
218*/
219#define WXS_IS_ANYTYPE(i) \
220     (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
221      ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
222
223#define WXS_IS_COMPLEX(i) \
224    (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
225     ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
226
227#define WXS_IS_SIMPLE(item) \
228    ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
229     ((item->type == XML_SCHEMA_TYPE_BASIC) && \
230      (item->builtInType != XML_SCHEMAS_ANYTYPE)))
231
232#define WXS_IS_ANY_SIMPLE_TYPE(i) \
233    (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
234      ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
235
236#define WXS_IS_RESTRICTION(t) \
237    ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
238
239#define WXS_IS_EXTENSION(t) \
240    ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
241
242#define WXS_IS_TYPE_NOT_FIXED(i) \
243    (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
244     (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
245
246#define WXS_IS_TYPE_NOT_FIXED_1(item) \
247    (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
248     (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
249
250#define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
251
252#define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
253/*
254* Macros for exclusively for complex types.
255*/
256#define WXS_HAS_COMPLEX_CONTENT(item) \
257    ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
258     (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
259     (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
260
261#define WXS_HAS_SIMPLE_CONTENT(item) \
262    ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
263     (item->contentType == XML_SCHEMA_CONTENT_BASIC))
264
265#define WXS_HAS_MIXED_CONTENT(item) \
266    (item->contentType == XML_SCHEMA_CONTENT_MIXED)
267
268#define WXS_EMPTIABLE(t) \
269    (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
270
271#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
272
273#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
274
275#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
276/*
277* Macros for exclusively for simple types.
278*/
279#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
280
281#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
282
283#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
284
285#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
286/*
287* Misc parser context macros.
288*/
289#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
290
291#define WXS_HAS_BUCKETS(ctx) \
292( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
293(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
294
295#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
296
297#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
298
299#define WXS_SCHEMA(ctx) (ctx)->schema
300
301#define WXS_ADD_LOCAL(ctx, item) \
302    xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
303
304#define WXS_ADD_GLOBAL(ctx, item) \
305    xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
306
307#define WXS_ADD_PENDING(ctx, item) \
308    xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
309/*
310* xmlSchemaItemList macros.
311*/
312#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
313/*
314* Misc macros.
315*/
316#define IS_SCHEMA(node, type) \
317   ((node != NULL) && (node->ns != NULL) && \
318    (xmlStrEqual(node->name, (const xmlChar *) type)) && \
319    (xmlStrEqual(node->ns->href, xmlSchemaNs)))
320
321#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
322
323/*
324* Since we put the default/fixed values into the dict, we can
325* use pointer comparison for those values.
326* REMOVED: (xmlStrEqual((v1), (v2)))
327*/
328#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
329
330#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
331
332#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
333
334#define HFAILURE if (res == -1) goto exit_failure;
335
336#define HERROR if (res != 0) goto exit_error;
337
338#define HSTOP(ctx) if ((ctx)->stop) goto exit;
339/*
340* Some flags used for various schema constraints.
341*/
342#define SUBSET_RESTRICTION  1<<0
343#define SUBSET_EXTENSION    1<<1
344#define SUBSET_SUBSTITUTION 1<<2
345#define SUBSET_LIST         1<<3
346#define SUBSET_UNION        1<<4
347
348typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
350
351typedef struct _xmlSchemaItemList xmlSchemaItemList;
352typedef xmlSchemaItemList *xmlSchemaItemListPtr;
353struct _xmlSchemaItemList {
354    void **items;  /* used for dynamic addition of schemata */
355    int nbItems; /* used for dynamic addition of schemata */
356    int sizeItems; /* used for dynamic addition of schemata */
357};
358
359#define XML_SCHEMA_CTXT_PARSER 1
360#define XML_SCHEMA_CTXT_VALIDATOR 2
361
362typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364struct _xmlSchemaAbstractCtxt {
365    int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
366};
367
368typedef struct _xmlSchemaBucket xmlSchemaBucket;
369typedef xmlSchemaBucket *xmlSchemaBucketPtr;
370
371#define XML_SCHEMA_SCHEMA_MAIN 0
372#define XML_SCHEMA_SCHEMA_IMPORT 1
373#define XML_SCHEMA_SCHEMA_INCLUDE 2
374#define XML_SCHEMA_SCHEMA_REDEFINE 3
375
376/**
377 * xmlSchemaSchemaRelation:
378 *
379 * Used to create a graph of schema relationships.
380 */
381typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383struct _xmlSchemaSchemaRelation {
384    xmlSchemaSchemaRelationPtr next;
385    int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386    const xmlChar *importNamespace;
387    xmlSchemaBucketPtr bucket;
388};
389
390#define XML_SCHEMA_BUCKET_MARKED 1<<0
391#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
392
393struct _xmlSchemaBucket {
394    int type;
395    int flags;
396    const xmlChar *schemaLocation;
397    const xmlChar *origTargetNamespace;
398    const xmlChar *targetNamespace;
399    xmlDocPtr doc;
400    xmlSchemaSchemaRelationPtr relations;
401    int located;
402    int parsed;
403    int imported;
404    int preserveDoc;
405    xmlSchemaItemListPtr globals; /* Global components. */
406    xmlSchemaItemListPtr locals; /* Local components. */
407};
408
409/**
410 * xmlSchemaImport:
411 * (extends xmlSchemaBucket)
412 *
413 * Reflects a schema. Holds some information
414 * about the schema and its toplevel components. Duplicate
415 * toplevel components are not checked at this level.
416 */
417typedef struct _xmlSchemaImport xmlSchemaImport;
418typedef xmlSchemaImport *xmlSchemaImportPtr;
419struct _xmlSchemaImport {
420    int type; /* Main OR import OR include. */
421    int flags;
422    const xmlChar *schemaLocation; /* The URI of the schema document. */
423    /* For chameleon includes, @origTargetNamespace will be NULL */
424    const xmlChar *origTargetNamespace;
425    /*
426    * For chameleon includes, @targetNamespace will be the
427    * targetNamespace of the including schema.
428    */
429    const xmlChar *targetNamespace;
430    xmlDocPtr doc; /* The schema node-tree. */
431    /* @relations will hold any included/imported/redefined schemas. */
432    xmlSchemaSchemaRelationPtr relations;
433    int located;
434    int parsed;
435    int imported;
436    int preserveDoc;
437    xmlSchemaItemListPtr globals;
438    xmlSchemaItemListPtr locals;
439    /* The imported schema. */
440    xmlSchemaPtr schema;
441};
442
443/*
444* (extends xmlSchemaBucket)
445*/
446typedef struct _xmlSchemaInclude xmlSchemaInclude;
447typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448struct _xmlSchemaInclude {
449    int type;
450    int flags;
451    const xmlChar *schemaLocation;
452    const xmlChar *origTargetNamespace;
453    const xmlChar *targetNamespace;
454    xmlDocPtr doc;
455    xmlSchemaSchemaRelationPtr relations;
456    int located;
457    int parsed;
458    int imported;
459    int preserveDoc;
460    xmlSchemaItemListPtr globals; /* Global components. */
461    xmlSchemaItemListPtr locals; /* Local components. */
462
463    /* The owning main or import schema bucket. */
464    xmlSchemaImportPtr ownerImport;
465};
466
467/**
468 * xmlSchemaBasicItem:
469 *
470 * The abstract base type for schema components.
471 */
472typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474struct _xmlSchemaBasicItem {
475    xmlSchemaTypeType type;
476};
477
478/**
479 * xmlSchemaAnnotItem:
480 *
481 * The abstract base type for annotated schema components.
482 * (Extends xmlSchemaBasicItem)
483 */
484typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486struct _xmlSchemaAnnotItem {
487    xmlSchemaTypeType type;
488    xmlSchemaAnnotPtr annot;
489};
490
491/**
492 * xmlSchemaTreeItem:
493 *
494 * The abstract base type for tree-like structured schema components.
495 * (Extends xmlSchemaAnnotItem)
496 */
497typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499struct _xmlSchemaTreeItem {
500    xmlSchemaTypeType type;
501    xmlSchemaAnnotPtr annot;
502    xmlSchemaTreeItemPtr next;
503    xmlSchemaTreeItemPtr children;
504};
505
506
507#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
508/**
509 * xmlSchemaAttributeUsePtr:
510 *
511 * The abstract base type for tree-like structured schema components.
512 * (Extends xmlSchemaTreeItem)
513 */
514typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516struct _xmlSchemaAttributeUse {
517    xmlSchemaTypeType type;
518    xmlSchemaAnnotPtr annot;
519    xmlSchemaAttributeUsePtr next; /* The next attr. use. */
520    /*
521    * The attr. decl. OR a QName-ref. to an attr. decl. OR
522    * a QName-ref. to an attribute group definition.
523    */
524    xmlSchemaAttributePtr attrDecl;
525
526    int flags;
527    xmlNodePtr node;
528    int occurs; /* required, optional */
529    const xmlChar * defValue;
530    xmlSchemaValPtr defVal;
531};
532
533/**
534 * xmlSchemaAttributeUseProhibPtr:
535 *
536 * A helper component to reflect attribute prohibitions.
537 * (Extends xmlSchemaBasicItem)
538 */
539typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541struct _xmlSchemaAttributeUseProhib {
542    xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
543    xmlNodePtr node;
544    const xmlChar *name;
545    const xmlChar *targetNamespace;
546    int isRef;
547};
548
549/**
550 * xmlSchemaRedef:
551 */
552typedef struct _xmlSchemaRedef xmlSchemaRedef;
553typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554struct _xmlSchemaRedef {
555    xmlSchemaRedefPtr next;
556    xmlSchemaBasicItemPtr item; /* The redefining component. */
557    xmlSchemaBasicItemPtr reference; /* The referencing component. */
558    xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
559    const xmlChar *refName; /* The name of the to-be-redefined component. */
560    const xmlChar *refTargetNs; /* The target namespace of the
561                                   to-be-redefined comp. */
562    xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
563};
564
565/**
566 * xmlSchemaConstructionCtxt:
567 */
568typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570struct _xmlSchemaConstructionCtxt {
571    xmlSchemaPtr mainSchema; /* The main schema. */
572    xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
573    xmlDictPtr dict;
574    xmlSchemaItemListPtr buckets; /* List of schema buckets. */
575    /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
576    xmlSchemaBucketPtr bucket; /* The current schema bucket */
577    xmlSchemaItemListPtr pending; /* All Components of all schemas that
578                                     need to be fixed. */
579    xmlHashTablePtr substGroups;
580    xmlSchemaRedefPtr redefs;
581    xmlSchemaRedefPtr lastRedef;
582};
583
584#define XML_SCHEMAS_PARSE_ERROR		1
585#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
586
587struct _xmlSchemaParserCtxt {
588    int type;
589    void *errCtxt;             /* user specific error context */
590    xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
591    xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
592    int err;
593    int nberrors;
594    xmlStructuredErrorFunc serror;
595
596    xmlSchemaConstructionCtxtPtr constructor;
597    int ownsConstructor; /* TODO: Move this to parser *flags*. */
598
599    /* xmlSchemaPtr topschema;	*/
600    /* xmlHashTablePtr namespaces;  */
601
602    xmlSchemaPtr schema;        /* The main schema in use */
603    int counter;
604
605    const xmlChar *URL;
606    xmlDocPtr doc;
607    int preserve;		/* Whether the doc should be freed  */
608
609    const char *buffer;
610    int size;
611
612    /*
613     * Used to build complex element content models
614     */
615    xmlAutomataPtr am;
616    xmlAutomataStatePtr start;
617    xmlAutomataStatePtr end;
618    xmlAutomataStatePtr state;
619
620    xmlDictPtr dict;		/* dictionnary for interned string names */
621    xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
622    int options;
623    xmlSchemaValidCtxtPtr vctxt;
624    int isS4S;
625    int isRedefine;
626    int xsiAssemble;
627    int stop; /* If the parser should stop; i.e. a critical error. */
628    const xmlChar *targetNamespace;
629    xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
630
631    xmlSchemaRedefPtr redef; /* Used for redefinitions. */
632    int redefCounter; /* Used for redefinitions. */
633    xmlSchemaItemListPtr attrProhibs;
634};
635
636/**
637 * xmlSchemaQNameRef:
638 *
639 * A component reference item (not a schema component)
640 * (Extends xmlSchemaBasicItem)
641 */
642typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644struct _xmlSchemaQNameRef {
645    xmlSchemaTypeType type;
646    xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647    xmlSchemaTypeType itemType;
648    const xmlChar *name;
649    const xmlChar *targetNamespace;
650    xmlNodePtr node;
651};
652
653/**
654 * xmlSchemaParticle:
655 *
656 * A particle component.
657 * (Extends xmlSchemaTreeItem)
658 */
659typedef struct _xmlSchemaParticle xmlSchemaParticle;
660typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661struct _xmlSchemaParticle {
662    xmlSchemaTypeType type;
663    xmlSchemaAnnotPtr annot;
664    xmlSchemaTreeItemPtr next; /* next particle */
665    xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667        etc.) */
668    int minOccurs;
669    int maxOccurs;
670    xmlNodePtr node;
671};
672
673/**
674 * xmlSchemaModelGroup:
675 *
676 * A model group component.
677 * (Extends xmlSchemaTreeItem)
678 */
679typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681struct _xmlSchemaModelGroup {
682    xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683    xmlSchemaAnnotPtr annot;
684    xmlSchemaTreeItemPtr next; /* not used */
685    xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686    xmlNodePtr node;
687};
688
689#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
691/**
692 * xmlSchemaModelGroupDef:
693 *
694 * A model group definition component.
695 * (Extends xmlSchemaTreeItem)
696 */
697typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699struct _xmlSchemaModelGroupDef {
700    xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701    xmlSchemaAnnotPtr annot;
702    xmlSchemaTreeItemPtr next; /* not used */
703    xmlSchemaTreeItemPtr children; /* the "model group" */
704    const xmlChar *name;
705    const xmlChar *targetNamespace;
706    xmlNodePtr node;
707    int flags;
708};
709
710typedef struct _xmlSchemaIDC xmlSchemaIDC;
711typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712
713/**
714 * xmlSchemaIDCSelect:
715 *
716 * The identity-constraint "field" and "selector" item, holding the
717 * XPath expression.
718 */
719typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721struct _xmlSchemaIDCSelect {
722    xmlSchemaIDCSelectPtr next;
723    xmlSchemaIDCPtr idc;
724    int index; /* an index position if significant for IDC key-sequences */
725    const xmlChar *xpath; /* the XPath expression */
726    void *xpathComp; /* the compiled XPath expression */
727};
728
729/**
730 * xmlSchemaIDC:
731 *
732 * The identity-constraint definition component.
733 * (Extends xmlSchemaAnnotItem)
734 */
735
736struct _xmlSchemaIDC {
737    xmlSchemaTypeType type;
738    xmlSchemaAnnotPtr annot;
739    xmlSchemaIDCPtr next;
740    xmlNodePtr node;
741    const xmlChar *name;
742    const xmlChar *targetNamespace;
743    xmlSchemaIDCSelectPtr selector;
744    xmlSchemaIDCSelectPtr fields;
745    int nbFields;
746    xmlSchemaQNameRefPtr ref;
747};
748
749/**
750 * xmlSchemaIDCAug:
751 *
752 * The augmented IDC information used for validation.
753 */
754typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756struct _xmlSchemaIDCAug {
757    xmlSchemaIDCAugPtr next; /* next in a list */
758    xmlSchemaIDCPtr def; /* the IDC definition */
759    int keyrefDepth; /* the lowest tree level to which IDC
760                        tables need to be bubbled upwards */
761};
762
763/**
764 * xmlSchemaPSVIIDCKeySequence:
765 *
766 * The key sequence of a node table item.
767 */
768typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770struct _xmlSchemaPSVIIDCKey {
771    xmlSchemaTypePtr type;
772    xmlSchemaValPtr val;
773};
774
775/**
776 * xmlSchemaPSVIIDCNode:
777 *
778 * The node table item of a node table.
779 */
780typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782struct _xmlSchemaPSVIIDCNode {
783    xmlNodePtr node;
784    xmlSchemaPSVIIDCKeyPtr *keys;
785    int nodeLine;
786    int nodeQNameID;
787
788};
789
790/**
791 * xmlSchemaPSVIIDCBinding:
792 *
793 * The identity-constraint binding item of the [identity-constraint table].
794 */
795typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797struct _xmlSchemaPSVIIDCBinding {
798    xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799    xmlSchemaIDCPtr definition; /* the IDC definition */
800    xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801    int nbNodes; /* number of entries in the node table */
802    int sizeNodes; /* size of the node table */
803    xmlSchemaItemListPtr dupls;
804};
805
806
807#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809
810#define XPATH_STATE_OBJ_MATCHES -2
811#define XPATH_STATE_OBJ_BLOCKED -3
812
813typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815
816/**
817 * xmlSchemaIDCStateObj:
818 *
819 * The state object used to evaluate XPath expressions.
820 */
821typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823struct _xmlSchemaIDCStateObj {
824    int type;
825    xmlSchemaIDCStateObjPtr next; /* next if in a list */
826    int depth; /* depth of creation */
827    int *history; /* list of (depth, state-id) tuples */
828    int nbHistory;
829    int sizeHistory;
830    xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831                                       matcher */
832    xmlSchemaIDCSelectPtr sel;
833    void *xpathCtxt;
834};
835
836#define IDC_MATCHER 0
837
838/**
839 * xmlSchemaIDCMatcher:
840 *
841 * Used to evaluate IDC selectors (and fields).
842 */
843struct _xmlSchemaIDCMatcher {
844    int type;
845    int depth; /* the tree depth at creation time */
846    xmlSchemaIDCMatcherPtr next; /* next in the list */
847    xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848    xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849    int idcType;
850    xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851                                         elements */
852    int sizeKeySeqs;
853    xmlSchemaItemListPtr targets; /* list of target-node
854                                     (xmlSchemaPSVIIDCNodePtr) entries */
855};
856
857/*
858* Element info flags.
859*/
860#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
861#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
862#define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2
863#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3
864
865#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
866#define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
867#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
868
869#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
870#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
871#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
872#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
873
874/**
875 * xmlSchemaNodeInfo:
876 *
877 * Holds information of an element node.
878 */
879struct _xmlSchemaNodeInfo {
880    int nodeType;
881    xmlNodePtr node;
882    int nodeLine;
883    const xmlChar *localName;
884    const xmlChar *nsName;
885    const xmlChar *value;
886    xmlSchemaValPtr val; /* the pre-computed value if any */
887    xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
888
889    int flags; /* combination of node info flags */
890
891    int valNeeded;
892    int normVal;
893
894    xmlSchemaElementPtr decl; /* the element/attribute declaration */
895    int depth;
896    xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
897                                            for the scope element*/
898    xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
899                                           element */
900    xmlRegExecCtxtPtr regexCtxt;
901
902    const xmlChar **nsBindings; /* Namespace bindings on this element */
903    int nbNsBindings;
904    int sizeNsBindings;
905
906    int hasKeyrefs;
907    int appliedXPath; /* Indicates that an XPath has been applied. */
908};
909
910#define XML_SCHEMAS_ATTR_UNKNOWN 1
911#define XML_SCHEMAS_ATTR_ASSESSED 2
912#define XML_SCHEMAS_ATTR_PROHIBITED 3
913#define XML_SCHEMAS_ATTR_ERR_MISSING 4
914#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
915#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
916#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
917#define XML_SCHEMAS_ATTR_DEFAULT 8
918#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
919#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
920#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
921#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
922#define XML_SCHEMAS_ATTR_WILD_SKIP 13
923#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
924#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
925#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
926#define XML_SCHEMAS_ATTR_META 17
927/*
928* @metaType values of xmlSchemaAttrInfo.
929*/
930#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
931#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
932#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
933#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
934#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
935
936typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938struct _xmlSchemaAttrInfo {
939    int nodeType;
940    xmlNodePtr node;
941    int nodeLine;
942    const xmlChar *localName;
943    const xmlChar *nsName;
944    const xmlChar *value;
945    xmlSchemaValPtr val; /* the pre-computed value if any */
946    xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
947    int flags; /* combination of node info flags */
948
949    xmlSchemaAttributePtr decl; /* the attribute declaration */
950    xmlSchemaAttributeUsePtr use;  /* the attribute use */
951    int state;
952    int metaType;
953    const xmlChar *vcValue; /* the value constraint value */
954    xmlSchemaNodeInfoPtr parent;
955};
956
957
958#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
959/**
960 * xmlSchemaValidCtxt:
961 *
962 * A Schemas validation context
963 */
964struct _xmlSchemaValidCtxt {
965    int type;
966    void *errCtxt;             /* user specific data block */
967    xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
968    xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
969    xmlStructuredErrorFunc serror;
970
971    xmlSchemaPtr schema;        /* The schema in use */
972    xmlDocPtr doc;
973    xmlParserInputBufferPtr input;
974    xmlCharEncoding enc;
975    xmlSAXHandlerPtr sax;
976    xmlParserCtxtPtr parserCtxt;
977    void *user_data; /* TODO: What is this for? */
978
979    int err;
980    int nberrors;
981
982    xmlNodePtr node;
983    xmlNodePtr cur;
984    /* xmlSchemaTypePtr type; */
985
986    xmlRegExecCtxtPtr regexp;
987    xmlSchemaValPtr value;
988
989    int valueWS;
990    int options;
991    xmlNodePtr validationRoot;
992    xmlSchemaParserCtxtPtr pctxt;
993    int xsiAssemble;
994
995    int depth;
996    xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
997    int sizeElemInfos;
998    xmlSchemaNodeInfoPtr inode; /* the current element information */
999
1000    xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1001
1002    xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1003    xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1004    xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1005
1006    xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1007    int nbIdcNodes;
1008    int sizeIdcNodes;
1009
1010    xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1011    int nbIdcKeys;
1012    int sizeIdcKeys;
1013
1014    int flags;
1015
1016    xmlDictPtr dict;
1017
1018#ifdef LIBXML_READER_ENABLED
1019    xmlTextReaderPtr reader;
1020#endif
1021
1022    xmlSchemaAttrInfoPtr *attrInfos;
1023    int nbAttrInfos;
1024    int sizeAttrInfos;
1025
1026    int skipDepth;
1027    xmlSchemaItemListPtr nodeQNames;
1028    int hasKeyrefs;
1029    int createIDCNodeTables;
1030    int psviExposeIDCNodeTables;
1031};
1032
1033/**
1034 * xmlSchemaSubstGroup:
1035 *
1036 *
1037 */
1038typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1039typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1040struct _xmlSchemaSubstGroup {
1041    xmlSchemaElementPtr head;
1042    xmlSchemaItemListPtr members;
1043};
1044
1045/************************************************************************
1046 * 									*
1047 * 			Some predeclarations				*
1048 * 									*
1049 ************************************************************************/
1050
1051static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1052                                 xmlSchemaPtr schema,
1053                                 xmlNodePtr node);
1054static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1055                                 xmlSchemaPtr schema,
1056                                 xmlNodePtr node);
1057static int
1058xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1059                   xmlSchemaAbstractCtxtPtr ctxt);
1060static const xmlChar *
1061xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1062static int
1063xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1064                     xmlNodePtr node);
1065static int
1066xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1067                       xmlSchemaParserCtxtPtr ctxt);
1068static void
1069xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1070static xmlSchemaWhitespaceValueType
1071xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1072static xmlSchemaTreeItemPtr
1073xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1074			 xmlNodePtr node, xmlSchemaTypeType type,
1075			 int withParticle);
1076static const xmlChar *
1077xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1078static xmlSchemaTypeLinkPtr
1079xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1080static void
1081xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1082		     const char *funcName,
1083		     const char *message);
1084static int
1085xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1086			     xmlSchemaTypePtr type,
1087			     xmlSchemaTypePtr baseType,
1088			     int subset);
1089static void
1090xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1091				   xmlSchemaParserCtxtPtr ctxt);
1092static void
1093xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1094static xmlSchemaQNameRefPtr
1095xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1096				xmlSchemaPtr schema,
1097				xmlNodePtr node);
1098
1099/************************************************************************
1100 *									*
1101 * 			Helper functions			        *
1102 *									*
1103 ************************************************************************/
1104
1105/**
1106 * xmlSchemaItemTypeToStr:
1107 * @type: the type of the schema item
1108 *
1109 * Returns the component name of a schema item.
1110 */
1111static const xmlChar *
1112xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1113{
1114    switch (type) {
1115	case XML_SCHEMA_TYPE_BASIC:
1116	    return(BAD_CAST "simple type definition");
1117	case XML_SCHEMA_TYPE_SIMPLE:
1118	    return(BAD_CAST "simple type definition");
1119	case XML_SCHEMA_TYPE_COMPLEX:
1120	    return(BAD_CAST "complex type definition");
1121	case XML_SCHEMA_TYPE_ELEMENT:
1122	    return(BAD_CAST "element declaration");
1123	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1124	    return(BAD_CAST "attribute use");
1125	case XML_SCHEMA_TYPE_ATTRIBUTE:
1126	    return(BAD_CAST "attribute declaration");
1127	case XML_SCHEMA_TYPE_GROUP:
1128	    return(BAD_CAST "model group definition");
1129	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1130	    return(BAD_CAST "attribute group definition");
1131	case XML_SCHEMA_TYPE_NOTATION:
1132	    return(BAD_CAST "notation declaration");
1133	case XML_SCHEMA_TYPE_SEQUENCE:
1134	    return(BAD_CAST "model group (sequence)");
1135	case XML_SCHEMA_TYPE_CHOICE:
1136	    return(BAD_CAST "model group (choice)");
1137	case XML_SCHEMA_TYPE_ALL:
1138	    return(BAD_CAST "model group (all)");
1139	case XML_SCHEMA_TYPE_PARTICLE:
1140	    return(BAD_CAST "particle");
1141	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1142	    return(BAD_CAST "unique identity-constraint");
1143	    /* return(BAD_CAST "IDC (unique)"); */
1144	case XML_SCHEMA_TYPE_IDC_KEY:
1145	    return(BAD_CAST "key identity-constraint");
1146	    /* return(BAD_CAST "IDC (key)"); */
1147	case XML_SCHEMA_TYPE_IDC_KEYREF:
1148	    return(BAD_CAST "keyref identity-constraint");
1149	    /* return(BAD_CAST "IDC (keyref)"); */
1150	case XML_SCHEMA_TYPE_ANY:
1151	    return(BAD_CAST "wildcard (any)");
1152	case XML_SCHEMA_EXTRA_QNAMEREF:
1153	    return(BAD_CAST "[helper component] QName reference");
1154	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1155	    return(BAD_CAST "[helper component] attribute use prohibition");
1156	default:
1157	    return(BAD_CAST "Not a schema component");
1158    }
1159}
1160
1161/**
1162 * xmlSchemaGetComponentTypeStr:
1163 * @type: the type of the schema item
1164 *
1165 * Returns the component name of a schema item.
1166 */
1167static const xmlChar *
1168xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1169{
1170    switch (item->type) {
1171	case XML_SCHEMA_TYPE_BASIC:
1172	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1173		return(BAD_CAST "complex type definition");
1174	    else
1175		return(BAD_CAST "simple type definition");
1176	default:
1177	    return(xmlSchemaItemTypeToStr(item->type));
1178    }
1179}
1180
1181/**
1182 * xmlSchemaGetComponentNode:
1183 * @item: a schema component
1184 *
1185 * Returns node associated with the schema component.
1186 * NOTE that such a node need not be available; plus, a component's
1187 * node need not to reflect the component directly, since there is no
1188 * one-to-one relationship between the XML Schema representation and
1189 * the component representation.
1190 */
1191static xmlNodePtr
1192xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1193{
1194    switch (item->type) {
1195	case XML_SCHEMA_TYPE_ELEMENT:
1196	    return (((xmlSchemaElementPtr) item)->node);
1197	case XML_SCHEMA_TYPE_ATTRIBUTE:
1198	    return (((xmlSchemaAttributePtr) item)->node);
1199	case XML_SCHEMA_TYPE_COMPLEX:
1200	case XML_SCHEMA_TYPE_SIMPLE:
1201	    return (((xmlSchemaTypePtr) item)->node);
1202	case XML_SCHEMA_TYPE_ANY:
1203	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1204	    return (((xmlSchemaWildcardPtr) item)->node);
1205	case XML_SCHEMA_TYPE_PARTICLE:
1206	    return (((xmlSchemaParticlePtr) item)->node);
1207	case XML_SCHEMA_TYPE_SEQUENCE:
1208	case XML_SCHEMA_TYPE_CHOICE:
1209	case XML_SCHEMA_TYPE_ALL:
1210	    return (((xmlSchemaModelGroupPtr) item)->node);
1211	case XML_SCHEMA_TYPE_GROUP:
1212	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1213	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1214	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1215	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1216	case XML_SCHEMA_TYPE_IDC_KEY:
1217	case XML_SCHEMA_TYPE_IDC_KEYREF:
1218	    return (((xmlSchemaIDCPtr) item)->node);
1219	case XML_SCHEMA_EXTRA_QNAMEREF:
1220	    return(((xmlSchemaQNameRefPtr) item)->node);
1221	/* TODO: What to do with NOTATIONs?
1222	case XML_SCHEMA_TYPE_NOTATION:
1223	    return (((xmlSchemaNotationPtr) item)->node);
1224	*/
1225	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1226	    return (((xmlSchemaAttributeUsePtr) item)->node);
1227	default:
1228	    return (NULL);
1229    }
1230}
1231
1232#if 0
1233/**
1234 * xmlSchemaGetNextComponent:
1235 * @item: a schema component
1236 *
1237 * Returns the next sibling of the schema component.
1238 */
1239static xmlSchemaBasicItemPtr
1240xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1241{
1242    switch (item->type) {
1243	case XML_SCHEMA_TYPE_ELEMENT:
1244	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1245	case XML_SCHEMA_TYPE_ATTRIBUTE:
1246	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1247	case XML_SCHEMA_TYPE_COMPLEX:
1248	case XML_SCHEMA_TYPE_SIMPLE:
1249	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1250	case XML_SCHEMA_TYPE_ANY:
1251	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1252	    return (NULL);
1253	case XML_SCHEMA_TYPE_PARTICLE:
1254	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1255	case XML_SCHEMA_TYPE_SEQUENCE:
1256	case XML_SCHEMA_TYPE_CHOICE:
1257	case XML_SCHEMA_TYPE_ALL:
1258	    return (NULL);
1259	case XML_SCHEMA_TYPE_GROUP:
1260	    return (NULL);
1261	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1262	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1263	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1264	case XML_SCHEMA_TYPE_IDC_KEY:
1265	case XML_SCHEMA_TYPE_IDC_KEYREF:
1266	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1267	default:
1268	    return (NULL);
1269    }
1270}
1271#endif
1272
1273
1274/**
1275 * xmlSchemaFormatQName:
1276 * @buf: the string buffer
1277 * @namespaceName:  the namespace name
1278 * @localName: the local name
1279 *
1280 * Returns the given QName in the format "{namespaceName}localName" or
1281 * just "localName" if @namespaceName is NULL.
1282 *
1283 * Returns the localName if @namespaceName is NULL, a formatted
1284 * string otherwise.
1285 */
1286static const xmlChar*
1287xmlSchemaFormatQName(xmlChar **buf,
1288		     const xmlChar *namespaceName,
1289		     const xmlChar *localName)
1290{
1291    FREE_AND_NULL(*buf)
1292    if (namespaceName != NULL) {
1293	*buf = xmlStrdup(BAD_CAST "{");
1294	*buf = xmlStrcat(*buf, namespaceName);
1295	*buf = xmlStrcat(*buf, BAD_CAST "}");
1296    }
1297    if (localName != NULL) {
1298	if (namespaceName == NULL)
1299	    return(localName);
1300	*buf = xmlStrcat(*buf, localName);
1301    } else {
1302	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1303    }
1304    return ((const xmlChar *) *buf);
1305}
1306
1307static const xmlChar*
1308xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1309{
1310    if (ns != NULL)
1311	return (xmlSchemaFormatQName(buf, ns->href, localName));
1312    else
1313	return (xmlSchemaFormatQName(buf, NULL, localName));
1314}
1315
1316static const xmlChar *
1317xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1318{
1319    switch (item->type) {
1320	case XML_SCHEMA_TYPE_ELEMENT:
1321	    return (((xmlSchemaElementPtr) item)->name);
1322	case XML_SCHEMA_TYPE_ATTRIBUTE:
1323	    return (((xmlSchemaAttributePtr) item)->name);
1324	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1325	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1326	case XML_SCHEMA_TYPE_BASIC:
1327	case XML_SCHEMA_TYPE_SIMPLE:
1328	case XML_SCHEMA_TYPE_COMPLEX:
1329	    return (((xmlSchemaTypePtr) item)->name);
1330	case XML_SCHEMA_TYPE_GROUP:
1331	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1332	case XML_SCHEMA_TYPE_IDC_KEY:
1333	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1334	case XML_SCHEMA_TYPE_IDC_KEYREF:
1335	    return (((xmlSchemaIDCPtr) item)->name);
1336	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1337	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1338		return(xmlSchemaGetComponentName(
1339		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1340	    } else
1341		return(NULL);
1342	case XML_SCHEMA_EXTRA_QNAMEREF:
1343	    return (((xmlSchemaQNameRefPtr) item)->name);
1344	case XML_SCHEMA_TYPE_NOTATION:
1345	    return (((xmlSchemaNotationPtr) item)->name);
1346	default:
1347	    /*
1348	    * Other components cannot have names.
1349	    */
1350	    break;
1351    }
1352    return (NULL);
1353}
1354
1355#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1356#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1357/*
1358static const xmlChar *
1359xmlSchemaGetQNameRefName(void *ref)
1360{
1361    return(((xmlSchemaQNameRefPtr) ref)->name);
1362}
1363
1364static const xmlChar *
1365xmlSchemaGetQNameRefTargetNs(void *ref)
1366{
1367    return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1368}
1369*/
1370
1371static const xmlChar *
1372xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1373{
1374    switch (item->type) {
1375	case XML_SCHEMA_TYPE_ELEMENT:
1376	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1377	case XML_SCHEMA_TYPE_ATTRIBUTE:
1378	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1379	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1380	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1381	case XML_SCHEMA_TYPE_BASIC:
1382	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1383	case XML_SCHEMA_TYPE_SIMPLE:
1384	case XML_SCHEMA_TYPE_COMPLEX:
1385	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1386	case XML_SCHEMA_TYPE_GROUP:
1387	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1388	case XML_SCHEMA_TYPE_IDC_KEY:
1389	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1390	case XML_SCHEMA_TYPE_IDC_KEYREF:
1391	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1392	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1393	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1394		return(xmlSchemaGetComponentTargetNs(
1395		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1396	    }
1397	    /* TODO: Will returning NULL break something? */
1398	    break;
1399	case XML_SCHEMA_EXTRA_QNAMEREF:
1400	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1401	case XML_SCHEMA_TYPE_NOTATION:
1402	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1403	default:
1404	    /*
1405	    * Other components cannot have names.
1406	    */
1407	    break;
1408    }
1409    return (NULL);
1410}
1411
1412static const xmlChar*
1413xmlSchemaGetComponentQName(xmlChar **buf,
1414			   void *item)
1415{
1416    return (xmlSchemaFormatQName(buf,
1417	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1418	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1419}
1420
1421static const xmlChar*
1422xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1423{
1424    xmlChar *str = NULL;
1425
1426    *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1427    *buf = xmlStrcat(*buf, BAD_CAST " '");
1428    *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1429	(xmlSchemaBasicItemPtr) item));
1430    *buf = xmlStrcat(*buf, BAD_CAST "'");
1431    FREE_AND_NULL(str);
1432    return(*buf);
1433}
1434
1435static const xmlChar*
1436xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1437{
1438    return(xmlSchemaGetComponentDesignation(buf, idc));
1439}
1440
1441/**
1442 * xmlSchemaWildcardPCToString:
1443 * @pc: the type of processContents
1444 *
1445 * Returns a string representation of the type of
1446 * processContents.
1447 */
1448static const xmlChar *
1449xmlSchemaWildcardPCToString(int pc)
1450{
1451    switch (pc) {
1452	case XML_SCHEMAS_ANY_SKIP:
1453	    return (BAD_CAST "skip");
1454	case XML_SCHEMAS_ANY_LAX:
1455	    return (BAD_CAST "lax");
1456	case XML_SCHEMAS_ANY_STRICT:
1457	    return (BAD_CAST "strict");
1458	default:
1459	    return (BAD_CAST "invalid process contents");
1460    }
1461}
1462
1463/**
1464 * xmlSchemaGetCanonValueWhtspExt:
1465 * @val: the precomputed value
1466 * @retValue: the returned value
1467 * @ws: the whitespace type of the value
1468 *
1469 * Get a the cononical representation of the value.
1470 * The caller has to free the returned retValue.
1471 *
1472 * Returns 0 if the value could be built and -1 in case of
1473 *         API errors or if the value type is not supported yet.
1474 */
1475static int
1476xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1477			       xmlSchemaWhitespaceValueType ws,
1478			       xmlChar **retValue)
1479{
1480    int list;
1481    xmlSchemaValType valType;
1482    const xmlChar *value, *value2 = NULL;
1483
1484
1485    if ((retValue == NULL) || (val == NULL))
1486	return (-1);
1487    list = xmlSchemaValueGetNext(val) ? 1 : 0;
1488    *retValue = NULL;
1489    do {
1490	value = NULL;
1491	valType = xmlSchemaGetValType(val);
1492	switch (valType) {
1493	    case XML_SCHEMAS_STRING:
1494	    case XML_SCHEMAS_NORMSTRING:
1495	    case XML_SCHEMAS_ANYSIMPLETYPE:
1496		value = xmlSchemaValueGetAsString(val);
1497		if (value != NULL) {
1498		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1499			value2 = xmlSchemaCollapseString(value);
1500		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1501			value2 = xmlSchemaWhiteSpaceReplace(value);
1502		    if (value2 != NULL)
1503			value = value2;
1504		}
1505		break;
1506	    default:
1507		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1508		    if (value2 != NULL)
1509			xmlFree((xmlChar *) value2);
1510		    goto internal_error;
1511		}
1512		value = value2;
1513	}
1514	if (*retValue == NULL)
1515	    if (value == NULL) {
1516		if (! list)
1517		    *retValue = xmlStrdup(BAD_CAST "");
1518	    } else
1519		*retValue = xmlStrdup(value);
1520	else if (value != NULL) {
1521	    /* List. */
1522	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1523	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1524	}
1525	FREE_AND_NULL(value2)
1526	val = xmlSchemaValueGetNext(val);
1527    } while (val != NULL);
1528
1529    return (0);
1530internal_error:
1531    if (*retValue != NULL)
1532	xmlFree((xmlChar *) (*retValue));
1533    if (value2 != NULL)
1534	xmlFree((xmlChar *) value2);
1535    return (-1);
1536}
1537
1538/**
1539 * xmlSchemaFormatItemForReport:
1540 * @buf: the string buffer
1541 * @itemDes: the designation of the item
1542 * @itemName: the name of the item
1543 * @item: the item as an object
1544 * @itemNode: the node of the item
1545 * @local: the local name
1546 * @parsing: if the function is used during the parse
1547 *
1548 * Returns a representation of the given item used
1549 * for error reports.
1550 *
1551 * The following order is used to build the resulting
1552 * designation if the arguments are not NULL:
1553 * 1a. If itemDes not NULL -> itemDes
1554 * 1b. If (itemDes not NULL) and (itemName not NULL)
1555 *     -> itemDes + itemName
1556 * 2. If the preceding was NULL and (item not NULL) -> item
1557 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1558 *
1559 * If the itemNode is an attribute node, the name of the attribute
1560 * will be appended to the result.
1561 *
1562 * Returns the formatted string and sets @buf to the resulting value.
1563 */
1564static xmlChar*
1565xmlSchemaFormatItemForReport(xmlChar **buf,
1566		     const xmlChar *itemDes,
1567		     xmlSchemaBasicItemPtr item,
1568		     xmlNodePtr itemNode)
1569{
1570    xmlChar *str = NULL;
1571    int named = 1;
1572
1573    if (*buf != NULL) {
1574	xmlFree(*buf);
1575	*buf = NULL;
1576    }
1577
1578    if (itemDes != NULL) {
1579	*buf = xmlStrdup(itemDes);
1580    } else if (item != NULL) {
1581	switch (item->type) {
1582	case XML_SCHEMA_TYPE_BASIC: {
1583	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1584
1585	    if (WXS_IS_ATOMIC(type))
1586		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1587	    else if (WXS_IS_LIST(type))
1588		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1589	    else if (WXS_IS_UNION(type))
1590		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1591	    else
1592		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1593	    *buf = xmlStrcat(*buf, type->name);
1594	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1595	    }
1596	    break;
1597	case XML_SCHEMA_TYPE_SIMPLE: {
1598	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1599
1600	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1601		*buf = xmlStrdup(BAD_CAST"");
1602	    } else {
1603		*buf = xmlStrdup(BAD_CAST "local ");
1604	    }
1605	    if (WXS_IS_ATOMIC(type))
1606		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1607	    else if (WXS_IS_LIST(type))
1608		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1609	    else if (WXS_IS_UNION(type))
1610		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1611	    else
1612		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1613	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1614		*buf = xmlStrcat(*buf, BAD_CAST " '");
1615		*buf = xmlStrcat(*buf, type->name);
1616		*buf = xmlStrcat(*buf, BAD_CAST "'");
1617	    }
1618	    }
1619	    break;
1620	case XML_SCHEMA_TYPE_COMPLEX: {
1621	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1622
1623	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1624		*buf = xmlStrdup(BAD_CAST "");
1625	    else
1626		*buf = xmlStrdup(BAD_CAST "local ");
1627	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1628	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1629		*buf = xmlStrcat(*buf, BAD_CAST " '");
1630		*buf = xmlStrcat(*buf, type->name);
1631		*buf = xmlStrcat(*buf, BAD_CAST "'");
1632	    }
1633	    }
1634	    break;
1635	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1636		xmlSchemaAttributeUsePtr ause;
1637
1638		ause = WXS_ATTR_USE_CAST item;
1639		*buf = xmlStrdup(BAD_CAST "attribute use ");
1640		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1641		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1642		    *buf = xmlStrcat(*buf,
1643			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1644		    FREE_AND_NULL(str)
1645			*buf = xmlStrcat(*buf, BAD_CAST "'");
1646		} else {
1647		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1648		}
1649	    }
1650	    break;
1651	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1652		xmlSchemaAttributePtr attr;
1653
1654		attr = (xmlSchemaAttributePtr) item;
1655		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1656		*buf = xmlStrcat(*buf, BAD_CAST " '");
1657		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1658		    attr->targetNamespace, attr->name));
1659		FREE_AND_NULL(str)
1660		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1661	    }
1662	    break;
1663	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1664	    xmlSchemaGetComponentDesignation(buf, item);
1665	    break;
1666	case XML_SCHEMA_TYPE_ELEMENT: {
1667		xmlSchemaElementPtr elem;
1668
1669		elem = (xmlSchemaElementPtr) item;
1670		*buf = xmlStrdup(BAD_CAST "element decl.");
1671		*buf = xmlStrcat(*buf, BAD_CAST " '");
1672		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1673		    elem->targetNamespace, elem->name));
1674		*buf = xmlStrcat(*buf, BAD_CAST "'");
1675	    }
1676	    break;
1677	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1678	case XML_SCHEMA_TYPE_IDC_KEY:
1679	case XML_SCHEMA_TYPE_IDC_KEYREF:
1680	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1681		*buf = xmlStrdup(BAD_CAST "unique '");
1682	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1683		*buf = xmlStrdup(BAD_CAST "key '");
1684	    else
1685		*buf = xmlStrdup(BAD_CAST "keyRef '");
1686	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1687	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1688	    break;
1689	case XML_SCHEMA_TYPE_ANY:
1690	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1691	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1692		    ((xmlSchemaWildcardPtr) item)->processContents));
1693	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1694	    break;
1695	case XML_SCHEMA_FACET_MININCLUSIVE:
1696	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1697	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1698	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1699	case XML_SCHEMA_FACET_TOTALDIGITS:
1700	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1701	case XML_SCHEMA_FACET_PATTERN:
1702	case XML_SCHEMA_FACET_ENUMERATION:
1703	case XML_SCHEMA_FACET_WHITESPACE:
1704	case XML_SCHEMA_FACET_LENGTH:
1705	case XML_SCHEMA_FACET_MAXLENGTH:
1706	case XML_SCHEMA_FACET_MINLENGTH:
1707	    *buf = xmlStrdup(BAD_CAST "facet '");
1708	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1709	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1710	    break;
1711	case XML_SCHEMA_TYPE_GROUP: {
1712		*buf = xmlStrdup(BAD_CAST "model group def.");
1713		*buf = xmlStrcat(*buf, BAD_CAST " '");
1714		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1715		*buf = xmlStrcat(*buf, BAD_CAST "'");
1716		FREE_AND_NULL(str)
1717	    }
1718	    break;
1719	case XML_SCHEMA_TYPE_SEQUENCE:
1720	case XML_SCHEMA_TYPE_CHOICE:
1721	case XML_SCHEMA_TYPE_ALL:
1722	case XML_SCHEMA_TYPE_PARTICLE:
1723	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1724	    break;
1725	case XML_SCHEMA_TYPE_NOTATION: {
1726		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1727		*buf = xmlStrcat(*buf, BAD_CAST " '");
1728		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1729		*buf = xmlStrcat(*buf, BAD_CAST "'");
1730		FREE_AND_NULL(str);
1731	    }
1732	default:
1733	    named = 0;
1734	}
1735    } else
1736	named = 0;
1737
1738    if ((named == 0) && (itemNode != NULL)) {
1739	xmlNodePtr elem;
1740
1741	if (itemNode->type == XML_ATTRIBUTE_NODE)
1742	    elem = itemNode->parent;
1743	else
1744	    elem = itemNode;
1745	*buf = xmlStrdup(BAD_CAST "Element '");
1746	if (elem->ns != NULL) {
1747	    *buf = xmlStrcat(*buf,
1748		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1749	    FREE_AND_NULL(str)
1750	} else
1751	    *buf = xmlStrcat(*buf, elem->name);
1752	*buf = xmlStrcat(*buf, BAD_CAST "'");
1753
1754    }
1755    if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1756	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1757	if (itemNode->ns != NULL) {
1758	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1759		itemNode->ns->href, itemNode->name));
1760	    FREE_AND_NULL(str)
1761	} else
1762	    *buf = xmlStrcat(*buf, itemNode->name);
1763	*buf = xmlStrcat(*buf, BAD_CAST "'");
1764    }
1765    FREE_AND_NULL(str)
1766
1767    return (*buf);
1768}
1769
1770/**
1771 * xmlSchemaFormatFacetEnumSet:
1772 * @buf: the string buffer
1773 * @type: the type holding the enumeration facets
1774 *
1775 * Builds a string consisting of all enumeration elements.
1776 *
1777 * Returns a string of all enumeration elements.
1778 */
1779static const xmlChar *
1780xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1781			    xmlChar **buf, xmlSchemaTypePtr type)
1782{
1783    xmlSchemaFacetPtr facet;
1784    xmlSchemaWhitespaceValueType ws;
1785    xmlChar *value = NULL;
1786    int res, found = 0;
1787
1788    if (*buf != NULL)
1789	xmlFree(*buf);
1790    *buf = NULL;
1791
1792    do {
1793	/*
1794	* Use the whitespace type of the base type.
1795	*/
1796	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1797	for (facet = type->facets; facet != NULL; facet = facet->next) {
1798	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1799		continue;
1800	    found = 1;
1801	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1802		ws, &value);
1803	    if (res == -1) {
1804		xmlSchemaInternalErr(actxt,
1805		    "xmlSchemaFormatFacetEnumSet",
1806		    "compute the canonical lexical representation");
1807		if (*buf != NULL)
1808		    xmlFree(*buf);
1809		*buf = NULL;
1810		return (NULL);
1811	    }
1812	    if (*buf == NULL)
1813		*buf = xmlStrdup(BAD_CAST "'");
1814	    else
1815		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1816	    *buf = xmlStrcat(*buf, BAD_CAST value);
1817	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1818	    if (value != NULL) {
1819		xmlFree((xmlChar *)value);
1820		value = NULL;
1821	    }
1822	}
1823	/*
1824	* The enumeration facet of a type restricts the enumeration
1825	* facet of the ancestor type; i.e., such restricted enumerations
1826	* do not belong to the set of the given type. Thus we break
1827	* on the first found enumeration.
1828	*/
1829	if (found)
1830	    break;
1831	type = type->baseType;
1832    } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1833
1834    return ((const xmlChar *) *buf);
1835}
1836
1837/************************************************************************
1838 *									*
1839 * 			Error functions				        *
1840 *									*
1841 ************************************************************************/
1842
1843#if 0
1844static void
1845xmlSchemaErrMemory(const char *msg)
1846{
1847    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1848                     msg);
1849}
1850#endif
1851
1852static void
1853xmlSchemaPSimpleErr(const char *msg)
1854{
1855    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1856                     msg);
1857}
1858
1859/**
1860 * xmlSchemaPErrMemory:
1861 * @node: a context node
1862 * @extra:  extra informations
1863 *
1864 * Handle an out of memory condition
1865 */
1866static void
1867xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1868                    const char *extra, xmlNodePtr node)
1869{
1870    if (ctxt != NULL)
1871        ctxt->nberrors++;
1872    __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1873                     extra);
1874}
1875
1876/**
1877 * xmlSchemaPErr:
1878 * @ctxt: the parsing context
1879 * @node: the context node
1880 * @error: the error code
1881 * @msg: the error message
1882 * @str1: extra data
1883 * @str2: extra data
1884 *
1885 * Handle a parser error
1886 */
1887static void
1888xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1889              const char *msg, const xmlChar * str1, const xmlChar * str2)
1890{
1891    xmlGenericErrorFunc channel = NULL;
1892    xmlStructuredErrorFunc schannel = NULL;
1893    void *data = NULL;
1894
1895    if (ctxt != NULL) {
1896        ctxt->nberrors++;
1897	ctxt->err = error;
1898        channel = ctxt->error;
1899        data = ctxt->errCtxt;
1900	schannel = ctxt->serror;
1901    }
1902    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1903                    error, XML_ERR_ERROR, NULL, 0,
1904                    (const char *) str1, (const char *) str2, NULL, 0, 0,
1905                    msg, str1, str2);
1906}
1907
1908/**
1909 * xmlSchemaPErr2:
1910 * @ctxt: the parsing context
1911 * @node: the context node
1912 * @node: the current child
1913 * @error: the error code
1914 * @msg: the error message
1915 * @str1: extra data
1916 * @str2: extra data
1917 *
1918 * Handle a parser error
1919 */
1920static void
1921xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1922               xmlNodePtr child, int error,
1923               const char *msg, const xmlChar * str1, const xmlChar * str2)
1924{
1925    if (child != NULL)
1926        xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1927    else
1928        xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1929}
1930
1931
1932/**
1933 * xmlSchemaPErrExt:
1934 * @ctxt: the parsing context
1935 * @node: the context node
1936 * @error: the error code
1937 * @strData1: extra data
1938 * @strData2: extra data
1939 * @strData3: extra data
1940 * @msg: the message
1941 * @str1:  extra parameter for the message display
1942 * @str2:  extra parameter for the message display
1943 * @str3:  extra parameter for the message display
1944 * @str4:  extra parameter for the message display
1945 * @str5:  extra parameter for the message display
1946 *
1947 * Handle a parser error
1948 */
1949static void
1950xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1951		const xmlChar * strData1, const xmlChar * strData2,
1952		const xmlChar * strData3, const char *msg, const xmlChar * str1,
1953		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1954		const xmlChar * str5)
1955{
1956
1957    xmlGenericErrorFunc channel = NULL;
1958    xmlStructuredErrorFunc schannel = NULL;
1959    void *data = NULL;
1960
1961    if (ctxt != NULL) {
1962        ctxt->nberrors++;
1963	ctxt->err = error;
1964        channel = ctxt->error;
1965        data = ctxt->errCtxt;
1966	schannel = ctxt->serror;
1967    }
1968    __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1969                    error, XML_ERR_ERROR, NULL, 0,
1970                    (const char *) strData1, (const char *) strData2,
1971		    (const char *) strData3, 0, 0, msg, str1, str2,
1972		    str3, str4, str5);
1973}
1974
1975/************************************************************************
1976 *									*
1977 * 			Allround error functions			*
1978 *									*
1979 ************************************************************************/
1980
1981/**
1982 * xmlSchemaVTypeErrMemory:
1983 * @node: a context node
1984 * @extra:  extra informations
1985 *
1986 * Handle an out of memory condition
1987 */
1988static void
1989xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1990                    const char *extra, xmlNodePtr node)
1991{
1992    if (ctxt != NULL) {
1993        ctxt->nberrors++;
1994        ctxt->err = XML_SCHEMAV_INTERNAL;
1995    }
1996    __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1997                     extra);
1998}
1999
2000static void
2001xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2002			    const char *msg, const xmlChar *str)
2003{
2004     __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2005	 msg, (const char *) str);
2006}
2007
2008#define WXS_ERROR_TYPE_ERROR 1
2009#define WXS_ERROR_TYPE_WARNING 2
2010/**
2011 * xmlSchemaErr3:
2012 * @ctxt: the validation context
2013 * @node: the context node
2014 * @error: the error code
2015 * @msg: the error message
2016 * @str1: extra data
2017 * @str2: extra data
2018 * @str3: extra data
2019 *
2020 * Handle a validation error
2021 */
2022static void
2023xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2024		  xmlErrorLevel errorLevel,
2025		  int error, xmlNodePtr node, int line, const char *msg,
2026		  const xmlChar *str1, const xmlChar *str2,
2027		  const xmlChar *str3, const xmlChar *str4)
2028{
2029    xmlStructuredErrorFunc schannel = NULL;
2030    xmlGenericErrorFunc channel = NULL;
2031    void *data = NULL;
2032
2033    if (ctxt != NULL) {
2034	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2035	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2036	    const char *file = NULL;
2037	    if (errorLevel != XML_ERR_WARNING) {
2038		vctxt->nberrors++;
2039		vctxt->err = error;
2040		channel = vctxt->error;
2041	    } else {
2042		channel = vctxt->warning;
2043	    }
2044	    schannel = vctxt->serror;
2045	    data = vctxt->errCtxt;
2046
2047	    /*
2048	    * Error node. If we specify a line number, then
2049	    * do not channel any node to the error function.
2050	    */
2051	    if (line == 0) {
2052		if ((node == NULL) &&
2053		    (vctxt->depth >= 0) &&
2054		    (vctxt->inode != NULL)) {
2055		    node = vctxt->inode->node;
2056		}
2057		/*
2058		* Get filename and line if no node-tree.
2059		*/
2060		if ((node == NULL) &&
2061		    (vctxt->parserCtxt != NULL) &&
2062		    (vctxt->parserCtxt->input != NULL)) {
2063		    file = vctxt->parserCtxt->input->filename;
2064		    line = vctxt->parserCtxt->input->line;
2065		}
2066	    } else {
2067		/*
2068		* Override the given node's (if any) position
2069		* and channel only the given line number.
2070		*/
2071		node = NULL;
2072		/*
2073		* Get filename.
2074		*/
2075		if (vctxt->doc != NULL)
2076		    file = (const char *) vctxt->doc->URL;
2077		else if ((vctxt->parserCtxt != NULL) &&
2078		    (vctxt->parserCtxt->input != NULL))
2079		    file = vctxt->parserCtxt->input->filename;
2080	    }
2081	    __xmlRaiseError(schannel, channel, data, ctxt,
2082		node, XML_FROM_SCHEMASV,
2083		error, errorLevel, file, line,
2084		(const char *) str1, (const char *) str2,
2085		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2086
2087	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2088	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2089	    if (errorLevel != XML_ERR_WARNING) {
2090		pctxt->nberrors++;
2091		pctxt->err = error;
2092		channel = pctxt->error;
2093	    } else {
2094		channel = pctxt->warning;
2095	    }
2096	    schannel = pctxt->serror;
2097	    data = pctxt->errCtxt;
2098	    __xmlRaiseError(schannel, channel, data, ctxt,
2099		node, XML_FROM_SCHEMASP, error,
2100		errorLevel, NULL, 0,
2101		(const char *) str1, (const char *) str2,
2102		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2103	} else {
2104	    TODO
2105	}
2106    }
2107}
2108
2109/**
2110 * xmlSchemaErr3:
2111 * @ctxt: the validation context
2112 * @node: the context node
2113 * @error: the error code
2114 * @msg: the error message
2115 * @str1: extra data
2116 * @str2: extra data
2117 * @str3: extra data
2118 *
2119 * Handle a validation error
2120 */
2121static void
2122xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2123	      int error, xmlNodePtr node, const char *msg,
2124	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2125{
2126    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2127	msg, str1, str2, str3, NULL);
2128}
2129
2130static void
2131xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2132	      int error, xmlNodePtr node, const char *msg,
2133	      const xmlChar *str1, const xmlChar *str2,
2134	      const xmlChar *str3, const xmlChar *str4)
2135{
2136    xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2137	msg, str1, str2, str3, str4);
2138}
2139
2140static void
2141xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2142	     int error, xmlNodePtr node, const char *msg,
2143	     const xmlChar *str1, const xmlChar *str2)
2144{
2145    xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2146}
2147
2148static xmlChar *
2149xmlSchemaFormatNodeForError(xmlChar ** msg,
2150			    xmlSchemaAbstractCtxtPtr actxt,
2151			    xmlNodePtr node)
2152{
2153    xmlChar *str = NULL;
2154
2155    *msg = NULL;
2156    if ((node != NULL) &&
2157	(node->type != XML_ELEMENT_NODE) &&
2158	(node->type != XML_ATTRIBUTE_NODE))
2159    {
2160	/*
2161	* Don't try to format other nodes than element and
2162	* attribute nodes.
2163	* Play save and return an empty string.
2164	*/
2165	*msg = xmlStrdup(BAD_CAST "");
2166	return(*msg);
2167    }
2168    if (node != NULL) {
2169	/*
2170	* Work on tree nodes.
2171	*/
2172	if (node->type == XML_ATTRIBUTE_NODE) {
2173	    xmlNodePtr elem = node->parent;
2174
2175	    *msg = xmlStrdup(BAD_CAST "Element '");
2176	    if (elem->ns != NULL)
2177		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2178		    elem->ns->href, elem->name));
2179	    else
2180		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2181		    NULL, elem->name));
2182	    FREE_AND_NULL(str);
2183	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2184	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2185	} else {
2186	    *msg = xmlStrdup(BAD_CAST "Element '");
2187	}
2188	if (node->ns != NULL)
2189	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2190	    node->ns->href, node->name));
2191	else
2192	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2193	    NULL, node->name));
2194	FREE_AND_NULL(str);
2195	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2196    } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2197	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2198	/*
2199	* Work on node infos.
2200	*/
2201	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2202	    xmlSchemaNodeInfoPtr ielem =
2203		vctxt->elemInfos[vctxt->depth];
2204
2205	    *msg = xmlStrdup(BAD_CAST "Element '");
2206	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2207		ielem->nsName, ielem->localName));
2208	    FREE_AND_NULL(str);
2209	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2210	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2211	} else {
2212	    *msg = xmlStrdup(BAD_CAST "Element '");
2213	}
2214	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2215	    vctxt->inode->nsName, vctxt->inode->localName));
2216	FREE_AND_NULL(str);
2217	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2218    } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2219	/*
2220	* Hmm, no node while parsing?
2221	* Return an empty string, in case NULL will break something.
2222	*/
2223	*msg = xmlStrdup(BAD_CAST "");
2224    } else {
2225	TODO
2226	return (NULL);
2227    }
2228    /*
2229    * VAL TODO: The output of the given schema component is currently
2230    * disabled.
2231    */
2232#if 0
2233    if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2234	*msg = xmlStrcat(*msg, BAD_CAST " [");
2235	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2236	    NULL, type, NULL, 0));
2237	FREE_AND_NULL(str)
2238	*msg = xmlStrcat(*msg, BAD_CAST "]");
2239    }
2240#endif
2241    return (*msg);
2242}
2243
2244static void
2245xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2246		     const char *funcName,
2247		     const char *message,
2248		     const xmlChar *str1,
2249		     const xmlChar *str2)
2250{
2251    xmlChar *msg = NULL;
2252
2253    if (actxt == NULL)
2254        return;
2255    msg = xmlStrdup(BAD_CAST "Internal error: ");
2256    msg = xmlStrcat(msg, BAD_CAST funcName);
2257    msg = xmlStrcat(msg, BAD_CAST ", ");
2258    msg = xmlStrcat(msg, BAD_CAST message);
2259    msg = xmlStrcat(msg, BAD_CAST ".\n");
2260
2261    if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2262	xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2263	    (const char *) msg, str1, str2);
2264
2265    else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2266	xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2267	    (const char *) msg, str1, str2);
2268
2269    FREE_AND_NULL(msg)
2270}
2271
2272static void
2273xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2274		     const char *funcName,
2275		     const char *message)
2276{
2277    xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2278}
2279
2280#if 0
2281static void
2282xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2283		     const char *funcName,
2284		     const char *message,
2285		     const xmlChar *str1,
2286		     const xmlChar *str2)
2287{
2288    xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2289	str1, str2);
2290}
2291#endif
2292
2293static void
2294xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2295		   xmlParserErrors error,
2296		   xmlNodePtr node,
2297		   xmlSchemaBasicItemPtr item,
2298		   const char *message,
2299		   const xmlChar *str1, const xmlChar *str2,
2300		   const xmlChar *str3, const xmlChar *str4)
2301{
2302    xmlChar *msg = NULL;
2303
2304    if ((node == NULL) && (item != NULL) &&
2305	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2306	node = WXS_ITEM_NODE(item);
2307	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2308	msg = xmlStrcat(msg, BAD_CAST ": ");
2309    } else
2310	xmlSchemaFormatNodeForError(&msg, actxt, node);
2311    msg = xmlStrcat(msg, (const xmlChar *) message);
2312    msg = xmlStrcat(msg, BAD_CAST ".\n");
2313    xmlSchemaErr4(actxt, error, node,
2314	(const char *) msg, str1, str2, str3, str4);
2315    FREE_AND_NULL(msg)
2316}
2317
2318static void
2319xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2320		   xmlParserErrors error,
2321		   xmlNodePtr node,
2322		   xmlSchemaBasicItemPtr item,
2323		   const char *message,
2324		   const xmlChar *str1,
2325		   const xmlChar *str2)
2326{
2327    xmlSchemaCustomErr4(actxt, error, node, item,
2328	message, str1, str2, NULL, NULL);
2329}
2330
2331
2332
2333static void
2334xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2335		   xmlParserErrors error,
2336		   xmlNodePtr node,
2337		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2338		   const char *message,
2339		   const xmlChar *str1,
2340		   const xmlChar *str2,
2341		   const xmlChar *str3)
2342{
2343    xmlChar *msg = NULL;
2344
2345    xmlSchemaFormatNodeForError(&msg, actxt, node);
2346    msg = xmlStrcat(msg, (const xmlChar *) message);
2347    msg = xmlStrcat(msg, BAD_CAST ".\n");
2348
2349    /* URGENT TODO: Set the error code to something sane. */
2350    xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2351	(const char *) msg, str1, str2, str3, NULL);
2352
2353    FREE_AND_NULL(msg)
2354}
2355
2356
2357
2358static void
2359xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2360		   xmlParserErrors error,
2361		   xmlSchemaPSVIIDCNodePtr idcNode,
2362		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2363		   const char *message,
2364		   const xmlChar *str1,
2365		   const xmlChar *str2)
2366{
2367    xmlChar *msg = NULL, *qname = NULL;
2368
2369    msg = xmlStrdup(BAD_CAST "Element '%s': ");
2370    msg = xmlStrcat(msg, (const xmlChar *) message);
2371    msg = xmlStrcat(msg, BAD_CAST ".\n");
2372    xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2373	error, NULL, idcNode->nodeLine, (const char *) msg,
2374	xmlSchemaFormatQName(&qname,
2375	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2376	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2377	str1, str2, NULL);
2378    FREE_AND_NULL(qname);
2379    FREE_AND_NULL(msg);
2380}
2381
2382static int
2383xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2384			   xmlNodePtr node)
2385{
2386    if (node != NULL)
2387	return (node->type);
2388    if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2389	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2390	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2391    return (-1);
2392}
2393
2394static int
2395xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2396{
2397    switch (item->type) {
2398	case XML_SCHEMA_TYPE_COMPLEX:
2399	case XML_SCHEMA_TYPE_SIMPLE:
2400	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2401		return(1);
2402	    break;
2403	case XML_SCHEMA_TYPE_GROUP:
2404	    return (1);
2405	case XML_SCHEMA_TYPE_ELEMENT:
2406	    if ( ((xmlSchemaElementPtr) item)->flags &
2407		XML_SCHEMAS_ELEM_GLOBAL)
2408		return(1);
2409	    break;
2410	case XML_SCHEMA_TYPE_ATTRIBUTE:
2411	    if ( ((xmlSchemaAttributePtr) item)->flags &
2412		XML_SCHEMAS_ATTR_GLOBAL)
2413		return(1);
2414	    break;
2415	/* Note that attribute groups are always global. */
2416	default:
2417	    return(1);
2418    }
2419    return (0);
2420}
2421
2422static void
2423xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2424		       xmlParserErrors error,
2425		       xmlNodePtr node,
2426		       const xmlChar *value,
2427		       xmlSchemaTypePtr type,
2428		       int displayValue)
2429{
2430    xmlChar *msg = NULL;
2431
2432    xmlSchemaFormatNodeForError(&msg, actxt, node);
2433
2434    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2435	    XML_ATTRIBUTE_NODE))
2436	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2437    else
2438	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2439	    "value of ");
2440
2441    if (! xmlSchemaIsGlobalItem(type))
2442	msg = xmlStrcat(msg, BAD_CAST "the local ");
2443    else
2444	msg = xmlStrcat(msg, BAD_CAST "the ");
2445
2446    if (WXS_IS_ATOMIC(type))
2447	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2448    else if (WXS_IS_LIST(type))
2449	msg = xmlStrcat(msg, BAD_CAST "list type");
2450    else if (WXS_IS_UNION(type))
2451	msg = xmlStrcat(msg, BAD_CAST "union type");
2452
2453    if (xmlSchemaIsGlobalItem(type)) {
2454	xmlChar *str = NULL;
2455	msg = xmlStrcat(msg, BAD_CAST " '");
2456	if (type->builtInType != 0) {
2457	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2458	    msg = xmlStrcat(msg, type->name);
2459	} else
2460	    msg = xmlStrcat(msg,
2461		xmlSchemaFormatQName(&str,
2462		    type->targetNamespace, type->name));
2463	msg = xmlStrcat(msg, BAD_CAST "'");
2464	FREE_AND_NULL(str);
2465    }
2466    msg = xmlStrcat(msg, BAD_CAST ".\n");
2467    if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2468	    XML_ATTRIBUTE_NODE))
2469	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2470    else
2471	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2472    FREE_AND_NULL(msg)
2473}
2474
2475static const xmlChar *
2476xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2477			      xmlSchemaNodeInfoPtr ni,
2478			      xmlNodePtr node)
2479{
2480    if (node != NULL) {
2481	if (node->ns != NULL)
2482	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2483	else
2484	    return (xmlSchemaFormatQName(str, NULL, node->name));
2485    } else if (ni != NULL)
2486	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2487    return (NULL);
2488}
2489
2490static void
2491xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2492			xmlParserErrors error,
2493			xmlSchemaAttrInfoPtr ni,
2494			xmlNodePtr node)
2495{
2496    xmlChar *msg = NULL, *str = NULL;
2497
2498    xmlSchemaFormatNodeForError(&msg, actxt, node);
2499    msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2500    xmlSchemaErr(actxt, error, node, (const char *) msg,
2501	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2502	NULL);
2503    FREE_AND_NULL(str)
2504    FREE_AND_NULL(msg)
2505}
2506
2507static void
2508xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2509		        xmlParserErrors error,
2510		        xmlNodePtr node,
2511			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2512			const char *message,
2513			int nbval,
2514			int nbneg,
2515			xmlChar **values)
2516{
2517    xmlChar *str = NULL, *msg = NULL;
2518    xmlChar *localName, *nsName;
2519    const xmlChar *cur, *end;
2520    int i;
2521
2522    xmlSchemaFormatNodeForError(&msg, actxt, node);
2523    msg = xmlStrcat(msg, (const xmlChar *) message);
2524    msg = xmlStrcat(msg, BAD_CAST ".");
2525    /*
2526    * Note that is does not make sense to report that we have a
2527    * wildcard here, since the wildcard might be unfolded into
2528    * multiple transitions.
2529    */
2530    if (nbval + nbneg > 0) {
2531	if (nbval + nbneg > 1) {
2532	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2533	} else
2534	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2535	nsName = NULL;
2536
2537	for (i = 0; i < nbval + nbneg; i++) {
2538	    cur = values[i];
2539	    if (cur == NULL)
2540	        continue;
2541	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2542	        (cur[3] == ' ')) {
2543		cur += 4;
2544		str = xmlStrcat(str, BAD_CAST "##other");
2545	    }
2546	    /*
2547	    * Get the local name.
2548	    */
2549	    localName = NULL;
2550
2551	    end = cur;
2552	    if (*end == '*') {
2553		localName = xmlStrdup(BAD_CAST "*");
2554		end++;
2555	    } else {
2556		while ((*end != 0) && (*end != '|'))
2557		    end++;
2558		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2559	    }
2560	    if (*end != 0) {
2561		end++;
2562		/*
2563		* Skip "*|*" if they come with negated expressions, since
2564		* they represent the same negated wildcard.
2565		*/
2566		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2567		    /*
2568		    * Get the namespace name.
2569		    */
2570		    cur = end;
2571		    if (*end == '*') {
2572			nsName = xmlStrdup(BAD_CAST "{*}");
2573		    } else {
2574			while (*end != 0)
2575			    end++;
2576
2577			if (i >= nbval)
2578			    nsName = xmlStrdup(BAD_CAST "{##other:");
2579			else
2580			    nsName = xmlStrdup(BAD_CAST "{");
2581
2582			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2583			nsName = xmlStrcat(nsName, BAD_CAST "}");
2584		    }
2585		    str = xmlStrcat(str, BAD_CAST nsName);
2586		    FREE_AND_NULL(nsName)
2587		} else {
2588		    FREE_AND_NULL(localName);
2589		    continue;
2590		}
2591	    }
2592	    str = xmlStrcat(str, BAD_CAST localName);
2593	    FREE_AND_NULL(localName);
2594
2595	    if (i < nbval + nbneg -1)
2596		str = xmlStrcat(str, BAD_CAST ", ");
2597	}
2598	str = xmlStrcat(str, BAD_CAST " ).\n");
2599	msg = xmlStrcat(msg, BAD_CAST str);
2600	FREE_AND_NULL(str)
2601    } else
2602      msg = xmlStrcat(msg, BAD_CAST "\n");
2603    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2604    xmlFree(msg);
2605}
2606
2607static void
2608xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2609		  xmlParserErrors error,
2610		  xmlNodePtr node,
2611		  const xmlChar *value,
2612		  unsigned long length,
2613		  xmlSchemaTypePtr type,
2614		  xmlSchemaFacetPtr facet,
2615		  const char *message,
2616		  const xmlChar *str1,
2617		  const xmlChar *str2)
2618{
2619    xmlChar *str = NULL, *msg = NULL;
2620    xmlSchemaTypeType facetType;
2621    int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2622
2623    xmlSchemaFormatNodeForError(&msg, actxt, node);
2624    if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2625	facetType = XML_SCHEMA_FACET_ENUMERATION;
2626	/*
2627	* If enumerations are validated, one must not expect the
2628	* facet to be given.
2629	*/
2630    } else
2631	facetType = facet->type;
2632    msg = xmlStrcat(msg, BAD_CAST "[");
2633    msg = xmlStrcat(msg, BAD_CAST "facet '");
2634    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2635    msg = xmlStrcat(msg, BAD_CAST "'] ");
2636    if (message == NULL) {
2637	/*
2638	* Use a default message.
2639	*/
2640	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2641	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2642	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2643
2644	    char len[25], actLen[25];
2645
2646	    /* FIXME, TODO: What is the max expected string length of the
2647	    * this value?
2648	    */
2649	    if (nodeType == XML_ATTRIBUTE_NODE)
2650		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2651	    else
2652		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2653
2654	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2655	    snprintf(actLen, 24, "%lu", length);
2656
2657	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2658		msg = xmlStrcat(msg,
2659		BAD_CAST "this differs from the allowed length of '%s'.\n");
2660	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2661		msg = xmlStrcat(msg,
2662		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2663	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2664		msg = xmlStrcat(msg,
2665		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2666
2667	    if (nodeType == XML_ATTRIBUTE_NODE)
2668		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2669		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2670	    else
2671		xmlSchemaErr(actxt, error, node, (const char *) msg,
2672		    (const xmlChar *) actLen, (const xmlChar *) len);
2673
2674	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2675	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2676		"of the set {%s}.\n");
2677	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2679	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2680	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2681		"by the pattern '%s'.\n");
2682	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683		facet->value);
2684	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2685	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2686		"minimum value allowed ('%s').\n");
2687	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2688		facet->value);
2689	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2690	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2691		"maximum value allowed ('%s').\n");
2692	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2693		facet->value);
2694	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2695	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2696		"'%s'.\n");
2697	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2698		facet->value);
2699	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2700	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2701		"'%s'.\n");
2702	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2703		facet->value);
2704	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2705	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2706		"digits than are allowed ('%s').\n");
2707	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2708		facet->value);
2709	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2710	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2711		"digits than are allowed ('%s').\n");
2712	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2713		facet->value);
2714	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2715	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2716	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2717	} else {
2718	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2719	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2720	}
2721    } else {
2722	msg = xmlStrcat(msg, (const xmlChar *) message);
2723	msg = xmlStrcat(msg, BAD_CAST ".\n");
2724	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2725    }
2726    FREE_AND_NULL(str)
2727    xmlFree(msg);
2728}
2729
2730#define VERROR(err, type, msg) \
2731    xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2732
2733#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2734
2735#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2736#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2737
2738#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2739
2740
2741/**
2742 * xmlSchemaPMissingAttrErr:
2743 * @ctxt: the schema validation context
2744 * @ownerDes: the designation of  the owner
2745 * @ownerName: the name of the owner
2746 * @ownerItem: the owner as a schema object
2747 * @ownerElem: the owner as an element node
2748 * @node: the parent element node of the missing attribute node
2749 * @type: the corresponding type of the attribute node
2750 *
2751 * Reports an illegal attribute.
2752 */
2753static void
2754xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2755			 xmlParserErrors error,
2756			 xmlSchemaBasicItemPtr ownerItem,
2757			 xmlNodePtr ownerElem,
2758			 const char *name,
2759			 const char *message)
2760{
2761    xmlChar *des = NULL;
2762
2763    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2764
2765    if (message != NULL)
2766	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2767    else
2768	xmlSchemaPErr(ctxt, ownerElem, error,
2769	    "%s: The attribute '%s' is required but missing.\n",
2770	    BAD_CAST des, BAD_CAST name);
2771    FREE_AND_NULL(des);
2772}
2773
2774
2775/**
2776 * xmlSchemaPResCompAttrErr:
2777 * @ctxt: the schema validation context
2778 * @error: the error code
2779 * @ownerDes: the designation of  the owner
2780 * @ownerItem: the owner as a schema object
2781 * @ownerElem: the owner as an element node
2782 * @name: the name of the attribute holding the QName
2783 * @refName: the referenced local name
2784 * @refURI: the referenced namespace URI
2785 * @message: optional message
2786 *
2787 * Used to report QName attribute values that failed to resolve
2788 * to schema components.
2789 */
2790static void
2791xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2792			 xmlParserErrors error,
2793			 xmlSchemaBasicItemPtr ownerItem,
2794			 xmlNodePtr ownerElem,
2795			 const char *name,
2796			 const xmlChar *refName,
2797			 const xmlChar *refURI,
2798			 xmlSchemaTypeType refType,
2799			 const char *refTypeStr)
2800{
2801    xmlChar *des = NULL, *strA = NULL;
2802
2803    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2804    if (refTypeStr == NULL)
2805	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2806	xmlSchemaPErrExt(ctxt, ownerElem, error,
2807	    NULL, NULL, NULL,
2808	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2809	    "%s.\n", BAD_CAST des, BAD_CAST name,
2810	    xmlSchemaFormatQName(&strA, refURI, refName),
2811	    BAD_CAST refTypeStr, NULL);
2812    FREE_AND_NULL(des)
2813    FREE_AND_NULL(strA)
2814}
2815
2816/**
2817 * xmlSchemaPCustomAttrErr:
2818 * @ctxt: the schema parser context
2819 * @error: the error code
2820 * @ownerDes: the designation of the owner
2821 * @ownerItem: the owner as a schema object
2822 * @attr: the illegal attribute node
2823 *
2824 * Reports an illegal attribute during the parse.
2825 */
2826static void
2827xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2828			xmlParserErrors error,
2829			xmlChar **ownerDes,
2830			xmlSchemaBasicItemPtr ownerItem,
2831			xmlAttrPtr attr,
2832			const char *msg)
2833{
2834    xmlChar *des = NULL;
2835
2836    if (ownerDes == NULL)
2837	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2838    else if (*ownerDes == NULL) {
2839	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2840	des = *ownerDes;
2841    } else
2842	des = *ownerDes;
2843    if (attr == NULL) {
2844	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2845	    "%s, attribute '%s': %s.\n",
2846	    BAD_CAST des, (const xmlChar *) "Unknown",
2847	    (const xmlChar *) msg, NULL, NULL);
2848    } else {
2849	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2850	    "%s, attribute '%s': %s.\n",
2851	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2852    }
2853    if (ownerDes == NULL)
2854	FREE_AND_NULL(des);
2855}
2856
2857/**
2858 * xmlSchemaPIllegalAttrErr:
2859 * @ctxt: the schema parser context
2860 * @error: the error code
2861 * @ownerDes: the designation of the attribute's owner
2862 * @ownerItem: the attribute's owner item
2863 * @attr: the illegal attribute node
2864 *
2865 * Reports an illegal attribute during the parse.
2866 */
2867static void
2868xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2869			 xmlParserErrors error,
2870			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2871			 xmlAttrPtr attr)
2872{
2873    xmlChar *strA = NULL, *strB = NULL;
2874
2875    xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2876    xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2877	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2878	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2879	NULL, NULL);
2880    FREE_AND_NULL(strA);
2881    FREE_AND_NULL(strB);
2882}
2883
2884/**
2885 * xmlSchemaPCustomErr:
2886 * @ctxt: the schema parser context
2887 * @error: the error code
2888 * @itemDes: the designation of the schema item
2889 * @item: the schema item
2890 * @itemElem: the node of the schema item
2891 * @message: the error message
2892 * @str1: an optional param for the error message
2893 * @str2: an optional param for the error message
2894 * @str3: an optional param for the error message
2895 *
2896 * Reports an error during parsing.
2897 */
2898static void
2899xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2900		    xmlParserErrors error,
2901		    xmlSchemaBasicItemPtr item,
2902		    xmlNodePtr itemElem,
2903		    const char *message,
2904		    const xmlChar *str1,
2905		    const xmlChar *str2,
2906		    const xmlChar *str3)
2907{
2908    xmlChar *des = NULL, *msg = NULL;
2909
2910    xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2911    msg = xmlStrdup(BAD_CAST "%s: ");
2912    msg = xmlStrcat(msg, (const xmlChar *) message);
2913    msg = xmlStrcat(msg, BAD_CAST ".\n");
2914    if ((itemElem == NULL) && (item != NULL))
2915	itemElem = WXS_ITEM_NODE(item);
2916    xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2917	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2918    FREE_AND_NULL(des);
2919    FREE_AND_NULL(msg);
2920}
2921
2922/**
2923 * xmlSchemaPCustomErr:
2924 * @ctxt: the schema parser context
2925 * @error: the error code
2926 * @itemDes: the designation of the schema item
2927 * @item: the schema item
2928 * @itemElem: the node of the schema item
2929 * @message: the error message
2930 * @str1: the optional param for the error message
2931 *
2932 * Reports an error during parsing.
2933 */
2934static void
2935xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2936		    xmlParserErrors error,
2937		    xmlSchemaBasicItemPtr item,
2938		    xmlNodePtr itemElem,
2939		    const char *message,
2940		    const xmlChar *str1)
2941{
2942    xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2943	str1, NULL, NULL);
2944}
2945
2946/**
2947 * xmlSchemaPAttrUseErr:
2948 * @ctxt: the schema parser context
2949 * @error: the error code
2950 * @itemDes: the designation of the schema type
2951 * @item: the schema type
2952 * @itemElem: the node of the schema type
2953 * @attr: the invalid schema attribute
2954 * @message: the error message
2955 * @str1: the optional param for the error message
2956 *
2957 * Reports an attribute use error during parsing.
2958 */
2959static void
2960xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2961		    xmlParserErrors error,
2962		    xmlNodePtr node,
2963		    xmlSchemaBasicItemPtr ownerItem,
2964		    const xmlSchemaAttributeUsePtr attruse,
2965		    const char *message,
2966		    const xmlChar *str1, const xmlChar *str2,
2967		    const xmlChar *str3,const xmlChar *str4)
2968{
2969    xmlChar *str = NULL, *msg = NULL;
2970
2971    xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2972    msg = xmlStrcat(msg, BAD_CAST ", ");
2973    msg = xmlStrcat(msg,
2974	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2975	WXS_BASIC_CAST attruse, NULL));
2976    FREE_AND_NULL(str);
2977    msg = xmlStrcat(msg, BAD_CAST ": ");
2978    msg = xmlStrcat(msg, (const xmlChar *) message);
2979    msg = xmlStrcat(msg, BAD_CAST ".\n");
2980    xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2981	(const char *) msg, str1, str2, str3, str4);
2982    xmlFree(msg);
2983}
2984
2985/**
2986 * xmlSchemaPIllegalFacetAtomicErr:
2987 * @ctxt: the schema parser context
2988 * @error: the error code
2989 * @type: the schema type
2990 * @baseType: the base type of type
2991 * @facet: the illegal facet
2992 *
2993 * Reports an illegal facet for atomic simple types.
2994 */
2995static void
2996xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2997			  xmlParserErrors error,
2998			  xmlSchemaTypePtr type,
2999			  xmlSchemaTypePtr baseType,
3000			  xmlSchemaFacetPtr facet)
3001{
3002    xmlChar *des = NULL, *strT = NULL;
3003
3004    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3005    xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3006	"%s: The facet '%s' is not allowed on types derived from the "
3007	"type %s.\n",
3008	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3009	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3010	NULL, NULL);
3011    FREE_AND_NULL(des);
3012    FREE_AND_NULL(strT);
3013}
3014
3015/**
3016 * xmlSchemaPIllegalFacetListUnionErr:
3017 * @ctxt: the schema parser context
3018 * @error: the error code
3019 * @itemDes: the designation of the schema item involved
3020 * @item: the schema item involved
3021 * @facet: the illegal facet
3022 *
3023 * Reports an illegal facet for <list> and <union>.
3024 */
3025static void
3026xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3027			  xmlParserErrors error,
3028			  xmlSchemaTypePtr type,
3029			  xmlSchemaFacetPtr facet)
3030{
3031    xmlChar *des = NULL;
3032
3033    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3034	type->node);
3035    xmlSchemaPErr(ctxt, type->node, error,
3036	"%s: The facet '%s' is not allowed.\n",
3037	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3038    FREE_AND_NULL(des);
3039}
3040
3041/**
3042 * xmlSchemaPMutualExclAttrErr:
3043 * @ctxt: the schema validation context
3044 * @error: the error code
3045 * @elemDes: the designation of the parent element node
3046 * @attr: the bad attribute node
3047 * @type: the corresponding type of the attribute node
3048 *
3049 * Reports an illegal attribute.
3050 */
3051static void
3052xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3053			 xmlParserErrors error,
3054			 xmlSchemaBasicItemPtr ownerItem,
3055			 xmlAttrPtr attr,
3056			 const char *name1,
3057			 const char *name2)
3058{
3059    xmlChar *des = NULL;
3060
3061    xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3062    xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3063	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3064	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3065    FREE_AND_NULL(des);
3066}
3067
3068/**
3069 * xmlSchemaPSimpleTypeErr:
3070 * @ctxt:  the schema validation context
3071 * @error: the error code
3072 * @type: the type specifier
3073 * @ownerDes: the designation of the owner
3074 * @ownerItem: the schema object if existent
3075 * @node: the validated node
3076 * @value: the validated value
3077 *
3078 * Reports a simple type validation error.
3079 * TODO: Should this report the value of an element as well?
3080 */
3081static void
3082xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3083			xmlParserErrors error,
3084			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3085			xmlNodePtr node,
3086			xmlSchemaTypePtr type,
3087			const char *expected,
3088			const xmlChar *value,
3089			const char *message,
3090			const xmlChar *str1,
3091			const xmlChar *str2)
3092{
3093    xmlChar *msg = NULL;
3094
3095    xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3096    if (message == NULL) {
3097	/*
3098	* Use default messages.
3099	*/
3100	if (type != NULL) {
3101	    if (node->type == XML_ATTRIBUTE_NODE)
3102		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3103	    else
3104		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3105		"valid value of ");
3106	    if (! xmlSchemaIsGlobalItem(type))
3107		msg = xmlStrcat(msg, BAD_CAST "the local ");
3108	    else
3109		msg = xmlStrcat(msg, BAD_CAST "the ");
3110
3111	    if (WXS_IS_ATOMIC(type))
3112		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3113	    else if (WXS_IS_LIST(type))
3114		msg = xmlStrcat(msg, BAD_CAST "list type");
3115	    else if (WXS_IS_UNION(type))
3116		msg = xmlStrcat(msg, BAD_CAST "union type");
3117
3118	    if (xmlSchemaIsGlobalItem(type)) {
3119		xmlChar *str = NULL;
3120		msg = xmlStrcat(msg, BAD_CAST " '");
3121		if (type->builtInType != 0) {
3122		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3123		    msg = xmlStrcat(msg, type->name);
3124		} else
3125		    msg = xmlStrcat(msg,
3126			xmlSchemaFormatQName(&str,
3127			    type->targetNamespace, type->name));
3128		msg = xmlStrcat(msg, BAD_CAST "'.");
3129		FREE_AND_NULL(str);
3130	    }
3131	} else {
3132	    if (node->type == XML_ATTRIBUTE_NODE)
3133		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3134	    else
3135		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3136		"valid.");
3137	}
3138	if (expected) {
3139	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3140	    msg = xmlStrcat(msg, BAD_CAST expected);
3141	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3142	} else
3143	    msg = xmlStrcat(msg, BAD_CAST "\n");
3144	if (node->type == XML_ATTRIBUTE_NODE)
3145	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3146	else
3147	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3148    } else {
3149	msg = xmlStrcat(msg, BAD_CAST message);
3150	msg = xmlStrcat(msg, BAD_CAST ".\n");
3151	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3152	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3153    }
3154    /* Cleanup. */
3155    FREE_AND_NULL(msg)
3156}
3157
3158/**
3159 * xmlSchemaPContentErr:
3160 * @ctxt: the schema parser context
3161 * @error: the error code
3162 * @onwerDes: the designation of the holder of the content
3163 * @ownerItem: the owner item of the holder of the content
3164 * @ownerElem: the node of the holder of the content
3165 * @child: the invalid child node
3166 * @message: the optional error message
3167 * @content: the optional string describing the correct content
3168 *
3169 * Reports an error concerning the content of a schema element.
3170 */
3171static void
3172xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3173		     xmlParserErrors error,
3174		     xmlSchemaBasicItemPtr ownerItem,
3175		     xmlNodePtr ownerElem,
3176		     xmlNodePtr child,
3177		     const char *message,
3178		     const char *content)
3179{
3180    xmlChar *des = NULL;
3181
3182    xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3183    if (message != NULL)
3184	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3185	    "%s: %s.\n",
3186	    BAD_CAST des, BAD_CAST message);
3187    else {
3188	if (content != NULL) {
3189	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3190		"%s: The content is not valid. Expected is %s.\n",
3191		BAD_CAST des, BAD_CAST content);
3192	} else {
3193	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3194		"%s: The content is not valid.\n",
3195		BAD_CAST des, NULL);
3196	}
3197    }
3198    FREE_AND_NULL(des)
3199}
3200
3201/************************************************************************
3202 * 									*
3203 * 			Streamable error functions                      *
3204 * 									*
3205 ************************************************************************/
3206
3207
3208
3209
3210/************************************************************************
3211 * 									*
3212 * 			Validation helper functions			*
3213 * 									*
3214 ************************************************************************/
3215
3216
3217/************************************************************************
3218 * 									*
3219 * 			Allocation functions				*
3220 * 									*
3221 ************************************************************************/
3222
3223/**
3224 * xmlSchemaNewSchemaForParserCtxt:
3225 * @ctxt:  a schema validation context
3226 *
3227 * Allocate a new Schema structure.
3228 *
3229 * Returns the newly allocated structure or NULL in case or error
3230 */
3231static xmlSchemaPtr
3232xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3233{
3234    xmlSchemaPtr ret;
3235
3236    ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3237    if (ret == NULL) {
3238        xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3239        return (NULL);
3240    }
3241    memset(ret, 0, sizeof(xmlSchema));
3242    ret->dict = ctxt->dict;
3243    xmlDictReference(ret->dict);
3244
3245    return (ret);
3246}
3247
3248/**
3249 * xmlSchemaNewFacet:
3250 *
3251 * Allocate a new Facet structure.
3252 *
3253 * Returns the newly allocated structure or NULL in case or error
3254 */
3255xmlSchemaFacetPtr
3256xmlSchemaNewFacet(void)
3257{
3258    xmlSchemaFacetPtr ret;
3259
3260    ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3261    if (ret == NULL) {
3262        return (NULL);
3263    }
3264    memset(ret, 0, sizeof(xmlSchemaFacet));
3265
3266    return (ret);
3267}
3268
3269/**
3270 * xmlSchemaNewAnnot:
3271 * @ctxt:  a schema validation context
3272 * @node:  a node
3273 *
3274 * Allocate a new annotation structure.
3275 *
3276 * Returns the newly allocated structure or NULL in case or error
3277 */
3278static xmlSchemaAnnotPtr
3279xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3280{
3281    xmlSchemaAnnotPtr ret;
3282
3283    ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3284    if (ret == NULL) {
3285        xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3286        return (NULL);
3287    }
3288    memset(ret, 0, sizeof(xmlSchemaAnnot));
3289    ret->content = node;
3290    return (ret);
3291}
3292
3293static xmlSchemaItemListPtr
3294xmlSchemaItemListCreate(void)
3295{
3296    xmlSchemaItemListPtr ret;
3297
3298    ret = xmlMalloc(sizeof(xmlSchemaItemList));
3299    if (ret == NULL) {
3300	xmlSchemaPErrMemory(NULL,
3301	    "allocating an item list structure", NULL);
3302	return (NULL);
3303    }
3304    memset(ret, 0, sizeof(xmlSchemaItemList));
3305    return (ret);
3306}
3307
3308static void
3309xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3310{
3311    if (list->items != NULL) {
3312	xmlFree(list->items);
3313	list->items = NULL;
3314    }
3315    list->nbItems = 0;
3316    list->sizeItems = 0;
3317}
3318
3319static int
3320xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3321{
3322    if (list->items == NULL) {
3323	list->items = (void **) xmlMalloc(
3324	    20 * sizeof(void *));
3325	if (list->items == NULL) {
3326	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3327	    return(-1);
3328	}
3329	list->sizeItems = 20;
3330    } else if (list->sizeItems <= list->nbItems) {
3331	list->sizeItems *= 2;
3332	list->items = (void **) xmlRealloc(list->items,
3333	    list->sizeItems * sizeof(void *));
3334	if (list->items == NULL) {
3335	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3336	    list->sizeItems = 0;
3337	    return(-1);
3338	}
3339    }
3340    list->items[list->nbItems++] = item;
3341    return(0);
3342}
3343
3344static int
3345xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3346			 int initialSize,
3347			 void *item)
3348{
3349    if (list->items == NULL) {
3350	if (initialSize <= 0)
3351	    initialSize = 1;
3352	list->items = (void **) xmlMalloc(
3353	    initialSize * sizeof(void *));
3354	if (list->items == NULL) {
3355	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3356	    return(-1);
3357	}
3358	list->sizeItems = initialSize;
3359    } else if (list->sizeItems <= list->nbItems) {
3360	list->sizeItems *= 2;
3361	list->items = (void **) xmlRealloc(list->items,
3362	    list->sizeItems * sizeof(void *));
3363	if (list->items == NULL) {
3364	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3365	    list->sizeItems = 0;
3366	    return(-1);
3367	}
3368    }
3369    list->items[list->nbItems++] = item;
3370    return(0);
3371}
3372
3373static int
3374xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3375{
3376    if (list->items == NULL) {
3377	list->items = (void **) xmlMalloc(
3378	    20 * sizeof(void *));
3379	if (list->items == NULL) {
3380	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3381	    return(-1);
3382	}
3383	list->sizeItems = 20;
3384    } else if (list->sizeItems <= list->nbItems) {
3385	list->sizeItems *= 2;
3386	list->items = (void **) xmlRealloc(list->items,
3387	    list->sizeItems * sizeof(void *));
3388	if (list->items == NULL) {
3389	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3390	    list->sizeItems = 0;
3391	    return(-1);
3392	}
3393    }
3394    /*
3395    * Just append if the index is greater/equal than the item count.
3396    */
3397    if (idx >= list->nbItems) {
3398	list->items[list->nbItems++] = item;
3399    } else {
3400	int i;
3401	for (i = list->nbItems; i > idx; i--)
3402	    list->items[i] = list->items[i-1];
3403	list->items[idx] = item;
3404	list->nbItems++;
3405    }
3406    return(0);
3407}
3408
3409#if 0 /* enable if ever needed */
3410static int
3411xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3412			    int initialSize,
3413			    void *item,
3414			    int idx)
3415{
3416    if (list->items == NULL) {
3417	if (initialSize <= 0)
3418	    initialSize = 1;
3419	list->items = (void **) xmlMalloc(
3420	    initialSize * sizeof(void *));
3421	if (list->items == NULL) {
3422	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3423	    return(-1);
3424	}
3425	list->sizeItems = initialSize;
3426    } else if (list->sizeItems <= list->nbItems) {
3427	list->sizeItems *= 2;
3428	list->items = (void **) xmlRealloc(list->items,
3429	    list->sizeItems * sizeof(void *));
3430	if (list->items == NULL) {
3431	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3432	    list->sizeItems = 0;
3433	    return(-1);
3434	}
3435    }
3436    /*
3437    * Just append if the index is greater/equal than the item count.
3438    */
3439    if (idx >= list->nbItems) {
3440	list->items[list->nbItems++] = item;
3441    } else {
3442	int i;
3443	for (i = list->nbItems; i > idx; i--)
3444	    list->items[i] = list->items[i-1];
3445	list->items[idx] = item;
3446	list->nbItems++;
3447    }
3448    return(0);
3449}
3450#endif
3451
3452static int
3453xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3454{
3455    int i;
3456    if ((list->items == NULL) || (idx >= list->nbItems)) {
3457	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3458	    "index error.\n");
3459	return(-1);
3460    }
3461
3462    if (list->nbItems == 1) {
3463	/* TODO: Really free the list? */
3464	xmlFree(list->items);
3465	list->items = NULL;
3466	list->nbItems = 0;
3467	list->sizeItems = 0;
3468    } else if (list->nbItems -1 == idx) {
3469	list->nbItems--;
3470    } else {
3471	for (i = idx; i < list->nbItems -1; i++)
3472	    list->items[i] = list->items[i+1];
3473	list->nbItems--;
3474    }
3475    return(0);
3476}
3477
3478/**
3479 * xmlSchemaItemListFree:
3480 * @annot:  a schema type structure
3481 *
3482 * Deallocate a annotation structure
3483 */
3484static void
3485xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3486{
3487    if (list == NULL)
3488	return;
3489    if (list->items != NULL)
3490	xmlFree(list->items);
3491    xmlFree(list);
3492}
3493
3494static void
3495xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3496{
3497    if (bucket == NULL)
3498	return;
3499    if (bucket->globals != NULL) {
3500	xmlSchemaComponentListFree(bucket->globals);
3501	xmlSchemaItemListFree(bucket->globals);
3502    }
3503    if (bucket->locals != NULL) {
3504	xmlSchemaComponentListFree(bucket->locals);
3505	xmlSchemaItemListFree(bucket->locals);
3506    }
3507    if (bucket->relations != NULL) {
3508	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3509	do {
3510	    prev = cur;
3511	    cur = cur->next;
3512	    xmlFree(prev);
3513	} while (cur != NULL);
3514    }
3515    if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3516	xmlFreeDoc(bucket->doc);
3517    }
3518    if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3519	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3520	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3521    }
3522    xmlFree(bucket);
3523}
3524
3525static xmlSchemaBucketPtr
3526xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3527			 int type, const xmlChar *targetNamespace)
3528{
3529    xmlSchemaBucketPtr ret;
3530    int size;
3531    xmlSchemaPtr mainSchema;
3532
3533    if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3534	PERROR_INT("xmlSchemaBucketCreate",
3535	    "no main schema on constructor");
3536	return(NULL);
3537    }
3538    mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3539    /* Create the schema bucket. */
3540    if (WXS_IS_BUCKET_INCREDEF(type))
3541	size = sizeof(xmlSchemaInclude);
3542    else
3543	size = sizeof(xmlSchemaImport);
3544    ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3545    if (ret == NULL) {
3546	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3547	return(NULL);
3548    }
3549    memset(ret, 0, size);
3550    ret->targetNamespace = targetNamespace;
3551    ret->type = type;
3552    ret->globals = xmlSchemaItemListCreate();
3553    if (ret->globals == NULL) {
3554	xmlFree(ret);
3555	return(NULL);
3556    }
3557    ret->locals = xmlSchemaItemListCreate();
3558    if (ret->locals == NULL) {
3559	xmlFree(ret);
3560	return(NULL);
3561    }
3562    /*
3563    * The following will assure that only the first bucket is marked as
3564    * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3565    * For each following import buckets an xmlSchema will be created.
3566    * An xmlSchema will be created for every distinct targetNamespace.
3567    * We assign the targetNamespace to the schemata here.
3568    */
3569    if (! WXS_HAS_BUCKETS(pctxt)) {
3570	if (WXS_IS_BUCKET_INCREDEF(type)) {
3571	    PERROR_INT("xmlSchemaBucketCreate",
3572		"first bucket but it's an include or redefine");
3573	    xmlSchemaBucketFree(ret);
3574	    return(NULL);
3575	}
3576	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3577	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3578	/* Point to the *main* schema. */
3579	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3580	WXS_IMPBUCKET(ret)->schema = mainSchema;
3581	/*
3582	* Ensure that the main schema gets a targetNamespace.
3583	*/
3584	mainSchema->targetNamespace = targetNamespace;
3585    } else {
3586	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3587	    PERROR_INT("xmlSchemaBucketCreate",
3588		"main bucket but it's not the first one");
3589	    xmlSchemaBucketFree(ret);
3590	    return(NULL);
3591	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3592	    /*
3593	    * Create a schema for imports and assign the
3594	    * targetNamespace.
3595	    */
3596	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3597	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3598		xmlSchemaBucketFree(ret);
3599		return(NULL);
3600	    }
3601	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3602	}
3603    }
3604    if (WXS_IS_BUCKET_IMPMAIN(type)) {
3605	int res;
3606	/*
3607	* Imports go into the "schemasImports" slot of the main *schema*.
3608	* Note that we create an import entry for the main schema as well; i.e.,
3609	* even if there's only one schema, we'll get an import.
3610	*/
3611	if (mainSchema->schemasImports == NULL) {
3612	    mainSchema->schemasImports = xmlHashCreateDict(5,
3613		WXS_CONSTRUCTOR(pctxt)->dict);
3614	    if (mainSchema->schemasImports == NULL) {
3615		xmlSchemaBucketFree(ret);
3616		return(NULL);
3617	    }
3618	}
3619	if (targetNamespace == NULL)
3620	    res = xmlHashAddEntry(mainSchema->schemasImports,
3621		XML_SCHEMAS_NO_NAMESPACE, ret);
3622	else
3623	    res = xmlHashAddEntry(mainSchema->schemasImports,
3624		targetNamespace, ret);
3625	if (res != 0) {
3626	    PERROR_INT("xmlSchemaBucketCreate",
3627		"failed to add the schema bucket to the hash");
3628	    xmlSchemaBucketFree(ret);
3629	    return(NULL);
3630	}
3631    } else {
3632	/* Set the @ownerImport of an include bucket. */
3633	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3634	    WXS_INCBUCKET(ret)->ownerImport =
3635		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3636	else
3637	    WXS_INCBUCKET(ret)->ownerImport =
3638		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3639
3640	/* Includes got into the "includes" slot of the *main* schema. */
3641	if (mainSchema->includes == NULL) {
3642	    mainSchema->includes = xmlSchemaItemListCreate();
3643	    if (mainSchema->includes == NULL) {
3644		xmlSchemaBucketFree(ret);
3645		return(NULL);
3646	    }
3647	}
3648	xmlSchemaItemListAdd(mainSchema->includes, ret);
3649    }
3650    /*
3651    * Add to list of all buckets; this is used for lookup
3652    * during schema construction time only.
3653    */
3654    if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3655	return(NULL);
3656    return(ret);
3657}
3658
3659static int
3660xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3661{
3662    if (*list == NULL) {
3663	*list = xmlSchemaItemListCreate();
3664	if (*list == NULL)
3665	    return(-1);
3666    }
3667    xmlSchemaItemListAddSize(*list, initialSize, item);
3668    return(0);
3669}
3670
3671/**
3672 * xmlSchemaFreeAnnot:
3673 * @annot:  a schema type structure
3674 *
3675 * Deallocate a annotation structure
3676 */
3677static void
3678xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3679{
3680    if (annot == NULL)
3681        return;
3682    if (annot->next == NULL) {
3683	xmlFree(annot);
3684    } else {
3685	xmlSchemaAnnotPtr prev;
3686
3687	do {
3688	    prev = annot;
3689	    annot = annot->next;
3690	    xmlFree(prev);
3691	} while (annot != NULL);
3692    }
3693}
3694
3695/**
3696 * xmlSchemaFreeNotation:
3697 * @schema:  a schema notation structure
3698 *
3699 * Deallocate a Schema Notation structure.
3700 */
3701static void
3702xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3703{
3704    if (nota == NULL)
3705        return;
3706    xmlFree(nota);
3707}
3708
3709/**
3710 * xmlSchemaFreeAttribute:
3711 * @attr:  an attribute declaration
3712 *
3713 * Deallocates an attribute declaration structure.
3714 */
3715static void
3716xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3717{
3718    if (attr == NULL)
3719        return;
3720    if (attr->annot != NULL)
3721	xmlSchemaFreeAnnot(attr->annot);
3722    if (attr->defVal != NULL)
3723	xmlSchemaFreeValue(attr->defVal);
3724    xmlFree(attr);
3725}
3726
3727/**
3728 * xmlSchemaFreeAttributeUse:
3729 * @use:  an attribute use
3730 *
3731 * Deallocates an attribute use structure.
3732 */
3733static void
3734xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3735{
3736    if (use == NULL)
3737        return;
3738    if (use->annot != NULL)
3739	xmlSchemaFreeAnnot(use->annot);
3740    if (use->defVal != NULL)
3741	xmlSchemaFreeValue(use->defVal);
3742    xmlFree(use);
3743}
3744
3745/**
3746 * xmlSchemaFreeAttributeUseProhib:
3747 * @prohib:  an attribute use prohibition
3748 *
3749 * Deallocates an attribute use structure.
3750 */
3751static void
3752xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3753{
3754    if (prohib == NULL)
3755        return;
3756    xmlFree(prohib);
3757}
3758
3759/**
3760 * xmlSchemaFreeWildcardNsSet:
3761 * set:  a schema wildcard namespace
3762 *
3763 * Deallocates a list of wildcard constraint structures.
3764 */
3765static void
3766xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3767{
3768    xmlSchemaWildcardNsPtr next;
3769
3770    while (set != NULL) {
3771	next = set->next;
3772	xmlFree(set);
3773	set = next;
3774    }
3775}
3776
3777/**
3778 * xmlSchemaFreeWildcard:
3779 * @wildcard:  a wildcard structure
3780 *
3781 * Deallocates a wildcard structure.
3782 */
3783void
3784xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3785{
3786    if (wildcard == NULL)
3787        return;
3788    if (wildcard->annot != NULL)
3789        xmlSchemaFreeAnnot(wildcard->annot);
3790    if (wildcard->nsSet != NULL)
3791	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3792    if (wildcard->negNsSet != NULL)
3793	xmlFree(wildcard->negNsSet);
3794    xmlFree(wildcard);
3795}
3796
3797/**
3798 * xmlSchemaFreeAttributeGroup:
3799 * @schema:  a schema attribute group structure
3800 *
3801 * Deallocate a Schema Attribute Group structure.
3802 */
3803static void
3804xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3805{
3806    if (attrGr == NULL)
3807        return;
3808    if (attrGr->annot != NULL)
3809        xmlSchemaFreeAnnot(attrGr->annot);
3810    if (attrGr->attrUses != NULL)
3811	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3812    xmlFree(attrGr);
3813}
3814
3815/**
3816 * xmlSchemaFreeQNameRef:
3817 * @item: a QName reference structure
3818 *
3819 * Deallocatea a QName reference structure.
3820 */
3821static void
3822xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3823{
3824    xmlFree(item);
3825}
3826
3827/**
3828 * xmlSchemaFreeTypeLinkList:
3829 * @alink: a type link
3830 *
3831 * Deallocate a list of types.
3832 */
3833static void
3834xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3835{
3836    xmlSchemaTypeLinkPtr next;
3837
3838    while (link != NULL) {
3839	next = link->next;
3840	xmlFree(link);
3841	link = next;
3842    }
3843}
3844
3845static void
3846xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3847{
3848    xmlSchemaIDCStateObjPtr next;
3849    while (sto != NULL) {
3850	next = sto->next;
3851	if (sto->history != NULL)
3852	    xmlFree(sto->history);
3853	if (sto->xpathCtxt != NULL)
3854	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3855	xmlFree(sto);
3856	sto = next;
3857    }
3858}
3859
3860/**
3861 * xmlSchemaFreeIDC:
3862 * @idc: a identity-constraint definition
3863 *
3864 * Deallocates an identity-constraint definition.
3865 */
3866static void
3867xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3868{
3869    xmlSchemaIDCSelectPtr cur, prev;
3870
3871    if (idcDef == NULL)
3872	return;
3873    if (idcDef->annot != NULL)
3874        xmlSchemaFreeAnnot(idcDef->annot);
3875    /* Selector */
3876    if (idcDef->selector != NULL) {
3877	if (idcDef->selector->xpathComp != NULL)
3878	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3879	xmlFree(idcDef->selector);
3880    }
3881    /* Fields */
3882    if (idcDef->fields != NULL) {
3883	cur = idcDef->fields;
3884	do {
3885	    prev = cur;
3886	    cur = cur->next;
3887	    if (prev->xpathComp != NULL)
3888		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3889	    xmlFree(prev);
3890	} while (cur != NULL);
3891    }
3892    xmlFree(idcDef);
3893}
3894
3895/**
3896 * xmlSchemaFreeElement:
3897 * @schema:  a schema element structure
3898 *
3899 * Deallocate a Schema Element structure.
3900 */
3901static void
3902xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3903{
3904    if (elem == NULL)
3905        return;
3906    if (elem->annot != NULL)
3907        xmlSchemaFreeAnnot(elem->annot);
3908    if (elem->contModel != NULL)
3909        xmlRegFreeRegexp(elem->contModel);
3910    if (elem->defVal != NULL)
3911	xmlSchemaFreeValue(elem->defVal);
3912    xmlFree(elem);
3913}
3914
3915/**
3916 * xmlSchemaFreeFacet:
3917 * @facet:  a schema facet structure
3918 *
3919 * Deallocate a Schema Facet structure.
3920 */
3921void
3922xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3923{
3924    if (facet == NULL)
3925        return;
3926    if (facet->val != NULL)
3927        xmlSchemaFreeValue(facet->val);
3928    if (facet->regexp != NULL)
3929        xmlRegFreeRegexp(facet->regexp);
3930    if (facet->annot != NULL)
3931        xmlSchemaFreeAnnot(facet->annot);
3932    xmlFree(facet);
3933}
3934
3935/**
3936 * xmlSchemaFreeType:
3937 * @type:  a schema type structure
3938 *
3939 * Deallocate a Schema Type structure.
3940 */
3941void
3942xmlSchemaFreeType(xmlSchemaTypePtr type)
3943{
3944    if (type == NULL)
3945        return;
3946    if (type->annot != NULL)
3947        xmlSchemaFreeAnnot(type->annot);
3948    if (type->facets != NULL) {
3949        xmlSchemaFacetPtr facet, next;
3950
3951        facet = type->facets;
3952        while (facet != NULL) {
3953            next = facet->next;
3954            xmlSchemaFreeFacet(facet);
3955            facet = next;
3956        }
3957    }
3958    if (type->attrUses != NULL)
3959	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3960    if (type->memberTypes != NULL)
3961	xmlSchemaFreeTypeLinkList(type->memberTypes);
3962    if (type->facetSet != NULL) {
3963	xmlSchemaFacetLinkPtr next, link;
3964
3965	link = type->facetSet;
3966	do {
3967	    next = link->next;
3968	    xmlFree(link);
3969	    link = next;
3970	} while (link != NULL);
3971    }
3972    if (type->contModel != NULL)
3973        xmlRegFreeRegexp(type->contModel);
3974    xmlFree(type);
3975}
3976
3977/**
3978 * xmlSchemaFreeModelGroupDef:
3979 * @item:  a schema model group definition
3980 *
3981 * Deallocates a schema model group definition.
3982 */
3983static void
3984xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3985{
3986    if (item->annot != NULL)
3987	xmlSchemaFreeAnnot(item->annot);
3988    xmlFree(item);
3989}
3990
3991/**
3992 * xmlSchemaFreeModelGroup:
3993 * @item:  a schema model group
3994 *
3995 * Deallocates a schema model group structure.
3996 */
3997static void
3998xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3999{
4000    if (item->annot != NULL)
4001	xmlSchemaFreeAnnot(item->annot);
4002    xmlFree(item);
4003}
4004
4005static void
4006xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4007{
4008    if ((list == NULL) || (list->nbItems == 0))
4009	return;
4010    {
4011	xmlSchemaTreeItemPtr item;
4012	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4013	int i;
4014
4015	for (i = 0; i < list->nbItems; i++) {
4016	    item = items[i];
4017	    if (item == NULL)
4018		continue;
4019	    switch (item->type) {
4020		case XML_SCHEMA_TYPE_SIMPLE:
4021		case XML_SCHEMA_TYPE_COMPLEX:
4022		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4023		    break;
4024		case XML_SCHEMA_TYPE_ATTRIBUTE:
4025		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4026		    break;
4027		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4028		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4029		    break;
4030		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4031		    xmlSchemaFreeAttributeUseProhib(
4032			(xmlSchemaAttributeUseProhibPtr) item);
4033		    break;
4034		case XML_SCHEMA_TYPE_ELEMENT:
4035		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4036		    break;
4037		case XML_SCHEMA_TYPE_PARTICLE:
4038		    if (item->annot != NULL)
4039			xmlSchemaFreeAnnot(item->annot);
4040		    xmlFree(item);
4041		    break;
4042		case XML_SCHEMA_TYPE_SEQUENCE:
4043		case XML_SCHEMA_TYPE_CHOICE:
4044		case XML_SCHEMA_TYPE_ALL:
4045		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4046		    break;
4047		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4048		    xmlSchemaFreeAttributeGroup(
4049			(xmlSchemaAttributeGroupPtr) item);
4050		    break;
4051		case XML_SCHEMA_TYPE_GROUP:
4052		    xmlSchemaFreeModelGroupDef(
4053			(xmlSchemaModelGroupDefPtr) item);
4054		    break;
4055		case XML_SCHEMA_TYPE_ANY:
4056		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4057		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4058		    break;
4059		case XML_SCHEMA_TYPE_IDC_KEY:
4060		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4061		case XML_SCHEMA_TYPE_IDC_KEYREF:
4062		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4063		    break;
4064		case XML_SCHEMA_TYPE_NOTATION:
4065		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4066		    break;
4067		case XML_SCHEMA_EXTRA_QNAMEREF:
4068		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4069		    break;
4070		default: {
4071		    /* TODO: This should never be hit. */
4072		    xmlSchemaPSimpleInternalErr(NULL,
4073			"Internal error: xmlSchemaComponentListFree, "
4074			"unexpected component type '%s'\n",
4075			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4076			 }
4077		    break;
4078	    }
4079	}
4080	list->nbItems = 0;
4081    }
4082}
4083
4084/**
4085 * xmlSchemaFree:
4086 * @schema:  a schema structure
4087 *
4088 * Deallocate a Schema structure.
4089 */
4090void
4091xmlSchemaFree(xmlSchemaPtr schema)
4092{
4093    if (schema == NULL)
4094        return;
4095    /* @volatiles is not used anymore :-/ */
4096    if (schema->volatiles != NULL)
4097	TODO
4098    /*
4099    * Note that those slots are not responsible for freeing
4100    * schema components anymore; this will now be done by
4101    * the schema buckets.
4102    */
4103    if (schema->notaDecl != NULL)
4104        xmlHashFree(schema->notaDecl, NULL);
4105    if (schema->attrDecl != NULL)
4106        xmlHashFree(schema->attrDecl, NULL);
4107    if (schema->attrgrpDecl != NULL)
4108        xmlHashFree(schema->attrgrpDecl, NULL);
4109    if (schema->elemDecl != NULL)
4110        xmlHashFree(schema->elemDecl, NULL);
4111    if (schema->typeDecl != NULL)
4112        xmlHashFree(schema->typeDecl, NULL);
4113    if (schema->groupDecl != NULL)
4114        xmlHashFree(schema->groupDecl, NULL);
4115    if (schema->idcDef != NULL)
4116        xmlHashFree(schema->idcDef, NULL);
4117
4118    if (schema->schemasImports != NULL)
4119	xmlHashFree(schema->schemasImports,
4120		    (xmlHashDeallocator) xmlSchemaBucketFree);
4121    if (schema->includes != NULL) {
4122	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4123	int i;
4124	for (i = 0; i < list->nbItems; i++) {
4125	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4126	}
4127	xmlSchemaItemListFree(list);
4128    }
4129    if (schema->annot != NULL)
4130        xmlSchemaFreeAnnot(schema->annot);
4131    /* Never free the doc here, since this will be done by the buckets. */
4132
4133    xmlDictFree(schema->dict);
4134    xmlFree(schema);
4135}
4136
4137/************************************************************************
4138 * 									*
4139 * 			Debug functions					*
4140 * 									*
4141 ************************************************************************/
4142
4143#ifdef LIBXML_OUTPUT_ENABLED
4144
4145static void
4146xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4147
4148/**
4149 * xmlSchemaElementDump:
4150 * @elem:  an element
4151 * @output:  the file output
4152 *
4153 * Dump the element
4154 */
4155static void
4156xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4157                     const xmlChar * name ATTRIBUTE_UNUSED,
4158		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4159                     const xmlChar * context ATTRIBUTE_UNUSED)
4160{
4161    if (elem == NULL)
4162        return;
4163
4164
4165    fprintf(output, "Element");
4166    if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4167	fprintf(output, " (global)");
4168    fprintf(output, ": '%s' ", elem->name);
4169    if (namespace != NULL)
4170	fprintf(output, "ns '%s'", namespace);
4171    fprintf(output, "\n");
4172#if 0
4173    if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4174	fprintf(output, "  min %d ", elem->minOccurs);
4175        if (elem->maxOccurs >= UNBOUNDED)
4176            fprintf(output, "max: unbounded\n");
4177        else if (elem->maxOccurs != 1)
4178            fprintf(output, "max: %d\n", elem->maxOccurs);
4179        else
4180            fprintf(output, "\n");
4181    }
4182#endif
4183    /*
4184    * Misc other properties.
4185    */
4186    if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4187	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4188	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4189	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4190	fprintf(output, "  props: ");
4191	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4192	    fprintf(output, "[fixed] ");
4193	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4194	    fprintf(output, "[default] ");
4195	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4196	    fprintf(output, "[abstract] ");
4197	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4198	    fprintf(output, "[nillable] ");
4199	fprintf(output, "\n");
4200    }
4201    /*
4202    * Default/fixed value.
4203    */
4204    if (elem->value != NULL)
4205	fprintf(output, "  value: '%s'\n", elem->value);
4206    /*
4207    * Type.
4208    */
4209    if (elem->namedType != NULL) {
4210	fprintf(output, "  type: '%s' ", elem->namedType);
4211	if (elem->namedTypeNs != NULL)
4212	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4213	else
4214	    fprintf(output, "\n");
4215    } else if (elem->subtypes != NULL) {
4216	/*
4217	* Dump local types.
4218	*/
4219	xmlSchemaTypeDump(elem->subtypes, output);
4220    }
4221    /*
4222    * Substitution group.
4223    */
4224    if (elem->substGroup != NULL) {
4225	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4226	if (elem->substGroupNs != NULL)
4227	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4228	else
4229	    fprintf(output, "\n");
4230    }
4231}
4232
4233/**
4234 * xmlSchemaAnnotDump:
4235 * @output:  the file output
4236 * @annot:  a annotation
4237 *
4238 * Dump the annotation
4239 */
4240static void
4241xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4242{
4243    xmlChar *content;
4244
4245    if (annot == NULL)
4246        return;
4247
4248    content = xmlNodeGetContent(annot->content);
4249    if (content != NULL) {
4250        fprintf(output, "  Annot: %s\n", content);
4251        xmlFree(content);
4252    } else
4253        fprintf(output, "  Annot: empty\n");
4254}
4255
4256/**
4257 * xmlSchemaContentModelDump:
4258 * @particle: the schema particle
4259 * @output: the file output
4260 * @depth: the depth used for intentation
4261 *
4262 * Dump a SchemaType structure
4263 */
4264static void
4265xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4266{
4267    xmlChar *str = NULL;
4268    xmlSchemaTreeItemPtr term;
4269    char shift[100];
4270    int i;
4271
4272    if (particle == NULL)
4273	return;
4274    for (i = 0;((i < depth) && (i < 25));i++)
4275        shift[2 * i] = shift[2 * i + 1] = ' ';
4276    shift[2 * i] = shift[2 * i + 1] = 0;
4277    fprintf(output, shift);
4278    if (particle->children == NULL) {
4279	fprintf(output, "MISSING particle term\n");
4280	return;
4281    }
4282    term = particle->children;
4283    if (term == NULL) {
4284	fprintf(output, "(NULL)");
4285    } else {
4286	switch (term->type) {
4287	    case XML_SCHEMA_TYPE_ELEMENT:
4288		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4289		    ((xmlSchemaElementPtr)term)->targetNamespace,
4290		    ((xmlSchemaElementPtr)term)->name));
4291		FREE_AND_NULL(str);
4292		break;
4293	    case XML_SCHEMA_TYPE_SEQUENCE:
4294		fprintf(output, "SEQUENCE");
4295		break;
4296	    case XML_SCHEMA_TYPE_CHOICE:
4297		fprintf(output, "CHOICE");
4298		break;
4299	    case XML_SCHEMA_TYPE_ALL:
4300		fprintf(output, "ALL");
4301		break;
4302	    case XML_SCHEMA_TYPE_ANY:
4303		fprintf(output, "ANY");
4304		break;
4305	    default:
4306		fprintf(output, "UNKNOWN\n");
4307		return;
4308	}
4309    }
4310    if (particle->minOccurs != 1)
4311	fprintf(output, " min: %d", particle->minOccurs);
4312    if (particle->maxOccurs >= UNBOUNDED)
4313	fprintf(output, " max: unbounded");
4314    else if (particle->maxOccurs != 1)
4315	fprintf(output, " max: %d", particle->maxOccurs);
4316    fprintf(output, "\n");
4317    if (term &&
4318	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4319	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4320	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4321	 (term->children != NULL)) {
4322	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4323	    output, depth +1);
4324    }
4325    if (particle->next != NULL)
4326	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4327		output, depth);
4328}
4329
4330/**
4331 * xmlSchemaAttrUsesDump:
4332 * @uses:  attribute uses list
4333 * @output:  the file output
4334 *
4335 * Dumps a list of attribute use components.
4336 */
4337static void
4338xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4339{
4340    xmlSchemaAttributeUsePtr use;
4341    xmlSchemaAttributeUseProhibPtr prohib;
4342    xmlSchemaQNameRefPtr ref;
4343    const xmlChar *name, *tns;
4344    xmlChar *str = NULL;
4345    int i;
4346
4347    if ((uses == NULL) || (uses->nbItems == 0))
4348        return;
4349
4350    fprintf(output, "  attributes:\n");
4351    for (i = 0; i < uses->nbItems; i++) {
4352	use = uses->items[i];
4353	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4354	    fprintf(output, "  [prohibition] ");
4355	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4356	    name = prohib->name;
4357	    tns = prohib->targetNamespace;
4358	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4359	    fprintf(output, "  [reference] ");
4360	    ref = (xmlSchemaQNameRefPtr) use;
4361	    name = ref->name;
4362	    tns = ref->targetNamespace;
4363	} else {
4364	    fprintf(output, "  [use] ");
4365	    name = WXS_ATTRUSE_DECL_NAME(use);
4366	    tns = WXS_ATTRUSE_DECL_TNS(use);
4367	}
4368	fprintf(output, "'%s'\n",
4369	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4370	FREE_AND_NULL(str);
4371    }
4372}
4373
4374/**
4375 * xmlSchemaTypeDump:
4376 * @output:  the file output
4377 * @type:  a type structure
4378 *
4379 * Dump a SchemaType structure
4380 */
4381static void
4382xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4383{
4384    if (type == NULL) {
4385        fprintf(output, "Type: NULL\n");
4386        return;
4387    }
4388    fprintf(output, "Type: ");
4389    if (type->name != NULL)
4390        fprintf(output, "'%s' ", type->name);
4391    else
4392        fprintf(output, "(no name) ");
4393    if (type->targetNamespace != NULL)
4394	fprintf(output, "ns '%s' ", type->targetNamespace);
4395    switch (type->type) {
4396        case XML_SCHEMA_TYPE_BASIC:
4397            fprintf(output, "[basic] ");
4398            break;
4399        case XML_SCHEMA_TYPE_SIMPLE:
4400            fprintf(output, "[simple] ");
4401            break;
4402        case XML_SCHEMA_TYPE_COMPLEX:
4403            fprintf(output, "[complex] ");
4404            break;
4405        case XML_SCHEMA_TYPE_SEQUENCE:
4406            fprintf(output, "[sequence] ");
4407            break;
4408        case XML_SCHEMA_TYPE_CHOICE:
4409            fprintf(output, "[choice] ");
4410            break;
4411        case XML_SCHEMA_TYPE_ALL:
4412            fprintf(output, "[all] ");
4413            break;
4414        case XML_SCHEMA_TYPE_UR:
4415            fprintf(output, "[ur] ");
4416            break;
4417        case XML_SCHEMA_TYPE_RESTRICTION:
4418            fprintf(output, "[restriction] ");
4419            break;
4420        case XML_SCHEMA_TYPE_EXTENSION:
4421            fprintf(output, "[extension] ");
4422            break;
4423        default:
4424            fprintf(output, "[unknown type %d] ", type->type);
4425            break;
4426    }
4427    fprintf(output, "content: ");
4428    switch (type->contentType) {
4429        case XML_SCHEMA_CONTENT_UNKNOWN:
4430            fprintf(output, "[unknown] ");
4431            break;
4432        case XML_SCHEMA_CONTENT_EMPTY:
4433            fprintf(output, "[empty] ");
4434            break;
4435        case XML_SCHEMA_CONTENT_ELEMENTS:
4436            fprintf(output, "[element] ");
4437            break;
4438        case XML_SCHEMA_CONTENT_MIXED:
4439            fprintf(output, "[mixed] ");
4440            break;
4441        case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4442	/* not used. */
4443            break;
4444        case XML_SCHEMA_CONTENT_BASIC:
4445            fprintf(output, "[basic] ");
4446            break;
4447        case XML_SCHEMA_CONTENT_SIMPLE:
4448            fprintf(output, "[simple] ");
4449            break;
4450        case XML_SCHEMA_CONTENT_ANY:
4451            fprintf(output, "[any] ");
4452            break;
4453    }
4454    fprintf(output, "\n");
4455    if (type->base != NULL) {
4456        fprintf(output, "  base type: '%s'", type->base);
4457	if (type->baseNs != NULL)
4458	    fprintf(output, " ns '%s'\n", type->baseNs);
4459	else
4460	    fprintf(output, "\n");
4461    }
4462    if (type->attrUses != NULL)
4463	xmlSchemaAttrUsesDump(type->attrUses, output);
4464    if (type->annot != NULL)
4465        xmlSchemaAnnotDump(output, type->annot);
4466#ifdef DUMP_CONTENT_MODEL
4467    if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4468	(type->subtypes != NULL)) {
4469	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4470	    output, 1);
4471    }
4472#endif
4473}
4474
4475/**
4476 * xmlSchemaDump:
4477 * @output:  the file output
4478 * @schema:  a schema structure
4479 *
4480 * Dump a Schema structure.
4481 */
4482void
4483xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4484{
4485    if (output == NULL)
4486        return;
4487    if (schema == NULL) {
4488        fprintf(output, "Schemas: NULL\n");
4489        return;
4490    }
4491    fprintf(output, "Schemas: ");
4492    if (schema->name != NULL)
4493        fprintf(output, "%s, ", schema->name);
4494    else
4495        fprintf(output, "no name, ");
4496    if (schema->targetNamespace != NULL)
4497        fprintf(output, "%s", (const char *) schema->targetNamespace);
4498    else
4499        fprintf(output, "no target namespace");
4500    fprintf(output, "\n");
4501    if (schema->annot != NULL)
4502        xmlSchemaAnnotDump(output, schema->annot);
4503    xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4504                output);
4505    xmlHashScanFull(schema->elemDecl,
4506                    (xmlHashScannerFull) xmlSchemaElementDump, output);
4507}
4508
4509#ifdef DEBUG_IDC_NODE_TABLE
4510/**
4511 * xmlSchemaDebugDumpIDCTable:
4512 * @vctxt: the WXS validation context
4513 *
4514 * Displays the current IDC table for debug purposes.
4515 */
4516static void
4517xmlSchemaDebugDumpIDCTable(FILE * output,
4518			   const xmlChar *namespaceName,
4519			   const xmlChar *localName,
4520			   xmlSchemaPSVIIDCBindingPtr bind)
4521{
4522    xmlChar *str = NULL;
4523    const xmlChar *value;
4524    xmlSchemaPSVIIDCNodePtr tab;
4525    xmlSchemaPSVIIDCKeyPtr key;
4526    int i, j, res;
4527
4528    fprintf(output, "IDC: TABLES on '%s'\n",
4529	xmlSchemaFormatQName(&str, namespaceName, localName));
4530    FREE_AND_NULL(str)
4531
4532    if (bind == NULL)
4533	return;
4534    do {
4535	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4536	    xmlSchemaGetComponentQName(&str,
4537		bind->definition), bind->nbNodes);
4538	FREE_AND_NULL(str)
4539	for (i = 0; i < bind->nbNodes; i++) {
4540	    tab = bind->nodeTable[i];
4541	    fprintf(output, "         ( ");
4542	    for (j = 0; j < bind->definition->nbFields; j++) {
4543		key = tab->keys[j];
4544		if ((key != NULL) && (key->val != NULL)) {
4545		    res = xmlSchemaGetCanonValue(key->val, &value);
4546		    if (res >= 0)
4547			fprintf(output, "'%s' ", value);
4548		    else
4549			fprintf(output, "CANON-VALUE-FAILED ");
4550		    if (res == 0)
4551			FREE_AND_NULL(value)
4552		} else if (key != NULL)
4553		    fprintf(output, "(no val), ");
4554		else
4555		    fprintf(output, "(key missing), ");
4556	    }
4557	    fprintf(output, ")\n");
4558	}
4559	if (bind->dupls && bind->dupls->nbItems) {
4560	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4561	    for (i = 0; i < bind->dupls->nbItems; i++) {
4562		tab = bind->dupls->items[i];
4563		fprintf(output, "         ( ");
4564		for (j = 0; j < bind->definition->nbFields; j++) {
4565		    key = tab->keys[j];
4566		    if ((key != NULL) && (key->val != NULL)) {
4567			res = xmlSchemaGetCanonValue(key->val, &value);
4568			if (res >= 0)
4569			    fprintf(output, "'%s' ", value);
4570			else
4571			    fprintf(output, "CANON-VALUE-FAILED ");
4572			if (res == 0)
4573			    FREE_AND_NULL(value)
4574		    } else if (key != NULL)
4575		    fprintf(output, "(no val), ");
4576			else
4577			    fprintf(output, "(key missing), ");
4578		}
4579		fprintf(output, ")\n");
4580	    }
4581	}
4582	bind = bind->next;
4583    } while (bind != NULL);
4584}
4585#endif /* DEBUG_IDC */
4586#endif /* LIBXML_OUTPUT_ENABLED */
4587
4588/************************************************************************
4589 *									*
4590 * 			Utilities					*
4591 *									*
4592 ************************************************************************/
4593
4594/**
4595 * xmlSchemaGetPropNode:
4596 * @node: the element node
4597 * @name: the name of the attribute
4598 *
4599 * Seeks an attribute with a name of @name in
4600 * no namespace.
4601 *
4602 * Returns the attribute or NULL if not present.
4603 */
4604static xmlAttrPtr
4605xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4606{
4607    xmlAttrPtr prop;
4608
4609    if ((node == NULL) || (name == NULL))
4610	return(NULL);
4611    prop = node->properties;
4612    while (prop != NULL) {
4613        if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4614	    return(prop);
4615	prop = prop->next;
4616    }
4617    return (NULL);
4618}
4619
4620/**
4621 * xmlSchemaGetPropNodeNs:
4622 * @node: the element node
4623 * @uri: the uri
4624 * @name: the name of the attribute
4625 *
4626 * Seeks an attribute with a local name of @name and
4627 * a namespace URI of @uri.
4628 *
4629 * Returns the attribute or NULL if not present.
4630 */
4631static xmlAttrPtr
4632xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4633{
4634    xmlAttrPtr prop;
4635
4636    if ((node == NULL) || (name == NULL))
4637	return(NULL);
4638    prop = node->properties;
4639    while (prop != NULL) {
4640	if ((prop->ns != NULL) &&
4641	    xmlStrEqual(prop->name, BAD_CAST name) &&
4642	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4643	    return(prop);
4644	prop = prop->next;
4645    }
4646    return (NULL);
4647}
4648
4649static const xmlChar *
4650xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4651{
4652    xmlChar *val;
4653    const xmlChar *ret;
4654
4655    val = xmlNodeGetContent(node);
4656    if (val == NULL)
4657	val = xmlStrdup((xmlChar *)"");
4658    ret = xmlDictLookup(ctxt->dict, val, -1);
4659    xmlFree(val);
4660    return(ret);
4661}
4662
4663static const xmlChar *
4664xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4665{
4666    return((const xmlChar*) xmlNodeGetContent(node));
4667}
4668
4669/**
4670 * xmlSchemaGetProp:
4671 * @ctxt: the parser context
4672 * @node: the node
4673 * @name: the property name
4674 *
4675 * Read a attribute value and internalize the string
4676 *
4677 * Returns the string or NULL if not present.
4678 */
4679static const xmlChar *
4680xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4681                 const char *name)
4682{
4683    xmlChar *val;
4684    const xmlChar *ret;
4685
4686    val = xmlGetNoNsProp(node, BAD_CAST name);
4687    if (val == NULL)
4688        return(NULL);
4689    ret = xmlDictLookup(ctxt->dict, val, -1);
4690    xmlFree(val);
4691    return(ret);
4692}
4693
4694/************************************************************************
4695 * 									*
4696 * 			Parsing functions				*
4697 * 									*
4698 ************************************************************************/
4699
4700#define WXS_FIND_GLOBAL_ITEM(slot)			\
4701    if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4702	ret = xmlHashLookup(schema->slot, name); \
4703	if (ret != NULL) goto exit; \
4704    } \
4705    if (xmlHashSize(schema->schemasImports) > 1) { \
4706	xmlSchemaImportPtr import; \
4707	if (nsName == NULL) \
4708	    import = xmlHashLookup(schema->schemasImports, \
4709		XML_SCHEMAS_NO_NAMESPACE); \
4710	else \
4711	    import = xmlHashLookup(schema->schemasImports, nsName); \
4712	if (import == NULL) \
4713	    goto exit; \
4714	ret = xmlHashLookup(import->schema->slot, name); \
4715    }
4716
4717/**
4718 * xmlSchemaGetElem:
4719 * @schema:  the schema context
4720 * @name:  the element name
4721 * @ns:  the element namespace
4722 *
4723 * Lookup a global element declaration in the schema.
4724 *
4725 * Returns the element declaration or NULL if not found.
4726 */
4727static xmlSchemaElementPtr
4728xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4729                 const xmlChar * nsName)
4730{
4731    xmlSchemaElementPtr ret = NULL;
4732
4733    if ((name == NULL) || (schema == NULL))
4734        return(NULL);
4735    if (schema != NULL) {
4736	WXS_FIND_GLOBAL_ITEM(elemDecl)
4737    }
4738exit:
4739#ifdef DEBUG
4740    if (ret == NULL) {
4741        if (nsName == NULL)
4742            fprintf(stderr, "Unable to lookup element decl. %s", name);
4743        else
4744            fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4745                    nsName);
4746    }
4747#endif
4748    return (ret);
4749}
4750
4751/**
4752 * xmlSchemaGetType:
4753 * @schema:  the main schema
4754 * @name:  the type's name
4755 * nsName:  the type's namespace
4756 *
4757 * Lookup a type in the schemas or the predefined types
4758 *
4759 * Returns the group definition or NULL if not found.
4760 */
4761static xmlSchemaTypePtr
4762xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4763                 const xmlChar * nsName)
4764{
4765    xmlSchemaTypePtr ret = NULL;
4766
4767    if (name == NULL)
4768        return (NULL);
4769    /* First try the built-in types. */
4770    if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4771	ret = xmlSchemaGetPredefinedType(name, nsName);
4772	if (ret != NULL)
4773	    goto exit;
4774	/*
4775	* Note that we try the parsed schemas as well here
4776	* since one might have parsed the S4S, which contain more
4777	* than the built-in types.
4778	* TODO: Can we optimize this?
4779	*/
4780    }
4781    if (schema != NULL) {
4782	WXS_FIND_GLOBAL_ITEM(typeDecl)
4783    }
4784exit:
4785
4786#ifdef DEBUG
4787    if (ret == NULL) {
4788        if (nsName == NULL)
4789            fprintf(stderr, "Unable to lookup type %s", name);
4790        else
4791            fprintf(stderr, "Unable to lookup type %s:%s", name,
4792                    nsName);
4793    }
4794#endif
4795    return (ret);
4796}
4797
4798/**
4799 * xmlSchemaGetAttributeDecl:
4800 * @schema:  the context of the schema
4801 * @name:  the name of the attribute
4802 * @ns:  the target namespace of the attribute
4803 *
4804 * Lookup a an attribute in the schema or imported schemas
4805 *
4806 * Returns the attribute declaration or NULL if not found.
4807 */
4808static xmlSchemaAttributePtr
4809xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4810                 const xmlChar * nsName)
4811{
4812    xmlSchemaAttributePtr ret = NULL;
4813
4814    if ((name == NULL) || (schema == NULL))
4815        return (NULL);
4816    if (schema != NULL) {
4817	WXS_FIND_GLOBAL_ITEM(attrDecl)
4818    }
4819exit:
4820#ifdef DEBUG
4821    if (ret == NULL) {
4822        if (nsName == NULL)
4823            fprintf(stderr, "Unable to lookup attribute %s", name);
4824        else
4825            fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4826                    nsName);
4827    }
4828#endif
4829    return (ret);
4830}
4831
4832/**
4833 * xmlSchemaGetAttributeGroup:
4834 * @schema:  the context of the schema
4835 * @name:  the name of the attribute group
4836 * @ns:  the target namespace of the attribute group
4837 *
4838 * Lookup a an attribute group in the schema or imported schemas
4839 *
4840 * Returns the attribute group definition or NULL if not found.
4841 */
4842static xmlSchemaAttributeGroupPtr
4843xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4844                 const xmlChar * nsName)
4845{
4846    xmlSchemaAttributeGroupPtr ret = NULL;
4847
4848    if ((name == NULL) || (schema == NULL))
4849        return (NULL);
4850    if (schema != NULL) {
4851	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4852    }
4853exit:
4854    /* TODO:
4855    if ((ret != NULL) && (ret->redef != NULL)) {
4856	* Return the last redefinition. *
4857	ret = ret->redef;
4858    }
4859    */
4860#ifdef DEBUG
4861    if (ret == NULL) {
4862        if (nsName == NULL)
4863            fprintf(stderr, "Unable to lookup attribute group %s", name);
4864        else
4865            fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4866                    nsName);
4867    }
4868#endif
4869    return (ret);
4870}
4871
4872/**
4873 * xmlSchemaGetGroup:
4874 * @schema:  the context of the schema
4875 * @name:  the name of the group
4876 * @ns:  the target namespace of the group
4877 *
4878 * Lookup a group in the schema or imported schemas
4879 *
4880 * Returns the group definition or NULL if not found.
4881 */
4882static xmlSchemaModelGroupDefPtr
4883xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4884                 const xmlChar * nsName)
4885{
4886    xmlSchemaModelGroupDefPtr ret = NULL;
4887
4888    if ((name == NULL) || (schema == NULL))
4889        return (NULL);
4890    if (schema != NULL) {
4891	WXS_FIND_GLOBAL_ITEM(groupDecl)
4892    }
4893exit:
4894
4895#ifdef DEBUG
4896    if (ret == NULL) {
4897        if (nsName == NULL)
4898            fprintf(stderr, "Unable to lookup group %s", name);
4899        else
4900            fprintf(stderr, "Unable to lookup group %s:%s", name,
4901                    nsName);
4902    }
4903#endif
4904    return (ret);
4905}
4906
4907static xmlSchemaNotationPtr
4908xmlSchemaGetNotation(xmlSchemaPtr schema,
4909		     const xmlChar *name,
4910		     const xmlChar *nsName)
4911{
4912    xmlSchemaNotationPtr ret = NULL;
4913
4914    if ((name == NULL) || (schema == NULL))
4915        return (NULL);
4916    if (schema != NULL) {
4917	WXS_FIND_GLOBAL_ITEM(notaDecl)
4918    }
4919exit:
4920    return (ret);
4921}
4922
4923static xmlSchemaIDCPtr
4924xmlSchemaGetIDC(xmlSchemaPtr schema,
4925		const xmlChar *name,
4926		const xmlChar *nsName)
4927{
4928    xmlSchemaIDCPtr ret = NULL;
4929
4930    if ((name == NULL) || (schema == NULL))
4931        return (NULL);
4932    if (schema != NULL) {
4933	WXS_FIND_GLOBAL_ITEM(idcDef)
4934    }
4935exit:
4936    return (ret);
4937}
4938
4939/**
4940 * xmlSchemaGetNamedComponent:
4941 * @schema:  the schema
4942 * @name:  the name of the group
4943 * @ns:  the target namespace of the group
4944 *
4945 * Lookup a group in the schema or imported schemas
4946 *
4947 * Returns the group definition or NULL if not found.
4948 */
4949static xmlSchemaBasicItemPtr
4950xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4951			   xmlSchemaTypeType itemType,
4952			   const xmlChar *name,
4953			   const xmlChar *targetNs)
4954{
4955    switch (itemType) {
4956	case XML_SCHEMA_TYPE_GROUP:
4957	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4958		name, targetNs));
4959	case XML_SCHEMA_TYPE_ELEMENT:
4960	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4961		name, targetNs));
4962	default:
4963	    TODO
4964	    return (NULL);
4965    }
4966}
4967
4968/************************************************************************
4969 * 									*
4970 * 			Parsing functions				*
4971 * 									*
4972 ************************************************************************/
4973
4974#define IS_BLANK_NODE(n)						\
4975    (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4976
4977/**
4978 * xmlSchemaIsBlank:
4979 * @str:  a string
4980 * @len: the length of the string or -1
4981 *
4982 * Check if a string is ignorable
4983 *
4984 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4985 */
4986static int
4987xmlSchemaIsBlank(xmlChar * str, int len)
4988{
4989    if (str == NULL)
4990        return (1);
4991    if (len < 0) {
4992	while (*str != 0) {
4993	    if (!(IS_BLANK_CH(*str)))
4994		return (0);
4995	    str++;
4996	}
4997    } else while ((*str != 0) && (len != 0)) {
4998	if (!(IS_BLANK_CH(*str)))
4999	    return (0);
5000	str++;
5001	len--;
5002    }
5003
5004    return (1);
5005}
5006
5007#define WXS_COMP_NAME(c, t) ((t) (c))->name
5008#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5009/*
5010* xmlSchemaFindRedefCompInGraph:
5011* ATTENTION TODO: This uses pointer comp. for strings.
5012*/
5013static xmlSchemaBasicItemPtr
5014xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5015			      xmlSchemaTypeType type,
5016			      const xmlChar *name,
5017			      const xmlChar *nsName)
5018{
5019    xmlSchemaBasicItemPtr ret;
5020    int i;
5021
5022    if ((bucket == NULL) || (name == NULL))
5023	return(NULL);
5024    if ((bucket->globals == NULL) ||
5025	(bucket->globals->nbItems == 0))
5026	goto subschemas;
5027    /*
5028    * Search in global components.
5029    */
5030    for (i = 0; i < bucket->globals->nbItems; i++) {
5031	ret = bucket->globals->items[i];
5032	if (ret->type == type) {
5033	    switch (type) {
5034		case XML_SCHEMA_TYPE_COMPLEX:
5035		case XML_SCHEMA_TYPE_SIMPLE:
5036		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5037			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5038			nsName))
5039		    {
5040			return(ret);
5041		    }
5042		    break;
5043		case XML_SCHEMA_TYPE_GROUP:
5044		    if ((WXS_COMP_NAME(ret,
5045			    xmlSchemaModelGroupDefPtr) == name) &&
5046			(WXS_COMP_TNS(ret,
5047			    xmlSchemaModelGroupDefPtr) == nsName))
5048		    {
5049			return(ret);
5050		    }
5051		    break;
5052		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5053		    if ((WXS_COMP_NAME(ret,
5054			    xmlSchemaAttributeGroupPtr) == name) &&
5055			(WXS_COMP_TNS(ret,
5056			    xmlSchemaAttributeGroupPtr) == nsName))
5057		    {
5058			return(ret);
5059		    }
5060		    break;
5061		default:
5062		    /* Should not be hit. */
5063		    return(NULL);
5064	    }
5065	}
5066    }
5067subschemas:
5068    /*
5069    * Process imported/included schemas.
5070    */
5071    if (bucket->relations != NULL) {
5072	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5073
5074	/*
5075	* TODO: Marking the bucket will not avoid multiple searches
5076	* in the same schema, but avoids at least circularity.
5077	*/
5078	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5079	do {
5080	    if ((rel->bucket != NULL) &&
5081		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5082		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5083		    type, name, nsName);
5084		if (ret != NULL)
5085		    return(ret);
5086	    }
5087	    rel = rel->next;
5088	} while (rel != NULL);
5089	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5090    }
5091    return(NULL);
5092}
5093
5094/**
5095 * xmlSchemaAddNotation:
5096 * @ctxt:  a schema parser context
5097 * @schema:  the schema being built
5098 * @name:  the item name
5099 *
5100 * Add an XML schema annotation declaration
5101 * *WARNING* this interface is highly subject to change
5102 *
5103 * Returns the new struture or NULL in case of error
5104 */
5105static xmlSchemaNotationPtr
5106xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5107                     const xmlChar *name, const xmlChar *nsName,
5108		     xmlNodePtr node ATTRIBUTE_UNUSED)
5109{
5110    xmlSchemaNotationPtr ret = NULL;
5111
5112    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5113        return (NULL);
5114
5115    ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5116    if (ret == NULL) {
5117        xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5118        return (NULL);
5119    }
5120    memset(ret, 0, sizeof(xmlSchemaNotation));
5121    ret->type = XML_SCHEMA_TYPE_NOTATION;
5122    ret->name = name;
5123    ret->targetNamespace = nsName;
5124    /* TODO: do we need the node to be set?
5125    * ret->node = node;*/
5126    WXS_ADD_GLOBAL(ctxt, ret);
5127    return (ret);
5128}
5129
5130/**
5131 * xmlSchemaAddAttribute:
5132 * @ctxt:  a schema parser context
5133 * @schema:  the schema being built
5134 * @name:  the item name
5135 * @namespace:  the namespace
5136 *
5137 * Add an XML schema Attrribute declaration
5138 * *WARNING* this interface is highly subject to change
5139 *
5140 * Returns the new struture or NULL in case of error
5141 */
5142static xmlSchemaAttributePtr
5143xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5144                      const xmlChar * name, const xmlChar * nsName,
5145		      xmlNodePtr node, int topLevel)
5146{
5147    xmlSchemaAttributePtr ret = NULL;
5148
5149    if ((ctxt == NULL) || (schema == NULL))
5150        return (NULL);
5151
5152    ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5153    if (ret == NULL) {
5154        xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5155        return (NULL);
5156    }
5157    memset(ret, 0, sizeof(xmlSchemaAttribute));
5158    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5159    ret->node = node;
5160    ret->name = name;
5161    ret->targetNamespace = nsName;
5162
5163    if (topLevel)
5164	WXS_ADD_GLOBAL(ctxt, ret);
5165    else
5166	WXS_ADD_LOCAL(ctxt, ret);
5167    WXS_ADD_PENDING(ctxt, ret);
5168    return (ret);
5169}
5170
5171/**
5172 * xmlSchemaAddAttributeUse:
5173 * @ctxt:  a schema parser context
5174 * @schema:  the schema being built
5175 * @name:  the item name
5176 * @namespace:  the namespace
5177 *
5178 * Add an XML schema Attrribute declaration
5179 * *WARNING* this interface is highly subject to change
5180 *
5181 * Returns the new struture or NULL in case of error
5182 */
5183static xmlSchemaAttributeUsePtr
5184xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5185			 xmlNodePtr node)
5186{
5187    xmlSchemaAttributeUsePtr ret = NULL;
5188
5189    if (pctxt == NULL)
5190        return (NULL);
5191
5192    ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5193    if (ret == NULL) {
5194        xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5195        return (NULL);
5196    }
5197    memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5198    ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5199    ret->node = node;
5200
5201    WXS_ADD_LOCAL(pctxt, ret);
5202    return (ret);
5203}
5204
5205/*
5206* xmlSchemaAddRedef:
5207*
5208* Adds a redefinition information. This is used at a later stage to:
5209* resolve references to the redefined components and to check constraints.
5210*/
5211static xmlSchemaRedefPtr
5212xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5213		  xmlSchemaBucketPtr targetBucket,
5214		  void *item,
5215		  const xmlChar *refName,
5216		  const xmlChar *refTargetNs)
5217{
5218    xmlSchemaRedefPtr ret;
5219
5220    ret = (xmlSchemaRedefPtr)
5221	xmlMalloc(sizeof(xmlSchemaRedef));
5222    if (ret == NULL) {
5223	xmlSchemaPErrMemory(pctxt,
5224	    "allocating redefinition info", NULL);
5225	return (NULL);
5226    }
5227    memset(ret, 0, sizeof(xmlSchemaRedef));
5228    ret->item = item;
5229    ret->targetBucket = targetBucket;
5230    ret->refName = refName;
5231    ret->refTargetNs = refTargetNs;
5232    if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5233	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5234    else
5235	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5236    WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5237
5238    return (ret);
5239}
5240
5241/**
5242 * xmlSchemaAddAttributeGroupDefinition:
5243 * @ctxt:  a schema parser context
5244 * @schema:  the schema being built
5245 * @name:  the item name
5246 * @nsName:  the target namespace
5247 * @node: the corresponding node
5248 *
5249 * Add an XML schema Attrribute Group definition.
5250 *
5251 * Returns the new struture or NULL in case of error
5252 */
5253static xmlSchemaAttributeGroupPtr
5254xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5255                           xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5256			   const xmlChar *name,
5257			   const xmlChar *nsName,
5258			   xmlNodePtr node)
5259{
5260    xmlSchemaAttributeGroupPtr ret = NULL;
5261
5262    if ((pctxt == NULL) || (name == NULL))
5263        return (NULL);
5264
5265    ret = (xmlSchemaAttributeGroupPtr)
5266        xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5267    if (ret == NULL) {
5268	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5269	return (NULL);
5270    }
5271    memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5272    ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5273    ret->name = name;
5274    ret->targetNamespace = nsName;
5275    ret->node = node;
5276
5277    /* TODO: Remove the flag. */
5278    ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5279    if (pctxt->isRedefine) {
5280	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5281	    ret, name, nsName);
5282	if (pctxt->redef == NULL) {
5283	    xmlFree(ret);
5284	    return(NULL);
5285	}
5286	pctxt->redefCounter = 0;
5287    }
5288    WXS_ADD_GLOBAL(pctxt, ret);
5289    WXS_ADD_PENDING(pctxt, ret);
5290    return (ret);
5291}
5292
5293/**
5294 * xmlSchemaAddElement:
5295 * @ctxt:  a schema parser context
5296 * @schema:  the schema being built
5297 * @name:  the type name
5298 * @namespace:  the type namespace
5299 *
5300 * Add an XML schema Element declaration
5301 * *WARNING* this interface is highly subject to change
5302 *
5303 * Returns the new struture or NULL in case of error
5304 */
5305static xmlSchemaElementPtr
5306xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5307                    const xmlChar * name, const xmlChar * nsName,
5308		    xmlNodePtr node, int topLevel)
5309{
5310    xmlSchemaElementPtr ret = NULL;
5311
5312    if ((ctxt == NULL) || (name == NULL))
5313        return (NULL);
5314
5315    ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5316    if (ret == NULL) {
5317        xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5318        return (NULL);
5319    }
5320    memset(ret, 0, sizeof(xmlSchemaElement));
5321    ret->type = XML_SCHEMA_TYPE_ELEMENT;
5322    ret->name = name;
5323    ret->targetNamespace = nsName;
5324    ret->node = node;
5325
5326    if (topLevel)
5327	WXS_ADD_GLOBAL(ctxt, ret);
5328    else
5329	WXS_ADD_LOCAL(ctxt, ret);
5330    WXS_ADD_PENDING(ctxt, ret);
5331    return (ret);
5332}
5333
5334/**
5335 * xmlSchemaAddType:
5336 * @ctxt:  a schema parser context
5337 * @schema:  the schema being built
5338 * @name:  the item name
5339 * @namespace:  the namespace
5340 *
5341 * Add an XML schema item
5342 * *WARNING* this interface is highly subject to change
5343 *
5344 * Returns the new struture or NULL in case of error
5345 */
5346static xmlSchemaTypePtr
5347xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5348		 xmlSchemaTypeType type,
5349                 const xmlChar * name, const xmlChar * nsName,
5350		 xmlNodePtr node, int topLevel)
5351{
5352    xmlSchemaTypePtr ret = NULL;
5353
5354    if ((ctxt == NULL) || (schema == NULL))
5355        return (NULL);
5356
5357    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5358    if (ret == NULL) {
5359        xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5360        return (NULL);
5361    }
5362    memset(ret, 0, sizeof(xmlSchemaType));
5363    ret->type = type;
5364    ret->name = name;
5365    ret->targetNamespace = nsName;
5366    ret->node = node;
5367    if (topLevel) {
5368	if (ctxt->isRedefine) {
5369	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5370		ret, name, nsName);
5371	    if (ctxt->redef == NULL) {
5372		xmlFree(ret);
5373		return(NULL);
5374	    }
5375	    ctxt->redefCounter = 0;
5376	}
5377	WXS_ADD_GLOBAL(ctxt, ret);
5378    } else
5379	WXS_ADD_LOCAL(ctxt, ret);
5380    WXS_ADD_PENDING(ctxt, ret);
5381    return (ret);
5382}
5383
5384static xmlSchemaQNameRefPtr
5385xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5386		     xmlSchemaTypeType refType,
5387		     const xmlChar *refName,
5388		     const xmlChar *refNs)
5389{
5390    xmlSchemaQNameRefPtr ret;
5391
5392    ret = (xmlSchemaQNameRefPtr)
5393	xmlMalloc(sizeof(xmlSchemaQNameRef));
5394    if (ret == NULL) {
5395	xmlSchemaPErrMemory(pctxt,
5396	    "allocating QName reference item", NULL);
5397	return (NULL);
5398    }
5399    ret->node = NULL;
5400    ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5401    ret->name = refName;
5402    ret->targetNamespace = refNs;
5403    ret->item = NULL;
5404    ret->itemType = refType;
5405    /*
5406    * Store the reference item in the schema.
5407    */
5408    WXS_ADD_LOCAL(pctxt, ret);
5409    return (ret);
5410}
5411
5412static xmlSchemaAttributeUseProhibPtr
5413xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5414{
5415    xmlSchemaAttributeUseProhibPtr ret;
5416
5417    ret = (xmlSchemaAttributeUseProhibPtr)
5418	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5419    if (ret == NULL) {
5420	xmlSchemaPErrMemory(pctxt,
5421	    "allocating attribute use prohibition", NULL);
5422	return (NULL);
5423    }
5424    memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5425    ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5426    WXS_ADD_LOCAL(pctxt, ret);
5427    return (ret);
5428}
5429
5430
5431/**
5432 * xmlSchemaAddModelGroup:
5433 * @ctxt:  a schema parser context
5434 * @schema:  the schema being built
5435 * @type: the "compositor" type of the model group
5436 * @node: the node in the schema doc
5437 *
5438 * Adds a schema model group
5439 * *WARNING* this interface is highly subject to change
5440 *
5441 * Returns the new struture or NULL in case of error
5442 */
5443static xmlSchemaModelGroupPtr
5444xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5445		       xmlSchemaPtr schema,
5446		       xmlSchemaTypeType type,
5447		       xmlNodePtr node)
5448{
5449    xmlSchemaModelGroupPtr ret = NULL;
5450
5451    if ((ctxt == NULL) || (schema == NULL))
5452        return (NULL);
5453
5454    ret = (xmlSchemaModelGroupPtr)
5455	xmlMalloc(sizeof(xmlSchemaModelGroup));
5456    if (ret == NULL) {
5457	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5458	    NULL);
5459	return (NULL);
5460    }
5461    memset(ret, 0, sizeof(xmlSchemaModelGroup));
5462    ret->type = type;
5463    ret->node = node;
5464    WXS_ADD_LOCAL(ctxt, ret);
5465    if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5466	(type == XML_SCHEMA_TYPE_CHOICE))
5467	WXS_ADD_PENDING(ctxt, ret);
5468    return (ret);
5469}
5470
5471
5472/**
5473 * xmlSchemaAddParticle:
5474 * @ctxt:  a schema parser context
5475 * @schema:  the schema being built
5476 * @node: the corresponding node in the schema doc
5477 * @min: the minOccurs
5478 * @max: the maxOccurs
5479 *
5480 * Adds an XML schema particle component.
5481 * *WARNING* this interface is highly subject to change
5482 *
5483 * Returns the new struture or NULL in case of error
5484 */
5485static xmlSchemaParticlePtr
5486xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5487		     xmlNodePtr node, int min, int max)
5488{
5489    xmlSchemaParticlePtr ret = NULL;
5490    if (ctxt == NULL)
5491        return (NULL);
5492
5493#ifdef DEBUG
5494    fprintf(stderr, "Adding particle component\n");
5495#endif
5496    ret = (xmlSchemaParticlePtr)
5497	xmlMalloc(sizeof(xmlSchemaParticle));
5498    if (ret == NULL) {
5499	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5500	    NULL);
5501	return (NULL);
5502    }
5503    ret->type = XML_SCHEMA_TYPE_PARTICLE;
5504    ret->annot = NULL;
5505    ret->node = node;
5506    ret->minOccurs = min;
5507    ret->maxOccurs = max;
5508    ret->next = NULL;
5509    ret->children = NULL;
5510
5511    WXS_ADD_LOCAL(ctxt, ret);
5512    /*
5513    * Note that addition to pending components will be done locally
5514    * to the specific parsing function, since the most particles
5515    * need not to be fixed up (i.e. the reference to be resolved).
5516    * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5517    */
5518    return (ret);
5519}
5520
5521/**
5522 * xmlSchemaAddModelGroupDefinition:
5523 * @ctxt:  a schema validation context
5524 * @schema:  the schema being built
5525 * @name:  the group name
5526 *
5527 * Add an XML schema Group definition
5528 *
5529 * Returns the new struture or NULL in case of error
5530 */
5531static xmlSchemaModelGroupDefPtr
5532xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5533				 xmlSchemaPtr schema,
5534				 const xmlChar *name,
5535				 const xmlChar *nsName,
5536				 xmlNodePtr node)
5537{
5538    xmlSchemaModelGroupDefPtr ret = NULL;
5539
5540    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5541        return (NULL);
5542
5543    ret = (xmlSchemaModelGroupDefPtr)
5544	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5545    if (ret == NULL) {
5546        xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5547        return (NULL);
5548    }
5549    memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5550    ret->name = name;
5551    ret->type = XML_SCHEMA_TYPE_GROUP;
5552    ret->node = node;
5553    ret->targetNamespace = nsName;
5554
5555    if (ctxt->isRedefine) {
5556	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5557	    ret, name, nsName);
5558	if (ctxt->redef == NULL) {
5559	    xmlFree(ret);
5560	    return(NULL);
5561	}
5562	ctxt->redefCounter = 0;
5563    }
5564    WXS_ADD_GLOBAL(ctxt, ret);
5565    WXS_ADD_PENDING(ctxt, ret);
5566    return (ret);
5567}
5568
5569/**
5570 * xmlSchemaNewWildcardNs:
5571 * @ctxt:  a schema validation context
5572 *
5573 * Creates a new wildcard namespace constraint.
5574 *
5575 * Returns the new struture or NULL in case of error
5576 */
5577static xmlSchemaWildcardNsPtr
5578xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5579{
5580    xmlSchemaWildcardNsPtr ret;
5581
5582    ret = (xmlSchemaWildcardNsPtr)
5583	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5584    if (ret == NULL) {
5585	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5586	return (NULL);
5587    }
5588    ret->value = NULL;
5589    ret->next = NULL;
5590    return (ret);
5591}
5592
5593static xmlSchemaIDCPtr
5594xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5595                  const xmlChar *name, const xmlChar *nsName,
5596		  int category, xmlNodePtr node)
5597{
5598    xmlSchemaIDCPtr ret = NULL;
5599
5600    if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5601        return (NULL);
5602
5603    ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5604    if (ret == NULL) {
5605        xmlSchemaPErrMemory(ctxt,
5606	    "allocating an identity-constraint definition", NULL);
5607        return (NULL);
5608    }
5609    memset(ret, 0, sizeof(xmlSchemaIDC));
5610    /* The target namespace of the parent element declaration. */
5611    ret->targetNamespace = nsName;
5612    ret->name = name;
5613    ret->type = category;
5614    ret->node = node;
5615
5616    WXS_ADD_GLOBAL(ctxt, ret);
5617    /*
5618    * Only keyrefs need to be fixup up.
5619    */
5620    if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5621	WXS_ADD_PENDING(ctxt, ret);
5622    return (ret);
5623}
5624
5625/**
5626 * xmlSchemaAddWildcard:
5627 * @ctxt:  a schema validation context
5628 * @schema: a schema
5629 *
5630 * Adds a wildcard.
5631 * It corresponds to a xsd:anyAttribute and xsd:any.
5632 *
5633 * Returns the new struture or NULL in case of error
5634 */
5635static xmlSchemaWildcardPtr
5636xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5637		     xmlSchemaTypeType type, xmlNodePtr node)
5638{
5639    xmlSchemaWildcardPtr ret = NULL;
5640
5641    if ((ctxt == NULL) || (schema == NULL))
5642        return (NULL);
5643
5644    ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5645    if (ret == NULL) {
5646        xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5647        return (NULL);
5648    }
5649    memset(ret, 0, sizeof(xmlSchemaWildcard));
5650    ret->type = type;
5651    ret->node = node;
5652    WXS_ADD_LOCAL(ctxt, ret);
5653    return (ret);
5654}
5655
5656static void
5657xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5658{
5659    if (group == NULL)
5660	return;
5661    if (group->members != NULL)
5662	xmlSchemaItemListFree(group->members);
5663    xmlFree(group);
5664}
5665
5666static xmlSchemaSubstGroupPtr
5667xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5668		       xmlSchemaElementPtr head)
5669{
5670    xmlSchemaSubstGroupPtr ret;
5671
5672    /* Init subst group hash. */
5673    if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5674	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5675	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5676	    return(NULL);
5677    }
5678    /* Create a new substitution group. */
5679    ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5680    if (ret == NULL) {
5681	xmlSchemaPErrMemory(NULL,
5682	    "allocating a substitution group container", NULL);
5683	return(NULL);
5684    }
5685    memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5686    ret->head = head;
5687    /* Create list of members. */
5688    ret->members = xmlSchemaItemListCreate();
5689    if (ret->members == NULL) {
5690	xmlSchemaSubstGroupFree(ret);
5691	return(NULL);
5692    }
5693    /* Add subst group to hash. */
5694    if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5695	head->name, head->targetNamespace, ret) != 0) {
5696	PERROR_INT("xmlSchemaSubstGroupAdd",
5697	    "failed to add a new substitution container");
5698	xmlSchemaSubstGroupFree(ret);
5699	return(NULL);
5700    }
5701    return(ret);
5702}
5703
5704static xmlSchemaSubstGroupPtr
5705xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5706		       xmlSchemaElementPtr head)
5707{
5708    if (WXS_SUBST_GROUPS(pctxt) == NULL)
5709	return(NULL);
5710    return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5711	head->name, head->targetNamespace));
5712
5713}
5714
5715/**
5716 * xmlSchemaAddElementSubstitutionMember:
5717 * @pctxt:  a schema parser context
5718 * @head:  the head of the substitution group
5719 * @member: the new member of the substitution group
5720 *
5721 * Allocate a new annotation structure.
5722 *
5723 * Returns the newly allocated structure or NULL in case or error
5724 */
5725static int
5726xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5727				      xmlSchemaElementPtr head,
5728				      xmlSchemaElementPtr member)
5729{
5730    xmlSchemaSubstGroupPtr substGroup = NULL;
5731
5732    if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5733	return (-1);
5734
5735    substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5736    if (substGroup == NULL)
5737	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5738    if (substGroup == NULL)
5739	return(-1);
5740    if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5741	return(-1);
5742    return(0);
5743}
5744
5745/************************************************************************
5746 * 									*
5747 *		Utilities for parsing					*
5748 * 									*
5749 ************************************************************************/
5750
5751/**
5752 * xmlSchemaPValAttrNodeQNameValue:
5753 * @ctxt:  a schema parser context
5754 * @schema: the schema context
5755 * @ownerDes: the designation of the parent element
5756 * @ownerItem: the parent as a schema object
5757 * @value:  the QName value
5758 * @local: the resulting local part if found, the attribute value otherwise
5759 * @uri:  the resulting namespace URI if found
5760 *
5761 * Extracts the local name and the URI of a QName value and validates it.
5762 * This one is intended to be used on attribute values that
5763 * should resolve to schema components.
5764 *
5765 * Returns 0, in case the QName is valid, a positive error code
5766 * if not valid and -1 if an internal error occurs.
5767 */
5768static int
5769xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5770				       xmlSchemaPtr schema,
5771				       xmlSchemaBasicItemPtr ownerItem,
5772				       xmlAttrPtr attr,
5773				       const xmlChar *value,
5774				       const xmlChar **uri,
5775				       const xmlChar **local)
5776{
5777    const xmlChar *pref;
5778    xmlNsPtr ns;
5779    int len, ret;
5780
5781    *uri = NULL;
5782    *local = NULL;
5783    ret = xmlValidateQName(value, 1);
5784    if (ret > 0) {
5785	xmlSchemaPSimpleTypeErr(ctxt,
5786	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5787	    ownerItem, (xmlNodePtr) attr,
5788	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5789	    NULL, value, NULL, NULL, NULL);
5790	*local = value;
5791	return (ctxt->err);
5792    } else if (ret < 0)
5793	return (-1);
5794
5795    if (!strchr((char *) value, ':')) {
5796	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5797	if (ns)
5798	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5799	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5800	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5801	    * parser context. */
5802	    /*
5803	    * This one takes care of included schemas with no
5804	    * target namespace.
5805	    */
5806	    *uri = ctxt->targetNamespace;
5807	}
5808	*local = xmlDictLookup(ctxt->dict, value, -1);
5809	return (0);
5810    }
5811    /*
5812    * At this point xmlSplitQName3 has to return a local name.
5813    */
5814    *local = xmlSplitQName3(value, &len);
5815    *local = xmlDictLookup(ctxt->dict, *local, -1);
5816    pref = xmlDictLookup(ctxt->dict, value, len);
5817    ns = xmlSearchNs(attr->doc, attr->parent, pref);
5818    if (ns == NULL) {
5819	xmlSchemaPSimpleTypeErr(ctxt,
5820	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5821	    ownerItem, (xmlNodePtr) attr,
5822	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5823	    "The value '%s' of simple type 'xs:QName' has no "
5824	    "corresponding namespace declaration in scope", value, NULL);
5825	return (ctxt->err);
5826    } else {
5827        *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5828    }
5829    return (0);
5830}
5831
5832/**
5833 * xmlSchemaPValAttrNodeQName:
5834 * @ctxt:  a schema parser context
5835 * @schema: the schema context
5836 * @ownerDes: the designation of the owner element
5837 * @ownerItem: the owner as a schema object
5838 * @attr:  the attribute node
5839 * @local: the resulting local part if found, the attribute value otherwise
5840 * @uri:  the resulting namespace URI if found
5841 *
5842 * Extracts and validates the QName of an attribute value.
5843 * This one is intended to be used on attribute values that
5844 * should resolve to schema components.
5845 *
5846 * Returns 0, in case the QName is valid, a positive error code
5847 * if not valid and -1 if an internal error occurs.
5848 */
5849static int
5850xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5851				       xmlSchemaPtr schema,
5852				       xmlSchemaBasicItemPtr ownerItem,
5853				       xmlAttrPtr attr,
5854				       const xmlChar **uri,
5855				       const xmlChar **local)
5856{
5857    const xmlChar *value;
5858
5859    value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5860    return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5861	ownerItem, attr, value, uri, local));
5862}
5863
5864/**
5865 * xmlSchemaPValAttrQName:
5866 * @ctxt:  a schema parser context
5867 * @schema: the schema context
5868 * @ownerDes: the designation of the parent element
5869 * @ownerItem: the owner as a schema object
5870 * @ownerElem:  the parent node of the attribute
5871 * @name:  the name of the attribute
5872 * @local: the resulting local part if found, the attribute value otherwise
5873 * @uri:  the resulting namespace URI if found
5874 *
5875 * Extracts and validates the QName of an attribute value.
5876 *
5877 * Returns 0, in case the QName is valid, a positive error code
5878 * if not valid and -1 if an internal error occurs.
5879 */
5880static int
5881xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5882				   xmlSchemaPtr schema,
5883				   xmlSchemaBasicItemPtr ownerItem,
5884				   xmlNodePtr ownerElem,
5885				   const char *name,
5886				   const xmlChar **uri,
5887				   const xmlChar **local)
5888{
5889    xmlAttrPtr attr;
5890
5891    attr = xmlSchemaGetPropNode(ownerElem, name);
5892    if (attr == NULL) {
5893	*local = NULL;
5894	*uri = NULL;
5895	return (0);
5896    }
5897    return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5898	ownerItem, attr, uri, local));
5899}
5900
5901/**
5902 * xmlSchemaPValAttrID:
5903 * @ctxt:  a schema parser context
5904 * @schema: the schema context
5905 * @ownerDes: the designation of the parent element
5906 * @ownerItem: the owner as a schema object
5907 * @ownerElem:  the parent node of the attribute
5908 * @name:  the name of the attribute
5909 *
5910 * Extracts and validates the ID of an attribute value.
5911 *
5912 * Returns 0, in case the ID is valid, a positive error code
5913 * if not valid and -1 if an internal error occurs.
5914 */
5915static int
5916xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5917{
5918    int ret;
5919    const xmlChar *value;
5920
5921    if (attr == NULL)
5922	return(0);
5923    value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5924    ret = xmlValidateNCName(value, 1);
5925    if (ret == 0) {
5926	/*
5927	* NOTE: the IDness might have already be declared in the DTD
5928	*/
5929	if (attr->atype != XML_ATTRIBUTE_ID) {
5930	    xmlIDPtr res;
5931	    xmlChar *strip;
5932
5933	    /*
5934	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5935	    * moment.
5936	    */
5937	    strip = xmlSchemaCollapseString(value);
5938	    if (strip != NULL) {
5939		xmlFree((xmlChar *) value);
5940		value = strip;
5941	    }
5942    	    res = xmlAddID(NULL, attr->doc, value, attr);
5943	    if (res == NULL) {
5944		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5945		xmlSchemaPSimpleTypeErr(ctxt,
5946		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5947		    NULL, (xmlNodePtr) attr,
5948		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5949		    NULL, NULL, "Duplicate value '%s' of simple "
5950		    "type 'xs:ID'", value, NULL);
5951	    } else
5952		attr->atype = XML_ATTRIBUTE_ID;
5953	}
5954    } else if (ret > 0) {
5955	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5956	xmlSchemaPSimpleTypeErr(ctxt,
5957	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5958	    NULL, (xmlNodePtr) attr,
5959	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5960	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5961	    "not a valid 'xs:NCName'",
5962	    value, NULL);
5963    }
5964    if (value != NULL)
5965	xmlFree((xmlChar *)value);
5966
5967    return (ret);
5968}
5969
5970static int
5971xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5972		    xmlNodePtr ownerElem,
5973		    const xmlChar *name)
5974{
5975    xmlAttrPtr attr;
5976
5977    attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5978    if (attr == NULL)
5979	return(0);
5980    return(xmlSchemaPValAttrNodeID(ctxt, attr));
5981
5982}
5983
5984/**
5985 * xmlGetMaxOccurs:
5986 * @ctxt:  a schema validation context
5987 * @node:  a subtree containing XML Schema informations
5988 *
5989 * Get the maxOccurs property
5990 *
5991 * Returns the default if not found, or the value
5992 */
5993static int
5994xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5995		int min, int max, int def, const char *expected)
5996{
5997    const xmlChar *val, *cur;
5998    int ret = 0;
5999    xmlAttrPtr attr;
6000
6001    attr = xmlSchemaGetPropNode(node, "maxOccurs");
6002    if (attr == NULL)
6003	return (def);
6004    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6005
6006    if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6007	if (max != UNBOUNDED) {
6008	    xmlSchemaPSimpleTypeErr(ctxt,
6009		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6010		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6011		NULL, (xmlNodePtr) attr, NULL, expected,
6012		val, NULL, NULL, NULL);
6013	    return (def);
6014	} else
6015	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6016    }
6017
6018    cur = val;
6019    while (IS_BLANK_CH(*cur))
6020        cur++;
6021    if (*cur == 0) {
6022        xmlSchemaPSimpleTypeErr(ctxt,
6023	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6024	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6025	    NULL, (xmlNodePtr) attr, NULL, expected,
6026	    val, NULL, NULL, NULL);
6027	return (def);
6028    }
6029    while ((*cur >= '0') && (*cur <= '9')) {
6030        ret = ret * 10 + (*cur - '0');
6031        cur++;
6032    }
6033    while (IS_BLANK_CH(*cur))
6034        cur++;
6035    /*
6036    * TODO: Restrict the maximal value to Integer.
6037    */
6038    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6039	xmlSchemaPSimpleTypeErr(ctxt,
6040	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6041	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6042	    NULL, (xmlNodePtr) attr, NULL, expected,
6043	    val, NULL, NULL, NULL);
6044        return (def);
6045    }
6046    return (ret);
6047}
6048
6049/**
6050 * xmlGetMinOccurs:
6051 * @ctxt:  a schema validation context
6052 * @node:  a subtree containing XML Schema informations
6053 *
6054 * Get the minOccurs property
6055 *
6056 * Returns the default if not found, or the value
6057 */
6058static int
6059xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6060		int min, int max, int def, const char *expected)
6061{
6062    const xmlChar *val, *cur;
6063    int ret = 0;
6064    xmlAttrPtr attr;
6065
6066    attr = xmlSchemaGetPropNode(node, "minOccurs");
6067    if (attr == NULL)
6068	return (def);
6069    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6070    cur = val;
6071    while (IS_BLANK_CH(*cur))
6072        cur++;
6073    if (*cur == 0) {
6074        xmlSchemaPSimpleTypeErr(ctxt,
6075	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6076	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6077	    NULL, (xmlNodePtr) attr, NULL, expected,
6078	    val, NULL, NULL, NULL);
6079        return (def);
6080    }
6081    while ((*cur >= '0') && (*cur <= '9')) {
6082        ret = ret * 10 + (*cur - '0');
6083        cur++;
6084    }
6085    while (IS_BLANK_CH(*cur))
6086        cur++;
6087    /*
6088    * TODO: Restrict the maximal value to Integer.
6089    */
6090    if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6091	xmlSchemaPSimpleTypeErr(ctxt,
6092	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6093	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6094	    NULL, (xmlNodePtr) attr, NULL, expected,
6095	    val, NULL, NULL, NULL);
6096        return (def);
6097    }
6098    return (ret);
6099}
6100
6101/**
6102 * xmlSchemaPGetBoolNodeValue:
6103 * @ctxt:  a schema validation context
6104 * @ownerDes:  owner designation
6105 * @ownerItem:  the owner as a schema item
6106 * @node: the node holding the value
6107 *
6108 * Converts a boolean string value into 1 or 0.
6109 *
6110 * Returns 0 or 1.
6111 */
6112static int
6113xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6114			   xmlSchemaBasicItemPtr ownerItem,
6115			   xmlNodePtr node)
6116{
6117    xmlChar *value = NULL;
6118    int res = 0;
6119
6120    value = xmlNodeGetContent(node);
6121    /*
6122    * 3.2.2.1 Lexical representation
6123    * An instance of a datatype that is defined as �boolean�
6124    * can have the following legal literals {true, false, 1, 0}.
6125    */
6126    if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6127        res = 1;
6128    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6129        res = 0;
6130    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6131	res = 1;
6132    else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6133        res = 0;
6134    else {
6135        xmlSchemaPSimpleTypeErr(ctxt,
6136	    XML_SCHEMAP_INVALID_BOOLEAN,
6137	    ownerItem, node,
6138	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6139	    NULL, BAD_CAST value,
6140	    NULL, NULL, NULL);
6141    }
6142    if (value != NULL)
6143	xmlFree(value);
6144    return (res);
6145}
6146
6147/**
6148 * xmlGetBooleanProp:
6149 * @ctxt:  a schema validation context
6150 * @node:  a subtree containing XML Schema informations
6151 * @name:  the attribute name
6152 * @def:  the default value
6153 *
6154 * Evaluate if a boolean property is set
6155 *
6156 * Returns the default if not found, 0 if found to be false,
6157 * 1 if found to be true
6158 */
6159static int
6160xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6161		  xmlNodePtr node,
6162                  const char *name, int def)
6163{
6164    const xmlChar *val;
6165
6166    val = xmlSchemaGetProp(ctxt, node, name);
6167    if (val == NULL)
6168        return (def);
6169    /*
6170    * 3.2.2.1 Lexical representation
6171    * An instance of a datatype that is defined as �boolean�
6172    * can have the following legal literals {true, false, 1, 0}.
6173    */
6174    if (xmlStrEqual(val, BAD_CAST "true"))
6175        def = 1;
6176    else if (xmlStrEqual(val, BAD_CAST "false"))
6177        def = 0;
6178    else if (xmlStrEqual(val, BAD_CAST "1"))
6179	def = 1;
6180    else if (xmlStrEqual(val, BAD_CAST "0"))
6181        def = 0;
6182    else {
6183        xmlSchemaPSimpleTypeErr(ctxt,
6184	    XML_SCHEMAP_INVALID_BOOLEAN,
6185	    NULL,
6186	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6187	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6188	    NULL, val, NULL, NULL, NULL);
6189    }
6190    return (def);
6191}
6192
6193/************************************************************************
6194 * 									*
6195 *		Shema extraction from an Infoset			*
6196 * 									*
6197 ************************************************************************/
6198static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6199                                                 ctxt, xmlSchemaPtr schema,
6200                                                 xmlNodePtr node,
6201						 int topLevel);
6202static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6203                                                  ctxt,
6204                                                  xmlSchemaPtr schema,
6205                                                  xmlNodePtr node,
6206						  int topLevel);
6207static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6208                                                  ctxt,
6209                                                  xmlSchemaPtr schema,
6210                                                  xmlNodePtr node,
6211						  xmlSchemaTypeType parentType);
6212static xmlSchemaBasicItemPtr
6213xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6214			     xmlSchemaPtr schema,
6215			     xmlNodePtr node,
6216			     xmlSchemaItemListPtr uses,
6217			     int parentType);
6218static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6219                                           xmlSchemaPtr schema,
6220                                           xmlNodePtr node);
6221static xmlSchemaWildcardPtr
6222xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6223                           xmlSchemaPtr schema, xmlNodePtr node);
6224
6225/**
6226 * xmlSchemaPValAttrNodeValue:
6227 *
6228 * @ctxt:  a schema parser context
6229 * @ownerDes: the designation of the parent element
6230 * @ownerItem: the schema object owner if existent
6231 * @attr:  the schema attribute node being validated
6232 * @value: the value
6233 * @type: the built-in type to be validated against
6234 *
6235 * Validates a value against the given built-in type.
6236 * This one is intended to be used internally for validation
6237 * of schema attribute values during parsing of the schema.
6238 *
6239 * Returns 0 if the value is valid, a positive error code
6240 * number otherwise and -1 in case of an internal or API error.
6241 */
6242static int
6243xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6244			   xmlSchemaBasicItemPtr ownerItem,
6245			   xmlAttrPtr attr,
6246			   const xmlChar *value,
6247			   xmlSchemaTypePtr type)
6248{
6249
6250    int ret = 0;
6251
6252    /*
6253    * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6254    * one is really meant to be used internally, so better not.
6255    */
6256    if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6257	return (-1);
6258    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6259	PERROR_INT("xmlSchemaPValAttrNodeValue",
6260	    "the given type is not a built-in type");
6261	return (-1);
6262    }
6263    switch (type->builtInType) {
6264	case XML_SCHEMAS_NCNAME:
6265	case XML_SCHEMAS_QNAME:
6266	case XML_SCHEMAS_ANYURI:
6267	case XML_SCHEMAS_TOKEN:
6268	case XML_SCHEMAS_LANGUAGE:
6269	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6270		(xmlNodePtr) attr);
6271	    break;
6272	default: {
6273	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6274		"validation using the given type is not supported while "
6275		"parsing a schema");
6276	    return (-1);
6277	}
6278    }
6279    /*
6280    * TODO: Should we use the S4S error codes instead?
6281    */
6282    if (ret < 0) {
6283	PERROR_INT("xmlSchemaPValAttrNodeValue",
6284	    "failed to validate a schema attribute value");
6285	return (-1);
6286    } else if (ret > 0) {
6287	if (WXS_IS_LIST(type))
6288	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6289	else
6290	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6291	xmlSchemaPSimpleTypeErr(pctxt,
6292	    ret, ownerItem, (xmlNodePtr) attr,
6293	    type, NULL, value, NULL, NULL, NULL);
6294    }
6295    return (ret);
6296}
6297
6298/**
6299 * xmlSchemaPValAttrNode:
6300 *
6301 * @ctxt:  a schema parser context
6302 * @ownerDes: the designation of the parent element
6303 * @ownerItem: the schema object owner if existent
6304 * @attr:  the schema attribute node being validated
6305 * @type: the built-in type to be validated against
6306 * @value: the resulting value if any
6307 *
6308 * Extracts and validates a value against the given built-in type.
6309 * This one is intended to be used internally for validation
6310 * of schema attribute values during parsing of the schema.
6311 *
6312 * Returns 0 if the value is valid, a positive error code
6313 * number otherwise and -1 in case of an internal or API error.
6314 */
6315static int
6316xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6317			   xmlSchemaBasicItemPtr ownerItem,
6318			   xmlAttrPtr attr,
6319			   xmlSchemaTypePtr type,
6320			   const xmlChar **value)
6321{
6322    const xmlChar *val;
6323
6324    if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6325	return (-1);
6326
6327    val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6328    if (value != NULL)
6329	*value = val;
6330
6331    return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6332	val, type));
6333}
6334
6335/**
6336 * xmlSchemaPValAttr:
6337 *
6338 * @ctxt:  a schema parser context
6339 * @node: the element node of the attribute
6340 * @ownerDes: the designation of the parent element
6341 * @ownerItem: the schema object owner if existent
6342 * @ownerElem: the owner element node
6343 * @name:  the name of the schema attribute node
6344 * @type: the built-in type to be validated against
6345 * @value: the resulting value if any
6346 *
6347 * Extracts and validates a value against the given built-in type.
6348 * This one is intended to be used internally for validation
6349 * of schema attribute values during parsing of the schema.
6350 *
6351 * Returns 0 if the value is valid, a positive error code
6352 * number otherwise and -1 in case of an internal or API error.
6353 */
6354static int
6355xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6356		       xmlSchemaBasicItemPtr ownerItem,
6357		       xmlNodePtr ownerElem,
6358		       const char *name,
6359		       xmlSchemaTypePtr type,
6360		       const xmlChar **value)
6361{
6362    xmlAttrPtr attr;
6363
6364    if ((ctxt == NULL) || (type == NULL)) {
6365	if (value != NULL)
6366	    *value = NULL;
6367	return (-1);
6368    }
6369    if (type->type != XML_SCHEMA_TYPE_BASIC) {
6370	if (value != NULL)
6371	    *value = NULL;
6372	xmlSchemaPErr(ctxt, ownerElem,
6373	    XML_SCHEMAP_INTERNAL,
6374	    "Internal error: xmlSchemaPValAttr, the given "
6375	    "type '%s' is not a built-in type.\n",
6376	    type->name, NULL);
6377	return (-1);
6378    }
6379    attr = xmlSchemaGetPropNode(ownerElem, name);
6380    if (attr == NULL) {
6381	if (value != NULL)
6382	    *value = NULL;
6383	return (0);
6384    }
6385    return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6386	type, value));
6387}
6388
6389static int
6390xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6391		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6392		  xmlNodePtr node,
6393		  xmlAttrPtr attr,
6394		  const xmlChar *namespaceName)
6395{
6396    /* TODO: Pointer comparison instead? */
6397    if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6398	return (0);
6399    if (xmlStrEqual(xmlSchemaNs, namespaceName))
6400	return (0);
6401    /*
6402    * Check if the referenced namespace was <import>ed.
6403    */
6404    if (WXS_BUCKET(pctxt)->relations != NULL) {
6405	xmlSchemaSchemaRelationPtr rel;
6406
6407	rel = WXS_BUCKET(pctxt)->relations;
6408	do {
6409	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6410		xmlStrEqual(namespaceName, rel->importNamespace))
6411		return (0);
6412	    rel = rel->next;
6413	} while (rel != NULL);
6414    }
6415    /*
6416    * No matching <import>ed namespace found.
6417    */
6418    {
6419	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6420
6421	if (namespaceName == NULL)
6422	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6423		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6424		"References from this schema to components in no "
6425		"namespace are not allowed, since not indicated by an "
6426		"import statement", NULL, NULL);
6427	else
6428	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6429		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6430		"References from this schema to components in the "
6431		"namespace '%s' are not allowed, since not indicated by an "
6432		"import statement", namespaceName, NULL);
6433    }
6434    return (XML_SCHEMAP_SRC_RESOLVE);
6435}
6436
6437/**
6438 * xmlSchemaParseLocalAttributes:
6439 * @ctxt:  a schema validation context
6440 * @schema:  the schema being built
6441 * @node:  a subtree containing XML Schema informations
6442 * @type:  the hosting type where the attributes will be anchored
6443 *
6444 * Parses attribute uses and attribute declarations and
6445 * attribute group references.
6446 */
6447static int
6448xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6449                        xmlNodePtr *child, xmlSchemaItemListPtr *list,
6450			int parentType, int *hasRefs)
6451{
6452    void *item;
6453
6454    while ((IS_SCHEMA((*child), "attribute")) ||
6455           (IS_SCHEMA((*child), "attributeGroup"))) {
6456        if (IS_SCHEMA((*child), "attribute")) {
6457	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6458		*list, parentType);
6459        } else {
6460            item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6461	    if ((item != NULL) && (hasRefs != NULL))
6462		*hasRefs = 1;
6463        }
6464	if (item != NULL) {
6465	    if (*list == NULL) {
6466		/* TODO: Customize grow factor. */
6467		*list = xmlSchemaItemListCreate();
6468		if (*list == NULL)
6469		    return(-1);
6470	    }
6471	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6472		return(-1);
6473	}
6474        *child = (*child)->next;
6475    }
6476    return (0);
6477}
6478
6479/**
6480 * xmlSchemaParseAnnotation:
6481 * @ctxt:  a schema validation context
6482 * @schema:  the schema being built
6483 * @node:  a subtree containing XML Schema informations
6484 *
6485 * parse a XML schema Attrribute declaration
6486 * *WARNING* this interface is highly subject to change
6487 *
6488 * Returns -1 in case of error, 0 if the declaration is improper and
6489 *         1 in case of success.
6490 */
6491static xmlSchemaAnnotPtr
6492xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6493{
6494    xmlSchemaAnnotPtr ret;
6495    xmlNodePtr child = NULL;
6496    xmlAttrPtr attr;
6497    int barked = 0;
6498
6499    /*
6500    * INFO: S4S completed.
6501    */
6502    /*
6503    * id = ID
6504    * {any attributes with non-schema namespace . . .}>
6505    * Content: (appinfo | documentation)*
6506    */
6507    if ((ctxt == NULL) || (node == NULL))
6508        return (NULL);
6509    if (needed)
6510	ret = xmlSchemaNewAnnot(ctxt, node);
6511    else
6512	ret = NULL;
6513    attr = node->properties;
6514    while (attr != NULL) {
6515	if (((attr->ns == NULL) &&
6516	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6517	    ((attr->ns != NULL) &&
6518	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6519
6520	    xmlSchemaPIllegalAttrErr(ctxt,
6521		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6522	}
6523	attr = attr->next;
6524    }
6525    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6526    /*
6527    * And now for the children...
6528    */
6529    child = node->children;
6530    while (child != NULL) {
6531	if (IS_SCHEMA(child, "appinfo")) {
6532	    /* TODO: make available the content of "appinfo". */
6533	    /*
6534	    * source = anyURI
6535	    * {any attributes with non-schema namespace . . .}>
6536	    * Content: ({any})*
6537	    */
6538	    attr = child->properties;
6539	    while (attr != NULL) {
6540		if (((attr->ns == NULL) &&
6541		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6542		     ((attr->ns != NULL) &&
6543		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6544
6545		    xmlSchemaPIllegalAttrErr(ctxt,
6546			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6547		}
6548		attr = attr->next;
6549	    }
6550	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6551		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6552	    child = child->next;
6553	} else if (IS_SCHEMA(child, "documentation")) {
6554	    /* TODO: make available the content of "documentation". */
6555	    /*
6556	    * source = anyURI
6557	    * {any attributes with non-schema namespace . . .}>
6558	    * Content: ({any})*
6559	    */
6560	    attr = child->properties;
6561	    while (attr != NULL) {
6562		if (attr->ns == NULL) {
6563		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6564			xmlSchemaPIllegalAttrErr(ctxt,
6565			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6566		    }
6567		} else {
6568		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6569			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6570			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6571
6572			xmlSchemaPIllegalAttrErr(ctxt,
6573			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6574		    }
6575		}
6576		attr = attr->next;
6577	    }
6578	    /*
6579	    * Attribute "xml:lang".
6580	    */
6581	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6582	    if (attr != NULL)
6583		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6584		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6585	    child = child->next;
6586	} else {
6587	    if (!barked)
6588		xmlSchemaPContentErr(ctxt,
6589		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6590		    NULL, node, child, NULL, "(appinfo | documentation)*");
6591	    barked = 1;
6592	    child = child->next;
6593	}
6594    }
6595
6596    return (ret);
6597}
6598
6599/**
6600 * xmlSchemaParseFacet:
6601 * @ctxt:  a schema validation context
6602 * @schema:  the schema being built
6603 * @node:  a subtree containing XML Schema informations
6604 *
6605 * parse a XML schema Facet declaration
6606 * *WARNING* this interface is highly subject to change
6607 *
6608 * Returns the new type structure or NULL in case of error
6609 */
6610static xmlSchemaFacetPtr
6611xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6612                    xmlNodePtr node)
6613{
6614    xmlSchemaFacetPtr facet;
6615    xmlNodePtr child = NULL;
6616    const xmlChar *value;
6617
6618    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6619        return (NULL);
6620
6621    facet = xmlSchemaNewFacet();
6622    if (facet == NULL) {
6623        xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6624        return (NULL);
6625    }
6626    facet->node = node;
6627    value = xmlSchemaGetProp(ctxt, node, "value");
6628    if (value == NULL) {
6629        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6630                       "Facet %s has no value\n", node->name, NULL);
6631        xmlSchemaFreeFacet(facet);
6632        return (NULL);
6633    }
6634    if (IS_SCHEMA(node, "minInclusive")) {
6635        facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6636    } else if (IS_SCHEMA(node, "minExclusive")) {
6637        facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6638    } else if (IS_SCHEMA(node, "maxInclusive")) {
6639        facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6640    } else if (IS_SCHEMA(node, "maxExclusive")) {
6641        facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6642    } else if (IS_SCHEMA(node, "totalDigits")) {
6643        facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6644    } else if (IS_SCHEMA(node, "fractionDigits")) {
6645        facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6646    } else if (IS_SCHEMA(node, "pattern")) {
6647        facet->type = XML_SCHEMA_FACET_PATTERN;
6648    } else if (IS_SCHEMA(node, "enumeration")) {
6649        facet->type = XML_SCHEMA_FACET_ENUMERATION;
6650    } else if (IS_SCHEMA(node, "whiteSpace")) {
6651        facet->type = XML_SCHEMA_FACET_WHITESPACE;
6652    } else if (IS_SCHEMA(node, "length")) {
6653        facet->type = XML_SCHEMA_FACET_LENGTH;
6654    } else if (IS_SCHEMA(node, "maxLength")) {
6655        facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6656    } else if (IS_SCHEMA(node, "minLength")) {
6657        facet->type = XML_SCHEMA_FACET_MINLENGTH;
6658    } else {
6659        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6660                       "Unknown facet type %s\n", node->name, NULL);
6661        xmlSchemaFreeFacet(facet);
6662        return (NULL);
6663    }
6664    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6665    facet->value = value;
6666    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6667	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6668	const xmlChar *fixed;
6669
6670	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6671	if (fixed != NULL) {
6672	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6673		facet->fixed = 1;
6674	}
6675    }
6676    child = node->children;
6677
6678    if (IS_SCHEMA(child, "annotation")) {
6679        facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6680        child = child->next;
6681    }
6682    if (child != NULL) {
6683        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6684                       "Facet %s has unexpected child content\n",
6685                       node->name, NULL);
6686    }
6687    return (facet);
6688}
6689
6690/**
6691 * xmlSchemaParseWildcardNs:
6692 * @ctxt:  a schema parser context
6693 * @wildc:  the wildcard, already created
6694 * @node:  a subtree containing XML Schema informations
6695 *
6696 * Parses the attribute "processContents" and "namespace"
6697 * of a xsd:anyAttribute and xsd:any.
6698 * *WARNING* this interface is highly subject to change
6699 *
6700 * Returns 0 if everything goes fine, a positive error code
6701 * if something is not valid and -1 if an internal error occurs.
6702 */
6703static int
6704xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6705			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6706			 xmlSchemaWildcardPtr wildc,
6707			 xmlNodePtr node)
6708{
6709    const xmlChar *pc, *ns, *dictnsItem;
6710    int ret = 0;
6711    xmlChar *nsItem;
6712    xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6713    xmlAttrPtr attr;
6714
6715    pc = xmlSchemaGetProp(ctxt, node, "processContents");
6716    if ((pc == NULL)
6717        || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6718        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6719    } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6720        wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6721    } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6722        wildc->processContents = XML_SCHEMAS_ANY_LAX;
6723    } else {
6724        xmlSchemaPSimpleTypeErr(ctxt,
6725	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6726	    NULL, node,
6727	    NULL, "(strict | skip | lax)", pc,
6728	    NULL, NULL, NULL);
6729        wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6730	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6731    }
6732    /*
6733     * Build the namespace constraints.
6734     */
6735    attr = xmlSchemaGetPropNode(node, "namespace");
6736    ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6737    if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6738	wildc->any = 1;
6739    else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6740	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6741	if (wildc->negNsSet == NULL) {
6742	    return (-1);
6743	}
6744	wildc->negNsSet->value = ctxt->targetNamespace;
6745    } else {
6746	const xmlChar *end, *cur;
6747
6748	cur = ns;
6749	do {
6750	    while (IS_BLANK_CH(*cur))
6751		cur++;
6752	    end = cur;
6753	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6754		end++;
6755	    if (end == cur)
6756		break;
6757	    nsItem = xmlStrndup(cur, end - cur);
6758	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6759		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6760		xmlSchemaPSimpleTypeErr(ctxt,
6761		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6762		    NULL, (xmlNodePtr) attr,
6763		    NULL,
6764		    "((##any | ##other) | List of (xs:anyURI | "
6765		    "(##targetNamespace | ##local)))",
6766		    nsItem, NULL, NULL, NULL);
6767		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6768	    } else {
6769		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6770		    dictnsItem = ctxt->targetNamespace;
6771		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6772		    dictnsItem = NULL;
6773		} else {
6774		    /*
6775		    * Validate the item (anyURI).
6776		    */
6777		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6778			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6779		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6780		}
6781		/*
6782		* Avoid dublicate namespaces.
6783		*/
6784		tmp = wildc->nsSet;
6785		while (tmp != NULL) {
6786		    if (dictnsItem == tmp->value)
6787			break;
6788		    tmp = tmp->next;
6789		}
6790		if (tmp == NULL) {
6791		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6792		    if (tmp == NULL) {
6793			xmlFree(nsItem);
6794			return (-1);
6795		    }
6796		    tmp->value = dictnsItem;
6797		    tmp->next = NULL;
6798		    if (wildc->nsSet == NULL)
6799			wildc->nsSet = tmp;
6800		    else
6801			lastNs->next = tmp;
6802		    lastNs = tmp;
6803		}
6804
6805	    }
6806	    xmlFree(nsItem);
6807	    cur = end;
6808	} while (*cur != 0);
6809    }
6810    return (ret);
6811}
6812
6813static int
6814xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6815				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6816				 xmlNodePtr node,
6817				 int minOccurs,
6818				 int maxOccurs) {
6819
6820    if ((maxOccurs == 0) && ( minOccurs == 0))
6821	return (0);
6822    if (maxOccurs != UNBOUNDED) {
6823	/*
6824	* TODO: Maybe we should better not create the particle,
6825	* if min/max is invalid, since it could confuse the build of the
6826	* content model.
6827	*/
6828	/*
6829	* 3.9.6 Schema Component Constraint: Particle Correct
6830	*
6831	*/
6832	if (maxOccurs < 1) {
6833	    /*
6834	    * 2.2 {max occurs} must be greater than or equal to 1.
6835	    */
6836	    xmlSchemaPCustomAttrErr(ctxt,
6837		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6838		NULL, NULL,
6839		xmlSchemaGetPropNode(node, "maxOccurs"),
6840		"The value must be greater than or equal to 1");
6841	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6842	} else if (minOccurs > maxOccurs) {
6843	    /*
6844	    * 2.1 {min occurs} must not be greater than {max occurs}.
6845	    */
6846	    xmlSchemaPCustomAttrErr(ctxt,
6847		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6848		NULL, NULL,
6849		xmlSchemaGetPropNode(node, "minOccurs"),
6850		"The value must not be greater than the value of 'maxOccurs'");
6851	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6852	}
6853    }
6854    return (0);
6855}
6856
6857/**
6858 * xmlSchemaParseAny:
6859 * @ctxt:  a schema validation context
6860 * @schema:  the schema being built
6861 * @node:  a subtree containing XML Schema informations
6862 *
6863 * Parsea a XML schema <any> element. A particle and wildcard
6864 * will be created (except if minOccurs==maxOccurs==0, in this case
6865 * nothing will be created).
6866 * *WARNING* this interface is highly subject to change
6867 *
6868 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6869 */
6870static xmlSchemaParticlePtr
6871xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6872                  xmlNodePtr node)
6873{
6874    xmlSchemaParticlePtr particle;
6875    xmlNodePtr child = NULL;
6876    xmlSchemaWildcardPtr wild;
6877    int min, max;
6878    xmlAttrPtr attr;
6879    xmlSchemaAnnotPtr annot = NULL;
6880
6881    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6882        return (NULL);
6883    /*
6884    * Check for illegal attributes.
6885    */
6886    attr = node->properties;
6887    while (attr != NULL) {
6888	if (attr->ns == NULL) {
6889	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6890		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6891		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6892	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6893		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6894		xmlSchemaPIllegalAttrErr(ctxt,
6895		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6896	    }
6897	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6898	    xmlSchemaPIllegalAttrErr(ctxt,
6899		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6900	}
6901	attr = attr->next;
6902    }
6903    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6904    /*
6905    * minOccurs/maxOccurs.
6906    */
6907    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6908	"(xs:nonNegativeInteger | unbounded)");
6909    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6910	"xs:nonNegativeInteger");
6911    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6912    /*
6913    * Create & parse the wildcard.
6914    */
6915    wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6916    if (wild == NULL)
6917	return (NULL);
6918    xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6919    /*
6920    * And now for the children...
6921    */
6922    child = node->children;
6923    if (IS_SCHEMA(child, "annotation")) {
6924        annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6925        child = child->next;
6926    }
6927    if (child != NULL) {
6928	xmlSchemaPContentErr(ctxt,
6929	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6930	    NULL, node, child,
6931	    NULL, "(annotation?)");
6932    }
6933    /*
6934    * No component if minOccurs==maxOccurs==0.
6935    */
6936    if ((min == 0) && (max == 0)) {
6937	/* Don't free the wildcard, since it's already on the list. */
6938	return (NULL);
6939    }
6940    /*
6941    * Create the particle.
6942    */
6943    particle = xmlSchemaAddParticle(ctxt, node, min, max);
6944    if (particle == NULL)
6945        return (NULL);
6946    particle->annot = annot;
6947    particle->children = (xmlSchemaTreeItemPtr) wild;
6948
6949    return (particle);
6950}
6951
6952/**
6953 * xmlSchemaParseNotation:
6954 * @ctxt:  a schema validation context
6955 * @schema:  the schema being built
6956 * @node:  a subtree containing XML Schema informations
6957 *
6958 * parse a XML schema Notation declaration
6959 *
6960 * Returns the new structure or NULL in case of error
6961 */
6962static xmlSchemaNotationPtr
6963xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6964                       xmlNodePtr node)
6965{
6966    const xmlChar *name;
6967    xmlSchemaNotationPtr ret;
6968    xmlNodePtr child = NULL;
6969
6970    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6971        return (NULL);
6972    name = xmlSchemaGetProp(ctxt, node, "name");
6973    if (name == NULL) {
6974        xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6975                       "Notation has no name\n", NULL, NULL);
6976        return (NULL);
6977    }
6978    ret = xmlSchemaAddNotation(ctxt, schema, name,
6979	ctxt->targetNamespace, node);
6980    if (ret == NULL)
6981        return (NULL);
6982    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6983
6984    child = node->children;
6985    if (IS_SCHEMA(child, "annotation")) {
6986        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6987        child = child->next;
6988    }
6989    if (child != NULL) {
6990	xmlSchemaPContentErr(ctxt,
6991	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6992	    NULL, node, child,
6993	    NULL, "(annotation?)");
6994    }
6995
6996    return (ret);
6997}
6998
6999/**
7000 * xmlSchemaParseAnyAttribute:
7001 * @ctxt:  a schema validation context
7002 * @schema:  the schema being built
7003 * @node:  a subtree containing XML Schema informations
7004 *
7005 * parse a XML schema AnyAttrribute declaration
7006 * *WARNING* this interface is highly subject to change
7007 *
7008 * Returns a wildcard or NULL.
7009 */
7010static xmlSchemaWildcardPtr
7011xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7012                           xmlSchemaPtr schema, xmlNodePtr node)
7013{
7014    xmlSchemaWildcardPtr ret;
7015    xmlNodePtr child = NULL;
7016    xmlAttrPtr attr;
7017
7018    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7019        return (NULL);
7020
7021    ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7022	node);
7023    if (ret == NULL) {
7024        return (NULL);
7025    }
7026    /*
7027    * Check for illegal attributes.
7028    */
7029    attr = node->properties;
7030    while (attr != NULL) {
7031	if (attr->ns == NULL) {
7032	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7033	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7034		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7035		xmlSchemaPIllegalAttrErr(ctxt,
7036		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7037	    }
7038	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7039	    xmlSchemaPIllegalAttrErr(ctxt,
7040		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7041	}
7042	attr = attr->next;
7043    }
7044    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7045    /*
7046    * Parse the namespace list.
7047    */
7048    if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7049	return (NULL);
7050    /*
7051    * And now for the children...
7052    */
7053    child = node->children;
7054    if (IS_SCHEMA(child, "annotation")) {
7055        ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7056        child = child->next;
7057    }
7058    if (child != NULL) {
7059	xmlSchemaPContentErr(ctxt,
7060	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7061	    NULL, node, child,
7062	    NULL, "(annotation?)");
7063    }
7064
7065    return (ret);
7066}
7067
7068
7069/**
7070 * xmlSchemaParseAttribute:
7071 * @ctxt:  a schema validation context
7072 * @schema:  the schema being built
7073 * @node:  a subtree containing XML Schema informations
7074 *
7075 * parse a XML schema Attrribute declaration
7076 * *WARNING* this interface is highly subject to change
7077 *
7078 * Returns the attribute declaration.
7079 */
7080static xmlSchemaBasicItemPtr
7081xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7082			     xmlSchemaPtr schema,
7083			     xmlNodePtr node,
7084			     xmlSchemaItemListPtr uses,
7085			     int parentType)
7086{
7087    const xmlChar *attrValue, *name = NULL, *ns = NULL;
7088    xmlSchemaAttributeUsePtr use = NULL;
7089    xmlNodePtr child = NULL;
7090    xmlAttrPtr attr;
7091    const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7092    int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7093    int	nberrors, hasForm = 0, defValueType = 0;
7094
7095#define WXS_ATTR_DEF_VAL_DEFAULT 1
7096#define WXS_ATTR_DEF_VAL_FIXED 2
7097
7098    /*
7099     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7100     */
7101
7102    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7103        return (NULL);
7104    attr = xmlSchemaGetPropNode(node, "ref");
7105    if (attr != NULL) {
7106	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7107	    NULL, attr, &tmpNs, &tmpName) != 0) {
7108	    return (NULL);
7109	}
7110	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7111	    return(NULL);
7112	isRef = 1;
7113    }
7114    nberrors = pctxt->nberrors;
7115    /*
7116    * Check for illegal attributes.
7117    */
7118    attr = node->properties;
7119    while (attr != NULL) {
7120	if (attr->ns == NULL) {
7121	    if (isRef) {
7122		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7123		    xmlSchemaPValAttrNodeID(pctxt, attr);
7124		    goto attr_next;
7125		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7126		    goto attr_next;
7127		}
7128	    } else {
7129		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7130		    goto attr_next;
7131		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7132		    xmlSchemaPValAttrNodeID(pctxt, attr);
7133		    goto attr_next;
7134		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7135		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7136			attr, &tmpNs, &tmpName);
7137		    goto attr_next;
7138		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7139		    /*
7140		    * Evaluate the target namespace
7141		    */
7142		    hasForm = 1;
7143		    attrValue = xmlSchemaGetNodeContent(pctxt,
7144			(xmlNodePtr) attr);
7145		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7146			ns = pctxt->targetNamespace;
7147		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7148		    {
7149			xmlSchemaPSimpleTypeErr(pctxt,
7150			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7151			    NULL, (xmlNodePtr) attr,
7152			    NULL, "(qualified | unqualified)",
7153			    attrValue, NULL, NULL, NULL);
7154		    }
7155		    goto attr_next;
7156		}
7157	    }
7158	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7159
7160		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7161		/* TODO: Maybe we need to normalize the value beforehand. */
7162		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7163		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7164		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7165		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7166		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7167		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7168		else {
7169		    xmlSchemaPSimpleTypeErr(pctxt,
7170			XML_SCHEMAP_INVALID_ATTR_USE,
7171			NULL, (xmlNodePtr) attr,
7172			NULL, "(optional | prohibited | required)",
7173			attrValue, NULL, NULL, NULL);
7174		}
7175		goto attr_next;
7176	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7177		/*
7178		* 3.2.3 : 1
7179		* default and fixed must not both be present.
7180		*/
7181		if (defValue) {
7182		    xmlSchemaPMutualExclAttrErr(pctxt,
7183			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7184			NULL, attr, "default", "fixed");
7185		} else {
7186		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7187		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7188		}
7189		goto attr_next;
7190	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7191		/*
7192		* 3.2.3 : 1
7193		* default and fixed must not both be present.
7194		*/
7195		if (defValue) {
7196		    xmlSchemaPMutualExclAttrErr(pctxt,
7197			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7198			NULL, attr, "default", "fixed");
7199		} else {
7200		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7201		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7202		}
7203		goto attr_next;
7204	    }
7205	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7206	    goto attr_next;
7207
7208	xmlSchemaPIllegalAttrErr(pctxt,
7209	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7210
7211attr_next:
7212	attr = attr->next;
7213    }
7214    /*
7215    * 3.2.3 : 2
7216    * If default and use are both present, use must have
7217    * the actual value optional.
7218    */
7219    if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7220	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7221	xmlSchemaPSimpleTypeErr(pctxt,
7222	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7223	    NULL, node, NULL,
7224	    "(optional | prohibited | required)", NULL,
7225	    "The value of the attribute 'use' must be 'optional' "
7226	    "if the attribute 'default' is present",
7227	    NULL, NULL);
7228    }
7229    /*
7230    * We want correct attributes.
7231    */
7232    if (nberrors != pctxt->nberrors)
7233	return(NULL);
7234    if (! isRef) {
7235	xmlSchemaAttributePtr attrDecl;
7236
7237	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7238	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7239	    ns = pctxt->targetNamespace;
7240	/*
7241	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7242	* TODO: Move this to the component layer.
7243	*/
7244	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7245	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7246		XML_SCHEMAP_NO_XSI,
7247		node, NULL,
7248		"The target namespace must not match '%s'",
7249		xmlSchemaInstanceNs, NULL);
7250	}
7251	attr = xmlSchemaGetPropNode(node, "name");
7252	if (attr == NULL) {
7253	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7254		NULL, node, "name", NULL);
7255	    return (NULL);
7256	}
7257	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7258	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7259	    return (NULL);
7260	}
7261	/*
7262	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7263	* TODO: Move this to the component layer.
7264	*/
7265	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7266	    xmlSchemaPSimpleTypeErr(pctxt,
7267		XML_SCHEMAP_NO_XMLNS,
7268		NULL, (xmlNodePtr) attr,
7269		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7270		"The value of the attribute must not match 'xmlns'",
7271		NULL, NULL);
7272	    return (NULL);
7273	}
7274	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7275	    goto check_children;
7276	/*
7277	* Create the attribute use component.
7278	*/
7279	use = xmlSchemaAddAttributeUse(pctxt, node);
7280	if (use == NULL)
7281	    return(NULL);
7282	use->occurs = occurs;
7283	/*
7284	* Create the attribute declaration.
7285	*/
7286	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7287	if (attrDecl == NULL)
7288	    return (NULL);
7289	if (tmpName != NULL) {
7290	    attrDecl->typeName = tmpName;
7291	    attrDecl->typeNs = tmpNs;
7292	}
7293	use->attrDecl = attrDecl;
7294	/*
7295	* Value constraint.
7296	*/
7297	if (defValue != NULL) {
7298	    attrDecl->defValue = defValue;
7299	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7300		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7301	}
7302    } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7303	xmlSchemaQNameRefPtr ref;
7304
7305	/*
7306	* Create the attribute use component.
7307	*/
7308	use = xmlSchemaAddAttributeUse(pctxt, node);
7309	if (use == NULL)
7310	    return(NULL);
7311	/*
7312	* We need to resolve the reference at later stage.
7313	*/
7314	WXS_ADD_PENDING(pctxt, use);
7315	use->occurs = occurs;
7316	/*
7317	* Create a QName reference to the attribute declaration.
7318	*/
7319	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7320	    tmpName, tmpNs);
7321	if (ref == NULL)
7322	    return(NULL);
7323	/*
7324	* Assign the reference. This will be substituted for the
7325	* referenced attribute declaration when the QName is resolved.
7326	*/
7327	use->attrDecl = WXS_ATTR_CAST ref;
7328	/*
7329	* Value constraint.
7330	*/
7331	if (defValue != NULL)
7332	    use->defValue = defValue;
7333	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7334		use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7335    }
7336
7337check_children:
7338    /*
7339    * And now for the children...
7340    */
7341    child = node->children;
7342    if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7343	xmlSchemaAttributeUseProhibPtr prohib;
7344
7345	if (IS_SCHEMA(child, "annotation")) {
7346	    xmlSchemaParseAnnotation(pctxt, child, 0);
7347	    child = child->next;
7348	}
7349	if (child != NULL) {
7350	    xmlSchemaPContentErr(pctxt,
7351		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7352		NULL, node, child, NULL,
7353		"(annotation?)");
7354	}
7355	/*
7356	* Check for pointlessness of attribute prohibitions.
7357	*/
7358	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7359	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7360		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7361		node, NULL,
7362		"Skipping attribute use prohibition, since it is "
7363		"pointless inside an <attributeGroup>",
7364		NULL, NULL, NULL);
7365	    return(NULL);
7366	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7367	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7368		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7369		node, NULL,
7370		"Skipping attribute use prohibition, since it is "
7371		"pointless when extending a type",
7372		NULL, NULL, NULL);
7373	    return(NULL);
7374	}
7375	if (! isRef) {
7376	    tmpName = name;
7377	    tmpNs = ns;
7378	}
7379	/*
7380	* Check for duplicate attribute prohibitions.
7381	*/
7382	if (uses) {
7383	    int i;
7384
7385	    for (i = 0; i < uses->nbItems; i++) {
7386		use = uses->items[i];
7387		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7388		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7389		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7390		{
7391		    xmlChar *str = NULL;
7392
7393		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7394			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7395			node, NULL,
7396			"Skipping duplicate attribute use prohibition '%s'",
7397			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7398			NULL, NULL);
7399		    FREE_AND_NULL(str)
7400		    return(NULL);
7401		}
7402	    }
7403	}
7404	/*
7405	* Create the attribute prohibition helper component.
7406	*/
7407	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7408	if (prohib == NULL)
7409	    return(NULL);
7410	prohib->node = node;
7411	prohib->name = tmpName;
7412	prohib->targetNamespace = tmpNs;
7413	if (isRef) {
7414	    /*
7415	    * We need at least to resolve to the attribute declaration.
7416	    */
7417	    WXS_ADD_PENDING(pctxt, prohib);
7418	}
7419	return(WXS_BASIC_CAST prohib);
7420    } else {
7421	if (IS_SCHEMA(child, "annotation")) {
7422	    /*
7423	    * TODO: Should this go into the attr decl?
7424	    */
7425	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7426	    child = child->next;
7427	}
7428	if (isRef) {
7429	    if (child != NULL) {
7430		if (IS_SCHEMA(child, "simpleType"))
7431		    /*
7432		    * 3.2.3 : 3.2
7433		    * If ref is present, then all of <simpleType>,
7434		    * form and type must be absent.
7435		    */
7436		    xmlSchemaPContentErr(pctxt,
7437			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7438			NULL, node, child, NULL,
7439			"(annotation?)");
7440		else
7441		    xmlSchemaPContentErr(pctxt,
7442			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7443			NULL, node, child, NULL,
7444			"(annotation?)");
7445	    }
7446	} else {
7447	    if (IS_SCHEMA(child, "simpleType")) {
7448		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7449		    /*
7450		    * 3.2.3 : 4
7451		    * type and <simpleType> must not both be present.
7452		    */
7453		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7454			NULL, node, child,
7455			"The attribute 'type' and the <simpleType> child "
7456			"are mutually exclusive", NULL);
7457		} else
7458		    WXS_ATTRUSE_TYPEDEF(use) =
7459			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7460		child = child->next;
7461	    }
7462	    if (child != NULL)
7463		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464		NULL, node, child, NULL,
7465		"(annotation?, simpleType?)");
7466	}
7467    }
7468    return (WXS_BASIC_CAST use);
7469}
7470
7471
7472static xmlSchemaAttributePtr
7473xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7474			      xmlSchemaPtr schema,
7475			      xmlNodePtr node)
7476{
7477    const xmlChar *attrValue;
7478    xmlSchemaAttributePtr ret;
7479    xmlNodePtr child = NULL;
7480    xmlAttrPtr attr;
7481
7482    /*
7483     * Note that the w3c spec assumes the schema to be validated with schema
7484     * for schemas beforehand.
7485     *
7486     * 3.2.3 Constraints on XML Representations of Attribute Declarations
7487     */
7488    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7489        return (NULL);
7490    /*
7491    * 3.2.3 : 3.1
7492    * One of ref or name must be present, but not both
7493    */
7494    attr = xmlSchemaGetPropNode(node, "name");
7495    if (attr == NULL) {
7496	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7497	    NULL, node, "name", NULL);
7498	return (NULL);
7499    }
7500    if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7501	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7502	return (NULL);
7503    }
7504    /*
7505    * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7506    * TODO: Move this to the component layer.
7507    */
7508    if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7509	xmlSchemaPSimpleTypeErr(pctxt,
7510	    XML_SCHEMAP_NO_XMLNS,
7511	    NULL, (xmlNodePtr) attr,
7512	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7513	    "The value of the attribute must not match 'xmlns'",
7514	    NULL, NULL);
7515	return (NULL);
7516    }
7517    /*
7518    * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7519    * TODO: Move this to the component layer.
7520    *       Or better leave it here and add it to the component layer
7521    *       if we have a schema construction API.
7522    */
7523    if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7524	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7525	    XML_SCHEMAP_NO_XSI, node, NULL,
7526	    "The target namespace must not match '%s'",
7527	    xmlSchemaInstanceNs, NULL);
7528    }
7529
7530    ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7531	pctxt->targetNamespace, node, 1);
7532    if (ret == NULL)
7533	return (NULL);
7534    ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7535
7536    /*
7537    * Check for illegal attributes.
7538    */
7539    attr = node->properties;
7540    while (attr != NULL) {
7541	if (attr->ns == NULL) {
7542	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7543		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7544		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7545		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7546		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7547	    {
7548		xmlSchemaPIllegalAttrErr(pctxt,
7549		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7550	    }
7551	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7552	    xmlSchemaPIllegalAttrErr(pctxt,
7553		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7554	}
7555	attr = attr->next;
7556    }
7557    xmlSchemaPValAttrQName(pctxt, schema, NULL,
7558	node, "type", &ret->typeNs, &ret->typeName);
7559
7560    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7561    /*
7562    * Attribute "fixed".
7563    */
7564    ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7565    if (ret->defValue != NULL)
7566	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7567    /*
7568    * Attribute "default".
7569    */
7570    attr = xmlSchemaGetPropNode(node, "default");
7571    if (attr != NULL) {
7572	/*
7573	* 3.2.3 : 1
7574	* default and fixed must not both be present.
7575	*/
7576	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7577	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7578		WXS_BASIC_CAST ret, attr, "default", "fixed");
7579	} else
7580	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7581    }
7582    /*
7583    * And now for the children...
7584    */
7585    child = node->children;
7586    if (IS_SCHEMA(child, "annotation")) {
7587        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7588        child = child->next;
7589    }
7590    if (IS_SCHEMA(child, "simpleType")) {
7591	if (ret->typeName != NULL) {
7592	    /*
7593	    * 3.2.3 : 4
7594	    * type and <simpleType> must not both be present.
7595	    */
7596	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7597		NULL, node, child,
7598		"The attribute 'type' and the <simpleType> child "
7599		"are mutually exclusive", NULL);
7600	} else
7601	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7602	child = child->next;
7603    }
7604    if (child != NULL)
7605	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7606	    NULL, node, child, NULL,
7607	    "(annotation?, simpleType?)");
7608
7609    return (ret);
7610}
7611
7612/**
7613 * xmlSchemaParseAttributeGroupRef:
7614 * @ctxt:  a schema validation context
7615 * @schema:  the schema being built
7616 * @node:  a subtree containing XML Schema informations
7617 *
7618 * Parse an attribute group definition reference.
7619 * Note that a reference to an attribute group does not
7620 * correspond to any component at all.
7621 * *WARNING* this interface is highly subject to change
7622 *
7623 * Returns the attribute group or NULL in case of error.
7624 */
7625static xmlSchemaQNameRefPtr
7626xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7627				xmlSchemaPtr schema,
7628				xmlNodePtr node)
7629{
7630    xmlSchemaQNameRefPtr ret;
7631    xmlNodePtr child = NULL;
7632    xmlAttrPtr attr;
7633    const xmlChar *refNs = NULL, *ref = NULL;
7634
7635    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7636        return (NULL);
7637
7638    attr = xmlSchemaGetPropNode(node, "ref");
7639    if (attr == NULL) {
7640	xmlSchemaPMissingAttrErr(pctxt,
7641	    XML_SCHEMAP_S4S_ATTR_MISSING,
7642	    NULL, node, "ref", NULL);
7643	return (NULL);
7644    }
7645    xmlSchemaPValAttrNodeQName(pctxt, schema,
7646	NULL, attr, &refNs, &ref);
7647    if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7648	return(NULL);
7649
7650    /*
7651    * Check for illegal attributes.
7652    */
7653    attr = node->properties;
7654    while (attr != NULL) {
7655	if (attr->ns == NULL) {
7656	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7657		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7658	    {
7659		xmlSchemaPIllegalAttrErr(pctxt,
7660		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7661	    }
7662	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7663	    xmlSchemaPIllegalAttrErr(pctxt,
7664		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7665	}
7666	attr = attr->next;
7667    }
7668    /* Attribute ID */
7669    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7670
7671    /*
7672    * And now for the children...
7673    */
7674    child = node->children;
7675    if (IS_SCHEMA(child, "annotation")) {
7676	/*
7677	* TODO: We do not have a place to store the annotation, do we?
7678	*/
7679        xmlSchemaParseAnnotation(pctxt, child, 0);
7680        child = child->next;
7681    }
7682    if (child != NULL) {
7683	xmlSchemaPContentErr(pctxt,
7684	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7685	    NULL, node, child, NULL,
7686	    "(annotation?)");
7687    }
7688
7689    /*
7690    * Handle attribute group redefinitions.
7691    */
7692    if (pctxt->isRedefine && pctxt->redef &&
7693	(pctxt->redef->item->type ==
7694	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7695	(ref == pctxt->redef->refName) &&
7696	(refNs == pctxt->redef->refTargetNs))
7697    {
7698	/*
7699	* SPEC src-redefine:
7700	* (7.1) "If it has an <attributeGroup> among its contents
7701	* the �actual value� of whose ref [attribute] is the same
7702	* as the �actual value� of its own name attribute plus
7703	* target namespace, then it must have exactly one such group."
7704	*/
7705	if (pctxt->redefCounter != 0) {
7706	    xmlChar *str = NULL;
7707
7708	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7709		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7710		"The redefining attribute group definition "
7711		"'%s' must not contain more than one "
7712		"reference to the redefined definition",
7713		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7714	    FREE_AND_NULL(str);
7715	    return(NULL);
7716	}
7717	pctxt->redefCounter++;
7718	/*
7719	* URGENT TODO: How to ensure that the reference will not be
7720	* handled by the normal component resolution mechanism?
7721	*/
7722	ret = xmlSchemaNewQNameRef(pctxt,
7723	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7724	if (ret == NULL)
7725	    return(NULL);
7726	ret->node = node;
7727	pctxt->redef->reference = WXS_BASIC_CAST ret;
7728    } else {
7729	/*
7730	* Create a QName-reference helper component. We will substitute this
7731	* component for the attribute uses of the referenced attribute group
7732	* definition.
7733	*/
7734	ret = xmlSchemaNewQNameRef(pctxt,
7735	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7736	if (ret == NULL)
7737	    return(NULL);
7738	ret->node = node;
7739	/* Add to pending items, to be able to resolve the reference. */
7740	WXS_ADD_PENDING(pctxt, ret);
7741    }
7742    return (ret);
7743}
7744
7745/**
7746 * xmlSchemaParseAttributeGroupDefinition:
7747 * @pctxt:  a schema validation context
7748 * @schema:  the schema being built
7749 * @node:  a subtree containing XML Schema informations
7750 *
7751 * parse a XML schema Attribute Group declaration
7752 * *WARNING* this interface is highly subject to change
7753 *
7754 * Returns the attribute group definition or NULL in case of error.
7755 */
7756static xmlSchemaAttributeGroupPtr
7757xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7758				       xmlSchemaPtr schema,
7759				       xmlNodePtr node)
7760{
7761    const xmlChar *name;
7762    xmlSchemaAttributeGroupPtr ret;
7763    xmlNodePtr child = NULL;
7764    xmlAttrPtr attr;
7765    int hasRefs = 0;
7766
7767    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7768        return (NULL);
7769
7770    attr = xmlSchemaGetPropNode(node, "name");
7771    if (attr == NULL) {
7772	xmlSchemaPMissingAttrErr(pctxt,
7773	    XML_SCHEMAP_S4S_ATTR_MISSING,
7774	    NULL, node, "name", NULL);
7775	return (NULL);
7776    }
7777    /*
7778    * The name is crucial, exit if invalid.
7779    */
7780    if (xmlSchemaPValAttrNode(pctxt,
7781	NULL, attr,
7782	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7783	return (NULL);
7784    }
7785    ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7786	name, pctxt->targetNamespace, node);
7787    if (ret == NULL)
7788	return (NULL);
7789    /*
7790    * Check for illegal attributes.
7791    */
7792    attr = node->properties;
7793    while (attr != NULL) {
7794	if (attr->ns == NULL) {
7795	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7796		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7797	    {
7798		xmlSchemaPIllegalAttrErr(pctxt,
7799		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7800	    }
7801	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7802	    xmlSchemaPIllegalAttrErr(pctxt,
7803		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7804	}
7805	attr = attr->next;
7806    }
7807    /* Attribute ID */
7808    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7809    /*
7810    * And now for the children...
7811    */
7812    child = node->children;
7813    if (IS_SCHEMA(child, "annotation")) {
7814        ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7815        child = child->next;
7816    }
7817    /*
7818    * Parse contained attribute decls/refs.
7819    */
7820    if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7821	(xmlSchemaItemListPtr *) &(ret->attrUses),
7822	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7823	return(NULL);
7824    if (hasRefs)
7825	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7826    /*
7827    * Parse the attribute wildcard.
7828    */
7829    if (IS_SCHEMA(child, "anyAttribute")) {
7830	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7831	    schema, child);
7832	child = child->next;
7833    }
7834    if (child != NULL) {
7835	xmlSchemaPContentErr(pctxt,
7836	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7837	    NULL, node, child, NULL,
7838	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7839    }
7840    return (ret);
7841}
7842
7843/**
7844 * xmlSchemaPValAttrFormDefault:
7845 * @value:  the value
7846 * @flags: the flags to be modified
7847 * @flagQualified: the specific flag for "qualified"
7848 *
7849 * Returns 0 if the value is valid, 1 otherwise.
7850 */
7851static int
7852xmlSchemaPValAttrFormDefault(const xmlChar *value,
7853			     int *flags,
7854			     int flagQualified)
7855{
7856    if (xmlStrEqual(value, BAD_CAST "qualified")) {
7857	if  ((*flags & flagQualified) == 0)
7858	    *flags |= flagQualified;
7859    } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7860	return (1);
7861
7862    return (0);
7863}
7864
7865/**
7866 * xmlSchemaPValAttrBlockFinal:
7867 * @value:  the value
7868 * @flags: the flags to be modified
7869 * @flagAll: the specific flag for "#all"
7870 * @flagExtension: the specific flag for "extension"
7871 * @flagRestriction: the specific flag for "restriction"
7872 * @flagSubstitution: the specific flag for "substitution"
7873 * @flagList: the specific flag for "list"
7874 * @flagUnion: the specific flag for "union"
7875 *
7876 * Validates the value of the attribute "final" and "block". The value
7877 * is converted into the specified flag values and returned in @flags.
7878 *
7879 * Returns 0 if the value is valid, 1 otherwise.
7880 */
7881
7882static int
7883xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7884			    int *flags,
7885			    int flagAll,
7886			    int flagExtension,
7887			    int flagRestriction,
7888			    int flagSubstitution,
7889			    int flagList,
7890			    int flagUnion)
7891{
7892    int ret = 0;
7893
7894    /*
7895    * TODO: This does not check for dublicate entries.
7896    */
7897    if ((flags == NULL) || (value == NULL))
7898	return (-1);
7899    if (value[0] == 0)
7900	return (0);
7901    if (xmlStrEqual(value, BAD_CAST "#all")) {
7902	if (flagAll != -1)
7903	    *flags |= flagAll;
7904	else {
7905	    if (flagExtension != -1)
7906		*flags |= flagExtension;
7907	    if (flagRestriction != -1)
7908		*flags |= flagRestriction;
7909	    if (flagSubstitution != -1)
7910		*flags |= flagSubstitution;
7911	    if (flagList != -1)
7912		*flags |= flagList;
7913	    if (flagUnion != -1)
7914		*flags |= flagUnion;
7915	}
7916    } else {
7917	const xmlChar *end, *cur = value;
7918	xmlChar *item;
7919
7920	do {
7921	    while (IS_BLANK_CH(*cur))
7922		cur++;
7923	    end = cur;
7924	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7925		end++;
7926	    if (end == cur)
7927		break;
7928	    item = xmlStrndup(cur, end - cur);
7929	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7930		if (flagExtension != -1) {
7931		    if ((*flags & flagExtension) == 0)
7932			*flags |= flagExtension;
7933		} else
7934		    ret = 1;
7935	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7936		if (flagRestriction != -1) {
7937		    if ((*flags & flagRestriction) == 0)
7938			*flags |= flagRestriction;
7939		} else
7940		    ret = 1;
7941	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7942		if (flagSubstitution != -1) {
7943		    if ((*flags & flagSubstitution) == 0)
7944			*flags |= flagSubstitution;
7945		} else
7946		    ret = 1;
7947	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
7948		if (flagList != -1) {
7949		    if ((*flags & flagList) == 0)
7950			*flags |= flagList;
7951		} else
7952		    ret = 1;
7953	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
7954		if (flagUnion != -1) {
7955		    if ((*flags & flagUnion) == 0)
7956			*flags |= flagUnion;
7957		} else
7958		    ret = 1;
7959	    } else
7960		ret = 1;
7961	    if (item != NULL)
7962		xmlFree(item);
7963	    cur = end;
7964	} while ((ret == 0) && (*cur != 0));
7965    }
7966
7967    return (ret);
7968}
7969
7970static int
7971xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7972			     xmlSchemaIDCPtr idc,
7973			     xmlSchemaIDCSelectPtr selector,
7974			     xmlAttrPtr attr,
7975			     int isField)
7976{
7977    xmlNodePtr node;
7978
7979    /*
7980    * c-selector-xpath:
7981    * Schema Component Constraint: Selector Value OK
7982    *
7983    * TODO: 1 The {selector} must be a valid XPath expression, as defined
7984    * in [XPath].
7985    */
7986    if (selector == NULL) {
7987	xmlSchemaPErr(ctxt, idc->node,
7988	    XML_SCHEMAP_INTERNAL,
7989	    "Internal error: xmlSchemaCheckCSelectorXPath, "
7990	    "the selector is not specified.\n", NULL, NULL);
7991	return (-1);
7992    }
7993    if (attr == NULL)
7994	node = idc->node;
7995    else
7996	node = (xmlNodePtr) attr;
7997    if (selector->xpath == NULL) {
7998	xmlSchemaPCustomErr(ctxt,
7999	    /* TODO: Adjust error code. */
8000	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8001	    NULL, node,
8002	    "The XPath expression of the selector is not valid", NULL);
8003	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8004    } else {
8005	const xmlChar **nsArray = NULL;
8006	xmlNsPtr *nsList = NULL;
8007	/*
8008	* Compile the XPath expression.
8009	*/
8010	/*
8011	* TODO: We need the array of in-scope namespaces for compilation.
8012	* TODO: Call xmlPatterncompile with different options for selector/
8013	* field.
8014	*/
8015	if (attr == NULL)
8016	    nsList = NULL;
8017	else
8018	    nsList = xmlGetNsList(attr->doc, attr->parent);
8019	/*
8020	* Build an array of prefixes and namespaces.
8021	*/
8022	if (nsList != NULL) {
8023	    int i, count = 0;
8024
8025	    for (i = 0; nsList[i] != NULL; i++)
8026		count++;
8027
8028	    nsArray = (const xmlChar **) xmlMalloc(
8029		(count * 2 + 1) * sizeof(const xmlChar *));
8030	    if (nsArray == NULL) {
8031		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8032		    NULL);
8033		xmlFree(nsList);
8034		return (-1);
8035	    }
8036	    for (i = 0; i < count; i++) {
8037		nsArray[2 * i] = nsList[i]->href;
8038		nsArray[2 * i + 1] = nsList[i]->prefix;
8039	    }
8040	    nsArray[count * 2] = NULL;
8041	    xmlFree(nsList);
8042	}
8043	/*
8044	* TODO: Differentiate between "selector" and "field".
8045	*/
8046	if (isField)
8047	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8048		NULL, XML_PATTERN_XSFIELD, nsArray);
8049	else
8050	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8051		NULL, XML_PATTERN_XSSEL, nsArray);
8052	if (nsArray != NULL)
8053	    xmlFree((xmlChar **) nsArray);
8054
8055	if (selector->xpathComp == NULL) {
8056	    xmlSchemaPCustomErr(ctxt,
8057		/* TODO: Adjust error code? */
8058		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8059		NULL, node,
8060		"The XPath expression '%s' could not be "
8061		"compiled", selector->xpath);
8062	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8063	}
8064    }
8065    return (0);
8066}
8067
8068#define ADD_ANNOTATION(annot)   \
8069    xmlSchemaAnnotPtr cur = item->annot; \
8070    if (item->annot == NULL) {  \
8071	item->annot = annot;    \
8072	return (annot);         \
8073    }                           \
8074    cur = item->annot;          \
8075    if (cur->next != NULL) {    \
8076	cur = cur->next;	\
8077    }                           \
8078    cur->next = annot;
8079
8080/**
8081 * xmlSchemaAssignAnnotation:
8082 * @item: the schema component
8083 * @annot: the annotation
8084 *
8085 * Adds the annotation to the given schema component.
8086 *
8087 * Returns the given annotaion.
8088 */
8089static xmlSchemaAnnotPtr
8090xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8091		       xmlSchemaAnnotPtr annot)
8092{
8093    if ((annItem == NULL) || (annot == NULL))
8094	return (NULL);
8095    switch (annItem->type) {
8096	case XML_SCHEMA_TYPE_ELEMENT: {
8097		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8098		ADD_ANNOTATION(annot)
8099	    }
8100	    break;
8101	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8102		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8103		ADD_ANNOTATION(annot)
8104	    }
8105	    break;
8106	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8107	case XML_SCHEMA_TYPE_ANY: {
8108		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8109		ADD_ANNOTATION(annot)
8110	    }
8111	    break;
8112	case XML_SCHEMA_TYPE_PARTICLE:
8113	case XML_SCHEMA_TYPE_IDC_KEY:
8114	case XML_SCHEMA_TYPE_IDC_KEYREF:
8115	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8116		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8117		ADD_ANNOTATION(annot)
8118	    }
8119	    break;
8120	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8121		xmlSchemaAttributeGroupPtr item =
8122		    (xmlSchemaAttributeGroupPtr) annItem;
8123		ADD_ANNOTATION(annot)
8124	    }
8125	    break;
8126	case XML_SCHEMA_TYPE_NOTATION: {
8127		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8128		ADD_ANNOTATION(annot)
8129	    }
8130	    break;
8131	case XML_SCHEMA_FACET_MININCLUSIVE:
8132	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8133	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8134	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8135	case XML_SCHEMA_FACET_TOTALDIGITS:
8136	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8137	case XML_SCHEMA_FACET_PATTERN:
8138	case XML_SCHEMA_FACET_ENUMERATION:
8139	case XML_SCHEMA_FACET_WHITESPACE:
8140	case XML_SCHEMA_FACET_LENGTH:
8141	case XML_SCHEMA_FACET_MAXLENGTH:
8142	case XML_SCHEMA_FACET_MINLENGTH: {
8143		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8144		ADD_ANNOTATION(annot)
8145	    }
8146	    break;
8147	case XML_SCHEMA_TYPE_SIMPLE:
8148	case XML_SCHEMA_TYPE_COMPLEX: {
8149		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8150		ADD_ANNOTATION(annot)
8151	    }
8152	    break;
8153	case XML_SCHEMA_TYPE_GROUP: {
8154		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8155		ADD_ANNOTATION(annot)
8156	    }
8157	    break;
8158	case XML_SCHEMA_TYPE_SEQUENCE:
8159	case XML_SCHEMA_TYPE_CHOICE:
8160	case XML_SCHEMA_TYPE_ALL: {
8161		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8162		ADD_ANNOTATION(annot)
8163	    }
8164	    break;
8165	default:
8166	     xmlSchemaPCustomErr(NULL,
8167		XML_SCHEMAP_INTERNAL,
8168		NULL, NULL,
8169		"Internal error: xmlSchemaAddAnnotation, "
8170		"The item is not a annotated schema component", NULL);
8171	     break;
8172    }
8173    return (annot);
8174}
8175
8176/**
8177 * xmlSchemaParseIDCSelectorAndField:
8178 * @ctxt:  a schema validation context
8179 * @schema:  the schema being built
8180 * @node:  a subtree containing XML Schema informations
8181 *
8182 * Parses a XML Schema identity-contraint definition's
8183 * <selector> and <field> elements.
8184 *
8185 * Returns the parsed identity-constraint definition.
8186 */
8187static xmlSchemaIDCSelectPtr
8188xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8189			  xmlSchemaIDCPtr idc,
8190			  xmlNodePtr node,
8191			  int isField)
8192{
8193    xmlSchemaIDCSelectPtr item;
8194    xmlNodePtr child = NULL;
8195    xmlAttrPtr attr;
8196
8197    /*
8198    * Check for illegal attributes.
8199    */
8200    attr = node->properties;
8201    while (attr != NULL) {
8202	if (attr->ns == NULL) {
8203	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8204		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8205		xmlSchemaPIllegalAttrErr(ctxt,
8206		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8207	    }
8208	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8209	    xmlSchemaPIllegalAttrErr(ctxt,
8210		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8211	}
8212	attr = attr->next;
8213    }
8214    /*
8215    * Create the item.
8216    */
8217    item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8218    if (item == NULL) {
8219        xmlSchemaPErrMemory(ctxt,
8220	    "allocating a 'selector' of an identity-constraint definition",
8221	    NULL);
8222        return (NULL);
8223    }
8224    memset(item, 0, sizeof(xmlSchemaIDCSelect));
8225    /*
8226    * Attribute "xpath" (mandatory).
8227    */
8228    attr = xmlSchemaGetPropNode(node, "xpath");
8229    if (attr == NULL) {
8230    	xmlSchemaPMissingAttrErr(ctxt,
8231	    XML_SCHEMAP_S4S_ATTR_MISSING,
8232	    NULL, node,
8233	    "name", NULL);
8234    } else {
8235	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8236	/*
8237	* URGENT TODO: "field"s have an other syntax than "selector"s.
8238	*/
8239
8240	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8241	    isField) == -1) {
8242	    xmlSchemaPErr(ctxt,
8243		(xmlNodePtr) attr,
8244		XML_SCHEMAP_INTERNAL,
8245		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8246		"validating the XPath expression of a IDC selector.\n",
8247		NULL, NULL);
8248	}
8249
8250    }
8251    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8252    /*
8253    * And now for the children...
8254    */
8255    child = node->children;
8256    if (IS_SCHEMA(child, "annotation")) {
8257	/*
8258	* Add the annotation to the parent IDC.
8259	*/
8260	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8261	    xmlSchemaParseAnnotation(ctxt, child, 1));
8262	child = child->next;
8263    }
8264    if (child != NULL) {
8265	xmlSchemaPContentErr(ctxt,
8266	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8267	    NULL, node, child,
8268	    NULL, "(annotation?)");
8269    }
8270
8271    return (item);
8272}
8273
8274/**
8275 * xmlSchemaParseIDC:
8276 * @ctxt:  a schema validation context
8277 * @schema:  the schema being built
8278 * @node:  a subtree containing XML Schema informations
8279 *
8280 * Parses a XML Schema identity-contraint definition.
8281 *
8282 * Returns the parsed identity-constraint definition.
8283 */
8284static xmlSchemaIDCPtr
8285xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8286		  xmlSchemaPtr schema,
8287		  xmlNodePtr node,
8288		  xmlSchemaTypeType idcCategory,
8289		  const xmlChar *targetNamespace)
8290{
8291    xmlSchemaIDCPtr item = NULL;
8292    xmlNodePtr child = NULL;
8293    xmlAttrPtr attr;
8294    const xmlChar *name = NULL;
8295    xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8296
8297    /*
8298    * Check for illegal attributes.
8299    */
8300    attr = node->properties;
8301    while (attr != NULL) {
8302	if (attr->ns == NULL) {
8303	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8304		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8305		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8306		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8307		xmlSchemaPIllegalAttrErr(ctxt,
8308		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8309	    }
8310	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8311	    xmlSchemaPIllegalAttrErr(ctxt,
8312		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8313	}
8314	attr = attr->next;
8315    }
8316    /*
8317    * Attribute "name" (mandatory).
8318    */
8319    attr = xmlSchemaGetPropNode(node, "name");
8320    if (attr == NULL) {
8321	xmlSchemaPMissingAttrErr(ctxt,
8322	    XML_SCHEMAP_S4S_ATTR_MISSING,
8323	    NULL, node,
8324	    "name", NULL);
8325	return (NULL);
8326    } else if (xmlSchemaPValAttrNode(ctxt,
8327	NULL, attr,
8328	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8329	return (NULL);
8330    }
8331    /* Create the component. */
8332    item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8333	idcCategory, node);
8334    if (item == NULL)
8335	return(NULL);
8336
8337    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8338    if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8339	/*
8340	* Attribute "refer" (mandatory).
8341	*/
8342	attr = xmlSchemaGetPropNode(node, "refer");
8343	if (attr == NULL) {
8344	    xmlSchemaPMissingAttrErr(ctxt,
8345		XML_SCHEMAP_S4S_ATTR_MISSING,
8346		NULL, node,
8347		"refer", NULL);
8348	} else {
8349	    /*
8350	    * Create a reference item.
8351	    */
8352	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8353		NULL, NULL);
8354	    if (item->ref == NULL)
8355		return (NULL);
8356	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8357		NULL, attr,
8358		&(item->ref->targetNamespace),
8359		&(item->ref->name));
8360	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8361		item->ref->targetNamespace);
8362	}
8363    }
8364    /*
8365    * And now for the children...
8366    */
8367    child = node->children;
8368    if (IS_SCHEMA(child, "annotation")) {
8369	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8370	child = child->next;
8371    }
8372    if (child == NULL) {
8373	xmlSchemaPContentErr(ctxt,
8374		XML_SCHEMAP_S4S_ELEM_MISSING,
8375		NULL, node, child,
8376		"A child element is missing",
8377		"(annotation?, (selector, field+))");
8378    }
8379    /*
8380    * Child element <selector>.
8381    */
8382    if (IS_SCHEMA(child, "selector")) {
8383	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8384	    item, child, 0);
8385	child = child->next;
8386	/*
8387	* Child elements <field>.
8388	*/
8389	if (IS_SCHEMA(child, "field")) {
8390	    do {
8391		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8392		    item, child, 1);
8393		if (field != NULL) {
8394		    field->index = item->nbFields;
8395		    item->nbFields++;
8396		    if (lastField != NULL)
8397			lastField->next = field;
8398		    else
8399			item->fields = field;
8400		    lastField = field;
8401		}
8402		child = child->next;
8403	    } while (IS_SCHEMA(child, "field"));
8404	} else {
8405	    xmlSchemaPContentErr(ctxt,
8406		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8407		NULL, node, child,
8408		NULL, "(annotation?, (selector, field+))");
8409	}
8410    }
8411    if (child != NULL) {
8412	xmlSchemaPContentErr(ctxt,
8413	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8414	    NULL, node, child,
8415	    NULL, "(annotation?, (selector, field+))");
8416    }
8417
8418    return (item);
8419}
8420
8421/**
8422 * xmlSchemaParseElement:
8423 * @ctxt:  a schema validation context
8424 * @schema:  the schema being built
8425 * @node:  a subtree containing XML Schema informations
8426 * @topLevel: indicates if this is global declaration
8427 *
8428 * Parses a XML schema element declaration.
8429 * *WARNING* this interface is highly subject to change
8430 *
8431 * Returns the element declaration or a particle; NULL in case
8432 * of an error or if the particle has minOccurs==maxOccurs==0.
8433 */
8434static xmlSchemaBasicItemPtr
8435xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8436                      xmlNodePtr node, int *isElemRef, int topLevel)
8437{
8438    xmlSchemaElementPtr decl = NULL;
8439    xmlSchemaParticlePtr particle = NULL;
8440    xmlSchemaAnnotPtr annot = NULL;
8441    xmlNodePtr child = NULL;
8442    xmlAttrPtr attr, nameAttr;
8443    int min, max, isRef = 0;
8444    xmlChar *des = NULL;
8445
8446    /* 3.3.3 Constraints on XML Representations of Element Declarations */
8447    /* TODO: Complete implementation of 3.3.6 */
8448
8449    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8450        return (NULL);
8451
8452    if (isElemRef != NULL)
8453	*isElemRef = 0;
8454    /*
8455    * If we get a "ref" attribute on a local <element> we will assume it's
8456    * a reference - even if there's a "name" attribute; this seems to be more
8457    * robust.
8458    */
8459    nameAttr = xmlSchemaGetPropNode(node, "name");
8460    attr = xmlSchemaGetPropNode(node, "ref");
8461    if ((topLevel) || (attr == NULL)) {
8462	if (nameAttr == NULL) {
8463	    xmlSchemaPMissingAttrErr(ctxt,
8464		XML_SCHEMAP_S4S_ATTR_MISSING,
8465		NULL, node, "name", NULL);
8466	    return (NULL);
8467	}
8468    } else
8469	isRef = 1;
8470
8471    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8472    child = node->children;
8473    if (IS_SCHEMA(child, "annotation")) {
8474	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8475	child = child->next;
8476    }
8477    /*
8478    * Skip particle part if a global declaration.
8479    */
8480    if (topLevel)
8481	goto declaration_part;
8482    /*
8483    * The particle part ==================================================
8484    */
8485    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8486    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8487    xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8488    particle = xmlSchemaAddParticle(ctxt, node, min, max);
8489    if (particle == NULL)
8490	goto return_null;
8491
8492    /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8493
8494    if (isRef) {
8495	const xmlChar *refNs = NULL, *ref = NULL;
8496	xmlSchemaQNameRefPtr refer = NULL;
8497	/*
8498	* The reference part =============================================
8499	*/
8500	if (isElemRef != NULL)
8501	    *isElemRef = 1;
8502
8503	xmlSchemaPValAttrNodeQName(ctxt, schema,
8504	    NULL, attr, &refNs, &ref);
8505	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8506	/*
8507	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8508	*/
8509	if (nameAttr != NULL) {
8510	    xmlSchemaPMutualExclAttrErr(ctxt,
8511		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8512	}
8513	/*
8514	* Check for illegal attributes.
8515	*/
8516	attr = node->properties;
8517	while (attr != NULL) {
8518	    if (attr->ns == NULL) {
8519		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8520		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8521		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8522		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8523		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8524		{
8525		    attr = attr->next;
8526		    continue;
8527		} else {
8528		    /* SPEC (3.3.3 : 2.2) */
8529		    xmlSchemaPCustomAttrErr(ctxt,
8530			XML_SCHEMAP_SRC_ELEMENT_2_2,
8531			NULL, NULL, attr,
8532			"Only the attributes 'minOccurs', 'maxOccurs' and "
8533			"'id' are allowed in addition to 'ref'");
8534		    break;
8535		}
8536	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8537		xmlSchemaPIllegalAttrErr(ctxt,
8538		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8539	    }
8540	    attr = attr->next;
8541	}
8542	/*
8543	* No children except <annotation> expected.
8544	*/
8545	if (child != NULL) {
8546	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8547		NULL, node, child, NULL, "(annotation?)");
8548	}
8549	if ((min == 0) && (max == 0))
8550	    goto return_null;
8551	/*
8552	* Create the reference item and attach it to the particle.
8553	*/
8554	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8555	    ref, refNs);
8556	if (refer == NULL)
8557	    goto return_null;
8558	particle->children = (xmlSchemaTreeItemPtr) refer;
8559	particle->annot = annot;
8560	/*
8561	* Add the particle to pending components, since the reference
8562	* need to be resolved.
8563	*/
8564	WXS_ADD_PENDING(ctxt, particle);
8565	return ((xmlSchemaBasicItemPtr) particle);
8566    }
8567    /*
8568    * The declaration part ===============================================
8569    */
8570declaration_part:
8571    {
8572	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8573	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8574
8575	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8576	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8577	    goto return_null;
8578	/*
8579	* Evaluate the target namespace.
8580	*/
8581	if (topLevel) {
8582	    ns = ctxt->targetNamespace;
8583	} else {
8584	    attr = xmlSchemaGetPropNode(node, "form");
8585	    if (attr != NULL) {
8586		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8587		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8588		    ns = ctxt->targetNamespace;
8589		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8590		    xmlSchemaPSimpleTypeErr(ctxt,
8591			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8592			NULL, (xmlNodePtr) attr,
8593			NULL, "(qualified | unqualified)",
8594			attrValue, NULL, NULL, NULL);
8595		}
8596	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8597		ns = ctxt->targetNamespace;
8598	}
8599	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8600	if (decl == NULL) {
8601	    goto return_null;
8602	}
8603	/*
8604	* Check for illegal attributes.
8605	*/
8606	attr = node->properties;
8607	while (attr != NULL) {
8608	    if (attr->ns == NULL) {
8609		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8610		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8611		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8612		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8613		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8614		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8615		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8616		{
8617		    if (topLevel == 0) {
8618			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8619			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8620			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8621			{
8622			    xmlSchemaPIllegalAttrErr(ctxt,
8623				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8624			}
8625		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8626			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8627			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8628
8629			xmlSchemaPIllegalAttrErr(ctxt,
8630			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8631		    }
8632		}
8633	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8634
8635		xmlSchemaPIllegalAttrErr(ctxt,
8636		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8637	    }
8638	    attr = attr->next;
8639	}
8640	/*
8641	* Extract/validate attributes.
8642	*/
8643	if (topLevel) {
8644	    /*
8645	    * Process top attributes of global element declarations here.
8646	    */
8647	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8648	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8649	    xmlSchemaPValAttrQName(ctxt, schema,
8650		NULL, node, "substitutionGroup",
8651		&(decl->substGroupNs), &(decl->substGroup));
8652	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8653		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8654	    /*
8655	    * Attribute "final".
8656	    */
8657	    attr = xmlSchemaGetPropNode(node, "final");
8658	    if (attr == NULL) {
8659		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8660		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8661		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8662		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8663	    } else {
8664		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8665		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8666		    -1,
8667		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8668		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8669		    xmlSchemaPSimpleTypeErr(ctxt,
8670			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8671			NULL, (xmlNodePtr) attr,
8672			NULL, "(#all | List of (extension | restriction))",
8673			attrValue, NULL, NULL, NULL);
8674		}
8675	    }
8676	}
8677	/*
8678	* Attribute "block".
8679	*/
8680	attr = xmlSchemaGetPropNode(node, "block");
8681	if (attr == NULL) {
8682	    /*
8683	    * Apply default "block" values.
8684	    */
8685	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8686		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8687	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8688		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8689	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8690		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8691	} else {
8692	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8693	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8694		-1,
8695		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8696		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8697		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8698		xmlSchemaPSimpleTypeErr(ctxt,
8699		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8700		    NULL, (xmlNodePtr) attr,
8701		    NULL, "(#all | List of (extension | "
8702		    "restriction | substitution))", attrValue,
8703		    NULL, NULL, NULL);
8704	    }
8705	}
8706	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8707	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8708
8709	attr = xmlSchemaGetPropNode(node, "type");
8710	if (attr != NULL) {
8711	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8712		NULL, attr,
8713		&(decl->namedTypeNs), &(decl->namedType));
8714	    xmlSchemaCheckReference(ctxt, schema, node,
8715		attr, decl->namedTypeNs);
8716	}
8717	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8718	attr = xmlSchemaGetPropNode(node, "fixed");
8719	if (attr != NULL) {
8720	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8721	    if (decl->value != NULL) {
8722		/*
8723		* 3.3.3 : 1
8724		* default and fixed must not both be present.
8725		*/
8726		xmlSchemaPMutualExclAttrErr(ctxt,
8727		    XML_SCHEMAP_SRC_ELEMENT_1,
8728		    NULL, attr, "default", "fixed");
8729	    } else {
8730		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8731		decl->value = fixed;
8732	    }
8733	}
8734	/*
8735	* And now for the children...
8736	*/
8737	if (IS_SCHEMA(child, "complexType")) {
8738	    /*
8739	    * 3.3.3 : 3
8740	    * "type" and either <simpleType> or <complexType> are mutually
8741	    * exclusive
8742	    */
8743	    if (decl->namedType != NULL) {
8744		xmlSchemaPContentErr(ctxt,
8745		    XML_SCHEMAP_SRC_ELEMENT_3,
8746		    NULL, node, child,
8747		    "The attribute 'type' and the <complexType> child are "
8748		    "mutually exclusive", NULL);
8749	    } else
8750		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8751	    child = child->next;
8752	} else if (IS_SCHEMA(child, "simpleType")) {
8753	    /*
8754	    * 3.3.3 : 3
8755	    * "type" and either <simpleType> or <complexType> are
8756	    * mutually exclusive
8757	    */
8758	    if (decl->namedType != NULL) {
8759		xmlSchemaPContentErr(ctxt,
8760		    XML_SCHEMAP_SRC_ELEMENT_3,
8761		    NULL, node, child,
8762		    "The attribute 'type' and the <simpleType> child are "
8763		    "mutually exclusive", NULL);
8764	    } else
8765		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8766	    child = child->next;
8767	}
8768	while ((IS_SCHEMA(child, "unique")) ||
8769	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8770	    if (IS_SCHEMA(child, "unique")) {
8771		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8772		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8773	    } else if (IS_SCHEMA(child, "key")) {
8774		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8775		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8776	    } else if (IS_SCHEMA(child, "keyref")) {
8777		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8778		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8779	    }
8780	    if (lastIDC != NULL)
8781		lastIDC->next = curIDC;
8782	    else
8783		decl->idcs = (void *) curIDC;
8784	    lastIDC = curIDC;
8785	    child = child->next;
8786	}
8787	if (child != NULL) {
8788	    xmlSchemaPContentErr(ctxt,
8789		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8790		NULL, node, child,
8791		NULL, "(annotation?, ((simpleType | complexType)?, "
8792		"(unique | key | keyref)*))");
8793	}
8794	decl->annot = annot;
8795    }
8796    /*
8797    * NOTE: Element Declaration Representation OK 4. will be checked at a
8798    * different layer.
8799    */
8800    FREE_AND_NULL(des)
8801    if (topLevel)
8802	return ((xmlSchemaBasicItemPtr) decl);
8803    else {
8804	particle->children = (xmlSchemaTreeItemPtr) decl;
8805	return ((xmlSchemaBasicItemPtr) particle);
8806    }
8807
8808return_null:
8809    FREE_AND_NULL(des);
8810    if (annot != NULL) {
8811	if (particle != NULL)
8812	    particle->annot = NULL;
8813	if (decl != NULL)
8814	    decl->annot = NULL;
8815	xmlSchemaFreeAnnot(annot);
8816    }
8817    return (NULL);
8818}
8819
8820/**
8821 * xmlSchemaParseUnion:
8822 * @ctxt:  a schema validation context
8823 * @schema:  the schema being built
8824 * @node:  a subtree containing XML Schema informations
8825 *
8826 * parse a XML schema Union definition
8827 * *WARNING* this interface is highly subject to change
8828 *
8829 * Returns -1 in case of internal error, 0 in case of success and a positive
8830 * error code otherwise.
8831 */
8832static int
8833xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8834                    xmlNodePtr node)
8835{
8836    xmlSchemaTypePtr type;
8837    xmlNodePtr child = NULL;
8838    xmlAttrPtr attr;
8839    const xmlChar *cur = NULL;
8840
8841    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8842        return (-1);
8843    /* Not a component, don't create it. */
8844    type = ctxt->ctxtType;
8845    /*
8846    * Mark the simple type as being of variety "union".
8847    */
8848    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8849    /*
8850    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8851    * then the �simple ur-type definition�."
8852    */
8853    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8854    /*
8855    * Check for illegal attributes.
8856    */
8857    attr = node->properties;
8858    while (attr != NULL) {
8859	if (attr->ns == NULL) {
8860	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8861		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8862		xmlSchemaPIllegalAttrErr(ctxt,
8863		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8864	    }
8865	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8866	    xmlSchemaPIllegalAttrErr(ctxt,
8867		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8868	}
8869	attr = attr->next;
8870    }
8871    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8872    /*
8873    * Attribute "memberTypes". This is a list of QNames.
8874    * TODO: Check the value to contain anything.
8875    */
8876    attr = xmlSchemaGetPropNode(node, "memberTypes");
8877    if (attr != NULL) {
8878	const xmlChar *end;
8879	xmlChar *tmp;
8880	const xmlChar *localName, *nsName;
8881	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8882	xmlSchemaQNameRefPtr ref;
8883
8884	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8885	type->base = cur;
8886	do {
8887	    while (IS_BLANK_CH(*cur))
8888		cur++;
8889	    end = cur;
8890	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8891		end++;
8892	    if (end == cur)
8893		break;
8894	    tmp = xmlStrndup(cur, end - cur);
8895	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8896		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8897		/*
8898		* Create the member type link.
8899		*/
8900		link = (xmlSchemaTypeLinkPtr)
8901		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8902		if (link == NULL) {
8903		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8904			"allocating a type link", NULL);
8905		    return (-1);
8906		}
8907		link->type = NULL;
8908		link->next = NULL;
8909		if (lastLink == NULL)
8910		    type->memberTypes = link;
8911		else
8912		    lastLink->next = link;
8913		lastLink = link;
8914		/*
8915		* Create a reference item.
8916		*/
8917		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8918		    localName, nsName);
8919		if (ref == NULL) {
8920		    FREE_AND_NULL(tmp)
8921		    return (-1);
8922		}
8923		/*
8924		* Assign the reference to the link, it will be resolved
8925		* later during fixup of the union simple type.
8926		*/
8927		link->type = (xmlSchemaTypePtr) ref;
8928	    }
8929	    FREE_AND_NULL(tmp)
8930	    cur = end;
8931	} while (*cur != 0);
8932
8933    }
8934    /*
8935    * And now for the children...
8936    */
8937    child = node->children;
8938    if (IS_SCHEMA(child, "annotation")) {
8939	/*
8940	* Add the annotation to the simple type ancestor.
8941	*/
8942	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8943	    xmlSchemaParseAnnotation(ctxt, child, 1));
8944        child = child->next;
8945    }
8946    if (IS_SCHEMA(child, "simpleType")) {
8947	xmlSchemaTypePtr subtype, last = NULL;
8948
8949	/*
8950	* Anchor the member types in the "subtypes" field of the
8951	* simple type.
8952	*/
8953	while (IS_SCHEMA(child, "simpleType")) {
8954	    subtype = (xmlSchemaTypePtr)
8955		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8956	    if (subtype != NULL) {
8957		if (last == NULL) {
8958		    type->subtypes = subtype;
8959		    last = subtype;
8960		} else {
8961		    last->next = subtype;
8962		    last = subtype;
8963		}
8964		last->next = NULL;
8965	    }
8966	    child = child->next;
8967	}
8968    }
8969    if (child != NULL) {
8970	xmlSchemaPContentErr(ctxt,
8971	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8972	    NULL, node, child, NULL, "(annotation?, simpleType*)");
8973    }
8974    if ((attr == NULL) && (type->subtypes == NULL)) {
8975	 /*
8976	* src-union-memberTypes-or-simpleTypes
8977	* Either the memberTypes [attribute] of the <union> element must
8978	* be non-empty or there must be at least one simpleType [child].
8979	*/
8980	xmlSchemaPCustomErr(ctxt,
8981	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8982	    NULL, node,
8983	    "Either the attribute 'memberTypes' or "
8984	    "at least one <simpleType> child must be present", NULL);
8985    }
8986    return (0);
8987}
8988
8989/**
8990 * xmlSchemaParseList:
8991 * @ctxt:  a schema validation context
8992 * @schema:  the schema being built
8993 * @node:  a subtree containing XML Schema informations
8994 *
8995 * parse a XML schema List definition
8996 * *WARNING* this interface is highly subject to change
8997 *
8998 * Returns -1 in case of error, 0 if the declaration is improper and
8999 *         1 in case of success.
9000 */
9001static xmlSchemaTypePtr
9002xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9003                   xmlNodePtr node)
9004{
9005    xmlSchemaTypePtr type;
9006    xmlNodePtr child = NULL;
9007    xmlAttrPtr attr;
9008
9009    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9010        return (NULL);
9011    /* Not a component, don't create it. */
9012    type = ctxt->ctxtType;
9013    /*
9014    * Mark the type as being of variety "list".
9015    */
9016    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9017    /*
9018    * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9019    * then the �simple ur-type definition�."
9020    */
9021    type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9022    /*
9023    * Check for illegal attributes.
9024    */
9025    attr = node->properties;
9026    while (attr != NULL) {
9027	if (attr->ns == NULL) {
9028	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9029		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9030		xmlSchemaPIllegalAttrErr(ctxt,
9031		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9032	    }
9033	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9034	    xmlSchemaPIllegalAttrErr(ctxt,
9035		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9036	}
9037	attr = attr->next;
9038    }
9039
9040    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9041
9042    /*
9043    * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9044    * fields for holding the reference to the itemType.
9045    *
9046    * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9047    * the "ref" fields.
9048    */
9049    xmlSchemaPValAttrQName(ctxt, schema, NULL,
9050	node, "itemType", &(type->baseNs), &(type->base));
9051    /*
9052    * And now for the children...
9053    */
9054    child = node->children;
9055    if (IS_SCHEMA(child, "annotation")) {
9056	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9057	    xmlSchemaParseAnnotation(ctxt, child, 1));
9058        child = child->next;
9059    }
9060    if (IS_SCHEMA(child, "simpleType")) {
9061	/*
9062	* src-list-itemType-or-simpleType
9063	* Either the itemType [attribute] or the <simpleType> [child] of
9064	* the <list> element must be present, but not both.
9065	*/
9066	if (type->base != NULL) {
9067	    xmlSchemaPCustomErr(ctxt,
9068		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9069		NULL, node,
9070		"The attribute 'itemType' and the <simpleType> child "
9071		"are mutually exclusive", NULL);
9072	} else {
9073	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9074	}
9075        child = child->next;
9076    } else if (type->base == NULL) {
9077	xmlSchemaPCustomErr(ctxt,
9078	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9079	    NULL, node,
9080	    "Either the attribute 'itemType' or the <simpleType> child "
9081	    "must be present", NULL);
9082    }
9083    if (child != NULL) {
9084	xmlSchemaPContentErr(ctxt,
9085	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9086	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9087    }
9088    if ((type->base == NULL) &&
9089	(type->subtypes == NULL) &&
9090	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9091	xmlSchemaPCustomErr(ctxt,
9092	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9093	    NULL, node,
9094	    "Either the attribute 'itemType' or the <simpleType> child "
9095	    "must be present", NULL);
9096    }
9097    return (NULL);
9098}
9099
9100/**
9101 * xmlSchemaParseSimpleType:
9102 * @ctxt:  a schema validation context
9103 * @schema:  the schema being built
9104 * @node:  a subtree containing XML Schema informations
9105 *
9106 * parse a XML schema Simple Type definition
9107 * *WARNING* this interface is highly subject to change
9108 *
9109 * Returns -1 in case of error, 0 if the declaration is improper and
9110 * 1 in case of success.
9111 */
9112static xmlSchemaTypePtr
9113xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9114                         xmlNodePtr node, int topLevel)
9115{
9116    xmlSchemaTypePtr type, oldCtxtType;
9117    xmlNodePtr child = NULL;
9118    const xmlChar *attrValue = NULL;
9119    xmlAttrPtr attr;
9120    int hasRestriction = 0;
9121
9122    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9123        return (NULL);
9124
9125    if (topLevel) {
9126	attr = xmlSchemaGetPropNode(node, "name");
9127	if (attr == NULL) {
9128	    xmlSchemaPMissingAttrErr(ctxt,
9129		XML_SCHEMAP_S4S_ATTR_MISSING,
9130		NULL, node,
9131		"name", NULL);
9132	    return (NULL);
9133	} else {
9134	    if (xmlSchemaPValAttrNode(ctxt,
9135		NULL, attr,
9136		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9137		return (NULL);
9138	    /*
9139	    * Skip built-in types.
9140	    */
9141	    if (ctxt->isS4S) {
9142		xmlSchemaTypePtr biType;
9143
9144		if (ctxt->isRedefine) {
9145		    /*
9146		    * REDEFINE: Disallow redefinition of built-in-types.
9147		    * TODO: It seems that the spec does not say anything
9148		    * about this case.
9149		    */
9150		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9151			NULL, node,
9152			"Redefinition of built-in simple types is not "
9153			"supported", NULL);
9154		    return(NULL);
9155		}
9156		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9157		if (biType != NULL)
9158		    return (biType);
9159	    }
9160	}
9161    }
9162    /*
9163    * TargetNamespace:
9164    * SPEC "The �actual value� of the targetNamespace [attribute]
9165    * of the <schema> ancestor element information item if present,
9166    * otherwise �absent�.
9167    */
9168    if (topLevel == 0) {
9169#ifdef ENABLE_NAMED_LOCALS
9170        char buf[40];
9171#endif
9172	/*
9173	* Parse as local simple type definition.
9174	*/
9175#ifdef ENABLE_NAMED_LOCALS
9176        snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9177	type = xmlSchemaAddType(ctxt, schema,
9178	    XML_SCHEMA_TYPE_SIMPLE,
9179	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9180	    ctxt->targetNamespace, node, 0);
9181#else
9182	type = xmlSchemaAddType(ctxt, schema,
9183	    XML_SCHEMA_TYPE_SIMPLE,
9184	    NULL, ctxt->targetNamespace, node, 0);
9185#endif
9186	if (type == NULL)
9187	    return (NULL);
9188	type->type = XML_SCHEMA_TYPE_SIMPLE;
9189	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9190	/*
9191	* Check for illegal attributes.
9192	*/
9193	attr = node->properties;
9194	while (attr != NULL) {
9195	    if (attr->ns == NULL) {
9196		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9197		    xmlSchemaPIllegalAttrErr(ctxt,
9198			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9199		}
9200	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9201		    xmlSchemaPIllegalAttrErr(ctxt,
9202			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9203	    }
9204	    attr = attr->next;
9205	}
9206    } else {
9207	/*
9208	* Parse as global simple type definition.
9209	*
9210	* Note that attrValue is the value of the attribute "name" here.
9211	*/
9212	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9213	    attrValue, ctxt->targetNamespace, node, 1);
9214	if (type == NULL)
9215	    return (NULL);
9216	type->type = XML_SCHEMA_TYPE_SIMPLE;
9217	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9218	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9219	/*
9220	* Check for illegal attributes.
9221	*/
9222	attr = node->properties;
9223	while (attr != NULL) {
9224	    if (attr->ns == NULL) {
9225		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9226		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9227		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9228		    xmlSchemaPIllegalAttrErr(ctxt,
9229			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9230		}
9231	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9232		xmlSchemaPIllegalAttrErr(ctxt,
9233		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9234	    }
9235	    attr = attr->next;
9236	}
9237	/*
9238	* Attribute "final".
9239	*/
9240	attr = xmlSchemaGetPropNode(node, "final");
9241	if (attr == NULL) {
9242	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9243		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9244	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9245		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9246	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9247		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9248	} else {
9249	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9250	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9251		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9252		XML_SCHEMAS_TYPE_FINAL_LIST,
9253		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9254
9255		xmlSchemaPSimpleTypeErr(ctxt,
9256		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9257		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9258		    NULL, "(#all | List of (list | union | restriction)",
9259		    attrValue, NULL, NULL, NULL);
9260	    }
9261	}
9262    }
9263    type->targetNamespace = ctxt->targetNamespace;
9264    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9265    /*
9266    * And now for the children...
9267    */
9268    oldCtxtType = ctxt->ctxtType;
9269
9270    ctxt->ctxtType = type;
9271
9272    child = node->children;
9273    if (IS_SCHEMA(child, "annotation")) {
9274        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9275        child = child->next;
9276    }
9277    if (child == NULL) {
9278	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9279	    NULL, node, child, NULL,
9280	    "(annotation?, (restriction | list | union))");
9281    } else if (IS_SCHEMA(child, "restriction")) {
9282        xmlSchemaParseRestriction(ctxt, schema, child,
9283	    XML_SCHEMA_TYPE_SIMPLE);
9284	hasRestriction = 1;
9285        child = child->next;
9286    } else if (IS_SCHEMA(child, "list")) {
9287        xmlSchemaParseList(ctxt, schema, child);
9288        child = child->next;
9289    } else if (IS_SCHEMA(child, "union")) {
9290        xmlSchemaParseUnion(ctxt, schema, child);
9291        child = child->next;
9292    }
9293    if (child != NULL) {
9294	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9295	    NULL, node, child, NULL,
9296	    "(annotation?, (restriction | list | union))");
9297    }
9298    /*
9299    * REDEFINE: SPEC src-redefine (5)
9300    * "Within the [children], each <simpleType> must have a
9301    * <restriction> among its [children] ... the �actual value� of whose
9302    * base [attribute] must be the same as the �actual value� of its own
9303    * name attribute plus target namespace;"
9304    */
9305    if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9306	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9307	    NULL, node, "This is a redefinition, thus the "
9308	    "<simpleType> must have a <restriction> child", NULL);
9309    }
9310
9311    ctxt->ctxtType = oldCtxtType;
9312    return (type);
9313}
9314
9315/**
9316 * xmlSchemaParseModelGroupDefRef:
9317 * @ctxt:  the parser context
9318 * @schema: the schema being built
9319 * @node:  the node
9320 *
9321 * Parses a reference to a model group definition.
9322 *
9323 * We will return a particle component with a qname-component or
9324 * NULL in case of an error.
9325 */
9326static xmlSchemaTreeItemPtr
9327xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9328			       xmlSchemaPtr schema,
9329			       xmlNodePtr node)
9330{
9331    xmlSchemaParticlePtr item;
9332    xmlNodePtr child = NULL;
9333    xmlAttrPtr attr;
9334    const xmlChar *ref = NULL, *refNs = NULL;
9335    int min, max;
9336
9337    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9338        return (NULL);
9339
9340    attr = xmlSchemaGetPropNode(node, "ref");
9341    if (attr == NULL) {
9342	xmlSchemaPMissingAttrErr(ctxt,
9343	    XML_SCHEMAP_S4S_ATTR_MISSING,
9344	    NULL, node, "ref", NULL);
9345	return (NULL);
9346    } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9347	attr, &refNs, &ref) != 0) {
9348	return (NULL);
9349    }
9350    xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9351    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9352    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9353	"(xs:nonNegativeInteger | unbounded)");
9354    /*
9355    * Check for illegal attributes.
9356    */
9357    attr = node->properties;
9358    while (attr != NULL) {
9359	if (attr->ns == NULL) {
9360	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9361		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9362		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9363		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9364		xmlSchemaPIllegalAttrErr(ctxt,
9365		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9366	    }
9367	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9368	    xmlSchemaPIllegalAttrErr(ctxt,
9369		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9370	}
9371	attr = attr->next;
9372    }
9373    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9374    item = xmlSchemaAddParticle(ctxt, node, min, max);
9375    if (item == NULL)
9376	return (NULL);
9377    /*
9378    * Create a qname-reference and set as the term; it will be substituted
9379    * for the model group after the reference has been resolved.
9380    */
9381    item->children = (xmlSchemaTreeItemPtr)
9382	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9383    xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9384    /*
9385    * And now for the children...
9386    */
9387    child = node->children;
9388    /* TODO: Is annotation even allowed for a model group reference? */
9389    if (IS_SCHEMA(child, "annotation")) {
9390	/*
9391	* TODO: What to do exactly with the annotation?
9392	*/
9393	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9394	child = child->next;
9395    }
9396    if (child != NULL) {
9397	xmlSchemaPContentErr(ctxt,
9398	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9399	    NULL, node, child, NULL,
9400	    "(annotation?)");
9401    }
9402    /*
9403    * Corresponds to no component at all if minOccurs==maxOccurs==0.
9404    */
9405    if ((min == 0) && (max == 0))
9406	return (NULL);
9407
9408    return ((xmlSchemaTreeItemPtr) item);
9409}
9410
9411/**
9412 * xmlSchemaParseModelGroupDefinition:
9413 * @ctxt:  a schema validation context
9414 * @schema:  the schema being built
9415 * @node:  a subtree containing XML Schema informations
9416 *
9417 * Parses a XML schema model group definition.
9418 *
9419 * Note that the contraint src-redefine (6.2) can't be applied until
9420 * references have been resolved. So we will do this at the
9421 * component fixup level.
9422 *
9423 * *WARNING* this interface is highly subject to change
9424 *
9425 * Returns -1 in case of error, 0 if the declaration is improper and
9426 *         1 in case of success.
9427 */
9428static xmlSchemaModelGroupDefPtr
9429xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9430				   xmlSchemaPtr schema,
9431				   xmlNodePtr node)
9432{
9433    xmlSchemaModelGroupDefPtr item;
9434    xmlNodePtr child = NULL;
9435    xmlAttrPtr attr;
9436    const xmlChar *name;
9437
9438    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9439        return (NULL);
9440
9441    attr = xmlSchemaGetPropNode(node, "name");
9442    if (attr == NULL) {
9443	xmlSchemaPMissingAttrErr(ctxt,
9444	    XML_SCHEMAP_S4S_ATTR_MISSING,
9445	    NULL, node,
9446	    "name", NULL);
9447	return (NULL);
9448    } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9449	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9450	return (NULL);
9451    }
9452    item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9453	ctxt->targetNamespace, node);
9454    if (item == NULL)
9455	return (NULL);
9456    /*
9457    * Check for illegal attributes.
9458    */
9459    attr = node->properties;
9460    while (attr != NULL) {
9461	if (attr->ns == NULL) {
9462	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9463		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9464		xmlSchemaPIllegalAttrErr(ctxt,
9465		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9466	    }
9467	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9468	    xmlSchemaPIllegalAttrErr(ctxt,
9469		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9470	}
9471	attr = attr->next;
9472    }
9473    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9474    /*
9475    * And now for the children...
9476    */
9477    child = node->children;
9478    if (IS_SCHEMA(child, "annotation")) {
9479	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9480	child = child->next;
9481    }
9482    if (IS_SCHEMA(child, "all")) {
9483	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9484	    XML_SCHEMA_TYPE_ALL, 0);
9485	child = child->next;
9486    } else if (IS_SCHEMA(child, "choice")) {
9487	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9488	    XML_SCHEMA_TYPE_CHOICE, 0);
9489	child = child->next;
9490    } else if (IS_SCHEMA(child, "sequence")) {
9491	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9492	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9493	child = child->next;
9494    }
9495
9496
9497
9498    if (child != NULL) {
9499	xmlSchemaPContentErr(ctxt,
9500	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9501	    NULL, node, child, NULL,
9502	    "(annotation?, (all | choice | sequence)?)");
9503    }
9504    return (item);
9505}
9506
9507/**
9508 * xmlSchemaCleanupDoc:
9509 * @ctxt:  a schema validation context
9510 * @node:  the root of the document.
9511 *
9512 * removes unwanted nodes in a schemas document tree
9513 */
9514static void
9515xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9516{
9517    xmlNodePtr delete, cur;
9518
9519    if ((ctxt == NULL) || (root == NULL)) return;
9520
9521    /*
9522     * Remove all the blank text nodes
9523     */
9524    delete = NULL;
9525    cur = root;
9526    while (cur != NULL) {
9527        if (delete != NULL) {
9528            xmlUnlinkNode(delete);
9529            xmlFreeNode(delete);
9530            delete = NULL;
9531        }
9532        if (cur->type == XML_TEXT_NODE) {
9533            if (IS_BLANK_NODE(cur)) {
9534                if (xmlNodeGetSpacePreserve(cur) != 1) {
9535                    delete = cur;
9536                }
9537            }
9538        } else if ((cur->type != XML_ELEMENT_NODE) &&
9539                   (cur->type != XML_CDATA_SECTION_NODE)) {
9540            delete = cur;
9541            goto skip_children;
9542        }
9543
9544        /*
9545         * Skip to next node
9546         */
9547        if (cur->children != NULL) {
9548            if ((cur->children->type != XML_ENTITY_DECL) &&
9549                (cur->children->type != XML_ENTITY_REF_NODE) &&
9550                (cur->children->type != XML_ENTITY_NODE)) {
9551                cur = cur->children;
9552                continue;
9553            }
9554        }
9555      skip_children:
9556        if (cur->next != NULL) {
9557            cur = cur->next;
9558            continue;
9559        }
9560
9561        do {
9562            cur = cur->parent;
9563            if (cur == NULL)
9564                break;
9565            if (cur == root) {
9566                cur = NULL;
9567                break;
9568            }
9569            if (cur->next != NULL) {
9570                cur = cur->next;
9571                break;
9572            }
9573        } while (cur != NULL);
9574    }
9575    if (delete != NULL) {
9576        xmlUnlinkNode(delete);
9577        xmlFreeNode(delete);
9578        delete = NULL;
9579    }
9580}
9581
9582
9583static void
9584xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9585{
9586    if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9587	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9588
9589    if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9590	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9591
9592    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9593	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9594    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9595	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9596    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9597	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9598    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9599	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9600
9601    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9602	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9603    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9604	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9605    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9606	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9607}
9608
9609static int
9610xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9611			     xmlSchemaPtr schema,
9612			     xmlNodePtr node)
9613{
9614    xmlAttrPtr attr;
9615    const xmlChar *val;
9616    int res = 0, oldErrs = ctxt->nberrors;
9617
9618    /*
9619    * Those flags should be moved to the parser context flags,
9620    * since they are not visible at the component level. I.e.
9621    * they are used if processing schema *documents* only.
9622    */
9623    res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9624    HFAILURE;
9625
9626    /*
9627    * Since the version is of type xs:token, we won't bother to
9628    * check it.
9629    */
9630    /* REMOVED:
9631    attr = xmlSchemaGetPropNode(node, "version");
9632    if (attr != NULL) {
9633	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9634	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9635	HFAILURE;
9636    }
9637    */
9638    attr = xmlSchemaGetPropNode(node, "targetNamespace");
9639    if (attr != NULL) {
9640	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9641	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9642	HFAILURE;
9643	if (res != 0) {
9644	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9645	    goto exit;
9646	}
9647    }
9648    attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9649    if (attr != NULL) {
9650	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9651	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9652	    XML_SCHEMAS_QUALIF_ELEM);
9653	HFAILURE;
9654	if (res != 0) {
9655	    xmlSchemaPSimpleTypeErr(ctxt,
9656		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9657		NULL, (xmlNodePtr) attr, NULL,
9658		"(qualified | unqualified)", val, NULL, NULL, NULL);
9659	}
9660    }
9661    attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9662    if (attr != NULL) {
9663	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9664	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9665	    XML_SCHEMAS_QUALIF_ATTR);
9666	HFAILURE;
9667	if (res != 0) {
9668	    xmlSchemaPSimpleTypeErr(ctxt,
9669		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9670		NULL, (xmlNodePtr) attr, NULL,
9671		"(qualified | unqualified)", val, NULL, NULL, NULL);
9672	}
9673    }
9674    attr = xmlSchemaGetPropNode(node, "finalDefault");
9675    if (attr != NULL) {
9676	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9677	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9678	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9679	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9680	    -1,
9681	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9682	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9683	HFAILURE;
9684	if (res != 0) {
9685	    xmlSchemaPSimpleTypeErr(ctxt,
9686		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9687		NULL, (xmlNodePtr) attr, NULL,
9688		"(#all | List of (extension | restriction | list | union))",
9689		val, NULL, NULL, NULL);
9690	}
9691    }
9692    attr = xmlSchemaGetPropNode(node, "blockDefault");
9693    if (attr != NULL) {
9694	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9695	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9696	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9697	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9698	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9699	HFAILURE;
9700	if (res != 0) {
9701	    xmlSchemaPSimpleTypeErr(ctxt,
9702		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9703		NULL, (xmlNodePtr) attr, NULL,
9704		"(#all | List of (extension | restriction | substitution))",
9705		val, NULL, NULL, NULL);
9706	}
9707    }
9708
9709exit:
9710    if (oldErrs != ctxt->nberrors)
9711	res = ctxt->err;
9712    return(res);
9713exit_failure:
9714    return(-1);
9715}
9716
9717/**
9718 * xmlSchemaParseSchemaTopLevel:
9719 * @ctxt:  a schema validation context
9720 * @schema:  the schemas
9721 * @nodes:  the list of top level nodes
9722 *
9723 * Returns the internal XML Schema structure built from the resource or
9724 *         NULL in case of error
9725 */
9726static int
9727xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9728                             xmlSchemaPtr schema, xmlNodePtr nodes)
9729{
9730    xmlNodePtr child;
9731    xmlSchemaAnnotPtr annot;
9732    int res = 0, oldErrs, tmpOldErrs;
9733
9734    if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9735        return(-1);
9736
9737    oldErrs = ctxt->nberrors;
9738    child = nodes;
9739    while ((IS_SCHEMA(child, "include")) ||
9740	   (IS_SCHEMA(child, "import")) ||
9741	   (IS_SCHEMA(child, "redefine")) ||
9742	   (IS_SCHEMA(child, "annotation"))) {
9743	if (IS_SCHEMA(child, "annotation")) {
9744	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9745	    if (schema->annot == NULL)
9746		schema->annot = annot;
9747	    else
9748		xmlSchemaFreeAnnot(annot);
9749	} else if (IS_SCHEMA(child, "import")) {
9750	    tmpOldErrs = ctxt->nberrors;
9751	    res = xmlSchemaParseImport(ctxt, schema, child);
9752	    HFAILURE;
9753	    HSTOP(ctxt);
9754	    if (tmpOldErrs != ctxt->nberrors)
9755		goto exit;
9756	} else if (IS_SCHEMA(child, "include")) {
9757	    tmpOldErrs = ctxt->nberrors;
9758	    res = xmlSchemaParseInclude(ctxt, schema, child);
9759	    HFAILURE;
9760	    HSTOP(ctxt);
9761	    if (tmpOldErrs != ctxt->nberrors)
9762		goto exit;
9763	} else if (IS_SCHEMA(child, "redefine")) {
9764	    tmpOldErrs = ctxt->nberrors;
9765	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9766	    HFAILURE;
9767	    HSTOP(ctxt);
9768	    if (tmpOldErrs != ctxt->nberrors)
9769		goto exit;
9770	}
9771	child = child->next;
9772    }
9773    /*
9774    * URGENT TODO: Change the functions to return int results.
9775    * We need especially to catch internal errors.
9776    */
9777    while (child != NULL) {
9778	if (IS_SCHEMA(child, "complexType")) {
9779	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9780	    child = child->next;
9781	} else if (IS_SCHEMA(child, "simpleType")) {
9782	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9783	    child = child->next;
9784	} else if (IS_SCHEMA(child, "element")) {
9785	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9786	    child = child->next;
9787	} else if (IS_SCHEMA(child, "attribute")) {
9788	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9789	    child = child->next;
9790	} else if (IS_SCHEMA(child, "attributeGroup")) {
9791	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9792	    child = child->next;
9793	} else if (IS_SCHEMA(child, "group")) {
9794	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9795	    child = child->next;
9796	} else if (IS_SCHEMA(child, "notation")) {
9797	    xmlSchemaParseNotation(ctxt, schema, child);
9798	    child = child->next;
9799	} else {
9800	    xmlSchemaPContentErr(ctxt,
9801		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9802		NULL, child->parent, child,
9803		NULL, "((include | import | redefine | annotation)*, "
9804		"(((simpleType | complexType | group | attributeGroup) "
9805		"| element | attribute | notation), annotation*)*)");
9806	    child = child->next;
9807	}
9808	while (IS_SCHEMA(child, "annotation")) {
9809	    /*
9810	    * TODO: We should add all annotations.
9811	    */
9812	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9813	    if (schema->annot == NULL)
9814		schema->annot = annot;
9815	    else
9816		xmlSchemaFreeAnnot(annot);
9817	    child = child->next;
9818	}
9819    }
9820exit:
9821    ctxt->ctxtType = NULL;
9822    if (oldErrs != ctxt->nberrors)
9823	res = ctxt->err;
9824    return(res);
9825exit_failure:
9826    return(-1);
9827}
9828
9829static xmlSchemaSchemaRelationPtr
9830xmlSchemaSchemaRelationCreate(void)
9831{
9832    xmlSchemaSchemaRelationPtr ret;
9833
9834    ret = (xmlSchemaSchemaRelationPtr)
9835	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9836    if (ret == NULL) {
9837	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9838	return(NULL);
9839    }
9840    memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9841    return(ret);
9842}
9843
9844#if 0
9845static void
9846xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9847{
9848    xmlFree(rel);
9849}
9850#endif
9851
9852static void
9853xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9854{
9855    xmlSchemaRedefPtr prev;
9856
9857    while (redef != NULL) {
9858	prev = redef;
9859	redef = redef->next;
9860	xmlFree(prev);
9861    }
9862}
9863
9864static void
9865xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9866{
9867    /*
9868    * After the construction context has been freed, there will be
9869    * no schema graph available any more. Only the schema buckets
9870    * will stay alive, which are put into the "schemasImports" and
9871    * "includes" slots of the xmlSchema.
9872    */
9873    if (con->buckets != NULL)
9874	xmlSchemaItemListFree(con->buckets);
9875    if (con->pending != NULL)
9876	xmlSchemaItemListFree(con->pending);
9877    if (con->substGroups != NULL)
9878	xmlHashFree(con->substGroups,
9879	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9880    if (con->redefs != NULL)
9881	xmlSchemaRedefListFree(con->redefs);
9882    if (con->dict != NULL)
9883	xmlDictFree(con->dict);
9884    xmlFree(con);
9885}
9886
9887static xmlSchemaConstructionCtxtPtr
9888xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9889{
9890    xmlSchemaConstructionCtxtPtr ret;
9891
9892    ret = (xmlSchemaConstructionCtxtPtr)
9893	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9894    if (ret == NULL) {
9895        xmlSchemaPErrMemory(NULL,
9896	    "allocating schema construction context", NULL);
9897        return (NULL);
9898    }
9899    memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9900
9901    ret->buckets = xmlSchemaItemListCreate();
9902    if (ret->buckets == NULL) {
9903	xmlSchemaPErrMemory(NULL,
9904	    "allocating list of schema buckets", NULL);
9905	xmlFree(ret);
9906        return (NULL);
9907    }
9908    ret->pending = xmlSchemaItemListCreate();
9909    if (ret->pending == NULL) {
9910	xmlSchemaPErrMemory(NULL,
9911	    "allocating list of pending global components", NULL);
9912	xmlSchemaConstructionCtxtFree(ret);
9913        return (NULL);
9914    }
9915    ret->dict = dict;
9916    xmlDictReference(dict);
9917    return(ret);
9918}
9919
9920static xmlSchemaParserCtxtPtr
9921xmlSchemaParserCtxtCreate(void)
9922{
9923    xmlSchemaParserCtxtPtr ret;
9924
9925    ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9926    if (ret == NULL) {
9927        xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9928                            NULL);
9929        return (NULL);
9930    }
9931    memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9932    ret->type = XML_SCHEMA_CTXT_PARSER;
9933    ret->attrProhibs = xmlSchemaItemListCreate();
9934    if (ret->attrProhibs == NULL) {
9935	xmlFree(ret);
9936	return(NULL);
9937    }
9938    return(ret);
9939}
9940
9941/**
9942 * xmlSchemaNewParserCtxtUseDict:
9943 * @URL:  the location of the schema
9944 * @dict: the dictionary to be used
9945 *
9946 * Create an XML Schemas parse context for that file/resource expected
9947 * to contain an XML Schemas file.
9948 *
9949 * Returns the parser context or NULL in case of error
9950 */
9951static xmlSchemaParserCtxtPtr
9952xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9953{
9954    xmlSchemaParserCtxtPtr ret;
9955
9956    ret = xmlSchemaParserCtxtCreate();
9957    if (ret == NULL)
9958        return (NULL);
9959    ret->dict = dict;
9960    xmlDictReference(dict);
9961    if (URL != NULL)
9962	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9963    return (ret);
9964}
9965
9966static int
9967xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9968{
9969    if (vctxt->pctxt == NULL) {
9970        if (vctxt->schema != NULL)
9971	    vctxt->pctxt =
9972		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9973	else
9974	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9975	if (vctxt->pctxt == NULL) {
9976	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9977		"failed to create a temp. parser context");
9978	    return (-1);
9979	}
9980	/* TODO: Pass user data. */
9981	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9982	    vctxt->warning, vctxt->errCtxt);
9983	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9984	    vctxt->errCtxt);
9985    }
9986    return (0);
9987}
9988
9989/**
9990 * xmlSchemaGetSchemaBucket:
9991 * @pctxt: the schema parser context
9992 * @schemaLocation: the URI of the schema document
9993 *
9994 * Returns a schema bucket if it was already parsed.
9995 *
9996 * Returns a schema bucket if it was already parsed from
9997 *         @schemaLocation, NULL otherwise.
9998 */
9999static xmlSchemaBucketPtr
10000xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10001			    const xmlChar *schemaLocation)
10002{
10003    xmlSchemaBucketPtr cur;
10004    xmlSchemaItemListPtr list;
10005
10006    list = pctxt->constructor->buckets;
10007    if (list->nbItems == 0)
10008	return(NULL);
10009    else {
10010	int i;
10011	for (i = 0; i < list->nbItems; i++) {
10012	    cur = (xmlSchemaBucketPtr) list->items[i];
10013	    /* Pointer comparison! */
10014	    if (cur->schemaLocation == schemaLocation)
10015		return(cur);
10016	}
10017    }
10018    return(NULL);
10019}
10020
10021static xmlSchemaBucketPtr
10022xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10023				     const xmlChar *schemaLocation,
10024				     const xmlChar *targetNamespace)
10025{
10026    xmlSchemaBucketPtr cur;
10027    xmlSchemaItemListPtr list;
10028
10029    list = pctxt->constructor->buckets;
10030    if (list->nbItems == 0)
10031	return(NULL);
10032    else {
10033	int i;
10034	for (i = 0; i < list->nbItems; i++) {
10035	    cur = (xmlSchemaBucketPtr) list->items[i];
10036	    /* Pointer comparison! */
10037	    if ((cur->origTargetNamespace == NULL) &&
10038		(cur->schemaLocation == schemaLocation) &&
10039		(cur->targetNamespace == targetNamespace))
10040		return(cur);
10041	}
10042    }
10043    return(NULL);
10044}
10045
10046
10047#define IS_BAD_SCHEMA_DOC(b) \
10048    (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10049
10050static xmlSchemaBucketPtr
10051xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10052				 const xmlChar *targetNamespace,
10053				 int imported)
10054{
10055    xmlSchemaBucketPtr cur;
10056    xmlSchemaItemListPtr list;
10057
10058    list = pctxt->constructor->buckets;
10059    if (list->nbItems == 0)
10060	return(NULL);
10061    else {
10062	int i;
10063	for (i = 0; i < list->nbItems; i++) {
10064	    cur = (xmlSchemaBucketPtr) list->items[i];
10065	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10066		(cur->origTargetNamespace == targetNamespace) &&
10067		((imported && cur->imported) ||
10068		 ((!imported) && (!cur->imported))))
10069		return(cur);
10070	}
10071    }
10072    return(NULL);
10073}
10074
10075static int
10076xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10077		     xmlSchemaPtr schema,
10078		     xmlSchemaBucketPtr bucket)
10079{
10080    int oldFlags;
10081    xmlDocPtr oldDoc;
10082    xmlNodePtr node;
10083    int ret, oldErrs;
10084    xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10085
10086    /*
10087    * Save old values; reset the *main* schema.
10088    * URGENT TODO: This is not good; move the per-document information
10089    * to the parser. Get rid of passing the main schema to the
10090    * parsing functions.
10091    */
10092    oldFlags = schema->flags;
10093    oldDoc = schema->doc;
10094    if (schema->flags != 0)
10095	xmlSchemaClearSchemaDefaults(schema);
10096    schema->doc = bucket->doc;
10097    pctxt->schema = schema;
10098    /*
10099    * Keep the current target namespace on the parser *not* on the
10100    * main schema.
10101    */
10102    pctxt->targetNamespace = bucket->targetNamespace;
10103    WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10104
10105    if ((bucket->targetNamespace != NULL) &&
10106	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10107	/*
10108	* We are parsing the schema for schemas!
10109	*/
10110	pctxt->isS4S = 1;
10111    }
10112    /* Mark it as parsed, even if parsing fails. */
10113    bucket->parsed++;
10114    /* Compile the schema doc. */
10115    node = xmlDocGetRootElement(bucket->doc);
10116    ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10117    if (ret != 0)
10118	goto exit;
10119    /* An empty schema; just get out. */
10120    if (node->children == NULL)
10121	goto exit;
10122    oldErrs = pctxt->nberrors;
10123    ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10124    if (ret != 0)
10125	goto exit;
10126    /*
10127    * TODO: Not nice, but I'm not 100% sure we will get always an error
10128    * as a result of the obove functions; so better rely on pctxt->err
10129    * as well.
10130    */
10131    if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10132	ret = pctxt->err;
10133	goto exit;
10134    }
10135
10136exit:
10137    WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10138    /* Restore schema values. */
10139    schema->doc = oldDoc;
10140    schema->flags = oldFlags;
10141    return(ret);
10142}
10143
10144static int
10145xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10146		     xmlSchemaPtr schema,
10147		     xmlSchemaBucketPtr bucket)
10148{
10149    xmlSchemaParserCtxtPtr newpctxt;
10150    int res = 0;
10151
10152    if (bucket == NULL)
10153	return(0);
10154    if (bucket->parsed) {
10155	PERROR_INT("xmlSchemaParseNewDoc",
10156	    "reparsing a schema doc");
10157	return(-1);
10158    }
10159    if (bucket->doc == NULL) {
10160	PERROR_INT("xmlSchemaParseNewDoc",
10161	    "parsing a schema doc, but there's no doc");
10162	return(-1);
10163    }
10164    if (pctxt->constructor == NULL) {
10165	PERROR_INT("xmlSchemaParseNewDoc",
10166	    "no constructor");
10167	return(-1);
10168    }
10169    /* Create and init the temporary parser context. */
10170    newpctxt = xmlSchemaNewParserCtxtUseDict(
10171	(const char *) bucket->schemaLocation, pctxt->dict);
10172    if (newpctxt == NULL)
10173	return(-1);
10174    newpctxt->constructor = pctxt->constructor;
10175    /*
10176    * TODO: Can we avoid that the parser knows about the main schema?
10177    * It would be better if he knows about the current schema bucket
10178    * only.
10179    */
10180    newpctxt->schema = schema;
10181    xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10182	pctxt->errCtxt);
10183    xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10184	pctxt->errCtxt);
10185    newpctxt->counter = pctxt->counter;
10186
10187
10188    res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10189
10190    /* Channel back errors and cleanup the temporary parser context. */
10191    if (res != 0)
10192	pctxt->err = res;
10193    pctxt->nberrors += newpctxt->nberrors;
10194    pctxt->counter = newpctxt->counter;
10195    newpctxt->constructor = NULL;
10196    /* Free the parser context. */
10197    xmlSchemaFreeParserCtxt(newpctxt);
10198    return(res);
10199}
10200
10201static void
10202xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10203				xmlSchemaSchemaRelationPtr rel)
10204{
10205    xmlSchemaSchemaRelationPtr cur = bucket->relations;
10206
10207    if (cur == NULL) {
10208	bucket->relations = rel;
10209	return;
10210    }
10211    while (cur->next != NULL)
10212	cur = cur->next;
10213    cur->next = rel;
10214}
10215
10216
10217static const xmlChar *
10218xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10219			  xmlNodePtr ctxtNode)
10220{
10221    /*
10222    * Build an absolue location URI.
10223    */
10224    if (location != NULL) {
10225	if (ctxtNode == NULL)
10226	    return(location);
10227	else {
10228	    xmlChar *base, *URI;
10229	    const xmlChar *ret = NULL;
10230
10231	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10232	    if (base == NULL) {
10233		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10234	    } else {
10235		URI = xmlBuildURI(location, base);
10236		xmlFree(base);
10237	    }
10238	    if (URI != NULL) {
10239		ret = xmlDictLookup(dict, URI, -1);
10240		xmlFree(URI);
10241		return(ret);
10242	    }
10243	}
10244    }
10245    return(NULL);
10246}
10247
10248
10249
10250/**
10251 * xmlSchemaAddSchemaDoc:
10252 * @pctxt:  a schema validation context
10253 * @schema:  the schema being built
10254 * @node:  a subtree containing XML Schema informations
10255 *
10256 * Parse an included (and to-be-redefined) XML schema document.
10257 *
10258 * Returns 0 on success, a positive error code on errors and
10259 *         -1 in case of an internal or API error.
10260 */
10261
10262static int
10263xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10264		int type, /* import or include or redefine */
10265		const xmlChar *schemaLocation,
10266		xmlDocPtr schemaDoc,
10267		const char *schemaBuffer,
10268		int schemaBufferLen,
10269		xmlNodePtr invokingNode,
10270		const xmlChar *sourceTargetNamespace,
10271		const xmlChar *importNamespace,
10272		xmlSchemaBucketPtr *bucket)
10273{
10274    const xmlChar *targetNamespace = NULL;
10275    xmlSchemaSchemaRelationPtr relation = NULL;
10276    xmlDocPtr doc = NULL;
10277    int res = 0, err = 0, located = 0, preserveDoc = 0;
10278    xmlSchemaBucketPtr bkt = NULL;
10279
10280    if (bucket != NULL)
10281	*bucket = NULL;
10282
10283    switch (type) {
10284	case XML_SCHEMA_SCHEMA_IMPORT:
10285	case XML_SCHEMA_SCHEMA_MAIN:
10286	    err = XML_SCHEMAP_SRC_IMPORT;
10287	    break;
10288	case XML_SCHEMA_SCHEMA_INCLUDE:
10289	    err = XML_SCHEMAP_SRC_INCLUDE;
10290	    break;
10291	case XML_SCHEMA_SCHEMA_REDEFINE:
10292	    err = XML_SCHEMAP_SRC_REDEFINE;
10293	    break;
10294    }
10295
10296
10297    /* Special handling for the main schema:
10298    * skip the location and relation logic and just parse the doc.
10299    * We need just a bucket to be returned in this case.
10300    */
10301    if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10302	goto doc_load;
10303
10304    /* Note that we expect the location to be an absulute URI. */
10305    if (schemaLocation != NULL) {
10306	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10307	if ((bkt != NULL) &&
10308	    (pctxt->constructor->bucket == bkt)) {
10309	    /* Report self-imports/inclusions/redefinitions. */
10310
10311	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10312		invokingNode, NULL,
10313		"The schema must not import/include/redefine itself",
10314		NULL, NULL);
10315	    goto exit;
10316	}
10317    }
10318    /*
10319    * Create a relation for the graph of schemas.
10320    */
10321    relation = xmlSchemaSchemaRelationCreate();
10322    if (relation == NULL)
10323	return(-1);
10324    xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10325	relation);
10326    relation->type = type;
10327
10328    /*
10329    * Save the namespace import information.
10330    */
10331    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10332	relation->importNamespace = importNamespace;
10333	if (schemaLocation == NULL) {
10334	    /*
10335	    * No location; this is just an import of the namespace.
10336	    * Note that we don't assign a bucket to the relation
10337	    * in this case.
10338	    */
10339	    goto exit;
10340	}
10341	targetNamespace = importNamespace;
10342    }
10343
10344    /* Did we already fetch the doc? */
10345    if (bkt != NULL) {
10346	/* TODO: The following nasty cases will produce an error. */
10347	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10348	    /* We included/redefined and then try to import a schema. */
10349	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10350		invokingNode, NULL,
10351		"The schema document '%s' cannot be imported, since "
10352		"it was already included or redefined",
10353		schemaLocation, NULL);
10354	    goto exit;
10355	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10356	    /* We imported and then try to include/redefine a schema. */
10357	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10358		invokingNode, NULL,
10359		"The schema document '%s' cannot be included or "
10360		"redefined, since it was already imported",
10361		schemaLocation, NULL);
10362	    goto exit;
10363	}
10364    }
10365
10366    if (WXS_IS_BUCKET_IMPMAIN(type)) {
10367	/*
10368	* Given that the schemaLocation [attribute] is only a hint, it is open
10369	* to applications to ignore all but the first <import> for a given
10370	* namespace, regardless of the �actual value� of schemaLocation, but
10371	* such a strategy risks missing useful information when new
10372	* schemaLocations are offered.
10373	*
10374	* We will use the first <import> that comes with a location.
10375	* Further <import>s *with* a location, will result in an error.
10376	* TODO: Better would be to just report a warning here, but
10377	* we'll try it this way until someone complains.
10378	*
10379	* Schema Document Location Strategy:
10380	* 3 Based on the namespace name, identify an existing schema document,
10381	* either as a resource which is an XML document or a <schema> element
10382	* information item, in some local schema repository;
10383	* 5 Attempt to resolve the namespace name to locate such a resource.
10384	*
10385	* NOTE: (3) and (5) are not supported.
10386	*/
10387	if (bkt != NULL) {
10388	    relation->bucket = bkt;
10389	    goto exit;
10390	}
10391	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10392	    importNamespace, 1);
10393
10394	if (bkt != NULL) {
10395	    relation->bucket = bkt;
10396	    if (bkt->schemaLocation == NULL) {
10397		/* First given location of the schema; load the doc. */
10398		bkt->schemaLocation = schemaLocation;
10399	    } else {
10400		if (!xmlStrEqual(schemaLocation,
10401		    bkt->schemaLocation)) {
10402		    /*
10403		    * Additional location given; just skip it.
10404		    * URGENT TODO: We should report a warning here.
10405		    * res = XML_SCHEMAP_SRC_IMPORT;
10406		    */
10407		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10408			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10409			invokingNode, NULL,
10410			"Skipping import of schema located at '%s' for the "
10411			"namespace '%s', since this namespace was already "
10412			"imported with the schema located at '%s'",
10413			schemaLocation, importNamespace, bkt->schemaLocation);
10414		}
10415		goto exit;
10416	    }
10417	}
10418	/*
10419	* No bucket + first location: load the doc and create a
10420	* bucket.
10421	*/
10422    } else {
10423	/* <include> and <redefine> */
10424	if (bkt != NULL) {
10425
10426	    if ((bkt->origTargetNamespace == NULL) &&
10427		(bkt->targetNamespace != sourceTargetNamespace)) {
10428		xmlSchemaBucketPtr chamel;
10429
10430		/*
10431		* Chameleon include/redefine: skip loading only if it was
10432		* aleady build for the targetNamespace of the including
10433		* schema.
10434		*/
10435		/*
10436		* URGENT TODO: If the schema is a chameleon-include then copy
10437		* the components into the including schema and modify the
10438		* targetNamespace of those components, do nothing otherwise.
10439		* NOTE: This is currently worked-around by compiling the
10440		* chameleon for every destinct including targetNamespace; thus
10441		* not performant at the moment.
10442		* TODO: Check when the namespace in wildcards for chameleons
10443		* needs to be converted: before we built wildcard intersections
10444		* or after.
10445		*   Answer: after!
10446		*/
10447		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10448		    schemaLocation, sourceTargetNamespace);
10449		if (chamel != NULL) {
10450		    /* A fitting chameleon was already parsed; NOP. */
10451		    relation->bucket = chamel;
10452		    goto exit;
10453		}
10454		/*
10455		* We need to parse the chameleon again for a different
10456		* targetNamespace.
10457		* CHAMELEON TODO: Optimize this by only parsing the
10458		* chameleon once, and then copying the components to
10459		* the new targetNamespace.
10460		*/
10461		bkt = NULL;
10462	    } else {
10463		relation->bucket = bkt;
10464		goto exit;
10465	    }
10466	}
10467    }
10468    if ((bkt != NULL) && (bkt->doc != NULL)) {
10469	PERROR_INT("xmlSchemaAddSchemaDoc",
10470	    "trying to load a schema doc, but a doc is already "
10471	    "assigned to the schema bucket");
10472	goto exit_failure;
10473    }
10474
10475doc_load:
10476    /*
10477    * Load the document.
10478    */
10479    if (schemaDoc != NULL) {
10480	doc = schemaDoc;
10481	/* Don' free this one, since it was provided by the caller. */
10482	preserveDoc = 1;
10483	/* TODO: Does the context or the doc hold the location? */
10484	if (schemaDoc->URL != NULL)
10485	    schemaLocation = xmlDictLookup(pctxt->dict,
10486		schemaDoc->URL, -1);
10487
10488    } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10489	xmlParserCtxtPtr parserCtxt;
10490
10491	parserCtxt = xmlNewParserCtxt();
10492	if (parserCtxt == NULL) {
10493	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10494		"allocating a parser context", NULL);
10495	    goto exit_failure;
10496	}
10497	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10498	    /*
10499	    * TODO: Do we have to burden the schema parser dict with all
10500	    * the content of the schema doc?
10501	    */
10502	    xmlDictFree(parserCtxt->dict);
10503	    parserCtxt->dict = pctxt->dict;
10504	    xmlDictReference(parserCtxt->dict);
10505	}
10506	if (schemaLocation != NULL) {
10507	    /* Parse from file. */
10508	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10509		NULL, SCHEMAS_PARSE_OPTIONS);
10510	} else if (schemaBuffer != NULL) {
10511	    /* Parse from memory buffer. */
10512	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10513		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10514	    schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10515	    if (doc != NULL)
10516		doc->URL = schemaLocation;
10517	}
10518	/*
10519	* For <import>:
10520	* 2.1 The referent is (a fragment of) a resource which is an
10521	* XML document (see clause 1.1), which in turn corresponds to
10522	* a <schema> element information item in a well-formed information
10523	* set, which in turn corresponds to a valid schema.
10524	* TODO: (2.1) fragments of XML documents are not supported.
10525	*
10526	* 2.2 The referent is a <schema> element information item in
10527	* a well-formed information set, which in turn corresponds
10528	* to a valid schema.
10529	* TODO: (2.2) is not supported.
10530	*/
10531	if (doc == NULL) {
10532	    xmlErrorPtr lerr;
10533	    lerr = xmlGetLastError();
10534	    /*
10535	    * Check if this a parser error, or if the document could
10536	    * just not be located.
10537	    * TODO: Try to find specific error codes to react only on
10538	    * localisation failures.
10539	    */
10540	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10541		/*
10542		* We assume a parser error here.
10543		*/
10544		located = 1;
10545		/* TODO: Error code ?? */
10546		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10547		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10548		    invokingNode, NULL,
10549		    "Failed to parse the XML resource '%s'",
10550		    schemaLocation, NULL);
10551	    }
10552	}
10553	xmlFreeParserCtxt(parserCtxt);
10554	if ((doc == NULL) && located)
10555	    goto exit_error;
10556    } else {
10557	xmlSchemaPErr(pctxt, NULL,
10558	    XML_SCHEMAP_NOTHING_TO_PARSE,
10559	    "No information for parsing was provided with the "
10560	    "given schema parser context.\n",
10561	    NULL, NULL);
10562	goto exit_failure;
10563    }
10564    /*
10565    * Preprocess the document.
10566    */
10567    if (doc != NULL) {
10568	xmlNodePtr docElem = NULL;
10569
10570	located = 1;
10571	docElem = xmlDocGetRootElement(doc);
10572	if (docElem == NULL) {
10573	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10574		invokingNode, NULL,
10575		"The document '%s' has no document element",
10576		schemaLocation, NULL);
10577	    goto exit_error;
10578	}
10579	/*
10580	* Remove all the blank text nodes.
10581	*/
10582	xmlSchemaCleanupDoc(pctxt, docElem);
10583	/*
10584	* Check the schema's top level element.
10585	*/
10586	if (!IS_SCHEMA(docElem, "schema")) {
10587	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10588		invokingNode, NULL,
10589		"The XML document '%s' is not a schema document",
10590		schemaLocation, NULL);
10591	    goto exit_error;
10592	}
10593	/*
10594	* Note that we don't apply a type check for the
10595	* targetNamespace value here.
10596	*/
10597	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10598	    "targetNamespace");
10599    }
10600
10601/* after_doc_loading: */
10602    if ((bkt == NULL) && located) {
10603	/* Only create a bucket if the schema was located. */
10604        bkt = xmlSchemaBucketCreate(pctxt, type,
10605	    targetNamespace);
10606	if (bkt == NULL)
10607	    goto exit_failure;
10608    }
10609    if (bkt != NULL) {
10610	bkt->schemaLocation = schemaLocation;
10611	bkt->located = located;
10612	if (doc != NULL) {
10613	    bkt->doc = doc;
10614	    bkt->targetNamespace = targetNamespace;
10615	    bkt->origTargetNamespace = targetNamespace;
10616	    if (preserveDoc)
10617		bkt->preserveDoc = 1;
10618	}
10619	if (WXS_IS_BUCKET_IMPMAIN(type))
10620	    bkt->imported++;
10621	    /*
10622	    * Add it to the graph of schemas.
10623	    */
10624	if (relation != NULL)
10625	    relation->bucket = bkt;
10626    }
10627
10628exit:
10629    /*
10630    * Return the bucket explicitely; this is needed for the
10631    * main schema.
10632    */
10633    if (bucket != NULL)
10634	*bucket = bkt;
10635    return (0);
10636
10637exit_error:
10638    if ((doc != NULL) && (! preserveDoc)) {
10639	xmlFreeDoc(doc);
10640	if (bkt != NULL)
10641	    bkt->doc = NULL;
10642    }
10643    return(pctxt->err);
10644
10645exit_failure:
10646    if ((doc != NULL) && (! preserveDoc)) {
10647	xmlFreeDoc(doc);
10648	if (bkt != NULL)
10649	    bkt->doc = NULL;
10650    }
10651    return (-1);
10652}
10653
10654/**
10655 * xmlSchemaParseImport:
10656 * @ctxt:  a schema validation context
10657 * @schema:  the schema being built
10658 * @node:  a subtree containing XML Schema informations
10659 *
10660 * parse a XML schema Import definition
10661 * *WARNING* this interface is highly subject to change
10662 *
10663 * Returns 0 in case of success, a positive error code if
10664 * not valid and -1 in case of an internal error.
10665 */
10666static int
10667xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10668                     xmlNodePtr node)
10669{
10670    xmlNodePtr child;
10671    const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10672    const xmlChar *thisTargetNamespace;
10673    xmlAttrPtr attr;
10674    int ret = 0;
10675    xmlSchemaBucketPtr bucket = NULL;
10676
10677    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10678        return (-1);
10679
10680    /*
10681    * Check for illegal attributes.
10682    */
10683    attr = node->properties;
10684    while (attr != NULL) {
10685	if (attr->ns == NULL) {
10686	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10687		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10688		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10689		xmlSchemaPIllegalAttrErr(pctxt,
10690		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10691	    }
10692	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10693	    xmlSchemaPIllegalAttrErr(pctxt,
10694		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10695	}
10696	attr = attr->next;
10697    }
10698    /*
10699    * Extract and validate attributes.
10700    */
10701    if (xmlSchemaPValAttr(pctxt, NULL, node,
10702	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10703	&namespaceName) != 0) {
10704	xmlSchemaPSimpleTypeErr(pctxt,
10705	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10706	    NULL, node,
10707	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10708	    NULL, namespaceName, NULL, NULL, NULL);
10709	return (pctxt->err);
10710    }
10711
10712    if (xmlSchemaPValAttr(pctxt, NULL, node,
10713	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10714	&schemaLocation) != 0) {
10715	xmlSchemaPSimpleTypeErr(pctxt,
10716	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10717	    NULL, node,
10718	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10719	    NULL, namespaceName, NULL, NULL, NULL);
10720	return (pctxt->err);
10721    }
10722    /*
10723    * And now for the children...
10724    */
10725    child = node->children;
10726    if (IS_SCHEMA(child, "annotation")) {
10727        /*
10728         * the annotation here is simply discarded ...
10729	 * TODO: really?
10730         */
10731        child = child->next;
10732    }
10733    if (child != NULL) {
10734	xmlSchemaPContentErr(pctxt,
10735	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10736	    NULL, node, child, NULL,
10737	    "(annotation?)");
10738    }
10739    /*
10740    * Apply additional constraints.
10741    *
10742    * Note that it is important to use the original @targetNamespace
10743    * (or none at all), to rule out imports of schemas _with_ a
10744    * @targetNamespace if the importing schema is a chameleon schema
10745    * (with no @targetNamespace).
10746    */
10747    thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10748    if (namespaceName != NULL) {
10749	/*
10750	* 1.1 If the namespace [attribute] is present, then its �actual value�
10751	* must not match the �actual value� of the enclosing <schema>'s
10752	* targetNamespace [attribute].
10753	*/
10754	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10755	    xmlSchemaPCustomErr(pctxt,
10756		XML_SCHEMAP_SRC_IMPORT_1_1,
10757		NULL, node,
10758		"The value of the attribute 'namespace' must not match "
10759		"the target namespace '%s' of the importing schema",
10760		thisTargetNamespace);
10761	    return (pctxt->err);
10762	}
10763    } else {
10764	/*
10765	* 1.2 If the namespace [attribute] is not present, then the enclosing
10766	* <schema> must have a targetNamespace [attribute].
10767	*/
10768	if (thisTargetNamespace == NULL) {
10769	    xmlSchemaPCustomErr(pctxt,
10770		XML_SCHEMAP_SRC_IMPORT_1_2,
10771		NULL, node,
10772		"The attribute 'namespace' must be existent if "
10773		"the importing schema has no target namespace",
10774		NULL);
10775	    return (pctxt->err);
10776	}
10777    }
10778    /*
10779    * Locate and acquire the schema document.
10780    */
10781    if (schemaLocation != NULL)
10782	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10783	    schemaLocation, node);
10784    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10785	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10786	namespaceName, &bucket);
10787
10788    if (ret != 0)
10789	return(ret);
10790
10791    /*
10792    * For <import>: "It is *not* an error for the application
10793    * schema reference strategy to fail."
10794    * So just don't parse if no schema document was found.
10795    * Note that we will get no bucket if the schema could not be
10796    * located or if there was no schemaLocation.
10797    */
10798    if ((bucket == NULL) && (schemaLocation != NULL)) {
10799	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10800	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10801	    node, NULL,
10802	    "Failed to locate a schema at location '%s'. "
10803	    "Skipping the import", schemaLocation, NULL, NULL);
10804    }
10805
10806    if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10807	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10808    }
10809
10810    return (ret);
10811}
10812
10813static int
10814xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10815				     xmlSchemaPtr schema,
10816				     xmlNodePtr node,
10817				     xmlChar **schemaLocation,
10818				     int type)
10819{
10820    xmlAttrPtr attr;
10821
10822    if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10823	(schemaLocation == NULL))
10824        return (-1);
10825
10826    *schemaLocation = NULL;
10827    /*
10828    * Check for illegal attributes.
10829    * Applies for both <include> and <redefine>.
10830    */
10831    attr = node->properties;
10832    while (attr != NULL) {
10833	if (attr->ns == NULL) {
10834	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10835		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10836		xmlSchemaPIllegalAttrErr(pctxt,
10837		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10838	    }
10839	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10840	    xmlSchemaPIllegalAttrErr(pctxt,
10841		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10842	}
10843	attr = attr->next;
10844    }
10845    xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10846    /*
10847    * Preliminary step, extract the URI-Reference and make an URI
10848    * from the base.
10849    */
10850    /*
10851    * Attribute "schemaLocation" is mandatory.
10852    */
10853    attr = xmlSchemaGetPropNode(node, "schemaLocation");
10854    if (attr != NULL) {
10855        xmlChar *base = NULL;
10856        xmlChar *uri = NULL;
10857
10858	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10859	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10860	    (const xmlChar **) schemaLocation) != 0)
10861	    goto exit_error;
10862	base = xmlNodeGetBase(node->doc, node);
10863	if (base == NULL) {
10864	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10865	} else {
10866	    uri = xmlBuildURI(*schemaLocation, base);
10867	    xmlFree(base);
10868	}
10869	if (uri == NULL) {
10870	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10871		"could not build an URI from the schemaLocation")
10872	    goto exit_failure;
10873	}
10874	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10875	xmlFree(uri);
10876    } else {
10877	xmlSchemaPMissingAttrErr(pctxt,
10878	    XML_SCHEMAP_S4S_ATTR_MISSING,
10879	    NULL, node, "schemaLocation", NULL);
10880	goto exit_error;
10881    }
10882    /*
10883    * Report self-inclusion and self-redefinition.
10884    */
10885    if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10886	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10887	    xmlSchemaPCustomErr(pctxt,
10888		XML_SCHEMAP_SRC_REDEFINE,
10889		NULL, node,
10890		"The schema document '%s' cannot redefine itself.",
10891		*schemaLocation);
10892	} else {
10893	    xmlSchemaPCustomErr(pctxt,
10894		XML_SCHEMAP_SRC_INCLUDE,
10895		NULL, node,
10896		"The schema document '%s' cannot include itself.",
10897		*schemaLocation);
10898	}
10899	goto exit_error;
10900    }
10901
10902    return(0);
10903exit_error:
10904    return(pctxt->err);
10905exit_failure:
10906    return(-1);
10907}
10908
10909static int
10910xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10911				xmlSchemaPtr schema,
10912				xmlNodePtr node,
10913				int type)
10914{
10915    xmlNodePtr child = NULL;
10916    const xmlChar *schemaLocation = NULL;
10917    int res = 0; /* hasRedefinitions = 0 */
10918    int isChameleon = 0, wasChameleon = 0;
10919    xmlSchemaBucketPtr bucket = NULL;
10920
10921    if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10922        return (-1);
10923
10924    /*
10925    * Parse attributes. Note that the returned schemaLocation will
10926    * be already converted to an absolute URI.
10927    */
10928    res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10929	node, (xmlChar **) (&schemaLocation), type);
10930    if (res != 0)
10931	return(res);
10932    /*
10933    * Load and add the schema document.
10934    */
10935    res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10936	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10937    if (res != 0)
10938	return(res);
10939    /*
10940    * If we get no schema bucket back, then this means that the schema
10941    * document could not be located or was broken XML or was not
10942    * a schema document.
10943    */
10944    if ((bucket == NULL) || (bucket->doc == NULL)) {
10945	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10946	    /*
10947	    * WARNING for <include>:
10948	    * We will raise an error if the schema cannot be located
10949	    * for inclusions, since the that was the feedback from the
10950	    * schema people. I.e. the following spec piece will *not* be
10951	    * satisfied:
10952	    * SPEC src-include: "It is not an error for the �actual value� of the
10953	    * schemaLocation [attribute] to fail to resolve it all, in which
10954	    * case no corresponding inclusion is performed.
10955	    * So do we need a warning report here?"
10956	    */
10957	    res = XML_SCHEMAP_SRC_INCLUDE;
10958	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10959		node, NULL,
10960		"Failed to load the document '%s' for inclusion",
10961		schemaLocation, NULL);
10962	} else {
10963	    /*
10964	    * NOTE: This was changed to raise an error even if no redefinitions
10965	    * are specified.
10966	    *
10967	    * SPEC src-redefine (1)
10968	    * "If there are any element information items among the [children]
10969	    * other than <annotation> then the �actual value� of the
10970	    * schemaLocation [attribute] must successfully resolve."
10971	    * TODO: Ask the WG if a the location has always to resolve
10972	    * here as well!
10973	    */
10974	    res = XML_SCHEMAP_SRC_REDEFINE;
10975	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10976		node, NULL,
10977		"Failed to load the document '%s' for redefinition",
10978		schemaLocation, NULL);
10979	}
10980    } else {
10981	/*
10982	* Check targetNamespace sanity before parsing the new schema.
10983	* TODO: Note that we won't check further content if the
10984	* targetNamespace was bad.
10985	*/
10986	if (bucket->origTargetNamespace != NULL) {
10987	    /*
10988	    * SPEC src-include (2.1)
10989	    * "SII has a targetNamespace [attribute], and its �actual
10990	    * value� is identical to the �actual value� of the targetNamespace
10991	    * [attribute] of SII� (which must have such an [attribute])."
10992	    */
10993	    if (pctxt->targetNamespace == NULL) {
10994		xmlSchemaCustomErr(ACTXT_CAST pctxt,
10995		    XML_SCHEMAP_SRC_INCLUDE,
10996		    node, NULL,
10997		    "The target namespace of the included/redefined schema "
10998		    "'%s' has to be absent, since the including/redefining "
10999		    "schema has no target namespace",
11000		    schemaLocation, NULL);
11001		goto exit_error;
11002	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11003		pctxt->targetNamespace)) {
11004		/* TODO: Change error function. */
11005		xmlSchemaPCustomErrExt(pctxt,
11006		    XML_SCHEMAP_SRC_INCLUDE,
11007		    NULL, node,
11008		    "The target namespace '%s' of the included/redefined "
11009		    "schema '%s' differs from '%s' of the "
11010		    "including/redefining schema",
11011		    bucket->origTargetNamespace, schemaLocation,
11012		    pctxt->targetNamespace);
11013		goto exit_error;
11014	    }
11015	} else if (pctxt->targetNamespace != NULL) {
11016	    /*
11017	    * Chameleons: the original target namespace will
11018	    * differ from the resulting namespace.
11019	    */
11020	    isChameleon = 1;
11021	    if (bucket->parsed &&
11022		(bucket->targetNamespace != pctxt->targetNamespace)) {
11023		/*
11024		* This is a sanity check, I dunno yet if this can happen.
11025		*/
11026		PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11027		    "trying to use an already parsed schema for a "
11028		    "different targetNamespace");
11029		return(-1);
11030	    }
11031	    bucket->targetNamespace = pctxt->targetNamespace;
11032	}
11033    }
11034    /*
11035    * Parse the schema.
11036    */
11037    if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11038	if (isChameleon) {
11039	    /* TODO: Get rid of this flag on the schema itself. */
11040	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11041		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11042	    } else
11043		wasChameleon = 1;
11044	}
11045	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11046	/* Restore chameleon flag. */
11047	if (isChameleon && (!wasChameleon))
11048	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11049    }
11050    /*
11051    * And now for the children...
11052    */
11053    child = node->children;
11054    if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11055	/*
11056	* Parse (simpleType | complexType | group | attributeGroup))*
11057	*/
11058	pctxt->redefined = bucket;
11059	/*
11060	* How to proceed if the redefined schema was not located?
11061	*/
11062	pctxt->isRedefine = 1;
11063	while (IS_SCHEMA(child, "annotation") ||
11064	    IS_SCHEMA(child, "simpleType") ||
11065	    IS_SCHEMA(child, "complexType") ||
11066	    IS_SCHEMA(child, "group") ||
11067	    IS_SCHEMA(child, "attributeGroup")) {
11068	    if (IS_SCHEMA(child, "annotation")) {
11069		/*
11070		* TODO: discard or not?
11071		*/
11072	    } else if (IS_SCHEMA(child, "simpleType")) {
11073		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11074	    } else if (IS_SCHEMA(child, "complexType")) {
11075		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11076		/* hasRedefinitions = 1; */
11077	    } else if (IS_SCHEMA(child, "group")) {
11078		/* hasRedefinitions = 1; */
11079		xmlSchemaParseModelGroupDefinition(pctxt,
11080		    schema, child);
11081	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11082		/* hasRedefinitions = 1; */
11083		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11084		    child);
11085	    }
11086	    child = child->next;
11087	}
11088	pctxt->redefined = NULL;
11089	pctxt->isRedefine = 0;
11090    } else {
11091	if (IS_SCHEMA(child, "annotation")) {
11092	    /*
11093	    * TODO: discard or not?
11094	    */
11095	    child = child->next;
11096	}
11097    }
11098    if (child != NULL) {
11099	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11100	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11101	    xmlSchemaPContentErr(pctxt, res,
11102		NULL, node, child, NULL,
11103		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11104	} else {
11105	     xmlSchemaPContentErr(pctxt, res,
11106		NULL, node, child, NULL,
11107		"(annotation?)");
11108	}
11109    }
11110    return(res);
11111
11112exit_error:
11113    return(pctxt->err);
11114}
11115
11116static int
11117xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11118                       xmlNodePtr node)
11119{
11120    int res;
11121#ifndef ENABLE_REDEFINE
11122    TODO
11123    return(0);
11124#endif
11125    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11126	XML_SCHEMA_SCHEMA_REDEFINE);
11127    if (res != 0)
11128	return(res);
11129    return(0);
11130}
11131
11132static int
11133xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11134                       xmlNodePtr node)
11135{
11136    int res;
11137
11138    res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11139	XML_SCHEMA_SCHEMA_INCLUDE);
11140    if (res != 0)
11141	return(res);
11142    return(0);
11143}
11144
11145/**
11146 * xmlSchemaParseModelGroup:
11147 * @ctxt:  a schema validation context
11148 * @schema:  the schema being built
11149 * @node:  a subtree containing XML Schema informations
11150 * @type: the "compositor" type
11151 * @particleNeeded: if a a model group with a particle
11152 *
11153 * parse a XML schema Sequence definition.
11154 * Applies parts of:
11155 *   Schema Representation Constraint:
11156 *     Redefinition Constraints and Semantics (src-redefine)
11157 *     (6.1), (6.1.1), (6.1.2)
11158 *
11159 *   Schema Component Constraint:
11160 *     All Group Limited (cos-all-limited) (2)
11161 *     TODO: Actually this should go to component-level checks,
11162 *     but is done here due to performance. Move it to an other layer
11163 *     is schema construction via an API is implemented.
11164 *
11165 * *WARNING* this interface is highly subject to change
11166 *
11167 * Returns -1 in case of error, 0 if the declaration is improper and
11168 *         1 in case of success.
11169 */
11170static xmlSchemaTreeItemPtr
11171xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11172			 xmlNodePtr node, xmlSchemaTypeType type,
11173			 int withParticle)
11174{
11175    xmlSchemaModelGroupPtr item;
11176    xmlSchemaParticlePtr particle = NULL;
11177    xmlNodePtr child = NULL;
11178    xmlAttrPtr attr;
11179    int min = 1, max = 1, isElemRef, hasRefs = 0;
11180
11181    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11182        return (NULL);
11183    /*
11184    * Create a model group with the given compositor.
11185    */
11186    item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11187    if (item == NULL)
11188	return (NULL);
11189
11190    if (withParticle) {
11191	if (type == XML_SCHEMA_TYPE_ALL) {
11192	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11193	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11194	} else {
11195	    /* choice + sequence */
11196	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11197	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11198		"(xs:nonNegativeInteger | unbounded)");
11199	}
11200	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11201	/*
11202	* Create a particle
11203	*/
11204	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11205	if (particle == NULL)
11206	    return (NULL);
11207	particle->children = (xmlSchemaTreeItemPtr) item;
11208	/*
11209	* Check for illegal attributes.
11210	*/
11211	attr = node->properties;
11212	while (attr != NULL) {
11213	    if (attr->ns == NULL) {
11214		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11215		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11216		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11217		    xmlSchemaPIllegalAttrErr(ctxt,
11218			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11219		}
11220	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11221		xmlSchemaPIllegalAttrErr(ctxt,
11222		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11223	    }
11224	    attr = attr->next;
11225	}
11226    } else {
11227	/*
11228	* Check for illegal attributes.
11229	*/
11230	attr = node->properties;
11231	while (attr != NULL) {
11232	    if (attr->ns == NULL) {
11233		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11234		    xmlSchemaPIllegalAttrErr(ctxt,
11235			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11236		}
11237	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11238		xmlSchemaPIllegalAttrErr(ctxt,
11239		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11240	    }
11241	    attr = attr->next;
11242	}
11243    }
11244
11245    /*
11246    * Extract and validate attributes.
11247    */
11248    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11249    /*
11250    * And now for the children...
11251    */
11252    child = node->children;
11253    if (IS_SCHEMA(child, "annotation")) {
11254        item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11255        child = child->next;
11256    }
11257    if (type == XML_SCHEMA_TYPE_ALL) {
11258	xmlSchemaParticlePtr part, last = NULL;
11259
11260	while (IS_SCHEMA(child, "element")) {
11261	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11262		schema, child, &isElemRef, 0);
11263	    /*
11264	    * SPEC cos-all-limited (2)
11265	    * "The {max occurs} of all the particles in the {particles}
11266	    * of the ('all') group must be 0 or 1.
11267	    */
11268	    if (part != NULL) {
11269		if (isElemRef)
11270		    hasRefs++;
11271		if (part->minOccurs > 1) {
11272		    xmlSchemaPCustomErr(ctxt,
11273			XML_SCHEMAP_COS_ALL_LIMITED,
11274			NULL, child,
11275			"Invalid value for minOccurs (must be 0 or 1)",
11276			NULL);
11277		    /* Reset to 1. */
11278		    part->minOccurs = 1;
11279		}
11280		if (part->maxOccurs > 1) {
11281		    xmlSchemaPCustomErr(ctxt,
11282			XML_SCHEMAP_COS_ALL_LIMITED,
11283			NULL, child,
11284			"Invalid value for maxOccurs (must be 0 or 1)",
11285			NULL);
11286		    /* Reset to 1. */
11287		    part->maxOccurs = 1;
11288		}
11289		if (last == NULL)
11290		    item->children = (xmlSchemaTreeItemPtr) part;
11291		else
11292		    last->next = (xmlSchemaTreeItemPtr) part;
11293		last = part;
11294	    }
11295	    child = child->next;
11296	}
11297	if (child != NULL) {
11298	    xmlSchemaPContentErr(ctxt,
11299		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11300		NULL, node, child, NULL,
11301		"(annotation?, (annotation?, element*)");
11302	}
11303    } else {
11304	/* choice + sequence */
11305	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11306
11307	while ((IS_SCHEMA(child, "element")) ||
11308	    (IS_SCHEMA(child, "group")) ||
11309	    (IS_SCHEMA(child, "any")) ||
11310	    (IS_SCHEMA(child, "choice")) ||
11311	    (IS_SCHEMA(child, "sequence"))) {
11312
11313	    if (IS_SCHEMA(child, "element")) {
11314		part = (xmlSchemaTreeItemPtr)
11315		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11316		if (part && isElemRef)
11317		    hasRefs++;
11318	    } else if (IS_SCHEMA(child, "group")) {
11319		part =
11320		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11321		if (part != NULL)
11322		    hasRefs++;
11323		/*
11324		* Handle redefinitions.
11325		*/
11326		if (ctxt->isRedefine && ctxt->redef &&
11327		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11328		    part && part->children)
11329		{
11330		    if ((xmlSchemaGetQNameRefName(part->children) ==
11331			    ctxt->redef->refName) &&
11332			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11333			    ctxt->redef->refTargetNs))
11334		    {
11335			/*
11336			* SPEC src-redefine:
11337			* (6.1) "If it has a <group> among its contents at
11338			* some level the �actual value� of whose ref
11339			* [attribute] is the same as the �actual value� of
11340			* its own name attribute plus target namespace, then
11341			* all of the following must be true:"
11342			* (6.1.1) "It must have exactly one such group."
11343			*/
11344			if (ctxt->redefCounter != 0) {
11345			    xmlChar *str = NULL;
11346
11347			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11348				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11349				"The redefining model group definition "
11350				"'%s' must not contain more than one "
11351				"reference to the redefined definition",
11352				xmlSchemaFormatQName(&str,
11353				    ctxt->redef->refTargetNs,
11354				    ctxt->redef->refName),
11355				NULL);
11356			    FREE_AND_NULL(str)
11357			    part = NULL;
11358			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11359			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11360			{
11361			    xmlChar *str = NULL;
11362			    /*
11363			    * SPEC src-redefine:
11364			    * (6.1.2) "The �actual value� of both that
11365			    * group's minOccurs and maxOccurs [attribute]
11366			    * must be 1 (or �absent�).
11367			    */
11368			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11369				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11370				"The redefining model group definition "
11371				"'%s' must not contain a reference to the "
11372				"redefined definition with a "
11373				"maxOccurs/minOccurs other than 1",
11374				xmlSchemaFormatQName(&str,
11375				    ctxt->redef->refTargetNs,
11376				    ctxt->redef->refName),
11377				NULL);
11378			    FREE_AND_NULL(str)
11379			    part = NULL;
11380			}
11381			ctxt->redef->reference = WXS_BASIC_CAST part;
11382			ctxt->redefCounter++;
11383		    }
11384		}
11385	    } else if (IS_SCHEMA(child, "any")) {
11386		part = (xmlSchemaTreeItemPtr)
11387		    xmlSchemaParseAny(ctxt, schema, child);
11388	    } else if (IS_SCHEMA(child, "choice")) {
11389		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11390		    XML_SCHEMA_TYPE_CHOICE, 1);
11391	    } else if (IS_SCHEMA(child, "sequence")) {
11392		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11393		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11394	    }
11395	    if (part != NULL) {
11396		if (last == NULL)
11397		    item->children = part;
11398		else
11399		    last->next = part;
11400		last = part;
11401	    }
11402	    child = child->next;
11403	}
11404	if (child != NULL) {
11405	    xmlSchemaPContentErr(ctxt,
11406		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11407		NULL, node, child, NULL,
11408		"(annotation?, (element | group | choice | sequence | any)*)");
11409	}
11410    }
11411    if ((max == 0) && (min == 0))
11412	return (NULL);
11413    if (hasRefs) {
11414	/*
11415	* We need to resolve references.
11416	*/
11417	WXS_ADD_PENDING(ctxt, item);
11418    }
11419    if (withParticle)
11420	return ((xmlSchemaTreeItemPtr) particle);
11421    else
11422	return ((xmlSchemaTreeItemPtr) item);
11423}
11424
11425/**
11426 * xmlSchemaParseRestriction:
11427 * @ctxt:  a schema validation context
11428 * @schema:  the schema being built
11429 * @node:  a subtree containing XML Schema informations
11430 *
11431 * parse a XML schema Restriction definition
11432 * *WARNING* this interface is highly subject to change
11433 *
11434 * Returns the type definition or NULL in case of error
11435 */
11436static xmlSchemaTypePtr
11437xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11438                          xmlNodePtr node, xmlSchemaTypeType parentType)
11439{
11440    xmlSchemaTypePtr type;
11441    xmlNodePtr child = NULL;
11442    xmlAttrPtr attr;
11443
11444    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11445        return (NULL);
11446    /* Not a component, don't create it. */
11447    type = ctxt->ctxtType;
11448    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11449
11450    /*
11451    * Check for illegal attributes.
11452    */
11453    attr = node->properties;
11454    while (attr != NULL) {
11455	if (attr->ns == NULL) {
11456	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11457		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11458		xmlSchemaPIllegalAttrErr(ctxt,
11459		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11460	    }
11461	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11462	    xmlSchemaPIllegalAttrErr(ctxt,
11463		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11464	}
11465	attr = attr->next;
11466    }
11467    /*
11468    * Extract and validate attributes.
11469    */
11470    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11471    /*
11472    * Attribute
11473    */
11474    /*
11475    * Extract the base type. The "base" attribute is mandatory if inside
11476    * a complex type or if redefining.
11477    *
11478    * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11479    * among its [children]), the simple type definition which is
11480    * the {content type} of the type definition �resolved� to by
11481    * the �actual value� of the base [attribute]"
11482    */
11483    if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11484	&(type->baseNs), &(type->base)) == 0)
11485    {
11486	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11487	    xmlSchemaPMissingAttrErr(ctxt,
11488		XML_SCHEMAP_S4S_ATTR_MISSING,
11489		NULL, node, "base", NULL);
11490	} else if ((ctxt->isRedefine) &&
11491	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11492	{
11493	    if (type->base == NULL) {
11494		xmlSchemaPMissingAttrErr(ctxt,
11495		    XML_SCHEMAP_S4S_ATTR_MISSING,
11496		    NULL, node, "base", NULL);
11497	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11498		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11499	    {
11500		xmlChar *str1 = NULL, *str2 = NULL;
11501		/*
11502		* REDEFINE: SPEC src-redefine (5)
11503		* "Within the [children], each <simpleType> must have a
11504		* <restriction> among its [children] ... the �actual value� of
11505		* whose base [attribute] must be the same as the �actual value�
11506		* of its own name attribute plus target namespace;"
11507		*/
11508		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11509		    NULL, node, "This is a redefinition, but the QName "
11510		    "value '%s' of the 'base' attribute does not match the "
11511		    "type's designation '%s'",
11512		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11513		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11514			type->name), NULL);
11515		FREE_AND_NULL(str1);
11516		FREE_AND_NULL(str2);
11517		/* Avoid confusion and erase the values. */
11518		type->base = NULL;
11519		type->baseNs = NULL;
11520	    }
11521	}
11522    }
11523    /*
11524    * And now for the children...
11525    */
11526    child = node->children;
11527    if (IS_SCHEMA(child, "annotation")) {
11528	/*
11529	* Add the annotation to the simple type ancestor.
11530	*/
11531	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11532	    xmlSchemaParseAnnotation(ctxt, child, 1));
11533        child = child->next;
11534    }
11535    if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11536	/*
11537	* Corresponds to <simpleType><restriction><simpleType>.
11538	*/
11539	if (IS_SCHEMA(child, "simpleType")) {
11540	    if (type->base != NULL) {
11541		/*
11542		* src-restriction-base-or-simpleType
11543		* Either the base [attribute] or the simpleType [child] of the
11544		* <restriction> element must be present, but not both.
11545		*/
11546		xmlSchemaPContentErr(ctxt,
11547		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11548		    NULL, node, child,
11549		    "The attribute 'base' and the <simpleType> child are "
11550		    "mutually exclusive", NULL);
11551	    } else {
11552		type->baseType = (xmlSchemaTypePtr)
11553		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11554	    }
11555	    child = child->next;
11556	} else if (type->base == NULL) {
11557	    xmlSchemaPContentErr(ctxt,
11558		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11559		NULL, node, child,
11560		"Either the attribute 'base' or a <simpleType> child "
11561		"must be present", NULL);
11562	}
11563    } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11564	/*
11565	* Corresponds to <complexType><complexContent><restriction>...
11566	* followed by:
11567	*
11568	* Model groups <all>, <choice> and <sequence>.
11569	*/
11570	if (IS_SCHEMA(child, "all")) {
11571	    type->subtypes = (xmlSchemaTypePtr)
11572		xmlSchemaParseModelGroup(ctxt, schema, child,
11573		    XML_SCHEMA_TYPE_ALL, 1);
11574	    child = child->next;
11575	} else if (IS_SCHEMA(child, "choice")) {
11576	    type->subtypes = (xmlSchemaTypePtr)
11577		xmlSchemaParseModelGroup(ctxt,
11578		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11579	    child = child->next;
11580	} else if (IS_SCHEMA(child, "sequence")) {
11581	    type->subtypes = (xmlSchemaTypePtr)
11582		xmlSchemaParseModelGroup(ctxt, schema, child,
11583		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11584	    child = child->next;
11585	/*
11586	* Model group reference <group>.
11587	*/
11588	} else if (IS_SCHEMA(child, "group")) {
11589	    type->subtypes = (xmlSchemaTypePtr)
11590		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11591	    /*
11592	    * Note that the reference will be resolved in
11593	    * xmlSchemaResolveTypeReferences();
11594	    */
11595	    child = child->next;
11596	}
11597    } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11598	/*
11599	* Corresponds to <complexType><simpleContent><restriction>...
11600	*
11601	* "1.1 the simple type definition corresponding to the <simpleType>
11602	* among the [children] of <restriction> if there is one;"
11603	*/
11604	if (IS_SCHEMA(child, "simpleType")) {
11605	    /*
11606	    * We will store the to-be-restricted simple type in
11607	    * type->contentTypeDef *temporarily*.
11608	    */
11609	    type->contentTypeDef = (xmlSchemaTypePtr)
11610		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11611	    if ( type->contentTypeDef == NULL)
11612		return (NULL);
11613	    child = child->next;
11614	}
11615    }
11616
11617    if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11618	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11619	xmlSchemaFacetPtr facet, lastfacet = NULL;
11620	/*
11621	* Corresponds to <complexType><simpleContent><restriction>...
11622	* <simpleType><restriction>...
11623	*/
11624
11625	/*
11626	* Add the facets to the simple type ancestor.
11627	*/
11628	/*
11629	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11630	* Simple Type Definition Schema Representation Constraint:
11631	* *Single Facet Value*
11632	*/
11633	while ((IS_SCHEMA(child, "minInclusive")) ||
11634	    (IS_SCHEMA(child, "minExclusive")) ||
11635	    (IS_SCHEMA(child, "maxInclusive")) ||
11636	    (IS_SCHEMA(child, "maxExclusive")) ||
11637	    (IS_SCHEMA(child, "totalDigits")) ||
11638	    (IS_SCHEMA(child, "fractionDigits")) ||
11639	    (IS_SCHEMA(child, "pattern")) ||
11640	    (IS_SCHEMA(child, "enumeration")) ||
11641	    (IS_SCHEMA(child, "whiteSpace")) ||
11642	    (IS_SCHEMA(child, "length")) ||
11643	    (IS_SCHEMA(child, "maxLength")) ||
11644	    (IS_SCHEMA(child, "minLength"))) {
11645	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11646	    if (facet != NULL) {
11647		if (lastfacet == NULL)
11648		    type->facets = facet;
11649		else
11650		    lastfacet->next = facet;
11651		lastfacet = facet;
11652		lastfacet->next = NULL;
11653	    }
11654	    child = child->next;
11655	}
11656	/*
11657	* Create links for derivation and validation.
11658	*/
11659	if (type->facets != NULL) {
11660	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11661
11662	    facet = type->facets;
11663	    do {
11664		facetLink = (xmlSchemaFacetLinkPtr)
11665		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11666		if (facetLink == NULL) {
11667		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11668		    xmlFree(facetLink);
11669		    return (NULL);
11670		}
11671		facetLink->facet = facet;
11672		facetLink->next = NULL;
11673		if (lastFacetLink == NULL)
11674		    type->facetSet = facetLink;
11675		else
11676		    lastFacetLink->next = facetLink;
11677		lastFacetLink = facetLink;
11678		facet = facet->next;
11679	    } while (facet != NULL);
11680	}
11681    }
11682    if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11683	/*
11684	* Attribute uses/declarations.
11685	*/
11686	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11687	    (xmlSchemaItemListPtr *) &(type->attrUses),
11688	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11689	    return(NULL);
11690	/*
11691	* Attribute wildcard.
11692	*/
11693	if (IS_SCHEMA(child, "anyAttribute")) {
11694	    type->attributeWildcard =
11695		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11696	    child = child->next;
11697	}
11698    }
11699    if (child != NULL) {
11700	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11701	    xmlSchemaPContentErr(ctxt,
11702		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11703		NULL, node, child, NULL,
11704		"annotation?, (group | all | choice | sequence)?, "
11705		"((attribute | attributeGroup)*, anyAttribute?))");
11706	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
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)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11714	} else {
11715	    /* Simple type */
11716	    xmlSchemaPContentErr(ctxt,
11717		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11718		NULL, node, child, NULL,
11719		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11720		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11721		"length | minLength | maxLength | enumeration | whiteSpace | "
11722		"pattern)*))");
11723	}
11724    }
11725    return (NULL);
11726}
11727
11728/**
11729 * xmlSchemaParseExtension:
11730 * @ctxt:  a schema validation context
11731 * @schema:  the schema being built
11732 * @node:  a subtree containing XML Schema informations
11733 *
11734 * Parses an <extension>, which is found inside a
11735 * <simpleContent> or <complexContent>.
11736 * *WARNING* this interface is highly subject to change.
11737 *
11738 * TODO: Returns the type definition or NULL in case of error
11739 */
11740static xmlSchemaTypePtr
11741xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11742                        xmlNodePtr node, xmlSchemaTypeType parentType)
11743{
11744    xmlSchemaTypePtr type;
11745    xmlNodePtr child = NULL;
11746    xmlAttrPtr attr;
11747
11748    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11749        return (NULL);
11750    /* Not a component, don't create it. */
11751    type = ctxt->ctxtType;
11752    type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11753
11754    /*
11755    * Check for illegal attributes.
11756    */
11757    attr = node->properties;
11758    while (attr != NULL) {
11759	if (attr->ns == NULL) {
11760	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11761		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11762		xmlSchemaPIllegalAttrErr(ctxt,
11763		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11764	    }
11765	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11766	    xmlSchemaPIllegalAttrErr(ctxt,
11767		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11768	}
11769	attr = attr->next;
11770    }
11771
11772    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11773
11774    /*
11775    * Attribute "base" - mandatory.
11776    */
11777    if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11778	"base", &(type->baseNs), &(type->base)) == 0) &&
11779	(type->base == NULL)) {
11780	xmlSchemaPMissingAttrErr(ctxt,
11781	    XML_SCHEMAP_S4S_ATTR_MISSING,
11782	    NULL, node, "base", NULL);
11783    }
11784    /*
11785    * And now for the children...
11786    */
11787    child = node->children;
11788    if (IS_SCHEMA(child, "annotation")) {
11789	/*
11790	* Add the annotation to the type ancestor.
11791	*/
11792	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11793	    xmlSchemaParseAnnotation(ctxt, child, 1));
11794        child = child->next;
11795    }
11796    if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11797	/*
11798	* Corresponds to <complexType><complexContent><extension>... and:
11799	*
11800	* Model groups <all>, <choice>, <sequence> and <group>.
11801	*/
11802	if (IS_SCHEMA(child, "all")) {
11803	    type->subtypes = (xmlSchemaTypePtr)
11804		xmlSchemaParseModelGroup(ctxt, schema,
11805		    child, XML_SCHEMA_TYPE_ALL, 1);
11806	    child = child->next;
11807	} else if (IS_SCHEMA(child, "choice")) {
11808	    type->subtypes = (xmlSchemaTypePtr)
11809		xmlSchemaParseModelGroup(ctxt, schema,
11810		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11811	    child = child->next;
11812	} else if (IS_SCHEMA(child, "sequence")) {
11813	    type->subtypes = (xmlSchemaTypePtr)
11814		xmlSchemaParseModelGroup(ctxt, schema,
11815		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11816	    child = child->next;
11817	} else if (IS_SCHEMA(child, "group")) {
11818	    type->subtypes = (xmlSchemaTypePtr)
11819		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11820	    /*
11821	    * Note that the reference will be resolved in
11822	    * xmlSchemaResolveTypeReferences();
11823	    */
11824	    child = child->next;
11825	}
11826    }
11827    if (child != NULL) {
11828	/*
11829	* Attribute uses/declarations.
11830	*/
11831	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11832	    (xmlSchemaItemListPtr *) &(type->attrUses),
11833	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11834	    return(NULL);
11835	/*
11836	* Attribute wildcard.
11837	*/
11838	if (IS_SCHEMA(child, "anyAttribute")) {
11839	    ctxt->ctxtType->attributeWildcard =
11840		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11841	    child = child->next;
11842	}
11843    }
11844    if (child != NULL) {
11845	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11846	    /* Complex content extension. */
11847	    xmlSchemaPContentErr(ctxt,
11848		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11849		NULL, node, child, NULL,
11850		"(annotation?, ((group | all | choice | sequence)?, "
11851		"((attribute | attributeGroup)*, anyAttribute?)))");
11852	} else {
11853	    /* Simple content extension. */
11854	    xmlSchemaPContentErr(ctxt,
11855		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11856		NULL, node, child, NULL,
11857		"(annotation?, ((attribute | attributeGroup)*, "
11858		"anyAttribute?))");
11859	}
11860    }
11861    return (NULL);
11862}
11863
11864/**
11865 * xmlSchemaParseSimpleContent:
11866 * @ctxt:  a schema validation context
11867 * @schema:  the schema being built
11868 * @node:  a subtree containing XML Schema informations
11869 *
11870 * parse a XML schema SimpleContent definition
11871 * *WARNING* this interface is highly subject to change
11872 *
11873 * Returns the type definition or NULL in case of error
11874 */
11875static int
11876xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11877                            xmlSchemaPtr schema, xmlNodePtr node,
11878			    int *hasRestrictionOrExtension)
11879{
11880    xmlSchemaTypePtr type;
11881    xmlNodePtr child = NULL;
11882    xmlAttrPtr attr;
11883
11884    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11885	(hasRestrictionOrExtension == NULL))
11886        return (-1);
11887    *hasRestrictionOrExtension = 0;
11888    /* Not a component, don't create it. */
11889    type = ctxt->ctxtType;
11890    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11891    /*
11892    * Check for illegal attributes.
11893    */
11894    attr = node->properties;
11895    while (attr != NULL) {
11896	if (attr->ns == NULL) {
11897	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11898		xmlSchemaPIllegalAttrErr(ctxt,
11899		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11900	    }
11901	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11902	    xmlSchemaPIllegalAttrErr(ctxt,
11903		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11904	}
11905	attr = attr->next;
11906    }
11907
11908    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11909
11910    /*
11911    * And now for the children...
11912    */
11913    child = node->children;
11914    if (IS_SCHEMA(child, "annotation")) {
11915	/*
11916	* Add the annotation to the complex type ancestor.
11917	*/
11918	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11919	    xmlSchemaParseAnnotation(ctxt, child, 1));
11920        child = child->next;
11921    }
11922    if (child == NULL) {
11923	xmlSchemaPContentErr(ctxt,
11924	    XML_SCHEMAP_S4S_ELEM_MISSING,
11925	    NULL, node, NULL, NULL,
11926	    "(annotation?, (restriction | extension))");
11927    }
11928    if (child == NULL) {
11929	xmlSchemaPContentErr(ctxt,
11930	    XML_SCHEMAP_S4S_ELEM_MISSING,
11931	    NULL, node, NULL, NULL,
11932	    "(annotation?, (restriction | extension))");
11933    }
11934    if (IS_SCHEMA(child, "restriction")) {
11935        xmlSchemaParseRestriction(ctxt, schema, child,
11936	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11937	(*hasRestrictionOrExtension) = 1;
11938        child = child->next;
11939    } else if (IS_SCHEMA(child, "extension")) {
11940        xmlSchemaParseExtension(ctxt, schema, child,
11941	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11942	(*hasRestrictionOrExtension) = 1;
11943        child = child->next;
11944    }
11945    if (child != NULL) {
11946	xmlSchemaPContentErr(ctxt,
11947	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11948	    NULL, node, child, NULL,
11949	    "(annotation?, (restriction | extension))");
11950    }
11951    return (0);
11952}
11953
11954/**
11955 * xmlSchemaParseComplexContent:
11956 * @ctxt:  a schema validation context
11957 * @schema:  the schema being built
11958 * @node:  a subtree containing XML Schema informations
11959 *
11960 * parse a XML schema ComplexContent definition
11961 * *WARNING* this interface is highly subject to change
11962 *
11963 * Returns the type definition or NULL in case of error
11964 */
11965static int
11966xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11967                             xmlSchemaPtr schema, xmlNodePtr node,
11968			     int *hasRestrictionOrExtension)
11969{
11970    xmlSchemaTypePtr type;
11971    xmlNodePtr child = NULL;
11972    xmlAttrPtr attr;
11973
11974    if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11975	(hasRestrictionOrExtension == NULL))
11976        return (-1);
11977    *hasRestrictionOrExtension = 0;
11978    /* Not a component, don't create it. */
11979    type = ctxt->ctxtType;
11980    /*
11981    * Check for illegal attributes.
11982    */
11983    attr = node->properties;
11984    while (attr != NULL) {
11985	if (attr->ns == NULL) {
11986	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11987		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
11988	    {
11989		xmlSchemaPIllegalAttrErr(ctxt,
11990		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11991	    }
11992	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11993	    xmlSchemaPIllegalAttrErr(ctxt,
11994		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11995	}
11996	attr = attr->next;
11997    }
11998
11999    xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12000
12001    /*
12002    * Set the 'mixed' on the complex type ancestor.
12003    */
12004    if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12005	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12006	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12007    }
12008    child = node->children;
12009    if (IS_SCHEMA(child, "annotation")) {
12010	/*
12011	* Add the annotation to the complex type ancestor.
12012	*/
12013	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12014	    xmlSchemaParseAnnotation(ctxt, child, 1));
12015        child = child->next;
12016    }
12017    if (child == NULL) {
12018	xmlSchemaPContentErr(ctxt,
12019	    XML_SCHEMAP_S4S_ELEM_MISSING,
12020	    NULL, node, NULL,
12021	    NULL, "(annotation?, (restriction | extension))");
12022    }
12023    if (child == NULL) {
12024	xmlSchemaPContentErr(ctxt,
12025	    XML_SCHEMAP_S4S_ELEM_MISSING,
12026	    NULL, node, NULL,
12027	    NULL, "(annotation?, (restriction | extension))");
12028    }
12029    if (IS_SCHEMA(child, "restriction")) {
12030        xmlSchemaParseRestriction(ctxt, schema, child,
12031	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12032	(*hasRestrictionOrExtension) = 1;
12033        child = child->next;
12034    } else if (IS_SCHEMA(child, "extension")) {
12035        xmlSchemaParseExtension(ctxt, schema, child,
12036	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12037	(*hasRestrictionOrExtension) = 1;
12038        child = child->next;
12039    }
12040    if (child != NULL) {
12041	xmlSchemaPContentErr(ctxt,
12042	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12043	    NULL, node, child,
12044	    NULL, "(annotation?, (restriction | extension))");
12045    }
12046    return (0);
12047}
12048
12049/**
12050 * xmlSchemaParseComplexType:
12051 * @ctxt:  a schema validation context
12052 * @schema:  the schema being built
12053 * @node:  a subtree containing XML Schema informations
12054 *
12055 * parse a XML schema Complex Type definition
12056 * *WARNING* this interface is highly subject to change
12057 *
12058 * Returns the type definition or NULL in case of error
12059 */
12060static xmlSchemaTypePtr
12061xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12062                          xmlNodePtr node, int topLevel)
12063{
12064    xmlSchemaTypePtr type, ctxtType;
12065    xmlNodePtr child = NULL;
12066    const xmlChar *name = NULL;
12067    xmlAttrPtr attr;
12068    const xmlChar *attrValue;
12069#ifdef ENABLE_NAMED_LOCALS
12070    char buf[40];
12071#endif
12072    int final = 0, block = 0, hasRestrictionOrExtension = 0;
12073
12074
12075    if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12076        return (NULL);
12077
12078    ctxtType = ctxt->ctxtType;
12079
12080    if (topLevel) {
12081	attr = xmlSchemaGetPropNode(node, "name");
12082	if (attr == NULL) {
12083	    xmlSchemaPMissingAttrErr(ctxt,
12084		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12085	    return (NULL);
12086	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12087	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12088	    return (NULL);
12089	}
12090    }
12091
12092    if (topLevel == 0) {
12093	/*
12094	* Parse as local complex type definition.
12095	*/
12096#ifdef ENABLE_NAMED_LOCALS
12097        snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12098	type = xmlSchemaAddType(ctxt, schema,
12099	    XML_SCHEMA_TYPE_COMPLEX,
12100	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12101	    ctxt->targetNamespace, node, 0);
12102#else
12103	type = xmlSchemaAddType(ctxt, schema,
12104	    XML_SCHEMA_TYPE_COMPLEX,
12105	    NULL, ctxt->targetNamespace, node, 0);
12106#endif
12107	if (type == NULL)
12108	    return (NULL);
12109	name = type->name;
12110	type->node = node;
12111	type->type = XML_SCHEMA_TYPE_COMPLEX;
12112	/*
12113	* TODO: We need the target namespace.
12114	*/
12115    } else {
12116	/*
12117	* Parse as global complex type definition.
12118	*/
12119	type = xmlSchemaAddType(ctxt, schema,
12120	    XML_SCHEMA_TYPE_COMPLEX,
12121	    name, ctxt->targetNamespace, node, 1);
12122	if (type == NULL)
12123	    return (NULL);
12124	type->node = node;
12125	type->type = XML_SCHEMA_TYPE_COMPLEX;
12126	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12127    }
12128    type->targetNamespace = ctxt->targetNamespace;
12129    /*
12130    * Handle attributes.
12131    */
12132    attr = node->properties;
12133    while (attr != NULL) {
12134	if (attr->ns == NULL) {
12135	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12136		/*
12137		* Attribute "id".
12138		*/
12139		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12140	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12141		/*
12142		* Attribute "mixed".
12143		*/
12144		if (xmlSchemaPGetBoolNodeValue(ctxt,
12145			NULL, (xmlNodePtr) attr))
12146		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12147	    } else if (topLevel) {
12148		/*
12149		* Attributes of global complex type definitions.
12150		*/
12151		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12152		    /* Pass. */
12153		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12154		    /*
12155		    * Attribute "abstract".
12156		    */
12157		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12158			    NULL, (xmlNodePtr) attr))
12159			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12160		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12161		    /*
12162		    * Attribute "final".
12163		    */
12164		    attrValue = xmlSchemaGetNodeContent(ctxt,
12165			(xmlNodePtr) attr);
12166		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12167			&(type->flags),
12168			-1,
12169			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12170			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12171			-1, -1, -1) != 0)
12172		    {
12173			xmlSchemaPSimpleTypeErr(ctxt,
12174			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12175			    NULL, (xmlNodePtr) attr, NULL,
12176			    "(#all | List of (extension | restriction))",
12177			    attrValue, NULL, NULL, NULL);
12178		    } else
12179			final = 1;
12180		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12181		    /*
12182		    * Attribute "block".
12183		    */
12184		    attrValue = xmlSchemaGetNodeContent(ctxt,
12185			(xmlNodePtr) attr);
12186		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12187			-1,
12188			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12189			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12190			-1, -1, -1) != 0) {
12191			xmlSchemaPSimpleTypeErr(ctxt,
12192			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12193			    NULL, (xmlNodePtr) attr, NULL,
12194			    "(#all | List of (extension | restriction)) ",
12195			    attrValue, NULL, NULL, NULL);
12196		    } else
12197			block = 1;
12198		} else {
12199			xmlSchemaPIllegalAttrErr(ctxt,
12200			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12201		}
12202	    } else {
12203		xmlSchemaPIllegalAttrErr(ctxt,
12204		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12205	    }
12206	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12207	    xmlSchemaPIllegalAttrErr(ctxt,
12208		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12209	}
12210	attr = attr->next;
12211    }
12212    if (! block) {
12213	/*
12214	* Apply default "block" values.
12215	*/
12216	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12217	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12218	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12219	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12220    }
12221    if (! final) {
12222	/*
12223	* Apply default "block" values.
12224	*/
12225	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12226	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12227	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12228	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12229    }
12230    /*
12231    * And now for the children...
12232    */
12233    child = node->children;
12234    if (IS_SCHEMA(child, "annotation")) {
12235        type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12236        child = child->next;
12237    }
12238    ctxt->ctxtType = type;
12239    if (IS_SCHEMA(child, "simpleContent")) {
12240	/*
12241	* <complexType><simpleContent>...
12242	* 3.4.3 : 2.2
12243	* Specifying mixed='true' when the <simpleContent>
12244	* alternative is chosen has no effect
12245	*/
12246	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12247	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12248        xmlSchemaParseSimpleContent(ctxt, schema, child,
12249	    &hasRestrictionOrExtension);
12250        child = child->next;
12251    } else if (IS_SCHEMA(child, "complexContent")) {
12252	/*
12253	* <complexType><complexContent>...
12254	*/
12255	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12256        xmlSchemaParseComplexContent(ctxt, schema, child,
12257	    &hasRestrictionOrExtension);
12258        child = child->next;
12259    } else {
12260	/*
12261	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12262	*
12263	* SPEC
12264	* "...the third alternative (neither <simpleContent> nor
12265	* <complexContent>) is chosen. This case is understood as shorthand
12266	* for complex content restricting the �ur-type definition�, and the
12267	* details of the mappings should be modified as necessary.
12268	*/
12269	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12270	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12271	/*
12272	* Parse model groups.
12273	*/
12274        if (IS_SCHEMA(child, "all")) {
12275            type->subtypes = (xmlSchemaTypePtr)
12276		xmlSchemaParseModelGroup(ctxt, schema, child,
12277		    XML_SCHEMA_TYPE_ALL, 1);
12278            child = child->next;
12279        } else if (IS_SCHEMA(child, "choice")) {
12280            type->subtypes = (xmlSchemaTypePtr)
12281		xmlSchemaParseModelGroup(ctxt, schema, child,
12282		    XML_SCHEMA_TYPE_CHOICE, 1);
12283            child = child->next;
12284        } else if (IS_SCHEMA(child, "sequence")) {
12285            type->subtypes = (xmlSchemaTypePtr)
12286		xmlSchemaParseModelGroup(ctxt, schema, child,
12287		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12288            child = child->next;
12289        } else if (IS_SCHEMA(child, "group")) {
12290            type->subtypes = (xmlSchemaTypePtr)
12291		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12292	    /*
12293	    * Note that the reference will be resolved in
12294	    * xmlSchemaResolveTypeReferences();
12295	    */
12296            child = child->next;
12297        }
12298	/*
12299	* Parse attribute decls/refs.
12300	*/
12301        if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12302	    (xmlSchemaItemListPtr *) &(type->attrUses),
12303	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12304	    return(NULL);
12305	/*
12306	* Parse attribute wildcard.
12307	*/
12308	if (IS_SCHEMA(child, "anyAttribute")) {
12309	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12310	    child = child->next;
12311	}
12312    }
12313    if (child != NULL) {
12314	xmlSchemaPContentErr(ctxt,
12315	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12316	    NULL, node, child,
12317	    NULL, "(annotation?, (simpleContent | complexContent | "
12318	    "((group | all | choice | sequence)?, ((attribute | "
12319	    "attributeGroup)*, anyAttribute?))))");
12320    }
12321    /*
12322    * REDEFINE: SPEC src-redefine (5)
12323    */
12324    if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12325	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12326	    NULL, node, "This is a redefinition, thus the "
12327	    "<complexType> must have a <restriction> or <extension> "
12328	    "grand-child", NULL);
12329    }
12330    ctxt->ctxtType = ctxtType;
12331    return (type);
12332}
12333
12334/************************************************************************
12335 * 									*
12336 * 			Validating using Schemas			*
12337 * 									*
12338 ************************************************************************/
12339
12340/************************************************************************
12341 * 									*
12342 * 			Reading/Writing Schemas				*
12343 * 									*
12344 ************************************************************************/
12345
12346#if 0 /* Will be enabled if it is clear what options are needed. */
12347/**
12348 * xmlSchemaParserCtxtSetOptions:
12349 * @ctxt:	a schema parser context
12350 * @options: a combination of xmlSchemaParserOption
12351 *
12352 * Sets the options to be used during the parse.
12353 *
12354 * Returns 0 in case of success, -1 in case of an
12355 * API error.
12356 */
12357static int
12358xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12359			      int options)
12360
12361{
12362    int i;
12363
12364    if (ctxt == NULL)
12365	return (-1);
12366    /*
12367    * WARNING: Change the start value if adding to the
12368    * xmlSchemaParseOption.
12369    */
12370    for (i = 1; i < (int) sizeof(int) * 8; i++) {
12371        if (options & 1<<i) {
12372	    return (-1);
12373        }
12374    }
12375    ctxt->options = options;
12376    return (0);
12377}
12378
12379/**
12380 * xmlSchemaValidCtxtGetOptions:
12381 * @ctxt: a schema parser context
12382 *
12383 * Returns the option combination of the parser context.
12384 */
12385static int
12386xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12387
12388{
12389    if (ctxt == NULL)
12390	return (-1);
12391    else
12392	return (ctxt->options);
12393}
12394#endif
12395
12396/**
12397 * xmlSchemaNewParserCtxt:
12398 * @URL:  the location of the schema
12399 *
12400 * Create an XML Schemas parse context for that file/resource expected
12401 * to contain an XML Schemas file.
12402 *
12403 * Returns the parser context or NULL in case of error
12404 */
12405xmlSchemaParserCtxtPtr
12406xmlSchemaNewParserCtxt(const char *URL)
12407{
12408    xmlSchemaParserCtxtPtr ret;
12409
12410    if (URL == NULL)
12411        return (NULL);
12412
12413    ret = xmlSchemaParserCtxtCreate();
12414    if (ret == NULL)
12415	return(NULL);
12416    ret->dict = xmlDictCreate();
12417    ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12418    return (ret);
12419}
12420
12421/**
12422 * xmlSchemaNewMemParserCtxt:
12423 * @buffer:  a pointer to a char array containing the schemas
12424 * @size:  the size of the array
12425 *
12426 * Create an XML Schemas parse context for that memory buffer expected
12427 * to contain an XML Schemas file.
12428 *
12429 * Returns the parser context or NULL in case of error
12430 */
12431xmlSchemaParserCtxtPtr
12432xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12433{
12434    xmlSchemaParserCtxtPtr ret;
12435
12436    if ((buffer == NULL) || (size <= 0))
12437        return (NULL);
12438    ret = xmlSchemaParserCtxtCreate();
12439    if (ret == NULL)
12440	return(NULL);
12441    ret->buffer = buffer;
12442    ret->size = size;
12443    ret->dict = xmlDictCreate();
12444    return (ret);
12445}
12446
12447/**
12448 * xmlSchemaNewDocParserCtxt:
12449 * @doc:  a preparsed document tree
12450 *
12451 * Create an XML Schemas parse context for that document.
12452 * NB. The document may be modified during the parsing process.
12453 *
12454 * Returns the parser context or NULL in case of error
12455 */
12456xmlSchemaParserCtxtPtr
12457xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12458{
12459    xmlSchemaParserCtxtPtr ret;
12460
12461    if (doc == NULL)
12462      return (NULL);
12463    ret = xmlSchemaParserCtxtCreate();
12464    if (ret == NULL)
12465	return(NULL);
12466    ret->doc = doc;
12467    ret->dict = xmlDictCreate();
12468    /* The application has responsibility for the document */
12469    ret->preserve = 1;
12470
12471    return (ret);
12472}
12473
12474/**
12475 * xmlSchemaFreeParserCtxt:
12476 * @ctxt:  the schema parser context
12477 *
12478 * Free the resources associated to the schema parser context
12479 */
12480void
12481xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12482{
12483    if (ctxt == NULL)
12484        return;
12485    if (ctxt->doc != NULL && !ctxt->preserve)
12486        xmlFreeDoc(ctxt->doc);
12487    if (ctxt->vctxt != NULL) {
12488	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12489    }
12490    if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12491	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12492	ctxt->constructor = NULL;
12493	ctxt->ownsConstructor = 0;
12494    }
12495    if (ctxt->attrProhibs != NULL)
12496	xmlSchemaItemListFree(ctxt->attrProhibs);
12497    xmlDictFree(ctxt->dict);
12498    xmlFree(ctxt);
12499}
12500
12501/************************************************************************
12502 *									*
12503 *			Building the content models			*
12504 *									*
12505 ************************************************************************/
12506
12507static void
12508xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12509	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12510{
12511    xmlAutomataStatePtr start, tmp;
12512    xmlSchemaElementPtr elemDecl, member;
12513    xmlSchemaSubstGroupPtr substGroup;
12514    int i;
12515
12516    elemDecl = (xmlSchemaElementPtr) particle->children;
12517    /*
12518    * Wrap the substitution group with a CHOICE.
12519    */
12520    start = pctxt->state;
12521    if (end == NULL)
12522	end = xmlAutomataNewState(pctxt->am);
12523    substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12524    if (substGroup == NULL) {
12525	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12526	    XML_SCHEMAP_INTERNAL,
12527	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12528	    "declaration is marked having a subst. group but none "
12529	    "available.\n", elemDecl->name, NULL);
12530	return;
12531    }
12532    if (counter >= 0) {
12533	/*
12534	* NOTE that we put the declaration in, even if it's abstract.
12535	* However, an error will be raised during *validation* if an element
12536	* information item shall be validated against an abstract element
12537	* declaration.
12538	*/
12539	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12540        xmlAutomataNewTransition2(pctxt->am, tmp, end,
12541	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12542	/*
12543	* Add subst. group members.
12544	*/
12545	for (i = 0; i < substGroup->members->nbItems; i++) {
12546	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12547            xmlAutomataNewTransition2(pctxt->am, tmp, end,
12548		               member->name, member->targetNamespace, member);
12549	}
12550    } else if (particle->maxOccurs == 1) {
12551	/*
12552	* NOTE that we put the declaration in, even if it's abstract,
12553	*/
12554	xmlAutomataNewEpsilon(pctxt->am,
12555	    xmlAutomataNewTransition2(pctxt->am,
12556	    start, NULL,
12557	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12558	/*
12559	* Add subst. group members.
12560	*/
12561	for (i = 0; i < substGroup->members->nbItems; i++) {
12562	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12563	    /*
12564	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12565	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12566	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12567	    *  section in xmlSchemaBuildAContentModel() ).
12568	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12569	    *  intended for the above "counter" section originally. I.e.,
12570	    *  check xs:all with subst-groups.
12571	    *
12572	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12573	    *	               member->name, member->targetNamespace,
12574	    *		       1, 1, member);
12575	    */
12576	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12577		member->name, member->targetNamespace, member);
12578	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12579	}
12580    } else {
12581	xmlAutomataStatePtr hop;
12582	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12583	    UNBOUNDED : particle->maxOccurs - 1;
12584	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12585
12586	counter =
12587	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12588	    maxOccurs);
12589	hop = xmlAutomataNewState(pctxt->am);
12590
12591	xmlAutomataNewEpsilon(pctxt->am,
12592	    xmlAutomataNewTransition2(pctxt->am,
12593	    start, NULL,
12594	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12595	    hop);
12596	/*
12597	 * Add subst. group members.
12598	 */
12599	for (i = 0; i < substGroup->members->nbItems; i++) {
12600	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12601	    xmlAutomataNewEpsilon(pctxt->am,
12602		xmlAutomataNewTransition2(pctxt->am,
12603		start, NULL,
12604		member->name, member->targetNamespace, member),
12605		hop);
12606	}
12607	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12608	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12609    }
12610    if (particle->minOccurs == 0)
12611	xmlAutomataNewEpsilon(pctxt->am, start, end);
12612    pctxt->state = end;
12613}
12614
12615static void
12616xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12617				     xmlSchemaParticlePtr particle)
12618{
12619    if (((xmlSchemaElementPtr) particle->children)->flags &
12620	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12621	/*
12622	* Substitution groups.
12623	*/
12624	xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12625    } else {
12626	xmlSchemaElementPtr elemDecl;
12627	xmlAutomataStatePtr start;
12628
12629	elemDecl = (xmlSchemaElementPtr) particle->children;
12630
12631	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12632	    return;
12633	if (particle->maxOccurs == 1) {
12634	    start = ctxt->state;
12635	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12636		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12637	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12638	           (particle->minOccurs < 2)) {
12639	    /* Special case. */
12640	    start = ctxt->state;
12641	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12642		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12643	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12644		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12645	} else {
12646	    int counter;
12647	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12648			    UNBOUNDED : particle->maxOccurs - 1;
12649	    int minOccurs = particle->minOccurs < 1 ?
12650			    0 : particle->minOccurs - 1;
12651
12652	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12653	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12654	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12655		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12656	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12657	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12658		NULL, counter);
12659	}
12660	if (particle->minOccurs == 0)
12661	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12662    }
12663}
12664
12665/**
12666 * xmlSchemaBuildAContentModel:
12667 * @ctxt:  the schema parser context
12668 * @particle:  the particle component
12669 * @name:  the complex type's name whose content is being built
12670 *
12671 * Create the automaton for the {content type} of a complex type.
12672 *
12673 */
12674static void
12675xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12676			    xmlSchemaParticlePtr particle)
12677{
12678    if (particle == NULL) {
12679	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12680	return;
12681    }
12682    if (particle->children == NULL) {
12683	/*
12684	* Just return in this case. A missing "term" of the particle
12685	* might arise due to an invalid "term" component.
12686	*/
12687	return;
12688    }
12689
12690    switch (particle->children->type) {
12691	case XML_SCHEMA_TYPE_ANY: {
12692	    xmlAutomataStatePtr start, end;
12693	    xmlSchemaWildcardPtr wild;
12694	    xmlSchemaWildcardNsPtr ns;
12695
12696	    wild = (xmlSchemaWildcardPtr) particle->children;
12697
12698	    start = pctxt->state;
12699	    end = xmlAutomataNewState(pctxt->am);
12700
12701	    if (particle->maxOccurs == 1) {
12702		if (wild->any == 1) {
12703		    /*
12704		    * We need to add both transitions:
12705		    *
12706		    * 1. the {"*", "*"} for elements in a namespace.
12707		    */
12708		    pctxt->state =
12709			xmlAutomataNewTransition2(pctxt->am,
12710			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12711		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12712		    /*
12713		    * 2. the {"*"} for elements in no namespace.
12714		    */
12715		    pctxt->state =
12716			xmlAutomataNewTransition2(pctxt->am,
12717			start, NULL, BAD_CAST "*", NULL, wild);
12718		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12719
12720		} else if (wild->nsSet != NULL) {
12721		    ns = wild->nsSet;
12722		    do {
12723			pctxt->state = start;
12724			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12725			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12726			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12727			ns = ns->next;
12728		    } while (ns != NULL);
12729
12730		} else if (wild->negNsSet != NULL) {
12731		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12732			start, end, BAD_CAST "*", wild->negNsSet->value,
12733			wild);
12734		}
12735	    } else {
12736		int counter;
12737		xmlAutomataStatePtr hop;
12738		int maxOccurs =
12739		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
12740		int minOccurs =
12741		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12742
12743		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12744		hop = xmlAutomataNewState(pctxt->am);
12745		if (wild->any == 1) {
12746		    pctxt->state =
12747			xmlAutomataNewTransition2(pctxt->am,
12748			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12749		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12750		    pctxt->state =
12751			xmlAutomataNewTransition2(pctxt->am,
12752			start, NULL, BAD_CAST "*", NULL, wild);
12753		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12754		} else if (wild->nsSet != NULL) {
12755		    ns = wild->nsSet;
12756		    do {
12757			pctxt->state =
12758			    xmlAutomataNewTransition2(pctxt->am,
12759				start, NULL, BAD_CAST "*", ns->value, wild);
12760			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12761			ns = ns->next;
12762		    } while (ns != NULL);
12763
12764		} else if (wild->negNsSet != NULL) {
12765		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12766			start, hop, BAD_CAST "*", wild->negNsSet->value,
12767			wild);
12768		}
12769		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12770		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12771	    }
12772	    if (particle->minOccurs == 0) {
12773		xmlAutomataNewEpsilon(pctxt->am, start, end);
12774	    }
12775	    pctxt->state = end;
12776            break;
12777	}
12778        case XML_SCHEMA_TYPE_ELEMENT:
12779	    xmlSchemaBuildContentModelForElement(pctxt, particle);
12780	    break;
12781        case XML_SCHEMA_TYPE_SEQUENCE:{
12782                xmlSchemaTreeItemPtr sub;
12783
12784                /*
12785                 * If max and min occurances are default (1) then
12786                 * simply iterate over the particles of the <sequence>.
12787                 */
12788                if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12789                    sub = particle->children->children;
12790                    while (sub != NULL) {
12791                        xmlSchemaBuildAContentModel(pctxt,
12792			    (xmlSchemaParticlePtr) sub);
12793                        sub = sub->next;
12794                    }
12795                } else {
12796                    xmlAutomataStatePtr oldstate = pctxt->state;
12797
12798                    if (particle->maxOccurs >= UNBOUNDED) {
12799                        if (particle->minOccurs > 1) {
12800                            xmlAutomataStatePtr tmp;
12801                            int counter;
12802
12803                            pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12804				oldstate, NULL);
12805                            oldstate = pctxt->state;
12806
12807                            counter = xmlAutomataNewCounter(pctxt->am,
12808				particle->minOccurs - 1, UNBOUNDED);
12809
12810                            sub = particle->children->children;
12811                            while (sub != NULL) {
12812                                xmlSchemaBuildAContentModel(pctxt,
12813				    (xmlSchemaParticlePtr) sub);
12814                                sub = sub->next;
12815                            }
12816                            tmp = pctxt->state;
12817                            xmlAutomataNewCountedTrans(pctxt->am, tmp,
12818                                                       oldstate, counter);
12819                            pctxt->state =
12820                                xmlAutomataNewCounterTrans(pctxt->am, tmp,
12821                                                           NULL, counter);
12822
12823                        } else {
12824                            pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12825				oldstate, NULL);
12826                            oldstate = pctxt->state;
12827
12828			    sub = particle->children->children;
12829                            while (sub != NULL) {
12830                                xmlSchemaBuildAContentModel(pctxt,
12831				    (xmlSchemaParticlePtr) sub);
12832                                sub = sub->next;
12833                            }
12834                            xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12835                                                  oldstate);
12836			    /*
12837			     * epsilon needed to block previous trans from
12838			     * being allowed to enter back from another
12839			     * construct
12840			     */
12841			    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12842						pctxt->state, NULL);
12843                            if (particle->minOccurs == 0) {
12844                                xmlAutomataNewEpsilon(pctxt->am,
12845				    oldstate, pctxt->state);
12846                            }
12847                        }
12848                    } else if ((particle->maxOccurs > 1)
12849                               || (particle->minOccurs > 1)) {
12850                        xmlAutomataStatePtr tmp;
12851                        int counter;
12852
12853                        pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12854			    oldstate, NULL);
12855                        oldstate = pctxt->state;
12856
12857                        counter = xmlAutomataNewCounter(pctxt->am,
12858			    particle->minOccurs - 1,
12859			    particle->maxOccurs - 1);
12860
12861                        sub = particle->children->children;
12862                        while (sub != NULL) {
12863                            xmlSchemaBuildAContentModel(pctxt,
12864				(xmlSchemaParticlePtr) sub);
12865                            sub = sub->next;
12866                        }
12867                        tmp = pctxt->state;
12868                        xmlAutomataNewCountedTrans(pctxt->am,
12869			    tmp, oldstate, counter);
12870                        pctxt->state =
12871                            xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12872                                                       counter);
12873                        if (particle->minOccurs == 0) {
12874                            xmlAutomataNewEpsilon(pctxt->am,
12875				oldstate, pctxt->state);
12876                        }
12877                    } else {
12878                        sub = particle->children->children;
12879                        while (sub != NULL) {
12880                            xmlSchemaBuildAContentModel(pctxt,
12881				(xmlSchemaParticlePtr) sub);
12882                            sub = sub->next;
12883                        }
12884                        if (particle->minOccurs == 0) {
12885                            xmlAutomataNewEpsilon(pctxt->am, oldstate,
12886                                                  pctxt->state);
12887                        }
12888                    }
12889                }
12890                break;
12891            }
12892        case XML_SCHEMA_TYPE_CHOICE:{
12893                xmlSchemaTreeItemPtr sub;
12894                xmlAutomataStatePtr start, end;
12895
12896                start = pctxt->state;
12897                end = xmlAutomataNewState(pctxt->am);
12898
12899                /*
12900                 * iterate over the subtypes and remerge the end with an
12901                 * epsilon transition
12902                 */
12903                if (particle->maxOccurs == 1) {
12904		    sub = particle->children->children;
12905                    while (sub != NULL) {
12906                        pctxt->state = start;
12907                        xmlSchemaBuildAContentModel(pctxt,
12908			    (xmlSchemaParticlePtr) sub);
12909                        xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12910                        sub = sub->next;
12911                    }
12912                } else {
12913                    int counter;
12914                    xmlAutomataStatePtr hop, base;
12915                    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12916                        UNBOUNDED : particle->maxOccurs - 1;
12917                    int minOccurs =
12918                        particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12919
12920                    /*
12921                     * use a counter to keep track of the number of transtions
12922                     * which went through the choice.
12923                     */
12924                    counter =
12925                        xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12926                    hop = xmlAutomataNewState(pctxt->am);
12927                    base = xmlAutomataNewState(pctxt->am);
12928
12929		    sub = particle->children->children;
12930                    while (sub != NULL) {
12931                        pctxt->state = base;
12932                        xmlSchemaBuildAContentModel(pctxt,
12933			    (xmlSchemaParticlePtr) sub);
12934                        xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12935                        sub = sub->next;
12936                    }
12937                    xmlAutomataNewEpsilon(pctxt->am, start, base);
12938		    xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12939                    xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12940                }
12941                if (particle->minOccurs == 0) {
12942                    xmlAutomataNewEpsilon(pctxt->am, start, end);
12943                }
12944                pctxt->state = end;
12945                break;
12946            }
12947        case XML_SCHEMA_TYPE_ALL:{
12948                xmlAutomataStatePtr start;
12949		xmlSchemaParticlePtr sub;
12950		xmlSchemaElementPtr elemDecl;
12951                int lax;
12952
12953		sub = (xmlSchemaParticlePtr) particle->children->children;
12954                if (sub == NULL)
12955                    break;
12956                start = pctxt->state;
12957                while (sub != NULL) {
12958                    pctxt->state = start;
12959
12960		    elemDecl = (xmlSchemaElementPtr) sub->children;
12961		    if (elemDecl == NULL) {
12962			PERROR_INT("xmlSchemaBuildAContentModel",
12963			    "<element> particle has no term");
12964			return;
12965		    };
12966		    /*
12967		    * NOTE: The {max occurs} of all the particles in the
12968		    * {particles} of the group must be 0 or 1; this is
12969		    * already ensured during the parse of the content of
12970		    * <all>.
12971		    */
12972		    if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12973			int counter;
12974
12975		        /*
12976			 * This is an abstract group, we need to share
12977			 * the same counter for all the element transitions
12978			 * derived from the group
12979			 */
12980			counter = xmlAutomataNewCounter(pctxt->am,
12981			                   sub->minOccurs, sub->maxOccurs);
12982			xmlSchemaBuildContentModelForSubstGroup(pctxt,
12983					   sub, counter, pctxt->state);
12984		    } else {
12985			if ((sub->minOccurs == 1) &&
12986			    (sub->maxOccurs == 1)) {
12987			    xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12988						    pctxt->state,
12989						    elemDecl->name,
12990						    elemDecl->targetNamespace,
12991						    1, 1, elemDecl);
12992			} else if ((sub->minOccurs == 0) &&
12993			    (sub->maxOccurs == 1)) {
12994
12995			    xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12996						     pctxt->state,
12997						     elemDecl->name,
12998						     elemDecl->targetNamespace,
12999						     0,
13000						     1,
13001						     elemDecl);
13002			}
13003		    }
13004                    sub = (xmlSchemaParticlePtr) sub->next;
13005                }
13006                lax = particle->minOccurs == 0;
13007                pctxt->state =
13008                    xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
13009                break;
13010            }
13011	case XML_SCHEMA_TYPE_GROUP:
13012	    /*
13013	    * If we hit a model group definition, then this means that
13014	    * it was empty, thus was not substituted for the containing
13015	    * model group. Just do nothing in this case.
13016	    * TODO: But the group should be substituted and not occur at
13017	    * all in the content model at this point. Fix this.
13018	    */
13019	    break;
13020        default:
13021	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13022		"xmlSchemaBuildAContentModel",
13023		"found unexpected term of type '%s' in content model",
13024		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13025            return;
13026    }
13027}
13028
13029/**
13030 * xmlSchemaBuildContentModel:
13031 * @ctxt:  the schema parser context
13032 * @type:  the complex type definition
13033 * @name:  the element name
13034 *
13035 * Builds the content model of the complex type.
13036 */
13037static void
13038xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13039			   xmlSchemaParserCtxtPtr ctxt)
13040{
13041    if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13042	(type->contModel != NULL) ||
13043	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13044	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13045	return;
13046
13047#ifdef DEBUG_CONTENT
13048    xmlGenericError(xmlGenericErrorContext,
13049                    "Building content model for %s\n", name);
13050#endif
13051    ctxt->am = NULL;
13052    ctxt->am = xmlNewAutomata();
13053    if (ctxt->am == NULL) {
13054        xmlGenericError(xmlGenericErrorContext,
13055	    "Cannot create automata for complex type %s\n", type->name);
13056        return;
13057    }
13058    ctxt->state = xmlAutomataGetInitState(ctxt->am);
13059    /*
13060    * Build the automaton.
13061    */
13062    xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13063    xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13064    type->contModel = xmlAutomataCompile(ctxt->am);
13065    if (type->contModel == NULL) {
13066        xmlSchemaPCustomErr(ctxt,
13067	    XML_SCHEMAP_INTERNAL,
13068	    WXS_BASIC_CAST type, type->node,
13069	    "Failed to compile the content model", NULL);
13070    } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13071        xmlSchemaPCustomErr(ctxt,
13072	    XML_SCHEMAP_NOT_DETERMINISTIC,
13073	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13074	    WXS_BASIC_CAST type, type->node,
13075	    "The content model is not determinist", NULL);
13076    } else {
13077#ifdef DEBUG_CONTENT_REGEXP
13078        xmlGenericError(xmlGenericErrorContext,
13079                        "Content model of %s:\n", type->name);
13080        xmlRegexpPrint(stderr, type->contModel);
13081#endif
13082    }
13083    ctxt->state = NULL;
13084    xmlFreeAutomata(ctxt->am);
13085    ctxt->am = NULL;
13086}
13087
13088/**
13089 * xmlSchemaResolveElementReferences:
13090 * @elem:  the schema element context
13091 * @ctxt:  the schema parser context
13092 *
13093 * Resolves the references of an element declaration
13094 * or particle, which has an element declaration as it's
13095 * term.
13096 */
13097static void
13098xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13099				  xmlSchemaParserCtxtPtr ctxt)
13100{
13101    if ((ctxt == NULL) || (elemDecl == NULL) ||
13102	((elemDecl != NULL) &&
13103	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13104        return;
13105    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13106
13107    if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13108	xmlSchemaTypePtr type;
13109
13110	/* (type definition) ... otherwise the type definition �resolved�
13111	* to by the �actual value� of the type [attribute] ...
13112	*/
13113	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13114	    elemDecl->namedTypeNs);
13115	if (type == NULL) {
13116	    xmlSchemaPResCompAttrErr(ctxt,
13117		XML_SCHEMAP_SRC_RESOLVE,
13118		WXS_BASIC_CAST elemDecl, elemDecl->node,
13119		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13120		XML_SCHEMA_TYPE_BASIC, "type definition");
13121	} else
13122	    elemDecl->subtypes = type;
13123    }
13124    if (elemDecl->substGroup != NULL) {
13125	xmlSchemaElementPtr substHead;
13126
13127	/*
13128	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13129	* substitutionGroup?
13130	*/
13131	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13132	    elemDecl->substGroupNs);
13133	if (substHead == NULL) {
13134	    xmlSchemaPResCompAttrErr(ctxt,
13135		XML_SCHEMAP_SRC_RESOLVE,
13136		WXS_BASIC_CAST elemDecl, NULL,
13137		"substitutionGroup", elemDecl->substGroup,
13138		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13139	} else {
13140	    xmlSchemaResolveElementReferences(substHead, ctxt);
13141	    /*
13142	    * Set the "substitution group affiliation".
13143	    * NOTE that now we use the "refDecl" field for this.
13144	    */
13145	    WXS_SUBST_HEAD(elemDecl) = substHead;
13146	    /*
13147	    * The type definitions is set to:
13148	    * SPEC "...the {type definition} of the element
13149	    * declaration �resolved� to by the �actual value�
13150	    * of the substitutionGroup [attribute], if present"
13151	    */
13152	    if (elemDecl->subtypes == NULL)
13153		elemDecl->subtypes = substHead->subtypes;
13154	}
13155    }
13156    /*
13157    * SPEC "The definition of anyType serves as the default type definition
13158    * for element declarations whose XML representation does not specify one."
13159    */
13160    if ((elemDecl->subtypes == NULL) &&
13161	(elemDecl->namedType == NULL) &&
13162	(elemDecl->substGroup == NULL))
13163	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13164}
13165
13166/**
13167 * xmlSchemaResolveUnionMemberTypes:
13168 * @ctxt:  the schema parser context
13169 * @type:  the schema simple type definition
13170 *
13171 * Checks and builds the "member type definitions" property of the union
13172 * simple type. This handles part (1), part (2) is done in
13173 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13174 *
13175 * Returns -1 in case of an internal error, 0 otherwise.
13176 */
13177static int
13178xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13179				 xmlSchemaTypePtr type)
13180{
13181
13182    xmlSchemaTypeLinkPtr link, lastLink, newLink;
13183    xmlSchemaTypePtr memberType;
13184
13185    /*
13186    * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13187    * define the explicit members as the type definitions �resolved�
13188    * to by the items in the �actual value� of the memberTypes [attribute],
13189    * if any, followed by the type definitions corresponding to the
13190    * <simpleType>s among the [children] of <union>, if any."
13191    */
13192    /*
13193    * Resolve references.
13194    */
13195    link = type->memberTypes;
13196    lastLink = NULL;
13197    while (link != NULL) {
13198	const xmlChar *name, *nsName;
13199
13200	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13201	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13202
13203	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13204	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13205	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13206		WXS_BASIC_CAST type, type->node, "memberTypes",
13207		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13208	    /*
13209	    * Remove the member type link.
13210	    */
13211	    if (lastLink == NULL)
13212		type->memberTypes = link->next;
13213	    else
13214		lastLink->next = link->next;
13215	    newLink = link;
13216	    link = link->next;
13217	    xmlFree(newLink);
13218	} else {
13219	    link->type = memberType;
13220	    lastLink = link;
13221	    link = link->next;
13222	}
13223    }
13224    /*
13225    * Add local simple types,
13226    */
13227    memberType = type->subtypes;
13228    while (memberType != NULL) {
13229	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13230	if (link == NULL) {
13231	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13232	    return (-1);
13233	}
13234	link->type = memberType;
13235	link->next = NULL;
13236	if (lastLink == NULL)
13237	    type->memberTypes = link;
13238	else
13239	    lastLink->next = link;
13240	lastLink = link;
13241	memberType = memberType->next;
13242    }
13243    return (0);
13244}
13245
13246/**
13247 * xmlSchemaIsDerivedFromBuiltInType:
13248 * @ctxt:  the schema parser context
13249 * @type:  the type definition
13250 * @valType: the value type
13251 *
13252 *
13253 * Returns 1 if the type has the given value type, or
13254 * is derived from such a type.
13255 */
13256static int
13257xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13258{
13259    if (type == NULL)
13260	return (0);
13261    if (WXS_IS_COMPLEX(type))
13262	return (0);
13263    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13264	if (type->builtInType == valType)
13265	    return(1);
13266	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13267	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13268	    return (0);
13269	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13270    }
13271    return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13272}
13273
13274#if 0
13275/**
13276 * xmlSchemaIsDerivedFromBuiltInType:
13277 * @ctxt:  the schema parser context
13278 * @type:  the type definition
13279 * @valType: the value type
13280 *
13281 *
13282 * Returns 1 if the type has the given value type, or
13283 * is derived from such a type.
13284 */
13285static int
13286xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13287{
13288    if (type == NULL)
13289	return (0);
13290    if (WXS_IS_COMPLEX(type))
13291	return (0);
13292    if (type->type == XML_SCHEMA_TYPE_BASIC) {
13293	if (type->builtInType == valType)
13294	    return(1);
13295	return (0);
13296    } else
13297	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13298
13299    return (0);
13300}
13301#endif
13302
13303static xmlSchemaTypePtr
13304xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13305{
13306    if (type == NULL)
13307	return (NULL);
13308    if (WXS_IS_COMPLEX(type))
13309	return (NULL);
13310    if (type->type == XML_SCHEMA_TYPE_BASIC)
13311	return(type);
13312    return(xmlSchemaQueryBuiltInType(type->subtypes));
13313}
13314
13315/**
13316 * xmlSchemaGetPrimitiveType:
13317 * @type:  the simpleType definition
13318 *
13319 * Returns the primitive type of the given type or
13320 * NULL in case of error.
13321 */
13322static xmlSchemaTypePtr
13323xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13324{
13325
13326    while (type != NULL) {
13327	/*
13328	* Note that anySimpleType is actually not a primitive type
13329	* but we need that here.
13330	*/
13331	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13332	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13333	    return (type);
13334	type = type->baseType;
13335    }
13336
13337    return (NULL);
13338}
13339
13340#if 0
13341/**
13342 * xmlSchemaGetBuiltInTypeAncestor:
13343 * @type:  the simpleType definition
13344 *
13345 * Returns the primitive type of the given type or
13346 * NULL in case of error.
13347 */
13348static xmlSchemaTypePtr
13349xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13350{
13351    if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13352	return (0);
13353    while (type != NULL) {
13354	if (type->type == XML_SCHEMA_TYPE_BASIC)
13355	    return (type);
13356	type = type->baseType;
13357    }
13358
13359    return (NULL);
13360}
13361#endif
13362
13363/**
13364 * xmlSchemaCloneWildcardNsConstraints:
13365 * @ctxt:  the schema parser context
13366 * @dest:  the destination wildcard
13367 * @source: the source wildcard
13368 *
13369 * Clones the namespace constraints of source
13370 * and assignes them to dest.
13371 * Returns -1 on internal error, 0 otherwise.
13372 */
13373static int
13374xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13375				    xmlSchemaWildcardPtr dest,
13376				    xmlSchemaWildcardPtr source)
13377{
13378    xmlSchemaWildcardNsPtr cur, tmp, last;
13379
13380    if ((source == NULL) || (dest == NULL))
13381	return(-1);
13382    dest->any = source->any;
13383    cur = source->nsSet;
13384    last = NULL;
13385    while (cur != NULL) {
13386	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13387	if (tmp == NULL)
13388	    return(-1);
13389	tmp->value = cur->value;
13390	if (last == NULL)
13391	    dest->nsSet = tmp;
13392	else
13393	    last->next = tmp;
13394	last = tmp;
13395	cur = cur->next;
13396    }
13397    if (dest->negNsSet != NULL)
13398	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13399    if (source->negNsSet != NULL) {
13400	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13401	if (dest->negNsSet == NULL)
13402	    return(-1);
13403	dest->negNsSet->value = source->negNsSet->value;
13404    } else
13405	dest->negNsSet = NULL;
13406    return(0);
13407}
13408
13409/**
13410 * xmlSchemaUnionWildcards:
13411 * @ctxt:  the schema parser context
13412 * @completeWild:  the first wildcard
13413 * @curWild: the second wildcard
13414 *
13415 * Unions the namespace constraints of the given wildcards.
13416 * @completeWild will hold the resulting union.
13417 * Returns a positive error code on failure, -1 in case of an
13418 * internal error, 0 otherwise.
13419 */
13420static int
13421xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13422			    xmlSchemaWildcardPtr completeWild,
13423			    xmlSchemaWildcardPtr curWild)
13424{
13425    xmlSchemaWildcardNsPtr cur, curB, tmp;
13426
13427    /*
13428    * 1 If O1 and O2 are the same value, then that value must be the
13429    * value.
13430    */
13431    if ((completeWild->any == curWild->any) &&
13432	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13433	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13434
13435	if ((completeWild->negNsSet == NULL) ||
13436	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13437
13438	    if (completeWild->nsSet != NULL) {
13439		int found = 0;
13440
13441		/*
13442		* Check equality of sets.
13443		*/
13444		cur = completeWild->nsSet;
13445		while (cur != NULL) {
13446		    found = 0;
13447		    curB = curWild->nsSet;
13448		    while (curB != NULL) {
13449			if (cur->value == curB->value) {
13450			    found = 1;
13451			    break;
13452			}
13453			curB = curB->next;
13454		    }
13455		    if (!found)
13456			break;
13457		    cur = cur->next;
13458		}
13459		if (found)
13460		    return(0);
13461	    } else
13462		return(0);
13463	}
13464    }
13465    /*
13466    * 2 If either O1 or O2 is any, then any must be the value
13467    */
13468    if (completeWild->any != curWild->any) {
13469	if (completeWild->any == 0) {
13470	    completeWild->any = 1;
13471	    if (completeWild->nsSet != NULL) {
13472		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13473		completeWild->nsSet = NULL;
13474	    }
13475	    if (completeWild->negNsSet != NULL) {
13476		xmlFree(completeWild->negNsSet);
13477		completeWild->negNsSet = NULL;
13478	    }
13479	}
13480	return (0);
13481    }
13482    /*
13483    * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13484    * then the union of those sets must be the value.
13485    */
13486    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13487	int found;
13488	xmlSchemaWildcardNsPtr start;
13489
13490	cur = curWild->nsSet;
13491	start = completeWild->nsSet;
13492	while (cur != NULL) {
13493	    found = 0;
13494	    curB = start;
13495	    while (curB != NULL) {
13496		if (cur->value == curB->value) {
13497		    found = 1;
13498		    break;
13499		}
13500		curB = curB->next;
13501	    }
13502	    if (!found) {
13503		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13504		if (tmp == NULL)
13505		    return (-1);
13506		tmp->value = cur->value;
13507		tmp->next = completeWild->nsSet;
13508		completeWild->nsSet = tmp;
13509	    }
13510	    cur = cur->next;
13511	}
13512
13513	return(0);
13514    }
13515    /*
13516    * 4 If the two are negations of different values (namespace names
13517    * or �absent�), then a pair of not and �absent� must be the value.
13518    */
13519    if ((completeWild->negNsSet != NULL) &&
13520	(curWild->negNsSet != NULL) &&
13521	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13522	completeWild->negNsSet->value = NULL;
13523
13524	return(0);
13525    }
13526    /*
13527     * 5.
13528     */
13529    if (((completeWild->negNsSet != NULL) &&
13530	(completeWild->negNsSet->value != NULL) &&
13531	(curWild->nsSet != NULL)) ||
13532	((curWild->negNsSet != NULL) &&
13533	(curWild->negNsSet->value != NULL) &&
13534	(completeWild->nsSet != NULL))) {
13535
13536	int nsFound, absentFound = 0;
13537
13538	if (completeWild->nsSet != NULL) {
13539	    cur = completeWild->nsSet;
13540	    curB = curWild->negNsSet;
13541	} else {
13542	    cur = curWild->nsSet;
13543	    curB = completeWild->negNsSet;
13544	}
13545	nsFound = 0;
13546	while (cur != NULL) {
13547	    if (cur->value == NULL)
13548		absentFound = 1;
13549	    else if (cur->value == curB->value)
13550		nsFound = 1;
13551	    if (nsFound && absentFound)
13552		break;
13553	    cur = cur->next;
13554	}
13555
13556	if (nsFound && absentFound) {
13557	    /*
13558	    * 5.1 If the set S includes both the negated namespace
13559	    * name and �absent�, then any must be the value.
13560	    */
13561	    completeWild->any = 1;
13562	    if (completeWild->nsSet != NULL) {
13563		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13564		completeWild->nsSet = NULL;
13565	    }
13566	    if (completeWild->negNsSet != NULL) {
13567		xmlFree(completeWild->negNsSet);
13568		completeWild->negNsSet = NULL;
13569	    }
13570	} else if (nsFound && (!absentFound)) {
13571	    /*
13572	    * 5.2 If the set S includes the negated namespace name
13573	    * but not �absent�, then a pair of not and �absent� must
13574	    * be the value.
13575	    */
13576	    if (completeWild->nsSet != NULL) {
13577		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13578		completeWild->nsSet = NULL;
13579	    }
13580	    if (completeWild->negNsSet == NULL) {
13581		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13582		if (completeWild->negNsSet == NULL)
13583		    return (-1);
13584	    }
13585	    completeWild->negNsSet->value = NULL;
13586	} else if ((!nsFound) && absentFound) {
13587	    /*
13588	    * 5.3 If the set S includes �absent� but not the negated
13589	    * namespace name, then the union is not expressible.
13590	    */
13591	    xmlSchemaPErr(ctxt, completeWild->node,
13592		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13593		"The union of the wilcard is not expressible.\n",
13594		NULL, NULL);
13595	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13596	} else if ((!nsFound) && (!absentFound)) {
13597	    /*
13598	    * 5.4 If the set S does not include either the negated namespace
13599	    * name or �absent�, then whichever of O1 or O2 is a pair of not
13600	    * and a namespace name must be the value.
13601	    */
13602	    if (completeWild->negNsSet == NULL) {
13603		if (completeWild->nsSet != NULL) {
13604		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13605		    completeWild->nsSet = NULL;
13606		}
13607		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13608		if (completeWild->negNsSet == NULL)
13609		    return (-1);
13610		completeWild->negNsSet->value = curWild->negNsSet->value;
13611	    }
13612	}
13613	return (0);
13614    }
13615    /*
13616     * 6.
13617     */
13618    if (((completeWild->negNsSet != NULL) &&
13619	(completeWild->negNsSet->value == NULL) &&
13620	(curWild->nsSet != NULL)) ||
13621	((curWild->negNsSet != NULL) &&
13622	(curWild->negNsSet->value == NULL) &&
13623	(completeWild->nsSet != NULL))) {
13624
13625	if (completeWild->nsSet != NULL) {
13626	    cur = completeWild->nsSet;
13627	} else {
13628	    cur = curWild->nsSet;
13629	}
13630	while (cur != NULL) {
13631	    if (cur->value == NULL) {
13632		/*
13633		* 6.1 If the set S includes �absent�, then any must be the
13634		* value.
13635		*/
13636		completeWild->any = 1;
13637		if (completeWild->nsSet != NULL) {
13638		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13639		    completeWild->nsSet = NULL;
13640		}
13641		if (completeWild->negNsSet != NULL) {
13642		    xmlFree(completeWild->negNsSet);
13643		    completeWild->negNsSet = NULL;
13644		}
13645		return (0);
13646	    }
13647	    cur = cur->next;
13648	}
13649	if (completeWild->negNsSet == NULL) {
13650	    /*
13651	    * 6.2 If the set S does not include �absent�, then a pair of not
13652	    * and �absent� must be the value.
13653	    */
13654	    if (completeWild->nsSet != NULL) {
13655		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13656		completeWild->nsSet = NULL;
13657	    }
13658	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13659	    if (completeWild->negNsSet == NULL)
13660		return (-1);
13661	    completeWild->negNsSet->value = NULL;
13662	}
13663	return (0);
13664    }
13665    return (0);
13666
13667}
13668
13669/**
13670 * xmlSchemaIntersectWildcards:
13671 * @ctxt:  the schema parser context
13672 * @completeWild:  the first wildcard
13673 * @curWild: the second wildcard
13674 *
13675 * Intersects the namespace constraints of the given wildcards.
13676 * @completeWild will hold the resulting intersection.
13677 * Returns a positive error code on failure, -1 in case of an
13678 * internal error, 0 otherwise.
13679 */
13680static int
13681xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13682			    xmlSchemaWildcardPtr completeWild,
13683			    xmlSchemaWildcardPtr curWild)
13684{
13685    xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13686
13687    /*
13688    * 1 If O1 and O2 are the same value, then that value must be the
13689    * value.
13690    */
13691    if ((completeWild->any == curWild->any) &&
13692	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13693	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13694
13695	if ((completeWild->negNsSet == NULL) ||
13696	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13697
13698	    if (completeWild->nsSet != NULL) {
13699		int found = 0;
13700
13701		/*
13702		* Check equality of sets.
13703		*/
13704		cur = completeWild->nsSet;
13705		while (cur != NULL) {
13706		    found = 0;
13707		    curB = curWild->nsSet;
13708		    while (curB != NULL) {
13709			if (cur->value == curB->value) {
13710			    found = 1;
13711			    break;
13712			}
13713			curB = curB->next;
13714		    }
13715		    if (!found)
13716			break;
13717		    cur = cur->next;
13718		}
13719		if (found)
13720		    return(0);
13721	    } else
13722		return(0);
13723	}
13724    }
13725    /*
13726    * 2 If either O1 or O2 is any, then the other must be the value.
13727    */
13728    if ((completeWild->any != curWild->any) && (completeWild->any)) {
13729	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13730	    return(-1);
13731	return(0);
13732    }
13733    /*
13734    * 3 If either O1 or O2 is a pair of not and a value (a namespace
13735    * name or �absent�) and the other is a set of (namespace names or
13736    * �absent�), then that set, minus the negated value if it was in
13737    * the set, minus �absent� if it was in the set, must be the value.
13738    */
13739    if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13740	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13741	const xmlChar *neg;
13742
13743	if (completeWild->nsSet == NULL) {
13744	    neg = completeWild->negNsSet->value;
13745	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13746		return(-1);
13747	} else
13748	    neg = curWild->negNsSet->value;
13749	/*
13750	* Remove absent and negated.
13751	*/
13752	prev = NULL;
13753	cur = completeWild->nsSet;
13754	while (cur != NULL) {
13755	    if (cur->value == NULL) {
13756		if (prev == NULL)
13757		    completeWild->nsSet = cur->next;
13758		else
13759		    prev->next = cur->next;
13760		xmlFree(cur);
13761		break;
13762	    }
13763	    prev = cur;
13764	    cur = cur->next;
13765	}
13766	if (neg != NULL) {
13767	    prev = NULL;
13768	    cur = completeWild->nsSet;
13769	    while (cur != NULL) {
13770		if (cur->value == neg) {
13771		    if (prev == NULL)
13772			completeWild->nsSet = cur->next;
13773		    else
13774			prev->next = cur->next;
13775		    xmlFree(cur);
13776		    break;
13777		}
13778		prev = cur;
13779		cur = cur->next;
13780	    }
13781	}
13782
13783	return(0);
13784    }
13785    /*
13786    * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13787    * then the intersection of those sets must be the value.
13788    */
13789    if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13790	int found;
13791
13792	cur = completeWild->nsSet;
13793	prev = NULL;
13794	while (cur != NULL) {
13795	    found = 0;
13796	    curB = curWild->nsSet;
13797	    while (curB != NULL) {
13798		if (cur->value == curB->value) {
13799		    found = 1;
13800		    break;
13801		}
13802		curB = curB->next;
13803	    }
13804	    if (!found) {
13805		if (prev == NULL)
13806		    completeWild->nsSet = cur->next;
13807		else
13808		    prev->next = cur->next;
13809		tmp = cur->next;
13810		xmlFree(cur);
13811		cur = tmp;
13812		continue;
13813	    }
13814	    prev = cur;
13815	    cur = cur->next;
13816	}
13817
13818	return(0);
13819    }
13820    /* 5 If the two are negations of different namespace names,
13821    * then the intersection is not expressible
13822    */
13823    if ((completeWild->negNsSet != NULL) &&
13824	(curWild->negNsSet != NULL) &&
13825	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13826	(completeWild->negNsSet->value != NULL) &&
13827	(curWild->negNsSet->value != NULL)) {
13828
13829	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13830	    "The intersection of the wilcard is not expressible.\n",
13831	    NULL, NULL);
13832	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13833    }
13834    /*
13835    * 6 If the one is a negation of a namespace name and the other
13836    * is a negation of �absent�, then the one which is the negation
13837    * of a namespace name must be the value.
13838    */
13839    if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13840	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13841	(completeWild->negNsSet->value == NULL)) {
13842	completeWild->negNsSet->value =  curWild->negNsSet->value;
13843    }
13844    return(0);
13845}
13846
13847/**
13848 * xmlSchemaIsWildcardNsConstraintSubset:
13849 * @ctxt:  the schema parser context
13850 * @sub:  the first wildcard
13851 * @super: the second wildcard
13852 *
13853 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13854 *
13855 * Returns 0 if the namespace constraint of @sub is an intensional
13856 * subset of @super, 1 otherwise.
13857 */
13858static int
13859xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13860			  xmlSchemaWildcardPtr super)
13861{
13862    /*
13863    * 1 super must be any.
13864    */
13865    if (super->any)
13866	return (0);
13867    /*
13868    * 2.1 sub must be a pair of not and a namespace name or �absent�.
13869    * 2.2 super must be a pair of not and the same value.
13870    */
13871    if ((sub->negNsSet != NULL) &&
13872	(super->negNsSet != NULL) &&
13873	(sub->negNsSet->value == sub->negNsSet->value))
13874	return (0);
13875    /*
13876    * 3.1 sub must be a set whose members are either namespace names or �absent�.
13877    */
13878    if (sub->nsSet != NULL) {
13879	/*
13880	* 3.2.1 super must be the same set or a superset thereof.
13881	*/
13882	if (super->nsSet != NULL) {
13883	    xmlSchemaWildcardNsPtr cur, curB;
13884	    int found = 0;
13885
13886	    cur = sub->nsSet;
13887	    while (cur != NULL) {
13888		found = 0;
13889		curB = super->nsSet;
13890		while (curB != NULL) {
13891		    if (cur->value == curB->value) {
13892			found = 1;
13893			break;
13894		    }
13895		    curB = curB->next;
13896		}
13897		if (!found)
13898		    return (1);
13899		cur = cur->next;
13900	    }
13901	    if (found)
13902		return (0);
13903	} else if (super->negNsSet != NULL) {
13904	    xmlSchemaWildcardNsPtr cur;
13905	    /*
13906	    * 3.2.2 super must be a pair of not and a namespace name or
13907	    * �absent� and that value must not be in sub's set.
13908	    */
13909	    cur = sub->nsSet;
13910	    while (cur != NULL) {
13911		if (cur->value == super->negNsSet->value)
13912		    return (1);
13913		cur = cur->next;
13914	    }
13915	    return (0);
13916	}
13917    }
13918    return (1);
13919}
13920
13921static int
13922xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13923				     int *fixed,
13924				     const xmlChar **value,
13925				     xmlSchemaValPtr *val)
13926{
13927    *fixed = 0;
13928    *value = NULL;
13929    if (val != 0)
13930	*val = NULL;
13931
13932    if (attruse->defValue != NULL) {
13933	*value = attruse->defValue;
13934	if (val != NULL)
13935	    *val = attruse->defVal;
13936	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
13937	    *fixed = 1;
13938	return(1);
13939    } else if ((attruse->attrDecl != NULL) &&
13940	(attruse->attrDecl->defValue != NULL)) {
13941	*value = attruse->attrDecl->defValue;
13942	if (val != NULL)
13943	    *val = attruse->attrDecl->defVal;
13944	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
13945	    *fixed = 1;
13946	return(1);
13947    }
13948    return(0);
13949}
13950/**
13951 * xmlSchemaCheckCVCWildcardNamespace:
13952 * @wild:  the wildcard
13953 * @ns:  the namespace
13954 *
13955 * Validation Rule: Wildcard allows Namespace Name
13956 * (cvc-wildcard-namespace)
13957 *
13958 * Returns 0 if the given namespace matches the wildcard,
13959 * 1 otherwise and -1 on API errors.
13960 */
13961static int
13962xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13963				   const xmlChar* ns)
13964{
13965    if (wild == NULL)
13966	return(-1);
13967
13968    if (wild->any)
13969	return(0);
13970    else if (wild->nsSet != NULL) {
13971	xmlSchemaWildcardNsPtr cur;
13972
13973	cur = wild->nsSet;
13974	while (cur != NULL) {
13975	    if (xmlStrEqual(cur->value, ns))
13976		return(0);
13977	    cur = cur->next;
13978	}
13979    } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
13980	(!xmlStrEqual(wild->negNsSet->value, ns)))
13981	return(0);
13982
13983    return(1);
13984}
13985
13986#define XML_SCHEMA_ACTION_DERIVE 0
13987#define XML_SCHEMA_ACTION_REDEFINE 1
13988
13989#define WXS_ACTION_STR(a) \
13990((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13991
13992/*
13993* Schema Component Constraint:
13994*   Derivation Valid (Restriction, Complex)
13995*   derivation-ok-restriction (2) - (4)
13996*
13997* ATTENTION:
13998* In XML Schema 1.1 this will be:
13999* Validation Rule:
14000*     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14001*
14002*/
14003static int
14004xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14005				       int action,
14006				       xmlSchemaBasicItemPtr item,
14007				       xmlSchemaBasicItemPtr baseItem,
14008				       xmlSchemaItemListPtr uses,
14009				       xmlSchemaItemListPtr baseUses,
14010				       xmlSchemaWildcardPtr wild,
14011				       xmlSchemaWildcardPtr baseWild)
14012{
14013    xmlSchemaAttributeUsePtr cur = NULL, bcur;
14014    int i, j, found; /* err = 0; */
14015    const xmlChar *bEffValue;
14016    int effFixed;
14017
14018    if (uses != NULL) {
14019	for (i = 0; i < uses->nbItems; i++) {
14020	    cur = uses->items[i];
14021	    found = 0;
14022	    if (baseUses == NULL)
14023		goto not_found;
14024	    for (j = 0; j < baseUses->nbItems; j++) {
14025		bcur = baseUses->items[j];
14026		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14027			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14028		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14029			WXS_ATTRUSE_DECL_TNS(bcur)))
14030		{
14031		    /*
14032		    * (2.1) "If there is an attribute use in the {attribute
14033		    * uses} of the {base type definition} (call this B) whose
14034		    * {attribute declaration} has the same {name} and {target
14035		    * namespace}, then  all of the following must be true:"
14036		    */
14037		    found = 1;
14038
14039		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14040			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14041		    {
14042			xmlChar *str = NULL;
14043			/*
14044			* (2.1.1) "one of the following must be true:"
14045			* (2.1.1.1) "B's {required} is false."
14046			* (2.1.1.2) "R's {required} is true."
14047			*/
14048			xmlSchemaPAttrUseErr4(pctxt,
14049			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14050			    WXS_ITEM_NODE(item), item, cur,
14051			    "The 'optional' attribute use is inconsistent "
14052			    "with the corresponding 'required' attribute use of "
14053			    "the %s %s",
14054			    WXS_ACTION_STR(action),
14055			    xmlSchemaGetComponentDesignation(&str, baseItem),
14056			    NULL, NULL);
14057			FREE_AND_NULL(str);
14058			/* err = pctxt->err; */
14059		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14060			WXS_ATTRUSE_TYPEDEF(cur),
14061			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14062		    {
14063			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14064
14065			/*
14066			* SPEC (2.1.2) "R's {attribute declaration}'s
14067			* {type definition} must be validly derived from
14068			* B's {type definition} given the empty set as
14069			* defined in Type Derivation OK (Simple) (�3.14.6)."
14070			*/
14071			xmlSchemaPAttrUseErr4(pctxt,
14072			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14073			    WXS_ITEM_NODE(item), item, cur,
14074			    "The attribute declaration's %s "
14075			    "is not validly derived from "
14076			    "the corresponding %s of the "
14077			    "attribute declaration in the %s %s",
14078			    xmlSchemaGetComponentDesignation(&strA,
14079				WXS_ATTRUSE_TYPEDEF(cur)),
14080			    xmlSchemaGetComponentDesignation(&strB,
14081				WXS_ATTRUSE_TYPEDEF(bcur)),
14082			    WXS_ACTION_STR(action),
14083			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14084			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14085			FREE_AND_NULL(strA);
14086			FREE_AND_NULL(strB);
14087			FREE_AND_NULL(strC);
14088			/* err = pctxt->err; */
14089		    } else {
14090			/*
14091			* 2.1.3 [Definition:]  Let the effective value
14092			* constraint of an attribute use be its {value
14093			* constraint}, if present, otherwise its {attribute
14094			* declaration}'s {value constraint} .
14095			*/
14096			xmlSchemaGetEffectiveValueConstraint(bcur,
14097			    &effFixed, &bEffValue, NULL);
14098			/*
14099			* 2.1.3 ... one of the following must be true
14100			*
14101			* 2.1.3.1 B's �effective value constraint� is
14102			* �absent� or default.
14103			*/
14104			if ((bEffValue != NULL) &&
14105			    (effFixed == 1)) {
14106			    const xmlChar *rEffValue = NULL;
14107
14108			    xmlSchemaGetEffectiveValueConstraint(bcur,
14109				&effFixed, &rEffValue, NULL);
14110			    /*
14111			    * 2.1.3.2 R's �effective value constraint� is
14112			    * fixed with the same string as B's.
14113			    * MAYBE TODO: Compare the computed values.
14114			    *       Hmm, it says "same string" so
14115			    *       string-equality might really be sufficient.
14116			    */
14117			    if ((effFixed == 0) ||
14118				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14119			    {
14120				xmlChar *str = NULL;
14121
14122				xmlSchemaPAttrUseErr4(pctxt,
14123				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14124				    WXS_ITEM_NODE(item), item, cur,
14125				    "The effective value constraint of the "
14126				    "attribute use is inconsistent with "
14127				    "its correspondent in the %s %s",
14128				    WXS_ACTION_STR(action),
14129				    xmlSchemaGetComponentDesignation(&str,
14130					baseItem),
14131				    NULL, NULL);
14132				FREE_AND_NULL(str);
14133				/* err = pctxt->err; */
14134			    }
14135			}
14136		    }
14137		    break;
14138		}
14139	    }
14140not_found:
14141	    if (!found) {
14142		/*
14143		* (2.2) "otherwise the {base type definition} must have an
14144		* {attribute wildcard} and the {target namespace} of the
14145		* R's {attribute declaration} must be �valid� with respect
14146		* to that wildcard, as defined in Wildcard allows Namespace
14147		* Name (�3.10.4)."
14148		*/
14149		if ((baseWild == NULL) ||
14150		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14151		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14152		{
14153		    xmlChar *str = NULL;
14154
14155		    xmlSchemaPAttrUseErr4(pctxt,
14156			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14157			WXS_ITEM_NODE(item), item, cur,
14158			"Neither a matching attribute use, "
14159			"nor a matching wildcard exists in the %s %s",
14160			WXS_ACTION_STR(action),
14161			xmlSchemaGetComponentDesignation(&str, baseItem),
14162			NULL, NULL);
14163		    FREE_AND_NULL(str);
14164		    /* err = pctxt->err; */
14165		}
14166	    }
14167	}
14168    }
14169    /*
14170    * SPEC derivation-ok-restriction (3):
14171    * (3) "For each attribute use in the {attribute uses} of the {base type
14172    * definition} whose {required} is true, there must be an attribute
14173    * use with an {attribute declaration} with the same {name} and
14174    * {target namespace} as its {attribute declaration} in the {attribute
14175    * uses} of the complex type definition itself whose {required} is true.
14176    */
14177    if (baseUses != NULL) {
14178	for (j = 0; j < baseUses->nbItems; j++) {
14179	    bcur = baseUses->items[j];
14180	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14181		continue;
14182	    found = 0;
14183	    if (uses != NULL) {
14184		for (i = 0; i < uses->nbItems; i++) {
14185		    cur = uses->items[i];
14186		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14187			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14188			(WXS_ATTRUSE_DECL_TNS(cur) ==
14189			WXS_ATTRUSE_DECL_TNS(bcur))) {
14190			found = 1;
14191			break;
14192		    }
14193		}
14194	    }
14195	    if (!found) {
14196		xmlChar *strA = NULL, *strB = NULL;
14197
14198		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14199		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14200		    NULL, item,
14201		    "A matching attribute use for the "
14202		    "'required' %s of the %s %s is missing",
14203		    xmlSchemaGetComponentDesignation(&strA, bcur),
14204		    WXS_ACTION_STR(action),
14205		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14206		    NULL);
14207		FREE_AND_NULL(strA);
14208		FREE_AND_NULL(strB);
14209	    }
14210	}
14211    }
14212    /*
14213    * derivation-ok-restriction (4)
14214    */
14215    if (wild != NULL) {
14216	/*
14217	* (4) "If there is an {attribute wildcard}, all of the
14218	* following must be true:"
14219	*/
14220	if (baseWild == NULL) {
14221	    xmlChar *str = NULL;
14222
14223	    /*
14224	    * (4.1) "The {base type definition} must also have one."
14225	    */
14226	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14227		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14228		NULL, item,
14229		"The %s has an attribute wildcard, "
14230		"but the %s %s '%s' does not have one",
14231		WXS_ITEM_TYPE_NAME(item),
14232		WXS_ACTION_STR(action),
14233		WXS_ITEM_TYPE_NAME(baseItem),
14234		xmlSchemaGetComponentQName(&str, baseItem));
14235	    FREE_AND_NULL(str);
14236	    return(pctxt->err);
14237	} else if ((baseWild->any == 0) &&
14238		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14239	{
14240	    xmlChar *str = NULL;
14241	    /*
14242	    * (4.2) "The complex type definition's {attribute wildcard}'s
14243	    * {namespace constraint} must be a subset of the {base type
14244	    * definition}'s {attribute wildcard}'s {namespace constraint},
14245	    * as defined by Wildcard Subset (�3.10.6)."
14246	    */
14247	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14248		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14249		NULL, item,
14250		"The attribute wildcard is not a valid "
14251		"subset of the wildcard in the %s %s '%s'",
14252		WXS_ACTION_STR(action),
14253		WXS_ITEM_TYPE_NAME(baseItem),
14254		xmlSchemaGetComponentQName(&str, baseItem),
14255		NULL);
14256	    FREE_AND_NULL(str);
14257	    return(pctxt->err);
14258	}
14259	/* 4.3 Unless the {base type definition} is the �ur-type
14260	* definition�, the complex type definition's {attribute
14261	* wildcard}'s {process contents} must be identical to or
14262	* stronger than the {base type definition}'s {attribute
14263	* wildcard}'s {process contents}, where strict is stronger
14264	* than lax is stronger than skip.
14265	*/
14266	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14267	    (wild->processContents < baseWild->processContents)) {
14268	    xmlChar *str = NULL;
14269	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14270		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14271		NULL, baseItem,
14272		"The {process contents} of the attribute wildcard is "
14273		"weaker than the one in the %s %s '%s'",
14274		WXS_ACTION_STR(action),
14275		WXS_ITEM_TYPE_NAME(baseItem),
14276		xmlSchemaGetComponentQName(&str, baseItem),
14277		NULL);
14278	    FREE_AND_NULL(str)
14279		return(pctxt->err);
14280	}
14281    }
14282    return(0);
14283}
14284
14285
14286static int
14287xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14288				  xmlSchemaBasicItemPtr item,
14289				  xmlSchemaWildcardPtr *completeWild,
14290				  xmlSchemaItemListPtr list,
14291				  xmlSchemaItemListPtr prohibs);
14292/**
14293 * xmlSchemaFixupTypeAttributeUses:
14294 * @ctxt:  the schema parser context
14295 * @type:  the complex type definition
14296 *
14297 *
14298 * Builds the wildcard and the attribute uses on the given complex type.
14299 * Returns -1 if an internal error occurs, 0 otherwise.
14300 *
14301 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14302 * strings, so recheck this if we start to hardcode some schemata, since
14303 * they might not be in the same dict.
14304 * NOTE: It is allowed to "extend" the xs:anyType type.
14305 */
14306static int
14307xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14308				  xmlSchemaTypePtr type)
14309{
14310    xmlSchemaTypePtr baseType = NULL;
14311    xmlSchemaAttributeUsePtr use;
14312    xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14313
14314    if (type->baseType == NULL) {
14315	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14316	    "no base type");
14317        return (-1);
14318    }
14319    baseType = type->baseType;
14320    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14321	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14322	    return(-1);
14323
14324    uses = type->attrUses;
14325    baseUses = baseType->attrUses;
14326    /*
14327    * Expand attribute group references. And build the 'complete'
14328    * wildcard, i.e. intersect multiple wildcards.
14329    * Move attribute prohibitions into a separate list.
14330    */
14331    if (uses != NULL) {
14332	if (WXS_IS_RESTRICTION(type)) {
14333	    /*
14334	    * This one will transfer all attr. prohibitions
14335	    * into pctxt->attrProhibs.
14336	    */
14337	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14338		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14339		pctxt->attrProhibs) == -1)
14340	    {
14341		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14342		"failed to expand attributes");
14343	    }
14344	    if (pctxt->attrProhibs->nbItems != 0)
14345		prohibs = pctxt->attrProhibs;
14346	} else {
14347	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14348		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14349		NULL) == -1)
14350	    {
14351		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14352		"failed to expand attributes");
14353	    }
14354	}
14355    }
14356    /*
14357    * Inherit the attribute uses of the base type.
14358    */
14359    if (baseUses != NULL) {
14360	int i, j;
14361	xmlSchemaAttributeUseProhibPtr pro;
14362
14363	if (WXS_IS_RESTRICTION(type)) {
14364	    int usesCount;
14365	    xmlSchemaAttributeUsePtr tmp;
14366
14367	    if (uses != NULL)
14368		usesCount = uses->nbItems;
14369	    else
14370		usesCount = 0;
14371
14372	    /* Restriction. */
14373	    for (i = 0; i < baseUses->nbItems; i++) {
14374		use = baseUses->items[i];
14375		if (prohibs) {
14376		    /*
14377		    * Filter out prohibited uses.
14378		    */
14379		    for (j = 0; j < prohibs->nbItems; j++) {
14380			pro = prohibs->items[j];
14381			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14382			    (WXS_ATTRUSE_DECL_TNS(use) ==
14383				pro->targetNamespace))
14384			{
14385			    goto inherit_next;
14386			}
14387		    }
14388		}
14389		if (usesCount) {
14390		    /*
14391		    * Filter out existing uses.
14392		    */
14393		    for (j = 0; j < usesCount; j++) {
14394			tmp = uses->items[j];
14395			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14396				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14397			    (WXS_ATTRUSE_DECL_TNS(use) ==
14398				WXS_ATTRUSE_DECL_TNS(tmp)))
14399			{
14400			    goto inherit_next;
14401			}
14402		    }
14403		}
14404		if (uses == NULL) {
14405		    type->attrUses = xmlSchemaItemListCreate();
14406		    if (type->attrUses == NULL)
14407			goto exit_failure;
14408		    uses = type->attrUses;
14409		}
14410		xmlSchemaItemListAddSize(uses, 2, use);
14411inherit_next: {}
14412	    }
14413	} else {
14414	    /* Extension. */
14415	    for (i = 0; i < baseUses->nbItems; i++) {
14416		use = baseUses->items[i];
14417		if (uses == NULL) {
14418		    type->attrUses = xmlSchemaItemListCreate();
14419		    if (type->attrUses == NULL)
14420			goto exit_failure;
14421		    uses = type->attrUses;
14422		}
14423		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14424	    }
14425	}
14426    }
14427    /*
14428    * Shrink attr. uses.
14429    */
14430    if (uses) {
14431	if (uses->nbItems == 0) {
14432	    xmlSchemaItemListFree(uses);
14433	    type->attrUses = NULL;
14434	}
14435	/*
14436	* TODO: We could shrink the size of the array
14437	* to fit the actual number of items.
14438	*/
14439    }
14440    /*
14441    * Compute the complete wildcard.
14442    */
14443    if (WXS_IS_EXTENSION(type)) {
14444	if (baseType->attributeWildcard != NULL) {
14445	    /*
14446	    * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14447	    * the appropriate case among the following:"
14448	    */
14449	    if (type->attributeWildcard != NULL) {
14450		/*
14451		* Union the complete wildcard with the base wildcard.
14452		* SPEC {attribute wildcard}
14453		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14454		* and {annotation} are those of the �complete wildcard�,
14455		* and whose {namespace constraint} is the intensional union
14456		* of the {namespace constraint} of the �complete wildcard�
14457		* and of the �base wildcard�, as defined in Attribute
14458		* Wildcard Union (�3.10.6)."
14459		*/
14460		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14461		    baseType->attributeWildcard) == -1)
14462		    goto exit_failure;
14463	    } else {
14464		/*
14465		* (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14466		* then the �base wildcard�."
14467		*/
14468		type->attributeWildcard = baseType->attributeWildcard;
14469	    }
14470	} else {
14471	    /*
14472	    * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14473	    * �complete wildcard"
14474	    * NOOP
14475	    */
14476	}
14477    } else {
14478	/*
14479	* SPEC {attribute wildcard}
14480	* (3.1) "If the <restriction> alternative is chosen, then the
14481	* �complete wildcard�;"
14482	* NOOP
14483	*/
14484    }
14485
14486    return (0);
14487
14488exit_failure:
14489    return(-1);
14490}
14491
14492/**
14493 * xmlSchemaTypeFinalContains:
14494 * @schema:  the schema
14495 * @type:  the type definition
14496 * @final: the final
14497 *
14498 * Evaluates if a type definition contains the given "final".
14499 * This does take "finalDefault" into account as well.
14500 *
14501 * Returns 1 if the type does containt the given "final",
14502 * 0 otherwise.
14503 */
14504static int
14505xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14506{
14507    if (type == NULL)
14508	return (0);
14509    if (type->flags & final)
14510	return (1);
14511    else
14512	return (0);
14513}
14514
14515/**
14516 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14517 * @type:  the Union Simple Type
14518 *
14519 * Returns a list of member types of @type if existing,
14520 * returns NULL otherwise.
14521 */
14522static xmlSchemaTypeLinkPtr
14523xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14524{
14525    while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14526	if (type->memberTypes != NULL)
14527	    return (type->memberTypes);
14528	else
14529	    type = type->baseType;
14530    }
14531    return (NULL);
14532}
14533
14534/**
14535 * xmlSchemaGetParticleTotalRangeMin:
14536 * @particle: the particle
14537 *
14538 * Schema Component Constraint: Effective Total Range
14539 * (all and sequence) + (choice)
14540 *
14541 * Returns the minimun Effective Total Range.
14542 */
14543static int
14544xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14545{
14546    if ((particle->children == NULL) ||
14547	(particle->minOccurs == 0))
14548	return (0);
14549    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14550	int min = -1, cur;
14551	xmlSchemaParticlePtr part =
14552	    (xmlSchemaParticlePtr) particle->children->children;
14553
14554	if (part == NULL)
14555	    return (0);
14556	while (part != NULL) {
14557	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14558		(part->children->type == XML_SCHEMA_TYPE_ANY))
14559		cur = part->minOccurs;
14560	    else
14561		cur = xmlSchemaGetParticleTotalRangeMin(part);
14562	    if (cur == 0)
14563		return (0);
14564	    if ((min > cur) || (min == -1))
14565		min = cur;
14566	    part = (xmlSchemaParticlePtr) part->next;
14567	}
14568	return (particle->minOccurs * min);
14569    } else {
14570	/* <all> and <sequence> */
14571	int sum = 0;
14572	xmlSchemaParticlePtr part =
14573	    (xmlSchemaParticlePtr) particle->children->children;
14574
14575	if (part == NULL)
14576	    return (0);
14577	do {
14578	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14579		(part->children->type == XML_SCHEMA_TYPE_ANY))
14580		sum += part->minOccurs;
14581	    else
14582		sum += xmlSchemaGetParticleTotalRangeMin(part);
14583	    part = (xmlSchemaParticlePtr) part->next;
14584	} while (part != NULL);
14585	return (particle->minOccurs * sum);
14586    }
14587}
14588
14589/**
14590 * xmlSchemaGetParticleTotalRangeMax:
14591 * @particle: the particle
14592 *
14593 * Schema Component Constraint: Effective Total Range
14594 * (all and sequence) + (choice)
14595 *
14596 * Returns the maximum Effective Total Range.
14597 */
14598static int
14599xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14600{
14601    if ((particle->children == NULL) ||
14602	(particle->children->children == NULL))
14603	return (0);
14604    if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14605	int max = -1, cur;
14606	xmlSchemaParticlePtr part =
14607	    (xmlSchemaParticlePtr) particle->children->children;
14608
14609	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14610	    if (part->children == NULL)
14611		continue;
14612	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14613		(part->children->type == XML_SCHEMA_TYPE_ANY))
14614		cur = part->maxOccurs;
14615	    else
14616		cur = xmlSchemaGetParticleTotalRangeMax(part);
14617	    if (cur == UNBOUNDED)
14618		return (UNBOUNDED);
14619	    if ((max < cur) || (max == -1))
14620		max = cur;
14621	}
14622	/* TODO: Handle overflows? */
14623	return (particle->maxOccurs * max);
14624    } else {
14625	/* <all> and <sequence> */
14626	int sum = 0, cur;
14627	xmlSchemaParticlePtr part =
14628	    (xmlSchemaParticlePtr) particle->children->children;
14629
14630	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14631	    if (part->children == NULL)
14632		continue;
14633	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14634		(part->children->type == XML_SCHEMA_TYPE_ANY))
14635		cur = part->maxOccurs;
14636	    else
14637		cur = xmlSchemaGetParticleTotalRangeMax(part);
14638	    if (cur == UNBOUNDED)
14639		return (UNBOUNDED);
14640	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14641		return (UNBOUNDED);
14642	    sum += cur;
14643	}
14644	/* TODO: Handle overflows? */
14645	return (particle->maxOccurs * sum);
14646    }
14647}
14648
14649/**
14650 * xmlSchemaIsParticleEmptiable:
14651 * @particle: the particle
14652 *
14653 * Schema Component Constraint: Particle Emptiable
14654 * Checks whether the given particle is emptiable.
14655 *
14656 * Returns 1 if emptiable, 0 otherwise.
14657 */
14658static int
14659xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14660{
14661    /*
14662    * SPEC (1) "Its {min occurs} is 0."
14663    */
14664    if ((particle == NULL) || (particle->minOccurs == 0) ||
14665	(particle->children == NULL))
14666	return (1);
14667    /*
14668    * SPEC (2) "Its {term} is a group and the minimum part of the
14669    * effective total range of that group, [...] is 0."
14670    */
14671    if (WXS_IS_MODEL_GROUP(particle->children)) {
14672	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14673	    return (1);
14674    }
14675    return (0);
14676}
14677
14678/**
14679 * xmlSchemaCheckCOSSTDerivedOK:
14680 * @actxt: a context
14681 * @type:  the derived simple type definition
14682 * @baseType:  the base type definition
14683 * @subset: the subset of ('restriction', ect.)
14684 *
14685 * Schema Component Constraint:
14686 * Type Derivation OK (Simple) (cos-st-derived-OK)
14687 *
14688 * Checks wheter @type can be validly
14689 * derived from @baseType.
14690 *
14691 * Returns 0 on success, an positive error code otherwise.
14692 */
14693static int
14694xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14695			     xmlSchemaTypePtr type,
14696			     xmlSchemaTypePtr baseType,
14697			     int subset)
14698{
14699    /*
14700    * 1 They are the same type definition.
14701    * TODO: The identy check might have to be more complex than this.
14702    */
14703    if (type == baseType)
14704	return (0);
14705    /*
14706    * 2.1 restriction is not in the subset, or in the {final}
14707    * of its own {base type definition};
14708    *
14709    * NOTE that this will be used also via "xsi:type".
14710    *
14711    * TODO: Revise this, it looks strange. How can the "type"
14712    * not be fixed or *in* fixing?
14713    */
14714    if (WXS_IS_TYPE_NOT_FIXED(type))
14715	if (xmlSchemaTypeFixup(type, actxt) == -1)
14716	    return(-1);
14717    if (WXS_IS_TYPE_NOT_FIXED(baseType))
14718	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14719	    return(-1);
14720    if ((subset & SUBSET_RESTRICTION) ||
14721	(xmlSchemaTypeFinalContains(type->baseType,
14722	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14723	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14724    }
14725    /* 2.2 */
14726    if (type->baseType == baseType) {
14727	/*
14728	* 2.2.1 D's �base type definition� is B.
14729	*/
14730	return (0);
14731    }
14732    /*
14733    * 2.2.2 D's �base type definition� is not the �ur-type definition�
14734    * and is validly derived from B given the subset, as defined by this
14735    * constraint.
14736    */
14737    if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14738	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14739	    baseType, subset) == 0)) {
14740	return (0);
14741    }
14742    /*
14743    * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14744    * definition�.
14745    */
14746    if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14747	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14748	return (0);
14749    }
14750    /*
14751    * 2.2.4 B's {variety} is union and D is validly derived from a type
14752    * definition in B's {member type definitions} given the subset, as
14753    * defined by this constraint.
14754    *
14755    * NOTE: This seems not to involve built-in types, since there is no
14756    * built-in Union Simple Type.
14757    */
14758    if (WXS_IS_UNION(baseType)) {
14759	xmlSchemaTypeLinkPtr cur;
14760
14761	cur = baseType->memberTypes;
14762	while (cur != NULL) {
14763	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14764		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14765		    return(-1);
14766	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14767		    type, cur->type, subset) == 0)
14768	    {
14769		/*
14770		* It just has to be validly derived from at least one
14771		* member-type.
14772		*/
14773		return (0);
14774	    }
14775	    cur = cur->next;
14776	}
14777    }
14778    return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14779}
14780
14781/**
14782 * xmlSchemaCheckTypeDefCircularInternal:
14783 * @pctxt:  the schema parser context
14784 * @ctxtType:  the type definition
14785 * @ancestor: an ancestor of @ctxtType
14786 *
14787 * Checks st-props-correct (2) + ct-props-correct (3).
14788 * Circular type definitions are not allowed.
14789 *
14790 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14791 * circular, 0 otherwise.
14792 */
14793static int
14794xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14795			   xmlSchemaTypePtr ctxtType,
14796			   xmlSchemaTypePtr ancestor)
14797{
14798    int ret;
14799
14800    if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14801	return (0);
14802
14803    if (ctxtType == ancestor) {
14804	xmlSchemaPCustomErr(pctxt,
14805	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14806	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14807	    "The definition is circular", NULL);
14808	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14809    }
14810    if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14811	/*
14812	* Avoid inifinite recursion on circular types not yet checked.
14813	*/
14814	return (0);
14815    }
14816    ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14817    ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14818	ancestor->baseType);
14819    ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14820    return (ret);
14821}
14822
14823/**
14824 * xmlSchemaCheckTypeDefCircular:
14825 * @item:  the complex/simple type definition
14826 * @ctxt:  the parser context
14827 * @name:  the name
14828 *
14829 * Checks for circular type definitions.
14830 */
14831static void
14832xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14833			      xmlSchemaParserCtxtPtr ctxt)
14834{
14835    if ((item == NULL) ||
14836	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14837	(item->baseType == NULL))
14838	return;
14839    xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14840	item->baseType);
14841}
14842
14843/*
14844* Simple Type Definition Representation OK (src-simple-type) 4
14845*
14846* "4 Circular union type definition is disallowed. That is, if the
14847* <union> alternative is chosen, there must not be any entries in the
14848* memberTypes [attribute] at any depth which resolve to the component
14849* corresponding to the <simpleType>."
14850*
14851* Note that this should work on the *representation* of a component,
14852* thus assumes any union types in the member types not being yet
14853* substituted. At this stage we need the variety of the types
14854* to be already computed.
14855*/
14856static int
14857xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14858					xmlSchemaTypePtr ctxType,
14859					xmlSchemaTypeLinkPtr members)
14860{
14861    xmlSchemaTypeLinkPtr member;
14862    xmlSchemaTypePtr memberType;
14863
14864    member = members;
14865    while (member != NULL) {
14866	memberType = member->type;
14867	while ((memberType != NULL) &&
14868	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14869	    if (memberType == ctxType) {
14870		xmlSchemaPCustomErr(pctxt,
14871		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14872		    WXS_BASIC_CAST ctxType, NULL,
14873		    "The union type definition is circular", NULL);
14874		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14875	    }
14876	    if ((WXS_IS_UNION(memberType)) &&
14877		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14878	    {
14879		int res;
14880		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14881		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14882		    ctxType,
14883		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14884		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14885		if (res != 0)
14886		    return(res);
14887	    }
14888	    memberType = memberType->baseType;
14889	}
14890	member = member->next;
14891    }
14892    return(0);
14893}
14894
14895static int
14896xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14897				   xmlSchemaTypePtr type)
14898{
14899    if (! WXS_IS_UNION(type))
14900	return(0);
14901    return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14902	type->memberTypes));
14903}
14904
14905/**
14906 * xmlSchemaResolveTypeReferences:
14907 * @item:  the complex/simple type definition
14908 * @ctxt:  the parser context
14909 * @name:  the name
14910 *
14911 * Resolvese type definition references
14912 */
14913static void
14914xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14915			 xmlSchemaParserCtxtPtr ctxt)
14916{
14917    if (typeDef == NULL)
14918	return;
14919
14920    /*
14921    * Resolve the base type.
14922    */
14923    if (typeDef->baseType == NULL) {
14924	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14925	    typeDef->base, typeDef->baseNs);
14926	if (typeDef->baseType == NULL) {
14927	    xmlSchemaPResCompAttrErr(ctxt,
14928		XML_SCHEMAP_SRC_RESOLVE,
14929		WXS_BASIC_CAST typeDef, typeDef->node,
14930		"base", typeDef->base, typeDef->baseNs,
14931		XML_SCHEMA_TYPE_SIMPLE, NULL);
14932	    return;
14933	}
14934    }
14935    if (WXS_IS_SIMPLE(typeDef)) {
14936	if (WXS_IS_UNION(typeDef)) {
14937	    /*
14938	    * Resolve the memberTypes.
14939	    */
14940	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14941	    return;
14942	} else if (WXS_IS_LIST(typeDef)) {
14943	    /*
14944	    * Resolve the itemType.
14945	    */
14946	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14947
14948		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
14949		    typeDef->base, typeDef->baseNs);
14950
14951		if ((typeDef->subtypes == NULL) ||
14952		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
14953		{
14954		    typeDef->subtypes = NULL;
14955		    xmlSchemaPResCompAttrErr(ctxt,
14956			XML_SCHEMAP_SRC_RESOLVE,
14957			WXS_BASIC_CAST typeDef, typeDef->node,
14958			"itemType", typeDef->base, typeDef->baseNs,
14959			XML_SCHEMA_TYPE_SIMPLE, NULL);
14960		}
14961	    }
14962	    return;
14963	}
14964    }
14965    /*
14966    * The ball of letters below means, that if we have a particle
14967    * which has a QName-helper component as its {term}, we want
14968    * to resolve it...
14969    */
14970    else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14971	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14972	    XML_SCHEMA_TYPE_PARTICLE) &&
14973	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14974	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14975	    XML_SCHEMA_EXTRA_QNAMEREF))
14976    {
14977	xmlSchemaQNameRefPtr ref =
14978	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14979	xmlSchemaModelGroupDefPtr groupDef;
14980
14981	/*
14982	* URGENT TODO: Test this.
14983	*/
14984	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14985	/*
14986	* Resolve the MG definition reference.
14987	*/
14988	groupDef =
14989	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14990		ref->itemType, ref->name, ref->targetNamespace);
14991	if (groupDef == NULL) {
14992	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
14993		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
14994		"ref", ref->name, ref->targetNamespace, ref->itemType,
14995		NULL);
14996	    /* Remove the particle. */
14997	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
14998	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
14999	    /* Remove the particle. */
15000	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15001	else {
15002	    /*
15003	    * Assign the MG definition's {model group} to the
15004	    * particle's {term}.
15005	    */
15006	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15007
15008	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15009		/*
15010		* SPEC cos-all-limited (1.2)
15011		* "1.2 the {term} property of a particle with
15012		* {max occurs}=1 which is part of a pair which constitutes
15013		* the {content type} of a complex type definition."
15014		*/
15015		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15016		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15017			/* TODO: error code */
15018			XML_SCHEMAP_COS_ALL_LIMITED,
15019			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15020			"The particle's {max occurs} must be 1, since the "
15021			"reference resolves to an 'all' model group",
15022			NULL, NULL);
15023		}
15024	    }
15025	}
15026    }
15027}
15028
15029
15030
15031/**
15032 * xmlSchemaCheckSTPropsCorrect:
15033 * @ctxt:  the schema parser context
15034 * @type:  the simple type definition
15035 *
15036 * Checks st-props-correct.
15037 *
15038 * Returns 0 if the properties are correct,
15039 * if not, a positive error code and -1 on internal
15040 * errors.
15041 */
15042static int
15043xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15044			     xmlSchemaTypePtr type)
15045{
15046    xmlSchemaTypePtr baseType = type->baseType;
15047    xmlChar *str = NULL;
15048
15049    /* STATE: error funcs converted. */
15050    /*
15051    * Schema Component Constraint: Simple Type Definition Properties Correct
15052    *
15053    * NOTE: This is somehow redundant, since we actually built a simple type
15054    * to have all the needed information; this acts as an self test.
15055    */
15056    /* Base type: If the datatype has been �derived� by �restriction�
15057    * then the Simple Type Definition component from which it is �derived�,
15058    * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15059    */
15060    if (baseType == NULL) {
15061	/*
15062	* TODO: Think about: "modulo the impact of Missing
15063	* Sub-components (�5.3)."
15064	*/
15065	xmlSchemaPCustomErr(ctxt,
15066	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15067	    WXS_BASIC_CAST type, NULL,
15068	    "No base type existent", NULL);
15069	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15070
15071    }
15072    if (! WXS_IS_SIMPLE(baseType)) {
15073	xmlSchemaPCustomErr(ctxt,
15074	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15075	    WXS_BASIC_CAST type, NULL,
15076	    "The base type '%s' is not a simple type",
15077	    xmlSchemaGetComponentQName(&str, baseType));
15078	FREE_AND_NULL(str)
15079	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15080    }
15081    if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15082	 (WXS_IS_RESTRICTION(type) == 0) &&
15083	 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15084	xmlSchemaPCustomErr(ctxt,
15085	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15086	    WXS_BASIC_CAST type, NULL,
15087	    "A type, derived by list or union, must have"
15088	    "the simple ur-type definition as base type, not '%s'",
15089	    xmlSchemaGetComponentQName(&str, baseType));
15090	FREE_AND_NULL(str)
15091	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15092    }
15093    /*
15094    * Variety: One of {atomic, list, union}.
15095    */
15096    if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15097	(! WXS_IS_LIST(type))) {
15098	xmlSchemaPCustomErr(ctxt,
15099	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15100	    WXS_BASIC_CAST type, NULL,
15101	    "The variety is absent", NULL);
15102	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15103    }
15104    /* TODO: Finish this. Hmm, is this finished? */
15105
15106    /*
15107    * 3 The {final} of the {base type definition} must not contain restriction.
15108    */
15109    if (xmlSchemaTypeFinalContains(baseType,
15110	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15111	xmlSchemaPCustomErr(ctxt,
15112	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15113	    WXS_BASIC_CAST type, NULL,
15114	    "The 'final' of its base type '%s' must not contain "
15115	    "'restriction'",
15116	    xmlSchemaGetComponentQName(&str, baseType));
15117	FREE_AND_NULL(str)
15118	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15119    }
15120
15121    /*
15122    * 2 All simple type definitions must be derived ultimately from the �simple
15123    * ur-type definition (so� circular definitions are disallowed). That is, it
15124    * must be possible to reach a built-in primitive datatype or the �simple
15125    * ur-type definition� by repeatedly following the {base type definition}.
15126    *
15127    * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15128    */
15129    return (0);
15130}
15131
15132/**
15133 * xmlSchemaCheckCOSSTRestricts:
15134 * @ctxt:  the schema parser context
15135 * @type:  the simple type definition
15136 *
15137 * Schema Component Constraint:
15138 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15139
15140 * Checks if the given @type (simpleType) is derived validly by restriction.
15141 * STATUS:
15142 *
15143 * Returns -1 on internal errors, 0 if the type is validly derived,
15144 * a positive error code otherwise.
15145 */
15146static int
15147xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15148			     xmlSchemaTypePtr type)
15149{
15150    xmlChar *str = NULL;
15151
15152    if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15153	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15154	    "given type is not a user-derived simpleType");
15155	return (-1);
15156    }
15157
15158    if (WXS_IS_ATOMIC(type)) {
15159	xmlSchemaTypePtr primitive;
15160	/*
15161	* 1.1 The {base type definition} must be an atomic simple
15162	* type definition or a built-in primitive datatype.
15163	*/
15164	if (! WXS_IS_ATOMIC(type->baseType)) {
15165	    xmlSchemaPCustomErr(pctxt,
15166		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15167		WXS_BASIC_CAST type, NULL,
15168		"The base type '%s' is not an atomic simple type",
15169		xmlSchemaGetComponentQName(&str, type->baseType));
15170	    FREE_AND_NULL(str)
15171	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15172	}
15173	/* 1.2 The {final} of the {base type definition} must not contain
15174	* restriction.
15175	*/
15176	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15177	if (xmlSchemaTypeFinalContains(type->baseType,
15178	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15179	    xmlSchemaPCustomErr(pctxt,
15180		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15181		WXS_BASIC_CAST type, NULL,
15182		"The final of its base type '%s' must not contain 'restriction'",
15183		xmlSchemaGetComponentQName(&str, type->baseType));
15184	    FREE_AND_NULL(str)
15185	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15186	}
15187
15188	/*
15189	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15190	* type definition}, as specified in the appropriate subsection of 3.2
15191	* Primitive datatypes.
15192	*/
15193	if (type->facets != NULL) {
15194	    xmlSchemaFacetPtr facet;
15195	    int ok = 1;
15196
15197	    primitive = xmlSchemaGetPrimitiveType(type);
15198	    if (primitive == NULL) {
15199		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15200		    "failed to get primitive type");
15201		return (-1);
15202	    }
15203	    facet = type->facets;
15204	    do {
15205		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15206		    ok = 0;
15207		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15208			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15209			type, primitive, facet);
15210		}
15211		facet = facet->next;
15212	    } while (facet != NULL);
15213	    if (ok == 0)
15214		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15215	}
15216	/*
15217	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15218	* of the {base type definition} (call this BF),then the DF's {value}
15219	* must be a valid restriction of BF's {value} as defined in
15220	* [XML Schemas: Datatypes]."
15221	*
15222	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15223	* xmlSchemaDeriveAndValidateFacets()
15224	*/
15225    } else if (WXS_IS_LIST(type)) {
15226	xmlSchemaTypePtr itemType = NULL;
15227
15228	itemType = type->subtypes;
15229	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15230	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15231		"failed to evaluate the item type");
15232	    return (-1);
15233	}
15234	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15235	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15236	/*
15237	* 2.1 The {item type definition} must have a {variety} of atomic or
15238	* union (in which case all the {member type definitions}
15239	* must be atomic).
15240	*/
15241	if ((! WXS_IS_ATOMIC(itemType)) &&
15242	    (! WXS_IS_UNION(itemType))) {
15243	    xmlSchemaPCustomErr(pctxt,
15244		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15245		WXS_BASIC_CAST type, NULL,
15246		"The item type '%s' does not have a variety of atomic or union",
15247		xmlSchemaGetComponentQName(&str, itemType));
15248	    FREE_AND_NULL(str)
15249	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15250	} else if (WXS_IS_UNION(itemType)) {
15251	    xmlSchemaTypeLinkPtr member;
15252
15253	    member = itemType->memberTypes;
15254	    while (member != NULL) {
15255		if (! WXS_IS_ATOMIC(member->type)) {
15256		    xmlSchemaPCustomErr(pctxt,
15257			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15258			WXS_BASIC_CAST type, NULL,
15259			"The item type is a union type, but the "
15260			"member type '%s' of this item type is not atomic",
15261			xmlSchemaGetComponentQName(&str, member->type));
15262		    FREE_AND_NULL(str)
15263		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15264		}
15265		member = member->next;
15266	    }
15267	}
15268
15269	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15270	    xmlSchemaFacetPtr facet;
15271	    /*
15272	    * This is the case if we have: <simpleType><list ..
15273	    */
15274	    /*
15275	    * 2.3.1
15276	    * 2.3.1.1 The {final} of the {item type definition} must not
15277	    * contain list.
15278	    */
15279	    if (xmlSchemaTypeFinalContains(itemType,
15280		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15281		xmlSchemaPCustomErr(pctxt,
15282		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15283		    WXS_BASIC_CAST type, NULL,
15284		    "The final of its item type '%s' must not contain 'list'",
15285		    xmlSchemaGetComponentQName(&str, itemType));
15286		FREE_AND_NULL(str)
15287		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15288	    }
15289	    /*
15290	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15291	    * facet component.
15292	    * OPTIMIZE TODO: the S4S already disallows any facet
15293	    * to be specified.
15294	    */
15295	    if (type->facets != NULL) {
15296		facet = type->facets;
15297		do {
15298		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15299			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15300			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15301			    type, facet);
15302			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15303		    }
15304		    facet = facet->next;
15305		} while (facet != NULL);
15306	    }
15307	    /*
15308	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15309	    * A �list� datatype can be �derived� from an �atomic� datatype
15310	    * whose �lexical space� allows space (such as string or anyURI)or
15311	    * a �union� datatype any of whose {member type definitions}'s
15312	    * �lexical space� allows space.
15313	    */
15314	} else {
15315	    /*
15316	    * This is the case if we have: <simpleType><restriction ...
15317	    * I.e. the variety of "list" is inherited.
15318	    */
15319	    /*
15320	    * 2.3.2
15321	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15322	    */
15323	    if (! WXS_IS_LIST(type->baseType)) {
15324		xmlSchemaPCustomErr(pctxt,
15325		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15326		    WXS_BASIC_CAST type, NULL,
15327		    "The base type '%s' must be a list type",
15328		    xmlSchemaGetComponentQName(&str, type->baseType));
15329		FREE_AND_NULL(str)
15330		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15331	    }
15332	    /*
15333	    * 2.3.2.2 The {final} of the {base type definition} must not
15334	    * contain restriction.
15335	    */
15336	    if (xmlSchemaTypeFinalContains(type->baseType,
15337		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15338		xmlSchemaPCustomErr(pctxt,
15339		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15340		    WXS_BASIC_CAST type, NULL,
15341		    "The 'final' of the base type '%s' must not contain 'restriction'",
15342		    xmlSchemaGetComponentQName(&str, type->baseType));
15343		FREE_AND_NULL(str)
15344		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15345	    }
15346	    /*
15347	    * 2.3.2.3 The {item type definition} must be validly derived
15348	    * from the {base type definition}'s {item type definition} given
15349	    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15350	    */
15351	    {
15352		xmlSchemaTypePtr baseItemType;
15353
15354		baseItemType = type->baseType->subtypes;
15355		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15356		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15357			"failed to eval the item type of a base type");
15358		    return (-1);
15359		}
15360		if ((itemType != baseItemType) &&
15361		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15362			baseItemType, 0) != 0)) {
15363		    xmlChar *strBIT = NULL, *strBT = NULL;
15364		    xmlSchemaPCustomErrExt(pctxt,
15365			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15366			WXS_BASIC_CAST type, NULL,
15367			"The item type '%s' is not validly derived from "
15368			"the item type '%s' of the base type '%s'",
15369			xmlSchemaGetComponentQName(&str, itemType),
15370			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15371			xmlSchemaGetComponentQName(&strBT, type->baseType));
15372
15373		    FREE_AND_NULL(str)
15374		    FREE_AND_NULL(strBIT)
15375		    FREE_AND_NULL(strBT)
15376		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15377		}
15378	    }
15379
15380	    if (type->facets != NULL) {
15381		xmlSchemaFacetPtr facet;
15382		int ok = 1;
15383		/*
15384		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15385		* and enumeration facet components are allowed among the {facets}.
15386		*/
15387		facet = type->facets;
15388		do {
15389		    switch (facet->type) {
15390			case XML_SCHEMA_FACET_LENGTH:
15391			case XML_SCHEMA_FACET_MINLENGTH:
15392			case XML_SCHEMA_FACET_MAXLENGTH:
15393			case XML_SCHEMA_FACET_WHITESPACE:
15394			    /*
15395			    * TODO: 2.5.1.2 List datatypes
15396			    * The value of �whiteSpace� is fixed to the value collapse.
15397			    */
15398			case XML_SCHEMA_FACET_PATTERN:
15399			case XML_SCHEMA_FACET_ENUMERATION:
15400			    break;
15401			default: {
15402			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15403				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15404				type, facet);
15405			    /*
15406			    * We could return, but it's nicer to report all
15407			    * invalid facets.
15408			    */
15409			    ok = 0;
15410			}
15411		    }
15412		    facet = facet->next;
15413		} while (facet != NULL);
15414		if (ok == 0)
15415		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15416		/*
15417		* SPEC (2.3.2.5) (same as 1.3.2)
15418		*
15419		* NOTE (2.3.2.5) This is currently done in
15420		* xmlSchemaDeriveAndValidateFacets()
15421		*/
15422	    }
15423	}
15424    } else if (WXS_IS_UNION(type)) {
15425	/*
15426	* 3.1 The {member type definitions} must all have {variety} of
15427	* atomic or list.
15428	*/
15429	xmlSchemaTypeLinkPtr member;
15430
15431	member = type->memberTypes;
15432	while (member != NULL) {
15433	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15434		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15435
15436	    if ((! WXS_IS_ATOMIC(member->type)) &&
15437		(! WXS_IS_LIST(member->type))) {
15438		xmlSchemaPCustomErr(pctxt,
15439		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15440		    WXS_BASIC_CAST type, NULL,
15441		    "The member type '%s' is neither an atomic, nor a list type",
15442		    xmlSchemaGetComponentQName(&str, member->type));
15443		FREE_AND_NULL(str)
15444		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15445	    }
15446	    member = member->next;
15447	}
15448	/*
15449	* 3.3.1 If the {base type definition} is the �simple ur-type
15450	* definition�
15451	*/
15452	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15453	    /*
15454	    * 3.3.1.1 All of the {member type definitions} must have a
15455	    * {final} which does not contain union.
15456	    */
15457	    member = type->memberTypes;
15458	    while (member != NULL) {
15459		if (xmlSchemaTypeFinalContains(member->type,
15460		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15461		    xmlSchemaPCustomErr(pctxt,
15462			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15463			WXS_BASIC_CAST type, NULL,
15464			"The 'final' of member type '%s' contains 'union'",
15465			xmlSchemaGetComponentQName(&str, member->type));
15466		    FREE_AND_NULL(str)
15467		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15468		}
15469		member = member->next;
15470	    }
15471	    /*
15472	    * 3.3.1.2 The {facets} must be empty.
15473	    */
15474	    if (type->facetSet != NULL) {
15475		xmlSchemaPCustomErr(pctxt,
15476		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15477		    WXS_BASIC_CAST type, NULL,
15478		    "No facets allowed", NULL);
15479		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15480	    }
15481	} else {
15482	    /*
15483	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15484	    * I.e. the variety of "list" is inherited.
15485	    */
15486	    if (! WXS_IS_UNION(type->baseType)) {
15487		xmlSchemaPCustomErr(pctxt,
15488		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15489		    WXS_BASIC_CAST type, NULL,
15490		    "The base type '%s' is not a union type",
15491		    xmlSchemaGetComponentQName(&str, type->baseType));
15492		FREE_AND_NULL(str)
15493		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15494	    }
15495	    /*
15496	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15497	    */
15498	    if (xmlSchemaTypeFinalContains(type->baseType,
15499		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15500		xmlSchemaPCustomErr(pctxt,
15501		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15502		    WXS_BASIC_CAST type, NULL,
15503		    "The 'final' of its base type '%s' must not contain 'restriction'",
15504		    xmlSchemaGetComponentQName(&str, type->baseType));
15505		FREE_AND_NULL(str)
15506		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15507	    }
15508	    /*
15509	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15510	    * derived from the corresponding type definitions in the {base
15511	    * type definition}'s {member type definitions} given the empty set,
15512	    * as defined in Type Derivation OK (Simple) (�3.14.6).
15513	    */
15514	    {
15515		xmlSchemaTypeLinkPtr baseMember;
15516
15517		/*
15518		* OPTIMIZE: if the type is restricting, it has no local defined
15519		* member types and inherits the member types of the base type;
15520		* thus a check for equality can be skipped.
15521		*/
15522		/*
15523		* Even worse: I cannot see a scenario where a restricting
15524		* union simple type can have other member types as the member
15525		* types of it's base type. This check seems not necessary with
15526		* respect to the derivation process in libxml2.
15527		* But necessary if constructing types with an API.
15528		*/
15529		if (type->memberTypes != NULL) {
15530		    member = type->memberTypes;
15531		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15532		    if ((member == NULL) && (baseMember != NULL)) {
15533			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15534			    "different number of member types in base");
15535		    }
15536		    while (member != NULL) {
15537			if (baseMember == NULL) {
15538			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15539			    "different number of member types in base");
15540			} else if ((member->type != baseMember->type) &&
15541			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15542				member->type, baseMember->type, 0) != 0)) {
15543			    xmlChar *strBMT = NULL, *strBT = NULL;
15544
15545			    xmlSchemaPCustomErrExt(pctxt,
15546				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15547				WXS_BASIC_CAST type, NULL,
15548				"The member type %s is not validly "
15549				"derived from its corresponding member "
15550				"type %s of the base type %s",
15551				xmlSchemaGetComponentQName(&str, member->type),
15552				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15553				xmlSchemaGetComponentQName(&strBT, type->baseType));
15554			    FREE_AND_NULL(str)
15555			    FREE_AND_NULL(strBMT)
15556			    FREE_AND_NULL(strBT)
15557			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15558			}
15559			member = member->next;
15560			baseMember = baseMember->next;
15561		    }
15562		}
15563	    }
15564	    /*
15565	    * 3.3.2.4 Only pattern and enumeration facet components are
15566	    * allowed among the {facets}.
15567	    */
15568	    if (type->facets != NULL) {
15569		xmlSchemaFacetPtr facet;
15570		int ok = 1;
15571
15572		facet = type->facets;
15573		do {
15574		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15575			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15576			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15577				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15578				type, facet);
15579			ok = 0;
15580		    }
15581		    facet = facet->next;
15582		} while (facet != NULL);
15583		if (ok == 0)
15584		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15585
15586	    }
15587	    /*
15588	    * SPEC (3.3.2.5) (same as 1.3.2)
15589	    *
15590	    * NOTE (3.3.2.5) This is currently done in
15591	    * xmlSchemaDeriveAndValidateFacets()
15592	    */
15593	}
15594    }
15595
15596    return (0);
15597}
15598
15599/**
15600 * xmlSchemaCheckSRCSimpleType:
15601 * @ctxt:  the schema parser context
15602 * @type:  the simple type definition
15603 *
15604 * Checks crc-simple-type constraints.
15605 *
15606 * Returns 0 if the constraints are satisfied,
15607 * if not a positive error code and -1 on internal
15608 * errors.
15609 */
15610#if 0
15611static int
15612xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15613			    xmlSchemaTypePtr type)
15614{
15615    /*
15616    * src-simple-type.1 The corresponding simple type definition, if any,
15617    * must satisfy the conditions set out in Constraints on Simple Type
15618    * Definition Schema Components (�3.14.6).
15619    */
15620    if (WXS_IS_RESTRICTION(type)) {
15621	/*
15622	* src-simple-type.2 "If the <restriction> alternative is chosen,
15623	* either it must have a base [attribute] or a <simpleType> among its
15624	* [children], but not both."
15625	* NOTE: This is checked in the parse function of <restriction>.
15626	*/
15627	/*
15628	*
15629	*/
15630    } else if (WXS_IS_LIST(type)) {
15631	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15632	* an itemType [attribute] or a <simpleType> among its [children],
15633	* but not both."
15634	*
15635	* NOTE: This is checked in the parse function of <list>.
15636	*/
15637    } else if (WXS_IS_UNION(type)) {
15638	/*
15639	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15640	*/
15641    }
15642    return (0);
15643}
15644#endif
15645
15646static int
15647xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15648{
15649   if (ctxt->vctxt == NULL) {
15650	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15651	if (ctxt->vctxt == NULL) {
15652	    xmlSchemaPErr(ctxt, NULL,
15653		XML_SCHEMAP_INTERNAL,
15654		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15655		"failed to create a temp. validation context.\n",
15656		NULL, NULL);
15657	    return (-1);
15658	}
15659	/* TODO: Pass user data. */
15660	xmlSchemaSetValidErrors(ctxt->vctxt,
15661	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15662	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15663	    ctxt->serror, ctxt->errCtxt);
15664    }
15665    return (0);
15666}
15667
15668static int
15669xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15670			     xmlNodePtr node,
15671			     xmlSchemaTypePtr type,
15672			     const xmlChar *value,
15673			     xmlSchemaValPtr *retVal,
15674			     int fireErrors,
15675			     int normalize,
15676			     int isNormalized);
15677
15678/**
15679 * xmlSchemaParseCheckCOSValidDefault:
15680 * @pctxt:  the schema parser context
15681 * @type:  the simple type definition
15682 * @value: the default value
15683 * @node: an optional node (the holder of the value)
15684 *
15685 * Schema Component Constraint: Element Default Valid (Immediate)
15686 * (cos-valid-default)
15687 * This will be used by the parser only. For the validator there's
15688 * an other version.
15689 *
15690 * Returns 0 if the constraints are satisfied,
15691 * if not, a positive error code and -1 on internal
15692 * errors.
15693 */
15694static int
15695xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15696				   xmlNodePtr node,
15697				   xmlSchemaTypePtr type,
15698				   const xmlChar *value,
15699				   xmlSchemaValPtr *val)
15700{
15701    int ret = 0;
15702
15703    /*
15704    * cos-valid-default:
15705    * Schema Component Constraint: Element Default Valid (Immediate)
15706    * For a string to be a valid default with respect to a type
15707    * definition the appropriate case among the following must be true:
15708    */
15709    if WXS_IS_COMPLEX(type) {
15710	/*
15711	* Complex type.
15712	*
15713	* SPEC (2.1) "its {content type} must be a simple type definition
15714	* or mixed."
15715	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15716	* type}'s particle must be �emptiable� as defined by
15717	* Particle Emptiable (�3.9.6)."
15718	*/
15719	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15720	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15721	    /* NOTE that this covers (2.2.2) as well. */
15722	    xmlSchemaPCustomErr(pctxt,
15723		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15724		WXS_BASIC_CAST type, type->node,
15725		"For a string to be a valid default, the type definition "
15726		"must be a simple type or a complex type with mixed content "
15727		"and a particle emptiable", NULL);
15728	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15729	}
15730    }
15731    /*
15732    * 1 If the type definition is a simple type definition, then the string
15733    * must be �valid� with respect to that definition as defined by String
15734    * Valid (�3.14.4).
15735    *
15736    * AND
15737    *
15738    * 2.2.1 If the {content type} is a simple type definition, then the
15739    * string must be �valid� with respect to that simple type definition
15740    * as defined by String Valid (�3.14.4).
15741    */
15742    if (WXS_IS_SIMPLE(type))
15743	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15744	    type, value, val, 1, 1, 0);
15745    else if (WXS_HAS_SIMPLE_CONTENT(type))
15746	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15747	    type->contentTypeDef, value, val, 1, 1, 0);
15748    else
15749	return (ret);
15750
15751    if (ret < 0) {
15752	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15753	    "calling xmlSchemaVCheckCVCSimpleType()");
15754    }
15755
15756    return (ret);
15757}
15758
15759/**
15760 * xmlSchemaCheckCTPropsCorrect:
15761 * @ctxt:  the schema parser context
15762 * @type:  the complex type definition
15763 *
15764 *.(4.6) Constraints on Complex Type Definition Schema Components
15765 * Schema Component Constraint:
15766 * Complex Type Definition Properties Correct (ct-props-correct)
15767 * STATUS: (seems) complete
15768 *
15769 * Returns 0 if the constraints are satisfied, a positive
15770 * error code if not and -1 if an internal error occured.
15771 */
15772static int
15773xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15774			     xmlSchemaTypePtr type)
15775{
15776    /*
15777    * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15778    *
15779    * SPEC (1) "The values of the properties of a complex type definition must
15780    * be as described in the property tableau in The Complex Type Definition
15781    * Schema Component (�3.4.1), modulo the impact of Missing
15782    * Sub-components (�5.3)."
15783    */
15784    if ((type->baseType != NULL) &&
15785	(WXS_IS_SIMPLE(type->baseType)) &&
15786	(WXS_IS_EXTENSION(type) == 0)) {
15787	/*
15788	* SPEC (2) "If the {base type definition} is a simple type definition,
15789	* the {derivation method} must be extension."
15790	*/
15791	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15792	    XML_SCHEMAP_SRC_CT_1,
15793	    NULL, WXS_BASIC_CAST type,
15794	    "If the base type is a simple type, the derivation method must be "
15795	    "'extension'", NULL, NULL);
15796	return (XML_SCHEMAP_SRC_CT_1);
15797    }
15798    /*
15799    * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15800    * definition�. That is, it must be possible to reach the �ur-type
15801    * definition by repeatedly following the {base type definition}."
15802    *
15803    * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15804    */
15805    /*
15806    * NOTE that (4) and (5) need the following:
15807    *   - attribute uses need to be already inherited (apply attr. prohibitions)
15808    *   - attribute group references need to be expanded already
15809    *   - simple types need to be typefixed already
15810    */
15811    if (type->attrUses &&
15812	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15813    {
15814	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15815	xmlSchemaAttributeUsePtr use, tmp;
15816	int i, j, hasId = 0;
15817
15818	for (i = uses->nbItems -1; i >= 0; i--) {
15819	    use = uses->items[i];
15820
15821	    /*
15822	    * SPEC ct-props-correct
15823	    * (4) "Two distinct attribute declarations in the
15824	    * {attribute uses} must not have identical {name}s and
15825	    * {target namespace}s."
15826	    */
15827	    if (i > 0) {
15828		for (j = i -1; j >= 0; j--) {
15829		    tmp = uses->items[j];
15830		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15831			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15832			(WXS_ATTRUSE_DECL_TNS(use) ==
15833			WXS_ATTRUSE_DECL_TNS(tmp)))
15834		    {
15835			xmlChar *str = NULL;
15836
15837			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15838			    XML_SCHEMAP_AG_PROPS_CORRECT,
15839			    NULL, WXS_BASIC_CAST type,
15840			    "Duplicate %s",
15841			    xmlSchemaGetComponentDesignation(&str, use),
15842			    NULL);
15843			FREE_AND_NULL(str);
15844			/*
15845			* Remove the duplicate.
15846			*/
15847			if (xmlSchemaItemListRemove(uses, i) == -1)
15848			    goto exit_failure;
15849			goto next_use;
15850		    }
15851		}
15852	    }
15853	    /*
15854	    * SPEC ct-props-correct
15855	    * (5) "Two distinct attribute declarations in the
15856	    * {attribute uses} must not have {type definition}s which
15857	    * are or are derived from ID."
15858	    */
15859	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15860		if (xmlSchemaIsDerivedFromBuiltInType(
15861		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15862		{
15863		    if (hasId) {
15864			xmlChar *str = NULL;
15865
15866			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15867			    XML_SCHEMAP_AG_PROPS_CORRECT,
15868			    NULL, WXS_BASIC_CAST type,
15869			    "There must not exist more than one attribute "
15870			    "declaration of type 'xs:ID' "
15871			    "(or derived from 'xs:ID'). The %s violates this "
15872			    "constraint",
15873			    xmlSchemaGetComponentDesignation(&str, use),
15874			    NULL);
15875			FREE_AND_NULL(str);
15876			if (xmlSchemaItemListRemove(uses, i) == -1)
15877			    goto exit_failure;
15878		    }
15879
15880		    hasId = 1;
15881		}
15882	    }
15883next_use: {}
15884	}
15885    }
15886    return (0);
15887exit_failure:
15888    return(-1);
15889}
15890
15891static int
15892xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15893		       xmlSchemaTypePtr typeB)
15894{
15895    /*
15896    * TODO: This should implement component-identity
15897    * in the future.
15898    */
15899    if ((typeA == NULL) || (typeB == NULL))
15900	return (0);
15901    return (typeA == typeB);
15902}
15903
15904/**
15905 * xmlSchemaCheckCOSCTDerivedOK:
15906 * @ctxt:  the schema parser context
15907 * @type:  the to-be derived complex type definition
15908 * @baseType:  the base complex type definition
15909 * @set: the given set
15910 *
15911 * Schema Component Constraint:
15912 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15913 *
15914 * STATUS: completed
15915 *
15916 * Returns 0 if the constraints are satisfied, or 1
15917 * if not.
15918 */
15919static int
15920xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
15921			     xmlSchemaTypePtr type,
15922			     xmlSchemaTypePtr baseType,
15923			     int set)
15924{
15925    int equal = xmlSchemaAreEqualTypes(type, baseType);
15926    /* TODO: Error codes. */
15927    /*
15928    * SPEC "For a complex type definition (call it D, for derived)
15929    * to be validly derived from a type definition (call this
15930    * B, for base) given a subset of {extension, restriction}
15931    * all of the following must be true:"
15932    */
15933    if (! equal) {
15934	/*
15935	* SPEC (1) "If B and D are not the same type definition, then the
15936	* {derivation method} of D must not be in the subset."
15937	*/
15938	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15939	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
15940	    return (1);
15941    } else {
15942	/*
15943	* SPEC (2.1) "B and D must be the same type definition."
15944	*/
15945	return (0);
15946    }
15947    /*
15948    * SPEC (2.2) "B must be D's {base type definition}."
15949    */
15950    if (type->baseType == baseType)
15951	return (0);
15952    /*
15953    * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
15954    * definition�."
15955    */
15956    if (WXS_IS_ANYTYPE(type->baseType))
15957	return (1);
15958
15959    if (WXS_IS_COMPLEX(type->baseType)) {
15960	/*
15961	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15962	* must be validly derived from B given the subset as defined by this
15963	* constraint."
15964	*/
15965	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
15966	    baseType, set));
15967    } else {
15968	/*
15969	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15970	* must be validly derived from B given the subset as defined in Type
15971	* Derivation OK (Simple) (�3.14.6).
15972	*/
15973	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
15974	    baseType, set));
15975    }
15976}
15977
15978/**
15979 * xmlSchemaCheckCOSDerivedOK:
15980 * @type:  the derived simple type definition
15981 * @baseType:  the base type definition
15982 *
15983 * Calls:
15984 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
15985 *
15986 * Checks wheter @type can be validly derived from @baseType.
15987 *
15988 * Returns 0 on success, an positive error code otherwise.
15989 */
15990static int
15991xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
15992			   xmlSchemaTypePtr type,
15993			   xmlSchemaTypePtr baseType,
15994			   int set)
15995{
15996    if (WXS_IS_SIMPLE(type))
15997	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
15998    else
15999	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16000}
16001
16002/**
16003 * xmlSchemaCheckCOSCTExtends:
16004 * @ctxt:  the schema parser context
16005 * @type:  the complex type definition
16006 *
16007 * (3.4.6) Constraints on Complex Type Definition Schema Components
16008 * Schema Component Constraint:
16009 * Derivation Valid (Extension) (cos-ct-extends)
16010 *
16011 * STATUS:
16012 *   missing:
16013 *     (1.5)
16014 *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16015 *
16016 * Returns 0 if the constraints are satisfied, a positive
16017 * error code if not and -1 if an internal error occured.
16018 */
16019static int
16020xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16021			   xmlSchemaTypePtr type)
16022{
16023    xmlSchemaTypePtr base = type->baseType;
16024    /*
16025    * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16026    * temporarily only.
16027    */
16028    /*
16029    * SPEC (1) "If the {base type definition} is a complex type definition,
16030    * then all of the following must be true:"
16031    */
16032    if (WXS_IS_COMPLEX(base)) {
16033	/*
16034	* SPEC (1.1) "The {final} of the {base type definition} must not
16035	* contain extension."
16036	*/
16037	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16038	    xmlSchemaPCustomErr(ctxt,
16039		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16040		WXS_BASIC_CAST type, NULL,
16041		"The 'final' of the base type definition "
16042		"contains 'extension'", NULL);
16043	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16044	}
16045
16046	/*
16047	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16048	* since they are automatically satisfied through the
16049	* inheriting mechanism.
16050	* Note that even if redefining components, the inheriting mechanism
16051	* is used.
16052	*/
16053#if 0
16054	/*
16055	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16056	* uses}
16057	* of the complex type definition itself, that is, for every attribute
16058	* use in the {attribute uses} of the {base type definition}, there
16059	* must be an attribute use in the {attribute uses} of the complex
16060	* type definition itself whose {attribute declaration} has the same
16061	* {name}, {target namespace} and {type definition} as its attribute
16062	* declaration"
16063	*/
16064	if (base->attrUses != NULL) {
16065	    int i, j, found;
16066	    xmlSchemaAttributeUsePtr use, buse;
16067
16068	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16069		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16070		found = 0;
16071		if (type->attrUses != NULL) {
16072		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16073		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16074		    {
16075			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16076				WXS_ATTRUSE_DECL_NAME(buse)) &&
16077			    (WXS_ATTRUSE_DECL_TNS(use) ==
16078				WXS_ATTRUSE_DECL_TNS(buse)) &&
16079			    (WXS_ATTRUSE_TYPEDEF(use) ==
16080				WXS_ATTRUSE_TYPEDEF(buse))
16081			{
16082			    found = 1;
16083			    break;
16084			}
16085		    }
16086		}
16087		if (! found) {
16088		    xmlChar *str = NULL;
16089
16090		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16091			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16092			NULL, WXS_BASIC_CAST type,
16093			/*
16094			* TODO: The report does not indicate that also the
16095			* type needs to be the same.
16096			*/
16097			"This type is missing a matching correspondent "
16098			"for its {base type}'s %s in its {attribute uses}",
16099			xmlSchemaGetComponentDesignation(&str,
16100			    buse->children),
16101			NULL);
16102		    FREE_AND_NULL(str)
16103		}
16104	    }
16105	}
16106	/*
16107	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16108	* definition must also have one, and the base type definition's
16109	* {attribute  wildcard}'s {namespace constraint} must be a subset
16110	* of the complex  type definition's {attribute wildcard}'s {namespace
16111	* constraint}, as defined by Wildcard Subset (�3.10.6)."
16112	*/
16113
16114	/*
16115	* MAYBE TODO: Enable if ever needed. But this will be needed only
16116	* if created the type via a schema construction API.
16117	*/
16118	if (base->attributeWildcard != NULL) {
16119	    if (type->attributeWilcard == NULL) {
16120		xmlChar *str = NULL;
16121
16122		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16123		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16124		    NULL, type,
16125		    "The base %s has an attribute wildcard, "
16126		    "but this type is missing an attribute wildcard",
16127		    xmlSchemaGetComponentDesignation(&str, base));
16128		FREE_AND_NULL(str)
16129
16130	    } else if (xmlSchemaCheckCOSNSSubset(
16131		base->attributeWildcard, type->attributeWildcard))
16132	    {
16133		xmlChar *str = NULL;
16134
16135		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16136		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16137		    NULL, type,
16138		    "The attribute wildcard is not a valid "
16139		    "superset of the one in the base %s",
16140		    xmlSchemaGetComponentDesignation(&str, base));
16141		FREE_AND_NULL(str)
16142	    }
16143	}
16144#endif
16145	/*
16146	* SPEC (1.4) "One of the following must be true:"
16147	*/
16148	if ((type->contentTypeDef != NULL) &&
16149	    (type->contentTypeDef == base->contentTypeDef)) {
16150	    /*
16151	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16152	    * and the {content type} of the complex type definition itself
16153	    * must be the same simple type definition"
16154	    * PASS
16155	    */
16156	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16157	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16158	    /*
16159	    * SPEC (1.4.2) "The {content type} of both the {base type
16160	    * definition} and the complex type definition itself must
16161	    * be empty."
16162	    * PASS
16163	    */
16164	} else {
16165	    /*
16166	    * SPEC (1.4.3) "All of the following must be true:"
16167	    */
16168	    if (type->subtypes == NULL) {
16169		/*
16170		* SPEC 1.4.3.1 The {content type} of the complex type
16171		* definition itself must specify a particle.
16172		*/
16173		xmlSchemaPCustomErr(ctxt,
16174		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16175		    WXS_BASIC_CAST type, NULL,
16176		    "The content type must specify a particle", NULL);
16177		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16178	    }
16179	    /*
16180	    * SPEC (1.4.3.2) "One of the following must be true:"
16181	    */
16182	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16183		/*
16184		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16185		* definition} must be empty.
16186		* PASS
16187		*/
16188	    } else {
16189		/*
16190		* SPEC (1.4.3.2.2) "All of the following must be true:"
16191		*/
16192		if ((type->contentType != base->contentType) ||
16193		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16194		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16195		    /*
16196		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16197		    * or both must be element-only."
16198		    */
16199		    xmlSchemaPCustomErr(ctxt,
16200			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16201			WXS_BASIC_CAST type, NULL,
16202			"The content type of both, the type and its base "
16203			"type, must either 'mixed' or 'element-only'", NULL);
16204		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16205		}
16206		/*
16207		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16208		* complex type definition must be a �valid extension�
16209		* of the {base type definition}'s particle, as defined
16210		* in Particle Valid (Extension) (�3.9.6)."
16211		*
16212		* NOTE that we won't check "Particle Valid (Extension)",
16213		* since it is ensured by the derivation process in
16214		* xmlSchemaTypeFixup(). We need to implement this when heading
16215		* for a construction API
16216		* TODO: !! This is needed to be checked if redefining a type !!
16217		*/
16218	    }
16219	    /*
16220	    * URGENT TODO (1.5)
16221	    */
16222	}
16223    } else {
16224	/*
16225	* SPEC (2) "If the {base type definition} is a simple type definition,
16226	* then all of the following must be true:"
16227	*/
16228	if (type->contentTypeDef != base) {
16229	    /*
16230	    * SPEC (2.1) "The {content type} must be the same simple type
16231	    * definition."
16232	    */
16233	    xmlSchemaPCustomErr(ctxt,
16234		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16235		WXS_BASIC_CAST type, NULL,
16236		"The content type must be the simple base type", NULL);
16237	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16238	}
16239	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16240	    /*
16241	    * SPEC (2.2) "The {final} of the {base type definition} must not
16242	    * contain extension"
16243	    * NOTE that this is the same as (1.1).
16244	    */
16245	    xmlSchemaPCustomErr(ctxt,
16246		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16247		WXS_BASIC_CAST type, NULL,
16248		"The 'final' of the base type definition "
16249		"contains 'extension'", NULL);
16250	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16251	}
16252    }
16253    return (0);
16254}
16255
16256/**
16257 * xmlSchemaCheckDerivationOKRestriction:
16258 * @ctxt:  the schema parser context
16259 * @type:  the complex type definition
16260 *
16261 * (3.4.6) Constraints on Complex Type Definition Schema Components
16262 * Schema Component Constraint:
16263 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16264 *
16265 * STATUS:
16266 *   missing:
16267 *     (5.4.2) ???
16268 *
16269 * ATTENTION:
16270 * In XML Schema 1.1 this will be:
16271 * Validation Rule: Checking complex type subsumption
16272 *
16273 * Returns 0 if the constraints are satisfied, a positive
16274 * error code if not and -1 if an internal error occured.
16275 */
16276static int
16277xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16278				      xmlSchemaTypePtr type)
16279{
16280    xmlSchemaTypePtr base;
16281
16282    /*
16283    * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16284    * temporarily only.
16285    */
16286    base = type->baseType;
16287    if (! WXS_IS_COMPLEX(base)) {
16288	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16289	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16290	    type->node, WXS_BASIC_CAST type,
16291	    "The base type must be a complex type", NULL, NULL);
16292	return(ctxt->err);
16293    }
16294    if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16295	/*
16296	* SPEC (1) "The {base type definition} must be a complex type
16297	* definition whose {final} does not contain restriction."
16298	*/
16299	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16300	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16301	    type->node, WXS_BASIC_CAST type,
16302	    "The 'final' of the base type definition "
16303	    "contains 'restriction'", NULL, NULL);
16304	return (ctxt->err);
16305    }
16306    /*
16307    * SPEC (2), (3) and (4)
16308    * Those are handled in a separate function, since the
16309    * same constraints are needed for redefinition of
16310    * attribute groups as well.
16311    */
16312    if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16313	XML_SCHEMA_ACTION_DERIVE,
16314	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16315	type->attrUses, base->attrUses,
16316	type->attributeWildcard,
16317	base->attributeWildcard) == -1)
16318    {
16319	return(-1);
16320    }
16321    /*
16322    * SPEC (5) "One of the following must be true:"
16323    */
16324    if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16325	/*
16326	* SPEC (5.1) "The {base type definition} must be the
16327	* �ur-type definition�."
16328	* PASS
16329	*/
16330    } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16331	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16332	/*
16333	* SPEC (5.2.1) "The {content type} of the complex type definition
16334	* must be a simple type definition"
16335	*
16336	* SPEC (5.2.2) "One of the following must be true:"
16337	*/
16338	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16339	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16340	{
16341	    int err;
16342	    /*
16343	    * SPEC (5.2.2.1) "The {content type} of the {base type
16344	    * definition} must be a simple type definition from which
16345	    * the {content type} is validly derived given the empty
16346	    * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16347	    *
16348	    * ATTENTION TODO: This seems not needed if the type implicitely
16349	    * derived from the base type.
16350	    *
16351	    */
16352	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16353		type->contentTypeDef, base->contentTypeDef, 0);
16354	    if (err != 0) {
16355		xmlChar *strA = NULL, *strB = NULL;
16356
16357		if (err == -1)
16358		    return(-1);
16359		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16360		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16361		    NULL, WXS_BASIC_CAST type,
16362		    "The {content type} %s is not validly derived from the "
16363		    "base type's {content type} %s",
16364		    xmlSchemaGetComponentDesignation(&strA,
16365			type->contentTypeDef),
16366		    xmlSchemaGetComponentDesignation(&strB,
16367			base->contentTypeDef));
16368		FREE_AND_NULL(strA);
16369		FREE_AND_NULL(strB);
16370		return(ctxt->err);
16371	    }
16372	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16373	    (xmlSchemaIsParticleEmptiable(
16374		(xmlSchemaParticlePtr) base->subtypes))) {
16375	    /*
16376	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16377	    * and have a particle which is �emptiable� as defined in
16378	    * Particle Emptiable (�3.9.6)."
16379	    * PASS
16380	    */
16381	} else {
16382	    xmlSchemaPCustomErr(ctxt,
16383		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16384		WXS_BASIC_CAST type, NULL,
16385		"The content type of the base type must be either "
16386		"a simple type or 'mixed' and an emptiable particle", NULL);
16387	    return (ctxt->err);
16388	}
16389    } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16390	/*
16391	* SPEC (5.3.1) "The {content type} of the complex type itself must
16392	* be empty"
16393	*/
16394	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16395	    /*
16396	    * SPEC (5.3.2.1) "The {content type} of the {base type
16397	    * definition} must also be empty."
16398	    * PASS
16399	    */
16400	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16401	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16402	    xmlSchemaIsParticleEmptiable(
16403		(xmlSchemaParticlePtr) base->subtypes)) {
16404	    /*
16405	    * SPEC (5.3.2.2) "The {content type} of the {base type
16406	    * definition} must be elementOnly or mixed and have a particle
16407	    * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16408	    * PASS
16409	    */
16410	} else {
16411	    xmlSchemaPCustomErr(ctxt,
16412		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16413		WXS_BASIC_CAST type, NULL,
16414		"The content type of the base type must be either "
16415		"empty or 'mixed' (or 'elements-only') and an emptiable "
16416		"particle", NULL);
16417	    return (ctxt->err);
16418	}
16419    } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16420	WXS_HAS_MIXED_CONTENT(type)) {
16421	/*
16422	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16423	* itself must be element-only"
16424	*/
16425	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16426	    /*
16427	    * SPEC (5.4.1.2) "The {content type} of the complex type
16428	    * definition itself and of the {base type definition} must be
16429	    * mixed"
16430	    */
16431	    xmlSchemaPCustomErr(ctxt,
16432		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16433		WXS_BASIC_CAST type, NULL,
16434		"If the content type is 'mixed', then the content type of the "
16435		"base type must also be 'mixed'", NULL);
16436	    return (ctxt->err);
16437	}
16438	/*
16439	* SPEC (5.4.2) "The particle of the complex type definition itself
16440	* must be a �valid restriction� of the particle of the {content
16441	* type} of the {base type definition} as defined in Particle Valid
16442	* (Restriction) (�3.9.6).
16443	*
16444	* URGENT TODO: (5.4.2)
16445	*/
16446    } else {
16447	xmlSchemaPCustomErr(ctxt,
16448	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16449	    WXS_BASIC_CAST type, NULL,
16450	    "The type is not a valid restriction of its base type", NULL);
16451	return (ctxt->err);
16452    }
16453    return (0);
16454}
16455
16456/**
16457 * xmlSchemaCheckCTComponent:
16458 * @ctxt:  the schema parser context
16459 * @type:  the complex type definition
16460 *
16461 * (3.4.6) Constraints on Complex Type Definition Schema Components
16462 *
16463 * Returns 0 if the constraints are satisfied, a positive
16464 * error code if not and -1 if an internal error occured.
16465 */
16466static int
16467xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16468			  xmlSchemaTypePtr type)
16469{
16470    int ret;
16471    /*
16472    * Complex Type Definition Properties Correct
16473    */
16474    ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16475    if (ret != 0)
16476	return (ret);
16477    if (WXS_IS_EXTENSION(type))
16478	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16479    else
16480	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16481    return (ret);
16482}
16483
16484/**
16485 * xmlSchemaCheckSRCCT:
16486 * @ctxt:  the schema parser context
16487 * @type:  the complex type definition
16488 *
16489 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16490 * Schema Representation Constraint:
16491 * Complex Type Definition Representation OK (src-ct)
16492 *
16493 * Returns 0 if the constraints are satisfied, a positive
16494 * error code if not and -1 if an internal error occured.
16495 */
16496static int
16497xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16498		    xmlSchemaTypePtr type)
16499{
16500    xmlSchemaTypePtr base;
16501    int ret = 0;
16502
16503    /*
16504    * TODO: Adjust the error codes here, as I used
16505    * XML_SCHEMAP_SRC_CT_1 only yet.
16506    */
16507    base = type->baseType;
16508    if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16509	/*
16510	* 1 If the <complexContent> alternative is chosen, the type definition
16511	* �resolved� to by the �actual value� of the base [attribute]
16512	* must be a complex type definition;
16513	*/
16514	if (! WXS_IS_COMPLEX(base)) {
16515	    xmlChar *str = NULL;
16516	    xmlSchemaPCustomErr(ctxt,
16517		XML_SCHEMAP_SRC_CT_1,
16518		WXS_BASIC_CAST type, type->node,
16519		"If using <complexContent>, the base type is expected to be "
16520		"a complex type. The base type '%s' is a simple type",
16521		xmlSchemaFormatQName(&str, base->targetNamespace,
16522		base->name));
16523	    FREE_AND_NULL(str)
16524	    return (XML_SCHEMAP_SRC_CT_1);
16525	}
16526    } else {
16527	/*
16528	* SPEC
16529	* 2 If the <simpleContent> alternative is chosen, all of the
16530	* following must be true:
16531	* 2.1 The type definition �resolved� to by the �actual value� of the
16532	* base [attribute] must be one of the following:
16533	*/
16534	if (WXS_IS_SIMPLE(base)) {
16535	    if (WXS_IS_EXTENSION(type) == 0) {
16536		xmlChar *str = NULL;
16537		/*
16538		* 2.1.3 only if the <extension> alternative is also
16539		* chosen, a simple type definition.
16540		*/
16541		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16542		xmlSchemaPCustomErr(ctxt,
16543		    XML_SCHEMAP_SRC_CT_1,
16544		    WXS_BASIC_CAST type, NULL,
16545		    "If using <simpleContent> and <restriction>, the base "
16546		    "type must be a complex type. The base type '%s' is "
16547		    "a simple type",
16548		    xmlSchemaFormatQName(&str, base->targetNamespace,
16549			base->name));
16550		FREE_AND_NULL(str)
16551		return (XML_SCHEMAP_SRC_CT_1);
16552	    }
16553	} else {
16554	    /* Base type is a complex type. */
16555	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16556		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16557		/*
16558		* 2.1.1 a complex type definition whose {content type} is a
16559		* simple type definition;
16560		* PASS
16561		*/
16562		if (base->contentTypeDef == NULL) {
16563		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16564			WXS_BASIC_CAST type, NULL,
16565			"Internal error: xmlSchemaCheckSRCCT, "
16566			"'%s', base type has no content type",
16567			type->name);
16568		    return (-1);
16569		}
16570	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16571		(WXS_IS_RESTRICTION(type))) {
16572
16573		/*
16574		* 2.1.2 only if the <restriction> alternative is also
16575		* chosen, a complex type definition whose {content type}
16576		* is mixed and a particle emptiable.
16577		*/
16578		if (! xmlSchemaIsParticleEmptiable(
16579		    (xmlSchemaParticlePtr) base->subtypes)) {
16580		    ret = XML_SCHEMAP_SRC_CT_1;
16581		} else
16582		    /*
16583		    * Attention: at this point the <simpleType> child is in
16584		    * ->contentTypeDef (put there during parsing).
16585		    */
16586		    if (type->contentTypeDef == NULL) {
16587		    xmlChar *str = NULL;
16588		    /*
16589		    * 2.2 If clause 2.1.2 above is satisfied, then there
16590		    * must be a <simpleType> among the [children] of
16591		    * <restriction>.
16592		    */
16593		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16594		    xmlSchemaPCustomErr(ctxt,
16595			XML_SCHEMAP_SRC_CT_1,
16596			WXS_BASIC_CAST type, NULL,
16597			"A <simpleType> is expected among the children "
16598			"of <restriction>, if <simpleContent> is used and "
16599			"the base type '%s' is a complex type",
16600			xmlSchemaFormatQName(&str, base->targetNamespace,
16601			base->name));
16602		    FREE_AND_NULL(str)
16603		    return (XML_SCHEMAP_SRC_CT_1);
16604		}
16605	    } else {
16606		ret = XML_SCHEMAP_SRC_CT_1;
16607	    }
16608	}
16609	if (ret > 0) {
16610	    xmlChar *str = NULL;
16611	    if (WXS_IS_RESTRICTION(type)) {
16612		xmlSchemaPCustomErr(ctxt,
16613		    XML_SCHEMAP_SRC_CT_1,
16614		    WXS_BASIC_CAST type, NULL,
16615		    "If <simpleContent> and <restriction> is used, the "
16616		    "base type must be a simple type or a complex type with "
16617		    "mixed content and particle emptiable. The base type "
16618		    "'%s' is none of those",
16619		    xmlSchemaFormatQName(&str, base->targetNamespace,
16620		    base->name));
16621	    } else {
16622		xmlSchemaPCustomErr(ctxt,
16623		    XML_SCHEMAP_SRC_CT_1,
16624		    WXS_BASIC_CAST type, NULL,
16625		    "If <simpleContent> and <extension> is used, the "
16626		    "base type must be a simple type. The base type '%s' "
16627		    "is a complex type",
16628		    xmlSchemaFormatQName(&str, base->targetNamespace,
16629		    base->name));
16630	    }
16631	    FREE_AND_NULL(str)
16632	}
16633    }
16634    /*
16635    * SPEC (3) "The corresponding complex type definition component must
16636    * satisfy the conditions set out in Constraints on Complex Type
16637    * Definition Schema Components (�3.4.6);"
16638    * NOTE (3) will be done in xmlSchemaTypeFixup().
16639    */
16640    /*
16641    * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16642    * above for {attribute wildcard} is satisfied, the intensional
16643    * intersection must be expressible, as defined in Attribute Wildcard
16644    * Intersection (�3.10.6).
16645    * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16646    */
16647    return (ret);
16648}
16649
16650#ifdef ENABLE_PARTICLE_RESTRICTION
16651/**
16652 * xmlSchemaCheckParticleRangeOK:
16653 * @ctxt:  the schema parser context
16654 * @type:  the complex type definition
16655 *
16656 * (3.9.6) Constraints on Particle Schema Components
16657 * Schema Component Constraint:
16658 * Occurrence Range OK (range-ok)
16659 *
16660 * STATUS: complete
16661 *
16662 * Returns 0 if the constraints are satisfied, a positive
16663 * error code if not and -1 if an internal error occured.
16664 */
16665static int
16666xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16667			      int bmin, int bmax)
16668{
16669    if (rmin < bmin)
16670	return (1);
16671    if ((bmax != UNBOUNDED) &&
16672	(rmax > bmax))
16673	return (1);
16674    return (0);
16675}
16676
16677/**
16678 * xmlSchemaCheckRCaseNameAndTypeOK:
16679 * @ctxt:  the schema parser context
16680 * @r: the restricting element declaration particle
16681 * @b: the base element declaration particle
16682 *
16683 * (3.9.6) Constraints on Particle Schema Components
16684 * Schema Component Constraint:
16685 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16686 * (rcase-NameAndTypeOK)
16687 *
16688 * STATUS:
16689 *   MISSING (3.2.3)
16690 *   CLARIFY: (3.2.2)
16691 *
16692 * Returns 0 if the constraints are satisfied, a positive
16693 * error code if not and -1 if an internal error occured.
16694 */
16695static int
16696xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16697				 xmlSchemaParticlePtr r,
16698				 xmlSchemaParticlePtr b)
16699{
16700    xmlSchemaElementPtr elemR, elemB;
16701
16702    /* TODO: Error codes (rcase-NameAndTypeOK). */
16703    elemR = (xmlSchemaElementPtr) r->children;
16704    elemB = (xmlSchemaElementPtr) b->children;
16705    /*
16706    * SPEC (1) "The declarations' {name}s and {target namespace}s are
16707    * the same."
16708    */
16709    if ((elemR != elemB) &&
16710	((! xmlStrEqual(elemR->name, elemB->name)) ||
16711	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16712	return (1);
16713    /*
16714    * SPEC (2) "R's occurrence range is a valid restriction of B's
16715    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16716    */
16717    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16718	    b->minOccurs, b->maxOccurs) != 0)
16719	return (1);
16720    /*
16721    * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16722    * {scope} are global."
16723    */
16724    if (elemR == elemB)
16725	return (0);
16726    /*
16727    * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16728    */
16729    if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16730	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16731	 return (1);
16732    /*
16733    * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16734    * or is not fixed, or R's declaration's {value constraint} is fixed
16735    * with the same value."
16736    */
16737    if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16738	((elemR->value == NULL) ||
16739	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16740	 /* TODO: Equality of the initial value or normalized or canonical? */
16741	 (! xmlStrEqual(elemR->value, elemB->value))))
16742	 return (1);
16743    /*
16744    * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16745    * definitions} is a subset of B's declaration's {identity-constraint
16746    * definitions}, if any."
16747    */
16748    if (elemB->idcs != NULL) {
16749	/* TODO */
16750    }
16751    /*
16752    * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16753    * superset of B's declaration's {disallowed substitutions}."
16754    */
16755    if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16756	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16757	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16758	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16759	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16760	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16761	 return (1);
16762    /*
16763    * SPEC (3.2.5) "R's {type definition} is validly derived given
16764    * {extension, list, union} from B's {type definition}"
16765    *
16766    * BADSPEC TODO: What's the point of adding "list" and "union" to the
16767    * set, if the corresponding constraints handle "restriction" and
16768    * "extension" only?
16769    *
16770    */
16771    {
16772	int set = 0;
16773
16774	set |= SUBSET_EXTENSION;
16775	set |= SUBSET_LIST;
16776	set |= SUBSET_UNION;
16777	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16778	    elemB->subtypes, set) != 0)
16779	    return (1);
16780    }
16781    return (0);
16782}
16783
16784/**
16785 * xmlSchemaCheckRCaseNSCompat:
16786 * @ctxt:  the schema parser context
16787 * @r: the restricting element declaration particle
16788 * @b: the base wildcard particle
16789 *
16790 * (3.9.6) Constraints on Particle Schema Components
16791 * Schema Component Constraint:
16792 * Particle Derivation OK (Elt:Any -- NSCompat)
16793 * (rcase-NSCompat)
16794 *
16795 * STATUS: complete
16796 *
16797 * Returns 0 if the constraints are satisfied, a positive
16798 * error code if not and -1 if an internal error occured.
16799 */
16800static int
16801xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16802			    xmlSchemaParticlePtr r,
16803			    xmlSchemaParticlePtr b)
16804{
16805    /* TODO:Error codes (rcase-NSCompat). */
16806    /*
16807    * SPEC "For an element declaration particle to be a �valid restriction�
16808    * of a wildcard particle all of the following must be true:"
16809    *
16810    * SPEC (1) "The element declaration's {target namespace} is �valid�
16811    * with respect to the wildcard's {namespace constraint} as defined by
16812    * Wildcard allows Namespace Name (�3.10.4)."
16813    */
16814    if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16815	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16816	return (1);
16817    /*
16818    * SPEC (2) "R's occurrence range is a valid restriction of B's
16819    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16820    */
16821    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16822	    b->minOccurs, b->maxOccurs) != 0)
16823	return (1);
16824
16825    return (0);
16826}
16827
16828/**
16829 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16830 * @ctxt:  the schema parser context
16831 * @r: the restricting element declaration particle
16832 * @b: the base model group particle
16833 *
16834 * (3.9.6) Constraints on Particle Schema Components
16835 * Schema Component Constraint:
16836 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16837 * (rcase-RecurseAsIfGroup)
16838 *
16839 * STATUS: TODO
16840 *
16841 * Returns 0 if the constraints are satisfied, a positive
16842 * error code if not and -1 if an internal error occured.
16843 */
16844static int
16845xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16846				    xmlSchemaParticlePtr r,
16847				    xmlSchemaParticlePtr b)
16848{
16849    /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16850    TODO
16851    return (0);
16852}
16853
16854/**
16855 * xmlSchemaCheckRCaseNSSubset:
16856 * @ctxt:  the schema parser context
16857 * @r: the restricting wildcard particle
16858 * @b: the base wildcard particle
16859 *
16860 * (3.9.6) Constraints on Particle Schema Components
16861 * Schema Component Constraint:
16862 * Particle Derivation OK (Any:Any -- NSSubset)
16863 * (rcase-NSSubset)
16864 *
16865 * STATUS: complete
16866 *
16867 * Returns 0 if the constraints are satisfied, a positive
16868 * error code if not and -1 if an internal error occured.
16869 */
16870static int
16871xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16872				    xmlSchemaParticlePtr r,
16873				    xmlSchemaParticlePtr b,
16874				    int isAnyTypeBase)
16875{
16876    /* TODO: Error codes (rcase-NSSubset). */
16877    /*
16878    * SPEC (1) "R's occurrence range is a valid restriction of B's
16879    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16880    */
16881    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16882	    b->minOccurs, b->maxOccurs))
16883	return (1);
16884    /*
16885    * SPEC (2) "R's {namespace constraint} must be an intensional subset
16886    * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16887    */
16888    if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16889	(xmlSchemaWildcardPtr) b->children))
16890	return (1);
16891    /*
16892    * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16893    * definition�, R's {process contents} must be identical to or stronger
16894    * than B's {process contents}, where strict is stronger than lax is
16895    * stronger than skip."
16896    */
16897    if (! isAnyTypeBase) {
16898	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16899	    ((xmlSchemaWildcardPtr) b->children)->processContents)
16900	    return (1);
16901    }
16902
16903    return (0);
16904}
16905
16906/**
16907 * xmlSchemaCheckCOSParticleRestrict:
16908 * @ctxt:  the schema parser context
16909 * @type:  the complex type definition
16910 *
16911 * (3.9.6) Constraints on Particle Schema Components
16912 * Schema Component Constraint:
16913 * Particle Valid (Restriction) (cos-particle-restrict)
16914 *
16915 * STATUS: TODO
16916 *
16917 * Returns 0 if the constraints are satisfied, a positive
16918 * error code if not and -1 if an internal error occured.
16919 */
16920static int
16921xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16922				  xmlSchemaParticlePtr r,
16923				  xmlSchemaParticlePtr b)
16924{
16925    int ret = 0;
16926
16927    /*part = WXS_TYPE_PARTICLE(type);
16928    basePart = WXS_TYPE_PARTICLE(base);
16929    */
16930
16931    TODO
16932
16933    /*
16934    * SPEC (1) "They are the same particle."
16935    */
16936    if (r == b)
16937	return (0);
16938
16939
16940    return (0);
16941}
16942
16943/**
16944 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16945 * @ctxt:  the schema parser context
16946 * @r: the model group particle
16947 * @b: the base wildcard particle
16948 *
16949 * (3.9.6) Constraints on Particle Schema Components
16950 * Schema Component Constraint:
16951 * Particle Derivation OK (All/Choice/Sequence:Any --
16952 *                         NSRecurseCheckCardinality)
16953 * (rcase-NSRecurseCheckCardinality)
16954 *
16955 * STATUS: TODO: subst-groups
16956 *
16957 * Returns 0 if the constraints are satisfied, a positive
16958 * error code if not and -1 if an internal error occured.
16959 */
16960static int
16961xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16962					     xmlSchemaParticlePtr r,
16963					     xmlSchemaParticlePtr b)
16964{
16965    xmlSchemaParticlePtr part;
16966    /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16967    if ((r->children == NULL) || (r->children->children == NULL))
16968	return (-1);
16969    /*
16970    * SPEC "For a group particle to be a �valid restriction� of a
16971    * wildcard particle..."
16972    *
16973    * SPEC (1) "Every member of the {particles} of the group is a �valid
16974    * restriction� of the wildcard as defined by
16975    * Particle Valid (Restriction) (�3.9.6)."
16976    */
16977    part = (xmlSchemaParticlePtr) r->children->children;
16978    do {
16979	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16980	    return (1);
16981	part = (xmlSchemaParticlePtr) part->next;
16982    } while (part != NULL);
16983    /*
16984    * SPEC (2) "The effective total range of the group [...] is a
16985    * valid restriction of B's occurrence range as defined by
16986    * Occurrence Range OK (�3.9.6)."
16987    */
16988    if (xmlSchemaCheckParticleRangeOK(
16989	    xmlSchemaGetParticleTotalRangeMin(r),
16990	    xmlSchemaGetParticleTotalRangeMax(r),
16991	    b->minOccurs, b->maxOccurs) != 0)
16992	return (1);
16993    return (0);
16994}
16995
16996/**
16997 * xmlSchemaCheckRCaseRecurse:
16998 * @ctxt:  the schema parser context
16999 * @r: the <all> or <sequence> model group particle
17000 * @b: the base <all> or <sequence> model group particle
17001 *
17002 * (3.9.6) Constraints on Particle Schema Components
17003 * Schema Component Constraint:
17004 * Particle Derivation OK (All:All,Sequence:Sequence --
17005                           Recurse)
17006 * (rcase-Recurse)
17007 *
17008 * STATUS:  ?
17009 * TODO: subst-groups
17010 *
17011 * Returns 0 if the constraints are satisfied, a positive
17012 * error code if not and -1 if an internal error occured.
17013 */
17014static int
17015xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17016			   xmlSchemaParticlePtr r,
17017			   xmlSchemaParticlePtr b)
17018{
17019    /* xmlSchemaParticlePtr part; */
17020    /* TODO: Error codes (rcase-Recurse). */
17021    if ((r->children == NULL) || (b->children == NULL) ||
17022	(r->children->type != b->children->type))
17023	return (-1);
17024    /*
17025    * SPEC "For an all or sequence group particle to be a �valid
17026    * restriction� of another group particle with the same {compositor}..."
17027    *
17028    * SPEC (1) "R's occurrence range is a valid restriction of B's
17029    * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17030    */
17031    if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17032	    b->minOccurs, b->maxOccurs))
17033	return (1);
17034
17035
17036    return (0);
17037}
17038
17039#endif
17040
17041#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17042    xmlSchemaPCustomErrExt(pctxt,      \
17043	XML_SCHEMAP_INVALID_FACET_VALUE, \
17044	WXS_BASIC_CAST fac1, fac1->node, \
17045	"It is an error for both '%s' and '%s' to be specified on the "\
17046	"same type definition", \
17047	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17048	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17049
17050#define FACET_RESTR_ERR(fac1, msg) \
17051    xmlSchemaPCustomErr(pctxt,      \
17052	XML_SCHEMAP_INVALID_FACET_VALUE, \
17053	WXS_BASIC_CAST fac1, fac1->node, \
17054	msg, NULL);
17055
17056#define FACET_RESTR_FIXED_ERR(fac) \
17057    xmlSchemaPCustomErr(pctxt, \
17058	XML_SCHEMAP_INVALID_FACET_VALUE, \
17059	WXS_BASIC_CAST fac, fac->node, \
17060	"The base type's facet is 'fixed', thus the value must not " \
17061	"differ", NULL);
17062
17063static void
17064xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17065			xmlSchemaFacetPtr facet1,
17066			xmlSchemaFacetPtr facet2,
17067			int lessGreater,
17068			int orEqual,
17069			int ofBase)
17070{
17071    xmlChar *msg = NULL;
17072
17073    msg = xmlStrdup(BAD_CAST "'");
17074    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17075    msg = xmlStrcat(msg, BAD_CAST "' has to be");
17076    if (lessGreater == 0)
17077	msg = xmlStrcat(msg, BAD_CAST " equal to");
17078    if (lessGreater == 1)
17079	msg = xmlStrcat(msg, BAD_CAST " greater than");
17080    else
17081	msg = xmlStrcat(msg, BAD_CAST " less than");
17082
17083    if (orEqual)
17084	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17085    msg = xmlStrcat(msg, BAD_CAST " '");
17086    msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17087    if (ofBase)
17088	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17089    else
17090	msg = xmlStrcat(msg, BAD_CAST "'");
17091
17092    xmlSchemaPCustomErr(pctxt,
17093	XML_SCHEMAP_INVALID_FACET_VALUE,
17094	WXS_BASIC_CAST facet1, NULL,
17095	(const char *) msg, NULL);
17096
17097    if (msg != NULL)
17098	xmlFree(msg);
17099}
17100
17101/*
17102* xmlSchemaDeriveAndValidateFacets:
17103*
17104* Schema Component Constraint: Simple Type Restriction (Facets)
17105* (st-restrict-facets)
17106*/
17107static int
17108xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17109				 xmlSchemaTypePtr type)
17110{
17111    xmlSchemaTypePtr base = type->baseType;
17112    xmlSchemaFacetLinkPtr link, cur, last = NULL;
17113    xmlSchemaFacetPtr facet, bfacet,
17114	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17115	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17116	fmininc = NULL, fmaxinc = NULL,
17117	fminexc = NULL, fmaxexc = NULL,
17118	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17119	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17120	bfmininc = NULL, bfmaxinc = NULL,
17121	bfminexc = NULL, bfmaxexc = NULL;
17122    int res; /* err = 0, fixedErr; */
17123
17124    /*
17125    * SPEC st-restrict-facets 1:
17126    * "The {variety} of R is the same as that of B."
17127    */
17128    /*
17129    * SPEC st-restrict-facets 2:
17130    * "If {variety} is atomic, the {primitive type definition}
17131    * of R is the same as that of B."
17132    *
17133    * NOTE: we leave 1 & 2 out for now, since this will be
17134    * satisfied by the derivation process.
17135    * CONSTRUCTION TODO: Maybe needed if using a construction API.
17136    */
17137    /*
17138    * SPEC st-restrict-facets 3:
17139    * "The {facets} of R are the union of S and the {facets}
17140    * of B, eliminating duplicates. To eliminate duplicates,
17141    * when a facet of the same kind occurs in both S and the
17142    * {facets} of B, the one in the {facets} of B is not
17143    * included, with the exception of enumeration and pattern
17144    * facets, for which multiple occurrences with distinct values
17145    * are allowed."
17146    */
17147
17148    if ((type->facetSet == NULL) && (base->facetSet == NULL))
17149	return (0);
17150
17151    last = type->facetSet;
17152    if (last != NULL)
17153	while (last->next != NULL)
17154	    last = last->next;
17155
17156    for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17157	facet = cur->facet;
17158	switch (facet->type) {
17159	    case XML_SCHEMA_FACET_LENGTH:
17160		flength = facet; break;
17161	    case XML_SCHEMA_FACET_MINLENGTH:
17162		fminlen = facet; break;
17163	    case XML_SCHEMA_FACET_MININCLUSIVE:
17164		fmininc = facet; break;
17165	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17166		fminexc = facet; break;
17167	    case XML_SCHEMA_FACET_MAXLENGTH:
17168		fmaxlen = facet; break;
17169	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17170		fmaxinc = facet; break;
17171	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17172		fmaxexc = facet; break;
17173	    case XML_SCHEMA_FACET_TOTALDIGITS:
17174		ftotdig = facet; break;
17175	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17176		ffracdig = facet; break;
17177	    default:
17178		break;
17179	}
17180    }
17181    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17182	facet = cur->facet;
17183	switch (facet->type) {
17184	    case XML_SCHEMA_FACET_LENGTH:
17185		bflength = facet; break;
17186	    case XML_SCHEMA_FACET_MINLENGTH:
17187		bfminlen = facet; break;
17188	    case XML_SCHEMA_FACET_MININCLUSIVE:
17189		bfmininc = facet; break;
17190	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17191		bfminexc = facet; break;
17192	    case XML_SCHEMA_FACET_MAXLENGTH:
17193		bfmaxlen = facet; break;
17194	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17195		bfmaxinc = facet; break;
17196	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17197		bfmaxexc = facet; break;
17198	    case XML_SCHEMA_FACET_TOTALDIGITS:
17199		bftotdig = facet; break;
17200	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17201		bffracdig = facet; break;
17202	    default:
17203		break;
17204	}
17205    }
17206    /*
17207    * length and minLength or maxLength (2.2) + (3.2)
17208    */
17209    if (flength && (fminlen || fmaxlen)) {
17210	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17211	    "either of 'minLength' or 'maxLength' to be specified on "
17212	    "the same type definition")
17213    }
17214    /*
17215    * Mutual exclusions in the same derivation step.
17216    */
17217    if ((fmaxinc) && (fmaxexc)) {
17218	/*
17219	* SCC "maxInclusive and maxExclusive"
17220	*/
17221	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17222    }
17223    if ((fmininc) && (fminexc)) {
17224	/*
17225	* SCC "minInclusive and minExclusive"
17226	*/
17227	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17228    }
17229
17230    if (flength && bflength) {
17231	/*
17232	* SCC "length valid restriction"
17233	* The values have to be equal.
17234	*/
17235	res = xmlSchemaCompareValues(flength->val, bflength->val);
17236	if (res == -2)
17237	    goto internal_error;
17238	if (res != 0)
17239	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17240	if ((res != 0) && (bflength->fixed)) {
17241	    FACET_RESTR_FIXED_ERR(flength)
17242	}
17243
17244    }
17245    if (fminlen && bfminlen) {
17246	/*
17247	* SCC "minLength valid restriction"
17248	* minLength >= BASE minLength
17249	*/
17250	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17251	if (res == -2)
17252	    goto internal_error;
17253	if (res == -1)
17254	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17255	if ((res != 0) && (bfminlen->fixed)) {
17256	    FACET_RESTR_FIXED_ERR(fminlen)
17257	}
17258    }
17259    if (fmaxlen && bfmaxlen) {
17260	/*
17261	* SCC "maxLength valid restriction"
17262	* maxLength <= BASE minLength
17263	*/
17264	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17265	if (res == -2)
17266	    goto internal_error;
17267	if (res == 1)
17268	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17269	if ((res != 0) && (bfmaxlen->fixed)) {
17270	    FACET_RESTR_FIXED_ERR(fmaxlen)
17271	}
17272    }
17273    /*
17274    * SCC "length and minLength or maxLength"
17275    */
17276    if (! flength)
17277	flength = bflength;
17278    if (flength) {
17279	if (! fminlen)
17280	    flength = bflength;
17281	if (fminlen) {
17282	    /* (1.1) length >= minLength */
17283	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17284	    if (res == -2)
17285		goto internal_error;
17286	    if (res == -1)
17287		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17288	}
17289	if (! fmaxlen)
17290	    fmaxlen = bfmaxlen;
17291	if (fmaxlen) {
17292	    /* (2.1) length <= maxLength */
17293	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17294	    if (res == -2)
17295		goto internal_error;
17296	    if (res == 1)
17297		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17298	}
17299    }
17300    if (fmaxinc) {
17301	/*
17302	* "maxInclusive"
17303	*/
17304	if (fmininc) {
17305	    /* SCC "maxInclusive >= minInclusive" */
17306	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17307	    if (res == -2)
17308		goto internal_error;
17309	    if (res == -1) {
17310		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17311	    }
17312	}
17313	/*
17314	* SCC "maxInclusive valid restriction"
17315	*/
17316	if (bfmaxinc) {
17317	    /* maxInclusive <= BASE maxInclusive */
17318	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17319	    if (res == -2)
17320		goto internal_error;
17321	    if (res == 1)
17322		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17323	    if ((res != 0) && (bfmaxinc->fixed)) {
17324		FACET_RESTR_FIXED_ERR(fmaxinc)
17325	    }
17326	}
17327	if (bfmaxexc) {
17328	    /* maxInclusive < BASE maxExclusive */
17329	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17330	    if (res == -2)
17331		goto internal_error;
17332	    if (res != -1) {
17333		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17334	    }
17335	}
17336	if (bfmininc) {
17337	    /* maxInclusive >= BASE minInclusive */
17338	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17339	    if (res == -2)
17340		goto internal_error;
17341	    if (res == -1) {
17342		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17343	    }
17344	}
17345	if (bfminexc) {
17346	    /* maxInclusive > BASE minExclusive */
17347	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17348	    if (res == -2)
17349		goto internal_error;
17350	    if (res != 1) {
17351		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17352	    }
17353	}
17354    }
17355    if (fmaxexc) {
17356	/*
17357	* "maxExclusive >= minExclusive"
17358	*/
17359	if (fminexc) {
17360	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17361	    if (res == -2)
17362		goto internal_error;
17363	    if (res == -1) {
17364		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17365	    }
17366	}
17367	/*
17368	* "maxExclusive valid restriction"
17369	*/
17370	if (bfmaxexc) {
17371	    /* maxExclusive <= BASE maxExclusive */
17372	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17373	    if (res == -2)
17374		goto internal_error;
17375	    if (res == 1) {
17376		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17377	    }
17378	    if ((res != 0) && (bfmaxexc->fixed)) {
17379		FACET_RESTR_FIXED_ERR(fmaxexc)
17380	    }
17381	}
17382	if (bfmaxinc) {
17383	    /* maxExclusive <= BASE maxInclusive */
17384	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17385	    if (res == -2)
17386		goto internal_error;
17387	    if (res == 1) {
17388		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17389	    }
17390	}
17391	if (bfmininc) {
17392	    /* maxExclusive > BASE minInclusive */
17393	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17394	    if (res == -2)
17395		goto internal_error;
17396	    if (res != 1) {
17397		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17398	    }
17399	}
17400	if (bfminexc) {
17401	    /* maxExclusive > BASE minExclusive */
17402	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17403	    if (res == -2)
17404		goto internal_error;
17405	    if (res != 1) {
17406		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17407	    }
17408	}
17409    }
17410    if (fminexc) {
17411	/*
17412	* "minExclusive < maxInclusive"
17413	*/
17414	if (fmaxinc) {
17415	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17416	    if (res == -2)
17417		goto internal_error;
17418	    if (res != -1) {
17419		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17420	    }
17421	}
17422	/*
17423	* "minExclusive valid restriction"
17424	*/
17425	if (bfminexc) {
17426	    /* minExclusive >= BASE minExclusive */
17427	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17428	    if (res == -2)
17429		goto internal_error;
17430	    if (res == -1) {
17431		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17432	    }
17433	    if ((res != 0) && (bfminexc->fixed)) {
17434		FACET_RESTR_FIXED_ERR(fminexc)
17435	    }
17436	}
17437	if (bfmaxinc) {
17438	    /* minExclusive <= BASE maxInclusive */
17439	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17440	    if (res == -2)
17441		goto internal_error;
17442	    if (res == 1) {
17443		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17444	    }
17445	}
17446	if (bfmininc) {
17447	    /* minExclusive >= BASE minInclusive */
17448	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17449	    if (res == -2)
17450		goto internal_error;
17451	    if (res == -1) {
17452		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17453	    }
17454	}
17455	if (bfmaxexc) {
17456	    /* minExclusive < BASE maxExclusive */
17457	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17458	    if (res == -2)
17459		goto internal_error;
17460	    if (res != -1) {
17461		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17462	    }
17463	}
17464    }
17465    if (fmininc) {
17466	/*
17467	* "minInclusive < maxExclusive"
17468	*/
17469	if (fmaxexc) {
17470	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17471	    if (res == -2)
17472		goto internal_error;
17473	    if (res != -1) {
17474		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17475	    }
17476	}
17477	/*
17478	* "minExclusive valid restriction"
17479	*/
17480	if (bfmininc) {
17481	    /* minInclusive >= BASE minInclusive */
17482	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17483	    if (res == -2)
17484		goto internal_error;
17485	    if (res == -1) {
17486		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17487	    }
17488	    if ((res != 0) && (bfmininc->fixed)) {
17489		FACET_RESTR_FIXED_ERR(fmininc)
17490	    }
17491	}
17492	if (bfmaxinc) {
17493	    /* minInclusive <= BASE maxInclusive */
17494	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17495	    if (res == -2)
17496		goto internal_error;
17497	    if (res == 1) {
17498		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17499	    }
17500	}
17501	if (bfminexc) {
17502	    /* minInclusive > BASE minExclusive */
17503	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17504	    if (res == -2)
17505		goto internal_error;
17506	    if (res != 1)
17507		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17508	}
17509	if (bfmaxexc) {
17510	    /* minInclusive < BASE maxExclusive */
17511	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17512	    if (res == -2)
17513		goto internal_error;
17514	    if (res != -1)
17515		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17516	}
17517    }
17518    if (ftotdig && bftotdig) {
17519	/*
17520	* SCC " totalDigits valid restriction"
17521	* totalDigits <= BASE totalDigits
17522	*/
17523	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17524	if (res == -2)
17525	    goto internal_error;
17526	if (res == 1)
17527	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17528	    -1, 1, 1);
17529	if ((res != 0) && (bftotdig->fixed)) {
17530	    FACET_RESTR_FIXED_ERR(ftotdig)
17531	}
17532    }
17533    if (ffracdig && bffracdig) {
17534	/*
17535	* SCC  "fractionDigits valid restriction"
17536	* fractionDigits <= BASE fractionDigits
17537	*/
17538	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17539	if (res == -2)
17540	    goto internal_error;
17541	if (res == 1)
17542	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17543	    -1, 1, 1);
17544	if ((res != 0) && (bffracdig->fixed)) {
17545	    FACET_RESTR_FIXED_ERR(ffracdig)
17546	}
17547    }
17548    /*
17549    * SCC "fractionDigits less than or equal to totalDigits"
17550    */
17551    if (! ftotdig)
17552	ftotdig = bftotdig;
17553    if (! ffracdig)
17554	ffracdig = bffracdig;
17555    if (ftotdig && ffracdig) {
17556	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17557	if (res == -2)
17558	    goto internal_error;
17559	if (res == 1)
17560	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17561		-1, 1, 0);
17562    }
17563    /*
17564    * *Enumerations* won' be added here, since only the first set
17565    * of enumerations in the ancestor-or-self axis is used
17566    * for validation, plus we need to use the base type of those
17567    * enumerations for whitespace.
17568    *
17569    * *Patterns*: won't be add here, since they are ORed at
17570    * type level and ANDed at ancestor level. This will
17571    * happed during validation by walking the base axis
17572    * of the type.
17573    */
17574    for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17575	bfacet = cur->facet;
17576	/*
17577	* Special handling of enumerations and patterns.
17578	* TODO: hmm, they should not appear in the set, so remove this.
17579	*/
17580	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17581	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17582	    continue;
17583	/*
17584	* Search for a duplicate facet in the current type.
17585	*/
17586	link = type->facetSet;
17587	/* err = 0; */
17588	/* fixedErr = 0; */
17589	while (link != NULL) {
17590	    facet = link->facet;
17591	    if (facet->type == bfacet->type) {
17592		switch (facet->type) {
17593		    case XML_SCHEMA_FACET_WHITESPACE:
17594			/*
17595			* The whitespace must be stronger.
17596			*/
17597			if (facet->whitespace < bfacet->whitespace) {
17598			    FACET_RESTR_ERR(flength,
17599				"The 'whitespace' value has to be equal to "
17600				"or stronger than the 'whitespace' value of "
17601				"the base type")
17602			}
17603			if ((bfacet->fixed) &&
17604			    (facet->whitespace != bfacet->whitespace)) {
17605			    FACET_RESTR_FIXED_ERR(facet)
17606			}
17607			break;
17608		    default:
17609			break;
17610		}
17611		/* Duplicate found. */
17612		break;
17613	    }
17614	    link = link->next;
17615	}
17616	/*
17617	* If no duplicate was found: add the base types's facet
17618	* to the set.
17619	*/
17620	if (link == NULL) {
17621	    link = (xmlSchemaFacetLinkPtr)
17622		xmlMalloc(sizeof(xmlSchemaFacetLink));
17623	    if (link == NULL) {
17624		xmlSchemaPErrMemory(pctxt,
17625		    "deriving facets, creating a facet link", NULL);
17626		return (-1);
17627	    }
17628	    link->facet = cur->facet;
17629	    link->next = NULL;
17630	    if (last == NULL)
17631		type->facetSet = link;
17632	    else
17633		last->next = link;
17634	    last = link;
17635	}
17636
17637    }
17638
17639    return (0);
17640internal_error:
17641    PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17642	"an error occured");
17643    return (-1);
17644}
17645
17646static int
17647xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17648					     xmlSchemaTypePtr type)
17649{
17650    xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17651    /*
17652    * The actual value is then formed by replacing any union type
17653    * definition in the �explicit members� with the members of their
17654    * {member type definitions}, in order.
17655    *
17656    * TODO: There's a bug entry at
17657    * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17658    * which indicates that we'll keep the union types the future.
17659    */
17660    link = type->memberTypes;
17661    while (link != NULL) {
17662
17663	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17664	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17665
17666	if (WXS_IS_UNION(link->type)) {
17667	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17668	    if (subLink != NULL) {
17669		link->type = subLink->type;
17670		if (subLink->next != NULL) {
17671		    lastLink = link->next;
17672		    subLink = subLink->next;
17673		    prevLink = link;
17674		    while (subLink != NULL) {
17675			newLink = (xmlSchemaTypeLinkPtr)
17676			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17677			if (newLink == NULL) {
17678			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17679				NULL);
17680			    return (-1);
17681			}
17682			newLink->type = subLink->type;
17683			prevLink->next = newLink;
17684			prevLink = newLink;
17685			newLink->next = lastLink;
17686
17687			subLink = subLink->next;
17688		    }
17689		}
17690	    }
17691	}
17692	link = link->next;
17693    }
17694    return (0);
17695}
17696
17697static void
17698xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17699{
17700    int has = 0, needVal = 0, normVal = 0;
17701
17702    has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17703    if (has) {
17704	needVal = (type->baseType->flags &
17705	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17706	normVal = (type->baseType->flags &
17707	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17708    }
17709    if (type->facets != NULL) {
17710	xmlSchemaFacetPtr fac;
17711
17712	for (fac = type->facets; fac != NULL; fac = fac->next) {
17713	    switch (fac->type) {
17714		case XML_SCHEMA_FACET_WHITESPACE:
17715		    break;
17716		case XML_SCHEMA_FACET_PATTERN:
17717		    normVal = 1;
17718		    has = 1;
17719		    break;
17720		case XML_SCHEMA_FACET_ENUMERATION:
17721		    needVal = 1;
17722		    normVal = 1;
17723		    has = 1;
17724		    break;
17725		default:
17726		    has = 1;
17727		    break;
17728	    }
17729	}
17730    }
17731    if (normVal)
17732	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17733    if (needVal)
17734	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17735    if (has)
17736	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17737
17738    if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17739	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17740	/*
17741	* OPTIMIZE VAL TODO: Some facets need a computed value.
17742	*/
17743	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17744	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17745	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17746	}
17747    }
17748}
17749
17750static int
17751xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17752{
17753
17754
17755    /*
17756    * Evaluate the whitespace-facet value.
17757    */
17758    if (WXS_IS_LIST(type)) {
17759	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17760	return (0);
17761    } else if (WXS_IS_UNION(type))
17762	return (0);
17763
17764    if (type->facetSet != NULL) {
17765	xmlSchemaFacetLinkPtr lin;
17766
17767	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17768	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17769		switch (lin->facet->whitespace) {
17770		case XML_SCHEMAS_FACET_PRESERVE:
17771		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17772		    break;
17773		case XML_SCHEMAS_FACET_REPLACE:
17774		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17775		    break;
17776		case XML_SCHEMAS_FACET_COLLAPSE:
17777		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17778		    break;
17779		default:
17780		    return (-1);
17781		}
17782		return (0);
17783	    }
17784	}
17785    }
17786    /*
17787    * For all �atomic� datatypes other than string (and types �derived�
17788    * by �restriction� from it) the value of whiteSpace is fixed to
17789    * collapse
17790    */
17791    {
17792	xmlSchemaTypePtr anc;
17793
17794	for (anc = type->baseType; anc != NULL &&
17795		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17796		anc = anc->baseType) {
17797
17798	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17799		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17800		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17801
17802		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17803		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17804		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17805
17806		} else
17807		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17808		break;
17809	    }
17810	}
17811    }
17812    return (0);
17813}
17814
17815static int
17816xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17817			  xmlSchemaTypePtr type)
17818{
17819    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17820	return(0);
17821    if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17822	return(0);
17823    type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17824
17825    if (WXS_IS_LIST(type)) {
17826	/*
17827	* Corresponds to <simpleType><list>...
17828	*/
17829	if (type->subtypes == NULL) {
17830	    /*
17831	    * This one is really needed, so get out.
17832	    */
17833	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17834		"list type has no item-type assigned");
17835	    return(-1);
17836	}
17837    } else if (WXS_IS_UNION(type)) {
17838	/*
17839	* Corresponds to <simpleType><union>...
17840	*/
17841	if (type->memberTypes == NULL) {
17842	    /*
17843	    * This one is really needed, so get out.
17844	    */
17845	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17846		"union type has no member-types assigned");
17847	    return(-1);
17848	}
17849    } else {
17850	/*
17851	* Corresponds to <simpleType><restriction>...
17852	*/
17853	if (type->baseType == NULL) {
17854	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17855		"type has no base-type assigned");
17856	    return(-1);
17857	}
17858	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17859	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17860		return(-1);
17861	/*
17862	* Variety
17863	* If the <restriction> alternative is chosen, then the
17864	* {variety} of the {base type definition}.
17865	*/
17866	if (WXS_IS_ATOMIC(type->baseType))
17867	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17868	else if (WXS_IS_LIST(type->baseType)) {
17869	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17870	    /*
17871	    * Inherit the itemType.
17872	    */
17873	    type->subtypes = type->baseType->subtypes;
17874	} else if (WXS_IS_UNION(type->baseType)) {
17875	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17876	    /*
17877	    * NOTE that we won't assign the memberTypes of the base,
17878	    * since this will make trouble when freeing them; we will
17879	    * use a lookup function to access them instead.
17880	    */
17881	}
17882    }
17883    return(0);
17884}
17885
17886#ifdef DEBUG_TYPE
17887static void
17888xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17889		       xmlSchemaTypePtr type)
17890{
17891    if (type->node != NULL) {
17892        xmlGenericError(xmlGenericErrorContext,
17893                        "Type of %s : %s:%d :", name,
17894                        type->node->doc->URL,
17895                        xmlGetLineNo(type->node));
17896    } else {
17897        xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17898    }
17899    if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17900	switch (type->contentType) {
17901	    case XML_SCHEMA_CONTENT_SIMPLE:
17902		xmlGenericError(xmlGenericErrorContext, "simple\n");
17903		break;
17904	    case XML_SCHEMA_CONTENT_ELEMENTS:
17905		xmlGenericError(xmlGenericErrorContext, "elements\n");
17906		break;
17907	    case XML_SCHEMA_CONTENT_UNKNOWN:
17908		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17909		break;
17910	    case XML_SCHEMA_CONTENT_EMPTY:
17911		xmlGenericError(xmlGenericErrorContext, "empty\n");
17912		break;
17913	    case XML_SCHEMA_CONTENT_MIXED:
17914		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17915		    type->subtypes))
17916		    xmlGenericError(xmlGenericErrorContext,
17917			"mixed as emptiable particle\n");
17918		else
17919		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
17920		break;
17921		/* Removed, since not used. */
17922		/*
17923		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17924		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17925		break;
17926		*/
17927	    case XML_SCHEMA_CONTENT_BASIC:
17928		xmlGenericError(xmlGenericErrorContext, "basic\n");
17929		break;
17930	    default:
17931		xmlGenericError(xmlGenericErrorContext,
17932		    "not registered !!!\n");
17933		break;
17934	}
17935    }
17936}
17937#endif
17938
17939/*
17940* 3.14.6 Constraints on Simple Type Definition Schema Components
17941*/
17942static int
17943xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17944				 xmlSchemaTypePtr type)
17945{
17946    int res, olderrs = pctxt->nberrors;
17947
17948    if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17949	return(-1);
17950
17951    if (! WXS_IS_TYPE_NOT_FIXED(type))
17952	return(0);
17953
17954    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17955    type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17956
17957    if (type->baseType == NULL) {
17958	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17959	    "missing baseType");
17960	goto exit_failure;
17961    }
17962    if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
17963	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
17964    /*
17965    * If a member type of a union is a union itself, we need to substitute
17966    * that member type for its member types.
17967    * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17968    * types in WXS 1.1.
17969    */
17970    if ((type->memberTypes != NULL) &&
17971	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17972	return(-1);
17973    /*
17974    * SPEC src-simple-type 1
17975    * "The corresponding simple type definition, if any, must satisfy
17976    * the conditions set out in Constraints on Simple Type Definition
17977    * Schema Components (�3.14.6)."
17978    */
17979    /*
17980    * Schema Component Constraint: Simple Type Definition Properties Correct
17981    * (st-props-correct)
17982    */
17983    res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17984    HFAILURE HERROR
17985    /*
17986    * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17987    * (cos-st-restricts)
17988    */
17989    res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17990    HFAILURE HERROR
17991    /*
17992    * TODO: Removed the error report, since it got annoying to get an
17993    * extra error report, if anything failed until now.
17994    * Enable this if needed.
17995    *
17996    * xmlSchemaPErr(ctxt, type->node,
17997    *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17998    *    "Simple type '%s' does not satisfy the constraints "
17999    *    "on simple type definitions.\n",
18000    *    type->name, NULL);
18001    */
18002    /*
18003    * Schema Component Constraint: Simple Type Restriction (Facets)
18004    * (st-restrict-facets)
18005    */
18006    res = xmlSchemaCheckFacetValues(type, pctxt);
18007    HFAILURE HERROR
18008    if ((type->facetSet != NULL) ||
18009	(type->baseType->facetSet != NULL)) {
18010	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18011	HFAILURE HERROR
18012    }
18013    /*
18014    * Whitespace value.
18015    */
18016    res = xmlSchemaTypeFixupWhitespace(type);
18017    HFAILURE HERROR
18018    xmlSchemaTypeFixupOptimFacets(type);
18019
18020exit_error:
18021#ifdef DEBUG_TYPE
18022    xmlSchemaDebugFixedType(pctxt, type);
18023#endif
18024    if (olderrs != pctxt->nberrors)
18025	return(pctxt->err);
18026    return(0);
18027
18028exit_failure:
18029#ifdef DEBUG_TYPE
18030    xmlSchemaDebugFixedType(pctxt, type);
18031#endif
18032    return(-1);
18033}
18034
18035static int
18036xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18037			  xmlSchemaTypePtr type)
18038{
18039    int res = 0, olderrs = pctxt->nberrors;
18040    xmlSchemaTypePtr baseType = type->baseType;
18041
18042    if (! WXS_IS_TYPE_NOT_FIXED(type))
18043	return(0);
18044    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18045    if (baseType == NULL) {
18046	PERROR_INT("xmlSchemaFixupComplexType",
18047	    "missing baseType");
18048	goto exit_failure;
18049    }
18050    /*
18051    * Fixup the base type.
18052    */
18053    if (WXS_IS_TYPE_NOT_FIXED(baseType))
18054	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18055    if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18056	/*
18057	* Skip fixup if the base type is invalid.
18058	* TODO: Generate a warning!
18059	*/
18060	return(0);
18061    }
18062    /*
18063    * This basically checks if the base type can be derived.
18064    */
18065    res = xmlSchemaCheckSRCCT(pctxt, type);
18066    HFAILURE HERROR
18067    /*
18068    * Fixup the content type.
18069    */
18070    if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18071	/*
18072	* Corresponds to <complexType><simpleContent>...
18073	*/
18074	if ((WXS_IS_COMPLEX(baseType)) &&
18075	    (baseType->contentTypeDef != NULL) &&
18076	    (WXS_IS_RESTRICTION(type))) {
18077	    xmlSchemaTypePtr contentBase, content;
18078#ifdef ENABLE_NAMED_LOCALS
18079	    char buf[30];
18080	    const xmlChar *tmpname;
18081#endif
18082	    /*
18083	    * SPEC (1) If <restriction> + base type is <complexType>,
18084	    * "whose own {content type} is a simple type..."
18085	    */
18086	    if (type->contentTypeDef != NULL) {
18087		/*
18088		* SPEC (1.1) "the simple type definition corresponding to the
18089		* <simpleType> among the [children] of <restriction> if there
18090		* is one;"
18091		* Note that this "<simpleType> among the [children]" was put
18092		* into ->contentTypeDef during parsing.
18093		*/
18094		contentBase = type->contentTypeDef;
18095		type->contentTypeDef = NULL;
18096	    } else {
18097		/*
18098		* (1.2) "...otherwise (<restriction> has no <simpleType>
18099		* among its [children]), the simple type definition which
18100		* is the {content type} of the ... base type."
18101		*/
18102		contentBase = baseType->contentTypeDef;
18103	    }
18104	    /*
18105	    * SPEC
18106	    * "... a simple type definition which restricts the simple
18107	    * type definition identified in clause 1.1 or clause 1.2
18108	    * with a set of facet components"
18109	    *
18110	    * Create the anonymous simple type, which will be the content
18111	    * type of the complex type.
18112	    */
18113#ifdef ENABLE_NAMED_LOCALS
18114	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18115	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18116	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18117		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18118		type->node, 0);
18119#else
18120	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18121		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18122		type->node, 0);
18123#endif
18124	    if (content == NULL)
18125		goto exit_failure;
18126	    /*
18127	    * We will use the same node as for the <complexType>
18128	    * to have it somehow anchored in the schema doc.
18129	    */
18130	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18131	    content->baseType = contentBase;
18132	    /*
18133	    * Move the facets, previously anchored on the
18134	    * complexType during parsing.
18135	    */
18136	    content->facets = type->facets;
18137	    type->facets = NULL;
18138	    content->facetSet = type->facetSet;
18139	    type->facetSet = NULL;
18140
18141	    type->contentTypeDef = content;
18142	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18143		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18144	    /*
18145	    * Fixup the newly created type. We don't need to check
18146	    * for circularity here.
18147	    */
18148	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18149	    HFAILURE HERROR
18150	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18151	    HFAILURE HERROR
18152
18153	} else if ((WXS_IS_COMPLEX(baseType)) &&
18154	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18155	    (WXS_IS_RESTRICTION(type))) {
18156	    /*
18157	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18158	    * an emptiable particle, then a simple type definition which
18159	    * restricts the <restriction>'s <simpleType> child.
18160	    */
18161	    if ((type->contentTypeDef == NULL) ||
18162		(type->contentTypeDef->baseType == NULL)) {
18163		/*
18164		* TODO: Check if this ever happens.
18165		*/
18166		xmlSchemaPCustomErr(pctxt,
18167		    XML_SCHEMAP_INTERNAL,
18168		    WXS_BASIC_CAST type, NULL,
18169		    "Internal error: xmlSchemaTypeFixup, "
18170		    "complex type '%s': the <simpleContent><restriction> "
18171		    "is missing a <simpleType> child, but was not catched "
18172		    "by xmlSchemaCheckSRCCT()", type->name);
18173		goto exit_failure;
18174	    }
18175	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18176	    /*
18177	    * SPEC (3) If <extension> + base is <complexType> with
18178	    * <simpleType> content, "...then the {content type} of that
18179	    * complex type definition"
18180	    */
18181	    if (baseType->contentTypeDef == NULL) {
18182		/*
18183		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18184		* should have catched this already.
18185		*/
18186		xmlSchemaPCustomErr(pctxt,
18187		    XML_SCHEMAP_INTERNAL,
18188		    WXS_BASIC_CAST type, NULL,
18189		    "Internal error: xmlSchemaTypeFixup, "
18190		    "complex type '%s': the <extension>ed base type is "
18191		    "a complex type with no simple content type",
18192		    type->name);
18193		goto exit_failure;
18194	    }
18195	    type->contentTypeDef = baseType->contentTypeDef;
18196	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18197	    /*
18198	    * SPEC (4) <extension> + base is <simpleType>
18199	    * "... then that simple type definition"
18200	    */
18201	    type->contentTypeDef = baseType;
18202	} else {
18203	    /*
18204	    * TODO: Check if this ever happens.
18205	    */
18206	    xmlSchemaPCustomErr(pctxt,
18207		XML_SCHEMAP_INTERNAL,
18208		WXS_BASIC_CAST type, NULL,
18209		"Internal error: xmlSchemaTypeFixup, "
18210		"complex type '%s' with <simpleContent>: unhandled "
18211		"derivation case", type->name);
18212	    goto exit_failure;
18213	}
18214    } else {
18215	int dummySequence = 0;
18216	xmlSchemaParticlePtr particle =
18217	    (xmlSchemaParticlePtr) type->subtypes;
18218	/*
18219	* Corresponds to <complexType><complexContent>...
18220	*
18221	* NOTE that the effective mixed was already set during parsing of
18222	* <complexType> and <complexContent>; its flag value is
18223	* XML_SCHEMAS_TYPE_MIXED.
18224	*
18225	* Compute the "effective content":
18226	* (2.1.1) + (2.1.2) + (2.1.3)
18227	*/
18228	if ((particle == NULL) ||
18229	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18230	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18231	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18232	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18233	    (particle->minOccurs == 0))) &&
18234	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18235	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18236		/*
18237		* SPEC (2.1.4) "If the �effective mixed� is true, then
18238		* a particle whose properties are as follows:..."
18239		*
18240		* Empty sequence model group with
18241		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18242		* NOTE that we sill assign it the <complexType> node to
18243		* somehow anchor it in the doc.
18244		*/
18245		if ((particle == NULL) ||
18246		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18247		    /*
18248		    * Create the particle.
18249		    */
18250		    particle = xmlSchemaAddParticle(pctxt,
18251			type->node, 1, 1);
18252		    if (particle == NULL)
18253			goto exit_failure;
18254		    /*
18255		    * Create the model group.
18256		    */ /* URGENT TODO: avoid adding to pending items. */
18257		    particle->children = (xmlSchemaTreeItemPtr)
18258			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18259			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18260		    if (particle->children == NULL)
18261			goto exit_failure;
18262
18263		    type->subtypes = (xmlSchemaTypePtr) particle;
18264		}
18265		dummySequence = 1;
18266		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18267	    } else {
18268		/*
18269		* SPEC (2.1.5) "otherwise empty"
18270		*/
18271		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18272	    }
18273	} else {
18274	    /*
18275	    * SPEC (2.2) "otherwise the particle corresponding to the
18276	    * <all>, <choice>, <group> or <sequence> among the
18277	    * [children]."
18278	    */
18279	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18280	}
18281	/*
18282	* Compute the "content type".
18283	*/
18284	if (WXS_IS_RESTRICTION(type)) {
18285	    /*
18286	    * SPEC (3.1) "If <restriction>..."
18287	    * (3.1.1) + (3.1.2) */
18288	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18289		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18290		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18291	    }
18292	} else {
18293	    /*
18294	    * SPEC (3.2) "If <extension>..."
18295	    */
18296	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18297		/*
18298		* SPEC (3.2.1)
18299		* "If the �effective content� is empty, then the
18300		*  {content type} of the [...] base ..."
18301		*/
18302		type->contentType = baseType->contentType;
18303		type->subtypes = baseType->subtypes;
18304		/*
18305		* Fixes bug #347316:
18306		* This is the case when the base type has a simple
18307		* type definition as content.
18308		*/
18309		type->contentTypeDef = baseType->contentTypeDef;
18310		/*
18311		* NOTE that the effective mixed is ignored here.
18312		*/
18313	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18314		/*
18315		* SPEC (3.2.2)
18316		*/
18317		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18318		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18319	    } else {
18320		/*
18321		* SPEC (3.2.3)
18322		*/
18323		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18324		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18325		    /*
18326		    * "A model group whose {compositor} is sequence and whose
18327		    * {particles} are..."
18328		    */
18329		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18330		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18331		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18332			XML_SCHEMA_TYPE_ALL))
18333		{
18334		    /*
18335		    * SPEC cos-all-limited (1)
18336		    */
18337		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18338			/* TODO: error code */
18339			XML_SCHEMAP_COS_ALL_LIMITED,
18340			WXS_ITEM_NODE(type), NULL,
18341			"The type has an 'all' model group in its "
18342			"{content type} and thus cannot be derived from "
18343			"a non-empty type, since this would produce a "
18344			"'sequence' model group containing the 'all' "
18345			"model group; 'all' model groups are not "
18346			"allowed to appear inside other model groups",
18347			NULL, NULL);
18348
18349		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18350		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18351		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18352			XML_SCHEMA_TYPE_ALL))
18353		{
18354		    /*
18355		    * SPEC cos-all-limited (1)
18356		    */
18357		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18358			/* TODO: error code */
18359			XML_SCHEMAP_COS_ALL_LIMITED,
18360			WXS_ITEM_NODE(type), NULL,
18361			"A type cannot be derived by extension from a type "
18362			"which has an 'all' model group in its "
18363			"{content type}, since this would produce a "
18364			"'sequence' model group containing the 'all' "
18365			"model group; 'all' model groups are not "
18366			"allowed to appear inside other model groups",
18367			NULL, NULL);
18368
18369		} else if (! dummySequence) {
18370		    xmlSchemaTreeItemPtr effectiveContent =
18371			(xmlSchemaTreeItemPtr) type->subtypes;
18372		    /*
18373		    * Create the particle.
18374		    */
18375		    particle = xmlSchemaAddParticle(pctxt,
18376			type->node, 1, 1);
18377		    if (particle == NULL)
18378			goto exit_failure;
18379		    /*
18380		    * Create the "sequence" model group.
18381		    */
18382		    particle->children = (xmlSchemaTreeItemPtr)
18383			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18384			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18385		    if (particle->children == NULL)
18386			goto exit_failure;
18387		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18388		    /*
18389		    * SPEC "the particle of the {content type} of
18390		    * the ... base ..."
18391		    * Create a duplicate of the base type's particle
18392		    * and assign its "term" to it.
18393		    */
18394		    particle->children->children =
18395			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18396			type->node,
18397			((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18398			((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18399		    if (particle->children->children == NULL)
18400			goto exit_failure;
18401		    particle = (xmlSchemaParticlePtr)
18402			particle->children->children;
18403		    particle->children =
18404			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18405		    /*
18406		    * SPEC "followed by the �effective content�."
18407		    */
18408		    particle->next = effectiveContent;
18409		    /*
18410		    * This all will result in:
18411		    * new-particle
18412		    *   --> new-sequence(
18413		    *         new-particle
18414		    *           --> base-model,
18415		    *         this-particle
18416		    *	        --> this-model
18417		    *	    )
18418		    */
18419		} else {
18420		    /*
18421		    * This is the case when there is already an empty
18422		    * <sequence> with minOccurs==maxOccurs==1.
18423		    * Just add the base types's content type.
18424		    * NOTE that, although we miss to add an intermediate
18425		    * <sequence>, this should produce no difference to
18426		    * neither the regex compilation of the content model,
18427		    * nor to the complex type contraints.
18428		    */
18429		    particle->children->children =
18430			(xmlSchemaTreeItemPtr) baseType->subtypes;
18431		}
18432	    }
18433	}
18434    }
18435    /*
18436    * Now fixup attribute uses:
18437    *   - expand attr. group references
18438    *     - intersect attribute wildcards
18439    *   - inherit attribute uses of the base type
18440    *   - inherit or union attr. wildcards if extending
18441    *   - apply attr. use prohibitions if restricting
18442    */
18443    res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18444    HFAILURE HERROR
18445    /*
18446    * Apply the complex type component constraints; this will not
18447    * check attributes, since this is done in
18448    * xmlSchemaFixupTypeAttributeUses().
18449    */
18450    res = xmlSchemaCheckCTComponent(pctxt, type);
18451    HFAILURE HERROR
18452
18453#ifdef DEBUG_TYPE
18454    xmlSchemaDebugFixedType(pctxt, type);
18455#endif
18456    if (olderrs != pctxt->nberrors)
18457	return(pctxt->err);
18458    else
18459	return(0);
18460
18461exit_error:
18462    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18463#ifdef DEBUG_TYPE
18464    xmlSchemaDebugFixedType(pctxt, type);
18465#endif
18466    return(pctxt->err);
18467
18468exit_failure:
18469    type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18470#ifdef DEBUG_TYPE
18471    xmlSchemaDebugFixedType(pctxt, type);
18472#endif
18473    return(-1);
18474}
18475
18476
18477/**
18478 * xmlSchemaTypeFixup:
18479 * @typeDecl:  the schema type definition
18480 * @ctxt:  the schema parser context
18481 *
18482 * Fixes the content model of the type.
18483 * URGENT TODO: We need an int result!
18484 */
18485static int
18486xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18487                   xmlSchemaAbstractCtxtPtr actxt)
18488{
18489    if (type == NULL)
18490        return(0);
18491    if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18492	AERROR_INT("xmlSchemaTypeFixup",
18493	    "this function needs a parser context");
18494	return(-1);
18495    }
18496    if (! WXS_IS_TYPE_NOT_FIXED(type))
18497	return(0);
18498    if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18499	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18500    else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18501	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18502    return(0);
18503}
18504
18505/**
18506 * xmlSchemaCheckFacet:
18507 * @facet:  the facet
18508 * @typeDecl:  the schema type definition
18509 * @pctxt:  the schema parser context or NULL
18510 * @name: the optional name of the type
18511 *
18512 * Checks and computes the values of facets.
18513 *
18514 * Returns 0 if valid, a positive error code if not valid and
18515 *         -1 in case of an internal or API error.
18516 */
18517int
18518xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18519                    xmlSchemaTypePtr typeDecl,
18520                    xmlSchemaParserCtxtPtr pctxt,
18521		    const xmlChar * name ATTRIBUTE_UNUSED)
18522{
18523    int ret = 0, ctxtGiven;
18524
18525    if ((facet == NULL) || (typeDecl == NULL))
18526        return(-1);
18527    /*
18528    * TODO: will the parser context be given if used from
18529    * the relaxNG module?
18530    */
18531    if (pctxt == NULL)
18532	ctxtGiven = 0;
18533    else
18534	ctxtGiven = 1;
18535
18536    switch (facet->type) {
18537        case XML_SCHEMA_FACET_MININCLUSIVE:
18538        case XML_SCHEMA_FACET_MINEXCLUSIVE:
18539        case XML_SCHEMA_FACET_MAXINCLUSIVE:
18540        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18541	case XML_SCHEMA_FACET_ENUMERATION: {
18542                /*
18543                 * Okay we need to validate the value
18544                 * at that point.
18545                 */
18546		xmlSchemaTypePtr base;
18547
18548		/* 4.3.5.5 Constraints on enumeration Schema Components
18549		* Schema Component Constraint: enumeration valid restriction
18550		* It is an �error� if any member of {value} is not in the
18551		* �value space� of {base type definition}.
18552		*
18553		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18554		* The value �must� be in the
18555		* �value space� of the �base type�.
18556		*/
18557		/*
18558		* This function is intended to deliver a compiled value
18559		* on the facet. In this implementation of XML Schemata the
18560		* type holding a facet, won't be a built-in type.
18561		* Thus to ensure that other API
18562		* calls (relaxng) do work, if the given type is a built-in
18563		* type, we will assume that the given built-in type *is
18564		* already* the base type.
18565		*/
18566		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18567		    base = typeDecl->baseType;
18568		    if (base == NULL) {
18569			PERROR_INT("xmlSchemaCheckFacet",
18570			    "a type user derived type has no base type");
18571			return (-1);
18572		    }
18573		} else
18574		    base = typeDecl;
18575
18576		if (! ctxtGiven) {
18577		    /*
18578		    * A context is needed if called from RelaxNG.
18579		    */
18580		    pctxt = xmlSchemaNewParserCtxt("*");
18581		    if (pctxt == NULL)
18582			return (-1);
18583		}
18584		/*
18585		* NOTE: This call does not check the content nodes,
18586		* since they are not available:
18587		* facet->node is just the node holding the facet
18588		* definition, *not* the attribute holding the *value*
18589		* of the facet.
18590		*/
18591		ret = xmlSchemaVCheckCVCSimpleType(
18592		    ACTXT_CAST pctxt, facet->node, base,
18593		    facet->value, &(facet->val), 1, 1, 0);
18594                if (ret != 0) {
18595		    if (ret < 0) {
18596			/* No error message for RelaxNG. */
18597			if (ctxtGiven) {
18598			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18599				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18600				"Internal error: xmlSchemaCheckFacet, "
18601				"failed to validate the value '%s' of the "
18602				"facet '%s' against the base type",
18603				facet->value, xmlSchemaFacetTypeToString(facet->type));
18604			}
18605			goto internal_error;
18606		    }
18607		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18608		    /* No error message for RelaxNG. */
18609		    if (ctxtGiven) {
18610			xmlChar *str = NULL;
18611
18612			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18613			    ret, facet->node, WXS_BASIC_CAST facet,
18614			    "The value '%s' of the facet does not validate "
18615			    "against the base type '%s'",
18616			    facet->value,
18617			    xmlSchemaFormatQName(&str,
18618				base->targetNamespace, base->name));
18619			FREE_AND_NULL(str);
18620		    }
18621		    goto exit;
18622                } else if (facet->val == NULL) {
18623		    if (ctxtGiven) {
18624			PERROR_INT("xmlSchemaCheckFacet",
18625			    "value was not computed");
18626		    }
18627		    TODO
18628		}
18629                break;
18630            }
18631        case XML_SCHEMA_FACET_PATTERN:
18632            facet->regexp = xmlRegexpCompile(facet->value);
18633            if (facet->regexp == NULL) {
18634		ret = XML_SCHEMAP_REGEXP_INVALID;
18635		/* No error message for RelaxNG. */
18636		if (ctxtGiven) {
18637		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18638			ret, facet->node, WXS_BASIC_CAST typeDecl,
18639			"The value '%s' of the facet 'pattern' is not a "
18640			"valid regular expression",
18641			facet->value, NULL);
18642		}
18643            }
18644            break;
18645        case XML_SCHEMA_FACET_TOTALDIGITS:
18646        case XML_SCHEMA_FACET_FRACTIONDIGITS:
18647        case XML_SCHEMA_FACET_LENGTH:
18648        case XML_SCHEMA_FACET_MAXLENGTH:
18649        case XML_SCHEMA_FACET_MINLENGTH:
18650
18651	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18652		ret = xmlSchemaValidatePredefinedType(
18653		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18654		    facet->value, &(facet->val));
18655	    } else {
18656		ret = xmlSchemaValidatePredefinedType(
18657		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18658		    facet->value, &(facet->val));
18659	    }
18660	    if (ret != 0) {
18661		if (ret < 0) {
18662		    /* No error message for RelaxNG. */
18663		    if (ctxtGiven) {
18664			PERROR_INT("xmlSchemaCheckFacet",
18665			    "validating facet value");
18666		    }
18667		    goto internal_error;
18668		}
18669		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18670		/* No error message for RelaxNG. */
18671		if (ctxtGiven) {
18672		    /* error code */
18673		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18674			ret, facet->node, WXS_BASIC_CAST typeDecl,
18675			"The value '%s' of the facet '%s' is not a valid '%s'",
18676			facet->value,
18677			xmlSchemaFacetTypeToString(facet->type),
18678			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18679			    BAD_CAST "nonNegativeInteger" :
18680			    BAD_CAST "positiveInteger",
18681			NULL);
18682		}
18683	    }
18684	    break;
18685
18686        case XML_SCHEMA_FACET_WHITESPACE:{
18687                if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18688                    facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18689                } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18690                    facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18691                } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18692                    facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18693                } else {
18694		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18695                    /* No error message for RelaxNG. */
18696		    if (ctxtGiven) {
18697			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18698			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18699			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18700			    "The value '%s' of the facet 'whitespace' is not "
18701			    "valid", facet->value, NULL);
18702                    }
18703                }
18704            }
18705        default:
18706            break;
18707    }
18708exit:
18709    if ((! ctxtGiven) && (pctxt != NULL))
18710	xmlSchemaFreeParserCtxt(pctxt);
18711    return (ret);
18712internal_error:
18713    if ((! ctxtGiven) && (pctxt != NULL))
18714	xmlSchemaFreeParserCtxt(pctxt);
18715    return (-1);
18716}
18717
18718/**
18719 * xmlSchemaCheckFacetValues:
18720 * @typeDecl:  the schema type definition
18721 * @ctxt:  the schema parser context
18722 *
18723 * Checks the default values types, especially for facets
18724 */
18725static int
18726xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18727			  xmlSchemaParserCtxtPtr pctxt)
18728{
18729    int res, olderrs = pctxt->nberrors;
18730    const xmlChar *name = typeDecl->name;
18731    /*
18732    * NOTE: It is intended to use the facets list, instead
18733    * of facetSet.
18734    */
18735    if (typeDecl->facets != NULL) {
18736	xmlSchemaFacetPtr facet = typeDecl->facets;
18737
18738	/*
18739	* Temporarily assign the "schema" to the validation context
18740	* of the parser context. This is needed for NOTATION validation.
18741	*/
18742	if (pctxt->vctxt == NULL) {
18743	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18744		return(-1);
18745	}
18746	pctxt->vctxt->schema = pctxt->schema;
18747	while (facet != NULL) {
18748	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18749	    HFAILURE
18750	    facet = facet->next;
18751	}
18752	pctxt->vctxt->schema = NULL;
18753    }
18754    if (olderrs != pctxt->nberrors)
18755	return(pctxt->err);
18756    return(0);
18757exit_failure:
18758    return(-1);
18759}
18760
18761/**
18762 * xmlSchemaGetCircModelGrDefRef:
18763 * @ctxtMGroup: the searched model group
18764 * @selfMGroup: the second searched model group
18765 * @particle: the first particle
18766 *
18767 * This one is intended to be used by
18768 * xmlSchemaCheckGroupDefCircular only.
18769 *
18770 * Returns the particle with the circular model group definition reference,
18771 * otherwise NULL.
18772 */
18773static xmlSchemaTreeItemPtr
18774xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18775			      xmlSchemaTreeItemPtr particle)
18776{
18777    xmlSchemaTreeItemPtr circ = NULL;
18778    xmlSchemaTreeItemPtr term;
18779    xmlSchemaModelGroupDefPtr gdef;
18780
18781    for (; particle != NULL; particle = particle->next) {
18782	term = particle->children;
18783	if (term == NULL)
18784	    continue;
18785	switch (term->type) {
18786	    case XML_SCHEMA_TYPE_GROUP:
18787		gdef = (xmlSchemaModelGroupDefPtr) term;
18788		if (gdef == groupDef)
18789		    return (particle);
18790		/*
18791		* Mark this model group definition to avoid infinite
18792		* recursion on circular references not yet examined.
18793		*/
18794		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18795		    continue;
18796		if (gdef->children != NULL) {
18797		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18798		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18799			gdef->children->children);
18800		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18801		    if (circ != NULL)
18802			return (circ);
18803		}
18804		break;
18805	    case XML_SCHEMA_TYPE_SEQUENCE:
18806	    case XML_SCHEMA_TYPE_CHOICE:
18807	    case XML_SCHEMA_TYPE_ALL:
18808		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18809		if (circ != NULL)
18810		    return (circ);
18811		break;
18812	    default:
18813		break;
18814	}
18815    }
18816    return (NULL);
18817}
18818
18819/**
18820 * xmlSchemaCheckGroupDefCircular:
18821 * @item:  the model group definition
18822 * @ctxt:  the parser context
18823 * @name:  the name
18824 *
18825 * Checks for circular references to model group definitions.
18826 */
18827static void
18828xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18829			       xmlSchemaParserCtxtPtr ctxt)
18830{
18831    /*
18832    * Schema Component Constraint: Model Group Correct
18833    * 2 Circular groups are disallowed. That is, within the {particles}
18834    * of a group there must not be at any depth a particle whose {term}
18835    * is the group itself.
18836    */
18837    if ((item == NULL) ||
18838	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18839	(item->children == NULL))
18840	return;
18841    {
18842	xmlSchemaTreeItemPtr circ;
18843
18844	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18845	if (circ != NULL) {
18846	    xmlChar *str = NULL;
18847	    /*
18848	    * TODO: The error report is not adequate: this constraint
18849	    * is defined for model groups but not definitions, but since
18850	    * there cannot be any circular model groups without a model group
18851	    * definition (if not using a construction API), we check those
18852	    * defintions only.
18853	    */
18854	    xmlSchemaPCustomErr(ctxt,
18855		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18856		NULL, WXS_ITEM_NODE(circ),
18857		"Circular reference to the model group definition '%s' "
18858		"defined", xmlSchemaFormatQName(&str,
18859		    item->targetNamespace, item->name));
18860	    FREE_AND_NULL(str)
18861	    /*
18862	    * NOTE: We will cut the reference to avoid further
18863	    * confusion of the processor. This is a fatal error.
18864	    */
18865	    circ->children = NULL;
18866	}
18867    }
18868}
18869
18870/**
18871 * xmlSchemaModelGroupToModelGroupDefFixup:
18872 * @ctxt:  the parser context
18873 * @mg:  the model group
18874 *
18875 * Assigns the model group of model group definitions to the "term"
18876 * of the referencing particle.
18877 * In xmlSchemaResolveModelGroupParticleReferences the model group
18878 * definitions were assigned to the "term", since needed for the
18879 * circularity check.
18880 *
18881 * Schema Component Constraint:
18882 *     All Group Limited (cos-all-limited) (1.2)
18883 */
18884static void
18885xmlSchemaModelGroupToModelGroupDefFixup(
18886    xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18887    xmlSchemaModelGroupPtr mg)
18888{
18889    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18890
18891    while (particle != NULL) {
18892	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18893	    ((WXS_PARTICLE_TERM(particle))->type !=
18894		XML_SCHEMA_TYPE_GROUP))
18895	{
18896	    particle = WXS_PTC_CAST particle->next;
18897	    continue;
18898	}
18899	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18900	    /*
18901	    * TODO: Remove the particle.
18902	    */
18903	    WXS_PARTICLE_TERM(particle) = NULL;
18904	    particle = WXS_PTC_CAST particle->next;
18905	    continue;
18906	}
18907	/*
18908	* Assign the model group to the {term} of the particle.
18909	*/
18910	WXS_PARTICLE_TERM(particle) =
18911	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18912
18913	particle = WXS_PTC_CAST particle->next;
18914    }
18915}
18916
18917/**
18918 * xmlSchemaCheckAttrGroupCircularRecur:
18919 * @ctxtGr: the searched attribute group
18920 * @attr: the current attribute list to be processed
18921 *
18922 * This one is intended to be used by
18923 * xmlSchemaCheckAttrGroupCircular only.
18924 *
18925 * Returns the circular attribute grou reference, otherwise NULL.
18926 */
18927static xmlSchemaQNameRefPtr
18928xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18929				     xmlSchemaItemListPtr list)
18930{
18931    xmlSchemaAttributeGroupPtr gr;
18932    xmlSchemaQNameRefPtr ref, circ;
18933    int i;
18934    /*
18935    * We will search for an attribute group reference which
18936    * references the context attribute group.
18937    */
18938    for (i = 0; i < list->nbItems; i++) {
18939	ref = list->items[i];
18940	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18941	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18942	    (ref->item != NULL))
18943	{
18944	    gr = WXS_ATTR_GROUP_CAST ref->item;
18945	    if (gr == ctxtGr)
18946		return(ref);
18947	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18948		continue;
18949	    /*
18950	    * Mark as visited to avoid infinite recursion on
18951	    * circular references not yet examined.
18952	    */
18953	    if ((gr->attrUses) &&
18954		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18955	    {
18956		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18957		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18958		    (xmlSchemaItemListPtr) gr->attrUses);
18959		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18960		if (circ != NULL)
18961		    return (circ);
18962	    }
18963
18964	}
18965    }
18966    return (NULL);
18967}
18968
18969/**
18970 * xmlSchemaCheckAttrGroupCircular:
18971 * attrGr:  the attribute group definition
18972 * @ctxt:  the parser context
18973 * @name:  the name
18974 *
18975 * Checks for circular references of attribute groups.
18976 */
18977static int
18978xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
18979				xmlSchemaParserCtxtPtr ctxt)
18980{
18981    /*
18982    * Schema Representation Constraint:
18983    * Attribute Group Definition Representation OK
18984    * 3 Circular group reference is disallowed outside <redefine>.
18985    * That is, unless this element information item's parent is
18986    * <redefine>, then among the [children], if any, there must
18987    * not be an <attributeGroup> with ref [attribute] which resolves
18988    * to the component corresponding to this <attributeGroup>. Indirect
18989    * circularity is also ruled out. That is, when QName resolution
18990    * (Schema Document) (�3.15.3) is applied to a �QName� arising from
18991    * any <attributeGroup>s with a ref [attribute] among the [children],
18992    * it must not be the case that a �QName� is encountered at any depth
18993    * which resolves to the component corresponding to this <attributeGroup>.
18994    */
18995    if (attrGr->attrUses == NULL)
18996	return(0);
18997    else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
18998	return(0);
18999    else {
19000	xmlSchemaQNameRefPtr circ;
19001
19002	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19003	    (xmlSchemaItemListPtr) attrGr->attrUses);
19004	if (circ != NULL) {
19005	    xmlChar *str = NULL;
19006	    /*
19007	    * TODO: Report the referenced attr group as QName.
19008	    */
19009	    xmlSchemaPCustomErr(ctxt,
19010		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19011		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19012		"Circular reference to the attribute group '%s' "
19013		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19014	    FREE_AND_NULL(str);
19015	    /*
19016	    * NOTE: We will cut the reference to avoid further
19017	    * confusion of the processor.
19018	    * BADSPEC TODO: The spec should define how to process in this case.
19019	    */
19020	    circ->item = NULL;
19021	    return(ctxt->err);
19022	}
19023    }
19024    return(0);
19025}
19026
19027static int
19028xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19029				  xmlSchemaAttributeGroupPtr attrGr);
19030
19031/**
19032 * xmlSchemaExpandAttributeGroupRefs:
19033 * @pctxt: the parser context
19034 * @node: the node of the component holding the attribute uses
19035 * @completeWild: the intersected wildcard to be returned
19036 * @list: the attribute uses
19037 *
19038 * Substitutes contained attribute group references
19039 * for their attribute uses. Wilcards are intersected.
19040 * Attribute use prohibitions are removed from the list
19041 * and returned via the @prohibs list.
19042 * Pointlessness of attr. prohibs, if a matching attr. decl
19043 * is existent a well, are checked.
19044 */
19045static int
19046xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19047				  xmlSchemaBasicItemPtr item,
19048				  xmlSchemaWildcardPtr *completeWild,
19049				  xmlSchemaItemListPtr list,
19050				  xmlSchemaItemListPtr prohibs)
19051{
19052    xmlSchemaAttributeGroupPtr gr;
19053    xmlSchemaAttributeUsePtr use;
19054    xmlSchemaItemListPtr sublist;
19055    int i, j;
19056    int created = (*completeWild == NULL) ? 0 : 1;
19057
19058    if (prohibs)
19059	prohibs->nbItems = 0;
19060
19061    for (i = 0; i < list->nbItems; i++) {
19062	use = list->items[i];
19063
19064	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19065	    if (prohibs == NULL) {
19066		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19067		    "unexpected attr prohibition found");
19068		return(-1);
19069	    }
19070	    /*
19071	    * Remove from attribute uses.
19072	    */
19073	    if (xmlSchemaItemListRemove(list, i) == -1)
19074		return(-1);
19075	    i--;
19076	    /*
19077	    * Note that duplicate prohibitions were already
19078	    * handled at parsing time.
19079	    */
19080	    /*
19081	    * Add to list of prohibitions.
19082	    */
19083	    xmlSchemaItemListAddSize(prohibs, 2, use);
19084	    continue;
19085	}
19086	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19087	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19088	{
19089	    if ((WXS_QNAME_CAST use)->item == NULL)
19090		return(-1);
19091	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19092	    /*
19093	    * Expand the referenced attr. group.
19094	    * TODO: remove this, this is done in a previous step, so
19095	    * already done here.
19096	    */
19097	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19098		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19099		    return(-1);
19100	    }
19101	    /*
19102	    * Build the 'complete' wildcard; i.e. intersect multiple
19103	    * wildcards.
19104	    */
19105	    if (gr->attributeWildcard != NULL) {
19106		if (*completeWild == NULL) {
19107		    *completeWild = gr->attributeWildcard;
19108		} else {
19109		    if (! created) {
19110			xmlSchemaWildcardPtr tmpWild;
19111
19112			 /*
19113			* Copy the first encountered wildcard as context,
19114			* except for the annotation.
19115			*
19116			* Although the complete wildcard might not correspond
19117			* to any node in the schema, we will anchor it on
19118			* the node of the owner component.
19119			*/
19120			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19121			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19122			    WXS_ITEM_NODE(item));
19123			if (tmpWild == NULL)
19124			    return(-1);
19125			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19126			    tmpWild, *completeWild) == -1)
19127			    return (-1);
19128			tmpWild->processContents = (*completeWild)->processContents;
19129			*completeWild = tmpWild;
19130			created = 1;
19131		    }
19132
19133		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19134			gr->attributeWildcard) == -1)
19135			return(-1);
19136		}
19137	    }
19138	    /*
19139	    * Just remove the reference if the referenced group does not
19140	    * contain any attribute uses.
19141	    */
19142	    if (gr->attrUses == NULL) {
19143		if (xmlSchemaItemListRemove(list, i) == -1)
19144		    return(-1);
19145		i--;
19146		continue;
19147	    }
19148	    /*
19149	    * Add the attribute uses.
19150	    */
19151	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19152	    if (sublist->nbItems != 0) {
19153		list->items[i] = sublist->items[0];
19154		if (sublist->nbItems != 1) {
19155		    for (j = 1; j < sublist->nbItems; j++) {
19156			i++;
19157			if (xmlSchemaItemListInsert(list,
19158				sublist->items[j], i) == -1)
19159			    return(-1);
19160		    }
19161		}
19162	    }
19163	}
19164
19165    }
19166    /*
19167    * Handle pointless prohibitions of declared attributes.
19168    */
19169    if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19170	xmlSchemaAttributeUseProhibPtr prohib;
19171
19172	for (i = prohibs->nbItems -1; i >= 0; i--) {
19173	    prohib = prohibs->items[i];
19174	    for (j = 0; j < list->nbItems; j++) {
19175		use = list->items[j];
19176
19177		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19178		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19179		{
19180		    xmlChar *str = NULL;
19181
19182		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19183			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19184			prohib->node, NULL,
19185			"Skipping pointless attribute use prohibition "
19186			"'%s', since a corresponding attribute use "
19187			"exists already in the type definition",
19188			xmlSchemaFormatQName(&str,
19189			    prohib->targetNamespace, prohib->name),
19190			NULL, NULL);
19191		    FREE_AND_NULL(str);
19192		    /*
19193		    * Remove the prohibition.
19194		    */
19195		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19196			return(-1);
19197		    break;
19198		}
19199	    }
19200	}
19201    }
19202    return(0);
19203}
19204
19205/**
19206 * xmlSchemaAttributeGroupExpandRefs:
19207 * @pctxt:  the parser context
19208 * @attrGr:  the attribute group definition
19209 *
19210 * Computation of:
19211 * {attribute uses} property
19212 * {attribute wildcard} property
19213 *
19214 * Substitutes contained attribute group references
19215 * for their attribute uses. Wilcards are intersected.
19216 */
19217static int
19218xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19219				  xmlSchemaAttributeGroupPtr attrGr)
19220{
19221    if ((attrGr->attrUses == NULL) ||
19222	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19223	return(0);
19224
19225    attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19226    if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19227	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19228	return(-1);
19229    return(0);
19230}
19231
19232/**
19233 * xmlSchemaAttributeGroupExpandRefs:
19234 * @pctxt:  the parser context
19235 * @attrGr:  the attribute group definition
19236 *
19237 * Substitutes contained attribute group references
19238 * for their attribute uses. Wilcards are intersected.
19239 *
19240 * Schema Component Constraint:
19241 *    Attribute Group Definition Properties Correct (ag-props-correct)
19242 */
19243static int
19244xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19245				  xmlSchemaAttributeGroupPtr attrGr)
19246{
19247    /*
19248    * SPEC ag-props-correct
19249    * (1) "The values of the properties of an attribute group definition
19250    * must be as described in the property tableau in The Attribute
19251    * Group Definition Schema Component (�3.6.1), modulo the impact of
19252    * Missing Sub-components (�5.3);"
19253    */
19254
19255    if ((attrGr->attrUses != NULL) &&
19256	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19257    {
19258	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19259	xmlSchemaAttributeUsePtr use, tmp;
19260	int i, j, hasId = 0;
19261
19262	for (i = uses->nbItems -1; i >= 0; i--) {
19263	    use = uses->items[i];
19264	    /*
19265	    * SPEC ag-props-correct
19266	    * (2) "Two distinct members of the {attribute uses} must not have
19267	    * {attribute declaration}s both of whose {name}s match and whose
19268	    * {target namespace}s are identical."
19269	    */
19270	    if (i > 0) {
19271		for (j = i -1; j >= 0; j--) {
19272		    tmp = uses->items[j];
19273		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19274			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19275			(WXS_ATTRUSE_DECL_TNS(use) ==
19276			WXS_ATTRUSE_DECL_TNS(tmp)))
19277		    {
19278			xmlChar *str = NULL;
19279
19280			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19281			    XML_SCHEMAP_AG_PROPS_CORRECT,
19282			    attrGr->node, WXS_BASIC_CAST attrGr,
19283			    "Duplicate %s",
19284			    xmlSchemaGetComponentDesignation(&str, use),
19285			    NULL);
19286			FREE_AND_NULL(str);
19287			/*
19288			* Remove the duplicate.
19289			*/
19290			if (xmlSchemaItemListRemove(uses, i) == -1)
19291			    return(-1);
19292			goto next_use;
19293		    }
19294		}
19295	    }
19296	    /*
19297	    * SPEC ag-props-correct
19298	    * (3) "Two distinct members of the {attribute uses} must not have
19299	    * {attribute declaration}s both of whose {type definition}s are or
19300	    * are derived from ID."
19301	    * TODO: Does 'derived' include member-types of unions?
19302	    */
19303	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19304		if (xmlSchemaIsDerivedFromBuiltInType(
19305		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19306		{
19307		    if (hasId) {
19308			xmlChar *str = NULL;
19309
19310			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19311			    XML_SCHEMAP_AG_PROPS_CORRECT,
19312			    attrGr->node, WXS_BASIC_CAST attrGr,
19313			    "There must not exist more than one attribute "
19314			    "declaration of type 'xs:ID' "
19315			    "(or derived from 'xs:ID'). The %s violates this "
19316			    "constraint",
19317			    xmlSchemaGetComponentDesignation(&str, use),
19318			    NULL);
19319			FREE_AND_NULL(str);
19320			if (xmlSchemaItemListRemove(uses, i) == -1)
19321			    return(-1);
19322		    }
19323		    hasId = 1;
19324		}
19325	    }
19326next_use: {}
19327	}
19328    }
19329    return(0);
19330}
19331
19332/**
19333 * xmlSchemaResolveAttrGroupReferences:
19334 * @attrgrpDecl:  the schema attribute definition
19335 * @ctxt:  the schema parser context
19336 * @name:  the attribute name
19337 *
19338 * Resolves references to attribute group definitions.
19339 */
19340static int
19341xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19342				    xmlSchemaParserCtxtPtr ctxt)
19343{
19344    xmlSchemaAttributeGroupPtr group;
19345
19346    if (ref->item != NULL)
19347        return(0);
19348    group = xmlSchemaGetAttributeGroup(ctxt->schema,
19349	ref->name,
19350	ref->targetNamespace);
19351    if (group == NULL) {
19352	xmlSchemaPResCompAttrErr(ctxt,
19353	    XML_SCHEMAP_SRC_RESOLVE,
19354	    NULL, ref->node,
19355	    "ref", ref->name, ref->targetNamespace,
19356	    ref->itemType, NULL);
19357	return(ctxt->err);
19358    }
19359    ref->item = WXS_BASIC_CAST group;
19360    return(0);
19361}
19362
19363/**
19364 * xmlSchemaCheckAttrPropsCorrect:
19365 * @item:  an schema attribute declaration/use
19366 * @ctxt:  a schema parser context
19367 * @name:  the name of the attribute
19368 *
19369 *
19370 * Schema Component Constraint:
19371 *    Attribute Declaration Properties Correct (a-props-correct)
19372 *
19373 * Validates the value constraints of an attribute declaration/use.
19374 * NOTE that this needs the simle type definitions to be already
19375 *   builded and checked.
19376 */
19377static int
19378xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19379			       xmlSchemaAttributePtr attr)
19380{
19381
19382    /*
19383    * SPEC a-props-correct (1)
19384    * "The values of the properties of an attribute declaration must
19385    * be as described in the property tableau in The Attribute
19386    * Declaration Schema Component (�3.2.1), modulo the impact of
19387    * Missing Sub-components (�5.3)."
19388    */
19389
19390    if (WXS_ATTR_TYPEDEF(attr) == NULL)
19391	return(0);
19392
19393    if (attr->defValue != NULL) {
19394	int ret;
19395
19396	/*
19397	* SPEC a-props-correct (3)
19398	* "If the {type definition} is or is derived from ID then there
19399	* must not be a {value constraint}."
19400	*/
19401	if (xmlSchemaIsDerivedFromBuiltInType(
19402	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19403	{
19404	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19405		XML_SCHEMAP_A_PROPS_CORRECT_3,
19406		NULL, WXS_BASIC_CAST attr,
19407		"Value constraints are not allowed if the type definition "
19408		"is or is derived from xs:ID",
19409		NULL, NULL);
19410	    return(pctxt->err);
19411	}
19412	/*
19413	* SPEC a-props-correct (2)
19414	* "if there is a {value constraint}, the canonical lexical
19415	* representation of its value must be �valid� with respect
19416	* to the {type definition} as defined in String Valid (�3.14.4)."
19417	* TODO: Don't care about the *cononical* stuff here, this requirement
19418	* will be removed in WXS 1.1 anyway.
19419	*/
19420	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19421	    attr->node, WXS_ATTR_TYPEDEF(attr),
19422	    attr->defValue, &(attr->defVal),
19423	    1, 1, 0);
19424	if (ret != 0) {
19425	    if (ret < 0) {
19426		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19427		    "calling xmlSchemaVCheckCVCSimpleType()");
19428		return(-1);
19429	    }
19430	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19431		XML_SCHEMAP_A_PROPS_CORRECT_2,
19432		NULL, WXS_BASIC_CAST attr,
19433		"The value of the value constraint is not valid",
19434		NULL, NULL);
19435	    return(pctxt->err);
19436	}
19437    }
19438
19439    return(0);
19440}
19441
19442static xmlSchemaElementPtr
19443xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19444				 xmlSchemaElementPtr ancestor)
19445{
19446    xmlSchemaElementPtr ret;
19447
19448    if (WXS_SUBST_HEAD(ancestor) == NULL)
19449	return (NULL);
19450    if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19451	return (ancestor);
19452
19453    if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19454	return (NULL);
19455    WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19456    ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19457	WXS_SUBST_HEAD(ancestor));
19458    WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19459
19460    return (ret);
19461}
19462
19463/**
19464 * xmlSchemaCheckElemPropsCorrect:
19465 * @ctxt:  a schema parser context
19466 * @decl: the element declaration
19467 * @name:  the name of the attribute
19468 *
19469 * Schema Component Constraint:
19470 * Element Declaration Properties Correct (e-props-correct)
19471 *
19472 * STATUS:
19473 *   missing: (6)
19474 */
19475static int
19476xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19477			       xmlSchemaElementPtr elemDecl)
19478{
19479    int ret = 0;
19480    xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19481    /*
19482    * SPEC (1) "The values of the properties of an element declaration
19483    * must be as described in the property tableau in The Element
19484    * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19485    * Sub-components (�5.3)."
19486    */
19487    if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19488	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19489
19490	xmlSchemaCheckElementDeclComponent(head, pctxt);
19491	/*
19492	* SPEC (3) "If there is a non-�absent� {substitution group
19493	* affiliation}, then {scope} must be global."
19494	*/
19495	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19496	    xmlSchemaPCustomErr(pctxt,
19497		XML_SCHEMAP_E_PROPS_CORRECT_3,
19498		WXS_BASIC_CAST elemDecl, NULL,
19499		"Only global element declarations can have a "
19500		"substitution group affiliation", NULL);
19501	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19502	}
19503	/*
19504	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19505	* That is, it must not be possible to return to an element declaration
19506	* by repeatedly following the {substitution group affiliation}
19507	* property."
19508	*/
19509	if (head == elemDecl)
19510	    circ = head;
19511	else if (WXS_SUBST_HEAD(head) != NULL)
19512	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19513	else
19514	    circ = NULL;
19515	if (circ != NULL) {
19516	    xmlChar *strA = NULL, *strB = NULL;
19517
19518	    xmlSchemaPCustomErrExt(pctxt,
19519		XML_SCHEMAP_E_PROPS_CORRECT_6,
19520		WXS_BASIC_CAST circ, NULL,
19521		"The element declaration '%s' defines a circular "
19522		"substitution group to element declaration '%s'",
19523		xmlSchemaGetComponentQName(&strA, circ),
19524		xmlSchemaGetComponentQName(&strB, head),
19525		NULL);
19526	    FREE_AND_NULL(strA)
19527	    FREE_AND_NULL(strB)
19528	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19529	}
19530	/*
19531	* SPEC (4) "If there is a {substitution group affiliation},
19532	* the {type definition}
19533	* of the element declaration must be validly derived from the {type
19534	* definition} of the {substitution group affiliation}, given the value
19535	* of the {substitution group exclusions} of the {substitution group
19536	* affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19537	* (if the {type definition} is complex) or as defined in
19538	* Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19539	* simple)."
19540	*
19541	* NOTE: {substitution group exclusions} means the values of the
19542	* attribute "final".
19543	*/
19544
19545	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19546	    int set = 0;
19547
19548	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19549		set |= SUBSET_EXTENSION;
19550	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19551		set |= SUBSET_RESTRICTION;
19552
19553	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19554		WXS_ELEM_TYPEDEF(head), set) != 0) {
19555		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19556
19557		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19558		xmlSchemaPCustomErrExt(pctxt,
19559		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19560		    WXS_BASIC_CAST elemDecl, NULL,
19561		    "The type definition '%s' was "
19562		    "either rejected by the substitution group "
19563		    "affiliation '%s', or not validly derived from its type "
19564		    "definition '%s'",
19565		    xmlSchemaGetComponentQName(&strA, typeDef),
19566		    xmlSchemaGetComponentQName(&strB, head),
19567		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19568		FREE_AND_NULL(strA)
19569		FREE_AND_NULL(strB)
19570		FREE_AND_NULL(strC)
19571	    }
19572	}
19573    }
19574    /*
19575    * SPEC (5) "If the {type definition} or {type definition}'s
19576    * {content type}
19577    * is or is derived from ID then there must not be a {value constraint}.
19578    * Note: The use of ID as a type definition for elements goes beyond
19579    * XML 1.0, and should be avoided if backwards compatibility is desired"
19580    */
19581    if ((elemDecl->value != NULL) &&
19582	((WXS_IS_SIMPLE(typeDef) &&
19583	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19584	 (WXS_IS_COMPLEX(typeDef) &&
19585	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19586	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19587	    XML_SCHEMAS_ID)))) {
19588
19589	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19590	xmlSchemaPCustomErr(pctxt,
19591	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19592	    WXS_BASIC_CAST elemDecl, NULL,
19593	    "The type definition (or type definition's content type) is or "
19594	    "is derived from ID; value constraints are not allowed in "
19595	    "conjunction with such a type definition", NULL);
19596    } else if (elemDecl->value != NULL) {
19597	int vcret;
19598	xmlNodePtr node = NULL;
19599
19600	/*
19601	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19602	* representation of its value must be �valid� with respect to the
19603	* {type definition} as defined in Element Default Valid (Immediate)
19604	* (�3.3.6)."
19605	*/
19606	if (typeDef == NULL) {
19607	    xmlSchemaPErr(pctxt, elemDecl->node,
19608		XML_SCHEMAP_INTERNAL,
19609		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19610		"type is missing... skipping validation of "
19611		"the value constraint", NULL, NULL);
19612	    return (-1);
19613	}
19614	if (elemDecl->node != NULL) {
19615	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19616		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19617		    BAD_CAST "fixed");
19618	    else
19619		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19620		    BAD_CAST "default");
19621	}
19622	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19623	    typeDef, elemDecl->value, &(elemDecl->defVal));
19624	if (vcret != 0) {
19625	    if (vcret < 0) {
19626		PERROR_INT("xmlSchemaElemCheckValConstr",
19627		    "failed to validate the value constraint of an "
19628		    "element declaration");
19629		return (-1);
19630	    }
19631	    return (vcret);
19632	}
19633    }
19634
19635    return (ret);
19636}
19637
19638/**
19639 * xmlSchemaCheckElemSubstGroup:
19640 * @ctxt:  a schema parser context
19641 * @decl: the element declaration
19642 * @name:  the name of the attribute
19643 *
19644 * Schema Component Constraint:
19645 * Substitution Group (cos-equiv-class)
19646 *
19647 * In Libxml2 the subst. groups will be precomputed, in terms of that
19648 * a list will be built for each subst. group head, holding all direct
19649 * referents to this head.
19650 * NOTE that this function needs:
19651 *   1. circular subst. groups to be checked beforehand
19652 *   2. the declaration's type to be derived from the head's type
19653 *
19654 * STATUS:
19655 *
19656 */
19657static void
19658xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19659			     xmlSchemaElementPtr elemDecl)
19660{
19661    if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19662	/* SPEC (1) "Its {abstract} is false." */
19663	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19664	return;
19665    {
19666	xmlSchemaElementPtr head;
19667	xmlSchemaTypePtr headType, type;
19668	int set, methSet;
19669	/*
19670	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19671	* {disallowed substitutions} as the blocking constraint, as defined in
19672	* Substitution Group OK (Transitive) (�3.3.6)."
19673	*/
19674	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19675	    head = WXS_SUBST_HEAD(head)) {
19676	    set = 0;
19677	    methSet = 0;
19678	    /*
19679	    * The blocking constraints.
19680	    */
19681	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19682		continue;
19683	    headType = head->subtypes;
19684	    type = elemDecl->subtypes;
19685	    if (headType == type)
19686		goto add_member;
19687	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19688		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19689	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19690		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19691	    /*
19692	    * SPEC: Substitution Group OK (Transitive) (2.3)
19693	    * "The set of all {derivation method}s involved in the
19694	    * derivation of D's {type definition} from C's {type definition}
19695	    * does not intersect with the union of the blocking constraint,
19696	    * C's {prohibited substitutions} (if C is complex, otherwise the
19697	    * empty set) and the {prohibited substitutions} (respectively the
19698	    * empty set) of any intermediate {type definition}s in the
19699	    * derivation of D's {type definition} from C's {type definition}."
19700	    */
19701	    /*
19702	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19703	    * subst.head axis, the methSet does not need to be computed for
19704	    * the full depth over and over.
19705	    */
19706	    /*
19707	    * The set of all {derivation method}s involved in the derivation
19708	    */
19709	    while ((type != NULL) && (type != headType)) {
19710		if ((WXS_IS_EXTENSION(type)) &&
19711		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19712		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19713
19714		if (WXS_IS_RESTRICTION(type) &&
19715		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19716		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19717
19718		type = type->baseType;
19719	    }
19720	    /*
19721	    * The {prohibited substitutions} of all intermediate types +
19722	    * the head's type.
19723	    */
19724	    type = elemDecl->subtypes->baseType;
19725	    while (type != NULL) {
19726		if (WXS_IS_COMPLEX(type)) {
19727		    if ((type->flags &
19728			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19729			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19730		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19731		    if ((type->flags &
19732			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19733			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19734		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19735		} else
19736		    break;
19737		if (type == headType)
19738		    break;
19739		type = type->baseType;
19740	    }
19741	    if ((set != 0) &&
19742		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19743		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19744		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19745		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19746		continue;
19747	    }
19748add_member:
19749	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19750	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19751		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19752	}
19753    }
19754}
19755
19756#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19757/**
19758 * xmlSchemaCheckElementDeclComponent
19759 * @pctxt: the schema parser context
19760 * @ctxtComponent: the context component (an element declaration)
19761 * @ctxtParticle: the first particle of the context component
19762 * @searchParticle: the element declaration particle to be analysed
19763 *
19764 * Schema Component Constraint: Element Declarations Consistent
19765 */
19766static int
19767xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19768				    xmlSchemaBasicItemPtr ctxtComponent,
19769				    xmlSchemaParticlePtr ctxtParticle,
19770				    xmlSchemaParticlePtr searchParticle,
19771				    xmlSchemaParticlePtr curParticle,
19772				    int search)
19773{
19774    return(0);
19775
19776    int ret = 0;
19777    xmlSchemaParticlePtr cur = curParticle;
19778    if (curParticle == NULL) {
19779	return(0);
19780    }
19781    if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19782	/*
19783	* Just return in this case. A missing "term" of the particle
19784	* might arise due to an invalid "term" component.
19785	*/
19786	return(0);
19787    }
19788    while (cur != NULL) {
19789	switch (WXS_PARTICLE_TERM(cur)->type) {
19790	    case XML_SCHEMA_TYPE_ANY:
19791		break;
19792	    case XML_SCHEMA_TYPE_ELEMENT:
19793		if (search == 0) {
19794		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19795			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19796		    if (ret != 0)
19797			return(ret);
19798		} else {
19799		    xmlSchemaElementPtr elem =
19800			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19801		    /*
19802		    * SPEC Element Declarations Consistent:
19803		    * "If the {particles} contains, either directly,
19804		    * indirectly (that is, within the {particles} of a
19805		    * contained model group, recursively) or �implicitly�
19806		    * two or more element declaration particles with
19807		    * the same {name} and {target namespace}, then
19808		    * all their type definitions must be the same
19809		    * top-level definition [...]"
19810		    */
19811		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19812			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19813			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19814			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19815		    {
19816			xmlChar *strA = NULL, *strB = NULL;
19817
19818			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19819			    /* TODO: error code */
19820			    XML_SCHEMAP_COS_NONAMBIG,
19821			    WXS_ITEM_NODE(cur), NULL,
19822			    "In the content model of %s, there are multiple "
19823			    "element declarations for '%s' with different "
19824			    "type definitions",
19825			    xmlSchemaGetComponentDesignation(&strA,
19826				ctxtComponent),
19827			    xmlSchemaFormatQName(&strB,
19828				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19829				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19830			FREE_AND_NULL(strA);
19831			FREE_AND_NULL(strB);
19832			return(XML_SCHEMAP_COS_NONAMBIG);
19833		    }
19834		}
19835		break;
19836	    case XML_SCHEMA_TYPE_SEQUENCE: {
19837		break;
19838		}
19839	    case XML_SCHEMA_TYPE_CHOICE:{
19840		/*
19841		xmlSchemaTreeItemPtr sub;
19842
19843		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19844		while (sub != NULL) {
19845		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19846			ctxtParticle, ctxtElem);
19847		    if (ret != 0)
19848			return(ret);
19849		    sub = sub->next;
19850		}
19851		*/
19852		break;
19853		}
19854	    case XML_SCHEMA_TYPE_ALL:
19855		break;
19856	    case XML_SCHEMA_TYPE_GROUP:
19857		break;
19858	    default:
19859		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19860		    "xmlSchemaCheckElementDeclConsistent",
19861		    "found unexpected term of type '%s' in content model",
19862		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19863		return(-1);
19864	}
19865	cur = (xmlSchemaParticlePtr) cur->next;
19866    }
19867
19868exit:
19869    return(ret);
19870}
19871#endif
19872
19873/**
19874 * xmlSchemaCheckElementDeclComponent
19875 * @item:  an schema element declaration/particle
19876 * @ctxt:  a schema parser context
19877 * @name:  the name of the attribute
19878 *
19879 * Validates the value constraints of an element declaration.
19880 * Adds substitution group members.
19881 */
19882static void
19883xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19884				   xmlSchemaParserCtxtPtr ctxt)
19885{
19886    if (elemDecl == NULL)
19887	return;
19888    if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19889	return;
19890    elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19891    if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19892	/*
19893	* Adds substitution group members.
19894	*/
19895	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19896    }
19897}
19898
19899/**
19900 * xmlSchemaResolveModelGroupParticleReferences:
19901 * @particle:  a particle component
19902 * @ctxt:  a parser context
19903 *
19904 * Resolves references of a model group's {particles} to
19905 * model group definitions and to element declarations.
19906 */
19907static void
19908xmlSchemaResolveModelGroupParticleReferences(
19909    xmlSchemaParserCtxtPtr ctxt,
19910    xmlSchemaModelGroupPtr mg)
19911{
19912    xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19913    xmlSchemaQNameRefPtr ref;
19914    xmlSchemaBasicItemPtr refItem;
19915
19916    /*
19917    * URGENT TODO: Test this.
19918    */
19919    while (particle != NULL) {
19920	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19921	    ((WXS_PARTICLE_TERM(particle))->type !=
19922		XML_SCHEMA_EXTRA_QNAMEREF))
19923	{
19924	    goto next_particle;
19925	}
19926	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19927	/*
19928	* Resolve the reference.
19929	* NULL the {term} by default.
19930	*/
19931	particle->children = NULL;
19932
19933	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19934	    ref->itemType, ref->name, ref->targetNamespace);
19935	if (refItem == NULL) {
19936	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19937		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19938		ref->targetNamespace, ref->itemType, NULL);
19939	    /* TODO: remove the particle. */
19940	    goto next_particle;
19941	}
19942	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19943	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19944		/* TODO: remove the particle. */
19945		goto next_particle;
19946	    /*
19947	    * NOTE that we will assign the model group definition
19948	    * itself to the "term" of the particle. This will ease
19949	    * the check for circular model group definitions. After
19950	    * that the "term" will be assigned the model group of the
19951	    * model group definition.
19952	    */
19953	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19954		    XML_SCHEMA_TYPE_ALL) {
19955		/*
19956		* SPEC cos-all-limited (1)
19957		* SPEC cos-all-limited (1.2)
19958		* "It appears only as the value of one or both of the
19959		* following properties:"
19960		* (1.1) "the {model group} property of a model group
19961		*        definition."
19962		* (1.2) "the {term} property of a particle [... of] the "
19963		* {content type} of a complex type definition."
19964		*/
19965		xmlSchemaCustomErr(ACTXT_CAST ctxt,
19966		    /* TODO: error code */
19967		    XML_SCHEMAP_COS_ALL_LIMITED,
19968		    WXS_ITEM_NODE(particle), NULL,
19969		    "A model group definition is referenced, but "
19970		    "it contains an 'all' model group, which "
19971		    "cannot be contained by model groups",
19972		    NULL, NULL);
19973		/* TODO: remove the particle. */
19974		goto next_particle;
19975	    }
19976	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19977	} else {
19978	    /*
19979	    * TODO: Are referenced element declarations the only
19980	    * other components we expect here?
19981	    */
19982	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19983	}
19984next_particle:
19985	particle = WXS_PTC_CAST particle->next;
19986    }
19987}
19988
19989static int
19990xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19991		       xmlSchemaValPtr y)
19992{
19993    xmlSchemaTypePtr tx, ty, ptx, pty;
19994    int ret;
19995
19996    while (x != NULL) {
19997	/* Same types. */
19998	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
19999	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20000	ptx = xmlSchemaGetPrimitiveType(tx);
20001	pty = xmlSchemaGetPrimitiveType(ty);
20002	/*
20003	* (1) if a datatype T' is �derived� by �restriction� from an
20004	* atomic datatype T then the �value space� of T' is a subset of
20005	* the �value space� of T. */
20006	/*
20007	* (2) if datatypes T' and T'' are �derived� by �restriction�
20008	* from a common atomic ancestor T then the �value space�s of T'
20009	* and T'' may overlap.
20010	*/
20011	if (ptx != pty)
20012	    return(0);
20013	/*
20014	* We assume computed values to be normalized, so do a fast
20015	* string comparison for string based types.
20016	*/
20017	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20018	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20019	    if (! xmlStrEqual(
20020		xmlSchemaValueGetAsString(x),
20021		xmlSchemaValueGetAsString(y)))
20022		return (0);
20023	} else {
20024	    ret = xmlSchemaCompareValuesWhtsp(
20025		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20026		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20027	    if (ret == -2)
20028		return(-1);
20029	    if (ret != 0)
20030		return(0);
20031	}
20032	/*
20033	* Lists.
20034	*/
20035	x = xmlSchemaValueGetNext(x);
20036	if (x != NULL) {
20037	    y = xmlSchemaValueGetNext(y);
20038	    if (y == NULL)
20039		return (0);
20040	} else if (xmlSchemaValueGetNext(y) != NULL)
20041	    return (0);
20042	else
20043	    return (1);
20044    }
20045    return (0);
20046}
20047
20048/**
20049 * xmlSchemaResolveAttrUseReferences:
20050 * @item:  an attribute use
20051 * @ctxt:  a parser context
20052 *
20053 * Resolves the referenced attribute declaration.
20054 */
20055static int
20056xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20057				  xmlSchemaParserCtxtPtr ctxt)
20058{
20059    if ((ctxt == NULL) || (ause == NULL))
20060	return(-1);
20061    if ((ause->attrDecl == NULL) ||
20062	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20063	return(0);
20064
20065    {
20066	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20067
20068	/*
20069	* TODO: Evaluate, what errors could occur if the declaration is not
20070	* found.
20071	*/
20072	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20073	    ref->name, ref->targetNamespace);
20074        if (ause->attrDecl == NULL) {
20075	    xmlSchemaPResCompAttrErr(ctxt,
20076	    	XML_SCHEMAP_SRC_RESOLVE,
20077		WXS_BASIC_CAST ause, ause->node,
20078		"ref", ref->name, ref->targetNamespace,
20079		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20080            return(ctxt->err);;
20081        }
20082    }
20083    return(0);
20084}
20085
20086/**
20087 * xmlSchemaCheckAttrUsePropsCorrect:
20088 * @ctxt:  a parser context
20089 * @use:  an attribute use
20090 *
20091 * Schema Component Constraint:
20092 * Attribute Use Correct (au-props-correct)
20093 *
20094 */
20095static int
20096xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20097			     xmlSchemaAttributeUsePtr use)
20098{
20099    if ((ctxt == NULL) || (use == NULL))
20100	return(-1);
20101    if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20102	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20103	return(0);
20104
20105    /*
20106    * SPEC au-props-correct (1)
20107    * "The values of the properties of an attribute use must be as
20108    * described in the property tableau in The Attribute Use Schema
20109    * Component (�3.5.1), modulo the impact of Missing
20110    * Sub-components (�5.3)."
20111    */
20112
20113    if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20114	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20115        ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20116    {
20117	xmlSchemaPCustomErr(ctxt,
20118	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20119	    WXS_BASIC_CAST use, NULL,
20120	    "The attribute declaration has a 'fixed' value constraint "
20121	    ", thus the attribute use must also have a 'fixed' value "
20122	    "constraint",
20123	    NULL);
20124	return(ctxt->err);
20125    }
20126    /*
20127    * Compute and check the value constraint's value.
20128    */
20129    if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20130	int ret;
20131	/*
20132	* TODO: The spec seems to be missing a check of the
20133	* value constraint of the attribute use. We will do it here.
20134	*/
20135	/*
20136	* SPEC a-props-correct (3)
20137	*/
20138	if (xmlSchemaIsDerivedFromBuiltInType(
20139	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20140	{
20141	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20142		XML_SCHEMAP_AU_PROPS_CORRECT,
20143		NULL, WXS_BASIC_CAST use,
20144		"Value constraints are not allowed if the type definition "
20145		"is or is derived from xs:ID",
20146		NULL, NULL);
20147	    return(ctxt->err);
20148	}
20149
20150	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20151	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20152	    use->defValue, &(use->defVal),
20153	    1, 1, 0);
20154	if (ret != 0) {
20155	    if (ret < 0) {
20156		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20157		    "calling xmlSchemaVCheckCVCSimpleType()");
20158		return(-1);
20159	    }
20160	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20161		XML_SCHEMAP_AU_PROPS_CORRECT,
20162		NULL, WXS_BASIC_CAST use,
20163		"The value of the value constraint is not valid",
20164		NULL, NULL);
20165	    return(ctxt->err);
20166	}
20167    }
20168    /*
20169    * SPEC au-props-correct (2)
20170    * "If the {attribute declaration} has a fixed
20171    * {value constraint}, then if the attribute use itself has a
20172    * {value constraint}, it must also be fixed and its value must match
20173    * that of the {attribute declaration}'s {value constraint}."
20174    */
20175    if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20176	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20177    {
20178	if (! xmlSchemaAreValuesEqual(use->defVal,
20179		(WXS_ATTRUSE_DECL(use))->defVal))
20180	{
20181	    xmlSchemaPCustomErr(ctxt,
20182		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20183		WXS_BASIC_CAST use, NULL,
20184		"The 'fixed' value constraint of the attribute use "
20185		"must match the attribute declaration's value "
20186		"constraint '%s'",
20187		(WXS_ATTRUSE_DECL(use))->defValue);
20188	}
20189	return(ctxt->err);
20190    }
20191    return(0);
20192}
20193
20194
20195
20196
20197/**
20198 * xmlSchemaResolveAttrTypeReferences:
20199 * @item:  an attribute declaration
20200 * @ctxt:  a parser context
20201 *
20202 * Resolves the referenced type definition component.
20203 */
20204static int
20205xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20206				   xmlSchemaParserCtxtPtr ctxt)
20207{
20208    /*
20209    * The simple type definition corresponding to the <simpleType> element
20210    * information item in the [children], if present, otherwise the simple
20211    * type definition �resolved� to by the �actual value� of the type
20212    * [attribute], if present, otherwise the �simple ur-type definition�.
20213    */
20214    if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20215	return(0);
20216    item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20217    if (item->subtypes != NULL)
20218        return(0);
20219    if (item->typeName != NULL) {
20220        xmlSchemaTypePtr type;
20221
20222	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20223	    item->typeNs);
20224	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20225	    xmlSchemaPResCompAttrErr(ctxt,
20226		XML_SCHEMAP_SRC_RESOLVE,
20227		WXS_BASIC_CAST item, item->node,
20228		"type", item->typeName, item->typeNs,
20229		XML_SCHEMA_TYPE_SIMPLE, NULL);
20230	    return(ctxt->err);
20231	} else
20232	    item->subtypes = type;
20233
20234    } else {
20235	/*
20236	* The type defaults to the xs:anySimpleType.
20237	*/
20238	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20239    }
20240    return(0);
20241}
20242
20243/**
20244 * xmlSchemaResolveIDCKeyReferences:
20245 * @idc:  the identity-constraint definition
20246 * @ctxt:  the schema parser context
20247 * @name:  the attribute name
20248 *
20249 * Resolve keyRef references to key/unique IDCs.
20250 * Schema Component Constraint:
20251 *   Identity-constraint Definition Properties Correct (c-props-correct)
20252 */
20253static int
20254xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20255			  xmlSchemaParserCtxtPtr pctxt)
20256{
20257    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20258        return(0);
20259    if (idc->ref->name != NULL) {
20260	idc->ref->item = (xmlSchemaBasicItemPtr)
20261	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20262		idc->ref->targetNamespace);
20263        if (idc->ref->item == NULL) {
20264	    /*
20265	    * TODO: It is actually not an error to fail to resolve
20266	    * at this stage. BUT we need to be that strict!
20267	    */
20268	    xmlSchemaPResCompAttrErr(pctxt,
20269		XML_SCHEMAP_SRC_RESOLVE,
20270		WXS_BASIC_CAST idc, idc->node,
20271		"refer", idc->ref->name,
20272		idc->ref->targetNamespace,
20273		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20274            return(pctxt->err);
20275	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20276	    /*
20277	    * SPEC c-props-correct (1)
20278	    */
20279	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20280		XML_SCHEMAP_C_PROPS_CORRECT,
20281		NULL, WXS_BASIC_CAST idc,
20282		"The keyref references a keyref",
20283		NULL, NULL);
20284	    idc->ref->item = NULL;
20285	    return(pctxt->err);
20286	} else {
20287	    if (idc->nbFields !=
20288		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20289		xmlChar *str = NULL;
20290		xmlSchemaIDCPtr refer;
20291
20292		refer = (xmlSchemaIDCPtr) idc->ref->item;
20293		/*
20294		* SPEC c-props-correct(2)
20295		* "If the {identity-constraint category} is keyref,
20296		* the cardinality of the {fields} must equal that of
20297		* the {fields} of the {referenced key}.
20298		*/
20299		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20300		    XML_SCHEMAP_C_PROPS_CORRECT,
20301		    NULL, WXS_BASIC_CAST idc,
20302		    "The cardinality of the keyref differs from the "
20303		    "cardinality of the referenced key/unique '%s'",
20304		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20305			refer->name),
20306		    NULL);
20307		FREE_AND_NULL(str)
20308		return(pctxt->err);
20309	    }
20310	}
20311    }
20312    return(0);
20313}
20314
20315static int
20316xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20317				       xmlSchemaParserCtxtPtr pctxt)
20318{
20319    if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20320	prohib->targetNamespace) == NULL) {
20321
20322	xmlSchemaPResCompAttrErr(pctxt,
20323	    XML_SCHEMAP_SRC_RESOLVE,
20324	    NULL, prohib->node,
20325	    "ref", prohib->name, prohib->targetNamespace,
20326	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20327	return(XML_SCHEMAP_SRC_RESOLVE);
20328    }
20329    return(0);
20330}
20331
20332#define WXS_REDEFINED_TYPE(c) \
20333(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20334
20335#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20336(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20337
20338#define WXS_REDEFINED_ATTR_GROUP(c) \
20339(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20340
20341static int
20342xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20343{
20344    int err = 0;
20345    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20346    xmlSchemaBasicItemPtr prev, item;
20347    int wasRedefined;
20348
20349    if (redef == NULL)
20350	return(0);
20351
20352    do {
20353	item = redef->item;
20354	/*
20355	* First try to locate the redefined component in the
20356	* schema graph starting with the redefined schema.
20357	* NOTE: According to this schema bug entry:
20358	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20359	*   it's not clear if the referenced component needs to originate
20360	*   from the <redefine>d schema _document_ or the schema; the latter
20361	*   would include all imported and included sub-schemas of the
20362	*   <redefine>d schema. Currenlty we latter approach is used.
20363	*   SUPPLEMENT: It seems that the WG moves towards the latter
20364	*   approach, so we are doing it right.
20365	*
20366	*/
20367	prev = xmlSchemaFindRedefCompInGraph(
20368	    redef->targetBucket, item->type,
20369	    redef->refName, redef->refTargetNs);
20370	if (prev == NULL) {
20371	    xmlChar *str = NULL;
20372	    xmlNodePtr node;
20373
20374	    /*
20375	    * SPEC src-redefine:
20376	    * (6.2.1) "The �actual value� of its own name attribute plus
20377	    * target namespace must successfully �resolve� to a model
20378	    * group definition in I."
20379	    * (7.2.1) "The �actual value� of its own name attribute plus
20380	    * target namespace must successfully �resolve� to an attribute
20381	    * group definition in I."
20382
20383	    *
20384	    * Note that, if we are redefining with the use of references
20385	    * to components, the spec assumes the src-resolve to be used;
20386	    * but this won't assure that we search only *inside* the
20387	    * redefined schema.
20388	    */
20389	    if (redef->reference)
20390		node = WXS_ITEM_NODE(redef->reference);
20391	    else
20392		node = WXS_ITEM_NODE(item);
20393	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20394		/*
20395		* TODO: error code.
20396		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20397		* reference kind.
20398		*/
20399		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20400		"The %s '%s' to be redefined could not be found in "
20401		"the redefined schema",
20402		WXS_ITEM_TYPE_NAME(item),
20403		xmlSchemaFormatQName(&str, redef->refTargetNs,
20404		    redef->refName));
20405	    FREE_AND_NULL(str);
20406	    err = pctxt->err;
20407	    redef = redef->next;
20408	    continue;
20409	}
20410	/*
20411	* TODO: Obtaining and setting the redefinition state is really
20412	* clumsy.
20413	*/
20414	wasRedefined = 0;
20415	switch (item->type) {
20416	    case XML_SCHEMA_TYPE_COMPLEX:
20417	    case XML_SCHEMA_TYPE_SIMPLE:
20418		if ((WXS_TYPE_CAST prev)->flags &
20419		    XML_SCHEMAS_TYPE_REDEFINED)
20420		{
20421		    wasRedefined = 1;
20422		    break;
20423		}
20424		/* Mark it as redefined. */
20425		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20426		/*
20427		* Assign the redefined type to the
20428		* base type of the redefining type.
20429		* TODO: How
20430		*/
20431		((xmlSchemaTypePtr) item)->baseType =
20432		    (xmlSchemaTypePtr) prev;
20433		break;
20434	    case XML_SCHEMA_TYPE_GROUP:
20435		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20436		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20437		{
20438		    wasRedefined = 1;
20439		    break;
20440		}
20441		/* Mark it as redefined. */
20442		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20443		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20444		if (redef->reference != NULL) {
20445		    /*
20446		    * Overwrite the QName-reference with the
20447		    * referenced model group def.
20448		    */
20449		    (WXS_PTC_CAST redef->reference)->children =
20450			WXS_TREE_CAST prev;
20451		}
20452		redef->target = prev;
20453		break;
20454	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20455		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20456		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20457		{
20458		    wasRedefined = 1;
20459		    break;
20460		}
20461		(WXS_ATTR_GROUP_CAST prev)->flags |=
20462		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20463		if (redef->reference != NULL) {
20464		    /*
20465		    * Assign the redefined attribute group to the
20466		    * QName-reference component.
20467		    * This is the easy case, since we will just
20468		    * expand the redefined group.
20469		    */
20470		    (WXS_QNAME_CAST redef->reference)->item = prev;
20471		    redef->target = NULL;
20472		} else {
20473		    /*
20474		    * This is the complicated case: we need
20475		    * to apply src-redefine (7.2.2) at a later
20476		    * stage, i.e. when attribute group references
20477		    * have beed expanded and simple types have
20478		    * beed fixed.
20479		    */
20480		    redef->target = prev;
20481		}
20482		break;
20483	    default:
20484		PERROR_INT("xmlSchemaResolveRedefReferences",
20485		    "Unexpected redefined component type");
20486		return(-1);
20487	}
20488	if (wasRedefined) {
20489	    xmlChar *str = NULL;
20490	    xmlNodePtr node;
20491
20492	    if (redef->reference)
20493		node = WXS_ITEM_NODE(redef->reference);
20494	    else
20495		node = WXS_ITEM_NODE(redef->item);
20496
20497	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20498		/* TODO: error code. */
20499		XML_SCHEMAP_SRC_REDEFINE,
20500		node, NULL,
20501		"The referenced %s was already redefined. Multiple "
20502		"redefinition of the same component is not supported",
20503		xmlSchemaGetComponentDesignation(&str, prev),
20504		NULL);
20505	    FREE_AND_NULL(str)
20506	    err = pctxt->err;
20507	    redef = redef->next;
20508	    continue;
20509	}
20510	redef = redef->next;
20511    } while (redef != NULL);
20512
20513    return(err);
20514}
20515
20516static int
20517xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20518{
20519    int err = 0;
20520    xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20521    xmlSchemaBasicItemPtr item;
20522
20523    if (redef == NULL)
20524	return(0);
20525
20526    do {
20527	if (redef->target == NULL) {
20528	    redef = redef->next;
20529	    continue;
20530	}
20531	item = redef->item;
20532
20533	switch (item->type) {
20534	    case XML_SCHEMA_TYPE_SIMPLE:
20535	    case XML_SCHEMA_TYPE_COMPLEX:
20536		/*
20537		* Since the spec wants the {name} of the redefined
20538		* type to be 'absent', we'll NULL it.
20539		*/
20540		(WXS_TYPE_CAST redef->target)->name = NULL;
20541
20542		/*
20543		* TODO: Seems like there's nothing more to do. The normal
20544		* inheritance mechanism is used. But not 100% sure.
20545		*/
20546		break;
20547	    case XML_SCHEMA_TYPE_GROUP:
20548		/*
20549		* URGENT TODO:
20550		* SPEC src-redefine:
20551		* (6.2.2) "The {model group} of the model group definition
20552		* which corresponds to it per XML Representation of Model
20553		* Group Definition Schema Components (�3.7.2) must be a
20554		* �valid restriction� of the {model group} of that model
20555		* group definition in I, as defined in Particle Valid
20556		* (Restriction) (�3.9.6)."
20557		*/
20558		break;
20559	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20560		/*
20561		* SPEC src-redefine:
20562		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20563		* the attribute group definition which corresponds to it
20564		* per XML Representation of Attribute Group Definition Schema
20565		* Components (�3.6.2) must be �valid restrictions� of the
20566		* {attribute uses} and {attribute wildcard} of that attribute
20567		* group definition in I, as defined in clause 2, clause 3 and
20568		* clause 4 of Derivation Valid (Restriction, Complex)
20569		* (�3.4.6) (where references to the base type definition are
20570		* understood as references to the attribute group definition
20571		* in I)."
20572		*/
20573		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20574		    XML_SCHEMA_ACTION_REDEFINE,
20575		    item, redef->target,
20576		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20577		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20578		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20579		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20580		if (err == -1)
20581		    return(-1);
20582		break;
20583	    default:
20584		break;
20585	}
20586	redef = redef->next;
20587    } while (redef != NULL);
20588    return(0);
20589}
20590
20591
20592static int
20593xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20594		       xmlSchemaBucketPtr bucket)
20595{
20596    xmlSchemaBasicItemPtr item;
20597    int err;
20598    xmlHashTablePtr *table;
20599    const xmlChar *name;
20600    int i;
20601
20602#define WXS_GET_GLOBAL_HASH(c, slot) { \
20603    if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20604	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20605    else \
20606	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20607
20608    /*
20609    * Add global components to the schema's hash tables.
20610    * This is the place where duplicate components will be
20611    * detected.
20612    * TODO: I think normally we should support imports of the
20613    *   same namespace from multiple locations. We don't do currently,
20614    *   but if we do then according to:
20615    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20616    *   we would need, if imported directly, to import redefined
20617    *   components as well to be able to catch clashing components.
20618    *   (I hope I'll still know what this means after some months :-()
20619    */
20620    if (bucket == NULL)
20621	return(-1);
20622    if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20623	return(0);
20624    bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20625
20626    for (i = 0; i < bucket->globals->nbItems; i++) {
20627	item = bucket->globals->items[i];
20628	table = NULL;
20629	switch (item->type) {
20630	    case XML_SCHEMA_TYPE_COMPLEX:
20631	    case XML_SCHEMA_TYPE_SIMPLE:
20632		if (WXS_REDEFINED_TYPE(item))
20633		    continue;
20634		name = (WXS_TYPE_CAST item)->name;
20635		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20636		break;
20637	    case XML_SCHEMA_TYPE_ELEMENT:
20638		name = (WXS_ELEM_CAST item)->name;
20639		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20640		break;
20641	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20642		name = (WXS_ATTR_CAST item)->name;
20643		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20644		break;
20645	    case XML_SCHEMA_TYPE_GROUP:
20646		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20647		    continue;
20648		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20649		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20650		break;
20651	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20652		if (WXS_REDEFINED_ATTR_GROUP(item))
20653		    continue;
20654		name = (WXS_ATTR_GROUP_CAST item)->name;
20655		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20656		break;
20657	    case XML_SCHEMA_TYPE_IDC_KEY:
20658	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20659	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20660		name = (WXS_IDC_CAST item)->name;
20661		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20662		break;
20663	    case XML_SCHEMA_TYPE_NOTATION:
20664		name = ((xmlSchemaNotationPtr) item)->name;
20665		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20666		break;
20667	    default:
20668		PERROR_INT("xmlSchemaAddComponents",
20669		    "Unexpected global component type");
20670		continue;
20671	}
20672	if (*table == NULL) {
20673	    *table = xmlHashCreateDict(10, pctxt->dict);
20674	    if (*table == NULL) {
20675		PERROR_INT("xmlSchemaAddComponents",
20676		    "failed to create a component hash table");
20677		return(-1);
20678	    }
20679	}
20680	err = xmlHashAddEntry(*table, name, item);
20681	if (err != 0) {
20682	    xmlChar *str = NULL;
20683
20684	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20685		XML_SCHEMAP_REDEFINED_TYPE,
20686		WXS_ITEM_NODE(item),
20687		WXS_BASIC_CAST item,
20688		"A global %s '%s' does already exist",
20689		WXS_ITEM_TYPE_NAME(item),
20690		xmlSchemaGetComponentQName(&str, item));
20691	    FREE_AND_NULL(str);
20692	}
20693    }
20694    /*
20695    * Process imported/included schemas.
20696    */
20697    if (bucket->relations != NULL) {
20698	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20699	do {
20700	    if ((rel->bucket != NULL) &&
20701		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20702		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20703		    return(-1);
20704	    }
20705	    rel = rel->next;
20706	} while (rel != NULL);
20707    }
20708    return(0);
20709}
20710
20711static int
20712xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20713			 xmlSchemaBucketPtr rootBucket)
20714{
20715    xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20716    xmlSchemaTreeItemPtr item, *items;
20717    int nbItems, i, ret = 0;
20718    xmlSchemaBucketPtr oldbucket = con->bucket;
20719    xmlSchemaElementPtr elemDecl;
20720
20721#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20722
20723    if ((con->pending == NULL) ||
20724	(con->pending->nbItems == 0))
20725	return(0);
20726
20727    /*
20728    * Since xmlSchemaFixupComplexType() will create new particles
20729    * (local components), and those particle components need a bucket
20730    * on the constructor, we'll assure here that the constructor has
20731    * a bucket.
20732    * TODO: Think about storing locals _only_ on the main bucket.
20733    */
20734    if (con->bucket == NULL)
20735	con->bucket = rootBucket;
20736
20737    /* TODO:
20738    * SPEC (src-redefine):
20739    * (6.2) "If it has no such self-reference, then all of the
20740    * following must be true:"
20741
20742    * (6.2.2) The {model group} of the model group definition which
20743    * corresponds to it per XML Representation of Model Group
20744    * Definition Schema Components (�3.7.2) must be a �valid
20745    * restriction� of the {model group} of that model group definition
20746    * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20747    */
20748    xmlSchemaCheckSRCRedefineFirst(pctxt);
20749
20750    /*
20751    * Add global components to the schemata's hash tables.
20752    */
20753    xmlSchemaAddComponents(pctxt, rootBucket);
20754
20755    pctxt->ctxtType = NULL;
20756    items = (xmlSchemaTreeItemPtr *) con->pending->items;
20757    nbItems = con->pending->nbItems;
20758    /*
20759    * Now that we have parsed *all* the schema document(s) and converted
20760    * them to schema components, we can resolve references, apply component
20761    * constraints, create the FSA from the content model, etc.
20762    */
20763    /*
20764    * Resolve references of..
20765    *
20766    * 1. element declarations:
20767    *   - the type definition
20768    *   - the substitution group affiliation
20769    * 2. simple/complex types:
20770    *   - the base type definition
20771    *   - the memberTypes of union types
20772    *   - the itemType of list types
20773    * 3. attributes declarations and attribute uses:
20774    *   - the type definition
20775    *   - if an attribute use, then the attribute declaration
20776    * 4. attribute group references:
20777    *   - the attribute group definition
20778    * 5. particles:
20779    *   - the term of the particle (e.g. a model group)
20780    * 6. IDC key-references:
20781    *   - the referenced IDC 'key' or 'unique' definition
20782    * 7. Attribute prohibitions which had a "ref" attribute.
20783    */
20784    for (i = 0; i < nbItems; i++) {
20785	item = items[i];
20786	switch (item->type) {
20787	    case XML_SCHEMA_TYPE_ELEMENT:
20788		xmlSchemaResolveElementReferences(
20789		    (xmlSchemaElementPtr) item, pctxt);
20790		FIXHFAILURE;
20791		break;
20792	    case XML_SCHEMA_TYPE_COMPLEX:
20793	    case XML_SCHEMA_TYPE_SIMPLE:
20794		xmlSchemaResolveTypeReferences(
20795		    (xmlSchemaTypePtr) item, pctxt);
20796		FIXHFAILURE;
20797		break;
20798	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20799		xmlSchemaResolveAttrTypeReferences(
20800		    (xmlSchemaAttributePtr) item, pctxt);
20801		FIXHFAILURE;
20802		break;
20803	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20804		xmlSchemaResolveAttrUseReferences(
20805		    (xmlSchemaAttributeUsePtr) item, pctxt);
20806		FIXHFAILURE;
20807		break;
20808	    case XML_SCHEMA_EXTRA_QNAMEREF:
20809		if ((WXS_QNAME_CAST item)->itemType ==
20810		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20811		{
20812		    xmlSchemaResolveAttrGroupReferences(
20813			WXS_QNAME_CAST item, pctxt);
20814		}
20815		FIXHFAILURE;
20816		break;
20817	    case XML_SCHEMA_TYPE_SEQUENCE:
20818	    case XML_SCHEMA_TYPE_CHOICE:
20819	    case XML_SCHEMA_TYPE_ALL:
20820		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20821		    WXS_MODEL_GROUP_CAST item);
20822		FIXHFAILURE;
20823		break;
20824	    case XML_SCHEMA_TYPE_IDC_KEY:
20825	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20826	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20827		xmlSchemaResolveIDCKeyReferences(
20828		    (xmlSchemaIDCPtr) item, pctxt);
20829		FIXHFAILURE;
20830		break;
20831	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20832		/*
20833		* Handle attribue prohibition which had a
20834		* "ref" attribute.
20835		*/
20836		xmlSchemaResolveAttrUseProhibReferences(
20837		    WXS_ATTR_PROHIB_CAST item, pctxt);
20838		FIXHFAILURE;
20839		break;
20840	    default:
20841		break;
20842	}
20843    }
20844    if (pctxt->nberrors != 0)
20845	goto exit_error;
20846
20847    /*
20848    * Now that all references are resolved we
20849    * can check for circularity of...
20850    * 1. the base axis of type definitions
20851    * 2. nested model group definitions
20852    * 3. nested attribute group definitions
20853    * TODO: check for circual substitution groups.
20854    */
20855    for (i = 0; i < nbItems; i++) {
20856	item = items[i];
20857	/*
20858	* Let's better stop on the first error here.
20859	*/
20860	switch (item->type) {
20861	    case XML_SCHEMA_TYPE_COMPLEX:
20862	    case XML_SCHEMA_TYPE_SIMPLE:
20863		xmlSchemaCheckTypeDefCircular(
20864		    (xmlSchemaTypePtr) item, pctxt);
20865		FIXHFAILURE;
20866		if (pctxt->nberrors != 0)
20867		    goto exit_error;
20868		break;
20869	    case XML_SCHEMA_TYPE_GROUP:
20870		xmlSchemaCheckGroupDefCircular(
20871		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20872		FIXHFAILURE;
20873		if (pctxt->nberrors != 0)
20874		    goto exit_error;
20875		break;
20876	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20877		xmlSchemaCheckAttrGroupCircular(
20878		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20879		FIXHFAILURE;
20880		if (pctxt->nberrors != 0)
20881		    goto exit_error;
20882		break;
20883	    default:
20884		break;
20885	}
20886    }
20887    if (pctxt->nberrors != 0)
20888	goto exit_error;
20889    /*
20890    * Model group definition references:
20891    * Such a reference is reflected by a particle at the component
20892    * level. Until now the 'term' of such particles pointed
20893    * to the model group definition; this was done, in order to
20894    * ease circularity checks. Now we need to set the 'term' of
20895    * such particles to the model group of the model group definition.
20896    */
20897    for (i = 0; i < nbItems; i++) {
20898	item = items[i];
20899	switch (item->type) {
20900	    case XML_SCHEMA_TYPE_SEQUENCE:
20901	    case XML_SCHEMA_TYPE_CHOICE:
20902		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20903		    WXS_MODEL_GROUP_CAST item);
20904		break;
20905	    default:
20906		break;
20907	}
20908    }
20909    if (pctxt->nberrors != 0)
20910	goto exit_error;
20911    /*
20912    * Expand attribute group references of attribute group definitions.
20913    */
20914    for (i = 0; i < nbItems; i++) {
20915	item = items[i];
20916	switch (item->type) {
20917            case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20918		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20919		    WXS_ATTR_GROUP_HAS_REFS(item))
20920		{
20921		    xmlSchemaAttributeGroupExpandRefs(pctxt,
20922			WXS_ATTR_GROUP_CAST item);
20923		    FIXHFAILURE;
20924		}
20925		break;
20926	    default:
20927		break;
20928	}
20929    }
20930    if (pctxt->nberrors != 0)
20931	goto exit_error;
20932    /*
20933    * First compute the variety of simple types. This is needed as
20934    * a seperate step, since otherwise we won't be able to detect
20935    * circular union types in all cases.
20936    */
20937    for (i = 0; i < nbItems; i++) {
20938	item = items[i];
20939	switch (item->type) {
20940            case XML_SCHEMA_TYPE_SIMPLE:
20941		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20942		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
20943			(xmlSchemaTypePtr) item);
20944		    FIXHFAILURE;
20945		}
20946		break;
20947	    default:
20948		break;
20949	}
20950    }
20951    if (pctxt->nberrors != 0)
20952	goto exit_error;
20953    /*
20954    * Detect circular union types. Note that this needs the variety to
20955    * be already computed.
20956    */
20957    for (i = 0; i < nbItems; i++) {
20958	item = items[i];
20959	switch (item->type) {
20960            case XML_SCHEMA_TYPE_SIMPLE:
20961		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20962		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
20963			(xmlSchemaTypePtr) item);
20964		    FIXHFAILURE;
20965		}
20966		break;
20967	    default:
20968		break;
20969	}
20970    }
20971    if (pctxt->nberrors != 0)
20972	goto exit_error;
20973
20974    /*
20975    * Do the complete type fixup for simple types.
20976    */
20977    for (i = 0; i < nbItems; i++) {
20978	item = items[i];
20979	switch (item->type) {
20980            case XML_SCHEMA_TYPE_SIMPLE:
20981		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20982		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20983		    FIXHFAILURE;
20984		}
20985		break;
20986	    default:
20987		break;
20988	}
20989    }
20990    if (pctxt->nberrors != 0)
20991	goto exit_error;
20992    /*
20993    * At this point we need build and check all simple types.
20994    */
20995    /*
20996    * Apply contraints for attribute declarations.
20997    */
20998    for (i = 0; i < nbItems; i++) {
20999	item = items[i];
21000	switch (item->type) {
21001	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21002		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21003		FIXHFAILURE;
21004		break;
21005	    default:
21006		break;
21007	}
21008    }
21009    if (pctxt->nberrors != 0)
21010	goto exit_error;
21011    /*
21012    * Apply constraints for attribute uses.
21013    */
21014    for (i = 0; i < nbItems; i++) {
21015	item = items[i];
21016	switch (item->type) {
21017	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21018		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21019		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21020			WXS_ATTR_USE_CAST item);
21021		    FIXHFAILURE;
21022		}
21023		break;
21024	    default:
21025		break;
21026	}
21027    }
21028    if (pctxt->nberrors != 0)
21029	goto exit_error;
21030
21031    /*
21032    * Apply constraints for attribute group definitions.
21033    */
21034    for (i = 0; i < nbItems; i++) {
21035	item = items[i];
21036	switch (item->type) {
21037	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21038	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21039		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21040	    {
21041		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21042		FIXHFAILURE;
21043	    }
21044	    break;
21045	default:
21046	    break;
21047	}
21048    }
21049    if (pctxt->nberrors != 0)
21050	goto exit_error;
21051
21052    /*
21053    * Apply constraints for redefinitions.
21054    */
21055    if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21056	xmlSchemaCheckSRCRedefineSecond(pctxt);
21057    if (pctxt->nberrors != 0)
21058	goto exit_error;
21059
21060    /*
21061    * Complex types are builded and checked.
21062    */
21063    for (i = 0; i < nbItems; i++) {
21064	item = con->pending->items[i];
21065	switch (item->type) {
21066	    case XML_SCHEMA_TYPE_COMPLEX:
21067		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21068		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21069		    FIXHFAILURE;
21070		}
21071		break;
21072	    default:
21073		break;
21074	}
21075    }
21076    if (pctxt->nberrors != 0)
21077	goto exit_error;
21078
21079    /*
21080    * The list could have changed, since xmlSchemaFixupComplexType()
21081    * will create particles and model groups in some cases.
21082    */
21083    items = (xmlSchemaTreeItemPtr *) con->pending->items;
21084    nbItems = con->pending->nbItems;
21085
21086    /*
21087    * Apply some constraints for element declarations.
21088    */
21089    for (i = 0; i < nbItems; i++) {
21090	item = items[i];
21091	switch (item->type) {
21092	    case XML_SCHEMA_TYPE_ELEMENT:
21093		elemDecl = (xmlSchemaElementPtr) item;
21094
21095		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21096		{
21097		    xmlSchemaCheckElementDeclComponent(
21098			(xmlSchemaElementPtr) elemDecl, pctxt);
21099		    FIXHFAILURE;
21100		}
21101
21102#ifdef WXS_ELEM_DECL_CONS_ENABLED
21103		/*
21104		* Schema Component Constraint: Element Declarations Consistent
21105		* Apply this constraint to local types of element declarations.
21106		*/
21107		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21108		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21109		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21110		{
21111		    xmlSchemaCheckElementDeclConsistent(pctxt,
21112			WXS_BASIC_CAST elemDecl,
21113			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21114			NULL, NULL, 0);
21115		}
21116#endif
21117		break;
21118	    default:
21119		break;
21120	}
21121    }
21122    if (pctxt->nberrors != 0)
21123	goto exit_error;
21124
21125    /*
21126    * Finally we can build the automaton from the content model of
21127    * complex types.
21128    */
21129
21130    for (i = 0; i < nbItems; i++) {
21131	item = items[i];
21132	switch (item->type) {
21133	    case XML_SCHEMA_TYPE_COMPLEX:
21134		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21135		/* FIXHFAILURE; */
21136		break;
21137	    default:
21138		break;
21139	}
21140    }
21141    if (pctxt->nberrors != 0)
21142	goto exit_error;
21143    /*
21144    * URGENT TODO: cos-element-consistent
21145    */
21146    goto exit;
21147
21148exit_error:
21149    ret = pctxt->err;
21150    goto exit;
21151
21152exit_failure:
21153    ret = -1;
21154
21155exit:
21156    /*
21157    * Reset the constructor. This is needed for XSI acquisition, since
21158    * those items will be processed over and over again for every XSI
21159    * if not cleared here.
21160    */
21161    con->bucket = oldbucket;
21162    con->pending->nbItems = 0;
21163    if (con->substGroups != NULL) {
21164	xmlHashFree(con->substGroups,
21165	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21166	con->substGroups = NULL;
21167    }
21168    if (con->redefs != NULL) {
21169	xmlSchemaRedefListFree(con->redefs);
21170	con->redefs = NULL;
21171    }
21172    return(ret);
21173}
21174/**
21175 * xmlSchemaParse:
21176 * @ctxt:  a schema validation context
21177 *
21178 * parse a schema definition resource and build an internal
21179 * XML Shema struture which can be used to validate instances.
21180 *
21181 * Returns the internal XML Schema structure built from the resource or
21182 *         NULL in case of error
21183 */
21184xmlSchemaPtr
21185xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21186{
21187    xmlSchemaPtr mainSchema = NULL;
21188    xmlSchemaBucketPtr bucket = NULL;
21189    int res;
21190
21191    /*
21192    * This one is used if the schema to be parsed was specified via
21193    * the API; i.e. not automatically by the validated instance document.
21194    */
21195
21196    xmlSchemaInitTypes();
21197
21198    if (ctxt == NULL)
21199        return (NULL);
21200
21201    /* TODO: Init the context. Is this all we need?*/
21202    ctxt->nberrors = 0;
21203    ctxt->err = 0;
21204    ctxt->counter = 0;
21205
21206    /* Create the *main* schema. */
21207    mainSchema = xmlSchemaNewSchema(ctxt);
21208    if (mainSchema == NULL)
21209	goto exit_failure;
21210    /*
21211    * Create the schema constructor.
21212    */
21213    if (ctxt->constructor == NULL) {
21214	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21215	if (ctxt->constructor == NULL)
21216	    return(NULL);
21217	/* Take ownership of the constructor to be able to free it. */
21218	ctxt->ownsConstructor = 1;
21219    }
21220    ctxt->constructor->mainSchema = mainSchema;
21221    /*
21222    * Locate and add the schema document.
21223    */
21224    res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21225	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21226	NULL, NULL, &bucket);
21227    if (res == -1)
21228	goto exit_failure;
21229    if (res != 0)
21230	goto exit;
21231
21232    if (bucket == NULL) {
21233	/* TODO: Error code, actually we failed to *locate* the schema. */
21234	if (ctxt->URL)
21235	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21236		NULL, NULL,
21237		"Failed to locate the main schema resource at '%s'",
21238		ctxt->URL, NULL);
21239	else
21240	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21241		NULL, NULL,
21242		"Failed to locate the main schema resource",
21243		    NULL, NULL);
21244	goto exit;
21245    }
21246    /* Then do the parsing for good. */
21247    if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21248	goto exit_failure;
21249    if (ctxt->nberrors != 0)
21250	goto exit;
21251
21252    mainSchema->doc = bucket->doc;
21253    mainSchema->preserve = ctxt->preserve;
21254
21255    ctxt->schema = mainSchema;
21256
21257    if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21258	goto exit_failure;
21259
21260    /*
21261    * TODO: This is not nice, since we cannot distinguish from the
21262    * result if there was an internal error or not.
21263    */
21264exit:
21265    if (ctxt->nberrors != 0) {
21266	if (mainSchema) {
21267	    xmlSchemaFree(mainSchema);
21268	    mainSchema = NULL;
21269	}
21270	if (ctxt->constructor) {
21271	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21272	    ctxt->constructor = NULL;
21273	    ctxt->ownsConstructor = 0;
21274	}
21275    }
21276    ctxt->schema = NULL;
21277    return(mainSchema);
21278exit_failure:
21279    /*
21280    * Quite verbose, but should catch internal errors, which were
21281    * not communitated.
21282    */
21283    if (mainSchema) {
21284        xmlSchemaFree(mainSchema);
21285	mainSchema = NULL;
21286    }
21287    if (ctxt->constructor) {
21288	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21289	ctxt->constructor = NULL;
21290	ctxt->ownsConstructor = 0;
21291    }
21292    PERROR_INT2("xmlSchemaParse",
21293	"An internal error occured");
21294    ctxt->schema = NULL;
21295    return(NULL);
21296}
21297
21298/**
21299 * xmlSchemaSetParserErrors:
21300 * @ctxt:  a schema validation context
21301 * @err:  the error callback
21302 * @warn:  the warning callback
21303 * @ctx:  contextual data for the callbacks
21304 *
21305 * Set the callback functions used to handle errors for a validation context
21306 */
21307void
21308xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21309                         xmlSchemaValidityErrorFunc err,
21310                         xmlSchemaValidityWarningFunc warn, void *ctx)
21311{
21312    if (ctxt == NULL)
21313        return;
21314    ctxt->error = err;
21315    ctxt->warning = warn;
21316    ctxt->errCtxt = ctx;
21317    if (ctxt->vctxt != NULL)
21318	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21319}
21320
21321/**
21322 * xmlSchemaSetParserStructuredErrors:
21323 * @ctxt:  a schema parser context
21324 * @serror:  the structured error function
21325 * @ctx: the functions context
21326 *
21327 * Set the structured error callback
21328 */
21329void
21330xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21331				   xmlStructuredErrorFunc serror,
21332				   void *ctx)
21333{
21334    if (ctxt == NULL)
21335	return;
21336    ctxt->serror = serror;
21337    ctxt->errCtxt = ctx;
21338    if (ctxt->vctxt != NULL)
21339	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21340}
21341
21342/**
21343 * xmlSchemaGetParserErrors:
21344 * @ctxt:  a XMl-Schema parser context
21345 * @err: the error callback result
21346 * @warn: the warning callback result
21347 * @ctx: contextual data for the callbacks result
21348 *
21349 * Get the callback information used to handle errors for a parser context
21350 *
21351 * Returns -1 in case of failure, 0 otherwise
21352 */
21353int
21354xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21355			 xmlSchemaValidityErrorFunc * err,
21356			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21357{
21358	if (ctxt == NULL)
21359		return(-1);
21360	if (err != NULL)
21361		*err = ctxt->error;
21362	if (warn != NULL)
21363		*warn = ctxt->warning;
21364	if (ctx != NULL)
21365		*ctx = ctxt->errCtxt;
21366	return(0);
21367}
21368
21369/**
21370 * xmlSchemaFacetTypeToString:
21371 * @type:  the facet type
21372 *
21373 * Convert the xmlSchemaTypeType to a char string.
21374 *
21375 * Returns the char string representation of the facet type if the
21376 *     type is a facet and an "Internal Error" string otherwise.
21377 */
21378static const xmlChar *
21379xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21380{
21381    switch (type) {
21382        case XML_SCHEMA_FACET_PATTERN:
21383            return (BAD_CAST "pattern");
21384        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21385            return (BAD_CAST "maxExclusive");
21386        case XML_SCHEMA_FACET_MAXINCLUSIVE:
21387            return (BAD_CAST "maxInclusive");
21388        case XML_SCHEMA_FACET_MINEXCLUSIVE:
21389            return (BAD_CAST "minExclusive");
21390        case XML_SCHEMA_FACET_MININCLUSIVE:
21391            return (BAD_CAST "minInclusive");
21392        case XML_SCHEMA_FACET_WHITESPACE:
21393            return (BAD_CAST "whiteSpace");
21394        case XML_SCHEMA_FACET_ENUMERATION:
21395            return (BAD_CAST "enumeration");
21396        case XML_SCHEMA_FACET_LENGTH:
21397            return (BAD_CAST "length");
21398        case XML_SCHEMA_FACET_MAXLENGTH:
21399            return (BAD_CAST "maxLength");
21400        case XML_SCHEMA_FACET_MINLENGTH:
21401            return (BAD_CAST "minLength");
21402        case XML_SCHEMA_FACET_TOTALDIGITS:
21403            return (BAD_CAST "totalDigits");
21404        case XML_SCHEMA_FACET_FRACTIONDIGITS:
21405            return (BAD_CAST "fractionDigits");
21406        default:
21407            break;
21408    }
21409    return (BAD_CAST "Internal Error");
21410}
21411
21412static xmlSchemaWhitespaceValueType
21413xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21414{
21415    /*
21416    * The normalization type can be changed only for types which are derived
21417    * from xsd:string.
21418    */
21419    if (type->type == XML_SCHEMA_TYPE_BASIC) {
21420	/*
21421	* Note that we assume a whitespace of preserve for anySimpleType.
21422	*/
21423	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21424	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21425	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21426	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21427	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21428	else {
21429	    /*
21430	    * For all �atomic� datatypes other than string (and types �derived�
21431	    * by �restriction� from it) the value of whiteSpace is fixed to
21432	    * collapse
21433	    * Note that this includes built-in list datatypes.
21434	    */
21435	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21436	}
21437    } else if (WXS_IS_LIST(type)) {
21438	/*
21439	* For list types the facet "whiteSpace" is fixed to "collapse".
21440	*/
21441	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21442    } else if (WXS_IS_UNION(type)) {
21443	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21444    } else if (WXS_IS_ATOMIC(type)) {
21445	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21446	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21447	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21448	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21449	else
21450	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21451    }
21452    return (-1);
21453}
21454
21455/************************************************************************
21456 * 									*
21457 * 			Simple type validation				*
21458 * 									*
21459 ************************************************************************/
21460
21461
21462/************************************************************************
21463 * 									*
21464 * 			DOM Validation code				*
21465 * 									*
21466 ************************************************************************/
21467
21468/**
21469 * xmlSchemaAssembleByLocation:
21470 * @pctxt:  a schema parser context
21471 * @vctxt:  a schema validation context
21472 * @schema: the existing schema
21473 * @node: the node that fired the assembling
21474 * @nsName: the namespace name of the new schema
21475 * @location: the location of the schema
21476 *
21477 * Expands an existing schema by an additional schema.
21478 *
21479 * Returns 0 if the new schema is correct, a positive error code
21480 * number otherwise and -1 in case of an internal or API error.
21481 */
21482static int
21483xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21484			    xmlSchemaPtr schema,
21485			    xmlNodePtr node,
21486			    const xmlChar *nsName,
21487			    const xmlChar *location)
21488{
21489    int ret = 0;
21490    xmlSchemaParserCtxtPtr pctxt;
21491    xmlSchemaBucketPtr bucket = NULL;
21492
21493    if ((vctxt == NULL) || (schema == NULL))
21494	return (-1);
21495
21496    if (vctxt->pctxt == NULL) {
21497	VERROR_INT("xmlSchemaAssembleByLocation",
21498	    "no parser context available");
21499	return(-1);
21500    }
21501    pctxt = vctxt->pctxt;
21502    if (pctxt->constructor == NULL) {
21503	PERROR_INT("xmlSchemaAssembleByLocation",
21504	    "no constructor");
21505	return(-1);
21506    }
21507    /*
21508    * Acquire the schema document.
21509    */
21510    location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21511	location, node);
21512    /*
21513    * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21514    * the process will automatically change this to
21515    * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21516    */
21517    ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21518	location, NULL, NULL, 0, node, NULL, nsName,
21519	&bucket);
21520    if (ret != 0)
21521	return(ret);
21522    if (bucket == NULL) {
21523	/*
21524	* Generate a warning that the document could not be located.
21525	*/
21526	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21527	    node, NULL,
21528	    "The document at location '%s' could not be acquired",
21529	    location, NULL, NULL);
21530	return(ret);
21531    }
21532    /*
21533    * The first located schema will be handled as if all other
21534    * schemas imported by XSI were imported by this first schema.
21535    */
21536    if ((bucket != NULL) &&
21537	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21538	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21539    /*
21540    * TODO: Is this handled like an import? I.e. is it not an error
21541    * if the schema cannot be located?
21542    */
21543    if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21544	return(0);
21545    /*
21546    * We will reuse the parser context for every schema imported
21547    * directly via XSI. So reset the context.
21548    */
21549    pctxt->nberrors = 0;
21550    pctxt->err = 0;
21551    pctxt->doc = bucket->doc;
21552
21553    ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21554    if (ret == -1) {
21555	pctxt->doc = NULL;
21556	goto exit_failure;
21557    }
21558    /* Paranoid error channelling. */
21559    if ((ret == 0) && (pctxt->nberrors != 0))
21560	ret = pctxt->err;
21561    if (pctxt->nberrors == 0) {
21562	/*
21563	* Only bother to fixup pending components, if there was
21564	* no error yet.
21565	* For every XSI acquired schema (and its sub-schemata) we will
21566	* fixup the components.
21567	*/
21568	xmlSchemaFixupComponents(pctxt, bucket);
21569	ret = pctxt->err;
21570	/*
21571	* Not nice, but we need somehow to channel the schema parser
21572	* error to the validation context.
21573	*/
21574	if ((ret != 0) && (vctxt->err == 0))
21575	    vctxt->err = ret;
21576	vctxt->nberrors += pctxt->nberrors;
21577    } else {
21578	/* Add to validation error sum. */
21579	vctxt->nberrors += pctxt->nberrors;
21580    }
21581    pctxt->doc = NULL;
21582    return(ret);
21583exit_failure:
21584    pctxt->doc = NULL;
21585    return (-1);
21586}
21587
21588static xmlSchemaAttrInfoPtr
21589xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21590			 int metaType)
21591{
21592    if (vctxt->nbAttrInfos == 0)
21593	return (NULL);
21594    {
21595	int i;
21596	xmlSchemaAttrInfoPtr iattr;
21597
21598	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21599	    iattr = vctxt->attrInfos[i];
21600	    if (iattr->metaType == metaType)
21601		return (iattr);
21602	}
21603
21604    }
21605    return (NULL);
21606}
21607
21608/**
21609 * xmlSchemaAssembleByXSI:
21610 * @vctxt:  a schema validation context
21611 *
21612 * Expands an existing schema by an additional schema using
21613 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21614 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21615 * must be set to 1.
21616 *
21617 * Returns 0 if the new schema is correct, a positive error code
21618 * number otherwise and -1 in case of an internal or API error.
21619 */
21620static int
21621xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21622{
21623    const xmlChar *cur, *end;
21624    const xmlChar *nsname = NULL, *location;
21625    int count = 0;
21626    int ret = 0;
21627    xmlSchemaAttrInfoPtr iattr;
21628
21629    /*
21630    * Parse the value; we will assume an even number of values
21631    * to be given (this is how Xerces and XSV work).
21632    *
21633    * URGENT TODO: !! This needs to work for both
21634    * @noNamespaceSchemaLocation AND @schemaLocation on the same
21635    * element !!
21636    */
21637    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21638	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21639    if (iattr == NULL)
21640	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21641	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21642    if (iattr == NULL)
21643	return (0);
21644    cur = iattr->value;
21645    do {
21646	/*
21647	* TODO: Move the string parsing mechanism away from here.
21648	*/
21649	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21650	    /*
21651	    * Get the namespace name.
21652	    */
21653	    while (IS_BLANK_CH(*cur))
21654		cur++;
21655	    end = cur;
21656	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21657		end++;
21658	    if (end == cur)
21659		break;
21660	    count++; /* TODO: Don't use the schema's dict. */
21661	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21662	    cur = end;
21663	}
21664	/*
21665	* Get the URI.
21666	*/
21667	while (IS_BLANK_CH(*cur))
21668	    cur++;
21669	end = cur;
21670	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21671	    end++;
21672	if (end == cur) {
21673	    if (iattr->metaType ==
21674		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21675	    {
21676		/*
21677		* If using @schemaLocation then tuples are expected.
21678		* I.e. the namespace name *and* the document's URI.
21679		*/
21680		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21681		    iattr->node, NULL,
21682		    "The value must consist of tuples: the target namespace "
21683		    "name and the document's URI", NULL, NULL, NULL);
21684	    }
21685	    break;
21686	}
21687	count++; /* TODO: Don't use the schema's dict. */
21688	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21689	cur = end;
21690	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21691	    iattr->node, nsname, location);
21692	if (ret == -1) {
21693	    VERROR_INT("xmlSchemaAssembleByXSI",
21694		"assembling schemata");
21695	    return (-1);
21696	}
21697    } while (*cur != 0);
21698    return (ret);
21699}
21700
21701static const xmlChar *
21702xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21703			 const xmlChar *prefix)
21704{
21705    if (vctxt->sax != NULL) {
21706	int i, j;
21707	xmlSchemaNodeInfoPtr inode;
21708
21709	for (i = vctxt->depth; i >= 0; i--) {
21710	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21711		inode = vctxt->elemInfos[i];
21712		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21713		    if (((prefix == NULL) &&
21714			    (inode->nsBindings[j] == NULL)) ||
21715			((prefix != NULL) && xmlStrEqual(prefix,
21716			    inode->nsBindings[j]))) {
21717
21718			/*
21719			* Note that the namespace bindings are already
21720			* in a string dict.
21721			*/
21722			return (inode->nsBindings[j+1]);
21723		    }
21724		}
21725	    }
21726	}
21727	return (NULL);
21728#ifdef LIBXML_WRITER_ENABLED
21729    } else if (vctxt->reader != NULL) {
21730	xmlChar *nsName;
21731
21732	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21733	if (nsName != NULL) {
21734	    const xmlChar *ret;
21735
21736	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21737	    xmlFree(nsName);
21738	    return (ret);
21739	} else
21740	    return (NULL);
21741#endif
21742    } else {
21743	xmlNsPtr ns;
21744
21745	if ((vctxt->inode->node == NULL) ||
21746	    (vctxt->inode->node->doc == NULL)) {
21747	    VERROR_INT("xmlSchemaLookupNamespace",
21748		"no node or node's doc avaliable");
21749	    return (NULL);
21750	}
21751	ns = xmlSearchNs(vctxt->inode->node->doc,
21752	    vctxt->inode->node, prefix);
21753	if (ns != NULL)
21754	    return (ns->href);
21755	return (NULL);
21756    }
21757}
21758
21759/*
21760* This one works on the schema of the validation context.
21761*/
21762static int
21763xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21764			  xmlSchemaPtr schema,
21765			  xmlNodePtr node,
21766			  const xmlChar *value,
21767			  xmlSchemaValPtr *val,
21768			  int valNeeded)
21769{
21770    int ret;
21771
21772    if (vctxt && (vctxt->schema == NULL)) {
21773	VERROR_INT("xmlSchemaValidateNotation",
21774	    "a schema is needed on the validation context");
21775	return (-1);
21776    }
21777    ret = xmlValidateQName(value, 1);
21778    if (ret != 0)
21779	return (ret);
21780    {
21781	xmlChar *localName = NULL;
21782	xmlChar *prefix = NULL;
21783
21784	localName = xmlSplitQName2(value, &prefix);
21785	if (prefix != NULL) {
21786	    const xmlChar *nsName = NULL;
21787
21788	    if (vctxt != NULL)
21789		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21790	    else if (node != NULL) {
21791		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21792		if (ns != NULL)
21793		    nsName = ns->href;
21794	    } else {
21795		xmlFree(prefix);
21796		xmlFree(localName);
21797		return (1);
21798	    }
21799	    if (nsName == NULL) {
21800		xmlFree(prefix);
21801		xmlFree(localName);
21802		return (1);
21803	    }
21804	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21805		if (valNeeded && (val != NULL)) {
21806		    (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
21807			BAD_CAST xmlStrdup(nsName));
21808		    if (*val == NULL)
21809			ret = -1;
21810		}
21811	    } else
21812		ret = 1;
21813	    xmlFree(prefix);
21814	    xmlFree(localName);
21815	} else {
21816	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21817		if (valNeeded && (val != NULL)) {
21818		    (*val) = xmlSchemaNewNOTATIONValue(
21819			BAD_CAST xmlStrdup(value), NULL);
21820		    if (*val == NULL)
21821			ret = -1;
21822		}
21823	    } else
21824		return (1);
21825	}
21826    }
21827    return (ret);
21828}
21829
21830static int
21831xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21832		       const xmlChar* lname,
21833		       const xmlChar* nsname)
21834{
21835    int i;
21836
21837    lname = xmlDictLookup(vctxt->dict, lname, -1);
21838    if (lname == NULL)
21839	return(-1);
21840    if (nsname != NULL) {
21841	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21842	if (nsname == NULL)
21843	    return(-1);
21844    }
21845    for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21846	if ((vctxt->nodeQNames->items [i] == lname) &&
21847	    (vctxt->nodeQNames->items[i +1] == nsname))
21848	    /* Already there */
21849	    return(i);
21850    }
21851    /* Add new entry. */
21852    i = vctxt->nodeQNames->nbItems;
21853    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21854    xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21855    return(i);
21856}
21857
21858/************************************************************************
21859 * 									*
21860 *  Validation of identity-constraints (IDC)                            *
21861 * 									*
21862 ************************************************************************/
21863
21864/**
21865 * xmlSchemaAugmentIDC:
21866 * @idcDef: the IDC definition
21867 *
21868 * Creates an augmented IDC definition item.
21869 *
21870 * Returns the item, or NULL on internal errors.
21871 */
21872static void
21873xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21874		    xmlSchemaValidCtxtPtr vctxt)
21875{
21876    xmlSchemaIDCAugPtr aidc;
21877
21878    aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21879    if (aidc == NULL) {
21880	xmlSchemaVErrMemory(vctxt,
21881	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21882	    NULL);
21883	return;
21884    }
21885    aidc->keyrefDepth = -1;
21886    aidc->def = idcDef;
21887    aidc->next = NULL;
21888    if (vctxt->aidcs == NULL)
21889	vctxt->aidcs = aidc;
21890    else {
21891	aidc->next = vctxt->aidcs;
21892	vctxt->aidcs = aidc;
21893    }
21894    /*
21895    * Save if we have keyrefs at all.
21896    */
21897    if ((vctxt->hasKeyrefs == 0) &&
21898	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21899	vctxt->hasKeyrefs = 1;
21900}
21901
21902/**
21903 * xmlSchemaIDCNewBinding:
21904 * @idcDef: the IDC definition of this binding
21905 *
21906 * Creates a new IDC binding.
21907 *
21908 * Returns the new IDC binding, NULL on internal errors.
21909 */
21910static xmlSchemaPSVIIDCBindingPtr
21911xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21912{
21913    xmlSchemaPSVIIDCBindingPtr ret;
21914
21915    ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21916	    sizeof(xmlSchemaPSVIIDCBinding));
21917    if (ret == NULL) {
21918	xmlSchemaVErrMemory(NULL,
21919	    "allocating a PSVI IDC binding item", NULL);
21920	return (NULL);
21921    }
21922    memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21923    ret->definition = idcDef;
21924    return (ret);
21925}
21926
21927/**
21928 * xmlSchemaIDCStoreNodeTableItem:
21929 * @vctxt: the WXS validation context
21930 * @item: the IDC node table item
21931 *
21932 * The validation context is used to store IDC node table items.
21933 * They are stored to avoid copying them if IDC node-tables are merged
21934 * with corresponding parent IDC node-tables (bubbling).
21935 *
21936 * Returns 0 if succeeded, -1 on internal errors.
21937 */
21938static int
21939xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
21940			       xmlSchemaPSVIIDCNodePtr item)
21941{
21942    /*
21943    * Add to gobal list.
21944    */
21945    if (vctxt->idcNodes == NULL) {
21946	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21947	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21948	if (vctxt->idcNodes == NULL) {
21949	    xmlSchemaVErrMemory(vctxt,
21950		"allocating the IDC node table item list", NULL);
21951	    return (-1);
21952	}
21953	vctxt->sizeIdcNodes = 20;
21954    } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21955	vctxt->sizeIdcNodes *= 2;
21956	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21957	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
21958	    sizeof(xmlSchemaPSVIIDCNodePtr));
21959	if (vctxt->idcNodes == NULL) {
21960	    xmlSchemaVErrMemory(vctxt,
21961		"re-allocating the IDC node table item list", NULL);
21962	    return (-1);
21963	}
21964    }
21965    vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
21966
21967    return (0);
21968}
21969
21970/**
21971 * xmlSchemaIDCStoreKey:
21972 * @vctxt: the WXS validation context
21973 * @item: the IDC key
21974 *
21975 * The validation context is used to store an IDC key.
21976 *
21977 * Returns 0 if succeeded, -1 on internal errors.
21978 */
21979static int
21980xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
21981		     xmlSchemaPSVIIDCKeyPtr key)
21982{
21983    /*
21984    * Add to gobal list.
21985    */
21986    if (vctxt->idcKeys == NULL) {
21987	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21988	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
21989	if (vctxt->idcKeys == NULL) {
21990	    xmlSchemaVErrMemory(vctxt,
21991		"allocating the IDC key storage list", NULL);
21992	    return (-1);
21993	}
21994	vctxt->sizeIdcKeys = 40;
21995    } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
21996	vctxt->sizeIdcKeys *= 2;
21997	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
21998	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
21999	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22000	if (vctxt->idcKeys == NULL) {
22001	    xmlSchemaVErrMemory(vctxt,
22002		"re-allocating the IDC key storage list", NULL);
22003	    return (-1);
22004	}
22005    }
22006    vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22007
22008    return (0);
22009}
22010
22011/**
22012 * xmlSchemaIDCAppendNodeTableItem:
22013 * @bind: the IDC binding
22014 * @ntItem: the node-table item
22015 *
22016 * Appends the IDC node-table item to the binding.
22017 *
22018 * Returns 0 on success and -1 on internal errors.
22019 */
22020static int
22021xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22022				xmlSchemaPSVIIDCNodePtr ntItem)
22023{
22024    if (bind->nodeTable == NULL) {
22025	bind->sizeNodes = 10;
22026	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22027	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22028	if (bind->nodeTable == NULL) {
22029	    xmlSchemaVErrMemory(NULL,
22030		"allocating an array of IDC node-table items", NULL);
22031	    return(-1);
22032	}
22033    } else if (bind->sizeNodes <= bind->nbNodes) {
22034	bind->sizeNodes *= 2;
22035	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22036	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22037		sizeof(xmlSchemaPSVIIDCNodePtr));
22038	if (bind->nodeTable == NULL) {
22039	    xmlSchemaVErrMemory(NULL,
22040		"re-allocating an array of IDC node-table items", NULL);
22041	    return(-1);
22042	}
22043    }
22044    bind->nodeTable[bind->nbNodes++] = ntItem;
22045    return(0);
22046}
22047
22048/**
22049 * xmlSchemaIDCAcquireBinding:
22050 * @vctxt: the WXS validation context
22051 * @matcher: the IDC matcher
22052 *
22053 * Looks up an PSVI IDC binding, for the IDC definition and
22054 * of the given matcher. If none found, a new one is created
22055 * and added to the IDC table.
22056 *
22057 * Returns an IDC binding or NULL on internal errors.
22058 */
22059static xmlSchemaPSVIIDCBindingPtr
22060xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22061			  xmlSchemaIDCMatcherPtr matcher)
22062{
22063    xmlSchemaNodeInfoPtr ielem;
22064
22065    ielem = vctxt->elemInfos[matcher->depth];
22066
22067    if (ielem->idcTable == NULL) {
22068	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22069	if (ielem->idcTable == NULL)
22070	    return (NULL);
22071	return(ielem->idcTable);
22072    } else {
22073	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22074
22075	bind = ielem->idcTable;
22076	do {
22077	    if (bind->definition == matcher->aidc->def)
22078		return(bind);
22079	    if (bind->next == NULL) {
22080		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22081		if (bind->next == NULL)
22082		    return (NULL);
22083		return(bind->next);
22084	    }
22085	    bind = bind->next;
22086	} while (bind != NULL);
22087    }
22088    return (NULL);
22089}
22090
22091static xmlSchemaItemListPtr
22092xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22093			     xmlSchemaIDCMatcherPtr matcher)
22094{
22095    if (matcher->targets == NULL)
22096	matcher->targets = xmlSchemaItemListCreate();
22097    return(matcher->targets);
22098}
22099
22100/**
22101 * xmlSchemaIDCFreeKey:
22102 * @key: the IDC key
22103 *
22104 * Frees an IDC key together with its compiled value.
22105 */
22106static void
22107xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22108{
22109    if (key->val != NULL)
22110	xmlSchemaFreeValue(key->val);
22111    xmlFree(key);
22112}
22113
22114/**
22115 * xmlSchemaIDCFreeBinding:
22116 *
22117 * Frees an IDC binding. Note that the node table-items
22118 * are not freed.
22119 */
22120static void
22121xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22122{
22123    if (bind->nodeTable != NULL)
22124	xmlFree(bind->nodeTable);
22125    if (bind->dupls != NULL)
22126	xmlSchemaItemListFree(bind->dupls);
22127    xmlFree(bind);
22128}
22129
22130/**
22131 * xmlSchemaIDCFreeIDCTable:
22132 * @bind: the first IDC binding in the list
22133 *
22134 * Frees an IDC table, i.e. all the IDC bindings in the list.
22135 */
22136static void
22137xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22138{
22139    xmlSchemaPSVIIDCBindingPtr prev;
22140
22141    while (bind != NULL) {
22142	prev = bind;
22143	bind = bind->next;
22144	xmlSchemaIDCFreeBinding(prev);
22145    }
22146}
22147
22148/**
22149 * xmlSchemaIDCFreeMatcherList:
22150 * @matcher: the first IDC matcher in the list
22151 *
22152 * Frees a list of IDC matchers.
22153 */
22154static void
22155xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22156{
22157    xmlSchemaIDCMatcherPtr next;
22158
22159    while (matcher != NULL) {
22160	next = matcher->next;
22161	if (matcher->keySeqs != NULL) {
22162	    int i;
22163	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22164		if (matcher->keySeqs[i] != NULL)
22165		    xmlFree(matcher->keySeqs[i]);
22166	    xmlFree(matcher->keySeqs);
22167	}
22168	if (matcher->targets != NULL) {
22169	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22170		int i;
22171		xmlSchemaPSVIIDCNodePtr idcNode;
22172		/*
22173		* Node-table items for keyrefs are not stored globally
22174		* to the validation context, since they are not bubbled.
22175		* We need to free them here.
22176		*/
22177		for (i = 0; i < matcher->targets->nbItems; i++) {
22178		    idcNode =
22179			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22180		    xmlFree(idcNode->keys);
22181		    xmlFree(idcNode);
22182		}
22183	    }
22184	    xmlSchemaItemListFree(matcher->targets);
22185	}
22186	xmlFree(matcher);
22187	matcher = next;
22188    }
22189}
22190
22191/**
22192 * xmlSchemaIDCReleaseMatcherList:
22193 * @vctxt: the WXS validation context
22194 * @matcher: the first IDC matcher in the list
22195 *
22196 * Caches a list of IDC matchers for reuse.
22197 */
22198static void
22199xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22200			       xmlSchemaIDCMatcherPtr matcher)
22201{
22202    xmlSchemaIDCMatcherPtr next;
22203
22204    while (matcher != NULL) {
22205	next = matcher->next;
22206	if (matcher->keySeqs != NULL) {
22207	    int i;
22208	    /*
22209	    * Don't free the array, but only the content.
22210	    */
22211	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22212		if (matcher->keySeqs[i] != NULL) {
22213		    xmlFree(matcher->keySeqs[i]);
22214		    matcher->keySeqs[i] = NULL;
22215		}
22216	}
22217	if (matcher->targets) {
22218	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22219		int i;
22220		xmlSchemaPSVIIDCNodePtr idcNode;
22221		/*
22222		* Node-table items for keyrefs are not stored globally
22223		* to the validation context, since they are not bubbled.
22224		* We need to free them here.
22225		*/
22226		for (i = 0; i < matcher->targets->nbItems; i++) {
22227		    idcNode =
22228			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22229		    xmlFree(idcNode->keys);
22230		    xmlFree(idcNode);
22231		}
22232	    }
22233	    xmlSchemaItemListFree(matcher->targets);
22234	    matcher->targets = NULL;
22235	}
22236	matcher->next = NULL;
22237	/*
22238	* Cache the matcher.
22239	*/
22240	if (vctxt->idcMatcherCache != NULL)
22241	    matcher->nextCached = vctxt->idcMatcherCache;
22242	vctxt->idcMatcherCache = matcher;
22243
22244	matcher = next;
22245    }
22246}
22247
22248/**
22249 * xmlSchemaIDCAddStateObject:
22250 * @vctxt: the WXS validation context
22251 * @matcher: the IDC matcher
22252 * @sel: the XPath information
22253 * @parent: the parent "selector" state object if any
22254 * @type: "selector" or "field"
22255 *
22256 * Creates/reuses and activates state objects for the given
22257 * XPath information; if the XPath expression consists of unions,
22258 * multiple state objects are created for every unioned expression.
22259 *
22260 * Returns 0 on success and -1 on internal errors.
22261 */
22262static int
22263xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22264			xmlSchemaIDCMatcherPtr matcher,
22265			xmlSchemaIDCSelectPtr sel,
22266			int type)
22267{
22268    xmlSchemaIDCStateObjPtr sto;
22269
22270    /*
22271    * Reuse the state objects from the pool.
22272    */
22273    if (vctxt->xpathStatePool != NULL) {
22274	sto = vctxt->xpathStatePool;
22275	vctxt->xpathStatePool = sto->next;
22276	sto->next = NULL;
22277    } else {
22278	/*
22279	* Create a new state object.
22280	*/
22281	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22282	if (sto == NULL) {
22283	    xmlSchemaVErrMemory(NULL,
22284		"allocating an IDC state object", NULL);
22285	    return (-1);
22286	}
22287	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22288    }
22289    /*
22290    * Add to global list.
22291    */
22292    if (vctxt->xpathStates != NULL)
22293	sto->next = vctxt->xpathStates;
22294    vctxt->xpathStates = sto;
22295
22296    /*
22297    * Free the old xpath validation context.
22298    */
22299    if (sto->xpathCtxt != NULL)
22300	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22301
22302    /*
22303    * Create a new XPath (pattern) validation context.
22304    */
22305    sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22306	(xmlPatternPtr) sel->xpathComp);
22307    if (sto->xpathCtxt == NULL) {
22308	VERROR_INT("xmlSchemaIDCAddStateObject",
22309	    "failed to create an XPath validation context");
22310	return (-1);
22311    }
22312    sto->type = type;
22313    sto->depth = vctxt->depth;
22314    sto->matcher = matcher;
22315    sto->sel = sel;
22316    sto->nbHistory = 0;
22317
22318#ifdef DEBUG_IDC
22319    xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22320	sto->sel->xpath);
22321#endif
22322    return (0);
22323}
22324
22325/**
22326 * xmlSchemaXPathEvaluate:
22327 * @vctxt: the WXS validation context
22328 * @nodeType: the nodeType of the current node
22329 *
22330 * Evaluates all active XPath state objects.
22331 *
22332 * Returns the number of IC "field" state objects which resolved to
22333 * this node, 0 if none resolved and -1 on internal errors.
22334 */
22335static int
22336xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22337		       xmlElementType nodeType)
22338{
22339    xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22340    int res, resolved = 0, depth = vctxt->depth;
22341
22342    if (vctxt->xpathStates == NULL)
22343	return (0);
22344
22345    if (nodeType == XML_ATTRIBUTE_NODE)
22346	depth++;
22347#ifdef DEBUG_IDC
22348    {
22349	xmlChar *str = NULL;
22350	xmlGenericError(xmlGenericErrorContext,
22351	    "IDC: EVAL on %s, depth %d, type %d\n",
22352	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22353		vctxt->inode->localName), depth, nodeType);
22354	FREE_AND_NULL(str)
22355    }
22356#endif
22357    /*
22358    * Process all active XPath state objects.
22359    */
22360    first = vctxt->xpathStates;
22361    sto = first;
22362    while (sto != head) {
22363#ifdef DEBUG_IDC
22364	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22365	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22366		sto->matcher->aidc->def->name, sto->sel->xpath);
22367	else
22368	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22369		sto->matcher->aidc->def->name, sto->sel->xpath);
22370#endif
22371	if (nodeType == XML_ELEMENT_NODE)
22372	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22373		vctxt->inode->localName, vctxt->inode->nsName);
22374	else
22375	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22376		vctxt->inode->localName, vctxt->inode->nsName);
22377
22378	if (res == -1) {
22379	    VERROR_INT("xmlSchemaXPathEvaluate",
22380		"calling xmlStreamPush()");
22381	    return (-1);
22382	}
22383	if (res == 0)
22384	    goto next_sto;
22385	/*
22386	* Full match.
22387	*/
22388#ifdef DEBUG_IDC
22389	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22390	    "MATCH\n");
22391#endif
22392	/*
22393	* Register a match in the state object history.
22394	*/
22395	if (sto->history == NULL) {
22396	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22397	    if (sto->history == NULL) {
22398		xmlSchemaVErrMemory(NULL,
22399		    "allocating the state object history", NULL);
22400		return(-1);
22401	    }
22402	    sto->sizeHistory = 5;
22403	} else if (sto->sizeHistory <= sto->nbHistory) {
22404	    sto->sizeHistory *= 2;
22405	    sto->history = (int *) xmlRealloc(sto->history,
22406		sto->sizeHistory * sizeof(int));
22407	    if (sto->history == NULL) {
22408		xmlSchemaVErrMemory(NULL,
22409		    "re-allocating the state object history", NULL);
22410		return(-1);
22411	    }
22412	}
22413	sto->history[sto->nbHistory++] = depth;
22414
22415#ifdef DEBUG_IDC
22416	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22417	    vctxt->depth);
22418#endif
22419
22420	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22421	    xmlSchemaIDCSelectPtr sel;
22422	    /*
22423	    * Activate state objects for the IDC fields of
22424	    * the IDC selector.
22425	    */
22426#ifdef DEBUG_IDC
22427	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22428		"activating field states\n");
22429#endif
22430	    sel = sto->matcher->aidc->def->fields;
22431	    while (sel != NULL) {
22432		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22433		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22434		    return (-1);
22435		sel = sel->next;
22436	    }
22437	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22438	    /*
22439	    * An IDC key node was found by the IDC field.
22440	    */
22441#ifdef DEBUG_IDC
22442	    xmlGenericError(xmlGenericErrorContext,
22443		"IDC:     key found\n");
22444#endif
22445	    /*
22446	    * Notify that the character value of this node is
22447	    * needed.
22448	    */
22449	    if (resolved == 0) {
22450		if ((vctxt->inode->flags &
22451		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22452		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22453	    }
22454	    resolved++;
22455	}
22456next_sto:
22457	if (sto->next == NULL) {
22458	    /*
22459	    * Evaluate field state objects created on this node as well.
22460	    */
22461	    head = first;
22462	    sto = vctxt->xpathStates;
22463	} else
22464	    sto = sto->next;
22465    }
22466    return (resolved);
22467}
22468
22469static const xmlChar *
22470xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22471			      xmlChar **buf,
22472			      xmlSchemaPSVIIDCKeyPtr *seq,
22473			      int count)
22474{
22475    int i, res;
22476    xmlChar *value = NULL;
22477
22478    *buf = xmlStrdup(BAD_CAST "[");
22479    for (i = 0; i < count; i++) {
22480	*buf = xmlStrcat(*buf, BAD_CAST "'");
22481	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22482	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22483	    &value);
22484	if (res == 0)
22485	    *buf = xmlStrcat(*buf, BAD_CAST value);
22486	else {
22487	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22488		"failed to compute a canonical value");
22489	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22490	}
22491	if (i < count -1)
22492	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22493	else
22494	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22495	if (value != NULL) {
22496	    xmlFree(value);
22497	    value = NULL;
22498	}
22499    }
22500    *buf = xmlStrcat(*buf, BAD_CAST "]");
22501
22502    return (BAD_CAST *buf);
22503}
22504
22505/**
22506 * xmlSchemaXPathPop:
22507 * @vctxt: the WXS validation context
22508 *
22509 * Pops all XPath states.
22510 *
22511 * Returns 0 on success and -1 on internal errors.
22512 */
22513static int
22514xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22515{
22516    xmlSchemaIDCStateObjPtr sto;
22517    int res;
22518
22519    if (vctxt->xpathStates == NULL)
22520	return(0);
22521    sto = vctxt->xpathStates;
22522    do {
22523	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22524	if (res == -1)
22525	    return (-1);
22526	sto = sto->next;
22527    } while (sto != NULL);
22528    return(0);
22529}
22530
22531/**
22532 * xmlSchemaXPathProcessHistory:
22533 * @vctxt: the WXS validation context
22534 * @type: the simple/complex type of the current node if any at all
22535 * @val: the precompiled value
22536 *
22537 * Processes and pops the history items of the IDC state objects.
22538 * IDC key-sequences are validated/created on IDC bindings.
22539 *
22540 * Returns 0 on success and -1 on internal errors.
22541 */
22542static int
22543xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22544			     int depth)
22545{
22546    xmlSchemaIDCStateObjPtr sto, nextsto;
22547    int res, matchDepth;
22548    xmlSchemaPSVIIDCKeyPtr key = NULL;
22549    xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22550
22551    if (vctxt->xpathStates == NULL)
22552	return (0);
22553    sto = vctxt->xpathStates;
22554
22555#ifdef DEBUG_IDC
22556    {
22557	xmlChar *str = NULL;
22558	xmlGenericError(xmlGenericErrorContext,
22559	    "IDC: BACK on %s, depth %d\n",
22560	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22561		vctxt->inode->localName), vctxt->depth);
22562	FREE_AND_NULL(str)
22563    }
22564#endif
22565    /*
22566    * Evaluate the state objects.
22567    */
22568    while (sto != NULL) {
22569	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22570	if (res == -1) {
22571	    VERROR_INT("xmlSchemaXPathProcessHistory",
22572		"calling xmlStreamPop()");
22573	    return (-1);
22574	}
22575#ifdef DEBUG_IDC
22576	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22577	    sto->sel->xpath);
22578#endif
22579	if (sto->nbHistory == 0)
22580	    goto deregister_check;
22581
22582	matchDepth = sto->history[sto->nbHistory -1];
22583
22584	/*
22585	* Only matches at the current depth are of interest.
22586	*/
22587	if (matchDepth != depth) {
22588	    sto = sto->next;
22589	    continue;
22590	}
22591	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22592	    /*
22593	    * NOTE: According to
22594	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22595	    *   ... the simple-content of complex types is also allowed.
22596	    */
22597
22598	    if (WXS_IS_COMPLEX(type)) {
22599		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22600		    /*
22601		    * Sanity check for complex types with simple content.
22602		    */
22603		    simpleType = type->contentTypeDef;
22604		    if (simpleType == NULL) {
22605			VERROR_INT("xmlSchemaXPathProcessHistory",
22606			    "field resolves to a CT with simple content "
22607			    "but the CT is missing the ST definition");
22608			return (-1);
22609		    }
22610		} else
22611		    simpleType = NULL;
22612	    } else
22613		simpleType = type;
22614	    if (simpleType == NULL) {
22615		xmlChar *str = NULL;
22616
22617		/*
22618		* Not qualified if the field resolves to a node of non
22619		* simple type.
22620		*/
22621		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22622		    XML_SCHEMAV_CVC_IDC, NULL,
22623		    WXS_BASIC_CAST sto->matcher->aidc->def,
22624		    "The XPath '%s' of a field of %s does evaluate to a node of "
22625		    "non-simple type",
22626		    sto->sel->xpath,
22627		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22628		FREE_AND_NULL(str);
22629		sto->nbHistory--;
22630		goto deregister_check;
22631	    }
22632
22633	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22634		/*
22635		* Failed to provide the normalized value; maybe
22636		* the value was invalid.
22637		*/
22638		VERROR(XML_SCHEMAV_CVC_IDC,
22639		    WXS_BASIC_CAST sto->matcher->aidc->def,
22640		    "Warning: No precomputed value available, the value "
22641		    "was either invalid or something strange happend");
22642		sto->nbHistory--;
22643		goto deregister_check;
22644	    } else {
22645		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22646		xmlSchemaPSVIIDCKeyPtr *keySeq;
22647		int pos, idx;
22648
22649		/*
22650		* The key will be anchored on the matcher's list of
22651		* key-sequences. The position in this list is determined
22652		* by the target node's depth relative to the matcher's
22653		* depth of creation (i.e. the depth of the scope element).
22654		*
22655		* Element        Depth    Pos   List-entries
22656		* <scope>          0              NULL
22657		*   <bar>          1              NULL
22658		*     <target/>    2       2      target
22659		*   <bar>
22660                * </scope>
22661		*
22662		* The size of the list is only dependant on the depth of
22663		* the tree.
22664		* An entry will be NULLed in selector_leave, i.e. when
22665		* we hit the target's
22666		*/
22667		pos = sto->depth - matcher->depth;
22668		idx = sto->sel->index;
22669
22670		/*
22671		* Create/grow the array of key-sequences.
22672		*/
22673		if (matcher->keySeqs == NULL) {
22674		    if (pos > 9)
22675			matcher->sizeKeySeqs = pos * 2;
22676		    else
22677			matcher->sizeKeySeqs = 10;
22678		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22679			xmlMalloc(matcher->sizeKeySeqs *
22680			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22681		    if (matcher->keySeqs == NULL) {
22682			xmlSchemaVErrMemory(NULL,
22683			    "allocating an array of key-sequences",
22684			    NULL);
22685			return(-1);
22686		    }
22687		    memset(matcher->keySeqs, 0,
22688			matcher->sizeKeySeqs *
22689			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22690		} else if (pos >= matcher->sizeKeySeqs) {
22691		    int i = matcher->sizeKeySeqs;
22692
22693		    matcher->sizeKeySeqs *= 2;
22694		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22695			xmlRealloc(matcher->keySeqs,
22696			matcher->sizeKeySeqs *
22697			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22698		    if (matcher->keySeqs == NULL) {
22699			xmlSchemaVErrMemory(NULL,
22700			    "reallocating an array of key-sequences",
22701			    NULL);
22702			return (-1);
22703		    }
22704		    /*
22705		    * The array needs to be NULLed.
22706		    * TODO: Use memset?
22707		    */
22708		    for (; i < matcher->sizeKeySeqs; i++)
22709			matcher->keySeqs[i] = NULL;
22710		}
22711
22712		/*
22713		* Get/create the key-sequence.
22714		*/
22715		keySeq = matcher->keySeqs[pos];
22716		if (keySeq == NULL) {
22717		    goto create_sequence;
22718		} else if (keySeq[idx] != NULL) {
22719		    xmlChar *str = NULL;
22720		    /*
22721		    * cvc-identity-constraint:
22722		    * 3 For each node in the �target node set� all
22723		    * of the {fields}, with that node as the context
22724		    * node, evaluate to either an empty node-set or
22725		    * a node-set with exactly one member, which must
22726		    * have a simple type.
22727		    *
22728		    * The key was already set; report an error.
22729		    */
22730		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22731			XML_SCHEMAV_CVC_IDC, NULL,
22732			WXS_BASIC_CAST matcher->aidc->def,
22733			"The XPath '%s' of a field of %s evaluates to a "
22734			"node-set with more than one member",
22735			sto->sel->xpath,
22736			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22737		    FREE_AND_NULL(str);
22738		    sto->nbHistory--;
22739		    goto deregister_check;
22740		} else
22741		    goto create_key;
22742
22743create_sequence:
22744		/*
22745		* Create a key-sequence.
22746		*/
22747		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22748		    matcher->aidc->def->nbFields *
22749		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22750		if (keySeq == NULL) {
22751		    xmlSchemaVErrMemory(NULL,
22752			"allocating an IDC key-sequence", NULL);
22753		    return(-1);
22754		}
22755		memset(keySeq, 0, matcher->aidc->def->nbFields *
22756		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22757		matcher->keySeqs[pos] = keySeq;
22758create_key:
22759		/*
22760		* Create a key once per node only.
22761		*/
22762		if (key == NULL) {
22763		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22764			sizeof(xmlSchemaPSVIIDCKey));
22765		    if (key == NULL) {
22766			xmlSchemaVErrMemory(NULL,
22767			    "allocating a IDC key", NULL);
22768			xmlFree(keySeq);
22769			matcher->keySeqs[pos] = NULL;
22770			return(-1);
22771		    }
22772		    /*
22773		    * Consume the compiled value.
22774		    */
22775		    key->type = simpleType;
22776		    key->val = vctxt->inode->val;
22777		    vctxt->inode->val = NULL;
22778		    /*
22779		    * Store the key in a global list.
22780		    */
22781		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22782			xmlSchemaIDCFreeKey(key);
22783			return (-1);
22784		    }
22785		}
22786		keySeq[idx] = key;
22787	    }
22788	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22789
22790	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22791	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22792	    xmlSchemaPSVIIDCNodePtr ntItem;
22793	    xmlSchemaIDCMatcherPtr matcher;
22794	    xmlSchemaIDCPtr idc;
22795	    xmlSchemaItemListPtr targets;
22796	    int pos, i, j, nbKeys;
22797	    /*
22798	    * Here we have the following scenario:
22799	    * An IDC 'selector' state object resolved to a target node,
22800	    * during the time this target node was in the
22801	    * ancestor-or-self axis, the 'field' state object(s) looked
22802	    * out for matching nodes to create a key-sequence for this
22803	    * target node. Now we are back to this target node and need
22804	    * to put the key-sequence, together with the target node
22805	    * itself, into the node-table of the corresponding IDC
22806	    * binding.
22807	    */
22808	    matcher = sto->matcher;
22809	    idc = matcher->aidc->def;
22810	    nbKeys = idc->nbFields;
22811	    pos = depth - matcher->depth;
22812	    /*
22813	    * Check if the matcher has any key-sequences at all, plus
22814	    * if it has a key-sequence for the current target node.
22815	    */
22816	    if ((matcher->keySeqs == NULL) ||
22817		(matcher->sizeKeySeqs <= pos)) {
22818		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22819		    goto selector_key_error;
22820		else
22821		    goto selector_leave;
22822	    }
22823
22824	    keySeq = &(matcher->keySeqs[pos]);
22825	    if (*keySeq == NULL) {
22826		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22827		    goto selector_key_error;
22828		else
22829		    goto selector_leave;
22830	    }
22831
22832	    for (i = 0; i < nbKeys; i++) {
22833		if ((*keySeq)[i] == NULL) {
22834		    /*
22835		    * Not qualified, if not all fields did resolve.
22836		    */
22837		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22838			/*
22839			* All fields of a "key" IDC must resolve.
22840			*/
22841			goto selector_key_error;
22842		    }
22843		    goto selector_leave;
22844		}
22845	    }
22846	    /*
22847	    * All fields did resolve.
22848	    */
22849
22850	    /*
22851	    * 4.1 If the {identity-constraint category} is unique(/key),
22852	    * then no two members of the �qualified node set� have
22853	    * �key-sequences� whose members are pairwise equal, as
22854	    * defined by Equal in [XML Schemas: Datatypes].
22855	    *
22856	    * Get the IDC binding from the matcher and check for
22857	    * duplicate key-sequences.
22858	    */
22859#if 0
22860	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22861#endif
22862	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22863	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22864		(targets->nbItems != 0)) {
22865		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22866
22867		i = 0;
22868		res = 0;
22869		/*
22870		* Compare the key-sequences, key by key.
22871		*/
22872		do {
22873		    bkeySeq =
22874			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22875		    for (j = 0; j < nbKeys; j++) {
22876			ckey = (*keySeq)[j];
22877			bkey = bkeySeq[j];
22878			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22879			if (res == -1) {
22880			    return (-1);
22881			} else if (res == 0) {
22882			    /*
22883			    * One of the keys differs, so the key-sequence
22884			    * won't be equal; get out.
22885			    */
22886			    break;
22887			}
22888		    }
22889		    if (res == 1) {
22890			/*
22891			* Duplicate key-sequence found.
22892			*/
22893			break;
22894		    }
22895		    i++;
22896		} while (i < targets->nbItems);
22897		if (i != targets->nbItems) {
22898		    xmlChar *str = NULL, *strB = NULL;
22899		    /*
22900		    * TODO: Try to report the key-sequence.
22901		    */
22902		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22903			XML_SCHEMAV_CVC_IDC, NULL,
22904			WXS_BASIC_CAST idc,
22905			"Duplicate key-sequence %s in %s",
22906			xmlSchemaFormatIDCKeySequence(vctxt, &str,
22907			    (*keySeq), nbKeys),
22908			xmlSchemaGetIDCDesignation(&strB, idc));
22909		    FREE_AND_NULL(str);
22910		    FREE_AND_NULL(strB);
22911		    goto selector_leave;
22912		}
22913	    }
22914	    /*
22915	    * Add a node-table item to the IDC binding.
22916	    */
22917	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22918		sizeof(xmlSchemaPSVIIDCNode));
22919	    if (ntItem == NULL) {
22920		xmlSchemaVErrMemory(NULL,
22921		    "allocating an IDC node-table item", NULL);
22922		xmlFree(*keySeq);
22923		*keySeq = NULL;
22924		return(-1);
22925	    }
22926	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22927
22928	    /*
22929	    * Store the node-table item in a global list.
22930	    */
22931	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22932		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22933		    xmlFree(ntItem);
22934		    xmlFree(*keySeq);
22935		    *keySeq = NULL;
22936		    return (-1);
22937		}
22938		ntItem->nodeQNameID = -1;
22939	    } else {
22940		/*
22941		* Save a cached QName for this node on the IDC node, to be
22942		* able to report it, even if the node is not saved.
22943		*/
22944		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22945		    vctxt->inode->localName, vctxt->inode->nsName);
22946		if (ntItem->nodeQNameID == -1) {
22947		    xmlFree(ntItem);
22948		    xmlFree(*keySeq);
22949		    *keySeq = NULL;
22950		    return (-1);
22951		}
22952	    }
22953	    /*
22954	    * Init the node-table item: Save the node, position and
22955	    * consume the key-sequence.
22956	    */
22957	    ntItem->node = vctxt->node;
22958	    ntItem->nodeLine = vctxt->inode->nodeLine;
22959	    ntItem->keys = *keySeq;
22960	    *keySeq = NULL;
22961#if 0
22962	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22963#endif
22964	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
22965		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22966		    /*
22967		    * Free the item, since keyref items won't be
22968		    * put on a global list.
22969		    */
22970		    xmlFree(ntItem->keys);
22971		    xmlFree(ntItem);
22972		}
22973		return (-1);
22974	    }
22975
22976	    goto selector_leave;
22977selector_key_error:
22978	    {
22979		xmlChar *str = NULL;
22980		/*
22981		* 4.2.1 (KEY) The �target node set� and the
22982		* �qualified node set� are equal, that is, every
22983		* member of the �target node set� is also a member
22984		* of the �qualified node set� and vice versa.
22985		*/
22986		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22987		    XML_SCHEMAV_CVC_IDC, NULL,
22988		    WXS_BASIC_CAST idc,
22989		    "Not all fields of %s evaluate to a node",
22990		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
22991		FREE_AND_NULL(str);
22992	    }
22993selector_leave:
22994	    /*
22995	    * Free the key-sequence if not added to the IDC table.
22996	    */
22997	    if ((keySeq != NULL) && (*keySeq != NULL)) {
22998		xmlFree(*keySeq);
22999		*keySeq = NULL;
23000	    }
23001	} /* if selector */
23002
23003	sto->nbHistory--;
23004
23005deregister_check:
23006	/*
23007	* Deregister state objects if they reach the depth of creation.
23008	*/
23009	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23010#ifdef DEBUG_IDC
23011	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23012		sto->sel->xpath);
23013#endif
23014	    if (vctxt->xpathStates != sto) {
23015		VERROR_INT("xmlSchemaXPathProcessHistory",
23016		    "The state object to be removed is not the first "
23017		    "in the list");
23018	    }
23019	    nextsto = sto->next;
23020	    /*
23021	    * Unlink from the list of active XPath state objects.
23022	    */
23023	    vctxt->xpathStates = sto->next;
23024	    sto->next = vctxt->xpathStatePool;
23025	    /*
23026	    * Link it to the pool of reusable state objects.
23027	    */
23028	    vctxt->xpathStatePool = sto;
23029	    sto = nextsto;
23030	} else
23031	    sto = sto->next;
23032    } /* while (sto != NULL) */
23033    return (0);
23034}
23035
23036/**
23037 * xmlSchemaIDCRegisterMatchers:
23038 * @vctxt: the WXS validation context
23039 * @elemDecl: the element declaration
23040 *
23041 * Creates helper objects to evaluate IDC selectors/fields
23042 * successively.
23043 *
23044 * Returns 0 if OK and -1 on internal errors.
23045 */
23046static int
23047xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23048			     xmlSchemaElementPtr elemDecl)
23049{
23050    xmlSchemaIDCMatcherPtr matcher, last = NULL;
23051    xmlSchemaIDCPtr idc, refIdc;
23052    xmlSchemaIDCAugPtr aidc;
23053
23054    idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23055    if (idc == NULL)
23056	return (0);
23057
23058#ifdef DEBUG_IDC
23059    {
23060	xmlChar *str = NULL;
23061	xmlGenericError(xmlGenericErrorContext,
23062	    "IDC: REGISTER on %s, depth %d\n",
23063	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23064		vctxt->inode->localName), vctxt->depth);
23065	FREE_AND_NULL(str)
23066    }
23067#endif
23068    if (vctxt->inode->idcMatchers != NULL) {
23069	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23070	    "The chain of IDC matchers is expected to be empty");
23071	return (-1);
23072    }
23073    do {
23074	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23075	    /*
23076	    * Since IDCs bubbles are expensive we need to know the
23077	    * depth at which the bubbles should stop; this will be
23078	    * the depth of the top-most keyref IDC. If no keyref
23079	    * references a key/unique IDC, the keyrefDepth will
23080	    * be -1, indicating that no bubbles are needed.
23081	    */
23082	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23083	    if (refIdc != NULL) {
23084		/*
23085		* Remember that we have keyrefs on this node.
23086		*/
23087		vctxt->inode->hasKeyrefs = 1;
23088		/*
23089		* Lookup the referenced augmented IDC info.
23090		*/
23091		aidc = vctxt->aidcs;
23092		while (aidc != NULL) {
23093		    if (aidc->def == refIdc)
23094			break;
23095		    aidc = aidc->next;
23096		}
23097		if (aidc == NULL) {
23098		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23099			"Could not find an augmented IDC item for an IDC "
23100			"definition");
23101		    return (-1);
23102		}
23103		if ((aidc->keyrefDepth == -1) ||
23104		    (vctxt->depth < aidc->keyrefDepth))
23105		    aidc->keyrefDepth = vctxt->depth;
23106	    }
23107	}
23108	/*
23109	* Lookup the augmented IDC item for the IDC definition.
23110	*/
23111	aidc = vctxt->aidcs;
23112	while (aidc != NULL) {
23113	    if (aidc->def == idc)
23114		break;
23115	    aidc = aidc->next;
23116	}
23117	if (aidc == NULL) {
23118	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23119		"Could not find an augmented IDC item for an IDC definition");
23120	    return (-1);
23121	}
23122	/*
23123	* Create an IDC matcher for every IDC definition.
23124	*/
23125	if (vctxt->idcMatcherCache != NULL) {
23126	    /*
23127	    * Reuse a cached matcher.
23128	    */
23129	    matcher = vctxt->idcMatcherCache;
23130	    vctxt->idcMatcherCache = matcher->nextCached;
23131	    matcher->nextCached = NULL;
23132	} else {
23133	    matcher = (xmlSchemaIDCMatcherPtr)
23134		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23135	    if (matcher == NULL) {
23136		xmlSchemaVErrMemory(vctxt,
23137		    "allocating an IDC matcher", NULL);
23138		return (-1);
23139	    }
23140	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23141	}
23142	if (last == NULL)
23143	    vctxt->inode->idcMatchers = matcher;
23144	else
23145	    last->next = matcher;
23146	last = matcher;
23147
23148	matcher->type = IDC_MATCHER;
23149	matcher->depth = vctxt->depth;
23150	matcher->aidc = aidc;
23151	matcher->idcType = aidc->def->type;
23152#ifdef DEBUG_IDC
23153	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23154#endif
23155	/*
23156	* Init the automaton state object.
23157	*/
23158	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23159	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23160	    return (-1);
23161
23162	idc = idc->next;
23163    } while (idc != NULL);
23164    return (0);
23165}
23166
23167static int
23168xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23169			   xmlSchemaNodeInfoPtr ielem)
23170{
23171    xmlSchemaPSVIIDCBindingPtr bind;
23172    int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23173    xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23174    xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23175
23176    xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23177    /* vctxt->createIDCNodeTables */
23178    while (matcher != NULL) {
23179	/*
23180	* Skip keyref IDCs and empty IDC target-lists.
23181	*/
23182	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23183	    WXS_ILIST_IS_EMPTY(matcher->targets))
23184	{
23185	    matcher = matcher->next;
23186	    continue;
23187	}
23188	/*
23189	* If we _want_ the IDC node-table to be created in any case
23190	* then do so. Otherwise create them only if keyrefs need them.
23191	*/
23192	if ((! vctxt->createIDCNodeTables) &&
23193	    ((matcher->aidc->keyrefDepth == -1) ||
23194	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23195	{
23196	    matcher = matcher->next;
23197	    continue;
23198	}
23199	/*
23200	* Get/create the IDC binding on this element for the IDC definition.
23201	*/
23202	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23203
23204	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23205	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23206	    nbDupls = bind->dupls->nbItems;
23207	} else {
23208	    dupls = NULL;
23209	    nbDupls = 0;
23210	}
23211	if (bind->nodeTable != NULL) {
23212	    nbNodeTable = bind->nbNodes;
23213	} else {
23214	    nbNodeTable = 0;
23215	}
23216
23217	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23218	    /*
23219	    * Transfer all IDC target-nodes to the IDC node-table.
23220	    */
23221	    bind->nodeTable =
23222		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23223	    bind->sizeNodes = matcher->targets->sizeItems;
23224	    bind->nbNodes = matcher->targets->nbItems;
23225
23226	    matcher->targets->items = NULL;
23227	    matcher->targets->sizeItems = 0;
23228	    matcher->targets->nbItems = 0;
23229	} else {
23230	    /*
23231	    * Compare the key-sequences and add to the IDC node-table.
23232	    */
23233	    nbTargets = matcher->targets->nbItems;
23234	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23235	    nbFields = matcher->aidc->def->nbFields;
23236	    i = 0;
23237	    do {
23238		keys = targets[i]->keys;
23239		if (nbDupls) {
23240		    /*
23241		    * Search in already found duplicates first.
23242		    */
23243		    j = 0;
23244		    do {
23245			if (nbFields == 1) {
23246			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23247				dupls[j]->keys[0]->val);
23248			    if (res == -1)
23249				goto internal_error;
23250			    if (res == 1) {
23251				/*
23252				* Equal key-sequence.
23253				*/
23254				goto next_target;
23255			    }
23256			} else {
23257			    res = 0;
23258			    ntkeys = dupls[j]->keys;
23259			    for (k = 0; k < nbFields; k++) {
23260				res = xmlSchemaAreValuesEqual(keys[k]->val,
23261				    ntkeys[k]->val);
23262				if (res == -1)
23263				    goto internal_error;
23264				if (res == 0) {
23265				    /*
23266				    * One of the keys differs.
23267				    */
23268				    break;
23269				}
23270			    }
23271			    if (res == 1) {
23272				/*
23273				* Equal key-sequence found.
23274				*/
23275				goto next_target;
23276			    }
23277			}
23278			j++;
23279		    } while (j < nbDupls);
23280		}
23281		if (nbNodeTable) {
23282		    j = 0;
23283		    do {
23284			if (nbFields == 1) {
23285			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23286				bind->nodeTable[j]->keys[0]->val);
23287			    if (res == -1)
23288				goto internal_error;
23289			    if (res == 0) {
23290				/*
23291				* The key-sequence differs.
23292				*/
23293				goto next_node_table_entry;
23294			    }
23295			} else {
23296			    res = 0;
23297			    ntkeys = bind->nodeTable[j]->keys;
23298			    for (k = 0; k < nbFields; k++) {
23299				res = xmlSchemaAreValuesEqual(keys[k]->val,
23300				    ntkeys[k]->val);
23301				if (res == -1)
23302				    goto internal_error;
23303				if (res == 0) {
23304				    /*
23305				    * One of the keys differs.
23306				    */
23307				    goto next_node_table_entry;
23308				}
23309			    }
23310			}
23311			/*
23312			* Add the duplicate to the list of duplicates.
23313			*/
23314			if (bind->dupls == NULL) {
23315			    bind->dupls = xmlSchemaItemListCreate();
23316			    if (bind->dupls == NULL)
23317				goto internal_error;
23318			}
23319			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23320			    goto internal_error;
23321			/*
23322			* Remove the duplicate entry from the IDC node-table.
23323			*/
23324			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23325			bind->nbNodes--;
23326
23327			goto next_target;
23328
23329next_node_table_entry:
23330			j++;
23331		    } while (j < nbNodeTable);
23332		}
23333		/*
23334		* If everything is fine, then add the IDC target-node to
23335		* the IDC node-table.
23336		*/
23337		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23338		    goto internal_error;
23339
23340next_target:
23341		i++;
23342	    } while (i < nbTargets);
23343	}
23344	matcher = matcher->next;
23345    }
23346    return(0);
23347
23348internal_error:
23349    return(-1);
23350}
23351
23352/**
23353 * xmlSchemaBubbleIDCNodeTables:
23354 * @depth: the current tree depth
23355 *
23356 * Merges IDC bindings of an element at @depth into the corresponding IDC
23357 * bindings of its parent element. If a duplicate note-table entry is found,
23358 * both, the parent node-table entry and child entry are discarded from the
23359 * node-table of the parent.
23360 *
23361 * Returns 0 if OK and -1 on internal errors.
23362 */
23363static int
23364xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23365{
23366    xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23367    xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23368    xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23369    xmlSchemaIDCAugPtr aidc;
23370    int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23371
23372    bind = vctxt->inode->idcTable;
23373    if (bind == NULL) {
23374	/* Fine, no table, no bubbles. */
23375	return (0);
23376    }
23377
23378    parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23379    /*
23380    * Walk all bindings; create new or add to existing bindings.
23381    * Remove duplicate key-sequences.
23382    */
23383    while (bind != NULL) {
23384
23385	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23386	    goto next_binding;
23387	/*
23388	* Check if the key/unique IDC table needs to be bubbled.
23389	*/
23390	if (! vctxt->createIDCNodeTables) {
23391	    aidc = vctxt->aidcs;
23392	    do {
23393		if (aidc->def == bind->definition) {
23394		    if ((aidc->keyrefDepth == -1) ||
23395			(aidc->keyrefDepth >= vctxt->depth)) {
23396			goto next_binding;
23397		    }
23398		    break;
23399		}
23400		aidc = aidc->next;
23401	    } while (aidc != NULL);
23402	}
23403
23404	if (parTable != NULL)
23405	    parBind = *parTable;
23406	/*
23407	* Search a matching parent binding for the
23408	* IDC definition.
23409	*/
23410	while (parBind != NULL) {
23411	    if (parBind->definition == bind->definition)
23412		break;
23413	    parBind = parBind->next;
23414	}
23415
23416	if (parBind != NULL) {
23417	    /*
23418	    * Compare every node-table entry of the child node,
23419	    * i.e. the key-sequence within, ...
23420	    */
23421	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23422
23423	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23424		oldDupls = parBind->dupls->nbItems;
23425		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23426	    } else {
23427		dupls = NULL;
23428		oldDupls = 0;
23429	    }
23430
23431	    parNodes = parBind->nodeTable;
23432	    nbFields = bind->definition->nbFields;
23433
23434	    for (i = 0; i < bind->nbNodes; i++) {
23435		node = bind->nodeTable[i];
23436		if (node == NULL)
23437		    continue;
23438		/*
23439		* ...with every key-sequence of the parent node, already
23440		* evaluated to be a duplicate key-sequence.
23441		*/
23442		if (oldDupls) {
23443		    j = 0;
23444		    while (j < oldDupls) {
23445			if (nbFields == 1) {
23446			    ret = xmlSchemaAreValuesEqual(
23447				node->keys[0]->val,
23448				dupls[j]->keys[0]->val);
23449			    if (ret == -1)
23450				goto internal_error;
23451			    if (ret == 0) {
23452				j++;
23453				continue;
23454			    }
23455			} else {
23456			    parNode = dupls[j];
23457			    for (k = 0; k < nbFields; k++) {
23458				ret = xmlSchemaAreValuesEqual(
23459				    node->keys[k]->val,
23460				    parNode->keys[k]->val);
23461				if (ret == -1)
23462				    goto internal_error;
23463				if (ret == 0)
23464				    break;
23465			    }
23466			}
23467			if (ret == 1)
23468			    /* Duplicate found. */
23469			    break;
23470			j++;
23471		    }
23472		    if (j != oldDupls) {
23473			/* Duplicate found. Skip this entry. */
23474			continue;
23475		    }
23476		}
23477		/*
23478		* ... and with every key-sequence of the parent node.
23479		*/
23480		if (oldNum) {
23481		    j = 0;
23482		    while (j < oldNum) {
23483			parNode = parNodes[j];
23484			if (nbFields == 1) {
23485			    ret = xmlSchemaAreValuesEqual(
23486				node->keys[0]->val,
23487				parNode->keys[0]->val);
23488			    if (ret == -1)
23489				goto internal_error;
23490			    if (ret == 0) {
23491				j++;
23492				continue;
23493			    }
23494			} else {
23495			    for (k = 0; k < nbFields; k++) {
23496				ret = xmlSchemaAreValuesEqual(
23497				    node->keys[k]->val,
23498				    parNode->keys[k]->val);
23499				if (ret == -1)
23500				    goto internal_error;
23501				if (ret == 0)
23502				    break;
23503			    }
23504			}
23505			if (ret == 1)
23506			    /* Duplicate found. */
23507			    break;
23508			j++;
23509		    }
23510		    if (j != oldNum) {
23511			/*
23512			* Handle duplicates. Move the duplicate in
23513			* the parent's node-table to the list of
23514			* duplicates.
23515			*/
23516			oldNum--;
23517			parBind->nbNodes--;
23518			/*
23519			* Move last old item to pos of duplicate.
23520			*/
23521			parNodes[j] = parNodes[oldNum];
23522
23523			if (parBind->nbNodes != oldNum) {
23524			    /*
23525			    * If new items exist, move last new item to
23526			    * last of old items.
23527			    */
23528			    parNodes[oldNum] =
23529				parNodes[parBind->nbNodes];
23530			}
23531			if (parBind->dupls == NULL) {
23532			    parBind->dupls = xmlSchemaItemListCreate();
23533			    if (parBind->dupls == NULL)
23534				goto internal_error;
23535			}
23536			xmlSchemaItemListAdd(parBind->dupls, parNode);
23537		    } else {
23538			/*
23539			* Add the node-table entry (node and key-sequence) of
23540			* the child node to the node table of the parent node.
23541			*/
23542			if (parBind->nodeTable == NULL) {
23543			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23544				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23545			    if (parBind->nodeTable == NULL) {
23546				xmlSchemaVErrMemory(NULL,
23547				    "allocating IDC list of node-table items", NULL);
23548				goto internal_error;
23549			    }
23550			    parBind->sizeNodes = 1;
23551			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23552			    parBind->sizeNodes *= 2;
23553			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23554				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23555				sizeof(xmlSchemaPSVIIDCNodePtr));
23556			    if (parBind->nodeTable == NULL) {
23557				xmlSchemaVErrMemory(NULL,
23558				    "re-allocating IDC list of node-table items", NULL);
23559				goto internal_error;
23560			    }
23561			}
23562			parNodes = parBind->nodeTable;
23563			/*
23564			* Append the new node-table entry to the 'new node-table
23565			* entries' section.
23566			*/
23567			parNodes[parBind->nbNodes++] = node;
23568		    }
23569
23570		}
23571
23572	    }
23573	} else {
23574	    /*
23575	    * No binding for the IDC was found: create a new one and
23576	    * copy all node-tables.
23577	    */
23578	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23579	    if (parBind == NULL)
23580		goto internal_error;
23581
23582	    /*
23583	    * TODO: Hmm, how to optimize the initial number of
23584	    * allocated entries?
23585	    */
23586	    if (bind->nbNodes != 0) {
23587		/*
23588		* Add all IDC node-table entries.
23589		*/
23590		if (! vctxt->psviExposeIDCNodeTables) {
23591		    /*
23592		    * Just move the entries.
23593		    * NOTE: this is quite save here, since
23594		    * all the keyref lookups have already been
23595		    * performed.
23596		    */
23597		    parBind->nodeTable = bind->nodeTable;
23598		    bind->nodeTable = NULL;
23599		    parBind->sizeNodes = bind->sizeNodes;
23600		    bind->sizeNodes = 0;
23601		    parBind->nbNodes = bind->nbNodes;
23602		    bind->nbNodes = 0;
23603		} else {
23604		    /*
23605		    * Copy the entries.
23606		    */
23607		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23608			xmlMalloc(bind->nbNodes *
23609			sizeof(xmlSchemaPSVIIDCNodePtr));
23610		    if (parBind->nodeTable == NULL) {
23611			xmlSchemaVErrMemory(NULL,
23612			    "allocating an array of IDC node-table "
23613			    "items", NULL);
23614			xmlSchemaIDCFreeBinding(parBind);
23615			goto internal_error;
23616		    }
23617		    parBind->sizeNodes = bind->nbNodes;
23618		    parBind->nbNodes = bind->nbNodes;
23619		    memcpy(parBind->nodeTable, bind->nodeTable,
23620			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23621		}
23622	    }
23623	    if (bind->dupls) {
23624		/*
23625		* Move the duplicates.
23626		*/
23627		if (parBind->dupls != NULL)
23628		    xmlSchemaItemListFree(parBind->dupls);
23629		parBind->dupls = bind->dupls;
23630		bind->dupls = NULL;
23631	    }
23632	    if (*parTable == NULL)
23633		*parTable = parBind;
23634	    else {
23635		parBind->next = *parTable;
23636		*parTable = parBind;
23637	    }
23638	}
23639
23640next_binding:
23641	bind = bind->next;
23642    }
23643    return (0);
23644
23645internal_error:
23646    return(-1);
23647}
23648
23649/**
23650 * xmlSchemaCheckCVCIDCKeyRef:
23651 * @vctxt: the WXS validation context
23652 * @elemDecl: the element declaration
23653 *
23654 * Check the cvc-idc-keyref constraints.
23655 */
23656static int
23657xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23658{
23659    xmlSchemaIDCMatcherPtr matcher;
23660    xmlSchemaPSVIIDCBindingPtr bind;
23661
23662    matcher = vctxt->inode->idcMatchers;
23663    /*
23664    * Find a keyref.
23665    */
23666    while (matcher != NULL) {
23667	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23668	    matcher->targets &&
23669	    matcher->targets->nbItems)
23670	{
23671	    int i, j, k, res, nbFields, hasDupls;
23672	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23673	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23674
23675	    nbFields = matcher->aidc->def->nbFields;
23676
23677	    /*
23678	    * Find the IDC node-table for the referenced IDC key/unique.
23679	    */
23680	    bind = vctxt->inode->idcTable;
23681	    while (bind != NULL) {
23682		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23683		    bind->definition)
23684		    break;
23685		bind = bind->next;
23686	    }
23687	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23688	    /*
23689	    * Search for a matching key-sequences.
23690	    */
23691	    for (i = 0; i < matcher->targets->nbItems; i++) {
23692		res = 0;
23693		refNode = matcher->targets->items[i];
23694		if (bind != NULL) {
23695		    refKeys = refNode->keys;
23696		    for (j = 0; j < bind->nbNodes; j++) {
23697			keys = bind->nodeTable[j]->keys;
23698			for (k = 0; k < nbFields; k++) {
23699			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23700				refKeys[k]->val);
23701			    if (res == 0)
23702				break;
23703			    else if (res == -1) {
23704				return (-1);
23705			    }
23706			}
23707			if (res == 1) {
23708			    /*
23709			    * Match found.
23710			    */
23711			    break;
23712			}
23713		    }
23714		    if ((res == 0) && hasDupls) {
23715			/*
23716			* Search in duplicates
23717			*/
23718			for (j = 0; j < bind->dupls->nbItems; j++) {
23719			    keys = ((xmlSchemaPSVIIDCNodePtr)
23720				bind->dupls->items[j])->keys;
23721			    for (k = 0; k < nbFields; k++) {
23722				res = xmlSchemaAreValuesEqual(keys[k]->val,
23723				    refKeys[k]->val);
23724				if (res == 0)
23725				    break;
23726				else if (res == -1) {
23727				    return (-1);
23728				}
23729			    }
23730			    if (res == 1) {
23731				/*
23732				* Match in duplicates found.
23733				*/
23734				xmlChar *str = NULL, *strB = NULL;
23735				xmlSchemaKeyrefErr(vctxt,
23736				    XML_SCHEMAV_CVC_IDC, refNode,
23737				    (xmlSchemaTypePtr) matcher->aidc->def,
23738				    "More than one match found for "
23739				    "key-sequence %s of keyref '%s'",
23740				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23741					refNode->keys, nbFields),
23742				    xmlSchemaGetComponentQName(&strB,
23743					matcher->aidc->def));
23744				FREE_AND_NULL(str);
23745				FREE_AND_NULL(strB);
23746				break;
23747			    }
23748			}
23749		    }
23750		}
23751
23752		if (res == 0) {
23753		    xmlChar *str = NULL, *strB = NULL;
23754		    xmlSchemaKeyrefErr(vctxt,
23755			XML_SCHEMAV_CVC_IDC, refNode,
23756			(xmlSchemaTypePtr) matcher->aidc->def,
23757			"No match found for key-sequence %s of keyref '%s'",
23758			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23759			    refNode->keys, nbFields),
23760			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23761		    FREE_AND_NULL(str);
23762		    FREE_AND_NULL(strB);
23763		}
23764	    }
23765	}
23766	matcher = matcher->next;
23767    }
23768    /* TODO: Return an error if any error encountered. */
23769    return (0);
23770}
23771
23772/************************************************************************
23773 * 									*
23774 * 			XML Reader validation code                      *
23775 * 									*
23776 ************************************************************************/
23777
23778static xmlSchemaAttrInfoPtr
23779xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23780{
23781    xmlSchemaAttrInfoPtr iattr;
23782    /*
23783    * Grow/create list of attribute infos.
23784    */
23785    if (vctxt->attrInfos == NULL) {
23786	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23787	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23788	vctxt->sizeAttrInfos = 1;
23789	if (vctxt->attrInfos == NULL) {
23790	    xmlSchemaVErrMemory(vctxt,
23791		"allocating attribute info list", NULL);
23792	    return (NULL);
23793	}
23794    } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23795	vctxt->sizeAttrInfos++;
23796	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23797	    xmlRealloc(vctxt->attrInfos,
23798		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23799	if (vctxt->attrInfos == NULL) {
23800	    xmlSchemaVErrMemory(vctxt,
23801		"re-allocating attribute info list", NULL);
23802	    return (NULL);
23803	}
23804    } else {
23805	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23806	if (iattr->localName != NULL) {
23807	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23808		"attr info not cleared");
23809	    return (NULL);
23810	}
23811	iattr->nodeType = XML_ATTRIBUTE_NODE;
23812	return (iattr);
23813    }
23814    /*
23815    * Create an attribute info.
23816    */
23817    iattr = (xmlSchemaAttrInfoPtr)
23818	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23819    if (iattr == NULL) {
23820	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23821	return (NULL);
23822    }
23823    memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23824    iattr->nodeType = XML_ATTRIBUTE_NODE;
23825    vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23826
23827    return (iattr);
23828}
23829
23830static int
23831xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23832			xmlNodePtr attrNode,
23833			int nodeLine,
23834			const xmlChar *localName,
23835			const xmlChar *nsName,
23836			int ownedNames,
23837			xmlChar *value,
23838			int ownedValue)
23839{
23840    xmlSchemaAttrInfoPtr attr;
23841
23842    attr = xmlSchemaGetFreshAttrInfo(vctxt);
23843    if (attr == NULL) {
23844	VERROR_INT("xmlSchemaPushAttribute",
23845	    "calling xmlSchemaGetFreshAttrInfo()");
23846	return (-1);
23847    }
23848    attr->node = attrNode;
23849    attr->nodeLine = nodeLine;
23850    attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23851    attr->localName = localName;
23852    attr->nsName = nsName;
23853    if (ownedNames)
23854	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23855    /*
23856    * Evaluate if it's an XSI attribute.
23857    */
23858    if (nsName != NULL) {
23859	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23860	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23861		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23862	    }
23863	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23864	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23865		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23866	    }
23867	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23868	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23869		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23870	    }
23871	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23872	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23873		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23874	    }
23875	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23876	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23877	}
23878    }
23879    attr->value = value;
23880    if (ownedValue)
23881	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23882    if (attr->metaType != 0)
23883	attr->state = XML_SCHEMAS_ATTR_META;
23884    return (0);
23885}
23886
23887/**
23888 * xmlSchemaClearElemInfo:
23889 * @vctxt: the WXS validation context
23890 * @ielem: the element information item
23891 */
23892static void
23893xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23894		       xmlSchemaNodeInfoPtr ielem)
23895{
23896    ielem->hasKeyrefs = 0;
23897    ielem->appliedXPath = 0;
23898    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23899	FREE_AND_NULL(ielem->localName);
23900	FREE_AND_NULL(ielem->nsName);
23901    } else {
23902	ielem->localName = NULL;
23903	ielem->nsName = NULL;
23904    }
23905    if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23906	FREE_AND_NULL(ielem->value);
23907    } else {
23908	ielem->value = NULL;
23909    }
23910    if (ielem->val != NULL) {
23911	/*
23912	* PSVI TODO: Be careful not to free it when the value is
23913	* exposed via PSVI.
23914	*/
23915	xmlSchemaFreeValue(ielem->val);
23916	ielem->val = NULL;
23917    }
23918    if (ielem->idcMatchers != NULL) {
23919	/*
23920	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
23921	*   Does it work?
23922	*/
23923	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
23924#if 0
23925	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23926#endif
23927	ielem->idcMatchers = NULL;
23928    }
23929    if (ielem->idcTable != NULL) {
23930	/*
23931	* OPTIMIZE TODO: Use a pool of IDC tables??.
23932	*/
23933	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23934	ielem->idcTable = NULL;
23935    }
23936    if (ielem->regexCtxt != NULL) {
23937	xmlRegFreeExecCtxt(ielem->regexCtxt);
23938	ielem->regexCtxt = NULL;
23939    }
23940    if (ielem->nsBindings != NULL) {
23941	xmlFree((xmlChar **)ielem->nsBindings);
23942	ielem->nsBindings = NULL;
23943	ielem->nbNsBindings = 0;
23944	ielem->sizeNsBindings = 0;
23945    }
23946}
23947
23948/**
23949 * xmlSchemaGetFreshElemInfo:
23950 * @vctxt: the schema validation context
23951 *
23952 * Creates/reuses and initializes the element info item for
23953 * the currect tree depth.
23954 *
23955 * Returns the element info item or NULL on API or internal errors.
23956 */
23957static xmlSchemaNodeInfoPtr
23958xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
23959{
23960    xmlSchemaNodeInfoPtr info = NULL;
23961
23962    if (vctxt->depth > vctxt->sizeElemInfos) {
23963	VERROR_INT("xmlSchemaGetFreshElemInfo",
23964	    "inconsistent depth encountered");
23965	return (NULL);
23966    }
23967    if (vctxt->elemInfos == NULL) {
23968	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23969	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23970	if (vctxt->elemInfos == NULL) {
23971	    xmlSchemaVErrMemory(vctxt,
23972		"allocating the element info array", NULL);
23973	    return (NULL);
23974	}
23975	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23976	vctxt->sizeElemInfos = 10;
23977    } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23978	int i = vctxt->sizeElemInfos;
23979
23980	vctxt->sizeElemInfos *= 2;
23981	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23982	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
23983	    sizeof(xmlSchemaNodeInfoPtr));
23984	if (vctxt->elemInfos == NULL) {
23985	    xmlSchemaVErrMemory(vctxt,
23986		"re-allocating the element info array", NULL);
23987	    return (NULL);
23988	}
23989	/*
23990	* We need the new memory to be NULLed.
23991	* TODO: Use memset instead?
23992	*/
23993	for (; i < vctxt->sizeElemInfos; i++)
23994	    vctxt->elemInfos[i] = NULL;
23995    } else
23996	info = vctxt->elemInfos[vctxt->depth];
23997
23998    if (info == NULL) {
23999	info = (xmlSchemaNodeInfoPtr)
24000	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24001	if (info == NULL) {
24002	    xmlSchemaVErrMemory(vctxt,
24003		"allocating an element info", NULL);
24004	    return (NULL);
24005	}
24006	vctxt->elemInfos[vctxt->depth] = info;
24007    } else {
24008	if (info->localName != NULL) {
24009	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24010		"elem info has not been cleared");
24011	    return (NULL);
24012	}
24013    }
24014    memset(info, 0, sizeof(xmlSchemaNodeInfo));
24015    info->nodeType = XML_ELEMENT_NODE;
24016    info->depth = vctxt->depth;
24017
24018    return (info);
24019}
24020
24021#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24022#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24023#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24024
24025static int
24026xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24027			xmlNodePtr node,
24028			xmlSchemaTypePtr type,
24029			xmlSchemaValType valType,
24030			const xmlChar * value,
24031			xmlSchemaValPtr val,
24032			unsigned long length,
24033			int fireErrors)
24034{
24035    int ret, error = 0;
24036
24037    xmlSchemaTypePtr tmpType;
24038    xmlSchemaFacetLinkPtr facetLink;
24039    xmlSchemaFacetPtr facet;
24040    unsigned long len = 0;
24041    xmlSchemaWhitespaceValueType ws;
24042
24043    /*
24044    * In Libxml2, derived built-in types have currently no explicit facets.
24045    */
24046    if (type->type == XML_SCHEMA_TYPE_BASIC)
24047	return (0);
24048
24049    /*
24050    * NOTE: Do not jump away, if the facetSet of the given type is
24051    * empty: until now, "pattern" and "enumeration" facets of the
24052    * *base types* need to be checked as well.
24053    */
24054    if (type->facetSet == NULL)
24055	goto pattern_and_enum;
24056
24057    if (! WXS_IS_ATOMIC(type)) {
24058	if (WXS_IS_LIST(type))
24059	    goto WXS_IS_LIST;
24060	else
24061	    goto pattern_and_enum;
24062    }
24063    /*
24064    * Whitespace handling is only of importance for string-based
24065    * types.
24066    */
24067    tmpType = xmlSchemaGetPrimitiveType(type);
24068    if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24069	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24070	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24071    } else
24072	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24073    /*
24074    * If the value was not computed (for string or
24075    * anySimpleType based types), then use the provided
24076    * type.
24077    */
24078    if (val == NULL)
24079	valType = valType;
24080    else
24081	valType = xmlSchemaGetValType(val);
24082
24083    ret = 0;
24084    for (facetLink = type->facetSet; facetLink != NULL;
24085	facetLink = facetLink->next) {
24086	/*
24087	* Skip the pattern "whiteSpace": it is used to
24088	* format the character content beforehand.
24089	*/
24090	switch (facetLink->facet->type) {
24091	    case XML_SCHEMA_FACET_WHITESPACE:
24092	    case XML_SCHEMA_FACET_PATTERN:
24093	    case XML_SCHEMA_FACET_ENUMERATION:
24094		continue;
24095	    case XML_SCHEMA_FACET_LENGTH:
24096	    case XML_SCHEMA_FACET_MINLENGTH:
24097	    case XML_SCHEMA_FACET_MAXLENGTH:
24098		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24099		    valType, value, val, &len, ws);
24100		break;
24101	    default:
24102		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24103		    valType, value, val, ws);
24104		break;
24105	}
24106	if (ret < 0) {
24107	    AERROR_INT("xmlSchemaValidateFacets",
24108		"validating against a atomic type facet");
24109	    return (-1);
24110	} else if (ret > 0) {
24111	    if (fireErrors)
24112		xmlSchemaFacetErr(actxt, ret, node,
24113		value, len, type, facetLink->facet, NULL, NULL, NULL);
24114	    else
24115		return (ret);
24116	    if (error == 0)
24117		error = ret;
24118	}
24119	ret = 0;
24120    }
24121
24122WXS_IS_LIST:
24123    if (! WXS_IS_LIST(type))
24124	goto pattern_and_enum;
24125    /*
24126    * "length", "minLength" and "maxLength" of list types.
24127    */
24128    ret = 0;
24129    for (facetLink = type->facetSet; facetLink != NULL;
24130	facetLink = facetLink->next) {
24131
24132	switch (facetLink->facet->type) {
24133	    case XML_SCHEMA_FACET_LENGTH:
24134	    case XML_SCHEMA_FACET_MINLENGTH:
24135	    case XML_SCHEMA_FACET_MAXLENGTH:
24136		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24137		    value, length, NULL);
24138		break;
24139	    default:
24140		continue;
24141	}
24142	if (ret < 0) {
24143	    AERROR_INT("xmlSchemaValidateFacets",
24144		"validating against a list type facet");
24145	    return (-1);
24146	} else if (ret > 0) {
24147	    if (fireErrors)
24148		xmlSchemaFacetErr(actxt, ret, node,
24149		value, length, type, facetLink->facet, NULL, NULL, NULL);
24150	    else
24151		return (ret);
24152	    if (error == 0)
24153		error = ret;
24154	}
24155	ret = 0;
24156    }
24157
24158pattern_and_enum:
24159    if (error >= 0) {
24160	int found = 0;
24161	/*
24162	* Process enumerations. Facet values are in the value space
24163	* of the defining type's base type. This seems to be a bug in the
24164	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24165	* Only the first set of enumerations in the ancestor-or-self axis
24166	* is used for validation.
24167	*/
24168	ret = 0;
24169	tmpType = type;
24170	do {
24171	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24172		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24173		    continue;
24174		found = 1;
24175		ret = xmlSchemaAreValuesEqual(facet->val, val);
24176		if (ret == 1)
24177		    break;
24178		else if (ret < 0) {
24179		    AERROR_INT("xmlSchemaValidateFacets",
24180			"validating against an enumeration facet");
24181		    return (-1);
24182		}
24183	    }
24184	    if (ret != 0)
24185		break;
24186	    /*
24187	    * Break on the first set of enumerations. Any additional
24188	    *  enumerations which might be existent on the ancestors
24189	    *  of the current type are restricted by this set; thus
24190	    *  *must* *not* be taken into account.
24191	    */
24192	    if (found)
24193		break;
24194	    tmpType = tmpType->baseType;
24195	} while ((tmpType != NULL) &&
24196	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24197	if (found && (ret == 0)) {
24198	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24199	    if (fireErrors) {
24200		xmlSchemaFacetErr(actxt, ret, node,
24201		    value, 0, type, NULL, NULL, NULL, NULL);
24202	    } else
24203		return (ret);
24204	    if (error == 0)
24205		error = ret;
24206	}
24207    }
24208
24209    if (error >= 0) {
24210	int found;
24211	/*
24212	* Process patters. Pattern facets are ORed at type level
24213	* and ANDed if derived. Walk the base type axis.
24214	*/
24215	tmpType = type;
24216	facet = NULL;
24217	do {
24218	    found = 0;
24219	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24220		facetLink = facetLink->next) {
24221		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24222		    continue;
24223		found = 1;
24224		/*
24225		* NOTE that for patterns, @value needs to be the
24226		* normalized vaule.
24227		*/
24228		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24229		if (ret == 1)
24230		    break;
24231		else if (ret < 0) {
24232		    AERROR_INT("xmlSchemaValidateFacets",
24233			"validating against a pattern facet");
24234		    return (-1);
24235		} else {
24236		    /*
24237		    * Save the last non-validating facet.
24238		    */
24239		    facet = facetLink->facet;
24240		}
24241	    }
24242	    if (found && (ret != 1)) {
24243		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24244		if (fireErrors) {
24245		    xmlSchemaFacetErr(actxt, ret, node,
24246			value, 0, type, facet, NULL, NULL, NULL);
24247		} else
24248		    return (ret);
24249		if (error == 0)
24250		    error = ret;
24251		break;
24252	    }
24253	    tmpType = tmpType->baseType;
24254	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24255    }
24256
24257    return (error);
24258}
24259
24260static xmlChar *
24261xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24262			const xmlChar *value)
24263{
24264    switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24265	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24266	    return (xmlSchemaCollapseString(value));
24267	case XML_SCHEMA_WHITESPACE_REPLACE:
24268	    return (xmlSchemaWhiteSpaceReplace(value));
24269	default:
24270	    return (NULL);
24271    }
24272}
24273
24274static int
24275xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24276		       const xmlChar *value,
24277		       xmlSchemaValPtr *val,
24278		       int valNeeded)
24279{
24280    int ret;
24281    const xmlChar *nsName;
24282    xmlChar *local, *prefix = NULL;
24283
24284    ret = xmlValidateQName(value, 1);
24285    if (ret != 0) {
24286	if (ret == -1) {
24287	    VERROR_INT("xmlSchemaValidateQName",
24288		"calling xmlValidateQName()");
24289	    return (-1);
24290	}
24291	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24292    }
24293    /*
24294    * NOTE: xmlSplitQName2 will always return a duplicated
24295    * strings.
24296    */
24297    local = xmlSplitQName2(value, &prefix);
24298    if (local == NULL)
24299	local = xmlStrdup(value);
24300    /*
24301    * OPTIMIZE TODO: Use flags for:
24302    *  - is there any namespace binding?
24303    *  - is there a default namespace?
24304    */
24305    nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24306
24307    if (prefix != NULL) {
24308	xmlFree(prefix);
24309	/*
24310	* A namespace must be found if the prefix is
24311	* NOT NULL.
24312	*/
24313	if (nsName == NULL) {
24314	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24315	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24316		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24317		"The QName value '%s' has no "
24318		"corresponding namespace declaration in "
24319		"scope", value, NULL);
24320	    if (local != NULL)
24321		xmlFree(local);
24322	    return (ret);
24323	}
24324    }
24325    if (valNeeded && val) {
24326	if (nsName != NULL)
24327	    *val = xmlSchemaNewQNameValue(
24328		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24329	else
24330	    *val = xmlSchemaNewQNameValue(NULL,
24331		BAD_CAST local);
24332    } else
24333	xmlFree(local);
24334    return (0);
24335}
24336
24337/*
24338* cvc-simple-type
24339*/
24340static int
24341xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24342			     xmlNodePtr node,
24343			     xmlSchemaTypePtr type,
24344			     const xmlChar *value,
24345			     xmlSchemaValPtr *retVal,
24346			     int fireErrors,
24347			     int normalize,
24348			     int isNormalized)
24349{
24350    int ret = 0, valNeeded = (retVal) ? 1 : 0;
24351    xmlSchemaValPtr val = NULL;
24352    /* xmlSchemaWhitespaceValueType ws; */
24353    xmlChar *normValue = NULL;
24354
24355#define NORMALIZE(atype) \
24356    if ((! isNormalized) && \
24357    (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24358	normValue = xmlSchemaNormalizeValue(atype, value); \
24359	if (normValue != NULL) \
24360	    value = normValue; \
24361	isNormalized = 1; \
24362    }
24363
24364    if ((retVal != NULL) && (*retVal != NULL)) {
24365	xmlSchemaFreeValue(*retVal);
24366	*retVal = NULL;
24367    }
24368    /*
24369    * 3.14.4 Simple Type Definition Validation Rules
24370    * Validation Rule: String Valid
24371    */
24372    /*
24373    * 1 It is schema-valid with respect to that definition as defined
24374    * by Datatype Valid in [XML Schemas: Datatypes].
24375    */
24376    /*
24377    * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24378    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24379    * the string must be a �declared entity name�.
24380    */
24381    /*
24382    * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24383    * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24384    * then every whitespace-delimited substring of the string must be a �declared
24385    * entity name�.
24386    */
24387    /*
24388    * 2.3 otherwise no further condition applies.
24389    */
24390    if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24391	valNeeded = 1;
24392    if (value == NULL)
24393	value = BAD_CAST "";
24394    if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24395	xmlSchemaTypePtr biType; /* The built-in type. */
24396	/*
24397	* SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24398	* a literal in the �lexical space� of {base type definition}"
24399	*/
24400	/*
24401	* Whitespace-normalize.
24402	*/
24403	NORMALIZE(type);
24404	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24405	    /*
24406	    * Get the built-in type.
24407	    */
24408	    biType = type->baseType;
24409	    while ((biType != NULL) &&
24410		(biType->type != XML_SCHEMA_TYPE_BASIC))
24411		biType = biType->baseType;
24412
24413	    if (biType == NULL) {
24414		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24415		    "could not get the built-in type");
24416		goto internal_error;
24417	    }
24418	} else
24419	    biType = type;
24420	/*
24421	* NOTATIONs need to be processed here, since they need
24422	* to lookup in the hashtable of NOTATION declarations of the schema.
24423	*/
24424	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24425	    switch (biType->builtInType) {
24426		case XML_SCHEMAS_NOTATION:
24427		    ret = xmlSchemaValidateNotation(
24428			(xmlSchemaValidCtxtPtr) actxt,
24429			((xmlSchemaValidCtxtPtr) actxt)->schema,
24430			NULL, value, &val, valNeeded);
24431		    break;
24432		case XML_SCHEMAS_QNAME:
24433		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24434			value, &val, valNeeded);
24435		    break;
24436		default:
24437		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24438		    if (valNeeded)
24439			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24440			    value, &val, NULL);
24441		    else
24442			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24443			    value, NULL, NULL);
24444		    break;
24445	    }
24446	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24447	    switch (biType->builtInType) {
24448		case XML_SCHEMAS_NOTATION:
24449		    ret = xmlSchemaValidateNotation(NULL,
24450			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24451			value, &val, valNeeded);
24452		    break;
24453		default:
24454		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24455		    if (valNeeded)
24456			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24457			    value, &val, node);
24458		    else
24459			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24460			    value, NULL, node);
24461		    break;
24462	    }
24463	} else {
24464	    /*
24465	    * Validation via a public API is not implemented yet.
24466	    */
24467	    TODO
24468	    goto internal_error;
24469	}
24470	if (ret != 0) {
24471	    if (ret < 0) {
24472		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24473		    "validating against a built-in type");
24474		goto internal_error;
24475	    }
24476	    if (WXS_IS_LIST(type))
24477		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24478	    else
24479		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24480	}
24481	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24482	    /*
24483	    * Check facets.
24484	    */
24485	    ret = xmlSchemaValidateFacets(actxt, node, type,
24486		(xmlSchemaValType) biType->builtInType, value, val,
24487		0, fireErrors);
24488	    if (ret != 0) {
24489		if (ret < 0) {
24490		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24491			"validating facets of atomic simple type");
24492		    goto internal_error;
24493		}
24494		if (WXS_IS_LIST(type))
24495		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24496		else
24497		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24498	    }
24499	}
24500	if (fireErrors && (ret > 0))
24501	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24502    } else if (WXS_IS_LIST(type)) {
24503
24504	xmlSchemaTypePtr itemType;
24505	const xmlChar *cur, *end;
24506	xmlChar *tmpValue = NULL;
24507	unsigned long len = 0;
24508	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24509	/* 1.2.2 if {variety} is �list� then the string must be a sequence
24510	* of white space separated tokens, each of which �match�es a literal
24511	* in the �lexical space� of {item type definition}
24512	*/
24513	/*
24514	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24515	* the list type has an enum or pattern facet.
24516	*/
24517	NORMALIZE(type);
24518	/*
24519	* VAL TODO: Optimize validation of empty values.
24520	* VAL TODO: We do not have computed values for lists.
24521	*/
24522	itemType = WXS_LIST_ITEMTYPE(type);
24523	cur = value;
24524	do {
24525	    while (IS_BLANK_CH(*cur))
24526		cur++;
24527	    end = cur;
24528	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24529		end++;
24530	    if (end == cur)
24531		break;
24532	    tmpValue = xmlStrndup(cur, end - cur);
24533	    len++;
24534
24535	    if (valNeeded)
24536		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24537		    tmpValue, &curVal, fireErrors, 0, 1);
24538	    else
24539		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24540		    tmpValue, NULL, fireErrors, 0, 1);
24541	    FREE_AND_NULL(tmpValue);
24542	    if (curVal != NULL) {
24543		/*
24544		* Add to list of computed values.
24545		*/
24546		if (val == NULL)
24547		    val = curVal;
24548		else
24549		    xmlSchemaValueAppend(prevVal, curVal);
24550		prevVal = curVal;
24551		curVal = NULL;
24552	    }
24553	    if (ret != 0) {
24554		if (ret < 0) {
24555		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24556			"validating an item of list simple type");
24557		    goto internal_error;
24558		}
24559		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24560		break;
24561	    }
24562	    cur = end;
24563	} while (*cur != 0);
24564	FREE_AND_NULL(tmpValue);
24565	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24566	    /*
24567	    * Apply facets (pattern, enumeration).
24568	    */
24569	    ret = xmlSchemaValidateFacets(actxt, node, type,
24570		XML_SCHEMAS_UNKNOWN, value, val,
24571		len, fireErrors);
24572	    if (ret != 0) {
24573		if (ret < 0) {
24574		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24575			"validating facets of list simple type");
24576		    goto internal_error;
24577		}
24578		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24579	    }
24580	}
24581	if (fireErrors && (ret > 0)) {
24582	    /*
24583	    * Report the normalized value.
24584	    */
24585	    normalize = 1;
24586	    NORMALIZE(type);
24587	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24588	}
24589    } else if (WXS_IS_UNION(type)) {
24590	xmlSchemaTypeLinkPtr memberLink;
24591	/*
24592	* TODO: For all datatypes �derived� by �union�  whiteSpace does
24593	* not apply directly; however, the normalization behavior of �union�
24594	* types is controlled by the value of whiteSpace on that one of the
24595	* �memberTypes� against which the �union� is successfully validated.
24596	*
24597	* This means that the value is normalized by the first validating
24598	* member type, then the facets of the union type are applied. This
24599	* needs changing of the value!
24600	*/
24601
24602	/*
24603	* 1.2.3 if {variety} is �union� then the string must �match� a
24604	* literal in the �lexical space� of at least one member of
24605	* {member type definitions}
24606	*/
24607	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24608	if (memberLink == NULL) {
24609	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24610		"union simple type has no member types");
24611	    goto internal_error;
24612	}
24613	/*
24614	* Always normalize union type values, since we currently
24615	* cannot store the whitespace information with the value
24616	* itself; otherwise a later value-comparison would be
24617	* not possible.
24618	*/
24619	while (memberLink != NULL) {
24620	    if (valNeeded)
24621		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24622		    memberLink->type, value, &val, 0, 1, 0);
24623	    else
24624		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24625		    memberLink->type, value, NULL, 0, 1, 0);
24626	    if (ret <= 0)
24627		break;
24628	    memberLink = memberLink->next;
24629	}
24630	if (ret != 0) {
24631	    if (ret < 0) {
24632		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24633		    "validating members of union simple type");
24634		goto internal_error;
24635	    }
24636	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24637	}
24638	/*
24639	* Apply facets (pattern, enumeration).
24640	*/
24641	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24642	    /*
24643	    * The normalization behavior of �union� types is controlled by
24644	    * the value of whiteSpace on that one of the �memberTypes�
24645	    * against which the �union� is successfully validated.
24646	    */
24647	    NORMALIZE(memberLink->type);
24648	    ret = xmlSchemaValidateFacets(actxt, node, type,
24649		XML_SCHEMAS_UNKNOWN, value, val,
24650		0, fireErrors);
24651	    if (ret != 0) {
24652		if (ret < 0) {
24653		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24654			"validating facets of union simple type");
24655		    goto internal_error;
24656		}
24657		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24658	    }
24659	}
24660	if (fireErrors && (ret > 0))
24661	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24662    }
24663
24664    if (normValue != NULL)
24665	xmlFree(normValue);
24666    if (ret == 0) {
24667	if (retVal != NULL)
24668	    *retVal = val;
24669	else if (val != NULL)
24670	    xmlSchemaFreeValue(val);
24671    } else if (val != NULL)
24672	xmlSchemaFreeValue(val);
24673    return (ret);
24674internal_error:
24675    if (normValue != NULL)
24676	xmlFree(normValue);
24677    if (val != NULL)
24678	xmlSchemaFreeValue(val);
24679    return (-1);
24680}
24681
24682static int
24683xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24684			   const xmlChar *value,
24685			   const xmlChar **nsName,
24686			   const xmlChar **localName)
24687{
24688    int ret = 0;
24689
24690    if ((nsName == NULL) || (localName == NULL))
24691	return (-1);
24692    *nsName = NULL;
24693    *localName = NULL;
24694
24695    ret = xmlValidateQName(value, 1);
24696    if (ret == -1)
24697	return (-1);
24698    if (ret > 0) {
24699	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24700	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24701	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24702	return (1);
24703    }
24704    {
24705	xmlChar *local = NULL;
24706	xmlChar *prefix;
24707
24708	/*
24709	* NOTE: xmlSplitQName2 will return a duplicated
24710	* string.
24711	*/
24712	local = xmlSplitQName2(value, &prefix);
24713	if (local == NULL)
24714	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24715	else {
24716	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24717	    xmlFree(local);
24718	}
24719
24720	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24721
24722	if (prefix != NULL) {
24723	    xmlFree(prefix);
24724	    /*
24725	    * A namespace must be found if the prefix is NOT NULL.
24726	    */
24727	    if (*nsName == NULL) {
24728		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24729		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24730		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24731		    "The QName value '%s' has no "
24732		    "corresponding namespace declaration in scope",
24733		    value, NULL);
24734		return (2);
24735	    }
24736	}
24737    }
24738    return (0);
24739}
24740
24741static int
24742xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24743			xmlSchemaAttrInfoPtr iattr,
24744			xmlSchemaTypePtr *localType,
24745			xmlSchemaElementPtr elemDecl)
24746{
24747    int ret = 0;
24748    /*
24749    * cvc-elt (3.3.4) : (4)
24750    * AND
24751    * Schema-Validity Assessment (Element) (cvc-assess-elt)
24752    *   (1.2.1.2.1) - (1.2.1.2.4)
24753    * Handle 'xsi:type'.
24754    */
24755    if (localType == NULL)
24756	return (-1);
24757    *localType = NULL;
24758    if (iattr == NULL)
24759	return (0);
24760    else {
24761	const xmlChar *nsName = NULL, *local = NULL;
24762	/*
24763	* TODO: We should report a *warning* that the type was overriden
24764	* by the instance.
24765	*/
24766	ACTIVATE_ATTRIBUTE(iattr);
24767	/*
24768	* (cvc-elt) (3.3.4) : (4.1)
24769	* (cvc-assess-elt) (1.2.1.2.2)
24770	*/
24771	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24772	    &nsName, &local);
24773	if (ret != 0) {
24774	    if (ret < 0) {
24775		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24776		    "calling xmlSchemaQNameExpand() to validate the "
24777		    "attribute 'xsi:type'");
24778		goto internal_error;
24779	    }
24780	    goto exit;
24781	}
24782	/*
24783	* (cvc-elt) (3.3.4) : (4.2)
24784	* (cvc-assess-elt) (1.2.1.2.3)
24785	*/
24786	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24787	if (*localType == NULL) {
24788	    xmlChar *str = NULL;
24789
24790	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24791		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24792		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24793		"The QName value '%s' of the xsi:type attribute does not "
24794		"resolve to a type definition",
24795		xmlSchemaFormatQName(&str, nsName, local), NULL);
24796	    FREE_AND_NULL(str);
24797	    ret = vctxt->err;
24798	    goto exit;
24799	}
24800	if (elemDecl != NULL) {
24801	    int set = 0;
24802
24803	    /*
24804	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24805	    * "The �local type definition� must be validly
24806	    * derived from the {type definition} given the union of
24807	    * the {disallowed substitutions} and the {type definition}'s
24808	    * {prohibited substitutions}, as defined in
24809	    * Type Derivation OK (Complex) (�3.4.6)
24810	    * (if it is a complex type definition),
24811	    * or given {disallowed substitutions} as defined in Type
24812	    * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24813	    * definition)."
24814	    *
24815	    * {disallowed substitutions}: the "block" on the element decl.
24816	    * {prohibited substitutions}: the "block" on the type def.
24817	    */
24818	    /*
24819	    * OPTIMIZE TODO: We could map types already evaluated
24820	    * to be validly derived from other types to avoid checking
24821	    * this over and over for the same types.
24822	    */
24823	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24824		(elemDecl->subtypes->flags &
24825		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24826		set |= SUBSET_EXTENSION;
24827
24828	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24829		(elemDecl->subtypes->flags &
24830		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24831		set |= SUBSET_RESTRICTION;
24832
24833	    /*
24834	    * REMOVED and CHANGED since this produced a parser context
24835	    * which adds to the string dict of the schema. So this would
24836	    * change the schema and we don't want this. We don't need
24837	    * the parser context anymore.
24838	    *
24839	    * if ((vctxt->pctxt == NULL) &&
24840	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24841	    *	    return (-1);
24842	    */
24843
24844	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24845		elemDecl->subtypes, set) != 0) {
24846		xmlChar *str = NULL;
24847
24848		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24849		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24850		    "The type definition '%s', specified by xsi:type, is "
24851		    "blocked or not validly derived from the type definition "
24852		    "of the element declaration",
24853		    xmlSchemaFormatQName(&str,
24854			(*localType)->targetNamespace,
24855			(*localType)->name),
24856		    NULL);
24857		FREE_AND_NULL(str);
24858		ret = vctxt->err;
24859		*localType = NULL;
24860	    }
24861	}
24862    }
24863exit:
24864    ACTIVATE_ELEM;
24865    return (ret);
24866internal_error:
24867    ACTIVATE_ELEM;
24868    return (-1);
24869}
24870
24871static int
24872xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24873{
24874    xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24875    xmlSchemaTypePtr actualType;
24876
24877    /*
24878    * cvc-elt (3.3.4) : 1
24879    */
24880    if (elemDecl == NULL) {
24881	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24882	    "No matching declaration available");
24883        return (vctxt->err);
24884    }
24885    actualType = WXS_ELEM_TYPEDEF(elemDecl);
24886    /*
24887    * cvc-elt (3.3.4) : 2
24888    */
24889    if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24890	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24891	    "The element declaration is abstract");
24892        return (vctxt->err);
24893    }
24894    if (actualType == NULL) {
24895    	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24896    	    "The type definition is absent");
24897    	return (XML_SCHEMAV_CVC_TYPE_1);
24898    }
24899    if (vctxt->nbAttrInfos != 0) {
24900	int ret;
24901	xmlSchemaAttrInfoPtr iattr;
24902	/*
24903	* cvc-elt (3.3.4) : 3
24904	* Handle 'xsi:nil'.
24905	*/
24906	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24907	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24908	if (iattr) {
24909	    ACTIVATE_ATTRIBUTE(iattr);
24910	    /*
24911	    * Validate the value.
24912	    */
24913	    ret = xmlSchemaVCheckCVCSimpleType(
24914		ACTXT_CAST vctxt, NULL,
24915		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24916		iattr->value, &(iattr->val), 1, 0, 0);
24917	    ACTIVATE_ELEM;
24918	    if (ret < 0) {
24919		VERROR_INT("xmlSchemaValidateElemDecl",
24920		    "calling xmlSchemaVCheckCVCSimpleType() to "
24921		    "validate the attribute 'xsi:nil'");
24922		return (-1);
24923	    }
24924	    if (ret == 0) {
24925		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24926		    /*
24927		    * cvc-elt (3.3.4) : 3.1
24928		    */
24929		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24930			"The element is not 'nillable'");
24931		    /* Does not return an error on purpose. */
24932		} else {
24933		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24934			/*
24935			* cvc-elt (3.3.4) : 3.2.2
24936			*/
24937			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24938			    (elemDecl->value != NULL)) {
24939			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24940				"The element cannot be 'nilled' because "
24941				"there is a fixed value constraint defined "
24942				"for it");
24943			     /* Does not return an error on purpose. */
24944			} else
24945			    vctxt->inode->flags |=
24946				XML_SCHEMA_ELEM_INFO_NILLED;
24947		    }
24948		}
24949	    }
24950	}
24951	/*
24952	* cvc-elt (3.3.4) : 4
24953	* Handle 'xsi:type'.
24954	*/
24955	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24956	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24957	if (iattr) {
24958	    xmlSchemaTypePtr localType = NULL;
24959
24960	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24961		elemDecl);
24962	    if (ret != 0) {
24963		if (ret == -1) {
24964		    VERROR_INT("xmlSchemaValidateElemDecl",
24965			"calling xmlSchemaProcessXSIType() to "
24966			"process the attribute 'xsi:type'");
24967		    return (-1);
24968		}
24969		/* Does not return an error on purpose. */
24970	    }
24971	    if (localType != NULL) {
24972		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24973		actualType = localType;
24974	    }
24975	}
24976    }
24977    /*
24978    * IDC: Register identity-constraint XPath matchers.
24979    */
24980    if ((elemDecl->idcs != NULL) &&
24981	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
24982	    return (-1);
24983    /*
24984    * No actual type definition.
24985    */
24986    if (actualType == NULL) {
24987    	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24988    	    "The type definition is absent");
24989    	return (XML_SCHEMAV_CVC_TYPE_1);
24990    }
24991    /*
24992    * Remember the actual type definition.
24993    */
24994    vctxt->inode->typeDef = actualType;
24995
24996    return (0);
24997}
24998
24999static int
25000xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25001{
25002    xmlSchemaAttrInfoPtr iattr;
25003    int ret = 0, i;
25004
25005    /*
25006    * SPEC cvc-type (3.1.1)
25007    * "The attributes of must be empty, excepting those whose namespace
25008    * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25009    * whose local name is one of type, nil, schemaLocation or
25010    * noNamespaceSchemaLocation."
25011    */
25012    if (vctxt->nbAttrInfos == 0)
25013	return (0);
25014    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25015	iattr = vctxt->attrInfos[i];
25016	if (! iattr->metaType) {
25017	    ACTIVATE_ATTRIBUTE(iattr)
25018	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25019		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25020	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25021        }
25022    }
25023    ACTIVATE_ELEM
25024    return (ret);
25025}
25026
25027/*
25028* Cleanup currently used attribute infos.
25029*/
25030static void
25031xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25032{
25033    int i;
25034    xmlSchemaAttrInfoPtr attr;
25035
25036    if (vctxt->nbAttrInfos == 0)
25037	return;
25038    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25039	attr = vctxt->attrInfos[i];
25040	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25041	    if (attr->localName != NULL)
25042		xmlFree((xmlChar *) attr->localName);
25043	    if (attr->nsName != NULL)
25044		xmlFree((xmlChar *) attr->nsName);
25045	}
25046	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25047	    if (attr->value != NULL)
25048		xmlFree((xmlChar *) attr->value);
25049	}
25050	if (attr->val != NULL) {
25051	    xmlSchemaFreeValue(attr->val);
25052	    attr->val = NULL;
25053	}
25054	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25055    }
25056    vctxt->nbAttrInfos = 0;
25057}
25058
25059/*
25060* 3.4.4 Complex Type Definition Validation Rules
25061*   Element Locally Valid (Complex Type) (cvc-complex-type)
25062* 3.2.4 Attribute Declaration Validation Rules
25063*   Validation Rule: Attribute Locally Valid (cvc-attribute)
25064*   Attribute Locally Valid (Use) (cvc-au)
25065*
25066* Only "assessed" attribute information items will be visible to
25067* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25068*/
25069static int
25070xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25071{
25072    xmlSchemaTypePtr type = vctxt->inode->typeDef;
25073    xmlSchemaItemListPtr attrUseList;
25074    xmlSchemaAttributeUsePtr attrUse = NULL;
25075    xmlSchemaAttributePtr attrDecl = NULL;
25076    xmlSchemaAttrInfoPtr iattr, tmpiattr;
25077    int i, j, found, nbAttrs, nbUses;
25078    int xpathRes = 0, res, wildIDs = 0, fixed;
25079    xmlNodePtr defAttrOwnerElem = NULL;
25080
25081    /*
25082    * SPEC (cvc-attribute)
25083    * (1) "The declaration must not be �absent� (see Missing
25084    * Sub-components (�5.3) for how this can fail to be
25085    * the case)."
25086    * (2) "Its {type definition} must not be absent."
25087    *
25088    * NOTE (1) + (2): This is not handled here, since we currently do not
25089    * allow validation against schemas which have missing sub-components.
25090    *
25091    * SPEC (cvc-complex-type)
25092    * (3) "For each attribute information item in the element information
25093    * item's [attributes] excepting those whose [namespace name] is
25094    * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25095    * [local name] is one of type, nil, schemaLocation or
25096    * noNamespaceSchemaLocation, the appropriate case among the following
25097    * must be true:
25098    *
25099    */
25100    attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25101    /*
25102    * @nbAttrs is the number of attributes present in the instance.
25103    */
25104    nbAttrs = vctxt->nbAttrInfos;
25105    if (attrUseList != NULL)
25106	nbUses = attrUseList->nbItems;
25107    else
25108	nbUses = 0;
25109    for (i = 0; i < nbUses; i++) {
25110        found = 0;
25111	attrUse = attrUseList->items[i];
25112	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25113        for (j = 0; j < nbAttrs; j++) {
25114	    iattr = vctxt->attrInfos[j];
25115	    /*
25116	    * SPEC (cvc-complex-type) (3)
25117	    * Skip meta attributes.
25118	    */
25119	    if (iattr->metaType)
25120		continue;
25121	    if (iattr->localName[0] != attrDecl->name[0])
25122		continue;
25123	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25124		continue;
25125	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25126		continue;
25127	    found = 1;
25128	    /*
25129	    * SPEC (cvc-complex-type)
25130	    * (3.1) "If there is among the {attribute uses} an attribute
25131	    * use with an {attribute declaration} whose {name} matches
25132	    * the attribute information item's [local name] and whose
25133	    * {target namespace} is identical to the attribute information
25134	    * item's [namespace name] (where an �absent� {target namespace}
25135	    * is taken to be identical to a [namespace name] with no value),
25136	    * then the attribute information must be �valid� with respect
25137	    * to that attribute use as per Attribute Locally Valid (Use)
25138	    * (�3.5.4). In this case the {attribute declaration} of that
25139	    * attribute use is the �context-determined declaration� for the
25140	    * attribute information item with respect to Schema-Validity
25141	    * Assessment (Attribute) (�3.2.4) and
25142	    * Assessment Outcome (Attribute) (�3.2.5).
25143	    */
25144	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25145	    iattr->use = attrUse;
25146	    /*
25147	    * Context-determined declaration.
25148	    */
25149	    iattr->decl = attrDecl;
25150	    iattr->typeDef = attrDecl->subtypes;
25151	    break;
25152	}
25153
25154	if (found)
25155	    continue;
25156
25157	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25158	    /*
25159	    * Handle non-existent, required attributes.
25160	    *
25161	    * SPEC (cvc-complex-type)
25162	    * (4) "The {attribute declaration} of each attribute use in
25163	    * the {attribute uses} whose {required} is true matches one
25164	    * of the attribute information items in the element information
25165	    * item's [attributes] as per clause 3.1 above."
25166	    */
25167	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25168	    if (tmpiattr == NULL) {
25169		VERROR_INT(
25170		    "xmlSchemaVAttributesComplex",
25171		    "calling xmlSchemaGetFreshAttrInfo()");
25172		return (-1);
25173	    }
25174	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25175	    tmpiattr->use = attrUse;
25176	    tmpiattr->decl = attrDecl;
25177	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25178	    ((attrUse->defValue != NULL) ||
25179	     (attrDecl->defValue != NULL))) {
25180	    /*
25181	    * Handle non-existent, optional, default/fixed attributes.
25182	    */
25183	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25184	    if (tmpiattr == NULL) {
25185		VERROR_INT(
25186		    "xmlSchemaVAttributesComplex",
25187		    "calling xmlSchemaGetFreshAttrInfo()");
25188		return (-1);
25189	    }
25190	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25191	    tmpiattr->use = attrUse;
25192	    tmpiattr->decl = attrDecl;
25193	    tmpiattr->typeDef = attrDecl->subtypes;
25194	    tmpiattr->localName = attrDecl->name;
25195	    tmpiattr->nsName = attrDecl->targetNamespace;
25196	}
25197    }
25198
25199    if (vctxt->nbAttrInfos == 0)
25200	return (0);
25201    nbUses = vctxt->nbAttrInfos;
25202    /*
25203    * Validate against the wildcard.
25204    */
25205    if (type->attributeWildcard != NULL) {
25206	/*
25207	* SPEC (cvc-complex-type)
25208	* (3.2.1) "There must be an {attribute wildcard}."
25209	*/
25210	for (i = 0; i < nbAttrs; i++) {
25211	    iattr = vctxt->attrInfos[i];
25212	    /*
25213	    * SPEC (cvc-complex-type) (3)
25214	    * Skip meta attributes.
25215	    */
25216	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25217		continue;
25218	    /*
25219	    * SPEC (cvc-complex-type)
25220	    * (3.2.2) "The attribute information item must be �valid� with
25221	    * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25222	    *
25223	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25224	    * "... its [namespace name] must be �valid� with respect to
25225	    * the wildcard constraint, as defined in Wildcard allows
25226	    * Namespace Name (�3.10.4)."
25227	    */
25228	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25229		    iattr->nsName) == 0) {
25230		/*
25231		* Handle processContents.
25232		*
25233		* SPEC (cvc-wildcard):
25234		* processContents | context-determined declaration:
25235		* "strict"          "mustFind"
25236		* "lax"             "none"
25237		* "skip"            "skip"
25238		*/
25239		if (type->attributeWildcard->processContents ==
25240		    XML_SCHEMAS_ANY_SKIP) {
25241		     /*
25242		    * context-determined declaration = "skip"
25243		    *
25244		    * SPEC PSVI Assessment Outcome (Attribute)
25245		    * [validity] = "notKnown"
25246		    * [validation attempted] = "none"
25247		    */
25248		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25249		    continue;
25250		}
25251		/*
25252		* Find an attribute declaration.
25253		*/
25254		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25255		    iattr->localName, iattr->nsName);
25256		if (iattr->decl != NULL) {
25257		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25258		    /*
25259		    * SPEC (cvc-complex-type)
25260		    * (5) "Let [Definition:]  the wild IDs be the set of
25261		    * all attribute information item to which clause 3.2
25262		    * applied and whose �validation� resulted in a
25263		    * �context-determined declaration� of mustFind or no
25264		    * �context-determined declaration� at all, and whose
25265		    * [local name] and [namespace name] resolve (as
25266		    * defined by QName resolution (Instance) (�3.15.4)) to
25267		    * an attribute declaration whose {type definition} is
25268		    * or is derived from ID. Then all of the following
25269		    * must be true:"
25270		    */
25271		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25272		    if (xmlSchemaIsDerivedFromBuiltInType(
25273			iattr->typeDef, XML_SCHEMAS_ID)) {
25274			/*
25275			* SPEC (5.1) "There must be no more than one
25276			* item in �wild IDs�."
25277			*/
25278			if (wildIDs != 0) {
25279			    /* VAL TODO */
25280			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25281			    TODO
25282			    continue;
25283			}
25284			wildIDs++;
25285			/*
25286			* SPEC (cvc-complex-type)
25287			* (5.2) "If �wild IDs� is non-empty, there must not
25288			* be any attribute uses among the {attribute uses}
25289			* whose {attribute declaration}'s {type definition}
25290			* is or is derived from ID."
25291			*/
25292			for (j = 0; j < attrUseList->nbItems; j++) {
25293			    if (xmlSchemaIsDerivedFromBuiltInType(
25294				WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25295				XML_SCHEMAS_ID)) {
25296				/* URGENT VAL TODO: implement */
25297				iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25298				TODO
25299				break;
25300			    }
25301			}
25302		    }
25303		} else if (type->attributeWildcard->processContents ==
25304		    XML_SCHEMAS_ANY_LAX) {
25305		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25306		    /*
25307		    * SPEC PSVI Assessment Outcome (Attribute)
25308		    * [validity] = "notKnown"
25309		    * [validation attempted] = "none"
25310		    */
25311		} else {
25312		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25313		}
25314	    }
25315	}
25316    }
25317
25318    if (vctxt->nbAttrInfos == 0)
25319	return (0);
25320
25321    /*
25322    * Get the owner element; needed for creation of default attributes.
25323    * This fixes bug #341337, reported by David Grohmann.
25324    */
25325    if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25326	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25327	if (ielem && ielem->node && ielem->node->doc)
25328	    defAttrOwnerElem = ielem->node;
25329    }
25330    /*
25331    * Validate values, create default attributes, evaluate IDCs.
25332    */
25333    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25334	iattr = vctxt->attrInfos[i];
25335	/*
25336	* VAL TODO: Note that we won't try to resolve IDCs to
25337	* "lax" and "skip" validated attributes. Check what to
25338	* do in this case.
25339	*/
25340	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25341	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25342	    continue;
25343	/*
25344	* VAL TODO: What to do if the type definition is missing?
25345	*/
25346	if (iattr->typeDef == NULL) {
25347	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25348	    continue;
25349	}
25350
25351	ACTIVATE_ATTRIBUTE(iattr);
25352	fixed = 0;
25353	xpathRes = 0;
25354
25355	if (vctxt->xpathStates != NULL) {
25356	    /*
25357	    * Evaluate IDCs.
25358	    */
25359	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25360		XML_ATTRIBUTE_NODE);
25361	    if (xpathRes == -1) {
25362		VERROR_INT("xmlSchemaVAttributesComplex",
25363		    "calling xmlSchemaXPathEvaluate()");
25364		goto internal_error;
25365	    }
25366	}
25367
25368	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25369	    /*
25370	    * Default/fixed attributes.
25371	    * We need the value only if we need to resolve IDCs or
25372	    * will create default attributes.
25373	    */
25374	    if ((xpathRes) || (defAttrOwnerElem)) {
25375		if (iattr->use->defValue != NULL) {
25376		    iattr->value = (xmlChar *) iattr->use->defValue;
25377		    iattr->val = iattr->use->defVal;
25378		} else {
25379		    iattr->value = (xmlChar *) iattr->decl->defValue;
25380		    iattr->val = iattr->decl->defVal;
25381		}
25382		/*
25383		* IDCs will consume the precomputed default value,
25384		* so we need to clone it.
25385		*/
25386		if (iattr->val == NULL) {
25387		    VERROR_INT("xmlSchemaVAttributesComplex",
25388			"default/fixed value on an attribute use was "
25389			"not precomputed");
25390		    goto internal_error;
25391		}
25392		iattr->val = xmlSchemaCopyValue(iattr->val);
25393		if (iattr->val == NULL) {
25394		    VERROR_INT("xmlSchemaVAttributesComplex",
25395			"calling xmlSchemaCopyValue()");
25396		    goto internal_error;
25397		}
25398	    }
25399	    /*
25400	    * PSVI: Add the default attribute to the current element.
25401	    * VAL TODO: Should we use the *normalized* value? This currently
25402	    *   uses the *initial* value.
25403	    */
25404
25405	    if (defAttrOwnerElem) {
25406		xmlChar *normValue;
25407		const xmlChar *value;
25408
25409		value = iattr->value;
25410		/*
25411		* Normalize the value.
25412		*/
25413		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25414		    iattr->value);
25415		if (normValue != NULL)
25416		    value = BAD_CAST normValue;
25417
25418		if (iattr->nsName == NULL) {
25419		    if (xmlNewProp(defAttrOwnerElem,
25420			iattr->localName, value) == NULL) {
25421			VERROR_INT("xmlSchemaVAttributesComplex",
25422			    "callling xmlNewProp()");
25423			if (normValue != NULL)
25424			    xmlFree(normValue);
25425			goto internal_error;
25426		    }
25427		} else {
25428		    xmlNsPtr ns;
25429
25430		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25431			defAttrOwnerElem, iattr->nsName);
25432		    if (ns == NULL) {
25433			xmlChar prefix[12];
25434			int counter = 0;
25435
25436			/*
25437			* Create a namespace declaration on the validation
25438			* root node if no namespace declaration is in scope.
25439			*/
25440			do {
25441			    snprintf((char *) prefix, 12, "p%d", counter++);
25442			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25443				defAttrOwnerElem, BAD_CAST prefix);
25444			    if (counter > 1000) {
25445				VERROR_INT(
25446				    "xmlSchemaVAttributesComplex",
25447				    "could not compute a ns prefix for a "
25448				    "default/fixed attribute");
25449				if (normValue != NULL)
25450				    xmlFree(normValue);
25451				goto internal_error;
25452			    }
25453			} while (ns != NULL);
25454			ns = xmlNewNs(vctxt->validationRoot,
25455			    iattr->nsName, BAD_CAST prefix);
25456		    }
25457		    /*
25458		    * TODO:
25459		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25460		    * If we have QNames: do we need to ensure there's a
25461		    * prefix defined for the QName?
25462		    */
25463		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25464		}
25465		if (normValue != NULL)
25466		    xmlFree(normValue);
25467	    }
25468	    /*
25469	    * Go directly to IDC evaluation.
25470	    */
25471	    goto eval_idcs;
25472	}
25473	/*
25474	* Validate the value.
25475	*/
25476	if (vctxt->value != NULL) {
25477	    /*
25478	    * Free last computed value; just for safety reasons.
25479	    */
25480	    xmlSchemaFreeValue(vctxt->value);
25481	    vctxt->value = NULL;
25482	}
25483	/*
25484	* Note that the attribute *use* can be unavailable, if
25485	* the attribute was a wild attribute.
25486	*/
25487	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25488	    ((iattr->use != NULL) &&
25489	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25490	    fixed = 1;
25491	else
25492	    fixed = 0;
25493	/*
25494	* SPEC (cvc-attribute)
25495	* (3) "The item's �normalized value� must be locally �valid�
25496	* with respect to that {type definition} as per
25497	* String Valid (�3.14.4)."
25498	*
25499	* VAL TODO: Do we already have the
25500	* "normalized attribute value" here?
25501	*/
25502	if (xpathRes || fixed) {
25503	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25504	    /*
25505	    * Request a computed value.
25506	    */
25507	    res = xmlSchemaVCheckCVCSimpleType(
25508		ACTXT_CAST vctxt,
25509		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25510		1, 1, 0);
25511	} else {
25512	    res = xmlSchemaVCheckCVCSimpleType(
25513		ACTXT_CAST vctxt,
25514		iattr->node, iattr->typeDef, iattr->value, NULL,
25515		1, 0, 0);
25516	}
25517
25518	if (res != 0) {
25519	    if (res == -1) {
25520		VERROR_INT("xmlSchemaVAttributesComplex",
25521		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25522		goto internal_error;
25523	    }
25524	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25525	    /*
25526	    * SPEC PSVI Assessment Outcome (Attribute)
25527	    * [validity] = "invalid"
25528	    */
25529	    goto eval_idcs;
25530	}
25531
25532	if (fixed) {
25533	    /*
25534	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25535	    * "For an attribute information item to be�valid�
25536	    * with respect to an attribute use its *normalized*
25537	    * value� must match the *canonical* lexical
25538	    * representation of the attribute use's {value
25539	    * constraint}value, if it is present and fixed."
25540	    *
25541	    * VAL TODO: The requirement for the *canonical* value
25542	    * will be removed in XML Schema 1.1.
25543	    */
25544	    /*
25545	    * SPEC Attribute Locally Valid (cvc-attribute)
25546	    * (4) "The item's *actual* value� must match the *value* of
25547	    * the {value constraint}, if it is present and fixed."
25548	    */
25549	    if (iattr->val == NULL) {
25550		/* VAL TODO: A value was not precomputed. */
25551		TODO
25552		goto eval_idcs;
25553	    }
25554	    if ((iattr->use != NULL) &&
25555		(iattr->use->defValue != NULL)) {
25556		if (iattr->use->defVal == NULL) {
25557		    /* VAL TODO: A default value was not precomputed. */
25558		    TODO
25559		    goto eval_idcs;
25560		}
25561		iattr->vcValue = iattr->use->defValue;
25562		/*
25563		if (xmlSchemaCompareValuesWhtsp(attr->val,
25564		    (xmlSchemaWhitespaceValueType) ws,
25565		    attr->use->defVal,
25566		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25567		*/
25568		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25569		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25570	    } else {
25571		if (iattr->decl->defVal == NULL) {
25572		    /* VAL TODO: A default value was not precomputed. */
25573		    TODO
25574		    goto eval_idcs;
25575		}
25576		iattr->vcValue = iattr->decl->defValue;
25577		/*
25578		if (xmlSchemaCompareValuesWhtsp(attr->val,
25579		    (xmlSchemaWhitespaceValueType) ws,
25580		    attrDecl->defVal,
25581		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25582		*/
25583		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25584		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25585	    }
25586	    /*
25587	    * [validity] = "valid"
25588	    */
25589	}
25590eval_idcs:
25591	/*
25592	* Evaluate IDCs.
25593	*/
25594	if (xpathRes) {
25595	    if (xmlSchemaXPathProcessHistory(vctxt,
25596		vctxt->depth +1) == -1) {
25597		VERROR_INT("xmlSchemaVAttributesComplex",
25598		    "calling xmlSchemaXPathEvaluate()");
25599		goto internal_error;
25600	    }
25601	} else if (vctxt->xpathStates != NULL)
25602	    xmlSchemaXPathPop(vctxt);
25603    }
25604
25605    /*
25606    * Report errors.
25607    */
25608    for (i = 0; i < vctxt->nbAttrInfos; i++) {
25609	iattr = vctxt->attrInfos[i];
25610	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25611	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25612	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25613	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25614	    continue;
25615	ACTIVATE_ATTRIBUTE(iattr);
25616	switch (iattr->state) {
25617	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25618		    xmlChar *str = NULL;
25619		    ACTIVATE_ELEM;
25620		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25621			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25622			"The attribute '%s' is required but missing",
25623			xmlSchemaFormatQName(&str,
25624			    iattr->decl->targetNamespace,
25625			    iattr->decl->name),
25626			NULL);
25627		    FREE_AND_NULL(str)
25628		    break;
25629		}
25630	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25631		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25632		    "The type definition is absent");
25633		break;
25634	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25635		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25636		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25637		    "The value '%s' does not match the fixed "
25638		    "value constraint '%s'",
25639		    iattr->value, iattr->vcValue);
25640		break;
25641	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25642		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25643		    "No matching global attribute declaration available, but "
25644		    "demanded by the strict wildcard");
25645		break;
25646	    case XML_SCHEMAS_ATTR_UNKNOWN:
25647		if (iattr->metaType)
25648		    break;
25649		/*
25650		* MAYBE VAL TODO: One might report different error messages
25651		* for the following errors.
25652		*/
25653		if (type->attributeWildcard == NULL) {
25654		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25655			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25656		} else {
25657		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25658			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25659		}
25660		break;
25661	    default:
25662		break;
25663	}
25664    }
25665
25666    ACTIVATE_ELEM;
25667    return (0);
25668internal_error:
25669    ACTIVATE_ELEM;
25670    return (-1);
25671}
25672
25673static int
25674xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25675			      int *skip)
25676{
25677    xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25678    /*
25679    * The namespace of the element was already identified to be
25680    * matching the wildcard.
25681    */
25682    if ((skip == NULL) || (wild == NULL) ||
25683	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25684	VERROR_INT("xmlSchemaValidateElemWildcard",
25685	    "bad arguments");
25686	return (-1);
25687    }
25688    *skip = 0;
25689    if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25690	/*
25691	* URGENT VAL TODO: Either we need to position the stream to the
25692	* next sibling, or walk the whole subtree.
25693	*/
25694	*skip = 1;
25695	return (0);
25696    }
25697    {
25698	xmlSchemaElementPtr decl = NULL;
25699
25700	decl = xmlSchemaGetElem(vctxt->schema,
25701	    vctxt->inode->localName, vctxt->inode->nsName);
25702	if (decl != NULL) {
25703	    vctxt->inode->decl = decl;
25704	    return (0);
25705	}
25706    }
25707    if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25708	/* VAL TODO: Change to proper error code. */
25709	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25710	    "No matching global element declaration available, but "
25711	    "demanded by the strict wildcard");
25712	return (vctxt->err);
25713    }
25714    if (vctxt->nbAttrInfos != 0) {
25715	xmlSchemaAttrInfoPtr iattr;
25716	/*
25717	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25718	* (1.2.1.2.1) - (1.2.1.2.3 )
25719	*
25720	* Use the xsi:type attribute for the type definition.
25721	*/
25722	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25723	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25724	if (iattr != NULL) {
25725	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25726		&(vctxt->inode->typeDef), NULL) == -1) {
25727		VERROR_INT("xmlSchemaValidateElemWildcard",
25728		    "calling xmlSchemaProcessXSIType() to "
25729		    "process the attribute 'xsi:nil'");
25730		return (-1);
25731	    }
25732	    /*
25733	    * Don't return an error on purpose.
25734	    */
25735	    return (0);
25736	}
25737    }
25738    /*
25739    * SPEC Validation Rule: Schema-Validity Assessment (Element)
25740    *
25741    * Fallback to "anyType".
25742    */
25743    vctxt->inode->typeDef =
25744	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25745    return (0);
25746}
25747
25748/*
25749* xmlSchemaCheckCOSValidDefault:
25750*
25751* This will be called if: not nilled, no content and a default/fixed
25752* value is provided.
25753*/
25754
25755static int
25756xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25757			      const xmlChar *value,
25758			      xmlSchemaValPtr *val)
25759{
25760    int ret = 0;
25761    xmlSchemaNodeInfoPtr inode = vctxt->inode;
25762
25763    /*
25764    * cos-valid-default:
25765    * Schema Component Constraint: Element Default Valid (Immediate)
25766    * For a string to be a valid default with respect to a type
25767    * definition the appropriate case among the following must be true:
25768    */
25769    if WXS_IS_COMPLEX(inode->typeDef) {
25770	/*
25771	* Complex type.
25772	*
25773	* SPEC (2.1) "its {content type} must be a simple type definition
25774	* or mixed."
25775	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25776	* type}'s particle must be �emptiable� as defined by
25777	* Particle Emptiable (�3.9.6)."
25778	*/
25779	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25780	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25781	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25782	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25783	    /* NOTE that this covers (2.2.2) as well. */
25784	    VERROR(ret, NULL,
25785		"For a string to be a valid default, the type definition "
25786		"must be a simple type or a complex type with simple content "
25787		"or mixed content and a particle emptiable");
25788	    return(ret);
25789	}
25790    }
25791    /*
25792    * 1 If the type definition is a simple type definition, then the string
25793    * must be �valid� with respect to that definition as defined by String
25794    * Valid (�3.14.4).
25795    *
25796    * AND
25797    *
25798    * 2.2.1 If the {content type} is a simple type definition, then the
25799    * string must be �valid� with respect to that simple type definition
25800    * as defined by String Valid (�3.14.4).
25801    */
25802    if (WXS_IS_SIMPLE(inode->typeDef)) {
25803
25804	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25805	    NULL, inode->typeDef, value, val, 1, 1, 0);
25806
25807    } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25808
25809	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25810	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25811    }
25812    if (ret < 0) {
25813	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25814	    "calling xmlSchemaVCheckCVCSimpleType()");
25815    }
25816    return (ret);
25817}
25818
25819static void
25820xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25821			       const xmlChar * name ATTRIBUTE_UNUSED,
25822			       xmlSchemaElementPtr item,
25823			       xmlSchemaNodeInfoPtr inode)
25824{
25825    inode->decl = item;
25826#ifdef DEBUG_CONTENT
25827    {
25828	xmlChar *str = NULL;
25829
25830	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25831	    xmlGenericError(xmlGenericErrorContext,
25832		"AUTOMATON callback for '%s' [declaration]\n",
25833		xmlSchemaFormatQName(&str,
25834		inode->localName, inode->nsName));
25835	} else {
25836	    xmlGenericError(xmlGenericErrorContext,
25837		    "AUTOMATON callback for '%s' [wildcard]\n",
25838		    xmlSchemaFormatQName(&str,
25839		    inode->localName, inode->nsName));
25840
25841	}
25842	FREE_AND_NULL(str)
25843    }
25844#endif
25845}
25846
25847static int
25848xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25849{
25850    vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25851    if (vctxt->inode == NULL) {
25852	VERROR_INT("xmlSchemaValidatorPushElem",
25853	    "calling xmlSchemaGetFreshElemInfo()");
25854	return (-1);
25855    }
25856    vctxt->nbAttrInfos = 0;
25857    return (0);
25858}
25859
25860static int
25861xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25862			     xmlSchemaNodeInfoPtr inode,
25863			     xmlSchemaTypePtr type,
25864			     const xmlChar *value)
25865{
25866    if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25867	return (xmlSchemaVCheckCVCSimpleType(
25868	    ACTXT_CAST vctxt, NULL,
25869	    type, value, &(inode->val), 1, 1, 0));
25870    else
25871	return (xmlSchemaVCheckCVCSimpleType(
25872	    ACTXT_CAST vctxt, NULL,
25873	    type, value, NULL, 1, 0, 0));
25874}
25875
25876
25877
25878/*
25879* Process END of element.
25880*/
25881static int
25882xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25883{
25884    int ret = 0;
25885    xmlSchemaNodeInfoPtr inode = vctxt->inode;
25886
25887    if (vctxt->nbAttrInfos != 0)
25888	xmlSchemaClearAttrInfos(vctxt);
25889    if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25890	/*
25891	* This element was not expected;
25892	* we will not validate child elements of broken parents.
25893	* Skip validation of all content of the parent.
25894	*/
25895	vctxt->skipDepth = vctxt->depth -1;
25896	goto end_elem;
25897    }
25898    if ((inode->typeDef == NULL) ||
25899	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25900	/*
25901	* 1. the type definition might be missing if the element was
25902	*    error prone
25903	* 2. it might be abstract.
25904	*/
25905	goto end_elem;
25906    }
25907    /*
25908    * Check the content model.
25909    */
25910    if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25911	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25912
25913	/*
25914	* Workaround for "anyType".
25915	*/
25916	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25917	    goto character_content;
25918
25919	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25920	    xmlChar *values[10];
25921	    int terminal, nbval = 10, nbneg;
25922
25923	    if (inode->regexCtxt == NULL) {
25924		/*
25925		* Create the regex context.
25926		*/
25927		inode->regexCtxt =
25928		    xmlRegNewExecCtxt(inode->typeDef->contModel,
25929		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25930		    vctxt);
25931		if (inode->regexCtxt == NULL) {
25932		    VERROR_INT("xmlSchemaValidatorPopElem",
25933			"failed to create a regex context");
25934		    goto internal_error;
25935		}
25936#ifdef DEBUG_AUTOMATA
25937		xmlGenericError(xmlGenericErrorContext,
25938		    "AUTOMATON create on '%s'\n", inode->localName);
25939#endif
25940	    }
25941	    /*
25942	    * Get hold of the still expected content, since a further
25943	    * call to xmlRegExecPushString() will loose this information.
25944	    */
25945	    xmlRegExecNextValues(inode->regexCtxt,
25946		&nbval, &nbneg, &values[0], &terminal);
25947	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25948	    if (ret <= 0) {
25949		/*
25950		* Still missing something.
25951		*/
25952		ret = 1;
25953		inode->flags |=
25954		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
25955		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
25956		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25957		    "Missing child element(s)",
25958		    nbval, nbneg, values);
25959#ifdef DEBUG_AUTOMATA
25960		xmlGenericError(xmlGenericErrorContext,
25961		    "AUTOMATON missing ERROR on '%s'\n",
25962		    inode->localName);
25963#endif
25964	    } else {
25965		/*
25966		* Content model is satisfied.
25967		*/
25968		ret = 0;
25969#ifdef DEBUG_AUTOMATA
25970		xmlGenericError(xmlGenericErrorContext,
25971		    "AUTOMATON succeeded on '%s'\n",
25972		    inode->localName);
25973#endif
25974	    }
25975
25976	}
25977    }
25978    if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25979	goto end_elem;
25980
25981character_content:
25982
25983    if (vctxt->value != NULL) {
25984	xmlSchemaFreeValue(vctxt->value);
25985	vctxt->value = NULL;
25986    }
25987    /*
25988    * Check character content.
25989    */
25990    if (inode->decl == NULL) {
25991	/*
25992	* Speedup if no declaration exists.
25993	*/
25994	if (WXS_IS_SIMPLE(inode->typeDef)) {
25995	    ret = xmlSchemaVCheckINodeDataType(vctxt,
25996		inode, inode->typeDef, inode->value);
25997	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25998	    ret = xmlSchemaVCheckINodeDataType(vctxt,
25999		inode, inode->typeDef->contentTypeDef,
26000		inode->value);
26001	}
26002	if (ret < 0) {
26003	    VERROR_INT("xmlSchemaValidatorPopElem",
26004		"calling xmlSchemaVCheckCVCSimpleType()");
26005	    goto internal_error;
26006	}
26007	goto end_elem;
26008    }
26009    /*
26010    * cvc-elt (3.3.4) : 5
26011    * The appropriate case among the following must be true:
26012    */
26013    /*
26014    * cvc-elt (3.3.4) : 5.1
26015    * If the declaration has a {value constraint},
26016    * the item has neither element nor character [children] and
26017    * clause 3.2 has not applied, then all of the following must be true:
26018    */
26019    if ((inode->decl->value != NULL) &&
26020	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26021	(! INODE_NILLED(inode))) {
26022	/*
26023	* cvc-elt (3.3.4) : 5.1.1
26024	* If the �actual type definition� is a �local type definition�
26025	* then the canonical lexical representation of the {value constraint}
26026	* value must be a valid default for the �actual type definition� as
26027	* defined in Element Default Valid (Immediate) (�3.3.6).
26028	*/
26029	/*
26030	* NOTE: 'local' above means types acquired by xsi:type.
26031	* NOTE: Although the *canonical* value is stated, it is not
26032	* relevant if canonical or not. Additionally XML Schema 1.1
26033	* will removed this requirement as well.
26034	*/
26035	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26036
26037	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26038		inode->decl->value, &(inode->val));
26039	    if (ret != 0) {
26040		if (ret < 0) {
26041		    VERROR_INT("xmlSchemaValidatorPopElem",
26042			"calling xmlSchemaCheckCOSValidDefault()");
26043		    goto internal_error;
26044		}
26045		goto end_elem;
26046	    }
26047	    /*
26048	    * Stop here, to avoid redundant validation of the value
26049	    * (see following).
26050	    */
26051	    goto default_psvi;
26052	}
26053	/*
26054	* cvc-elt (3.3.4) : 5.1.2
26055	* The element information item with the canonical lexical
26056	* representation of the {value constraint} value used as its
26057	* �normalized value� must be �valid� with respect to the
26058	* �actual type definition� as defined by Element Locally Valid (Type)
26059	* (�3.3.4).
26060	*/
26061	if (WXS_IS_SIMPLE(inode->typeDef)) {
26062	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26063		inode, inode->typeDef, inode->decl->value);
26064	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26065	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26066		inode, inode->typeDef->contentTypeDef,
26067		inode->decl->value);
26068	}
26069	if (ret != 0) {
26070	    if (ret < 0) {
26071		VERROR_INT("xmlSchemaValidatorPopElem",
26072		    "calling xmlSchemaVCheckCVCSimpleType()");
26073		goto internal_error;
26074	    }
26075	    goto end_elem;
26076	}
26077
26078default_psvi:
26079	/*
26080	* PSVI: Create a text node on the instance element.
26081	*/
26082	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26083	    (inode->node != NULL)) {
26084	    xmlNodePtr textChild;
26085	    xmlChar *normValue;
26086	    /*
26087	    * VAL TODO: Normalize the value.
26088	    */
26089	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26090		inode->decl->value);
26091	    if (normValue != NULL) {
26092		textChild = xmlNewText(BAD_CAST normValue);
26093		xmlFree(normValue);
26094	    } else
26095		textChild = xmlNewText(inode->decl->value);
26096	    if (textChild == NULL) {
26097		VERROR_INT("xmlSchemaValidatorPopElem",
26098		    "calling xmlNewText()");
26099		goto internal_error;
26100	    } else
26101		xmlAddChild(inode->node, textChild);
26102	}
26103
26104    } else if (! INODE_NILLED(inode)) {
26105	/*
26106	* 5.2.1 The element information item must be �valid� with respect
26107	* to the �actual type definition� as defined by Element Locally
26108	* Valid (Type) (�3.3.4).
26109	*/
26110	if (WXS_IS_SIMPLE(inode->typeDef)) {
26111	     /*
26112	    * SPEC (cvc-type) (3.1)
26113	    * "If the type definition is a simple type definition, ..."
26114	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26115	    * (Element) (�3.3.4) did not apply, then the �normalized value�
26116	    * must be �valid� with respect to the type definition as defined
26117	    * by String Valid (�3.14.4).
26118	    */
26119	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26120		    inode, inode->typeDef, inode->value);
26121	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26122	    /*
26123	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26124	    * definition, then the element information item must be
26125	    * �valid� with respect to the type definition as per
26126	    * Element Locally Valid (Complex Type) (�3.4.4);"
26127	    *
26128	    * SPEC (cvc-complex-type) (2.2)
26129	    * "If the {content type} is a simple type definition, ...
26130	    * the �normalized value� of the element information item is
26131	    * �valid� with respect to that simple type definition as
26132	    * defined by String Valid (�3.14.4)."
26133	    */
26134	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26135		inode, inode->typeDef->contentTypeDef, inode->value);
26136	}
26137	if (ret != 0) {
26138	    if (ret < 0) {
26139		VERROR_INT("xmlSchemaValidatorPopElem",
26140		    "calling xmlSchemaVCheckCVCSimpleType()");
26141		goto internal_error;
26142	    }
26143	    goto end_elem;
26144	}
26145	/*
26146	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26147	* not applied, all of the following must be true:
26148	*/
26149	if ((inode->decl->value != NULL) &&
26150	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26151
26152	    /*
26153	    * TODO: We will need a computed value, when comparison is
26154	    * done on computed values.
26155	    */
26156	    /*
26157	    * 5.2.2.1 The element information item must have no element
26158	    * information item [children].
26159	    */
26160	    if (inode->flags &
26161		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26162		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26163		VERROR(ret, NULL,
26164		    "The content must not containt element nodes since "
26165		    "there is a fixed value constraint");
26166		goto end_elem;
26167	    } else {
26168		/*
26169		* 5.2.2.2 The appropriate case among the following must
26170		* be true:
26171		*/
26172		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26173		    /*
26174		    * 5.2.2.2.1 If the {content type} of the �actual type
26175		    * definition� is mixed, then the *initial value* of the
26176		    * item must match the canonical lexical representation
26177		    * of the {value constraint} value.
26178		    *
26179		    * ... the *initial value* of an element information
26180		    * item is the string composed of, in order, the
26181		    * [character code] of each character information item in
26182		    * the [children] of that element information item.
26183		    */
26184		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26185			/*
26186			* VAL TODO: Report invalid & expected values as well.
26187			* VAL TODO: Implement the canonical stuff.
26188			*/
26189			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26190			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26191			    ret, NULL, NULL,
26192			    "The initial value '%s' does not match the fixed "
26193			    "value constraint '%s'",
26194			    inode->value, inode->decl->value);
26195			goto end_elem;
26196		    }
26197		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26198		    /*
26199		    * 5.2.2.2.2 If the {content type} of the �actual type
26200		    * definition� is a simple type definition, then the
26201		    * *actual value* of the item must match the canonical
26202		    * lexical representation of the {value constraint} value.
26203		    */
26204		    /*
26205		    * VAL TODO: *actual value* is the normalized value, impl.
26206		    *           this.
26207		    * VAL TODO: Report invalid & expected values as well.
26208		    * VAL TODO: Implement a comparison with the computed values.
26209		    */
26210		    if (! xmlStrEqual(inode->value,
26211			    inode->decl->value)) {
26212			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26213			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26214			    ret, NULL, NULL,
26215			    "The actual value '%s' does not match the fixed "
26216			    "value constraint '%s'",
26217			    inode->value,
26218			    inode->decl->value);
26219			goto end_elem;
26220		    }
26221		}
26222	    }
26223	}
26224    }
26225
26226end_elem:
26227    if (vctxt->depth < 0) {
26228	/* TODO: raise error? */
26229	return (0);
26230    }
26231    if (vctxt->depth == vctxt->skipDepth)
26232	vctxt->skipDepth = -1;
26233    /*
26234    * Evaluate the history of XPath state objects.
26235    */
26236    if (inode->appliedXPath &&
26237	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26238	goto internal_error;
26239    /*
26240    * MAYBE TODO:
26241    * SPEC (6) "The element information item must be �valid� with
26242    * respect to each of the {identity-constraint definitions} as per
26243    * Identity-constraint Satisfied (�3.11.4)."
26244    */
26245    /*
26246    * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26247    *   need to be built in any case.
26248    *   We will currently build IDC node-tables and bubble them only if
26249    *   keyrefs do exist.
26250    */
26251
26252    /*
26253    * Add the current IDC target-nodes to the IDC node-tables.
26254    */
26255    if ((inode->idcMatchers != NULL) &&
26256	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26257    {
26258	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26259	    goto internal_error;
26260    }
26261    /*
26262    * Validate IDC keyrefs.
26263    */
26264    if (vctxt->inode->hasKeyrefs)
26265	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26266	    goto internal_error;
26267    /*
26268    * Merge/free the IDC table.
26269    */
26270    if (inode->idcTable != NULL) {
26271#ifdef DEBUG_IDC_NODE_TABLE
26272	xmlSchemaDebugDumpIDCTable(stdout,
26273	    inode->nsName,
26274	    inode->localName,
26275	    inode->idcTable);
26276#endif
26277	if ((vctxt->depth > 0) &&
26278	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26279	{
26280	    /*
26281	    * Merge the IDC node table with the table of the parent node.
26282	    */
26283	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26284		goto internal_error;
26285	}
26286    }
26287    /*
26288    * Clear the current ielem.
26289    * VAL TODO: Don't free the PSVI IDC tables if they are
26290    * requested for the PSVI.
26291    */
26292    xmlSchemaClearElemInfo(vctxt, inode);
26293    /*
26294    * Skip further processing if we are on the validation root.
26295    */
26296    if (vctxt->depth == 0) {
26297	vctxt->depth--;
26298	vctxt->inode = NULL;
26299	return (0);
26300    }
26301    /*
26302    * Reset the keyrefDepth if needed.
26303    */
26304    if (vctxt->aidcs != NULL) {
26305	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26306	do {
26307	    if (aidc->keyrefDepth == vctxt->depth) {
26308		/*
26309		* A 'keyrefDepth' of a key/unique IDC matches the current
26310		* depth, this means that we are leaving the scope of the
26311		* top-most keyref IDC which refers to this IDC.
26312		*/
26313		aidc->keyrefDepth = -1;
26314	    }
26315	    aidc = aidc->next;
26316	} while (aidc != NULL);
26317    }
26318    vctxt->depth--;
26319    vctxt->inode = vctxt->elemInfos[vctxt->depth];
26320    /*
26321    * VAL TODO: 7 If the element information item is the �validation root�, it must be
26322    * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26323    */
26324    return (ret);
26325
26326internal_error:
26327    vctxt->err = -1;
26328    return (-1);
26329}
26330
26331/*
26332* 3.4.4 Complex Type Definition Validation Rules
26333* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26334*/
26335static int
26336xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26337{
26338    xmlSchemaNodeInfoPtr pielem;
26339    xmlSchemaTypePtr ptype;
26340    int ret = 0;
26341
26342    if (vctxt->depth <= 0) {
26343	VERROR_INT("xmlSchemaValidateChildElem",
26344	    "not intended for the validation root");
26345	return (-1);
26346    }
26347    pielem = vctxt->elemInfos[vctxt->depth -1];
26348    if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26349	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26350    /*
26351    * Handle 'nilled' elements.
26352    */
26353    if (INODE_NILLED(pielem)) {
26354	/*
26355	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26356	*/
26357	ACTIVATE_PARENT_ELEM;
26358	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26359	VERROR(ret, NULL,
26360	    "Neither character nor element content is allowed, "
26361	    "because the element was 'nilled'");
26362	ACTIVATE_ELEM;
26363	goto unexpected_elem;
26364    }
26365
26366    ptype = pielem->typeDef;
26367
26368    if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26369	/*
26370	* Workaround for "anyType": we have currently no content model
26371	* assigned for "anyType", so handle it explicitely.
26372	* "anyType" has an unbounded, lax "any" wildcard.
26373	*/
26374	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26375	    vctxt->inode->localName,
26376	    vctxt->inode->nsName);
26377
26378	if (vctxt->inode->decl == NULL) {
26379	    xmlSchemaAttrInfoPtr iattr;
26380	    /*
26381	    * Process "xsi:type".
26382	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26383	    */
26384	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26385		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26386	    if (iattr != NULL) {
26387		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26388		    &(vctxt->inode->typeDef), NULL);
26389		if (ret != 0) {
26390		    if (ret == -1) {
26391			VERROR_INT("xmlSchemaValidateChildElem",
26392			    "calling xmlSchemaProcessXSIType() to "
26393			    "process the attribute 'xsi:nil'");
26394			return (-1);
26395		    }
26396		    return (ret);
26397		}
26398	    } else {
26399		 /*
26400		 * Fallback to "anyType".
26401		 *
26402		 * SPEC (cvc-assess-elt)
26403		 * "If the item cannot be �strictly assessed�, [...]
26404		 * an element information item's schema validity may be laxly
26405		 * assessed if its �context-determined declaration� is not
26406		 * skip by �validating� with respect to the �ur-type
26407		 * definition� as per Element Locally Valid (Type) (�3.3.4)."
26408		*/
26409		vctxt->inode->typeDef =
26410		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26411	    }
26412	}
26413	return (0);
26414    }
26415
26416    switch (ptype->contentType) {
26417	case XML_SCHEMA_CONTENT_EMPTY:
26418	    /*
26419	    * SPEC (2.1) "If the {content type} is empty, then the
26420	    * element information item has no character or element
26421	    * information item [children]."
26422	    */
26423	    ACTIVATE_PARENT_ELEM
26424	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26425	    VERROR(ret, NULL,
26426		"Element content is not allowed, "
26427		"because the content type is empty");
26428	    ACTIVATE_ELEM
26429	    goto unexpected_elem;
26430	    break;
26431
26432	case XML_SCHEMA_CONTENT_MIXED:
26433        case XML_SCHEMA_CONTENT_ELEMENTS: {
26434	    xmlRegExecCtxtPtr regexCtxt;
26435	    xmlChar *values[10];
26436	    int terminal, nbval = 10, nbneg;
26437
26438	    /* VAL TODO: Optimized "anyType" validation.*/
26439
26440	    if (ptype->contModel == NULL) {
26441		VERROR_INT("xmlSchemaValidateChildElem",
26442		    "type has elem content but no content model");
26443		return (-1);
26444	    }
26445	    /*
26446	    * Safety belf for evaluation if the cont. model was already
26447	    * examined to be invalid.
26448	    */
26449	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26450		VERROR_INT("xmlSchemaValidateChildElem",
26451		    "validating elem, but elem content is already invalid");
26452		return (-1);
26453	    }
26454
26455	    regexCtxt = pielem->regexCtxt;
26456	    if (regexCtxt == NULL) {
26457		/*
26458		* Create the regex context.
26459		*/
26460		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26461		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26462		    vctxt);
26463		if (regexCtxt == NULL) {
26464		    VERROR_INT("xmlSchemaValidateChildElem",
26465			"failed to create a regex context");
26466		    return (-1);
26467		}
26468		pielem->regexCtxt = regexCtxt;
26469#ifdef DEBUG_AUTOMATA
26470		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26471		    pielem->localName);
26472#endif
26473	    }
26474
26475	    /*
26476	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26477	    * then the sequence of the element information item's
26478	    * element information item [children], if any, taken in
26479	    * order, is �valid� with respect to the {content type}'s
26480	    * particle, as defined in Element Sequence Locally Valid
26481	    * (Particle) (�3.9.4)."
26482	    */
26483	    ret = xmlRegExecPushString2(regexCtxt,
26484		vctxt->inode->localName,
26485		vctxt->inode->nsName,
26486		vctxt->inode);
26487#ifdef DEBUG_AUTOMATA
26488	    if (ret < 0)
26489		xmlGenericError(xmlGenericErrorContext,
26490		"AUTOMATON push ERROR for '%s' on '%s'\n",
26491		vctxt->inode->localName, pielem->localName);
26492	    else
26493		xmlGenericError(xmlGenericErrorContext,
26494		"AUTOMATON push OK for '%s' on '%s'\n",
26495		vctxt->inode->localName, pielem->localName);
26496#endif
26497	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26498		VERROR_INT("xmlSchemaValidateChildElem",
26499		    "calling xmlRegExecPushString2()");
26500		return (-1);
26501	    }
26502	    if (ret < 0) {
26503		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26504		    &values[0], &terminal);
26505		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26506		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26507		    "This element is not expected",
26508		    nbval, nbneg, values);
26509		ret = vctxt->err;
26510		goto unexpected_elem;
26511	    } else
26512		ret = 0;
26513	}
26514	    break;
26515	case XML_SCHEMA_CONTENT_SIMPLE:
26516	case XML_SCHEMA_CONTENT_BASIC:
26517	    ACTIVATE_PARENT_ELEM
26518	    if (WXS_IS_COMPLEX(ptype)) {
26519		/*
26520		* SPEC (cvc-complex-type) (2.2)
26521		* "If the {content type} is a simple type definition, then
26522		* the element information item has no element information
26523		* item [children], ..."
26524		*/
26525		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26526		VERROR(ret, NULL, "Element content is not allowed, "
26527		    "because the content type is a simple type definition");
26528	    } else {
26529		/*
26530		* SPEC (cvc-type) (3.1.2) "The element information item must
26531		* have no element information item [children]."
26532		*/
26533		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26534		VERROR(ret, NULL, "Element content is not allowed, "
26535		    "because the type definition is simple");
26536	    }
26537	    ACTIVATE_ELEM
26538	    ret = vctxt->err;
26539	    goto unexpected_elem;
26540	    break;
26541
26542	default:
26543	    break;
26544    }
26545    return (ret);
26546unexpected_elem:
26547    /*
26548    * Pop this element and set the skipDepth to skip
26549    * all further content of the parent element.
26550    */
26551    vctxt->skipDepth = vctxt->depth;
26552    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26553    pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26554    return (ret);
26555}
26556
26557#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26558#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26559#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26560
26561static int
26562xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26563		  int nodeType, const xmlChar *value, int len,
26564		  int mode, int *consumed)
26565{
26566    /*
26567    * Unfortunately we have to duplicate the text sometimes.
26568    * OPTIMIZE: Maybe we could skip it, if:
26569    *   1. content type is simple
26570    *   2. whitespace is "collapse"
26571    *   3. it consists of whitespace only
26572    *
26573    * Process character content.
26574    */
26575    if (consumed != NULL)
26576	*consumed = 0;
26577    if (INODE_NILLED(vctxt->inode)) {
26578	/*
26579	* SPEC cvc-elt (3.3.4 - 3.2.1)
26580	* "The element information item must have no character or
26581	* element information item [children]."
26582	*/
26583	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26584	    "Neither character nor element content is allowed "
26585	    "because the element is 'nilled'");
26586	return (vctxt->err);
26587    }
26588    /*
26589    * SPEC (2.1) "If the {content type} is empty, then the
26590    * element information item has no character or element
26591    * information item [children]."
26592    */
26593    if (vctxt->inode->typeDef->contentType ==
26594	    XML_SCHEMA_CONTENT_EMPTY) {
26595	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26596	    "Character content is not allowed, "
26597	    "because the content type is empty");
26598	return (vctxt->err);
26599    }
26600
26601    if (vctxt->inode->typeDef->contentType ==
26602	    XML_SCHEMA_CONTENT_ELEMENTS) {
26603	if ((nodeType != XML_TEXT_NODE) ||
26604	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26605	    /*
26606	    * SPEC cvc-complex-type (2.3)
26607	    * "If the {content type} is element-only, then the
26608	    * element information item has no character information
26609	    * item [children] other than those whose [character
26610	    * code] is defined as a white space in [XML 1.0 (Second
26611	    * Edition)]."
26612	    */
26613	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26614		"Character content other than whitespace is not allowed "
26615		"because the content type is 'element-only'");
26616	    return (vctxt->err);
26617	}
26618	return (0);
26619    }
26620
26621    if ((value == NULL) || (value[0] == 0))
26622	return (0);
26623    /*
26624    * Save the value.
26625    * NOTE that even if the content type is *mixed*, we need the
26626    * *initial value* for default/fixed value constraints.
26627    */
26628    if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26629	((vctxt->inode->decl == NULL) ||
26630	(vctxt->inode->decl->value == NULL)))
26631	return (0);
26632
26633    if (vctxt->inode->value == NULL) {
26634	/*
26635	* Set the value.
26636	*/
26637	switch (mode) {
26638	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26639		/*
26640		* When working on a tree.
26641		*/
26642		vctxt->inode->value = value;
26643		break;
26644	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26645		/*
26646		* When working with the reader.
26647		* The value will be freed by the element info.
26648		*/
26649		vctxt->inode->value = value;
26650		if (consumed != NULL)
26651		    *consumed = 1;
26652		vctxt->inode->flags |=
26653		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26654		break;
26655	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26656		/*
26657		* When working with SAX.
26658		* The value will be freed by the element info.
26659		*/
26660		if (len != -1)
26661		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26662		else
26663		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26664		vctxt->inode->flags |=
26665		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26666		break;
26667	    default:
26668		break;
26669	}
26670    } else {
26671	if (len < 0)
26672	    len = xmlStrlen(value);
26673	/*
26674	* Concat the value.
26675	*/
26676	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26677	    vctxt->inode->value = BAD_CAST xmlStrncat(
26678		(xmlChar *) vctxt->inode->value, value, len);
26679	} else {
26680	    vctxt->inode->value =
26681		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26682	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26683	}
26684    }
26685
26686    return (0);
26687}
26688
26689static int
26690xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26691{
26692    int ret = 0;
26693
26694    if ((vctxt->skipDepth != -1) &&
26695	(vctxt->depth >= vctxt->skipDepth)) {
26696	VERROR_INT("xmlSchemaValidateElem",
26697	    "in skip-state");
26698	goto internal_error;
26699    }
26700    if (vctxt->xsiAssemble) {
26701	/*
26702	* We will stop validation if there was an error during
26703	* dynamic schema construction.
26704	* Note that we simply set @skipDepth to 0, this could
26705	* mean that a streaming document via SAX would be
26706	* still read to the end but it won't be validated any more.
26707	* TODO: If we are sure how to stop the validation at once
26708	*   for all input scenarios, then this should be changed to
26709	*   instantly stop the validation.
26710	*/
26711	ret = xmlSchemaAssembleByXSI(vctxt);
26712	if (ret != 0) {
26713	    if (ret == -1)
26714		goto internal_error;
26715	    vctxt->skipDepth = 0;
26716	    return(ret);
26717	}
26718    }
26719    if (vctxt->depth > 0) {
26720	/*
26721	* Validate this element against the content model
26722	* of the parent.
26723	*/
26724	ret = xmlSchemaValidateChildElem(vctxt);
26725	if (ret != 0) {
26726	    if (ret < 0) {
26727		VERROR_INT("xmlSchemaValidateElem",
26728		    "calling xmlSchemaStreamValidateChildElement()");
26729		goto internal_error;
26730	    }
26731	    goto exit;
26732	}
26733	if (vctxt->depth == vctxt->skipDepth)
26734	    goto exit;
26735	if ((vctxt->inode->decl == NULL) &&
26736	    (vctxt->inode->typeDef == NULL)) {
26737	    VERROR_INT("xmlSchemaValidateElem",
26738		"the child element was valid but neither the "
26739		"declaration nor the type was set");
26740	    goto internal_error;
26741	}
26742    } else {
26743	/*
26744	* Get the declaration of the validation root.
26745	*/
26746	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26747	    vctxt->inode->localName,
26748	    vctxt->inode->nsName);
26749	if (vctxt->inode->decl == NULL) {
26750	    ret = XML_SCHEMAV_CVC_ELT_1;
26751	    VERROR(ret, NULL,
26752		"No matching global declaration available "
26753		"for the validation root");
26754	    goto exit;
26755	}
26756    }
26757
26758    if (vctxt->inode->decl == NULL)
26759	goto type_validation;
26760
26761    if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26762	int skip;
26763	/*
26764	* Wildcards.
26765	*/
26766	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26767	if (ret != 0) {
26768	    if (ret < 0) {
26769		VERROR_INT("xmlSchemaValidateElem",
26770		    "calling xmlSchemaValidateElemWildcard()");
26771		goto internal_error;
26772	    }
26773	    goto exit;
26774	}
26775	if (skip) {
26776	    vctxt->skipDepth = vctxt->depth;
26777	    goto exit;
26778	}
26779	/*
26780	* The declaration might be set by the wildcard validation,
26781	* when the processContents is "lax" or "strict".
26782	*/
26783	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26784	    /*
26785	    * Clear the "decl" field to not confuse further processing.
26786	    */
26787	    vctxt->inode->decl = NULL;
26788	    goto type_validation;
26789	}
26790    }
26791    /*
26792    * Validate against the declaration.
26793    */
26794    ret = xmlSchemaValidateElemDecl(vctxt);
26795    if (ret != 0) {
26796	if (ret < 0) {
26797	    VERROR_INT("xmlSchemaValidateElem",
26798		"calling xmlSchemaValidateElemDecl()");
26799	    goto internal_error;
26800	}
26801	goto exit;
26802    }
26803    /*
26804    * Validate against the type definition.
26805    */
26806type_validation:
26807
26808    if (vctxt->inode->typeDef == NULL) {
26809	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26810	ret = XML_SCHEMAV_CVC_TYPE_1;
26811    	VERROR(ret, NULL,
26812    	    "The type definition is absent");
26813	goto exit;
26814    }
26815    if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26816	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26817	ret = XML_SCHEMAV_CVC_TYPE_2;
26818    	    VERROR(ret, NULL,
26819    	    "The type definition is abstract");
26820	goto exit;
26821    }
26822    /*
26823    * Evaluate IDCs. Do it here, since new IDC matchers are registered
26824    * during validation against the declaration. This must be done
26825    * _before_ attribute validation.
26826    */
26827    if (vctxt->xpathStates != NULL) {
26828	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26829	vctxt->inode->appliedXPath = 1;
26830	if (ret == -1) {
26831	    VERROR_INT("xmlSchemaValidateElem",
26832		"calling xmlSchemaXPathEvaluate()");
26833	    goto internal_error;
26834	}
26835    }
26836    /*
26837    * Validate attributes.
26838    */
26839    if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26840	if ((vctxt->nbAttrInfos != 0) ||
26841	    (vctxt->inode->typeDef->attrUses != NULL)) {
26842
26843	    ret = xmlSchemaVAttributesComplex(vctxt);
26844	}
26845    } else if (vctxt->nbAttrInfos != 0) {
26846
26847	ret = xmlSchemaVAttributesSimple(vctxt);
26848    }
26849    /*
26850    * Clear registered attributes.
26851    */
26852    if (vctxt->nbAttrInfos != 0)
26853	xmlSchemaClearAttrInfos(vctxt);
26854    if (ret == -1) {
26855	VERROR_INT("xmlSchemaValidateElem",
26856	    "calling attributes validation");
26857	goto internal_error;
26858    }
26859    /*
26860    * Don't return an error if attributes are invalid on purpose.
26861    */
26862    ret = 0;
26863
26864exit:
26865    if (ret != 0)
26866	vctxt->skipDepth = vctxt->depth;
26867    return (ret);
26868internal_error:
26869    return (-1);
26870}
26871
26872#ifdef XML_SCHEMA_READER_ENABLED
26873static int
26874xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26875{
26876    const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26877    int depth, nodeType, ret = 0, consumed;
26878    xmlSchemaNodeInfoPtr ielem;
26879
26880    vctxt->depth = -1;
26881    ret = xmlTextReaderRead(vctxt->reader);
26882    /*
26883    * Move to the document element.
26884    */
26885    while (ret == 1) {
26886	nodeType = xmlTextReaderNodeType(vctxt->reader);
26887	if (nodeType == XML_ELEMENT_NODE)
26888	    goto root_found;
26889	ret = xmlTextReaderRead(vctxt->reader);
26890    }
26891    goto exit;
26892
26893root_found:
26894
26895    do {
26896	depth = xmlTextReaderDepth(vctxt->reader);
26897	nodeType = xmlTextReaderNodeType(vctxt->reader);
26898
26899	if (nodeType == XML_ELEMENT_NODE) {
26900
26901	    vctxt->depth++;
26902	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26903		VERROR_INT("xmlSchemaVReaderWalk",
26904		    "calling xmlSchemaValidatorPushElem()");
26905		goto internal_error;
26906	    }
26907	    ielem = vctxt->inode;
26908	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26909	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26910	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26911	    /*
26912	    * Is the element empty?
26913	    */
26914	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26915	    if (ret == -1) {
26916		VERROR_INT("xmlSchemaVReaderWalk",
26917		    "calling xmlTextReaderIsEmptyElement()");
26918		goto internal_error;
26919	    }
26920	    if (ret) {
26921		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26922	    }
26923	    /*
26924	    * Register attributes.
26925	    */
26926	    vctxt->nbAttrInfos = 0;
26927	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26928	    if (ret == -1) {
26929		VERROR_INT("xmlSchemaVReaderWalk",
26930		    "calling xmlTextReaderMoveToFirstAttribute()");
26931		goto internal_error;
26932	    }
26933	    if (ret == 1) {
26934		do {
26935		    /*
26936		    * VAL TODO: How do we know that the reader works on a
26937		    * node tree, to be able to pass a node here?
26938		    */
26939		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26940			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26941			xmlTextReaderNamespaceUri(vctxt->reader), 1,
26942			xmlTextReaderValue(vctxt->reader), 1) == -1) {
26943
26944			VERROR_INT("xmlSchemaVReaderWalk",
26945			    "calling xmlSchemaValidatorPushAttribute()");
26946			goto internal_error;
26947		    }
26948		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26949		    if (ret == -1) {
26950			VERROR_INT("xmlSchemaVReaderWalk",
26951			    "calling xmlTextReaderMoveToFirstAttribute()");
26952			goto internal_error;
26953		    }
26954		} while (ret == 1);
26955		/*
26956		* Back to element position.
26957		*/
26958		ret = xmlTextReaderMoveToElement(vctxt->reader);
26959		if (ret == -1) {
26960		    VERROR_INT("xmlSchemaVReaderWalk",
26961			"calling xmlTextReaderMoveToElement()");
26962		    goto internal_error;
26963		}
26964	    }
26965	    /*
26966	    * Validate the element.
26967	    */
26968	    ret= xmlSchemaValidateElem(vctxt);
26969	    if (ret != 0) {
26970		if (ret == -1) {
26971		    VERROR_INT("xmlSchemaVReaderWalk",
26972			"calling xmlSchemaValidateElem()");
26973		    goto internal_error;
26974		}
26975		goto exit;
26976	    }
26977	    if (vctxt->depth == vctxt->skipDepth) {
26978		int curDepth;
26979		/*
26980		* Skip all content.
26981		*/
26982		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
26983		    ret = xmlTextReaderRead(vctxt->reader);
26984		    curDepth = xmlTextReaderDepth(vctxt->reader);
26985		    while ((ret == 1) && (curDepth != depth)) {
26986			ret = xmlTextReaderRead(vctxt->reader);
26987			curDepth = xmlTextReaderDepth(vctxt->reader);
26988		    }
26989		    if (ret < 0) {
26990			/*
26991			* VAL TODO: A reader error occured; what to do here?
26992			*/
26993			ret = 1;
26994			goto exit;
26995		    }
26996		}
26997		goto leave_elem;
26998	    }
26999	    /*
27000	    * READER VAL TODO: Is an END_ELEM really never called
27001	    * if the elem is empty?
27002	    */
27003	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27004		goto leave_elem;
27005	} else if (nodeType == END_ELEM) {
27006	    /*
27007	    * Process END of element.
27008	    */
27009leave_elem:
27010	    ret = xmlSchemaValidatorPopElem(vctxt);
27011	    if (ret != 0) {
27012		if (ret < 0) {
27013		    VERROR_INT("xmlSchemaVReaderWalk",
27014			"calling xmlSchemaValidatorPopElem()");
27015		    goto internal_error;
27016		}
27017		goto exit;
27018	    }
27019	    if (vctxt->depth >= 0)
27020		ielem = vctxt->inode;
27021	    else
27022		ielem = NULL;
27023	} else if ((nodeType == XML_TEXT_NODE) ||
27024	    (nodeType == XML_CDATA_SECTION_NODE) ||
27025	    (nodeType == WHTSP) ||
27026	    (nodeType == SIGN_WHTSP)) {
27027	    /*
27028	    * Process character content.
27029	    */
27030	    xmlChar *value;
27031
27032	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27033		nodeType = XML_TEXT_NODE;
27034
27035	    value = xmlTextReaderValue(vctxt->reader);
27036	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27037		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27038	    if (! consumed)
27039		xmlFree(value);
27040	    if (ret == -1) {
27041		VERROR_INT("xmlSchemaVReaderWalk",
27042		    "calling xmlSchemaVPushText()");
27043		goto internal_error;
27044	    }
27045	} else if ((nodeType == XML_ENTITY_NODE) ||
27046	    (nodeType == XML_ENTITY_REF_NODE)) {
27047	    /*
27048	    * VAL TODO: What to do with entities?
27049	    */
27050	    TODO
27051	}
27052	/*
27053	* Read next node.
27054	*/
27055	ret = xmlTextReaderRead(vctxt->reader);
27056    } while (ret == 1);
27057
27058exit:
27059    return (ret);
27060internal_error:
27061    return (-1);
27062}
27063#endif
27064
27065/************************************************************************
27066 * 									*
27067 * 			SAX validation handlers				*
27068 * 									*
27069 ************************************************************************/
27070
27071/*
27072* Process text content.
27073*/
27074static void
27075xmlSchemaSAXHandleText(void *ctx,
27076		       const xmlChar * ch,
27077		       int len)
27078{
27079    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27080
27081    if (vctxt->depth < 0)
27082	return;
27083    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27084	return;
27085    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27086	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27087    if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27088	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27089	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27090	    "calling xmlSchemaVPushText()");
27091	vctxt->err = -1;
27092	xmlStopParser(vctxt->parserCtxt);
27093    }
27094}
27095
27096/*
27097* Process CDATA content.
27098*/
27099static void
27100xmlSchemaSAXHandleCDataSection(void *ctx,
27101			     const xmlChar * ch,
27102			     int len)
27103{
27104    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27105
27106    if (vctxt->depth < 0)
27107	return;
27108    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27109	return;
27110    if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27111	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27112    if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27113	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27114	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27115	    "calling xmlSchemaVPushText()");
27116	vctxt->err = -1;
27117	xmlStopParser(vctxt->parserCtxt);
27118    }
27119}
27120
27121static void
27122xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27123			    const xmlChar * name ATTRIBUTE_UNUSED)
27124{
27125    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27126
27127    if (vctxt->depth < 0)
27128	return;
27129    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27130	return;
27131    /* SAX VAL TODO: What to do here? */
27132    TODO
27133}
27134
27135static void
27136xmlSchemaSAXHandleStartElementNs(void *ctx,
27137				 const xmlChar * localname,
27138				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27139				 const xmlChar * URI,
27140				 int nb_namespaces,
27141				 const xmlChar ** namespaces,
27142				 int nb_attributes,
27143				 int nb_defaulted ATTRIBUTE_UNUSED,
27144				 const xmlChar ** attributes)
27145{
27146    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27147    int ret;
27148    xmlSchemaNodeInfoPtr ielem;
27149    int i, j;
27150
27151    /*
27152    * SAX VAL TODO: What to do with nb_defaulted?
27153    */
27154    /*
27155    * Skip elements if inside a "skip" wildcard or invalid.
27156    */
27157    vctxt->depth++;
27158    if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27159	return;
27160    /*
27161    * Push the element.
27162    */
27163    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27164	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27165	    "calling xmlSchemaValidatorPushElem()");
27166	goto internal_error;
27167    }
27168    ielem = vctxt->inode;
27169    /*
27170    * TODO: Is this OK?
27171    */
27172    ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27173    ielem->localName = localname;
27174    ielem->nsName = URI;
27175    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27176    /*
27177    * Register namespaces on the elem info.
27178    */
27179    if (nb_namespaces != 0) {
27180	/*
27181	* Although the parser builds its own namespace list,
27182	* we have no access to it, so we'll use an own one.
27183	*/
27184        for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27185	    /*
27186	    * Store prefix and namespace name.
27187	    */
27188	    if (ielem->nsBindings == NULL) {
27189		ielem->nsBindings =
27190		    (const xmlChar **) xmlMalloc(10 *
27191			sizeof(const xmlChar *));
27192		if (ielem->nsBindings == NULL) {
27193		    xmlSchemaVErrMemory(vctxt,
27194			"allocating namespace bindings for SAX validation",
27195			NULL);
27196		    goto internal_error;
27197		}
27198		ielem->nbNsBindings = 0;
27199		ielem->sizeNsBindings = 5;
27200	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27201		ielem->sizeNsBindings *= 2;
27202		ielem->nsBindings =
27203		    (const xmlChar **) xmlRealloc(
27204			(void *) ielem->nsBindings,
27205			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27206		if (ielem->nsBindings == NULL) {
27207		    xmlSchemaVErrMemory(vctxt,
27208			"re-allocating namespace bindings for SAX validation",
27209			NULL);
27210		    goto internal_error;
27211		}
27212	    }
27213
27214	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27215	    if (namespaces[j+1][0] == 0) {
27216		/*
27217		* Handle xmlns="".
27218		*/
27219		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27220	    } else
27221		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27222		    namespaces[j+1];
27223	    ielem->nbNsBindings++;
27224	}
27225    }
27226    /*
27227    * Register attributes.
27228    * SAX VAL TODO: We are not adding namespace declaration
27229    * attributes yet.
27230    */
27231    if (nb_attributes != 0) {
27232	xmlChar *value;
27233
27234        for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27235	    /*
27236	    * Duplicate the value.
27237	    */
27238	    value = xmlStrndup(attributes[j+3],
27239		attributes[j+4] - attributes[j+3]);
27240	    /*
27241	    * TODO: Set the node line.
27242	    */
27243	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27244		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27245		value, 1);
27246	    if (ret == -1) {
27247		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27248		    "calling xmlSchemaValidatorPushAttribute()");
27249		goto internal_error;
27250	    }
27251	}
27252    }
27253    /*
27254    * Validate the element.
27255    */
27256    ret = xmlSchemaValidateElem(vctxt);
27257    if (ret != 0) {
27258	if (ret == -1) {
27259	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27260		"calling xmlSchemaValidateElem()");
27261	    goto internal_error;
27262	}
27263	goto exit;
27264    }
27265
27266exit:
27267    return;
27268internal_error:
27269    vctxt->err = -1;
27270    xmlStopParser(vctxt->parserCtxt);
27271    return;
27272}
27273
27274static void
27275xmlSchemaSAXHandleEndElementNs(void *ctx,
27276			       const xmlChar * localname ATTRIBUTE_UNUSED,
27277			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27278			       const xmlChar * URI ATTRIBUTE_UNUSED)
27279{
27280    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27281    int res;
27282
27283    /*
27284    * Skip elements if inside a "skip" wildcard or if invalid.
27285    */
27286    if (vctxt->skipDepth != -1) {
27287	if (vctxt->depth > vctxt->skipDepth) {
27288	    vctxt->depth--;
27289	    return;
27290	} else
27291	    vctxt->skipDepth = -1;
27292    }
27293    /*
27294    * SAX VAL TODO: Just a temporary check.
27295    */
27296    if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27297	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27298	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27299	    "elem pop mismatch");
27300    }
27301    res = xmlSchemaValidatorPopElem(vctxt);
27302    if (res != 0) {
27303	if (res < 0) {
27304	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27305		"calling xmlSchemaValidatorPopElem()");
27306	    goto internal_error;
27307	}
27308	goto exit;
27309    }
27310exit:
27311    return;
27312internal_error:
27313    vctxt->err = -1;
27314    xmlStopParser(vctxt->parserCtxt);
27315    return;
27316}
27317
27318/************************************************************************
27319 * 									*
27320 * 			Validation interfaces				*
27321 * 									*
27322 ************************************************************************/
27323
27324/**
27325 * xmlSchemaNewValidCtxt:
27326 * @schema:  a precompiled XML Schemas
27327 *
27328 * Create an XML Schemas validation context based on the given schema.
27329 *
27330 * Returns the validation context or NULL in case of error
27331 */
27332xmlSchemaValidCtxtPtr
27333xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27334{
27335    xmlSchemaValidCtxtPtr ret;
27336
27337    ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27338    if (ret == NULL) {
27339        xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27340        return (NULL);
27341    }
27342    memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27343    ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27344    ret->dict = xmlDictCreate();
27345    ret->nodeQNames = xmlSchemaItemListCreate();
27346    ret->schema = schema;
27347    return (ret);
27348}
27349
27350/**
27351 * xmlSchemaClearValidCtxt:
27352 * @ctxt: the schema validation context
27353 *
27354 * Free the resources associated to the schema validation context;
27355 * leaves some fields alive intended for reuse of the context.
27356 */
27357static void
27358xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27359{
27360    if (vctxt == NULL)
27361        return;
27362
27363    /*
27364    * TODO: Should we clear the flags?
27365    *   Might be problematic if one reuses the context
27366    *   and assumes that the options remain the same.
27367    */
27368    vctxt->flags = 0;
27369    vctxt->validationRoot = NULL;
27370    vctxt->doc = NULL;
27371#ifdef LIBXML_READER_ENABLED
27372    vctxt->reader = NULL;
27373#endif
27374    vctxt->hasKeyrefs = 0;
27375
27376    if (vctxt->value != NULL) {
27377        xmlSchemaFreeValue(vctxt->value);
27378	vctxt->value = NULL;
27379    }
27380    /*
27381    * Augmented IDC information.
27382    */
27383    if (vctxt->aidcs != NULL) {
27384	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27385	do {
27386	    next = cur->next;
27387	    xmlFree(cur);
27388	    cur = next;
27389	} while (cur != NULL);
27390	vctxt->aidcs = NULL;
27391    }
27392    if (vctxt->idcMatcherCache != NULL) {
27393	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27394
27395	while (matcher) {
27396	    tmp = matcher;
27397	    matcher = matcher->nextCached;
27398	    xmlSchemaIDCFreeMatcherList(tmp);
27399	}
27400	vctxt->idcMatcherCache = NULL;
27401    }
27402
27403
27404    if (vctxt->idcNodes != NULL) {
27405	int i;
27406	xmlSchemaPSVIIDCNodePtr item;
27407
27408	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27409	    item = vctxt->idcNodes[i];
27410	    xmlFree(item->keys);
27411	    xmlFree(item);
27412	}
27413	xmlFree(vctxt->idcNodes);
27414	vctxt->idcNodes = NULL;
27415	vctxt->nbIdcNodes = 0;
27416	vctxt->sizeIdcNodes = 0;
27417    }
27418    /*
27419    * Note that we won't delete the XPath state pool here.
27420    */
27421    if (vctxt->xpathStates != NULL) {
27422	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27423	vctxt->xpathStates = NULL;
27424    }
27425    /*
27426    * Attribute info.
27427    */
27428    if (vctxt->nbAttrInfos != 0) {
27429	xmlSchemaClearAttrInfos(vctxt);
27430    }
27431    /*
27432    * Element info.
27433    */
27434    if (vctxt->elemInfos != NULL) {
27435	int i;
27436	xmlSchemaNodeInfoPtr ei;
27437
27438	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27439	    ei = vctxt->elemInfos[i];
27440	    if (ei == NULL)
27441		break;
27442	    xmlSchemaClearElemInfo(vctxt, ei);
27443	}
27444    }
27445    xmlSchemaItemListClear(vctxt->nodeQNames);
27446    /* Recreate the dict. */
27447    xmlDictFree(vctxt->dict);
27448    /*
27449    * TODO: Is is save to recreate it? Do we have a scenario
27450    * where the user provides the dict?
27451    */
27452    vctxt->dict = xmlDictCreate();
27453}
27454
27455/**
27456 * xmlSchemaFreeValidCtxt:
27457 * @ctxt:  the schema validation context
27458 *
27459 * Free the resources associated to the schema validation context
27460 */
27461void
27462xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27463{
27464    if (ctxt == NULL)
27465        return;
27466    if (ctxt->value != NULL)
27467        xmlSchemaFreeValue(ctxt->value);
27468    if (ctxt->pctxt != NULL)
27469	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27470    if (ctxt->idcNodes != NULL) {
27471	int i;
27472	xmlSchemaPSVIIDCNodePtr item;
27473
27474	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27475	    item = ctxt->idcNodes[i];
27476	    xmlFree(item->keys);
27477	    xmlFree(item);
27478	}
27479	xmlFree(ctxt->idcNodes);
27480    }
27481    if (ctxt->idcKeys != NULL) {
27482	int i;
27483	for (i = 0; i < ctxt->nbIdcKeys; i++)
27484	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27485	xmlFree(ctxt->idcKeys);
27486    }
27487
27488    if (ctxt->xpathStates != NULL) {
27489	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27490	ctxt->xpathStates = NULL;
27491    }
27492    if (ctxt->xpathStatePool != NULL) {
27493	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27494	ctxt->xpathStatePool = NULL;
27495    }
27496
27497    /*
27498    * Augmented IDC information.
27499    */
27500    if (ctxt->aidcs != NULL) {
27501	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27502	do {
27503	    next = cur->next;
27504	    xmlFree(cur);
27505	    cur = next;
27506	} while (cur != NULL);
27507    }
27508    if (ctxt->attrInfos != NULL) {
27509	int i;
27510	xmlSchemaAttrInfoPtr attr;
27511
27512	/* Just a paranoid call to the cleanup. */
27513	if (ctxt->nbAttrInfos != 0)
27514	    xmlSchemaClearAttrInfos(ctxt);
27515	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27516	    attr = ctxt->attrInfos[i];
27517	    xmlFree(attr);
27518	}
27519	xmlFree(ctxt->attrInfos);
27520    }
27521    if (ctxt->elemInfos != NULL) {
27522	int i;
27523	xmlSchemaNodeInfoPtr ei;
27524
27525	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27526	    ei = ctxt->elemInfos[i];
27527	    if (ei == NULL)
27528		break;
27529	    xmlSchemaClearElemInfo(ctxt, ei);
27530	    xmlFree(ei);
27531	}
27532	xmlFree(ctxt->elemInfos);
27533    }
27534    if (ctxt->nodeQNames != NULL)
27535	xmlSchemaItemListFree(ctxt->nodeQNames);
27536    if (ctxt->dict != NULL)
27537	xmlDictFree(ctxt->dict);
27538    xmlFree(ctxt);
27539}
27540
27541/**
27542 * xmlSchemaIsValid:
27543 * @ctxt: the schema validation context
27544 *
27545 * Check if any error was detected during validation.
27546 *
27547 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27548 *         of internal error.
27549 */
27550int
27551xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27552{
27553    if (ctxt == NULL)
27554        return(-1);
27555    return(ctxt->err == 0);
27556}
27557
27558/**
27559 * xmlSchemaSetValidErrors:
27560 * @ctxt:  a schema validation context
27561 * @err:  the error function
27562 * @warn: the warning function
27563 * @ctx: the functions context
27564 *
27565 * Set the error and warning callback informations
27566 */
27567void
27568xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27569                        xmlSchemaValidityErrorFunc err,
27570                        xmlSchemaValidityWarningFunc warn, void *ctx)
27571{
27572    if (ctxt == NULL)
27573        return;
27574    ctxt->error = err;
27575    ctxt->warning = warn;
27576    ctxt->errCtxt = ctx;
27577    if (ctxt->pctxt != NULL)
27578	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27579}
27580
27581/**
27582 * xmlSchemaSetValidStructuredErrors:
27583 * @ctxt:  a schema validation context
27584 * @serror:  the structured error function
27585 * @ctx: the functions context
27586 *
27587 * Set the structured error callback
27588 */
27589void
27590xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27591				  xmlStructuredErrorFunc serror, void *ctx)
27592{
27593    if (ctxt == NULL)
27594        return;
27595	ctxt->serror = serror;
27596    ctxt->error = NULL;
27597    ctxt->warning = NULL;
27598    ctxt->errCtxt = ctx;
27599    if (ctxt->pctxt != NULL)
27600	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27601}
27602
27603/**
27604 * xmlSchemaGetValidErrors:
27605 * @ctxt:	a XML-Schema validation context
27606 * @err: the error function result
27607 * @warn: the warning function result
27608 * @ctx: the functions context result
27609 *
27610 * Get the error and warning callback informations
27611 *
27612 * Returns -1 in case of error and 0 otherwise
27613 */
27614int
27615xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27616			xmlSchemaValidityErrorFunc * err,
27617			xmlSchemaValidityWarningFunc * warn, void **ctx)
27618{
27619	if (ctxt == NULL)
27620		return (-1);
27621	if (err != NULL)
27622		*err = ctxt->error;
27623	if (warn != NULL)
27624		*warn = ctxt->warning;
27625	if (ctx != NULL)
27626		*ctx = ctxt->errCtxt;
27627	return (0);
27628}
27629
27630
27631/**
27632 * xmlSchemaSetValidOptions:
27633 * @ctxt:	a schema validation context
27634 * @options: a combination of xmlSchemaValidOption
27635 *
27636 * Sets the options to be used during the validation.
27637 *
27638 * Returns 0 in case of success, -1 in case of an
27639 * API error.
27640 */
27641int
27642xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27643			 int options)
27644
27645{
27646    int i;
27647
27648    if (ctxt == NULL)
27649	return (-1);
27650    /*
27651    * WARNING: Change the start value if adding to the
27652    * xmlSchemaValidOption.
27653    * TODO: Is there an other, more easy to maintain,
27654    * way?
27655    */
27656    for (i = 1; i < (int) sizeof(int) * 8; i++) {
27657        if (options & 1<<i)
27658	    return (-1);
27659    }
27660    ctxt->options = options;
27661    return (0);
27662}
27663
27664/**
27665 * xmlSchemaValidCtxtGetOptions:
27666 * @ctxt:	a schema validation context
27667 *
27668 * Get the validation context options.
27669 *
27670 * Returns the option combination or -1 on error.
27671 */
27672int
27673xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27674
27675{
27676    if (ctxt == NULL)
27677	return (-1);
27678    else
27679	return (ctxt->options);
27680}
27681
27682static int
27683xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27684{
27685    xmlAttrPtr attr;
27686    int ret = 0;
27687    xmlSchemaNodeInfoPtr ielem = NULL;
27688    xmlNodePtr node, valRoot;
27689    const xmlChar *nsName;
27690
27691    /* DOC VAL TODO: Move this to the start function. */
27692    valRoot = xmlDocGetRootElement(vctxt->doc);
27693    if (valRoot == NULL) {
27694	/* VAL TODO: Error code? */
27695	VERROR(1, NULL, "The document has no document element");
27696	return (1);
27697    }
27698    vctxt->depth = -1;
27699    vctxt->validationRoot = valRoot;
27700    node = valRoot;
27701    while (node != NULL) {
27702	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27703	    goto next_sibling;
27704	if (node->type == XML_ELEMENT_NODE) {
27705
27706	    /*
27707	    * Init the node-info.
27708	    */
27709	    vctxt->depth++;
27710	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27711		goto internal_error;
27712	    ielem = vctxt->inode;
27713	    ielem->node = node;
27714	    ielem->nodeLine = node->line;
27715	    ielem->localName = node->name;
27716	    if (node->ns != NULL)
27717		ielem->nsName = node->ns->href;
27718	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27719	    /*
27720	    * Register attributes.
27721	    * DOC VAL TODO: We do not register namespace declaration
27722	    * attributes yet.
27723	    */
27724	    vctxt->nbAttrInfos = 0;
27725	    if (node->properties != NULL) {
27726		attr = node->properties;
27727		do {
27728		    if (attr->ns != NULL)
27729			nsName = attr->ns->href;
27730		    else
27731			nsName = NULL;
27732		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27733			(xmlNodePtr) attr,
27734			/*
27735			* Note that we give it the line number of the
27736			* parent element.
27737			*/
27738			ielem->nodeLine,
27739			attr->name, nsName, 0,
27740			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27741		    if (ret == -1) {
27742			VERROR_INT("xmlSchemaDocWalk",
27743			    "calling xmlSchemaValidatorPushAttribute()");
27744			goto internal_error;
27745		    }
27746		    attr = attr->next;
27747		} while (attr);
27748	    }
27749	    /*
27750	    * Validate the element.
27751	    */
27752	    ret = xmlSchemaValidateElem(vctxt);
27753	    if (ret != 0) {
27754		if (ret == -1) {
27755		    VERROR_INT("xmlSchemaDocWalk",
27756			"calling xmlSchemaValidateElem()");
27757		    goto internal_error;
27758		}
27759		/*
27760		* Don't stop validation; just skip the content
27761		* of this element.
27762		*/
27763		goto leave_node;
27764	    }
27765	    if ((vctxt->skipDepth != -1) &&
27766		(vctxt->depth >= vctxt->skipDepth))
27767		goto leave_node;
27768	} else if ((node->type == XML_TEXT_NODE) ||
27769	    (node->type == XML_CDATA_SECTION_NODE)) {
27770	    /*
27771	    * Process character content.
27772	    */
27773	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27774		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27775	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27776		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27777	    if (ret < 0) {
27778		VERROR_INT("xmlSchemaVDocWalk",
27779		    "calling xmlSchemaVPushText()");
27780		goto internal_error;
27781	    }
27782	    /*
27783	    * DOC VAL TODO: Should we skip further validation of the
27784	    * element content here?
27785	    */
27786	} else if ((node->type == XML_ENTITY_NODE) ||
27787	    (node->type == XML_ENTITY_REF_NODE)) {
27788	    /*
27789	    * DOC VAL TODO: What to do with entities?
27790	    */
27791	    VERROR_INT("xmlSchemaVDocWalk",
27792		"there is at least one entity reference in the node-tree "
27793		"currently being validated. Processing of entities with "
27794		"this XML Schema processor is not supported (yet). Please "
27795		"substitute entities before validation.");
27796	    goto internal_error;
27797	} else {
27798	    goto leave_node;
27799	    /*
27800	    * DOC VAL TODO: XInclude nodes, etc.
27801	    */
27802	}
27803	/*
27804	* Walk the doc.
27805	*/
27806	if (node->children != NULL) {
27807	    node = node->children;
27808	    continue;
27809	}
27810leave_node:
27811	if (node->type == XML_ELEMENT_NODE) {
27812	    /*
27813	    * Leaving the scope of an element.
27814	    */
27815	    if (node != vctxt->inode->node) {
27816		VERROR_INT("xmlSchemaVDocWalk",
27817		    "element position mismatch");
27818		goto internal_error;
27819	    }
27820	    ret = xmlSchemaValidatorPopElem(vctxt);
27821	    if (ret != 0) {
27822		if (ret < 0) {
27823		    VERROR_INT("xmlSchemaVDocWalk",
27824			"calling xmlSchemaValidatorPopElem()");
27825		    goto internal_error;
27826		}
27827	    }
27828	    if (node == valRoot)
27829		goto exit;
27830	}
27831next_sibling:
27832	if (node->next != NULL)
27833	    node = node->next;
27834	else {
27835	    node = node->parent;
27836	    goto leave_node;
27837	}
27838    }
27839
27840exit:
27841    return (ret);
27842internal_error:
27843    return (-1);
27844}
27845
27846static int
27847xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27848    /*
27849    * Some initialization.
27850    */
27851    vctxt->err = 0;
27852    vctxt->nberrors = 0;
27853    vctxt->depth = -1;
27854    vctxt->skipDepth = -1;
27855    vctxt->xsiAssemble = 0;
27856    vctxt->hasKeyrefs = 0;
27857#ifdef ENABLE_IDC_NODE_TABLES_TEST
27858    vctxt->createIDCNodeTables = 1;
27859#else
27860    vctxt->createIDCNodeTables = 0;
27861#endif
27862    /*
27863    * Create a schema + parser if necessary.
27864    */
27865    if (vctxt->schema == NULL) {
27866	xmlSchemaParserCtxtPtr pctxt;
27867
27868	vctxt->xsiAssemble = 1;
27869	/*
27870	* If not schema was given then we will create a schema
27871	* dynamically using XSI schema locations.
27872	*
27873	* Create the schema parser context.
27874	*/
27875	if ((vctxt->pctxt == NULL) &&
27876	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27877	   return (-1);
27878	pctxt = vctxt->pctxt;
27879	pctxt->xsiAssemble = 1;
27880	/*
27881	* Create the schema.
27882	*/
27883	vctxt->schema = xmlSchemaNewSchema(pctxt);
27884	if (vctxt->schema == NULL)
27885	    return (-1);
27886	/*
27887	* Create the schema construction context.
27888	*/
27889	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27890	if (pctxt->constructor == NULL)
27891	    return(-1);
27892	pctxt->constructor->mainSchema = vctxt->schema;
27893	/*
27894	* Take ownership of the constructor to be able to free it.
27895	*/
27896	pctxt->ownsConstructor = 1;
27897    }
27898    /*
27899    * Augment the IDC definitions.
27900    */
27901    if (vctxt->schema->idcDef != NULL) {
27902	xmlHashScan(vctxt->schema->idcDef,
27903	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
27904    }
27905    return(0);
27906}
27907
27908static void
27909xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
27910    if (vctxt->xsiAssemble) {
27911	if (vctxt->schema != NULL) {
27912	    xmlSchemaFree(vctxt->schema);
27913	    vctxt->schema = NULL;
27914	}
27915    }
27916    xmlSchemaClearValidCtxt(vctxt);
27917}
27918
27919static int
27920xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27921{
27922    int ret = 0;
27923
27924    if (xmlSchemaPreRun(vctxt) < 0)
27925        return(-1);
27926
27927    if (vctxt->doc != NULL) {
27928	/*
27929	 * Tree validation.
27930	 */
27931	ret = xmlSchemaVDocWalk(vctxt);
27932#ifdef LIBXML_READER_ENABLED
27933    } else if (vctxt->reader != NULL) {
27934	/*
27935	 * XML Reader validation.
27936	 */
27937#ifdef XML_SCHEMA_READER_ENABLED
27938	ret = xmlSchemaVReaderWalk(vctxt);
27939#endif
27940#endif
27941    } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27942	/*
27943	 * SAX validation.
27944	 */
27945	ret = xmlParseDocument(vctxt->parserCtxt);
27946    } else {
27947	VERROR_INT("xmlSchemaVStart",
27948	    "no instance to validate");
27949	ret = -1;
27950    }
27951
27952    xmlSchemaPostRun(vctxt);
27953    if (ret == 0)
27954	ret = vctxt->err;
27955    return (ret);
27956}
27957
27958/**
27959 * xmlSchemaValidateOneElement:
27960 * @ctxt:  a schema validation context
27961 * @elem:  an element node
27962 *
27963 * Validate a branch of a tree, starting with the given @elem.
27964 *
27965 * Returns 0 if the element and its subtree is valid, a positive error
27966 * code number otherwise and -1 in case of an internal or API error.
27967 */
27968int
27969xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27970{
27971    if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27972	return (-1);
27973
27974    if (ctxt->schema == NULL)
27975	return (-1);
27976
27977    ctxt->doc = elem->doc;
27978    ctxt->node = elem;
27979    ctxt->validationRoot = elem;
27980    return(xmlSchemaVStart(ctxt));
27981}
27982
27983/**
27984 * xmlSchemaValidateDoc:
27985 * @ctxt:  a schema validation context
27986 * @doc:  a parsed document tree
27987 *
27988 * Validate a document tree in memory.
27989 *
27990 * Returns 0 if the document is schemas valid, a positive error code
27991 *     number otherwise and -1 in case of internal or API error.
27992 */
27993int
27994xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
27995{
27996    if ((ctxt == NULL) || (doc == NULL))
27997        return (-1);
27998
27999    ctxt->doc = doc;
28000    ctxt->node = xmlDocGetRootElement(doc);
28001    if (ctxt->node == NULL) {
28002        xmlSchemaCustomErr(ACTXT_CAST ctxt,
28003	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28004	    (xmlNodePtr) doc, NULL,
28005	    "The document has no document element", NULL, NULL);
28006        return (ctxt->err);
28007    }
28008    ctxt->validationRoot = ctxt->node;
28009    return (xmlSchemaVStart(ctxt));
28010}
28011
28012
28013/************************************************************************
28014 * 									*
28015 * 		Function and data for SAX streaming API			*
28016 * 									*
28017 ************************************************************************/
28018typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28019typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28020
28021struct _xmlSchemaSplitSAXData {
28022    xmlSAXHandlerPtr      user_sax;
28023    void                 *user_data;
28024    xmlSchemaValidCtxtPtr ctxt;
28025    xmlSAXHandlerPtr      schemas_sax;
28026};
28027
28028#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28029
28030struct _xmlSchemaSAXPlug {
28031    unsigned int magic;
28032
28033    /* the original callbacks informations */
28034    xmlSAXHandlerPtr     *user_sax_ptr;
28035    xmlSAXHandlerPtr      user_sax;
28036    void                **user_data_ptr;
28037    void                 *user_data;
28038
28039    /* the block plugged back and validation informations */
28040    xmlSAXHandler         schemas_sax;
28041    xmlSchemaValidCtxtPtr ctxt;
28042};
28043
28044/* All those functions just bounces to the user provided SAX handlers */
28045static void
28046internalSubsetSplit(void *ctx, const xmlChar *name,
28047	       const xmlChar *ExternalID, const xmlChar *SystemID)
28048{
28049    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28050    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28051        (ctxt->user_sax->internalSubset != NULL))
28052	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28053	                               SystemID);
28054}
28055
28056static int
28057isStandaloneSplit(void *ctx)
28058{
28059    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28060    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28061        (ctxt->user_sax->isStandalone != NULL))
28062	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28063    return(0);
28064}
28065
28066static int
28067hasInternalSubsetSplit(void *ctx)
28068{
28069    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28070    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28071        (ctxt->user_sax->hasInternalSubset != NULL))
28072	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28073    return(0);
28074}
28075
28076static int
28077hasExternalSubsetSplit(void *ctx)
28078{
28079    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28080    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28081        (ctxt->user_sax->hasExternalSubset != NULL))
28082	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28083    return(0);
28084}
28085
28086static void
28087externalSubsetSplit(void *ctx, const xmlChar *name,
28088	       const xmlChar *ExternalID, const xmlChar *SystemID)
28089{
28090    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28091    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28092        (ctxt->user_sax->internalSubset != NULL))
28093	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28094	                               SystemID);
28095}
28096
28097static xmlParserInputPtr
28098resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28099{
28100    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28101    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28102        (ctxt->user_sax->resolveEntity != NULL))
28103	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28104	                                     systemId));
28105    return(NULL);
28106}
28107
28108static xmlEntityPtr
28109getEntitySplit(void *ctx, const xmlChar *name)
28110{
28111    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28112    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28113        (ctxt->user_sax->getEntity != NULL))
28114	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28115    return(NULL);
28116}
28117
28118static xmlEntityPtr
28119getParameterEntitySplit(void *ctx, const xmlChar *name)
28120{
28121    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28122    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28123        (ctxt->user_sax->getParameterEntity != NULL))
28124	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28125    return(NULL);
28126}
28127
28128
28129static void
28130entityDeclSplit(void *ctx, const xmlChar *name, int type,
28131          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28132{
28133    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28134    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28135        (ctxt->user_sax->entityDecl != NULL))
28136	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28137	                           systemId, content);
28138}
28139
28140static void
28141attributeDeclSplit(void *ctx, const xmlChar * elem,
28142                   const xmlChar * name, int type, int def,
28143                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
28144{
28145    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28146    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28147        (ctxt->user_sax->attributeDecl != NULL)) {
28148	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28149	                              def, defaultValue, tree);
28150    } else {
28151	xmlFreeEnumeration(tree);
28152    }
28153}
28154
28155static void
28156elementDeclSplit(void *ctx, const xmlChar *name, int type,
28157	    xmlElementContentPtr content)
28158{
28159    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28160    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28161        (ctxt->user_sax->elementDecl != NULL))
28162	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28163}
28164
28165static void
28166notationDeclSplit(void *ctx, const xmlChar *name,
28167	     const xmlChar *publicId, const xmlChar *systemId)
28168{
28169    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28170    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28171        (ctxt->user_sax->notationDecl != NULL))
28172	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28173	                             systemId);
28174}
28175
28176static void
28177unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28178		   const xmlChar *publicId, const xmlChar *systemId,
28179		   const xmlChar *notationName)
28180{
28181    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28182    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28183        (ctxt->user_sax->unparsedEntityDecl != NULL))
28184	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28185	                                   systemId, notationName);
28186}
28187
28188static void
28189setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28190{
28191    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28192    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28193        (ctxt->user_sax->setDocumentLocator != NULL))
28194	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28195}
28196
28197static void
28198startDocumentSplit(void *ctx)
28199{
28200    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28201    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28202        (ctxt->user_sax->startDocument != NULL))
28203	ctxt->user_sax->startDocument(ctxt->user_data);
28204}
28205
28206static void
28207endDocumentSplit(void *ctx)
28208{
28209    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28210    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28211        (ctxt->user_sax->endDocument != NULL))
28212	ctxt->user_sax->endDocument(ctxt->user_data);
28213}
28214
28215static void
28216processingInstructionSplit(void *ctx, const xmlChar *target,
28217                      const xmlChar *data)
28218{
28219    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28220    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28221        (ctxt->user_sax->processingInstruction != NULL))
28222	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28223}
28224
28225static void
28226commentSplit(void *ctx, const xmlChar *value)
28227{
28228    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28229    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28230        (ctxt->user_sax->comment != NULL))
28231	ctxt->user_sax->comment(ctxt->user_data, value);
28232}
28233
28234/*
28235 * Varargs error callbacks to the user application, harder ...
28236 */
28237
28238static void XMLCDECL
28239warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28240    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28241    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28242        (ctxt->user_sax->warning != NULL)) {
28243	TODO
28244    }
28245}
28246static void XMLCDECL
28247errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28248    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28249    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28250        (ctxt->user_sax->error != NULL)) {
28251	TODO
28252    }
28253}
28254static void XMLCDECL
28255fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28256    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28257    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28258        (ctxt->user_sax->fatalError != NULL)) {
28259	TODO
28260    }
28261}
28262
28263/*
28264 * Those are function where both the user handler and the schemas handler
28265 * need to be called.
28266 */
28267static void
28268charactersSplit(void *ctx, const xmlChar *ch, int len)
28269{
28270    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28271    if (ctxt == NULL)
28272        return;
28273    if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28274	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28275    if (ctxt->ctxt != NULL)
28276	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28277}
28278
28279static void
28280ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28281{
28282    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28283    if (ctxt == NULL)
28284        return;
28285    if ((ctxt->user_sax != NULL) &&
28286        (ctxt->user_sax->ignorableWhitespace != NULL))
28287	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28288    if (ctxt->ctxt != NULL)
28289	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28290}
28291
28292static void
28293cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28294{
28295    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28296    if (ctxt == NULL)
28297        return;
28298    if ((ctxt->user_sax != NULL) &&
28299        (ctxt->user_sax->ignorableWhitespace != NULL))
28300	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
28301    if (ctxt->ctxt != NULL)
28302	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28303}
28304
28305static void
28306referenceSplit(void *ctx, const xmlChar *name)
28307{
28308    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28309    if (ctxt == NULL)
28310        return;
28311    if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28312        (ctxt->user_sax->reference != NULL))
28313	ctxt->user_sax->reference(ctxt->user_data, name);
28314    if (ctxt->ctxt != NULL)
28315        xmlSchemaSAXHandleReference(ctxt->user_data, name);
28316}
28317
28318static void
28319startElementNsSplit(void *ctx, const xmlChar * localname,
28320		    const xmlChar * prefix, const xmlChar * URI,
28321		    int nb_namespaces, const xmlChar ** namespaces,
28322		    int nb_attributes, int nb_defaulted,
28323		    const xmlChar ** attributes) {
28324    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28325    if (ctxt == NULL)
28326        return;
28327    if ((ctxt->user_sax != NULL) &&
28328        (ctxt->user_sax->startElementNs != NULL))
28329	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28330	                               URI, nb_namespaces, namespaces,
28331				       nb_attributes, nb_defaulted,
28332				       attributes);
28333    if (ctxt->ctxt != NULL)
28334	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28335	                                 URI, nb_namespaces, namespaces,
28336					 nb_attributes, nb_defaulted,
28337					 attributes);
28338}
28339
28340static void
28341endElementNsSplit(void *ctx, const xmlChar * localname,
28342		    const xmlChar * prefix, const xmlChar * URI) {
28343    xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28344    if (ctxt == NULL)
28345        return;
28346    if ((ctxt->user_sax != NULL) &&
28347        (ctxt->user_sax->endElementNs != NULL))
28348	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28349    if (ctxt->ctxt != NULL)
28350	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28351}
28352
28353/**
28354 * xmlSchemaSAXPlug:
28355 * @ctxt:  a schema validation context
28356 * @sax:  a pointer to the original xmlSAXHandlerPtr
28357 * @user_data:  a pointer to the original SAX user data pointer
28358 *
28359 * Plug a SAX based validation layer in a SAX parsing event flow.
28360 * The original @saxptr and @dataptr data are replaced by new pointers
28361 * but the calls to the original will be maintained.
28362 *
28363 * Returns a pointer to a data structure needed to unplug the validation layer
28364 *         or NULL in case of errors.
28365 */
28366xmlSchemaSAXPlugPtr
28367xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28368		 xmlSAXHandlerPtr *sax, void **user_data)
28369{
28370    xmlSchemaSAXPlugPtr ret;
28371    xmlSAXHandlerPtr old_sax;
28372
28373    if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28374        return(NULL);
28375
28376    /*
28377     * We only allow to plug into SAX2 event streams
28378     */
28379    old_sax = *sax;
28380    if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28381        return(NULL);
28382    if ((old_sax != NULL) &&
28383        (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28384        ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28385        return(NULL);
28386
28387    /*
28388     * everything seems right allocate the local data needed for that layer
28389     */
28390    ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28391    if (ret == NULL) {
28392        return(NULL);
28393    }
28394    memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28395    ret->magic = XML_SAX_PLUG_MAGIC;
28396    ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28397    ret->ctxt = ctxt;
28398    ret->user_sax_ptr = sax;
28399    ret->user_sax = old_sax;
28400    if (old_sax == NULL) {
28401        /*
28402	 * go direct, no need for the split block and functions.
28403	 */
28404	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28405	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28406	/*
28407	 * Note that we use the same text-function for both, to prevent
28408	 * the parser from testing for ignorable whitespace.
28409	 */
28410	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28411	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28412
28413	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28414	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28415
28416	ret->user_data = ctxt;
28417	*user_data = ctxt;
28418    } else {
28419       /*
28420        * for each callback unused by Schemas initialize it to the Split
28421	* routine only if non NULL in the user block, this can speed up
28422	* things at the SAX level.
28423	*/
28424        if (old_sax->internalSubset != NULL)
28425            ret->schemas_sax.internalSubset = internalSubsetSplit;
28426        if (old_sax->isStandalone != NULL)
28427            ret->schemas_sax.isStandalone = isStandaloneSplit;
28428        if (old_sax->hasInternalSubset != NULL)
28429            ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28430        if (old_sax->hasExternalSubset != NULL)
28431            ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28432        if (old_sax->resolveEntity != NULL)
28433            ret->schemas_sax.resolveEntity = resolveEntitySplit;
28434        if (old_sax->getEntity != NULL)
28435            ret->schemas_sax.getEntity = getEntitySplit;
28436        if (old_sax->entityDecl != NULL)
28437            ret->schemas_sax.entityDecl = entityDeclSplit;
28438        if (old_sax->notationDecl != NULL)
28439            ret->schemas_sax.notationDecl = notationDeclSplit;
28440        if (old_sax->attributeDecl != NULL)
28441            ret->schemas_sax.attributeDecl = attributeDeclSplit;
28442        if (old_sax->elementDecl != NULL)
28443            ret->schemas_sax.elementDecl = elementDeclSplit;
28444        if (old_sax->unparsedEntityDecl != NULL)
28445            ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28446        if (old_sax->setDocumentLocator != NULL)
28447            ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28448        if (old_sax->startDocument != NULL)
28449            ret->schemas_sax.startDocument = startDocumentSplit;
28450        if (old_sax->endDocument != NULL)
28451            ret->schemas_sax.endDocument = endDocumentSplit;
28452        if (old_sax->processingInstruction != NULL)
28453            ret->schemas_sax.processingInstruction = processingInstructionSplit;
28454        if (old_sax->comment != NULL)
28455            ret->schemas_sax.comment = commentSplit;
28456        if (old_sax->warning != NULL)
28457            ret->schemas_sax.warning = warningSplit;
28458        if (old_sax->error != NULL)
28459            ret->schemas_sax.error = errorSplit;
28460        if (old_sax->fatalError != NULL)
28461            ret->schemas_sax.fatalError = fatalErrorSplit;
28462        if (old_sax->getParameterEntity != NULL)
28463            ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28464        if (old_sax->externalSubset != NULL)
28465            ret->schemas_sax.externalSubset = externalSubsetSplit;
28466
28467	/*
28468	 * the 6 schemas callback have to go to the splitter functions
28469	 * Note that we use the same text-function for ignorableWhitespace
28470	 * if possible, to prevent the parser from testing for ignorable
28471	 * whitespace.
28472	 */
28473        ret->schemas_sax.characters = charactersSplit;
28474	if ((old_sax->ignorableWhitespace != NULL) &&
28475	    (old_sax->ignorableWhitespace != old_sax->characters))
28476	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28477	else
28478	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28479        ret->schemas_sax.cdataBlock = cdataBlockSplit;
28480        ret->schemas_sax.reference = referenceSplit;
28481        ret->schemas_sax.startElementNs = startElementNsSplit;
28482        ret->schemas_sax.endElementNs = endElementNsSplit;
28483
28484	ret->user_data_ptr = user_data;
28485	ret->user_data = *user_data;
28486	*user_data = ret;
28487    }
28488
28489    /*
28490     * plug the pointers back.
28491     */
28492    *sax = &(ret->schemas_sax);
28493    ctxt->sax = *sax;
28494    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28495    xmlSchemaPreRun(ctxt);
28496    return(ret);
28497}
28498
28499/**
28500 * xmlSchemaSAXUnplug:
28501 * @plug:  a data structure returned by xmlSchemaSAXPlug
28502 *
28503 * Unplug a SAX based validation layer in a SAX parsing event flow.
28504 * The original pointers used in the call are restored.
28505 *
28506 * Returns 0 in case of success and -1 in case of failure.
28507 */
28508int
28509xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28510{
28511    xmlSAXHandlerPtr *sax;
28512    void **user_data;
28513
28514    if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28515        return(-1);
28516    plug->magic = 0;
28517
28518    xmlSchemaPostRun(plug->ctxt);
28519    /* restore the data */
28520    sax = plug->user_sax_ptr;
28521    *sax = plug->user_sax;
28522    if (plug->user_sax != NULL) {
28523	user_data = plug->user_data_ptr;
28524	*user_data = plug->user_data;
28525    }
28526
28527    /* free and return */
28528    xmlFree(plug);
28529    return(0);
28530}
28531
28532/**
28533 * xmlSchemaValidateStream:
28534 * @ctxt:  a schema validation context
28535 * @input:  the input to use for reading the data
28536 * @enc:  an optional encoding information
28537 * @sax:  a SAX handler for the resulting events
28538 * @user_data:  the context to provide to the SAX handler.
28539 *
28540 * Validate an input based on a flow of SAX event from the parser
28541 * and forward the events to the @sax handler with the provided @user_data
28542 * the user provided @sax handler must be a SAX2 one.
28543 *
28544 * Returns 0 if the document is schemas valid, a positive error code
28545 *     number otherwise and -1 in case of internal or API error.
28546 */
28547int
28548xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28549                        xmlParserInputBufferPtr input, xmlCharEncoding enc,
28550                        xmlSAXHandlerPtr sax, void *user_data)
28551{
28552    xmlSchemaSAXPlugPtr plug = NULL;
28553    xmlSAXHandlerPtr old_sax = NULL;
28554    xmlParserCtxtPtr pctxt = NULL;
28555    xmlParserInputPtr inputStream = NULL;
28556    int ret;
28557
28558    if ((ctxt == NULL) || (input == NULL))
28559        return (-1);
28560
28561    /*
28562     * prepare the parser
28563     */
28564    pctxt = xmlNewParserCtxt();
28565    if (pctxt == NULL)
28566        return (-1);
28567    old_sax = pctxt->sax;
28568    pctxt->sax = sax;
28569    pctxt->userData = user_data;
28570#if 0
28571    if (options)
28572        xmlCtxtUseOptions(pctxt, options);
28573#endif
28574    pctxt->linenumbers = 1;
28575
28576    inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28577    if (inputStream == NULL) {
28578        ret = -1;
28579	goto done;
28580    }
28581    inputPush(pctxt, inputStream);
28582    ctxt->parserCtxt = pctxt;
28583    ctxt->input = input;
28584
28585    /*
28586     * Plug the validation and launch the parsing
28587     */
28588    plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28589    if (plug == NULL) {
28590        ret = -1;
28591	goto done;
28592    }
28593    ctxt->input = input;
28594    ctxt->enc = enc;
28595    ctxt->sax = pctxt->sax;
28596    ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28597    ret = xmlSchemaVStart(ctxt);
28598
28599    if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28600	ret = ctxt->parserCtxt->errNo;
28601	if (ret == 0)
28602	    ret = 1;
28603    }
28604
28605done:
28606    ctxt->parserCtxt = NULL;
28607    ctxt->sax = NULL;
28608    ctxt->input = NULL;
28609    if (plug != NULL) {
28610        xmlSchemaSAXUnplug(plug);
28611    }
28612    /* cleanup */
28613    if (pctxt != NULL) {
28614	pctxt->sax = old_sax;
28615	xmlFreeParserCtxt(pctxt);
28616    }
28617    return (ret);
28618}
28619
28620/**
28621 * xmlSchemaValidateFile:
28622 * @ctxt: a schema validation context
28623 * @filename: the URI of the instance
28624 * @options: a future set of options, currently unused
28625 *
28626 * Do a schemas validation of the given resource, it will use the
28627 * SAX streamable validation internally.
28628 *
28629 * Returns 0 if the document is valid, a positive error code
28630 *     number otherwise and -1 in case of an internal or API error.
28631 */
28632int
28633xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28634                      const char * filename,
28635		      int options ATTRIBUTE_UNUSED)
28636{
28637    int ret;
28638    xmlParserInputBufferPtr input;
28639
28640    if ((ctxt == NULL) || (filename == NULL))
28641        return (-1);
28642
28643    input = xmlParserInputBufferCreateFilename(filename,
28644	XML_CHAR_ENCODING_NONE);
28645    if (input == NULL)
28646	return (-1);
28647    ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28648	NULL, NULL);
28649    return (ret);
28650}
28651
28652#define bottom_xmlschemas
28653#include "elfgcchack.h"
28654#endif /* LIBXML_SCHEMAS_ENABLED */
28655