BRANCH release for 2.5.x critical patches
[baserock-morphs:libxml2.git] / relaxng.c
1 /*
2  * relaxng.c : implementation of the Relax-NG handling and validity checking
3  *
4  * See Copyright for the status of this software.
5  *
6  * Daniel Veillard <veillard@redhat.com>
7  */
8
9 /**
10  * TODO:
11  * - add support for DTD compatibility spec
12  *   http://www.oasis-open.org/committees/relax-ng/compatibility-20011203.html
13  * - report better mem allocations pbms at runtime and abort immediately.
14  */
15
16 #define IN_LIBXML
17 #include "libxml.h"
18
19 #ifdef LIBXML_SCHEMAS_ENABLED
20
21 #include <string.h>
22 #include <stdio.h>
23 #include <libxml/xmlmemory.h>
24 #include <libxml/parser.h>
25 #include <libxml/parserInternals.h>
26 #include <libxml/hash.h>
27 #include <libxml/uri.h>
28
29 #include <libxml/relaxng.h>
30
31 #include <libxml/xmlschemastypes.h>
32 #include <libxml/xmlautomata.h>
33 #include <libxml/xmlregexp.h>
34 #include <libxml/xmlschemastypes.h>
35
36 /*
37  * The Relax-NG namespace
38  */
39 static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
40     "http://relaxng.org/ns/structure/1.0";
41
42 #define IS_RELAXNG(node, type)                                          \
43    ((node != NULL) && (node->ns != NULL) &&                             \
44     (xmlStrEqual(node->name, (const xmlChar *) type)) &&                \
45     (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))
46
47
48 /* #define DEBUG 1 */
49 /* #define DEBUG_GRAMMAR 1 */
50 /* #define DEBUG_CONTENT 1 */
51 /* #define DEBUG_TYPE 1 */
52 /* #define DEBUG_VALID 1 */
53 /* #define DEBUG_INTERLEAVE 1 */
54 /* #define DEBUG_LIST 1 */
55 /* #define DEBUG_INCLUDE */
56 /* #define DEBUG_ERROR 1 */
57 /* #define DEBUG_COMPILE 1 */
58 /* #define DEBUG_PROGRESSIVE 1 */
59
60 #define MAX_ERROR 5
61
62 #define TODO                                                            \
63     xmlGenericError(xmlGenericErrorContext,                             \
64             "Unimplemented block at %s:%d\n",                           \
65             __FILE__, __LINE__);
66
67 typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;
68 typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;
69
70 typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine;
71 typedef xmlRelaxNGDefine *xmlRelaxNGDefinePtr;
72
73 typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument;
74 typedef xmlRelaxNGDocument *xmlRelaxNGDocumentPtr;
75
76 typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude;
77 typedef xmlRelaxNGInclude *xmlRelaxNGIncludePtr;
78
79 typedef enum {
80     XML_RELAXNG_COMBINE_UNDEFINED = 0,  /* undefined */
81     XML_RELAXNG_COMBINE_CHOICE,         /* choice */
82     XML_RELAXNG_COMBINE_INTERLEAVE      /* interleave */
83 } xmlRelaxNGCombine;
84
85 typedef enum {
86     XML_RELAXNG_CONTENT_ERROR = -1,
87     XML_RELAXNG_CONTENT_EMPTY = 0,
88     XML_RELAXNG_CONTENT_SIMPLE,
89     XML_RELAXNG_CONTENT_COMPLEX
90 } xmlRelaxNGContentType;
91
92 typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar;
93 typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr;
94
95 struct _xmlRelaxNGGrammar {
96     xmlRelaxNGGrammarPtr parent;/* the parent grammar if any */
97     xmlRelaxNGGrammarPtr children;/* the children grammar if any */
98     xmlRelaxNGGrammarPtr next;  /* the next grammar if any */
99     xmlRelaxNGDefinePtr start;  /* <start> content */
100     xmlRelaxNGCombine combine;  /* the default combine value */
101     xmlRelaxNGDefinePtr startList;/* list of <start> definitions */
102     xmlHashTablePtr defs;       /* define* */
103     xmlHashTablePtr refs;       /* references */
104 };
105
106
107 typedef enum {
108     XML_RELAXNG_NOOP = -1,      /* a no operation from simplification  */
109     XML_RELAXNG_EMPTY = 0,      /* an empty pattern */
110     XML_RELAXNG_NOT_ALLOWED,    /* not allowed top */
111     XML_RELAXNG_EXCEPT,         /* except present in nameclass defs */
112     XML_RELAXNG_TEXT,           /* textual content */
113     XML_RELAXNG_ELEMENT,        /* an element */
114     XML_RELAXNG_DATATYPE,       /* extenal data type definition */
115     XML_RELAXNG_PARAM,          /* extenal data type parameter */
116     XML_RELAXNG_VALUE,          /* value from an extenal data type definition */
117     XML_RELAXNG_LIST,           /* a list of patterns */
118     XML_RELAXNG_ATTRIBUTE,      /* an attrbute following a pattern */
119     XML_RELAXNG_DEF,            /* a definition */
120     XML_RELAXNG_REF,            /* reference to a definition */
121     XML_RELAXNG_EXTERNALREF,    /* reference to an external def */
122     XML_RELAXNG_PARENTREF,      /* reference to a def in the parent grammar */
123     XML_RELAXNG_OPTIONAL,       /* optional patterns */
124     XML_RELAXNG_ZEROORMORE,     /* zero or more non empty patterns */
125     XML_RELAXNG_ONEORMORE,      /* one or more non empty patterns */
126     XML_RELAXNG_CHOICE,         /* a choice between non empty patterns */
127     XML_RELAXNG_GROUP,          /* a pair/group of non empty patterns */
128     XML_RELAXNG_INTERLEAVE,     /* interleaving choice of non-empty patterns */
129     XML_RELAXNG_START           /* Used to keep track of starts on grammars */
130 } xmlRelaxNGType;
131
132 #define IS_NULLABLE             (1 << 0)
133 #define IS_NOT_NULLABLE         (1 << 1)
134 #define IS_INDETERMINIST        (1 << 2)
135 #define IS_MIXED                (1 << 3)
136 #define IS_TRIABLE              (1 << 4)
137 #define IS_PROCESSED            (1 << 5)
138 #define IS_COMPILABLE           (1 << 6)
139 #define IS_NOT_COMPILABLE       (1 << 7)
140
141 struct _xmlRelaxNGDefine {
142     xmlRelaxNGType type;        /* the type of definition */
143     xmlNodePtr     node;        /* the node in the source */
144     xmlChar       *name;        /* the element local name if present */
145     xmlChar       *ns;          /* the namespace local name if present */
146     xmlChar       *value;       /* value when available */
147     void          *data;        /* data lib or specific pointer */
148     xmlRelaxNGDefinePtr content;/* the expected content */
149     xmlRelaxNGDefinePtr parent; /* the parent definition, if any */
150     xmlRelaxNGDefinePtr next;   /* list within grouping sequences */
151     xmlRelaxNGDefinePtr attrs;  /* list of attributes for elements */
152     xmlRelaxNGDefinePtr nameClass;/* the nameClass definition if any */
153     xmlRelaxNGDefinePtr nextHash;/* next define in defs/refs hash tables */
154     short           depth;       /* used for the cycle detection */
155     short           dflags;      /* define related flags */
156     xmlRegexpPtr    contModel;   /* a compiled content model if available */
157 };
158
159 /**
160  * _xmlRelaxNG:
161  *
162  * A RelaxNGs definition
163  */
164 struct _xmlRelaxNG {
165     void *_private;     /* unused by the library for users or bindings */
166     xmlRelaxNGGrammarPtr topgrammar;
167     xmlDocPtr doc;
168
169     int             idref;      /* requires idref checking */
170
171     xmlHashTablePtr defs;       /* define */
172     xmlHashTablePtr refs;       /* references */
173     xmlRelaxNGDocumentPtr documents; /* all the documents loaded */
174     xmlRelaxNGIncludePtr includes;   /* all the includes loaded */
175     int                  defNr; /* number of defines used */
176     xmlRelaxNGDefinePtr *defTab;/* pointer to the allocated definitions */
177
178 };
179
180 #define XML_RELAXNG_IN_ATTRIBUTE        (1 << 0)
181 #define XML_RELAXNG_IN_ONEORMORE        (1 << 1)
182 #define XML_RELAXNG_IN_LIST             (1 << 2)
183 #define XML_RELAXNG_IN_DATAEXCEPT       (1 << 3)
184 #define XML_RELAXNG_IN_START            (1 << 4)
185 #define XML_RELAXNG_IN_OOMGROUP         (1 << 5)
186 #define XML_RELAXNG_IN_OOMINTERLEAVE    (1 << 6)
187 #define XML_RELAXNG_IN_EXTERNALREF      (1 << 7)
188 #define XML_RELAXNG_IN_ANYEXCEPT        (1 << 8)
189 #define XML_RELAXNG_IN_NSEXCEPT         (1 << 9)
190
191 struct _xmlRelaxNGParserCtxt {
192     void *userData;                     /* user specific data block */
193     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */
194     xmlRelaxNGValidityWarningFunc warning;/* the callback in case of warning */
195     xmlRelaxNGValidErr err;
196
197     xmlRelaxNGPtr      schema;        /* The schema in use */
198     xmlRelaxNGGrammarPtr grammar;     /* the current grammar */
199     xmlRelaxNGGrammarPtr parentgrammar;/* the parent grammar */
200     int                flags;         /* parser flags */
201     int                nbErrors;      /* number of errors at parse time */
202     int                nbWarnings;    /* number of warnings at parse time */
203     const xmlChar     *define;        /* the current define scope */
204     xmlRelaxNGDefinePtr def;          /* the current define */
205
206     int                nbInterleaves;
207     xmlHashTablePtr    interleaves;   /* keep track of all the interleaves */
208
209     xmlRelaxNGDocumentPtr documents;  /* all the documents loaded */
210     xmlRelaxNGIncludePtr includes;    /* all the includes loaded */
211     xmlChar           *URL;
212     xmlDocPtr          document;
213
214     int                  defNr;       /* number of defines used */
215     int                  defMax;      /* number of defines aloocated */
216     xmlRelaxNGDefinePtr *defTab;      /* pointer to the allocated definitions */
217
218     const char     *buffer;
219     int               size;
220
221     /* the document stack */
222     xmlRelaxNGDocumentPtr doc;        /* Current parsed external ref */
223     int                   docNr;      /* Depth of the parsing stack */
224     int                   docMax;     /* Max depth of the parsing stack */
225     xmlRelaxNGDocumentPtr *docTab;    /* array of docs */
226
227     /* the include stack */
228     xmlRelaxNGIncludePtr  inc;        /* Current parsed include */
229     int                   incNr;      /* Depth of the include parsing stack */
230     int                   incMax;     /* Max depth of the parsing stack */
231     xmlRelaxNGIncludePtr *incTab;     /* array of incs */
232
233     int                   idref;      /* requires idref checking */
234
235     /* used to compile content models */
236     xmlAutomataPtr        am;         /* the automata */
237     xmlAutomataStatePtr   state;      /* used to build the automata */
238 };
239
240 #define FLAGS_IGNORABLE         1
241 #define FLAGS_NEGATIVE          2
242 #define FLAGS_MIXED_CONTENT     4
243
244 /**
245  * xmlRelaxNGInterleaveGroup:
246  *
247  * A RelaxNGs partition set associated to lists of definitions
248  */
249 typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup;
250 typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr;
251 struct _xmlRelaxNGInterleaveGroup {
252     xmlRelaxNGDefinePtr  rule;  /* the rule to satisfy */
253     xmlRelaxNGDefinePtr *defs;  /* the array of element definitions */
254     xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */
255 };
256
257 #define IS_DETERMINIST          1
258 #define IS_NEEDCHECK            2
259 /**
260  * xmlRelaxNGPartitions:
261  *
262  * A RelaxNGs partition associated to an interleave group
263  */
264 typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition;
265 typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr;
266 struct _xmlRelaxNGPartition {
267     int nbgroups;               /* number of groups in the partitions */
268     xmlHashTablePtr triage;     /* hash table used to direct nodes to the
269                                    right group when possible */
270     int flags;                  /* determinist ? */
271     xmlRelaxNGInterleaveGroupPtr *groups;
272 };
273
274 /**
275  * xmlRelaxNGValidState:
276  *
277  * A RelaxNGs validation state
278  */
279 #define MAX_ATTR 20
280 typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState;
281 typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr;
282 struct _xmlRelaxNGValidState {
283     xmlNodePtr   node;          /* the current node */
284     xmlNodePtr    seq;          /* the sequence of children left to validate */
285     int       nbAttrs;          /* the number of attributes */
286     int      maxAttrs;          /* the size of attrs */
287     int    nbAttrLeft;          /* the number of attributes left to validate */
288     xmlChar    *value;          /* the value when operating on string */
289     xmlChar *endvalue;          /* the end value when operating on string */
290     xmlAttrPtr *attrs;          /* the array of attributes */
291 };
292
293 /**
294  * xmlRelaxNGStates:
295  *
296  * A RelaxNGs container for validation state
297  */
298 typedef struct _xmlRelaxNGStates xmlRelaxNGStates;
299 typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr;
300 struct _xmlRelaxNGStates {
301     int       nbState;          /* the number of states */
302     int      maxState;          /* the size of the array */
303     xmlRelaxNGValidStatePtr *tabState;
304 };
305
306 #define ERROR_IS_DUP    1
307 /**
308  * xmlRelaxNGValidError:
309  *
310  * A RelaxNGs validation error
311  */
312 typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;
313 typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;
314 struct _xmlRelaxNGValidError {
315     xmlRelaxNGValidErr  err;    /* the error number */
316     int                 flags;  /* flags */
317     xmlNodePtr          node;   /* the current node */
318     xmlNodePtr          seq;    /* the current child */
319     const xmlChar *     arg1;   /* first arg */
320     const xmlChar *     arg2;   /* second arg */
321 };
322
323 /**
324  * xmlRelaxNGValidCtxt:
325  *
326  * A RelaxNGs validation context
327  */
328
329 struct _xmlRelaxNGValidCtxt {
330     void *userData;                     /* user specific data block */
331     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */
332     xmlRelaxNGValidityWarningFunc warning;/* the callback in case of warning */
333
334     xmlRelaxNGPtr           schema;     /* The schema in use */
335     xmlDocPtr               doc;        /* the document being validated */
336     int                     flags;      /* validation flags */
337     int                     depth;      /* validation depth */
338     int                     idref;      /* requires idref checking */
339     int                     errNo;      /* the first error found */
340
341     /*
342      * Errors accumulated in branches may have to be stacked to be
343      * provided back when it's sure they affect validation.
344      */
345     xmlRelaxNGValidErrorPtr err;        /* Last error */
346     int                     errNr;      /* Depth of the error stack */
347     int                     errMax;     /* Max depth of the error stack */
348     xmlRelaxNGValidErrorPtr errTab;     /* stack of errors */
349
350     xmlRelaxNGValidStatePtr state;      /* the current validation state */
351     xmlRelaxNGStatesPtr     states;     /* the accumulated state list */
352
353     xmlRelaxNGStatesPtr     freeState;  /* the pool of free valid states */
354     int                     freeStatesNr;
355     int                     freeStatesMax;
356     xmlRelaxNGStatesPtr    *freeStates; /* the pool of free state groups */
357
358     /*
359      * This is used for "progressive" validation
360      */
361     xmlRegExecCtxtPtr       elem;       /* the current element regexp */
362     int                     elemNr;     /* the number of element validated */
363     int                     elemMax;    /* the max depth of elements */
364     xmlRegExecCtxtPtr      *elemTab;    /* the stack of regexp runtime */
365     int                     pstate;     /* progressive state */
366     xmlNodePtr              pnode;      /* the current node */
367     xmlRelaxNGDefinePtr     pdef;       /* the non-streamable definition */
368 };
369
370 /**
371  * xmlRelaxNGInclude:
372  *
373  * Structure associated to a RelaxNGs document element
374  */
375 struct _xmlRelaxNGInclude {
376     xmlRelaxNGIncludePtr next;  /* keep a chain of includes */
377     xmlChar   *href;            /* the normalized href value */
378     xmlDocPtr  doc;             /* the associated XML document */
379     xmlRelaxNGDefinePtr content;/* the definitions */
380     xmlRelaxNGPtr       schema; /* the schema */
381 };
382
383 /**
384  * xmlRelaxNGDocument:
385  *
386  * Structure associated to a RelaxNGs document element
387  */
388 struct _xmlRelaxNGDocument {
389     xmlRelaxNGDocumentPtr next; /* keep a chain of documents */
390     xmlChar   *href;            /* the normalized href value */
391     xmlDocPtr  doc;             /* the associated XML document */
392     xmlRelaxNGDefinePtr content;/* the definitions */
393     xmlRelaxNGPtr       schema; /* the schema */
394 };
395
396
397 /************************************************************************
398  *                                                                      *
399  *              Preliminary type checking interfaces                    *
400  *                                                                      *
401  ************************************************************************/
402 /**
403  * xmlRelaxNGTypeHave:
404  * @data:  data needed for the library
405  * @type:  the type name
406  * @value:  the value to check
407  *
408  * Function provided by a type library to check if a type is exported
409  *
410  * Returns 1 if yes, 0 if no and -1 in case of error.
411  */
412 typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar *type);
413
414 /**
415  * xmlRelaxNGTypeCheck:
416  * @data:  data needed for the library
417  * @type:  the type name
418  * @value:  the value to check
419  * @result:  place to store the result if needed
420  *
421  * Function provided by a type library to check if a value match a type
422  *
423  * Returns 1 if yes, 0 if no and -1 in case of error.
424  */
425 typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar *type,
426                                     const xmlChar *value, void **result,
427                                     xmlNodePtr node);
428
429 /**
430  * xmlRelaxNGFacetCheck:
431  * @data:  data needed for the library
432  * @type:  the type name
433  * @facet:  the facet name
434  * @val:  the facet value
435  * @strval:  the string value
436  * @value:  the value to check
437  *
438  * Function provided by a type library to check a value facet
439  *
440  * Returns 1 if yes, 0 if no and -1 in case of error.
441  */
442 typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar *type,
443                                      const xmlChar *facet, const xmlChar *val,
444                                      const xmlChar *strval, void *value);
445
446 /**
447  * xmlRelaxNGTypeFree:
448  * @data:  data needed for the library
449  * @result:  the value to free
450  *
451  * Function provided by a type library to free a returned result
452  */
453 typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);
454
455 /**
456  * xmlRelaxNGTypeCompare:
457  * @data:  data needed for the library
458  * @type:  the type name
459  * @value1:  the first value
460  * @value2:  the second value
461  *
462  * Function provided by a type library to compare two values accordingly
463  * to a type.
464  *
465  * Returns 1 if yes, 0 if no and -1 in case of error.
466  */
467 typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar *type,
468                                       const xmlChar *value1,
469                                       xmlNodePtr ctxt1,
470                                       void *comp1,
471                                       const xmlChar *value2,
472                                       xmlNodePtr ctxt2);
473 typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
474 typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
475 struct _xmlRelaxNGTypeLibrary {
476     const xmlChar     *namespace;       /* the datatypeLibrary value */
477     void                   *data;       /* data needed for the library */
478     xmlRelaxNGTypeHave      have;       /* the export function */
479     xmlRelaxNGTypeCheck    check;       /* the checking function */
480     xmlRelaxNGTypeCompare   comp;       /* the compare function */
481     xmlRelaxNGFacetCheck   facet;       /* the facet check function */
482     xmlRelaxNGTypeFree     freef;       /* the freeing function */
483 };
484
485 /************************************************************************
486  *                                                                      *
487  *                      Allocation functions                            *
488  *                                                                      *
489  ************************************************************************/
490 static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);
491 static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);
492 static void xmlRelaxNGNormExtSpace(xmlChar *value);
493 static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema);
494 static int xmlRelaxNGEqualValidState(
495                          xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
496                          xmlRelaxNGValidStatePtr state1,
497                          xmlRelaxNGValidStatePtr state2);
498 static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
499                                      xmlRelaxNGValidStatePtr state);
500
501 /**
502  * xmlRelaxNGFreeDocument:
503  * @docu:  a document structure
504  *
505  * Deallocate a RelaxNG document structure.
506  */
507 static void
508 xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu)
509 {
510     if (docu == NULL)
511         return;
512
513     if (docu->href != NULL)
514         xmlFree(docu->href);
515     if (docu->doc != NULL)
516         xmlFreeDoc(docu->doc);
517     if (docu->schema != NULL)
518         xmlRelaxNGFreeInnerSchema(docu->schema);
519     xmlFree(docu);
520 }
521
522 /**
523  * xmlRelaxNGFreeDocumentList:
524  * @docu:  a list of  document structure
525  *
526  * Deallocate a RelaxNG document structures.
527  */
528 static void
529 xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu)
530 {
531     xmlRelaxNGDocumentPtr next;
532     while (docu != NULL) {
533         next = docu->next;
534         xmlRelaxNGFreeDocument(docu);
535         docu = next;
536     }
537 }
538
539 /**
540  * xmlRelaxNGFreeInclude:
541  * @incl:  a include structure
542  *
543  * Deallocate a RelaxNG include structure.
544  */
545 static void
546 xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl)
547 {
548     if (incl == NULL)
549         return;
550
551     if (incl->href != NULL)
552         xmlFree(incl->href);
553     if (incl->doc != NULL)
554         xmlFreeDoc(incl->doc);
555     if (incl->schema != NULL)
556         xmlRelaxNGFree(incl->schema);
557     xmlFree(incl);
558 }
559
560 /**
561  * xmlRelaxNGFreeIncludeList:
562  * @incl:  a include structure list
563  *
564  * Deallocate a RelaxNG include structure.
565  */
566 static void
567 xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl)
568 {
569     xmlRelaxNGIncludePtr next;
570     while (incl != NULL) {
571         next = incl->next;
572         xmlRelaxNGFreeInclude(incl);
573         incl = next;
574     }
575 }
576
577 /**
578  * xmlRelaxNGNewRelaxNG:
579  * @ctxt:  a Relax-NG validation context (optional)
580  *
581  * Allocate a new RelaxNG structure.
582  *
583  * Returns the newly allocated structure or NULL in case or error
584  */
585 static xmlRelaxNGPtr
586 xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)
587 {
588     xmlRelaxNGPtr ret;
589
590     ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));
591     if (ret == NULL) {
592         if ((ctxt != NULL) && (ctxt->error != NULL))
593             ctxt->error(ctxt->userData, "Out of memory\n");
594         ctxt->nbErrors++;
595         return (NULL);
596     }
597     memset(ret, 0, sizeof(xmlRelaxNG));
598
599     return (ret);
600 }
601
602 /**
603  * xmlRelaxNGFreeInnerSchema:
604  * @schema:  a schema structure
605  *
606  * Deallocate a RelaxNG schema structure.
607  */
608 static void
609 xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema)
610 {
611     if (schema == NULL)
612         return;
613
614     if (schema->doc != NULL)
615         xmlFreeDoc(schema->doc);
616     if (schema->defTab != NULL) {
617         int i;
618
619         for (i = 0;i < schema->defNr;i++)
620             xmlRelaxNGFreeDefine(schema->defTab[i]);
621         xmlFree(schema->defTab);
622     }
623
624     xmlFree(schema);
625 }
626
627 /**
628  * xmlRelaxNGFree:
629  * @schema:  a schema structure
630  *
631  * Deallocate a RelaxNG structure.
632  */
633 void
634 xmlRelaxNGFree(xmlRelaxNGPtr schema)
635 {
636     if (schema == NULL)
637         return;
638
639     if (schema->topgrammar != NULL)
640         xmlRelaxNGFreeGrammar(schema->topgrammar);
641     if (schema->doc != NULL)
642         xmlFreeDoc(schema->doc);
643     if (schema->documents != NULL)
644         xmlRelaxNGFreeDocumentList(schema->documents);
645     if (schema->includes != NULL)
646         xmlRelaxNGFreeIncludeList(schema->includes);
647     if (schema->defTab != NULL) {
648         int i;
649
650         for (i = 0;i < schema->defNr;i++)
651             xmlRelaxNGFreeDefine(schema->defTab[i]);
652         xmlFree(schema->defTab);
653     }
654
655     xmlFree(schema);
656 }
657
658 /**
659  * xmlRelaxNGNewGrammar:
660  * @ctxt:  a Relax-NG validation context (optional)
661  *
662  * Allocate a new RelaxNG grammar.
663  *
664  * Returns the newly allocated structure or NULL in case or error
665  */
666 static xmlRelaxNGGrammarPtr
667 xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)
668 {
669     xmlRelaxNGGrammarPtr ret;
670
671     ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));
672     if (ret == NULL) {
673         if ((ctxt != NULL) && (ctxt->error != NULL))
674             ctxt->error(ctxt->userData, "Out of memory\n");
675         ctxt->nbErrors++;
676         return (NULL);
677     }
678     memset(ret, 0, sizeof(xmlRelaxNGGrammar));
679
680     return (ret);
681 }
682
683 /**
684  * xmlRelaxNGFreeGrammar:
685  * @grammar:  a grammar structure
686  *
687  * Deallocate a RelaxNG grammar structure.
688  */
689 static void
690 xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar)
691 {
692     if (grammar == NULL)
693         return;
694
695     if (grammar->children != NULL) {
696         xmlRelaxNGFreeGrammar(grammar->children);
697     }
698     if (grammar->next != NULL) {
699         xmlRelaxNGFreeGrammar(grammar->next);
700     }
701     if (grammar->refs != NULL) {
702         xmlHashFree(grammar->refs, NULL);
703     }
704     if (grammar->defs != NULL) {
705         xmlHashFree(grammar->defs, NULL);
706     }
707
708     xmlFree(grammar);
709 }
710
711 /**
712  * xmlRelaxNGNewDefine:
713  * @ctxt:  a Relax-NG validation context
714  * @node:  the node in the input document.
715  *
716  * Allocate a new RelaxNG define.
717  *
718  * Returns the newly allocated structure or NULL in case or error
719  */
720 static xmlRelaxNGDefinePtr
721 xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
722 {
723     xmlRelaxNGDefinePtr ret;
724
725     if (ctxt->defMax == 0) {
726         ctxt->defMax = 16;
727         ctxt->defNr = 0;
728         ctxt->defTab = (xmlRelaxNGDefinePtr *)
729             xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
730         if (ctxt->defTab == NULL) {
731             if ((ctxt != NULL) && (ctxt->error != NULL))
732                 ctxt->error(ctxt->userData, "Out of memory\n");
733             ctxt->nbErrors++;
734             return (NULL);
735         }
736     } else if (ctxt->defMax <= ctxt->defNr) {
737         xmlRelaxNGDefinePtr *tmp;
738         ctxt->defMax *= 2;
739         tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,
740                 ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
741         if (tmp == NULL) {
742             if ((ctxt != NULL) && (ctxt->error != NULL))
743                 ctxt->error(ctxt->userData, "Out of memory\n");
744             ctxt->nbErrors++;
745             return (NULL);
746         }
747         ctxt->defTab = tmp;
748     }
749     ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
750     if (ret == NULL) {
751         if ((ctxt != NULL) && (ctxt->error != NULL))
752             ctxt->error(ctxt->userData, "Out of memory\n");
753         ctxt->nbErrors++;
754         return(NULL);
755     }
756     memset(ret, 0, sizeof(xmlRelaxNGDefine));
757     ctxt->defTab[ctxt->defNr++] = ret;
758     ret->node = node;
759     ret->depth = -1;
760     return (ret);
761 }
762
763 /**
764  * xmlRelaxNGFreePartition:
765  * @partitions:  a partition set structure
766  *
767  * Deallocate RelaxNG partition set structures.
768  */
769 static void
770 xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions) {
771     xmlRelaxNGInterleaveGroupPtr group;
772     int j;
773
774     if (partitions != NULL) {
775         if (partitions->groups != NULL) {
776             for (j = 0;j < partitions->nbgroups;j++) {
777                 group = partitions->groups[j];
778                 if (group != NULL) {
779                     if (group->defs != NULL)
780                         xmlFree(group->defs);
781                     if (group->attrs != NULL)
782                         xmlFree(group->attrs);
783                     xmlFree(group);
784                 }
785             }
786             xmlFree(partitions->groups);
787         }
788         if (partitions->triage != NULL) {
789             xmlHashFree(partitions->triage, NULL);
790         }
791         xmlFree(partitions);
792     }
793 }
794 /**
795  * xmlRelaxNGFreeDefine:
796  * @define:  a define structure
797  *
798  * Deallocate a RelaxNG define structure.
799  */
800 static void
801 xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define)
802 {
803     if (define == NULL)
804         return;
805
806     if ((define->type == XML_RELAXNG_VALUE) &&
807         (define->attrs != NULL)) {
808         xmlRelaxNGTypeLibraryPtr lib;
809
810         lib = (xmlRelaxNGTypeLibraryPtr) define->data;
811         if ((lib != NULL) && (lib->freef != NULL))
812             lib->freef(lib->data, (void *) define->attrs);
813     }
814     if ((define->data != NULL) &&
815         (define->type == XML_RELAXNG_INTERLEAVE))
816         xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
817     if ((define->data != NULL) &&
818         (define->type == XML_RELAXNG_CHOICE))
819         xmlHashFree((xmlHashTablePtr) define->data, NULL);
820     if (define->name != NULL)
821         xmlFree(define->name);
822     if (define->ns != NULL)
823         xmlFree(define->ns);
824     if (define->value != NULL)
825         xmlFree(define->value);
826     if (define->contModel != NULL)
827         xmlRegFreeRegexp(define->contModel);
828     xmlFree(define);
829 }
830
831 /**
832  * xmlRelaxNGNewStates:
833  * @ctxt:  a Relax-NG validation context
834  * @size:  the default size for the container
835  *
836  * Allocate a new RelaxNG validation state container
837  *
838  * Returns the newly allocated structure or NULL in case or error
839  */
840 static xmlRelaxNGStatesPtr
841 xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
842 {
843     xmlRelaxNGStatesPtr ret;
844
845     if ((ctxt != NULL) &&
846         (ctxt->freeState != NULL) && 
847         (ctxt->freeStatesNr > 0)) {
848         ctxt->freeStatesNr--;
849         ret = ctxt->freeStates[ctxt->freeStatesNr];
850         ret->nbState = 0;
851         return(ret);
852     }
853     if (size < 16) size = 16;
854
855     ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +
856                               (size - 1) * sizeof(xmlRelaxNGValidStatePtr));
857     if (ret == NULL) {
858         if ((ctxt != NULL) && (ctxt->error != NULL))
859             ctxt->error(ctxt->userData, "Out of memory\n");
860         return (NULL);
861     }
862     ret->nbState = 0;
863     ret->maxState = size;
864     ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc(
865                             (size) * sizeof(xmlRelaxNGValidStatePtr));
866     if (ret->tabState == NULL) {
867         if ((ctxt != NULL) && (ctxt->error != NULL))
868             ctxt->error(ctxt->userData, "Out of memory\n");
869         xmlFree(ret->tabState);
870         return (NULL);
871     }
872     return(ret);
873 }
874
875 /**
876  * xmlRelaxNGAddStateUniq:
877  * @ctxt:  a Relax-NG validation context
878  * @states:  the states container
879  * @state:  the validation state
880  *
881  * Add a RelaxNG validation state to the container without checking
882  * for unicity.
883  *
884  * Return 1 in case of success and 0 if this is a duplicate and -1 on error
885  */
886 static int
887 xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,
888                     xmlRelaxNGStatesPtr states,
889                     xmlRelaxNGValidStatePtr state)
890 {
891     if (state == NULL) {
892         return(-1);
893     }
894     if (states->nbState >= states->maxState) {
895         xmlRelaxNGValidStatePtr *tmp;
896         int size;
897
898         size = states->maxState * 2;
899         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
900                               (size) * sizeof(xmlRelaxNGValidStatePtr));
901         if (tmp == NULL) {
902             if ((ctxt != NULL) && (ctxt->error != NULL))
903                 ctxt->error(ctxt->userData, "Out of memory\n");
904             return(-1);
905         }
906         states->tabState = tmp;
907         states->maxState = size;
908     }
909     states->tabState[states->nbState++] = state;
910     return(1);
911 }
912
913 /**
914  * xmlRelaxNGAddState:
915  * @ctxt:  a Relax-NG validation context
916  * @states:  the states container
917  * @state:  the validation state
918  *
919  * Add a RelaxNG validation state to the container
920  *
921  * Return 1 in case of success and 0 if this is a duplicate and -1 on error
922  */
923 static int
924 xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGStatesPtr states,
925                     xmlRelaxNGValidStatePtr state)
926 {
927     int i;
928
929     if (state == NULL) {
930         return(-1);
931     }
932     if (states->nbState >= states->maxState) {
933         xmlRelaxNGValidStatePtr *tmp;
934         int size;
935
936         size = states->maxState * 2;
937         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
938                               (size) * sizeof(xmlRelaxNGValidStatePtr));
939         if (tmp == NULL) {
940             if ((ctxt != NULL) && (ctxt->error != NULL))
941                 ctxt->error(ctxt->userData, "Out of memory\n");
942             return(-1);
943         }
944         states->tabState = tmp;
945         states->maxState = size;
946     }
947     for (i = 0;i < states->nbState;i++) {
948         if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) {
949             xmlRelaxNGFreeValidState(ctxt, state);
950             return(0);
951         }
952     }
953     states->tabState[states->nbState++] = state;
954     return(1);
955 }
956
957 /**
958  * xmlRelaxNGFreeStates:
959  * @ctxt:  a Relax-NG validation context
960  * @states:  teh container
961  *
962  * Free a RelaxNG validation state container
963  */
964 static void
965 xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
966                      xmlRelaxNGStatesPtr states)
967 {
968     if (states == NULL)
969         return;
970     if ((ctxt != NULL) && (ctxt->freeStates == NULL)) {
971         ctxt->freeStatesMax = 40;
972         ctxt->freeStatesNr = 0;
973         ctxt->freeStates = (xmlRelaxNGStatesPtr *)
974              xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
975         if (ctxt->freeStates == NULL) {
976             if ((ctxt != NULL) && (ctxt->error != NULL))
977                 ctxt->error(ctxt->userData, "Out of memory\n");
978         }
979     } else if ((ctxt != NULL) && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) {
980         xmlRelaxNGStatesPtr *tmp;
981
982         tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates,
983                 2 * ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
984         if (tmp == NULL) {
985             if ((ctxt != NULL) && (ctxt->error != NULL))
986                 ctxt->error(ctxt->userData, "Out of memory\n");
987             xmlFree(states->tabState);
988             xmlFree(states);
989             return;
990         }
991         ctxt->freeStates = tmp;
992         ctxt->freeStatesMax *= 2;
993     }
994     if ((ctxt == NULL) || (ctxt->freeState == NULL)) {
995         xmlFree(states->tabState);
996         xmlFree(states);
997     } else {
998         ctxt->freeStates[ctxt->freeStatesNr++] = states;
999     }
1000 }
1001
1002 /**
1003  * xmlRelaxNGNewValidState:
1004  * @ctxt:  a Relax-NG validation context
1005  * @node:  the current node or NULL for the document
1006  *
1007  * Allocate a new RelaxNG validation state
1008  *
1009  * Returns the newly allocated structure or NULL in case or error
1010  */
1011 static xmlRelaxNGValidStatePtr
1012 xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
1013 {
1014     xmlRelaxNGValidStatePtr ret;
1015     xmlAttrPtr attr;
1016     xmlAttrPtr attrs[MAX_ATTR];
1017     int nbAttrs = 0;
1018     xmlNodePtr root = NULL;
1019
1020     if (node == NULL) {
1021         root = xmlDocGetRootElement(ctxt->doc);
1022         if (root == NULL)
1023             return(NULL);
1024     } else {
1025         attr = node->properties;
1026         while (attr != NULL) {
1027             if (nbAttrs < MAX_ATTR)
1028                 attrs[nbAttrs++] = attr;
1029             else
1030                 nbAttrs++;
1031             attr = attr->next;
1032         }
1033     }
1034     if ((ctxt->freeState != NULL) && 
1035         (ctxt->freeState->nbState > 0)) {
1036         ctxt->freeState->nbState--;
1037         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
1038     } else {
1039         ret = (xmlRelaxNGValidStatePtr) xmlMalloc(sizeof(xmlRelaxNGValidState));
1040         if (ret == NULL) {
1041             if ((ctxt != NULL) && (ctxt->error != NULL))
1042                 ctxt->error(ctxt->userData, "Out of memory\n");
1043             return (NULL);
1044         }
1045         memset(ret, 0, sizeof(xmlRelaxNGValidState));
1046     }
1047     ret->value = NULL;
1048     ret->endvalue = NULL;
1049     if (node == NULL) {
1050         ret->node = (xmlNodePtr) ctxt->doc;
1051         ret->seq = root;
1052     } else {
1053         ret->node = node;
1054         ret->seq = node->children;
1055     }
1056     ret->nbAttrs = 0;
1057     if (nbAttrs > 0) {
1058         if (ret->attrs == NULL) {
1059             if (nbAttrs < 4) ret->maxAttrs = 4;
1060             else ret->maxAttrs = nbAttrs;
1061             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
1062                                                 sizeof(xmlAttrPtr));
1063             if (ret->attrs == NULL) {
1064                 if ((ctxt != NULL) && (ctxt->error != NULL))
1065                     ctxt->error(ctxt->userData, "Out of memory\n");
1066                 return (ret);
1067             }
1068         } else if (ret->maxAttrs < nbAttrs) {
1069             xmlAttrPtr *tmp;
1070
1071             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *
1072                                           sizeof(xmlAttrPtr));
1073             if (tmp == NULL) {
1074                 if ((ctxt != NULL) && (ctxt->error != NULL))
1075                     ctxt->error(ctxt->userData, "Out of memory\n");
1076                 return (ret);
1077             }
1078             ret->attrs = tmp;
1079             ret->maxAttrs = nbAttrs;
1080         }
1081         ret->nbAttrs = nbAttrs;
1082         if (nbAttrs < MAX_ATTR) {
1083             memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs);
1084         } else {
1085             attr = node->properties;
1086             nbAttrs = 0;
1087             while (attr != NULL) {
1088                 ret->attrs[nbAttrs++] = attr;
1089                 attr = attr->next;
1090             }
1091         }
1092     }
1093     ret->nbAttrLeft = ret->nbAttrs;
1094     return (ret);
1095 }
1096
1097 /**
1098  * xmlRelaxNGCopyValidState:
1099  * @ctxt:  a Relax-NG validation context
1100  * @state:  a validation state
1101  *
1102  * Copy the validation state
1103  *
1104  * Returns the newly allocated structure or NULL in case or error
1105  */
1106 static xmlRelaxNGValidStatePtr
1107 xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
1108                          xmlRelaxNGValidStatePtr state)
1109 {
1110     xmlRelaxNGValidStatePtr ret;
1111     unsigned int maxAttrs;
1112     xmlAttrPtr *attrs;
1113
1114     if (state == NULL)
1115         return(NULL);
1116     if ((ctxt->freeState != NULL) && 
1117         (ctxt->freeState->nbState > 0)) {
1118         ctxt->freeState->nbState--;
1119         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
1120     } else {
1121         ret = (xmlRelaxNGValidStatePtr) xmlMalloc(sizeof(xmlRelaxNGValidState));
1122         if (ret == NULL) {
1123             if ((ctxt != NULL) && (ctxt->error != NULL))
1124                 ctxt->error(ctxt->userData, "Out of memory\n");
1125             return (NULL);
1126         }
1127         memset(ret, 0, sizeof(xmlRelaxNGValidState));
1128     }
1129     attrs = ret->attrs;
1130     maxAttrs = ret->maxAttrs;
1131     memcpy(ret, state, sizeof(xmlRelaxNGValidState));
1132     ret->attrs = attrs;
1133     ret->maxAttrs = maxAttrs;
1134     if (state->nbAttrs > 0) {
1135         if (ret->attrs == NULL) {
1136             ret->maxAttrs = state->maxAttrs;
1137             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
1138                                                 sizeof(xmlAttrPtr));
1139             if (ret->attrs == NULL) {
1140                 if ((ctxt != NULL) && (ctxt->error != NULL))
1141                     ctxt->error(ctxt->userData, "Out of memory\n");
1142                 ret->nbAttrs = 0;
1143                 return (ret);
1144             }
1145         } else if (ret->maxAttrs < state->nbAttrs) {
1146             xmlAttrPtr *tmp;
1147
1148             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *
1149                                           sizeof(xmlAttrPtr));
1150             if (tmp == NULL) {
1151                 if ((ctxt != NULL) && (ctxt->error != NULL))
1152                     ctxt->error(ctxt->userData, "Out of memory\n");
1153                 ret->nbAttrs = 0;
1154                 return (ret);
1155             }
1156             ret->maxAttrs = state->maxAttrs;
1157             ret->attrs = tmp;
1158         }
1159         memcpy(ret->attrs, state->attrs, state->nbAttrs * sizeof(xmlAttrPtr));
1160     }
1161     return(ret);
1162 }
1163
1164 /**
1165  * xmlRelaxNGEqualValidState:
1166  * @ctxt:  a Relax-NG validation context
1167  * @state1:  a validation state
1168  * @state2:  a validation state
1169  *
1170  * Compare the validation states for equality
1171  *
1172  * Returns 1 if equald, 0 otherwise
1173  */
1174 static int
1175 xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
1176                          xmlRelaxNGValidStatePtr state1,
1177                          xmlRelaxNGValidStatePtr state2)
1178 {
1179     int i;
1180
1181     if ((state1 == NULL) || (state2 == NULL))
1182         return(0);
1183     if (state1 == state2)
1184         return(1);
1185     if (state1->node != state2->node)
1186         return(0);
1187     if (state1->seq != state2->seq)
1188         return(0);
1189     if (state1->nbAttrLeft != state2->nbAttrLeft)
1190         return(0);
1191     if (state1->nbAttrs != state2->nbAttrs)
1192         return(0);
1193     if (state1->endvalue != state2->endvalue)
1194         return(0);
1195     if ((state1->value != state2->value) &&
1196         (!xmlStrEqual(state1->value, state2->value)))
1197         return(0);
1198     for (i = 0;i < state1->nbAttrs;i++) {
1199         if (state1->attrs[i] != state2->attrs[i])
1200             return(0);
1201     }
1202     return(1);
1203 }
1204
1205 /**
1206  * xmlRelaxNGFreeValidState:
1207  * @state:  a validation state structure
1208  *
1209  * Deallocate a RelaxNG validation state structure.
1210  */
1211 static void
1212 xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
1213                          xmlRelaxNGValidStatePtr state)
1214 {
1215     if (state == NULL)
1216         return;
1217
1218     if ((ctxt != NULL) && (ctxt->freeState == NULL)) {
1219         ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40);
1220     }
1221     if ((ctxt == NULL) || (ctxt->freeState == NULL)) {
1222         if (state->attrs != NULL)
1223             xmlFree(state->attrs);
1224         xmlFree(state);
1225     } else {
1226         xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state);
1227     }
1228 }
1229
1230 /************************************************************************
1231  *                                                                      *
1232  *                      Document functions                                      *
1233  *                                                                      *
1234  ************************************************************************/
1235 static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
1236                                       xmlDocPtr doc);
1237
1238 /**
1239  * xmlRelaxNGIncludePush:
1240  * @ctxt:  the parser context
1241  * @value:  the element doc
1242  *
1243  * Pushes a new include on top of the include stack
1244  *
1245  * Returns 0 in case of error, the index in the stack otherwise
1246  */
1247 static int
1248 xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
1249                        xmlRelaxNGIncludePtr value)
1250 {
1251     if (ctxt->incTab == NULL) {
1252         ctxt->incMax = 4;
1253         ctxt->incNr = 0;
1254         ctxt->incTab = (xmlRelaxNGIncludePtr *) xmlMalloc(
1255                         ctxt->incMax * sizeof(ctxt->incTab[0]));
1256         if (ctxt->incTab == NULL) {
1257             xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
1258             return (0);
1259         }
1260     }
1261     if (ctxt->incNr >= ctxt->incMax) {
1262         ctxt->incMax *= 2;
1263         ctxt->incTab =
1264             (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,
1265                                       ctxt->incMax *
1266                                       sizeof(ctxt->incTab[0]));
1267         if (ctxt->incTab == NULL) {
1268             xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
1269             return (0);
1270         }
1271     }
1272     ctxt->incTab[ctxt->incNr] = value;
1273     ctxt->inc = value;
1274     return (ctxt->incNr++);
1275 }
1276
1277 /**
1278  * xmlRelaxNGIncludePop:
1279  * @ctxt: the parser context
1280  *
1281  * Pops the top include from the include stack
1282  *
1283  * Returns the include just removed
1284  */
1285 static xmlRelaxNGIncludePtr
1286 xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt)
1287 {
1288     xmlRelaxNGIncludePtr ret;
1289
1290     if (ctxt->incNr <= 0)
1291         return (0);
1292     ctxt->incNr--;
1293     if (ctxt->incNr > 0)
1294         ctxt->inc = ctxt->incTab[ctxt->incNr - 1];
1295     else
1296         ctxt->inc = NULL;
1297     ret = ctxt->incTab[ctxt->incNr];
1298     ctxt->incTab[ctxt->incNr] = 0;
1299     return (ret);
1300 }
1301
1302 /**
1303  * xmlRelaxNGRemoveRedefine:
1304  * @ctxt: the parser context
1305  * @URL:  the normalized URL
1306  * @target:  the included target
1307  * @name:  the define name to eliminate
1308  *
1309  * Applies the elimination algorithm of 4.7
1310  *
1311  * Returns 0 in case of error, 1 in case of success.
1312  */
1313 static int
1314 xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
1315                          const xmlChar *URL ATTRIBUTE_UNUSED,
1316                          xmlNodePtr target, const xmlChar *name) {
1317     int found = 0;
1318     xmlNodePtr tmp, tmp2;
1319     xmlChar *name2;
1320
1321 #ifdef DEBUG_INCLUDE
1322     if (name == NULL)
1323         xmlGenericError(xmlGenericErrorContext,
1324                     "Elimination of <include> start from %s\n", URL);
1325     else
1326         xmlGenericError(xmlGenericErrorContext,
1327                 "Elimination of <include> define %s from %s\n", name, URL);
1328 #endif
1329     tmp = target;
1330     while (tmp != NULL) {
1331         tmp2 = tmp->next;
1332         if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) {
1333             found = 1;
1334             xmlUnlinkNode(tmp);
1335             xmlFreeNode(tmp);
1336         } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) {
1337             name2 = xmlGetProp(tmp, BAD_CAST "name");
1338             xmlRelaxNGNormExtSpace(name2);
1339             if (name2 != NULL) {
1340                 if (xmlStrEqual(name, name2)) {
1341                     found = 1;
1342                     xmlUnlinkNode(tmp);
1343                     xmlFreeNode(tmp);
1344                 }
1345                 xmlFree(name2);
1346             }
1347         } else if (IS_RELAXNG(tmp, "include")) {
1348             xmlChar *href = NULL;
1349             xmlRelaxNGDocumentPtr inc = tmp->_private;
1350
1351             if ((inc != NULL) && (inc->doc != NULL) &&
1352                 (inc->doc->children != NULL)) {
1353
1354                 if (xmlStrEqual(inc->doc->children->name, BAD_CAST "grammar")) {
1355 #ifdef DEBUG_INCLUDE
1356                     href = xmlGetProp(tmp, BAD_CAST "href");
1357 #endif
1358                     if (xmlRelaxNGRemoveRedefine(ctxt, href,
1359                                 inc->doc->children->children, name) == 1) {
1360                         found = 1;
1361                     }
1362                     if (href != NULL)
1363                         xmlFree(href);
1364                 }
1365             }
1366         }
1367         tmp = tmp2;
1368     }
1369     return(found);
1370 }
1371
1372 /**
1373  * xmlRelaxNGLoadInclude:
1374  * @ctxt: the parser context
1375  * @URL:  the normalized URL
1376  * @node: the include node.
1377  * @ns:  the namespace passed from the context.
1378  *
1379  * First lookup if the document is already loaded into the parser context,
1380  * check against recursion. If not found the resource is loaded and
1381  * the content is preprocessed before being returned back to the caller.
1382  *
1383  * Returns the xmlRelaxNGIncludePtr or NULL in case of error
1384  */
1385 static xmlRelaxNGIncludePtr
1386 xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar *URL,
1387                       xmlNodePtr node, const xmlChar *ns) {
1388     xmlRelaxNGIncludePtr ret = NULL;
1389     xmlDocPtr doc;
1390     int i;
1391     xmlNodePtr root, cur;
1392
1393 #ifdef DEBUG_INCLUDE
1394     xmlGenericError(xmlGenericErrorContext,
1395                     "xmlRelaxNGLoadInclude(%s)\n", URL);
1396 #endif
1397
1398     /*
1399      * check against recursion in the stack
1400      */
1401     for (i = 0;i < ctxt->incNr;i++) {
1402         if (xmlStrEqual(ctxt->incTab[i]->href, URL)) {
1403             if (ctxt->error != NULL)
1404                 ctxt->error(ctxt->userData,
1405                     "Detected an Include recursion for %s\n",
1406                             URL);
1407             ctxt->nbErrors++;
1408             return(NULL);
1409         }
1410     }
1411
1412     /*
1413      * load the document
1414      */
1415     doc = xmlParseFile((const char *) URL);
1416     if (doc == NULL) {
1417         if (ctxt->error != NULL)
1418             ctxt->error(ctxt->userData,
1419                         "xmlRelaxNG: could not load %s\n", URL);
1420         ctxt->nbErrors++;
1421         return (NULL);
1422     }
1423
1424 #ifdef DEBUG_INCLUDE
1425     xmlGenericError(xmlGenericErrorContext,
1426                     "Parsed %s Okay\n", URL);
1427 #endif
1428
1429     /*
1430      * Allocate the document structures and register it first.
1431      */
1432     ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));
1433     if (ret == NULL) {
1434         if (ctxt->error != NULL)
1435             ctxt->error(ctxt->userData,
1436                         "xmlRelaxNG: allocate memory for doc %s\n", URL);
1437         ctxt->nbErrors++;
1438         xmlFreeDoc(doc);
1439         return (NULL);
1440     }
1441     memset(ret, 0, sizeof(xmlRelaxNGInclude));
1442     ret->doc = doc;
1443     ret->href = xmlStrdup(URL);
1444     ret->next = ctxt->includes;
1445     ctxt->includes = ret;
1446
1447     /*
1448      * transmit the ns if needed
1449      */
1450     if (ns != NULL) {
1451         root = xmlDocGetRootElement(doc);
1452         if (root != NULL) {
1453             if (xmlHasProp(root, BAD_CAST"ns") == NULL) {
1454                 xmlSetProp(root, BAD_CAST"ns", ns);
1455             }
1456         }
1457     }
1458
1459     /*
1460      * push it on the stack
1461      */
1462     xmlRelaxNGIncludePush(ctxt, ret);
1463
1464     /*
1465      * Some preprocessing of the document content, this include recursing
1466      * in the include stack.
1467      */
1468 #ifdef DEBUG_INCLUDE
1469     xmlGenericError(xmlGenericErrorContext,
1470                     "cleanup of %s\n", URL);
1471 #endif
1472
1473     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
1474     if (doc == NULL) {
1475         ctxt->inc = NULL;
1476         return(NULL);
1477     }
1478
1479     /*
1480      * Pop up the include from the stack
1481      */
1482     xmlRelaxNGIncludePop(ctxt);
1483
1484 #ifdef DEBUG_INCLUDE
1485     xmlGenericError(xmlGenericErrorContext,
1486                     "Checking of %s\n", URL);
1487 #endif
1488     /*
1489      * Check that the top element is a grammar
1490      */
1491     root = xmlDocGetRootElement(doc);
1492     if (root == NULL) {
1493         if (ctxt->error != NULL)
1494             ctxt->error(ctxt->userData,
1495                         "xmlRelaxNG: included document is empty %s\n", URL);
1496         ctxt->nbErrors++;
1497         return (NULL);
1498     }
1499     if (!IS_RELAXNG(root, "grammar")) {
1500         if (ctxt->error != NULL)
1501             ctxt->error(ctxt->userData,
1502                     "xmlRelaxNG: included document %s root is not a grammar\n",
1503                         URL);
1504         ctxt->nbErrors++;
1505         return (NULL);
1506     }
1507
1508     /*
1509      * Elimination of redefined rules in the include.
1510      */
1511     cur = node->children;
1512     while (cur != NULL) {
1513         if (IS_RELAXNG(cur, "start")) {
1514             int found = 0;
1515
1516             found = xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);
1517             if (!found) {
1518                 if (ctxt->error != NULL)
1519                     ctxt->error(ctxt->userData,
1520         "xmlRelaxNG: include %s has a start but not the included grammar\n",
1521                                 URL);
1522                 ctxt->nbErrors++;
1523             }
1524         } else if (IS_RELAXNG(cur, "define")) {
1525             xmlChar *name;
1526
1527             name = xmlGetProp(cur, BAD_CAST "name");
1528             if (name == NULL) {
1529                 if (ctxt->error != NULL)
1530                     ctxt->error(ctxt->userData,
1531                             "xmlRelaxNG: include %s has define without name\n",
1532                                 URL);
1533                 ctxt->nbErrors++;
1534             } else {
1535                 int found;
1536
1537                 xmlRelaxNGNormExtSpace(name);
1538                 found = xmlRelaxNGRemoveRedefine(ctxt, URL,
1539                                                  root->children, name);
1540                 if (!found) {
1541                     if (ctxt->error != NULL)
1542                         ctxt->error(ctxt->userData,
1543     "xmlRelaxNG: include %s has a define %s but not the included grammar\n",
1544                                     URL, name);
1545                     ctxt->nbErrors++;
1546                 }
1547                 xmlFree(name);
1548             }
1549         }
1550         cur = cur->next;
1551     }
1552
1553
1554     return(ret);
1555 }
1556
1557 /**
1558  * xmlRelaxNGValidErrorPush:
1559  * @ctxt:  the validation context
1560  * @err:  the error code
1561  * @arg1:  the first string argument
1562  * @arg2:  the second string argument
1563  * @dup:  arg need to be duplicated
1564  *
1565  * Pushes a new error on top of the error stack
1566  *
1567  * Returns 0 in case of error, the index in the stack otherwise
1568  */
1569 static int
1570 xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err,
1571         const xmlChar *arg1, const xmlChar *arg2, int dup)
1572 {
1573     xmlRelaxNGValidErrorPtr cur;
1574 #ifdef DEBUG_ERROR
1575     xmlGenericError(xmlGenericErrorContext,
1576             "Pushing error %d at %d on stack\n", err, ctxt->errNr);
1577 #endif
1578     if (ctxt->errTab == NULL) {
1579         ctxt->errMax = 8;
1580         ctxt->errNr = 0;
1581         ctxt->errTab = (xmlRelaxNGValidErrorPtr) xmlMalloc(
1582                         ctxt->errMax * sizeof(xmlRelaxNGValidError));
1583         if (ctxt->errTab == NULL) {
1584             xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
1585             return (0);
1586         }
1587         ctxt->err = NULL;
1588     }
1589     if (ctxt->errNr >= ctxt->errMax) {
1590         ctxt->errMax *= 2;
1591         ctxt->errTab =
1592             (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,
1593                             ctxt->errMax * sizeof(xmlRelaxNGValidError));
1594         if (ctxt->errTab == NULL) {
1595             xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
1596             return (0);
1597         }
1598         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
1599     }
1600     if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
1601         (ctxt->err->node == ctxt->state->node) &&
1602         (ctxt->err->err == err))
1603         return(ctxt->errNr);
1604     cur = &ctxt->errTab[ctxt->errNr];
1605     cur->err = err;
1606     if (dup) {
1607         cur->arg1 = xmlStrdup(arg1);
1608         cur->arg2 = xmlStrdup(arg2);
1609         cur->flags = ERROR_IS_DUP;
1610     } else {
1611         cur->arg1 = arg1;
1612         cur->arg2 = arg2;
1613         cur->flags = 0;
1614     }
1615     if (ctxt->state != NULL) {
1616         cur->node = ctxt->state->node;
1617         cur->seq = ctxt->state->seq;
1618     } else {
1619         cur->node = NULL;
1620         cur->seq = NULL;
1621     }
1622     ctxt->err = cur;
1623     return (ctxt->errNr++);
1624 }
1625
1626 /**
1627  * xmlRelaxNGValidErrorPop:
1628  * @ctxt: the validation context
1629  *
1630  * Pops the top error from the error stack
1631  */
1632 static void
1633 xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
1634 {
1635     xmlRelaxNGValidErrorPtr cur;
1636
1637     if (ctxt->errNr <= 0) {
1638         ctxt->err = NULL;
1639         return;
1640     }
1641     ctxt->errNr--;
1642     if (ctxt->errNr > 0)
1643         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
1644     else
1645         ctxt->err = NULL;
1646     cur = &ctxt->errTab[ctxt->errNr];
1647     if (cur->flags & ERROR_IS_DUP) {
1648         if (cur->arg1 != NULL)
1649             xmlFree((xmlChar *)cur->arg1);
1650         cur->arg1 = NULL;
1651         if (cur->arg2 != NULL)
1652             xmlFree((xmlChar *)cur->arg2);
1653         cur->arg2 = NULL;
1654         cur->flags = 0;
1655     }
1656 }
1657
1658 /**
1659  * xmlRelaxNGDocumentPush:
1660  * @ctxt:  the parser context
1661  * @value:  the element doc
1662  *
1663  * Pushes a new doc on top of the doc stack
1664  *
1665  * Returns 0 in case of error, the index in the stack otherwise
1666  */
1667 static int
1668 xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
1669                        xmlRelaxNGDocumentPtr value)
1670 {
1671     if (ctxt->docTab == NULL) {
1672         ctxt->docMax = 4;
1673         ctxt->docNr = 0;
1674         ctxt->docTab = (xmlRelaxNGDocumentPtr *) xmlMalloc(
1675                         ctxt->docMax * sizeof(ctxt->docTab[0]));
1676         if (ctxt->docTab == NULL) {
1677             xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
1678             return (0);
1679         }
1680     }
1681     if (ctxt->docNr >= ctxt->docMax) {
1682         ctxt->docMax *= 2;
1683         ctxt->docTab =
1684             (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,
1685                                       ctxt->docMax *
1686                                       sizeof(ctxt->docTab[0]));
1687         if (ctxt->docTab == NULL) {
1688             xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
1689             return (0);
1690         }
1691     }
1692     ctxt->docTab[ctxt->docNr] = value;
1693     ctxt->doc = value;
1694     return (ctxt->docNr++);
1695 }
1696
1697 /**
1698  * xmlRelaxNGDocumentPop:
1699  * @ctxt: the parser context
1700  *
1701  * Pops the top doc from the doc stack
1702  *
1703  * Returns the doc just removed
1704  */
1705 static xmlRelaxNGDocumentPtr
1706 xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)
1707 {
1708     xmlRelaxNGDocumentPtr ret;
1709
1710     if (ctxt->docNr <= 0)
1711         return (0);
1712     ctxt->docNr--;
1713     if (ctxt->docNr > 0)
1714         ctxt->doc = ctxt->docTab[ctxt->docNr - 1];
1715     else
1716         ctxt->doc = NULL;
1717     ret = ctxt->docTab[ctxt->docNr];
1718     ctxt->docTab[ctxt->docNr] = 0;
1719     return (ret);
1720 }
1721
1722 /**
1723  * xmlRelaxNGLoadExternalRef:
1724  * @ctxt: the parser context
1725  * @URL:  the normalized URL
1726  * @ns:  the inherited ns if any
1727  *
1728  * First lookup if the document is already loaded into the parser context,
1729  * check against recursion. If not found the resource is loaded and
1730  * the content is preprocessed before being returned back to the caller.
1731  *
1732  * Returns the xmlRelaxNGDocumentPtr or NULL in case of error
1733  */
1734 static xmlRelaxNGDocumentPtr
1735 xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar *URL,
1736                        const xmlChar *ns) {
1737     xmlRelaxNGDocumentPtr ret = NULL;
1738     xmlDocPtr doc;
1739     xmlNodePtr root;
1740     int i;
1741
1742     /*
1743      * check against recursion in the stack
1744      */
1745     for (i = 0;i < ctxt->docNr;i++) {
1746         if (xmlStrEqual(ctxt->docTab[i]->href, URL)) {
1747             if (ctxt->error != NULL)
1748                 ctxt->error(ctxt->userData,
1749                     "Detected an externalRef recursion for %s\n",
1750                             URL);
1751             ctxt->nbErrors++;
1752             return(NULL);
1753         }
1754     }
1755
1756     /*
1757      * load the document
1758      */
1759     doc = xmlParseFile((const char *) URL);
1760     if (doc == NULL) {
1761         if (ctxt->error != NULL)
1762             ctxt->error(ctxt->userData,
1763                         "xmlRelaxNG: could not load %s\n", URL);
1764         ctxt->nbErrors++;
1765         return (NULL);
1766     }
1767
1768     /*
1769      * Allocate the document structures and register it first.
1770      */
1771     ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
1772     if (ret == NULL) {
1773         if (ctxt->error != NULL)
1774             ctxt->error(ctxt->userData,
1775                         "xmlRelaxNG: allocate memory for doc %s\n", URL);
1776         ctxt->nbErrors++;
1777         xmlFreeDoc(doc);
1778         return (NULL);
1779     }
1780     memset(ret, 0, sizeof(xmlRelaxNGDocument));
1781     ret->doc = doc;
1782     ret->href = xmlStrdup(URL);
1783     ret->next = ctxt->documents;
1784     ctxt->documents = ret;
1785
1786     /*
1787      * transmit the ns if needed
1788      */
1789     if (ns != NULL) {
1790         root = xmlDocGetRootElement(doc);
1791         if (root != NULL) {
1792             if (xmlHasProp(root, BAD_CAST"ns") == NULL) {
1793                 xmlSetProp(root, BAD_CAST"ns", ns);
1794             }
1795         }
1796     }
1797
1798     /*
1799      * push it on the stack and register it in the hash table
1800      */
1801     xmlRelaxNGDocumentPush(ctxt, ret);
1802
1803     /*
1804      * Some preprocessing of the document content
1805      */
1806     doc = xmlRelaxNGCleanupDoc(ctxt, doc);
1807     if (doc == NULL) {
1808         ctxt->doc = NULL;
1809         return(NULL);
1810     }
1811
1812     xmlRelaxNGDocumentPop(ctxt);
1813
1814     return(ret);
1815 }
1816
1817 /************************************************************************
1818  *                                                                      *
1819  *                      Error functions                                 *
1820  *                                                                      *
1821  ************************************************************************/
1822
1823 #define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
1824 #define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
1825 #define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
1826 #define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
1827 #define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
1828
1829 static const char *
1830 xmlRelaxNGDefName(xmlRelaxNGDefinePtr def) {
1831     if (def == NULL)
1832         return("none");
1833     switch(def->type) {
1834         case XML_RELAXNG_EMPTY: return("empty");
1835         case XML_RELAXNG_NOT_ALLOWED: return("notAllowed");
1836         case XML_RELAXNG_EXCEPT: return("except");
1837         case XML_RELAXNG_TEXT: return("text");
1838         case XML_RELAXNG_ELEMENT: return("element");
1839         case XML_RELAXNG_DATATYPE: return("datatype");
1840         case XML_RELAXNG_VALUE: return("value");
1841         case XML_RELAXNG_LIST: return("list");
1842         case XML_RELAXNG_ATTRIBUTE: return("attribute");
1843         case XML_RELAXNG_DEF: return("def");
1844         case XML_RELAXNG_REF: return("ref");
1845         case XML_RELAXNG_EXTERNALREF: return("externalRef");
1846         case XML_RELAXNG_PARENTREF: return("parentRef");
1847         case XML_RELAXNG_OPTIONAL: return("optional");
1848         case XML_RELAXNG_ZEROORMORE: return("zeroOrMore");
1849         case XML_RELAXNG_ONEORMORE: return("oneOrMore");
1850         case XML_RELAXNG_CHOICE: return("choice");
1851         case XML_RELAXNG_GROUP: return("group");
1852         case XML_RELAXNG_INTERLEAVE: return("interleave");
1853         case XML_RELAXNG_START: return("start");
1854         case XML_RELAXNG_NOOP: return("noop");
1855         case XML_RELAXNG_PARAM: return("param");
1856     }
1857     return("unknown");
1858 }
1859
1860 /**
1861  * xmlRelaxNGGetErrorString:
1862  * @err:  the error code
1863  * @arg1:  the first string argument
1864  * @arg2:  the second string argument
1865  *
1866  * computes a formatted error string for the given error code and args
1867  *
1868  * Returns the error string, it must be deallocated by the caller
1869  */
1870 static xmlChar *
1871 xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar *arg1,
1872                          const xmlChar *arg2) {
1873     char msg[1000];
1874
1875     if (arg1 == NULL)
1876         arg1 = BAD_CAST "";
1877     if (arg2 == NULL)
1878         arg2 = BAD_CAST "";
1879
1880     msg[0] = 0;
1881     switch (err) {
1882         case XML_RELAXNG_OK:
1883             return(NULL);
1884         case XML_RELAXNG_ERR_MEMORY:
1885             return(xmlCharStrdup("out of memory"));
1886         case XML_RELAXNG_ERR_TYPE:
1887             snprintf(msg, 1000, "failed to validate type %s", arg1);
1888             break;
1889         case XML_RELAXNG_ERR_TYPEVAL:
1890             snprintf(msg, 1000, "Type %s doesn't allow value '%s'", arg1, arg2);
1891             break;
1892         case XML_RELAXNG_ERR_DUPID:
1893             snprintf(msg, 1000, "ID %s redefined", arg1);
1894             break;
1895         case XML_RELAXNG_ERR_TYPECMP:
1896             snprintf(msg, 1000, "failed to compare type %s", arg1);
1897             break;
1898         case XML_RELAXNG_ERR_NOSTATE:
1899             return(xmlCharStrdup("Internal error: no state"));
1900         case XML_RELAXNG_ERR_NODEFINE:
1901             return(xmlCharStrdup("Internal error: no define"));
1902         case XML_RELAXNG_ERR_INTERNAL:
1903             snprintf(msg, 1000, "Internal error: %s", arg1);
1904             break;
1905         case XML_RELAXNG_ERR_LISTEXTRA:
1906             snprintf(msg, 1000, "Extra data in list: %s", arg1);
1907             break;
1908         case XML_RELAXNG_ERR_INTERNODATA:
1909             return(xmlCharStrdup("Internal: interleave block has no data"));
1910         case XML_RELAXNG_ERR_INTERSEQ:
1911             return(xmlCharStrdup("Invalid sequence in interleave"));
1912         case XML_RELAXNG_ERR_INTEREXTRA:
1913             snprintf(msg, 1000, "Extra element %s in interleave", arg1);
1914             break;
1915         case XML_RELAXNG_ERR_ELEMNAME:
1916             snprintf(msg, 1000, "Expecting element %s, got %s", arg1, arg2);
1917             break;
1918         case XML_RELAXNG_ERR_ELEMNONS:
1919             snprintf(msg, 1000, "Expecting a namespace for element %s", arg1);
1920             break;
1921         case XML_RELAXNG_ERR_ELEMWRONGNS:
1922             snprintf(msg, 1000, "Element %s has wrong namespace: expecting %s",
1923                      arg1, arg2);
1924             break;
1925         case XML_RELAXNG_ERR_ELEMWRONG:
1926             snprintf(msg, 1000, "Did not expect element %s there",
1927                      arg1);
1928             break;
1929         case XML_RELAXNG_ERR_TEXTWRONG:
1930             snprintf(msg, 1000, "Did not expect text in element %s content",
1931                      arg1);
1932             break;
1933         case XML_RELAXNG_ERR_ELEMEXTRANS:
1934             snprintf(msg, 1000, "Expecting no namespace for element %s", arg1);
1935             break;
1936         case XML_RELAXNG_ERR_ELEMNOTEMPTY:
1937             snprintf(msg, 1000, "Expecting element %s to be empty", arg1);
1938             break;
1939         case XML_RELAXNG_ERR_NOELEM:
1940             snprintf(msg, 1000, "Expecting an element %s, got nothing", arg1);
1941             break;
1942         case XML_RELAXNG_ERR_NOTELEM:
1943             return(xmlCharStrdup("Expecting an element got text"));
1944         case XML_RELAXNG_ERR_ATTRVALID:
1945             snprintf(msg, 1000, "Element %s failed to validate attributes",
1946                      arg1);
1947             break;
1948         case XML_RELAXNG_ERR_CONTENTVALID:
1949             snprintf(msg, 1000, "Element %s failed to validate content",
1950                      arg1);
1951             break;
1952         case XML_RELAXNG_ERR_EXTRACONTENT:
1953             snprintf(msg, 1000, "Element %s has extra content: %s",
1954                      arg1, arg2);
1955             break;
1956         case XML_RELAXNG_ERR_INVALIDATTR:
1957             snprintf(msg, 1000, "Invalid attribute %s for element %s",
1958                      arg1, arg2);
1959             break;
1960         case XML_RELAXNG_ERR_LACKDATA:
1961             snprintf(msg, 1000, "Datatype element %s contains no data",
1962                      arg1);
1963             break;
1964         case XML_RELAXNG_ERR_DATAELEM:
1965             snprintf(msg, 1000, "Datatype element %s has child elements",
1966                      arg1);
1967             break;
1968         case XML_RELAXNG_ERR_VALELEM:
1969             snprintf(msg, 1000, "Value element %s has child elements",
1970                      arg1);
1971             break;
1972         case XML_RELAXNG_ERR_LISTELEM:
1973             snprintf(msg, 1000, "List element %s has child elements",
1974                      arg1);
1975             break;
1976         case XML_RELAXNG_ERR_DATATYPE:
1977             snprintf(msg, 1000, "Error validating datatype %s",
1978                      arg1);
1979             break;
1980         case XML_RELAXNG_ERR_VALUE:
1981             snprintf(msg, 1000, "Error validating value %s",
1982                      arg1);
1983             break;
1984         case XML_RELAXNG_ERR_LIST:
1985             return(xmlCharStrdup("Error validating list"));
1986         case XML_RELAXNG_ERR_NOGRAMMAR:
1987             return(xmlCharStrdup("No top grammar defined"));
1988         case XML_RELAXNG_ERR_EXTRADATA:
1989             return(xmlCharStrdup("Extra data in the document"));
1990         default:
1991             return(xmlCharStrdup("Unknown error !"));
1992     }
1993     if (msg[0] == 0) {
1994         snprintf(msg, 1000, "Unknown error code %d", err);
1995     }
1996     msg[1000 - 1] = 0;
1997     return(xmlStrdup((xmlChar *) msg));
1998 }
1999
2000 /**
2001  * xmlRelaxNGValidErrorContext:
2002  * @ctxt:  the validation context
2003  * @node:  the node
2004  * @child:  the node child generating the problem.
2005  *
2006  * Dump informations about the kocation of the error in the instance
2007  */
2008 static void
2009 xmlRelaxNGValidErrorContext(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node,
2010                             xmlNodePtr child)
2011 {
2012     int line = 0;
2013     const xmlChar *file = NULL;
2014     const xmlChar *name = NULL;
2015     const char *type = "error";
2016
2017     if ((ctxt == NULL) || (ctxt->error == NULL))
2018         return;
2019
2020     if (child != NULL)
2021         node = child;
2022
2023     if (node != NULL)  {
2024         if ((node->type == XML_DOCUMENT_NODE) ||
2025             (node->type == XML_HTML_DOCUMENT_NODE)) {
2026             xmlDocPtr doc = (xmlDocPtr) node;
2027
2028             file = doc->URL;
2029         } else {
2030             /*
2031              * Try to find contextual informations to report
2032              */
2033             if (node->type == XML_ELEMENT_NODE) {
2034                 line = (long) node->content;
2035             } else if ((node->prev != NULL) &&
2036                        (node->prev->type == XML_ELEMENT_NODE)) {
2037                 line = (long) node->prev->content;
2038             } else if ((node->parent != NULL) &&
2039                        (node->parent->type == XML_ELEMENT_NODE)) {
2040                 line = (long) node->parent->content;
2041             }
2042             if ((node->doc != NULL) && (node->doc->URL != NULL))
2043                 file = node->doc->URL;
2044             if (node->name != NULL)
2045                 name = node->name;
2046         }
2047     } 
2048     
2049     type = "RNG validity error";
2050
2051     if ((file != NULL) && (line != 0) && (name != NULL))
2052         ctxt->error(ctxt->userData, "%s: file %s line %d element %s\n",
2053                 type, file, line, name);
2054     else if ((file != NULL) && (name != NULL))
2055         ctxt->error(ctxt->userData, "%s: file %s element %s\n",
2056                 type, file, name);
2057     else if ((file != NULL) && (line != 0))
2058         ctxt->error(ctxt->userData, "%s: file %s line %d\n", type, file, line);
2059     else if (file != NULL)
2060         ctxt->error(ctxt->userData, "%s: file %s\n", type, file);
2061     else if (name != NULL)
2062         ctxt->error(ctxt->userData, "%s: element %s\n", type, name);
2063     else
2064         ctxt->error(ctxt->userData, "%s\n", type);
2065 }
2066
2067 /**
2068  * xmlRelaxNGShowValidError:
2069  * @ctxt:  the validation context
2070  * @err:  the error number
2071  * @node:  the node
2072  * @child:  the node child generating the problem.
2073  * @arg1:  the first argument
2074  * @arg2:  the second argument
2075  *
2076  * Show a validation error.
2077  */
2078 static void
2079 xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err,
2080                          xmlNodePtr node, xmlNodePtr child,
2081                          const xmlChar *arg1, const xmlChar *arg2)
2082 {
2083     xmlChar *msg;
2084
2085     if (ctxt->error == NULL)
2086         return;
2087
2088 #ifdef DEBUG_ERROR
2089     xmlGenericError(xmlGenericErrorContext,
2090             "Show error %d\n", err);
2091 #endif
2092     msg = xmlRelaxNGGetErrorString(err, arg1, arg2);
2093     if (msg == NULL)
2094         return;
2095
2096     if (ctxt->errNo == XML_RELAXNG_OK)
2097         ctxt->errNo = err;
2098     xmlRelaxNGValidErrorContext(ctxt, node, child);
2099     ctxt->error(ctxt->userData, "%s\n", msg);
2100     xmlFree(msg);
2101 }
2102
2103 /**
2104  * xmlRelaxNGPopErrors:
2105  * @ctxt:  the validation context
2106  * @level:  the error level in the stack
2107  *
2108  * pop and discard all errors until the given level is reached
2109  */
2110 static void
2111 xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level) {
2112     int i;
2113     xmlRelaxNGValidErrorPtr err;
2114
2115 #ifdef DEBUG_ERROR
2116     xmlGenericError(xmlGenericErrorContext,
2117             "Pop errors till level %d\n", level);
2118 #endif
2119     for (i = level;i < ctxt->errNr;i++) {
2120         err = &ctxt->errTab[i];
2121         if (err->flags & ERROR_IS_DUP) {
2122             if (err->arg1 != NULL)
2123                 xmlFree((xmlChar *)err->arg1);
2124             err->arg1 = NULL;
2125             if (err->arg2 != NULL)
2126                 xmlFree((xmlChar *)err->arg2);
2127             err->arg2 = NULL;
2128             err->flags = 0;
2129         }
2130     }
2131     ctxt->errNr = level;
2132     if (ctxt->errNr <= 0)
2133         ctxt->err = NULL;
2134 }
2135 /**
2136  * xmlRelaxNGDumpValidError:
2137  * @ctxt:  the validation context
2138  *
2139  * Show all validation error over a given index.
2140  */
2141 static void
2142 xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt) {
2143     int i, j, k;
2144     xmlRelaxNGValidErrorPtr err, dup;
2145
2146 #ifdef DEBUG_ERROR
2147     xmlGenericError(xmlGenericErrorContext,
2148             "Dumping error stack %d errors\n", ctxt->errNr);
2149 #endif
2150     for (i = 0, k = 0;i < ctxt->errNr;i++) {
2151         err = &ctxt->errTab[i];
2152         if (k < MAX_ERROR) {
2153             for (j = 0;j < i;j++) {
2154                 dup = &ctxt->errTab[j];
2155                 if ((err->err == dup->err) && (err->node == dup->node) &&
2156                     (xmlStrEqual(err->arg1, dup->arg1)) &&
2157                     (xmlStrEqual(err->arg2, dup->arg2))) {
2158                     goto skip;
2159                 }
2160             }
2161             xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,
2162                                      err->arg1, err->arg2);
2163             k++;
2164         }
2165 skip:
2166         if (err->flags & ERROR_IS_DUP) {
2167             if (err->arg1 != NULL)
2168                 xmlFree((xmlChar *)err->arg1);
2169             err->arg1 = NULL;
2170             if (err->arg2 != NULL)
2171                 xmlFree((xmlChar *)err->arg2);
2172             err->arg2 = NULL;
2173             err->flags = 0;
2174         }
2175     }
2176     ctxt->errNr = 0;
2177 }
2178 /**
2179  * xmlRelaxNGAddValidError:
2180  * @ctxt:  the validation context
2181  * @err:  the error number
2182  * @arg1:  the first argument
2183  * @arg2:  the second argument
2184  * @dup:  need to dup the args
2185  *
2186  * Register a validation error, either generating it if it's sure
2187  * or stacking it for later handling if unsure.
2188  */
2189 static void
2190 xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidErr err,
2191                         const xmlChar *arg1, const xmlChar *arg2, int dup)
2192 {
2193     if ((ctxt == NULL) || (ctxt->error == NULL))
2194         return;
2195
2196 #ifdef DEBUG_ERROR
2197     xmlGenericError(xmlGenericErrorContext,
2198             "Adding error %d\n", err);
2199 #endif
2200     /*
2201      * generate the error directly
2202      */
2203     if (((ctxt->flags & 1) == 0) || (ctxt->flags & 2)) {
2204         xmlNodePtr node, seq;
2205         /*
2206          * Flush first any stacked error which might be the
2207          * real cause of the problem.
2208          */
2209         if (ctxt->errNr != 0)
2210             xmlRelaxNGDumpValidError(ctxt);
2211         if (ctxt->state != NULL) {
2212             node = ctxt->state->node;
2213             seq = ctxt->state->seq;
2214         } else {
2215             node = seq = NULL;
2216         }
2217         xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2);
2218     }
2219     /*
2220      * Stack the error for later processing if needed
2221      */
2222     else {
2223         xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);
2224     }
2225 }
2226
2227
2228 /************************************************************************
2229  *                                                                      *
2230  *                      Type library hooks                              *
2231  *                                                                      *
2232  ************************************************************************/
2233 static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt,
2234                                     const xmlChar *str);
2235
2236 /**
2237  * xmlRelaxNGSchemaTypeHave:
2238  * @data:  data needed for the library
2239  * @type:  the type name
2240  *
2241  * Check if the given type is provided by
2242  * the W3C XMLSchema Datatype library.
2243  *
2244  * Returns 1 if yes, 0 if no and -1 in case of error.
2245  */
2246 static int
2247 xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED,
2248                          const xmlChar *type) {
2249     xmlSchemaTypePtr typ;
2250
2251     if (type == NULL)
2252         return(-1);
2253     typ = xmlSchemaGetPredefinedType(type, 
2254                BAD_CAST "http://www.w3.org/2001/XMLSchema");
2255     if (typ == NULL)
2256         return(0);
2257     return(1);
2258 }
2259
2260 /**
2261  * xmlRelaxNGSchemaTypeCheck:
2262  * @data:  data needed for the library
2263  * @type:  the type name
2264  * @value:  the value to check
2265  * @node:  the node
2266  *
2267  * Check if the given type and value are validated by
2268  * the W3C XMLSchema Datatype library.
2269  *
2270  * Returns 1 if yes, 0 if no and -1 in case of error.
2271  */
2272 static int
2273 xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
2274                           const xmlChar *type,
2275                           const xmlChar *value,
2276                           void **result,
2277                           xmlNodePtr node) {
2278     xmlSchemaTypePtr typ;
2279     int ret;
2280
2281     if ((type == NULL) || (value == NULL))
2282         return(-1);
2283     typ = xmlSchemaGetPredefinedType(type, 
2284                BAD_CAST "http://www.w3.org/2001/XMLSchema");
2285     if (typ == NULL)
2286         return(-1);
2287     ret = xmlSchemaValPredefTypeNode(typ, value,
2288                                      (xmlSchemaValPtr *) result, node);
2289     if (ret == 2) /* special ID error code */
2290         return(2);
2291     if (ret == 0)
2292         return(1);
2293     if (ret > 0)
2294         return(0);
2295     return(-1);
2296 }
2297
2298 /**
2299  * xmlRelaxNGSchemaFacetCheck:
2300  * @data:  data needed for the library
2301  * @type:  the type name
2302  * @facet:  the facet name
2303  * @val:  the facet value
2304  * @strval:  the string value
2305  * @value:  the value to check
2306  *
2307  * Function provided by a type library to check a value facet
2308  *
2309  * Returns 1 if yes, 0 if no and -1 in case of error.
2310  */
2311 static int
2312 xmlRelaxNGSchemaFacetCheck (void *data ATTRIBUTE_UNUSED, const xmlChar *type,
2313                             const xmlChar *facetname, const xmlChar *val,
2314                             const xmlChar *strval, void *value) {
2315     xmlSchemaFacetPtr facet;
2316     xmlSchemaTypePtr typ;
2317     int ret;
2318
2319     if ((type == NULL) || (strval == NULL))
2320         return(-1);
2321     typ = xmlSchemaGetPredefinedType(type, 
2322                BAD_CAST "http://www.w3.org/2001/XMLSchema");
2323     if (typ == NULL)
2324         return(-1);
2325
2326     facet = xmlSchemaNewFacet();
2327     if (facet == NULL)
2328         return(-1);
2329
2330     if (xmlStrEqual(facetname, BAD_CAST "minInclusive"))  {
2331         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
2332     } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive"))  {
2333         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
2334     } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive"))  {
2335         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
2336     } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive"))  {
2337         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
2338     } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits"))  {
2339         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
2340     } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits"))  {
2341         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
2342     } else if (xmlStrEqual(facetname, BAD_CAST "pattern"))  {
2343         facet->type = XML_SCHEMA_FACET_PATTERN;
2344     } else if (xmlStrEqual(facetname, BAD_CAST "enumeration"))  {
2345         facet->type = XML_SCHEMA_FACET_ENUMERATION;
2346     } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace"))  {
2347         facet->type = XML_SCHEMA_FACET_WHITESPACE;
2348     } else if (xmlStrEqual(facetname, BAD_CAST "length"))  {
2349         facet->type = XML_SCHEMA_FACET_LENGTH;
2350     } else if (xmlStrEqual(facetname, BAD_CAST "maxLength"))  {
2351         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
2352     } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) {
2353         facet->type = XML_SCHEMA_FACET_MINLENGTH;
2354     } else {
2355         xmlSchemaFreeFacet(facet);
2356         return(-1);
2357     }
2358     facet->value = xmlStrdup(val);
2359     ret = xmlSchemaCheckFacet(facet, typ, NULL, type);
2360     if (ret != 0) {
2361         xmlSchemaFreeFacet(facet);
2362         return(-1);
2363     }
2364     ret = xmlSchemaValidateFacet(typ, facet, strval, value);
2365     xmlSchemaFreeFacet(facet);
2366     if (ret != 0)
2367         return(-1);
2368     return(0);
2369 }
2370
2371 /**
2372  * xmlRelaxNGSchemaFreeValue:
2373  * @data:  data needed for the library
2374  * @value:  the value to free
2375  *
2376  * Function provided by a type library to free a Schemas value
2377  *
2378  * Returns 1 if yes, 0 if no and -1 in case of error.
2379  */
2380 static void
2381 xmlRelaxNGSchemaFreeValue (void *data ATTRIBUTE_UNUSED, void *value) {
2382     xmlSchemaFreeValue(value);
2383 }
2384
2385 /**
2386  * xmlRelaxNGSchemaTypeCompare:
2387  * @data:  data needed for the library
2388  * @type:  the type name
2389  * @value1:  the first value
2390  * @value2:  the second value
2391  *
2392  * Compare two values for equality accordingly a type from the W3C XMLSchema
2393  * Datatype library.
2394  *
2395  * Returns 1 if equal, 0 if no and -1 in case of error.
2396  */
2397 static int
2398 xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
2399                             const xmlChar *type,
2400                             const xmlChar *value1,
2401                             xmlNodePtr ctxt1,
2402                             void *comp1,
2403                             const xmlChar *value2,
2404                             xmlNodePtr ctxt2) {
2405     int ret;
2406     xmlSchemaTypePtr typ;
2407     xmlSchemaValPtr res1 = NULL, res2 = NULL;
2408
2409     if ((type == NULL) || (value1 == NULL) || (value2 == NULL))
2410         return(-1);
2411     typ = xmlSchemaGetPredefinedType(type, 
2412                BAD_CAST "http://www.w3.org/2001/XMLSchema");
2413     if (typ == NULL)
2414         return(-1);
2415     if (comp1 == NULL) {
2416         ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1);
2417         if (ret != 0)
2418             return(-1);
2419         if (res1 == NULL)
2420             return(-1);
2421     } else {
2422         res1 = (xmlSchemaValPtr) comp1;
2423     }
2424     ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2);
2425     if (ret != 0) {
2426         xmlSchemaFreeValue(res1);
2427         return(-1);
2428     }
2429     if (res1 == NULL) {
2430         xmlSchemaFreeValue(res1);
2431         return(-1);
2432     }
2433     ret = xmlSchemaCompareValues(res1, res2);
2434     if (res1 != (xmlSchemaValPtr) comp1)
2435         xmlSchemaFreeValue(res1);
2436     xmlSchemaFreeValue(res2);
2437     if (ret == -2)
2438         return(-1);
2439     if (ret == 0)
2440         return(1);
2441     return(0);
2442 }
2443  
2444 /**
2445  * xmlRelaxNGDefaultTypeHave:
2446  * @data:  data needed for the library
2447  * @type:  the type name
2448  *
2449  * Check if the given type is provided by
2450  * the default datatype library.
2451  *
2452  * Returns 1 if yes, 0 if no and -1 in case of error.
2453  */
2454 static int
2455 xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar *type) {
2456     if (type == NULL)
2457         return(-1);
2458     if (xmlStrEqual(type, BAD_CAST "string"))
2459         return(1);
2460     if (xmlStrEqual(type, BAD_CAST "token"))
2461         return(1);
2462     return(0);
2463 }
2464
2465 /**
2466  * xmlRelaxNGDefaultTypeCheck:
2467  * @data:  data needed for the library
2468  * @type:  the type name
2469  * @value:  the value to check
2470  * @node:  the node
2471  *
2472  * Check if the given type and value are validated by
2473  * the default datatype library.
2474  *
2475  * Returns 1 if yes, 0 if no and -1 in case of error.
2476  */
2477 static int
2478 xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
2479                            const xmlChar *type ATTRIBUTE_UNUSED,
2480                            const xmlChar *value ATTRIBUTE_UNUSED,
2481                            void **result ATTRIBUTE_UNUSED,
2482                            xmlNodePtr node ATTRIBUTE_UNUSED) {
2483     if (value == NULL)
2484         return(-1);
2485     if (xmlStrEqual(type, BAD_CAST "string"))
2486         return(1);
2487     if (xmlStrEqual(type, BAD_CAST "token")) {
2488         return(1);
2489     }
2490
2491     return(0);
2492 }
2493
2494 /**
2495  * xmlRelaxNGDefaultTypeCompare:
2496  * @data:  data needed for the library
2497  * @type:  the type name
2498  * @value1:  the first value
2499  * @value2:  the second value
2500  *
2501  * Compare two values accordingly a type from the default
2502  * datatype library.
2503  *
2504  * Returns 1 if yes, 0 if no and -1 in case of error.
2505  */
2506 static int
2507 xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
2508                              const xmlChar *type,
2509                              const xmlChar *value1,
2510                              xmlNodePtr ctxt1 ATTRIBUTE_UNUSED,
2511                              void *comp1 ATTRIBUTE_UNUSED,
2512                              const xmlChar *value2,
2513                              xmlNodePtr ctxt2 ATTRIBUTE_UNUSED) {
2514     int ret = -1;
2515
2516     if (xmlStrEqual(type, BAD_CAST "string")) {
2517         ret = xmlStrEqual(value1, value2);
2518     } else if (xmlStrEqual(type, BAD_CAST "token")) {
2519         if (!xmlStrEqual(value1, value2)) {
2520             xmlChar *nval, *nvalue;
2521
2522             /*
2523              * TODO: trivial optimizations are possible by
2524              * computing at compile-time
2525              */
2526             nval = xmlRelaxNGNormalize(NULL, value1);
2527             nvalue = xmlRelaxNGNormalize(NULL, value2);
2528
2529             if ((nval == NULL) || (nvalue == NULL))
2530                 ret = -1;
2531             else if (xmlStrEqual(nval, nvalue))
2532                 ret = 1;
2533             else
2534                 ret = 0;
2535             if (nval != NULL)
2536                 xmlFree(nval);
2537             if (nvalue != NULL)
2538                 xmlFree(nvalue);
2539         } else
2540             ret = 1;
2541     }
2542     return(ret);
2543 }
2544  
2545 static int xmlRelaxNGTypeInitialized = 0;
2546 static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
2547
2548 /**
2549  * xmlRelaxNGFreeTypeLibrary:
2550  * @lib:  the type library structure
2551  * @namespace:  the URI bound to the library
2552  *
2553  * Free the structure associated to the type library
2554  */
2555 static void
2556 xmlRelaxNGFreeTypeLibrary(xmlRelaxNGTypeLibraryPtr lib,
2557                           const xmlChar *namespace ATTRIBUTE_UNUSED) {
2558     if (lib == NULL)
2559         return;
2560     if (lib->namespace != NULL)
2561         xmlFree((xmlChar *)lib->namespace);
2562     xmlFree(lib);
2563 }
2564
2565 /**
2566  * xmlRelaxNGRegisterTypeLibrary:
2567  * @namespace:  the URI bound to the library
2568  * @data:  data associated to the library
2569  * @have:  the provide function
2570  * @check:  the checking function
2571  * @comp:  the comparison function
2572  *
2573  * Register a new type library
2574  *
2575  * Returns 0 in case of success and -1 in case of error.
2576  */
2577 static int
2578 xmlRelaxNGRegisterTypeLibrary(const xmlChar *namespace, void *data,
2579     xmlRelaxNGTypeHave have, xmlRelaxNGTypeCheck check,
2580     xmlRelaxNGTypeCompare comp, xmlRelaxNGFacetCheck facet,
2581     xmlRelaxNGTypeFree freef) {
2582     xmlRelaxNGTypeLibraryPtr lib;
2583     int ret;
2584
2585     if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
2586         (check == NULL) || (comp == NULL))
2587         return(-1);
2588     if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
2589         xmlGenericError(xmlGenericErrorContext,
2590                 "Relax-NG types library '%s' already registered\n",
2591                         namespace);
2592         return(-1);
2593     }
2594     lib = (xmlRelaxNGTypeLibraryPtr) xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
2595     if (lib == NULL) {
2596         xmlGenericError(xmlGenericErrorContext,
2597                 "Relax-NG types library '%s' malloc() failed\n",
2598                         namespace);
2599         return (-1);
2600     }
2601     memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
2602     lib->namespace = xmlStrdup(namespace);
2603     lib->data = data;
2604     lib->have = have;
2605     lib->comp = comp;
2606     lib->check = check;
2607     lib->facet = facet;
2608     lib->freef = freef;
2609     ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
2610     if (ret < 0) {
2611         xmlGenericError(xmlGenericErrorContext,
2612                 "Relax-NG types library failed to register '%s'\n",
2613                         namespace);
2614         xmlRelaxNGFreeTypeLibrary(lib, namespace);
2615         return(-1);
2616     }
2617     return(0);
2618 }
2619
2620 /**
2621  * xmlRelaxNGInitTypes:
2622  *
2623  * Initilize the default type libraries.
2624  *
2625  * Returns 0 in case of success and -1 in case of error.
2626  */
2627 static int
2628 xmlRelaxNGInitTypes(void) {
2629     if (xmlRelaxNGTypeInitialized != 0)
2630         return(0);
2631     xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
2632     if (xmlRelaxNGRegisteredTypes == NULL) {
2633         xmlGenericError(xmlGenericErrorContext,
2634                 "Failed to allocate sh table for Relax-NG types\n");
2635         return(-1);
2636     }
2637     xmlRelaxNGRegisterTypeLibrary(
2638             BAD_CAST "http://www.w3.org/2001/XMLSchema-datatypes",
2639             NULL,
2640             xmlRelaxNGSchemaTypeHave,
2641             xmlRelaxNGSchemaTypeCheck,
2642             xmlRelaxNGSchemaTypeCompare,
2643             xmlRelaxNGSchemaFacetCheck,
2644             xmlRelaxNGSchemaFreeValue);
2645     xmlRelaxNGRegisterTypeLibrary(
2646             xmlRelaxNGNs,
2647             NULL,
2648             xmlRelaxNGDefaultTypeHave,
2649             xmlRelaxNGDefaultTypeCheck,
2650             xmlRelaxNGDefaultTypeCompare,
2651             NULL,
2652             NULL);
2653     xmlRelaxNGTypeInitialized = 1;
2654     return(0);
2655 }
2656
2657 /**
2658  * xmlRelaxNGCleanupTypes:
2659  *
2660  * Cleanup the default Schemas type library associated to RelaxNG
2661  */
2662 void    
2663 xmlRelaxNGCleanupTypes(void) {
2664     xmlSchemaCleanupTypes();
2665     if (xmlRelaxNGTypeInitialized == 0)
2666         return;
2667     xmlHashFree(xmlRelaxNGRegisteredTypes, (xmlHashDeallocator)
2668                 xmlRelaxNGFreeTypeLibrary);
2669     xmlRelaxNGTypeInitialized = 0;
2670 }
2671
2672 /************************************************************************
2673  *                                                                      *
2674  *              Compiling element content into regexp                   *
2675  *                                                                      *
2676  * Sometime the element content can be compiled into a pure regexp,     *
2677  * This allows a faster execution and streamability at that level       *
2678  *                                                                      *
2679  ************************************************************************/
2680
2681 static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,
2682                                 xmlRelaxNGDefinePtr def);
2683
2684 /**
2685  * xmlRelaxNGIsCompileable:
2686  * @define:  the definition to check
2687  *
2688  * Check if a definition is nullable.
2689  *
2690  * Returns 1 if yes, 0 if no and -1 in case of error
2691  */
2692 static int
2693 xmlRelaxNGIsCompileable(xmlRelaxNGDefinePtr def) {
2694     int ret = -1;
2695
2696     if (def == NULL) {
2697         return(-1);
2698     }
2699     if ((def->type != XML_RELAXNG_ELEMENT) &&
2700         (def->dflags & IS_COMPILABLE))
2701         return(1);
2702     if ((def->type != XML_RELAXNG_ELEMENT) &&
2703         (def->dflags & IS_NOT_COMPILABLE))
2704         return(0);
2705     switch(def->type) {
2706         case XML_RELAXNG_NOOP:
2707             ret = xmlRelaxNGIsCompileable(def->content);
2708             break;
2709         case XML_RELAXNG_TEXT:
2710         case XML_RELAXNG_EMPTY:
2711             ret = 1;
2712             break;
2713         case XML_RELAXNG_ELEMENT:
2714             /*
2715              * Check if the element content is compileable
2716              */
2717             if (((def->dflags & IS_NOT_COMPILABLE) == 0) &&
2718                 ((def->dflags & IS_COMPILABLE) == 0)) {
2719                 xmlRelaxNGDefinePtr list;
2720                 list = def->content;
2721                 while (list != NULL) {
2722                     ret = xmlRelaxNGIsCompileable(list);
2723                     if (ret != 1)
2724                         break;
2725                     list = list->next;
2726                 }
2727                 if (ret == 0) def->dflags |= IS_NOT_COMPILABLE;
2728                 if (ret == 1) def->dflags |= IS_COMPILABLE;
2729 #ifdef DEBUG_COMPILE
2730                 if (ret == 1) {
2731                     xmlGenericError(xmlGenericErrorContext,
2732                                 "element content for %s is compilable\n",
2733                                 def->name);
2734                 } else if (ret == 0) {
2735                     xmlGenericError(xmlGenericErrorContext,
2736                                 "element content for %s is not compilable\n",
2737                                 def->name);
2738                 } else {
2739                     xmlGenericError(xmlGenericErrorContext,
2740                             "Problem in RelaxNGIsCompileable for element %s\n",
2741                                 def->name);
2742                 }
2743 #endif
2744             }
2745             /*
2746              * All elements return a compileable status unless they
2747              * are generic like anyName
2748              */
2749             if ((def->nameClass != NULL) || (def->name == NULL))
2750                 ret = 0;
2751             else
2752                 ret = 1;
2753             return(ret);
2754         case XML_RELAXNG_REF:
2755         case XML_RELAXNG_EXTERNALREF:
2756         case XML_RELAXNG_PARENTREF:
2757             if (def->depth == -20) {
2758                 return(1);
2759             } else {
2760                 xmlRelaxNGDefinePtr list;
2761
2762                 def->depth = -20;
2763                 list = def->content;
2764                 while (list != NULL) {
2765                     ret = xmlRelaxNGIsCompileable(list);
2766                     if (ret != 1)
2767                         break;
2768                     list = list->next;
2769                 }
2770             }
2771             break;
2772         case XML_RELAXNG_START:
2773         case XML_RELAXNG_OPTIONAL:
2774         case XML_RELAXNG_ZEROORMORE:
2775         case XML_RELAXNG_ONEORMORE:
2776         case XML_RELAXNG_CHOICE:
2777         case XML_RELAXNG_GROUP:
2778         case XML_RELAXNG_DEF: {
2779             xmlRelaxNGDefinePtr list;
2780
2781             list = def->content;
2782             while (list != NULL) {
2783                 ret = xmlRelaxNGIsCompileable(list);
2784                 if (ret != 1)
2785                     break;
2786                 list = list->next;
2787             }
2788             break;
2789         }
2790         case XML_RELAXNG_EXCEPT:
2791         case XML_RELAXNG_ATTRIBUTE:
2792         case XML_RELAXNG_INTERLEAVE:
2793         case XML_RELAXNG_DATATYPE:
2794         case XML_RELAXNG_LIST:
2795         case XML_RELAXNG_PARAM:
2796         case XML_RELAXNG_VALUE:
2797             ret = 0;
2798             break;
2799         case XML_RELAXNG_NOT_ALLOWED:
2800             ret = -1;
2801             break;
2802     }
2803     if (ret == 0) def->dflags |= IS_NOT_COMPILABLE;
2804     if (ret == 1) def->dflags |= IS_COMPILABLE;
2805 #ifdef DEBUG_COMPILE
2806     if (ret == 1) {
2807         xmlGenericError(xmlGenericErrorContext,
2808                     "RelaxNGIsCompileable %s : true\n",
2809                     xmlRelaxNGDefName(def));
2810     } else if (ret == 0) {
2811         xmlGenericError(xmlGenericErrorContext,
2812                     "RelaxNGIsCompileable %s : false\n",
2813                     xmlRelaxNGDefName(def));
2814     } else {
2815         xmlGenericError(xmlGenericErrorContext,
2816                     "Problem in RelaxNGIsCompileable %s\n",
2817                     xmlRelaxNGDefName(def));
2818     }
2819 #endif
2820     return(ret);
2821 }
2822
2823 /**
2824  * xmlRelaxNGCompile:
2825  * ctxt:  the RelaxNG parser context
2826  * @define:  the definition tree to compile
2827  *
2828  * Compile the set of definitions, it works recursively, till the
2829  * element boundaries, where it tries to compile the content if possible
2830  *
2831  * Returns 0 if success and -1 in case of error
2832  */
2833 static int
2834 xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) {
2835     int ret = 0;
2836     xmlRelaxNGDefinePtr list;
2837
2838     if ((ctxt == NULL) || (def == NULL)) return(-1);
2839
2840     switch(def->type) {
2841         case XML_RELAXNG_START:
2842             if ((xmlRelaxNGIsCompileable(def) == 1) && (def->depth != -25)) {
2843                 xmlAutomataPtr oldam = ctxt->am;
2844                 xmlAutomataStatePtr oldstate = ctxt->state;
2845
2846                 def->depth = -25;
2847
2848                 list = def->content;
2849                 ctxt->am = xmlNewAutomata();
2850                 if (ctxt->am == NULL)
2851                     return(-1);
2852                 ctxt->state = xmlAutomataGetInitState(ctxt->am);
2853                 while (list != NULL) {
2854                     xmlRelaxNGCompile(ctxt, list);
2855                     list = list->next;
2856                 }
2857                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
2858                 def->contModel = xmlAutomataCompile(ctxt->am);
2859                 xmlRegexpIsDeterminist(def->contModel);
2860
2861                 xmlFreeAutomata(ctxt->am);
2862                 ctxt->state = oldstate;
2863                 ctxt->am = oldam;
2864             }
2865             break;
2866         case XML_RELAXNG_ELEMENT:
2867             if ((ctxt->am != NULL) && (def->name != NULL)) {
2868                 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
2869                    ctxt->state, NULL, def->name, def->ns, def);
2870             }
2871             if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
2872                 xmlAutomataPtr oldam = ctxt->am;
2873                 xmlAutomataStatePtr oldstate = ctxt->state;
2874
2875                 def->depth = -25;
2876
2877                 list = def->content;
2878                 ctxt->am = xmlNewAutomata();
2879                 if (ctxt->am == NULL)
2880                     return(-1);
2881                 ctxt->state = xmlAutomataGetInitState(ctxt->am);
2882                 while (list != NULL) {
2883                     xmlRelaxNGCompile(ctxt, list);
2884                     list = list->next;
2885                 }
2886                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
2887                 def->contModel = xmlAutomataCompile(ctxt->am);
2888                 if (!xmlRegexpIsDeterminist(def->contModel)) {
2889                     /*
2890                      * we can only use the automata if it is determinist
2891                      */
2892                     xmlRegFreeRegexp(def->contModel);
2893                     def->contModel = NULL;
2894                 }
2895                 xmlFreeAutomata(ctxt->am);
2896                 ctxt->state = oldstate;
2897                 ctxt->am = oldam;
2898             } else {
2899                 xmlAutomataPtr oldam = ctxt->am;
2900
2901                 /*
2902                  * we can't build the content model for this element content
2903                  * but it still might be possible to build it for some of its
2904                  * children, recurse.
2905                  */
2906                 ret = xmlRelaxNGTryCompile(ctxt, def);
2907                 ctxt->am = oldam;
2908             }
2909             break;
2910         case XML_RELAXNG_NOOP:
2911             ret = xmlRelaxNGCompile(ctxt, def->content);
2912             break;
2913         case XML_RELAXNG_OPTIONAL: {
2914             xmlAutomataStatePtr oldstate = ctxt->state;
2915             
2916             xmlRelaxNGCompile(ctxt, def->content);
2917             xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
2918             break;
2919         }
2920         case XML_RELAXNG_ZEROORMORE: {
2921             xmlAutomataStatePtr oldstate;
2922
2923             ctxt->state = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
2924             oldstate = ctxt->state;
2925             list = def->content;
2926             while (list != NULL) {
2927                 xmlRelaxNGCompile(ctxt, list);
2928                 list = list->next;
2929             }
2930             xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
2931             ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
2932             break;
2933         }
2934         case XML_RELAXNG_ONEORMORE: {
2935             xmlAutomataStatePtr oldstate;
2936
2937             list = def->content;
2938             while (list != NULL) {
2939                 xmlRelaxNGCompile(ctxt, list);
2940                 list = list->next;
2941             }
2942             oldstate = ctxt->state;
2943             list = def->content;
2944             while (list != NULL) {
2945                 xmlRelaxNGCompile(ctxt, list);
2946                 list = list->next;
2947             }
2948             xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
2949             ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
2950             break;
2951         }
2952         case XML_RELAXNG_CHOICE: {
2953             xmlAutomataStatePtr target = NULL;
2954             xmlAutomataStatePtr oldstate = ctxt->state;
2955             
2956             list = def->content;
2957             while (list != NULL) {
2958                 ctxt->state = oldstate;
2959                 ret = xmlRelaxNGCompile(ctxt, list);
2960                 if (ret != 0)
2961                     break;
2962                 if (target == NULL)
2963                     target = ctxt->state;
2964                 else {
2965                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, target);
2966                 }
2967                 list = list->next;
2968             }
2969             ctxt->state = target;
2970
2971             break;
2972         }
2973         case XML_RELAXNG_REF:
2974         case XML_RELAXNG_EXTERNALREF:
2975         case XML_RELAXNG_PARENTREF:
2976         case XML_RELAXNG_GROUP:
2977         case XML_RELAXNG_DEF:
2978             list = def->content;
2979             while (list != NULL) {
2980                 ret = xmlRelaxNGCompile(ctxt, list);
2981                 if (ret != 0)
2982                     break;
2983                 list = list->next;
2984             }
2985             break;
2986         case XML_RELAXNG_TEXT: {
2987             xmlAutomataStatePtr oldstate;
2988
2989             ctxt->state = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
2990             oldstate = ctxt->state;
2991             xmlRelaxNGCompile(ctxt, def->content);
2992             xmlAutomataNewTransition(ctxt->am, ctxt->state, ctxt->state,
2993                                      BAD_CAST "#text", NULL);
2994             ctxt->state = xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
2995             break;
2996         }
2997         case XML_RELAXNG_EMPTY:
2998             ctxt->state = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
2999             break;
3000         case XML_RELAXNG_EXCEPT:
3001         case XML_RELAXNG_ATTRIBUTE:
3002         case XML_RELAXNG_INTERLEAVE:
3003         case XML_RELAXNG_NOT_ALLOWED:
3004         case XML_RELAXNG_DATATYPE:
3005         case XML_RELAXNG_LIST:
3006         case XML_RELAXNG_PARAM:
3007         case XML_RELAXNG_VALUE:
3008             /* This should not happen and generate an internal error */
3009             fprintf(stderr, "RNG internal error trying to compile %s\n",
3010                     xmlRelaxNGDefName(def));
3011             break;
3012     }
3013     return(ret);
3014 }
3015
3016 /**
3017  * xmlRelaxNGTryCompile:
3018  * ctxt:  the RelaxNG parser context
3019  * @define:  the definition tree to compile
3020  *
3021  * Try to compile the set of definitions, it works recursively,
3022  * possibly ignoring parts which cannot be compiled.
3023  *
3024  * Returns 0 if success and -1 in case of error
3025  */
3026 static int
3027 xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) {
3028     int ret = 0;
3029     xmlRelaxNGDefinePtr list;
3030
3031     if ((ctxt == NULL) || (def == NULL)) return(-1);
3032
3033     if ((def->type == XML_RELAXNG_START) ||
3034         (def->type == XML_RELAXNG_ELEMENT)) {
3035         ret = xmlRelaxNGIsCompileable(def);
3036         if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
3037             ctxt->am = NULL;
3038             ret = xmlRelaxNGCompile(ctxt, def);
3039 #ifdef DEBUG_PROGRESSIVE
3040             if (ret == 0) {
3041                 if (def->type == XML_RELAXNG_START)
3042                     xmlGenericError(xmlGenericErrorContext,
3043                         "compiled the start\n");
3044                 else
3045                     xmlGenericError(xmlGenericErrorContext,
3046                         "compiled element %s\n", def->name);
3047             } else {
3048                 if (def->type == XML_RELAXNG_START)
3049                     xmlGenericError(xmlGenericErrorContext,
3050                         "failed to compile the start\n");
3051                 else
3052                     xmlGenericError(xmlGenericErrorContext,
3053                         "failed to compile element %s\n", def->name);
3054             }
3055 #endif
3056             return(ret);
3057         }
3058     }
3059     switch(def->type) {
3060         case XML_RELAXNG_NOOP:
3061             ret = xmlRelaxNGTryCompile(ctxt, def->content);
3062             break;
3063         case XML_RELAXNG_TEXT:
3064         case XML_RELAXNG_DATATYPE:
3065         case XML_RELAXNG_LIST:
3066         case XML_RELAXNG_PARAM:
3067         case XML_RELAXNG_VALUE:
3068         case XML_RELAXNG_EMPTY:
3069         case XML_RELAXNG_ELEMENT:
3070             ret = 0;
3071             break;
3072         case XML_RELAXNG_OPTIONAL:
3073         case XML_RELAXNG_ZEROORMORE:
3074         case XML_RELAXNG_ONEORMORE:
3075         case XML_RELAXNG_CHOICE:
3076         case XML_RELAXNG_GROUP:
3077         case XML_RELAXNG_DEF:
3078         case XML_RELAXNG_START:
3079         case XML_RELAXNG_REF:
3080         case XML_RELAXNG_EXTERNALREF:
3081         case XML_RELAXNG_PARENTREF:
3082             list = def->content;
3083             while (list != NULL) {
3084                 ret = xmlRelaxNGTryCompile(ctxt, list);
3085                 if (ret != 0)
3086                     break;
3087                 list = list->next;
3088             }
3089             break;
3090         case XML_RELAXNG_EXCEPT:
3091         case XML_RELAXNG_ATTRIBUTE:
3092         case XML_RELAXNG_INTERLEAVE:
3093         case XML_RELAXNG_NOT_ALLOWED:
3094             ret = 0;
3095             break;
3096     }
3097     return(ret);
3098 }
3099
3100 /************************************************************************
3101  *                                                                      *
3102  *                      Parsing functions                               *
3103  *                                                                      *
3104  ************************************************************************/
3105
3106 static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(
3107               xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node);
3108 static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(
3109               xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node);
3110 static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(
3111               xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes, int group);
3112 static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(
3113               xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node);
3114 static xmlRelaxNGPtr xmlRelaxNGParseDocument(
3115               xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node);
3116 static int xmlRelaxNGParseGrammarContent(
3117               xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes);
3118 static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(
3119               xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
3120               xmlRelaxNGDefinePtr def);
3121 static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(
3122               xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes);
3123 static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt, 
3124               xmlRelaxNGDefinePtr define, xmlNodePtr elem);
3125
3126
3127 #define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
3128
3129 /**
3130  * xmlRelaxNGIsNullable:
3131  * @define:  the definition to verify
3132  *
3133  * Check if a definition is nullable.
3134  *
3135  * Returns 1 if yes, 0 if no and -1 in case of error
3136  */
3137 static int
3138 xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define) {
3139     int ret;
3140     if (define == NULL)
3141         return(-1);
3142
3143     if (define->dflags & IS_NULLABLE)
3144         return(1);
3145     if (define->dflags & IS_NOT_NULLABLE)
3146         return(0);
3147     switch (define->type) {
3148         case XML_RELAXNG_EMPTY:
3149         case XML_RELAXNG_TEXT:
3150             ret = 1; break;
3151         case XML_RELAXNG_NOOP:
3152         case XML_RELAXNG_DEF:
3153         case XML_RELAXNG_REF:
3154         case XML_RELAXNG_EXTERNALREF:
3155         case XML_RELAXNG_PARENTREF:
3156         case XML_RELAXNG_ONEORMORE:
3157             ret = xmlRelaxNGIsNullable(define->content);
3158             break;
3159         case XML_RELAXNG_EXCEPT:
3160         case XML_RELAXNG_NOT_ALLOWED:
3161         case XML_RELAXNG_ELEMENT:
3162         case XML_RELAXNG_DATATYPE:
3163         case XML_RELAXNG_PARAM:
3164         case XML_RELAXNG_VALUE:
3165         case XML_RELAXNG_LIST:
3166         case XML_RELAXNG_ATTRIBUTE:
3167             ret = 0; break;
3168         case XML_RELAXNG_CHOICE: {
3169             xmlRelaxNGDefinePtr list = define->content;
3170
3171             while (list != NULL) {
3172                 ret = xmlRelaxNGIsNullable(list);
3173                 if (ret != 0)
3174                     goto done;
3175                 list = list->next;
3176             }
3177             ret = 0; break;
3178         }
3179         case XML_RELAXNG_START:
3180         case XML_RELAXNG_INTERLEAVE:
3181         case XML_RELAXNG_GROUP: {
3182             xmlRelaxNGDefinePtr list = define->content;
3183
3184             while (list != NULL) {
3185                 ret = xmlRelaxNGIsNullable(list);
3186                 if (ret != 1)
3187                     goto done;
3188                 list = list->next;
3189             }
3190             return(1);
3191         }
3192         default:
3193             return(-1);
3194     }
3195 done:
3196     if (ret == 0)
3197         define->dflags |= IS_NOT_NULLABLE;
3198     if (ret == 1)
3199         define->dflags |= IS_NULLABLE;
3200     return(ret);
3201 }
3202
3203 /**
3204  * xmlRelaxNGIsBlank:
3205  * @str:  a string
3206  *
3207  * Check if a string is ignorable c.f. 4.2. Whitespace
3208  *
3209  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3210  */
3211 static int
3212 xmlRelaxNGIsBlank(xmlChar *str) {
3213     if (str == NULL)
3214         return(1);
3215     while (*str != 0) {
3216         if (!(IS_BLANK(*str))) return(0);
3217         str++;
3218     }
3219     return(1);
3220 }
3221
3222 /**
3223  * xmlRelaxNGGetDataTypeLibrary:
3224  * @ctxt:  a Relax-NG parser context
3225  * @node:  the current data or value element
3226  *
3227  * Applies algorithm from 4.3. datatypeLibrary attribute
3228  *
3229  * Returns the datatypeLibary value or NULL if not found
3230  */
3231 static xmlChar *
3232 xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
3233                              xmlNodePtr node) {
3234     xmlChar *ret, *escape;
3235
3236     if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
3237         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
3238         if (ret != NULL) {
3239             if (ret[0] == 0) {
3240                 xmlFree(ret);
3241                 return(NULL);
3242             }
3243             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
3244             if (escape == NULL) {
3245                 return(ret);
3246             }
3247             xmlFree(ret);
3248             return(escape);
3249         }
3250     }
3251     node = node->parent;
3252     while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
3253         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
3254         if (ret != NULL) {
3255             if (ret[0] == 0) {
3256                 xmlFree(ret);
3257                 return(NULL);
3258             }
3259             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
3260             if (escape == NULL) {
3261                 return(ret);
3262             }
3263             xmlFree(ret);
3264             return(escape);
3265         }
3266         node = node->parent;
3267     }
3268     return(NULL);
3269 }
3270
3271 /**
3272  * xmlRelaxNGParseValue:
3273  * @ctxt:  a Relax-NG parser context
3274  * @node:  the data node.
3275  *
3276  * parse the content of a RelaxNG value node.
3277  *
3278  * Returns the definition pointer or NULL in case of error
3279  */
3280 static xmlRelaxNGDefinePtr
3281 xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
3282     xmlRelaxNGDefinePtr def = NULL;
3283     xmlRelaxNGTypeLibraryPtr lib = NULL;
3284     xmlChar *type;
3285     xmlChar *library;
3286     int success = 0;
3287
3288     def = xmlRelaxNGNewDefine(ctxt, node);
3289     if (def == NULL)
3290         return(NULL);
3291     def->type = XML_RELAXNG_VALUE;
3292
3293     type = xmlGetProp(node, BAD_CAST "type");
3294     if (type != NULL) {
3295         xmlRelaxNGNormExtSpace(type);
3296         if (xmlValidateNCName(type, 0)) {
3297             if (ctxt->error != NULL)
3298                 ctxt->error(ctxt->userData,
3299                     "value type '%s' is not an NCName\n",
3300                             type);
3301             ctxt->nbErrors++;
3302         }
3303         library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
3304         if (library == NULL)
3305             library = xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
3306
3307         def->name = type;
3308         def->ns = library;
3309
3310         lib = (xmlRelaxNGTypeLibraryPtr)
3311             xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
3312         if (lib == NULL) {
3313             if (ctxt->error != NULL)
3314                 ctxt->error(ctxt->userData,
3315                     "Use of unregistered type library '%s'\n",
3316                             library);
3317             ctxt->nbErrors++;
3318             def->data = NULL;
3319         } else {
3320             def->data = lib;
3321             if (lib->have == NULL) {
3322                 if (ctxt->error != NULL)
3323                     ctxt->error(ctxt->userData,
3324                     "Internal error with type library '%s': no 'have'\n",
3325                             library);
3326                 ctxt->nbErrors++;
3327             } else {
3328                 success = lib->have(lib->data, def->name);
3329                 if (success != 1) {
3330                     if (ctxt->error != NULL)
3331                         ctxt->error(ctxt->userData,
3332                     "Error type '%s' is not exported by type library '%s'\n",
3333                                 def->name, library);
3334                     ctxt->nbErrors++;
3335                 }
3336             }
3337         }
3338     }
3339     if (node->children == NULL) {
3340         def->value = xmlStrdup(BAD_CAST "");
3341     } else if (((node->children->type != XML_TEXT_NODE) &&
3342                 (node->children->type != XML_CDATA_SECTION_NODE)) ||
3343                (node->children->next != NULL)) {
3344         if (ctxt->error != NULL)
3345             ctxt->error(ctxt->userData,
3346                 "Expecting a single text value for <value>content\n");
3347         ctxt->nbErrors++;
3348     } else if (def != NULL) {
3349         def->value = xmlNodeGetContent(node);
3350         if (def->value == NULL) {
3351             if (ctxt->error != NULL)
3352                 ctxt->error(ctxt->userData,
3353                             "Element <value> has no content\n");
3354             ctxt->nbErrors++;
3355         } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) {
3356             void *val = NULL;
3357
3358             success = lib->check(lib->data, def->name, def->value, &val, node);
3359             if (success != 1) {
3360                 if (ctxt->error != NULL)
3361                     ctxt->error(ctxt->userData,
3362                         "Value '%s' is not acceptable for type '%s'\n",
3363                                 def->value, def->name);
3364                 ctxt->nbErrors++;
3365             } else {
3366                 if (val != NULL)
3367                     def->attrs = val;
3368             }
3369         }
3370     }
3371     return(def);
3372 }
3373
3374 /**
3375  * xmlRelaxNGParseData:
3376  * @ctxt:  a Relax-NG parser context
3377  * @node:  the data node.
3378  *
3379  * parse the content of a RelaxNG data node.
3380  *
3381  * Returns the definition pointer or NULL in case of error
3382  */
3383 static xmlRelaxNGDefinePtr
3384 xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
3385     xmlRelaxNGDefinePtr def = NULL, except, last = NULL;
3386     xmlRelaxNGDefinePtr param, lastparam = NULL;
3387     xmlRelaxNGTypeLibraryPtr lib;
3388     xmlChar *type;
3389     xmlChar *library;
3390     xmlNodePtr content;
3391     int tmp;
3392
3393     type = xmlGetProp(node, BAD_CAST "type");
3394     if (type == NULL) {
3395         if (ctxt->error != NULL)
3396             ctxt->error(ctxt->userData,
3397                         "data has no type\n");
3398         ctxt->nbErrors++;
3399         return(NULL);
3400     }
3401     xmlRelaxNGNormExtSpace(type);
3402     if (xmlValidateNCName(type, 0)) {
3403         if (ctxt->error != NULL)
3404             ctxt->error(ctxt->userData,
3405                 "data type '%s' is not an NCName\n",
3406                         type);
3407         ctxt->nbErrors++;
3408     }
3409     library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
3410     if (library == NULL)
3411         library = xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
3412
3413     def = xmlRelaxNGNewDefine(ctxt, node);
3414     if (def == NULL) {
3415         xmlFree(type);
3416         return(NULL);
3417     }
3418     def->type = XML_RELAXNG_DATATYPE;
3419     def->name = type;
3420     def->ns = library;
3421
3422     lib = (xmlRelaxNGTypeLibraryPtr)
3423         xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
3424     if (lib == NULL) {
3425         if (ctxt->error != NULL)
3426             ctxt->error(ctxt->userData,
3427                 "Use of unregistered type library '%s'\n",
3428                         library);
3429         ctxt->nbErrors++;
3430         def->data = NULL;
3431     } else {
3432         def->data = lib;
3433         if (lib->have == NULL) {
3434             if (ctxt->error != NULL)
3435                 ctxt->error(ctxt->userData,
3436                 "Internal error with type library '%s': no 'have'\n",
3437                         library);
3438             ctxt->nbErrors++;
3439         } else {
3440             tmp = lib->have(lib->data, def->name);
3441             if (tmp != 1) {
3442                 if (ctxt->error != NULL)
3443                     ctxt->error(ctxt->userData,
3444                     "Error type '%s' is not exported by type library '%s'\n",
3445                             def->name, library);
3446                 ctxt->nbErrors++;
3447             } else if ((xmlStrEqual(library, BAD_CAST
3448                            "http://www.w3.org/2001/XMLSchema-datatypes")) &&
3449                        ((xmlStrEqual(def->name, BAD_CAST "IDREF")) ||
3450                         (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) {
3451                 ctxt->idref = 1;
3452             }
3453         }
3454     }
3455