ReactOS 0.4.16-dev-2232-gc2aaa52
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#include "private/error.h"
38#include "private/regexp.h"
39#include "private/string.h"
40
41/*
42 * The Relax-NG namespace
43 */
44static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
45 "http://relaxng.org/ns/structure/1.0";
46
47#define IS_RELAXNG(node, typ) \
48 ((node != NULL) && (node->ns != NULL) && \
49 (node->type == XML_ELEMENT_NODE) && \
50 (xmlStrEqual(node->name, (const xmlChar *) typ)) && \
51 (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))
52
53
54#define MAX_ERROR 5
55
56#define TODO \
57 xmlGenericError(xmlGenericErrorContext, \
58 "Unimplemented block at %s:%d\n", \
59 __FILE__, __LINE__);
60
61typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;
62typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;
63
64typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine;
65typedef xmlRelaxNGDefine *xmlRelaxNGDefinePtr;
66
67typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument;
68typedef xmlRelaxNGDocument *xmlRelaxNGDocumentPtr;
69
70typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude;
71typedef xmlRelaxNGInclude *xmlRelaxNGIncludePtr;
72
73typedef enum {
74 XML_RELAXNG_COMBINE_UNDEFINED = 0, /* undefined */
75 XML_RELAXNG_COMBINE_CHOICE, /* choice */
76 XML_RELAXNG_COMBINE_INTERLEAVE /* interleave */
77} xmlRelaxNGCombine;
78
79typedef enum {
80 XML_RELAXNG_CONTENT_ERROR = -1,
81 XML_RELAXNG_CONTENT_EMPTY = 0,
82 XML_RELAXNG_CONTENT_SIMPLE,
83 XML_RELAXNG_CONTENT_COMPLEX
84} xmlRelaxNGContentType;
85
86typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar;
87typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr;
88
89struct _xmlRelaxNGGrammar {
90 xmlRelaxNGGrammarPtr parent; /* the parent grammar if any */
91 xmlRelaxNGGrammarPtr children; /* the children grammar if any */
92 xmlRelaxNGGrammarPtr next; /* the next grammar if any */
93 xmlRelaxNGDefinePtr start; /* <start> content */
94 xmlRelaxNGCombine combine; /* the default combine value */
95 xmlRelaxNGDefinePtr startList; /* list of <start> definitions */
96 xmlHashTablePtr defs; /* define* */
97 xmlHashTablePtr refs; /* references */
98};
99
100
101typedef enum {
102 XML_RELAXNG_NOOP = -1, /* a no operation from simplification */
103 XML_RELAXNG_EMPTY = 0, /* an empty pattern */
104 XML_RELAXNG_NOT_ALLOWED, /* not allowed top */
105 XML_RELAXNG_EXCEPT, /* except present in nameclass defs */
106 XML_RELAXNG_TEXT, /* textual content */
107 XML_RELAXNG_ELEMENT, /* an element */
108 XML_RELAXNG_DATATYPE, /* external data type definition */
109 XML_RELAXNG_PARAM, /* external data type parameter */
110 XML_RELAXNG_VALUE, /* value from an external data type definition */
111 XML_RELAXNG_LIST, /* a list of patterns */
112 XML_RELAXNG_ATTRIBUTE, /* an attribute following a pattern */
113 XML_RELAXNG_DEF, /* a definition */
114 XML_RELAXNG_REF, /* reference to a definition */
115 XML_RELAXNG_EXTERNALREF, /* reference to an external def */
116 XML_RELAXNG_PARENTREF, /* reference to a def in the parent grammar */
117 XML_RELAXNG_OPTIONAL, /* optional patterns */
118 XML_RELAXNG_ZEROORMORE, /* zero or more non empty patterns */
119 XML_RELAXNG_ONEORMORE, /* one or more non empty patterns */
120 XML_RELAXNG_CHOICE, /* a choice between non empty patterns */
121 XML_RELAXNG_GROUP, /* a pair/group of non empty patterns */
122 XML_RELAXNG_INTERLEAVE, /* interleaving choice of non-empty patterns */
123 XML_RELAXNG_START /* Used to keep track of starts on grammars */
124} xmlRelaxNGType;
125
126#define IS_NULLABLE (1 << 0)
127#define IS_NOT_NULLABLE (1 << 1)
128#define IS_INDETERMINIST (1 << 2)
129#define IS_MIXED (1 << 3)
130#define IS_TRIABLE (1 << 4)
131#define IS_PROCESSED (1 << 5)
132#define IS_COMPILABLE (1 << 6)
133#define IS_NOT_COMPILABLE (1 << 7)
134#define IS_EXTERNAL_REF (1 << 8)
135
136struct _xmlRelaxNGDefine {
137 xmlRelaxNGType type; /* the type of definition */
138 xmlNodePtr node; /* the node in the source */
139 xmlChar *name; /* the element local name if present */
140 xmlChar *ns; /* the namespace local name if present */
141 xmlChar *value; /* value when available */
142 void *data; /* data lib or specific pointer */
143 xmlRelaxNGDefinePtr content; /* the expected content */
144 xmlRelaxNGDefinePtr parent; /* the parent definition, if any */
145 xmlRelaxNGDefinePtr next; /* list within grouping sequences */
146 xmlRelaxNGDefinePtr attrs; /* list of attributes for elements */
147 xmlRelaxNGDefinePtr nameClass; /* the nameClass definition if any */
148 xmlRelaxNGDefinePtr nextHash; /* next define in defs/refs hash tables */
149 short depth; /* used for the cycle detection */
150 short dflags; /* define related flags */
151 xmlRegexpPtr contModel; /* a compiled content model if available */
152};
153
159struct _xmlRelaxNG {
160 void *_private; /* unused by the library for users or bindings */
161 xmlRelaxNGGrammarPtr topgrammar;
162 xmlDocPtr doc;
163
164 int idref; /* requires idref checking */
165
166 xmlHashTablePtr defs; /* define */
167 xmlHashTablePtr refs; /* references */
168 xmlRelaxNGDocumentPtr documents; /* all the documents loaded */
169 xmlRelaxNGIncludePtr includes; /* all the includes loaded */
170 int defNr; /* number of defines used */
171 xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */
172
173};
174
175#define XML_RELAXNG_IN_ATTRIBUTE (1 << 0)
176#define XML_RELAXNG_IN_ONEORMORE (1 << 1)
177#define XML_RELAXNG_IN_LIST (1 << 2)
178#define XML_RELAXNG_IN_DATAEXCEPT (1 << 3)
179#define XML_RELAXNG_IN_START (1 << 4)
180#define XML_RELAXNG_IN_OOMGROUP (1 << 5)
181#define XML_RELAXNG_IN_OOMINTERLEAVE (1 << 6)
182#define XML_RELAXNG_IN_EXTERNALREF (1 << 7)
183#define XML_RELAXNG_IN_ANYEXCEPT (1 << 8)
184#define XML_RELAXNG_IN_NSEXCEPT (1 << 9)
185
186struct _xmlRelaxNGParserCtxt {
187 void *userData; /* user specific data block */
188 xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */
189 xmlRelaxNGValidityWarningFunc warning; /* the callback in case of warning */
191 xmlRelaxNGValidErr err;
192
193 xmlRelaxNGPtr schema; /* The schema in use */
194 xmlRelaxNGGrammarPtr grammar; /* the current grammar */
195 xmlRelaxNGGrammarPtr parentgrammar; /* the parent grammar */
196 int flags; /* parser flags */
197 int nbErrors; /* number of errors at parse time */
198 int nbWarnings; /* number of warnings at parse time */
199 const xmlChar *define; /* the current define scope */
200 xmlRelaxNGDefinePtr def; /* the current define */
201
202 int nbInterleaves;
203 xmlHashTablePtr interleaves; /* keep track of all the interleaves */
204
205 xmlRelaxNGDocumentPtr documents; /* all the documents loaded */
206 xmlRelaxNGIncludePtr includes; /* all the includes loaded */
207 xmlChar *URL;
208 xmlDocPtr document;
209
210 int defNr; /* number of defines used */
211 int defMax; /* number of defines allocated */
212 xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */
213
214 const char *buffer;
215 int size;
216
217 /* the document stack */
218 xmlRelaxNGDocumentPtr doc; /* Current parsed external ref */
219 int docNr; /* Depth of the parsing stack */
220 int docMax; /* Max depth of the parsing stack */
221 xmlRelaxNGDocumentPtr *docTab; /* array of docs */
222
223 /* the include stack */
224 xmlRelaxNGIncludePtr inc; /* Current parsed include */
225 int incNr; /* Depth of the include parsing stack */
226 int incMax; /* Max depth of the parsing stack */
227 xmlRelaxNGIncludePtr *incTab; /* array of incs */
228
229 int idref; /* requires idref checking */
230
231 /* used to compile content models */
232 xmlAutomataPtr am; /* the automata */
233 xmlAutomataStatePtr state; /* used to build the automata */
234
235 int crng; /* compact syntax and other flags */
236 int freedoc; /* need to free the document */
237};
238
239#define FLAGS_IGNORABLE 1
240#define FLAGS_NEGATIVE 2
241#define FLAGS_MIXED_CONTENT 4
242#define FLAGS_NOERROR 8
243
249typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup;
250typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr;
251struct _xmlRelaxNGInterleaveGroup {
252 xmlRelaxNGDefinePtr rule; /* the rule to satisfy */
253 xmlRelaxNGDefinePtr *defs; /* the array of element definitions */
254 xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */
255};
256
257#define IS_DETERMINIST 1
258#define IS_NEEDCHECK 2
259
265typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition;
266typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr;
267struct _xmlRelaxNGPartition {
268 int nbgroups; /* number of groups in the partitions */
269 xmlHashTablePtr triage; /* hash table used to direct nodes to the
270 * right group when possible */
271 int flags; /* determinist ? */
272 xmlRelaxNGInterleaveGroupPtr *groups;
273};
274
280#define MAX_ATTR 20
281typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState;
282typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr;
283struct _xmlRelaxNGValidState {
284 xmlNodePtr node; /* the current node */
285 xmlNodePtr seq; /* the sequence of children left to validate */
286 int nbAttrs; /* the number of attributes */
287 int maxAttrs; /* the size of attrs */
288 int nbAttrLeft; /* the number of attributes left to validate */
289 xmlChar *value; /* the value when operating on string */
290 xmlChar *endvalue; /* the end value when operating on string */
291 xmlAttrPtr *attrs; /* the array of attributes */
292};
293
299typedef struct _xmlRelaxNGStates xmlRelaxNGStates;
300typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr;
301struct _xmlRelaxNGStates {
302 int nbState; /* the number of states */
303 int maxState; /* the size of the array */
304 xmlRelaxNGValidStatePtr *tabState;
305};
306
307#define ERROR_IS_DUP 1
308
314typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;
315typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;
316struct _xmlRelaxNGValidError {
317 xmlRelaxNGValidErr err; /* the error number */
318 int flags; /* flags */
319 xmlNodePtr node; /* the current node */
320 xmlNodePtr seq; /* the current child */
321 const xmlChar *arg1; /* first arg */
322 const xmlChar *arg2; /* second arg */
323};
324
331struct _xmlRelaxNGValidCtxt {
332 void *userData; /* user specific data block */
333 xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */
334 xmlRelaxNGValidityWarningFunc warning; /* the callback in case of warning */
336 int nbErrors; /* number of errors in validation */
337
338 xmlRelaxNGPtr schema; /* The schema in use */
339 xmlDocPtr doc; /* the document being validated */
340 int flags; /* validation flags */
341 int depth; /* validation depth */
342 int idref; /* requires idref checking */
343 int errNo; /* the first error found */
344
345 /*
346 * Errors accumulated in branches may have to be stacked to be
347 * provided back when it's sure they affect validation.
348 */
349 xmlRelaxNGValidErrorPtr err; /* Last error */
350 int errNr; /* Depth of the error stack */
351 int errMax; /* Max depth of the error stack */
352 xmlRelaxNGValidErrorPtr errTab; /* stack of errors */
353
354 xmlRelaxNGValidStatePtr state; /* the current validation state */
355 xmlRelaxNGStatesPtr states; /* the accumulated state list */
356
357 xmlRelaxNGStatesPtr freeState; /* the pool of free valid states */
358 int freeStatesNr;
359 int freeStatesMax;
360 xmlRelaxNGStatesPtr *freeStates; /* the pool of free state groups */
361
362 /*
363 * This is used for "progressive" validation
364 */
365 xmlRegExecCtxtPtr elem; /* the current element regexp */
366 int elemNr; /* the number of element validated */
367 int elemMax; /* the max depth of elements */
368 xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */
369 int pstate; /* progressive state */
370 xmlNodePtr pnode; /* the current node */
371 xmlRelaxNGDefinePtr pdef; /* the non-streamable definition */
372 int perr; /* signal error in content model
373 * outside the regexp */
374};
375
381struct _xmlRelaxNGInclude {
382 xmlRelaxNGIncludePtr next; /* keep a chain of includes */
383 xmlChar *href; /* the normalized href value */
384 xmlDocPtr doc; /* the associated XML document */
385 xmlRelaxNGDefinePtr content; /* the definitions */
386 xmlRelaxNGPtr schema; /* the schema */
387};
388
394struct _xmlRelaxNGDocument {
395 xmlRelaxNGDocumentPtr next; /* keep a chain of documents */
396 xmlChar *href; /* the normalized href value */
397 xmlDocPtr doc; /* the associated XML document */
398 xmlRelaxNGDefinePtr content; /* the definitions */
399 xmlRelaxNGPtr schema; /* the schema */
400 int externalRef; /* 1 if an external ref */
401};
402
403
404/************************************************************************
405 * *
406 * Some factorized error routines *
407 * *
408 ************************************************************************/
409
417static void
418xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
419{
420 xmlStructuredErrorFunc schannel = NULL;
421 xmlGenericErrorFunc channel = NULL;
422 void *data = NULL;
423
424 if (ctxt != NULL) {
425 if (ctxt->serror != NULL)
426 schannel = ctxt->serror;
427 else
428 channel = ctxt->error;
429 data = ctxt->userData;
430 ctxt->nbErrors++;
431 }
432 if (extra)
433 __xmlRaiseError(schannel, channel, data,
436 NULL, NULL, 0, 0,
437 "Memory allocation failed : %s\n", extra);
438 else
439 __xmlRaiseError(schannel, channel, data,
442 NULL, NULL, 0, 0, "Memory allocation failed\n");
443}
444
452static void
453xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)
454{
455 xmlStructuredErrorFunc schannel = NULL;
456 xmlGenericErrorFunc channel = NULL;
457 void *data = NULL;
458
459 if (ctxt != NULL) {
460 if (ctxt->serror != NULL)
461 schannel = ctxt->serror;
462 else
463 channel = ctxt->error;
464 data = ctxt->userData;
465 ctxt->nbErrors++;
466 }
467 if (extra)
468 __xmlRaiseError(schannel, channel, data,
471 NULL, NULL, 0, 0,
472 "Memory allocation failed : %s\n", extra);
473 else
474 __xmlRaiseError(schannel, channel, data,
477 NULL, NULL, 0, 0, "Memory allocation failed\n");
478}
479
491static void LIBXML_ATTR_FORMAT(4,0)
492xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
494{
495 xmlStructuredErrorFunc schannel = NULL;
496 xmlGenericErrorFunc channel = NULL;
497 void *data = NULL;
498
499 if (ctxt != NULL) {
500 if (ctxt->serror != NULL)
501 schannel = ctxt->serror;
502 else
503 channel = ctxt->error;
504 data = ctxt->userData;
505 ctxt->nbErrors++;
506 }
507 __xmlRaiseError(schannel, channel, data,
510 (const char *) str1, (const char *) str2, NULL, 0, 0,
511 msg, str1, str2);
512}
513
525static void LIBXML_ATTR_FORMAT(4,0)
526xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
528{
529 xmlStructuredErrorFunc schannel = NULL;
530 xmlGenericErrorFunc channel = NULL;
531 void *data = NULL;
532
533 if (ctxt != NULL) {
534 if (ctxt->serror != NULL)
535 schannel = ctxt->serror;
536 else
537 channel = ctxt->error;
538 data = ctxt->userData;
539 ctxt->nbErrors++;
540 }
541 __xmlRaiseError(schannel, channel, data,
544 (const char *) str1, (const char *) str2, NULL, 0, 0,
545 msg, str1, str2);
546}
547
548/************************************************************************
549 * *
550 * Preliminary type checking interfaces *
551 * *
552 ************************************************************************/
553
564typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar * type);
565
577typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar * type,
578 const xmlChar * value, void **result,
579 xmlNodePtr node);
580
594typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar * type,
595 const xmlChar * facet,
596 const xmlChar * val,
597 const xmlChar * strval, void *value);
598
606typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);
607
620typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar * type,
621 const xmlChar * value1,
622 xmlNodePtr ctxt1,
623 void *comp1,
624 const xmlChar * value2,
625 xmlNodePtr ctxt2);
626typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
627typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
628struct _xmlRelaxNGTypeLibrary {
629 const xmlChar *namespace; /* the datatypeLibrary value */
630 void *data; /* data needed for the library */
631 xmlRelaxNGTypeHave have; /* the export function */
632 xmlRelaxNGTypeCheck check; /* the checking function */
633 xmlRelaxNGTypeCompare comp; /* the compare function */
634 xmlRelaxNGFacetCheck facet; /* the facet check function */
635 xmlRelaxNGTypeFree freef; /* the freeing function */
636};
637
638/************************************************************************
639 * *
640 * Allocation functions *
641 * *
642 ************************************************************************/
643static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);
644static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);
645static void xmlRelaxNGNormExtSpace(xmlChar * value);
646static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema);
647static int xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt
649 xmlRelaxNGValidStatePtr state1,
650 xmlRelaxNGValidStatePtr state2);
651static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
652 xmlRelaxNGValidStatePtr state);
653
660static void
661xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu)
662{
663 if (docu == NULL)
664 return;
665
666 if (docu->href != NULL)
667 xmlFree(docu->href);
668 if (docu->doc != NULL)
669 xmlFreeDoc(docu->doc);
670 if (docu->schema != NULL)
671 xmlRelaxNGFreeInnerSchema(docu->schema);
672 xmlFree(docu);
673}
674
681static void
682xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu)
683{
684 xmlRelaxNGDocumentPtr next;
685
686 while (docu != NULL) {
687 next = docu->next;
688 xmlRelaxNGFreeDocument(docu);
689 docu = next;
690 }
691}
692
699static void
700xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl)
701{
702 if (incl == NULL)
703 return;
704
705 if (incl->href != NULL)
706 xmlFree(incl->href);
707 if (incl->doc != NULL)
708 xmlFreeDoc(incl->doc);
709 if (incl->schema != NULL)
710 xmlRelaxNGFree(incl->schema);
711 xmlFree(incl);
712}
713
720static void
721xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl)
722{
723 xmlRelaxNGIncludePtr next;
724
725 while (incl != NULL) {
726 next = incl->next;
727 xmlRelaxNGFreeInclude(incl);
728 incl = next;
729 }
730}
731
740static xmlRelaxNGPtr
741xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)
742{
743 xmlRelaxNGPtr ret;
744
745 ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));
746 if (ret == NULL) {
747 xmlRngPErrMemory(ctxt, NULL);
748 return (NULL);
749 }
750 memset(ret, 0, sizeof(xmlRelaxNG));
751
752 return (ret);
753}
754
761static void
762xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema)
763{
764 if (schema == NULL)
765 return;
766
767 if (schema->doc != NULL)
768 xmlFreeDoc(schema->doc);
769 if (schema->defTab != NULL) {
770 int i;
771
772 for (i = 0; i < schema->defNr; i++)
773 xmlRelaxNGFreeDefine(schema->defTab[i]);
774 xmlFree(schema->defTab);
775 }
776
778}
779
786void
787xmlRelaxNGFree(xmlRelaxNGPtr schema)
788{
789 if (schema == NULL)
790 return;
791
792 if (schema->topgrammar != NULL)
793 xmlRelaxNGFreeGrammar(schema->topgrammar);
794 if (schema->doc != NULL)
795 xmlFreeDoc(schema->doc);
796 if (schema->documents != NULL)
797 xmlRelaxNGFreeDocumentList(schema->documents);
798 if (schema->includes != NULL)
799 xmlRelaxNGFreeIncludeList(schema->includes);
800 if (schema->defTab != NULL) {
801 int i;
802
803 for (i = 0; i < schema->defNr; i++)
804 xmlRelaxNGFreeDefine(schema->defTab[i]);
805 xmlFree(schema->defTab);
806 }
807
809}
810
819static xmlRelaxNGGrammarPtr
820xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)
821{
822 xmlRelaxNGGrammarPtr ret;
823
824 ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));
825 if (ret == NULL) {
826 xmlRngPErrMemory(ctxt, NULL);
827 return (NULL);
828 }
829 memset(ret, 0, sizeof(xmlRelaxNGGrammar));
830
831 return (ret);
832}
833
840static void
841xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar)
842{
843 if (grammar == NULL)
844 return;
845
846 if (grammar->children != NULL) {
847 xmlRelaxNGFreeGrammar(grammar->children);
848 }
849 if (grammar->next != NULL) {
850 xmlRelaxNGFreeGrammar(grammar->next);
851 }
852 if (grammar->refs != NULL) {
853 xmlHashFree(grammar->refs, NULL);
854 }
855 if (grammar->defs != NULL) {
856 xmlHashFree(grammar->defs, NULL);
857 }
858
859 xmlFree(grammar);
860}
861
871static xmlRelaxNGDefinePtr
872xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
873{
874 xmlRelaxNGDefinePtr ret;
875
876 if (ctxt->defMax == 0) {
877 ctxt->defMax = 16;
878 ctxt->defNr = 0;
879 ctxt->defTab = (xmlRelaxNGDefinePtr *)
880 xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
881 if (ctxt->defTab == NULL) {
882 xmlRngPErrMemory(ctxt, "allocating define\n");
883 return (NULL);
884 }
885 } else if (ctxt->defMax <= ctxt->defNr) {
886 xmlRelaxNGDefinePtr *tmp;
887
888 ctxt->defMax *= 2;
889 tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,
890 ctxt->defMax *
891 sizeof
892 (xmlRelaxNGDefinePtr));
893 if (tmp == NULL) {
894 xmlRngPErrMemory(ctxt, "allocating define\n");
895 return (NULL);
896 }
897 ctxt->defTab = tmp;
898 }
899 ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
900 if (ret == NULL) {
901 xmlRngPErrMemory(ctxt, "allocating define\n");
902 return (NULL);
903 }
904 memset(ret, 0, sizeof(xmlRelaxNGDefine));
905 ctxt->defTab[ctxt->defNr++] = ret;
906 ret->node = node;
907 ret->depth = -1;
908 return (ret);
909}
910
917static void
918xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions)
919{
920 xmlRelaxNGInterleaveGroupPtr group;
921 int j;
922
923 if (partitions != NULL) {
924 if (partitions->groups != NULL) {
925 for (j = 0; j < partitions->nbgroups; j++) {
926 group = partitions->groups[j];
927 if (group != NULL) {
928 if (group->defs != NULL)
929 xmlFree(group->defs);
930 if (group->attrs != NULL)
931 xmlFree(group->attrs);
932 xmlFree(group);
933 }
934 }
935 xmlFree(partitions->groups);
936 }
937 if (partitions->triage != NULL) {
938 xmlHashFree(partitions->triage, NULL);
939 }
940 xmlFree(partitions);
941 }
942}
943
950static void
951xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define)
952{
953 if (define == NULL)
954 return;
955
956 if ((define->type == XML_RELAXNG_VALUE) && (define->attrs != NULL)) {
957 xmlRelaxNGTypeLibraryPtr lib;
958
959 lib = (xmlRelaxNGTypeLibraryPtr) define->data;
960 if ((lib != NULL) && (lib->freef != NULL))
961 lib->freef(lib->data, (void *) define->attrs);
962 }
963 if ((define->data != NULL) && (define->type == XML_RELAXNG_INTERLEAVE))
964 xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
965 if ((define->data != NULL) && (define->type == XML_RELAXNG_CHOICE))
967 if (define->name != NULL)
969 if (define->ns != NULL)
970 xmlFree(define->ns);
971 if (define->value != NULL)
973 if (define->contModel != NULL)
974 xmlRegFreeRegexp(define->contModel);
976}
977
987static xmlRelaxNGStatesPtr
988xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
989{
990 xmlRelaxNGStatesPtr ret;
991
992 if ((ctxt != NULL) &&
993 (ctxt->freeStates != NULL) && (ctxt->freeStatesNr > 0)) {
994 ctxt->freeStatesNr--;
995 ret = ctxt->freeStates[ctxt->freeStatesNr];
996 ret->nbState = 0;
997 return (ret);
998 }
999 if (size < 16)
1000 size = 16;
1001
1002 ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +
1003 (size -
1004 1) *
1005 sizeof(xmlRelaxNGValidStatePtr));
1006 if (ret == NULL) {
1007 xmlRngVErrMemory(ctxt, "allocating states\n");
1008 return (NULL);
1009 }
1010 ret->nbState = 0;
1011 ret->maxState = size;
1012 ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc((size) *
1013 sizeof
1014 (xmlRelaxNGValidStatePtr));
1015 if (ret->tabState == NULL) {
1016 xmlRngVErrMemory(ctxt, "allocating states\n");
1017 xmlFree(ret);
1018 return (NULL);
1019 }
1020 return (ret);
1021}
1022
1034static int
1035xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,
1036 xmlRelaxNGStatesPtr states,
1037 xmlRelaxNGValidStatePtr state)
1038{
1039 if (state == NULL) {
1040 return (-1);
1041 }
1042 if (states->nbState >= states->maxState) {
1043 xmlRelaxNGValidStatePtr *tmp;
1044 int size;
1045
1046 size = states->maxState * 2;
1047 tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
1048 (size) *
1049 sizeof
1050 (xmlRelaxNGValidStatePtr));
1051 if (tmp == NULL) {
1052 xmlRngVErrMemory(ctxt, "adding states\n");
1053 return (-1);
1054 }
1055 states->tabState = tmp;
1056 states->maxState = size;
1057 }
1058 states->tabState[states->nbState++] = state;
1059 return (1);
1060}
1061
1072static int
1073xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt,
1074 xmlRelaxNGStatesPtr states,
1075 xmlRelaxNGValidStatePtr state)
1076{
1077 int i;
1078
1079 if (state == NULL || states == NULL) {
1080 return (-1);
1081 }
1082 if (states->nbState >= states->maxState) {
1083 xmlRelaxNGValidStatePtr *tmp;
1084 int size;
1085
1086 size = states->maxState * 2;
1087 tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
1088 (size) *
1089 sizeof
1090 (xmlRelaxNGValidStatePtr));
1091 if (tmp == NULL) {
1092 xmlRngVErrMemory(ctxt, "adding states\n");
1093 return (-1);
1094 }
1095 states->tabState = tmp;
1096 states->maxState = size;
1097 }
1098 for (i = 0; i < states->nbState; i++) {
1099 if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) {
1100 xmlRelaxNGFreeValidState(ctxt, state);
1101 return (0);
1102 }
1103 }
1104 states->tabState[states->nbState++] = state;
1105 return (1);
1106}
1107
1115static void
1116xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
1117 xmlRelaxNGStatesPtr states)
1118{
1119 if (states == NULL)
1120 return;
1121 if ((ctxt != NULL) && (ctxt->freeStates == NULL)) {
1122 ctxt->freeStatesMax = 40;
1123 ctxt->freeStatesNr = 0;
1124 ctxt->freeStates = (xmlRelaxNGStatesPtr *)
1125 xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
1126 if (ctxt->freeStates == NULL) {
1127 xmlRngVErrMemory(ctxt, "storing states\n");
1128 }
1129 } else if ((ctxt != NULL)
1130 && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) {
1131 xmlRelaxNGStatesPtr *tmp;
1132
1133 tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates,
1134 2 * ctxt->freeStatesMax *
1135 sizeof
1136 (xmlRelaxNGStatesPtr));
1137 if (tmp == NULL) {
1138 xmlRngVErrMemory(ctxt, "storing states\n");
1139 xmlFree(states->tabState);
1140 xmlFree(states);
1141 return;
1142 }
1143 ctxt->freeStates = tmp;
1144 ctxt->freeStatesMax *= 2;
1145 }
1146 if ((ctxt == NULL) || (ctxt->freeStates == NULL)) {
1147 xmlFree(states->tabState);
1148 xmlFree(states);
1149 } else {
1150 ctxt->freeStates[ctxt->freeStatesNr++] = states;
1151 }
1152}
1153
1163static xmlRelaxNGValidStatePtr
1164xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
1165{
1166 xmlRelaxNGValidStatePtr ret;
1167 xmlAttrPtr attr;
1168 xmlAttrPtr attrs[MAX_ATTR];
1169 int nbAttrs = 0;
1170 xmlNodePtr root = NULL;
1171
1172 if (node == NULL) {
1173 root = xmlDocGetRootElement(ctxt->doc);
1174 if (root == NULL)
1175 return (NULL);
1176 } else {
1177 attr = node->properties;
1178 while (attr != NULL) {
1179 if (nbAttrs < MAX_ATTR)
1180 attrs[nbAttrs++] = attr;
1181 else
1182 nbAttrs++;
1183 attr = attr->next;
1184 }
1185 }
1186 if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
1187 ctxt->freeState->nbState--;
1188 ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
1189 } else {
1190 ret =
1191 (xmlRelaxNGValidStatePtr)
1192 xmlMalloc(sizeof(xmlRelaxNGValidState));
1193 if (ret == NULL) {
1194 xmlRngVErrMemory(ctxt, "allocating states\n");
1195 return (NULL);
1196 }
1197 memset(ret, 0, sizeof(xmlRelaxNGValidState));
1198 }
1199 ret->value = NULL;
1200 ret->endvalue = NULL;
1201 if (node == NULL) {
1202 ret->node = (xmlNodePtr) ctxt->doc;
1203 ret->seq = root;
1204 } else {
1205 ret->node = node;
1206 ret->seq = node->children;
1207 }
1208 ret->nbAttrs = 0;
1209 if (nbAttrs > 0) {
1210 if (ret->attrs == NULL) {
1211 if (nbAttrs < 4)
1212 ret->maxAttrs = 4;
1213 else
1214 ret->maxAttrs = nbAttrs;
1215 ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
1216 sizeof(xmlAttrPtr));
1217 if (ret->attrs == NULL) {
1218 xmlRngVErrMemory(ctxt, "allocating states\n");
1219 return (ret);
1220 }
1221 } else if (ret->maxAttrs < nbAttrs) {
1222 xmlAttrPtr *tmp;
1223
1224 tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *
1225 sizeof(xmlAttrPtr));
1226 if (tmp == NULL) {
1227 xmlRngVErrMemory(ctxt, "allocating states\n");
1228 return (ret);
1229 }
1230 ret->attrs = tmp;
1231 ret->maxAttrs = nbAttrs;
1232 }
1233 ret->nbAttrs = nbAttrs;
1234 if (nbAttrs < MAX_ATTR) {
1235 memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs);
1236 } else {
1237 attr = node->properties;
1238 nbAttrs = 0;
1239 while (attr != NULL) {
1240 ret->attrs[nbAttrs++] = attr;
1241 attr = attr->next;
1242 }
1243 }
1244 }
1245 ret->nbAttrLeft = ret->nbAttrs;
1246 return (ret);
1247}
1248
1258static xmlRelaxNGValidStatePtr
1259xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
1260 xmlRelaxNGValidStatePtr state)
1261{
1262 xmlRelaxNGValidStatePtr ret;
1263 unsigned int maxAttrs;
1264 xmlAttrPtr *attrs;
1265
1266 if (state == NULL)
1267 return (NULL);
1268 if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
1269 ctxt->freeState->nbState--;
1270 ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
1271 } else {
1272 ret =
1273 (xmlRelaxNGValidStatePtr)
1274 xmlMalloc(sizeof(xmlRelaxNGValidState));
1275 if (ret == NULL) {
1276 xmlRngVErrMemory(ctxt, "allocating states\n");
1277 return (NULL);
1278 }
1279 memset(ret, 0, sizeof(xmlRelaxNGValidState));
1280 }
1281 attrs = ret->attrs;
1282 maxAttrs = ret->maxAttrs;
1283 memcpy(ret, state, sizeof(xmlRelaxNGValidState));
1284 ret->attrs = attrs;
1285 ret->maxAttrs = maxAttrs;
1286 if (state->nbAttrs > 0) {
1287 if (ret->attrs == NULL) {
1288 ret->maxAttrs = state->maxAttrs;
1289 ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
1290 sizeof(xmlAttrPtr));
1291 if (ret->attrs == NULL) {
1292 xmlRngVErrMemory(ctxt, "allocating states\n");
1293 ret->nbAttrs = 0;
1294 return (ret);
1295 }
1296 } else if (ret->maxAttrs < state->nbAttrs) {
1297 xmlAttrPtr *tmp;
1298
1299 tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *
1300 sizeof(xmlAttrPtr));
1301 if (tmp == NULL) {
1302 xmlRngVErrMemory(ctxt, "allocating states\n");
1303 ret->nbAttrs = 0;
1304 return (ret);
1305 }
1306 ret->maxAttrs = state->maxAttrs;
1307 ret->attrs = tmp;
1308 }
1309 memcpy(ret->attrs, state->attrs,
1310 state->nbAttrs * sizeof(xmlAttrPtr));
1311 }
1312 return (ret);
1313}
1314
1325static int
1326xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
1327 xmlRelaxNGValidStatePtr state1,
1328 xmlRelaxNGValidStatePtr state2)
1329{
1330 int i;
1331
1332 if ((state1 == NULL) || (state2 == NULL))
1333 return (0);
1334 if (state1 == state2)
1335 return (1);
1336 if (state1->node != state2->node)
1337 return (0);
1338 if (state1->seq != state2->seq)
1339 return (0);
1340 if (state1->nbAttrLeft != state2->nbAttrLeft)
1341 return (0);
1342 if (state1->nbAttrs != state2->nbAttrs)
1343 return (0);
1344 if (state1->endvalue != state2->endvalue)
1345 return (0);
1346 if ((state1->value != state2->value) &&
1347 (!xmlStrEqual(state1->value, state2->value)))
1348 return (0);
1349 for (i = 0; i < state1->nbAttrs; i++) {
1350 if (state1->attrs[i] != state2->attrs[i])
1351 return (0);
1352 }
1353 return (1);
1354}
1355
1362static void
1363xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
1364 xmlRelaxNGValidStatePtr state)
1365{
1366 if (state == NULL)
1367 return;
1368
1369 if ((ctxt != NULL) && (ctxt->freeState == NULL)) {
1370 ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40);
1371 }
1372 if ((ctxt == NULL) || (ctxt->freeState == NULL)) {
1373 if (state->attrs != NULL)
1374 xmlFree(state->attrs);
1375 xmlFree(state);
1376 } else {
1377 xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state);
1378 }
1379}
1380
1381/************************************************************************
1382 * *
1383 * Semi internal functions *
1384 * *
1385 ************************************************************************/
1386
1397int
1398xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags)
1399{
1400 if (ctxt == NULL) return(-1);
1401 if (flags & XML_RELAXNGP_FREE_DOC) {
1402 ctxt->crng |= XML_RELAXNGP_FREE_DOC;
1403 flags -= XML_RELAXNGP_FREE_DOC;
1404 }
1405 if (flags & XML_RELAXNGP_CRNG) {
1406 ctxt->crng |= XML_RELAXNGP_CRNG;
1407 flags -= XML_RELAXNGP_CRNG;
1408 }
1409 if (flags != 0) return(-1);
1410 return(0);
1411}
1412
1413/************************************************************************
1414 * *
1415 * Document functions *
1416 * *
1417 ************************************************************************/
1418static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
1419 xmlDocPtr doc);
1420
1430static int
1431xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
1432 xmlRelaxNGIncludePtr value)
1433{
1434 if (ctxt->incTab == NULL) {
1435 ctxt->incMax = 4;
1436 ctxt->incNr = 0;
1437 ctxt->incTab =
1438 (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *
1439 sizeof(ctxt->incTab[0]));
1440 if (ctxt->incTab == NULL) {
1441 xmlRngPErrMemory(ctxt, "allocating include\n");
1442 return (0);
1443 }
1444 }
1445 if (ctxt->incNr >= ctxt->incMax) {
1446 ctxt->incMax *= 2;
1447 ctxt->incTab =
1448 (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,
1449 ctxt->incMax *
1450 sizeof(ctxt->incTab[0]));
1451 if (ctxt->incTab == NULL) {
1452 xmlRngPErrMemory(ctxt, "allocating include\n");
1453 return (0);
1454 }
1455 }
1456 ctxt->incTab[ctxt->incNr] = value;
1457 ctxt->inc = value;
1458 return (ctxt->incNr++);
1459}
1460
1469static xmlRelaxNGIncludePtr
1470xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt)
1471{
1472 xmlRelaxNGIncludePtr ret;
1473
1474 if (ctxt->incNr <= 0)
1475 return (NULL);
1476 ctxt->incNr--;
1477 if (ctxt->incNr > 0)
1478 ctxt->inc = ctxt->incTab[ctxt->incNr - 1];
1479 else
1480 ctxt->inc = NULL;
1481 ret = ctxt->incTab[ctxt->incNr];
1482 ctxt->incTab[ctxt->incNr] = NULL;
1483 return (ret);
1484}
1485
1497static int
1498xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
1499 const xmlChar * URL ATTRIBUTE_UNUSED,
1500 xmlNodePtr target, const xmlChar * name)
1501{
1502 int found = 0;
1503 xmlNodePtr tmp, tmp2;
1504 xmlChar *name2;
1505
1506 tmp = target;
1507 while (tmp != NULL) {
1508 tmp2 = tmp->next;
1509 if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) {
1510 found = 1;
1511 xmlUnlinkNode(tmp);
1512 xmlFreeNode(tmp);
1513 } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) {
1514 name2 = xmlGetProp(tmp, BAD_CAST "name");
1515 xmlRelaxNGNormExtSpace(name2);
1516 if (name2 != NULL) {
1517 if (xmlStrEqual(name, name2)) {
1518 found = 1;
1519 xmlUnlinkNode(tmp);
1520 xmlFreeNode(tmp);
1521 }
1522 xmlFree(name2);
1523 }
1524 } else if (IS_RELAXNG(tmp, "include")) {
1525 xmlChar *href = NULL;
1526 xmlRelaxNGDocumentPtr inc = tmp->psvi;
1527
1528 if ((inc != NULL) && (inc->doc != NULL) &&
1529 (inc->doc->children != NULL)) {
1530
1531 if (xmlStrEqual
1532 (inc->doc->children->name, BAD_CAST "grammar")) {
1533 if (xmlRelaxNGRemoveRedefine(ctxt, href,
1534 xmlDocGetRootElement(inc->doc)->children,
1535 name) == 1) {
1536 found = 1;
1537 }
1538 }
1539 }
1540 if (xmlRelaxNGRemoveRedefine(ctxt, URL, tmp->children, name) == 1) {
1541 found = 1;
1542 }
1543 }
1544 tmp = tmp2;
1545 }
1546 return (found);
1547}
1548
1562static xmlRelaxNGIncludePtr
1563xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
1564 xmlNodePtr node, const xmlChar * ns)
1565{
1566 xmlRelaxNGIncludePtr ret = NULL;
1567 xmlDocPtr doc;
1568 int i;
1569 xmlNodePtr root, cur;
1570
1571 /*
1572 * check against recursion in the stack
1573 */
1574 for (i = 0; i < ctxt->incNr; i++) {
1575 if (xmlStrEqual(ctxt->incTab[i]->href, URL)) {
1576 xmlRngPErr(ctxt, NULL, XML_RNGP_INCLUDE_RECURSE,
1577 "Detected an Include recursion for %s\n", URL,
1578 NULL);
1579 return (NULL);
1580 }
1581 }
1582
1583 /*
1584 * load the document
1585 */
1586 doc = xmlReadFile((const char *) URL,NULL,0);
1587 if (doc == NULL) {
1588 xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR,
1589 "xmlRelaxNG: could not load %s\n", URL, NULL);
1590 return (NULL);
1591 }
1592
1593 /*
1594 * Allocate the document structures and register it first.
1595 */
1596 ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));
1597 if (ret == NULL) {
1598 xmlRngPErrMemory(ctxt, "allocating include\n");
1599 xmlFreeDoc(doc);
1600 return (NULL);
1601 }
1602 memset(ret, 0, sizeof(xmlRelaxNGInclude));
1603 ret->doc = doc;
1604 ret->href = xmlStrdup(URL);
1605 ret->next = ctxt->includes;
1606 ctxt->includes = ret;
1607
1608 /*
1609 * transmit the ns if needed
1610 */
1611 if (ns != NULL) {
1612 root = xmlDocGetRootElement(doc);
1613 if (root != NULL) {
1614 if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
1615 xmlSetProp(root, BAD_CAST "ns", ns);
1616 }
1617 }
1618 }
1619
1620 /*
1621 * push it on the stack
1622 */
1623 xmlRelaxNGIncludePush(ctxt, ret);
1624
1625 /*
1626 * Some preprocessing of the document content, this include recursing
1627 * in the include stack.
1628 */
1629
1630 doc = xmlRelaxNGCleanupDoc(ctxt, doc);
1631 if (doc == NULL) {
1632 ctxt->inc = NULL;
1633 return (NULL);
1634 }
1635
1636 /*
1637 * Pop up the include from the stack
1638 */
1639 xmlRelaxNGIncludePop(ctxt);
1640
1641 /*
1642 * Check that the top element is a grammar
1643 */
1644 root = xmlDocGetRootElement(doc);
1645 if (root == NULL) {
1646 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY,
1647 "xmlRelaxNG: included document is empty %s\n", URL,
1648 NULL);
1649 return (NULL);
1650 }
1651 if (!IS_RELAXNG(root, "grammar")) {
1652 xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
1653 "xmlRelaxNG: included document %s root is not a grammar\n",
1654 URL, NULL);
1655 return (NULL);
1656 }
1657
1658 /*
1659 * Elimination of redefined rules in the include.
1660 */
1661 cur = node->children;
1662 while (cur != NULL) {
1663 if (IS_RELAXNG(cur, "start")) {
1664 int found = 0;
1665
1666 found =
1667 xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);
1668 if (!found) {
1669 xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING,
1670 "xmlRelaxNG: include %s has a start but not the included grammar\n",
1671 URL, NULL);
1672 }
1673 } else if (IS_RELAXNG(cur, "define")) {
1674 xmlChar *name;
1675
1676 name = xmlGetProp(cur, BAD_CAST "name");
1677 if (name == NULL) {
1678 xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING,
1679 "xmlRelaxNG: include %s has define without name\n",
1680 URL, NULL);
1681 } else {
1682 int found;
1683
1684 xmlRelaxNGNormExtSpace(name);
1685 found = xmlRelaxNGRemoveRedefine(ctxt, URL,
1686 root->children, name);
1687 if (!found) {
1688 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING,
1689 "xmlRelaxNG: include %s has a define %s but not the included grammar\n",
1690 URL, name);
1691 }
1692 xmlFree(name);
1693 }
1694 }
1695 if (IS_RELAXNG(cur, "div") && cur->children != NULL) {
1696 cur = cur->children;
1697 } else {
1698 if (cur->next != NULL) {
1699 cur = cur->next;
1700 } else {
1701 while (cur->parent != node && cur->parent->next == NULL) {
1702 cur = cur->parent;
1703 }
1704 cur = cur->parent != node ? cur->parent->next : NULL;
1705 }
1706 }
1707 }
1708
1709
1710 return (ret);
1711}
1712
1725static int
1726xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
1727 xmlRelaxNGValidErr err, const xmlChar * arg1,
1728 const xmlChar * arg2, int dup)
1729{
1730 xmlRelaxNGValidErrorPtr cur;
1731
1732 if (ctxt->errTab == NULL) {
1733 ctxt->errMax = 8;
1734 ctxt->errNr = 0;
1735 ctxt->errTab =
1736 (xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax *
1737 sizeof
1738 (xmlRelaxNGValidError));
1739 if (ctxt->errTab == NULL) {
1740 xmlRngVErrMemory(ctxt, "pushing error\n");
1741 return (0);
1742 }
1743 ctxt->err = NULL;
1744 }
1745 if (ctxt->errNr >= ctxt->errMax) {
1746 ctxt->errMax *= 2;
1747 ctxt->errTab =
1748 (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,
1749 ctxt->errMax *
1750 sizeof
1751 (xmlRelaxNGValidError));
1752 if (ctxt->errTab == NULL) {
1753 xmlRngVErrMemory(ctxt, "pushing error\n");
1754 return (0);
1755 }
1756 ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
1757 }
1758 if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
1759 (ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err))
1760 return (ctxt->errNr);
1761 cur = &ctxt->errTab[ctxt->errNr];
1762 cur->err = err;
1763 if (dup) {
1764 cur->arg1 = xmlStrdup(arg1);
1765 cur->arg2 = xmlStrdup(arg2);
1766 cur->flags = ERROR_IS_DUP;
1767 } else {
1768 cur->arg1 = arg1;
1769 cur->arg2 = arg2;
1770 cur->flags = 0;
1771 }
1772 if (ctxt->state != NULL) {
1773 cur->node = ctxt->state->node;
1774 cur->seq = ctxt->state->seq;
1775 } else {
1776 cur->node = NULL;
1777 cur->seq = NULL;
1778 }
1779 ctxt->err = cur;
1780 return (ctxt->errNr++);
1781}
1782
1789static void
1790xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
1791{
1792 xmlRelaxNGValidErrorPtr cur;
1793
1794 if (ctxt->errNr <= 0) {
1795 ctxt->err = NULL;
1796 return;
1797 }
1798 ctxt->errNr--;
1799 if (ctxt->errNr > 0)
1800 ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
1801 else
1802 ctxt->err = NULL;
1803 cur = &ctxt->errTab[ctxt->errNr];
1804 if (cur->flags & ERROR_IS_DUP) {
1805 if (cur->arg1 != NULL)
1806 xmlFree((xmlChar *) cur->arg1);
1807 cur->arg1 = NULL;
1808 if (cur->arg2 != NULL)
1809 xmlFree((xmlChar *) cur->arg2);
1810 cur->arg2 = NULL;
1811 cur->flags = 0;
1812 }
1813}
1814
1824static int
1825xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
1826 xmlRelaxNGDocumentPtr value)
1827{
1828 if (ctxt->docTab == NULL) {
1829 ctxt->docMax = 4;
1830 ctxt->docNr = 0;
1831 ctxt->docTab =
1832 (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *
1833 sizeof(ctxt->docTab[0]));
1834 if (ctxt->docTab == NULL) {
1835 xmlRngPErrMemory(ctxt, "adding document\n");
1836 return (0);
1837 }
1838 }
1839 if (ctxt->docNr >= ctxt->docMax) {
1840 ctxt->docMax *= 2;
1841 ctxt->docTab =
1842 (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,
1843 ctxt->docMax *
1844 sizeof(ctxt->docTab[0]));
1845 if (ctxt->docTab == NULL) {
1846 xmlRngPErrMemory(ctxt, "adding document\n");
1847 return (0);
1848 }
1849 }
1850 ctxt->docTab[ctxt->docNr] = value;
1851 ctxt->doc = value;
1852 return (ctxt->docNr++);
1853}
1854
1863static xmlRelaxNGDocumentPtr
1864xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)
1865{
1866 xmlRelaxNGDocumentPtr ret;
1867
1868 if (ctxt->docNr <= 0)
1869 return (NULL);
1870 ctxt->docNr--;
1871 if (ctxt->docNr > 0)
1872 ctxt->doc = ctxt->docTab[ctxt->docNr - 1];
1873 else
1874 ctxt->doc = NULL;
1875 ret = ctxt->docTab[ctxt->docNr];
1876 ctxt->docTab[ctxt->docNr] = NULL;
1877 return (ret);
1878}
1879
1892static xmlRelaxNGDocumentPtr
1893xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
1894 const xmlChar * URL, const xmlChar * ns)
1895{
1896 xmlRelaxNGDocumentPtr ret = NULL;
1897 xmlDocPtr doc;
1898 xmlNodePtr root;
1899 int i;
1900
1901 /*
1902 * check against recursion in the stack
1903 */
1904 for (i = 0; i < ctxt->docNr; i++) {
1905 if (xmlStrEqual(ctxt->docTab[i]->href, URL)) {
1906 xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE,
1907 "Detected an externalRef recursion for %s\n", URL,
1908 NULL);
1909 return (NULL);
1910 }
1911 }
1912
1913 /*
1914 * load the document
1915 */
1916 doc = xmlReadFile((const char *) URL,NULL,0);
1917 if (doc == NULL) {
1918 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
1919 "xmlRelaxNG: could not load %s\n", URL, NULL);
1920 return (NULL);
1921 }
1922
1923 /*
1924 * Allocate the document structures and register it first.
1925 */
1926 ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
1927 if (ret == NULL) {
1928 xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,
1929 "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);
1930 xmlFreeDoc(doc);
1931 return (NULL);
1932 }
1933 memset(ret, 0, sizeof(xmlRelaxNGDocument));
1934 ret->doc = doc;
1935 ret->href = xmlStrdup(URL);
1936 ret->next = ctxt->documents;
1937 ret->externalRef = 1;
1938 ctxt->documents = ret;
1939
1940 /*
1941 * transmit the ns if needed
1942 */
1943 if (ns != NULL) {
1944 root = xmlDocGetRootElement(doc);
1945 if (root != NULL) {
1946 if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
1947 xmlSetProp(root, BAD_CAST "ns", ns);
1948 }
1949 }
1950 }
1951
1952 /*
1953 * push it on the stack and register it in the hash table
1954 */
1955 xmlRelaxNGDocumentPush(ctxt, ret);
1956
1957 /*
1958 * Some preprocessing of the document content
1959 */
1960 doc = xmlRelaxNGCleanupDoc(ctxt, doc);
1961 if (doc == NULL) {
1962 ctxt->doc = NULL;
1963 return (NULL);
1964 }
1965
1966 xmlRelaxNGDocumentPop(ctxt);
1967
1968 return (ret);
1969}
1970
1971/************************************************************************
1972 * *
1973 * Error functions *
1974 * *
1975 ************************************************************************/
1976
1977#define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
1978#define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
1979#define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
1980#define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
1981#define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
1982
1983static const char *
1984xmlRelaxNGDefName(xmlRelaxNGDefinePtr def)
1985{
1986 if (def == NULL)
1987 return ("none");
1988 switch (def->type) {
1989 case XML_RELAXNG_EMPTY:
1990 return ("empty");
1991 case XML_RELAXNG_NOT_ALLOWED:
1992 return ("notAllowed");
1993 case XML_RELAXNG_EXCEPT:
1994 return ("except");
1995 case XML_RELAXNG_TEXT:
1996 return ("text");
1997 case XML_RELAXNG_ELEMENT:
1998 return ("element");
1999 case XML_RELAXNG_DATATYPE:
2000 return ("datatype");
2001 case XML_RELAXNG_VALUE:
2002 return ("value");
2003 case XML_RELAXNG_LIST:
2004 return ("list");
2005 case XML_RELAXNG_ATTRIBUTE:
2006 return ("attribute");
2007 case XML_RELAXNG_DEF:
2008 return ("def");
2009 case XML_RELAXNG_REF:
2010 return ("ref");
2011 case XML_RELAXNG_EXTERNALREF:
2012 return ("externalRef");
2013 case XML_RELAXNG_PARENTREF:
2014 return ("parentRef");
2015 case XML_RELAXNG_OPTIONAL:
2016 return ("optional");
2017 case XML_RELAXNG_ZEROORMORE:
2018 return ("zeroOrMore");
2019 case XML_RELAXNG_ONEORMORE:
2020 return ("oneOrMore");
2021 case XML_RELAXNG_CHOICE:
2022 return ("choice");
2023 case XML_RELAXNG_GROUP:
2024 return ("group");
2025 case XML_RELAXNG_INTERLEAVE:
2026 return ("interleave");
2027 case XML_RELAXNG_START:
2028 return ("start");
2029 case XML_RELAXNG_NOOP:
2030 return ("noop");
2031 case XML_RELAXNG_PARAM:
2032 return ("param");
2033 }
2034 return ("unknown");
2035}
2036
2047static xmlChar *
2048xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
2049 const xmlChar * arg2)
2050{
2051 char msg[1000];
2052 xmlChar *result;
2053
2054 if (arg1 == NULL)
2055 arg1 = BAD_CAST "";
2056 if (arg2 == NULL)
2057 arg2 = BAD_CAST "";
2058
2059 msg[0] = 0;
2060 switch (err) {
2061 case XML_RELAXNG_OK:
2062 return (NULL);
2063 case XML_RELAXNG_ERR_MEMORY:
2064 return (xmlCharStrdup("out of memory\n"));
2065 case XML_RELAXNG_ERR_TYPE:
2066 snprintf(msg, 1000, "failed to validate type %s\n", arg1);
2067 break;
2068 case XML_RELAXNG_ERR_TYPEVAL:
2069 snprintf(msg, 1000, "Type %s doesn't allow value '%s'\n", arg1,
2070 arg2);
2071 break;
2072 case XML_RELAXNG_ERR_DUPID:
2073 snprintf(msg, 1000, "ID %s redefined\n", arg1);
2074 break;
2075 case XML_RELAXNG_ERR_TYPECMP:
2076 snprintf(msg, 1000, "failed to compare type %s\n", arg1);
2077 break;
2078 case XML_RELAXNG_ERR_NOSTATE:
2079 return (xmlCharStrdup("Internal error: no state\n"));
2080 case XML_RELAXNG_ERR_NODEFINE:
2081 return (xmlCharStrdup("Internal error: no define\n"));
2082 case XML_RELAXNG_ERR_INTERNAL:
2083 snprintf(msg, 1000, "Internal error: %s\n", arg1);
2084 break;
2085 case XML_RELAXNG_ERR_LISTEXTRA:
2086 snprintf(msg, 1000, "Extra data in list: %s\n", arg1);
2087 break;
2088 case XML_RELAXNG_ERR_INTERNODATA:
2089 return (xmlCharStrdup
2090 ("Internal: interleave block has no data\n"));
2091 case XML_RELAXNG_ERR_INTERSEQ:
2092 return (xmlCharStrdup("Invalid sequence in interleave\n"));
2093 case XML_RELAXNG_ERR_INTEREXTRA:
2094 snprintf(msg, 1000, "Extra element %s in interleave\n", arg1);
2095 break;
2096 case XML_RELAXNG_ERR_ELEMNAME:
2097 snprintf(msg, 1000, "Expecting element %s, got %s\n", arg1,
2098 arg2);
2099 break;
2100 case XML_RELAXNG_ERR_ELEMNONS:
2101 snprintf(msg, 1000, "Expecting a namespace for element %s\n",
2102 arg1);
2103 break;
2104 case XML_RELAXNG_ERR_ELEMWRONGNS:
2105 snprintf(msg, 1000,
2106 "Element %s has wrong namespace: expecting %s\n", arg1,
2107 arg2);
2108 break;
2109 case XML_RELAXNG_ERR_ELEMWRONG:
2110 snprintf(msg, 1000, "Did not expect element %s there\n", arg1);
2111 break;
2112 case XML_RELAXNG_ERR_TEXTWRONG:
2113 snprintf(msg, 1000,
2114 "Did not expect text in element %s content\n", arg1);
2115 break;
2116 case XML_RELAXNG_ERR_ELEMEXTRANS:
2117 snprintf(msg, 1000, "Expecting no namespace for element %s\n",
2118 arg1);
2119 break;
2120 case XML_RELAXNG_ERR_ELEMNOTEMPTY:
2121 snprintf(msg, 1000, "Expecting element %s to be empty\n", arg1);
2122 break;
2123 case XML_RELAXNG_ERR_NOELEM:
2124 snprintf(msg, 1000, "Expecting an element %s, got nothing\n",
2125 arg1);
2126 break;
2127 case XML_RELAXNG_ERR_NOTELEM:
2128 return (xmlCharStrdup("Expecting an element got text\n"));
2129 case XML_RELAXNG_ERR_ATTRVALID:
2130 snprintf(msg, 1000, "Element %s failed to validate attributes\n",
2131 arg1);
2132 break;
2133 case XML_RELAXNG_ERR_CONTENTVALID:
2134 snprintf(msg, 1000, "Element %s failed to validate content\n",
2135 arg1);
2136 break;
2137 case XML_RELAXNG_ERR_EXTRACONTENT:
2138 snprintf(msg, 1000, "Element %s has extra content: %s\n",
2139 arg1, arg2);
2140 break;
2141 case XML_RELAXNG_ERR_INVALIDATTR:
2142 snprintf(msg, 1000, "Invalid attribute %s for element %s\n",
2143 arg1, arg2);
2144 break;
2145 case XML_RELAXNG_ERR_LACKDATA:
2146 snprintf(msg, 1000, "Datatype element %s contains no data\n",
2147 arg1);
2148 break;
2149 case XML_RELAXNG_ERR_DATAELEM:
2150 snprintf(msg, 1000, "Datatype element %s has child elements\n",
2151 arg1);
2152 break;
2153 case XML_RELAXNG_ERR_VALELEM:
2154 snprintf(msg, 1000, "Value element %s has child elements\n",
2155 arg1);
2156 break;
2157 case XML_RELAXNG_ERR_LISTELEM:
2158 snprintf(msg, 1000, "List element %s has child elements\n",
2159 arg1);
2160 break;
2161 case XML_RELAXNG_ERR_DATATYPE:
2162 snprintf(msg, 1000, "Error validating datatype %s\n", arg1);
2163 break;
2164 case XML_RELAXNG_ERR_VALUE:
2165 snprintf(msg, 1000, "Error validating value %s\n", arg1);
2166 break;
2167 case XML_RELAXNG_ERR_LIST:
2168 return (xmlCharStrdup("Error validating list\n"));
2169 case XML_RELAXNG_ERR_NOGRAMMAR:
2170 return (xmlCharStrdup("No top grammar defined\n"));
2171 case XML_RELAXNG_ERR_EXTRADATA:
2172 return (xmlCharStrdup("Extra data in the document\n"));
2173 default:
2174 return (xmlCharStrdup("Unknown error !\n"));
2175 }
2176 if (msg[0] == 0) {
2177 snprintf(msg, 1000, "Unknown error code %d\n", err);
2178 }
2179 msg[1000 - 1] = 0;
2181 return (xmlEscapeFormatString(&result));
2182}
2183
2195static void
2196xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt,
2197 xmlRelaxNGValidErr err, xmlNodePtr node,
2198 xmlNodePtr child, const xmlChar * arg1,
2199 const xmlChar * arg2)
2200{
2201 xmlChar *msg;
2202
2203 if (ctxt->flags & FLAGS_NOERROR)
2204 return;
2205
2206 msg = xmlRelaxNGGetErrorString(err, arg1, arg2);
2207 if (msg == NULL)
2208 return;
2209
2210 if (ctxt->errNo == XML_RELAXNG_OK)
2211 ctxt->errNo = err;
2212 xmlRngVErr(ctxt, (child == NULL ? node : child), err,
2213 (const char *) msg, arg1, arg2);
2214 xmlFree(msg);
2215}
2216
2224static void
2225xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level)
2226{
2227 int i;
2228 xmlRelaxNGValidErrorPtr err;
2229
2230 for (i = level; i < ctxt->errNr; i++) {
2231 err = &ctxt->errTab[i];
2232 if (err->flags & ERROR_IS_DUP) {
2233 if (err->arg1 != NULL)
2234 xmlFree((xmlChar *) err->arg1);
2235 err->arg1 = NULL;
2236 if (err->arg2 != NULL)
2237 xmlFree((xmlChar *) err->arg2);
2238 err->arg2 = NULL;
2239 err->flags = 0;
2240 }
2241 }
2242 ctxt->errNr = level;
2243 if (ctxt->errNr <= 0)
2244 ctxt->err = NULL;
2245}
2246
2253static void
2254xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt)
2255{
2256 int i, j, k;
2257 xmlRelaxNGValidErrorPtr err, dup;
2258
2259 for (i = 0, k = 0; i < ctxt->errNr; i++) {
2260 err = &ctxt->errTab[i];
2261 if (k < MAX_ERROR) {
2262 for (j = 0; j < i; j++) {
2263 dup = &ctxt->errTab[j];
2264 if ((err->err == dup->err) && (err->node == dup->node) &&
2265 (xmlStrEqual(err->arg1, dup->arg1)) &&
2266 (xmlStrEqual(err->arg2, dup->arg2))) {
2267 goto skip;
2268 }
2269 }
2270 xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,
2271 err->arg1, err->arg2);
2272 k++;
2273 }
2274 skip:
2275 if (err->flags & ERROR_IS_DUP) {
2276 if (err->arg1 != NULL)
2277 xmlFree((xmlChar *) err->arg1);
2278 err->arg1 = NULL;
2279 if (err->arg2 != NULL)
2280 xmlFree((xmlChar *) err->arg2);
2281 err->arg2 = NULL;
2282 err->flags = 0;
2283 }
2284 }
2285 ctxt->errNr = 0;
2286}
2287
2299static void
2300xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt,
2301 xmlRelaxNGValidErr err, const xmlChar * arg1,
2302 const xmlChar * arg2, int dup)
2303{
2304 if (ctxt == NULL)
2305 return;
2306 if (ctxt->flags & FLAGS_NOERROR)
2307 return;
2308
2309 /*
2310 * generate the error directly
2311 */
2312 if (((ctxt->flags & FLAGS_IGNORABLE) == 0) ||
2313 (ctxt->flags & FLAGS_NEGATIVE)) {
2314 xmlNodePtr node, seq;
2315
2316 /*
2317 * Flush first any stacked error which might be the
2318 * real cause of the problem.
2319 */
2320 if (ctxt->errNr != 0)
2321 xmlRelaxNGDumpValidError(ctxt);
2322 if (ctxt->state != NULL) {
2323 node = ctxt->state->node;
2324 seq = ctxt->state->seq;
2325 } else {
2326 node = seq = NULL;
2327 }
2328 if ((node == NULL) && (seq == NULL)) {
2329 node = ctxt->pnode;
2330 }
2331 xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2);
2332 }
2333 /*
2334 * Stack the error for later processing if needed
2335 */
2336 else {
2337 xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);
2338 }
2339}
2340
2341
2342/************************************************************************
2343 * *
2344 * Type library hooks *
2345 * *
2346 ************************************************************************/
2347static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt,
2348 const xmlChar * str);
2349
2360static int
2361xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar * type)
2362{
2363 xmlSchemaTypePtr typ;
2364
2365 if (type == NULL)
2366 return (-1);
2367 typ = xmlSchemaGetPredefinedType(type,
2368 BAD_CAST
2369 "http://www.w3.org/2001/XMLSchema");
2370 if (typ == NULL)
2371 return (0);
2372 return (1);
2373}
2374
2387static int
2388xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
2389 const xmlChar * type,
2390 const xmlChar * value,
2391 void **result, xmlNodePtr node)
2392{
2393 xmlSchemaTypePtr typ;
2394 int ret;
2395
2396 if ((type == NULL) || (value == NULL))
2397 return (-1);
2398 typ = xmlSchemaGetPredefinedType(type,
2399 BAD_CAST
2400 "http://www.w3.org/2001/XMLSchema");
2401 if (typ == NULL)
2402 return (-1);
2403 ret = xmlSchemaValPredefTypeNode(typ, value,
2404 (xmlSchemaValPtr *) result, node);
2405 if (ret == 2) /* special ID error code */
2406 return (2);
2407 if (ret == 0)
2408 return (1);
2409 if (ret > 0)
2410 return (0);
2411 return (-1);
2412}
2413
2427static int
2428xmlRelaxNGSchemaFacetCheck(void *data ATTRIBUTE_UNUSED,
2429 const xmlChar * type, const xmlChar * facetname,
2430 const xmlChar * val, const xmlChar * strval,
2431 void *value)
2432{
2433 xmlSchemaFacetPtr facet;
2434 xmlSchemaTypePtr typ;
2435 int ret;
2436
2437 if ((type == NULL) || (strval == NULL))
2438 return (-1);
2439 typ = xmlSchemaGetPredefinedType(type,
2440 BAD_CAST
2441 "http://www.w3.org/2001/XMLSchema");
2442 if (typ == NULL)
2443 return (-1);
2444
2445 facet = xmlSchemaNewFacet();
2446 if (facet == NULL)
2447 return (-1);
2448
2449 if (xmlStrEqual(facetname, BAD_CAST "minInclusive")) {
2450 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
2451 } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive")) {
2452 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
2453 } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive")) {
2454 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
2455 } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive")) {
2456 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
2457 } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits")) {
2458 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
2459 } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits")) {
2460 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
2461 } else if (xmlStrEqual(facetname, BAD_CAST "pattern")) {
2462 facet->type = XML_SCHEMA_FACET_PATTERN;
2463 } else if (xmlStrEqual(facetname, BAD_CAST "enumeration")) {
2464 facet->type = XML_SCHEMA_FACET_ENUMERATION;
2465 } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace")) {
2466 facet->type = XML_SCHEMA_FACET_WHITESPACE;
2467 } else if (xmlStrEqual(facetname, BAD_CAST "length")) {
2468 facet->type = XML_SCHEMA_FACET_LENGTH;
2469 } else if (xmlStrEqual(facetname, BAD_CAST "maxLength")) {
2470 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
2471 } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) {
2472 facet->type = XML_SCHEMA_FACET_MINLENGTH;
2473 } else {
2474 xmlSchemaFreeFacet(facet);
2475 return (-1);
2476 }
2477 facet->value = val;
2478 ret = xmlSchemaCheckFacet(facet, typ, NULL, type);
2479 if (ret != 0) {
2480 xmlSchemaFreeFacet(facet);
2481 return (-1);
2482 }
2483 ret = xmlSchemaValidateFacet(typ, facet, strval, value);
2484 xmlSchemaFreeFacet(facet);
2485 if (ret != 0)
2486 return (-1);
2487 return (0);
2488}
2489
2499static void
2500xmlRelaxNGSchemaFreeValue(void *data ATTRIBUTE_UNUSED, void *value)
2501{
2502 xmlSchemaFreeValue(value);
2503}
2504
2517static int
2518xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
2519 const xmlChar * type,
2520 const xmlChar * value1,
2521 xmlNodePtr ctxt1,
2522 void *comp1,
2523 const xmlChar * value2, xmlNodePtr ctxt2)
2524{
2525 int ret;
2526 xmlSchemaTypePtr typ;
2527 xmlSchemaValPtr res1 = NULL, res2 = NULL;
2528
2529 if ((type == NULL) || (value1 == NULL) || (value2 == NULL))
2530 return (-1);
2531 typ = xmlSchemaGetPredefinedType(type,
2532 BAD_CAST
2533 "http://www.w3.org/2001/XMLSchema");
2534 if (typ == NULL)
2535 return (-1);
2536 if (comp1 == NULL) {
2537 ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1);
2538 if (ret != 0)
2539 return (-1);
2540 if (res1 == NULL)
2541 return (-1);
2542 } else {
2543 res1 = (xmlSchemaValPtr) comp1;
2544 }
2545 ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2);
2546 if (ret != 0) {
2547 if (res1 != (xmlSchemaValPtr) comp1)
2548 xmlSchemaFreeValue(res1);
2549 return (-1);
2550 }
2551 ret = xmlSchemaCompareValues(res1, res2);
2552 if (res1 != (xmlSchemaValPtr) comp1)
2553 xmlSchemaFreeValue(res1);
2554 xmlSchemaFreeValue(res2);
2555 if (ret == -2)
2556 return (-1);
2557 if (ret == 0)
2558 return (1);
2559 return (0);
2560}
2561
2572static int
2573xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED,
2574 const xmlChar * type)
2575{
2576 if (type == NULL)
2577 return (-1);
2578 if (xmlStrEqual(type, BAD_CAST "string"))
2579 return (1);
2580 if (xmlStrEqual(type, BAD_CAST "token"))
2581 return (1);
2582 return (0);
2583}
2584
2597static int
2598xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
2601 void **result ATTRIBUTE_UNUSED,
2602 xmlNodePtr node ATTRIBUTE_UNUSED)
2603{
2604 if (value == NULL)
2605 return (-1);
2606 if (xmlStrEqual(type, BAD_CAST "string"))
2607 return (1);
2608 if (xmlStrEqual(type, BAD_CAST "token")) {
2609 return (1);
2610 }
2611
2612 return (0);
2613}
2614
2627static int
2628xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
2629 const xmlChar * type,
2630 const xmlChar * value1,
2631 xmlNodePtr ctxt1 ATTRIBUTE_UNUSED,
2632 void *comp1 ATTRIBUTE_UNUSED,
2633 const xmlChar * value2,
2634 xmlNodePtr ctxt2 ATTRIBUTE_UNUSED)
2635{
2636 int ret = -1;
2637
2638 if (xmlStrEqual(type, BAD_CAST "string")) {
2639 ret = xmlStrEqual(value1, value2);
2640 } else if (xmlStrEqual(type, BAD_CAST "token")) {
2641 if (!xmlStrEqual(value1, value2)) {
2642 xmlChar *nval, *nvalue;
2643
2644 /*
2645 * TODO: trivial optimizations are possible by
2646 * computing at compile-time
2647 */
2648 nval = xmlRelaxNGNormalize(NULL, value1);
2649 nvalue = xmlRelaxNGNormalize(NULL, value2);
2650
2651 if ((nval == NULL) || (nvalue == NULL))
2652 ret = -1;
2653 else if (xmlStrEqual(nval, nvalue))
2654 ret = 1;
2655 else
2656 ret = 0;
2657 if (nval != NULL)
2658 xmlFree(nval);
2659 if (nvalue != NULL)
2660 xmlFree(nvalue);
2661 } else
2662 ret = 1;
2663 }
2664 return (ret);
2665}
2666
2667static int xmlRelaxNGTypeInitialized = 0;
2668static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
2669
2677static void
2678xmlRelaxNGFreeTypeLibrary(void *payload,
2679 const xmlChar * namespace ATTRIBUTE_UNUSED)
2680{
2681 xmlRelaxNGTypeLibraryPtr lib = (xmlRelaxNGTypeLibraryPtr) payload;
2682 if (lib == NULL)
2683 return;
2684 if (lib->namespace != NULL)
2685 xmlFree((xmlChar *) lib->namespace);
2686 xmlFree(lib);
2687}
2688
2701static int
2702xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,
2703 xmlRelaxNGTypeHave have,
2704 xmlRelaxNGTypeCheck check,
2705 xmlRelaxNGTypeCompare comp,
2706 xmlRelaxNGFacetCheck facet,
2707 xmlRelaxNGTypeFree freef)
2708{
2709 xmlRelaxNGTypeLibraryPtr lib;
2710 int ret;
2711
2712 if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
2713 (check == NULL) || (comp == NULL))
2714 return (-1);
2715 if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
2717 "Relax-NG types library '%s' already registered\n",
2718 namespace);
2719 return (-1);
2720 }
2721 lib =
2722 (xmlRelaxNGTypeLibraryPtr)
2723 xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
2724 if (lib == NULL) {
2725 xmlRngVErrMemory(NULL, "adding types library\n");
2726 return (-1);
2727 }
2728 memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
2729 lib->namespace = xmlStrdup(namespace);
2730 lib->data = data;
2731 lib->have = have;
2732 lib->comp = comp;
2733 lib->check = check;
2734 lib->facet = facet;
2735 lib->freef = freef;
2736 ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
2737 if (ret < 0) {
2739 "Relax-NG types library failed to register '%s'\n",
2740 namespace);
2741 xmlRelaxNGFreeTypeLibrary(lib, namespace);
2742 return (-1);
2743 }
2744 return (0);
2745}
2746
2754int
2755xmlRelaxNGInitTypes(void)
2756{
2757 if (xmlRelaxNGTypeInitialized != 0)
2758 return (0);
2759 xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
2760 if (xmlRelaxNGRegisteredTypes == NULL) {
2762 "Failed to allocate sh table for Relax-NG types\n");
2763 return (-1);
2764 }
2765 xmlRelaxNGRegisterTypeLibrary(BAD_CAST
2766 "http://www.w3.org/2001/XMLSchema-datatypes",
2767 NULL, xmlRelaxNGSchemaTypeHave,
2768 xmlRelaxNGSchemaTypeCheck,
2769 xmlRelaxNGSchemaTypeCompare,
2770 xmlRelaxNGSchemaFacetCheck,
2771 xmlRelaxNGSchemaFreeValue);
2772 xmlRelaxNGRegisterTypeLibrary(xmlRelaxNGNs, NULL,
2773 xmlRelaxNGDefaultTypeHave,
2774 xmlRelaxNGDefaultTypeCheck,
2775 xmlRelaxNGDefaultTypeCompare, NULL,
2776 NULL);
2777 xmlRelaxNGTypeInitialized = 1;
2778 return (0);
2779}
2780
2791void
2792xmlRelaxNGCleanupTypes(void)
2793{
2794 xmlSchemaCleanupTypes();
2795 if (xmlRelaxNGTypeInitialized == 0)
2796 return;
2797 xmlHashFree(xmlRelaxNGRegisteredTypes, xmlRelaxNGFreeTypeLibrary);
2798 xmlRelaxNGTypeInitialized = 0;
2799}
2800
2801/************************************************************************
2802 * *
2803 * Compiling element content into regexp *
2804 * *
2805 * Sometime the element content can be compiled into a pure regexp, *
2806 * This allows a faster execution and streamability at that level *
2807 * *
2808 ************************************************************************/
2809
2810static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,
2811 xmlRelaxNGDefinePtr def);
2812
2821static int
2822xmlRelaxNGIsCompilable(xmlRelaxNGDefinePtr def)
2823{
2824 int ret = -1;
2825
2826 if (def == NULL) {
2827 return (-1);
2828 }
2829 if ((def->type != XML_RELAXNG_ELEMENT) &&
2830 (def->dflags & IS_COMPILABLE))
2831 return (1);
2832 if ((def->type != XML_RELAXNG_ELEMENT) &&
2833 (def->dflags & IS_NOT_COMPILABLE))
2834 return (0);
2835 switch (def->type) {
2836 case XML_RELAXNG_NOOP:
2837 ret = xmlRelaxNGIsCompilable(def->content);
2838 break;
2839 case XML_RELAXNG_TEXT:
2840 case XML_RELAXNG_EMPTY:
2841 ret = 1;
2842 break;
2843 case XML_RELAXNG_ELEMENT:
2844 /*
2845 * Check if the element content is compilable
2846 */
2847 if (((def->dflags & IS_NOT_COMPILABLE) == 0) &&
2848 ((def->dflags & IS_COMPILABLE) == 0)) {
2849 xmlRelaxNGDefinePtr list;
2850
2851 list = def->content;
2852 while (list != NULL) {
2853 ret = xmlRelaxNGIsCompilable(list);
2854 if (ret != 1)
2855 break;
2856 list = list->next;
2857 }
2858 /*
2859 * Because the routine is recursive, we must guard against
2860 * discovering both COMPILABLE and NOT_COMPILABLE
2861 */
2862 if (ret == 0) {
2863 def->dflags &= ~IS_COMPILABLE;
2864 def->dflags |= IS_NOT_COMPILABLE;
2865 }
2866 if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE))
2867 def->dflags |= IS_COMPILABLE;
2868 }
2869 /*
2870 * All elements return a compilable status unless they
2871 * are generic like anyName
2872 */
2873 if ((def->nameClass != NULL) || (def->name == NULL))
2874 ret = 0;
2875 else
2876 ret = 1;
2877 return (ret);
2878 case XML_RELAXNG_REF:
2879 case XML_RELAXNG_EXTERNALREF:
2880 case XML_RELAXNG_PARENTREF:
2881 if (def->depth == -20) {
2882 return (1);
2883 } else {
2884 xmlRelaxNGDefinePtr list;
2885
2886 def->depth = -20;
2887 list = def->content;
2888 while (list != NULL) {
2889 ret = xmlRelaxNGIsCompilable(list);
2890 if (ret != 1)
2891 break;
2892 list = list->next;
2893 }
2894 }
2895 break;
2896 case XML_RELAXNG_START:
2897 case XML_RELAXNG_OPTIONAL:
2898 case XML_RELAXNG_ZEROORMORE:
2899 case XML_RELAXNG_ONEORMORE:
2900 case XML_RELAXNG_CHOICE:
2901 case XML_RELAXNG_GROUP:
2902 case XML_RELAXNG_DEF:{
2903 xmlRelaxNGDefinePtr list;
2904
2905 list = def->content;
2906 while (list != NULL) {
2907 ret = xmlRelaxNGIsCompilable(list);
2908 if (ret != 1)
2909 break;
2910 list = list->next;
2911 }
2912 break;
2913 }
2914 case XML_RELAXNG_EXCEPT:
2915 case XML_RELAXNG_ATTRIBUTE:
2916 case XML_RELAXNG_INTERLEAVE:
2917 case XML_RELAXNG_DATATYPE:
2918 case XML_RELAXNG_LIST:
2919 case XML_RELAXNG_PARAM:
2920 case XML_RELAXNG_VALUE:
2921 case XML_RELAXNG_NOT_ALLOWED:
2922 ret = 0;
2923 break;
2924 }
2925 if (ret == 0)
2926 def->dflags |= IS_NOT_COMPILABLE;
2927 if (ret == 1)
2928 def->dflags |= IS_COMPILABLE;
2929 return (ret);
2930}
2931
2942static int
2943xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
2944{
2945 int ret = 0;
2946 xmlRelaxNGDefinePtr list;
2947
2948 if ((ctxt == NULL) || (def == NULL))
2949 return (-1);
2950
2951 switch (def->type) {
2952 case XML_RELAXNG_START:
2953 if ((xmlRelaxNGIsCompilable(def) == 1) && (def->depth != -25)) {
2954 xmlAutomataPtr oldam = ctxt->am;
2955 xmlAutomataStatePtr oldstate = ctxt->state;
2956
2957 def->depth = -25;
2958
2959 list = def->content;
2960 ctxt->am = xmlNewAutomata();
2961 if (ctxt->am == NULL)
2962 return (-1);
2963
2964 /*
2965 * assume identical strings but not same pointer are different
2966 * atoms, needed for non-determinism detection
2967 * That way if 2 elements with the same name are in a choice
2968 * branch the automata is found non-deterministic and
2969 * we fallback to the normal validation which does the right
2970 * thing of exploring both choices.
2971 */
2972 xmlAutomataSetFlags(ctxt->am, 1);
2973
2974 ctxt->state = xmlAutomataGetInitState(ctxt->am);
2975 while (list != NULL) {
2976 xmlRelaxNGCompile(ctxt, list);
2977 list = list->next;
2978 }
2979 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
2980 if (xmlAutomataIsDeterminist(ctxt->am))
2981 def->contModel = xmlAutomataCompile(ctxt->am);
2982
2983 xmlFreeAutomata(ctxt->am);
2984 ctxt->state = oldstate;
2985 ctxt->am = oldam;
2986 }
2987 break;
2988 case XML_RELAXNG_ELEMENT:
2989 if ((ctxt->am != NULL) && (def->name != NULL)) {
2990 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
2991 ctxt->state, NULL,
2992 def->name, def->ns,
2993 def);
2994 }
2995 if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
2996 xmlAutomataPtr oldam = ctxt->am;
2997 xmlAutomataStatePtr oldstate = ctxt->state;
2998
2999 def->depth = -25;
3000
3001 list = def->content;
3002 ctxt->am = xmlNewAutomata();
3003 if (ctxt->am == NULL)
3004 return (-1);
3005 xmlAutomataSetFlags(ctxt->am, 1);
3006 ctxt->state = xmlAutomataGetInitState(ctxt->am);
3007 while (list != NULL) {
3008 xmlRelaxNGCompile(ctxt, list);
3009 list = list->next;
3010 }
3011 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
3012 def->contModel = xmlAutomataCompile(ctxt->am);
3013 if (!xmlRegexpIsDeterminist(def->contModel)) {
3014 /*
3015 * we can only use the automata if it is determinist
3016 */
3017 xmlRegFreeRegexp(def->contModel);
3018 def->contModel = NULL;
3019 }
3020 xmlFreeAutomata(ctxt->am);
3021 ctxt->state = oldstate;
3022 ctxt->am = oldam;
3023 } else {
3024 xmlAutomataPtr oldam = ctxt->am;
3025
3026 /*
3027 * we can't build the content model for this element content
3028 * but it still might be possible to build it for some of its
3029 * children, recurse.
3030 */
3031 ret = xmlRelaxNGTryCompile(ctxt, def);
3032 ctxt->am = oldam;
3033 }
3034 break;
3035 case XML_RELAXNG_NOOP:
3036 ret = xmlRelaxNGCompile(ctxt, def->content);
3037 break;
3038 case XML_RELAXNG_OPTIONAL:{
3039 xmlAutomataStatePtr oldstate = ctxt->state;
3040
3041 list = def->content;
3042 while (list != NULL) {
3043 xmlRelaxNGCompile(ctxt, list);
3044 list = list->next;
3045 }
3046 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
3047 break;
3048 }
3049 case XML_RELAXNG_ZEROORMORE:{
3050 xmlAutomataStatePtr oldstate;
3051
3052 ctxt->state =
3053 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
3054 oldstate = ctxt->state;
3055 list = def->content;
3056 while (list != NULL) {
3057 xmlRelaxNGCompile(ctxt, list);
3058 list = list->next;
3059 }
3060 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3061 ctxt->state =
3062 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
3063 break;
3064 }
3065 case XML_RELAXNG_ONEORMORE:{
3066 xmlAutomataStatePtr oldstate;
3067
3068 list = def->content;
3069 while (list != NULL) {
3070 xmlRelaxNGCompile(ctxt, list);
3071 list = list->next;
3072 }
3073 oldstate = ctxt->state;
3074 list = def->content;
3075 while (list != NULL) {
3076 xmlRelaxNGCompile(ctxt, list);
3077 list = list->next;
3078 }
3079 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
3080 ctxt->state =
3081 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
3082 break;
3083 }
3084 case XML_RELAXNG_CHOICE:{
3085 xmlAutomataStatePtr target = NULL;
3086 xmlAutomataStatePtr oldstate = ctxt->state;
3087
3088 list = def->content;
3089 while (list != NULL) {
3090 ctxt->state = oldstate;
3091 ret = xmlRelaxNGCompile(ctxt, list);
3092 if (ret != 0)
3093 break;
3094 if (target == NULL)
3095 target = ctxt->state;
3096 else {
3097 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
3098 target);
3099 }
3100 list = list->next;
3101 }
3102 ctxt->state = target;
3103
3104 break;
3105 }
3106 case XML_RELAXNG_REF:
3107 case XML_RELAXNG_EXTERNALREF:
3108 case XML_RELAXNG_PARENTREF:
3109 case XML_RELAXNG_GROUP:
3110 case XML_RELAXNG_DEF:
3111 list = def->content;
3112 while (list != NULL) {
3113 ret = xmlRelaxNGCompile(ctxt, list);
3114 if (ret != 0)
3115 break;
3116 list = list->next;
3117 }
3118 break;
3119 case XML_RELAXNG_TEXT:{
3120 xmlAutomataStatePtr oldstate;
3121
3122 ctxt->state =
3123 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
3124 oldstate = ctxt->state;
3125 xmlRelaxNGCompile(ctxt, def->content);
3126 xmlAutomataNewTransition(ctxt->am, ctxt->state,
3127 ctxt->state, BAD_CAST "#text",
3128 NULL);
3129 ctxt->state =
3130 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
3131 break;
3132 }
3133 case XML_RELAXNG_EMPTY:
3134 ctxt->state =
3135 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
3136 break;
3137 case XML_RELAXNG_EXCEPT:
3138 case XML_RELAXNG_ATTRIBUTE:
3139 case XML_RELAXNG_INTERLEAVE:
3140 case XML_RELAXNG_NOT_ALLOWED:
3141 case XML_RELAXNG_DATATYPE:
3142 case XML_RELAXNG_LIST:
3143 case XML_RELAXNG_PARAM:
3144 case XML_RELAXNG_VALUE:
3145 /* This should not happen and generate an internal error */
3146 fprintf(stderr, "RNG internal error trying to compile %s\n",
3147 xmlRelaxNGDefName(def));
3148 break;
3149 }
3150 return (ret);
3151}
3152
3163static int
3164xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
3165{
3166 int ret = 0;
3167 xmlRelaxNGDefinePtr list;
3168
3169 if ((ctxt == NULL) || (def == NULL))
3170 return (-1);
3171
3172 if ((def->type == XML_RELAXNG_START) ||
3173 (def->type == XML_RELAXNG_ELEMENT)) {
3174 ret = xmlRelaxNGIsCompilable(def);
3175 if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
3176 ctxt->am = NULL;
3177 ret = xmlRelaxNGCompile(ctxt, def);
3178 return (ret);
3179 }
3180 }
3181 switch (def->type) {
3182 case XML_RELAXNG_NOOP:
3183 ret = xmlRelaxNGTryCompile(ctxt, def->content);
3184 break;
3185 case XML_RELAXNG_TEXT:
3186 case XML_RELAXNG_DATATYPE:
3187 case XML_RELAXNG_LIST:
3188 case XML_RELAXNG_PARAM:
3189 case XML_RELAXNG_VALUE:
3190 case XML_RELAXNG_EMPTY:
3191 case XML_RELAXNG_ELEMENT:
3192 ret = 0;
3193 break;
3194 case XML_RELAXNG_OPTIONAL:
3195 case XML_RELAXNG_ZEROORMORE:
3196 case XML_RELAXNG_ONEORMORE:
3197 case XML_RELAXNG_CHOICE:
3198 case XML_RELAXNG_GROUP:
3199 case XML_RELAXNG_DEF:
3200 case XML_RELAXNG_START:
3201 case XML_RELAXNG_REF:
3202 case XML_RELAXNG_EXTERNALREF:
3203 case XML_RELAXNG_PARENTREF:
3204 list = def->content;
3205 while (list != NULL) {
3206 ret = xmlRelaxNGTryCompile(ctxt, list);
3207 if (ret != 0)
3208 break;
3209 list = list->next;
3210 }
3211 break;
3212 case XML_RELAXNG_EXCEPT:
3213 case XML_RELAXNG_ATTRIBUTE:
3214 case XML_RELAXNG_INTERLEAVE:
3215 case XML_RELAXNG_NOT_ALLOWED:
3216 ret = 0;
3217 break;
3218 }
3219 return (ret);
3220}
3221
3222/************************************************************************
3223 * *
3224 * Parsing functions *
3225 * *
3226 ************************************************************************/
3227
3228static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr
3229 ctxt, xmlNodePtr node);
3230static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr
3231 ctxt, xmlNodePtr node);
3232static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr
3233 ctxt, xmlNodePtr nodes,
3234 int group);
3235static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr
3236 ctxt, xmlNodePtr node);
3237static xmlRelaxNGPtr xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt,
3238 xmlNodePtr node);
3239static int xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
3240 xmlNodePtr nodes);
3241static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr
3242 ctxt, xmlNodePtr node,
3243 xmlRelaxNGDefinePtr
3244 def);
3245static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr
3246 ctxt, xmlNodePtr nodes);
3247static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
3248 xmlRelaxNGDefinePtr define,
3249 xmlNodePtr elem);
3250
3251
3252#define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
3253
3262static int
3263xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define)
3264{
3265 int ret;
3266
3267 if (define == NULL)
3268 return (-1);
3269
3270 if (define->dflags & IS_NULLABLE)
3271 return (1);
3272 if (define->dflags & IS_NOT_NULLABLE)
3273 return (0);
3274 switch (define->type) {
3275 case XML_RELAXNG_EMPTY:
3276 case XML_RELAXNG_TEXT:
3277 ret = 1;
3278 break;
3279 case XML_RELAXNG_NOOP:
3280 case XML_RELAXNG_DEF:
3281 case XML_RELAXNG_REF:
3282 case XML_RELAXNG_EXTERNALREF:
3283 case XML_RELAXNG_PARENTREF:
3284 case XML_RELAXNG_ONEORMORE:
3285 ret = xmlRelaxNGIsNullable(define->content);
3286 break;
3287 case XML_RELAXNG_EXCEPT:
3288 case XML_RELAXNG_NOT_ALLOWED:
3289 case XML_RELAXNG_ELEMENT:
3290 case XML_RELAXNG_DATATYPE:
3291 case XML_RELAXNG_PARAM:
3292 case XML_RELAXNG_VALUE:
3293 case XML_RELAXNG_LIST:
3294 case XML_RELAXNG_ATTRIBUTE:
3295 ret = 0;
3296 break;
3297 case XML_RELAXNG_CHOICE:{
3298 xmlRelaxNGDefinePtr list = define->content;
3299
3300 while (list != NULL) {
3301 ret = xmlRelaxNGIsNullable(list);
3302 if (ret != 0)
3303 goto done;
3304 list = list->next;
3305 }
3306 ret = 0;
3307 break;
3308 }
3309 case XML_RELAXNG_START:
3310 case XML_RELAXNG_INTERLEAVE:
3311 case XML_RELAXNG_GROUP:{
3312 xmlRelaxNGDefinePtr list = define->content;
3313
3314 while (list != NULL) {
3315 ret = xmlRelaxNGIsNullable(list);
3316 if (ret != 1)
3317 goto done;
3318 list = list->next;
3319 }
3320 return (1);
3321 }
3322 default:
3323 return (-1);
3324 }
3325 done:
3326 if (ret == 0)
3327 define->dflags |= IS_NOT_NULLABLE;
3328 if (ret == 1)
3329 define->dflags |= IS_NULLABLE;
3330 return (ret);
3331}
3332
3341static int
3342xmlRelaxNGIsBlank(xmlChar * str)
3343{
3344 if (str == NULL)
3345 return (1);
3346 while (*str != 0) {
3347 if (!(IS_BLANK_CH(*str)))
3348 return (0);
3349 str++;
3350 }
3351 return (1);
3352}
3353
3363static xmlChar *
3364xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
3365 xmlNodePtr node)
3366{
3367 xmlChar *ret, *escape;
3368
3369 if (node == NULL)
3370 return(NULL);
3371
3372 if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
3373 ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
3374 if (ret != NULL) {
3375 if (ret[0] == 0) {
3376 xmlFree(ret);
3377 return (NULL);
3378 }
3380 if (escape == NULL) {
3381 return (ret);
3382 }
3383 xmlFree(ret);
3384 return (escape);
3385 }
3386 }
3387 node = node->parent;
3388 while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
3389 ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
3390 if (ret != NULL) {
3391 if (ret[0] == 0) {
3392 xmlFree(ret);
3393 return (NULL);
3394 }
3396 if (escape == NULL) {
3397 return (ret);
3398 }
3399 xmlFree(ret);
3400 return (escape);
3401 }
3402 node = node->parent;
3403 }
3404 return (NULL);
3405}
3406
3416static xmlRelaxNGDefinePtr
3417xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
3418{
3419 xmlRelaxNGDefinePtr def = NULL;
3420 xmlRelaxNGTypeLibraryPtr lib = NULL;
3421 xmlChar *type;
3423 int success = 0;
3424
3425 def = xmlRelaxNGNewDefine(ctxt, node);
3426 if (def == NULL)
3427 return (NULL);
3428 def->type = XML_RELAXNG_VALUE;
3429
3430 type = xmlGetProp(node, BAD_CAST "type");
3431 if (type != NULL) {
3432 xmlRelaxNGNormExtSpace(type);
3433 if (xmlValidateNCName(type, 0)) {
3434 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
3435 "value type '%s' is not an NCName\n", type, NULL);
3436 }
3437 library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
3438 if (library == NULL)
3439 library =
3440 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
3441
3442 def->name = type;
3443 def->ns = library;
3444
3445 lib = (xmlRelaxNGTypeLibraryPtr)
3446 xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
3447 if (lib == NULL) {
3448 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
3449 "Use of unregistered type library '%s'\n", library,
3450 NULL);
3451 def->data = NULL;
3452 } else {
3453 def->data = lib;
3454 if (lib->have == NULL) {
3455 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
3456 "Internal error with type library '%s': no 'have'\n",
3457 library, NULL);
3458 } else {
3459 success = lib->have(lib->data, def->name);
3460 if (success != 1) {
3461 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
3462 "Error type '%s' is not exported by type library '%s'\n",
3463 def->name, library);
3464 }
3465 }
3466 }
3467 }
3468 if (node->children == NULL) {
3469 def->value = xmlStrdup(BAD_CAST "");
3470 } else if (((node->children->type != XML_TEXT_NODE) &&
3471 (node->children->type != XML_CDATA_SECTION_NODE)) ||
3472 (node->children->next != NULL)) {
3473 xmlRngPErr(ctxt, node, XML_RNGP_TEXT_EXPECTED,
3474 "Expecting a single text value for <value>content\n",
3475 NULL, NULL);
3476 } else if (def != NULL) {
3477 def->value = xmlNodeGetContent(node);
3478 if (def->value == NULL) {
3479 xmlRngPErr(ctxt, node, XML_RNGP_VALUE_NO_CONTENT,
3480 "Element <value> has no content\n", NULL, NULL);
3481 } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) {
3482 void *val = NULL;
3483
3484 success =
3485 lib->check(lib->data, def->name, def->value, &val, node);
3486 if (success != 1) {
3487 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_VALUE,
3488 "Value '%s' is not acceptable for type '%s'\n",
3489 def->value, def->name);
3490 } else {
3491 if (val != NULL)
3492 def->attrs = val;
3493 }
3494 }
3495 }
3496 return (def);
3497}
3498
3508static xmlRelaxNGDefinePtr
3509xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
3510{
3511 xmlRelaxNGDefinePtr def = NULL, except;
3512 xmlRelaxNGDefinePtr param, lastparam = NULL;
3513 xmlRelaxNGTypeLibraryPtr lib;
3514 xmlChar *type;
3516 xmlNodePtr content;
3517 int tmp;
3518
3519 type = xmlGetProp(node, BAD_CAST "type");
3520 if (type == NULL) {
3521 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_MISSING, "data has no type\n", NULL,
3522 NULL);
3523 return (NULL);
3524 }
3525 xmlRelaxNGNormExtSpace(type);
3526 if (xmlValidateNCName(type, 0)) {
3527 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
3528 "data type '%s' is not an NCName\n", type, NULL);
3529 }
3530 library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
3531 if (library == NULL)
3532 library =
3533 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
3534
3535 def = xmlRelaxNGNewDefine(ctxt, node);
3536 if (def == NULL) {
3538 xmlFree(type);
3539 return (NULL);
3540 }
3541 def->type = XML_RELAXNG_DATATYPE;
3542 def->name = type;
3543 def->ns = library;
3544
3545 lib = (xmlRelaxNGTypeLibraryPtr)
3546 xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
3547 if (lib == NULL) {
3548 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
3549 "Use of unregistered type library '%s'\n", library,
3550 NULL);
3551 def->data = NULL;
3552 } else {
3553 def->data = lib;
3554 if (lib->have == NULL) {
3555 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
3556 "Internal error with type library '%s': no 'have'\n",
3557 library, NULL);
3558 } else {
3559 tmp = lib->have(lib->data, def->name);
3560 if (tmp != 1) {
3561 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
3562 "Error type '%s' is not exported by type library '%s'\n",
3563 def->name, library);
3564 } else
3565 if ((xmlStrEqual
3566 (library,
3567 BAD_CAST
3568 "http://www.w3.org/2001/XMLSchema-datatypes"))
3569 && ((xmlStrEqual(def->name, BAD_CAST "IDREF"))
3570 || (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) {
3571 ctxt->idref = 1;
3572 }
3573 }
3574 }
3575 content = node->children;
3576
3577 /*
3578 * Handle optional params
3579 */
3580 while (content != NULL) {
3581 if (!xmlStrEqual(content->name, BAD_CAST "param"))
3582 break;
3583 if (xmlStrEqual(library,
3584 BAD_CAST "http://relaxng.org/ns/structure/1.0")) {
3585 xmlRngPErr(ctxt, node, XML_RNGP_PARAM_FORBIDDEN,
3586 "Type library '%s' does not allow type parameters\n",
3587 library, NULL);
3588 content = content->next;
3589 while ((content != NULL) &&
3590 (xmlStrEqual(content->name, BAD_CAST "param")))
3591 content = content->next;
3592 } else {
3593 param = xmlRelaxNGNewDefine(ctxt, node);
3594 if (param != NULL) {
3595 param->type = XML_RELAXNG_PARAM;
3596 param->name = xmlGetProp(content, BAD_CAST "name");
3597 if (param->name == NULL) {
3598 xmlRngPErr(ctxt, node, XML_RNGP_PARAM_NAME_MISSING,
3599 "param has no name\n", NULL, NULL);
3600 }
3601 param->value = xmlNodeGetContent(content);
3602 if (lastparam == NULL) {
3603 def->attrs = lastparam = param;
3604 } else {
3605 lastparam->next = param;
3606 lastparam = param;
3607 }
3608 if (lib != NULL) {
3609 }
3610 }
3611 content = content->next;
3612 }
3613 }
3614 /*
3615 * Handle optional except
3616 */
3617 if ((content != NULL)
3618 && (xmlStrEqual(content->name, BAD_CAST "except"))) {
3619 xmlNodePtr child;
3620 xmlRelaxNGDefinePtr tmp2, last = NULL;
3621
3622 except = xmlRelaxNGNewDefine(ctxt, node);
3623 if (except == NULL) {
3624 return (def);
3625 }
3626 except->type = XML_RELAXNG_EXCEPT;
3627 child = content->children;
3628 def->content = except;
3629 if (child == NULL) {
3630 xmlRngPErr(ctxt, content, XML_RNGP_EXCEPT_NO_CONTENT,
3631 "except has no content\n", NULL, NULL);
3632 }
3633 while (child != NULL) {
3634 tmp2 = xmlRelaxNGParsePattern(ctxt, child);
3635 if (tmp2 != NULL) {
3636 if (last == NULL) {
3637 except->content = last = tmp2;
3638 } else {
3639 last->next = tmp2;
3640 last = tmp2;
3641 }
3642 }
3643 child = child->next;
3644 }
3645 content = content->next;
3646 }
3647 /*
3648 * Check there is no unhandled data
3649 */
3650 if (content != NULL) {
3651 xmlRngPErr(ctxt, content, XML_RNGP_DATA_CONTENT,
3652 "Element data has unexpected content %s\n",
3653 content->name, NULL);
3654 }
3655
3656 return (def);
3657}
3658
3659static const xmlChar *invalidName = BAD_CAST "\1";
3660
3674static int
3675xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,
3676 xmlRelaxNGDefinePtr def2)
3677{
3678 int ret = 1;
3679 xmlNode node;
3680 xmlNs ns;
3681 xmlRelaxNGValidCtxt ctxt;
3682
3683 memset(&ctxt, 0, sizeof(xmlRelaxNGValidCtxt));
3684
3685 ctxt.flags = FLAGS_IGNORABLE | FLAGS_NOERROR;
3686
3687 if ((def1->type == XML_RELAXNG_ELEMENT) ||
3688 (def1->type == XML_RELAXNG_ATTRIBUTE)) {
3689 if (def2->type == XML_RELAXNG_TEXT)
3690 return (1);
3691 if (def1->name != NULL) {
3692 node.name = def1->name;
3693 } else {
3694 node.name = invalidName;
3695 }
3696 if (def1->ns != NULL) {
3697 if (def1->ns[0] == 0) {
3698 node.ns = NULL;
3699 } else {
3700 node.ns = &ns;
3701 ns.href = def1->ns;
3702 }
3703 } else {
3704 node.ns = NULL;
3705 }
3706 if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) {
3707 if (def1->nameClass != NULL) {
3708 ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2);
3709 } else {
3710 ret = 0;
3711 }
3712 } else {
3713 ret = 1;
3714 }
3715 } else if (def1->type == XML_RELAXNG_TEXT) {
3716 if (def2->type == XML_RELAXNG_TEXT)
3717 return (0);
3718 return (1);
3719 } else if (def1->type == XML_RELAXNG_EXCEPT) {
3720 ret = xmlRelaxNGCompareNameClasses(def1->content, def2);
3721 if (ret == 0)
3722 ret = 1;
3723 else if (ret == 1)
3724 ret = 0;
3725 } else {
3726 TODO ret = 0;
3727 }
3728 if (ret == 0)
3729 return (ret);
3730 if ((def2->type == XML_RELAXNG_ELEMENT) ||
3731 (def2->type == XML_RELAXNG_ATTRIBUTE)) {
3732 if (def2->name != NULL) {
3733 node.name = def2->name;
3734 } else {
3735 node.name = invalidName;
3736 }
3737 node.ns = &ns;
3738 if (def2->ns != NULL) {
3739 if (def2->ns[0] == 0) {
3740 node.ns = NULL;
3741 } else {
3742 ns.href = def2->ns;
3743 }
3744 } else {
3745 ns.href = invalidName;
3746 }
3747 if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) {
3748 if (def2->nameClass != NULL) {
3749 ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1);
3750 } else {
3751 ret = 0;
3752 }
3753 } else {
3754 ret = 1;
3755 }
3756 } else {
3757 TODO ret = 0;
3758 }
3759
3760 return (ret);
3761}
3762
3775static int
3776xmlRelaxNGCompareElemDefLists(xmlRelaxNGParserCtxtPtr ctxt
3777 ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr * def1,
3778 xmlRelaxNGDefinePtr * def2)
3779{
3780 xmlRelaxNGDefinePtr *basedef2 = def2;
3781
3782 if ((def1 == NULL) || (def2 == NULL))
3783 return (1);
3784 if ((*def1 == NULL) || (*def2 == NULL))
3785 return (1);
3786 while (*def1 != NULL) {
3787 while ((*def2) != NULL) {
3788 if (xmlRelaxNGCompareNameClasses(*def1, *def2) == 0)
3789 return (0);
3790 def2++;
3791 }
3792 def2 = basedef2;
3793 def1++;
3794 }
3795 return (1);
3796}
3797
3807static int
3808xmlRelaxNGGenerateAttributes(xmlRelaxNGParserCtxtPtr ctxt,
3809 xmlRelaxNGDefinePtr def)
3810{
3811 xmlRelaxNGDefinePtr parent, cur, tmp;
3812
3813 /*
3814 * Don't run that check in case of error. Infinite recursion
3815 * becomes possible.
3816 */
3817 if (ctxt->nbErrors != 0)
3818 return (-1);
3819
3820 parent = NULL;
3821 cur = def;
3822 while (cur != NULL) {
3823 if ((cur->type == XML_RELAXNG_ELEMENT) ||
3824 (cur->type == XML_RELAXNG_TEXT) ||
3825 (cur->type == XML_RELAXNG_DATATYPE) ||
3826 (cur->type == XML_RELAXNG_PARAM) ||
3827 (cur->type == XML_RELAXNG_LIST) ||
3828 (cur->type == XML_RELAXNG_VALUE) ||
3829 (cur->type == XML_RELAXNG_EMPTY))
3830 return (0);
3831 if ((cur->type == XML_RELAXNG_CHOICE) ||
3832 (cur->type == XML_RELAXNG_INTERLEAVE) ||
3833 (cur->type == XML_RELAXNG_GROUP) ||
3834 (cur->type == XML_RELAXNG_ONEORMORE) ||
3835 (cur->type == XML_RELAXNG_ZEROORMORE) ||
3836 (cur->type == XML_RELAXNG_OPTIONAL) ||
3837 (cur->type == XML_RELAXNG_PARENTREF) ||
3838 (cur->type == XML_RELAXNG_EXTERNALREF) ||
3839 (cur->type == XML_RELAXNG_REF) ||
3840 (cur->type == XML_RELAXNG_DEF)) {
3841 if (cur->content != NULL) {
3842 parent = cur;
3843 cur = cur->content;
3844 tmp = cur;
3845 while (tmp != NULL) {
3846 tmp->parent = parent;
3847 tmp = tmp->next;
3848 }
3849 continue;
3850 }
3851 }
3852 if (cur == def)
3853 break;
3854 if (cur->next != NULL) {
3855 cur = cur->next;
3856 continue;
3857 }
3858 do {
3859 cur = cur->parent;
3860 if (cur == NULL)
3861 break;
3862 if (cur == def)
3863 return (1);
3864 if (cur->next != NULL) {
3865 cur = cur->next;
3866 break;
3867 }
3868 } while (cur != NULL);
3869 }
3870 return (1);
3871}
3872
3883static xmlRelaxNGDefinePtr *
3884xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
3885 xmlRelaxNGDefinePtr def, int eora)
3886{
3887 xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp;
3888 int len = 0;
3889 int max = 0;
3890
3891 /*
3892 * Don't run that check in case of error. Infinite recursion
3893 * becomes possible.
3894 */
3895 if (ctxt->nbErrors != 0)
3896 return (NULL);
3897
3898 parent = NULL;
3899 cur = def;
3900 while (cur != NULL) {
3901 if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||
3902 (cur->type == XML_RELAXNG_TEXT))) ||
3903 ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE)) ||
3904 ((eora == 2) && ((cur->type == XML_RELAXNG_DATATYPE) ||
3905 (cur->type == XML_RELAXNG_ELEMENT) ||
3906 (cur->type == XML_RELAXNG_LIST) ||
3907 (cur->type == XML_RELAXNG_TEXT) ||
3908 (cur->type == XML_RELAXNG_VALUE)))) {
3909 if (ret == NULL) {
3910 max = 10;
3911 ret = (xmlRelaxNGDefinePtr *)
3912 xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr));
3913 if (ret == NULL) {
3914 xmlRngPErrMemory(ctxt, "getting element list\n");
3915 return (NULL);
3916 }
3917 } else if (max <= len) {
3918 xmlRelaxNGDefinePtr *temp;
3919
3920 max *= 2;
3922 (max + 1) * sizeof(xmlRelaxNGDefinePtr));
3923 if (temp == NULL) {
3924 xmlRngPErrMemory(ctxt, "getting element list\n");
3925 xmlFree(ret);
3926 return (NULL);
3927 }
3928 ret = temp;
3929 }
3930 ret[len++] = cur;
3931 ret[len] = NULL;
3932 } else if ((cur->type == XML_RELAXNG_CHOICE) ||
3933 (cur->type == XML_RELAXNG_INTERLEAVE) ||
3934 (cur->type == XML_RELAXNG_GROUP) ||
3935 (cur->type == XML_RELAXNG_ONEORMORE) ||
3936 (cur->type == XML_RELAXNG_ZEROORMORE) ||
3937 (cur->type == XML_RELAXNG_OPTIONAL) ||
3938 (cur->type == XML_RELAXNG_PARENTREF) ||
3939 (cur->type == XML_RELAXNG_REF) ||
3940 (cur->type == XML_RELAXNG_DEF) ||
3941 (cur->type == XML_RELAXNG_EXTERNALREF)) {
3942 /*
3943 * Don't go within elements or attributes or string values.
3944 * Just gather the element top list
3945 */
3946 if (cur->content != NULL) {
3947 parent = cur;
3948 cur = cur->content;
3949 tmp = cur;
3950 while (tmp != NULL) {
3951 tmp->parent = parent;
3952 tmp = tmp->next;
3953 }
3954 continue;
3955 }
3956 }
3957 if (cur == def)
3958 break;
3959 if (cur->next != NULL) {
3960 cur = cur->next;
3961 continue;
3962 }
3963 do {
3964 cur = cur->parent;
3965 if (cur == NULL)
3966 break;
3967 if (cur == def)
3968 return (ret);
3969 if (cur->next != NULL) {
3970 cur = cur->next;
3971 break;
3972 }
3973 } while (cur != NULL);
3974 }
3975 return (ret);
3976}
3977
3985static void
3986xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt,
3987 xmlRelaxNGDefinePtr def)
3988{
3989 xmlRelaxNGDefinePtr **list;
3990 xmlRelaxNGDefinePtr cur;
3991 int nbchild = 0, i, j, ret;
3992 int is_nullable = 0;
3993 int is_indeterminist = 0;
3994 xmlHashTablePtr triage = NULL;
3995 int is_triable = 1;
3996
3997 if ((def == NULL) || (def->type != XML_RELAXNG_CHOICE))
3998 return;
3999
4000 if (def->dflags & IS_PROCESSED)
4001 return;
4002
4003 /*
4004 * Don't run that check in case of error. Infinite recursion
4005 * becomes possible.
4006 */
4007 if (ctxt->nbErrors != 0)
4008 return;
4009
4010 is_nullable = xmlRelaxNGIsNullable(def);
4011
4012 cur = def->content;
4013 while (cur != NULL) {
4014 nbchild++;
4015 cur = cur->next;
4016 }
4017
4018 list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
4019 sizeof(xmlRelaxNGDefinePtr
4020 *));
4021 if (list == NULL) {
4022 xmlRngPErrMemory(ctxt, "building choice\n");
4023 return;
4024 }
4025 i = 0;
4026 /*
4027 * a bit strong but safe
4028 */
4029 if (is_nullable == 0) {
4030 triage = xmlHashCreate(10);
4031 } else {
4032 is_triable = 0;
4033 }
4034 cur = def->content;
4035 while (cur != NULL) {
4036 list[i] = xmlRelaxNGGetElements(ctxt, cur, 0);
4037 if ((list[i] == NULL) || (list[i][0] == NULL)) {
4038 is_triable = 0;
4039 } else if (is_triable == 1) {
4040 xmlRelaxNGDefinePtr *tmp;
4041 int res;
4042
4043 tmp = list[i];
4044 while ((*tmp != NULL) && (is_triable == 1)) {
4045 if ((*tmp)->type == XML_RELAXNG_TEXT) {
4046 res = xmlHashAddEntry2(triage,
4047 BAD_CAST "#text", NULL,
4048 (void *) cur);
4049 if (res != 0)
4050 is_triable = -1;
4051 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
4052 ((*tmp)->name != NULL)) {
4053 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
4054 res = xmlHashAddEntry2(triage,
4055 (*tmp)->name, NULL,
4056 (void *) cur);
4057 else
4058 res = xmlHashAddEntry2(triage,
4059 (*tmp)->name, (*tmp)->ns,
4060 (void *) cur);
4061 if (res != 0)
4062 is_triable = -1;
4063 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
4064 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
4065 res = xmlHashAddEntry2(triage,
4066 BAD_CAST "#any", NULL,
4067 (void *) cur);
4068 else
4069 res = xmlHashAddEntry2(triage,
4070 BAD_CAST "#any", (*tmp)->ns,
4071 (void *) cur);
4072 if (res != 0)
4073 is_triable = -1;
4074 } else {
4075 is_triable = -1;
4076 }
4077 tmp++;
4078 }
4079 }
4080 i++;
4081 cur = cur->next;
4082 }
4083
4084 for (i = 0; i < nbchild; i++) {
4085 if (list[i] == NULL)
4086 continue;
4087 for (j = 0; j < i; j++) {
4088 if (list[j] == NULL)
4089 continue;
4090 ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
4091 if (ret == 0) {
4092 is_indeterminist = 1;
4093 }
4094 }
4095 }
4096 for (i = 0; i < nbchild; i++) {
4097 if (list[i] != NULL)
4098 xmlFree(list[i]);
4099 }
4100
4101 xmlFree(list);
4102 if (is_indeterminist) {
4103 def->dflags |= IS_INDETERMINIST;
4104 }
4105 if (is_triable == 1) {
4106 def->dflags |= IS_TRIABLE;
4107 def->data = triage;
4108 } else if (triage != NULL) {
4109 xmlHashFree(triage, NULL);
4110 }
4111 def->dflags |= IS_PROCESSED;
4112}
4113
4121static void
4122xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,
4123 xmlRelaxNGDefinePtr def)
4124{
4125 xmlRelaxNGDefinePtr **list;
4126 xmlRelaxNGDefinePtr cur;
4127 int nbchild = 0, i, j, ret;
4128
4129 if ((def == NULL) ||
4130 ((def->type != XML_RELAXNG_GROUP) &&
4131 (def->type != XML_RELAXNG_ELEMENT)))
4132 return;
4133
4134 if (def->dflags & IS_PROCESSED)
4135 return;
4136
4137 /*
4138 * Don't run that check in case of error. Infinite recursion
4139 * becomes possible.
4140 */
4141 if (ctxt->nbErrors != 0)
4142 return;
4143
4144 cur = def->attrs;
4145 while (cur != NULL) {
4146 nbchild++;
4147 cur = cur->next;
4148 }
4149 cur = def->content;
4150 while (cur != NULL) {
4151 nbchild++;
4152 cur = cur->next;
4153 }
4154
4155 list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
4156 sizeof(xmlRelaxNGDefinePtr
4157 *));
4158 if (list == NULL) {
4159 xmlRngPErrMemory(ctxt, "building group\n");
4160 return;
4161 }
4162 i = 0;
4163 cur = def->attrs;
4164 while (cur != NULL) {
4165 list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
4166 i++;
4167 cur = cur->next;
4168 }
4169 cur = def->content;
4170 while (cur != NULL) {
4171 list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
4172 i++;
4173 cur = cur->next;
4174 }
4175
4176 for (i = 0; i < nbchild; i++) {
4177 if (list[i] == NULL)
4178 continue;
4179 for (j = 0; j < i; j++) {
4180 if (list[j] == NULL)
4181 continue;
4182 ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
4183 if (ret == 0) {
4184 xmlRngPErr(ctxt, def->node, XML_RNGP_GROUP_ATTR_CONFLICT,
4185 "Attributes conflicts in group\n", NULL, NULL);
4186 }
4187 }
4188 }
4189 for (i = 0; i < nbchild; i++) {
4190 if (list[i] != NULL)
4191 xmlFree(list[i]);
4192 }
4193
4194 xmlFree(list);
4195 def->dflags |= IS_PROCESSED;
4196}
4197
4213static void
4214xmlRelaxNGComputeInterleaves(void *payload, void *data,
4216{
4217 xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
4218 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
4219 xmlRelaxNGDefinePtr cur, *tmp;
4220
4221 xmlRelaxNGPartitionPtr partitions = NULL;
4222 xmlRelaxNGInterleaveGroupPtr *groups = NULL;
4223 xmlRelaxNGInterleaveGroupPtr group;
4224 int i, j, ret, res;
4225 int nbgroups = 0;
4226 int nbchild = 0;
4227 int is_mixed = 0;
4228 int is_determinist = 1;
4229
4230 /*
4231 * Don't run that check in case of error. Infinite recursion
4232 * becomes possible.
4233 */
4234 if (ctxt->nbErrors != 0)
4235 return;
4236
4237 cur = def->content;
4238 while (cur != NULL) {
4239 nbchild++;
4240 cur = cur->next;
4241 }
4242
4243 groups = (xmlRelaxNGInterleaveGroupPtr *)
4244 xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr));
4245 if (groups == NULL)
4246 goto error;
4247 cur = def->content;
4248 while (cur != NULL) {
4249 groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr)
4250 xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup));
4251 if (groups[nbgroups] == NULL)
4252 goto error;
4253 if (cur->type == XML_RELAXNG_TEXT)
4254 is_mixed++;
4255 groups[nbgroups]->rule = cur;
4256 groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 2);
4257 groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
4258 nbgroups++;
4259 cur = cur->next;
4260 }
4261
4262 /*
4263 * Let's check that all rules makes a partitions according to 7.4
4264 */
4265 partitions = (xmlRelaxNGPartitionPtr)
4266 xmlMalloc(sizeof(xmlRelaxNGPartition));
4267 if (partitions == NULL)
4268 goto error;
4269 memset(partitions, 0, sizeof(xmlRelaxNGPartition));
4270 partitions->nbgroups = nbgroups;
4271 partitions->triage = xmlHashCreate(nbgroups);
4272 for (i = 0; i < nbgroups; i++) {
4273 group = groups[i];
4274 for (j = i + 1; j < nbgroups; j++) {
4275 if (groups[j] == NULL)
4276 continue;
4277
4278 ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs,
4279 groups[j]->defs);
4280 if (ret == 0) {
4281 xmlRngPErr(ctxt, def->node, XML_RNGP_ELEM_TEXT_CONFLICT,
4282 "Element or text conflicts in interleave\n",
4283 NULL, NULL);
4284 }
4285 ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs,
4286 groups[j]->attrs);
4287 if (ret == 0) {
4288 xmlRngPErr(ctxt, def->node, XML_RNGP_ATTR_CONFLICT,
4289 "Attributes conflicts in interleave\n", NULL,
4290 NULL);
4291 }
4292 }
4293 tmp = group->defs;
4294 if ((tmp != NULL) && (*tmp != NULL)) {
4295 while (*tmp != NULL) {
4296 if ((*tmp)->type == XML_RELAXNG_TEXT) {
4297 res = xmlHashAddEntry2(partitions->triage,
4298 BAD_CAST "#text", NULL,
4299 (void *) (ptrdiff_t) (i + 1));
4300 if (res != 0)
4301 is_determinist = -1;
4302 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
4303 ((*tmp)->name != NULL)) {
4304 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
4305 res = xmlHashAddEntry2(partitions->triage,
4306 (*tmp)->name, NULL,
4307 (void *) (ptrdiff_t) (i + 1));
4308 else
4309 res = xmlHashAddEntry2(partitions->triage,
4310 (*tmp)->name, (*tmp)->ns,
4311 (void *) (ptrdiff_t) (i + 1));
4312 if (res != 0)
4313 is_determinist = -1;
4314 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
4315 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
4316 res = xmlHashAddEntry2(partitions->triage,
4317 BAD_CAST "#any", NULL,
4318 (void *) (ptrdiff_t) (i + 1));
4319 else
4320 res = xmlHashAddEntry2(partitions->triage,
4321 BAD_CAST "#any", (*tmp)->ns,
4322 (void *) (ptrdiff_t) (i + 1));
4323 if ((*tmp)->nameClass != NULL)
4324 is_determinist = 2;
4325 if (res != 0)
4326 is_determinist = -1;
4327 } else {
4328 is_determinist = -1;
4329 }
4330 tmp++;
4331 }
4332 } else {
4333 is_determinist = 0;
4334 }
4335 }
4336 partitions->groups = groups;
4337
4338 /*
4339 * and save the partition list back in the def
4340 */
4341 def->data = partitions;
4342 if (is_mixed != 0)
4343 def->dflags |= IS_MIXED;
4344 if (is_determinist == 1)
4345 partitions->flags = IS_DETERMINIST;
4346 if (is_determinist == 2)
4347 partitions->flags = IS_DETERMINIST | IS_NEEDCHECK;
4348 return;
4349
4350 error:
4351 xmlRngPErrMemory(ctxt, "in interleave computation\n");
4352 if (groups != NULL) {
4353 for (i = 0; i < nbgroups; i++)
4354 if (groups[i] != NULL) {
4355 if (groups[i]->defs != NULL)
4356 xmlFree(groups[i]->defs);
4357 xmlFree(groups[i]);
4358 }
4359 xmlFree(groups);
4360 }
4361 xmlRelaxNGFreePartition(partitions);
4362}
4363
4373static xmlRelaxNGDefinePtr
4374xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4375{
4376 xmlRelaxNGDefinePtr def = NULL;
4377 xmlRelaxNGDefinePtr last = NULL, cur;
4378 xmlNodePtr child;
4379
4380 def = xmlRelaxNGNewDefine(ctxt, node);
4381 if (def == NULL) {
4382 return (NULL);
4383 }
4384 def->type = XML_RELAXNG_INTERLEAVE;
4385
4386 if (ctxt->interleaves == NULL)
4387 ctxt->interleaves = xmlHashCreate(10);
4388 if (ctxt->interleaves == NULL) {
4389 xmlRngPErrMemory(ctxt, "create interleaves\n");
4390 } else {
4391 char name[32];
4392
4393 snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++);
4394 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) {
4395 xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_ADD,
4396 "Failed to add %s to hash table\n",
4397 (const xmlChar *) name, NULL);
4398 }
4399 }
4400 child = node->children;
4401 if (child == NULL) {
4402 xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_NO_CONTENT,
4403 "Element interleave is empty\n", NULL, NULL);
4404 }
4405 while (child != NULL) {
4406 if (IS_RELAXNG(child, "element")) {
4407 cur = xmlRelaxNGParseElement(ctxt, child);
4408 } else {
4409 cur = xmlRelaxNGParsePattern(ctxt, child);
4410 }
4411 if (cur != NULL) {
4412 cur->parent = def;
4413 if (last == NULL) {
4414 def->content = last = cur;
4415 } else {
4416 last->next = cur;
4417 last = cur;
4418 }
4419 }
4420 child = child->next;
4421 }
4422
4423 return (def);
4424}
4425
4435static int
4436xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4437{
4438 xmlRelaxNGIncludePtr incl;
4439 xmlNodePtr root;
4440 int ret = 0, tmp;
4441
4442 incl = node->psvi;
4443 if (incl == NULL) {
4444 xmlRngPErr(ctxt, node, XML_RNGP_INCLUDE_EMPTY,
4445 "Include node has no data\n", NULL, NULL);
4446 return (-1);
4447 }
4448 root = xmlDocGetRootElement(incl->doc);
4449 if (root == NULL) {
4450 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, "Include document is empty\n",
4451 NULL, NULL);
4452 return (-1);
4453 }
4454 if (!xmlStrEqual(root->name, BAD_CAST "grammar")) {
4455 xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
4456 "Include document root is not a grammar\n", NULL, NULL);
4457 return (-1);
4458 }
4459
4460 /*
4461 * Merge the definition from both the include and the internal list
4462 */
4463 if (root->children != NULL) {
4464 tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children);
4465 if (tmp != 0)
4466 ret = -1;
4467 }
4468 if (node->children != NULL) {
4469 tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children);
4470 if (tmp != 0)
4471 ret = -1;
4472 }
4473 return (ret);
4474}
4475
4485static int
4486xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4487{
4488 xmlChar *name;
4489 int ret = 0, tmp;
4490 xmlRelaxNGDefinePtr def;
4491 const xmlChar *olddefine;
4492
4493 name = xmlGetProp(node, BAD_CAST "name");
4494 if (name == NULL) {
4495 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_NAME_MISSING,
4496 "define has no name\n", NULL, NULL);
4497 } else {
4498 xmlRelaxNGNormExtSpace(name);
4499 if (xmlValidateNCName(name, 0)) {
4500 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_DEFINE_NAME,
4501 "define name '%s' is not an NCName\n", name, NULL);
4502 }
4503 def = xmlRelaxNGNewDefine(ctxt, node);
4504 if (def == NULL) {
4505 xmlFree(name);
4506 return (-1);
4507 }
4508 def->type = XML_RELAXNG_DEF;
4509 def->name = name;
4510 if (node->children == NULL) {
4511 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_EMPTY,
4512 "define has no children\n", NULL, NULL);
4513 } else {
4514 olddefine = ctxt->define;
4515 ctxt->define = name;
4516 def->content =
4517 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
4518 ctxt->define = olddefine;
4519 }
4520 if (ctxt->grammar->defs == NULL)
4521 ctxt->grammar->defs = xmlHashCreate(10);
4522 if (ctxt->grammar->defs == NULL) {
4523 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
4524 "Could not create definition hash\n", NULL, NULL);
4525 ret = -1;
4526 } else {
4527 tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
4528 if (tmp < 0) {
4529 xmlRelaxNGDefinePtr prev;
4530
4531 prev = xmlHashLookup(ctxt->grammar->defs, name);
4532 if (prev == NULL) {
4533 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
4534 "Internal error on define aggregation of %s\n",
4535 name, NULL);
4536 ret = -1;
4537 } else {
4538 while (prev->nextHash != NULL)
4539 prev = prev->nextHash;
4540 prev->nextHash = def;
4541 }
4542 }
4543 }
4544 }
4545 return (ret);
4546}
4547
4556static void
4557xmlRelaxNGParseImportRef(void *payload, void *data, const xmlChar *name) {
4558 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
4559 xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;
4560 int tmp;
4561
4562 def->dflags |= IS_EXTERNAL_REF;
4563
4564 tmp = xmlHashAddEntry(ctxt->grammar->refs, name, def);
4565 if (tmp < 0) {
4566 xmlRelaxNGDefinePtr prev;
4567
4568 prev = (xmlRelaxNGDefinePtr)
4569 xmlHashLookup(ctxt->grammar->refs, def->name);
4570 if (prev == NULL) {
4571 if (def->name != NULL) {
4572 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
4573 "Error refs definitions '%s'\n",
4574 def->name, NULL);
4575 } else {
4576 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
4577 "Error refs definitions\n",
4578 NULL, NULL);
4579 }
4580 } else {
4581 def->nextHash = prev->nextHash;
4582 prev->nextHash = def;
4583 }
4584 }
4585}
4586
4596static int
4597xmlRelaxNGParseImportRefs(xmlRelaxNGParserCtxtPtr ctxt,
4598 xmlRelaxNGGrammarPtr grammar) {
4599 if ((ctxt == NULL) || (grammar == NULL) || (ctxt->grammar == NULL))
4600 return(-1);
4601 if (grammar->refs == NULL)
4602 return(0);
4603 if (ctxt->grammar->refs == NULL)
4604 ctxt->grammar->refs = xmlHashCreate(10);
4605 if (ctxt->grammar->refs == NULL) {
4606 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,
4607 "Could not create references hash\n", NULL, NULL);
4608 return(-1);
4609 }
4610 xmlHashScan(grammar->refs, xmlRelaxNGParseImportRef, ctxt);
4611 return(0);
4612}
4613
4623static xmlRelaxNGDefinePtr
4624xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4625{
4626 xmlRelaxNGDocumentPtr docu;
4627 xmlNodePtr root, tmp;
4628 xmlChar *ns;
4629 int newNs = 0, oldflags;
4630 xmlRelaxNGDefinePtr def;
4631
4632 docu = node->psvi;
4633 if (docu != NULL) {
4634 def = xmlRelaxNGNewDefine(ctxt, node);
4635 if (def == NULL)
4636 return (NULL);
4637 def->type = XML_RELAXNG_EXTERNALREF;
4638
4639 if (docu->content == NULL) {
4640 /*
4641 * Then do the parsing for good
4642 */
4643 root = xmlDocGetRootElement(docu->doc);
4644 if (root == NULL) {
4645 xmlRngPErr(ctxt, node, XML_RNGP_EXTERNALREF_EMTPY,
4646 "xmlRelaxNGParse: %s is empty\n", ctxt->URL,
4647 NULL);
4648 return (NULL);
4649 }
4650 /*
4651 * ns transmission rules
4652 */
4653 ns = xmlGetProp(root, BAD_CAST "ns");
4654 if (ns == NULL) {
4655 tmp = node;
4656 while ((tmp != NULL) && (tmp->type == XML_ELEMENT_NODE)) {
4657 ns = xmlGetProp(tmp, BAD_CAST "ns");
4658 if (ns != NULL) {
4659 break;
4660 }
4661 tmp = tmp->parent;
4662 }
4663 if (ns != NULL) {
4664 xmlSetProp(root, BAD_CAST "ns", ns);
4665 newNs = 1;
4666 xmlFree(ns);
4667 }
4668 } else {
4669 xmlFree(ns);
4670 }
4671
4672 /*
4673 * Parsing to get a precompiled schemas.
4674 */
4675 oldflags = ctxt->flags;
4676 ctxt->flags |= XML_RELAXNG_IN_EXTERNALREF;
4677 docu->schema = xmlRelaxNGParseDocument(ctxt, root);
4678 ctxt->flags = oldflags;
4679 if ((docu->schema != NULL) &&
4680 (docu->schema->topgrammar != NULL)) {
4681 docu->content = docu->schema->topgrammar->start;
4682 if (docu->schema->topgrammar->refs)
4683 xmlRelaxNGParseImportRefs(ctxt, docu->schema->topgrammar);
4684 }
4685
4686 /*
4687 * the externalRef may be reused in a different ns context
4688 */
4689 if (newNs == 1) {
4690 xmlUnsetProp(root, BAD_CAST "ns");
4691 }
4692 }
4693 def->content = docu->content;
4694 } else {
4695 def = NULL;
4696 }
4697 return (def);
4698}
4699
4710static xmlRelaxNGDefinePtr
4711xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
4712{
4713 xmlRelaxNGDefinePtr def = NULL;
4714
4715 if (node == NULL) {
4716 return (NULL);
4717 }
4718 if (IS_RELAXNG(node, "element")) {
4719 def = xmlRelaxNGParseElement(ctxt, node);
4720 } else if (IS_RELAXNG(node, "attribute")) {
4721 def = xmlRelaxNGParseAttribute(ctxt, node);
4722 } else if (IS_RELAXNG(node, "empty")) {
4723 def = xmlRelaxNGNewDefine(ctxt, node);
4724 if (def == NULL)
4725 return (NULL);
4726 def->type = XML_RELAXNG_EMPTY;
4727 if (node->children != NULL) {
4728 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_NOT_EMPTY,
4729 "empty: had a child node\n", NULL, NULL);
4730 }
4731 } else if (IS_RELAXNG(node, "text")) {
4732 def = xmlRelaxNGNewDefine(ctxt, node);
4733 if (def == NULL)
4734 return (NULL);
4735 def->type = XML_RELAXNG_TEXT;
4736 if (node->children != NULL) {
4737 xmlRngPErr(ctxt, node, XML_RNGP_TEXT_HAS_CHILD,
4738 "text: had a child node\n", NULL, NULL);
4739 }
4740 } else if (IS_RELAXNG(node, "zeroOrMore")) {
4741 def = xmlRelaxNGNewDefine(ctxt, node);
4742 if (def == NULL)
4743 return (NULL);
4744 def->type = XML_RELAXNG_ZEROORMORE;
4745 if (node->children == NULL) {
4746 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4747 "Element %s is empty\n", node->name, NULL);
4748 } else {
4749 def->content =
4750 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
4751 }
4752 } else if (IS_RELAXNG(node, "oneOrMore")) {
4753 def = xmlRelaxNGNewDefine(ctxt, node);
4754 if (def == NULL)
4755 return (NULL);
4756 def->type = XML_RELAXNG_ONEORMORE;
4757 if (node->children == NULL) {
4758 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4759 "Element %s is empty\n", node->name, NULL);
4760 } else {
4761 def->content =
4762 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
4763 }
4764 } else if (IS_RELAXNG(node, "optional")) {
4765 def = xmlRelaxNGNewDefine(ctxt, node);
4766 if (def == NULL)
4767 return (NULL);
4768 def->type = XML_RELAXNG_OPTIONAL;
4769 if (node->children == NULL) {
4770 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4771 "Element %s is empty\n", node->name, NULL);
4772 } else {
4773 def->content =
4774 xmlRelaxNGParsePatterns(ctxt, node->children, 1);
4775 }
4776 } else if (IS_RELAXNG(node, "choice")) {
4777 def = xmlRelaxNGNewDefine(ctxt, node);
4778 if (def == NULL)
4779 return (NULL);
4780 def->type = XML_RELAXNG_CHOICE;
4781 if (node->children == NULL) {
4782 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4783 "Element %s is empty\n", node->name, NULL);
4784 } else {
4785 def->content =
4786 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
4787 }
4788 } else if (IS_RELAXNG(node, "group")) {
4789 def = xmlRelaxNGNewDefine(ctxt, node);
4790 if (def == NULL)
4791 return (NULL);
4792 def->type = XML_RELAXNG_GROUP;
4793 if (node->children == NULL) {
4794 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4795 "Element %s is empty\n", node->name, NULL);
4796 } else {
4797 def->content =
4798 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
4799 }
4800 } else if (IS_RELAXNG(node, "ref")) {
4801 def = xmlRelaxNGNewDefine(ctxt, node);
4802 if (def == NULL)
4803 return (NULL);
4804 def->type = XML_RELAXNG_REF;
4805 def->name = xmlGetProp(node, BAD_CAST "name");
4806 if (def->name == NULL) {
4807 xmlRngPErr(ctxt, node, XML_RNGP_REF_NO_NAME, "ref has no name\n",
4808 NULL, NULL);
4809 } else {
4810 xmlRelaxNGNormExtSpace(def->name);
4811 if (xmlValidateNCName(def->name, 0)) {
4812 xmlRngPErr(ctxt, node, XML_RNGP_REF_NAME_INVALID,
4813 "ref name '%s' is not an NCName\n", def->name,
4814 NULL);
4815 }
4816 }
4817 if (node->children != NULL) {
4818 xmlRngPErr(ctxt, node, XML_RNGP_REF_NOT_EMPTY, "ref is not empty\n",
4819 NULL, NULL);
4820 }
4821 if (ctxt->grammar->refs == NULL)
4822 ctxt->grammar->refs = xmlHashCreate(10);
4823 if (ctxt->grammar->refs == NULL) {
4824 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
4825 "Could not create references hash\n", NULL, NULL);
4826 def = NULL;
4827 } else {
4828 int tmp;
4829
4830 tmp = xmlHashAddEntry(ctxt->grammar->refs, def->name, def);
4831 if (tmp < 0) {
4832 xmlRelaxNGDefinePtr prev;
4833
4834 prev = (xmlRelaxNGDefinePtr)
4835 xmlHashLookup(ctxt->grammar->refs, def->name);
4836 if (prev == NULL) {
4837 if (def->name != NULL) {
4838 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
4839 "Error refs definitions '%s'\n",
4840 def->name, NULL);
4841 } else {
4842 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
4843 "Error refs definitions\n",
4844 NULL, NULL);
4845 }
4846 def = NULL;
4847 } else {
4848 def->nextHash = prev->nextHash;
4849 prev->nextHash = def;
4850 }
4851 }
4852 }
4853 } else if (IS_RELAXNG(node, "data")) {
4854 def = xmlRelaxNGParseData(ctxt, node);
4855 } else if (IS_RELAXNG(node, "value")) {
4856 def = xmlRelaxNGParseValue(ctxt, node);
4857 } else if (IS_RELAXNG(node, "list")) {
4858 def = xmlRelaxNGNewDefine(ctxt, node);
4859 if (def == NULL)
4860 return (NULL);
4861 def->type = XML_RELAXNG_LIST;
4862 if (node->children == NULL) {
4863 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
4864 "Element %s is empty\n", node->name, NULL);
4865 } else {
4866 def->content =
4867 xmlRelaxNGParsePatterns(ctxt, node->children, 0);
4868 }
4869 } else if (IS_RELAXNG(node, "interleave")) {
4870 def = xmlRelaxNGParseInterleave(ctxt, node);
4871 } else if (IS_RELAXNG(node, "externalRef")) {
4872 def = xmlRelaxNGProcessExternalRef(ctxt, node);
4873 } else if (IS_RELAXNG(node, "notAllowed")) {
4874 def = xmlRelaxNGNewDefine(ctxt, node);
4875 if (def == NULL)
4876 return (NULL);
4877 def->type = XML_RELAXNG_NOT_ALLOWED;
4878 if (node->children != NULL) {
4879 xmlRngPErr(ctxt, node, XML_RNGP_NOTALLOWED_NOT_EMPTY,
4880 "xmlRelaxNGParse: notAllowed element is not empty\n",
4881 NULL, NULL);
4882 }
4883 } else if (IS_RELAXNG(node, "grammar")) {
4884 xmlRelaxNGGrammarPtr grammar, old;
4885 xmlRelaxNGGrammarPtr oldparent;
4886
4887 oldparent = ctxt->parentgrammar;
4888 old = ctxt->grammar;
4889 ctxt->parentgrammar = old;
4890 grammar = xmlRelaxNGParseGrammar(ctxt, node->children);
4891 if (old != NULL) {
4892 ctxt->grammar = old;
4893 ctxt->parentgrammar = oldparent;
4894#if 0
4895 if (grammar != NULL) {
4896 grammar->next = old->next;
4897 old->next = grammar;
4898 }
4899#endif
4900 }
4901 if (grammar != NULL)
4902 def = grammar->start;
4903 else
4904 def = NULL;
4905 } else if (IS_RELAXNG(node, "parentRef")) {
4906 if (ctxt->parentgrammar == NULL) {
4907 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_PARENT,
4908 "Use of parentRef without a parent grammar\n", NULL,
4909 NULL);
4910 return (NULL);
4911 }
4912 def = xmlRelaxNGNewDefine(ctxt, node);
4913 if (def == NULL)
4914 return (NULL);
4915 def->type = XML_RELAXNG_PARENTREF;
4916 def->name = xmlGetProp(node, BAD_CAST "name");
4917 if (def->name == NULL) {
4918 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_NAME,
4919 "parentRef has no name\n", NULL, NULL);
4920 } else {
4921 xmlRelaxNGNormExtSpace(def->name);
4922 if (xmlValidateNCName(def->name, 0)) {
4923 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NAME_INVALID,
4924 "parentRef name '%s' is not an NCName\n",
4925 def->name, NULL);
4926 }
4927 }
4928 if (node->children != NULL) {
4929 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NOT_EMPTY,
4930 "parentRef is not empty\n", NULL, NULL);
4931 }
4932 if (ctxt->parentgrammar->refs == NULL)
4933 ctxt->parentgrammar->refs = xmlHashCreate(10);
4934 if (ctxt->parentgrammar->refs == NULL) {
4935 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
4936 "Could not create references hash\n", NULL, NULL);
4937 def = NULL;
4938 } else if (def->name != NULL) {
4939 int tmp;
4940
4941 tmp =
4942 xmlHashAddEntry(ctxt->parentgrammar->refs, def->name, def);
4943 if (tmp < 0) {
4944 xmlRelaxNGDefinePtr prev;
4945
4946 prev = (xmlRelaxNGDefinePtr)
4947 xmlHashLookup(ctxt->parentgrammar->refs, def->name);
4948 if (prev == NULL) {
4949 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
4950 "Internal error parentRef definitions '%s'\n",
4951 def->name, NULL);
4952 def = NULL;
4953 } else {
4954 def->nextHash = prev->nextHash;
4955 prev->nextHash = def;
4956 }
4957 }
4958 }
4959 } else if (IS_RELAXNG(node, "mixed")) {
4960 if (node->children == NULL) {
4961 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, "Mixed is empty\n",
4962 NULL, NULL);
4963 def = NULL;
4964 } else {
4965 def = xmlRelaxNGParseInterleave(ctxt, node);
4966 if (def != NULL) {
4967 xmlRelaxNGDefinePtr tmp;
4968
4969 if ((def->content != NULL) && (def->content->next != NULL)) {
4970 tmp = xmlRelaxNGNewDefine(ctxt, node);
4971 if (tmp != NULL) {
4972 tmp->type = XML_RELAXNG_GROUP;
4973 tmp->content = def->content;
4974 def->content = tmp;
4975 }
4976 }
4977
4978 tmp = xmlRelaxNGNewDefine(ctxt, node);
4979 if (tmp == NULL)
4980 return (def);
4981 tmp->type = XML_RELAXNG_TEXT;
4982 tmp->next = def->content;
4983 def->content = tmp;
4984 }
4985 }
4986 } else {
4987 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_CONSTRUCT,
4988 "Unexpected node %s is not a pattern\n", node->name,
4989 NULL);
4990 def = NULL;
4991 }
4992 return (def);
4993}
4994
5004static xmlRelaxNGDefinePtr
5005xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
5006{
5007 xmlRelaxNGDefinePtr ret, cur;
5008 xmlNodePtr child;
5009 int old_flags;
5010
5011 ret = xmlRelaxNGNewDefine(ctxt, node);
5012 if (ret == NULL)
5013 return (NULL);
5014 ret->type = XML_RELAXNG_ATTRIBUTE;
5015 ret->parent = ctxt->def;
5016 child = node->children;
5017 if (child == NULL) {
5018 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_EMPTY,
5019 "xmlRelaxNGParseattribute: attribute has no children\n",
5020 NULL, NULL);
5021 return (ret);
5022 }
5023 old_flags = ctxt->flags;
5024 ctxt->flags |= XML_RELAXNG_IN_ATTRIBUTE;
5025 cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
5026 if (cur != NULL)
5027 child = child->next;
5028
5029 if (child != NULL) {
5030 cur = xmlRelaxNGParsePattern(ctxt, child);
5031 if (cur != NULL) {
5032 switch (cur->type) {
5033 case XML_RELAXNG_EMPTY:
5034 case XML_RELAXNG_NOT_ALLOWED:
5035 case XML_RELAXNG_TEXT:
5036 case XML_RELAXNG_ELEMENT:
5037 case XML_RELAXNG_DATATYPE:
5038 case XML_RELAXNG_VALUE:
5039 case XML_RELAXNG_LIST:
5040 case XML_RELAXNG_REF:
5041 case XML_RELAXNG_PARENTREF:
5042 case XML_RELAXNG_EXTERNALREF:
5043 case XML_RELAXNG_DEF:
5044 case XML_RELAXNG_ONEORMORE:
5045 case XML_RELAXNG_ZEROORMORE:
5046 case XML_RELAXNG_OPTIONAL:
5047 case XML_RELAXNG_CHOICE:
5048 case XML_RELAXNG_GROUP:
5049 case XML_RELAXNG_INTERLEAVE:
5050 case XML_RELAXNG_ATTRIBUTE:
5051 ret->content = cur;
5052 cur->parent = ret;
5053 break;
5054 case XML_RELAXNG_START:
5055 case XML_RELAXNG_PARAM:
5056 case XML_RELAXNG_EXCEPT:
5057 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CONTENT,
5058 "attribute has invalid content\n", NULL,
5059 NULL);
5060 break;
5061 case XML_RELAXNG_NOOP:
5062 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_NOOP,
5063 "RNG Internal error, noop found in attribute\n",
5064 NULL, NULL);
5065 break;
5066 }
5067 }
5068 child = child->next;
5069 }
5070 if (child != NULL) {
5071 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CHILDREN,
5072 "attribute has multiple children\n", NULL, NULL);
5073 }
5074 ctxt->flags = old_flags;
5075 return (ret);
5076}
5077
5088static xmlRelaxNGDefinePtr
5089xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt,
5090 xmlNodePtr node, int attr)
5091{
5092 xmlRelaxNGDefinePtr ret, cur, last = NULL;
5093 xmlNodePtr child;
5094
5095 if (!IS_RELAXNG(node, "except")) {
5096 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MISSING,
5097 "Expecting an except node\n", NULL, NULL);
5098 return (NULL);
5099 }
5100 if (node->next != NULL) {
5101 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MULTIPLE,
5102 "exceptNameClass allows only a single except node\n",
5103 NULL, NULL);
5104 }
5105 if (node->children == NULL) {
5106 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_EMPTY, "except has no content\n",
5107 NULL, NULL);
5108 return (NULL);
5109 }
5110
5111 ret = xmlRelaxNGNewDefine(ctxt, node);
5112 if (ret == NULL)
5113 return (NULL);
5114 ret->type = XML_RELAXNG_EXCEPT;
5115 child = node->children;
5116 while (child != NULL) {
5117 cur = xmlRelaxNGNewDefine(ctxt, child);
5118 if (cur == NULL)
5119 break;
5120 if (attr)
5121 cur->type = XML_RELAXNG_ATTRIBUTE;
5122 else
5123 cur->type = XML_RELAXNG_ELEMENT;
5124
5125 if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) {
5126 if (last == NULL) {
5127 ret->content = cur;
5128 } else {
5129 last->next = cur;
5130 }
5131 last = cur;
5132 }
5133 child = child->next;
5134 }
5135
5136 return (ret);
5137}
5138
5149static xmlRelaxNGDefinePtr
5150xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
5151 xmlRelaxNGDefinePtr def)
5152{
5153 xmlRelaxNGDefinePtr ret, tmp;
5154 xmlChar *val;
5155
5156 ret = def;
5157 if ((IS_RELAXNG(node, "name")) || (IS_RELAXNG(node, "anyName")) ||
5158 (IS_RELAXNG(node, "nsName"))) {
5159 if ((def->type != XML_RELAXNG_ELEMENT) &&
5160 (def->type != XML_RELAXNG_ATTRIBUTE)) {
5161 ret = xmlRelaxNGNewDefine(ctxt, node);
5162 if (ret == NULL)
5163 return (NULL);
5164 ret->parent = def;
5165 if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE)
5166 ret->type = XML_RELAXNG_ATTRIBUTE;
5167 else
5168 ret->type = XML_RELAXNG_ELEMENT;
5169 }
5170 }
5171 if (IS_RELAXNG(node, "name")) {
5172 val = xmlNodeGetContent(node);
5173 xmlRelaxNGNormExtSpace(val);
5174 if (xmlValidateNCName(val, 0)) {
5175 if (node->parent != NULL)
5176 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
5177 "Element %s name '%s' is not an NCName\n",
5178 node->parent->name, val);
5179 else
5180 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
5181 "name '%s' is not an NCName\n",
5182 val, NULL);
5183 }
5184 ret->name = val;
5185 val = xmlGetProp(node, BAD_CAST "ns");
5186 ret->ns = val;
5187 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
5188 (val != NULL) &&
5189 (xmlStrEqual(val, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
5190 xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
5191 "Attribute with namespace '%s' is not allowed\n",
5192 val, NULL);
5193 }
5194 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
5195 (val != NULL) &&
5196 (val[0] == 0) && (xmlStrEqual(ret->name, BAD_CAST "xmlns"))) {
5197 xmlRngPErr(ctxt, node, XML_RNGP_XMLNS_NAME,
5198 "Attribute with QName 'xmlns' is not allowed\n",
5199 val, NULL);
5200 }
5201 } else if (IS_RELAXNG(node, "anyName")) {
5202 ret->name = NULL;
5203 ret->ns = NULL;
5204 if (node->children != NULL) {
5205 ret->nameClass =
5206 xmlRelaxNGParseExceptNameClass(ctxt, node->children,
5207 (def->type ==
5208 XML_RELAXNG_ATTRIBUTE));
5209 }
5210 } else if (IS_RELAXNG(node, "nsName")) {
5211 ret->name = NULL;
5212 ret->ns = xmlGetProp(node, BAD_CAST "ns");
5213 if (ret->ns == NULL) {
5214 xmlRngPErr(ctxt, node, XML_RNGP_NSNAME_NO_NS,
5215 "nsName has no ns attribute\n", NULL, NULL);
5216 }
5217 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
5218 (ret->ns != NULL) &&
5220 (ret->ns, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
5221 xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
5222 "Attribute with namespace '%s' is not allowed\n",
5223 ret->ns, NULL);
5224 }
5225 if (node->children != NULL) {
5226 ret->nameClass =
5227 xmlRelaxNGParseExceptNameClass(ctxt, node->children,
5228 (def->type ==
5229 XML_RELAXNG_ATTRIBUTE));
5230 }
5231 } else if (IS_RELAXNG(node, "choice")) {
5232 xmlNodePtr child;
5233 xmlRelaxNGDefinePtr last = NULL;
5234
5235 if (def->type == XML_RELAXNG_CHOICE) {
5236 ret = def;
5237 } else {
5238 ret = xmlRelaxNGNewDefine(ctxt, node);
5239 if (ret == NULL)
5240 return (NULL);
5241 ret->parent = def;
5242 ret->type = XML_RELAXNG_CHOICE;
5243 }
5244
5245 if (node->children == NULL) {
5246 xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,
5247 "Element choice is empty\n", NULL, NULL);
5248 } else {
5249
5250 child = node->children;
5251 while (child != NULL) {
5252 tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);
5253 if (tmp != NULL) {
5254 if (last == NULL) {
5255 last = tmp;
5256 } else {
5257 last->next = tmp;
5258 last = tmp;
5259 }
5260 }
5261 child = child->next;
5262 }
5263 }
5264 } else {
5265 xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT,
5266 "expecting name, anyName, nsName or choice : got %s\n",
5267 (node == NULL ? (const xmlChar *) "nothing" : node->name),
5268 NULL);
5269 return (NULL);
5270 }
5271 if (ret != def) {
5272 if (def->nameClass == NULL) {
5273 def->nameClass = ret;
5274 } else {
5275 tmp = def->nameClass;
5276 while (tmp->next != NULL) {
5277 tmp = tmp->next;
5278 }
5279 tmp->next = ret;
5280 }
5281 }
5282 return (ret);
5283}
5284
5294static xmlRelaxNGDefinePtr
5295xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
5296{
5297 xmlRelaxNGDefinePtr ret, cur, last;
5298 xmlNodePtr child;
5299 const xmlChar *olddefine;
5300
5301 ret = xmlRelaxNGNewDefine(ctxt, node);
5302 if (ret == NULL)
5303 return (NULL);
5304 ret->type = XML_RELAXNG_ELEMENT;
5305 ret->parent = ctxt->def;
5306 child = node->children;
5307 if (child == NULL) {
5308 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_EMPTY,
5309 "xmlRelaxNGParseElement: element has no children\n",
5310 NULL, NULL);
5311 return (ret);
5312 }
5313 cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
5314 if (cur != NULL)
5315 child = child->next;
5316
5317 if (child == NULL) {
5318 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NO_CONTENT,
5319 "xmlRelaxNGParseElement: element has no content\n",
5320 NULL, NULL);
5321 return (ret);
5322 }
5323 olddefine = ctxt->define;
5324 ctxt->define = NULL;
5325 last = NULL;
5326 while (child != NULL) {
5327 cur = xmlRelaxNGParsePattern(ctxt, child);
5328 if (cur != NULL) {
5329 cur->parent = ret;
5330 switch (cur->type) {
5331 case XML_RELAXNG_EMPTY:
5332 case XML_RELAXNG_NOT_ALLOWED:
5333 case XML_RELAXNG_TEXT:
5334 case XML_RELAXNG_ELEMENT:
5335 case XML_RELAXNG_DATATYPE:
5336 case XML_RELAXNG_VALUE:
5337 case XML_RELAXNG_LIST:
5338 case XML_RELAXNG_REF:
5339 case XML_RELAXNG_PARENTREF:
5340 case XML_RELAXNG_EXTERNALREF:
5341 case XML_RELAXNG_DEF:
5342 case XML_RELAXNG_ZEROORMORE:
5343 case XML_RELAXNG_ONEORMORE:
5344 case XML_RELAXNG_OPTIONAL:
5345 case XML_RELAXNG_CHOICE:
5346 case XML_RELAXNG_GROUP:
5347 case XML_RELAXNG_INTERLEAVE:
5348 if (last == NULL) {
5349 ret->content = last = cur;
5350 } else {
5351 if ((last->type == XML_RELAXNG_ELEMENT) &&
5352 (ret->content == last)) {
5353 ret->content = xmlRelaxNGNewDefine(ctxt, node);
5354 if (ret->content != NULL) {
5355 ret->content->type = XML_RELAXNG_GROUP;
5356 ret->content->content = last;
5357 } else {
5358 ret->content = last;
5359 }
5360 }
5361 last->next = cur;
5362 last = cur;
5363 }
5364 break;
5365 case XML_RELAXNG_ATTRIBUTE:
5366 cur->next = ret->attrs;
5367 ret->attrs = cur;
5368 break;
5369 case XML_RELAXNG_START:
5370 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
5371 "RNG Internal error, start found in element\n",
5372 NULL, NULL);
5373 break;
5374 case XML_RELAXNG_PARAM:
5375 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
5376 "RNG Internal error, param found in element\n",
5377 NULL, NULL);
5378 break;
5379 case XML_RELAXNG_EXCEPT:
5380 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
5381 "RNG Internal error, except found in element\n",
5382 NULL, NULL);
5383 break;
5384 case XML_RELAXNG_NOOP:
5385 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
5386 "RNG Internal error, noop found in element\n",
5387 NULL, NULL);
5388 break;
5389 }
5390 }
5391 child = child->next;
5392 }
5393 ctxt->define = olddefine;
5394 return (ret);
5395}
5396
5407static xmlRelaxNGDefinePtr
5408xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes,
5409 int group)
5410{
5411 xmlRelaxNGDefinePtr def = NULL, last = NULL, cur, parent;
5412
5413 parent = ctxt->def;
5414 while (nodes != NULL) {
5415 if (IS_RELAXNG(nodes, "element")) {
5416 cur = xmlRelaxNGParseElement(ctxt, nodes);
5417 if (cur == NULL)
5418 return (NULL);
5419 if (def == NULL) {
5420 def = last = cur;
5421 } else {
5422 if ((group == 1) && (def->type == XML_RELAXNG_ELEMENT) &&
5423 (def == last)) {
5424 def = xmlRelaxNGNewDefine(ctxt, nodes);
5425 if (def == NULL)
5426 return (NULL);
5427 def->type = XML_RELAXNG_GROUP;
5428 def->content = last;
5429 }
5430 last->next = cur;
5431 last = cur;
5432 }
5433 cur->parent = parent;
5434 } else {
5435 cur = xmlRelaxNGParsePattern(ctxt, nodes);
5436 if (cur != NULL) {
5437 if (def == NULL) {
5438 def = last = cur;
5439 } else {
5440 last->next = cur;
5441 last = cur;
5442 }
5443 }
5444 }
5445 nodes = nodes->next;
5446 }
5447 return (def);
5448}
5449
5459static int
5460xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
5461{
5462 int ret = 0;
5463 xmlRelaxNGDefinePtr def = NULL, last;
5464
5465 if (nodes == NULL) {
5466 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY, "start has no children\n",
5467 NULL, NULL);
5468 return (-1);
5469 }
5470 if (IS_RELAXNG(nodes, "empty")) {
5471 def = xmlRelaxNGNewDefine(ctxt, nodes);
5472 if (def == NULL)
5473 return (-1);
5474 def->type = XML_RELAXNG_EMPTY;
5475 if (nodes->children != NULL) {
5476 xmlRngPErr(ctxt, nodes, XML_RNGP_EMPTY_CONTENT,
5477 "element empty is not empty\n", NULL, NULL);
5478 }
5479 } else if (IS_RELAXNG(nodes, "notAllowed")) {
5480 def = xmlRelaxNGNewDefine(ctxt, nodes);
5481 if (def == NULL)
5482 return (-1);
5483 def->type = XML_RELAXNG_NOT_ALLOWED;
5484 if (nodes->children != NULL) {
5485 xmlRngPErr(ctxt, nodes, XML_RNGP_NOTALLOWED_NOT_EMPTY,
5486 "element notAllowed is not empty\n", NULL, NULL);
5487 }
5488 } else {
5489 def = xmlRelaxNGParsePatterns(ctxt, nodes, 1);
5490 }
5491 if (ctxt->grammar->start != NULL) {
5492 last = ctxt->grammar->start;
5493 while (last->next != NULL)
5494 last = last->next;
5495 last->next = def;
5496 } else {
5497 ctxt->grammar->start = def;
5498 }
5499 nodes = nodes->next;
5500 if (nodes != NULL) {
5501 xmlRngPErr(ctxt, nodes, XML_RNGP_START_CONTENT,
5502 "start more than one children\n", NULL, NULL);
5503 return (-1);
5504 }
5505 return (ret);
5506}
5507
5517static int
5518xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
5519 xmlNodePtr nodes)
5520{
5521 int ret = 0, tmp;
5522
5523 if (nodes == NULL) {
5524 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_EMPTY,
5525 "grammar has no children\n", NULL, NULL);
5526 return (-1);
5527 }
5528 while (nodes != NULL) {
5529 if (IS_RELAXNG(nodes, "start")) {
5530 if (nodes->children == NULL) {
5531 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY,
5532 "start has no children\n", NULL, NULL);
5533 } else {
5534 tmp = xmlRelaxNGParseStart(ctxt, nodes->children);
5535 if (tmp != 0)
5536 ret = -1;
5537 }
5538 } else if (IS_RELAXNG(nodes, "define")) {
5539 tmp = xmlRelaxNGParseDefine(ctxt, nodes);
5540 if (tmp != 0)
5541 ret = -1;
5542 } else if (IS_RELAXNG(nodes, "include")) {
5543 tmp = xmlRelaxNGParseInclude(ctxt, nodes);
5544 if (tmp != 0)
5545 ret = -1;
5546 } else {
5547 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
5548 "grammar has unexpected child %s\n", nodes->name,
5549 NULL);
5550 ret = -1;
5551 }
5552 nodes = nodes->next;
5553 }
5554 return (ret);
5555}
5556
5566static void
5567xmlRelaxNGCheckReference(void *payload, void *data, const xmlChar * name)
5568{
5569 xmlRelaxNGDefinePtr ref = (xmlRelaxNGDefinePtr) payload;
5570 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
5571 xmlRelaxNGGrammarPtr grammar;
5572 xmlRelaxNGDefinePtr def, cur;
5573
5574 /*
5575 * Those rules don't apply to imported ref from xmlRelaxNGParseImportRef
5576 */
5577 if (ref->dflags & IS_EXTERNAL_REF)
5578 return;
5579
5580 grammar = ctxt->grammar;
5581 if (grammar == NULL) {
5582 xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
5583 "Internal error: no grammar in CheckReference %s\n",
5584 name, NULL);
5585 return;
5586 }
5587 if (ref->content != NULL) {
5588 xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
5589 "Internal error: reference has content in CheckReference %s\n",
5590 name, NULL);
5591 return;
5592 }
5593 if (grammar->defs != NULL) {
5594 def = xmlHashLookup(grammar->defs, name);
5595 if (def != NULL) {
5596 cur = ref;
5597 while (cur != NULL) {
5598 cur->content = def;
5599 cur = cur->nextHash;
5600 }
5601 } else {
5602 xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
5603 "Reference %s has no matching definition\n", name,
5604 NULL);
5605 }
5606 } else {
5607 xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
5608 "Reference %s has no matching definition\n", name,
5609 NULL);
5610 }
5611}
5612
5622static void
5623xmlRelaxNGCheckCombine(void *payload, void *data, const xmlChar * name)
5624{
5625 xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) payload;
5626 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;
5627 xmlChar *combine;
5628 int choiceOrInterleave = -1;
5629 int missing = 0;
5630 xmlRelaxNGDefinePtr cur, last, tmp, tmp2;
5631
5632 if (define->nextHash == NULL)
5633 return;
5634 cur = define;
5635 while (cur != NULL) {
5636 combine = xmlGetProp(cur->node, BAD_CAST "combine");
5637 if (combine != NULL) {
5638 if (xmlStrEqual(combine, BAD_CAST "choice")) {
5639 if (choiceOrInterleave == -1)
5640 choiceOrInterleave = 1;
5641 else if (choiceOrInterleave == 0) {
5642 xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
5643 "Defines for %s use both 'choice' and 'interleave'\n",
5644 name, NULL);
5645 }
5646 } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
5647 if (choiceOrInterleave == -1)
5648 choiceOrInterleave = 0;
5649 else if (choiceOrInterleave == 1) {
5650 xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
5651 "Defines for %s use both 'choice' and 'interleave'\n",
5652 name, NULL);
5653 }
5654 } else {
5655 xmlRngPErr(ctxt, define->node, XML_RNGP_UNKNOWN_COMBINE,
5656 "Defines for %s use unknown combine value '%s''\n",
5657 name, combine);
5658 }
5659 xmlFree(combine);
5660 } else {
5661 if (missing == 0)
5662 missing = 1;
5663 else {
5664 xmlRngPErr(ctxt, define->node, XML_RNGP_NEED_COMBINE,
5665 "Some defines for %s needs the combine attribute\n",
5666 name, NULL);
5667 }
5668 }
5669
5670 cur = cur->nextHash;
5671 }
5672 if (choiceOrInterleave == -1)
5673 choiceOrInterleave = 0;
5674 cur = xmlRelaxNGNewDefine(ctxt, define->node);
5675 if (cur == NULL)
5676 return;
5677 if (choiceOrInterleave == 0)
5678 cur->type = XML_RELAXNG_INTERLEAVE;
5679 else
5680 cur->type = XML_RELAXNG_CHOICE;
5681 tmp = define;
5682 last = NULL;
5683 while (tmp != NULL) {
5684 if (tmp->content != NULL) {
5685 if (tmp->content->next != NULL) {
5686 /*
5687 * we need first to create a wrapper.
5688 */
5689 tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node);
5690 if (tmp2 == NULL)
5691 break;
5692 tmp2->type = XML_RELAXNG_GROUP;
5693 tmp2->content = tmp->content;
5694 } else {
5695 tmp2 = tmp->content;
5696 }
5697 if (last == NULL) {
5698 cur->content = tmp2;
5699 } else {
5700 last->next = tmp2;
5701 }
5702 last = tmp2;
5703 }
5704 tmp->content = cur;
5705 tmp = tmp->nextHash;
5706 }
5707 define->content = cur;
5708 if (choiceOrInterleave == 0) {
5709 if (ctxt->interleaves == NULL)
5710 ctxt->interleaves = xmlHashCreate(10);
5711 if (ctxt->interleaves == NULL) {
5712 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
5713 "Failed to create interleaves hash table\n", NULL,
5714 NULL);
5715 } else {
5716 char tmpname[32];
5717
5718 snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
5719 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
5720 0) {
5721 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
5722 "Failed to add %s to hash table\n",
5723 (const xmlChar *) tmpname, NULL);
5724 }
5725 }
5726 }
5727}
5728
5737static void
5738xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt,
5739 xmlRelaxNGGrammarPtr grammar)
5740{
5741 xmlRelaxNGDefinePtr starts;
5742 xmlChar *combine;
5743 int choiceOrInterleave = -1;
5744 int missing = 0;
5745 xmlRelaxNGDefinePtr cur;
5746
5747 starts = grammar->start;
5748 if ((starts == NULL) || (starts->next == NULL))
5749 return;
5750 cur = starts;
5751 while (cur != NULL) {
5752 if ((cur->node == NULL) || (cur->node->parent == NULL) ||
5753 (!xmlStrEqual(cur->node->parent->name, BAD_CAST "start"))) {
5754 combine = NULL;
5755 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_MISSING,
5756 "Internal error: start element not found\n", NULL,
5757 NULL);
5758 } else {
5759 combine = xmlGetProp(cur->node->parent, BAD_CAST "combine");
5760 }
5761
5762 if (combine != NULL) {
5763 if (xmlStrEqual(combine, BAD_CAST "choice")) {
5764 if (choiceOrInterleave == -1)
5765 choiceOrInterleave = 1;
5766 else if (choiceOrInterleave == 0) {
5767 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
5768 "<start> use both 'choice' and 'interleave'\n",
5769 NULL, NULL);
5770 }
5771 } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
5772 if (choiceOrInterleave == -1)
5773 choiceOrInterleave = 0;
5774 else if (choiceOrInterleave == 1) {
5775 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
5776 "<start> use both 'choice' and 'interleave'\n",
5777 NULL, NULL);
5778 }
5779 } else {
5780 xmlRngPErr(ctxt, cur->node, XML_RNGP_UNKNOWN_COMBINE,
5781 "<start> uses unknown combine value '%s''\n",
5782 combine, NULL);
5783 }
5784 xmlFree(combine);
5785 } else {
5786 if (missing == 0)
5787 missing = 1;
5788 else {
5789 xmlRngPErr(ctxt, cur->node, XML_RNGP_NEED_COMBINE,
5790 "Some <start> element miss the combine attribute\n",
5791 NULL, NULL);
5792 }
5793 }
5794
5795 cur = cur->next;
5796 }
5797 if (choiceOrInterleave == -1)
5798 choiceOrInterleave = 0;
5799 cur = xmlRelaxNGNewDefine(ctxt, starts->node);
5800 if (cur == NULL)
5801 return;
5802 if (choiceOrInterleave == 0)
5803 cur->type = XML_RELAXNG_INTERLEAVE;
5804 else
5805 cur->type = XML_RELAXNG_CHOICE;
5806 cur->content = grammar->start;
5807 grammar->start = cur;
5808 if (choiceOrInterleave == 0) {
5809 if (ctxt->interleaves == NULL)
5810 ctxt->interleaves = xmlHashCreate(10);
5811 if (ctxt->interleaves == NULL) {
5812 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
5813 "Failed to create interleaves hash table\n", NULL,
5814 NULL);
5815 } else {
5816 char tmpname[32];
5817
5818 snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
5819 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
5820 0) {
5821 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
5822 "Failed to add %s to hash table\n",
5823 (const xmlChar *) tmpname, NULL);
5824 }
5825 }
5826 }
5827}
5828
5839static int
5840xmlRelaxNGCheckCycles(xmlRelaxNGParserCtxtPtr ctxt,
5841 xmlRelaxNGDefinePtr cur, int depth)
5842{
5843 int ret = 0;
5844
5845 while ((ret == 0) && (cur != NULL)) {
5846 if ((cur->type == XML_RELAXNG_REF) ||
5847 (cur->type == XML_RELAXNG_PARENTREF)) {
5848 if (cur->depth == -1) {
5849 cur->depth = depth;
5850 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
5851 cur->depth = -2;
5852 } else if (depth == cur->depth) {
5853 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_CYCLE,
5854 "Detected a cycle in %s references\n",
5855 cur->name, NULL);
5856 return (-1);
5857 }
5858 } else if (cur->type == XML_RELAXNG_ELEMENT) {
5859 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth + 1);
5860 } else {
5861 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
5862 }
5863 cur = cur->next;
5864 }
5865 return (ret);
5866}
5867
5879static xmlRelaxNGDefinePtr
5880xmlRelaxNGTryUnlink(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
5881 xmlRelaxNGDefinePtr cur,
5882 xmlRelaxNGDefinePtr parent, xmlRelaxNGDefinePtr prev)
5883{
5884 if (prev != NULL) {
5885 prev->next = cur->next;
5886 } else {
5887 if (parent != NULL) {
5888 if (parent->content == cur)
5889 parent->content = cur->next;
5890 else if (parent->attrs == cur)
5891 parent->attrs = cur->next;
5892 else if (parent->nameClass == cur)
5893 parent->nameClass = cur->next;
5894 } else {
5895 cur->type = XML_RELAXNG_NOOP;
5896 prev = cur;
5897 }
5898 }
5899 return (prev);
5900}
5901
5909static void
5910xmlRelaxNGSimplify(xmlRelaxNGParserCtxtPtr ctxt,
5911 xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent)
5912{
5913 xmlRelaxNGDefinePtr prev = NULL;
5914
5915 while (cur != NULL) {
5916 if ((cur->type == XML_RELAXNG_REF) ||
5917 (cur->type == XML_RELAXNG_PARENTREF)) {
5918 if (cur->depth != -3) {
5919 cur->depth = -3;
5920 xmlRelaxNGSimplify(ctxt, cur->content, cur);
5921 }
5922 } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
5923 cur->parent = parent;
5924 if ((parent != NULL) &&
5925 ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
5926 (parent->type == XML_RELAXNG_LIST) ||
5927 (parent->type == XML_RELAXNG_GROUP) ||
5928 (parent->type == XML_RELAXNG_INTERLEAVE) ||
5929 (parent->type == XML_RELAXNG_ONEORMORE) ||
5930 (parent->type == XML_RELAXNG_ZEROORMORE))) {
5931 parent->type = XML_RELAXNG_NOT_ALLOWED;
5932 break;
5933 }
5934 if ((parent != NULL) && (parent->type == XML_RELAXNG_CHOICE)) {
5935 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
5936 } else
5937 prev = cur;
5938 } else if (cur->type == XML_RELAXNG_EMPTY) {
5939 cur->parent = parent;
5940 if ((parent != NULL) &&
5941 ((parent->type == XML_RELAXNG_ONEORMORE) ||
5942 (parent->type == XML_RELAXNG_ZEROORMORE))) {
5943 parent->type = XML_RELAXNG_EMPTY;
5944 break;
5945 }
5946 if ((parent != NULL) &&
5947 ((parent->type == XML_RELAXNG_GROUP) ||
5948 (parent->type == XML_RELAXNG_INTERLEAVE))) {
5949 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
5950 } else
5951 prev = cur;
5952 } else {
5953 cur->parent = parent;
5954 if (cur->content != NULL)
5955 xmlRelaxNGSimplify(ctxt, cur->content, cur);
5956 if ((cur->type != XML_RELAXNG_VALUE) && (cur->attrs != NULL))
5957 xmlRelaxNGSimplify(ctxt, cur->attrs, cur);
5958 if (cur->nameClass != NULL)
5959 xmlRelaxNGSimplify(ctxt, cur->nameClass, cur);
5960 /*
5961 * On Elements, try to move attribute only generating rules on
5962 * the attrs rules.
5963 */
5964 if (cur->type == XML_RELAXNG_ELEMENT) {
5965 int attronly;
5966 xmlRelaxNGDefinePtr tmp, pre;
5967
5968 while (cur->content != NULL) {
5969 attronly =
5970 xmlRelaxNGGenerateAttributes(ctxt, cur->content);
5971 if (attronly == 1) {
5972 /*
5973 * migrate cur->content to attrs
5974 */
5975 tmp = cur->content;
5976 cur->content = tmp->next;
5977 tmp->next = cur->attrs;
5978 cur->attrs = tmp;
5979 } else {
5980 /*
5981 * cur->content can generate elements or text
5982 */
5983 break;
5984 }
5985 }
5986 pre = cur->content;
5987 while ((pre != NULL) && (pre->next != NULL)) {
5988 tmp = pre->next;
5989 attronly = xmlRelaxNGGenerateAttributes(ctxt, tmp);
5990 if (attronly == 1) {
5991 /*
5992 * migrate tmp to attrs
5993 */
5994 pre->next = tmp->next;
5995 tmp->next = cur->attrs;
5996 cur->attrs = tmp;
5997 } else {
5998 pre = tmp;
5999 }
6000 }
6001 }
6002 /*
6003 * This may result in a simplification
6004 */
6005 if ((cur->type == XML_RELAXNG_GROUP) ||
6006 (cur->type == XML_RELAXNG_INTERLEAVE)) {
6007 if (cur->content == NULL)
6008 cur->type = XML_RELAXNG_EMPTY;
6009 else if (cur->content->next == NULL) {
6010 if ((parent == NULL) && (prev == NULL)) {
6011 cur->type = XML_RELAXNG_NOOP;
6012 } else if (prev == NULL) {
6013 parent->content = cur->content;
6014 cur->content->next = cur->next;
6015 cur = cur->content;
6016 } else {
6017 cur->content->next = cur->next;
6018 prev->next = cur->content;
6019 cur = cur->content;
6020 }
6021 }
6022 }
6023 /*
6024 * the current node may have been transformed back
6025 */
6026 if ((cur->type == XML_RELAXNG_EXCEPT) &&
6027 (cur->content != NULL) &&
6028 (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) {
6029 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
6030 } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
6031 if ((parent != NULL) &&
6032 ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
6033 (parent->type == XML_RELAXNG_LIST) ||
6034 (parent->type == XML_RELAXNG_GROUP) ||
6035 (parent->type == XML_RELAXNG_INTERLEAVE) ||
6036 (parent->type == XML_RELAXNG_ONEORMORE) ||
6037 (parent->type == XML_RELAXNG_ZEROORMORE))) {
6038 parent->type = XML_RELAXNG_NOT_ALLOWED;
6039 break;
6040 }
6041 if ((parent != NULL) &&
6042 (parent->type == XML_RELAXNG_CHOICE)) {
6043 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
6044 } else
6045 prev = cur;
6046 } else if (cur->type == XML_RELAXNG_EMPTY) {
6047 if ((parent != NULL) &&
6048 ((parent->type == XML_RELAXNG_ONEORMORE) ||
6049 (parent->type == XML_RELAXNG_ZEROORMORE))) {
6050 parent->type = XML_RELAXNG_EMPTY;
6051 break;
6052 }
6053 if ((parent != NULL) &&
6054 ((parent->type == XML_RELAXNG_GROUP) ||
6055 (parent->type == XML_RELAXNG_INTERLEAVE) ||
6056 (parent->type == XML_RELAXNG_CHOICE))) {
6057 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
6058 } else
6059 prev = cur;
6060 } else {
6061 prev = cur;
6062 }
6063 }
6064 cur = cur->next;
6065 }
6066}
6067
6077static xmlRelaxNGContentType
6078xmlRelaxNGGroupContentType(xmlRelaxNGContentType ct1,
6079 xmlRelaxNGContentType ct2)
6080{
6081 if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
6082 (ct2 == XML_RELAXNG_CONTENT_ERROR))
6083 return (XML_RELAXNG_CONTENT_ERROR);
6084 if (ct1 == XML_RELAXNG_CONTENT_EMPTY)
6085 return (ct2);
6086 if (ct2 == XML_RELAXNG_CONTENT_EMPTY)
6087 return (ct1);
6088 if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) &&
6089 (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
6090 return (XML_RELAXNG_CONTENT_COMPLEX);
6091 return (XML_RELAXNG_CONTENT_ERROR);
6092}
6093
6103static xmlRelaxNGContentType
6104xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1,
6105 xmlRelaxNGContentType ct2)
6106{
6107 if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
6108 (ct2 == XML_RELAXNG_CONTENT_ERROR))
6109 return (XML_RELAXNG_CONTENT_ERROR);
6110 if ((ct1 == XML_RELAXNG_CONTENT_SIMPLE) ||
6111 (ct2 == XML_RELAXNG_CONTENT_SIMPLE))
6112 return (XML_RELAXNG_CONTENT_SIMPLE);
6113 if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) ||
6114 (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
6115 return (XML_RELAXNG_CONTENT_COMPLEX);
6116 return (XML_RELAXNG_CONTENT_EMPTY);
6117}
6118
6130static xmlRelaxNGContentType
6131xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt,
6132 xmlRelaxNGDefinePtr cur, int flags,
6133 xmlRelaxNGType ptype)
6134{
6135 int nflags;
6136 xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY;
6137
6138 while (cur != NULL) {
6139 ret = XML_RELAXNG_CONTENT_EMPTY;
6140 if ((cur->type == XML_RELAXNG_REF) ||
6141 (cur->type == XML_RELAXNG_PARENTREF)) {
6142 /*
6143 * This should actually be caught by list//element(ref) at the
6144 * element boundaries, c.f. Bug #159968 local refs are dropped
6145 * in step 4.19.
6146 */
6147#if 0
6148 if (flags & XML_RELAXNG_IN_LIST) {
6149 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_REF,
6150 "Found forbidden pattern list//ref\n", NULL,
6151 NULL);
6152 }
6153#endif
6154 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6155 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_REF,
6156 "Found forbidden pattern data/except//ref\n",
6157 NULL, NULL);
6158 }
6159 if (cur->content == NULL) {
6160 if (cur->type == XML_RELAXNG_PARENTREF)
6161 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,
6162 "Internal found no define for parent refs\n",
6163 NULL, NULL);
6164 else
6165 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,
6166 "Internal found no define for ref %s\n",
6167 (cur->name ? cur->name: BAD_CAST "null"), NULL);
6168 }
6169 if (cur->depth > -4) {
6170 cur->depth = -4;
6171 ret = xmlRelaxNGCheckRules(ctxt, cur->content,
6172 flags, cur->type);
6173 cur->depth = ret - 15;
6174 } else if (cur->depth == -4) {
6175 ret = XML_RELAXNG_CONTENT_COMPLEX;
6176 } else {
6177 ret = (xmlRelaxNGContentType) (cur->depth + 15);
6178 }
6179 } else if (cur->type == XML_RELAXNG_ELEMENT) {
6180 /*
6181 * The 7.3 Attribute derivation rule for groups is plugged there
6182 */
6183 xmlRelaxNGCheckGroupAttrs(ctxt, cur);
6184 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6185 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ELEM,
6186 "Found forbidden pattern data/except//element(ref)\n",
6187 NULL, NULL);
6188 }
6189 if (flags & XML_RELAXNG_IN_LIST) {
6190 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ELEM,
6191 "Found forbidden pattern list//element(ref)\n",
6192 NULL, NULL);
6193 }
6194 if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
6195 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
6196 "Found forbidden pattern attribute//element(ref)\n",
6197 NULL, NULL);
6198 }
6199 if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
6200 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
6201 "Found forbidden pattern attribute//element(ref)\n",
6202 NULL, NULL);
6203 }
6204 /*
6205 * reset since in the simple form elements are only child
6206 * of grammar/define
6207 */
6208 nflags = 0;
6209 ret =
6210 xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type);
6211 if (ret != XML_RELAXNG_CONTENT_EMPTY) {
6212 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_EMPTY,
6213 "Element %s attributes have a content type error\n",
6214 cur->name, NULL);
6215 }
6216 ret =
6217 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6218 cur->type);
6219 if (ret == XML_RELAXNG_CONTENT_ERROR) {
6220 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_ERROR,
6221 "Element %s has a content type error\n",
6222 cur->name, NULL);
6223 } else {
6224 ret = XML_RELAXNG_CONTENT_COMPLEX;
6225 }
6226 } else if (cur->type == XML_RELAXNG_ATTRIBUTE) {
6227 if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
6228 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ATTR,
6229 "Found forbidden pattern attribute//attribute\n",
6230 NULL, NULL);
6231 }
6232 if (flags & XML_RELAXNG_IN_LIST) {
6233 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ATTR,
6234 "Found forbidden pattern list//attribute\n",
6235 NULL, NULL);
6236 }
6237 if (flags & XML_RELAXNG_IN_OOMGROUP) {
6238 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_GROUP_ATTR,
6239 "Found forbidden pattern oneOrMore//group//attribute\n",
6240 NULL, NULL);
6241 }
6242 if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) {
6243 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR,
6244 "Found forbidden pattern oneOrMore//interleave//attribute\n",
6245 NULL, NULL);
6246 }
6247 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6248 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ATTR,
6249 "Found forbidden pattern data/except//attribute\n",
6250 NULL, NULL);
6251 }
6252 if (flags & XML_RELAXNG_IN_START) {
6253 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ATTR,
6254 "Found forbidden pattern start//attribute\n",
6255 NULL, NULL);
6256 }
6257 if ((!(flags & XML_RELAXNG_IN_ONEORMORE))
6258 && cur->name == NULL
6259 /* following is checking alternative name class readiness
6260 in case it went the "choice" route */
6261 && cur->nameClass == NULL) {
6262 if (cur->ns == NULL) {
6263 xmlRngPErr(ctxt, cur->node, XML_RNGP_ANYNAME_ATTR_ANCESTOR,
6264 "Found anyName attribute without oneOrMore ancestor\n",
6265 NULL, NULL);
6266 } else {
6267 xmlRngPErr(ctxt, cur->node, XML_RNGP_NSNAME_ATTR_ANCESTOR,
6268 "Found nsName attribute without oneOrMore ancestor\n",
6269 NULL, NULL);
6270 }
6271 }
6272 nflags = flags | XML_RELAXNG_IN_ATTRIBUTE;
6273 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
6274 ret = XML_RELAXNG_CONTENT_EMPTY;
6275 } else if ((cur->type == XML_RELAXNG_ONEORMORE) ||
6276 (cur->type == XML_RELAXNG_ZEROORMORE)) {
6277 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6278 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ONEMORE,
6279 "Found forbidden pattern data/except//oneOrMore\n",
6280 NULL, NULL);
6281 }
6282 if (flags & XML_RELAXNG_IN_START) {
6283 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ONEMORE,
6284 "Found forbidden pattern start//oneOrMore\n",
6285 NULL, NULL);
6286 }
6287 nflags = flags | XML_RELAXNG_IN_ONEORMORE;
6288 ret =
6289 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6290 cur->type);
6291 ret = xmlRelaxNGGroupContentType(ret, ret);
6292 } else if (cur->type == XML_RELAXNG_LIST) {
6293 if (flags & XML_RELAXNG_IN_LIST) {
6294 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_LIST,
6295 "Found forbidden pattern list//list\n", NULL,
6296 NULL);
6297 }
6298 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6299 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_LIST,
6300 "Found forbidden pattern data/except//list\n",
6301 NULL, NULL);
6302 }
6303 if (flags & XML_RELAXNG_IN_START) {
6304 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_LIST,
6305 "Found forbidden pattern start//list\n", NULL,
6306 NULL);
6307 }
6308 nflags = flags | XML_RELAXNG_IN_LIST;
6309 ret =
6310 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6311 cur->type);
6312 } else if (cur->type == XML_RELAXNG_GROUP) {
6313 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6314 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_GROUP,
6315 "Found forbidden pattern data/except//group\n",
6316 NULL, NULL);
6317 }
6318 if (flags & XML_RELAXNG_IN_START) {
6319 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_GROUP,
6320 "Found forbidden pattern start//group\n", NULL,
6321 NULL);
6322 }
6323 if (flags & XML_RELAXNG_IN_ONEORMORE)
6324 nflags = flags | XML_RELAXNG_IN_OOMGROUP;
6325 else
6326 nflags = flags;
6327 ret =
6328 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6329 cur->type);
6330 /*
6331 * The 7.3 Attribute derivation rule for groups is plugged there
6332 */
6333 xmlRelaxNGCheckGroupAttrs(ctxt, cur);
6334 } else if (cur->type == XML_RELAXNG_INTERLEAVE) {
6335 if (flags & XML_RELAXNG_IN_LIST) {
6336 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_INTERLEAVE,
6337 "Found forbidden pattern list//interleave\n",
6338 NULL, NULL);
6339 }
6340 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6341 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
6342 "Found forbidden pattern data/except//interleave\n",
6343 NULL, NULL);
6344 }
6345 if (flags & XML_RELAXNG_IN_START) {
6346 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
6347 "Found forbidden pattern start//interleave\n",
6348 NULL, NULL);
6349 }
6350 if (flags & XML_RELAXNG_IN_ONEORMORE)
6351 nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE;
6352 else
6353 nflags = flags;
6354 ret =
6355 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6356 cur->type);
6357 } else if (cur->type == XML_RELAXNG_EXCEPT) {
6358 if ((cur->parent != NULL) &&
6359 (cur->parent->type == XML_RELAXNG_DATATYPE))
6360 nflags = flags | XML_RELAXNG_IN_DATAEXCEPT;
6361 else
6362 nflags = flags;
6363 ret =
6364 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
6365 cur->type);
6366 } else if (cur->type == XML_RELAXNG_DATATYPE) {
6367 if (flags & XML_RELAXNG_IN_START) {
6368 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_DATA,
6369 "Found forbidden pattern start//data\n", NULL,
6370 NULL);
6371 }
6372 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
6373 ret = XML_RELAXNG_CONTENT_SIMPLE;
6374 } else if (cur->type == XML_RELAXNG_VALUE) {
6375 if (flags & XML_RELAXNG_IN_START) {
6376 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_VALUE,
6377 "Found forbidden pattern start//value\n", NULL,
6378 NULL);
6379 }
6380 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
6381 ret = XML_RELAXNG_CONTENT_SIMPLE;
6382 } else if (cur->type == XML_RELAXNG_TEXT) {
6383 if (flags & XML_RELAXNG_IN_LIST) {
6384 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_TEXT,
6385 "Found forbidden pattern list//text\n", NULL,
6386 NULL);
6387 }
6388 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6389 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_TEXT,
6390 "Found forbidden pattern data/except//text\n",
6391 NULL, NULL);
6392 }
6393 if (flags & XML_RELAXNG_IN_START) {
6394 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_TEXT,
6395 "Found forbidden pattern start//text\n", NULL,
6396 NULL);
6397 }
6398 ret = XML_RELAXNG_CONTENT_COMPLEX;
6399 } else if (cur->type == XML_RELAXNG_EMPTY) {
6400 if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
6401 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_EMPTY,
6402 "Found forbidden pattern data/except//empty\n",
6403 NULL, NULL);
6404 }
6405 if (flags & XML_RELAXNG_IN_START) {
6406 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_EMPTY,
6407 "Found forbidden pattern start//empty\n", NULL,
6408 NULL);
6409 }
6410 ret = XML_RELAXNG_CONTENT_EMPTY;
6411 } else if (cur->type == XML_RELAXNG_CHOICE) {
6412 xmlRelaxNGCheckChoiceDeterminism(ctxt, cur);
6413 ret =
6414 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
6415 } else {
6416 ret =
6417 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
6418 }
6419 cur = cur->next;
6420 if (ptype == XML_RELAXNG_GROUP) {
6421 val = xmlRelaxNGGroupContentType(val, ret);
6422 } else if (ptype == XML_RELAXNG_INTERLEAVE) {
6423 /*
6424 * TODO: scan complain that tmp is never used, seems on purpose
6425 * need double-checking
6426 */
6427 tmp = xmlRelaxNGGroupContentType(val, ret);
6428 if (tmp != XML_RELAXNG_CONTENT_ERROR)
6429 tmp = xmlRelaxNGMaxContentType(val, ret);
6430 } else if (ptype == XML_RELAXNG_CHOICE) {
6431 val = xmlRelaxNGMaxContentType(val, ret);
6432 } else if (ptype == XML_RELAXNG_LIST) {
6433 val = XML_RELAXNG_CONTENT_SIMPLE;
6434 } else if (ptype == XML_RELAXNG_EXCEPT) {
6435 if (ret == XML_RELAXNG_CONTENT_ERROR)
6436 val = XML_RELAXNG_CONTENT_ERROR;
6437 else
6438 val = XML_RELAXNG_CONTENT_SIMPLE;
6439 } else {
6440 val = xmlRelaxNGGroupContentType(val, ret);
6441 }
6442
6443 }
6444 return (val);
6445}
6446
6457static xmlRelaxNGGrammarPtr
6458xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
6459{
6460 xmlRelaxNGGrammarPtr ret, tmp, old;
6461
6462 ret = xmlRelaxNGNewGrammar(ctxt);
6463 if (ret == NULL)
6464 return (NULL);
6465
6466 /*
6467 * Link the new grammar in the tree
6468 */
6469 ret->parent = ctxt->grammar;
6470 if (ctxt->grammar != NULL) {
6471 tmp = ctxt->grammar->children;
6472 if (tmp == NULL) {
6473 ctxt->grammar->children = ret;
6474 } else {
6475 while (tmp->next != NULL)
6476 tmp = tmp->next;
6477 tmp->next = ret;
6478 }
6479 }
6480
6481 old = ctxt->grammar;
6482 ctxt->grammar = ret;
6483 xmlRelaxNGParseGrammarContent(ctxt, nodes);
6484 ctxt->grammar = ret;
6485 if (ctxt->grammar == NULL) {
6486 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
6487 "Failed to parse <grammar> content\n", NULL, NULL);
6488 } else if (ctxt->grammar->start == NULL) {
6489 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_NO_START,
6490 "Element <grammar> has no <start>\n", NULL, NULL);
6491 }
6492
6493 /*
6494 * Apply 4.17 merging rules to defines and starts
6495 */
6496 xmlRelaxNGCombineStart(ctxt, ret);
6497 if (ret->defs != NULL) {
6498 xmlHashScan(ret->defs, xmlRelaxNGCheckCombine, ctxt);
6499 }
6500
6501 /*
6502 * link together defines and refs in this grammar
6503 */
6504 if (ret->refs != NULL) {
6505 xmlHashScan(ret->refs, xmlRelaxNGCheckReference, ctxt);
6506 }
6507
6508
6509 /* @@@@ */
6510
6511 ctxt->grammar = old;
6512 return (ret);
6513}
6514
6526static xmlRelaxNGPtr
6527xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
6528{
6529 xmlRelaxNGPtr schema = NULL;
6530 const xmlChar *olddefine;
6531 xmlRelaxNGGrammarPtr old;
6532
6533 if ((ctxt == NULL) || (node == NULL))
6534 return (NULL);
6535
6536 schema = xmlRelaxNGNewRelaxNG(ctxt);
6537 if (schema == NULL)
6538 return (NULL);
6539
6540 olddefine = ctxt->define;
6541 ctxt->define = NULL;
6542 if (IS_RELAXNG(node, "grammar")) {
6543 schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children);
6544 if (schema->topgrammar == NULL) {
6545 xmlRelaxNGFree(schema);
6546 return (NULL);
6547 }
6548 } else {
6549 xmlRelaxNGGrammarPtr tmp, ret;
6550
6551 schema->topgrammar = ret = xmlRelaxNGNewGrammar(ctxt);
6552 if (schema->topgrammar == NULL) {
6553 xmlRelaxNGFree(schema);
6554 return (NULL);
6555 }
6556 /*
6557 * Link the new grammar in the tree
6558 */
6559 ret->parent = ctxt->grammar;
6560 if (ctxt->grammar != NULL) {
6561 tmp = ctxt->grammar->children;
6562 if (tmp == NULL) {
6563 ctxt->grammar->children = ret;
6564 } else {
6565 while (tmp->next != NULL)
6566 tmp = tmp->next;
6567 tmp->next = ret;
6568 }
6569 }
6570 old = ctxt->grammar;
6571 ctxt->grammar = ret;
6572 xmlRelaxNGParseStart(ctxt, node);
6573 if (old != NULL)
6574 ctxt->grammar = old;
6575 }
6576 ctxt->define = olddefine;
6577 if (schema->topgrammar->start != NULL) {
6578 xmlRelaxNGCheckCycles(ctxt, schema->topgrammar->start, 0);
6579 if ((ctxt->flags & XML_RELAXNG_IN_EXTERNALREF) == 0) {
6580 xmlRelaxNGSimplify(ctxt, schema->topgrammar->start, NULL);
6581 while ((schema->topgrammar->start != NULL) &&
6582 (schema->topgrammar->start->type == XML_RELAXNG_NOOP) &&
6583 (schema->topgrammar->start->next != NULL))
6584 schema->topgrammar->start =
6585 schema->topgrammar->start->content;
6586 xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start,
6587 XML_RELAXNG_IN_START, XML_RELAXNG_NOOP);
6588 }
6589 }
6590
6591 return (schema);
6592}
6593
6594/************************************************************************
6595 * *
6596 * Reading RelaxNGs *
6597 * *
6598 ************************************************************************/
6599
6609xmlRelaxNGParserCtxtPtr
6610xmlRelaxNGNewParserCtxt(const char *URL)
6611{
6612 xmlRelaxNGParserCtxtPtr ret;
6613
6614 if (URL == NULL)
6615 return (NULL);
6616
6617 ret =
6618 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
6619 if (ret == NULL) {
6620 xmlRngPErrMemory(NULL, "building parser\n");
6621 return (NULL);
6622 }
6623 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
6624 ret->URL = xmlStrdup((const xmlChar *) URL);
6625 ret->error = xmlGenericError;
6626 ret->userData = xmlGenericErrorContext;
6627 return (ret);
6628}
6629
6640xmlRelaxNGParserCtxtPtr
6641xmlRelaxNGNewMemParserCtxt(const char *buffer, int size)
6642{
6643 xmlRelaxNGParserCtxtPtr ret;
6644
6645 if ((buffer == NULL) || (size <= 0))
6646 return (NULL);
6647
6648 ret =
6649 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
6650 if (ret == NULL) {
6651 xmlRngPErrMemory(NULL, "building parser\n");
6652 return (NULL);
6653 }
6654 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
6655 ret->buffer = buffer;
6656 ret->size = size;
6657 ret->error = xmlGenericError;
6658 ret->userData = xmlGenericErrorContext;
6659 return (ret);
6660}
6661
6672xmlRelaxNGParserCtxtPtr
6673xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc)
6674{
6675 xmlRelaxNGParserCtxtPtr ret;
6676 xmlDocPtr copy;
6677
6678 if (doc == NULL)
6679 return (NULL);
6680 copy = xmlCopyDoc(doc, 1);
6681 if (copy == NULL)
6682 return (NULL);
6683
6684 ret =
6685 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
6686 if (ret == NULL) {
6687 xmlRngPErrMemory(NULL, "building parser\n");
6688 xmlFreeDoc(copy);
6689 return (NULL);
6690 }
6691 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
6692 ret->document = copy;
6693 ret->freedoc = 1;
6694 ret->userData = xmlGenericErrorContext;
6695 return (ret);
6696}
6697
6704void
6705xmlRelaxNGFreeParserCtxt(xmlRelaxNGParserCtxtPtr ctxt)
6706{
6707 if (ctxt == NULL)
6708 return;
6709 if (ctxt->URL != NULL)
6710 xmlFree(ctxt->URL);
6711 if (ctxt->doc != NULL)
6712 xmlRelaxNGFreeDocument(ctxt->doc);
6713 if (ctxt->interleaves != NULL)
6714 xmlHashFree(ctxt->interleaves, NULL);
6715 if (ctxt->documents != NULL)
6716 xmlRelaxNGFreeDocumentList(ctxt->documents);
6717 if (ctxt->includes != NULL)
6718 xmlRelaxNGFreeIncludeList(ctxt->includes);
6719 if (ctxt->docTab != NULL)
6720 xmlFree(ctxt->docTab);
6721 if (ctxt->incTab != NULL)
6722 xmlFree(ctxt->incTab);
6723 if (ctxt->defTab != NULL) {
6724 int i;
6725
6726 for (i = 0; i < ctxt->defNr; i++)
6727 xmlRelaxNGFreeDefine(ctxt->defTab[i]);
6728 xmlFree(ctxt->defTab);
6729 }
6730 if ((ctxt->document != NULL) && (ctxt->freedoc))
6731 xmlFreeDoc(ctxt->document);
6732 xmlFree(ctxt);
6733}
6734
6742static void
6743xmlRelaxNGNormExtSpace(xmlChar * value)
6744{
6745 xmlChar *start = value;
6746 xmlChar *cur = value;
6747
6748 if (value == NULL)
6749 return;
6750
6751 while (IS_BLANK_CH(*cur))
6752 cur++;
6753 if (cur == start) {
6754 do {
6755 while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
6756 cur++;
6757 if (*cur == 0)
6758 return;
6759 start = cur;
6760 while (IS_BLANK_CH(*cur))
6761 cur++;
6762 if (*cur == 0) {
6763 *start = 0;
6764 return;
6765 }
6766 } while (1);
6767 } else {
6768 do {
6769 while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
6770 *start++ = *cur++;
6771 if (*cur == 0) {
6772 *start = 0;
6773 return;
6774 }
6775 /* don't try to normalize the inner spaces */
6776 while (IS_BLANK_CH(*cur))
6777 cur++;
6778 if (*cur == 0) {
6779 *start = 0;
6780 return;
6781 }
6782 *start++ = *cur++;
6783 } while (1);
6784 }
6785}
6786
6794static void
6795xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
6796{
6797 xmlAttrPtr cur, next;
6798
6799 cur = node->properties;
6800 while (cur != NULL) {
6801 next = cur->next;
6802 if ((cur->ns == NULL) ||
6803 (xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
6804 if (xmlStrEqual(cur->name, BAD_CAST "name")) {
6805 if ((!xmlStrEqual(node->name, BAD_CAST "element")) &&
6806 (!xmlStrEqual(node->name, BAD_CAST "attribute")) &&
6807 (!xmlStrEqual(node->name, BAD_CAST "ref")) &&
6808 (!xmlStrEqual(node->name, BAD_CAST "parentRef")) &&
6809 (!xmlStrEqual(node->name, BAD_CAST "param")) &&
6810 (!xmlStrEqual(node->name, BAD_CAST "define"))) {
6811 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
6812 "Attribute %s is not allowed on %s\n",
6813 cur->name, node->name);
6814 }
6815 } else if (xmlStrEqual(cur->name, BAD_CAST "type")) {
6816 if ((!xmlStrEqual(node->name, BAD_CAST "value")) &&
6817 (!xmlStrEqual(node->name, BAD_CAST "data"))) {
6818 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
6819 "Attribute %s is not allowed on %s\n",
6820 cur->name, node->name);
6821 }
6822 } else if (xmlStrEqual(cur->name, BAD_CAST "href")) {
6823 if ((!xmlStrEqual(node->name, BAD_CAST "externalRef")) &&
6824 (!xmlStrEqual(node->name, BAD_CAST "include"))) {
6825 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
6826 "Attribute %s is not allowed on %s\n",
6827 cur->name, node->name);
6828 }
6829 } else if (xmlStrEqual(cur->name, BAD_CAST "combine")) {
6830 if ((!xmlStrEqual(node->name, BAD_CAST "start")) &&
6831 (!xmlStrEqual(node->name, BAD_CAST "define"))) {
6832 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
6833 "Attribute %s is not allowed on %s\n",
6834 cur->name, node->name);
6835 }
6836 } else if (xmlStrEqual(cur->name, BAD_CAST "datatypeLibrary")) {
6837 xmlChar *val;
6838 xmlURIPtr uri;
6839
6840 val = xmlNodeListGetString(node->doc, cur->children, 1);
6841 if (val != NULL) {
6842 if (val[0] != 0) {
6843 uri = xmlParseURI((const char *) val);
6844 if (uri == NULL) {
6845 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_URI,
6846 "Attribute %s contains invalid URI %s\n",
6847 cur->name, val);
6848 } else {
6849 if (uri->scheme == NULL) {
6850 xmlRngPErr(ctxt, node, XML_RNGP_URI_NOT_ABSOLUTE,
6851 "Attribute %s URI %s is not absolute\n",
6852 cur->name, val);
6853 }
6854 if (uri->fragment != NULL) {
6855 xmlRngPErr(ctxt, node, XML_RNGP_URI_FRAGMENT,
6856 "Attribute %s URI %s has a fragment ID\n",
6857 cur->name, val);
6858 }
6859 xmlFreeURI(uri);
6860 }
6861 }
6862 xmlFree(val);
6863 }
6864 } else if (!xmlStrEqual(cur->name, BAD_CAST "ns")) {
6865 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_ATTRIBUTE,
6866 "Unknown attribute %s on %s\n", cur->name,
6867 node->name);
6868 }
6869 }
6870 cur = next;
6871 }
6872}
6873
6882static void
6883xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root)
6884{
6885 xmlNodePtr cur, delete;
6886
6887 delete = NULL;
6888 cur = root;
6889 while (cur != NULL) {
6890 if (delete != NULL) {
6891 xmlUnlinkNode(delete);
6892 xmlFreeNode(delete);
6893 delete = NULL;
6894 }
6895 if (cur->type == XML_ELEMENT_NODE) {
6896 /*
6897 * Simplification 4.1. Annotations
6898 */
6899 if ((cur->ns == NULL) ||
6900 (!xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
6901 if ((cur->parent != NULL) &&
6902 (cur->parent->type == XML_ELEMENT_NODE) &&
6903 ((xmlStrEqual(cur->parent->name, BAD_CAST "name")) ||
6904 (xmlStrEqual(cur->parent->name, BAD_CAST "value")) ||
6905 (xmlStrEqual(cur->parent->name, BAD_CAST "param")))) {
6906 xmlRngPErr(ctxt, cur, XML_RNGP_FOREIGN_ELEMENT,
6907 "element %s doesn't allow foreign elements\n",
6908 cur->parent->name, NULL);
6909 }
6910 delete = cur;
6911 goto skip_children;
6912 } else {
6913 xmlRelaxNGCleanupAttributes(ctxt, cur);
6914 if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) {
6915 xmlChar *href, *ns, *base, *URL;
6916 xmlRelaxNGDocumentPtr docu;
6917 xmlNodePtr tmp;
6918 xmlURIPtr uri;
6919
6920 ns = xmlGetProp(cur, BAD_CAST "ns");
6921 if (ns == NULL) {
6922 tmp = cur->parent;
6923 while ((tmp != NULL) &&
6924 (tmp->type == XML_ELEMENT_NODE)) {
6925 ns = xmlGetProp(tmp, BAD_CAST "ns");
6926 if (ns != NULL)
6927 break;
6928 tmp = tmp->parent;
6929 }
6930 }
6931 href = xmlGetProp(cur, BAD_CAST "href");
6932 if (href == NULL) {
6933 xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
6934 "xmlRelaxNGParse: externalRef has no href attribute\n",
6935 NULL, NULL);
6936 if (ns != NULL)
6937 xmlFree(ns);
6938 delete = cur;
6939 goto skip_children;
6940 }
6941 uri = xmlParseURI((const char *) href);
6942 if (uri == NULL) {
6943 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
6944 "Incorrect URI for externalRef %s\n",
6945 href, NULL);
6946 if (ns != NULL)
6947 xmlFree(ns);
6948 if (href != NULL)
6949 xmlFree(href);
6950 delete = cur;
6951 goto skip_children;
6952 }
6953 if (uri->fragment != NULL) {
6954 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
6955 "Fragment forbidden in URI for externalRef %s\n",
6956 href, NULL);
6957 if (ns != NULL)
6958 xmlFree(ns);
6959 xmlFreeURI(uri);
6960 if (href != NULL)
6961 xmlFree(href);
6962 delete = cur;
6963 goto skip_children;
6964 }
6965 xmlFreeURI(uri);
6966 base = xmlNodeGetBase(cur->doc, cur);
6967 URL = xmlBuildURI(href, base);
6968 if (URL == NULL) {
6969 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
6970 "Failed to compute URL for externalRef %s\n",
6971 href, NULL);
6972 if (ns != NULL)
6973 xmlFree(ns);
6974 if (href != NULL)
6975 xmlFree(href);
6976 if (base != NULL)
6977 xmlFree(base);
6978 delete = cur;
6979 goto skip_children;
6980 }
6981 if (href != NULL)
6982 xmlFree(href);
6983 if (base != NULL)
6984 xmlFree(base);
6985 docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns);
6986 if (docu == NULL) {
6987 xmlRngPErr(ctxt, cur, XML_RNGP_EXTERNAL_REF_FAILURE,
6988 "Failed to load externalRef %s\n", URL,
6989 NULL);
6990 if (ns != NULL)
6991 xmlFree(ns);
6992 xmlFree(URL);
6993 delete = cur;
6994 goto skip_children;
6995 }
6996 if (ns != NULL)
6997 xmlFree(ns);
6998 xmlFree(URL);
6999 cur->psvi = docu;
7000 } else if (xmlStrEqual(cur->name, BAD_CAST "include")) {
7001 xmlChar *href, *ns, *base, *URL;
7002 xmlRelaxNGIncludePtr incl;
7003 xmlNodePtr tmp;
7004
7005 href = xmlGetProp(cur, BAD_CAST "href");
7006 if (href == NULL) {
7007 xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
7008 "xmlRelaxNGParse: include has no href attribute\n",
7009 NULL, NULL);
7010 delete = cur;
7011 goto skip_children;
7012 }
7013 base = xmlNodeGetBase(cur->doc, cur);
7014 URL = xmlBuildURI(href, base);
7015 if (URL == NULL) {
7016 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
7017 "Failed to compute URL for include %s\n",
7018 href, NULL);
7019 if (href != NULL)
7020 xmlFree(href);
7021 if (base != NULL)
7022 xmlFree(base);
7023 delete = cur;
7024 goto skip_children;
7025 }
7026 if (href != NULL)
7027 xmlFree(href);
7028 if (base != NULL)
7029 xmlFree(base);
7030 ns = xmlGetProp(cur, BAD_CAST "ns");
7031 if (ns == NULL) {
7032 tmp = cur->parent;
7033 while ((tmp != NULL) &&
7034 (tmp->type == XML_ELEMENT_NODE)) {
7035 ns = xmlGetProp(tmp, BAD_CAST "ns");
7036 if (ns != NULL)
7037 break;
7038 tmp = tmp->parent;
7039 }
7040 }
7041 incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns);
7042 if (ns != NULL)
7043 xmlFree(ns);
7044 if (incl == NULL) {
7045 xmlRngPErr(ctxt, cur, XML_RNGP_INCLUDE_FAILURE,
7046 "Failed to load include %s\n", URL,
7047 NULL);
7048 xmlFree(URL);
7049 delete = cur;
7050 goto skip_children;
7051 }
7052 xmlFree(URL);
7053 cur->psvi = incl;
7054 } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) ||
7055 (xmlStrEqual(cur->name, BAD_CAST "attribute")))
7056 {
7057 xmlChar *name, *ns;
7058 xmlNodePtr text = NULL;
7059
7060 /*
7061 * Simplification 4.8. name attribute of element
7062 * and attribute elements
7063 */
7064 name = xmlGetProp(cur, BAD_CAST "name");
7065 if (name != NULL) {
7066 if (cur->children == NULL) {
7067 text =
7068 xmlNewChild(cur, cur->ns, BAD_CAST "name",
7069 name);
7070 } else {
7071 xmlNodePtr node;
7072
7073 node = xmlNewDocNode(cur->doc, cur->ns,
7074 BAD_CAST "name", NULL);
7075 if (node != NULL) {
7076 xmlAddPrevSibling(cur->children, node);
7077 text = xmlNewDocText(node->doc, name);
7078 xmlAddChild(node, text);
7079 text = node;
7080 }
7081 }
7082 if (text == NULL) {
7083 xmlRngPErr(ctxt, cur, XML_RNGP_CREATE_FAILURE,
7084 "Failed to create a name %s element\n",
7085 name, NULL);
7086 }
7087 xmlUnsetProp(cur, BAD_CAST "name");
7088 xmlFree(name);
7089 ns = xmlGetProp(cur, BAD_CAST "ns");
7090 if (ns != NULL) {
7091 if (text != NULL) {
7092 xmlSetProp(text, BAD_CAST "ns", ns);
7093 /* xmlUnsetProp(cur, BAD_CAST "ns"); */
7094 }
7095 xmlFree(ns);
7096 } else if (xmlStrEqual(cur->name,
7097 BAD_CAST "attribute")) {
7098 xmlSetProp(text, BAD_CAST "ns", BAD_CAST "");
7099 }
7100 }
7101 } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) ||
7102 (xmlStrEqual(cur->name, BAD_CAST "nsName")) ||
7103 (xmlStrEqual(cur->name, BAD_CAST "value"))) {
7104 /*
7105 * Simplification 4.8. name attribute of element
7106 * and attribute elements
7107 */
7108 if (xmlHasProp(cur, BAD_CAST "ns") == NULL) {
7109 xmlNodePtr node;
7110 xmlChar *ns = NULL;
7111
7112 node = cur->parent;
7113 while ((node != NULL) &&
7114 (node->type == XML_ELEMENT_NODE)) {
7115 ns = xmlGetProp(node, BAD_CAST "ns");
7116 if (ns != NULL) {
7117 break;
7118 }
7119 node = node->parent;
7120 }
7121 if (ns == NULL) {
7122 xmlSetProp(cur, BAD_CAST "ns", BAD_CAST "");
7123 } else {
7124 xmlSetProp(cur, BAD_CAST "ns", ns);
7125 xmlFree(ns);
7126 }
7127 }
7128 if (xmlStrEqual(cur->name, BAD_CAST "name")) {
7129 xmlChar *name, *local, *prefix;
7130
7131 /*
7132 * Simplification: 4.10. QNames
7133 */
7134 name = xmlNodeGetContent(cur);
7135 if (name != NULL) {
7136 local = xmlSplitQName2(name, &prefix);
7137 if (local != NULL) {
7138 xmlNsPtr ns;
7139
7140 ns = xmlSearchNs(cur->doc, cur, prefix);
7141 if (ns == NULL) {
7142 xmlRngPErr(ctxt, cur,
7144 "xmlRelaxNGParse: no namespace for prefix %s\n",
7145 prefix, NULL);
7146 } else {
7147 xmlSetProp(cur, BAD_CAST "ns",
7148 ns->href);
7149 xmlNodeSetContent(cur, local);
7150 }
7151 xmlFree(local);
7152 xmlFree(prefix);
7153 }
7154 xmlFree(name);
7155 }
7156 }
7157 /*
7158 * 4.16
7159 */
7160 if (xmlStrEqual(cur->name, BAD_CAST "nsName")) {
7161 if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
7162 xmlRngPErr(ctxt, cur,
7164 "Found nsName/except//nsName forbidden construct\n",
7165 NULL, NULL);
7166 }
7167 }
7168 } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) &&
7169 (cur != root)) {
7170 int oldflags = ctxt->flags;
7171
7172 /*
7173 * 4.16
7174 */
7175 if ((cur->parent != NULL) &&
7177 (cur->parent->name, BAD_CAST "anyName"))) {
7178 ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT;
7179 xmlRelaxNGCleanupTree(ctxt, cur);
7180 ctxt->flags = oldflags;
7181 goto skip_children;
7182 } else if ((cur->parent != NULL) &&
7184 (cur->parent->name, BAD_CAST "nsName"))) {
7185 ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT;
7186 xmlRelaxNGCleanupTree(ctxt, cur);
7187 ctxt->flags = oldflags;
7188 goto skip_children;
7189 }
7190 } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) {
7191 /*
7192 * 4.16
7193 */
7194 if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) {
7195 xmlRngPErr(ctxt, cur,
7197 "Found anyName/except//anyName forbidden construct\n",
7198 NULL, NULL);
7199 } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
7200 xmlRngPErr(ctxt, cur,
7202 "Found nsName/except//anyName forbidden construct\n",
7203 NULL, NULL);
7204 }
7205 }
7206 /*
7207 * This is not an else since "include" is transformed
7208 * into a div
7209 */
7210 if (xmlStrEqual(cur->name, BAD_CAST "div")) {
7211 xmlChar *ns;
7212 xmlNodePtr child, ins, tmp;
7213
7214 /*
7215 * implements rule 4.11
7216 */
7217
7218 ns = xmlGetProp(cur, BAD_CAST "ns");
7219
7220 child = cur->children;
7221 ins = cur;
7222 while (child != NULL) {
7223 if (ns != NULL) {
7224 if (!xmlHasProp(child, BAD_CAST "ns")) {
7225 xmlSetProp(child, BAD_CAST "ns", ns);
7226 }
7227 }
7228 tmp = child->next;
7229 xmlUnlinkNode(child);
7230 ins = xmlAddNextSibling(ins, child);
7231 child = tmp;
7232 }
7233 if (ns != NULL)
7234 xmlFree(ns);
7235 /*
7236 * Since we are about to delete cur, if its nsDef is non-NULL we
7237 * need to preserve it (it contains the ns definitions for the
7238 * children we just moved). We'll just stick it on to the end
7239 * of cur->parent's list, since it's never going to be re-serialized
7240 * (bug 143738).
7241 */
7242 if ((cur->nsDef != NULL) && (cur->parent != NULL)) {
7243 xmlNsPtr parDef = (xmlNsPtr)&cur->parent->nsDef;
7244 while (parDef->next != NULL)
7245 parDef = parDef->next;
7246 parDef->next = cur->nsDef;
7247 cur->nsDef = NULL;
7248 }
7249 delete = cur;
7250 goto skip_children;
7251 }
7252 }
7253 }
7254 /*
7255 * Simplification 4.2 whitespaces
7256 */
7257 else if ((cur->type == XML_TEXT_NODE) ||
7258 (cur->type == XML_CDATA_SECTION_NODE)) {
7259 if (IS_BLANK_NODE(cur)) {
7260 if ((cur->parent != NULL) &&
7261 (cur->parent->type == XML_ELEMENT_NODE)) {
7262 if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value"))
7263 &&
7264 (!xmlStrEqual
7265 (cur->parent->name, BAD_CAST "param")))
7266 delete = cur;
7267 } else {
7268 delete = cur;
7269 goto skip_children;
7270 }
7271 }
7272 } else {
7273 delete = cur;
7274 goto skip_children;
7275 }
7276
7277 /*
7278 * Skip to next node
7279 */
7280 if (cur->children != NULL) {
7281 if ((cur->children->type != XML_ENTITY_DECL) &&
7282 (cur->children->type != XML_ENTITY_REF_NODE) &&
7283 (cur->children->type != XML_ENTITY_NODE)) {
7284 cur = cur->children;
7285 continue;
7286 }
7287 }
7288 skip_children:
7289 if (cur->next != NULL) {
7290 cur = cur->next;
7291 continue;
7292 }
7293
7294 do {
7295 cur = cur->parent;
7296 if (cur == NULL)
7297 break;
7298 if (cur == root) {
7299 cur = NULL;
7300 break;
7301 }
7302 if (cur->next != NULL) {
7303 cur = cur->next;
7304 break;
7305 }
7306 } while (cur != NULL);
7307 }
7308 if (delete != NULL) {
7309 xmlUnlinkNode(delete);
7310 xmlFreeNode(delete);
7311 delete = NULL;
7312 }
7313}
7314
7325static xmlDocPtr
7326xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc)
7327{
7328 xmlNodePtr root;
7329
7330 /*
7331 * Extract the root
7332 */
7333 root = xmlDocGetRootElement(doc);
7334 if (root == NULL) {
7335 xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
7336 ctxt->URL, NULL);
7337 return (NULL);
7338 }
7339 xmlRelaxNGCleanupTree(ctxt, root);
7340 return (doc);
7341}
7342
7353xmlRelaxNGPtr
7354xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
7355{
7356 xmlRelaxNGPtr ret = NULL;
7357 xmlDocPtr doc;
7358 xmlNodePtr root;
7359
7360 xmlRelaxNGInitTypes();
7361
7362 if (ctxt == NULL)
7363 return (NULL);
7364
7365 /*
7366 * First step is to parse the input document into an DOM/Infoset
7367 */
7368 if (ctxt->URL != NULL) {
7369 doc = xmlReadFile((const char *) ctxt->URL,NULL,0);
7370 if (doc == NULL) {
7371 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
7372 "xmlRelaxNGParse: could not load %s\n", ctxt->URL,
7373 NULL);
7374 return (NULL);
7375 }
7376 } else if (ctxt->buffer != NULL) {
7377 doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0);
7378 if (doc == NULL) {
7379 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
7380 "xmlRelaxNGParse: could not parse schemas\n", NULL,
7381 NULL);
7382 return (NULL);
7383 }
7384 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
7385 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
7386 } else if (ctxt->document != NULL) {
7387 doc = ctxt->document;
7388 } else {
7389 xmlRngPErr(ctxt, NULL, XML_RNGP_EMPTY,
7390 "xmlRelaxNGParse: nothing to parse\n", NULL, NULL);
7391 return (NULL);
7392 }
7393 ctxt->document = doc;
7394
7395 /*
7396 * Some preprocessing of the document content
7397 */
7398 doc = xmlRelaxNGCleanupDoc(ctxt, doc);
7399 if (doc == NULL) {
7400 xmlFreeDoc(ctxt->document);
7401 ctxt->document = NULL;
7402 return (NULL);
7403 }
7404
7405 /*
7406 * Then do the parsing for good
7407 */
7408 root = xmlDocGetRootElement(doc);
7409 if (root == NULL) {
7410 xmlRngPErr(ctxt, (xmlNodePtr) doc,
7411 XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
7412 (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL);
7413
7414 xmlFreeDoc(ctxt->document);
7415 ctxt->document = NULL;
7416 return (NULL);
7417 }
7418 ret = xmlRelaxNGParseDocument(ctxt, root);
7419 if (ret == NULL) {
7420 xmlFreeDoc(ctxt->document);
7421 ctxt->document = NULL;
7422 return (NULL);
7423 }
7424
7425 /*
7426 * Check the ref/defines links
7427 */
7428 /*
7429 * try to preprocess interleaves
7430 */
7431 if (ctxt->interleaves != NULL) {
7432 xmlHashScan(ctxt->interleaves, xmlRelaxNGComputeInterleaves, ctxt);
7433 }
7434
7435 /*
7436 * if there was a parsing error return NULL
7437 */
7438 if (ctxt->nbErrors > 0) {
7439 xmlRelaxNGFree(ret);
7440 ctxt->document = NULL;
7441 xmlFreeDoc(doc);
7442 return (NULL);
7443 }
7444
7445 /*
7446 * try to compile (parts of) the schemas
7447 */
7448 if ((ret->topgrammar != NULL) && (ret->topgrammar->start != NULL)) {
7449 if (ret->topgrammar->start->type != XML_RELAXNG_START) {
7450 xmlRelaxNGDefinePtr def;
7451
7452 def = xmlRelaxNGNewDefine(ctxt, NULL);
7453 if (def != NULL) {
7454 def->type = XML_RELAXNG_START;
7455 def->content = ret->topgrammar->start;
7456 ret->topgrammar->start = def;
7457 }
7458 }
7459 xmlRelaxNGTryCompile(ctxt, ret->topgrammar->start);
7460 }
7461
7462 /*
7463 * Transfer the pointer for cleanup at the schema level.
7464 */
7465 ret->doc = doc;
7466 ctxt->document = NULL;
7467 ret->documents = ctxt->documents;
7468 ctxt->documents = NULL;
7469
7470 ret->includes = ctxt->includes;
7471 ctxt->includes = NULL;
7472 ret->defNr = ctxt->defNr;
7473 ret->defTab = ctxt->defTab;
7474 ctxt->defTab = NULL;
7475 if (ctxt->idref == 1)
7476 ret->idref = 1;
7477
7478 return (ret);
7479}
7480
7490void
7491xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
7492 xmlRelaxNGValidityErrorFunc err,
7493 xmlRelaxNGValidityWarningFunc warn, void *ctx)
7494{
7495 if (ctxt == NULL)
7496 return;
7497 ctxt->error = err;
7498 ctxt->warning = warn;
7499 ctxt->serror = NULL;
7500 ctxt->userData = ctx;
7501}
7502
7514int
7515xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
7516 xmlRelaxNGValidityErrorFunc * err,
7517 xmlRelaxNGValidityWarningFunc * warn, void **ctx)
7518{
7519 if (ctxt == NULL)
7520 return (-1);
7521 if (err != NULL)
7522 *err = ctxt->error;
7523 if (warn != NULL)
7524 *warn = ctxt->warning;
7525 if (ctx != NULL)
7526 *ctx = ctxt->userData;
7527 return (0);
7528}
7529
7538void
7539xmlRelaxNGSetParserStructuredErrors(xmlRelaxNGParserCtxtPtr ctxt,
7541 void *ctx)
7542{
7543 if (ctxt == NULL)
7544 return;
7545 ctxt->serror = serror;
7546 ctxt->error = NULL;
7547 ctxt->warning = NULL;
7548 ctxt->userData = ctx;
7549}
7550
7551#ifdef LIBXML_OUTPUT_ENABLED
7552
7553/************************************************************************
7554 * *
7555 * Dump back a compiled form *
7556 * *
7557 ************************************************************************/
7558static void xmlRelaxNGDumpDefine(FILE * output,
7559 xmlRelaxNGDefinePtr define);
7560
7568static void
7569xmlRelaxNGDumpDefines(FILE * output, xmlRelaxNGDefinePtr defines)
7570{
7571 while (defines != NULL) {
7572 xmlRelaxNGDumpDefine(output, defines);
7573 defines = defines->next;
7574 }
7575}
7576
7584static void
7585xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define)
7586{
7587 if (define == NULL)
7588 return;
7589 switch (define->type) {
7590 case XML_RELAXNG_EMPTY:
7591 fprintf(output, "<empty/>\n");
7592 break;
7593 case XML_RELAXNG_NOT_ALLOWED:
7594 fprintf(output, "<notAllowed/>\n");
7595 break;
7596 case XML_RELAXNG_TEXT:
7597 fprintf(output, "<text/>\n");
7598 break;
7599 case XML_RELAXNG_ELEMENT:
7600 fprintf(output, "<element>\n");
7601 if (define->name != NULL) {
7602 fprintf(output, "<name");
7603 if (define->ns != NULL)
7604 fprintf(output, " ns=\"%s\"", define->ns);
7605 fprintf(output, ">%s</name>\n", define->name);
7606 }
7607 xmlRelaxNGDumpDefines(output, define->attrs);
7608 xmlRelaxNGDumpDefines(output, define->content);
7609 fprintf(output, "</element>\n");
7610 break;
7611 case XML_RELAXNG_LIST:
7612 fprintf(output, "<list>\n");
7613 xmlRelaxNGDumpDefines(output, define->content);
7614 fprintf(output, "</list>\n");
7615 break;
7616 case XML_RELAXNG_ONEORMORE:
7617 fprintf(output, "<oneOrMore>\n");
7618 xmlRelaxNGDumpDefines(output, define->content);
7619 fprintf(output, "</oneOrMore>\n");
7620 break;
7621 case XML_RELAXNG_ZEROORMORE:
7622 fprintf(output, "<zeroOrMore>\n");
7623 xmlRelaxNGDumpDefines(output, define->content);
7624 fprintf(output, "</zeroOrMore>\n");
7625 break;
7626 case XML_RELAXNG_CHOICE:
7627 fprintf(output, "<choice>\n");
7628 xmlRelaxNGDumpDefines(output, define->content);
7629 fprintf(output, "</choice>\n");
7630 break;
7631 case XML_RELAXNG_GROUP:
7632 fprintf(output, "<group>\n");
7633 xmlRelaxNGDumpDefines(output, define->content);
7634 fprintf(output, "</group>\n");
7635 break;
7636 case XML_RELAXNG_INTERLEAVE:
7637 fprintf(output, "<interleave>\n");
7638 xmlRelaxNGDumpDefines(output, define->content);
7639 fprintf(output, "</interleave>\n");
7640 break;
7641 case XML_RELAXNG_OPTIONAL:
7642 fprintf(output, "<optional>\n");
7643 xmlRelaxNGDumpDefines(output, define->content);
7644 fprintf(output, "</optional>\n");
7645 break;
7646 case XML_RELAXNG_ATTRIBUTE:
7647 fprintf(output, "<attribute>\n");
7648 xmlRelaxNGDumpDefines(output, define->content);
7649 fprintf(output, "</attribute>\n");
7650 break;
7651 case XML_RELAXNG_DEF:
7652 fprintf(output, "<define");
7653 if (define->name != NULL)
7654 fprintf(output, " name=\"%s\"", define->name);
7655 fprintf(output, ">\n");
7656 xmlRelaxNGDumpDefines(output, define->content);
7657 fprintf(output, "</define>\n");
7658 break;
7659 case XML_RELAXNG_REF:
7660 fprintf(output, "<ref");
7661 if (define->name != NULL)
7662 fprintf(output, " name=\"%s\"", define->name);
7663 fprintf(output, ">\n");
7664 xmlRelaxNGDumpDefines(output, define->content);
7665 fprintf(output, "</ref>\n");
7666 break;
7667 case XML_RELAXNG_PARENTREF:
7668 fprintf(output, "<parentRef");
7669 if (define->name != NULL)
7670 fprintf(output, " name=\"%s\"", define->name);
7671 fprintf(output, ">\n");
7672 xmlRelaxNGDumpDefines(output, define->content);
7673 fprintf(output, "</parentRef>\n");
7674 break;
7675 case XML_RELAXNG_EXTERNALREF:
7676 fprintf(output, "<externalRef>");
7677 xmlRelaxNGDumpDefines(output, define->content);
7678 fprintf(output, "</externalRef>\n");
7679 break;
7680 case XML_RELAXNG_DATATYPE:
7681 case XML_RELAXNG_VALUE:
7682 TODO break;
7683 case XML_RELAXNG_START:
7684 case XML_RELAXNG_EXCEPT:
7685 case XML_RELAXNG_PARAM:
7686 TODO break;
7687 case XML_RELAXNG_NOOP:
7688 xmlRelaxNGDumpDefines(output, define->content);
7689 break;
7690 }
7691}
7692
7701static void
7702xmlRelaxNGDumpGrammar(FILE * output, xmlRelaxNGGrammarPtr grammar, int top)
7703{
7704 if (grammar == NULL)
7705 return;
7706
7707 fprintf(output, "<grammar");
7708 if (top)
7709 fprintf(output, " xmlns=\"http://relaxng.org/ns/structure/1.0\"");
7710 switch (grammar->combine) {
7711 case XML_RELAXNG_COMBINE_UNDEFINED:
7712 break;
7713 case XML_RELAXNG_COMBINE_CHOICE:
7714 fprintf(output, " combine=\"choice\"");
7715 break;
7716 case XML_RELAXNG_COMBINE_INTERLEAVE:
7717 fprintf(output, " combine=\"interleave\"");
7718 break;
7719 default:
7720 fprintf(output, " <!-- invalid combine value -->");
7721 }
7722 fprintf(output, ">\n");
7723 if (grammar->start == NULL) {
7724 fprintf(output, " <!-- grammar had no start -->");
7725 } else {
7726 fprintf(output, "<start>\n");
7727 xmlRelaxNGDumpDefine(output, grammar->start);
7728 fprintf(output, "</start>\n");
7729 }
7730 /* TODO ? Dump the defines ? */
7731 fprintf(output, "</grammar>\n");
7732}
7733
7741void
7742xmlRelaxNGDump(FILE * output, xmlRelaxNGPtr schema)
7743{
7744 if (output == NULL)
7745 return;
7746 if (schema == NULL) {
7747 fprintf(output, "RelaxNG empty or failed to compile\n");
7748 return;
7749 }
7750 fprintf(output, "RelaxNG: ");
7751 if (schema->doc == NULL) {
7752 fprintf(output, "no document\n");
7753 } else if (schema->doc->URL != NULL) {
7754 fprintf(output, "%s\n", schema->doc->URL);
7755 } else {
7756 fprintf(output, "\n");
7757 }
7758 if (schema->topgrammar == NULL) {
7759 fprintf(output, "RelaxNG has no top grammar\n");
7760 return;
7761 }
7762 xmlRelaxNGDumpGrammar(output, schema->topgrammar, 1);
7763}
7764
7772void
7773xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema)
7774{
7775 if (output == NULL)
7776 return;
7777 if (schema == NULL) {
7778 fprintf(output, "RelaxNG empty or failed to compile\n");
7779 return;
7780 }
7781 if (schema->doc == NULL) {
7782 fprintf(output, "no document\n");
7783 } else {
7784 xmlDocDump(output, schema->doc);
7785 }
7786}
7787#endif /* LIBXML_OUTPUT_ENABLED */
7788
7789/************************************************************************
7790 * *
7791 * Validation of compiled content *
7792 * *
7793 ************************************************************************/
7794static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
7795 xmlRelaxNGDefinePtr define);
7796
7806static void
7807xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
7808 const xmlChar * token,
7809 void *transdata, void *inputdata)
7810{
7811 xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
7812 xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
7813 int ret;
7814
7815 if (ctxt == NULL) {
7816 fprintf(stderr, "callback on %s missing context\n", token);
7817 return;
7818 }
7819 if (define == NULL) {
7820 if (token[0] == '#')
7821 return;
7822 fprintf(stderr, "callback on %s missing define\n", token);
7823 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
7824 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
7825 return;
7826 }
7827 if (define->type != XML_RELAXNG_ELEMENT) {
7828 fprintf(stderr, "callback on %s define is not element\n", token);
7829 if (ctxt->errNo == XML_RELAXNG_OK)
7830 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
7831 return;
7832 }
7833 ret = xmlRelaxNGValidateDefinition(ctxt, define);
7834 if (ret != 0)
7835 ctxt->perr = ret;
7836}
7837
7848static int
7849xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt,
7850 xmlRegexpPtr regexp, xmlNodePtr content)
7851{
7852 xmlRegExecCtxtPtr exec;
7853 xmlNodePtr cur;
7854 int ret = 0;
7855 int oldperr;
7856
7857 if ((ctxt == NULL) || (regexp == NULL))
7858 return (-1);
7859 oldperr = ctxt->perr;
7860 exec = xmlRegNewExecCtxt(regexp,
7861 xmlRelaxNGValidateCompiledCallback, ctxt);
7862 ctxt->perr = 0;
7863 cur = content;
7864 while (cur != NULL) {
7865 ctxt->state->seq = cur;
7866 switch (cur->type) {
7867 case XML_TEXT_NODE:
7868 case XML_CDATA_SECTION_NODE:
7869 if (xmlIsBlankNode(cur))
7870 break;
7871 ret = xmlRegExecPushString(exec, BAD_CAST "#text", ctxt);
7872 if (ret < 0) {
7873 VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG,
7874 cur->parent->name);
7875 }
7876 break;
7877 case XML_ELEMENT_NODE:
7878 if (cur->ns != NULL) {
7879 ret = xmlRegExecPushString2(exec, cur->name,
7880 cur->ns->href, ctxt);
7881 } else {
7882 ret = xmlRegExecPushString(exec, cur->name, ctxt);
7883 }
7884 if (ret < 0) {
7885 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, cur->name);
7886 }
7887 break;
7888 default:
7889 break;
7890 }
7891 if (ret < 0)
7892 break;
7893 /*
7894 * Switch to next element
7895 */
7896 cur = cur->next;
7897 }
7898 ret = xmlRegExecPushString(exec, NULL, NULL);
7899 if (ret == 1) {
7900 ret = 0;
7901 ctxt->state->seq = NULL;
7902 } else if (ret == 0) {
7903 /*
7904 * TODO: get some of the names needed to exit the current state of exec
7905 */
7906 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
7907 ret = -1;
7908 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
7909 xmlRelaxNGDumpValidError(ctxt);
7910 } else {
7911 ret = -1;
7912 }
7913 xmlRegFreeExecCtxt(exec);
7914 /*
7915 * There might be content model errors outside of the pure
7916 * regexp validation, e.g. for attribute values.
7917 */
7918 if ((ret == 0) && (ctxt->perr != 0)) {
7919 ret = ctxt->perr;
7920 }
7921 ctxt->perr = oldperr;
7922 return (ret);
7923}
7924
7925/************************************************************************
7926 * *
7927 * Progressive validation of when possible *
7928 * *
7929 ************************************************************************/
7930static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
7931 xmlRelaxNGDefinePtr defines);
7932static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt,
7933 int dolog);
7934static void xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt);
7935
7945static int
7946xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec)
7947{
7948 if (ctxt->elemTab == NULL) {
7949 ctxt->elemMax = 10;
7950 ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlMalloc(ctxt->elemMax *
7951 sizeof
7952 (xmlRegExecCtxtPtr));
7953 if (ctxt->elemTab == NULL) {
7954 xmlRngVErrMemory(ctxt, "validating\n");
7955 return (-1);
7956 }
7957 }
7958 if (ctxt->elemNr >= ctxt->elemMax) {
7959 ctxt->elemMax *= 2;
7960 ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlRealloc(ctxt->elemTab,
7961 ctxt->elemMax *
7962 sizeof
7963 (xmlRegExecCtxtPtr));
7964 if (ctxt->elemTab == NULL) {
7965 xmlRngVErrMemory(ctxt, "validating\n");
7966 return (-1);
7967 }
7968 }
7969 ctxt->elemTab[ctxt->elemNr++] = exec;
7970 ctxt->elem = exec;
7971 return (0);
7972}
7973
7982static xmlRegExecCtxtPtr
7983xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt)
7984{
7985 xmlRegExecCtxtPtr ret;
7986
7987 if (ctxt->elemNr <= 0)
7988 return (NULL);
7989 ctxt->elemNr--;
7990 ret = ctxt->elemTab[ctxt->elemNr];
7991 ctxt->elemTab[ctxt->elemNr] = NULL;
7992 if (ctxt->elemNr > 0)
7993 ctxt->elem = ctxt->elemTab[ctxt->elemNr - 1];
7994 else
7995 ctxt->elem = NULL;
7996 return (ret);
7997}
7998
8009static void
8010xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec
8012 const xmlChar * token,
8013 void *transdata, void *inputdata)
8014{
8015 xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;
8016 xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;
8017 xmlRelaxNGValidStatePtr state, oldstate;
8018 xmlNodePtr node;
8019 int ret = 0, oldflags;
8020
8021 if (ctxt == NULL) {
8022 fprintf(stderr, "callback on %s missing context\n", token);
8023 return;
8024 }
8025 node = ctxt->pnode;
8026 ctxt->pstate = 1;
8027 if (define == NULL) {
8028 if (token[0] == '#')
8029 return;
8030 fprintf(stderr, "callback on %s missing define\n", token);
8031 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
8032 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
8033 ctxt->pstate = -1;
8034 return;
8035 }
8036 if ((ctxt == NULL) || (define == NULL)) {
8037 fprintf(stderr, "callback on %s missing info\n", token);
8038 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))
8039 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
8040 ctxt->pstate = -1;
8041 return;
8042 } else if (define->type != XML_RELAXNG_ELEMENT) {
8043 fprintf(stderr, "callback on %s define is not element\n", token);
8044 if (ctxt->errNo == XML_RELAXNG_OK)
8045 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;
8046 ctxt->pstate = -1;
8047 return;
8048 }
8049 if (node->type != XML_ELEMENT_NODE) {
8050 VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
8051 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
8052 xmlRelaxNGDumpValidError(ctxt);
8053 ctxt->pstate = -1;
8054 return;
8055 }
8056 if (define->contModel == NULL) {
8057 /*
8058 * this node cannot be validated in a streamable fashion
8059 */
8060 ctxt->pstate = 0;
8061 ctxt->pdef = define;
8062 return;
8063 }
8064 exec = xmlRegNewExecCtxt(define->contModel,
8065 xmlRelaxNGValidateProgressiveCallback, ctxt);
8066 if (exec == NULL) {
8067 ctxt->pstate = -1;
8068 return;
8069 }
8070 xmlRelaxNGElemPush(ctxt, exec);
8071
8072 /*
8073 * Validate the attributes part of the content.
8074 */
8075 state = xmlRelaxNGNewValidState(ctxt, node);
8076 if (state == NULL) {
8077 ctxt->pstate = -1;
8078 return;
8079 }
8080 oldstate = ctxt->state;
8081 ctxt->state = state;
8082 if (define->attrs != NULL) {
8083 ret = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
8084 if (ret != 0) {
8085 ctxt->pstate = -1;
8086 VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
8087 }
8088 }
8089 if (ctxt->state != NULL) {
8090 ctxt->state->seq = NULL;
8091 ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
8092 if (ret != 0) {
8093 ctxt->pstate = -1;
8094 }
8095 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
8096 } else if (ctxt->states != NULL) {
8097 int tmp = -1, i;
8098
8099 oldflags = ctxt->flags;
8100
8101 for (i = 0; i < ctxt->states->nbState; i++) {
8102 state = ctxt->states->tabState[i];
8103 ctxt->state = state;
8104 ctxt->state->seq = NULL;
8105
8106 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
8107 tmp = 0;
8108 break;
8109 }
8110 }
8111 if (tmp != 0) {
8112 /*
8113 * validation error, log the message for the "best" one
8114 */
8115 ctxt->flags |= FLAGS_IGNORABLE;
8116 xmlRelaxNGLogBestError(ctxt);
8117 }
8118 for (i = 0; i < ctxt->states->nbState; i++) {
8119 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[i]);
8120 }
8121 xmlRelaxNGFreeStates(ctxt, ctxt->states);
8122 ctxt->states = NULL;
8123 if ((ret == 0) && (tmp == -1))
8124 ctxt->pstate = -1;
8125 ctxt->flags = oldflags;
8126 }
8127 if (ctxt->pstate == -1) {
8128 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
8129 xmlRelaxNGDumpValidError(ctxt);
8130 }
8131 }
8132 ctxt->state = oldstate;
8133}
8134
8146int
8147xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt,
8148 xmlDocPtr doc ATTRIBUTE_UNUSED,
8149 xmlNodePtr elem)
8150{
8151 int ret = 1;
8152
8153 if ((ctxt == NULL) || (elem == NULL))
8154 return (-1);
8155
8156 if (ctxt->elem == 0) {
8157 xmlRelaxNGPtr schema;
8158 xmlRelaxNGGrammarPtr grammar;
8159 xmlRegExecCtxtPtr exec;
8160 xmlRelaxNGDefinePtr define;
8161
8162 schema = ctxt->schema;
8163 if (schema == NULL) {
8164 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
8165 return (-1);
8166 }
8167 grammar = schema->topgrammar;
8168 if ((grammar == NULL) || (grammar->start == NULL)) {
8169 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
8170 return (-1);
8171 }
8172 define = grammar->start;
8173 if (define->contModel == NULL) {
8174 ctxt->pdef = define;
8175 return (0);
8176 }
8177 exec = xmlRegNewExecCtxt(define->contModel,
8178 xmlRelaxNGValidateProgressiveCallback,
8179 ctxt);
8180 if (exec == NULL) {
8181 return (-1);
8182 }
8183 xmlRelaxNGElemPush(ctxt, exec);
8184 }
8185 ctxt->pnode = elem;
8186 ctxt->pstate = 0;
8187 if (elem->ns != NULL) {
8188 ret =
8189 xmlRegExecPushString2(ctxt->elem, elem->name, elem->ns->href,
8190 ctxt);
8191 } else {
8192 ret = xmlRegExecPushString(ctxt->elem, elem->name, ctxt);
8193 }
8194 if (ret < 0) {
8195 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, elem->name);
8196 } else {
8197 if (ctxt->pstate == 0)
8198 ret = 0;
8199 else if (ctxt->pstate < 0)
8200 ret = -1;
8201 else
8202 ret = 1;
8203 }
8204 return (ret);
8205}
8206
8217int
8218xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt,
8219 const xmlChar * data, int len ATTRIBUTE_UNUSED)
8220{
8221 int ret = 1;
8222
8223 if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL))
8224 return (-1);
8225
8226 while (*data != 0) {
8227 if (!IS_BLANK_CH(*data))
8228 break;
8229 data++;
8230 }
8231 if (*data == 0)
8232 return (1);
8233
8234 ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt);
8235 if (ret < 0) {
8236 VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO ");
8237
8238 return (-1);
8239 }
8240 return (1);
8241}
8242
8253int
8254xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,
8255 xmlDocPtr doc ATTRIBUTE_UNUSED,
8256 xmlNodePtr elem)
8257{
8258 int ret;
8259 xmlRegExecCtxtPtr exec;
8260
8261 if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL))
8262 return (-1);
8263 /*
8264 * verify that we reached a terminal state of the content model.
8265 */
8266 exec = xmlRelaxNGElemPop(ctxt);
8267 ret = xmlRegExecPushString(exec, NULL, NULL);
8268 if (ret == 0) {
8269 /*
8270 * TODO: get some of the names needed to exit the current state of exec
8271 */
8272 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");
8273 ret = -1;
8274 } else if (ret < 0) {
8275 ret = -1;
8276 } else {
8277 ret = 1;
8278 }
8279 xmlRegFreeExecCtxt(exec);
8280 return (ret);
8281}
8282
8294int
8295xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt,
8296 xmlDocPtr doc ATTRIBUTE_UNUSED,
8297 xmlNodePtr elem)
8298{
8299 int ret;
8300 xmlRelaxNGValidStatePtr state;
8301
8302 if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL))
8303 return (-1);
8304 state = xmlRelaxNGNewValidState(ctxt, elem->parent);
8305 if (state == NULL) {
8306 return (-1);
8307 }
8308 state->seq = elem;
8309 ctxt->state = state;
8310 ctxt->errNo = XML_RELAXNG_OK;
8311 ret = xmlRelaxNGValidateDefinition(ctxt, ctxt->pdef);
8312 if ((ret != 0) || (ctxt->errNo != XML_RELAXNG_OK))
8313 ret = -1;
8314 else
8315 ret = 1;
8316 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
8317 ctxt->state = NULL;
8318 return (ret);
8319}
8320
8321/************************************************************************
8322 * *
8323 * Generic interpreted validation implementation *
8324 * *
8325 ************************************************************************/
8326static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
8327 xmlRelaxNGDefinePtr define);
8328
8338static xmlNodePtr
8339xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
8340 xmlNodePtr node)
8341{
8342 /*
8343 * TODO complete and handle entities
8344 */
8345 while ((node != NULL) &&
8346 ((node->type == XML_COMMENT_NODE) ||
8347 (node->type == XML_PI_NODE) ||
8348 (node->type == XML_XINCLUDE_START) ||
8349 (node->type == XML_XINCLUDE_END) ||
8350 (((node->type == XML_TEXT_NODE) ||
8351 (node->type == XML_CDATA_SECTION_NODE)) &&
8352 ((ctxt->flags & FLAGS_MIXED_CONTENT) ||
8353 (IS_BLANK_NODE(node)))))) {
8354 node = node->next;
8355 }
8356 return (node);
8357}
8358
8369static xmlChar *
8370xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str)
8371{
8372 xmlChar *ret, *p;
8373 const xmlChar *tmp;
8374 int len;
8375
8376 if (str == NULL)
8377 return (NULL);
8378 tmp = str;
8379 while (*tmp != 0)
8380 tmp++;
8381 len = tmp - str;
8382
8383 ret = (xmlChar *) xmlMallocAtomic(len + 1);
8384 if (ret == NULL) {
8385 xmlRngVErrMemory(ctxt, "validating\n");
8386 return (NULL);
8387 }
8388 p = ret;
8389 while (IS_BLANK_CH(*str))
8390 str++;
8391 while (*str != 0) {
8392 if (IS_BLANK_CH(*str)) {
8393 while (IS_BLANK_CH(*str))
8394 str++;
8395 if (*str == 0)
8396 break;
8397 *p++ = ' ';
8398 } else
8399 *p++ = *str++;
8400 }
8401 *p = 0;
8402 return (ret);
8403}
8404
8416static int
8417xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt,
8418 const xmlChar * value,
8419 xmlRelaxNGDefinePtr define, xmlNodePtr node)
8420{
8421 int ret, tmp;
8422 xmlRelaxNGTypeLibraryPtr lib;
8423 void *result = NULL;
8424 xmlRelaxNGDefinePtr cur;
8425
8426 if ((define == NULL) || (define->data == NULL)) {
8427 return (-1);
8428 }
8429 lib = (xmlRelaxNGTypeLibraryPtr) define->data;
8430 if (lib->check != NULL) {
8431 if ((define->attrs != NULL) &&
8432 (define->attrs->type == XML_RELAXNG_PARAM)) {
8433 ret =
8434 lib->check(lib->data, define->name, value, &result, node);
8435 } else {
8436 ret = lib->check(lib->data, define->name, value, NULL, node);
8437 }
8438 } else
8439 ret = -1;
8440 if (ret < 0) {
8441 VALID_ERR2(XML_RELAXNG_ERR_TYPE, define->name);
8442 if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
8443 lib->freef(lib->data, result);
8444 return (-1);
8445 } else if (ret == 1) {
8446 ret = 0;
8447 } else if (ret == 2) {
8448 VALID_ERR2P(XML_RELAXNG_ERR_DUPID, value);
8449 } else {
8450 VALID_ERR3P(XML_RELAXNG_ERR_TYPEVAL, define->name, value);
8451 ret = -1;
8452 }
8453 cur = define->attrs;
8454 while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) {
8455 if (lib->facet != NULL) {
8456 tmp = lib->facet(lib->data, define->name, cur->name,
8457 cur->value, value, result);
8458 if (tmp != 0)
8459 ret = -1;
8460 }
8461 cur = cur->next;
8462 }
8463 if ((ret == 0) && (define->content != NULL)) {
8464 const xmlChar *oldvalue, *oldendvalue;
8465
8466 oldvalue = ctxt->state->value;
8467 oldendvalue = ctxt->state->endvalue;
8468 ctxt->state->value = (xmlChar *) value;
8469 ctxt->state->endvalue = NULL;
8470 ret = xmlRelaxNGValidateValue(ctxt, define->content);
8471 ctxt->state->value = (xmlChar *) oldvalue;
8472 ctxt->state->endvalue = (xmlChar *) oldendvalue;
8473 }
8474 if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))
8475 lib->freef(lib->data, result);
8476 return (ret);
8477}
8478
8487static int
8488xmlRelaxNGNextValue(xmlRelaxNGValidCtxtPtr ctxt)
8489{
8490 xmlChar *cur;
8491
8492 cur = ctxt->state->value;
8493 if ((cur == NULL) || (ctxt->state->endvalue == NULL)) {
8494 ctxt->state->value = NULL;
8495 ctxt->state->endvalue = NULL;
8496 return (0);
8497 }
8498 while (*cur != 0)
8499 cur++;
8500 while ((cur != ctxt->state->endvalue) && (*cur == 0))
8501 cur++;
8502 if (cur == ctxt->state->endvalue)
8503 ctxt->state->value = NULL;
8504 else
8505 ctxt->state->value = cur;
8506 return (0);
8507}
8508
8518static int
8519xmlRelaxNGValidateValueList(xmlRelaxNGValidCtxtPtr ctxt,
8520 xmlRelaxNGDefinePtr defines)
8521{
8522 int ret = 0;
8523
8524 while (defines != NULL) {
8525 ret = xmlRelaxNGValidateValue(ctxt, defines);
8526 if (ret != 0)
8527 break;
8528 defines = defines->next;
8529 }
8530 return (ret);
8531}
8532
8542static int
8543xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,
8544 xmlRelaxNGDefinePtr define)
8545{
8546 int ret = 0, oldflags;
8547 xmlChar *value;
8548
8549 value = ctxt->state->value;
8550 switch (define->type) {
8551 case XML_RELAXNG_EMPTY:{
8552 if ((value != NULL) && (value[0] != 0)) {
8553 int idx = 0;
8554
8555 while (IS_BLANK_CH(value[idx]))
8556 idx++;
8557 if (value[idx] != 0)
8558 ret = -1;
8559 }
8560 break;
8561 }
8562 case XML_RELAXNG_TEXT:
8563 break;
8564 case XML_RELAXNG_VALUE:{
8565 if (!xmlStrEqual(value, define->value)) {
8566 if (define->name != NULL) {
8567 xmlRelaxNGTypeLibraryPtr lib;
8568
8569 lib = (xmlRelaxNGTypeLibraryPtr) define->data;
8570 if ((lib != NULL) && (lib->comp != NULL)) {
8571 ret = lib->comp(lib->data, define->name,
8572 define->value, define->node,
8573 (void *) define->attrs,
8574 value, ctxt->state->node);
8575 } else
8576 ret = -1;
8577 if (ret < 0) {
8578 VALID_ERR2(XML_RELAXNG_ERR_TYPECMP,
8579 define->name);
8580 return (-1);
8581 } else if (ret == 1) {
8582 ret = 0;
8583 } else {
8584 ret = -1;
8585 }
8586 } else {
8587 xmlChar *nval, *nvalue;
8588
8589 /*
8590 * TODO: trivial optimizations are possible by
8591 * computing at compile-time
8592 */
8593 nval = xmlRelaxNGNormalize(ctxt, define->value);
8594 nvalue = xmlRelaxNGNormalize(ctxt, value);
8595
8596 if ((nval == NULL) || (nvalue == NULL) ||
8597 (!xmlStrEqual(nval, nvalue)))
8598 ret = -1;
8599 if (nval != NULL)
8600 xmlFree(nval);
8601 if (nvalue != NULL)
8602 xmlFree(nvalue);
8603 }
8604 }
8605 if (ret == 0)
8606 xmlRelaxNGNextValue(ctxt);
8607 break;
8608 }
8609 case XML_RELAXNG_DATATYPE:{
8610 ret = xmlRelaxNGValidateDatatype(ctxt, value, define,
8611 ctxt->state->seq);
8612 if (ret == 0)
8613 xmlRelaxNGNextValue(ctxt);
8614
8615 break;
8616 }
8617 case XML_RELAXNG_CHOICE:{
8618 xmlRelaxNGDefinePtr list = define->content;
8619 xmlChar *oldvalue;
8620
8621 oldflags = ctxt->flags;
8622 ctxt->flags |= FLAGS_IGNORABLE;
8623
8624 oldvalue = ctxt->state->value;
8625 while (list != NULL) {
8626 ret = xmlRelaxNGValidateValue(ctxt, list);
8627 if (ret == 0) {
8628 break;
8629 }
8630 ctxt->state->value = oldvalue;
8631 list = list->next;
8632 }
8633 ctxt->flags = oldflags;
8634 if (ret != 0) {
8635 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
8636 xmlRelaxNGDumpValidError(ctxt);
8637 } else {
8638 if (ctxt->errNr > 0)
8639 xmlRelaxNGPopErrors(ctxt, 0);
8640 }
8641 break;
8642 }
8643 case XML_RELAXNG_LIST:{
8644 xmlRelaxNGDefinePtr list = define->content;
8645 xmlChar *oldvalue, *oldend, *val, *cur;
8646
8647 oldvalue = ctxt->state->value;
8648 oldend = ctxt->state->endvalue;
8649
8650 val = xmlStrdup(oldvalue);
8651 if (val == NULL) {
8652 val = xmlStrdup(BAD_CAST "");
8653 }
8654 if (val == NULL) {
8655 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
8656 return (-1);
8657 }
8658 cur = val;
8659 while (*cur != 0) {
8660 if (IS_BLANK_CH(*cur)) {
8661 *cur = 0;
8662 cur++;
8663 while (IS_BLANK_CH(*cur))
8664 *cur++ = 0;
8665 } else
8666 cur++;
8667 }
8668 ctxt->state->endvalue = cur;
8669 cur = val;
8670 while ((*cur == 0) && (cur != ctxt->state->endvalue))
8671 cur++;
8672
8673 ctxt->state->value = cur;
8674
8675 while (list != NULL) {
8676 if (ctxt->state->value == ctxt->state->endvalue)
8677 ctxt->state->value = NULL;
8678 ret = xmlRelaxNGValidateValue(ctxt, list);
8679 if (ret != 0) {
8680 break;
8681 }
8682 list = list->next;
8683 }
8684
8685 if ((ret == 0) && (ctxt->state->value != NULL) &&
8686 (ctxt->state->value != ctxt->state->endvalue)) {
8687 VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA,
8688 ctxt->state->value);
8689 ret = -1;
8690 }
8691 xmlFree(val);
8692 ctxt->state->value = oldvalue;
8693 ctxt->state->endvalue = oldend;
8694 break;
8695 }
8696 case XML_RELAXNG_ONEORMORE:
8697 ret = xmlRelaxNGValidateValueList(ctxt, define->content);
8698 if (ret != 0) {
8699 break;
8700 }
8701 /* Falls through. */
8702 case XML_RELAXNG_ZEROORMORE:{
8703 xmlChar *cur, *temp;
8704
8705 if ((ctxt->state->value == NULL) ||
8706 (*ctxt->state->value == 0)) {
8707 ret = 0;
8708 break;
8709 }
8710 oldflags = ctxt->flags;
8711 ctxt->flags |= FLAGS_IGNORABLE;
8712 cur = ctxt->state->value;
8713 temp = NULL;
8714 while ((cur != NULL) && (cur != ctxt->state->endvalue) &&
8715 (temp != cur)) {
8716 temp = cur;
8717 ret =
8718 xmlRelaxNGValidateValueList(ctxt, define->content);
8719 if (ret != 0) {
8720 ctxt->state->value = temp;
8721 ret = 0;
8722 break;
8723 }
8724 cur = ctxt->state->value;
8725 }
8726 ctxt->flags = oldflags;
8727 if (ctxt->errNr > 0)
8728 xmlRelaxNGPopErrors(ctxt, 0);
8729 break;
8730 }
8731 case XML_RELAXNG_OPTIONAL:{
8732 xmlChar *temp;
8733
8734 if ((ctxt->state->value == NULL) ||
8735 (*ctxt->state->value == 0)) {
8736 ret = 0;
8737 break;
8738 }
8739 oldflags = ctxt->flags;
8740 ctxt->flags |= FLAGS_IGNORABLE;
8741 temp = ctxt->state->value;
8742 ret = xmlRelaxNGValidateValue(ctxt, define->content);
8743 ctxt->flags = oldflags;
8744 if (ret != 0) {
8745 ctxt->state->value = temp;
8746 if (ctxt->errNr > 0)
8747 xmlRelaxNGPopErrors(ctxt, 0);
8748 ret = 0;
8749 break;
8750 }
8751 if (ctxt->errNr > 0)
8752 xmlRelaxNGPopErrors(ctxt, 0);
8753 break;
8754 }
8755 case XML_RELAXNG_EXCEPT:{
8756 xmlRelaxNGDefinePtr list;
8757
8758 list = define->content;
8759 while (list != NULL) {
8760 ret = xmlRelaxNGValidateValue(ctxt, list);
8761 if (ret == 0) {
8762 ret = -1;
8763 break;
8764 } else
8765 ret = 0;
8766 list = list->next;
8767 }
8768 break;
8769 }
8770 case XML_RELAXNG_DEF:
8771 case XML_RELAXNG_GROUP:{
8772 xmlRelaxNGDefinePtr list;
8773
8774 list = define->content;
8775 while (list != NULL) {
8776 ret = xmlRelaxNGValidateValue(ctxt, list);
8777 if (ret != 0) {
8778 ret = -1;
8779 break;
8780 } else
8781 ret = 0;
8782 list = list->next;
8783 }
8784 break;
8785 }
8786 case XML_RELAXNG_REF:
8787 case XML_RELAXNG_PARENTREF:
8788 if (define->content == NULL) {
8789 VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
8790 ret = -1;
8791 } else {
8792 ret = xmlRelaxNGValidateValue(ctxt, define->content);
8793 }
8794 break;
8795 default:
8796 TODO ret = -1;
8797 }
8798 return (ret);
8799}
8800
8810static int
8811xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt,
8812 xmlRelaxNGDefinePtr defines)
8813{
8814 int ret = 0;
8815
8816 while (defines != NULL) {
8817 ret = xmlRelaxNGValidateValue(ctxt, defines);
8818 if (ret != 0)
8819 break;
8820 defines = defines->next;
8821 }
8822 return (ret);
8823}
8824
8835static int
8836xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt,
8837 xmlRelaxNGDefinePtr define, xmlAttrPtr prop)
8838{
8839 int ret;
8840
8841 if (define->name != NULL) {
8842 if (!xmlStrEqual(define->name, prop->name))
8843 return (0);
8844 }
8845 if (define->ns != NULL) {
8846 if (define->ns[0] == 0) {
8847 if (prop->ns != NULL)
8848 return (0);
8849 } else {
8850 if ((prop->ns == NULL) ||
8851 (!xmlStrEqual(define->ns, prop->ns->href)))
8852 return (0);
8853 }
8854 }
8855 if (define->nameClass == NULL)
8856 return (1);
8857 define = define->nameClass;
8858 if (define->type == XML_RELAXNG_EXCEPT) {
8859 xmlRelaxNGDefinePtr list;
8860
8861 list = define->content;
8862 while (list != NULL) {
8863 ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);
8864 if (ret == 1)
8865 return (0);
8866 if (ret < 0)
8867 return (ret);
8868 list = list->next;
8869 }
8870 } else if (define->type == XML_RELAXNG_CHOICE) {
8871 xmlRelaxNGDefinePtr list;
8872
8873 list = define->nameClass;
8874 while (list != NULL) {
8875 ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);
8876 if (ret == 1)
8877 return (1);
8878 if (ret < 0)
8879 return (ret);
8880 list = list->next;
8881 }
8882 return (0);
8883 } else {
8884 TODO}
8885 return (1);
8886}
8887
8897static int
8898xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,
8899 xmlRelaxNGDefinePtr define)
8900{
8901 int ret = 0, i;
8902 xmlChar *value, *oldvalue;
8903 xmlAttrPtr prop = NULL, tmp;
8904 xmlNodePtr oldseq;
8905
8906 if (ctxt->state->nbAttrLeft <= 0)
8907 return (-1);
8908 if (define->name != NULL) {
8909 for (i = 0; i < ctxt->state->nbAttrs; i++) {
8910 tmp = ctxt->state->attrs[i];
8911 if ((tmp != NULL) && (xmlStrEqual(define->name, tmp->name))) {
8912 if ((((define->ns == NULL) || (define->ns[0] == 0)) &&
8913 (tmp->ns == NULL)) ||
8914 ((tmp->ns != NULL) &&
8915 (xmlStrEqual(define->ns, tmp->ns->href)))) {
8916 prop = tmp;
8917 break;
8918 }
8919 }
8920 }
8921 if (prop != NULL) {
8922 value = xmlNodeListGetString(prop->doc, prop->children, 1);
8923 oldvalue = ctxt->state->value;
8924 oldseq = ctxt->state->seq;
8925 ctxt->state->seq = (xmlNodePtr) prop;
8926 ctxt->state->value = value;
8927 ctxt->state->endvalue = NULL;
8928 ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
8929 if (ctxt->state->value != NULL)
8930 value = ctxt->state->value;
8931 if (value != NULL)
8932 xmlFree(value);
8933 ctxt->state->value = oldvalue;
8934 ctxt->state->seq = oldseq;
8935 if (ret == 0) {
8936 /*
8937 * flag the attribute as processed
8938 */
8939 ctxt->state->attrs[i] = NULL;
8940 ctxt->state->nbAttrLeft--;
8941 }
8942 } else {
8943 ret = -1;
8944 }
8945 } else {
8946 for (i = 0; i < ctxt->state->nbAttrs; i++) {
8947 tmp = ctxt->state->attrs[i];
8948 if ((tmp != NULL) &&
8949 (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) {
8950 prop = tmp;
8951 break;
8952 }
8953 }
8954 if (prop != NULL) {
8955 value = xmlNodeListGetString(prop->doc, prop->children, 1);
8956 oldvalue = ctxt->state->value;
8957 oldseq = ctxt->state->seq;
8958 ctxt->state->seq = (xmlNodePtr) prop;
8959 ctxt->state->value = value;
8960 ret = xmlRelaxNGValidateValueContent(ctxt, define->content);
8961 if (ctxt->state->value != NULL)
8962 value = ctxt->state->value;
8963 if (value != NULL)
8964 xmlFree(value);
8965 ctxt->state->value = oldvalue;
8966 ctxt->state->seq = oldseq;
8967 if (ret == 0) {
8968 /*
8969 * flag the attribute as processed
8970 */
8971 ctxt->state->attrs[i] = NULL;
8972 ctxt->state->nbAttrLeft--;
8973 }
8974 } else {
8975 ret = -1;
8976 }
8977 }
8978
8979 return (ret);
8980}
8981
8991static int
8992xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,
8993 xmlRelaxNGDefinePtr defines)
8994{
8995 int ret = 0, res;
8996 int needmore = 0;
8997 xmlRelaxNGDefinePtr cur;
8998
8999 cur = defines;
9000 while (cur != NULL) {
9001 if (cur->type == XML_RELAXNG_ATTRIBUTE) {
9002 if (xmlRelaxNGValidateAttribute(ctxt, cur) != 0)
9003 ret = -1;
9004 } else
9005 needmore = 1;
9006 cur = cur->next;
9007 }
9008 if (!needmore)
9009 return (ret);
9010 cur = defines;
9011 while (cur != NULL) {
9012 if (cur->type != XML_RELAXNG_ATTRIBUTE) {
9013 if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
9014 res = xmlRelaxNGValidateDefinition(ctxt, cur);
9015 if (res < 0)
9016 ret = -1;
9017 } else {
9018 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
9019 return (-1);
9020 }
9021 if (res == -1) /* continues on -2 */
9022 break;
9023 }
9024 cur = cur->next;
9025 }
9026
9027 return (ret);
9028}
9029
9039static int
9040xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr * list)
9041{
9042 xmlRelaxNGDefinePtr cur;
9043 int i = 0, tmp;
9044
9045 if ((node == NULL) || (list == NULL))
9046 return (0);
9047
9048 cur = list[i++];
9049 while (cur != NULL) {
9050 if ((node->type == XML_ELEMENT_NODE) &&
9051 (cur->type == XML_RELAXNG_ELEMENT)) {
9052 tmp = xmlRelaxNGElementMatch(NULL, cur, node);
9053 if (tmp == 1)
9054 return (1);
9055 } else if (((node->type == XML_TEXT_NODE) ||
9056 (node->type == XML_CDATA_SECTION_NODE)) &&
9057 ((cur->type == XML_RELAXNG_DATATYPE) ||
9058 (cur->type == XML_RELAXNG_LIST) ||
9059 (cur->type == XML_RELAXNG_TEXT) ||
9060 (cur->type == XML_RELAXNG_VALUE))) {
9061 return (1);
9062 }
9063 cur = list[i++];
9064 }
9065 return (0);
9066}
9067
9077static int
9078xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt,
9079 xmlRelaxNGDefinePtr define)
9080{
9081 int ret = 0, i, nbgroups;
9082 int errNr = ctxt->errNr;
9083 int oldflags;
9084
9085 xmlRelaxNGValidStatePtr oldstate;
9086 xmlRelaxNGPartitionPtr partitions;
9087 xmlRelaxNGInterleaveGroupPtr group = NULL;
9088 xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem;
9089 xmlNodePtr *list = NULL, *lasts = NULL;
9090
9091 if (define->data != NULL) {
9092 partitions = (xmlRelaxNGPartitionPtr) define->data;
9093 nbgroups = partitions->nbgroups;
9094 } else {
9095 VALID_ERR(XML_RELAXNG_ERR_INTERNODATA);
9096 return (-1);
9097 }
9098 /*
9099 * Optimizations for MIXED
9100 */
9101 oldflags = ctxt->flags;
9102 if (define->dflags & IS_MIXED) {
9103 ctxt->flags |= FLAGS_MIXED_CONTENT;
9104 if (nbgroups == 2) {
9105 /*
9106 * this is a pure <mixed> case
9107 */
9108 if (ctxt->state != NULL)
9109 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
9110 ctxt->state->seq);
9111 if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT)
9112 ret = xmlRelaxNGValidateDefinition(ctxt,
9113 partitions->groups[1]->
9114 rule);
9115 else
9116 ret = xmlRelaxNGValidateDefinition(ctxt,
9117 partitions->groups[0]->
9118 rule);
9119 if (ret == 0) {
9120 if (ctxt->state != NULL)
9121 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,
9122 ctxt->state->
9123 seq);
9124 }
9125 ctxt->flags = oldflags;
9126 return (ret);
9127 }
9128 }
9129
9130 /*
9131 * Build arrays to store the first and last node of the chain
9132 * pertaining to each group
9133 */
9134 list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
9135 if (list == NULL) {
9136 xmlRngVErrMemory(ctxt, "validating\n");
9137 return (-1);
9138 }
9139 memset(list, 0, nbgroups * sizeof(xmlNodePtr));
9140 lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));
9141 if (lasts == NULL) {
9142 xmlRngVErrMemory(ctxt, "validating\n");
9143 return (-1);
9144 }
9145 memset(lasts, 0, nbgroups * sizeof(xmlNodePtr));
9146
9147 /*
9148 * Walk the sequence of children finding the right group and
9149 * sorting them in sequences.
9150 */
9151 cur = ctxt->state->seq;
9152 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
9153 start = cur;
9154 while (cur != NULL) {
9155 ctxt->state->seq = cur;
9156 if ((partitions->triage != NULL) &&
9157 (partitions->flags & IS_DETERMINIST)) {
9158 void *tmp = NULL;
9159
9160 if ((cur->type == XML_TEXT_NODE) ||
9161 (cur->type == XML_CDATA_SECTION_NODE)) {
9162 tmp = xmlHashLookup2(partitions->triage, BAD_CAST "#text",
9163 NULL);
9164 } else if (cur->type == XML_ELEMENT_NODE) {
9165 if (cur->ns != NULL) {
9166 tmp = xmlHashLookup2(partitions->triage, cur->name,
9167 cur->ns->href);
9168 if (tmp == NULL)
9169 tmp = xmlHashLookup2(partitions->triage,
9170 BAD_CAST "#any",
9171 cur->ns->href);
9172 } else
9173 tmp =
9174 xmlHashLookup2(partitions->triage, cur->name,
9175 NULL);
9176 if (tmp == NULL)
9177 tmp =
9178 xmlHashLookup2(partitions->triage, BAD_CAST "#any",
9179 NULL);
9180 }
9181
9182 if (tmp == NULL) {
9183 i = nbgroups;
9184 } else {
9185 i = ((ptrdiff_t) tmp) - 1;
9186 if (partitions->flags & IS_NEEDCHECK) {
9187 group = partitions->groups[i];
9188 if (!xmlRelaxNGNodeMatchesList(cur, group->defs))
9189 i = nbgroups;
9190 }
9191 }
9192 } else {
9193 for (i = 0; i < nbgroups; i++) {
9194 group = partitions->groups[i];
9195 if (group == NULL)
9196 continue;
9197 if (xmlRelaxNGNodeMatchesList(cur, group->defs))
9198 break;
9199 }
9200 }
9201 /*
9202 * We break as soon as an element not matched is found
9203 */
9204 if (i >= nbgroups) {
9205 break;
9206 }
9207 if (lasts[i] != NULL) {
9208 lasts[i]->next = cur;
9209 lasts[i] = cur;
9210 } else {
9211 list[i] = cur;
9212 lasts[i] = cur;
9213 }
9214 if (cur->next != NULL)
9215 lastchg = cur->next;
9216 else
9217 lastchg = cur;
9218 cur = xmlRelaxNGSkipIgnored(ctxt, cur->next);
9219 }
9220 if (ret != 0) {
9221 VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
9222 ret = -1;
9223 goto done;
9224 }
9225 lastelem = cur;
9226 oldstate = ctxt->state;
9227 for (i = 0; i < nbgroups; i++) {
9228 ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate);
9229 if (ctxt->state == NULL) {
9230 ret = -1;
9231 break;
9232 }
9233 group = partitions->groups[i];
9234 if (lasts[i] != NULL) {
9235 last = lasts[i]->next;
9236 lasts[i]->next = NULL;
9237 }
9238 ctxt->state->seq = list[i];
9239 ret = xmlRelaxNGValidateDefinition(ctxt, group->rule);
9240 if (ret != 0)
9241 break;
9242 if (ctxt->state != NULL) {
9243 cur = ctxt->state->seq;
9244 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
9245 xmlRelaxNGFreeValidState(ctxt, oldstate);
9246 oldstate = ctxt->state;
9247 ctxt->state = NULL;
9248 if (cur != NULL
9249 /* there's a nasty violation of context-free unambiguities,
9250 since in open-name-class context, interleave in the
9251 production shall finish without caring about anything
9252 else that is OK to follow in that case -- it would
9253 otherwise get marked as "extra content" and would
9254 hence fail the validation, hence this perhaps
9255 dirty attempt to rectify such a situation */
9256 && (define->parent->type != XML_RELAXNG_DEF
9257 || !xmlStrEqual(define->parent->name,
9258 (const xmlChar *) "open-name-class"))) {
9259 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
9260 ret = -1;
9261 ctxt->state = oldstate;
9262 goto done;
9263 }
9264 } else if (ctxt->states != NULL) {
9265 int j;
9266 int found = 0;
9267 int best = -1;
9268 int lowattr = -1;
9269
9270 /*
9271 * PBM: what happen if there is attributes checks in the interleaves
9272 */
9273
9274 for (j = 0; j < ctxt->states->nbState; j++) {
9275 cur = ctxt->states->tabState[j]->seq;
9276 cur = xmlRelaxNGSkipIgnored(ctxt, cur);
9277 if (cur == NULL) {
9278 if (found == 0) {
9279 lowattr = ctxt->states->tabState[j]->nbAttrLeft;
9280 best = j;
9281 }
9282 found = 1;
9283 if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) {
9284 /* try to keep the latest one to mach old heuristic */
9285 lowattr = ctxt->states->tabState[j]->nbAttrLeft;
9286 best = j;
9287 }
9288 if (lowattr == 0)
9289 break;
9290 } else if (found == 0) {
9291 if (lowattr == -1) {
9292 lowattr = ctxt->states->tabState[j]->nbAttrLeft;
9293 best = j;
9294 } else
9295 if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) {
9296 /* try to keep the latest one to mach old heuristic */
9297 lowattr = ctxt->states->tabState[j]->nbAttrLeft;
9298 best = j;
9299 }
9300 }
9301 }
9302 /*
9303 * BIG PBM: here we pick only one restarting point :-(
9304 */
9305 if (ctxt->states->nbState > 0) {
9306 xmlRelaxNGFreeValidState(ctxt, oldstate);
9307 if (best != -1) {
9308 oldstate = ctxt->states->tabState[best];
9309 ctxt->states->tabState[best] = NULL;
9310 } else {
9311 oldstate =
9312 ctxt->states->tabState[ctxt->states->nbState - 1];
9313 ctxt->states->tabState[ctxt->states->nbState - 1] = NULL;
9314 ctxt->states->nbState--;
9315 }
9316 }
9317 for (j = 0; j < ctxt->states->nbState ; j++) {
9318 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[j]);
9319 }
9320 xmlRelaxNGFreeStates(ctxt, ctxt->states);
9321 ctxt->states = NULL;
9322 if (found == 0) {
9323 if (cur == NULL) {
9324 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA,
9325 (const xmlChar *) "noname");
9326 } else {
9327 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);
9328 }
9329 ret = -1;
9330 ctxt->state = oldstate;
9331 goto done;
9332 }
9333 } else {
9334 ret = -1;
9335 break;
9336 }
9337 if (lasts[i] != NULL) {
9338 lasts[i]->next = last;
9339 }
9340 }
9341 if (ctxt->state != NULL)
9342 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
9343 ctxt->state = oldstate;
9344 ctxt->state->seq = lastelem;
9345 if (ret != 0) {
9346 VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);
9347 ret = -1;
9348 goto done;
9349 }
9350
9351 done:
9352 ctxt->flags = oldflags;
9353 /*
9354 * builds the next links chain from the prev one
9355 */
9356 cur = lastchg;
9357 while (cur != NULL) {
9358 if ((cur == start) || (cur->prev == NULL))
9359 break;
9360 cur->prev->next = cur;
9361 cur = cur->prev;
9362 }
9363 if (ret == 0) {
9364 if (ctxt->errNr > errNr)
9365 xmlRelaxNGPopErrors(ctxt, errNr);
9366 }
9367
9368 xmlFree(list);
9369 xmlFree(lasts);
9370 return (ret);
9371}
9372
9382static int
9383xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt,
9384 xmlRelaxNGDefinePtr defines)
9385{
9386 int ret = 0, res;
9387
9388
9389 if (defines == NULL) {
9390 VALID_ERR2(XML_RELAXNG_ERR_INTERNAL,
9391 BAD_CAST "NULL definition list");
9392 return (-1);
9393 }
9394 while (defines != NULL) {
9395 if ((ctxt->state != NULL) || (ctxt->states != NULL)) {
9396 res = xmlRelaxNGValidateDefinition(ctxt, defines);
9397 if (res < 0)
9398 ret = -1;
9399 } else {
9400 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);
9401 return (-1);
9402 }
9403 if (res == -1) /* continues on -2 */
9404 break;
9405 defines = defines->next;
9406 }
9407
9408 return (ret);
9409}
9410
9421static int
9422xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
9423 xmlRelaxNGDefinePtr define, xmlNodePtr elem)
9424{
9425 int ret = 0, oldflags = 0;
9426
9427 if (define->name != NULL) {
9428 if (!xmlStrEqual(elem->name, define->name)) {
9429 VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name);
9430 return (0);
9431 }
9432 }
9433 if ((define->ns != NULL) && (define->ns[0] != 0)) {
9434 if (elem->ns == NULL) {
9435 VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name);
9436 return (0);
9437 } else if (!xmlStrEqual(elem->ns->href, define->ns)) {
9438 VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS,
9439 elem->name, define->ns);
9440 return (0);
9441 }
9442 } else if ((elem->ns != NULL) && (define->ns != NULL) &&
9443 (define->name == NULL)) {
9444 VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name);
9445 return (0);
9446 } else if ((elem->ns != NULL) && (define->name != NULL)) {
9447 VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name);
9448 return (0);
9449 }
9450
9451 if (define->nameClass == NULL)
9452 return (1);
9453
9454 define = define->nameClass;
9455 if (define->type == XML_RELAXNG_EXCEPT) {
9456 xmlRelaxNGDefinePtr list;
9457
9458 if (ctxt != NULL) {
9459 oldflags = ctxt->flags;
9460 ctxt->flags |= FLAGS_IGNORABLE;
9461 }
9462
9463 list = define->content;
9464 while (list != NULL) {
9465 ret = xmlRelaxNGElementMatch(ctxt, list, elem);
9466 if (ret == 1) {
9467 if (ctxt != NULL)
9468 ctxt->flags = oldflags;
9469 return (0);
9470 }
9471 if (ret < 0) {
9472 if (ctxt != NULL)
9473 ctxt->flags = oldflags;
9474 return (ret);
9475 }
9476 list = list->next;
9477 }
9478 ret = 1;
9479 if (ctxt != NULL) {
9480 ctxt->flags = oldflags;
9481 }
9482 } else if (define->type == XML_RELAXNG_CHOICE) {
9483 xmlRelaxNGDefinePtr list;
9484
9485 if (ctxt != NULL) {
9486 oldflags = ctxt->flags;
9487 ctxt->flags |= FLAGS_IGNORABLE;
9488 }
9489
9490 list = define->nameClass;
9491 while (list != NULL) {
9492 ret = xmlRelaxNGElementMatch(ctxt, list, elem);
9493 if (ret == 1) {
9494 if (ctxt != NULL)
9495 ctxt->flags = oldflags;
9496 return (1);
9497 }
9498 if (ret < 0) {
9499 if (ctxt != NULL)
9500 ctxt->flags = oldflags;
9501 return (ret);
9502 }
9503 list = list->next;
9504 }
9505 if (ctxt != NULL) {
9506 if (ret != 0) {
9507 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9508 xmlRelaxNGDumpValidError(ctxt);
9509 } else {
9510 if (ctxt->errNr > 0)
9511 xmlRelaxNGPopErrors(ctxt, 0);
9512 }
9513 }
9514 ret = 0;
9515 if (ctxt != NULL) {
9516 ctxt->flags = oldflags;
9517 }
9518 } else {
9519 TODO ret = -1;
9520 }
9521 return (ret);
9522}
9523
9535static int
9536xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt)
9537{
9538 xmlRelaxNGValidStatePtr state;
9539 int i, tmp;
9540 int best = -1;
9541 int value = 1000000;
9542
9543 if ((ctxt == NULL) || (ctxt->states == NULL) ||
9544 (ctxt->states->nbState <= 0))
9545 return (-1);
9546
9547 for (i = 0; i < ctxt->states->nbState; i++) {
9548 state = ctxt->states->tabState[i];
9549 if (state == NULL)
9550 continue;
9551 if (state->seq != NULL) {
9552 if ((best == -1) || (value > 100000)) {
9553 value = 100000;
9554 best = i;
9555 }
9556 } else {
9557 tmp = state->nbAttrLeft;
9558 if ((best == -1) || (value > tmp)) {
9559 value = tmp;
9560 best = i;
9561 }
9562 }
9563 }
9564 return (best);
9565}
9566
9574static void
9575xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt)
9576{
9577 int best;
9578
9579 if ((ctxt == NULL) || (ctxt->states == NULL) ||
9580 (ctxt->states->nbState <= 0))
9581 return;
9582
9583 best = xmlRelaxNGBestState(ctxt);
9584 if ((best >= 0) && (best < ctxt->states->nbState)) {
9585 ctxt->state = ctxt->states->tabState[best];
9586
9587 xmlRelaxNGValidateElementEnd(ctxt, 1);
9588 }
9589}
9590
9602static int
9603xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int dolog)
9604{
9605 int i;
9606 xmlRelaxNGValidStatePtr state;
9607
9608 state = ctxt->state;
9609 if (state->seq != NULL) {
9610 state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq);
9611 if (state->seq != NULL) {
9612 if (dolog) {
9613 VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT,
9614 state->node->name, state->seq->name);
9615 }
9616 return (-1);
9617 }
9618 }
9619 for (i = 0; i < state->nbAttrs; i++) {
9620 if (state->attrs[i] != NULL) {
9621 if (dolog) {
9622 VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR,
9623 state->attrs[i]->name, state->node->name);
9624 }
9625 return (-1 - i);
9626 }
9627 }
9628 return (0);
9629}
9630
9640static int
9641xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,
9642 xmlRelaxNGDefinePtr define)
9643{
9644 xmlNodePtr node;
9645 int ret = 0, i, tmp, oldflags, errNr;
9646 xmlRelaxNGValidStatePtr oldstate = NULL, state;
9647
9648 if (define == NULL) {
9649 VALID_ERR(XML_RELAXNG_ERR_NODEFINE);
9650 return (-1);
9651 }
9652
9653 if (ctxt->state != NULL) {
9654 node = ctxt->state->seq;
9655 } else {
9656 node = NULL;
9657 }
9658 ctxt->depth++;
9659 switch (define->type) {
9660 case XML_RELAXNG_EMPTY:
9661 ret = 0;
9662 break;
9663 case XML_RELAXNG_NOT_ALLOWED:
9664 ret = -1;
9665 break;
9666 case XML_RELAXNG_TEXT:
9667 while ((node != NULL) &&
9668 ((node->type == XML_TEXT_NODE) ||
9669 (node->type == XML_COMMENT_NODE) ||
9670 (node->type == XML_PI_NODE) ||
9671 (node->type == XML_CDATA_SECTION_NODE)))
9672 node = node->next;
9673 ctxt->state->seq = node;
9674 break;
9675 case XML_RELAXNG_ELEMENT:
9676 errNr = ctxt->errNr;
9677 node = xmlRelaxNGSkipIgnored(ctxt, node);
9678 if (node == NULL) {
9679 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name);
9680 ret = -1;
9681 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9682 xmlRelaxNGDumpValidError(ctxt);
9683 break;
9684 }
9685 if (node->type != XML_ELEMENT_NODE) {
9686 VALID_ERR(XML_RELAXNG_ERR_NOTELEM);
9687 ret = -1;
9688 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9689 xmlRelaxNGDumpValidError(ctxt);
9690 break;
9691 }
9692 /*
9693 * This node was already validated successfully against
9694 * this definition.
9695 */
9696 if (node->psvi == define) {
9697 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
9698 if (ctxt->errNr > errNr)
9699 xmlRelaxNGPopErrors(ctxt, errNr);
9700 if (ctxt->errNr != 0) {
9701 while ((ctxt->err != NULL) &&
9702 (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME)
9703 && (xmlStrEqual(ctxt->err->arg2, node->name)))
9704 ||
9705 ((ctxt->err->err ==
9706 XML_RELAXNG_ERR_ELEMEXTRANS)
9707 && (xmlStrEqual(ctxt->err->arg1, node->name)))
9708 || (ctxt->err->err == XML_RELAXNG_ERR_NOELEM)
9709 || (ctxt->err->err ==
9710 XML_RELAXNG_ERR_NOTELEM)))
9711 xmlRelaxNGValidErrorPop(ctxt);
9712 }
9713 break;
9714 }
9715
9716 ret = xmlRelaxNGElementMatch(ctxt, define, node);
9717 if (ret <= 0) {
9718 ret = -1;
9719 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9720 xmlRelaxNGDumpValidError(ctxt);
9721 break;
9722 }
9723 ret = 0;
9724 if (ctxt->errNr != 0) {
9725 if (ctxt->errNr > errNr)
9726 xmlRelaxNGPopErrors(ctxt, errNr);
9727 while ((ctxt->err != NULL) &&
9728 (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) &&
9729 (xmlStrEqual(ctxt->err->arg2, node->name))) ||
9730 ((ctxt->err->err == XML_RELAXNG_ERR_ELEMEXTRANS) &&
9731 (xmlStrEqual(ctxt->err->arg1, node->name))) ||
9732 (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) ||
9733 (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM)))
9734 xmlRelaxNGValidErrorPop(ctxt);
9735 }
9736 errNr = ctxt->errNr;
9737
9738 oldflags = ctxt->flags;
9739 if (ctxt->flags & FLAGS_MIXED_CONTENT) {
9740 ctxt->flags -= FLAGS_MIXED_CONTENT;
9741 }
9742 state = xmlRelaxNGNewValidState(ctxt, node);
9743 if (state == NULL) {
9744 ret = -1;
9745 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)
9746 xmlRelaxNGDumpValidError(ctxt);
9747 break;
9748 }
9749
9750 oldstate = ctxt->state;
9751 ctxt->state = state;
9752 if (define->attrs != NULL) {
9753 tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);
9754 if (tmp != 0) {
9755 ret = -1;
9756 VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);
9757 }
9758 }
9759 if (define->contModel != NULL) {
9760 xmlRelaxNGValidStatePtr nstate, tmpstate = ctxt->state;
9761 xmlRelaxNGStatesPtr tmpstates = ctxt->states;
9762 xmlNodePtr nseq;
9763
9764 nstate = xmlRelaxNGNewValidState(ctxt, node);
9765 ctxt->state = nstate;
9766 ctxt->states = NULL;
9767
9768 tmp = xmlRelaxNGValidateCompiledContent(ctxt,
9769 define->contModel,
9770 ctxt->state->seq);
9771 nseq = ctxt->state->seq;
9772 ctxt->state = tmpstate;
9773 ctxt->states = tmpstates;
9774 xmlRelaxNGFreeValidState(ctxt, nstate);
9775
9776 if (tmp != 0)
9777 ret = -1;
9778
9779 if (ctxt->states != NULL) {
9780 tmp = -1;
9781
9782 for (i = 0; i < ctxt->states->nbState; i++) {
9783 state = ctxt->states->tabState[i];
9784 ctxt->state = state;
9785 ctxt->state->seq = nseq;
9786
9787 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
9788 tmp = 0;
9789 break;
9790 }
9791 }
9792 if (tmp != 0) {
9793 /*
9794 * validation error, log the message for the "best" one
9795 */
9796 ctxt->flags |= FLAGS_IGNORABLE;
9797 xmlRelaxNGLogBestError(ctxt);
9798 }
9799 for (i = 0; i < ctxt->states->nbState; i++) {
9800 xmlRelaxNGFreeValidState(ctxt,
9801 ctxt->states->
9802 tabState[i]);
9803 }
9804 xmlRelaxNGFreeStates(ctxt, ctxt->states);
9805 ctxt->flags = oldflags;
9806 ctxt->states = NULL;
9807 if ((ret == 0) && (tmp == -1))
9808 ret = -1;
9809 } else {
9810 state = ctxt->state;
9811 if (ctxt->state != NULL)
9812 ctxt->state->seq = nseq;
9813 if (ret == 0)
9814 ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
9815 xmlRelaxNGFreeValidState(ctxt, state);
9816 }
9817 } else {
9818 if (define->content != NULL) {
9819 tmp = xmlRelaxNGValidateDefinitionList(ctxt,
9820 define->
9821 content);
9822 if (tmp != 0) {
9823 ret = -1;
9824 if (ctxt->state == NULL) {
9825 ctxt->state = oldstate;
9826 VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
9827 node->name);
9828 ctxt->state = NULL;
9829 } else {
9830 VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,
9831 node->name);
9832 }
9833
9834 }
9835 }
9836 if (ctxt->states != NULL) {
9837 tmp = -1;
9838
9839 for (i = 0; i < ctxt->states->nbState; i++) {
9840 state = ctxt->states->tabState[i];
9841 ctxt->state = state;
9842
9843 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) {
9844 tmp = 0;
9845 break;
9846 }
9847 }
9848 if (tmp != 0) {
9849 /*
9850 * validation error, log the message for the "best" one
9851 */
9852 ctxt->flags |= FLAGS_IGNORABLE;
9853 xmlRelaxNGLogBestError(ctxt);
9854 }
9855 for (i = 0; i < ctxt->states->nbState; i++) {
9856 xmlRelaxNGFreeValidState(ctxt,
9857 ctxt->states->tabState[i]);
9858 ctxt->states->tabState[i] = NULL;
9859 }
9860 xmlRelaxNGFreeStates(ctxt, ctxt->states);
9861 ctxt->flags = oldflags;
9862 ctxt->states = NULL;
9863 if ((ret == 0) && (tmp == -1))
9864 ret = -1;
9865 } else {
9866 state = ctxt->state;
9867 if (ret == 0)
9868 ret = xmlRelaxNGValidateElementEnd(ctxt, 1);
9869 xmlRelaxNGFreeValidState(ctxt, state);
9870 }
9871 }
9872 if (ret == 0) {
9873 node->psvi = define;
9874 }
9875 ctxt->flags = oldflags;
9876 ctxt->state = oldstate;
9877 if (oldstate != NULL)
9878 oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);
9879 if (ret != 0) {
9880 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
9881 xmlRelaxNGDumpValidError(ctxt);
9882 ret = 0;
9883#if 0
9884 } else {
9885 ret = -2;
9886#endif
9887 }
9888 } else {
9889 if (ctxt->errNr > errNr)
9890 xmlRelaxNGPopErrors(ctxt, errNr);
9891 }
9892
9893 break;
9894 case XML_RELAXNG_OPTIONAL:{
9895 errNr = ctxt->errNr;
9896 oldflags = ctxt->flags;
9897 ctxt->flags |= FLAGS_IGNORABLE;
9898 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
9899 ret =
9900 xmlRelaxNGValidateDefinitionList(ctxt,
9901 define->content);
9902 if (ret != 0) {
9903 if (ctxt->state != NULL)
9904 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
9905 ctxt->state = oldstate;
9906 ctxt->flags = oldflags;
9907 ret = 0;
9908 if (ctxt->errNr > errNr)
9909 xmlRelaxNGPopErrors(ctxt, errNr);
9910 break;
9911 }
9912 if (ctxt->states != NULL) {
9913 xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
9914 } else {
9915 ctxt->states = xmlRelaxNGNewStates(ctxt, 1);
9916 if (ctxt->states == NULL) {
9917 xmlRelaxNGFreeValidState(ctxt, oldstate);
9918 ctxt->flags = oldflags;
9919 ret = -1;
9920 if (ctxt->errNr > errNr)
9921 xmlRelaxNGPopErrors(ctxt, errNr);
9922 break;
9923 }
9924 xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);
9925 xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state);
9926 ctxt->state = NULL;
9927 }
9928 ctxt->flags = oldflags;
9929 ret = 0;
9930 if (ctxt->errNr > errNr)
9931 xmlRelaxNGPopErrors(ctxt, errNr);
9932 break;
9933 }
9934 case XML_RELAXNG_ONEORMORE:
9935 errNr = ctxt->errNr;
9936 ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
9937 if (ret != 0) {
9938 break;
9939 }
9940 if (ctxt->errNr > errNr)
9941 xmlRelaxNGPopErrors(ctxt, errNr);
9942 /* Falls through. */
9943 case XML_RELAXNG_ZEROORMORE:{
9944 int progress;
9945 xmlRelaxNGStatesPtr states = NULL, res = NULL;
9946 int base, j;
9947
9948 errNr = ctxt->errNr;
9949 res = xmlRelaxNGNewStates(ctxt, 1);
9950 if (res == NULL) {
9951 ret = -1;
9952 break;
9953 }
9954 /*
9955 * All the input states are also exit states
9956 */
9957 if (ctxt->state != NULL) {
9958 xmlRelaxNGAddStates(ctxt, res,
9959 xmlRelaxNGCopyValidState(ctxt,
9960 ctxt->
9961 state));
9962 } else {
9963 for (j = 0; j < ctxt->states->nbState; j++) {
9964 xmlRelaxNGAddStates(ctxt, res,
9965 xmlRelaxNGCopyValidState(ctxt,
9966 ctxt->states->tabState[j]));
9967 }
9968 }
9969 oldflags = ctxt->flags;
9970 ctxt->flags |= FLAGS_IGNORABLE;
9971 do {
9972 progress = 0;
9973 base = res->nbState;
9974
9975 if (ctxt->states != NULL) {
9976 states = ctxt->states;
9977 for (i = 0; i < states->nbState; i++) {
9978 ctxt->state = states->tabState[i];
9979 ctxt->states = NULL;
9980 ret = xmlRelaxNGValidateDefinitionList(ctxt,
9981 define->
9982 content);
9983 if (ret == 0) {
9984 if (ctxt->state != NULL) {
9985 tmp = xmlRelaxNGAddStates(ctxt, res,
9986 ctxt->state);
9987 ctxt->state = NULL;
9988 if (tmp == 1)
9989 progress = 1;
9990 } else if (ctxt->states != NULL) {
9991 for (j = 0; j < ctxt->states->nbState;
9992 j++) {
9993 tmp =
9994 xmlRelaxNGAddStates(ctxt, res,
9995 ctxt->states->tabState[j]);
9996 if (tmp == 1)
9997 progress = 1;
9998 }
9999 xmlRelaxNGFreeStates(ctxt,
10000 ctxt->states);
10001 ctxt->states = NULL;
10002 }
10003 } else {
10004 if (ctxt->state != NULL) {
10005 xmlRelaxNGFreeValidState(ctxt,
10006 ctxt->state);
10007 ctxt->state = NULL;
10008 }
10009 }
10010 }
10011 } else {
10012 ret = xmlRelaxNGValidateDefinitionList(ctxt,
10013 define->
10014 content);
10015 if (ret != 0) {
10016 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10017 ctxt->state = NULL;
10018 } else {
10019 base = res->nbState;
10020 if (ctxt->state != NULL) {
10021 tmp = xmlRelaxNGAddStates(ctxt, res,
10022 ctxt->state);
10023 ctxt->state = NULL;
10024 if (tmp == 1)
10025 progress = 1;
10026 } else if (ctxt->states != NULL) {
10027 for (j = 0; j < ctxt->states->nbState; j++) {
10028 tmp = xmlRelaxNGAddStates(ctxt, res,
10029 ctxt->states->tabState[j]);
10030 if (tmp == 1)
10031 progress = 1;
10032 }
10033 if (states == NULL) {
10034 states = ctxt->states;
10035 } else {
10036 xmlRelaxNGFreeStates(ctxt,
10037 ctxt->states);
10038 }
10039 ctxt->states = NULL;
10040 }
10041 }
10042 }
10043 if (progress) {
10044 /*
10045 * Collect all the new nodes added at that step
10046 * and make them the new node set
10047 */
10048 if (res->nbState - base == 1) {
10049 ctxt->state = xmlRelaxNGCopyValidState(ctxt,
10050 res->
10051 tabState
10052 [base]);
10053 } else {
10054 if (states == NULL) {
10055 xmlRelaxNGNewStates(ctxt,
10056 res->nbState - base);
10057 states = ctxt->states;
10058 if (states == NULL) {
10059 progress = 0;
10060 break;
10061 }
10062 }
10063 states->nbState = 0;
10064 for (i = base; i < res->nbState; i++)
10065 xmlRelaxNGAddStates(ctxt, states,
10066 xmlRelaxNGCopyValidState
10067 (ctxt, res->tabState[i]));
10068 ctxt->states = states;
10069 }
10070 }
10071 } while (progress == 1);
10072 if (states != NULL) {
10073 xmlRelaxNGFreeStates(ctxt, states);
10074 }
10075 ctxt->states = res;
10076 ctxt->flags = oldflags;
10077#if 0
10078 /*
10079 * errors may have to be propagated back...
10080 */
10081 if (ctxt->errNr > errNr)
10082 xmlRelaxNGPopErrors(ctxt, errNr);
10083#endif
10084 ret = 0;
10085 break;
10086 }
10087 case XML_RELAXNG_CHOICE:{
10088 xmlRelaxNGDefinePtr list = NULL;
10089 xmlRelaxNGStatesPtr states = NULL;
10090
10091 node = xmlRelaxNGSkipIgnored(ctxt, node);
10092
10093 errNr = ctxt->errNr;
10094 if ((define->dflags & IS_TRIABLE) && (define->data != NULL) &&
10095 (node != NULL)) {
10096 /*
10097 * node == NULL can't be optimized since IS_TRIABLE
10098 * doesn't account for choice which may lead to
10099 * only attributes.
10100 */
10101 xmlHashTablePtr triage =
10102 (xmlHashTablePtr) define->data;
10103
10104 /*
10105 * Something we can optimize cleanly there is only one
10106 * possible branch out !
10107 */
10108 if ((node->type == XML_TEXT_NODE) ||
10109 (node->type == XML_CDATA_SECTION_NODE)) {
10110 list =
10111 xmlHashLookup2(triage, BAD_CAST "#text", NULL);
10112 } else if (node->type == XML_ELEMENT_NODE) {
10113 if (node->ns != NULL) {
10114 list = xmlHashLookup2(triage, node->name,
10115 node->ns->href);
10116 if (list == NULL)
10117 list =
10118 xmlHashLookup2(triage, BAD_CAST "#any",
10119 node->ns->href);
10120 } else
10121 list =
10122 xmlHashLookup2(triage, node->name, NULL);
10123 if (list == NULL)
10124 list =
10125 xmlHashLookup2(triage, BAD_CAST "#any",
10126 NULL);
10127 }
10128 if (list == NULL) {
10129 ret = -1;
10130 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, node->name);
10131 break;
10132 }
10133 ret = xmlRelaxNGValidateDefinition(ctxt, list);
10134 if (ret == 0) {
10135 }
10136 break;
10137 }
10138
10139 list = define->content;
10140 oldflags = ctxt->flags;
10141 ctxt->flags |= FLAGS_IGNORABLE;
10142
10143 while (list != NULL) {
10144 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);
10145 ret = xmlRelaxNGValidateDefinition(ctxt, list);
10146 if (ret == 0) {
10147 if (states == NULL) {
10148 states = xmlRelaxNGNewStates(ctxt, 1);
10149 }
10150 if (ctxt->state != NULL) {
10151 xmlRelaxNGAddStates(ctxt, states, ctxt->state);
10152 } else if (ctxt->states != NULL) {
10153 for (i = 0; i < ctxt->states->nbState; i++) {
10154 xmlRelaxNGAddStates(ctxt, states,
10155 ctxt->states->
10156 tabState[i]);
10157 }
10158 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10159 ctxt->states = NULL;
10160 }
10161 } else {
10162 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10163 }
10164 ctxt->state = oldstate;
10165 list = list->next;
10166 }
10167 if (states != NULL) {
10168 xmlRelaxNGFreeValidState(ctxt, oldstate);
10169 ctxt->states = states;
10170 ctxt->state = NULL;
10171 ret = 0;
10172 } else {
10173 ctxt->states = NULL;
10174 }
10175 ctxt->flags = oldflags;
10176 if (ret != 0) {
10177 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) {
10178 xmlRelaxNGDumpValidError(ctxt);
10179 }
10180 } else {
10181 if (ctxt->errNr > errNr)
10182 xmlRelaxNGPopErrors(ctxt, errNr);
10183 }
10184 break;
10185 }
10186 case XML_RELAXNG_DEF:
10187 case XML_RELAXNG_GROUP:
10188 ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);
10189 break;
10190 case XML_RELAXNG_INTERLEAVE:
10191 ret = xmlRelaxNGValidateInterleave(ctxt, define);
10192 break;
10193 case XML_RELAXNG_ATTRIBUTE:
10194 ret = xmlRelaxNGValidateAttribute(ctxt, define);
10195 break;
10196 case XML_RELAXNG_START:
10197 case XML_RELAXNG_NOOP:
10198 case XML_RELAXNG_REF:
10199 case XML_RELAXNG_EXTERNALREF:
10200 case XML_RELAXNG_PARENTREF:
10201 ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
10202 break;
10203 case XML_RELAXNG_DATATYPE:{
10204 xmlNodePtr child;
10205 xmlChar *content = NULL;
10206
10207 child = node;
10208 while (child != NULL) {
10209 if (child->type == XML_ELEMENT_NODE) {
10210 VALID_ERR2(XML_RELAXNG_ERR_DATAELEM,
10211 node->parent->name);
10212 ret = -1;
10213 break;
10214 } else if ((child->type == XML_TEXT_NODE) ||
10215 (child->type == XML_CDATA_SECTION_NODE)) {
10216 content = xmlStrcat(content, child->content);
10217 }
10218 /* TODO: handle entities ... */
10219 child = child->next;
10220 }
10221 if (ret == -1) {
10222 if (content != NULL)
10224 break;
10225 }
10226 if (content == NULL) {
10228 if (content == NULL) {
10229 xmlRngVErrMemory(ctxt, "validating\n");
10230 ret = -1;
10231 break;
10232 }
10233 }
10234 ret = xmlRelaxNGValidateDatatype(ctxt, content, define,
10235 ctxt->state->seq);
10236 if (ret == -1) {
10237 VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name);
10238 } else if (ret == 0) {
10239 ctxt->state->seq = NULL;
10240 }
10241 if (content != NULL)
10243 break;
10244 }
10245 case XML_RELAXNG_VALUE:{
10246 xmlChar *content = NULL;
10247 xmlChar *oldvalue;
10248 xmlNodePtr child;
10249
10250 child = node;
10251 while (child != NULL) {
10252 if (child->type == XML_ELEMENT_NODE) {
10253 VALID_ERR2(XML_RELAXNG_ERR_VALELEM,
10254 node->parent->name);
10255 ret = -1;
10256 break;
10257 } else if ((child->type == XML_TEXT_NODE) ||
10258 (child->type == XML_CDATA_SECTION_NODE)) {
10259 content = xmlStrcat(content, child->content);
10260 }
10261 /* TODO: handle entities ... */
10262 child = child->next;
10263 }
10264 if (ret == -1) {
10265 if (content != NULL)
10267 break;
10268 }
10269 if (content == NULL) {
10271 if (content == NULL) {
10272 xmlRngVErrMemory(ctxt, "validating\n");
10273 ret = -1;
10274 break;
10275 }
10276 }
10277 oldvalue = ctxt->state->value;
10278 ctxt->state->value = content;
10279 ret = xmlRelaxNGValidateValue(ctxt, define);
10280 ctxt->state->value = oldvalue;
10281 if (ret == -1) {
10282 VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name);
10283 } else if (ret == 0) {
10284 ctxt->state->seq = NULL;
10285 }
10286 if (content != NULL)
10288 break;
10289 }
10290 case XML_RELAXNG_LIST:{
10292 xmlNodePtr child;
10293 xmlChar *oldvalue, *oldendvalue;
10294 int len;
10295
10296 /*
10297 * Make sure it's only text nodes
10298 */
10299
10300 content = NULL;
10301 child = node;
10302 while (child != NULL) {
10303 if (child->type == XML_ELEMENT_NODE) {
10304 VALID_ERR2(XML_RELAXNG_ERR_LISTELEM,
10305 node->parent->name);
10306 ret = -1;
10307 break;
10308 } else if ((child->type == XML_TEXT_NODE) ||
10309 (child->type == XML_CDATA_SECTION_NODE)) {
10310 content = xmlStrcat(content, child->content);
10311 }
10312 /* TODO: handle entities ... */
10313 child = child->next;
10314 }
10315 if (ret == -1) {
10316 if (content != NULL)
10318 break;
10319 }
10320 if (content == NULL) {
10322 if (content == NULL) {
10323 xmlRngVErrMemory(ctxt, "validating\n");
10324 ret = -1;
10325 break;
10326 }
10327 }
10329 oldvalue = ctxt->state->value;
10330 oldendvalue = ctxt->state->endvalue;
10331 ctxt->state->value = content;
10332 ctxt->state->endvalue = content + len;
10333 ret = xmlRelaxNGValidateValue(ctxt, define);
10334 ctxt->state->value = oldvalue;
10335 ctxt->state->endvalue = oldendvalue;
10336 if (ret == -1) {
10337 VALID_ERR(XML_RELAXNG_ERR_LIST);
10338 } else if ((ret == 0) && (node != NULL)) {
10339 ctxt->state->seq = node->next;
10340 }
10341 if (content != NULL)
10343 break;
10344 }
10345 case XML_RELAXNG_EXCEPT:
10346 case XML_RELAXNG_PARAM:
10347 TODO ret = -1;
10348 break;
10349 }
10350 ctxt->depth--;
10351 return (ret);
10352}
10353
10363static int
10364xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
10365 xmlRelaxNGDefinePtr define)
10366{
10367 xmlRelaxNGStatesPtr states, res;
10368 int i, j, k, ret, oldflags;
10369
10370 /*
10371 * We should NOT have both ctxt->state and ctxt->states
10372 */
10373 if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
10374 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10375 ctxt->state = NULL;
10376 }
10377
10378 if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) {
10379 if (ctxt->states != NULL) {
10380 ctxt->state = ctxt->states->tabState[0];
10381 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10382 ctxt->states = NULL;
10383 }
10384 ret = xmlRelaxNGValidateState(ctxt, define);
10385 if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
10386 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10387 ctxt->state = NULL;
10388 }
10389 if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) {
10390 ctxt->state = ctxt->states->tabState[0];
10391 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10392 ctxt->states = NULL;
10393 }
10394 return (ret);
10395 }
10396
10397 states = ctxt->states;
10398 ctxt->states = NULL;
10399 res = NULL;
10400 j = 0;
10401 oldflags = ctxt->flags;
10402 ctxt->flags |= FLAGS_IGNORABLE;
10403 for (i = 0; i < states->nbState; i++) {
10404 ctxt->state = states->tabState[i];
10405 ctxt->states = NULL;
10406 ret = xmlRelaxNGValidateState(ctxt, define);
10407 /*
10408 * We should NOT have both ctxt->state and ctxt->states
10409 */
10410 if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
10411 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10412 ctxt->state = NULL;
10413 }
10414 if (ret == 0) {
10415 if (ctxt->states == NULL) {
10416 if (res != NULL) {
10417 /* add the state to the container */
10418 xmlRelaxNGAddStates(ctxt, res, ctxt->state);
10419 ctxt->state = NULL;
10420 } else {
10421 /* add the state directly in states */
10422 states->tabState[j++] = ctxt->state;
10423 ctxt->state = NULL;
10424 }
10425 } else {
10426 if (res == NULL) {
10427 /* make it the new container and copy other results */
10428 res = ctxt->states;
10429 ctxt->states = NULL;
10430 for (k = 0; k < j; k++)
10431 xmlRelaxNGAddStates(ctxt, res,
10432 states->tabState[k]);
10433 } else {
10434 /* add all the new results to res and reff the container */
10435 for (k = 0; k < ctxt->states->nbState; k++)
10436 xmlRelaxNGAddStates(ctxt, res,
10437 ctxt->states->tabState[k]);
10438 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10439 ctxt->states = NULL;
10440 }
10441 }
10442 } else {
10443 if (ctxt->state != NULL) {
10444 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10445 ctxt->state = NULL;
10446 } else if (ctxt->states != NULL) {
10447 for (k = 0; k < ctxt->states->nbState; k++)
10448 xmlRelaxNGFreeValidState(ctxt,
10449 ctxt->states->tabState[k]);
10450 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10451 ctxt->states = NULL;
10452 }
10453 }
10454 }
10455 ctxt->flags = oldflags;
10456 if (res != NULL) {
10457 xmlRelaxNGFreeStates(ctxt, states);
10458 ctxt->states = res;
10459 ret = 0;
10460 } else if (j > 1) {
10461 states->nbState = j;
10462 ctxt->states = states;
10463 ret = 0;
10464 } else if (j == 1) {
10465 ctxt->state = states->tabState[0];
10466 xmlRelaxNGFreeStates(ctxt, states);
10467 ret = 0;
10468 } else {
10469 ret = -1;
10470 xmlRelaxNGFreeStates(ctxt, states);
10471 if (ctxt->states != NULL) {
10472 xmlRelaxNGFreeStates(ctxt, ctxt->states);
10473 ctxt->states = NULL;
10474 }
10475 }
10476 if ((ctxt->state != NULL) && (ctxt->states != NULL)) {
10477 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10478 ctxt->state = NULL;
10479 }
10480 return (ret);
10481}
10482
10492static int
10493xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
10494{
10495 int ret;
10496 xmlRelaxNGPtr schema;
10497 xmlRelaxNGGrammarPtr grammar;
10498 xmlRelaxNGValidStatePtr state;
10499 xmlNodePtr node;
10500
10501 if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL))
10502 return (-1);
10503
10504 ctxt->errNo = XML_RELAXNG_OK;
10505 schema = ctxt->schema;
10506 grammar = schema->topgrammar;
10507 if (grammar == NULL) {
10508 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);
10509 return (-1);
10510 }
10511 state = xmlRelaxNGNewValidState(ctxt, NULL);
10512 ctxt->state = state;
10513 ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start);
10514 if ((ctxt->state != NULL) && (state->seq != NULL)) {
10515 state = ctxt->state;
10516 node = state->seq;
10517 node = xmlRelaxNGSkipIgnored(ctxt, node);
10518 if (node != NULL) {
10519 if (ret != -1) {
10520 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
10521 ret = -1;
10522 }
10523 }
10524 } else if (ctxt->states != NULL) {
10525 int i;
10526 int tmp = -1;
10527
10528 for (i = 0; i < ctxt->states->nbState; i++) {
10529 state = ctxt->states->tabState[i];
10530 node = state->seq;
10531 node = xmlRelaxNGSkipIgnored(ctxt, node);
10532 if (node == NULL)
10533 tmp = 0;
10534 xmlRelaxNGFreeValidState(ctxt, state);
10535 }
10536 if (tmp == -1) {
10537 if (ret != -1) {
10538 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);
10539 ret = -1;
10540 }
10541 }
10542 }
10543 if (ctxt->state != NULL) {
10544 xmlRelaxNGFreeValidState(ctxt, ctxt->state);
10545 ctxt->state = NULL;
10546 }
10547 if (ret != 0)
10548 xmlRelaxNGDumpValidError(ctxt);
10549#ifdef LIBXML_VALID_ENABLED
10550 if (ctxt->idref == 1) {
10551 xmlValidCtxt vctxt;
10552
10553 memset(&vctxt, 0, sizeof(xmlValidCtxt));
10554 vctxt.valid = 1;
10555 vctxt.error = ctxt->error;
10556 vctxt.warning = ctxt->warning;
10557 vctxt.userData = ctxt->userData;
10558
10559 if (xmlValidateDocumentFinal(&vctxt, doc) != 1)
10560 ret = -1;
10561 }
10562#endif /* LIBXML_VALID_ENABLED */
10563 if ((ret == 0) && (ctxt->errNo != XML_RELAXNG_OK))
10564 ret = -1;
10565
10566 return (ret);
10567}
10568
10582static void
10583xmlRelaxNGCleanPSVI(xmlNodePtr node) {
10584 xmlNodePtr cur;
10585
10586 if ((node == NULL) ||
10587 ((node->type != XML_ELEMENT_NODE) &&
10588 (node->type != XML_DOCUMENT_NODE) &&
10589 (node->type != XML_HTML_DOCUMENT_NODE)))
10590 return;
10591 if (node->type == XML_ELEMENT_NODE)
10592 node->psvi = NULL;
10593
10594 cur = node->children;
10595 while (cur != NULL) {
10596 if (cur->type == XML_ELEMENT_NODE) {
10597 cur->psvi = NULL;
10598 if (cur->children != NULL) {
10599 cur = cur->children;
10600 continue;
10601 }
10602 }
10603 if (cur->next != NULL) {
10604 cur = cur->next;
10605 continue;
10606 }
10607 do {
10608 cur = cur->parent;
10609 if (cur == NULL)
10610 break;
10611 if (cur == node) {
10612 cur = NULL;
10613 break;
10614 }
10615 if (cur->next != NULL) {
10616 cur = cur->next;
10617 break;
10618 }
10619 } while (cur != NULL);
10620 }
10621 return;
10622}
10623/************************************************************************
10624 * *
10625 * Validation interfaces *
10626 * *
10627 ************************************************************************/
10628
10637xmlRelaxNGValidCtxtPtr
10638xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema)
10639{
10640 xmlRelaxNGValidCtxtPtr ret;
10641
10642 ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt));
10643 if (ret == NULL) {
10644 xmlRngVErrMemory(NULL, "building context\n");
10645 return (NULL);
10646 }
10647 memset(ret, 0, sizeof(xmlRelaxNGValidCtxt));
10648 ret->schema = schema;
10649 ret->error = xmlGenericError;
10650 ret->userData = xmlGenericErrorContext;
10651 ret->errNr = 0;
10652 ret->errMax = 0;
10653 ret->err = NULL;
10654 ret->errTab = NULL;
10655 if (schema != NULL)
10656 ret->idref = schema->idref;
10657 ret->states = NULL;
10658 ret->freeState = NULL;
10659 ret->freeStates = NULL;
10660 ret->errNo = XML_RELAXNG_OK;
10661 return (ret);
10662}
10663
10670void
10671xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt)
10672{
10673 int k;
10674
10675 if (ctxt == NULL)
10676 return;
10677 if (ctxt->states != NULL)
10678 xmlRelaxNGFreeStates(NULL, ctxt->states);
10679 if (ctxt->freeState != NULL) {
10680 for (k = 0; k < ctxt->freeState->nbState; k++) {
10681 xmlRelaxNGFreeValidState(NULL, ctxt->freeState->tabState[k]);
10682 }
10683 xmlRelaxNGFreeStates(NULL, ctxt->freeState);
10684 }
10685 if (ctxt->freeStates != NULL) {
10686 for (k = 0; k < ctxt->freeStatesNr; k++) {
10687 xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]);
10688 }
10689 xmlFree(ctxt->freeStates);
10690 }
10691 if (ctxt->errTab != NULL)
10692 xmlFree(ctxt->errTab);
10693 if (ctxt->elemTab != NULL) {
10694 xmlRegExecCtxtPtr exec;
10695
10696 exec = xmlRelaxNGElemPop(ctxt);
10697 while (exec != NULL) {
10698 xmlRegFreeExecCtxt(exec);
10699 exec = xmlRelaxNGElemPop(ctxt);
10700 }
10701 xmlFree(ctxt->elemTab);
10702 }
10703 xmlFree(ctxt);
10704}
10705
10715void
10716xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
10717 xmlRelaxNGValidityErrorFunc err,
10718 xmlRelaxNGValidityWarningFunc warn, void *ctx)
10719{
10720 if (ctxt == NULL)
10721 return;
10722 ctxt->error = err;
10723 ctxt->warning = warn;
10724 ctxt->userData = ctx;
10725 ctxt->serror = NULL;
10726}
10727
10736void
10737xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt,
10738 xmlStructuredErrorFunc serror, void *ctx)
10739{
10740 if (ctxt == NULL)
10741 return;
10742 ctxt->serror = serror;
10743 ctxt->error = NULL;
10744 ctxt->warning = NULL;
10745 ctxt->userData = ctx;
10746}
10747
10759int
10760xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,
10761 xmlRelaxNGValidityErrorFunc * err,
10762 xmlRelaxNGValidityWarningFunc * warn, void **ctx)
10763{
10764 if (ctxt == NULL)
10765 return (-1);
10766 if (err != NULL)
10767 *err = ctxt->error;
10768 if (warn != NULL)
10769 *warn = ctxt->warning;
10770 if (ctx != NULL)
10771 *ctx = ctxt->userData;
10772 return (0);
10773}
10774
10785int
10786xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)
10787{
10788 int ret;
10789
10790 if ((ctxt == NULL) || (doc == NULL))
10791 return (-1);
10792
10793 ctxt->doc = doc;
10794
10795 ret = xmlRelaxNGValidateDocument(ctxt, doc);
10796 /*
10797 * Remove all left PSVI
10798 */
10799 xmlRelaxNGCleanPSVI((xmlNodePtr) doc);
10800
10801 /*
10802 * TODO: build error codes
10803 */
10804 if (ret == -1)
10805 return (1);
10806 return (ret);
10807}
10808
10809#endif /* LIBXML_SCHEMAS_ENABLED */
#define TODO
Definition: SAX2.c:44
static int state
Definition: maze.c:121
#define skip(...)
Definition: atltest.h:64
#define msg(x)
Definition: auth_time.c:54
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
struct _root root
#define except(x)
Definition: btrfs_drv.h:136
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
cd_progress_ptr progress
Definition: cdjpeg.h:152
FT_Library library
Definition: cffdrivr.c:661
Definition: list.h:37
struct list * next
Definition: list.h:38
static struct loaded_include * includes
Definition: compiler.c:53
static SIZE_T const char const D3D_SHADER_MACRO * defines
Definition: asm.c:31
#define NULL
Definition: types.h:112
#define IS_BLANK_NODE(n)
Definition: attributes.c:48
unsigned int idx
Definition: utils.c:41
content
Definition: atl_ax.c:994
const WCHAR * text
Definition: package.c:1794
int WINAPIV fprintf(FILE *file, const char *format,...)
Definition: file.c:5549
int ptrdiff_t
Definition: corecrt.h:194
#define stderr
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define check(expected, result)
Definition: dplayx.c:32
return ret
Definition: mutex.c:146
r parent
Definition: btrfs.c:3010
#define local
Definition: zutil.h:30
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint res
Definition: glext.h:9613
GLsizei GLuint * groups
Definition: glext.h:11113
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:9514
GLbitfield flags
Definition: glext.h:7161
GLboolean GLuint group
Definition: glext.h:11120
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
@ extra
Definition: id3.c:95
#define dup
Definition: syshdrs.h:51
if(dx< 0)
Definition: linetemp.h:194
const WCHAR * schema
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static WCHAR name2[]
Definition: record.c:35
static UINT UINT last
Definition: font.c:45
static size_t elem
Definition: string.c:71
const char * uri
Definition: sec_mgr.c:1588
static HWND child
Definition: cursoricon.c:298
static WCHAR escape[]
Definition: url.c:36
int k
Definition: mpi.c:3369
#define IS_BLANK_CH(c)
static unsigned __int64 next
Definition: rand_nt.c:6
#define warn(...)
#define err(...)
#define list
Definition: rosglue.h:35
const WCHAR * str
static calc_node_t temp
Definition: rpn_ieee.c:38
#define warning(s)
Definition: debug.h:83
void * xmlGenericErrorContext
Definition: globals.c:410
xmlReallocFunc xmlRealloc
Definition: globals.c:214
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlGenericErrorFunc xmlGenericError
Definition: globals.c:396
xmlMallocFunc xmlMalloc
Definition: globals.c:193
xmlMallocFunc xmlMallocAtomic
Definition: globals.c:204
void xmlHashScan(xmlHashTablePtr hash, xmlHashScanner scan, void *data)
Definition: hash.c:898
void xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc)
Definition: hash.c:229
void * xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key)
Definition: hash.c:739
void * xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2)
Definition: hash.c:754
int xmlHashAddEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload)
Definition: hash.c:621
xmlHashTablePtr xmlHashCreate(int size)
Definition: hash.c:160
int xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, void *payload)
Definition: hash.c:639
xmlHashTable * xmlHashTablePtr
Definition: hash.h:26
XMLPUBFUN xmlDocPtr xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
Definition: parser.c:14835
XMLPUBFUN xmlDocPtr xmlReadFile(const char *URL, const char *encoding, int options)
Definition: parser.c:14811
XML_HIDDEN void __xmlRaiseError(xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, void *data, void *ctx, void *nod, int domain, int code, xmlErrorLevel level, const char *file, int line, const char *str1, const char *str2, const char *str3, int int1, int col, const char *msg,...) LIBXML_ATTR_FORMAT(16
XML_HIDDEN void xmlParserErrors const char const xmlChar const xmlChar * str2
Definition: parser.h:35
XML_HIDDEN void xmlParserErrors const char const xmlChar * str1
Definition: parser.h:35
XML_HIDDEN void xmlAutomataSetFlags(xmlAutomataPtr am, int flags)
XML_HIDDEN xmlChar * xmlEscapeFormatString(xmlChar **msg)
Definition: xmlstring.c:1001
#define memset(x, y, z)
Definition: compat.h:39
Definition: uri.h:34
Definition: cookie.c:202
char * value
Definition: compiler.c:67
char * name
Definition: compiler.c:66
Definition: name.c:39
Definition: mxnamespace.c:38
Definition: send.c:48
Definition: reader.c:220
Definition: tools.h:99
#define max(a, b)
Definition: svc.c:63
Character const *const prefix
Definition: tempnam.cpp:195
Definition: dlist.c:348
void * next
Definition: dlist.c:360
Definition: pdh_main.c:96
XMLPUBFUN xmlChar * xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1902
XMLPUBFUN void xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1396
XMLPUBFUN xmlChar * xmlURIEscapeStr(const xmlChar *str, const xmlChar *list)
Definition: uri.c:1689
XMLPUBFUN xmlURIPtr xmlParseURI(const char *str)
Definition: uri.c:947
typedeftypedef void(*) typedef void(*) struct _xmlValidCtx xmlValidCtxt)
Definition: valid.h:67
#define success(from, fromstr, to, tostr)
#define snprintf
Definition: wintirpc.h:48
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
void(*) typedef void(* xmlStructuredErrorFunc)(void *userData, const xmlError *error)
Definition: xmlerror.h:859
@ XML_ERR_ERROR
Definition: xmlerror.h:27
@ XML_ERR_FATAL
Definition: xmlerror.h:28
@ XML_FROM_RELAXNGV
Definition: xmlerror.h:56
@ XML_FROM_RELAXNGP
Definition: xmlerror.h:55
void(* xmlGenericErrorFunc)(void *ctx, const char *msg,...) LIBXML_ATTR_FORMAT(2
Definition: xmlerror.h:848
@ XML_RNGP_UNKNOWN_TYPE_LIB
Definition: xmlerror.h:381
@ XML_RNGP_ELEM_TEXT_CONFLICT
Definition: xmlerror.h:286
@ XML_RNGP_EXCEPT_NO_CONTENT
Definition: xmlerror.h:295
@ XML_RNGP_PARAM_FORBIDDEN
Definition: xmlerror.h:323
@ XML_RNGP_GROUP_ATTR_CONFLICT
Definition: xmlerror.h:305
@ XML_RNGP_ATTR_CONFLICT
Definition: xmlerror.h:266
@ XML_RNGP_XMLNS_NAME
Definition: xmlerror.h:386
@ XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR
Definition: xmlerror.h:352
@ XML_RNGP_PAT_START_DATA
Definition: xmlerror.h:354
@ XML_RNGP_PAT_START_GROUP
Definition: xmlerror.h:356
@ XML_RNGP_PAT_DATA_EXCEPT_ONEMORE
Definition: xmlerror.h:340
@ XML_RNGP_EMPTY_CONSTRUCT
Definition: xmlerror.h:288
@ XML_RNGP_PARENTREF_CREATE_FAILED
Definition: xmlerror.h:325
@ XML_RNGP_ELEM_CONTENT_ERROR
Definition: xmlerror.h:281
@ XML_RNGP_DEFINE_NAME_MISSING
Definition: xmlerror.h:279
@ XML_RNGP_START_MISSING
Definition: xmlerror.h:372
@ XML_RNGP_TEXT_HAS_CHILD
Definition: xmlerror.h:374
@ XML_RNGP_PAT_LIST_TEXT
Definition: xmlerror.h:348
@ XML_RNGP_FORBIDDEN_ATTRIBUTE
Definition: xmlerror.h:299
@ XML_RNGP_PARENTREF_NO_PARENT
Definition: xmlerror.h:328
@ XML_RNGP_PAT_DATA_EXCEPT_ATTR
Definition: xmlerror.h:334
@ XML_RNGP_PARSE_ERROR
Definition: xmlerror.h:330
@ XML_RNGP_EXTERNALREF_RECURSE
Definition: xmlerror.h:298
@ XML_RNGP_PAT_ONEMORE_GROUP_ATTR
Definition: xmlerror.h:351
@ XML_RNGP_EXCEPT_MISSING
Definition: xmlerror.h:293
@ XML_RNGP_START_CHOICE_AND_INTERLEAVE
Definition: xmlerror.h:369
@ XML_RNGP_ELEMENT_NAME
Definition: xmlerror.h:284
@ XML_RNGP_URI_NOT_ABSOLUTE
Definition: xmlerror.h:383
@ XML_RNGP_PAT_LIST_ELEM
Definition: xmlerror.h:344
@ XML_RNGP_GRAMMAR_NO_START
Definition: xmlerror.h:304
@ XML_RNGP_ELEMENT_CONTENT
Definition: xmlerror.h:283
@ XML_RNGP_NOTALLOWED_NOT_EMPTY
Definition: xmlerror.h:320
@ XML_RNGP_DEF_CHOICE_AND_INTERLEAVE
Definition: xmlerror.h:275
@ XML_RNGP_DATA_CONTENT
Definition: xmlerror.h:274
@ XML_RNGP_INCLUDE_RECURSE
Definition: xmlerror.h:309
@ XML_RNGP_PAT_ATTR_ELEM
Definition: xmlerror.h:333
@ XML_RNGP_EXTERNAL_REF_FAILURE
Definition: xmlerror.h:297
@ XML_RNGP_HREF_ERROR
Definition: xmlerror.h:306
@ XML_RNGP_PAT_START_ATTR
Definition: xmlerror.h:353
@ XML_RNGP_ANYNAME_ATTR_ANCESTOR
Definition: xmlerror.h:265
@ XML_RNGP_ERROR_TYPE_LIB
Definition: xmlerror.h:291
@ XML_RNGP_ELEMENT_NO_CONTENT
Definition: xmlerror.h:285
@ XML_RNGP_PAT_START_EMPTY
Definition: xmlerror.h:355
@ XML_RNGP_DEFINE_EMPTY
Definition: xmlerror.h:277
@ XML_RNGP_ELEMENT_EMPTY
Definition: xmlerror.h:282
@ XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE
Definition: xmlerror.h:338
@ XML_RNGP_INVALID_URI
Definition: xmlerror.h:315
@ XML_RNGP_NSNAME_NO_NS
Definition: xmlerror.h:322
@ XML_RNGP_PAT_START_VALUE
Definition: xmlerror.h:361
@ XML_RNGP_ELEM_CONTENT_EMPTY
Definition: xmlerror.h:280
@ XML_RNGP_EMPTY_NOT_EMPTY
Definition: xmlerror.h:290
@ XML_RNGP_INVALID_VALUE
Definition: xmlerror.h:316
@ XML_RNGP_PAT_DATA_EXCEPT_TEXT
Definition: xmlerror.h:342
@ XML_RNGP_ATTRIBUTE_NOOP
Definition: xmlerror.h:270
@ XML_RNGP_EXCEPT_MULTIPLE
Definition: xmlerror.h:294
@ XML_RNGP_PAT_LIST_ATTR
Definition: xmlerror.h:343
@ XML_RNGP_DEFINE_MISSING
Definition: xmlerror.h:278
@ XML_RNGP_UNKNOWN_CONSTRUCT
Definition: xmlerror.h:380
@ XML_RNGP_PAT_DATA_EXCEPT_GROUP
Definition: xmlerror.h:337
@ XML_RNGP_REF_CREATE_FAILED
Definition: xmlerror.h:363
@ XML_ERR_INTERNAL_ERROR
Definition: xmlerror.h:101
@ XML_RNGP_PAT_ATTR_ATTR
Definition: xmlerror.h:332
@ XML_RNGP_INCLUDE_FAILURE
Definition: xmlerror.h:308
@ XML_RNGP_TEXT_EXPECTED
Definition: xmlerror.h:373
@ XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME
Definition: xmlerror.h:349
@ XML_RNGP_REF_NAME_INVALID
Definition: xmlerror.h:365
@ XML_RNGP_EXTERNALREF_EMTPY
Definition: xmlerror.h:296
@ XML_RNGP_PAT_START_LIST
Definition: xmlerror.h:358
@ XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME
Definition: xmlerror.h:331
@ XML_RNGP_PARENTREF_NAME_INVALID
Definition: xmlerror.h:326
@ XML_RNGP_NAME_MISSING
Definition: xmlerror.h:318
@ XML_RNGP_ATTRIBUTE_CHILDREN
Definition: xmlerror.h:267
@ XML_RNGP_MISSING_HREF
Definition: xmlerror.h:317
@ XML_RNGP_TYPE_NOT_FOUND
Definition: xmlerror.h:376
@ XML_RNGP_UNKNOWN_ATTRIBUTE
Definition: xmlerror.h:378
@ XML_RNGP_TYPE_VALUE
Definition: xmlerror.h:377
@ XML_RNGP_GRAMMAR_CONTENT
Definition: xmlerror.h:301
@ XML_RNGP_REF_NO_DEF
Definition: xmlerror.h:366
@ XML_RNGP_INCLUDE_EMPTY
Definition: xmlerror.h:307
@ XML_RNGP_REF_CYCLE
Definition: xmlerror.h:364
@ XML_RNGP_PREFIX_UNDEFINED
Definition: xmlerror.h:362
@ XML_RNGP_TYPE_MISSING
Definition: xmlerror.h:375
@ XML_RNGP_PAT_LIST_INTERLEAVE
Definition: xmlerror.h:345
@ XML_RNGP_PAT_DATA_EXCEPT_LIST
Definition: xmlerror.h:339
@ XML_RNGP_XML_NS
Definition: xmlerror.h:387
@ XML_RNGP_REF_NO_NAME
Definition: xmlerror.h:367
@ XML_RNGP_PAT_LIST_REF
Definition: xmlerror.h:347
@ XML_RNGP_PAT_LIST_LIST
Definition: xmlerror.h:346
@ XML_RNGP_URI_FRAGMENT
Definition: xmlerror.h:382
@ XML_RNGP_DEFINE_CREATE_FAILED
Definition: xmlerror.h:276
@ XML_RNGP_EMPTY
Definition: xmlerror.h:287
@ XML_RNGP_REF_NOT_EMPTY
Definition: xmlerror.h:368
@ XML_RNGP_PARENTREF_NOT_EMPTY
Definition: xmlerror.h:329
@ XML_RNGP_ATTRIBUTE_EMPTY
Definition: xmlerror.h:269
@ XML_RNGP_EMPTY_CONTENT
Definition: xmlerror.h:289
@ XML_RNGP_PAT_DATA_EXCEPT_REF
Definition: xmlerror.h:341
@ XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME
Definition: xmlerror.h:350
@ XML_RNGP_EXCEPT_EMPTY
Definition: xmlerror.h:292
@ XML_RNGP_INTERLEAVE_NO_CONTENT
Definition: xmlerror.h:313
@ XML_RNGP_FOREIGN_ELEMENT
Definition: xmlerror.h:300
@ XML_RNGP_VALUE_NO_CONTENT
Definition: xmlerror.h:385
@ XML_RNGP_PAT_START_TEXT
Definition: xmlerror.h:360
@ XML_RNGP_CREATE_FAILURE
Definition: xmlerror.h:273
@ XML_RNGP_CHOICE_CONTENT
Definition: xmlerror.h:271
@ XML_RNGP_INTERLEAVE_ADD
Definition: xmlerror.h:310
@ XML_RNGP_PAT_DATA_EXCEPT_EMPTY
Definition: xmlerror.h:336
@ XML_RNGP_ATTRIBUTE_CONTENT
Definition: xmlerror.h:268
@ XML_RNGP_START_CONTENT
Definition: xmlerror.h:370
@ XML_RNGP_NEED_COMBINE
Definition: xmlerror.h:319
@ XML_RNGP_CHOICE_EMPTY
Definition: xmlerror.h:272
@ XML_RNGP_INTERLEAVE_CREATE_FAILED
Definition: xmlerror.h:311
@ XML_RNGP_INVALID_DEFINE_NAME
Definition: xmlerror.h:314
@ XML_RNGP_UNKNOWN_COMBINE
Definition: xmlerror.h:379
@ XML_RNGP_GRAMMAR_MISSING
Definition: xmlerror.h:303
@ XML_RNGP_PAT_DATA_EXCEPT_ELEM
Definition: xmlerror.h:335
@ XML_RNGP_PAT_START_ONEMORE
Definition: xmlerror.h:359
@ XML_RNGP_PARAM_NAME_MISSING
Definition: xmlerror.h:324
@ XML_RNGP_NSNAME_ATTR_ANCESTOR
Definition: xmlerror.h:321
@ XML_RNGP_GRAMMAR_EMPTY
Definition: xmlerror.h:302
@ XML_RNGP_PARENTREF_NO_NAME
Definition: xmlerror.h:327
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
@ XML_RNGP_START_EMPTY
Definition: xmlerror.h:371
XMLPUBFUN int xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:428
XMLPUBFUN xmlChar * xmlCharStrdup(const char *cur)
Definition: xmlstring.c:116
XMLPUBFUN xmlChar * xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
#define LIBXML_ATTR_FORMAT(fmt, args)
Definition: xmlversion.h:472
#define const
Definition: zconf.h:233