ReactOS 0.4.15-dev-7712-gbbbcd8e
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;