ReactOS 0.4.15-dev-7842-g558ab78
relaxng.c
Go to the documentation of this file.
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
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 <stddef.h>
24#include <libxml/xmlmemory.h>
25#include <libxml/parser.h>
27#include <libxml/hash.h>
28#include <libxml/uri.h>
29
30#include <libxml/relaxng.h>
31
33#include <libxml/xmlautomata.h>
34#include <libxml/xmlregexp.h>
36
37/*
38 * The Relax-NG namespace
39 */
40static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
41 "http://relaxng.org/ns/structure/1.0";
42
43#define IS_RELAXNG(node, typ) \
44 ((node != NULL) && (node->ns != NULL) && \
45 (node->type == XML_ELEMENT_NODE) && \
46 (xmlStrEqual(node->name, (const xmlChar *) typ)) && \
47 (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))
48
49
50#if 0
51#define DEBUG 1
52
53#define DEBUG_GRAMMAR 1
54
55#define DEBUG_CONTENT 1
56
57#define DEBUG_TYPE 1
58
59#define DEBUG_VALID 1
60
61#define DEBUG_INTERLEAVE 1
62
63#define DEBUG_LIST 1
64
65#define DEBUG_INCLUDE 1
66
67#define DEBUG_ERROR 1
68
69#define DEBUG_COMPILE 1
70
71#define DEBUG_PROGRESSIVE 1
72#endif
73
74#define MAX_ERROR 5
75
76#define TODO \
77 xmlGenericError(xmlGenericErrorContext, \
78 "Unimplemented block at %s:%d\n", \
79 __FILE__, __LINE__);
80
81typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;
82typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;
83
84typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine;
85typedef xmlRelaxNGDefine *xmlRelaxNGDefinePtr;
86
87typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument;
88typedef xmlRelaxNGDocument *xmlRelaxNGDocumentPtr;
89
90typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude;
91typedef xmlRelaxNGInclude *xmlRelaxNGIncludePtr;
92
93typedef enum {
94 XML_RELAXNG_COMBINE_UNDEFINED = 0, /* undefined */
95 XML_RELAXNG_COMBINE_CHOICE, /* choice */
96 XML_RELAXNG_COMBINE_INTERLEAVE /* interleave */
97} xmlRelaxNGCombine;
98
99typedef enum {
100 XML_RELAXNG_CONTENT_ERROR = -1,
101 XML_RELAXNG_CONTENT_EMPTY = 0,
102 XML_RELAXNG_CONTENT_SIMPLE,
103 XML_RELAXNG_CONTENT_COMPLEX
104} xmlRelaxNGContentType;
105
106typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar;
107typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr;
108
109struct _xmlRelaxNGGrammar {
110 xmlRelaxNGGrammarPtr parent; /* the parent grammar if any */
111 xmlRelaxNGGrammarPtr children; /* the children grammar if any */
112 xmlRelaxNGGrammarPtr next; /* the next grammar if any */
113 xmlRelaxNGDefinePtr start; /* <start> content */
114 xmlRelaxNGCombine combine; /* the default combine value */
115 xmlRelaxNGDefinePtr startList; /* list of <start> definitions */
116 xmlHashTablePtr defs; /* define* */
117 xmlHashTablePtr refs; /* references */
118};
119
120
121typedef enum {
122 XML_RELAXNG_NOOP = -1, /* a no operation from simplification */
123 XML_RELAXNG_EMPTY = 0, /* an empty pattern */
124 XML_RELAXNG_NOT_ALLOWED, /* not allowed top */
125 XML_RELAXNG_EXCEPT, /* except present in nameclass defs */
126 XML_RELAXNG_TEXT, /* textual content */
127 XML_RELAXNG_ELEMENT, /* an element */
128 XML_RELAXNG_DATATYPE, /* external data type definition */
129 XML_RELAXNG_PARAM, /* external data type parameter */
130 XML_RELAXNG_VALUE, /* value from an external data type definition */
131 XML_RELAXNG_LIST, /* a list of patterns */
132 XML_RELAXNG_ATTRIBUTE, /* an attribute following a pattern */
133 XML_RELAXNG_DEF, /* a definition */
134 XML_RELAXNG_REF, /* reference to a definition */
135 XML_RELAXNG_EXTERNALREF, /* reference to an external def */
136 XML_RELAXNG_PARENTREF, /* reference to a def in the parent grammar */
137 XML_RELAXNG_OPTIONAL, /* optional patterns */
138 XML_RELAXNG_ZEROORMORE, /* zero or more non empty patterns */
139 XML_RELAXNG_ONEORMORE, /* one or more non empty patterns */
140 XML_RELAXNG_CHOICE, /* a choice between non empty patterns */
141 XML_RELAXNG_GROUP, /* a pair/group of non empty patterns */
142 XML_RELAXNG_INTERLEAVE, /* interleaving choice of non-empty patterns */
143 XML_RELAXNG_START /* Used to keep track of starts on grammars */
144} xmlRelaxNGType;
145
146#define IS_NULLABLE (1 << 0)
147#define IS_NOT_NULLABLE (1 << 1)
148#define IS_INDETERMINIST (1 << 2)
149#define IS_MIXED (1 << 3)
150#define IS_TRIABLE (1 << 4)
151#define IS_PROCESSED (1 << 5)
152#define IS_COMPILABLE (1 << 6)
153#define IS_NOT_COMPILABLE (1 << 7)
154#define IS_EXTERNAL_REF (1 << 8)
155
156struct _xmlRelaxNGDefine {
157 xmlRelaxNGType type; /* the type of definition */
158 xmlNodePtr node; /* the node in the source */
159 xmlChar *name; /* the element local name if present */
160 xmlChar *ns; /* the namespace local name if present */
161 xmlChar *value; /* value when available */
162 void *data; /* data lib or specific pointer */
163 xmlRelaxNGDefinePtr content; /* the expected content */
164 xmlRelaxNGDefinePtr parent; /* the parent definition, if any */
165 xmlRelaxNGDefinePtr next; /* list within grouping sequences */
166 xmlRelaxNGDefinePtr attrs; /* list of attributes for elements */
167 xmlRelaxNGDefinePtr nameClass; /* the nameClass definition if any */
168 xmlRelaxNGDefinePtr nextHash; /* next define in defs/refs hash tables */
169 short depth; /* used for the cycle detection */
170 short dflags; /* define related flags */
171 xmlRegexpPtr contModel; /* a compiled content model if available */
172};
173
179struct _xmlRelaxNG {
180 void *_private; /* unused by the library for users or bindings */
181 xmlRelaxNGGrammarPtr topgrammar;
182 xmlDocPtr doc;
183
184 int idref; /* requires idref checking */
185
186 xmlHashTablePtr defs; /* define */
187 xmlHashTablePtr refs; /* references */
188 xmlRelaxNGDocumentPtr documents; /* all the documents loaded */
189 xmlRelaxNGIncludePtr includes; /* all the includes loaded */
190 int defNr; /* number of defines used */
191 xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */
192
193};
194
195#define XML_RELAXNG_IN_ATTRIBUTE (1 << 0)
196#define XML_RELAXNG_IN_ONEORMORE (1 << 1)
197#define XML_RELAXNG_IN_LIST (1 << 2)
198#define XML_RELAXNG_IN_DATAEXCEPT (1 << 3)
199#define XML_RELAXNG_IN_START (1 << 4)
200#define XML_RELAXNG_IN_OOMGROUP (1 << 5)
201#define XML_RELAXNG_IN_OOMINTERLEAVE (1 << 6)
202#define XML_RELAXNG_IN_EXTERNALREF (1 << 7)
203#define XML_RELAXNG_IN_ANYEXCEPT (1 << 8)
204#define XML_RELAXNG_IN_NSEXCEPT (1 << 9)
205
206struct _xmlRelaxNGParserCtxt {
207 void *userData; /* user specific data block */
208 xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */
209 xmlRelaxNGValidityWarningFunc warning; /* the callback in case of warning */
211 xmlRelaxNGValidErr err;
212
213 xmlRelaxNGPtr schema; /* The schema in use */
214 xmlRelaxNGGrammarPtr grammar; /* the current grammar */
215 xmlRelaxNGGrammarPtr parentgrammar; /* the parent grammar */
216 int flags; /* parser flags */
217 int nbErrors; /* number of errors at parse time */
218 int nbWarnings; /* number of warnings at parse time */
219 const xmlChar *define; /* the current define scope */
220 xmlRelaxNGDefinePtr def; /* the current define */
221
222 int nbInterleaves;
223 xmlHashTablePtr interleaves; /* keep track of all the interleaves */
224
225 xmlRelaxNGDocumentPtr documents; /* all the documents loaded */
226 xmlRelaxNGIncludePtr includes; /* all the includes loaded */
227 xmlChar *URL;
228 xmlDocPtr document;
229
230 int defNr; /* number of defines used */
231 int defMax; /* number of defines allocated */
232 xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */
233
234 const char *buffer;
235 int size;
236
237 /* the document stack */
238 xmlRelaxNGDocumentPtr doc; /* Current parsed external ref */
239 int docNr; /* Depth of the parsing stack */
240 int docMax; /* Max depth of the parsing stack */
241 xmlRelaxNGDocumentPtr *docTab; /* array of docs */
242
243 /* the include stack */
244 xmlRelaxNGIncludePtr inc; /* Current parsed include */
245 int incNr; /* Depth of the include parsing stack */
246 int incMax; /* Max depth of the parsing stack */
247 xmlRelaxNGIncludePtr *incTab; /* array of incs */
248
249 int idref; /* requires idref checking */
250
251 /* used to compile content models */
252 xmlAutomataPtr am; /* the automata */
253 xmlAutomataStatePtr state; /* used to build the automata */
254
255 int crng; /* compact syntax and other flags */
256 int freedoc; /* need to free the document */
257};
258
259#define FLAGS_IGNORABLE 1
260#define FLAGS_NEGATIVE 2
261#define FLAGS_MIXED_CONTENT 4
262#define FLAGS_NOERROR 8
263
269typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup;
270typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr;
271struct _xmlRelaxNGInterleaveGroup {
272 xmlRelaxNGDefinePtr rule; /* the rule to satisfy */
273 xmlRelaxNGDefinePtr *defs; /* the array of element definitions */
274 xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */
275};
276
277#define IS_DETERMINIST 1
278#define IS_NEEDCHECK 2
279
285typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition;
286typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr;
287struct _xmlRelaxNGPartition {
288 int nbgroups; /* number of groups in the partitions */
289 xmlHashTablePtr triage; /* hash table used to direct nodes to the
290 * right group when possible */
291 int flags; /* determinist ? */
292 xmlRelaxNGInterleaveGroupPtr *groups;
293};
294
300#define MAX_ATTR 20
301typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState;
302typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr;
303struct _xmlRelaxNGValidState {
304 xmlNodePtr node; /* the current node */
305 xmlNodePtr seq; /* the sequence of children left to validate */
306 int nbAttrs; /* the number of attributes */
307 int maxAttrs; /* the size of attrs */
308 int nbAttrLeft; /* the number of attributes left to validate */
309 xmlChar *value; /* the value when operating on string */
310 xmlChar *endvalue; /* the end value when operating on string */
311 xmlAttrPtr *attrs; /* the array of attributes */
312};
313
319typedef struct _xmlRelaxNGStates xmlRelaxNGStates;
320typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr;
321struct _xmlRelaxNGStates {
322 int nbState; /* the number of states */
323 int maxState; /* the size of the array */
324 xmlRelaxNGValidStatePtr *tabState;
325};
326
327#define ERROR_IS_DUP 1
328
334typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;
335typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;
336struct _xmlRelaxNGValidError {
337 xmlRelaxNGValidErr err; /* the error number */
338 int flags; /* flags */
339 xmlNodePtr node; /* the current node */
340 xmlNodePtr seq; /* the current child */
341 const xmlChar *arg1; /* first arg */
342 const xmlChar *arg2; /* second arg */
343};
344
351struct _xmlRelaxNGValidCtxt {
352 void *userData; /* user specific data block */
353 xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */
354 xmlRelaxNGValidityWarningFunc warning; /* the callback in case of warning */
356 int nbErrors; /* number of errors in validation */
357
358 xmlRelaxNGPtr schema; /* The schema in use */
359 xmlDocPtr doc; /* the document being validated */
360 int flags; /* validation flags */
361 int depth; /* validation depth */
362 int idref; /* requires idref checking */
363 int errNo; /* the first error found */
364
365 /*
366 * Errors accumulated in branches may have to be stacked to be
367 * provided back when it's sure they affect validation.
368 */
369 xmlRelaxNGValidErrorPtr err; /* Last error */
370 int errNr; /* Depth of the error stack */
371 int errMax; /* Max depth of the error stack */
372 xmlRelaxNGValidErrorPtr errTab; /* stack of errors */
373
374 xmlRelaxNGValidStatePtr state; /* the current validation state */
375 xmlRelaxNGStatesPtr states; /* the accumulated state list */
376
377 xmlRelaxNGStatesPtr freeState; /* the pool of free valid states */
378 int freeStatesNr;
379 int freeStatesMax;
380 xmlRelaxNGStatesPtr *freeStates; /* the pool of free state groups */
381
382 /*
383 * This is used for "progressive" validation
384 */
385 xmlRegExecCtxtPtr elem; /* the current element regexp */
386 int elemNr; /* the number of element validated */
387 int elemMax; /* the max depth of elements */
388 xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */
389 int pstate; /* progressive state */
390 xmlNodePtr pnode; /* the current node */
391 xmlRelaxNGDefinePtr pdef; /* the non-streamable definition */
392 int perr; /* signal error in content model
393 * outside the regexp */
394};
395
401struct _xmlRelaxNGInclude {
402 xmlRelaxNGIncludePtr next; /* keep a chain of includes */
403 xmlChar *href; /* the normalized href value */
404 xmlDocPtr doc; /* the associated XML document */
405 xmlRelaxNGDefinePtr content; /* the definitions */
406 xmlRelaxNGPtr schema; /* the schema */
407};
408
414struct _xmlRelaxNGDocument {
415 xmlRelaxNGDocumentPtr next; /* keep a chain of documents */
416 xmlChar *href; /* the normalized href value */
417 xmlDocPtr doc; /* the associated XML document */
418 xmlRelaxNGDefinePtr content; /* the definitions */
419 xmlRelaxNGPtr schema; /* the schema */
420 int externalRef; /* 1 if an external ref */
421};
422
423
424/************************************************************************
425 * *
426 * Some factorized error routines *
427 * *
428 ************************************************************************/
429
437static void
438xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
439{
440 xmlStructuredErrorFunc schannel = NULL;
441 xmlGenericErrorFunc channel = NULL;
442 void *data = NULL;
443
444 if (ctxt != NULL) {
445 if (ctxt->serror != NULL)
446 schannel = ctxt->serror;
447 else
448 channel = ctxt->error;
449 data = ctxt->userData;
450 ctxt->nbErrors++;
451 }
452 if (extra)
453 __xmlRaiseError(schannel, channel, data,
456 NULL, NULL, 0, 0,
457 "Memory allocation failed : %s\n", extra);
458 else
459 __xmlRaiseError(schannel, channel, data,
462 NULL, NULL, 0, 0, "Memory allocation failed\n");
463}
464
472static void
473xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)
474{
475 xmlStructuredErrorFunc schannel = NULL;
476 xmlGenericErrorFunc channel = NULL;
477 void *data = NULL;
478
479 if (ctxt != NULL) {
480 if (ctxt->serror != NULL)
481 schannel = ctxt->serror;
482 else
483 channel = ctxt->error;
484 data = ctxt->userData;
485 ctxt->nbErrors++;
486 }
487 if (extra)
488 __xmlRaiseError(schannel, channel, data,
491 NULL, NULL, 0, 0,
492 "Memory allocation failed : %s\n", extra);
493 else
494 __xmlRaiseError(schannel, channel, data,
497 NULL, NULL, 0, 0, "Memory allocation failed\n");
498}
499
511static void LIBXML_ATTR_FORMAT(4,0)
512xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
513 const char *msg, const xmlChar * str1, const xmlChar * str2)
514{
515 xmlStructuredErrorFunc schannel = NULL;
516 xmlGenericErrorFunc channel = NULL;
517 void *data = NULL;
518
519 if (ctxt != NULL) {
520 if (ctxt->serror != NULL)
521 schannel = ctxt->serror;
522 else
523 channel = ctxt->error;
524 data = ctxt->userData;
525 ctxt->nbErrors++;
526 }
527 __xmlRaiseError(schannel, channel, data,
530 (const char *) str1, (const char *) str2, NULL, 0, 0,
531 msg, str1, str2);
532}
533
545static void LIBXML_ATTR_FORMAT(4,0)
546xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
547 const char *msg, const xmlChar * str1, const xmlChar * str2)
548{
549 xmlStructuredErrorFunc schannel = NULL;
550 xmlGenericErrorFunc channel = NULL;
551 void *data = NULL;
552
553 if (ctxt != NULL) {
554 if (ctxt->serror != NULL)
555 schannel = ctxt->serror;
556 else
557 channel = ctxt->error;
558 data = ctxt->userData;
559 ctxt->nbErrors++;
560 }
561 __xmlRaiseError(schannel, channel, data,
564 (const char *) str1, (const char *) str2, NULL, 0, 0,
565 msg, str1, str2);
566}
567
568/************************************************************************
569 * *
570 * Preliminary type checking interfaces *
571 * *
572 ************************************************************************/
573
584typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar * type);
585
597typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar * type,
598 const xmlChar * value, void **result,
600
614typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar * type,
615 const xmlChar * facet,
616 const xmlChar * val,
617 const xmlChar * strval, void *value);
618
626typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);
627
640typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar * type,
641 const xmlChar * value1,
642 xmlNodePtr ctxt1,
643 void *comp1,
644 const xmlChar * value2,
645 xmlNodePtr ctxt2);
646typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
647typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
648struct _xmlRelaxNGTypeLibrary {
649 const xmlChar *namespace; /* the datatypeLibrary value */
650 void *data; /* data needed for the library */
651 xmlRelaxNGTypeHave have; /* the export function */
652 xmlRelaxNGTypeCheck check; /* the checking function */
653 xmlRelaxNGTypeCompare comp; /* the compare function */
654 xmlRelaxNGFacetCheck facet; /* the facet check function */
655 xmlRelaxNGTypeFree freef; /* the freeing function */
656};
657
658/************************************************************************
659 * *
660 * Allocation functions *
661 * *
662 ************************************************************************/
663static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);
664static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);
665static void xmlRelaxNGNormExtSpace(xmlChar * value);
666static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema);
667static int xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt
669 xmlRelaxNGValidStatePtr state1,
670 xmlRelaxNGValidStatePtr state2);
671static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
672 xmlRelaxNGValidStatePtr state);
673
680static void
681xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu)
682{
683 if (docu == NULL)
684 return;
685
686 if (docu->href != NULL)
687 xmlFree(docu->href);
688 if (docu->doc != NULL)
689 xmlFreeDoc(docu->doc);
690 if (docu->schema != NULL)
691 xmlRelaxNGFreeInnerSchema(docu->schema);
692 xmlFree(docu);
693}
694
701static void
702xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu)
703{
704 xmlRelaxNGDocumentPtr next;
705
706 while (docu != NULL) {
707 next = docu->next;
708 xmlRelaxNGFreeDocument(docu);
709 docu = next;
710 }
711}
712
719static void
720xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl)
721{
722 if (incl == NULL)
723 return;
724
725 if (incl->href != NULL)
726 xmlFree(incl->href);
727 if (incl->doc != NULL)
728 xmlFreeDoc(incl->doc);
729 if (incl->schema != NULL)
730 xmlRelaxNGFree(incl->schema);
731 xmlFree(incl);
732}
733
740static void
741xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl)
742{
743 xmlRelaxNGIncludePtr next;
744
745 while (incl != NULL) {
746 next = incl->next;
747 xmlRelaxNGFreeInclude(incl);
748 incl = next;
749 }
750}
751
760static xmlRelaxNGPtr
761xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)
762{
763 xmlRelaxNGPtr ret;
764
765 ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));
766 if (ret == NULL) {
767 xmlRngPErrMemory(ctxt, NULL);
768 return (NULL);
769 }
770 memset(ret, 0, sizeof(xmlRelaxNG));
771
772 return (ret);
773}
774
781static void
782xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema)
783{
784 if (schema == NULL)
785 return;
786
787 if (schema->doc != NULL)
788 xmlFreeDoc(schema->doc);
789 if (schema->defTab != NULL) {
790 int i;
791
792 for (i = 0; i < schema->defNr; i++)
793 xmlRelaxNGFreeDefine(schema->defTab[i]);
794 xmlFree(schema->defTab);
795 }
796
798}
799
806void
807xmlRelaxNGFree(xmlRelaxNGPtr schema)
808{
809 if (schema == NULL)
810 return;
811
812 if (schema->topgrammar != NULL)
813 xmlRelaxNGFreeGrammar(schema->topgrammar);
814 if (schema->doc != NULL)
815 xmlFreeDoc(schema->doc);
816 if (schema->documents != NULL)
817 xmlRelaxNGFreeDocumentList(schema->documents);
818 if (schema->includes != NULL)
819 xmlRelaxNGFreeIncludeList(schema->includes);
820 if (schema->defTab != NULL) {
821 int i;
822
823 for (i = 0; i < schema->defNr; i++)
824 xmlRelaxNGFreeDefine(schema->defTab[i]);
825 xmlFree(schema->defTab);
826 }
827
829}
830
839static xmlRelaxNGGrammarPtr
840xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)
841{
842 xmlRelaxNGGrammarPtr ret;
843
844 ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));
845 if (ret == NULL) {
846 xmlRngPErrMemory(ctxt, NULL);
847 return (NULL);
848 }
849 memset(ret, 0, sizeof(xmlRelaxNGGrammar));
850
851 return (ret);
852}
853
860static void
861xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar)
862{
863 if (grammar == NULL)
864 return;
865
866 if (grammar->children != NULL) {
867 xmlRelaxNGFreeGrammar(grammar->children);
868 }
869 if (grammar->next != NULL) {
870 xmlRelaxNGFreeGrammar(grammar->next);
871 }
872 if (grammar->refs != NULL) {
873 xmlHashFree(grammar->refs, NULL);
874 }
875 if (grammar->defs != NULL) {
876 xmlHashFree(grammar->defs, NULL);
877 }
878
879 xmlFree(grammar);
880}
881
891static xmlRelaxNGDefinePtr
892xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
893{
894 xmlRelaxNGDefinePtr ret;
895
896 if (ctxt->defMax == 0) {
897 ctxt->defMax = 16;
898 ctxt->defNr = 0;
899 ctxt->defTab = (xmlRelaxNGDefinePtr *)
900 xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
901 if (ctxt->defTab == NULL) {
902 xmlRngPErrMemory(ctxt, "allocating define\n");
903 return (NULL);
904 }
905 } else if (ctxt->defMax <= ctxt->defNr) {
906 xmlRelaxNGDefinePtr *tmp;
907
908 ctxt->defMax *= 2;
909 tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,
910 ctxt->defMax *
911 sizeof
912 (xmlRelaxNGDefinePtr));
913 if (tmp == NULL) {
914 xmlRngPErrMemory(ctxt, "allocating define\n");
915 return (NULL);
916 }
917 ctxt->defTab = tmp;
918 }
919 ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
920 if (ret == NULL) {
921 xmlRngPErrMemory(ctxt, "allocating define\n");
922 return (NULL);
923 }
924 memset(ret, 0, sizeof(xmlRelaxNGDefine));
925 ctxt->defTab[ctxt->defNr++] = ret;
926 ret->node = node;
927 ret->depth = -1;
928 return (ret);
929}
930
937static void
938xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions)
939{
940 xmlRelaxNGInterleaveGroupPtr group;
941 int j;
942
943 if (partitions != NULL) {
944 if (partitions->groups != NULL) {
945 for (j = 0; j < partitions->nbgroups; j++) {
946 group = partitions->groups[j];
947 if (group != NULL) {
948 if (group->defs != NULL)
949 xmlFree(group->defs);
950 if (group->attrs != NULL)
951 xmlFree(group->attrs);
952 xmlFree(group);
953 }
954 }
955 xmlFree(partitions->groups);
956 }
957 if (partitions->triage != NULL) {
958 xmlHashFree(partitions->triage, NULL);
959 }
960 xmlFree(partitions);
961 }
962}
963
970static void
971xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define)
972{
973 if (define == NULL)
974 return;
975
976 if ((define->type == XML_RELAXNG_VALUE) && (define->attrs != NULL)) {
977 xmlRelaxNGTypeLibraryPtr lib;
978
979 lib = (xmlRelaxNGTypeLibraryPtr) define->data;
980 if ((lib != NULL) && (lib->freef != NULL))
981 lib->freef(lib->data, (void *) define->attrs);
982 }
983 if ((define->data != NULL) && (define->type == XML_RELAXNG_INTERLEAVE))
984 xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
985 if ((define->data != NULL) && (define->type == XML_RELAXNG_CHOICE))
987 if (define->name != NULL)
989 if (define->ns != NULL)
990 xmlFree(define->ns);
991 if (define->value != NULL)
993 if (define->contModel != NULL)
994 xmlRegFreeRegexp(define->contModel);
996}
997
1007static xmlRelaxNGStatesPtr
1008xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
1009{
1010 xmlRelaxNGStatesPtr ret;
1011
1012 if ((ctxt != NULL) &&
1013 (ctxt->freeStates != NULL) && (ctxt->freeStatesNr > 0)) {
1014 ctxt->freeStatesNr--;
1015 ret = ctxt->freeStates[ctxt->freeStatesNr];
1016 ret->nbState = 0;
1017 return (ret);
1018 }
1019 if (size < 16)
1020 size = 16;
1021
1022 ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +
1023 (size -
1024 1) *
1025 sizeof(xmlRelaxNGValidStatePtr));
1026 if (ret == NULL) {
1027 xmlRngVErrMemory(ctxt, "allocating states\n");
1028 return (NULL);
1029 }
1030 ret->nbState = 0;
1031 ret->maxState = size;
1032 ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc((size) *
1033 sizeof
1034 (xmlRelaxNGValidStatePtr));
1035 if (ret->tabState == NULL) {
1036 xmlRngVErrMemory(ctxt, "allocating states\n");
1037 xmlFree(ret);
1038 return (NULL);
1039 }
1040 return (ret);
1041}
1042
1054static int
1055xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,
1056 xmlRelaxNGStatesPtr states,
1057 xmlRelaxNGValidStatePtr state)
1058{
1059 if (state == NULL) {
1060 return (-1);
1061 }
1062 if (states->nbState >= states->maxState) {
1063 xmlRelaxNGValidStatePtr *tmp;
1064 int size;
1065
1066 size = states->maxState * 2;
1067 tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
1068 (size) *
1069 sizeof
1070 (xmlRelaxNGValidStatePtr));
1071 if (tmp == NULL) {
1072 xmlRngVErrMemory(ctxt, "adding states\n");
1073 return (-1);
1074 }
1075 states->tabState = tmp;
1076 states->maxState = size;
1077 }
1078 states->tabState[states->nbState++] = state;
1079 return (1);
1080}
1081
1092static int
1093xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt,
1094 xmlRelaxNGStatesPtr states,
1095 xmlRelaxNGValidStatePtr state)
1096{
1097 int i;
1098
1099 if (state == NULL || states == NULL) {
1100 return (-1);
1101 }
1102 if (states->nbState >= states->maxState) {
1103 xmlRelaxNGValidStatePtr *tmp;
1104 int size;
1105
1106 size = states->maxState * 2;
1107 tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
1108 (size) *
1109 sizeof
1110 (xmlRelaxNGValidStatePtr));
1111 if (tmp == NULL) {
1112 xmlRngVErrMemory(ctxt, "adding states\n");
1113 return (-1);
1114 }
1115 states->tabState = tmp;
1116 states->maxState = size;
1117 }
1118 for (i = 0; i < states->nbState; i++) {
1119 if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) {
1120 xmlRelaxNGFreeValidState(ctxt, state);
1121 return (0);
1122 }
1123 }
1124 states->tabState[states->nbState++] = state;
1125 return (1);
1126}
1127
1135static void
1136xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
1137 xmlRelaxNGStatesPtr states)
1138{
1139 if (states == NULL)
1140 return;
1141 if ((ctxt != NULL) && (ctxt->freeStates == NULL)) {
1142 ctxt->freeStatesMax = 40;
1143 ctxt->freeStatesNr = 0;
1144 ctxt->freeStates = (xmlRelaxNGStatesPtr *)
1145 xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
1146 if (ctxt->freeStates == NULL) {
1147 xmlRngVErrMemory(ctxt, "storing states\n");
1148 }
1149 } else if ((ctxt != NULL)
1150 && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) {
1151 xmlRelaxNGStatesPtr *tmp;
1152
1153 tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates,
1154 2 * ctxt->freeStatesMax *
1155 sizeof
1156 (xmlRelaxNGStatesPtr));
1157 if (tmp == NULL) {
1158 xmlRngVErrMemory(ctxt, "storing states\n");
1159 xmlFree(states->tabState);
1160 xmlFree(states);
1161 return;
1162 }
1163 ctxt->freeStates = tmp;
1164 ctxt->freeStatesMax *= 2;
1165 }
1166 if ((ctxt == NULL) || (ctxt->freeStates == NULL)) {
1167 xmlFree(states->tabState);
1168 xmlFree(states);
1169 } else {
1170 ctxt->freeStates[ctxt->freeStatesNr++] = states;
1171 }
1172}
1173
1183static xmlRelaxNGValidStatePtr
1184xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
1185{
1186 xmlRelaxNGValidStatePtr ret;
1188 xmlAttrPtr attrs[MAX_ATTR];
1189 int nbAttrs = 0;
1191
1192 if (node == NULL) {
1193 root = xmlDocGetRootElement(ctxt->doc);
1194 if (root == NULL)
1195 return (NULL);
1196 } else {
1197 attr = node->properties;
1198 while (attr != NULL) {
1199 if (nbAttrs < MAX_ATTR)
1200 attrs[nbAttrs++] = attr;
1201 else
1202 nbAttrs++;
1203 attr = attr->next;
1204 }
1205 }
1206 if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
1207 ctxt->freeState->nbState--;
1208 ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
1209 } else {
1210 ret =
1211 (xmlRelaxNGValidStatePtr)
1212 xmlMalloc(sizeof(xmlRelaxNGValidState));
1213 if (ret == NULL) {
1214 xmlRngVErrMemory(ctxt, "allocating states\n");
1215 return (NULL);
1216 }
1217 memset(ret, 0, sizeof(xmlRelaxNGValidState));
1218 }
1219 ret->value = NULL;
1220 ret->endvalue = NULL;
1221 if (node == NULL) {
1222 ret->node = (xmlNodePtr) ctxt->doc;
1223 ret->seq = root;
1224 } else {
1225 ret->node = node;
1226 ret->seq = node->children;
1227 }
1228 ret->nbAttrs = 0;
1229 if (nbAttrs > 0) {
1230 if (ret->attrs == NULL) {
1231 if (nbAttrs < 4)
1232 ret->maxAttrs = 4;
1233 else
1234 ret->maxAttrs = nbAttrs;
1235 ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
1236 sizeof(xmlAttrPtr));
1237 if (ret->attrs == NULL) {
1238 xmlRngVErrMemory(ctxt, "allocating states\n");
1239 return (ret);
1240 }
1241 } else if (ret->maxAttrs < nbAttrs) {
1242 xmlAttrPtr *tmp;
1243
1244 tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *
1245 sizeof(xmlAttrPtr));
1246 if (tmp == NULL) {
1247 xmlRngVErrMemory(ctxt, "allocating states\n");
1248 return (ret);
1249 }
1250 ret->attrs = tmp;
1251 ret->maxAttrs = nbAttrs;
1252 }
1253 ret->nbAttrs = nbAttrs;
1254 if (nbAttrs < MAX_ATTR) {
1255 memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs);
1256 } else {
1257 attr = node->properties;
1258 nbAttrs = 0;
1259 while (attr != NULL) {
1260 ret->attrs[nbAttrs++] = attr;
1261 attr = attr->next;
1262 }
1263 }
1264 }
1265 ret->nbAttrLeft = ret->nbAttrs;
1266 return (ret);
1267}
1268
1278static xmlRelaxNGValidStatePtr
1279xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
1280 xmlRelaxNGValidStatePtr state)
1281{
1282 xmlRelaxNGValidStatePtr ret;
1283 unsigned int maxAttrs;
1284 xmlAttrPtr *attrs;
1285
1286 if (state == NULL)
1287 return (NULL);
1288 if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
1289 ctxt->freeState->nbState--;
1290 ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
1291 } else {
1292 ret =
1293 (xmlRelaxNGValidStatePtr)
1294 xmlMalloc(sizeof(xmlRelaxNGValidState));
1295 if (ret == NULL) {
1296 xmlRngVErrMemory(ctxt, "allocating states\n");
1297 return (NULL);
1298 }
1299 memset(ret, 0, sizeof(xmlRelaxNGValidState));
1300 }
1301 attrs = ret->attrs;
1302 maxAttrs = ret->maxAttrs;
1303 memcpy(ret, state, sizeof(xmlRelaxNGValidState));
1304 ret->attrs = attrs;
1305 ret->maxAttrs = maxAttrs;
1306 if (state->nbAttrs > 0) {
1307 if (ret->attrs == NULL) {
1308 ret->maxAttrs = state->maxAttrs;
1309 ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
1310 sizeof(xmlAttrPtr));
1311 if (ret->attrs == NULL) {
1312 xmlRngVErrMemory(ctxt, "allocating states\n");
1313 ret->nbAttrs = 0;
1314 return (ret);
1315 }
1316 } else if (ret->maxAttrs < state->nbAttrs) {
1317 xmlAttrPtr *tmp;
1318
1319 tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *
1320 sizeof(xmlAttrPtr));
1321 if (tmp == NULL) {
1322 xmlRngVErrMemory(ctxt, "allocating states\n");
1323 ret->nbAttrs = 0;
1324 return (ret);
1325 }
1326 ret->maxAttrs = state->maxAttrs;
1327 ret->attrs = tmp;
1328 }
1329 memcpy(ret->attrs, state->attrs,
1330 state->nbAttrs * sizeof(xmlAttrPtr));
1331 }
1332 return (ret);
1333}
1334
1345static int
1346xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
1347 xmlRelaxNGValidStatePtr state1,
1348 xmlRelaxNGValidStatePtr state2)
1349{
1350 int i;
1351
1352 if ((state1 == NULL) || (state2 == NULL))
1353 return (0);
1354 if (state1 == state2)
1355 return (1);
1356 if (state1->node != state2->node)
1357 return (0);
1358 if (state1->seq != state2->seq)
1359 return (0);
1360 if (state1->nbAttrLeft != state2->nbAttrLeft)
1361 return (0);
1362 if (state1->nbAttrs != state2->nbAttrs)
1363 return (0);
1364 if (state1->endvalue != state2->endvalue)
1365 return (0);
1366 if ((state1->value != state2->value) &&
1367 (!xmlStrEqual(state1->value, state2->value)))
1368 return (0);
1369 for (i = 0; i < state1->nbAttrs; i++) {
1370 if (state1->attrs[i] != state2->attrs[i])
1371 return (0);
1372 }
1373 return (1);
1374}
1375
1382static void
1383xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
1384 xmlRelaxNGValidStatePtr state)
1385{
1386 if (state == NULL)
1387 return;
1388
1389 if ((ctxt != NULL) && (ctxt->freeState == NULL)) {
1390 ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40);
1391 }
1392 if ((ctxt == NULL) || (ctxt->freeState == NULL)) {
1393 if (state->attrs != NULL)
1394 xmlFree(state->attrs);
1395 xmlFree(state);
1396 } else {
1397 xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state);
1398 }
1399}
1400
1401/************************************************************************
1402 * *
1403 * Semi internal functions *
1404 * *
1405 ************************************************************************/
1406
1417int
1418xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags)
1419{
1420 if (ctxt == NULL) return(-1);
1421 if (flags & XML_RELAXNGP_FREE_DOC) {
1422 ctxt->crng |= XML_RELAXNGP_FREE_DOC;
1423 flags -= XML_RELAXNGP_FREE_DOC;
1424 }
1425 if (flags & XML_RELAXNGP_CRNG) {
1426 ctxt->crng |= XML_RELAXNGP_CRNG;
1427 flags -= XML_RELAXNGP_CRNG;
1428 }
1429 if (flags != 0) return(-1);
1430 return(0);
1431}
1432
1433/************************************************************************
1434 * *
1435 * Document functions *
1436 * *
1437 ************************************************************************/
1438static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
1439 xmlDocPtr doc);
1440
1450static int
1451xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
1452 xmlRelaxNGIncludePtr value)
1453{
1454 if (ctxt->incTab == NULL) {
1455 ctxt->incMax = 4;
1456 ctxt->incNr = 0;
1457 ctxt->incTab =
1458 (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *
1459 sizeof(ctxt->incTab[0]));
1460 if (ctxt->incTab == NULL) {
1461 xmlRngPErrMemory(ctxt, "allocating include\n");
1462 return (0);
1463 }
1464 }
1465 if (ctxt->incNr >= ctxt->incMax) {
1466 ctxt->incMax *= 2;
1467 ctxt->incTab =
1468 (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,
1469 ctxt->incMax *
1470 sizeof(ctxt->incTab[0]));
1471 if (ctxt->incTab == NULL) {
1472 xmlRngPErrMemory(ctxt, "allocating include\n");
1473 return (0);
1474 }
1475 }
1476 ctxt->incTab[ctxt->incNr] = value;
1477 ctxt->inc = value;
1478 return (ctxt->incNr++);
1479}
1480
1489static xmlRelaxNGIncludePtr
1490xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt)
1491{
1492 xmlRelaxNGIncludePtr ret;
1493
1494 if (ctxt->incNr <= 0)
1495 return (NULL);
1496 ctxt->incNr--;
1497 if (ctxt->incNr > 0)
1498 ctxt->inc = ctxt->incTab[ctxt->incNr - 1];
1499 else
1500 ctxt->inc = NULL;
1501 ret = ctxt->incTab[ctxt->incNr];
1502 ctxt->incTab[ctxt->incNr] = NULL;
1503 return (ret);
1504}
1505
1517static int
1518xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
1519 const xmlChar * URL ATTRIBUTE_UNUSED,
1520 xmlNodePtr target, const xmlChar * name)
1521{
1522 int found = 0;
1523 xmlNodePtr tmp, tmp2;
1524 xmlChar *name2;
1525
1526#ifdef DEBUG_INCLUDE
1527 if (name == NULL)
1529 "Elimination of <include> start from %s\n", URL);
1530 else
1532 "Elimination of <include> define %s from %s\n",
1533 name, URL);
1534#endif
1535 tmp = target;
1536 while (tmp != NULL) {
1537 tmp2 = tmp->next;
1538 if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) {
1539 found = 1;
1540 xmlUnlinkNode(tmp);
1541 xmlFreeNode(tmp);
1542 } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) {
1543 name2 = xmlGetProp(tmp, BAD_CAST "name");
1544 xmlRelaxNGNormExtSpace(name2);
1545 if (name2 != NULL) {
1546 if (xmlStrEqual(name, name2)) {
1547 found = 1;
1548 xmlUnlinkNode(tmp);
1549 xmlFreeNode(tmp);
1550 }
1551 xmlFree(name2);
1552 }
1553 } else if (IS_RELAXNG(tmp, "include")) {
1554 xmlChar *href = NULL;
1555 xmlRelaxNGDocumentPtr inc = tmp->psvi;
1556
1557 if ((inc != NULL) && (inc->doc != NULL) &&
1558 (inc->doc->children != NULL)) {
1559
1560 if (xmlStrEqual
1561 (inc->doc->children->name, BAD_CAST "grammar")) {
1562#ifdef DEBUG_INCLUDE
1563 href = xmlGetProp(tmp, BAD_CAST "href");
1564#endif
1565 if (xmlRelaxNGRemoveRedefine(ctxt, href,
1566 xmlDocGetRootElement(inc->doc)->children,
1567 name) == 1) {
1568 found = 1;
1569 }
1570#ifdef DEBUG_INCLUDE
1571 if (href != NULL)
1572 xmlFree(href);
1573#endif
1574 }
1575 }
1576 if (xmlRelaxNGRemoveRedefine(ctxt, URL, tmp->children, name) == 1) {
1577 found = 1;
1578 }
1579 }
1580 tmp = tmp2;
1581 }
1582 return (found);
1583}
1584
1598static xmlRelaxNGIncludePtr
1599xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
1600 xmlNodePtr node, const xmlChar * ns)
1601{
1602 xmlRelaxNGIncludePtr ret = NULL;
1603 xmlDocPtr doc;
1604 int i;
1606
1607#ifdef DEBUG_INCLUDE
1609 "xmlRelaxNGLoadInclude(%s)\n", URL);
1610#endif
1611
1612 /*
1613 * check against recursion in the stack
1614 */
1615 for (i = 0; i < ctxt->incNr; i++) {
1616 if (xmlStrEqual(ctxt->incTab[i]->href, URL)) {
1617 xmlRngPErr(ctxt, NULL, XML_RNGP_INCLUDE_RECURSE,
1618 "Detected an Include recursion for %s\n", URL,
1619 NULL);
1620 return (NULL);
1621 }
1622 }
1623
1624 /*
1625 * load the document
1626 */
1627 doc = xmlReadFile((const char *) URL,NULL,0);
1628 if (doc == NULL) {
1629 xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR,
1630 "xmlRelaxNG: could not load %s\n", URL, NULL);
1631 return (NULL);
1632 }
1633#ifdef DEBUG_INCLUDE
1634 xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL);
1635#endif
1636
1637 /*
1638 * Allocate the document structures and register it first.
1639 */
1640 ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));
1641 if (ret == NULL) {
1642 xmlRngPErrMemory(ctxt, "allocating include\n");
1643 xmlFreeDoc(doc);
1644 return (NULL);
1645 }
1646 memset(ret, 0, sizeof(xmlRelaxNGInclude));
1647 ret->doc = doc;
1648 ret->href = xmlStrdup(URL);
1649 ret->next = ctxt->includes;
1650 ctxt->includes = ret;
1651
1652 /*
1653 * transmit the ns if needed
1654 */
1655 if (ns != NULL) {
1657 if (root != NULL) {
1658 if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
1659 xmlSetProp(root, BAD_CAST "ns", ns);
1660 }
1661 }
1662 }
1663
1664 /*
1665 * push it on the stack
1666 */
1667 xmlRelaxNGIncludePush(ctxt, ret);
1668
1669 /*
1670 * Some preprocessing of the document content, this include recursing
1671 * in the include stack.
1672 */
1673#ifdef DEBUG_INCLUDE
1674 xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL);
1675#endif
1676
1677 doc = xmlRelaxNGCleanupDoc(ctxt, doc);
1678 if (doc == NULL) {
1679 ctxt->inc = NULL;
1680 return (NULL);
1681 }
1682
1683 /*
1684 * Pop up the include from the stack
1685 */
1686 xmlRelaxNGIncludePop(ctxt);
1687
1688#ifdef DEBUG_INCLUDE
1689 xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL);
1690#endif
1691 /*
1692 * Check that the top element is a grammar
1693 */
1695 if (root == NULL) {
1696 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY,
1697 "xmlRelaxNG: included document is empty %s\n", URL,
1698 NULL);
1699 return (NULL);
1700 }
1701 if (!IS_RELAXNG(root, "grammar")) {
1702 xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
1703 "xmlRelaxNG: included document %s root is not a grammar\n",
1704 URL, NULL);
1705 return (NULL);
1706 }
1707
1708 /*
1709 * Elimination of redefined rules in the include.
1710 */
1711 cur = node->children;
1712 while (cur != NULL) {
1713 if (IS_RELAXNG(cur, "start")) {
1714 int found = 0;
1715
1716 found =
1717 xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);
1718 if (!found) {
1719 xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING,
1720 "xmlRelaxNG: include %s has a start but not the included grammar\n",
1721 URL, NULL);
1722 }
1723 } else if (IS_RELAXNG(cur, "define")) {
1724 xmlChar *name;
1725
1726 name = xmlGetProp(cur, BAD_CAST "name");
1727 if (name == NULL) {
1728 xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING,
1729 "xmlRelaxNG: include %s has define without name\n",
1730 URL, NULL);
1731 } else {
1732 int found;
1733
1734 xmlRelaxNGNormExtSpace(name);
1735 found = xmlRelaxNGRemoveRedefine(ctxt, URL,
1736 root->children, name);
1737 if (!found) {
1738 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING,
1739 "xmlRelaxNG: include %s has a define %s but not the included grammar\n",
1740 URL, name);
1741 }
1742 xmlFree(name);
1743 }
1744 }
1745 if (IS_RELAXNG(cur, "div") && cur->children != NULL) {
1746 cur = cur->children;
1747 } else {
1748 if (cur->next != NULL) {
1749 cur = cur->next;
1750 } else {
1751 while (cur->parent != node && cur->parent->next == NULL) {
1752 cur = cur->parent;
1753 }
1754 cur = cur->parent != node ? cur->parent->next : NULL;
1755 }
1756 }
1757 }
1758
1759
1760 return (ret);
1761}
1762
1775static int
1776xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
1777 xmlRelaxNGValidErr err, const xmlChar * arg1,
1778 const xmlChar * arg2, int dup)
1779{
1780 xmlRelaxNGValidErrorPtr cur;
1781
1782#ifdef DEBUG_ERROR
1784 "Pushing error %d at %d on stack\n", err, ctxt->errNr);
1785#endif
1786 if (ctxt->errTab == NULL) {
1787 ctxt->errMax = 8;
1788 ctxt->errNr = 0;
1789 ctxt->errTab =
1790 (xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax *
1791 sizeof
1792 (xmlRelaxNGValidError));
1793 if (ctxt->errTab == NULL) {
1794 xmlRngVErrMemory(ctxt, "pushing error\n");
1795 return (0);
1796 }
1797 ctxt->err = NULL;
1798 }
1799 if (ctxt->errNr >= ctxt->errMax) {
1800 ctxt->errMax *= 2;
1801 ctxt->errTab =
1802 (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,
1803 ctxt->errMax *
1804 sizeof
1805 (xmlRelaxNGValidError));
1806 if (ctxt->errTab == NULL) {
1807 xmlRngVErrMemory(ctxt, "pushing error\n");
1808 return (0);
1809 }
1810 ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
1811 }
1812 if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
1813 (ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err))
1814 return (ctxt->errNr);
1815 cur = &ctxt->errTab[ctxt->errNr];
1816 cur->err = err;
1817 if (dup) {
1818 cur->arg1 = xmlStrdup(arg1);
1819 cur->arg2 = xmlStrdup(arg2);
1820 cur->flags = ERROR_IS_DUP;
1821 } else {
1822 cur->arg1 = arg1;
1823 cur->arg2 = arg2;
1824 cur->flags = 0;
1825 }
1826 if (ctxt->state != NULL) {
1827 cur->node = ctxt->state->node;
1828 cur->seq = ctxt->state->seq;
1829 } else {
1830 cur->node = NULL;
1831 cur->seq = NULL;
1832 }
1833 ctxt->err = cur;
1834 return (ctxt->errNr++);
1835}
1836
1843static void
1844xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
1845{
1846 xmlRelaxNGValidErrorPtr cur;
1847
1848 if (ctxt->errNr <= 0) {
1849 ctxt->err = NULL;
1850 return;
1851 }
1852 ctxt->errNr--;
1853 if (ctxt->errNr > 0)
1854 ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
1855 else
1856 ctxt->err = NULL;
1857 cur = &ctxt->errTab[ctxt->errNr];
1858 if (cur->flags & ERROR_IS_DUP) {
1859 if (cur->arg1 != NULL)
1860 xmlFree((xmlChar *) cur->arg1);
1861 cur->arg1 = NULL;
1862 if (cur->arg2 != NULL)
1863 xmlFree((xmlChar *) cur->arg2);
1864 cur->arg2 = NULL;
1865 cur->flags = 0;
1866 }
1867}
1868
1878static int
1879xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
1880 xmlRelaxNGDocumentPtr value)
1881{
1882 if (ctxt->docTab == NULL) {
1883 ctxt->docMax = 4;
1884 ctxt->docNr = 0;
1885 ctxt->docTab =
1886 (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *
1887 sizeof(ctxt->docTab[0]));
1888 if (ctxt->docTab == NULL) {
1889 xmlRngPErrMemory(ctxt, "adding document\n");
1890 return (0);
1891 }
1892 }
1893 if (ctxt->docNr >= ctxt->docMax) {
1894 ctxt->docMax *= 2;
1895 ctxt->docTab =
1896 (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,
1897 ctxt->docMax *
1898 sizeof(ctxt->docTab[0]));
1899 if (ctxt->docTab == NULL) {
1900 xmlRngPErrMemory(ctxt, "adding document\n");
1901 return (0);
1902 }
1903 }
1904 ctxt->docTab[ctxt->docNr] = value;
1905 ctxt->doc = value;
1906 return (ctxt->docNr++);
1907}
1908
1917static xmlRelaxNGDocumentPtr
1918xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)
1919{
1920 xmlRelaxNGDocumentPtr ret;
1921
1922 if (ctxt->docNr <= 0)
1923 return (NULL);
1924 ctxt->docNr--;
1925 if (ctxt->docNr > 0)
1926 ctxt->doc = ctxt->docTab[ctxt->docNr - 1];
1927 else
1928 ctxt->doc = NULL;
1929 ret = ctxt->docTab[ctxt->docNr];
1930 ctxt->docTab[ctxt->docNr] = NULL;
1931 return (ret);
1932}
1933
1946static xmlRelaxNGDocumentPtr
1947xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
1948 const xmlChar * URL, const xmlChar * ns)
1949{
1950 xmlRelaxNGDocumentPtr ret = NULL;
1951 xmlDocPtr doc;
1953 int i;
1954
1955 /*
1956 * check against recursion in the stack
1957 */
1958 for (i = 0; i < ctxt->docNr; i++) {
1959 if (xmlStrEqual(ctxt->docTab[i]->href, URL)) {
1960 xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE,
1961 "Detected an externalRef recursion for %s\n", URL,
1962 NULL);
1963 return (NULL);
1964 }
1965 }
1966
1967 /*
1968 * load the document
1969 */
1970 doc = xmlReadFile((const char *) URL,NULL,0);
1971 if (doc == NULL) {
1972 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
1973 "xmlRelaxNG: could not load %s\n", URL, NULL);
1974 return (NULL);
1975 }
1976
1977 /*
1978 * Allocate the document structures and register it first.
1979 */
1980 ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
1981 if (ret == NULL) {
1982 xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,
1983 "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);
1984 xmlFreeDoc(doc);
1985 return (NULL);
1986 }
1987 memset(ret, 0, sizeof(xmlRelaxNGDocument));
1988 ret->doc = doc;
1989 ret->href = xmlStrdup(URL);
1990 ret->next = ctxt->documents;
1991 ret->externalRef = 1;
1992 ctxt->documents = ret;
1993
1994 /*
1995 * transmit the ns if needed
1996 */
1997 if (ns != NULL) {
1999 if (root != NULL) {
2000 if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
2001 xmlSetProp(root, BAD_CAST "ns", ns);
2002 }
2003 }
2004 }
2005
2006 /*
2007 * push it on the stack and register it in the hash table
2008 */
2009 xmlRelaxNGDocumentPush(ctxt, ret);
2010
2011 /*
2012 * Some preprocessing of the document content
2013 */
2014 doc = xmlRelaxNGCleanupDoc(ctxt, doc);
2015 if (doc == NULL) {
2016 ctxt->doc = NULL;
2017 return (NULL);
2018 }
2019
2020 xmlRelaxNGDocumentPop(ctxt);
2021
2022 return (ret);
2023}
2024
2025/************************************************************************
2026 * *
2027 * Error functions *
2028 * *
2029 ************************************************************************/
2030
2031#define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
2032#define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
2033#define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
2034#define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
2035#define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
2036
2037static const char *
2038xmlRelaxNGDefName(xmlRelaxNGDefinePtr def)
2039{
2040 if (def == NULL)
2041 return ("none");
2042 switch (def->type) {
2043 case XML_RELAXNG_EMPTY:
2044 return ("empty");
2045 case XML_RELAXNG_NOT_ALLOWED:
2046 return ("notAllowed");
2047 case XML_RELAXNG_EXCEPT:
2048 return ("except");
2049 case XML_RELAXNG_TEXT:
2050 return ("text");
2051 case XML_RELAXNG_ELEMENT:
2052 return ("element");
2053 case XML_RELAXNG_DATATYPE:
2054 return ("datatype");
2055 case XML_RELAXNG_VALUE:
2056 return ("value");
2057 case XML_RELAXNG_LIST:
2058 return ("list");
2059 case XML_RELAXNG_ATTRIBUTE:
2060 return ("attribute");
2061 case XML_RELAXNG_DEF:
2062 return ("def");
2063 case XML_RELAXNG_REF:
2064 return ("ref");
2065 case XML_RELAXNG_EXTERNALREF:
2066 return ("externalRef");
2067 case XML_RELAXNG_PARENTREF:
2068 return ("parentRef");
2069 case XML_RELAXNG_OPTIONAL:
2070 return ("optional");
2071 case XML_RELAXNG_ZEROORMORE:
2072 return ("zeroOrMore");
2073 case XML_RELAXNG_ONEORMORE:
2074 return ("oneOrMore");
2075 case XML_RELAXNG_CHOICE:
2076 return ("choice");
2077 case XML_RELAXNG_GROUP:
2078 return ("group");
2079 case XML_RELAXNG_INTERLEAVE:
2080 return ("interleave");
2081 case XML_RELAXNG_START:
2082 return ("start");
2083 case XML_RELAXNG_NOOP:
2084 return ("noop");
2085 case XML_RELAXNG_PARAM:
2086 return ("param");
2087 }
2088 return ("unknown");
2089}
2090
2101static xmlChar *
2102xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
2103 const xmlChar * arg2)
2104{
2105 char msg[1000];
2106 xmlChar *result;
2107
2108 if (arg1 == NULL)
2109 arg1 = BAD_CAST "";
2110 if (arg2 == NULL)
2111 arg2 = BAD_CAST "";
2112
2113 msg[0] = 0;
2114 switch (err) {
2115 case XML_RELAXNG_OK:
2116 return (NULL);
2117 case XML_RELAXNG_ERR_MEMORY:
2118 return (xmlCharStrdup("out of memory\n"));
2119 case XML_RELAXNG_ERR_TYPE:
2120 snprintf(msg, 1000, "failed to validate type %s\n", arg1);
2121 break;
2122 case XML_RELAXNG_ERR_TYPEVAL:
2123 snprintf(msg, 1000, "Type %s doesn't allow value '%s'\n", arg1,
2124 arg2);
2125 break;
2126 case XML_RELAXNG_ERR_DUPID:
2127 snprintf(msg, 1000, "ID %s redefined\n", arg1);
2128 break;
2129 case XML_RELAXNG_ERR_TYPECMP:
2130 snprintf(msg, 1000, "failed to compare type %s\n", arg1);
2131 break;
2132 case XML_RELAXNG_ERR_NOSTATE:
2133 return (xmlCharStrdup("Internal error: no state\n"));
2134 case XML_RELAXNG_ERR_NODEFINE:
2135 return (xmlCharStrdup("Internal error: no define\n"));
2136 case XML_RELAXNG_ERR_INTERNAL:
2137 snprintf(msg, 1000, "Internal error: %s\n", arg1);
2138 break;
2139 case XML_RELAXNG_ERR_LISTEXTRA:
2140 snprintf(msg, 1000, "Extra data in list: %s\n", arg1);
2141 break;
2142 case XML_RELAXNG_ERR_INTERNODATA:
2143 return (xmlCharStrdup
2144 ("Internal: interleave block has no data\n"));
2145 case XML_RELAXNG_ERR_INTERSEQ:
2146 return (xmlCharStrdup("Invalid sequence in interleave\n"));
2147 case XML_RELAXNG_ERR_INTEREXTRA:
2148 snprintf(msg, 1000, "Extra element %s in interleave\n", arg1);
2149 break;
2150 case XML_RELAXNG_ERR_ELEMNAME:
2151 snprintf(msg, 1000, "Expecting element %s, got %s\n", arg1,
2152 arg2);
2153 break;
2154 case XML_RELAXNG_ERR_ELEMNONS:
2155 snprintf(msg, 1000, "Expecting a namespace for element %s\n",
2156 arg1);
2157 break;
2158 case XML_RELAXNG_ERR_ELEMWRONGNS:
2159 snprintf(msg, 1000,
2160 "Element %s has wrong namespace: expecting %s\n", arg1,
2161 arg2);
2162 break;
2163 case XML_RELAXNG_ERR_ELEMWRONG:
2164 snprintf(msg, 1000, "Did not expect element %s there\n", arg1);
2165 break;
2166 case XML_RELAXNG_ERR_TEXTWRONG:
2167 snprintf(msg, 1000,
2168 "Did not expect text in element %s content\n", arg1);
2169 break;
2170 case XML_RELAXNG_ERR_ELEMEXTRANS:
2171 snprintf(msg, 1000, "Expecting no namespace for element %s\n",
2172 arg1);
2173 break;
2174 case XML_RELAXNG_ERR_ELEMNOTEMPTY:
2175 snprintf(msg, 1000, "Expecting element %s to be empty\n", arg1);
2176 break;
2177 case XML_RELAXNG_ERR_NOELEM:
2178 snprintf(msg, 1000, "Expecting an element %s, got nothing\n",
2179 arg1);
2180 break;
2181 case XML_RELAXNG_ERR_NOTELEM:
2182 return (xmlCharStrdup("Expecting an element got text\n"));
2183 case XML_RELAXNG_ERR_ATTRVALID:
2184 snprintf(msg, 1000, "Element %s failed to validate attributes\n",
2185 arg1);
2186 break;
2187 case XML_RELAXNG_ERR_CONTENTVALID:
2188 snprintf(msg, 1000, "Element %s failed to validate content\n",
2189 arg1);
2190 break;
2191 case XML_RELAXNG_ERR_EXTRACONTENT:
2192 snprintf(msg, 1000, "Element %s has extra content: %s\n",
2193 arg1, arg2);
2194 break;
2195 case XML_RELAXNG_ERR_INVALIDATTR:
2196 snprintf(msg, 1000, "Invalid attribute %s for element %s\n",
2197 arg1, arg2);
2198 break;
2199 case XML_RELAXNG_ERR_LACKDATA:
2200 snprintf(msg, 1000, "Datatype element %s contains no data\n",
2201 arg1);
2202 break;
2203 case XML_RELAXNG_ERR_DATAELEM:
2204 snprintf(msg, 1000, "Datatype element %s has child elements\n",
2205 arg1);
2206 break;
2207 case XML_RELAXNG_ERR_VALELEM:
2208 snprintf(msg, 1000, "Value element %s has child elements\n",
2209 arg1);
2210 break;
2211 case XML_RELAXNG_ERR_LISTELEM:
2212 snprintf(msg, 1000, "List element %s has child elements\n",
2213 arg1);
2214 break;
2215 case XML_RELAXNG_ERR_DATATYPE:
2216 snprintf(msg, 1000, "Error validating datatype %s\n", arg1);
2217 break;
2218 case XML_RELAXNG_ERR_VALUE:
2219 snprintf(msg, 1000, "Error validating value %s\n", arg1);
2220 break;
2221 case XML_RELAXNG_ERR_LIST:
2222 return (xmlCharStrdup("Error validating list\n"));
2223 case XML_RELAXNG_ERR_NOGRAMMAR:
2224 return (xmlCharStrdup("No top grammar defined\n"));
2225 case XML_RELAXNG_ERR_EXTRADATA:
2226 return (xmlCharStrdup("Extra data in the document\n"));
2227 default:
2228 return (xmlCharStrdup("Unknown error !\n"));
2229 }
2230 if (msg[0] == 0) {
2231 snprintf(msg, 1000, "Unknown error code %d\n", err);
2232 }
2233 msg[1000 - 1] = 0;
2235 return (xmlEscapeFormatString(&result));
2236}
2237
2249static void
2250xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt,
2251 xmlRelaxNGValidErr err, xmlNodePtr node,
2252 xmlNodePtr child, const xmlChar * arg1,
2253 const xmlChar * arg2)
2254{
2255 xmlChar *msg;
2256
2257 if (ctxt->flags & FLAGS_NOERROR)
2258 return;
2259
2260#ifdef DEBUG_ERROR
2261 xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err);
2262#endif
2263 msg = xmlRelaxNGGetErrorString(err, arg1, arg2);
2264 if (msg == NULL)
2265 return;
2266
2267 if (ctxt->errNo == XML_RELAXNG_OK)
2268 ctxt->errNo = err;
2269 xmlRngVErr(ctxt, (child == NULL ? node : child), err,
2270 (const char *) msg, arg1, arg2);
2271 xmlFree(msg);
2272}
2273
2281static void
2282xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level)
2283{
2284 int i;
2285 xmlRelaxNGValidErrorPtr err;
2286
2287#ifdef DEBUG_ERROR
2289 "Pop errors till level %d\n", level);
2290#endif
2291 for (i = level; i < ctxt->errNr; i++) {
2292 err = &ctxt->errTab[i];
2293 if (err->flags & ERROR_IS_DUP) {
2294 if (err->arg1 != NULL)
2295 xmlFree((xmlChar *) err->arg1);
2296 err->arg1 = NULL;
2297 if (err->arg2 != NULL)
2298 xmlFree((xmlChar *) err->arg2);
2299 err->arg2 = NULL;
2300 err->flags = 0;
2301 }
2302 }
2303 ctxt->errNr = level;
2304 if (ctxt->errNr <= 0)
2305 ctxt->err = NULL;
2306}
2307
2314static void
2315xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt)
2316{
2317 int i, j, k;
2318 xmlRelaxNGValidErrorPtr err, dup;
2319
2320#ifdef DEBUG_ERROR
2322 "Dumping error stack %d errors\n", ctxt->errNr);
2323#endif
2324 for (i = 0, k = 0; i < ctxt->errNr; i++) {
2325 err = &ctxt->errTab[i];
2326 if (k < MAX_ERROR) {
2327 for (j = 0; j < i; j++) {
2328 dup = &ctxt->errTab[j];
2329 if ((err->err == dup->err) && (err->node == dup->node) &&
2330 (xmlStrEqual(err->arg1, dup->arg1)) &&
2331 (xmlStrEqual(err->arg2, dup->arg2))) {
2332 goto skip;
2333 }
2334 }
2335 xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,
2336 err->arg1, err->arg2);
2337 k++;
2338 }
2339 skip:
2340 if (err->flags & ERROR_IS_DUP) {
2341 if (err->arg1 != NULL)
2342 xmlFree((xmlChar *) err->arg1);
2343 err->arg1 = NULL;
2344 if (err->arg2 != NULL)
2345 xmlFree((xmlChar *) err->arg2);
2346 err->arg2 = NULL;
2347 err->flags = 0;
2348 }
2349 }
2350 ctxt->errNr = 0;
2351}
2352
2364static void
2365xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt,
2366 xmlRelaxNGValidErr err, const xmlChar * arg1,
2367 const xmlChar * arg2, int dup)
2368{
2369 if (ctxt == NULL)
2370 return;
2371 if (ctxt->flags & FLAGS_NOERROR)
2372 return;
2373
2374#ifdef DEBUG_ERROR
2375 xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err);
2376#endif
2377 /*
2378 * generate the error directly
2379 */
2380 if (((ctxt->flags & FLAGS_IGNORABLE) == 0) ||
2381 (ctxt->flags & FLAGS_NEGATIVE)) {
2382 xmlNodePtr node, seq;
2383
2384 /*
2385 * Flush first any stacked error which might be the
2386 * real cause of the problem.
2387 */
2388 if (ctxt->errNr != 0)
2389 xmlRelaxNGDumpValidError(ctxt);
2390 if (ctxt->state != NULL) {
2391 node = ctxt->state->node;
2392 seq = ctxt->state->seq;
2393 } else {
2394 node = seq = NULL;
2395 }
2396 if ((node == NULL) && (seq == NULL)) {
2397 node = ctxt->pnode;
2398 }
2399 xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2);
2400 }
2401 /*
2402 * Stack the error for later processing if needed
2403 */
2404 else {
2405 xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);
2406 }
2407}
2408
2409
2410/************************************************************************
2411 * *
2412 * Type library hooks *
2413 * *
2414 ************************************************************************/
2415static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt,
2416 const xmlChar * str);
2417
2428static int
2429xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar * type)
2430{
2431 xmlSchemaTypePtr typ;
2432
2433 if (type == NULL)
2434 return (-1);
2435 typ = xmlSchemaGetPredefinedType(type,
2436 BAD_CAST
2437 "http://www.w3.org/2001/XMLSchema");
2438 if (typ == NULL)
2439 return (0);
2440 return (1);
2441}
2442
2455static int
2456xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
2457 const xmlChar * type,
2458 const xmlChar * value,
2459 void **result, xmlNodePtr node)
2460{
2461 xmlSchemaTypePtr typ;
2462 int ret;
2463
2464 if ((type == NULL) || (value == NULL))
2465 return (-1);
2466 typ = xmlSchemaGetPredefinedType(type,
2467 BAD_CAST
2468 "http://www.w3.org/2001/XMLSchema");
2469 if (typ == NULL)
2470 return (-1);
2471 ret = xmlSchemaValPredefTypeNode(typ, value,
2472 (xmlSchemaValPtr *) result, node);
2473 if (ret == 2) /* special ID error code */
2474 return (2);
2475 if (ret == 0)
2476 return (1);
2477 if (ret > 0)
2478 return (0);
2479 return (-1);
2480}
2481
2495static int
2496xmlRelaxNGSchemaFacetCheck(void *data ATTRIBUTE_UNUSED,
2497 const xmlChar * type, const xmlChar * facetname,
2498 const xmlChar * val, const xmlChar * strval,
2499 void *value)
2500{
2501 xmlSchemaFacetPtr facet;
2502 xmlSchemaTypePtr typ;
2503 int ret;
2504
2505 if ((type == NULL) || (strval == NULL))
2506 return (-1);
2507 typ = xmlSchemaGetPredefinedType(type,
2508 BAD_CAST
2509 "http://www.w3.org/2001/XMLSchema");
2510 if (typ == NULL)
2511 return (-1);
2512
2513 facet = xmlSchemaNewFacet();
2514 if (facet == NULL)
2515 return (-1);
2516
2517 if (xmlStrEqual(facetname, BAD_CAST "minInclusive")) {
2518 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
2519 } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive")) {
2520 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
2521 } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive")) {
2522 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
2523 } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive")) {
2524 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
2525 } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits")) {
2526 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
2527 } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits")) {
2528 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
2529 } else if (xmlStrEqual(facetname, BAD_CAST "pattern")) {
2530 facet->type = XML_SCHEMA_FACET_PATTERN;
2531 } else if (xmlStrEqual(facetname, BAD_CAST "enumeration")) {
2532 facet->type = XML_SCHEMA_FACET_ENUMERATION;
2533 } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace")) {
2534 facet->type = XML_SCHEMA_FACET_WHITESPACE;
2535 } else if (xmlStrEqual(facetname, BAD_CAST "length")) {
2536 facet->type = XML_SCHEMA_FACET_LENGTH;
2537 } else if (xmlStrEqual(facetname, BAD_CAST "maxLength")) {
2538 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
2539 } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) {
2540 facet->type = XML_SCHEMA_FACET_MINLENGTH;
2541 } else {
2542 xmlSchemaFreeFacet(facet);
2543 return (-1);
2544 }
2545 facet->value = val;
2546 ret = xmlSchemaCheckFacet(facet, typ, NULL, type);
2547 if (ret != 0) {
2548 xmlSchemaFreeFacet(facet);
2549 return (-1);
2550 }
2551 ret = xmlSchemaValidateFacet(typ, facet, strval, value);
2552 xmlSchemaFreeFacet(facet);
2553 if (ret != 0)
2554 return (-1);
2555 return (0);
2556}
2557
2567static void
2568xmlRelaxNGSchemaFreeValue(void *data ATTRIBUTE_UNUSED, void *value)
2569{
2570 xmlSchemaFreeValue(value);
2571}
2572
2585static int
2586xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
2587 const xmlChar * type,
2588 const xmlChar * value1,
2589 xmlNodePtr ctxt1,
2590 void *comp1,
2591 const xmlChar * value2, xmlNodePtr ctxt2)
2592{
2593 int ret;
2594 xmlSchemaTypePtr typ;
2595 xmlSchemaValPtr res1 = NULL, res2 = NULL;
2596
2597 if ((type == NULL) || (value1 == NULL) || (value2 == NULL))
2598 return (-1);
2599 typ = xmlSchemaGetPredefinedType(type,
2600 BAD_CAST
2601 "http://www.w3.org/2001/XMLSchema");
2602 if (typ == NULL)
2603 return (-1);
2604 if (comp1 == NULL) {
2605 ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1);
2606 if (ret != 0)
2607 return (-1);
2608 if (res1 == NULL)
2609 return (-1);
2610 } else {
2611 res1 = (xmlSchemaValPtr) comp1;
2612 }
2613 ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2);
2614 if (ret != 0) {
2615 if (res1 != (xmlSchemaValPtr) comp1)
2616 xmlSchemaFreeValue(res1);
2617 return (-1);
2618 }
2619 ret = xmlSchemaCompareValues(res1, res2);
2620 if (res1 != (xmlSchemaValPtr) comp1)
2621 xmlSchemaFreeValue(res1);
2622 xmlSchemaFreeValue(res2);
2623 if (ret == -2)
2624 return (-1);
2625 if (ret == 0)
2626 return (1);
2627 return (0);
2628}
2629
2640static int
2641xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED,
2642 const xmlChar * type)
2643{
2644 if (type == NULL)
2645 return (-1);
2646 if (xmlStrEqual(type, BAD_CAST "string"))
2647 return (1);
2648 if (xmlStrEqual(type, BAD_CAST "token"))
2649 return (1);
2650 return (0);
2651}
2652
2665static int
2666xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
2669 void **result ATTRIBUTE_UNUSED,
2671{
2672 if (value == NULL)
2673 return (-1);
2674 if (xmlStrEqual(type, BAD_CAST "string"))
2675 return (1);
2676 if (xmlStrEqual(type, BAD_CAST "token")) {
2677 return (1);
2678 }
2679
2680 return (0);
2681}
2682
2695static int
2696xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
2697 const xmlChar * type,
2698 const xmlChar * value1,
2700 void *comp1 ATTRIBUTE_UNUSED,
2701 const xmlChar * value2,
2703{
2704 int ret = -1;
2705
2706 if (xmlStrEqual(type, BAD_CAST "string")) {
2707 ret = xmlStrEqual(value1, value2);
2708 } else if (xmlStrEqual(type, BAD_CAST "token")) {
2709 if (!xmlStrEqual(value1, value2)) {
2710 xmlChar *nval, *nvalue;
2711
2712 /*
2713 * TODO: trivial optimizations are possible by
2714 * computing at compile-time
2715 */
2716 nval = xmlRelaxNGNormalize(NULL, value1);
2717 nvalue = xmlRelaxNGNormalize(NULL, value2);
2718
2719 if ((nval == NULL) || (nvalue == NULL))
2720 ret = -1;
2721 else if (xmlStrEqual(nval, nvalue))
2722 ret = 1;
2723 else
2724 ret = 0;
2725 if (nval != NULL)
2726 xmlFree(nval);
2727 if (nvalue != NULL)
2728 xmlFree(nvalue);
2729 } else
2730 ret = 1;
2731 }
2732 return (ret);
2733}
2734
2735static int xmlRelaxNGTypeInitialized = 0;
2736static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
2737
2745static void
2746xmlRelaxNGFreeTypeLibrary(void *payload,
2747 const xmlChar * namespace ATTRIBUTE_UNUSED)
2748{
2749 xmlRelaxNGTypeLibraryPtr lib = (xmlRelaxNGTypeLibraryPtr) payload;
2750 if (lib == NULL)
2751 return;
2752 if (lib->namespace != NULL)
2753 xmlFree((xmlChar *) lib->namespace);
2754 xmlFree(lib);
2755}
2756
2769static int
2770xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,
2771 xmlRelaxNGTypeHave have,
2772 xmlRelaxNGTypeCheck check,
2773 xmlRelaxNGTypeCompare comp,
2774 xmlRelaxNGFacetCheck facet,
2775 xmlRelaxNGTypeFree freef)
2776{
2777 xmlRelaxNGTypeLibraryPtr lib;
2778 int ret;
2779
2780 if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
2781 (check == NULL) || (comp == NULL))
2782 return (-1);
2783 if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
2785 "Relax-NG types library '%s' already registered\n",
2786 namespace);
2787 return (-1);
2788 }
2789 lib =
2790 (xmlRelaxNGTypeLibraryPtr)
2791 xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
2792 if (lib == NULL) {
2793 xmlRngVErrMemory(NULL, "adding types library\n");
2794 return (-1);
2795 }
2796 memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
2797 lib->namespace = xmlStrdup(namespace);
2798 lib->data = data;
2799 lib->have = have;
2800 lib->comp = comp;
2801 lib->check = check;
2802 lib->facet = facet;
2803 lib->freef = freef;
2804 ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
2805 if (ret < 0) {
2807 "Relax-NG types library failed to register '%s'\n",
2808 namespace);
2809 xmlRelaxNGFreeTypeLibrary(lib, namespace);
2810 return (-1);
2811 }
2812 return (0);
2813}
2814
2822int
2823xmlRelaxNGInitTypes(void)
2824{
2825 if (xmlRelaxNGTypeInitialized != 0)
2826 return (0);
2827 xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
2828 if (xmlRelaxNGRegisteredTypes == NULL) {
2830 "Failed to allocate sh table for Relax-NG types\n");
2831 return (-1);
2832 }
2833 xmlRelaxNGRegisterTypeLibrary(BAD_CAST
2834 "http://www.w3.org/2001/XMLSchema-datatypes",
2835 NULL, xmlRelaxNGSchemaTypeHave,
2836 xmlRelaxNGSchemaTypeCheck,
2837 xmlRelaxNGSchemaTypeCompare,
2838 xmlRelaxNGSchemaFacetCheck,
2839 xmlRelaxNGSchemaFreeValue);
2840 xmlRelaxNGRegisterTypeLibrary(xmlRelaxNGNs, NULL,
2841 xmlRelaxNGDefaultTypeHave,
2842 xmlRelaxNGDefaultTypeCheck,
2843 xmlRelaxNGDefaultTypeCompare, NULL,
2844 NULL);
2845 xmlRelaxNGTypeInitialized = 1;
2846 return (0);
2847}
2848
2859void
2860xmlRelaxNGCleanupTypes(void)
2861{
2862 xmlSchemaCleanupTypes();
2863 if (xmlRelaxNGTypeInitialized == 0)
2864 return;
2865 xmlHashFree(xmlRelaxNGRegisteredTypes, xmlRelaxNGFreeTypeLibrary);
2866 xmlRelaxNGTypeInitialized = 0;
2867}
2868
2869/************************************************************************
2870 * *
2871 * Compiling element content into regexp *
2872 * *
2873 * Sometime the element content can be compiled into a pure regexp, *
2874 * This allows a faster execution and streamability at that level *
2875 * *
2876 ************************************************************************/
2877
2878/* from automata.c but not exported */
2879void xmlAutomataSetFlags(xmlAutomataPtr am, int flags);
2880
2881
2882static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,
2883 xmlRelaxNGDefinePtr def);
2884
2893static int
2894xmlRelaxNGIsCompilable(xmlRelaxNGDefinePtr def)
2895{
2896 int ret = -1;
2897
2898 if (def == NULL) {
2899 return (-1);
2900 }
2901 if ((def->type != XML_RELAXNG_ELEMENT) &&
2902 (def->dflags & IS_COMPILABLE))
2903 return (1);
2904 if ((def->type != XML_RELAXNG_ELEMENT) &&
2905 (def->dflags & IS_NOT_COMPILABLE))
2906 return (0);
2907 switch (def->type) {
2908 case XML_RELAXNG_NOOP:
2909 ret = xmlRelaxNGIsCompilable(def->content);
2910 break;
2911 case XML_RELAXNG_TEXT:
2912 case XML_RELAXNG_EMPTY:
2913 ret = 1;
2914 break;
2915 case XML_RELAXNG_ELEMENT:
2916 /*
2917 * Check if the element content is compilable
2918 */
2919 if (((def->dflags & IS_NOT_COMPILABLE) == 0) &&
2920 ((def->dflags & IS_COMPILABLE) == 0)) {
2921 xmlRelaxNGDefinePtr list;
2922
2923 list = def->content;
2924 while (list != NULL) {
2925 ret = xmlRelaxNGIsCompilable(list);
2926 if (ret != 1)
2927 break;
2928 list = list->next;
2929 }
2930 /*
2931 * Because the routine is recursive, we must guard against
2932 * discovering both COMPILABLE and NOT_COMPILABLE
2933 */
2934 if (ret == 0) {
2935 def->dflags &= ~IS_COMPILABLE;
2936 def->dflags |= IS_NOT_COMPILABLE;
2937 }
2938 if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE))
2939 def->dflags |= IS_COMPILABLE;
2940#ifdef DEBUG_COMPILE
2941 if (ret == 1) {
2943 "element content for %s is compilable\n",
2944 def->name);
2945 } else if (ret == 0) {
2947 "element content for %s is not compilable\n",
2948 def->name);
2949 } else {
2951 "Problem in RelaxNGIsCompilable for element %s\n",
2952 def->name);
2953 }
2954#endif
2955 }
2956 /*
2957 * All elements return a compilable status unless they
2958 * are generic like anyName
2959 */
2960 if ((def->nameClass != NULL) || (def->name == NULL))
2961 ret = 0;
2962 else
2963 ret = 1;
2964 return (ret);
2965 case XML_RELAXNG_REF:
2966 case XML_RELAXNG_EXTERNALREF:
2967 case XML_RELAXNG_PARENTREF:
2968 if (def->depth == -20) {
2969 return (1);
2970 } else {
2971 xmlRelaxNGDefinePtr list;
2972
2973 def->depth = -20;
2974 list = def->content;
2975 while (list != NULL) {
2976 ret = xmlRelaxNGIsCompilable(list);
2977 if (ret != 1)
2978 break;
2979 list = list->next;
2980 }
2981 }
2982 break;
2983 case XML_RELAXNG_START:
2984 case XML_RELAXNG_OPTIONAL:
2985 case XML_RELAXNG_ZEROORMORE:
2986 case XML_RELAXNG_ONEORMORE:
2987 case XML_RELAXNG_CHOICE:
2988 case XML_RELAXNG_GROUP:
2989 case XML_RELAXNG_DEF:{
2990 xmlRelaxNGDefinePtr list;
2991
2992 list = def->content;
2993 while (list != NULL) {
2994 ret = xmlRelaxNGIsCompilable(list);
2995 if (ret != 1)
2996 break;
2997 list = list->next;
2998 }
2999 break;
3000 }
3001 case XML_RELAXNG_EXCEPT:
3002 case XML_RELAXNG_ATTRIBUTE:
3003 case XML_RELAXNG_INTERLEAVE:
3004 case XML_RELAXNG_DATATYPE:
3005 case XML_RELAXNG_LIST:
3006 case XML_RELAXNG_PARAM:
3007 case XML_RELAXNG_VALUE:
3008 case XML_RELAXNG_NOT_ALLOWED:
3009 ret = 0;
3010 break;
3011 }
3012 if (ret == 0)
3013 def->dflags |= IS_NOT_COMPILABLE;
3014 if (ret == 1)
3015 def->dflags |= IS_COMPILABLE;
3016#ifdef DEBUG_COMPILE
3017 if (ret == 1) {
3019 "RelaxNGIsCompilable %s : true\n",
3020 xmlRelaxNGDefName(def));
3021 } else if (ret == 0) {
3023 "RelaxNGIsCompilable %s : false\n",
3024 xmlRelaxNGDefName(def));
3025 } else {
3027 "Problem in RelaxNGIsCompilable %s\n",
3028 xmlRelaxNGDefName(def));
3029 }
3030#endif
3031 return (ret);
3032}
3033
3044static int
3045xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
3046{
3047 int ret = 0;
3048 xmlRelaxNGDefinePtr list;
3049
3050 if ((ctxt == NULL) || (def == NULL))
3051 return (-1);
3052
3053 switch (def->type) {
3054 case XML_RELAXNG_START:
3055 if ((xmlRelaxNGIsCompilable(def) == 1) && (def->depth != -25)) {
3056 xmlAutomataPtr oldam = ctxt->am;
3057 xmlAutomataStatePtr oldstate = ctxt->state;
3058
3059 def->depth = -25;
3060
3061 list = def->content;
3062 ctxt->am = xmlNewAutomata();
3063 if (ctxt->am == NULL)
3064 return (-1);
3065
3066 /*
3067 * assume identical strings but not same pointer are different
3068 * atoms, needed for non-determinism detection
3069 * That way if 2 elements with the same name are in a choice
3070 * branch the automata is found non-deterministic and
3071 * we fallback to the normal validation which does the right
3072 * thing of exploring both choices.
3073 */
3074 xmlAutomataSetFlags(ctxt->am, 1);
3075
3076 ctxt->state = xmlAutomataGetInitState(ctxt->am);
3077 while (list != NULL) {
3078 xmlRelaxNGCompile(ctxt, list);
3079 list = list->next;
3080 }
3081 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
3082 if (xmlAutomataIsDeterminist(ctxt->am))
3083 def->contModel = xmlAutomataCompile(ctxt->am);
3084
3085 xmlFreeAutomata(ctxt->am);
3086 ctxt->state = oldstate;
3087 ctxt->am = oldam;
3088 }
3089 break;
3090 case XML_RELAXNG_ELEMENT:
3091 if ((ctxt->am != NULL) && (def->name != NULL)) {
3092 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
3093 ctxt->state, NULL,
3094 def->name, def->ns,
3095 def);
3096 }
3097 if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
3098 xmlAutomataPtr oldam = ctxt->am;
3099 xmlAutomataStatePtr oldstate = ctxt->state;
3100
3101 def->depth = -25;
3102
3103 list = def->content;
3104 ctxt->am = xmlNewAutomata();
3105 if (ctxt->am == NULL)
3106 return (-1);
3107 xmlAutomataSetFlags(ctxt->am, 1);
3108 ctxt->state = xmlAutomataGetInitState(ctxt->am);
3109 while (list != NULL) {
3110 xmlRelaxNGCompile(ctxt, list);
3111 list = list->next;
3112 }
3113 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
3114 def->contModel = xmlAutomataCompile(ctxt->am);
3115 if (!xmlRegexpIsDeterminist(def->contModel)) {
3116#ifdef DEBUG_COMPILE
3118 "Content model not determinist %s\n",
3119 def->name);
3120#endif
3121 /*
3122 * we can only use the automata if it is determinist
3123 */
3124 xmlRegFreeRegexp(def->contModel);
3125 def->contModel = NULL;
3126 }
3127 xmlFreeAutomata(ctxt->am);
3128 ctxt->state = oldstate;
3129 ctxt->am = oldam;
3130 } else {
3131 xmlAutomataPtr oldam = ctxt->am;
3132
3133 /*
3134 * we can't build the content model for this element content
3135 * but it still might be possible to build it for some of its
3136 * children, recurse.
3137 */
3138 ret = xmlRelaxNGTryCompile(ctxt, def);
3139 ctxt->am = oldam;
3140 }
3141 break;
3142 case XML_RELAXNG_NOOP:
3143 ret = xmlRelaxNGCompile(ctxt, def->content);
3144 break;
3145 case XML_RELAXNG_OPTIONAL:{
3146 xmlAutomataStatePtr oldstate = ctxt->state;
3147
3148 list = def->content;
3149 while (list != NULL) {
3150 xmlRelaxNGCompile(ctxt, list);
3151 list = list->next;
3152 }
3153 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3154 break;
3155 }
3156 case XML_RELAXNG_ZEROORMORE:{
3157 xmlAutomataStatePtr oldstate;
3158
3159 ctxt->state =
3160 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
3161 oldstate = ctxt->state;
3162 list = def->content;
3163 while (list != NULL) {
3164 xmlRelaxNGCompile(ctxt, list);
3165 list = list->next;
3166 }
3167 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3168 ctxt->state =
3169 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
3170 break;
3171 }
3172 case XML_RELAXNG_ONEORMORE:{
3173 xmlAutomataStatePtr oldstate;
3174
3175 list = def->content;
3176 while (list != NULL) {
3177 xmlRelaxNGCompile(ctxt, list);
3178 list = list->next;
3179 }
3180 oldstate = ctxt->state;
3181 list = def->content;
3182 while (list != NULL) {
3183 xmlRelaxNGCompile(ctxt, list);
3184 list = list->next;
3185 }
3186 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3187 ctxt->state =
3188 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
3189 break;
3190 }
3191 case XML_RELAXNG_CHOICE:{
3192 xmlAutomataStatePtr target = NULL;
3193 xmlAutomataStatePtr oldstate = ctxt->state;
3194
3195 list = def->content;
3196 while (list != NULL) {
3197 ctxt->state = oldstate;
3198 ret = xmlRelaxNGCompile(ctxt, list);
3199 if (ret != 0)
3200 break;
3201 if (target == NULL)
3202 target = ctxt->state;
3203 else {
3204 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3205 target);
3206 }
3207 list = list->next;
3208 }
3209 ctxt->state = target;
3210
3211 break;
3212 }
3213 case XML_RELAXNG_REF:
3214 case XML_RELAXNG_EXTERNALREF:
3215 case XML_RELAXNG_PARENTREF:
3216 case XML_RELAXNG_GROUP:
3217 case XML_RELAXNG_DEF:
3218 list = def->content;
3219 while (list != NULL) {
3220 ret = xmlRelaxNGCompile(ctxt, list);
3221 if (ret != 0)
3222 break;
3223 list = list->next;
3224 }
3225 break;
3226 case XML_RELAXNG_TEXT:{
3227 xmlAutomataStatePtr oldstate;
3228
3229 ctxt->state =
3230 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
3231 oldstate = ctxt->state;
3232 xmlRelaxNGCompile(ctxt, def->content);
3233 xmlAutomataNewTransition(ctxt->am, ctxt->state,
3234 ctxt->state, BAD_CAST "#text",
3235 NULL);
3236 ctxt->state =
3237 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
3238 break;
3239 }
3240 case XML_RELAXNG_EMPTY:
3241 ctxt->state =
3242 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
3243 break;
3244 case XML_RELAXNG_EXCEPT:
3245 case XML_RELAXNG_ATTRIBUTE:
3246 case XML_RELAXNG_INTERLEAVE:
3247 case XML_RELAXNG_NOT_ALLOWED:
3248 case XML_RELAXNG_DATATYPE:
3249 case XML_RELAXNG_LIST:
3250 case XML_RELAXNG_PARAM:
3251 case XML_RELAXNG_VALUE:
3252 /* This should not happen and generate an internal error */
3253 fprintf(stderr, "RNG internal error trying to compile %s\n",
3254 xmlRelaxNGDefName(def));
3255 break;
3256 }
3257 return (ret);
3258}
3259
3270static int
3271xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
3272{
3273 int ret = 0;
3274 xmlRelaxNGDefinePtr list;
3275
3276 if ((ctxt == NULL) || (def == NULL))
3277 return (-1);
3278
3279 if ((def->type == XML_RELAXNG_START) ||
3280 (def->type == XML_RELAXNG_ELEMENT)) {
3281 ret = xmlRelaxNGIsCompilable(def);
3282 if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
3283 ctxt->am = NULL;
3284 ret = xmlRelaxNGCompile(ctxt, def);
3285#ifdef DEBUG_PROGRESSIVE
3286 if (ret == 0) {
3287 if (def->type == XML_RELAXNG_START)
3289 "compiled the start\n");
3290 else
3292 "compiled element %s\n", def->name);
3293 } else {
3294 if (def->type == XML_RELAXNG_START)
3296 "failed to compile the start\n");
3297 else
3299 "failed to compile element %s\n",
3300 def->name);
3301 }
3302#endif
3303 return (ret);
3304 }
3305 }
3306 switch (def->type) {
3307 case XML_RELAXNG_NOOP:
3308 ret = xmlRelaxNGTryCompile(ctxt, def->content);
3309 break;
3310 case XML_RELAXNG_TEXT:
3311 case XML_RELAXNG_DATATYPE:
3312 case XML_RELAXNG_LIST:
3313 case XML_RELAXNG_PARAM:
3314 case XML_RELAXNG_VALUE:
3315 case XML_RELAXNG_EMPTY:
3316 case XML_RELAXNG_ELEMENT:
3317 ret = 0;
3318 break;
3319 case XML_RELAXNG_OPTIONAL:
3320 case XML_RELAXNG_ZEROORMORE:
3321 case XML_RELAXNG_ONEORMORE:
3322 case XML_RELAXNG_CHOICE:
3323 case XML_RELAXNG_GROUP:
3324 case XML_RELAXNG_DEF:
3325 case XML_RELAXNG_START:
3326 case XML_RELAXNG_REF:
3327 case XML_RELAXNG_EXTERNALREF:
3328 case XML_RELAXNG_PARENTREF:
3329 list = def->content;
3330 while (list != NULL) {
3331 ret = xmlRelaxNGTryCompile(ctxt, list);
3332 if (ret != 0)
3333 break;
3334 list = list->next;
3335 }
3336 break;
3337 case XML_RELAXNG_EXCEPT:
3338 case XML_RELAXNG_ATTRIBUTE:
3339 case XML_RELAXNG_INTERLEAVE:
3340 case XML_RELAXNG_NOT_ALLOWED:
3341 ret = 0;
3342 break;
3343 }
3344 return (ret);
3345}
3346
3347/************************************************************************
3348 * *
3349 * Parsing functions *
3350 * *
3351 ************************************************************************/
3352
3353static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr
3354 ctxt, xmlNodePtr node);
3355static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr
3356 ctxt, xmlNodePtr node);
3357static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr
3358 ctxt, xmlNodePtr nodes,
3359 int group);
3360static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr
3361 ctxt, xmlNodePtr node);
3362static xmlRelaxNGPtr xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt,
3364static int xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
3365 xmlNodePtr nodes);
3366static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr
3367 ctxt, xmlNodePtr node,
3368 xmlRelaxNGDefinePtr
3369 def);
3370static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr
3371 ctxt, xmlNodePtr nodes);
3372static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
3373 xmlRelaxNGDefinePtr define,
3375
3376
3377#define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
3378
3387static int
3388xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define)
3389{
3390 int ret;
3391
3392 if (define == NULL)
3393 return (-1);
3394
3395 if (define->dflags & IS_NULLABLE)
3396 return (1);
3397 if (define->dflags & IS_NOT_NULLABLE)
3398 return (0);
3399 switch (define->type) {
3400 case XML_RELAXNG_EMPTY:
3401 case XML_RELAXNG_TEXT:
3402 ret = 1;
3403 break;
3404 case XML_RELAXNG_NOOP:
3405 case XML_RELAXNG_DEF:
3406 case XML_RELAXNG_REF:
3407 case XML_RELAXNG_EXTERNALREF:
3408 case XML_RELAXNG_PARENTREF:
3409 case XML_RELAXNG_ONEORMORE:
3410 ret = xmlRelaxNGIsNullable(define->content);
3411 break;
3412 case XML_RELAXNG_EXCEPT:
3413 case XML_RELAXNG_NOT_ALLOWED:
3414 case XML_RELAXNG_ELEMENT:
3415 case XML_RELAXNG_DATATYPE:
3416 case XML_RELAXNG_PARAM:
3417 case XML_RELAXNG_VALUE:
3418 case XML_RELAXNG_LIST:
3419 case XML_RELAXNG_ATTRIBUTE:
3420 ret = 0;
3421 break;
3422 case XML_RELAXNG_CHOICE:{
3423 xmlRelaxNGDefinePtr list = define->content;
3424
3425 while (list != NULL) {
3426 ret = xmlRelaxNGIsNullable(list);
3427 if (ret != 0)
3428 goto done;
3429 list = list->next;
3430 }
3431 ret = 0;
3432 break;
3433 }
3434 case XML_RELAXNG_START:
3435 case XML_RELAXNG_INTERLEAVE:
3436 case XML_RELAXNG_GROUP:{
3437 xmlRelaxNGDefinePtr list = define->content;
3438
3439 while (list != NULL) {
3440 ret = xmlRelaxNGIsNullable(list);
3441 if (ret != 1)
3442 goto done;
3443 list = list->next;
3444 }
3445 return (1);
3446 }
3447 default:
3448 return (-1);
3449 }
3450 done:
3451 if (ret == 0)
3452 define->dflags |= IS_NOT_NULLABLE;
3453 if (ret == 1)
3454 define->dflags |= IS_NULLABLE;
3455 return (ret);
3456}
3457
3466static int
3467xmlRelaxNGIsBlank(xmlChar * str)
3468{
3469 if (str == NULL)
3470 return (1);
3471 while (*str != 0) {
3472 if (!(IS_BLANK_CH(*str)))
3473 return (0);
3474 str++;
3475 }
3476 return (1);
3477}
3478
3488static xmlChar *
3489xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
3491{
3492 xmlChar *ret, *escape;
3493
3494 if (node == NULL)
3495 return(NULL);
3496
3497 if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
3498 ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
3499 if (ret != NULL) {
3500 if (ret[0] == 0) {
3501 xmlFree(ret);
3502 return (NULL);
3503 }
3505 if (escape == NULL) {
3506 return (ret);
3507 }
3508 xmlFree(ret);
3509 return (escape);
3510 }
3511 }
3512 node = node->parent;
3513 while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
3514 ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
3515 if (ret != NULL) {
3516 if (ret[0] == 0) {
3517 xmlFree(ret);
3518 return (NULL);
3519 }
3521 if (escape == NULL) {
3522 return (ret);
3523 }
3524 xmlFree(ret);
3525 return (escape);
3526 }
3527 node = node->parent;
3528 }
3529 return (NULL);
3530}
3531
3541static xmlRelaxNGDefinePtr
3542xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
3543{
3544 xmlRelaxNGDefinePtr def = NULL;
3545 xmlRelaxNGTypeLibraryPtr lib = NULL;
3546 xmlChar *type;
3548 int success = 0;
3549
3550 def = xmlRelaxNGNewDefine(ctxt, node);
3551 if (def == NULL)
3552 return (NULL);
3553 def->type = XML_RELAXNG_VALUE;
3554
3555 type = xmlGetProp(node, BAD_CAST "type");
3556 if (type != NULL) {
3557 xmlRelaxNGNormExtSpace(type);
3558 if (xmlValidateNCName(type, 0)) {
3559 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
3560 "value type '%s' is not an NCName\n", type, NULL);
3561 }
3562 library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
3563 if (library == NULL)
3564 library =
3565 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
3566
3567 def->name = type;
3568 def->ns = library;
3569
3570 lib = (xmlRelaxNGTypeLibraryPtr)
3571 xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
3572 if (lib == NULL) {
3573 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
3574 "Use of unregistered type library '%s'\n", library,
3575 NULL);
3576 def->data = NULL;
3577 } else {
3578 def->data = lib;
3579 if (lib->have == NULL) {
3580 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
3581 "Internal error with type library '%s': no 'have'\n",
3582 library, NULL);
3583 } else {
3584 success = lib->have(lib->data, def->name);
3585 if (success != 1) {
3586 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
3587 "Error type '%s' is not exported by type library '%s'\n",
3588 def->name, library);
3589 }
3590 }
3591 }
3592 }
3593 if (node->children == NULL) {
3594 def->value = xmlStrdup(BAD_CAST "");
3595 } else if (((node->children->type != XML_TEXT_NODE) &&
3596 (node->children->type != XML_CDATA_SECTION_NODE)) ||
3597 (node->children->next != NULL)) {
3598 xmlRngPErr(ctxt, node, XML_RNGP_TEXT_EXPECTED,
3599 "Expecting a single text value for <value>content\n",
3600 NULL, NULL);
3601 } else if (def != NULL) {
3602 def->value = xmlNodeGetContent(node);
3603 if (def->value == NULL) {
3604 xmlRngPErr(ctxt, node, XML_RNGP_VALUE_NO_CONTENT,
3605 "Element <value> has no content\n", NULL, NULL);
3606 } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) {
3607 void *val = NULL;
3608
3609 success =
3610 lib->check(lib->data, def->name, def->value, &val, node);
3611 if (success != 1) {
3612 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_VALUE,
3613 "Value '%s' is not acceptable for type '%s'\n",
3614 def->value, def->name);
3615 } else {
3616 if (val != NULL)
3617 def->attrs = val;
3618 }
3619 }
3620 }
3621 return (def);
3622}
3623
3633static xmlRelaxNGDefinePtr
3634xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
3635{
3636 xmlRelaxNGDefinePtr def = NULL, except;
3637 xmlRelaxNGDefinePtr param, lastparam = NULL;
3638 xmlRelaxNGTypeLibraryPtr lib;
3639 xmlChar *type;
3642 int tmp;
3643
3644 type = xmlGetProp(node, BAD_CAST "type");
3645 if (type == NULL) {
3646 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_MISSING, "data has no type\n", NULL,
3647 NULL);
3648 return (NULL);
3649 }
3650 xmlRelaxNGNormExtSpace(type);
3651 if (xmlValidateNCName(type, 0)) {
3652 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
3653 "data type '%s' is not an NCName\n", type, NULL);
3654 }
3655 library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
3656 if (library == NULL)
3657 library =
3658 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
3659
3660 def = xmlRelaxNGNewDefine(ctxt, node);
3661 if (def == NULL) {
3663 xmlFree(type);
3664 return (NULL);
3665 }
3666 def->type = XML_RELAXNG_DATATYPE;
3667 def->name = type;
3668 def->ns = library;
3669
3670 lib = (xmlRelaxNGTypeLibraryPtr)
3671 xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
3672 if (lib == NULL) {
3673 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
3674 "Use of unregistered type library '%s'\n", library,
3675 NULL);
3676 def->data = NULL;
3677 } else {
3678 def->data = lib;
3679 if (lib->have == NULL) {
3680 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
3681 "Internal error with type library '%s': no 'have'\n",
3682 library, NULL);
3683 } else {
3684 tmp = lib->have(lib->data, def->name);
3685 if (tmp != 1) {
3686 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
3687 "Error type '%s' is not exported by type library '%s'\n",
3688 def->name, library);
3689 } else
3690 if ((xmlStrEqual
3691 (library,
3692 BAD_CAST
3693 "http://www.w3.org/2001/XMLSchema-datatypes"))
3694 && ((xmlStrEqual(def->name, BAD_CAST "IDREF"))
3695 || (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) {
3696 ctxt->idref = 1;
3697 }
3698 }
3699 }
3700 content = node->children;
3701
3702 /*
3703 * Handle optional params
3704 */
3705 while (content != NULL) {
3706 if (!xmlStrEqual(content->name, BAD_CAST "param"))
3707 break;
3708 if (xmlStrEqual(library,
3709 BAD_CAST "http://relaxng.org/ns/structure/1.0")) {
3710 xmlRngPErr(ctxt, node, XML_RNGP_PARAM_FORBIDDEN,
3711 "Type library '%s' does not allow type parameters\n",
3712 library, NULL);
3713 content = content->next;
3714 while ((content != NULL) &&
3715 (xmlStrEqual(content->name, BAD_CAST "param")))
3716 content = content->next;
3717 } else {
3718 param = xmlRelaxNGNewDefine(ctxt, node);
3719 if (param != NULL) {
3720 param->type = XML_RELAXNG_PARAM;
3721 param->name = xmlGetProp(content, BAD_CAST "name");
3722 if (param->name == NULL) {
3723 xmlRngPErr(ctxt, node, XML_RNGP_PARAM_NAME_MISSING,
3724 "param has no name\n", NULL, NULL);
3725 }
3727 if (lastparam == NULL) {
3728 def->attrs = lastparam = param;
3729 } else {
3730 lastparam->next = param;
3731 lastparam = param;
3732 }
3733 if (lib != NULL) {
3734 }
3735 }
3736 content = content->next;
3737 }
3738 }
3739 /*
3740 * Handle optional except
3741 */
3742 if ((content != NULL)
3743 && (xmlStrEqual(content->name, BAD_CAST "except"))) {
3745 xmlRelaxNGDefinePtr tmp2, last = NULL;
3746
3747 except = xmlRelaxNGNewDefine(ctxt, node);
3748 if (except == NULL) {
3749 return (def);
3750 }
3751 except->type = XML_RELAXNG_EXCEPT;
3752 child = content->children;
3753 def->content = except;
3754 if (child == NULL) {
3755 xmlRngPErr(ctxt, content, XML_RNGP_EXCEPT_NO_CONTENT,
3756 "except has no content\n", NULL, NULL);
3757 }
3758 while (child != NULL) {
3759 tmp2 = xmlRelaxNGParsePattern(ctxt, child);
3760 if (tmp2 != NULL) {
3761 if (last == NULL) {
3762 except->content = last = tmp2;
3763 } else {
3764 last->next = tmp2;
3765 last = tmp2;
3766 }
3767 }
3768 child = child->next;
3769 }
3770 content = content->next;
3771 }
3772 /*
3773 * Check there is no unhandled data
3774 */
3775 if (content != NULL) {
3776 xmlRngPErr(ctxt, content, XML_RNGP_DATA_CONTENT,
3777 "Element data has unexpected content %s\n",
3778 content->name, NULL);
3779 }
3780
3781 return (def);
3782}
3783
3784static const xmlChar *invalidName = BAD_CAST "\1";
3785
3799static int
3800xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,
3801 xmlRelaxNGDefinePtr def2)
3802{
3803 int ret = 1;
3804 xmlNode node;
3805 xmlNs ns;
3806 xmlRelaxNGValidCtxt ctxt;
3807
3808 memset(&ctxt, 0, sizeof(xmlRelaxNGValidCtxt));
3809
3810 ctxt.flags = FLAGS_IGNORABLE | FLAGS_NOERROR;
3811
3812 if ((def1->type == XML_RELAXNG_ELEMENT) ||
3813 (def1->type == XML_RELAXNG_ATTRIBUTE)) {
3814 if (def2->type == XML_RELAXNG_TEXT)
3815 return (1);
3816 if (def1->name != NULL) {
3817 node.name = def1->name;
3818 } else {
3819 node.name = invalidName;
3820 }
3821 if (def1->ns != NULL) {
3822 if (def1->ns[0] == 0) {
3823 node.ns = NULL;
3824 } else {
3825 node.ns = &ns;
3826 ns.href = def1->ns;
3827 }
3828 } else {
3829 node.ns = NULL;
3830 }
3831 if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) {
3832 if (def1->nameClass != NULL) {
3833 ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2);
3834 } else {
3835 ret = 0;
3836 }
3837 } else {
3838 ret = 1;
3839 }
3840 } else if (def1->type == XML_RELAXNG_TEXT) {
3841 if (def2->type == XML_RELAXNG_TEXT)
3842 return (0);
3843 return (1);
3844 } else if (def1->type == XML_RELAXNG_EXCEPT) {
3845 ret = xmlRelaxNGCompareNameClasses(def1->content, def2);
3846 if (ret == 0)
3847 ret = 1;
3848 else if (ret == 1)
3849 ret = 0;
3850 } else {
3851 TODO ret = 0;
3852 }
3853 if (ret == 0)
3854 return (ret);
3855 if ((def2->type == XML_RELAXNG_ELEMENT) ||
3856 (def2->type == XML_RELAXNG_ATTRIBUTE)) {
3857 if (def2->name != NULL) {
3858 node.name = def2->name;
3859 } else {
3860 node.name = invalidName;
3861 }
3862 node.ns = &ns;
3863 if (def2->ns != NULL) {
3864 if (def2->ns[0] == 0) {
3865 node.ns = NULL;
3866 } else {
3867 ns.href = def2->ns;
3868 }
3869 } else {
3870 ns.href = invalidName;
3871 }
3872 if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) {
3873 if (def2->nameClass != NULL) {
3874 ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1);
3875 } else {
3876 ret = 0;
3877 }
3878 } else {
3879 ret = 1;
3880 }
3881 } else {
3882 TODO ret = 0;
3883 }
3884
3885 return (ret);
3886}
3887
3900static int
3901xmlRelaxNGCompareElemDefLists(xmlRelaxNGParserCtxtPtr ctxt
3902 ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr * def1,
3903 xmlRelaxNGDefinePtr * def2)
3904{
3905 xmlRelaxNGDefinePtr *basedef2 = def2;
3906
3907 if ((def1 == NULL) || (def2 == NULL))
3908 return (1);
3909 if ((*def1 == NULL) || (*def2 == NULL))
3910 return (1);
3911 while (*def1 != NULL) {
3912 while ((*def2) != NULL) {
3913 if (xmlRelaxNGCompareNameClasses(*def1, *def2) == 0)
3914 return (0);
3915 def2++;
3916 }
3917 def2 = basedef2;
3918 def1++;
3919 }
3920 return (1);
3921}
3922
3932static int
3933xmlRelaxNGGenerateAttributes(xmlRelaxNGParserCtxtPtr ctxt,
3934 xmlRelaxNGDefinePtr def)
3935{
3936 xmlRelaxNGDefinePtr parent, cur, tmp;
3937
3938 /*
3939 * Don't run that check in case of error. Infinite recursion
3940 * becomes possible.
3941 */
3942 if (ctxt->nbErrors != 0)
3943 return (-1);
3944
3945 parent = NULL;
3946 cur = def;
3947 while (cur != NULL) {
3948 if ((cur->type == XML_RELAXNG_ELEMENT) ||
3949 (cur->type == XML_RELAXNG_TEXT) ||
3950 (cur->type == XML_RELAXNG_DATATYPE) ||
3951 (cur->type == XML_RELAXNG_PARAM) ||
3952 (cur->type == XML_RELAXNG_LIST) ||
3953 (cur->type == XML_RELAXNG_VALUE) ||
3954 (cur->type == XML_RELAXNG_EMPTY))
3955 return (0);
3956 if ((cur->type == XML_RELAXNG_CHOICE) ||
3957 (cur->type == XML_RELAXNG_INTERLEAVE) ||
3958 (cur->type == XML_RELAXNG_GROUP) ||
3959 (cur->type == XML_RELAXNG_ONEORMORE) ||
3960 (cur->type == XML_RELAXNG_ZEROORMORE) ||
3961 (cur->type == XML_RELAXNG_OPTIONAL) ||
3962 (cur->type == XML_RELAXNG_PARENTREF) ||
3963 (cur->type == XML_RELAXNG_EXTERNALREF) ||
3964 (cur->type == XML_RELAXNG_REF) ||
3965 (cur->type == XML_RELAXNG_DEF)) {
3966 if (cur->content != NULL) {
3967 parent = cur;
3968 cur = cur->content;
3969 tmp = cur;
3970 while (tmp != NULL) {
3971 tmp->parent = parent;
3972 tmp = tmp->next;
3973 }
3974 continue;
3975 }
3976 }
3977 if (cur == def)
3978 break;
3979 if (cur->next != NULL) {
3980 cur = cur->next;
3981 continue;
3982 }
3983 do {
3984 cur = cur->parent;
3985 if (cur == NULL)
3986 break;
3987 if (cur == def)
3988 return (1);
3989 if (cur->next != NULL) {
3990 cur = cur->next;
3991 break;
3992 }
3993 } while (cur != NULL);
3994 }
3995 return (1);
3996}
3997
4008static xmlRelaxNGDefinePtr *
4009xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
4010 xmlRelaxNGDefinePtr def, int eora)
4011{
4012 xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp;
4013 int len = 0;
4014 int max = 0;
4015
4016 /*
4017 * Don't run that check in case of error. Infinite recursion
4018 * becomes possible.
4019 */
4020 if (ctxt->nbErrors != 0)
4021 return (NULL);
4022
4023 parent = NULL;
4024 cur = def;
4025 while (cur != NULL) {
4026 if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||
4027 (cur->type == XML_RELAXNG_TEXT))) ||
4028 ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE)) ||
4029 ((eora == 2) && ((cur->type == XML_RELAXNG_DATATYPE) ||
4030 (cur->type == XML_RELAXNG_ELEMENT) ||
4031 (cur->type == XML_RELAXNG_LIST) ||
4032 (cur->type == XML_RELAXNG_TEXT) ||
4033 (cur->type == XML_RELAXNG_VALUE)))) {
4034 if (ret == NULL) {
4035 max = 10;
4036 ret = (xmlRelaxNGDefinePtr *)
4037 xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr));
4038 if (ret == NULL) {
4039 xmlRngPErrMemory(ctxt, "getting element list\n");
4040 return (NULL);
4041 }
4042 } else if (max <= len) {
4043 xmlRelaxNGDefinePtr *temp;
4044
4045 max *= 2;
4047 (max + 1) * sizeof(xmlRelaxNGDefinePtr));
4048 if (temp == NULL) {
4049 xmlRngPErrMemory(ctxt, "getting element list\n");
4050 xmlFree(ret);
4051 return (NULL);
4052 }
4053 ret = temp;
4054 }
4055 ret[len++] = cur;
4056 ret[len] = NULL;
4057 } else if ((cur->type == XML_RELAXNG_CHOICE) ||
4058 (cur->type == XML_RELAXNG_INTERLEAVE) ||
4059 (cur->type == XML_RELAXNG_GROUP) ||
4060 (cur->type == XML_RELAXNG_ONEORMORE) ||
4061 (cur->type == XML_RELAXNG_ZEROORMORE) ||
4062 (cur->type == XML_RELAXNG_OPTIONAL) ||
4063 (cur->type == XML_RELAXNG_PARENTREF) ||
4064 (cur->type == XML_RELAXNG_REF) ||
4065 (cur->type == XML_RELAXNG_DEF) ||
4066 (cur->type == XML_RELAXNG_EXTERNALREF)) {
4067 /*
4068 * Don't go within elements or attributes or string values.
4069 * Just gather the element top list
4070 */
4071 if (cur->content != NULL) {
4072 parent = cur;
4073 cur = cur->content;
4074 tmp = cur;
4075 while (tmp != NULL) {
4076 tmp->parent = parent;
4077 tmp = tmp->next;
4078 }
4079 continue;
4080 }
4081 }
4082 if (cur == def)
4083 break;
4084 if (cur->next != NULL) {
4085 cur = cur->next;
4086 continue;
4087 }
4088 do {
4089 cur = cur->parent;
4090 if (cur == NULL)
4091 break;
4092 if (cur == def)
4093 return (ret);
4094 if (cur->next != NULL) {
4095 cur = cur->next;
4096 break;
4097 }
4098 } while (cur != NULL);
4099 }
4100 return (ret);
4101}
4102
4110static void
4111xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt,
4112 xmlRelaxNGDefinePtr def)
4113{
4114 xmlRelaxNGDefinePtr **list;
4115 xmlRelaxNGDefinePtr cur;
4116 int nbchild = 0, i, j, ret;
4117 int is_nullable = 0;
4118 int is_indeterminist = 0;
4119 xmlHashTablePtr triage = NULL;
4120 int is_triable = 1;
4121
4122 if ((def == NULL) || (def->type != XML_RELAXNG_CHOICE))
4123 return;
4124
4125 if (def->dflags & IS_PROCESSED)
4126 return;
4127
4128 /*
4129 * Don't run that check in case of error. Infinite recursion
4130 * becomes possible.
4131 */
4132 if (ctxt->nbErrors != 0)
4133 return;
4134
4135 is_nullable = xmlRelaxNGIsNullable(def);
4136
4137 cur = def->content;
4138 while (cur != NULL) {
4139 nbchild++;
4140 cur = cur->next;
4141 }
4142
4143 list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
4144 sizeof(xmlRelaxNGDefinePtr
4145 *));
4146 if (list == NULL) {
4147 xmlRngPErrMemory(ctxt, "building choice\n");
4148 return;
4149 }
4150 i = 0;
4151 /*
4152 * a bit strong but safe
4153 */
4154 if (is_nullable == 0) {
4155 triage = xmlHashCreate(10);
4156 } else {
4157 is_triable = 0;
4158 }
4159 cur = def->content;
4160 while (cur != NULL) {
4161 list[i] = xmlRelaxNGGetElements(ctxt, cur, 0);
4162 if ((list[i] == NULL) || (list[i][0] == NULL)) {
4163 is_triable = 0;
4164 } else if (is_triable == 1) {
4165 xmlRelaxNGDefinePtr *tmp;
4166 int res;
4167
4168 tmp = list[i];
4169 while ((*tmp != NULL) && (is_triable == 1)) {
4170 if ((*tmp)->type == XML_RELAXNG_TEXT) {
4171 res = xmlHashAddEntry2(triage,
4172 BAD_CAST "#text", NULL,
4173 (void *) cur);
4174 if (res != 0)
4175 is_triable = -1;
4176 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
4177 ((*tmp)->name != NULL)) {
4178 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
4179 res = xmlHashAddEntry2(triage,
4180 (*tmp)->name, NULL,
4181 (void *) cur);
4182 else
4183 res = xmlHashAddEntry2(triage,
4184 (*tmp)->name, (*tmp)->ns,
4185 (void *) cur);
4186 if (res != 0)
4187 is_triable = -1;
4188 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
4189 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
4190 res = xmlHashAddEntry2(triage,
4191 BAD_CAST "#any", NULL,
4192 (void *) cur);
4193 else
4194 res = xmlHashAddEntry2(triage,
4195 BAD_CAST "#any", (*tmp)->ns,
4196 (void *) cur);
4197 if (res != 0)
4198 is_triable = -1;
4199 } else {
4200 is_triable = -1;
4201 }
4202 tmp++;
4203 }
4204 }
4205 i++;
4206 cur = cur->next;
4207 }
4208
4209 for (i = 0; i < nbchild; i++) {
4210 if (list[i] == NULL)
4211 continue;
4212 for (j = 0; j < i; j++) {
4213 if (list[j] == NULL)
4214 continue;
4215 ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
4216 if (ret == 0) {
4217 is_indeterminist = 1;
4218 }
4219 }
4220 }
4221 for (i = 0; i < nbchild; i++) {
4222 if (list[i] != NULL)
4223 xmlFree(list[i]);
4224 }
4225
4226 xmlFree(list);
4227 if (is_indeterminist) {
4228 def->dflags |= IS_INDETERMINIST;
4229 }
4230 if (is_triable == 1) {
4231 def->dflags |= IS_TRIABLE;
4232 def->data = triage;
4233 } else if (triage != NULL) {
4234 xmlHashFree(triage, NULL);
4235 }
4236 def->dflags |= IS_PROCESSED;
4237}
4238
4246static void
4247xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,
4248 xmlRelaxNGDefinePtr def)
4249{
4250 xmlRelaxNGDefinePtr **list;
4251 xmlRelaxNGDefinePtr cur;
4252 int nbchild = 0, i, j, ret;
4253
4254 if ((def == NULL) ||
4255 ((def->type != XML_RELAXNG_GROUP) &&
4256 (def->type != XML_RELAXNG_ELEMENT)))
4257 return;
4258
4259 if (def->dflags & IS_PROCESSED)
4260 return;
4261
4262 /*
4263 * Don't run that check in case of error. Infinite recursion
4264 * becomes possible.
4265 */
4266 if (ctxt->nbErrors != 0)
4267 return;
4268
4269 cur = def->attrs;
4270 while (cur != NULL) {
4271 nbchild++;
4272 cur = cur->next;
4273 }
4274 cur = def->content;
4275 while (cur != NULL) {
4276 nbchild++;
4277 cur = cur->next;
4278 }
4279
4280 list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
4281 sizeof(xmlRelaxNGDefinePtr
4282 *));
4283 if (list == NULL) {
4284 xmlRngPErrMemory(ctxt, "building group\n");
4285 return;
4286 }
4287 i = 0;
4288 cur = def->attrs;
4289 while (cur != NULL) {
4290 list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
4291 i++;
4292 cur = cur->next;
4293 }
4294 cur = def->content;
4295 while (cur != NULL) {
4296 list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
4297 i++;
4298 cur = cur->next;
4299 }
4300
4301 for (i = 0; i < nbchild; i++) {
4302 if (list[i] == NULL)
4303 continue;
4304 for (j = 0; j < i; j++) {
4305 if (list[j] == NULL)
4306 continue;
4307 ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
4308 if (ret == 0) {
4309 xmlRngPErr(ctxt, def->node, XML_RNGP_GROUP_ATTR_CONFLICT,
4310 "Attributes conflicts in group\n", NULL, NULL);
4311 }
4312 }
4313 }
4314 for (i = 0; i < nbchild; i++) {
4315 if (list[i] != NULL)
4316 xmlFree(list[i]);
4317 }
4318
4319 xmlFree(list);
4320 def->dflags |= IS_PROCESSED;
4321}
4322
4338static void
4339xmlRelaxNGComputeInterleaves(void *payload, void *data,
4341{
4342 xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
4343 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
4344 xmlRelaxNGDefinePtr cur, *tmp;
4345
4346 xmlRelaxNGPartitionPtr partitions = NULL;
4347 xmlRelaxNGInterleaveGroupPtr *groups = NULL;
4348 xmlRelaxNGInterleaveGroupPtr group;
4349 int i, j, ret, res;
4350 int nbgroups = 0;
4351 int nbchild = 0;
4352 int is_mixed = 0;
4353 int is_determinist = 1;
4354
4355 /*
4356 * Don't run that check in case of error. Infinite recursion
4357 * becomes possible.
4358 */
4359 if (ctxt->nbErrors != 0)
4360 return;
4361
4362#ifdef DEBUG_INTERLEAVE
4364 "xmlRelaxNGComputeInterleaves(%s)\n", name);
4365#endif
4366 cur = def->content;
4367 while (cur != NULL) {
4368 nbchild++;
4369 cur = cur->next;
4370 }
4371
4372#ifdef DEBUG_INTERLEAVE
4373 xmlGenericError(xmlGenericErrorContext, " %d child\n", nbchild);
4374#endif
4375 groups = (xmlRelaxNGInterleaveGroupPtr *)
4376 xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr));
4377 if (groups == NULL)
4378 goto error;
4379 cur = def->content;
4380 while (cur != NULL) {
4381 groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr)
4382 xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup));
4383 if (groups[nbgroups] == NULL)
4384 goto error;
4385 if (cur->type == XML_RELAXNG_TEXT)
4386 is_mixed++;
4387 groups[nbgroups]->rule = cur;
4388 groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 2);
4389 groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
4390 nbgroups++;
4391 cur = cur->next;
4392 }
4393#ifdef DEBUG_INTERLEAVE
4394 xmlGenericError(xmlGenericErrorContext, " %d groups\n", nbgroups);
4395#endif
4396
4397 /*
4398 * Let's check that all rules makes a partitions according to 7.4
4399 */
4400 partitions = (xmlRelaxNGPartitionPtr)
4401 xmlMalloc(sizeof(xmlRelaxNGPartition));
4402 if (partitions == NULL)
4403 goto error;
4404 memset(partitions, 0, sizeof(xmlRelaxNGPartition));
4405 partitions->nbgroups = nbgroups;
4406 partitions->triage = xmlHashCreate(nbgroups);
4407 for (i = 0; i < nbgroups; i++) {
4408 group = groups[i];
4409 for (j = i + 1; j < nbgroups; j++) {
4410 if (groups[j] == NULL)
4411 continue;
4412
4413 ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs,
4414 groups[j]->defs);
4415 if (ret == 0) {
4416 xmlRngPErr(ctxt, def->node, XML_RNGP_ELEM_TEXT_CONFLICT,
4417 "Element or text conflicts in interleave\n",
4418 NULL, NULL);
4419 }
4420 ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs,
4421 groups[j]->attrs);
4422 if (ret == 0) {
4423 xmlRngPErr(ctxt, def->node, XML_RNGP_ATTR_CONFLICT,
4424 "Attributes conflicts in interleave\n", NULL,
4425 NULL);
4426 }
4427 }
4428 tmp = group->defs;
4429 if ((tmp != NULL) && (*tmp != NULL)) {
4430 while (*tmp != NULL) {
4431 if ((*tmp)->type == XML_RELAXNG_TEXT) {
4432 res = xmlHashAddEntry2(partitions->triage,
4433 BAD_CAST "#text", NULL,
4434 (void *) (ptrdiff_t) (i + 1));
4435 if (res != 0)
4436 is_determinist = -1;
4437 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
4438 ((*tmp)->name != NULL)) {
4439 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
4440 res = xmlHashAddEntry2(partitions->triage,
4441 (*tmp)->name, NULL,
4442 (void *) (ptrdiff_t) (i + 1));
4443 else
4444 res = xmlHashAddEntry2(partitions->triage,
4445 (*tmp)->name, (*tmp)->ns,
4446 (void *) (ptrdiff_t) (i + 1));
4447 if (res != 0)
4448 is_determinist = -1;
4449 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
4450 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
4451 res = xmlHashAddEntry2(partitions->triage,
4452 BAD_CAST "#any", NULL,
4453 (void *) (ptrdiff_t) (i + 1));
4454 else
4455 res = xmlHashAddEntry2(partitions->triage,
4456 BAD_CAST "#any", (*tmp)->ns,
4457 (void *) (ptrdiff_t) (i + 1));
4458 if ((*tmp)->nameClass != NULL)
4459 is_determinist = 2;
4460 if (res != 0)
4461 is_determinist = -1;
4462 } else {
4463 is_determinist = -1;
4464 }
4465 tmp++;
4466 }
4467 } else {
4468 is_determinist = 0;
4469 }
4470 }
4471 partitions->groups = groups;
4472
4473 /*
4474 * and save the partition list back in the def
4475 */
4476 def->data = partitions;
4477 if (is_mixed != 0)
4478 def->dflags |= IS_MIXED;
4479 if (is_determinist == 1)
4480 partitions->flags = IS_DETERMINIST;
4481 if (is_determinist == 2)
4482 partitions->flags = IS_DETERMINIST | IS_NEEDCHECK;
4483 return;
4484
4485 error:
4486 xmlRngPErrMemory(ctxt, "in interleave computation\n");
4487 if (groups != NULL) {
4488 for (i = 0; i < nbgroups; i++)
4489 if (groups[i] != NULL) {
4490 if (groups[i]->defs != NULL)
4491 xmlFree(groups[i]->defs);
4492 xmlFree(groups[i]);
4493 }
4494 xmlFree(groups);
4495 }
4496 xmlRelaxNGFreePartition(partitions);
4497}
4498
4508static xmlRelaxNGDefinePtr
4509xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4510{
4511 xmlRelaxNGDefinePtr def = NULL;
4512 xmlRelaxNGDefinePtr last = NULL, cur;
4514
4515 def = xmlRelaxNGNewDefine(ctxt, node);
4516 if (def == NULL) {
4517 return (NULL);
4518 }
4519 def->type = XML_RELAXNG_INTERLEAVE;
4520
4521 if (ctxt->interleaves == NULL)
4522 ctxt->interleaves = xmlHashCreate(10);
4523 if (ctxt->interleaves == NULL) {
4524 xmlRngPErrMemory(ctxt, "create interleaves\n");
4525 } else {
4526 char name[32];
4527
4528 snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++);
4529 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) {
4530 xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_ADD,
4531 "Failed to add %s to hash table\n",
4532 (const xmlChar *) name, NULL);
4533 }
4534 }
4535 child = node->children;
4536 if (child == NULL) {
4537 xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_NO_CONTENT,
4538 "Element interleave is empty\n", NULL, NULL);
4539 }
4540 while (child != NULL) {
4541 if (IS_RELAXNG(child, "element")) {
4542 cur = xmlRelaxNGParseElement(ctxt, child);
4543 } else {
4544 cur = xmlRelaxNGParsePattern(ctxt, child);
4545 }
4546 if (cur != NULL) {
4547 cur->parent = def;
4548 if (last == NULL) {
4549 def->content = last = cur;
4550 } else {
4551 last->next = cur;
4552 last = cur;
4553 }
4554 }
4555 child = child->next;
4556 }
4557
4558 return (def);
4559}
4560
4570static int
4571xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4572{
4573 xmlRelaxNGIncludePtr incl;
4575 int ret = 0, tmp;
4576
4577 incl = node->psvi;
4578 if (incl == NULL) {
4579 xmlRngPErr(ctxt, node, XML_RNGP_INCLUDE_EMPTY,
4580 "Include node has no data\n", NULL, NULL);
4581 return (-1);
4582 }
4583 root = xmlDocGetRootElement(incl->doc);
4584 if (root == NULL) {
4585 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, "Include document is empty\n",
4586 NULL, NULL);
4587 return (-1);
4588 }
4589 if (!xmlStrEqual(root->name, BAD_CAST "grammar")) {
4590 xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
4591 "Include document root is not a grammar\n", NULL, NULL);
4592 return (-1);
4593 }
4594
4595 /*
4596 * Merge the definition from both the include and the internal list
4597 */
4598 if (root->children != NULL) {
4599 tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children);
4600 if (tmp != 0)
4601 ret = -1;
4602 }
4603 if (node->children != NULL) {
4604 tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children);
4605 if (tmp != 0)
4606 ret = -1;
4607 }
4608 return (ret);
4609}
4610
4620static int
4621xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4622{
4623 xmlChar *name;
4624 int ret = 0, tmp;
4625 xmlRelaxNGDefinePtr def;
4626 const xmlChar *olddefine;
4627
4628 name = xmlGetProp(node, BAD_CAST "name");
4629 if (name == NULL) {
4630 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_NAME_MISSING,
4631 "define has no name\n", NULL, NULL);
4632 } else {
4633 xmlRelaxNGNormExtSpace(name);
4634 if (xmlValidateNCName(name, 0)) {
4635 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_DEFINE_NAME,
4636 "define name '%s' is not an NCName\n", name, NULL);
4637 }
4638 def = xmlRelaxNGNewDefine(ctxt, node);
4639 if (def == NULL) {
4640 xmlFree(name);
4641 return (-1);
4642 }
4643 def->type = XML_RELAXNG_DEF;
4644 def->name = name;
4645 if (node->children == NULL) {
4646 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_EMPTY,
4647 "define has no children\n", NULL, NULL);
4648 } else {
4649 olddefine = ctxt->define;
4650 ctxt->define = name;
4651 def->content =
4652 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
4653 ctxt->define = olddefine;
4654 }
4655 if (ctxt->grammar->defs == NULL)
4656 ctxt->grammar->defs = xmlHashCreate(10);
4657 if (ctxt->grammar->defs == NULL) {
4658 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
4659 "Could not create definition hash\n", NULL, NULL);
4660 ret = -1;
4661 } else {
4662 tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
4663 if (tmp < 0) {
4664 xmlRelaxNGDefinePtr prev;
4665
4666 prev = xmlHashLookup(ctxt->grammar->defs, name);
4667 if (prev == NULL) {
4668 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
4669 "Internal error on define aggregation of %s\n",
4670 name, NULL);
4671 ret = -1;
4672 } else {
4673 while (prev->nextHash != NULL)
4674 prev = prev->nextHash;
4675 prev->nextHash = def;
4676 }
4677 }
4678 }
4679 }
4680 return (ret);
4681}
4682
4691static void
4692xmlRelaxNGParseImportRef(void *payload, void *data, const xmlChar *name) {
4693 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
4694 xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
4695 int tmp;
4696
4697 def->dflags |= IS_EXTERNAL_REF;
4698
4699 tmp = xmlHashAddEntry(ctxt->grammar->refs, name, def);
4700 if (tmp < 0) {
4701 xmlRelaxNGDefinePtr prev;
4702
4703 prev = (xmlRelaxNGDefinePtr)
4704 xmlHashLookup(ctxt->grammar->refs, def->name);
4705 if (prev == NULL) {
4706 if (def->name != NULL) {
4707 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
4708 "Error refs definitions '%s'\n",
4709 def->name, NULL);
4710 } else {
4711 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
4712 "Error refs definitions\n",
4713 NULL, NULL);
4714 }
4715 } else {
4716 def->nextHash = prev->nextHash;
4717 prev->nextHash = def;
4718 }
4719 }
4720}
4721
4731static int
4732xmlRelaxNGParseImportRefs(xmlRelaxNGParserCtxtPtr ctxt,
4733 xmlRelaxNGGrammarPtr grammar) {
4734 if ((ctxt == NULL) || (grammar == NULL) || (ctxt->grammar == NULL))
4735 return(-1);
4736 if (grammar->refs == NULL)
4737 return(0);
4738 if (ctxt->grammar->refs == NULL)
4739 ctxt->grammar->refs = xmlHashCreate(10);
4740 if (ctxt->grammar->refs == NULL) {
4741 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
4742 "Could not create references hash\n", NULL, NULL);
4743 return(-1);
4744 }
4745 xmlHashScan(grammar->refs, xmlRelaxNGParseImportRef, ctxt);
4746 return(0);
4747}
4748
4758static xmlRelaxNGDefinePtr
4759xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4760{
4761 xmlRelaxNGDocumentPtr docu;
4762 xmlNodePtr root, tmp;
4763 xmlChar *ns;
4764 int newNs = 0, oldflags;
4765 xmlRelaxNGDefinePtr def;
4766
4767 docu = node->psvi;
4768 if (docu != NULL) {
4769 def = xmlRelaxNGNewDefine(ctxt, node);
4770 if (def == NULL)
4771 return (NULL);
4772 def->type = XML_RELAXNG_EXTERNALREF;
4773
4774 if (docu->content == NULL) {
4775 /*
4776 * Then do the parsing for good
4777 */
4778 root = xmlDocGetRootElement(docu->doc);
4779 if (root == NULL) {
4780 xmlRngPErr(ctxt, node, XML_RNGP_EXTERNALREF_EMTPY,
4781 "xmlRelaxNGParse: %s is empty\n", ctxt->URL,
4782 NULL);
4783 return (NULL);
4784 }
4785 /*
4786 * ns transmission rules
4787 */
4788 ns = xmlGetProp(root, BAD_CAST "ns");
4789 if (ns == NULL) {
4790 tmp = node;
4791 while ((tmp != NULL) && (tmp->type == XML_ELEMENT_NODE)) {
4792 ns = xmlGetProp(tmp, BAD_CAST "ns");
4793 if (ns != NULL) {
4794 break;
4795 }
4796 tmp = tmp->parent;
4797 }
4798 if (ns != NULL) {
4799 xmlSetProp(root, BAD_CAST "ns", ns);
4800 newNs = 1;
4801 xmlFree(ns);
4802 }
4803 } else {
4804 xmlFree(ns);
4805 }
4806
4807 /*
4808 * Parsing to get a precompiled schemas.
4809 */
4810 oldflags = ctxt->flags;
4811 ctxt->flags |= XML_RELAXNG_IN_EXTERNALREF;
4812 docu->schema = xmlRelaxNGParseDocument(ctxt, root);
4813 ctxt->flags = oldflags;
4814 if ((docu->schema != NULL) &&
4815 (docu->schema->topgrammar != NULL)) {
4816 docu->content = docu->schema->topgrammar->start;
4817 if (docu->schema->topgrammar->refs)
4818 xmlRelaxNGParseImportRefs(ctxt, docu->schema->topgrammar);
4819 }
4820
4821 /*
4822 * the externalRef may be reused in a different ns context
4823 */
4824 if (newNs == 1) {
4825 xmlUnsetProp(root, BAD_CAST "ns");
4826 }
4827 }
4828 def->content = docu->content;
4829 } else {
4830 def = NULL;
4831 }
4832 return (def);
4833}
4834
4845static xmlRelaxNGDefinePtr
4846xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4847{
4848 xmlRelaxNGDefinePtr def = NULL;
4849
4850 if (node == NULL) {
4851 return (NULL);
4852 }
4853 if (IS_RELAXNG(node, "element")) {
4854 def = xmlRelaxNGParseElement(ctxt, node);
4855 } else if (IS_RELAXNG(node, "attribute")) {
4856 def = xmlRelaxNGParseAttribute(ctxt, node);
4857 } else if (IS_RELAXNG(node, "empty")) {
4858 def = xmlRelaxNGNewDefine(ctxt, node);
4859 if (def == NULL)
4860 return (NULL);
4861 def->type = XML_RELAXNG_EMPTY;
4862 if (node->children != NULL) {
4863 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_NOT_EMPTY,
4864 "empty: had a child node\n", NULL, NULL);
4865 }
4866 } else if (IS_RELAXNG(node, "text")) {
4867 def = xmlRelaxNGNewDefine(ctxt, node);
4868 if (def == NULL)
4869 return (NULL);
4870 def->type = XML_RELAXNG_TEXT;
4871 if (node->children != NULL) {
4872 xmlRngPErr(ctxt, node, XML_RNGP_TEXT_HAS_CHILD,
4873 "text: had a child node\n", NULL, NULL);
4874 }
4875 } else if (IS_RELAXNG(node, "zeroOrMore")) {
4876 def = xmlRelaxNGNewDefine(ctxt, node);
4877 if (def == NULL)
4878 return (NULL);
4879 def->type = XML_RELAXNG_ZEROORMORE;
4880 if (node->children == NULL) {
4881 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4882 "Element %s is empty\n", node->name, NULL);
4883 } else {
4884 def->content =
4885 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
4886 }
4887 } else if (IS_RELAXNG(node, "oneOrMore")) {
4888 def = xmlRelaxNGNewDefine(ctxt, node);
4889 if (def == NULL)
4890 return (NULL);
4891 def->type = XML_RELAXNG_ONEORMORE;
4892 if (node->children == NULL) {
4893 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4894 "Element %s is empty\n", node->name, NULL);
4895 } else {
4896 def->content =
4897 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
4898 }
4899 } else if (IS_RELAXNG(node, "optional")) {
4900 def = xmlRelaxNGNewDefine(ctxt, node);
4901 if (def == NULL)
4902 return (NULL);
4903 def->type = XML_RELAXNG_OPTIONAL;
4904 if (node->children == NULL) {
4905 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4906 "Element %s is empty\n", node->name, NULL);
4907 } else {
4908 def->content =
4909 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
4910 }
4911 } else if (IS_RELAXNG(node, "choice")) {
4912 def = xmlRelaxNGNewDefine(ctxt, node);
4913 if (def == NULL)
4914 return (NULL);
4915 def->type = XML_RELAXNG_CHOICE;
4916 if (node->children == NULL) {
4917 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4918 "Element %s is empty\n", node->name, NULL);
4919 } else {
4920 def->content =
4921 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
4922 }
4923 } else if (IS_RELAXNG(node, "group")) {
4924 def = xmlRelaxNGNewDefine(ctxt, node);
4925 if (def == NULL)
4926 return (NULL);
4927 def->type = XML_RELAXNG_GROUP;
4928 if (node->children == NULL) {
4929 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4930 "Element %s is empty\n", node->name, NULL);
4931 } else {
4932 def->content =
4933 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
4934 }
4935 } else if (IS_RELAXNG(node, "ref")) {
4936 def = xmlRelaxNGNewDefine(ctxt, node);
4937 if (def == NULL)
4938 return (NULL);
4939 def->type = XML_RELAXNG_REF;
4940 def->name = xmlGetProp(node, BAD_CAST "name");
4941 if (def->name == NULL) {
4942 xmlRngPErr(ctxt, node, XML_RNGP_REF_NO_NAME, "ref has no name\n",
4943 NULL, NULL);
4944 } else {
4945 xmlRelaxNGNormExtSpace(def->name);
4946 if (xmlValidateNCName(def->name, 0)) {
4947 xmlRngPErr(ctxt, node, XML_RNGP_REF_NAME_INVALID,
4948 "ref name '%s' is not an NCName\n", def->name,
4949 NULL);
4950 }
4951 }
4952 if (node->children != NULL) {
4953 xmlRngPErr(ctxt, node, XML_RNGP_REF_NOT_EMPTY, "ref is not empty\n",
4954 NULL, NULL);
4955 }
4956 if (ctxt->grammar->refs == NULL)
4957 ctxt->grammar->refs = xmlHashCreate(10);
4958 if (ctxt->grammar->refs == NULL) {
4959 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
4960 "Could not create references hash\n", NULL, NULL);
4961 def = NULL;
4962 } else {
4963 int tmp;
4964
4965 tmp = xmlHashAddEntry(ctxt->grammar->refs, def->name, def);
4966 if (tmp < 0) {
4967 xmlRelaxNGDefinePtr prev;
4968
4969 prev = (xmlRelaxNGDefinePtr)
4970 xmlHashLookup(ctxt->grammar->refs, def->name);
4971 if (prev == NULL) {
4972 if (def->name != NULL) {
4973 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
4974 "Error refs definitions '%s'\n",
4975 def->name, NULL);
4976 } else {
4977 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
4978 "Error refs definitions\n",
4979 NULL, NULL);
4980 }
4981 def = NULL;
4982 } else {
4983 def->nextHash = prev->nextHash;
4984 prev->nextHash = def;
4985 }
4986 }
4987 }
4988 } else if (IS_RELAXNG(node, "data")) {
4989 def = xmlRelaxNGParseData(ctxt, node);
4990 } else if (IS_RELAXNG(node, "value")) {
4991 def = xmlRelaxNGParseValue(ctxt, node);
4992 } else if (IS_RELAXNG(node, "list")) {
4993 def = xmlRelaxNGNewDefine(ctxt, node);
4994 if (def == NULL)
4995 return (NULL);
4996 def->type = XML_RELAXNG_LIST;
4997 if (node->children == NULL) {
4998 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4999 "Element %s is empty\n", node->name, NULL);
5000 } else {
5001 def->content =
5002 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
5003 }
5004 } else if (IS_RELAXNG(node, "interleave")) {
5005 def = xmlRelaxNGParseInterleave(ctxt, node);
5006 } else if (IS_RELAXNG(node, "externalRef")) {
5007 def = xmlRelaxNGProcessExternalRef(ctxt, node);
5008 } else if (IS_RELAXNG(node, "notAllowed")) {
5009 def = xmlRelaxNGNewDefine(ctxt, node);
5010 if (def == NULL)
5011 return (NULL);
5012 def->type = XML_RELAXNG_NOT_ALLOWED;
5013 if (node->children != NULL) {
5014 xmlRngPErr(ctxt, node, XML_RNGP_NOTALLOWED_NOT_EMPTY,
5015 "xmlRelaxNGParse: notAllowed element is not empty\n",
5016 NULL, NULL);
5017 }
5018 } else if (IS_RELAXNG(node, "grammar")) {
5019 xmlRelaxNGGrammarPtr grammar, old;
5020 xmlRelaxNGGrammarPtr oldparent;
5021
5022#ifdef DEBUG_GRAMMAR
5024 "Found <grammar> pattern\n");
5025#endif
5026
5027 oldparent = ctxt->parentgrammar;
5028 old = ctxt->grammar;
5029 ctxt->parentgrammar = old;
5030 grammar = xmlRelaxNGParseGrammar(ctxt, node->children);
5031 if (old != NULL) {
5032 ctxt->grammar = old;
5033 ctxt->parentgrammar = oldparent;
5034#if 0
5035 if (grammar != NULL) {
5036 grammar->next = old->next;
5037 old->next = grammar;
5038 }
5039#endif
5040 }
5041 if (grammar != NULL)
5042 def = grammar->start;
5043 else
5044 def = NULL;
5045 } else if (IS_RELAXNG(node, "parentRef")) {
5046 if (ctxt->parentgrammar == NULL) {
5047 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_PARENT,
5048 "Use of parentRef without a parent grammar\n", NULL,
5049 NULL);
5050 return (NULL);
5051 }
5052 def = xmlRelaxNGNewDefine(ctxt, node);
5053 if (def == NULL)
5054 return (NULL);
5055 def->type = XML_RELAXNG_PARENTREF;
5056 def->name = xmlGetProp(node, BAD_CAST "name");
5057 if (def->name == NULL) {
5058 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_NAME,
5059 "parentRef has no name\n", NULL, NULL);
5060 } else {
5061 xmlRelaxNGNormExtSpace(def->name);
5062 if (xmlValidateNCName(def->name, 0)) {
5063 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NAME_INVALID,
5064 "parentRef name '%s' is not an NCName\n",
5065 def->name, NULL);
5066 }
5067 }
5068 if (node->children != NULL) {
5069 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NOT_EMPTY,
5070 "parentRef is not empty\n", NULL, NULL);
5071 }
5072 if (ctxt->parentgrammar->refs == NULL)
5073 ctxt->parentgrammar->refs = xmlHashCreate(10);
5074 if (ctxt->parentgrammar->refs == NULL) {
5075 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
5076 "Could not create references hash\n", NULL, NULL);
5077 def = NULL;
5078 } else if (def->name != NULL) {
5079 int tmp;
5080
5081 tmp =
5082 xmlHashAddEntry(ctxt->parentgrammar->refs, def->name, def);
5083 if (tmp < 0) {
5084 xmlRelaxNGDefinePtr prev;
5085
5086 prev = (xmlRelaxNGDefinePtr)
5087 xmlHashLookup(ctxt->parentgrammar->refs, def->name);
5088 if (prev == NULL) {
5089 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
5090 "Internal error parentRef definitions '%s'\n",
5091 def->name, NULL);
5092 def = NULL;
5093 } else {
5094 def->nextHash = prev->nextHash;
5095 prev->nextHash = def;
5096 }
5097 }
5098 }
5099 } else if (IS_RELAXNG(node, "mixed")) {
5100 if (node->children == NULL) {
5101 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, "Mixed is empty\n",
5102 NULL, NULL);
5103 def = NULL;
5104 } else {
5105 def = xmlRelaxNGParseInterleave(ctxt, node);
5106 if (def != NULL) {
5107 xmlRelaxNGDefinePtr tmp;
5108
5109 if ((def->content != NULL) && (def->content->next != NULL)) {
5110 tmp = xmlRelaxNGNewDefine(ctxt, node);
5111 if (tmp != NULL) {
5112 tmp->type = XML_RELAXNG_GROUP;
5113 tmp->content = def->content;
5114 def->content = tmp;
5115 }
5116 }
5117
5118 tmp = xmlRelaxNGNewDefine(ctxt, node);
5119 if (tmp == NULL)
5120 return (def);
5121 tmp->type = XML_RELAXNG_TEXT;
5122 tmp->next = def->content;
5123 def->content = tmp;
5124 }
5125 }
5126 } else {
5127 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_CONSTRUCT,
5128 "Unexpected node %s is not a pattern\n", node->name,
5129 NULL);
5130 def = NULL;
5131 }
5132 return (def);
5133}
5134
5144static xmlRelaxNGDefinePtr
5145xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
5146{
5147 xmlRelaxNGDefinePtr ret, cur;
5149 int old_flags;
5150
5151 ret = xmlRelaxNGNewDefine(ctxt, node);
5152 if (ret == NULL)
5153 return (NULL);
5154 ret->type = XML_RELAXNG_ATTRIBUTE;
5155 ret->parent = ctxt->def;
5156 child = node->children;
5157 if (child == NULL) {
5158 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_EMPTY,
5159 "xmlRelaxNGParseattribute: attribute has no children\n",
5160 NULL, NULL);
5161 return (ret);
5162 }
5163 old_flags = ctxt->flags;
5164 ctxt->flags |= XML_RELAXNG_IN_ATTRIBUTE;
5165 cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
5166 if (cur != NULL)
5167 child = child->next;
5168
5169 if (child != NULL) {
5170 cur = xmlRelaxNGParsePattern(ctxt, child);
5171 if (cur != NULL) {
5172 switch (cur->type) {
5173 case XML_RELAXNG_EMPTY:
5174 case XML_RELAXNG_NOT_ALLOWED:
5175 case XML_RELAXNG_TEXT:
5176 case XML_RELAXNG_ELEMENT:
5177 case XML_RELAXNG_DATATYPE:
5178 case XML_RELAXNG_VALUE:
5179 case XML_RELAXNG_LIST:
5180 case XML_RELAXNG_REF:
5181 case XML_RELAXNG_PARENTREF:
5182 case XML_RELAXNG_EXTERNALREF:
5183 case XML_RELAXNG_DEF:
5184 case XML_RELAXNG_ONEORMORE:
5185 case XML_RELAXNG_ZEROORMORE:
5186 case XML_RELAXNG_OPTIONAL:
5187 case XML_RELAXNG_CHOICE:
5188 case XML_RELAXNG_GROUP:
5189 case XML_RELAXNG_INTERLEAVE:
5190 case XML_RELAXNG_ATTRIBUTE:
5191 ret->content = cur;
5192 cur->parent = ret;
5193 break;
5194 case XML_RELAXNG_START:
5195 case XML_RELAXNG_PARAM:
5196 case XML_RELAXNG_EXCEPT:
5197 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CONTENT,
5198 "attribute has invalid content\n", NULL,
5199 NULL);
5200 break;
5201 case XML_RELAXNG_NOOP:
5202 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_NOOP,
5203 "RNG Internal error, noop found in attribute\n",
5204 NULL, NULL);
5205 break;
5206 }
5207 }
5208 child = child->next;
5209 }
5210 if (child != NULL) {
5211 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CHILDREN,
5212 "attribute has multiple children\n", NULL, NULL);
5213 }
5214 ctxt->flags = old_flags;
5215 return (ret);
5216}
5217
5228static xmlRelaxNGDefinePtr
5229xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt,
5230 xmlNodePtr node, int attr)
5231{
5232 xmlRelaxNGDefinePtr ret, cur, last = NULL;
5234
5235 if (!IS_RELAXNG(node, "except")) {
5236 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MISSING,
5237 "Expecting an except node\n", NULL, NULL);
5238 return (NULL);
5239 }
5240 if (node->next != NULL) {
5241 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MULTIPLE,
5242 "exceptNameClass allows only a single except node\n",
5243 NULL, NULL);
5244 }
5245 if (node->children == NULL) {
5246 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_EMPTY, "except has no content\n",
5247 NULL, NULL);
5248 return (NULL);
5249 }
5250
5251 ret = xmlRelaxNGNewDefine(ctxt, node);
5252 if (ret == NULL)
5253 return (NULL);
5254 ret->type = XML_RELAXNG_EXCEPT;
5255 child = node->children;
5256 while (child != NULL) {
5257 cur = xmlRelaxNGNewDefine(ctxt, child);
5258 if (cur == NULL)
5259 break;
5260 if (attr)
5261 cur->type = XML_RELAXNG_ATTRIBUTE;
5262 else
5263 cur->type = XML_RELAXNG_ELEMENT;
5264
5265 if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) {
5266 if (last == NULL) {
5267 ret->content = cur;
5268 } else {
5269 last->next = cur;
5270 }
5271 last = cur;
5272 }
5273 child = child->next;
5274 }
5275
5276 return (ret);
5277}
5278
5289static xmlRelaxNGDefinePtr
5290xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
5291 xmlRelaxNGDefinePtr def)
5292{
5293 xmlRelaxNGDefinePtr ret, tmp;
5294 xmlChar *val;
5295
5296 ret = def;
5297 if ((IS_RELAXNG(node, "name")) || (IS_RELAXNG(node, "anyName")) ||
5298 (IS_RELAXNG(node, "nsName"))) {
5299 if ((def->type != XML_RELAXNG_ELEMENT) &&
5300 (def->type != XML_RELAXNG_ATTRIBUTE)) {
5301 ret = xmlRelaxNGNewDefine(ctxt, node);
5302 if (ret == NULL)
5303 return (NULL);
5304 ret->parent = def;
5305 if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE)
5306 ret->type = XML_RELAXNG_ATTRIBUTE;
5307 else
5308 ret->type = XML_RELAXNG_ELEMENT;
5309 }
5310 }
5311 if (IS_RELAXNG(node, "name")) {
5313 xmlRelaxNGNormExtSpace(val);
5314 if (xmlValidateNCName(val, 0)) {
5315 if (node->parent != NULL)
5316 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
5317 "Element %s name '%s' is not an NCName\n",
5318 node->parent->name, val);
5319 else
5320 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
5321 "name '%s' is not an NCName\n",
5322 val, NULL);
5323 }
5324 ret->name = val;
5325 val = xmlGetProp(node, BAD_CAST "ns");
5326 ret->ns = val;
5327 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
5328 (val != NULL) &&
5329 (xmlStrEqual(val, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
5330 xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
5331 "Attribute with namespace '%s' is not allowed\n",
5332 val, NULL);
5333 }
5334 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
5335 (val != NULL) &&
5336 (val[0] == 0) && (xmlStrEqual(ret->name, BAD_CAST "xmlns"))) {
5337 xmlRngPErr(ctxt, node, XML_RNGP_XMLNS_NAME,
5338 "Attribute with QName 'xmlns' is not allowed\n",
5339 val, NULL);
5340 }
5341 } else if (IS_RELAXNG(node, "anyName")) {
5342 ret->name = NULL;
5343 ret->ns = NULL;
5344 if (node->children != NULL) {
5345 ret->nameClass =
5346 xmlRelaxNGParseExceptNameClass(ctxt, node->children,
5347 (def->type ==
5348 XML_RELAXNG_ATTRIBUTE));
5349 }
5350 } else if (IS_RELAXNG(node, "nsName")) {
5351 ret->name = NULL;
5352 ret->ns = xmlGetProp(node, BAD_CAST "ns");
5353 if (ret->ns == NULL) {
5354 xmlRngPErr(ctxt, node, XML_RNGP_NSNAME_NO_NS,
5355 "nsName has no ns attribute\n", NULL, NULL);
5356 }
5357 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
5358 (ret->ns != NULL) &&
5360 (ret->ns, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
5361 xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
5362 "Attribute with namespace '%s' is not allowed\n",
5363 ret->ns, NULL);
5364 }
5365 if (node->children != NULL) {
5366 ret->nameClass =
5367 xmlRelaxNGParseExceptNameClass(ctxt, node->children,
5368 (def->type ==
5369 XML_RELAXNG_ATTRIBUTE));
5370 }
5371 } else if (IS_RELAXNG(node, "choice")) {
5373 xmlRelaxNGDefinePtr last = NULL;
5374
5375 if (def->type == XML_RELAXNG_CHOICE) {
5376 ret = def;
5377 } else {
5378 ret = xmlRelaxNGNewDefine(ctxt, node);
5379 if (ret == NULL)
5380 return (NULL);
5381 ret->parent = def;
5382 ret->type = XML_RELAXNG_CHOICE;
5383 }
5384
5385 if (node->children == NULL) {
5386 xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,
5387 "Element choice is empty\n", NULL, NULL);
5388 } else {
5389
5390 child = node->children;
5391 while (child != NULL) {
5392 tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);
5393 if (tmp != NULL) {
5394 if (last == NULL) {
5395 last = tmp;
5396 } else {
5397 last->next = tmp;
5398 last = tmp;
5399 }
5400 }
5401 child = child->next;
5402 }
5403 }
5404 } else {
5405 xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT,
5406 "expecting name, anyName, nsName or choice : got %s\n",
5407 (node == NULL ? (const xmlChar *) "nothing" : node->name),
5408 NULL);
5409 return (NULL);
5410 }
5411 if (ret != def) {
5412 if (def->nameClass == NULL) {
5413 def->nameClass = ret;
5414 } else {
5415 tmp = def->nameClass;
5416 while (tmp->next != NULL) {
5417 tmp = tmp->next;
5418 }
5419 tmp->next = ret;
5420 }
5421 }
5422 return (ret);
5423}
5424
5434static xmlRelaxNGDefinePtr
5435xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
5436{
5437 xmlRelaxNGDefinePtr ret, cur, last;
5439 const xmlChar *olddefine;
5440
5441 ret = xmlRelaxNGNewDefine(ctxt, node);
5442 if (ret == NULL)
5443 return (NULL);
5444 ret->type = XML_RELAXNG_ELEMENT;
5445 ret->parent = ctxt->def;
5446 child = node->children;
5447 if (child == NULL) {
5448 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_EMPTY,
5449 "xmlRelaxNGParseElement: element has no children\n",
5450 NULL, NULL);
5451 return (ret);
5452 }
5453 cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
5454 if (cur != NULL)
5455 child = child->next;
5456
5457 if (child == NULL) {
5458 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NO_CONTENT,
5459 "xmlRelaxNGParseElement: element has no content\n",
5460 NULL, NULL);
5461 return (ret);
5462 }
5463 olddefine = ctxt->define;
5464 ctxt->define = NULL;
5465 last = NULL;
5466 while (child != NULL) {
5467 cur = xmlRelaxNGParsePattern(ctxt, child);
5468 if (cur != NULL) {
5469 cur->parent = ret;
5470 switch (cur->type) {
5471 case XML_RELAXNG_EMPTY:
5472 case XML_RELAXNG_NOT_ALLOWED:
5473 case XML_RELAXNG_TEXT:
5474 case XML_RELAXNG_ELEMENT:
5475 case XML_RELAXNG_DATATYPE:
5476 case XML_RELAXNG_VALUE:
5477 case XML_RELAXNG_LIST:
5478 case XML_RELAXNG_REF:
5479 case XML_RELAXNG_PARENTREF:
5480 case XML_RELAXNG_EXTERNALREF:
5481 case XML_RELAXNG_DEF:
5482 case XML_RELAXNG_ZEROORMORE:
5483 case XML_RELAXNG_ONEORMORE:
5484 case XML_RELAXNG_OPTIONAL:
5485 case XML_RELAXNG_CHOICE:
5486 case XML_RELAXNG_GROUP:
5487 case XML_RELAXNG_INTERLEAVE:
5488 if (last == NULL) {
5489 ret->content = last = cur;
5490 } else {
5491 if ((last->type == XML_RELAXNG_ELEMENT) &&
5492 (ret->content == last)) {
5493 ret->content = xmlRelaxNGNewDefine(ctxt, node);
5494 if (ret->content != NULL) {
5495 ret->content->type = XML_RELAXNG_GROUP;
5496 ret->content->content = last;
5497 } else {
5498 ret->content = last;
5499 }
5500 }
5501 last->next = cur;
5502 last = cur;
5503 }
5504 break;
5505 case XML_RELAXNG_ATTRIBUTE:
5506 cur->next = ret->attrs;
5507 ret->attrs = cur;
5508 break;
5509 case XML_RELAXNG_START:
5510 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
5511 "RNG Internal error, start found in element\n",
5512 NULL, NULL);
5513 break;
5514 case XML_RELAXNG_PARAM:
5515 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
5516 "RNG Internal error, param found in element\n",
5517 NULL, NULL);
5518 break;
5519 case XML_RELAXNG_EXCEPT:
5520 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
5521 "RNG Internal error, except found in element\n",
5522 NULL, NULL);
5523 break;
5524 case XML_RELAXNG_NOOP:
5525 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
5526 "RNG Internal error, noop found in element\n",
5527 NULL, NULL);
5528 break;
5529 }
5530 }
5531 child = child->next;
5532 }
5533 ctxt->define = olddefine;
5534 return (ret);
5535}
5536
5547static xmlRelaxNGDefinePtr
5548xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes,
5549 int group)
5550{
5551 xmlRelaxNGDefinePtr def = NULL, last = NULL, cur, parent;
5552
5553 parent = ctxt->def;
5554 while (nodes != NULL) {
5555 if (IS_RELAXNG(nodes, "element")) {
5556 cur = xmlRelaxNGParseElement(ctxt, nodes);
5557 if (cur == NULL)
5558 return (NULL);
5559 if (def == NULL) {
5560 def = last = cur;
5561 } else {
5562 if ((group == 1) && (def->type == XML_RELAXNG_ELEMENT) &&
5563 (def == last)) {
5564 def = xmlRelaxNGNewDefine(ctxt, nodes);
5565 if (def == NULL)
5566 return (NULL);
5567 def->type = XML_RELAXNG_GROUP;
5568 def->content = last;
5569 }
5570 last->next = cur;
5571 last = cur;
5572 }
5573 cur->parent = parent;
5574 } else {
5575 cur = xmlRelaxNGParsePattern(ctxt, nodes);
5576 if (cur != NULL) {
5577 if (def == NULL) {
5578 def = last = cur;
5579 } else {
5580 last->next = cur;
5581 last = cur;
5582 }
5583 }
5584 }
5585 nodes = nodes->next;
5586 }
5587 return (def);
5588}
5589
5599static int
5600xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
5601{
5602 int ret = 0;
5603 xmlRelaxNGDefinePtr def = NULL, last;
5604
5605 if (nodes == NULL) {
5606 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY, "start has no children\n",
5607 NULL, NULL);
5608 return (-1);
5609 }
5610 if (IS_RELAXNG(nodes, "empty")) {
5611 def = xmlRelaxNGNewDefine(ctxt, nodes);
5612 if (def == NULL)
5613 return (-1);
5614 def->type = XML_RELAXNG_EMPTY;
5615 if (nodes->children != NULL) {
5616 xmlRngPErr(ctxt, nodes, XML_RNGP_EMPTY_CONTENT,
5617 "element empty is not empty\n", NULL, NULL);
5618 }
5619 } else if (IS_RELAXNG(nodes, "notAllowed")) {
5620 def = xmlRelaxNGNewDefine(ctxt, nodes);
5621 if (def == NULL)
5622 return (-1);
5623 def->type = XML_RELAXNG_NOT_ALLOWED;
5624 if (nodes->children != NULL) {
5625 xmlRngPErr(ctxt, nodes, XML_RNGP_NOTALLOWED_NOT_EMPTY,
5626 "element notAllowed is not empty\n", NULL, NULL);
5627 }
5628 } else {
5629 def = xmlRelaxNGParsePatterns(ctxt, nodes, 1);
5630 }
5631 if (ctxt->grammar->start != NULL) {
5632 last = ctxt->grammar->start;
5633 while (last->next != NULL)
5634 last = last->next;
5635 last->next = def;
5636 } else {
5637 ctxt->grammar->start = def;
5638 }
5639 nodes = nodes->next;
5640 if (nodes != NULL) {
5641 xmlRngPErr(ctxt, nodes, XML_RNGP_START_CONTENT,
5642 "start more than one children\n", NULL, NULL);
5643 return (-1);
5644 }
5645 return (ret);
5646}
5647
5657static int
5658xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
5659 xmlNodePtr nodes)
5660{
5661 int ret = 0, tmp;
5662
5663 if (nodes == NULL) {
5664 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_EMPTY,
5665 "grammar has no children\n", NULL, NULL);
5666 return (-1);
5667 }
5668 while (nodes != NULL) {
5669 if (IS_RELAXNG(nodes, "start")) {
5670 if (nodes->children == NULL) {
5671 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY,
5672 "start has no children\n", NULL, NULL);
5673 } else {
5674 tmp = xmlRelaxNGParseStart(ctxt, nodes->children);
5675 if (tmp != 0)
5676 ret = -1;
5677 }
5678 } else if (IS_RELAXNG(nodes, "define")) {
5679 tmp = xmlRelaxNGParseDefine(ctxt, nodes);
5680 if (tmp != 0)
5681 ret = -1;
5682 } else if (IS_RELAXNG(nodes, "include")) {
5683 tmp = xmlRelaxNGParseInclude(ctxt, nodes);
5684 if (tmp != 0)
5685 ret = -1;
5686 } else {
5687 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
5688 "grammar has unexpected child %s\n", nodes->name,
5689 NULL);
5690 ret = -1;
5691 }
5692 nodes = nodes->next;
5693 }
5694 return (ret);
5695}
5696
5706static void
5707xmlRelaxNGCheckReference(void *payload, void *data, const xmlChar * name)
5708{
5709 xmlRelaxNGDefinePtr ref = (xmlRelaxNGDefinePtr) payload;
5710 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
5711 xmlRelaxNGGrammarPtr grammar;
5712 xmlRelaxNGDefinePtr def, cur;
5713
5714 /*
5715 * Those rules don't apply to imported ref from xmlRelaxNGParseImportRef
5716 */
5717 if (ref->dflags & IS_EXTERNAL_REF)
5718 return;
5719
5720 grammar = ctxt->grammar;
5721 if (grammar == NULL) {
5722 xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
5723 "Internal error: no grammar in CheckReference %s\n",
5724 name, NULL);
5725 return;
5726 }
5727 if (ref->content != NULL) {
5728 xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
5729 "Internal error: reference has content in CheckReference %s\n",
5730 name, NULL);
5731 return;
5732 }
5733 if (grammar->defs != NULL) {
5734 def = xmlHashLookup(grammar->defs, name);
5735 if (def != NULL) {
5736 cur = ref;
5737 while (cur != NULL) {
5738 cur->content = def;
5739 cur = cur->nextHash;
5740 }
5741 } else {
5742 xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
5743 "Reference %s has no matching definition\n", name,
5744 NULL);
5745 }
5746 } else {
5747 xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
5748 "Reference %s has no matching definition\n", name,
5749 NULL);
5750 }
5751}
5752
5762static void
5763xmlRelaxNGCheckCombine(void *payload, void *data, const xmlChar * name)
5764{
5765 xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) payload;
5766 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
5767 xmlChar *combine;
5768 int choiceOrInterleave = -1;
5769 int missing = 0;
5770 xmlRelaxNGDefinePtr cur, last, tmp, tmp2;
5771
5772 if (define->nextHash == NULL)
5773 return;
5774 cur = define;
5775 while (cur != NULL) {
5776 combine = xmlGetProp(cur->node, BAD_CAST "combine");
5777 if (combine != NULL) {
5778 if (xmlStrEqual(combine, BAD_CAST "choice")) {
5779 if (choiceOrInterleave == -1)
5780 choiceOrInterleave = 1;
5781 else if (choiceOrInterleave == 0) {
5782 xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
5783 "Defines for %s use both 'choice' and 'interleave'\n",
5784 name, NULL);
5785 }
5786 } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
5787 if (choiceOrInterleave == -1)
5788 choiceOrInterleave = 0;
5789 else if (choiceOrInterleave == 1) {
5790 xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
5791 "Defines for %s use both 'choice' and 'interleave'\n",
5792 name, NULL);
5793 }
5794 } else {
5795 xmlRngPErr(ctxt, define->node, XML_RNGP_UNKNOWN_COMBINE,
5796 "Defines for %s use unknown combine value '%s''\n",
5797 name, combine);
5798 }
5799 xmlFree(combine);
5800 } else {
5801 if (missing == 0)
5802 missing = 1;
5803 else {
5804 xmlRngPErr(ctxt, define->node, XML_RNGP_NEED_COMBINE,
5805 "Some defines for %s needs the combine attribute\n",
5806 name, NULL);
5807 }
5808 }
5809
5810 cur = cur->nextHash;
5811 }
5812#ifdef DEBUG
5814 "xmlRelaxNGCheckCombine(): merging %s defines: %d\n",
5815 name, choiceOrInterleave);
5816#endif
5817 if (choiceOrInterleave == -1)
5818 choiceOrInterleave = 0;
5819 cur = xmlRelaxNGNewDefine(ctxt, define->node);
5820 if (cur == NULL)
5821 return;
5822 if (choiceOrInterleave == 0)
5823 cur->type = XML_RELAXNG_INTERLEAVE;
5824 else
5825 cur->type = XML_RELAXNG_CHOICE;
5826 tmp = define;
5827 last = NULL;
5828 while (tmp != NULL) {
5829 if (tmp->content != NULL) {
5830 if (tmp->content->next != NULL) {
5831 /*
5832 * we need first to create a wrapper.
5833 */
5834 tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node);
5835 if (tmp2 == NULL)
5836 break;
5837 tmp2->type = XML_RELAXNG_GROUP;
5838 tmp2->content = tmp->content;
5839 } else {
5840 tmp2 = tmp->content;
5841 }
5842 if (last == NULL) {
5843 cur->content = tmp2;
5844 } else {
5845 last->next = tmp2;
5846 }
5847 last = tmp2;
5848 }
5849 tmp->content = cur;
5850 tmp = tmp->nextHash;
5851 }
5852 define->content = cur;
5853 if (choiceOrInterleave == 0) {
5854 if (ctxt->interleaves == NULL)
5855 ctxt->interleaves = xmlHashCreate(10);
5856 if (ctxt->interleaves == NULL) {
5857 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
5858 "Failed to create interleaves hash table\n", NULL,
5859 NULL);
5860 } else {
5861 char tmpname[32];
5862
5863 snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
5864 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
5865 0) {
5866 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
5867 "Failed to add %s to hash table\n",
5868 (const xmlChar *) tmpname, NULL);
5869 }
5870 }
5871 }
5872}
5873
5882static void
5883xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt,
5884 xmlRelaxNGGrammarPtr grammar)
5885{
5886 xmlRelaxNGDefinePtr starts;
5887 xmlChar *combine;
5888 int choiceOrInterleave = -1;
5889 int missing = 0;
5890 xmlRelaxNGDefinePtr cur;
5891
5892 starts = grammar->start;
5893 if ((starts == NULL) || (starts->next == NULL))
5894 return;
5895 cur = starts;
5896 while (cur != NULL) {
5897 if ((cur->node == NULL) || (cur->node->parent == NULL) ||
5898 (!xmlStrEqual(cur->node->parent->name, BAD_CAST "start"))) {
5899 combine = NULL;
5900 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_MISSING,
5901 "Internal error: start element not found\n", NULL,
5902 NULL);
5903 } else {
5904 combine = xmlGetProp(cur->node->parent, BAD_CAST "combine");
5905 }
5906
5907 if (combine != NULL) {
5908 if (xmlStrEqual(combine, BAD_CAST "choice")) {
5909 if (choiceOrInterleave == -1)
5910 choiceOrInterleave = 1;
5911 else if (choiceOrInterleave == 0) {
5912 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
5913 "<start> use both 'choice' and 'interleave'\n",
5914 NULL, NULL);
5915 }
5916 } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
5917 if (choiceOrInterleave == -1)
5918 choiceOrInterleave = 0;
5919 else if (choiceOrInterleave == 1) {
5920 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
5921 "<start> use both 'choice' and 'interleave'\n",
5922 NULL, NULL);
5923 }
5924 } else {
5925 xmlRngPErr(ctxt, cur->node, XML_RNGP_UNKNOWN_COMBINE,
5926 "<start> uses unknown combine value '%s''\n",
5927 combine, NULL);
5928 }
5929 xmlFree(combine);
5930 } else {
5931 if (missing == 0)
5932 missing = 1;
5933 else {
5934 xmlRngPErr(ctxt, cur->node, XML_RNGP_NEED_COMBINE,
5935 "Some <start> element miss the combine attribute\n",
5936 NULL, NULL);
5937 }
5938 }
5939
5940 cur = cur->next;
5941 }
5942#ifdef DEBUG
5944 "xmlRelaxNGCombineStart(): merging <start>: %d\n",
5945 choiceOrInterleave);
5946#endif
5947 if (choiceOrInterleave == -1)
5948 choiceOrInterleave = 0;
5949 cur = xmlRelaxNGNewDefine(ctxt, starts->node);
5950 if (cur == NULL)
5951 return;
5952 if (choiceOrInterleave == 0)
5953 cur->type = XML_RELAXNG_INTERLEAVE;
5954 else
5955 cur->type = XML_RELAXNG_CHOICE;
5956 cur->content = grammar->start;
5957 grammar->start = cur;
5958 if (choiceOrInterleave == 0) {
5959 if (ctxt->interleaves == NULL)
5960 ctxt->interleaves = xmlHashCreate(10);
5961 if (ctxt->interleaves == NULL) {
5962 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
5963 "Failed to create interleaves hash table\n", NULL,
5964 NULL);
5965 } else {
5966 char tmpname[32];
5967
5968 snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
5969 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
5970 0) {
5971 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
5972 "Failed to add %s to hash table\n",
5973 (const xmlChar *) tmpname, NULL);
5974 }
5975 }
5976 }
5977}
5978
5989static int
5990xmlRelaxNGCheckCycles(xmlRelaxNGParserCtxtPtr ctxt,
5991 xmlRelaxNGDefinePtr cur, int depth)
5992{
5993 int ret = 0;
5994
5995 while ((ret == 0) && (cur != NULL)) {
5996 if ((cur->type == XML_RELAXNG_REF) ||
5997 (cur->type == XML_RELAXNG_PARENTREF)) {
5998 if (cur->depth == -1) {
5999 cur->depth = depth;
6000 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
6001 cur->depth = -2;
6002 } else if (depth == cur->depth) {
6003 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_CYCLE,
6004 "Detected a cycle in %s references\n",
6005 cur->name, NULL);
6006 return (-1);
6007 }
6008 } else if (cur->type == XML_RELAXNG_ELEMENT) {
6009 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth + 1);
6010 } else {
6011 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
6012 }
6013 cur = cur->next;
6014 }
6015 return (ret);
6016}
6017
6029static xmlRelaxNGDefinePtr
6030xmlRelaxNGTryUnlink(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
6031 xmlRelaxNGDefinePtr cur,
6032 xmlRelaxNGDefinePtr parent, xmlRelaxNGDefinePtr prev)
6033{
6034 if (prev != NULL) {
6035 prev->next = cur->next;
6036 } else {
6037 if (parent != NULL) {
6038 if (parent->content == cur)
6039 parent->content = cur->next;
6040 else if (parent->attrs == cur)
6041 parent->attrs = cur->next;
6042 else if (parent->nameClass == cur)
6043 parent->nameClass = cur->next;
6044 } else {
6045 cur->type = XML_RELAXNG_NOOP;
6046 prev = cur;
6047 }
6048 }
6049 return (prev);
6050}
6051
6059static void
6060xmlRelaxNGSimplify(xmlRelaxNGParserCtxtPtr ctxt,
6061 xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent)
6062{
6063 xmlRelaxNGDefinePtr prev = NULL;
6064
6065 while (cur != NULL) {
6066 if ((cur->type == XML_RELAXNG_REF) ||
6067 (cur->type == XML_RELAXNG_PARENTREF)) {
6068 if (cur->depth != -3) {
6069 cur->depth = -3;
6070 xmlRelaxNGSimplify(ctxt, cur->content, cur);
6071 }
6072 } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
6073 cur->parent = parent;
6074 if ((parent != NULL) &&
6075 ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
6076 (parent->type == XML_RELAXNG_LIST) ||
6077 (parent->type == XML_RELAXNG_GROUP) ||
6078 (parent->type == XML_RELAXNG_INTERLEAVE) ||
6079 (parent->type == XML_RELAXNG_ONEORMORE) ||
6080 (parent->type == XML_RELAXNG_ZEROORMORE))) {
6081 parent->type = XML_RELAXNG_NOT_ALLOWED;
6082 break;
6083 }
6084 if ((parent != NULL) && (parent->type == XML_RELAXNG_CHOICE)) {
6085 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
6086 } else
6087 prev = cur;
6088 } else if (cur->type == XML_RELAXNG_EMPTY) {
6089 cur->parent = parent;
6090 if ((parent != NULL) &&
6091 ((parent->type == XML_RELAXNG_ONEORMORE) ||
6092 (parent->type == XML_RELAXNG_ZEROORMORE))) {
6093 parent->type = XML_RELAXNG_EMPTY;
6094 break;
6095 }
6096 if ((parent != NULL) &&
6097 ((parent->type == XML_RELAXNG_GROUP) ||
6098 (parent->type == XML_RELAXNG_INTERLEAVE))) {
6099 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
6100 } else
6101 prev = cur;
6102 } else {
6103 cur->parent = parent;
6104 if (cur->content != NULL)
6105 xmlRelaxNGSimplify(ctxt, cur->content, cur);
6106 if ((cur->type != XML_RELAXNG_VALUE) && (cur->attrs != NULL))
6107 xmlRelaxNGSimplify(ctxt, cur->attrs, cur);
6108 if (cur->nameClass != NULL)
6109 xmlRelaxNGSimplify(ctxt, cur->nameClass, cur);
6110 /*
6111 * On Elements, try to move attribute only generating rules on
6112 * the attrs rules.
6113 */
6114 if (cur->type == XML_RELAXNG_ELEMENT) {
6115 int attronly;
6116 xmlRelaxNGDefinePtr tmp, pre;
6117
6118 while (cur->content != NULL) {
6119 attronly =
6120 xmlRelaxNGGenerateAttributes(ctxt, cur->content);
6121 if (attronly == 1) {
6122 /*
6123 * migrate cur->content to attrs
6124 */
6125 tmp = cur->content;
6126 cur->content = tmp->next;
6127 tmp->next = cur->attrs;
6128 cur->attrs = tmp;
6129 } else {
6130 /*
6131 * cur->content can generate elements or text
6132 */
6133 break;
6134 }
6135 }
6136 pre = cur->content;
6137 while ((pre != NULL) && (pre->next != NULL)) {
6138 tmp = pre->next;
6139 attronly = xmlRelaxNGGenerateAttributes(ctxt, tmp);
6140 if (attronly == 1) {
6141 /*
6142 * migrate tmp to attrs
6143 */
6144 pre->next = tmp->next;
6145 tmp->next = cur->attrs;
6146 cur->attrs = tmp;
6147 } else {
6148 pre = tmp;
6149 }
6150 }
6151 }
6152 /*
6153 * This may result in a simplification
6154 */
6155 if ((cur->type == XML_RELAXNG_GROUP) ||
6156 (cur->type == XML_RELAXNG_INTERLEAVE)) {
6157 if (cur->content == NULL)
6158 cur->type = XML_RELAXNG_EMPTY;
6159 else if (cur->content->next == NULL) {
6160 if ((parent == NULL) && (prev == NULL)) {
6161 cur->type = XML_RELAXNG_NOOP;
6162 } else if (prev == NULL) {
6163 parent->content = cur->content;
6164 cur->content->next = cur->next;
6165 cur = cur->content;
6166 } else {
6167 cur->content->next = cur->next;
6168 prev->next = cur->content;
6169 cur = cur->content;
6170 }
6171 }
6172 }
6173 /*
6174 * the current node may have been transformed back
6175 */
6176 if ((cur->type == XML_RELAXNG_EXCEPT) &&
6177 (cur->content != NULL) &&
6178 (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) {
6179 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
6180 } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
6181 if ((parent != NULL) &&
6182 ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
6183 (parent->type == XML_RELAXNG_LIST) ||
6184 (parent->type == XML_RELAXNG_GROUP) ||
6185 (parent->type == XML_RELAXNG_INTERLEAVE) ||
6186 (parent->type == XML_RELAXNG_ONEORMORE) ||
6187 (parent->type == XML_RELAXNG_ZEROORMORE))) {
6188 parent->type = XML_RELAXNG_NOT_ALLOWED;
6189 break;
6190 }
6191 if ((parent != NULL) &&
6192 (parent->type == XML_RELAXNG_CHOICE)) {
6193 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
6194 } else
6195 prev = cur;
6196 } else if (cur->type == XML_RELAXNG_EMPTY) {
6197 if ((parent != NULL) &&
6198 ((parent->type == XML_RELAXNG_ONEORMORE) ||
6199 (parent->type == XML_RELAXNG_ZEROORMORE))) {
6200 parent->type = XML_RELAXNG_EMPTY;
6201 break;
6202 }
6203 if ((parent != NULL) &&
6204 ((parent->type == XML_RELAXNG_GROUP) ||
6205 (parent->type == XML_RELAXNG_INTERLEAVE) ||
6206 (parent->type == XML_RELAXNG_CHOICE))) {
6207 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
6208 } else
6209 prev = cur;
6210 } else {
6211 prev = cur;
6212 }
6213 }
6214 cur = cur->next;
6215 }
6216}
6217
6227static xmlRelaxNGContentType
6228xmlRelaxNGGroupContentType(xmlRelaxNGContentType ct1,
6229 xmlRelaxNGContentType ct2)
6230{
6231 if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
6232 (ct2 == XML_RELAXNG_CONTENT_ERROR))
6233 return (XML_RELAXNG_CONTENT_ERROR);
6234 if (ct1 == XML_RELAXNG_CONTENT_EMPTY)
6235 return (ct2);
6236 if (ct2 == XML_RELAXNG_CONTENT_EMPTY)
6237 return (ct1);
6238 if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) &&
6239 (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
6240 return (XML_RELAXNG_CONTENT_COMPLEX);
6241 return (XML_RELAXNG_CONTENT_ERROR);
6242}
6243
6253static xmlRelaxNGContentType
6254xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1,
6255 xmlRelaxNGContentType ct2)
6256{
6257 if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
6258 (ct2 == XML_RELAXNG_CONTENT_ERROR))
6259 return (XML_RELAXNG_CONTENT_ERROR);
6260 if ((ct1 == XML_RELAXNG_CONTENT_SIMPLE) ||
6261 (ct2 == XML_RELAXNG_CONTENT_SIMPLE))
6262 return (XML_RELAXNG_CONTENT_SIMPLE);
6263 if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) ||
6264 (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
6265 return (XML_RELAXNG_CONTENT_COMPLEX);
6266 return (XML_RELAXNG_CONTENT_EMPTY);
6267}
6268
6280static xmlRelaxNGContentType
6281xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt,
6282 xmlRelaxNGDefinePtr cur, int flags,
6283 xmlRelaxNGType ptype)
6284{
6285 int nflags;
6286 xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY;
6287
6288 while (cur != NULL) {
6289 ret = XML_RELAXNG_CONTENT_EMPTY;
6290 if ((cur->type == XML_RELAXNG_REF) ||
6291 (cur->type == XML_RELAXNG_PARENTREF)) {
6292 /*
6293 * This should actually be caught by list//element(ref) at the
6294 * element boundaries, c.f. Bug #159968 local refs are dropped
6295 * in step 4.19.
6296 */
6297#if 0
6298 if (flags & XML_RELAXNG_IN_LIST) {
6299 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_REF,
6300 "Found forbidden pattern list//ref\n", NULL,
6301 NULL);
6302 }
6303#endif
6304 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6305 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_REF,
6306 "Found forbidden pattern data/except//ref\n",
6307 NULL, NULL);
6308 }
6309 if (cur->content == NULL) {
6310 if (cur->type == XML_RELAXNG_PARENTREF)
6311 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,
6312 "Internal found no define for parent refs\n",
6313 NULL, NULL);
6314 else
6315 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,
6316 "Internal found no define for ref %s\n",
6317 (cur->name ? cur->name: BAD_CAST "null"), NULL);
6318 }
6319 if (cur->depth > -4) {
6320 cur->depth = -4;
6321 ret = xmlRelaxNGCheckRules(ctxt, cur->content,
6322 flags, cur->type);
6323 cur->depth = ret - 15;
6324 } else if (cur->depth == -4) {
6325 ret = XML_RELAXNG_CONTENT_COMPLEX;
6326 } else {
6327 ret = (xmlRelaxNGContentType) (cur->depth + 15);
6328 }
6329 } else if (cur->type == XML_RELAXNG_ELEMENT) {
6330 /*
6331 * The 7.3 Attribute derivation rule for groups is plugged there
6332 */
6333 xmlRelaxNGCheckGroupAttrs(ctxt, cur);
6334 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6335 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ELEM,
6336 "Found forbidden pattern data/except//element(ref)\n",
6337 NULL, NULL);
6338 }
6339 if (flags & XML_RELAXNG_IN_LIST) {
6340 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ELEM,
6341 "Found forbidden pattern list//element(ref)\n",
6342 NULL, NULL);
6343 }
6344 if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
6345 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
6346 "Found forbidden pattern attribute//element(ref)\n",
6347 NULL, NULL);
6348 }
6349 if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
6350 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
6351 "Found forbidden pattern attribute//element(ref)\n",
6352 NULL, NULL);
6353 }
6354 /*
6355 * reset since in the simple form elements are only child
6356 * of grammar/define
6357 */
6358 nflags = 0;
6359 ret =
6360 xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type);
6361 if (ret != XML_RELAXNG_CONTENT_EMPTY) {
6362 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_EMPTY,
6363 "Element %s attributes have a content type error\n",
6364 cur->name, NULL);
6365 }
6366 ret =
6367 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6368 cur->type);
6369 if (ret == XML_RELAXNG_CONTENT_ERROR) {
6370 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_ERROR,
6371 "Element %s has a content type error\n",
6372 cur->name, NULL);
6373 } else {
6374 ret = XML_RELAXNG_CONTENT_COMPLEX;
6375 }
6376 } else if (cur->type == XML_RELAXNG_ATTRIBUTE) {
6377 if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
6378 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ATTR,
6379 "Found forbidden pattern attribute//attribute\n",
6380 NULL, NULL);
6381 }
6382 if (flags & XML_RELAXNG_IN_LIST) {
6383 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ATTR,
6384 "Found forbidden pattern list//attribute\n",
6385 NULL, NULL);
6386 }
6387 if (flags & XML_RELAXNG_IN_OOMGROUP) {
6388 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_GROUP_ATTR,
6389 "Found forbidden pattern oneOrMore//group//attribute\n",
6390 NULL, NULL);
6391 }
6392 if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) {
6393 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR,
6394 "Found forbidden pattern oneOrMore//interleave//attribute\n",
6395 NULL, NULL);
6396 }
6397 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6398 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ATTR,
6399 "Found forbidden pattern data/except//attribute\n",
6400 NULL, NULL);
6401 }
6402 if (flags & XML_RELAXNG_IN_START) {
6403 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ATTR,
6404 "Found forbidden pattern start//attribute\n",
6405 NULL, NULL);
6406 }
6407 if ((!(flags & XML_RELAXNG_IN_ONEORMORE))
6408 && cur->name == NULL
6409 /* following is checking alternative name class readiness
6410 in case it went the "choice" route */
6411 && cur->nameClass == NULL) {
6412 if (cur->ns == NULL) {
6413 xmlRngPErr(ctxt, cur->node, XML_RNGP_ANYNAME_ATTR_ANCESTOR,
6414 "Found anyName attribute without oneOrMore ancestor\n",
6415 NULL, NULL);
6416 } else {
6417 xmlRngPErr(ctxt, cur->node, XML_RNGP_NSNAME_ATTR_ANCESTOR,
6418 "Found nsName attribute without oneOrMore ancestor\n",
6419 NULL, NULL);
6420 }
6421 }
6422 nflags = flags | XML_RELAXNG_IN_ATTRIBUTE;
6423 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
6424 ret = XML_RELAXNG_CONTENT_EMPTY;
6425 } else if ((cur->type == XML_RELAXNG_ONEORMORE) ||
6426 (cur->type == XML_RELAXNG_ZEROORMORE)) {
6427 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6428 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ONEMORE,
6429 "Found forbidden pattern data/except//oneOrMore\n",
6430 NULL, NULL);
6431 }
6432 if (flags & XML_RELAXNG_IN_START) {
6433 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ONEMORE,
6434 "Found forbidden pattern start//oneOrMore\n",
6435 NULL, NULL);
6436 }
6437 nflags = flags | XML_RELAXNG_IN_ONEORMORE;
6438 ret =
6439 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6440 cur->type);
6441 ret = xmlRelaxNGGroupContentType(ret, ret);
6442 } else if (cur->type == XML_RELAXNG_LIST) {
6443 if (flags & XML_RELAXNG_IN_LIST) {
6444 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_LIST,
6445 "Found forbidden pattern list//list\n", NULL,
6446 NULL);
6447 }
6448 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6449 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_LIST,
6450 "Found forbidden pattern data/except//list\n",
6451 NULL, NULL);
6452 }
6453 if (flags & XML_RELAXNG_IN_START) {
6454 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_LIST,
6455 "Found forbidden pattern start//list\n", NULL,
6456 NULL);
6457 }
6458 nflags = flags | XML_RELAXNG_IN_LIST;
6459 ret =
6460 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6461 cur->type);
6462 } else if (cur->type == XML_RELAXNG_GROUP) {
6463 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6464 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_GROUP,
6465 "Found forbidden pattern data/except//group\n",
6466 NULL, NULL);
6467 }
6468 if (flags & XML_RELAXNG_IN_START) {
6469 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_GROUP,
6470 "Found forbidden pattern start//group\n", NULL,
6471 NULL);
6472 }
6473 if (flags & XML_RELAXNG_IN_ONEORMORE)
6474 nflags = flags | XML_RELAXNG_IN_OOMGROUP;
6475 else
6476 nflags = flags;
6477 ret =
6478 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6479 cur->type);
6480 /*
6481 * The 7.3 Attribute derivation rule for groups is plugged there
6482 */
6483 xmlRelaxNGCheckGroupAttrs(ctxt, cur);
6484 } else if (cur->type == XML_RELAXNG_INTERLEAVE) {
6485 if (flags & XML_RELAXNG_IN_LIST) {
6486 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_INTERLEAVE,
6487 "Found forbidden pattern list//interleave\n",
6488 NULL, NULL);
6489 }
6490 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6491 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
6492 "Found forbidden pattern data/except//interleave\n",
6493 NULL, NULL);
6494 }
6495 if (flags & XML_RELAXNG_IN_START) {
6496 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
6497 "Found forbidden pattern start//interleave\n",
6498 NULL, NULL);
6499 }
6500 if (flags & XML_RELAXNG_IN_ONEORMORE)
6501 nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE;
6502 else
6503 nflags = flags;
6504 ret =
6505 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6506 cur->type);
6507 } else if (cur->type == XML_RELAXNG_EXCEPT) {
6508 if ((cur->parent != NULL) &&
6509 (cur->parent->type == XML_RELAXNG_DATATYPE))
6510 nflags = flags | XML_RELAXNG_IN_DATAEXCEPT;
6511 else
6512 nflags = flags;
6513 ret =
6514 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6515 cur->type);
6516 } else if (cur->type == XML_RELAXNG_DATATYPE) {
6517 if (flags & XML_RELAXNG_IN_START) {
6518 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_DATA,
6519 "Found forbidden pattern start//data\n", NULL,
6520 NULL);
6521 }
6522 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
6523 ret = XML_RELAXNG_CONTENT_SIMPLE;
6524 } else if (cur->type == XML_RELAXNG_VALUE) {
6525 if (flags & XML_RELAXNG_IN_START) {
6526 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_VALUE,
6527 "Found forbidden pattern start//value\n", NULL,
6528 NULL);
6529 }
6530 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
6531 ret = XML_RELAXNG_CONTENT_SIMPLE;
6532 } else if (cur->type == XML_RELAXNG_TEXT) {
6533 if (flags & XML_RELAXNG_IN_LIST) {
6534 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_TEXT,
6535 "Found forbidden pattern list//text\n", NULL,
6536 NULL);
6537 }
6538 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6539 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_TEXT,
6540 "Found forbidden pattern data/except//text\n",
6541 NULL, NULL);
6542 }
6543 if (flags & XML_RELAXNG_IN_START) {
6544 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_TEXT,
6545 "Found forbidden pattern start//text\n", NULL,
6546 NULL);
6547 }
6548 ret = XML_RELAXNG_CONTENT_COMPLEX;
6549 } else if (cur->type == XML_RELAXNG_EMPTY) {
6550 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6551 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_EMPTY,
6552 "Found forbidden pattern data/except//empty\n",
6553 NULL, NULL);
6554 }
6555 if (flags & XML_RELAXNG_IN_START) {
6556 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_EMPTY,
6557 "Found forbidden pattern start//empty\n", NULL,
6558 NULL);
6559 }
6560 ret = XML_RELAXNG_CONTENT_EMPTY;
6561 } else if (cur->type == XML_RELAXNG_CHOICE) {
6562 xmlRelaxNGCheckChoiceDeterminism(ctxt, cur);
6563 ret =
6564 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
6565 } else {
6566 ret =
6567 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
6568 }
6569 cur = cur->next;
6570 if (ptype == XML_RELAXNG_GROUP) {
6571 val = xmlRelaxNGGroupContentType(val, ret);
6572 } else if (ptype == XML_RELAXNG_INTERLEAVE) {
6573 /*
6574 * TODO: scan complain that tmp is never used, seems on purpose
6575 * need double-checking
6576 */
6577 tmp = xmlRelaxNGGroupContentType(val, ret);
6578 if (tmp != XML_RELAXNG_CONTENT_ERROR)
6579 tmp = xmlRelaxNGMaxContentType(val, ret);
6580 } else if (ptype == XML_RELAXNG_CHOICE) {
6581 val = xmlRelaxNGMaxContentType(val, ret);
6582 } else if (ptype == XML_RELAXNG_LIST) {
6583 val = XML_RELAXNG_CONTENT_SIMPLE;
6584 } else if (ptype == XML_RELAXNG_EXCEPT) {
6585 if (ret == XML_RELAXNG_CONTENT_ERROR)
6586 val = XML_RELAXNG_CONTENT_ERROR;
6587 else
6588 val = XML_RELAXNG_CONTENT_SIMPLE;
6589 } else {
6590 val = xmlRelaxNGGroupContentType(val, ret);
6591 }
6592
6593 }
6594 return (val);
6595}
6596
6607static xmlRelaxNGGrammarPtr
6608xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
6609{
6610 xmlRelaxNGGrammarPtr ret, tmp, old;
6611
6612#ifdef DEBUG_GRAMMAR
6613 xmlGenericError(xmlGenericErrorContext, "Parsing a new grammar\n");
6614#endif
6615
6616 ret = xmlRelaxNGNewGrammar(ctxt);
6617 if (ret == NULL)
6618 return (NULL);
6619
6620 /*
6621 * Link the new grammar in the tree
6622 */
6623 ret->parent = ctxt->grammar;
6624 if (ctxt->grammar != NULL) {
6625 tmp = ctxt->grammar->children;
6626 if (tmp == NULL) {
6627 ctxt->grammar->children = ret;
6628 } else {
6629 while (tmp->next != NULL)
6630 tmp = tmp->next;
6631 tmp->next = ret;
6632 }
6633 }
6634
6635 old = ctxt->grammar;
6636 ctxt->grammar = ret;
6637 xmlRelaxNGParseGrammarContent(ctxt, nodes);
6638 ctxt->grammar = ret;
6639 if (ctxt->grammar == NULL) {
6640 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
6641 "Failed to parse <grammar> content\n", NULL, NULL);
6642 } else if (ctxt->grammar->start == NULL) {
6643 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_NO_START,
6644 "Element <grammar> has no <start>\n", NULL, NULL);
6645 }
6646
6647 /*
6648 * Apply 4.17 merging rules to defines and starts
6649 */
6650 xmlRelaxNGCombineStart(ctxt, ret);
6651 if (ret->defs != NULL) {
6652 xmlHashScan(ret->defs, xmlRelaxNGCheckCombine, ctxt);
6653 }
6654
6655 /*
6656 * link together defines and refs in this grammar
6657 */
6658 if (ret->refs != NULL) {
6659 xmlHashScan(ret->refs, xmlRelaxNGCheckReference, ctxt);
6660 }
6661
6662
6663 /* @@@@ */
6664
6665 ctxt->grammar = old;
6666 return (ret);
6667}
6668
6680static xmlRelaxNGPtr
6681xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
6682{
6683 xmlRelaxNGPtr schema = NULL;
6684 const xmlChar *olddefine;
6685 xmlRelaxNGGrammarPtr old;
6686
6687 if ((ctxt == NULL) || (node == NULL))
6688 return (NULL);
6689
6690 schema = xmlRelaxNGNewRelaxNG(ctxt);
6691 if (schema == NULL)
6692 return (NULL);
6693
6694 olddefine = ctxt->define;
6695 ctxt->define = NULL;
6696 if (IS_RELAXNG(node, "grammar")) {
6697 schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children);
6698 if (schema->topgrammar == NULL) {
6699 xmlRelaxNGFree(schema);
6700 return (NULL);
6701 }
6702 } else {
6703 xmlRelaxNGGrammarPtr tmp, ret;
6704
6705 schema->topgrammar = ret = xmlRelaxNGNewGrammar(ctxt);
6706 if (schema->topgrammar == NULL) {
6707 xmlRelaxNGFree(schema);
6708 return (NULL);
6709 }
6710 /*
6711 * Link the new grammar in the tree
6712 */
6713 ret->parent = ctxt->grammar;
6714 if (ctxt->grammar != NULL) {
6715 tmp = ctxt->grammar->children;
6716 if (tmp == NULL) {
6717 ctxt->grammar->children = ret;
6718 } else {
6719 while (tmp->next != NULL)
6720 tmp = tmp->next;
6721 tmp->next = ret;
6722 }
6723 }
6724 old = ctxt->grammar;
6725 ctxt->grammar = ret;
6726 xmlRelaxNGParseStart(ctxt, node);
6727 if (old != NULL)
6728 ctxt->grammar = old;
6729 }
6730 ctxt->define = olddefine;
6731 if (schema->topgrammar->start != NULL) {
6732 xmlRelaxNGCheckCycles(ctxt, schema->topgrammar->start, 0);
6733 if ((ctxt->flags & XML_RELAXNG_IN_EXTERNALREF) == 0) {
6734 xmlRelaxNGSimplify(ctxt, schema->topgrammar->start, NULL);
6735 while ((schema->topgrammar->start != NULL) &&
6736 (schema->topgrammar->start->type == XML_RELAXNG_NOOP) &&
6737 (schema->topgrammar->start->next != NULL))
6738 schema->topgrammar->start =
6739 schema->topgrammar->start->content;
6740 xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start,
6741 XML_RELAXNG_IN_START, XML_RELAXNG_NOOP);
6742 }
6743 }
6744#ifdef DEBUG
6745 if (schema == NULL)
6747 "xmlRelaxNGParseDocument() failed\n");
6748#endif
6749
6750 return (schema);
6751}
6752
6753/************************************************************************
6754 * *
6755 * Reading RelaxNGs *
6756 * *
6757 ************************************************************************/
6758
6768xmlRelaxNGParserCtxtPtr
6769xmlRelaxNGNewParserCtxt(const char *URL)
6770{
6771 xmlRelaxNGParserCtxtPtr ret;
6772
6773 if (URL == NULL)
6774 return (NULL);
6775
6776 ret =
6777 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
6778 if (ret == NULL) {
6779 xmlRngPErrMemory(NULL, "building parser\n");
6780 return (NULL);
6781 }
6782 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
6783 ret->URL = xmlStrdup((const xmlChar *) URL);
6784 ret->error = xmlGenericError;
6785 ret->userData = xmlGenericErrorContext;
6786 return (ret);
6787}
6788
6799xmlRelaxNGParserCtxtPtr
6800xmlRelaxNGNewMemParserCtxt(const char *buffer, int size)
6801{
6802 xmlRelaxNGParserCtxtPtr ret;
6803
6804 if ((buffer == NULL) || (size <= 0))
6805 return (NULL);
6806
6807 ret =
6808 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
6809 if (ret == NULL) {
6810 xmlRngPErrMemory(NULL, "building parser\n");
6811 return (NULL);
6812 }
6813 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
6814 ret->buffer = buffer;
6815 ret->size = size;
6816 ret->error = xmlGenericError;
6817 ret->userData = xmlGenericErrorContext;
6818 return (ret);
6819}
6820
6831xmlRelaxNGParserCtxtPtr
6832xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc)
6833{
6834 xmlRelaxNGParserCtxtPtr ret;
6836
6837 if (doc == NULL)
6838 return (NULL);
6839 copy = xmlCopyDoc(doc, 1);
6840 if (copy == NULL)
6841 return (NULL);
6842
6843 ret =
6844 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
6845 if (ret == NULL) {
6846 xmlRngPErrMemory(NULL, "building parser\n");
6848 return (NULL);
6849 }
6850 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
6851 ret->document = copy;
6852 ret->freedoc = 1;
6853 ret->userData = xmlGenericErrorContext;
6854 return (ret);
6855}
6856
6863void
6864xmlRelaxNGFreeParserCtxt(xmlRelaxNGParserCtxtPtr ctxt)
6865{
6866 if (ctxt == NULL)
6867 return;
6868 if (ctxt->URL != NULL)
6869 xmlFree(ctxt->URL);
6870 if (ctxt->doc != NULL)
6871 xmlRelaxNGFreeDocument(ctxt->doc);
6872 if (ctxt->interleaves != NULL)
6873 xmlHashFree(ctxt->interleaves, NULL);
6874 if (ctxt->documents != NULL)
6875 xmlRelaxNGFreeDocumentList(ctxt->documents);
6876 if (ctxt->includes != NULL)
6877 xmlRelaxNGFreeIncludeList(ctxt->includes);
6878 if (ctxt->docTab != NULL)
6879 xmlFree(ctxt->docTab);
6880 if (ctxt->incTab != NULL)
6881 xmlFree(ctxt->incTab);
6882 if (ctxt->defTab != NULL) {
6883 int i;
6884
6885 for (i = 0; i < ctxt->defNr; i++)
6886 xmlRelaxNGFreeDefine(ctxt->defTab[i]);
6887 xmlFree(ctxt->defTab);
6888 }
6889 if ((ctxt->document != NULL) && (ctxt->freedoc))
6890 xmlFreeDoc(ctxt->document);
6891 xmlFree(ctxt);
6892}
6893
6901static void
6902xmlRelaxNGNormExtSpace(xmlChar * value)
6903{
6904 xmlChar *start = value;
6905 xmlChar *cur = value;
6906
6907 if (value == NULL)
6908 return;
6909
6910 while (IS_BLANK_CH(*cur))
6911 cur++;
6912 if (cur == start) {
6913 do {
6914 while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
6915 cur++;
6916 if (*cur == 0)
6917 return;
6918 start = cur;
6919 while (IS_BLANK_CH(*cur))
6920 cur++;
6921 if (*cur == 0) {
6922 *start = 0;
6923 return;
6924 }
6925 } while (1);
6926 } else {
6927 do {
6928 while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
6929 *start++ = *cur++;
6930 if (*cur == 0) {
6931 *start = 0;
6932 return;
6933 }
6934 /* don't try to normalize the inner spaces */
6935 while (IS_BLANK_CH(*cur))
6936 cur++;
6937 if (*cur == 0) {
6938 *start = 0;
6939 return;
6940 }
6941 *start++ = *cur++;
6942 } while (1);
6943 }
6944}
6945
6953static void
6954xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
6955{
6957
6958 cur = node->properties;
6959 while (cur != NULL) {
6960 next = cur->next;
6961 if ((cur->ns == NULL) ||
6962 (xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
6963 if (xmlStrEqual(cur->name, BAD_CAST "name")) {
6964 if ((!xmlStrEqual(node->name, BAD_CAST "element")) &&
6965 (!xmlStrEqual(node->name, BAD_CAST "attribute")) &&
6966 (!xmlStrEqual(node->name, BAD_CAST "ref")) &&
6967 (!xmlStrEqual(node->name, BAD_CAST "parentRef")) &&
6968 (!xmlStrEqual(node->name, BAD_CAST "param")) &&
6969 (!xmlStrEqual(node->name, BAD_CAST "define"))) {
6970 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
6971 "Attribute %s is not allowed on %s\n",
6972 cur->name, node->name);
6973 }
6974 } else if (xmlStrEqual(cur->name, BAD_CAST "type")) {
6975 if ((!xmlStrEqual(node->name, BAD_CAST "value")) &&
6976 (!xmlStrEqual(node->name, BAD_CAST "data"))) {
6977 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
6978 "Attribute %s is not allowed on %s\n",
6979 cur->name, node->name);
6980 }
6981 } else if (xmlStrEqual(cur->name, BAD_CAST "href")) {
6982 if ((!xmlStrEqual(node->name, BAD_CAST "externalRef")) &&
6983 (!xmlStrEqual(node->name, BAD_CAST "include"))) {
6984 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
6985 "Attribute %s is not allowed on %s\n",
6986 cur->name, node->name);
6987 }
6988 } else if (xmlStrEqual(cur->name, BAD_CAST "combine")) {
6989 if ((!xmlStrEqual(node->name, BAD_CAST "start")) &&
6990 (!xmlStrEqual(node->name, BAD_CAST "define"))) {
6991 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
6992 "Attribute %s is not allowed on %s\n",
6993 cur->name, node->name);
6994 }
6995 } else if (xmlStrEqual(cur->name, BAD_CAST "datatypeLibrary")) {
6996 xmlChar *val;
6997 xmlURIPtr uri;
6998
6999 val = xmlNodeListGetString(node->doc, cur->children, 1);
7000 if (val != NULL) {
7001 if (val[0] != 0) {
7002 uri = xmlParseURI((const char *) val);
7003 if (uri == NULL) {
7004 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_URI,
7005 "Attribute %s contains invalid URI %s\n",
7006 cur->name, val);
7007 } else {
7008 if (uri->scheme == NULL) {
7009 xmlRngPErr(ctxt, node, XML_RNGP_URI_NOT_ABSOLUTE,
7010 "Attribute %s URI %s is not absolute\n",
7011 cur->name, val);
7012 }
7013 if (uri->fragment != NULL) {
7014 xmlRngPErr(ctxt, node, XML_RNGP_URI_FRAGMENT,
7015 "Attribute %s URI %s has a fragment ID\n",
7016 cur->name, val);
7017 }
7018 xmlFreeURI(uri);
7019 }
7020 }
7021 xmlFree(val);
7022 }
7023 } else if (!xmlStrEqual(cur->name, BAD_CAST "ns")) {
7024 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_ATTRIBUTE,
7025 "Unknown attribute %s on %s\n", cur->name,
7026 node->name);
7027 }
7028 }
7029 cur = next;
7030 }
7031}
7032
7041static void
7042xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root)
7043{
7044 xmlNodePtr cur, delete;
7045
7046 delete = NULL;
7047 cur = root;
7048 while (cur != NULL) {
7049 if (delete != NULL) {
7050 xmlUnlinkNode(delete);
7051 xmlFreeNode(delete);
7052 delete = NULL;
7053 }
7054 if (cur->type == XML_ELEMENT_NODE) {
7055 /*
7056 * Simplification 4.1. Annotations
7057 */
7058 if ((cur->ns == NULL) ||
7059 (!xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
7060 if ((cur->parent != NULL) &&
7061 (cur->parent->type == XML_ELEMENT_NODE) &&
7062 ((xmlStrEqual(cur->parent->name, BAD_CAST "name")) ||
7063 (xmlStrEqual(cur->parent->name, BAD_CAST "value")) ||
7064 (xmlStrEqual(cur->parent->name, BAD_CAST "param")))) {
7065 xmlRngPErr(ctxt, cur, XML_RNGP_FOREIGN_ELEMENT,
7066 "element %s doesn't allow foreign elements\n",
7067 cur->parent->name, NULL);
7068 }
7069 delete = cur;
7070 goto skip_children;
7071 } else {
7072 xmlRelaxNGCleanupAttributes(ctxt, cur);
7073 if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) {
7074 xmlChar *href, *ns, *base, *URL;
7075 xmlRelaxNGDocumentPtr docu;
7076 xmlNodePtr tmp;
7077 xmlURIPtr uri;
7078
7079 ns = xmlGetProp(cur, BAD_CAST "ns");
7080 if (ns == NULL) {
7081 tmp = cur->parent;
7082 while ((tmp != NULL) &&
7083 (tmp->type == XML_ELEMENT_NODE)) {
7084 ns = xmlGetProp(tmp, BAD_CAST "ns");
7085 if (ns != NULL)
7086 break;
7087 tmp = tmp->parent;
7088 }
7089 }
7090 href = xmlGetProp(cur, BAD_CAST "href");
7091 if (href == NULL) {
7092 xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
7093 "xmlRelaxNGParse: externalRef has no href attribute\n",
7094 NULL, NULL);
7095 if (ns != NULL)
7096 xmlFree(ns);
7097 delete = cur;
7098 goto skip_children;
7099 }
7100 uri = xmlParseURI((const char *) href);
7101 if (uri == NULL) {
7102 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
7103 "Incorrect URI for externalRef %s\n",
7104 href, NULL);
7105 if (ns != NULL)
7106 xmlFree(ns);
7107 if (href != NULL)
7108 xmlFree(href);
7109 delete = cur;
7110 goto skip_children;
7111 }
7112 if (uri->fragment != NULL) {
7113 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
7114 "Fragment forbidden in URI for externalRef %s\n",
7115 href, NULL);
7116 if (ns != NULL)
7117 xmlFree(ns);
7118 xmlFreeURI(uri);
7119 if (href != NULL)
7120 xmlFree(href);
7121 delete = cur;
7122 goto skip_children;
7123 }
7124 xmlFreeURI(uri);
7125 base = xmlNodeGetBase(cur->doc, cur);
7126 URL = xmlBuildURI(href, base);
7127 if (URL == NULL) {
7128 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
7129 "Failed to compute URL for externalRef %s\n",
7130 href, NULL);
7131 if (ns != NULL)
7132 xmlFree(ns);
7133 if (href != NULL)
7134 xmlFree(href);
7135 if (base != NULL)
7136 xmlFree(base);
7137 delete = cur;
7138 goto skip_children;
7139 }
7140 if (href != NULL)
7141 xmlFree(href);
7142 if (base != NULL)
7143 xmlFree(base);
7144 docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns);
7145 if (docu == NULL) {
7146 xmlRngPErr(ctxt, cur, XML_RNGP_EXTERNAL_REF_FAILURE,
7147 "Failed to load externalRef %s\n", URL,
7148 NULL);
7149 if (ns != NULL)
7150 xmlFree(ns);
7151 xmlFree(URL);
7152 delete = cur;
7153 goto skip_children;
7154 }
7155 if (ns != NULL)
7156 xmlFree(ns);
7157 xmlFree(URL);
7158 cur->psvi = docu;
7159 } else if (xmlStrEqual(cur->name, BAD_CAST "include")) {
7160 xmlChar *href, *ns, *base, *URL;
7161 xmlRelaxNGIncludePtr incl;
7162 xmlNodePtr tmp;
7163
7164 href = xmlGetProp(cur, BAD_CAST "href");
7165 if (href == NULL) {
7166 xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
7167 "xmlRelaxNGParse: include has no href attribute\n",
7168 NULL, NULL);
7169 delete = cur;
7170 goto skip_children;
7171 }
7172 base = xmlNodeGetBase(cur->doc, cur);
7173 URL = xmlBuildURI(href, base);
7174 if (URL == NULL) {
7175 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
7176 "Failed to compute URL for include %s\n",
7177 href, NULL);
7178 if (href != NULL)
7179 xmlFree(href);
7180 if (base != NULL)
7181 xmlFree(base);
7182 delete = cur;
7183 goto skip_children;
7184 }
7185 if (href != NULL)
7186 xmlFree(href);
7187 if (base != NULL)
7188 xmlFree(base);
7189 ns = xmlGetProp(cur, BAD_CAST "ns");
7190 if (ns == NULL) {
7191 tmp = cur->parent;
7192 while ((tmp != NULL) &&
7193 (tmp->type == XML_ELEMENT_NODE)) {
7194 ns = xmlGetProp(tmp, BAD_CAST "ns");
7195 if (ns != NULL)
7196 break;
7197 tmp = tmp->parent;
7198 }
7199 }
7200 incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns);
7201 if (ns != NULL)
7202 xmlFree(ns);
7203 if (incl == NULL) {
7204 xmlRngPErr(ctxt, cur, XML_RNGP_INCLUDE_FAILURE,
7205 "Failed to load include %s\n", URL,
7206 NULL);
7207 xmlFree(URL);
7208 delete = cur;
7209 goto skip_children;
7210 }
7211 xmlFree(URL);
7212 cur->psvi = incl;
7213 } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) ||
7214 (xmlStrEqual(cur->name, BAD_CAST "attribute")))
7215 {
7216 xmlChar *name, *ns;
7218
7219 /*
7220 * Simplification 4.8. name attribute of element
7221 * and attribute elements
7222 */
7223 name = xmlGetProp(cur, BAD_CAST "name");
7224 if (name != NULL) {
7225 if (cur->children == NULL) {
7226 text =
7227 xmlNewChild(cur, cur->ns, BAD_CAST "name",
7228 name);
7229 } else {
7231
7232 node = xmlNewDocNode(cur->doc, cur->ns,
7233 BAD_CAST "name", NULL);
7234 if (node != NULL) {
7235 xmlAddPrevSibling(cur->children, node);
7236 text = xmlNewDocText(node->doc, name);
7238 text = node;
7239 }
7240 }
7241 if (text == NULL) {
7242 xmlRngPErr(ctxt, cur, XML_RNGP_CREATE_FAILURE,
7243 "Failed to create a name %s element\n",
7244 name, NULL);
7245 }
7246 xmlUnsetProp(cur, BAD_CAST "name");
7247 xmlFree(name);
7248 ns = xmlGetProp(cur, BAD_CAST "ns");
7249 if (ns != NULL) {
7250 if (text != NULL) {
7251 xmlSetProp(text, BAD_CAST "ns", ns);
7252 /* xmlUnsetProp(cur, BAD_CAST "ns"); */
7253 }
7254 xmlFree(ns);
7255 } else if (xmlStrEqual(cur->name,
7256 BAD_CAST "attribute")) {
7257 xmlSetProp(text, BAD_CAST "ns", BAD_CAST "");
7258 }
7259 }
7260 } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) ||
7261 (xmlStrEqual(cur->name, BAD_CAST "nsName")) ||
7262 (xmlStrEqual(cur->name, BAD_CAST "value"))) {
7263 /*
7264 * Simplification 4.8. name attribute of element
7265 * and attribute elements
7266 */
7267 if (xmlHasProp(cur, BAD_CAST "ns") == NULL) {
7269 xmlChar *ns = NULL;
7270
7271 node = cur->parent;
7272 while ((node != NULL) &&
7273 (node->type == XML_ELEMENT_NODE)) {
7274 ns = xmlGetProp(node, BAD_CAST "ns");
7275 if (ns != NULL) {
7276 break;
7277 }
7278 node = node->parent;
7279 }
7280 if (ns == NULL) {
7281 xmlSetProp(cur, BAD_CAST "ns", BAD_CAST "");
7282 } else {
7283 xmlSetProp(cur, BAD_CAST "ns", ns);
7284 xmlFree(ns);
7285 }
7286 }
7287 if (xmlStrEqual(cur->name, BAD_CAST "name")) {
7288 xmlChar *name, *local, *prefix;
7289
7290 /*
7291 * Simplification: 4.10. QNames
7292 */
7294 if (name != NULL) {
7295 local = xmlSplitQName2(name, &prefix);
7296 if (local != NULL) {
7297 xmlNsPtr ns;
7298
7299 ns = xmlSearchNs(cur->doc, cur, prefix);
7300 if (ns == NULL) {
7301 xmlRngPErr(ctxt, cur,
7303 "xmlRelaxNGParse: no namespace for prefix %s\n",
7304 prefix, NULL);
7305 } else {
7306 xmlSetProp(cur, BAD_CAST "ns",
7307 ns->href);
7309 }
7310 xmlFree(local);
7311 xmlFree(prefix);
7312 }
7313 xmlFree(name);
7314 }
7315 }
7316 /*
7317 * 4.16
7318 */
7319 if (xmlStrEqual(cur->name, BAD_CAST "nsName")) {
7320 if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
7321 xmlRngPErr(ctxt, cur,
7323 "Found nsName/except//nsName forbidden construct\n",
7324 NULL, NULL);
7325 }
7326 }
7327 } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) &&
7328 (cur != root)) {
7329 int oldflags = ctxt->flags;
7330
7331 /*
7332 * 4.16
7333 */
7334 if ((cur->parent != NULL) &&
7336 (cur->parent->name, BAD_CAST "anyName"))) {
7337 ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT;
7338 xmlRelaxNGCleanupTree(ctxt, cur);
7339 ctxt->flags = oldflags;
7340 goto skip_children;
7341 } else if ((cur->parent != NULL) &&
7343 (cur->parent->name, BAD_CAST "nsName"))) {
7344 ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT;
7345 xmlRelaxNGCleanupTree(ctxt, cur);
7346 ctxt->flags = oldflags;
7347 goto skip_children;
7348 }
7349 } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) {
7350 /*
7351 * 4.16
7352 */
7353 if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) {
7354 xmlRngPErr(ctxt, cur,
7356 "Found anyName/except//anyName forbidden construct\n",
7357 NULL, NULL);
7358 } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
7359 xmlRngPErr(ctxt, cur,
7361 "Found nsName/except//anyName forbidden construct\n",
7362 NULL, NULL);
7363 }
7364 }
7365 /*
7366 * This is not an else since "include" is transformed
7367 * into a div
7368 */
7369 if (xmlStrEqual(cur->name, BAD_CAST "div")) {
7370 xmlChar *ns;
7371 xmlNodePtr child, ins, tmp;
7372
7373 /*
7374 * implements rule 4.11
7375 */
7376
7377 ns = xmlGetProp(cur, BAD_CAST "ns");
7378
7379 child = cur->children;
7380 ins = cur;
7381 while (child != NULL) {
7382 if (ns != NULL) {
7383 if (!xmlHasProp(child, BAD_CAST "ns")) {
7384 xmlSetProp(child, BAD_CAST "ns", ns);
7385 }
7386 }
7387 tmp = child->next;
7389 ins = xmlAddNextSibling(ins, child);
7390 child = tmp;
7391 }
7392 if (ns != NULL)
7393 xmlFree(ns);
7394 /*
7395 * Since we are about to delete cur, if its nsDef is non-NULL we
7396 * need to preserve it (it contains the ns definitions for the
7397 * children we just moved). We'll just stick it on to the end
7398 * of cur->parent's list, since it's never going to be re-serialized
7399 * (bug 143738).
7400 */
7401 if ((cur->nsDef != NULL) && (cur->parent != NULL)) {
7402 xmlNsPtr parDef = (xmlNsPtr)&cur->parent->nsDef;
7403 while (parDef->next != NULL)
7404 parDef = parDef->next;
7405 parDef->next = cur->nsDef;
7406 cur->nsDef = NULL;
7407 }
7408 delete = cur;
7409 goto skip_children;
7410 }
7411 }
7412 }
7413 /*
7414 * Simplification 4.2 whitespaces
7415 */
7416 else if ((cur->type == XML_TEXT_NODE) ||
7417 (cur->type == XML_CDATA_SECTION_NODE)) {
7418 if (IS_BLANK_NODE(cur)) {
7419 if ((cur->parent != NULL) &&
7420 (cur->parent->type == XML_ELEMENT_NODE)) {
7421 if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value"))
7422 &&
7423 (!xmlStrEqual
7424 (cur->parent->name, BAD_CAST "param")))
7425 delete = cur;
7426 } else {
7427 delete = cur;
7428 goto skip_children;
7429 }
7430 }
7431 } else {
7432 delete = cur;
7433 goto skip_children;
7434 }
7435
7436 /*
7437 * Skip to next node
7438 */
7439 if (cur->children != NULL) {
7440 if ((cur->children->type != XML_ENTITY_DECL) &&
7441 (cur->children->type != XML_ENTITY_REF_NODE) &&
7442 (cur->children->type != XML_ENTITY_NODE)) {
7443 cur = cur->children;
7444 continue;
7445 }
7446 }
7447 skip_children:
7448 if (cur->next != NULL) {
7449 cur = cur->next;
7450 continue;
7451 }
7452
7453 do {
7454 cur = cur->parent;
7455 if (cur == NULL)
7456 break;
7457 if (cur == root) {
7458 cur = NULL;
7459 break;
7460 }
7461 if (cur->next != NULL) {
7462 cur = cur->next;
7463 break;
7464 }
7465 } while (cur != NULL);
7466 }
7467 if (delete != NULL) {
7468 xmlUnlinkNode(delete);
7469 xmlFreeNode(delete);
7470 delete = NULL;
7471 }
7472}
7473
7484static xmlDocPtr
7485xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc)
7486{
7488
7489 /*
7490 * Extract the root
7491 */
7493 if (root == NULL) {
7494 xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
7495 ctxt->URL, NULL);
7496 return (NULL);
7497 }
7498 xmlRelaxNGCleanupTree(ctxt, root);
7499 return (doc);
7500}
7501
7512xmlRelaxNGPtr
7513xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
7514{
7515 xmlRelaxNGPtr ret = NULL;
7516 xmlDocPtr doc;
7518
7519 xmlRelaxNGInitTypes();
7520
7521 if (ctxt == NULL)
7522 return (NULL);
7523
7524 /*
7525 * First step is to parse the input document into an DOM/Infoset
7526 */
7527 if (ctxt->URL != NULL) {
7528 doc = xmlReadFile((const char *) ctxt->URL,NULL,0);
7529 if (doc == NULL) {
7530 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
7531 "xmlRelaxNGParse: could not load %s\n", ctxt->URL,
7532 NULL);
7533 return (NULL);
7534 }
7535 } else if (ctxt->buffer != NULL) {
7536 doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0);
7537 if (doc == NULL) {
7538 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
7539 "xmlRelaxNGParse: could not parse schemas\n", NULL,
7540 NULL);
7541 return (NULL);
7542 }
7543 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
7544 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
7545 } else if (ctxt->document != NULL) {
7546 doc = ctxt->document;
7547 } else {
7548 xmlRngPErr(ctxt, NULL, XML_RNGP_EMPTY,
7549 "xmlRelaxNGParse: nothing to parse\n", NULL, NULL);
7550 return (NULL);
7551 }
7552 ctxt->document = doc;
7553
7554 /*
7555 * Some preprocessing of the document content
7556 */
7557 doc = xmlRelaxNGCleanupDoc(ctxt, doc);
7558 if (doc == NULL) {
7559 xmlFreeDoc(ctxt->document);
7560 ctxt->document = NULL;
7561 return (NULL);
7562 }
7563
7564 /*
7565 * Then do the parsing for good
7566 */
7568 if (root == NULL) {
7569 xmlRngPErr(ctxt, (xmlNodePtr) doc,
7570 XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
7571 (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL);
7572
7573 xmlFreeDoc(ctxt->document);
7574 ctxt->document = NULL;
7575 return (NULL);
7576 }
7577 ret = xmlRelaxNGParseDocument(ctxt, root);
7578 if (ret == NULL) {
7579 xmlFreeDoc(ctxt->document);
7580 ctxt->document = NULL;
7581 return (NULL);
7582 }
7583
7584 /*
7585 * Check the ref/defines links
7586 */
7587 /*
7588 * try to preprocess interleaves
7589 */
7590 if (ctxt->interleaves != NULL) {
7591 xmlHashScan(ctxt->interleaves, xmlRelaxNGComputeInterleaves, ctxt);
7592 }
7593
7594 /*
7595 * if there was a parsing error return NULL
7596 */
7597 if (ctxt->nbErrors > 0) {
7598 xmlRelaxNGFree(ret);
7599 ctxt->document = NULL;
7600 xmlFreeDoc(doc);
7601 return (NULL);
7602 }
7603
7604 /*
7605 * try to compile (parts of) the schemas
7606 */
7607 if ((ret->topgrammar != NULL) && (ret->topgrammar->start != NULL)) {
7608 if (ret->topgrammar->start->type != XML_RELAXNG_START) {
7609 xmlRelaxNGDefinePtr def;
7610
7611 def = xmlRelaxNGNewDefine(ctxt, NULL);
7612 if (def != NULL) {
7613 def->type = XML_RELAXNG_START;
7614 def->content = ret->topgrammar->start;
7615 ret->topgrammar->start = def;
7616 }
7617 }
7618 xmlRelaxNGTryCompile(ctxt, ret->topgrammar->start);
7619 }
7620
7621 /*
7622 * Transfer the pointer for cleanup at the schema level.
7623 */
7624 ret->doc = doc;
7625 ctxt->document = NULL;
7626 ret->documents = ctxt->documents;
7627 ctxt->documents = NULL;
7628
7629 ret->includes = ctxt->includes;
7630 ctxt->includes = NULL;
7631 ret->defNr = ctxt->defNr;
7632 ret->defTab = ctxt->defTab;
7633 ctxt->defTab = NULL;
7634 if (ctxt->idref == 1)
7635 ret->idref = 1;
7636
7637 return (ret);
7638}
7639
7649void
7650xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
7651 xmlRelaxNGValidityErrorFunc err,
7652 xmlRelaxNGValidityWarningFunc warn, void *ctx)
7653{
7654 if (ctxt == NULL)
7655 return;
7656 ctxt->error = err;
7657 ctxt->warning = warn;
7658 ctxt->serror = NULL;
7659 ctxt->userData = ctx;
7660}
7661
7673int
7674xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
7675 xmlRelaxNGValidityErrorFunc * err,
7676 xmlRelaxNGValidityWarningFunc * warn, void **ctx)
7677{
7678 if (ctxt == NULL)
7679 return (-1);
7680 if (err != NULL)
7681 *err = ctxt->error;
7682 if (warn != NULL)
7683 *warn = ctxt->warning;
7684 if (ctx != NULL)
7685 *ctx = ctxt->userData;
7686 return (0);
7687}
7688
7697void
7698xmlRelaxNGSetParserStructuredErrors(xmlRelaxNGParserCtxtPtr ctxt,
7700 void *ctx)
7701{
7702 if (ctxt == NULL)
7703 return;
7704 ctxt->serror = serror;
7705 ctxt->error = NULL;
7706 ctxt->warning = NULL;
7707 ctxt->userData = ctx;
7708}
7709
7710#ifdef LIBXML_OUTPUT_ENABLED
7711
7712/************************************************************************
7713 * *
7714 * Dump back a compiled form *
7715 * *
7716 ************************************************************************/
7717static void xmlRelaxNGDumpDefine(FILE * output,
7718 xmlRelaxNGDefinePtr define);
7719
7727static void
7728xmlRelaxNGDumpDefines(FILE * output, xmlRelaxNGDefinePtr defines)
7729{
7730 while (defines != NULL) {
7731 xmlRelaxNGDumpDefine(output, defines);
7732 defines = defines->next;
7733 }
7734}
7735
7743static void
7744xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define)
7745{
7746 if (define == NULL)
7747 return;
7748 switch (define->type) {
7749 case XML_RELAXNG_EMPTY:
7750 fprintf(output, "<empty/>\n");
7751 break;
7752 case XML_RELAXNG_NOT_ALLOWED:
7753 fprintf(output, "<notAllowed/>\n");
7754 break;
7755 case XML_RELAXNG_TEXT:
7756 fprintf(output, "<text/>\n");
7757 break;
7758 case XML_RELAXNG_ELEMENT:
7759 fprintf(output, "<element>\n");
7760 if (define->name != NULL) {
7761 fprintf(output, "<name");
7762 if (define->ns != NULL)
7763 fprintf(output, " ns=\"%s\"", define->ns);
7764 fprintf(output, ">%s</name>\n", define->name);
7765 }
7766 xmlRelaxNGDumpDefines(output, define->attrs);
7767 xmlRelaxNGDumpDefines(output, define->content);
7768 fprintf(output, "</element>\n");
7769 break;
7770 case XML_RELAXNG_LIST:
7771 fprintf(output, "<list>\n");
7772 xmlRelaxNGDumpDefines(output, define->content);
7773 fprintf(output, "</list>\n");
7774 break;
7775 case XML_RELAXNG_ONEORMORE:
7776 fprintf(output, "<oneOrMore>\n");
7777 xmlRelaxNGDumpDefines(output, define->content);
7778 fprintf(output, "</oneOrMore>\n");
7779 break;
7780 case XML_RELAXNG_ZEROORMORE:
7781 fprintf(output, "<zeroOrMore>\n");
7782 xmlRelaxNGDumpDefines(output, define->content);
7783 fprintf(output, "</zeroOrMore>\n");
7784 break;
7785 case XML_RELAXNG_CHOICE:
7786 fprintf(output, "<choice>\n");
7787 xmlRelaxNGDumpDefines(output, define->content);
7788 fprintf(output, "</choice>\n");
7789 break;
7790 case XML_RELAXNG_GROUP:
7791 fprintf(output, "<group>\n");
7792 xmlRelaxNGDumpDefines(output, define->content);
7793 fprintf(output, "</group>\n");
7794 break;
7795 case XML_RELAXNG_INTERLEAVE:
7796 fprintf(output, "<interleave>\n");
7797 xmlRelaxNGDumpDefines(output, define->content);
7798 fprintf(output, "</interleave>\n");
7799 break;
7800 case XML_RELAXNG_OPTIONAL:
7801 fprintf(output, "<optional>\n");
7802 xmlRelaxNGDumpDefines(output, define->content);
7803 fprintf(output, "</optional>\n");
7804 break;
7805 case XML_RELAXNG_ATTRIBUTE:
7806 fprintf(output, "<attribute>\n");
7807 xmlRelaxNGDumpDefines(output, define->content);
7808 fprintf(output, "</attribute>\n");
7809 break;
7810 case XML_RELAXNG_DEF:
7811 fprintf(output, "<define");
7812 if (define->name != NULL)
7813 fprintf(output, " name=\"%s\"", define->name);
7814 fprintf(output, ">\n");
7815 xmlRelaxNGDumpDefines(output, define->content);
7816 fprintf(output, "</define>\n");
7817 break;
7818 case XML_RELAXNG_REF:
7819 fprintf(output, "<ref");
7820 if (define->name != NULL)
7821 fprintf(output, " name=\"%s\"", define->name);
7822 fprintf(output, ">\n");
7823 xmlRelaxNGDumpDefines(output, define->content);
7824 fprintf(output, "</ref>\n");
7825 break;
7826 case XML_RELAXNG_PARENTREF:
7827 fprintf(output, "<parentRef");
7828 if (define->name != NULL)
7829 fprintf(output, " name=\"%s\"", define->name);
7830 fprintf(output, ">\n");
7831 xmlRelaxNGDumpDefines(output, define->content);
7832 fprintf(output, "</parentRef>\n");
7833 break;
7834 case XML_RELAXNG_EXTERNALREF:
7835 fprintf(output, "<externalRef>");
7836 xmlRelaxNGDumpDefines(output, define->content);
7837 fprintf(output, "</externalRef>\n");
7838 break;
7839 case XML_RELAXNG_DATATYPE:
7840 case XML_RELAXNG_VALUE:
7841 TODO break;
7842 case XML_RELAXNG_START:
7843 case XML_RELAXNG_EXCEPT:
7844 case XML_RELAXNG_PARAM:
7845 TODO break;
7846 case XML_RELAXNG_NOOP:
7847 xmlRelaxNGDumpDefines(output, define->content);
7848 break;
7849 }
7850}
7851
7860static void
7861xmlRelaxNGDumpGrammar(FILE * output, xmlRelaxNGGrammarPtr grammar, int top)
7862{
7863 if (grammar == NULL)
7864 return;
7865
7866 fprintf(output, "<grammar");
7867 if (top)
7868 fprintf(output, " xmlns=\"http://relaxng.org/ns/structure/1.0\"");
7869 switch (grammar->combine) {
7870 case XML_RELAXNG_COMBINE_UNDEFINED:
7871 break;
7872 case XML_RELAXNG_COMBINE_CHOICE:
7873 fprintf(output, " combine=\"choice\"");
7874 break;
7875 case XML_RELAXNG_COMBINE_INTERLEAVE:
7876 fprintf(output, " combine=\"interleave\"");
7877 break;
7878 default:
7879 fprintf(output, " <!-- invalid combine value -->");
7880 }
7881 fprintf(output, ">\n");
7882 if (grammar->start == NULL) {
7883 fprintf(output, " <!-- grammar had no start -->");
7884 } else {
7885 fprintf(output, "<start>\n");
7886 xmlRelaxNGDumpDefine(output, grammar->start);
7887 fprintf(output, "</start>\n");
7888 }
7889 /* TODO ? Dump the defines ? */
7890 fprintf(output, "</grammar>\n");
7891}
7892
7900void
7901xmlRelaxNGDump(FILE * output, xmlRelaxNGPtr schema)
7902{
7903 if (output == NULL)
7904 return;
7905 if (schema == NULL) {
7906 fprintf(output, "RelaxNG empty or failed to compile\n");
7907 return;
7908 }
7909 fprintf(output, "RelaxNG: ");
7910 if (schema->doc == NULL) {
7911 fprintf(output, "no document\n");
7912 } else if (schema->doc->URL != NULL) {
7913 fprintf(output, "%s\n", schema->doc->URL);
7914 } else {
7915 fprintf(output, "\n");
7916 }
7917 if (schema->topgrammar == NULL) {
7918 fprintf(output, "RelaxNG has no top grammar\n");
7919 return;
7920 }
7921 xmlRelaxNGDumpGrammar(output, schema->topgrammar, 1);
7922}
7923
7931void
7932xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema)
7933{
7934 if (output == NULL)
7935 return;
7936 if (schema == NULL) {
7937 fprintf(output, "RelaxNG empty or failed to compile\n");
7938 return;
7939 }
7940 if (schema->doc == NULL) {
7941 fprintf(output, "no document\n");
7942 } else {
7943 xmlDocDump(output, schema->doc);
7944 }
7945}
7946#endif /* LIBXML_OUTPUT_ENABLED */
7947
7948/************************************************************************
7949 * *
7950 * Validation of compiled content *
7951 * *
7952 ************************************************************************/
7953static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
7954 xmlRelaxNGDefinePtr define);
7955
7965static void
7966xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
7967 const xmlChar * token,
7968 void *transdata, void *inputdata)
7969{
7970 xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
7971 xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
7972 int ret;
7973
7974#ifdef DEBUG_COMPILE
7976 "Compiled callback for: '%s'\n", token);
7977#endif
7978 if (ctxt == NULL) {
7979 fprintf(stderr, "callback on %s missing context\n", token);
7980 return;
7981 }
7982 if (define == NULL) {
7983 if (token[0] == '#')
7984 return;
7985 fprintf(stderr, "callback on %s missing define\n", token);
7986 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
7987 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
7988 return;
7989 }
7990 if ((ctxt == NULL) || (define == NULL)) {
7991 fprintf(stderr, "callback on %s missing info\n", token);
7992 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
7993 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
7994 return;
7995 } else if (define->type != XML_RELAXNG_ELEMENT) {
7996 fprintf(stderr, "callback on %s define is not element\n", token);
7997 if (ctxt->errNo == XML_RELAXNG_OK)
7998 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
7999 return;
8000 }
8001 ret = xmlRelaxNGValidateDefinition(ctxt, define);
8002 if (ret != 0)
8003 ctxt->perr = ret;
8004}
8005
8016static int
8017xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt,
8018 xmlRegexpPtr regexp, xmlNodePtr content)
8019{
8020 xmlRegExecCtxtPtr exec;
8022 int ret = 0;
8023 int oldperr;
8024
8025 if ((ctxt == NULL) || (regexp == NULL))
8026 return (-1);
8027 oldperr = ctxt->perr;
8028 exec = xmlRegNewExecCtxt(regexp,
8029 xmlRelaxNGValidateCompiledCallback, ctxt);
8030 ctxt->perr = 0;
8031 cur = content;
8032 while (cur != NULL) {
8033 ctxt->state->seq = cur;
8034 switch (cur->type) {
8035 case XML_TEXT_NODE:
8037 if (xmlIsBlankNode(cur))
8038 break;
8039 ret = xmlRegExecPushString(exec, BAD_CAST "#text", ctxt);
8040 if (ret < 0) {
8041 VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG,
8042 cur->parent->name);
8043 }
8044 break;
8045 case XML_ELEMENT_NODE:
8046 if (cur->ns != NULL) {
8047 ret = xmlRegExecPushString2(exec, cur->name,
8048 cur->ns->href, ctxt);
8049 } else {
8050 ret = xmlRegExecPushString(exec, cur->name, ctxt);
8051 }
8052 if (ret < 0) {
8053 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, cur->name);
8054 }
8055 break;
8056 default:
8057 break;
8058 }
8059 if (ret < 0)
8060 break;
8061 /*
8062 * Switch to next element
8063 */
8064 cur = cur->next;
8065 }
8066 ret = xmlRegExecPushString(exec, NULL, NULL);
8067 if (ret == 1) {
8068 ret = 0;
8069 ctxt->state->seq = NULL;
8070 } else if (ret == 0) {
8071 /*
8072 * TODO: get some of the names needed to exit the current state of exec
8073 */
8074 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
8075 ret = -1;
8076 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
8077 xmlRelaxNGDumpValidError(ctxt);
8078 } else {
8079 ret = -1;
8080 }
8081 xmlRegFreeExecCtxt(exec);
8082 /*
8083 * There might be content model errors outside of the pure
8084 * regexp validation, e.g. for attribute values.
8085 */
8086 if ((ret == 0) && (ctxt->perr != 0)) {
8087 ret = ctxt->perr;
8088 }
8089 ctxt->perr = oldperr;
8090 return (ret);
8091}
8092
8093/************************************************************************
8094 * *
8095 * Progressive validation of when possible *
8096 * *
8097 ************************************************************************/
8098static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
8099 xmlRelaxNGDefinePtr defines);
8100static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt,
8101 int dolog);
8102static void xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt);
8103
8113static int
8114xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec)
8115{
8116 if (ctxt->elemTab == NULL) {
8117 ctxt->elemMax = 10;
8118 ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlMalloc(ctxt->elemMax *
8119 sizeof
8120 (xmlRegExecCtxtPtr));
8121 if (ctxt->elemTab == NULL) {
8122 xmlRngVErrMemory(ctxt, "validating\n");
8123 return (-1);
8124 }
8125 }
8126 if (ctxt->elemNr >= ctxt->elemMax) {
8127 ctxt->elemMax *= 2;
8128 ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlRealloc(ctxt->elemTab,
8129 ctxt->elemMax *
8130 sizeof
8131 (xmlRegExecCtxtPtr));
8132 if (ctxt->elemTab == NULL) {
8133 xmlRngVErrMemory(ctxt, "validating\n");
8134 return (-1);
8135 }
8136 }
8137 ctxt->elemTab[ctxt->elemNr++] = exec;
8138 ctxt->elem = exec;
8139 return (0);
8140}
8141
8150static xmlRegExecCtxtPtr
8151xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt)
8152{
8153 xmlRegExecCtxtPtr ret;
8154
8155 if (ctxt->elemNr <= 0)
8156 return (NULL);
8157 ctxt->elemNr--;
8158 ret = ctxt->elemTab[ctxt->elemNr];
8159 ctxt->elemTab[ctxt->elemNr] = NULL;
8160 if (ctxt->elemNr > 0)
8161 ctxt->elem = ctxt->elemTab[ctxt->elemNr - 1];
8162 else
8163 ctxt->elem = NULL;
8164 return (ret);
8165}
8166
8177static void
8178xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec
8180 const xmlChar * token,
8181 void *transdata, void *inputdata)
8182{
8183 xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
8184 xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
8185 xmlRelaxNGValidStatePtr state, oldstate;
8187 int ret = 0, oldflags;
8188
8189#ifdef DEBUG_PROGRESSIVE
8191 "Progressive callback for: '%s'\n", token);
8192#endif
8193 if (ctxt == NULL) {
8194 fprintf(stderr, "callback on %s missing context\n", token);
8195 return;
8196 }
8197 node = ctxt->pnode;
8198 ctxt->pstate = 1;
8199 if (define == NULL) {
8200 if (token[0] == '#')
8201 return;
8202 fprintf(stderr, "callback on %s missing define\n", token);
8203 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
8204 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
8205 ctxt->pstate = -1;
8206 return;
8207 }
8208 if ((ctxt == NULL) || (define == NULL)) {
8209 fprintf(stderr, "callback on %s missing info\n", token);
8210 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
8211 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
8212 ctxt->pstate = -1;
8213 return;
8214 } else if (define->type != XML_RELAXNG_ELEMENT) {
8215 fprintf(stderr, "callback on %s define is not element\n", token);
8216 if (ctxt->errNo == XML_RELAXNG_OK)
8217 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
8218 ctxt->pstate = -1;
8219 return;
8220 }
8221 if (node->type != XML_ELEMENT_NODE) {
8222 VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
8223 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
8224 xmlRelaxNGDumpValidError(ctxt);
8225 ctxt->pstate = -1;
8226 return;
8227 }
8228 if (define->contModel == NULL) {
8229 /*
8230 * this node cannot be validated in a streamable fashion
8231 */
8232#ifdef DEBUG_PROGRESSIVE
8234 "Element '%s' validation is not streamable\n",
8235 token);
8236#endif
8237 ctxt->pstate = 0;
8238 ctxt->pdef = define;
8239 return;
8240 }
8241 exec = xmlRegNewExecCtxt(define->contModel,
8242 xmlRelaxNGValidateProgressiveCallback, ctxt);
8243 if (exec == NULL) {
8244 ctxt->pstate = -1;
8245 return;
8246 }
8247 xmlRelaxNGElemPush(ctxt, exec);
8248
8249 /*
8250 * Validate the attributes part of the content.
8251 */
8252 state = xmlRelaxNGNewValidState(ctxt, node);
8253 if (state == NULL) {
8254 ctxt->pstate = -1;
8255 return;
8256 }
8257 oldstate = ctxt->state;
8258 ctxt->state = state;
8259 if (define->attrs != NULL) {
8260 ret = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
8261 if (ret != 0) {
8262 ctxt->pstate = -1;
8263 VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
8264 }
8265 }
8266 if (ctxt->state != NULL) {
8267 ctxt->state->seq = NULL;
8268 ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
8269 if (ret != 0) {
8270 ctxt->pstate = -1;
8271 }
8272 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
8273 } else if (ctxt->states != NULL) {
8274 int tmp = -1, i;
8275
8276 oldflags = ctxt->flags;
8277
8278 for (i = 0; i < ctxt->states->nbState; i++) {
8279 state = ctxt->states->tabState[i];
8280 ctxt->state = state;
8281 ctxt->state->seq = NULL;
8282
8283 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
8284 tmp = 0;
8285 break;
8286 }
8287 }
8288 if (tmp != 0) {
8289 /*
8290 * validation error, log the message for the "best" one
8291 */
8292 ctxt->flags |= FLAGS_IGNORABLE;
8293 xmlRelaxNGLogBestError(ctxt);
8294 }
8295 for (i = 0; i < ctxt->states->nbState; i++) {
8296 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[i]);
8297 }
8298 xmlRelaxNGFreeStates(ctxt, ctxt->states);
8299 ctxt->states = NULL;
8300 if ((ret == 0) && (tmp == -1))
8301 ctxt->pstate = -1;
8302 ctxt->flags = oldflags;
8303 }
8304 if (ctxt->pstate == -1) {
8305 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
8306 xmlRelaxNGDumpValidError(ctxt);
8307 }
8308 }
8309 ctxt->state = oldstate;
8310}
8311
8323int
8324xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt,
8327{
8328 int ret = 1;
8329
8330 if ((ctxt == NULL) || (elem == NULL))
8331 return (-1);
8332
8333#ifdef DEBUG_PROGRESSIVE
8334 xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name);
8335#endif
8336 if (ctxt->elem == 0) {
8337 xmlRelaxNGPtr schema;
8338 xmlRelaxNGGrammarPtr grammar;
8339 xmlRegExecCtxtPtr exec;
8340 xmlRelaxNGDefinePtr define;
8341
8342 schema = ctxt->schema;
8343 if (schema == NULL) {
8344 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
8345 return (-1);
8346 }
8347 grammar = schema->topgrammar;
8348 if ((grammar == NULL) || (grammar->start == NULL)) {
8349 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
8350 return (-1);
8351 }
8352 define = grammar->start;
8353 if (define->contModel == NULL) {
8354 ctxt->pdef = define;
8355 return (0);
8356 }
8357 exec = xmlRegNewExecCtxt(define->contModel,
8358 xmlRelaxNGValidateProgressiveCallback,
8359 ctxt);
8360 if (exec == NULL) {
8361 return (-1);
8362 }
8363 xmlRelaxNGElemPush(ctxt, exec);
8364 }
8365 ctxt->pnode = elem;
8366 ctxt->pstate = 0;
8367 if (elem->ns != NULL) {
8368 ret =
8369 xmlRegExecPushString2(ctxt->elem, elem->name, elem->ns->href,
8370 ctxt);
8371 } else {
8372 ret = xmlRegExecPushString(ctxt->elem, elem->name, ctxt);
8373 }
8374 if (ret < 0) {
8375 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, elem->name);
8376 } else {
8377 if (ctxt->pstate == 0)
8378 ret = 0;
8379 else if (ctxt->pstate < 0)
8380 ret = -1;
8381 else
8382 ret = 1;
8383 }
8384#ifdef DEBUG_PROGRESSIVE
8385 if (ret < 0)
8386 xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n",
8387 elem->name);
8388#endif
8389 return (ret);
8390}
8391
8402int
8403xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt,
8404 const xmlChar * data, int len ATTRIBUTE_UNUSED)
8405{
8406 int ret = 1;
8407
8408 if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL))
8409 return (-1);
8410
8411#ifdef DEBUG_PROGRESSIVE
8412 xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len);
8413#endif
8414
8415 while (*data != 0) {
8416 if (!IS_BLANK_CH(*data))
8417 break;
8418 data++;
8419 }
8420 if (*data == 0)
8421 return (1);
8422
8423 ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt);
8424 if (ret < 0) {
8425 VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO ");
8426#ifdef DEBUG_PROGRESSIVE
8427 xmlGenericError(xmlGenericErrorContext, "CDATA failed\n");
8428#endif
8429
8430 return (-1);
8431 }
8432 return (1);
8433}
8434
8445int
8446xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,
8449{
8450 int ret;
8451 xmlRegExecCtxtPtr exec;
8452
8453 if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL))
8454 return (-1);
8455#ifdef DEBUG_PROGRESSIVE
8456 xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name);
8457#endif
8458 /*
8459 * verify that we reached a terminal state of the content model.
8460 */
8461 exec = xmlRelaxNGElemPop(ctxt);
8462 ret = xmlRegExecPushString(exec, NULL, NULL);
8463 if (ret == 0) {
8464 /*
8465 * TODO: get some of the names needed to exit the current state of exec
8466 */
8467 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
8468 ret = -1;
8469 } else if (ret < 0) {
8470 ret = -1;
8471 } else {
8472 ret = 1;
8473 }
8474 xmlRegFreeExecCtxt(exec);
8475#ifdef DEBUG_PROGRESSIVE
8476 if (ret < 0)
8477 xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n",
8478 elem->name);
8479#endif
8480 return (ret);
8481}
8482
8494int
8495xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt,
8498{
8499 int ret;
8500 xmlRelaxNGValidStatePtr state;
8501
8502 if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL))
8503 return (-1);
8504#ifdef DEBUG_PROGRESSIVE
8505 xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name);
8506#endif
8507 state = xmlRelaxNGNewValidState(ctxt, elem->parent);
8508 if (state == NULL) {
8509 return (-1);
8510 }
8511 state->seq = elem;
8512 ctxt->state = state;
8513 ctxt->errNo = XML_RELAXNG_OK;
8514 ret = xmlRelaxNGValidateDefinition(ctxt, ctxt->pdef);
8515 if ((ret != 0) || (ctxt->errNo != XML_RELAXNG_OK))
8516 ret = -1;
8517 else
8518 ret = 1;
8519 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
8520 ctxt->state = NULL;
8521#ifdef DEBUG_PROGRESSIVE
8522 if (ret < 0)
8523 xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n",
8524 elem->name);
8525#endif
8526 return (ret);
8527}
8528
8529/************************************************************************
8530 * *
8531 * Generic interpreted validation implementation *
8532 * *
8533 ************************************************************************/
8534static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
8535 xmlRelaxNGDefinePtr define);
8536
8546static xmlNodePtr
8547xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
8549{
8550 /*
8551 * TODO complete and handle entities
8552 */
8553 while ((node != NULL) &&
8554 ((node->type == XML_COMMENT_NODE) ||
8555 (node->type == XML_PI_NODE) ||
8556 (node->type == XML_XINCLUDE_START) ||
8557 (node->type == XML_XINCLUDE_END) ||
8558 (((node->type == XML_TEXT_NODE) ||
8559 (node->type == XML_CDATA_SECTION_NODE)) &&
8560 ((ctxt->flags & FLAGS_MIXED_CONTENT) ||
8561 (IS_BLANK_NODE(node)))))) {
8562 node = node->next;
8563 }
8564 return (node);
8565}
8566
8577static xmlChar *
8578xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str)
8579{
8580 xmlChar *ret, *p;
8581 const xmlChar *tmp;
8582 int len;
8583
8584 if (str == NULL)
8585 return (NULL);
8586 tmp = str;
8587 while (*tmp != 0)
8588 tmp++;
8589 len = tmp - str;
8590
8591 ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar));
8592 if (ret == NULL) {
8593 xmlRngVErrMemory(ctxt, "validating\n");
8594 return (NULL);
8595 }
8596 p = ret;
8597 while (IS_BLANK_CH(*str))
8598 str++;
8599 while (*str != 0) {
8600 if (IS_BLANK_CH(*str)) {
8601 while (IS_BLANK_CH(*str))
8602 str++;
8603 if (*str == 0)
8604 break;
8605 *p++ = ' ';
8606 } else
8607 *p++ = *str++;
8608 }
8609 *p = 0;
8610 return (ret);
8611}
8612
8624static int
8625xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt,
8626 const xmlChar * value,
8627 xmlRelaxNGDefinePtr define, xmlNodePtr node)
8628{
8629 int ret, tmp;
8630 xmlRelaxNGTypeLibraryPtr lib;
8631 void *result = NULL;
8632 xmlRelaxNGDefinePtr cur;
8633
8634 if ((define == NULL) || (define->data == NULL)) {
8635 return (-1);
8636 }
8637 lib = (xmlRelaxNGTypeLibraryPtr) define->data;
8638 if (lib->check != NULL) {
8639 if ((define->attrs != NULL) &&
8640 (define->attrs->type == XML_RELAXNG_PARAM)) {
8641 ret =
8642 lib->check(lib->data, define->name, value, &result, node);
8643 } else {
8644 ret = lib->check(lib->data, define->name, value, NULL, node);
8645 }
8646 } else
8647 ret = -1;
8648 if (ret < 0) {
8649 VALID_ERR2(XML_RELAXNG_ERR_TYPE, define->name);
8650 if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
8651 lib->freef(lib->data, result);
8652 return (-1);
8653 } else if (ret == 1) {
8654 ret = 0;
8655 } else if (ret == 2) {
8656 VALID_ERR2P(XML_RELAXNG_ERR_DUPID, value);
8657 } else {
8658 VALID_ERR3P(XML_RELAXNG_ERR_TYPEVAL, define->name, value);
8659 ret = -1;
8660 }
8661 cur = define->attrs;
8662 while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) {
8663 if (lib->facet != NULL) {
8664 tmp = lib->facet(lib->data, define->name, cur->name,
8665 cur->value, value, result);
8666 if (tmp != 0)
8667 ret = -1;
8668 }
8669 cur = cur->next;
8670 }
8671 if ((ret == 0) && (define->content != NULL)) {
8672 const xmlChar *oldvalue, *oldendvalue;
8673
8674 oldvalue = ctxt->state->value;
8675 oldendvalue = ctxt->state->endvalue;
8676 ctxt->state->value = (xmlChar *) value;
8677 ctxt->state->endvalue = NULL;
8678 ret = xmlRelaxNGValidateValue(ctxt, define->content);
8679 ctxt->state->value = (xmlChar *) oldvalue;
8680 ctxt->state->endvalue = (xmlChar *) oldendvalue;
8681 }
8682 if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
8683 lib->freef(lib->data, result);
8684 return (ret);
8685}
8686
8695static int
8696xmlRelaxNGNextValue(xmlRelaxNGValidCtxtPtr ctxt)
8697{
8698 xmlChar *cur;
8699
8700 cur = ctxt->state->value;
8701 if ((cur == NULL) || (ctxt->state->endvalue == NULL)) {
8702 ctxt->state->value = NULL;
8703 ctxt->state->endvalue = NULL;
8704 return (0);
8705 }
8706 while (*cur != 0)
8707 cur++;
8708 while ((cur != ctxt->state->endvalue) && (*cur == 0))
8709 cur++;
8710 if (cur == ctxt->state->endvalue)
8711 ctxt->state->value = NULL;
8712 else
8713 ctxt->state->value = cur;
8714 return (0);
8715}
8716
8726static int
8727xmlRelaxNGValidateValueList(xmlRelaxNGValidCtxtPtr ctxt,
8728 xmlRelaxNGDefinePtr defines)
8729{
8730 int ret = 0;
8731
8732 while (defines != NULL) {
8733 ret = xmlRelaxNGValidateValue(ctxt, defines);
8734 if (ret != 0)
8735 break;
8736 defines = defines->next;
8737 }
8738 return (ret);
8739}
8740
8750static int
8751xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
8752 xmlRelaxNGDefinePtr define)
8753{
8754 int ret = 0, oldflags;
8755 xmlChar *value;
8756
8757 value = ctxt->state->value;
8758 switch (define->type) {
8759 case XML_RELAXNG_EMPTY:{
8760 if ((value != NULL) && (value[0] != 0)) {
8761 int idx = 0;
8762
8763 while (IS_BLANK_CH(value[idx]))
8764 idx++;
8765 if (value[idx] != 0)
8766 ret = -1;
8767 }
8768 break;
8769 }
8770 case XML_RELAXNG_TEXT:
8771 break;
8772 case XML_RELAXNG_VALUE:{
8773 if (!xmlStrEqual(value, define->value)) {
8774 if (define->name != NULL) {
8775 xmlRelaxNGTypeLibraryPtr lib;
8776
8777 lib = (xmlRelaxNGTypeLibraryPtr) define->data;
8778 if ((lib != NULL) && (lib->comp != NULL)) {
8779 ret = lib->comp(lib->data, define->name,
8780 define->value, define->node,
8781 (void *) define->attrs,
8782 value, ctxt->state->node);
8783 } else
8784 ret = -1;
8785 if (ret < 0) {
8786 VALID_ERR2(XML_RELAXNG_ERR_TYPECMP,
8787 define->name);
8788 return (-1);
8789 } else if (ret == 1) {
8790 ret = 0;
8791 } else {
8792 ret = -1;
8793 }
8794 } else {
8795 xmlChar *nval, *nvalue;
8796
8797 /*
8798 * TODO: trivial optimizations are possible by
8799 * computing at compile-time
8800 */
8801 nval = xmlRelaxNGNormalize(ctxt, define->value);
8802 nvalue = xmlRelaxNGNormalize(ctxt, value);
8803
8804 if ((nval == NULL) || (nvalue == NULL) ||
8805 (!xmlStrEqual(nval, nvalue)))
8806 ret = -1;
8807 if (nval != NULL)
8808 xmlFree(nval);
8809 if (nvalue != NULL)
8810 xmlFree(nvalue);
8811 }
8812 }
8813 if (ret == 0)
8814 xmlRelaxNGNextValue(ctxt);
8815 break;
8816 }
8817 case XML_RELAXNG_DATATYPE:{
8818 ret = xmlRelaxNGValidateDatatype(ctxt, value, define,
8819 ctxt->state->seq);
8820 if (ret == 0)
8821 xmlRelaxNGNextValue(ctxt);
8822
8823 break;
8824 }
8825 case XML_RELAXNG_CHOICE:{
8826 xmlRelaxNGDefinePtr list = define->content;
8827 xmlChar *oldvalue;
8828
8829 oldflags = ctxt->flags;
8830 ctxt->flags |= FLAGS_IGNORABLE;
8831
8832 oldvalue = ctxt->state->value;
8833 while (list != NULL) {
8834 ret = xmlRelaxNGValidateValue(ctxt, list);
8835 if (ret == 0) {
8836 break;
8837 }
8838 ctxt->state->value = oldvalue;
8839 list = list->next;
8840 }
8841 ctxt->flags = oldflags;
8842 if (ret != 0) {
8843 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
8844 xmlRelaxNGDumpValidError(ctxt);
8845 } else {
8846 if (ctxt->errNr > 0)
8847 xmlRelaxNGPopErrors(ctxt, 0);
8848 }
8849 break;
8850 }
8851 case XML_RELAXNG_LIST:{
8852 xmlRelaxNGDefinePtr list = define->content;
8853 xmlChar *oldvalue, *oldend, *val, *cur;
8854
8855#ifdef DEBUG_LIST
8856 int nb_values = 0;
8857#endif
8858
8859 oldvalue = ctxt->state->value;
8860 oldend = ctxt->state->endvalue;
8861
8862 val = xmlStrdup(oldvalue);
8863 if (val == NULL) {
8864 val = xmlStrdup(BAD_CAST "");
8865 }
8866 if (val == NULL) {
8867 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
8868 return (-1);
8869 }
8870 cur = val;
8871 while (*cur != 0) {
8872 if (IS_BLANK_CH(*cur)) {
8873 *cur = 0;
8874 cur++;
8875#ifdef DEBUG_LIST
8876 nb_values++;
8877#endif
8878 while (IS_BLANK_CH(*cur))
8879 *cur++ = 0;
8880 } else
8881 cur++;
8882 }
8883#ifdef DEBUG_LIST
8885 "list value: '%s' found %d items\n",
8886 oldvalue, nb_values);
8887 nb_values = 0;
8888#endif
8889 ctxt->state->endvalue = cur;
8890 cur = val;
8891 while ((*cur == 0) && (cur != ctxt->state->endvalue))
8892 cur++;
8893
8894 ctxt->state->value = cur;
8895
8896 while (list != NULL) {
8897 if (ctxt->state->value == ctxt->state->endvalue)
8898 ctxt->state->value = NULL;
8899 ret = xmlRelaxNGValidateValue(ctxt, list);
8900 if (ret != 0) {
8901#ifdef DEBUG_LIST
8903 "Failed to validate value: '%s' with %d rule\n",
8904 ctxt->state->value, nb_values);
8905#endif
8906 break;
8907 }
8908#ifdef DEBUG_LIST
8909 nb_values++;
8910#endif
8911 list = list->next;
8912 }
8913
8914 if ((ret == 0) && (ctxt->state->value != NULL) &&
8915 (ctxt->state->value != ctxt->state->endvalue)) {
8916 VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA,
8917 ctxt->state->value);
8918 ret = -1;
8919 }
8920 xmlFree(val);
8921 ctxt->state->value = oldvalue;
8922 ctxt->state->endvalue = oldend;
8923 break;
8924 }
8925 case XML_RELAXNG_ONEORMORE:
8926 ret = xmlRelaxNGValidateValueList(ctxt, define->content);
8927 if (ret != 0) {
8928 break;
8929 }
8930 /* Falls through. */
8931 case XML_RELAXNG_ZEROORMORE:{
8932 xmlChar *cur, *temp;
8933
8934 if ((ctxt->state->value == NULL) ||
8935 (*ctxt->state->value == 0)) {
8936 ret = 0;
8937 break;
8938 }
8939 oldflags = ctxt->flags;
8940 ctxt->flags |= FLAGS_IGNORABLE;
8941 cur = ctxt->state->value;
8942 temp = NULL;
8943 while ((cur != NULL) && (cur != ctxt->state->endvalue) &&
8944 (temp != cur)) {
8945 temp = cur;
8946 ret =
8947 xmlRelaxNGValidateValueList(ctxt, define->content);
8948 if (ret != 0) {
8949 ctxt->state->value = temp;
8950 ret = 0;
8951 break;
8952 }
8953 cur = ctxt->state->value;
8954 }
8955 ctxt->flags = oldflags;
8956 if (ctxt->errNr > 0)
8957 xmlRelaxNGPopErrors(ctxt, 0);
8958 break;
8959 }
8960 case XML_RELAXNG_OPTIONAL:{
8961 xmlChar *temp;
8962
8963 if ((ctxt->state->value == NULL) ||
8964 (*ctxt->state->value == 0)) {
8965 ret = 0;
8966 break;
8967 }
8968 oldflags = ctxt->flags;
8969 ctxt->flags |= FLAGS_IGNORABLE;
8970 temp = ctxt->state->value;
8971 ret = xmlRelaxNGValidateValue(ctxt, define->content);
8972 ctxt->flags = oldflags;
8973 if (ret != 0) {
8974 ctxt->state->value = temp;
8975 if (ctxt->errNr > 0)
8976 xmlRelaxNGPopErrors(ctxt, 0);
8977 ret = 0;
8978 break;
8979 }
8980 if (ctxt->errNr > 0)
8981 xmlRelaxNGPopErrors(ctxt, 0);
8982 break;
8983 }
8984 case XML_RELAXNG_EXCEPT:{
8985 xmlRelaxNGDefinePtr list;
8986
8987 list = define->content;
8988 while (list != NULL) {
8989 ret = xmlRelaxNGValidateValue(ctxt, list);
8990 if (ret == 0) {
8991 ret = -1;
8992 break;
8993 } else
8994 ret = 0;
8995 list = list->next;
8996 }
8997 break;
8998 }
8999 case XML_RELAXNG_DEF:
9000 case XML_RELAXNG_GROUP:{
9001 xmlRelaxNGDefinePtr list;
9002
9003 list = define->content;
9004 while (list != NULL) {
9005 ret = xmlRelaxNGValidateValue(ctxt, list);
9006 if (ret != 0) {
9007 ret = -1;
9008 break;
9009 } else
9010 ret = 0;
9011 list = list->next;
9012 }
9013 break;
9014 }
9015 case XML_RELAXNG_REF:
9016 case XML_RELAXNG_PARENTREF:
9017 if (define->content == NULL) {
9018 VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
9019 ret = -1;
9020 } else {
9021 ret = xmlRelaxNGValidateValue(ctxt, define->content);
9022 }
9023 break;
9024 default:
9025 TODO ret = -1;
9026 }
9027 return (ret);
9028}
9029
9039static int
9040xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt,
9041 xmlRelaxNGDefinePtr defines)
9042{
9043 int ret = 0;
9044
9045 while (defines != NULL) {
9046 ret = xmlRelaxNGValidateValue(ctxt, defines);
9047 if (ret != 0)
9048 break;
9049 defines = defines->next;
9050 }
9051 return (ret);
9052}
9053
9064static int
9065xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt,
9066 xmlRelaxNGDefinePtr define, xmlAttrPtr prop)
9067{
9068 int ret;
9069
9070 if (define->name != NULL) {
9071 if (!xmlStrEqual(define->name, prop->name))
9072 return (0);
9073 }
9074 if (define->ns != NULL) {
9075 if (define->ns[0] == 0) {
9076 if (prop->ns != NULL)
9077 return (0);
9078 } else {
9079 if ((prop->ns == NULL) ||
9080 (!xmlStrEqual(define->ns, prop->ns->href)))
9081 return (0);
9082 }
9083 }
9084 if (define->nameClass == NULL)
9085 return (1);
9086 define = define->nameClass;
9087 if (define->type == XML_RELAXNG_EXCEPT) {
9088 xmlRelaxNGDefinePtr list;
9089
9090 list = define->content;
9091 while (list != NULL) {
9092 ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);
9093 if (ret == 1)
9094 return (0);
9095 if (ret < 0)
9096 return (ret);
9097 list = list->next;
9098 }
9099 } else if (define->type == XML_RELAXNG_CHOICE) {
9100 xmlRelaxNGDefinePtr list;
9101
9102 list = define->nameClass;
9103 while (list != NULL) {
9104 ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);
9105 if (ret == 1)
9106 return (1);
9107 if (ret < 0)
9108 return (ret);
9109 list = list->next;
9110 }
9111 return (0);
9112 } else {
9113 TODO}
9114 return (1);
9115}
9116
9126static int
9127xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
9128 xmlRelaxNGDefinePtr define)
9129{
9130 int ret = 0, i;
9131 xmlChar *value, *oldvalue;
9132 xmlAttrPtr prop = NULL, tmp;
9133 xmlNodePtr oldseq;
9134
9135 if (ctxt->state->nbAttrLeft <= 0)
9136 return (-1);
9137 if (define->name != NULL) {
9138 for (i = 0; i < ctxt->state->nbAttrs; i++) {
9139 tmp = ctxt->state->attrs[i];
9140 if ((tmp != NULL) && (xmlStrEqual(define->name, tmp->name))) {
9141 if ((((define->ns == NULL) || (define->ns[0] == 0)) &&
9142 (tmp->ns == NULL)) ||
9143 ((tmp->ns != NULL) &&
9144 (xmlStrEqual(define->ns, tmp->ns->href)))) {
9145 prop = tmp;
9146 break;
9147 }
9148 }
9149 }
9150 if (prop != NULL) {
9151 value = xmlNodeListGetString(prop->doc, prop->children, 1);
9152 oldvalue = ctxt->state->value;
9153 oldseq = ctxt->state->seq;
9154 ctxt->state->seq = (xmlNodePtr) prop;
9155 ctxt->state->value = value;
9156 ctxt->state->endvalue = NULL;
9157 ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
9158 if (ctxt->state->value != NULL)
9159 value = ctxt->state->value;
9160 if (value != NULL)
9161 xmlFree(value);
9162 ctxt->state->value = oldvalue;
9163 ctxt->state->seq = oldseq;
9164 if (ret == 0) {
9165 /*
9166 * flag the attribute as processed
9167 */
9168 ctxt->state->attrs[i] = NULL;
9169 ctxt->state->nbAttrLeft--;
9170 }
9171 } else {
9172 ret = -1;
9173 }
9174#ifdef DEBUG
9176 "xmlRelaxNGValidateAttribute(%s): %d\n",
9177 define->name, ret);
9178#endif
9179 } else {
9180 for (i = 0; i < ctxt->state->nbAttrs; i++) {
9181 tmp = ctxt->state->attrs[i];
9182 if ((tmp != NULL) &&
9183 (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) {
9184 prop = tmp;
9185 break;
9186 }
9187 }
9188 if (prop != NULL) {
9189 value = xmlNodeListGetString(prop->doc, prop->children, 1);
9190 oldvalue = ctxt->state->value;
9191 oldseq = ctxt->state->seq;
9192 ctxt->state->seq = (xmlNodePtr) prop;
9193 ctxt->state->value = value;
9194 ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
9195 if (ctxt->state->value != NULL)
9196 value = ctxt->state->value;
9197 if (value != NULL)
9198 xmlFree(value);
9199 ctxt->state->value = oldvalue;
9200 ctxt->state->seq = oldseq;
9201 if (ret == 0) {
9202 /*
9203 * flag the attribute as processed
9204 */
9205 ctxt->state->attrs[i] = NULL;
9206 ctxt->state->nbAttrLeft--;
9207 }
9208 } else {
9209 ret = -1;
9210 }
9211#ifdef DEBUG
9212 if (define->ns != NULL) {
9214 "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",
9215 define->ns, ret);
9216 } else {
9218 "xmlRelaxNGValidateAttribute(anyName): %d\n",
9219 ret);
9220 }
9221#endif
9222 }
9223
9224 return (ret);
9225}
9226
9236static int
9237xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
9238 xmlRelaxNGDefinePtr defines)
9239{
9240 int ret = 0, res;
9241 int needmore = 0;
9242 xmlRelaxNGDefinePtr cur;
9243
9244 cur = defines;
9245 while (cur != NULL) {
9246 if (cur->type == XML_RELAXNG_ATTRIBUTE) {
9247 if (xmlRelaxNGValidateAttribute(ctxt, cur) != 0)
9248 ret = -1;
9249 } else
9250 needmore = 1;
9251 cur = cur->next;
9252 }
9253 if (!needmore)
9254 return (ret);
9255 cur = defines;
9256 while (cur != NULL) {
9257 if (cur->type != XML_RELAXNG_ATTRIBUTE) {
9258 if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
9259 res = xmlRelaxNGValidateDefinition(ctxt, cur);
9260 if (res < 0)
9261 ret = -1;
9262 } else {
9263 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
9264 return (-1);
9265 }
9266 if (res == -1) /* continues on -2 */
9267 break;
9268 }
9269 cur = cur->next;
9270 }
9271
9272 return (ret);
9273}
9274
9284static int
9285xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr * list)
9286{
9287 xmlRelaxNGDefinePtr cur;
9288 int i = 0, tmp;
9289
9290 if ((node == NULL) || (list == NULL))
9291 return (0);
9292
9293 cur = list[i++];
9294 while (cur != NULL) {
9295 if ((node->type == XML_ELEMENT_NODE) &&
9296 (cur->type == XML_RELAXNG_ELEMENT)) {
9297 tmp = xmlRelaxNGElementMatch(NULL, cur, node);
9298 if (tmp == 1)
9299 return (1);
9300 } else if (((node->type == XML_TEXT_NODE) ||
9301 (node->type == XML_CDATA_SECTION_NODE)) &&
9302 ((cur->type == XML_RELAXNG_DATATYPE) ||
9303 (cur->type == XML_RELAXNG_LIST) ||
9304 (cur->type == XML_RELAXNG_TEXT) ||
9305 (cur->type == XML_RELAXNG_VALUE))) {
9306 return (1);
9307 }
9308 cur = list[i++];
9309 }
9310 return (0);
9311}
9312
9322static int
9323xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt,
9324 xmlRelaxNGDefinePtr define)
9325{
9326 int ret = 0, i, nbgroups;
9327 int errNr = ctxt->errNr;
9328 int oldflags;
9329
9330 xmlRelaxNGValidStatePtr oldstate;
9331 xmlRelaxNGPartitionPtr partitions;
9332 xmlRelaxNGInterleaveGroupPtr group = NULL;
9333 xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem;
9334 xmlNodePtr *list = NULL, *lasts = NULL;
9335
9336 if (define->data != NULL) {
9337 partitions = (xmlRelaxNGPartitionPtr) define->data;
9338 nbgroups = partitions->nbgroups;
9339 } else {
9340 VALID_ERR(XML_RELAXNG_ERR_INTERNODATA);
9341 return (-1);
9342 }
9343 /*
9344 * Optimizations for MIXED
9345 */
9346 oldflags = ctxt->flags;
9347 if (define->dflags & IS_MIXED) {
9348 ctxt->flags |= FLAGS_MIXED_CONTENT;
9349 if (nbgroups == 2) {
9350 /*
9351 * this is a pure <mixed> case
9352 */
9353 if (ctxt->state != NULL)
9354 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
9355 ctxt->state->seq);
9356 if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT)
9357 ret = xmlRelaxNGValidateDefinition(ctxt,
9358 partitions->groups[1]->
9359 rule);
9360 else
9361 ret = xmlRelaxNGValidateDefinition(ctxt,
9362 partitions->groups[0]->
9363 rule);
9364 if (ret == 0) {
9365 if (ctxt->state != NULL)
9366 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
9367 ctxt->state->
9368 seq);
9369 }
9370 ctxt->flags = oldflags;
9371 return (ret);
9372 }
9373 }
9374
9375 /*
9376 * Build arrays to store the first and last node of the chain
9377 * pertaining to each group
9378 */
9379 list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
9380 if (list == NULL) {
9381 xmlRngVErrMemory(ctxt, "validating\n");
9382 return (-1);
9383 }
9384 memset(list, 0, nbgroups * sizeof(xmlNodePtr));
9385 lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
9386 if (lasts == NULL) {
9387 xmlRngVErrMemory(ctxt, "validating\n");
9388 return (-1);
9389 }
9390 memset(lasts, 0, nbgroups * sizeof(xmlNodePtr));
9391
9392 /*
9393 * Walk the sequence of children finding the right group and
9394 * sorting them in sequences.
9395 */
9396 cur = ctxt->state->seq;
9397 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
9398 start = cur;
9399 while (cur != NULL) {
9400 ctxt->state->seq = cur;
9401 if ((partitions->triage != NULL) &&
9402 (partitions->flags & IS_DETERMINIST)) {
9403 void *tmp = NULL;
9404
9405 if ((cur->type == XML_TEXT_NODE) ||
9406 (cur->type == XML_CDATA_SECTION_NODE)) {
9407 tmp = xmlHashLookup2(partitions->triage, BAD_CAST "#text",
9408 NULL);
9409 } else if (cur->type == XML_ELEMENT_NODE) {
9410 if (cur->ns != NULL) {
9411 tmp = xmlHashLookup2(partitions->triage, cur->name,
9412 cur->ns->href);
9413 if (tmp == NULL)
9414 tmp = xmlHashLookup2(partitions->triage,
9415 BAD_CAST "#any",
9416 cur->ns->href);
9417 } else
9418 tmp =
9419 xmlHashLookup2(partitions->triage, cur->name,
9420 NULL);
9421 if (tmp == NULL)
9422 tmp =
9423 xmlHashLookup2(partitions->triage, BAD_CAST "#any",
9424 NULL);
9425 }
9426
9427 if (tmp == NULL) {
9428 i = nbgroups;
9429 } else {
9430 i = ((ptrdiff_t) tmp) - 1;
9431 if (partitions->flags & IS_NEEDCHECK) {
9432 group = partitions->groups[i];
9433 if (!xmlRelaxNGNodeMatchesList(cur, group->defs))
9434 i = nbgroups;
9435 }
9436 }
9437 } else {
9438 for (i = 0; i < nbgroups; i++) {
9439 group = partitions->groups[i];
9440 if (group == NULL)
9441 continue;
9442 if (xmlRelaxNGNodeMatchesList(cur, group->defs))
9443 break;
9444 }
9445 }
9446 /*
9447 * We break as soon as an element not matched is found
9448 */
9449 if (i >= nbgroups) {
9450 break;
9451 }
9452 if (lasts[i] != NULL) {
9453 lasts[i]->next = cur;
9454 lasts[i] = cur;
9455 } else {
9456 list[i] = cur;
9457 lasts[i] = cur;
9458 }
9459 if (cur->next != NULL)
9460 lastchg = cur->next;
9461 else
9462 lastchg = cur;
9463 cur = xmlRelaxNGSkipIgnored(ctxt, cur->next);
9464 }
9465 if (ret != 0) {
9466 VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
9467 ret = -1;
9468 goto done;
9469 }
9470 lastelem = cur;
9471 oldstate = ctxt->state;
9472 for (i = 0; i < nbgroups; i++) {
9473 ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate);
9474 if (ctxt->state == NULL) {
9475 ret = -1;
9476 break;
9477 }
9478 group = partitions->groups[i];
9479 if (lasts[i] != NULL) {
9480 last = lasts[i]->next;
9481 lasts[i]->next = NULL;
9482 }
9483 ctxt->state->seq = list[i];
9484 ret = xmlRelaxNGValidateDefinition(ctxt, group->rule);
9485 if (ret != 0)
9486 break;
9487 if (ctxt->state != NULL) {
9488 cur = ctxt->state->seq;
9489 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
9490 xmlRelaxNGFreeValidState(ctxt, oldstate);
9491 oldstate = ctxt->state;
9492 ctxt->state = NULL;
9493 if (cur != NULL
9494 /* there's a nasty violation of context-free unambiguities,
9495 since in open-name-class context, interleave in the
9496 production shall finish without caring about anything
9497 else that is OK to follow in that case -- it would
9498 otherwise get marked as "extra content" and would
9499 hence fail the validation, hence this perhaps
9500 dirty attempt to rectify such a situation */
9501 && (define->parent->type != XML_RELAXNG_DEF
9502 || !xmlStrEqual(define->parent->name,
9503 (const xmlChar *) "open-name-class"))) {
9504 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
9505 ret = -1;
9506 ctxt->state = oldstate;
9507 goto done;
9508 }
9509 } else if (ctxt->states != NULL) {
9510 int j;
9511 int found = 0;
9512 int best = -1;
9513 int lowattr = -1;
9514
9515 /*
9516 * PBM: what happen if there is attributes checks in the interleaves
9517 */
9518
9519 for (j = 0; j < ctxt->states->nbState; j++) {
9520 cur = ctxt->states->tabState[j]->seq;
9521 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
9522 if (cur == NULL) {
9523 if (found == 0) {
9524 lowattr = ctxt->states->tabState[j]->nbAttrLeft;
9525 best = j;
9526 }
9527 found = 1;
9528 if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) {
9529 /* try to keep the latest one to mach old heuristic */
9530 lowattr = ctxt->states->tabState[j]->nbAttrLeft;
9531 best = j;
9532 }
9533 if (lowattr == 0)
9534 break;
9535 } else if (found == 0) {
9536 if (lowattr == -1) {
9537 lowattr = ctxt->states->tabState[j]->nbAttrLeft;
9538 best = j;
9539 } else
9540 if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) {
9541 /* try to keep the latest one to mach old heuristic */
9542 lowattr = ctxt->states->tabState[j]->nbAttrLeft;
9543 best = j;
9544 }
9545 }
9546 }
9547 /*
9548 * BIG PBM: here we pick only one restarting point :-(
9549 */
9550 if (ctxt->states->nbState > 0) {
9551 xmlRelaxNGFreeValidState(ctxt, oldstate);
9552 if (best != -1) {
9553 oldstate = ctxt->states->tabState[best];
9554 ctxt->states->tabState[best] = NULL;
9555 } else {
9556 oldstate =
9557 ctxt->states->tabState[ctxt->states->nbState - 1];
9558 ctxt->states->tabState[ctxt->states->nbState - 1] = NULL;
9559 ctxt->states->nbState--;
9560 }
9561 }
9562 for (j = 0; j < ctxt->states->nbState ; j++) {
9563 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[j]);
9564 }
9565 xmlRelaxNGFreeStates(ctxt, ctxt->states);
9566 ctxt->states = NULL;
9567 if (found == 0) {
9568 if (cur == NULL) {
9569 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA,
9570 (const xmlChar *) "noname");
9571 } else {
9572 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
9573 }
9574 ret = -1;
9575 ctxt->state = oldstate;
9576 goto done;
9577 }
9578 } else {
9579 ret = -1;
9580 break;
9581 }
9582 if (lasts[i] != NULL) {
9583 lasts[i]->next = last;
9584 }
9585 }
9586 if (ctxt->state != NULL)
9587 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
9588 ctxt->state = oldstate;
9589 ctxt->state->seq = lastelem;
9590 if (ret != 0) {
9591 VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
9592 ret = -1;
9593 goto done;
9594 }
9595
9596 done:
9597 ctxt->flags = oldflags;
9598 /*
9599 * builds the next links chain from the prev one
9600 */
9601 cur = lastchg;
9602 while (cur != NULL) {
9603 if ((cur == start) || (cur->prev == NULL))
9604 break;
9605 cur->prev->next = cur;
9606 cur = cur->prev;
9607 }
9608 if (ret == 0) {
9609 if (ctxt->errNr > errNr)
9610 xmlRelaxNGPopErrors(ctxt, errNr);
9611 }
9612
9613 xmlFree(list);
9614 xmlFree(lasts);
9615 return (ret);
9616}
9617
9627static int
9628xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt,
9629 xmlRelaxNGDefinePtr defines)
9630{
9631 int ret = 0, res;
9632
9633
9634 if (defines == NULL) {
9635 VALID_ERR2(XML_RELAXNG_ERR_INTERNAL,
9636 BAD_CAST "NULL definition list");
9637 return (-1);
9638 }
9639 while (defines != NULL) {
9640 if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
9641 res = xmlRelaxNGValidateDefinition(ctxt, defines);
9642 if (res < 0)
9643 ret = -1;
9644 } else {
9645 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
9646 return (-1);
9647 }
9648 if (res == -1) /* continues on -2 */
9649 break;
9650 defines = defines->next;
9651 }
9652
9653 return (ret);
9654}
9655
9666static int
9667xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
9668 xmlRelaxNGDefinePtr define, xmlNodePtr elem)
9669{
9670 int ret = 0, oldflags = 0;
9671
9672 if (define->name != NULL) {
9673 if (!xmlStrEqual(elem->name, define->name)) {
9674 VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name);
9675 return (0);
9676 }
9677 }
9678 if ((define->ns != NULL) && (define->ns[0] != 0)) {
9679 if (elem->ns == NULL) {
9680 VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name);
9681 return (0);
9682 } else if (!xmlStrEqual(elem->ns->href, define->ns)) {
9683 VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS,
9684 elem->name, define->ns);
9685 return (0);
9686 }
9687 } else if ((elem->ns != NULL) && (define->ns != NULL) &&
9688 (define->name == NULL)) {
9689 VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name);
9690 return (0);
9691 } else if ((elem->ns != NULL) && (define->name != NULL)) {
9692 VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name);
9693 return (0);
9694 }
9695
9696 if (define->nameClass == NULL)
9697 return (1);
9698
9699 define = define->nameClass;
9700 if (define->type == XML_RELAXNG_EXCEPT) {
9701 xmlRelaxNGDefinePtr list;
9702
9703 if (ctxt != NULL) {
9704 oldflags = ctxt->flags;
9705 ctxt->flags |= FLAGS_IGNORABLE;
9706 }
9707
9708 list = define->content;
9709 while (list != NULL) {
9710 ret = xmlRelaxNGElementMatch(ctxt, list, elem);
9711 if (ret == 1) {
9712 if (ctxt != NULL)
9713 ctxt->flags = oldflags;
9714 return (0);
9715 }
9716 if (ret < 0) {
9717 if (ctxt != NULL)
9718 ctxt->flags = oldflags;
9719 return (ret);
9720 }
9721 list = list->next;
9722 }
9723 ret = 1;
9724 if (ctxt != NULL) {
9725 ctxt->flags = oldflags;
9726 }
9727 } else if (define->type == XML_RELAXNG_CHOICE) {
9728 xmlRelaxNGDefinePtr list;
9729
9730 if (ctxt != NULL) {
9731 oldflags = ctxt->flags;
9732 ctxt->flags |= FLAGS_IGNORABLE;
9733 }
9734
9735 list = define->nameClass;
9736 while (list != NULL) {
9737 ret = xmlRelaxNGElementMatch(ctxt, list, elem);
9738 if (ret == 1) {
9739 if (ctxt != NULL)
9740 ctxt->flags = oldflags;
9741 return (1);
9742 }
9743 if (ret < 0) {
9744 if (ctxt != NULL)
9745 ctxt->flags = oldflags;
9746 return (ret);
9747 }
9748 list = list->next;
9749 }
9750 if (ctxt != NULL) {
9751 if (ret != 0) {
9752 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9753 xmlRelaxNGDumpValidError(ctxt);
9754 } else {
9755 if (ctxt->errNr > 0)
9756 xmlRelaxNGPopErrors(ctxt, 0);
9757 }
9758 }
9759 ret = 0;
9760 if (ctxt != NULL) {
9761 ctxt->flags = oldflags;
9762 }
9763 } else {
9764 TODO ret = -1;
9765 }
9766 return (ret);
9767}
9768
9780static int
9781xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt)
9782{
9783 xmlRelaxNGValidStatePtr state;
9784 int i, tmp;
9785 int best = -1;
9786 int value = 1000000;
9787
9788 if ((ctxt == NULL) || (ctxt->states == NULL) ||
9789 (ctxt->states->nbState <= 0))
9790 return (-1);
9791
9792 for (i = 0; i < ctxt->states->nbState; i++) {
9793 state = ctxt->states->tabState[i];
9794 if (state == NULL)
9795 continue;
9796 if (state->seq != NULL) {
9797 if ((best == -1) || (value > 100000)) {
9798 value = 100000;
9799 best = i;
9800 }
9801 } else {
9802 tmp = state->nbAttrLeft;
9803 if ((best == -1) || (value > tmp)) {
9804 value = tmp;
9805 best = i;
9806 }
9807 }
9808 }
9809 return (best);
9810}
9811
9819static void
9820xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt)
9821{
9822 int best;
9823
9824 if ((ctxt == NULL) || (ctxt->states == NULL) ||
9825 (ctxt->states->nbState <= 0))
9826 return;
9827
9828 best = xmlRelaxNGBestState(ctxt);
9829 if ((best >= 0) && (best < ctxt->states->nbState)) {
9830 ctxt->state = ctxt->states->tabState[best];
9831
9832 xmlRelaxNGValidateElementEnd(ctxt, 1);
9833 }
9834}
9835
9847static int
9848xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int dolog)
9849{
9850 int i;
9851 xmlRelaxNGValidStatePtr state;
9852
9853 state = ctxt->state;
9854 if (state->seq != NULL) {
9855 state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq);
9856 if (state->seq != NULL) {
9857 if (dolog) {
9858 VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT,
9859 state->node->name, state->seq->name);
9860 }
9861 return (-1);
9862 }
9863 }
9864 for (i = 0; i < state->nbAttrs; i++) {
9865 if (state->attrs[i] != NULL) {
9866 if (dolog) {
9867 VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR,
9868 state->attrs[i]->name, state->node->name);
9869 }
9870 return (-1 - i);
9871 }
9872 }
9873 return (0);
9874}
9875
9885static int
9886xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
9887 xmlRelaxNGDefinePtr define)
9888{
9890 int ret = 0, i, tmp, oldflags, errNr;
9891 xmlRelaxNGValidStatePtr oldstate = NULL, state;
9892
9893 if (define == NULL) {
9894 VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
9895 return (-1);
9896 }
9897
9898 if (ctxt->state != NULL) {
9899 node = ctxt->state->seq;
9900 } else {
9901 node = NULL;
9902 }
9903#ifdef DEBUG
9904 for (i = 0; i < ctxt->depth; i++)
9907 "Start validating %s ", xmlRelaxNGDefName(define));
9908 if (define->name != NULL)
9910 if ((node != NULL) && (node->name != NULL))
9911 xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name);
9912 else
9914#endif
9915 ctxt->depth++;
9916 switch (define->type) {
9917 case XML_RELAXNG_EMPTY:
9918 ret = 0;
9919 break;
9920 case XML_RELAXNG_NOT_ALLOWED:
9921 ret = -1;
9922 break;
9923 case XML_RELAXNG_TEXT:
9924 while ((node != NULL) &&
9925 ((node->type == XML_TEXT_NODE) ||
9926 (node->type == XML_COMMENT_NODE) ||
9927 (node->type == XML_PI_NODE) ||
9928 (node->type == XML_CDATA_SECTION_NODE)))
9929 node = node->next;
9930 ctxt->state->seq = node;
9931 break;
9932 case XML_RELAXNG_ELEMENT:
9933 errNr = ctxt->errNr;
9934 node = xmlRelaxNGSkipIgnored(ctxt, node);
9935 if (node == NULL) {
9936 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name);
9937 ret = -1;
9938 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9939 xmlRelaxNGDumpValidError(ctxt);
9940 break;
9941 }
9942 if (node->type != XML_ELEMENT_NODE) {
9943 VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
9944 ret = -1;
9945 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9946 xmlRelaxNGDumpValidError(ctxt);
9947 break;
9948 }
9949 /*
9950 * This node was already validated successfully against
9951 * this definition.
9952 */
9953 if (node->psvi == define) {
9954 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
9955 if (ctxt->errNr > errNr)
9956 xmlRelaxNGPopErrors(ctxt, errNr);
9957 if (ctxt->errNr != 0) {
9958 while ((ctxt->err != NULL) &&
9959 (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME)
9960 && (xmlStrEqual(ctxt->err->arg2, node->name)))
9961 ||
9962 ((ctxt->err->err ==
9963 XML_RELAXNG_ERR_ELEMEXTRANS)
9964 && (xmlStrEqual(ctxt->err->arg1, node->name)))
9965 || (ctxt->err->err == XML_RELAXNG_ERR_NOELEM)
9966 || (ctxt->err->err ==
9967 XML_RELAXNG_ERR_NOTELEM)))
9968 xmlRelaxNGValidErrorPop(ctxt);
9969 }
9970 break;
9971 }
9972
9973 ret = xmlRelaxNGElementMatch(ctxt, define, node);
9974 if (ret <= 0) {
9975 ret = -1;
9976 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9977 xmlRelaxNGDumpValidError(ctxt);
9978 break;
9979 }
9980 ret = 0;
9981 if (ctxt->errNr != 0) {
9982 if (ctxt->errNr > errNr)
9983 xmlRelaxNGPopErrors(ctxt, errNr);
9984 while ((ctxt->err != NULL) &&
9985 (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) &&
9986 (xmlStrEqual(ctxt->err->arg2, node->name))) ||
9987 ((ctxt->err->err == XML_RELAXNG_ERR_ELEMEXTRANS) &&
9988 (xmlStrEqual(ctxt->err->arg1, node->name))) ||
9989 (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) ||
9990 (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM)))
9991 xmlRelaxNGValidErrorPop(ctxt);
9992 }
9993 errNr = ctxt->errNr;
9994
9995 oldflags = ctxt->flags;
9996 if (ctxt->flags & FLAGS_MIXED_CONTENT) {
9997 ctxt->flags -= FLAGS_MIXED_CONTENT;
9998 }
9999 state = xmlRelaxNGNewValidState(ctxt, node);
10000 if (state == NULL) {
10001 ret = -1;
10002 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
10003 xmlRelaxNGDumpValidError(ctxt);
10004 break;
10005 }
10006
10007 oldstate = ctxt->state;
10008 ctxt->state = state;
10009 if (define->attrs != NULL) {
10010 tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
10011 if (tmp != 0) {
10012 ret = -1;
10013 VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
10014 }
10015 }
10016 if (define->contModel != NULL) {
10017 xmlRelaxNGValidStatePtr nstate, tmpstate = ctxt->state;
10018 xmlRelaxNGStatesPtr tmpstates = ctxt->states;
10019 xmlNodePtr nseq;
10020
10021 nstate = xmlRelaxNGNewValidState(ctxt, node);
10022 ctxt->state = nstate;
10023 ctxt->states = NULL;
10024
10025 tmp = xmlRelaxNGValidateCompiledContent(ctxt,
10026 define->contModel,
10027 ctxt->state->seq);
10028 nseq = ctxt->state->seq;
10029 ctxt->state = tmpstate;
10030 ctxt->states = tmpstates;
10031 xmlRelaxNGFreeValidState(ctxt, nstate);
10032
10033#ifdef DEBUG_COMPILE
10035 "Validating content of '%s' : %d\n",
10036 define->name, tmp);
10037#endif
10038 if (tmp != 0)
10039 ret = -1;
10040
10041 if (ctxt->states != NULL) {
10042 tmp = -1;
10043
10044 for (i = 0; i < ctxt->states->nbState; i++) {
10045 state = ctxt->states->tabState[i];
10046 ctxt->state = state;
10047 ctxt->state->seq = nseq;
10048
10049 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
10050 tmp = 0;
10051 break;
10052 }
10053 }
10054 if (tmp != 0) {
10055 /*
10056 * validation error, log the message for the "best" one
10057 */
10058 ctxt->flags |= FLAGS_IGNORABLE;
10059 xmlRelaxNGLogBestError(ctxt);
10060 }
10061 for (i = 0; i < ctxt->states->nbState; i++) {
10062 xmlRelaxNGFreeValidState(ctxt,
10063 ctxt->states->
10064 tabState[i]);
10065 }
10066 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10067 ctxt->flags = oldflags;
10068 ctxt->states = NULL;
10069 if ((ret == 0) && (tmp == -1))
10070 ret = -1;
10071 } else {
10072 state = ctxt->state;
10073 if (ctxt->state != NULL)
10074 ctxt->state->seq = nseq;
10075 if (ret == 0)
10076 ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
10077 xmlRelaxNGFreeValidState(ctxt, state);
10078 }
10079 } else {
10080 if (define->content != NULL) {
10081 tmp = xmlRelaxNGValidateDefinitionList(ctxt,
10082 define->
10083 content);
10084 if (tmp != 0) {
10085 ret = -1;
10086 if (ctxt->state == NULL) {
10087 ctxt->state = oldstate;
10088 VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
10089 node->name);
10090 ctxt->state = NULL;
10091 } else {
10092 VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
10093 node->name);
10094 }
10095
10096 }
10097 }
10098 if (ctxt->states != NULL) {
10099 tmp = -1;
10100
10101 for (i = 0; i < ctxt->states->nbState; i++) {
10102 state = ctxt->states->tabState[i];
10103 ctxt->state = state;
10104
10105 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
10106 tmp = 0;
10107 break;
10108 }
10109 }
10110 if (tmp != 0) {
10111 /*
10112 * validation error, log the message for the "best" one
10113 */
10114 ctxt->flags |= FLAGS_IGNORABLE;
10115 xmlRelaxNGLogBestError(ctxt);
10116 }
10117 for (i = 0; i < ctxt->states->nbState; i++) {
10118 xmlRelaxNGFreeValidState(ctxt,
10119 ctxt->states->tabState[i]);
10120 ctxt->states->tabState[i] = NULL;
10121 }
10122 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10123 ctxt->flags = oldflags;
10124 ctxt->states = NULL;
10125 if ((ret == 0) && (tmp == -1))
10126 ret = -1;
10127 } else {
10128 state = ctxt->state;
10129 if (ret == 0)
10130 ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
10131 xmlRelaxNGFreeValidState(ctxt, state);
10132 }
10133 }
10134 if (ret == 0) {
10135 node->psvi = define;
10136 }
10137 ctxt->flags = oldflags;
10138 ctxt->state = oldstate;
10139 if (oldstate != NULL)
10140 oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
10141 if (ret != 0) {
10142 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
10143 xmlRelaxNGDumpValidError(ctxt);
10144 ret = 0;
10145#if 0
10146 } else {
10147 ret = -2;
10148#endif
10149 }
10150 } else {
10151 if (ctxt->errNr > errNr)
10152 xmlRelaxNGPopErrors(ctxt, errNr);
10153 }
10154
10155#ifdef DEBUG
10157 "xmlRelaxNGValidateDefinition(): validated %s : %d",
10158 node->name, ret);
10159 if (oldstate == NULL)
10160 xmlGenericError(xmlGenericErrorContext, ": no state\n");
10161 else if (oldstate->seq == NULL)
10163 else if (oldstate->seq->type == XML_ELEMENT_NODE)
10164 xmlGenericError(xmlGenericErrorContext, ": next elem %s\n",
10165 oldstate->seq->name);
10166 else
10167 xmlGenericError(xmlGenericErrorContext, ": next %s %d\n",
10168 oldstate->seq->name, oldstate->seq->type);
10169#endif
10170 break;
10171 case XML_RELAXNG_OPTIONAL:{
10172 errNr = ctxt->errNr;
10173 oldflags = ctxt->flags;
10174 ctxt->flags |= FLAGS_IGNORABLE;
10175 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
10176 ret =
10177 xmlRelaxNGValidateDefinitionList(ctxt,
10178 define->content);
10179 if (ret != 0) {
10180 if (ctxt->state != NULL)
10181 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10182 ctxt->state = oldstate;
10183 ctxt->flags = oldflags;
10184 ret = 0;
10185 if (ctxt->errNr > errNr)
10186 xmlRelaxNGPopErrors(ctxt, errNr);
10187 break;
10188 }
10189 if (ctxt->states != NULL) {
10190 xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
10191 } else {
10192 ctxt->states = xmlRelaxNGNewStates(ctxt, 1);
10193 if (ctxt->states == NULL) {
10194 xmlRelaxNGFreeValidState(ctxt, oldstate);
10195 ctxt->flags = oldflags;
10196 ret = -1;
10197 if (ctxt->errNr > errNr)
10198 xmlRelaxNGPopErrors(ctxt, errNr);
10199 break;
10200 }
10201 xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
10202 xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state);
10203 ctxt->state = NULL;
10204 }
10205 ctxt->flags = oldflags;
10206 ret = 0;
10207 if (ctxt->errNr > errNr)
10208 xmlRelaxNGPopErrors(ctxt, errNr);
10209 break;
10210 }
10211 case XML_RELAXNG_ONEORMORE:
10212 errNr = ctxt->errNr;
10213 ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
10214 if (ret != 0) {
10215 break;
10216 }
10217 if (ctxt->errNr > errNr)
10218 xmlRelaxNGPopErrors(ctxt, errNr);
10219 /* Falls through. */
10220 case XML_RELAXNG_ZEROORMORE:{
10221 int progress;
10222 xmlRelaxNGStatesPtr states = NULL, res = NULL;
10223 int base, j;
10224
10225 errNr = ctxt->errNr;
10226 res = xmlRelaxNGNewStates(ctxt, 1);
10227 if (res == NULL) {
10228 ret = -1;
10229 break;
10230 }
10231 /*
10232 * All the input states are also exit states
10233 */
10234 if (ctxt->state != NULL) {
10235 xmlRelaxNGAddStates(ctxt, res,
10236 xmlRelaxNGCopyValidState(ctxt,
10237 ctxt->
10238 state));
10239 } else {
10240 for (j = 0; j < ctxt->states->nbState; j++) {
10241 xmlRelaxNGAddStates(ctxt, res,
10242 xmlRelaxNGCopyValidState(ctxt,
10243 ctxt->states->tabState[j]));
10244 }
10245 }
10246 oldflags = ctxt->flags;
10247 ctxt->flags |= FLAGS_IGNORABLE;
10248 do {
10249 progress = 0;
10250 base = res->nbState;
10251
10252 if (ctxt->states != NULL) {
10253 states = ctxt->states;
10254 for (i = 0; i < states->nbState; i++) {
10255 ctxt->state = states->tabState[i];
10256 ctxt->states = NULL;
10257 ret = xmlRelaxNGValidateDefinitionList(ctxt,
10258 define->
10259 content);
10260 if (ret == 0) {
10261 if (ctxt->state != NULL) {
10262 tmp = xmlRelaxNGAddStates(ctxt, res,
10263 ctxt->state);
10264 ctxt->state = NULL;
10265 if (tmp == 1)
10266 progress = 1;
10267 } else if (ctxt->states != NULL) {
10268 for (j = 0; j < ctxt->states->nbState;
10269 j++) {
10270 tmp =
10271 xmlRelaxNGAddStates(ctxt, res,
10272 ctxt->states->tabState[j]);
10273 if (tmp == 1)
10274 progress = 1;
10275 }
10276 xmlRelaxNGFreeStates(ctxt,
10277 ctxt->states);
10278 ctxt->states = NULL;
10279 }
10280 } else {
10281 if (ctxt->state != NULL) {
10282 xmlRelaxNGFreeValidState(ctxt,
10283 ctxt->state);
10284 ctxt->state = NULL;
10285 }
10286 }
10287 }
10288 } else {
10289 ret = xmlRelaxNGValidateDefinitionList(ctxt,
10290 define->
10291 content);
10292 if (ret != 0) {
10293 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10294 ctxt->state = NULL;
10295 } else {
10296 base = res->nbState;
10297 if (ctxt->state != NULL) {
10298 tmp = xmlRelaxNGAddStates(ctxt, res,
10299 ctxt->state);
10300 ctxt->state = NULL;
10301 if (tmp == 1)
10302 progress = 1;
10303 } else if (ctxt->states != NULL) {
10304 for (j = 0; j < ctxt->states->nbState; j++) {
10305 tmp = xmlRelaxNGAddStates(ctxt, res,
10306 ctxt->states->tabState[j]);
10307 if (tmp == 1)
10308 progress = 1;
10309 }
10310 if (states == NULL) {
10311 states = ctxt->states;
10312 } else {
10313 xmlRelaxNGFreeStates(ctxt,
10314 ctxt->states);
10315 }
10316 ctxt->states = NULL;
10317 }
10318 }
10319 }
10320 if (progress) {
10321 /*
10322 * Collect all the new nodes added at that step
10323 * and make them the new node set
10324 */
10325 if (res->nbState - base == 1) {
10326 ctxt->state = xmlRelaxNGCopyValidState(ctxt,
10327 res->
10328 tabState
10329 [base]);
10330 } else {
10331 if (states == NULL) {
10332 xmlRelaxNGNewStates(ctxt,
10333 res->nbState - base);
10334 states = ctxt->states;
10335 if (states == NULL) {
10336 progress = 0;
10337 break;
10338 }
10339 }
10340 states->nbState = 0;
10341 for (i = base; i < res->nbState; i++)
10342 xmlRelaxNGAddStates(ctxt, states,
10343 xmlRelaxNGCopyValidState
10344 (ctxt, res->tabState[i]));
10345 ctxt->states = states;
10346 }
10347 }
10348 } while (progress == 1);
10349 if (states != NULL) {
10350 xmlRelaxNGFreeStates(ctxt, states);
10351 }
10352 ctxt->states = res;
10353 ctxt->flags = oldflags;
10354#if 0
10355 /*
10356 * errors may have to be propagated back...
10357 */
10358 if (ctxt->errNr > errNr)
10359 xmlRelaxNGPopErrors(ctxt, errNr);
10360#endif
10361 ret = 0;
10362 break;
10363 }
10364 case XML_RELAXNG_CHOICE:{
10365 xmlRelaxNGDefinePtr list = NULL;
10366 xmlRelaxNGStatesPtr states = NULL;
10367
10368 node = xmlRelaxNGSkipIgnored(ctxt, node);
10369
10370 errNr = ctxt->errNr;
10371 if ((define->dflags & IS_TRIABLE) && (define->data != NULL) &&
10372 (node != NULL)) {
10373 /*
10374 * node == NULL can't be optimized since IS_TRIABLE
10375 * doesn't account for choice which may lead to
10376 * only attributes.
10377 */
10378 xmlHashTablePtr triage =
10379 (xmlHashTablePtr) define->data;
10380
10381 /*
10382 * Something we can optimize cleanly there is only one
10383 * possible branch out !
10384 */
10385 if ((node->type == XML_TEXT_NODE) ||
10386 (node->type == XML_CDATA_SECTION_NODE)) {
10387 list =
10388 xmlHashLookup2(triage, BAD_CAST "#text", NULL);
10389 } else if (node->type == XML_ELEMENT_NODE) {
10390 if (node->ns != NULL) {
10391 list = xmlHashLookup2(triage, node->name,
10392 node->ns->href);
10393 if (list == NULL)
10394 list =
10395 xmlHashLookup2(triage, BAD_CAST "#any",
10396 node->ns->href);
10397 } else
10398 list =
10399 xmlHashLookup2(triage, node->name, NULL);
10400 if (list == NULL)
10401 list =
10402 xmlHashLookup2(triage, BAD_CAST "#any",
10403 NULL);
10404 }
10405 if (list == NULL) {
10406 ret = -1;
10407 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, node->name);
10408 break;
10409 }
10410 ret = xmlRelaxNGValidateDefinition(ctxt, list);
10411 if (ret == 0) {
10412 }
10413 break;
10414 }
10415
10416 list = define->content;
10417 oldflags = ctxt->flags;
10418 ctxt->flags |= FLAGS_IGNORABLE;
10419
10420 while (list != NULL) {
10421 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
10422 ret = xmlRelaxNGValidateDefinition(ctxt, list);
10423 if (ret == 0) {
10424 if (states == NULL) {
10425 states = xmlRelaxNGNewStates(ctxt, 1);
10426 }
10427 if (ctxt->state != NULL) {
10428 xmlRelaxNGAddStates(ctxt, states, ctxt->state);
10429 } else if (ctxt->states != NULL) {
10430 for (i = 0; i < ctxt->states->nbState; i++) {
10431 xmlRelaxNGAddStates(ctxt, states,
10432 ctxt->states->
10433 tabState[i]);
10434 }
10435 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10436 ctxt->states = NULL;
10437 }
10438 } else {
10439 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10440 }
10441 ctxt->state = oldstate;
10442 list = list->next;
10443 }
10444 if (states != NULL) {
10445 xmlRelaxNGFreeValidState(ctxt, oldstate);
10446 ctxt->states = states;
10447 ctxt->state = NULL;
10448 ret = 0;
10449 } else {
10450 ctxt->states = NULL;
10451 }
10452 ctxt->flags = oldflags;
10453 if (ret != 0) {
10454 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
10455 xmlRelaxNGDumpValidError(ctxt);
10456 }
10457 } else {
10458 if (ctxt->errNr > errNr)
10459 xmlRelaxNGPopErrors(ctxt, errNr);
10460 }
10461 break;
10462 }
10463 case XML_RELAXNG_DEF:
10464 case XML_RELAXNG_GROUP:
10465 ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
10466 break;
10467 case XML_RELAXNG_INTERLEAVE:
10468 ret = xmlRelaxNGValidateInterleave(ctxt, define);
10469 break;
10470 case XML_RELAXNG_ATTRIBUTE:
10471 ret = xmlRelaxNGValidateAttribute(ctxt, define);
10472 break;
10473 case XML_RELAXNG_START:
10474 case XML_RELAXNG_NOOP:
10475 case XML_RELAXNG_REF:
10476 case XML_RELAXNG_EXTERNALREF:
10477 case XML_RELAXNG_PARENTREF:
10478 ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
10479 break;
10480 case XML_RELAXNG_DATATYPE:{
10482 xmlChar *content = NULL;
10483
10484 child = node;
10485 while (child != NULL) {
10486 if (child->type == XML_ELEMENT_NODE) {
10487 VALID_ERR2(XML_RELAXNG_ERR_DATAELEM,
10488 node->parent->name);
10489 ret = -1;
10490 break;
10491 } else if ((child->type == XML_TEXT_NODE) ||
10492 (child->type == XML_CDATA_SECTION_NODE)) {
10493 content = xmlStrcat(content, child->content);
10494 }
10495 /* TODO: handle entities ... */
10496 child = child->next;
10497 }
10498 if (ret == -1) {
10499 if (content != NULL)
10501 break;
10502 }
10503 if (content == NULL) {
10505 if (content == NULL) {
10506 xmlRngVErrMemory(ctxt, "validating\n");
10507 ret = -1;
10508 break;
10509 }
10510 }
10511 ret = xmlRelaxNGValidateDatatype(ctxt, content, define,
10512 ctxt->state->seq);
10513 if (ret == -1) {
10514 VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name);
10515 } else if (ret == 0) {
10516 ctxt->state->seq = NULL;
10517 }
10518 if (content != NULL)
10520 break;
10521 }
10522 case XML_RELAXNG_VALUE:{
10523 xmlChar *content = NULL;
10524 xmlChar *oldvalue;
10526
10527 child = node;
10528 while (child != NULL) {
10529 if (child->type == XML_ELEMENT_NODE) {
10530 VALID_ERR2(XML_RELAXNG_ERR_VALELEM,
10531 node->parent->name);
10532 ret = -1;
10533 break;
10534 } else if ((child->type == XML_TEXT_NODE) ||
10535 (child->type == XML_CDATA_SECTION_NODE)) {
10536 content = xmlStrcat(content, child->content);
10537 }
10538 /* TODO: handle entities ... */
10539 child = child->next;
10540 }
10541 if (ret == -1) {
10542 if (content != NULL)
10544 break;
10545 }
10546 if (content == NULL) {
10548 if (content == NULL) {
10549 xmlRngVErrMemory(ctxt, "validating\n");
10550 ret = -1;
10551 break;
10552 }
10553 }
10554 oldvalue = ctxt->state->value;
10555 ctxt->state->value = content;
10556 ret = xmlRelaxNGValidateValue(ctxt, define);
10557 ctxt->state->value = oldvalue;
10558 if (ret == -1) {
10559 VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name);
10560 } else if (ret == 0) {
10561 ctxt->state->seq = NULL;
10562 }
10563 if (content != NULL)
10565 break;
10566 }
10567 case XML_RELAXNG_LIST:{
10570 xmlChar *oldvalue, *oldendvalue;
10571 int len;
10572
10573 /*
10574 * Make sure it's only text nodes
10575 */
10576
10577 content = NULL;
10578 child = node;
10579 while (child != NULL) {
10580 if (child->type == XML_ELEMENT_NODE) {
10581 VALID_ERR2(XML_RELAXNG_ERR_LISTELEM,
10582 node->parent->name);
10583 ret = -1;
10584 break;
10585 } else if ((child->type == XML_TEXT_NODE) ||
10586 (child->type == XML_CDATA_SECTION_NODE)) {
10587 content = xmlStrcat(content, child->content);
10588 }
10589 /* TODO: handle entities ... */
10590 child = child->next;
10591 }
10592 if (ret == -1) {
10593 if (content != NULL)
10595 break;
10596 }
10597 if (content == NULL) {
10599 if (content == NULL) {
10600 xmlRngVErrMemory(ctxt, "validating\n");
10601 ret = -1;
10602 break;
10603 }
10604 }
10606 oldvalue = ctxt->state->value;
10607 oldendvalue = ctxt->state->endvalue;
10608 ctxt->state->value = content;
10609 ctxt->state->endvalue = content + len;
10610 ret = xmlRelaxNGValidateValue(ctxt, define);
10611 ctxt->state->value = oldvalue;
10612 ctxt->state->endvalue = oldendvalue;
10613 if (ret == -1) {
10614 VALID_ERR(XML_RELAXNG_ERR_LIST);
10615 } else if ((ret == 0) && (node != NULL)) {
10616 ctxt->state->seq = node->next;
10617 }
10618 if (content != NULL)
10620 break;
10621 }
10622 case XML_RELAXNG_EXCEPT:
10623 case XML_RELAXNG_PARAM:
10624 TODO ret = -1;
10625 break;
10626 }
10627 ctxt->depth--;
10628#ifdef DEBUG
10629 for (i = 0; i < ctxt->depth; i++)
10632 "Validating %s ", xmlRelaxNGDefName(define));
10633 if (define->name != NULL)
10635 if (ret == 0)
10637 else
10639#endif
10640 return (ret);
10641}
10642
10652static int
10653xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
10654 xmlRelaxNGDefinePtr define)
10655{
10656 xmlRelaxNGStatesPtr states, res;
10657 int i, j, k, ret, oldflags;
10658
10659 /*
10660 * We should NOT have both ctxt->state and ctxt->states
10661 */
10662 if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
10663 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10664 ctxt->state = NULL;
10665 }
10666
10667 if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) {
10668 if (ctxt->states != NULL) {
10669 ctxt->state = ctxt->states->tabState[0];
10670 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10671 ctxt->states = NULL;
10672 }
10673 ret = xmlRelaxNGValidateState(ctxt, define);
10674 if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
10675 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10676 ctxt->state = NULL;
10677 }
10678 if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) {
10679 ctxt->state = ctxt->states->tabState[0];
10680 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10681 ctxt->states = NULL;
10682 }
10683 return (ret);
10684 }
10685
10686 states = ctxt->states;
10687 ctxt->states = NULL;
10688 res = NULL;
10689 j = 0;
10690 oldflags = ctxt->flags;
10691 ctxt->flags |= FLAGS_IGNORABLE;
10692 for (i = 0; i < states->nbState; i++) {
10693 ctxt->state = states->tabState[i];
10694 ctxt->states = NULL;
10695 ret = xmlRelaxNGValidateState(ctxt, define);
10696 /*
10697 * We should NOT have both ctxt->state and ctxt->states
10698 */
10699 if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
10700 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10701 ctxt->state = NULL;
10702 }
10703 if (ret == 0) {
10704 if (ctxt->states == NULL) {
10705 if (res != NULL) {
10706 /* add the state to the container */
10707 xmlRelaxNGAddStates(ctxt, res, ctxt->state);
10708 ctxt->state = NULL;
10709 } else {
10710 /* add the state directly in states */
10711 states->tabState[j++] = ctxt->state;
10712 ctxt->state = NULL;
10713 }
10714 } else {
10715 if (res == NULL) {
10716 /* make it the new container and copy other results */
10717 res = ctxt->states;
10718 ctxt->states = NULL;
10719 for (k = 0; k < j; k++)
10720 xmlRelaxNGAddStates(ctxt, res,
10721 states->tabState[k]);
10722 } else {
10723 /* add all the new results to res and reff the container */
10724 for (k = 0; k < ctxt->states->nbState; k++)
10725 xmlRelaxNGAddStates(ctxt, res,
10726 ctxt->states->tabState[k]);
10727 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10728 ctxt->states = NULL;
10729 }
10730 }
10731 } else {
10732 if (ctxt->state != NULL) {
10733 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10734 ctxt->state = NULL;
10735 } else if (ctxt->states != NULL) {
10736 for (k = 0; k < ctxt->states->nbState; k++)
10737 xmlRelaxNGFreeValidState(ctxt,
10738 ctxt->states->tabState[k]);
10739 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10740 ctxt->states = NULL;
10741 }
10742 }
10743 }
10744 ctxt->flags = oldflags;
10745 if (res != NULL) {
10746 xmlRelaxNGFreeStates(ctxt, states);
10747 ctxt->states = res;
10748 ret = 0;
10749 } else if (j > 1) {
10750 states->nbState = j;
10751 ctxt->states = states;
10752 ret = 0;
10753 } else if (j == 1) {
10754 ctxt->state = states->tabState[0];
10755 xmlRelaxNGFreeStates(ctxt, states);
10756 ret = 0;
10757 } else {
10758 ret = -1;
10759 xmlRelaxNGFreeStates(ctxt, states);
10760 if (ctxt->states != NULL) {
10761 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10762 ctxt->states = NULL;
10763 }
10764 }
10765 if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
10766 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10767 ctxt->state = NULL;
10768 }
10769 return (ret);
10770}
10771
10781static int
10782xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
10783{
10784 int ret;
10785 xmlRelaxNGPtr schema;
10786 xmlRelaxNGGrammarPtr grammar;
10787 xmlRelaxNGValidStatePtr state;
10789
10790 if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL))
10791 return (-1);
10792
10793 ctxt->errNo = XML_RELAXNG_OK;
10794 schema = ctxt->schema;
10795 grammar = schema->topgrammar;
10796 if (grammar == NULL) {
10797 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
10798 return (-1);
10799 }
10800 state = xmlRelaxNGNewValidState(ctxt, NULL);
10801 ctxt->state = state;
10802 ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start);
10803 if ((ctxt->state != NULL) && (state->seq != NULL)) {
10804 state = ctxt->state;
10805 node = state->seq;
10806 node = xmlRelaxNGSkipIgnored(ctxt, node);
10807 if (node != NULL) {
10808 if (ret != -1) {
10809 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
10810 ret = -1;
10811 }
10812 }
10813 } else if (ctxt->states != NULL) {
10814 int i;
10815 int tmp = -1;
10816
10817 for (i = 0; i < ctxt->states->nbState; i++) {
10818 state = ctxt->states->tabState[i];
10819 node = state->seq;
10820 node = xmlRelaxNGSkipIgnored(ctxt, node);
10821 if (node == NULL)
10822 tmp = 0;
10823 xmlRelaxNGFreeValidState(ctxt, state);
10824 }
10825 if (tmp == -1) {
10826 if (ret != -1) {
10827 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
10828 ret = -1;
10829 }
10830 }
10831 }
10832 if (ctxt->state != NULL) {
10833 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10834 ctxt->state = NULL;
10835 }
10836 if (ret != 0)
10837 xmlRelaxNGDumpValidError(ctxt);
10838#ifdef DEBUG
10839 else if (ctxt->errNr != 0) {
10840 ctxt->error(ctxt->userData,
10841 "%d Extra error messages left on stack !\n",
10842 ctxt->errNr);
10843 xmlRelaxNGDumpValidError(ctxt);
10844 }
10845#endif
10846#ifdef LIBXML_VALID_ENABLED
10847 if (ctxt->idref == 1) {
10848 xmlValidCtxt vctxt;
10849
10850 memset(&vctxt, 0, sizeof(xmlValidCtxt));
10851 vctxt.valid = 1;
10852 vctxt.error = ctxt->error;
10853 vctxt.warning = ctxt->warning;
10854 vctxt.userData = ctxt->userData;
10855
10856 if (xmlValidateDocumentFinal(&vctxt, doc) != 1)
10857 ret = -1;
10858 }
10859#endif /* LIBXML_VALID_ENABLED */
10860 if ((ret == 0) && (ctxt->errNo != XML_RELAXNG_OK))
10861 ret = -1;
10862
10863 return (ret);
10864}
10865
10879static void
10880xmlRelaxNGCleanPSVI(xmlNodePtr node) {
10882
10883 if ((node == NULL) ||
10884 ((node->type != XML_ELEMENT_NODE) &&
10885 (node->type != XML_DOCUMENT_NODE) &&
10886 (node->type != XML_HTML_DOCUMENT_NODE)))
10887 return;
10888 if (node->type == XML_ELEMENT_NODE)
10889 node->psvi = NULL;
10890
10891 cur = node->children;
10892 while (cur != NULL) {
10893 if (cur->type == XML_ELEMENT_NODE) {
10894 cur->psvi = NULL;
10895 if (cur->children != NULL) {
10896 cur = cur->children;
10897 continue;
10898 }
10899 }
10900 if (cur->next != NULL) {
10901 cur = cur->next;
10902 continue;
10903 }
10904 do {
10905 cur = cur->parent;
10906 if (cur == NULL)
10907 break;
10908 if (cur == node) {
10909 cur = NULL;
10910 break;
10911 }
10912 if (cur->next != NULL) {
10913 cur = cur->next;
10914 break;
10915 }
10916 } while (cur != NULL);
10917 }
10918 return;
10919}
10920/************************************************************************
10921 * *
10922 * Validation interfaces *
10923 * *
10924 ************************************************************************/
10925
10934xmlRelaxNGValidCtxtPtr
10935xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema)
10936{
10937 xmlRelaxNGValidCtxtPtr ret;
10938
10939 ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt));
10940 if (ret == NULL) {
10941 xmlRngVErrMemory(NULL, "building context\n");
10942 return (NULL);
10943 }
10944 memset(ret, 0, sizeof(xmlRelaxNGValidCtxt));
10945 ret->schema = schema;
10946 ret->error = xmlGenericError;
10947 ret->userData = xmlGenericErrorContext;
10948 ret->errNr = 0;
10949 ret->errMax = 0;
10950 ret->err = NULL;
10951 ret->errTab = NULL;
10952 if (schema != NULL)
10953 ret->idref = schema->idref;
10954 ret->states = NULL;
10955 ret->freeState = NULL;
10956 ret->freeStates = NULL;
10957 ret->errNo = XML_RELAXNG_OK;
10958 return (ret);
10959}
10960
10967void
10968xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt)
10969{
10970 int k;
10971
10972 if (ctxt == NULL)
10973 return;
10974 if (ctxt->states != NULL)
10975 xmlRelaxNGFreeStates(NULL, ctxt->states);
10976 if (ctxt->freeState != NULL) {
10977 for (k = 0; k < ctxt->freeState->nbState; k++) {
10978 xmlRelaxNGFreeValidState(NULL, ctxt->freeState->tabState[k]);
10979 }
10980 xmlRelaxNGFreeStates(NULL, ctxt->freeState);
10981 }
10982 if (ctxt->freeStates != NULL) {
10983 for (k = 0; k < ctxt->freeStatesNr; k++) {
10984 xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]);
10985 }
10986 xmlFree(ctxt->freeStates);
10987 }
10988 if (ctxt->errTab != NULL)
10989 xmlFree(ctxt->errTab);
10990 if (ctxt->elemTab != NULL) {
10991 xmlRegExecCtxtPtr exec;
10992
10993 exec = xmlRelaxNGElemPop(ctxt);
10994 while (exec != NULL) {
10995 xmlRegFreeExecCtxt(exec);
10996 exec = xmlRelaxNGElemPop(ctxt);
10997 }
10998 xmlFree(ctxt->elemTab);
10999 }
11000 xmlFree(ctxt);
11001}
11002
11012void
11013xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
11014 xmlRelaxNGValidityErrorFunc err,
11015 xmlRelaxNGValidityWarningFunc warn, void *ctx)
11016{
11017 if (ctxt == NULL)
11018 return;
11019 ctxt->error = err;
11020 ctxt->warning = warn;
11021 ctxt->userData = ctx;
11022 ctxt->serror = NULL;
11023}
11024
11033void
11034xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt,
11035 xmlStructuredErrorFunc serror, void *ctx)
11036{
11037 if (ctxt == NULL)
11038 return;
11039 ctxt->serror = serror;
11040 ctxt->error = NULL;
11041 ctxt->warning = NULL;
11042 ctxt->userData = ctx;
11043}
11044
11056int
11057xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
11058 xmlRelaxNGValidityErrorFunc * err,
11059 xmlRelaxNGValidityWarningFunc * warn, void **ctx)
11060{
11061 if (ctxt == NULL)
11062 return (-1);
11063 if (err != NULL)
11064 *err = ctxt->error;
11065 if (warn != NULL)
11066 *warn = ctxt->warning;
11067 if (ctx != NULL)
11068 *ctx = ctxt->userData;
11069 return (0);
11070}
11071
11082int
11083xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
11084{
11085 int ret;
11086
11087 if ((ctxt == NULL) || (doc == NULL))
11088 return (-1);
11089
11090 ctxt->doc = doc;
11091
11092 ret = xmlRelaxNGValidateDocument(ctxt, doc);
11093 /*
11094 * Remove all left PSVI
11095 */
11096 xmlRelaxNGCleanPSVI((xmlNodePtr) doc);
11097
11098 /*
11099 * TODO: build error codes
11100 */
11101 if (ret == -1)
11102 return (1);
11103 return (ret);
11104}
11105
11106#endif /* LIBXML_SCHEMAS_ENABLED */
#define TODO
Definition: SAX2.c:44
static int state
Definition: maze.c:121
#define skip(...)
Definition: atltest.h:64
#define msg(x)
Definition: auth_time.c:54
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
struct _root root
#define except(x)
Definition: btrfs_drv.h:136
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
cd_progress_ptr progress
Definition: cdjpeg.h:152
FT_Library library
Definition: cffdrivr.c:654
Definition: list.h:37
struct list * next
Definition: list.h:38
static struct loaded_include * includes
Definition: compiler.c:53
static SIZE_T const char const D3D_SHADER_MACRO * defines
Definition: asm.c:31
#define NULL
Definition: types.h:112
#define IS_BLANK_NODE(n)
Definition: attributes.c:29
unsigned int idx
Definition: utils.c:41
content
Definition: atl_ax.c:994
const WCHAR * text
Definition: package.c:1799
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define check(expected, result)
Definition: dplayx.c:32
r parent
Definition: btrfs.c:3010
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247
#define local
Definition: zutil.h:30
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLsizei GLuint * groups
Definition: glext.h:11113
GLuint buffer
Definition: glext.h:5915
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:9514
GLbitfield flags
Definition: glext.h:7161
GLboolean GLuint group
Definition: glext.h:11120
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLenum target
Definition: glext.h:7315
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
@ extra
Definition: id3.c:95
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define dup
Definition: syshdrs.h:51
XMLPUBFUN xmlChar *XMLCALL xmlEscapeFormatString(xmlChar **msg)
Definition: xmlstring.c:1001
if(dx< 0)
Definition: linetemp.h:194
const WCHAR * schema
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static WCHAR name2[]
Definition: record.c:35
static UINT UINT last
Definition: font.c:45
static size_t elem
Definition: string.c:68
const char * uri
Definition: sec_mgr.c:1588
static HWND child
Definition: cursoricon.c:298
static WCHAR escape[]
Definition: url.c:36
int k
Definition: mpi.c:3369
#define IS_BLANK_CH(c)
static unsigned __int64 next
Definition: rand_nt.c:6
#define warn(...)
#define err(...)
#define list
Definition: rosglue.h:35
const WCHAR * str
static calc_node_t temp
Definition: rpn_ieee.c:38
#define warning(s)
Definition: debug.h:83
XMLPUBVAR xmlMallocFunc xmlMallocAtomic
Definition: globals.h:249
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:353
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:250
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:337
XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata)
Definition: hash.c:406
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:322
xmlHashTable * xmlHashTablePtr
Definition: hash.h:22
XMLPUBFUN void *XMLCALL xmlHashLookup(xmlHashTablePtr table, const xmlChar *name)
Definition: hash.c:461
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:176
XMLPUBFUN int XMLCALL xmlHashAddEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata)
Definition: hash.c:389
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:476
XMLPUBFUN void XMLCALL xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data)
Definition: hash.c:859
XMLPUBFUN xmlDocPtr XMLCALL xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
Definition: parser.c:15253
XMLPUBFUN xmlDocPtr XMLCALL xmlReadFile(const char *URL, const char *encoding, int options)
Definition: parser.c:15229
XMLPUBFUN xmlNodePtr XMLCALL xmlAddChild(xmlNodePtr parent, xmlNodePtr cur)
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetContent(const xmlNode *cur)
XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement(const xmlDoc *doc)
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
XMLPUBFUN xmlAttrPtr XMLCALL xmlHasProp(const xmlNode *node, const xmlChar *name)
XMLPUBFUN xmlChar *XMLCALL xmlGetProp(const xmlNode *node, const xmlChar *name)
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, const xmlChar *content)
xmlNode * xmlNodePtr
Definition: tree.h:488
XMLPUBFUN xmlNodePtr XMLCALL xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem)
@ XML_ENTITY_DECL
Definition: tree.h:176
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_XINCLUDE_START
Definition: tree.h:178
@ XML_ENTITY_NODE
Definition: tree.h:165
@ XML_PI_NODE
Definition: tree.h:166
@ XML_XINCLUDE_END
Definition: tree.h:179
@ XML_COMMENT_NODE
Definition: tree.h:167
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
@ XML_ELEMENT_NODE
Definition: tree.h:160
@ XML_ENTITY_REF_NODE
Definition: tree.h:164
XMLPUBFUN void XMLCALL xmlUnlinkNode(xmlNodePtr cur)
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur)
XMLPUBFUN void XMLCALL xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content)
XMLPUBFUN int XMLCALL xmlIsBlankNode(const xmlNode *node)
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocText(const xmlDoc *doc, const xmlChar *content)
xmlNs * xmlNsPtr
Definition: tree.h:388
XMLPUBFUN void XMLCALL xmlFreeNode(xmlNodePtr cur)
XMLPUBFUN xmlChar *XMLCALL xmlSplitQName2(const xmlChar *name, xmlChar **prefix)
XMLPUBFUN xmlChar *XMLCALL xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
#define memset(x, y, z)
Definition: compat.h:39
Definition: tree.h:434
xmlNs * ns
Definition: tree.h:444
struct _xmlNode * children
Definition: tree.h:438
struct _xmlDoc * doc
Definition: tree.h:443
const xmlChar * name
Definition: tree.h:437
Definition: tree.h:551
const xmlChar * URL
Definition: tree.h:577
Definition: tree.h:489
struct _xmlNode * children
Definition: tree.h:493
struct _xmlNode * next
Definition: tree.h:496
void * psvi
Definition: tree.h:505
const xmlChar * name
Definition: tree.h:492
xmlElementType type
Definition: tree.h:491
struct _xmlNode * parent
Definition: tree.h:495
Definition: tree.h:389
const xmlChar * href
Definition: tree.h:392
struct _xmlNs * next
Definition: tree.h:390
Definition: uri.h:33
Definition: cookie.c:202
char * value
Definition: compiler.c:67
char * name
Definition: compiler.c:66
Definition: name.c:39
Definition: mxnamespace.c:45
Definition: send.c:48
Definition: reader.c:220
#define max(a, b)
Definition: svc.c:63
Definition: dlist.c:348
void * next
Definition: dlist.c:360
Definition: pdh_main.c:94
XMLPUBFUN xmlURIPtr XMLCALL xmlParseURI(const char *str)
Definition: uri.c:940
XMLPUBFUN xmlChar *XMLCALL xmlURIEscapeStr(const xmlChar *str, const xmlChar *list)
Definition: uri.c:1679
XMLPUBFUN void XMLCALL xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1387
XMLPUBFUN xmlChar *XMLCALL xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1892
typedeftypedef void(XMLCDECL *) typedef void(XMLCDECL *) struct _xmlValidCtx xmlValidCtxt)
Definition: valid.h:80
int ret
#define success(from, fromstr, to, tostr)
#define snprintf
Definition: wintirpc.h:48
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
void(XMLCDECL * xmlGenericErrorFunc)(void *ctx, const char *msg,...) LIBXML_ATTR_FORMAT(2
Definition: xmlerror.h:847
@ XML_ERR_ERROR
Definition: xmlerror.h:27
@ XML_ERR_FATAL
Definition: xmlerror.h:28
@ XML_FROM_RELAXNGV
Definition: xmlerror.h:56
@ XML_FROM_RELAXNGP
Definition: xmlerror.h:55
void(XMLCDECL *) typedef void(XMLCALL * xmlStructuredErrorFunc)(void *userData, xmlErrorPtr error)
Definition: xmlerror.h:858
@ XML_RNGP_UNKNOWN_TYPE_LIB
Definition: xmlerror.h:380
@ XML_RNGP_ELEM_TEXT_CONFLICT
Definition: xmlerror.h:285
@ XML_RNGP_EXCEPT_NO_CONTENT
Definition: xmlerror.h:294
@ XML_RNGP_PARAM_FORBIDDEN
Definition: xmlerror.h:322
@ XML_RNGP_GROUP_ATTR_CONFLICT
Definition: xmlerror.h:304
@ XML_RNGP_ATTR_CONFLICT
Definition: xmlerror.h:265
@ XML_RNGP_XMLNS_NAME
Definition: xmlerror.h:385
@ XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR
Definition: xmlerror.h:351
@ XML_RNGP_PAT_START_DATA
Definition: xmlerror.h:353
@ XML_RNGP_PAT_START_GROUP
Definition: xmlerror.h:355
@ XML_RNGP_PAT_DATA_EXCEPT_ONEMORE
Definition: xmlerror.h:339
@ XML_RNGP_EMPTY_CONSTRUCT
Definition: xmlerror.h:287
@ XML_RNGP_PARENTREF_CREATE_FAILED
Definition: xmlerror.h:324
@ XML_RNGP_ELEM_CONTENT_ERROR
Definition: xmlerror.h:280
@ XML_RNGP_DEFINE_NAME_MISSING
Definition: xmlerror.h:278
@ XML_RNGP_START_MISSING
Definition: xmlerror.h:371
@ XML_RNGP_TEXT_HAS_CHILD
Definition: xmlerror.h:373
@ XML_RNGP_PAT_LIST_TEXT
Definition: xmlerror.h:347
@ XML_RNGP_FORBIDDEN_ATTRIBUTE
Definition: xmlerror.h:298
@ XML_RNGP_PARENTREF_NO_PARENT
Definition: xmlerror.h:327
@ XML_RNGP_PAT_DATA_EXCEPT_ATTR
Definition: xmlerror.h:333
@ XML_RNGP_PARSE_ERROR
Definition: xmlerror.h:329
@ XML_RNGP_EXTERNALREF_RECURSE
Definition: xmlerror.h:297
@ XML_RNGP_PAT_ONEMORE_GROUP_ATTR
Definition: xmlerror.h:350
@ XML_RNGP_EXCEPT_MISSING
Definition: xmlerror.h:292
@ XML_RNGP_START_CHOICE_AND_INTERLEAVE
Definition: xmlerror.h:368
@ XML_RNGP_ELEMENT_NAME
Definition: xmlerror.h:283
@ XML_RNGP_URI_NOT_ABSOLUTE
Definition: xmlerror.h:382
@ XML_RNGP_PAT_LIST_ELEM
Definition: xmlerror.h:343
@ XML_RNGP_GRAMMAR_NO_START
Definition: xmlerror.h:303
@ XML_RNGP_ELEMENT_CONTENT
Definition: xmlerror.h:282
@ XML_RNGP_NOTALLOWED_NOT_EMPTY
Definition: xmlerror.h:319
@ XML_RNGP_DEF_CHOICE_AND_INTERLEAVE
Definition: xmlerror.h:274
@ XML_RNGP_DATA_CONTENT
Definition: xmlerror.h:273
@ XML_RNGP_INCLUDE_RECURSE
Definition: xmlerror.h:308
@ XML_RNGP_PAT_ATTR_ELEM
Definition: xmlerror.h:332
@ XML_RNGP_EXTERNAL_REF_FAILURE
Definition: xmlerror.h:296
@ XML_RNGP_HREF_ERROR
Definition: xmlerror.h:305
@ XML_RNGP_PAT_START_ATTR
Definition: xmlerror.h:352
@ XML_RNGP_ANYNAME_ATTR_ANCESTOR
Definition: xmlerror.h:264
@ XML_RNGP_ERROR_TYPE_LIB
Definition: xmlerror.h:290
@ XML_RNGP_ELEMENT_NO_CONTENT
Definition: xmlerror.h:284
@ XML_RNGP_PAT_START_EMPTY
Definition: xmlerror.h:354
@ XML_RNGP_DEFINE_EMPTY
Definition: xmlerror.h:276
@ XML_RNGP_ELEMENT_EMPTY
Definition: xmlerror.h:281
@ XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE
Definition: xmlerror.h:337
@ XML_RNGP_INVALID_URI
Definition: xmlerror.h:314
@ XML_RNGP_NSNAME_NO_NS
Definition: xmlerror.h:321
@ XML_RNGP_PAT_START_VALUE
Definition: xmlerror.h:360
@ XML_RNGP_ELEM_CONTENT_EMPTY
Definition: xmlerror.h:279
@ XML_RNGP_EMPTY_NOT_EMPTY
Definition: xmlerror.h:289
@ XML_RNGP_INVALID_VALUE
Definition: xmlerror.h:315
@ XML_RNGP_PAT_DATA_EXCEPT_TEXT
Definition: xmlerror.h:341
@ XML_RNGP_ATTRIBUTE_NOOP
Definition: xmlerror.h:269
@ XML_RNGP_EXCEPT_MULTIPLE
Definition: xmlerror.h:293
@ XML_RNGP_PAT_LIST_ATTR
Definition: xmlerror.h:342
@ XML_RNGP_DEFINE_MISSING
Definition: xmlerror.h:277
@ XML_RNGP_UNKNOWN_CONSTRUCT
Definition: xmlerror.h:379
@ XML_RNGP_PAT_DATA_EXCEPT_GROUP
Definition: xmlerror.h:336
@ XML_RNGP_REF_CREATE_FAILED
Definition: xmlerror.h:362
@ XML_ERR_INTERNAL_ERROR
Definition: xmlerror.h:101
@ XML_RNGP_PAT_ATTR_ATTR
Definition: xmlerror.h:331
@ XML_RNGP_INCLUDE_FAILURE
Definition: xmlerror.h:307
@ XML_RNGP_TEXT_EXPECTED
Definition: xmlerror.h:372
@ XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME
Definition: xmlerror.h:348
@ XML_RNGP_REF_NAME_INVALID
Definition: xmlerror.h:364
@ XML_RNGP_EXTERNALREF_EMTPY
Definition: xmlerror.h:295
@ XML_RNGP_PAT_START_LIST
Definition: xmlerror.h:357
@ XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME
Definition: xmlerror.h:330
@ XML_RNGP_PARENTREF_NAME_INVALID
Definition: xmlerror.h:325
@ XML_RNGP_NAME_MISSING
Definition: xmlerror.h:317
@ XML_RNGP_ATTRIBUTE_CHILDREN
Definition: xmlerror.h:266
@ XML_RNGP_MISSING_HREF
Definition: xmlerror.h:316
@ XML_RNGP_TYPE_NOT_FOUND
Definition: xmlerror.h:375
@ XML_RNGP_UNKNOWN_ATTRIBUTE
Definition: xmlerror.h:377
@ XML_RNGP_TYPE_VALUE
Definition: xmlerror.h:376
@ XML_RNGP_GRAMMAR_CONTENT
Definition: xmlerror.h:300
@ XML_RNGP_REF_NO_DEF
Definition: xmlerror.h:365
@ XML_RNGP_INCLUDE_EMPTY
Definition: xmlerror.h:306
@ XML_RNGP_REF_CYCLE
Definition: xmlerror.h:363
@ XML_RNGP_PREFIX_UNDEFINED
Definition: xmlerror.h:361
@ XML_RNGP_TYPE_MISSING
Definition: xmlerror.h:374
@ XML_RNGP_PAT_LIST_INTERLEAVE
Definition: xmlerror.h:344
@ XML_RNGP_PAT_DATA_EXCEPT_LIST
Definition: xmlerror.h:338
@ XML_RNGP_XML_NS
Definition: xmlerror.h:386
@ XML_RNGP_REF_NO_NAME
Definition: xmlerror.h:366
@ XML_RNGP_PAT_LIST_REF
Definition: xmlerror.h:346
@ XML_RNGP_PAT_LIST_LIST
Definition: xmlerror.h:345
@ XML_RNGP_URI_FRAGMENT
Definition: xmlerror.h:381
@ XML_RNGP_DEFINE_CREATE_FAILED
Definition: xmlerror.h:275
@ XML_RNGP_EMPTY
Definition: xmlerror.h:286
@ XML_RNGP_REF_NOT_EMPTY
Definition: xmlerror.h:367
@ XML_RNGP_PARENTREF_NOT_EMPTY
Definition: xmlerror.h:328
@ XML_RNGP_ATTRIBUTE_EMPTY
Definition: xmlerror.h:268
@ XML_RNGP_EMPTY_CONTENT
Definition: xmlerror.h:288
@ XML_RNGP_PAT_DATA_EXCEPT_REF
Definition: xmlerror.h:340
@ XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME
Definition: xmlerror.h:349
@ XML_RNGP_EXCEPT_EMPTY
Definition: xmlerror.h:291
@ XML_RNGP_INTERLEAVE_NO_CONTENT
Definition: xmlerror.h:312
@ XML_RNGP_FOREIGN_ELEMENT
Definition: xmlerror.h:299
@ XML_RNGP_VALUE_NO_CONTENT
Definition: xmlerror.h:384
@ XML_RNGP_PAT_START_TEXT
Definition: xmlerror.h:359
@ XML_RNGP_CREATE_FAILURE
Definition: xmlerror.h:272
@ XML_RNGP_CHOICE_CONTENT
Definition: xmlerror.h:270
@ XML_RNGP_INTERLEAVE_ADD
Definition: xmlerror.h:309
@ XML_RNGP_PAT_DATA_EXCEPT_EMPTY
Definition: xmlerror.h:335
@ XML_RNGP_ATTRIBUTE_CONTENT
Definition: xmlerror.h:267
@ XML_RNGP_START_CONTENT
Definition: xmlerror.h:369
@ XML_RNGP_NEED_COMBINE
Definition: xmlerror.h:318
@ XML_RNGP_CHOICE_EMPTY
Definition: xmlerror.h:271
@ XML_RNGP_INTERLEAVE_CREATE_FAILED
Definition: xmlerror.h:310
@ XML_RNGP_INVALID_DEFINE_NAME
Definition: xmlerror.h:313
@ XML_RNGP_UNKNOWN_COMBINE
Definition: xmlerror.h:378
@ XML_RNGP_GRAMMAR_MISSING
Definition: xmlerror.h:302
@ XML_RNGP_PAT_DATA_EXCEPT_ELEM
Definition: xmlerror.h:334
@ XML_RNGP_PAT_START_ONEMORE
Definition: xmlerror.h:358
@ XML_RNGP_PARAM_NAME_MISSING
Definition: xmlerror.h:323
@ XML_RNGP_NSNAME_ATTR_ANCESTOR
Definition: xmlerror.h:320
@ XML_RNGP_GRAMMAR_EMPTY
Definition: xmlerror.h:301
@ XML_RNGP_PARENTREF_NO_NAME
Definition: xmlerror.h:326
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
@ XML_RNGP_START_EMPTY
Definition: xmlerror.h:370
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
XMLPUBFUN xmlChar *XMLCALL xmlCharStrdup(const char *cur)
Definition: xmlstring.c:114
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:426
unsigned char xmlChar
Definition: xmlstring.h:28
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:486
#define const
Definition: zconf.h:233