Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * relaxng.c : implementation of the Relax-NG handling and validity checking  | 
3  |  |  *  | 
4  |  |  * See Copyright for the status of this software.  | 
5  |  |  *  | 
6  |  |  * Daniel Veillard <veillard@redhat.com>  | 
7  |  |  */  | 
8  |  |  | 
9  |  | /**  | 
10  |  |  * TODO:  | 
11  |  |  * - add support for DTD compatibility spec  | 
12  |  |  *   http://www.oasis-open.org/committees/relax-ng/compatibility-20011203.html  | 
13  |  |  * - report better mem allocations pbms at runtime and abort immediately.  | 
14  |  |  */  | 
15  |  |  | 
16  |  | #define IN_LIBXML  | 
17  |  | #include "libxml.h"  | 
18  |  |  | 
19  |  | #ifdef LIBXML_SCHEMAS_ENABLED  | 
20  |  |  | 
21  |  | #include <string.h>  | 
22  |  | #include <stdio.h>  | 
23  |  | #include <stddef.h>  | 
24  |  | #include <libxml/xmlmemory.h>  | 
25  |  | #include <libxml/parser.h>  | 
26  |  | #include <libxml/parserInternals.h>  | 
27  |  | #include <libxml/hash.h>  | 
28  |  | #include <libxml/uri.h>  | 
29  |  |  | 
30  |  | #include <libxml/relaxng.h>  | 
31  |  |  | 
32  |  | #include <libxml/xmlschemastypes.h>  | 
33  |  | #include <libxml/xmlautomata.h>  | 
34  |  | #include <libxml/xmlregexp.h>  | 
35  |  | #include <libxml/xmlschemastypes.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  |  |  */  | 
44  |  | static const xmlChar *xmlRelaxNGNs = (const xmlChar *)  | 
45  |  |     "http://relaxng.org/ns/structure/1.0";  | 
46  |  |  | 
47  |  | #define IS_RELAXNG(node, typ)           \  | 
48  | 0  |    ((node != NULL) && (node->ns != NULL) &&       \  | 
49  | 0  |     (node->type == XML_ELEMENT_NODE) &&         \  | 
50  | 0  |     (xmlStrEqual(node->name, (const xmlChar *) typ)) &&   \  | 
51  | 0  |     (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))  | 
52  |  |  | 
53  |  |  | 
54  |  | #if 0  | 
55  |  | #define DEBUG 1  | 
56  |  |  | 
57  |  | #define DEBUG_GRAMMAR 1  | 
58  |  |  | 
59  |  | #define DEBUG_CONTENT 1  | 
60  |  |  | 
61  |  | #define DEBUG_TYPE 1  | 
62  |  |  | 
63  |  | #define DEBUG_VALID 1  | 
64  |  |  | 
65  |  | #define DEBUG_INTERLEAVE 1  | 
66  |  |  | 
67  |  | #define DEBUG_LIST 1  | 
68  |  |  | 
69  |  | #define DEBUG_INCLUDE 1  | 
70  |  |  | 
71  |  | #define DEBUG_ERROR 1  | 
72  |  |  | 
73  |  | #define DEBUG_COMPILE 1  | 
74  |  |  | 
75  |  | #define DEBUG_PROGRESSIVE 1  | 
76  |  | #endif  | 
77  |  |  | 
78  | 0  | #define MAX_ERROR 5  | 
79  |  |  | 
80  |  | #define TODO                \  | 
81  | 0  |     xmlGenericError(xmlGenericErrorContext,       \  | 
82  | 0  |       "Unimplemented block at %s:%d\n",       \  | 
83  | 0  |             __FILE__, __LINE__);  | 
84  |  |  | 
85  |  | typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;  | 
86  |  | typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;  | 
87  |  |  | 
88  |  | typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine;  | 
89  |  | typedef xmlRelaxNGDefine *xmlRelaxNGDefinePtr;  | 
90  |  |  | 
91  |  | typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument;  | 
92  |  | typedef xmlRelaxNGDocument *xmlRelaxNGDocumentPtr;  | 
93  |  |  | 
94  |  | typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude;  | 
95  |  | typedef xmlRelaxNGInclude *xmlRelaxNGIncludePtr;  | 
96  |  |  | 
97  |  | typedef enum { | 
98  |  |     XML_RELAXNG_COMBINE_UNDEFINED = 0,  /* undefined */  | 
99  |  |     XML_RELAXNG_COMBINE_CHOICE, /* choice */  | 
100  |  |     XML_RELAXNG_COMBINE_INTERLEAVE      /* interleave */  | 
101  |  | } xmlRelaxNGCombine;  | 
102  |  |  | 
103  |  | typedef enum { | 
104  |  |     XML_RELAXNG_CONTENT_ERROR = -1,  | 
105  |  |     XML_RELAXNG_CONTENT_EMPTY = 0,  | 
106  |  |     XML_RELAXNG_CONTENT_SIMPLE,  | 
107  |  |     XML_RELAXNG_CONTENT_COMPLEX  | 
108  |  | } xmlRelaxNGContentType;  | 
109  |  |  | 
110  |  | typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar;  | 
111  |  | typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr;  | 
112  |  |  | 
113  |  | struct _xmlRelaxNGGrammar { | 
114  |  |     xmlRelaxNGGrammarPtr parent;        /* the parent grammar if any */  | 
115  |  |     xmlRelaxNGGrammarPtr children;      /* the children grammar if any */  | 
116  |  |     xmlRelaxNGGrammarPtr next;  /* the next grammar if any */  | 
117  |  |     xmlRelaxNGDefinePtr start;  /* <start> content */  | 
118  |  |     xmlRelaxNGCombine combine;  /* the default combine value */  | 
119  |  |     xmlRelaxNGDefinePtr startList;      /* list of <start> definitions */  | 
120  |  |     xmlHashTablePtr defs;       /* define* */  | 
121  |  |     xmlHashTablePtr refs;       /* references */  | 
122  |  | };  | 
123  |  |  | 
124  |  |  | 
125  |  | typedef enum { | 
126  |  |     XML_RELAXNG_NOOP = -1,      /* a no operation from simplification  */  | 
127  |  |     XML_RELAXNG_EMPTY = 0,      /* an empty pattern */  | 
128  |  |     XML_RELAXNG_NOT_ALLOWED,    /* not allowed top */  | 
129  |  |     XML_RELAXNG_EXCEPT,         /* except present in nameclass defs */  | 
130  |  |     XML_RELAXNG_TEXT,           /* textual content */  | 
131  |  |     XML_RELAXNG_ELEMENT,        /* an element */  | 
132  |  |     XML_RELAXNG_DATATYPE,       /* external data type definition */  | 
133  |  |     XML_RELAXNG_PARAM,          /* external data type parameter */  | 
134  |  |     XML_RELAXNG_VALUE,          /* value from an external data type definition */  | 
135  |  |     XML_RELAXNG_LIST,           /* a list of patterns */  | 
136  |  |     XML_RELAXNG_ATTRIBUTE,      /* an attribute following a pattern */  | 
137  |  |     XML_RELAXNG_DEF,            /* a definition */  | 
138  |  |     XML_RELAXNG_REF,            /* reference to a definition */  | 
139  |  |     XML_RELAXNG_EXTERNALREF,    /* reference to an external def */  | 
140  |  |     XML_RELAXNG_PARENTREF,      /* reference to a def in the parent grammar */  | 
141  |  |     XML_RELAXNG_OPTIONAL,       /* optional patterns */  | 
142  |  |     XML_RELAXNG_ZEROORMORE,     /* zero or more non empty patterns */  | 
143  |  |     XML_RELAXNG_ONEORMORE,      /* one or more non empty patterns */  | 
144  |  |     XML_RELAXNG_CHOICE,         /* a choice between non empty patterns */  | 
145  |  |     XML_RELAXNG_GROUP,          /* a pair/group of non empty patterns */  | 
146  |  |     XML_RELAXNG_INTERLEAVE,     /* interleaving choice of non-empty patterns */  | 
147  |  |     XML_RELAXNG_START           /* Used to keep track of starts on grammars */  | 
148  |  | } xmlRelaxNGType;  | 
149  |  |  | 
150  | 0  | #define IS_NULLABLE   (1 << 0)  | 
151  | 0  | #define IS_NOT_NULLABLE   (1 << 1)  | 
152  | 0  | #define IS_INDETERMINIST  (1 << 2)  | 
153  | 0  | #define IS_MIXED    (1 << 3)  | 
154  | 0  | #define IS_TRIABLE    (1 << 4)  | 
155  | 0  | #define IS_PROCESSED    (1 << 5)  | 
156  | 0  | #define IS_COMPILABLE   (1 << 6)  | 
157  | 0  | #define IS_NOT_COMPILABLE (1 << 7)  | 
158  | 0  | #define IS_EXTERNAL_REF         (1 << 8)  | 
159  |  |  | 
160  |  | struct _xmlRelaxNGDefine { | 
161  |  |     xmlRelaxNGType type;        /* the type of definition */  | 
162  |  |     xmlNodePtr node;            /* the node in the source */  | 
163  |  |     xmlChar *name;              /* the element local name if present */  | 
164  |  |     xmlChar *ns;                /* the namespace local name if present */  | 
165  |  |     xmlChar *value;             /* value when available */  | 
166  |  |     void *data;                 /* data lib or specific pointer */  | 
167  |  |     xmlRelaxNGDefinePtr content;        /* the expected content */  | 
168  |  |     xmlRelaxNGDefinePtr parent; /* the parent definition, if any */  | 
169  |  |     xmlRelaxNGDefinePtr next;   /* list within grouping sequences */  | 
170  |  |     xmlRelaxNGDefinePtr attrs;  /* list of attributes for elements */  | 
171  |  |     xmlRelaxNGDefinePtr nameClass;      /* the nameClass definition if any */  | 
172  |  |     xmlRelaxNGDefinePtr nextHash;       /* next define in defs/refs hash tables */  | 
173  |  |     short depth;                /* used for the cycle detection */  | 
174  |  |     short dflags;               /* define related flags */  | 
175  |  |     xmlRegexpPtr contModel;     /* a compiled content model if available */  | 
176  |  | };  | 
177  |  |  | 
178  |  | /**  | 
179  |  |  * _xmlRelaxNG:  | 
180  |  |  *  | 
181  |  |  * A RelaxNGs definition  | 
182  |  |  */  | 
183  |  | struct _xmlRelaxNG { | 
184  |  |     void *_private;             /* unused by the library for users or bindings */  | 
185  |  |     xmlRelaxNGGrammarPtr topgrammar;  | 
186  |  |     xmlDocPtr doc;  | 
187  |  |  | 
188  |  |     int idref;                  /* requires idref checking */  | 
189  |  |  | 
190  |  |     xmlHashTablePtr defs;       /* define */  | 
191  |  |     xmlHashTablePtr refs;       /* references */  | 
192  |  |     xmlRelaxNGDocumentPtr documents;    /* all the documents loaded */  | 
193  |  |     xmlRelaxNGIncludePtr includes;      /* all the includes loaded */  | 
194  |  |     int defNr;                  /* number of defines used */  | 
195  |  |     xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */  | 
196  |  |  | 
197  |  | };  | 
198  |  |  | 
199  | 0  | #define XML_RELAXNG_IN_ATTRIBUTE  (1 << 0)  | 
200  | 0  | #define XML_RELAXNG_IN_ONEORMORE  (1 << 1)  | 
201  | 0  | #define XML_RELAXNG_IN_LIST   (1 << 2)  | 
202  | 0  | #define XML_RELAXNG_IN_DATAEXCEPT (1 << 3)  | 
203  | 0  | #define XML_RELAXNG_IN_START    (1 << 4)  | 
204  | 0  | #define XML_RELAXNG_IN_OOMGROUP   (1 << 5)  | 
205  | 0  | #define XML_RELAXNG_IN_OOMINTERLEAVE  (1 << 6)  | 
206  | 0  | #define XML_RELAXNG_IN_EXTERNALREF  (1 << 7)  | 
207  | 0  | #define XML_RELAXNG_IN_ANYEXCEPT  (1 << 8)  | 
208  | 0  | #define XML_RELAXNG_IN_NSEXCEPT   (1 << 9)  | 
209  |  |  | 
210  |  | struct _xmlRelaxNGParserCtxt { | 
211  |  |     void *userData;             /* user specific data block */  | 
212  |  |     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */  | 
213  |  |     xmlRelaxNGValidityWarningFunc warning;      /* the callback in case of warning */  | 
214  |  |     xmlStructuredErrorFunc serror;  | 
215  |  |     xmlRelaxNGValidErr err;  | 
216  |  |  | 
217  |  |     xmlRelaxNGPtr schema;       /* The schema in use */  | 
218  |  |     xmlRelaxNGGrammarPtr grammar;       /* the current grammar */  | 
219  |  |     xmlRelaxNGGrammarPtr parentgrammar; /* the parent grammar */  | 
220  |  |     int flags;                  /* parser flags */  | 
221  |  |     int nbErrors;               /* number of errors at parse time */  | 
222  |  |     int nbWarnings;             /* number of warnings at parse time */  | 
223  |  |     const xmlChar *define;      /* the current define scope */  | 
224  |  |     xmlRelaxNGDefinePtr def;    /* the current define */  | 
225  |  |  | 
226  |  |     int nbInterleaves;  | 
227  |  |     xmlHashTablePtr interleaves;        /* keep track of all the interleaves */  | 
228  |  |  | 
229  |  |     xmlRelaxNGDocumentPtr documents;    /* all the documents loaded */  | 
230  |  |     xmlRelaxNGIncludePtr includes;      /* all the includes loaded */  | 
231  |  |     xmlChar *URL;  | 
232  |  |     xmlDocPtr document;  | 
233  |  |  | 
234  |  |     int defNr;                  /* number of defines used */  | 
235  |  |     int defMax;                 /* number of defines allocated */  | 
236  |  |     xmlRelaxNGDefinePtr *defTab;        /* pointer to the allocated definitions */  | 
237  |  |  | 
238  |  |     const char *buffer;  | 
239  |  |     int size;  | 
240  |  |  | 
241  |  |     /* the document stack */  | 
242  |  |     xmlRelaxNGDocumentPtr doc;  /* Current parsed external ref */  | 
243  |  |     int docNr;                  /* Depth of the parsing stack */  | 
244  |  |     int docMax;                 /* Max depth of the parsing stack */  | 
245  |  |     xmlRelaxNGDocumentPtr *docTab;      /* array of docs */  | 
246  |  |  | 
247  |  |     /* the include stack */  | 
248  |  |     xmlRelaxNGIncludePtr inc;   /* Current parsed include */  | 
249  |  |     int incNr;                  /* Depth of the include parsing stack */  | 
250  |  |     int incMax;                 /* Max depth of the parsing stack */  | 
251  |  |     xmlRelaxNGIncludePtr *incTab;       /* array of incs */  | 
252  |  |  | 
253  |  |     int idref;                  /* requires idref checking */  | 
254  |  |  | 
255  |  |     /* used to compile content models */  | 
256  |  |     xmlAutomataPtr am;          /* the automata */  | 
257  |  |     xmlAutomataStatePtr state;  /* used to build the automata */  | 
258  |  |  | 
259  |  |     int crng;     /* compact syntax and other flags */  | 
260  |  |     int freedoc;    /* need to free the document */  | 
261  |  | };  | 
262  |  |  | 
263  | 0  | #define FLAGS_IGNORABLE   1  | 
264  | 0  | #define FLAGS_NEGATIVE    2  | 
265  | 0  | #define FLAGS_MIXED_CONTENT 4  | 
266  | 0  | #define FLAGS_NOERROR   8  | 
267  |  |  | 
268  |  | /**  | 
269  |  |  * xmlRelaxNGInterleaveGroup:  | 
270  |  |  *  | 
271  |  |  * A RelaxNGs partition set associated to lists of definitions  | 
272  |  |  */  | 
273  |  | typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup;  | 
274  |  | typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr;  | 
275  |  | struct _xmlRelaxNGInterleaveGroup { | 
276  |  |     xmlRelaxNGDefinePtr rule;   /* the rule to satisfy */  | 
277  |  |     xmlRelaxNGDefinePtr *defs;  /* the array of element definitions */  | 
278  |  |     xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */  | 
279  |  | };  | 
280  |  |  | 
281  | 0  | #define IS_DETERMINIST    1  | 
282  | 0  | #define IS_NEEDCHECK    2  | 
283  |  |  | 
284  |  | /**  | 
285  |  |  * xmlRelaxNGPartitions:  | 
286  |  |  *  | 
287  |  |  * A RelaxNGs partition associated to an interleave group  | 
288  |  |  */  | 
289  |  | typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition;  | 
290  |  | typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr;  | 
291  |  | struct _xmlRelaxNGPartition { | 
292  |  |     int nbgroups;               /* number of groups in the partitions */  | 
293  |  |     xmlHashTablePtr triage;     /* hash table used to direct nodes to the  | 
294  |  |                                  * right group when possible */  | 
295  |  |     int flags;                  /* determinist ? */  | 
296  |  |     xmlRelaxNGInterleaveGroupPtr *groups;  | 
297  |  | };  | 
298  |  |  | 
299  |  | /**  | 
300  |  |  * xmlRelaxNGValidState:  | 
301  |  |  *  | 
302  |  |  * A RelaxNGs validation state  | 
303  |  |  */  | 
304  | 0  | #define MAX_ATTR 20  | 
305  |  | typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState;  | 
306  |  | typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr;  | 
307  |  | struct _xmlRelaxNGValidState { | 
308  |  |     xmlNodePtr node;            /* the current node */  | 
309  |  |     xmlNodePtr seq;             /* the sequence of children left to validate */  | 
310  |  |     int nbAttrs;                /* the number of attributes */  | 
311  |  |     int maxAttrs;               /* the size of attrs */  | 
312  |  |     int nbAttrLeft;             /* the number of attributes left to validate */  | 
313  |  |     xmlChar *value;             /* the value when operating on string */  | 
314  |  |     xmlChar *endvalue;          /* the end value when operating on string */  | 
315  |  |     xmlAttrPtr *attrs;          /* the array of attributes */  | 
316  |  | };  | 
317  |  |  | 
318  |  | /**  | 
319  |  |  * xmlRelaxNGStates:  | 
320  |  |  *  | 
321  |  |  * A RelaxNGs container for validation state  | 
322  |  |  */  | 
323  |  | typedef struct _xmlRelaxNGStates xmlRelaxNGStates;  | 
324  |  | typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr;  | 
325  |  | struct _xmlRelaxNGStates { | 
326  |  |     int nbState;                /* the number of states */  | 
327  |  |     int maxState;               /* the size of the array */  | 
328  |  |     xmlRelaxNGValidStatePtr *tabState;  | 
329  |  | };  | 
330  |  |  | 
331  | 0  | #define ERROR_IS_DUP  1  | 
332  |  |  | 
333  |  | /**  | 
334  |  |  * xmlRelaxNGValidError:  | 
335  |  |  *  | 
336  |  |  * A RelaxNGs validation error  | 
337  |  |  */  | 
338  |  | typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;  | 
339  |  | typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;  | 
340  |  | struct _xmlRelaxNGValidError { | 
341  |  |     xmlRelaxNGValidErr err;     /* the error number */  | 
342  |  |     int flags;                  /* flags */  | 
343  |  |     xmlNodePtr node;            /* the current node */  | 
344  |  |     xmlNodePtr seq;             /* the current child */  | 
345  |  |     const xmlChar *arg1;        /* first arg */  | 
346  |  |     const xmlChar *arg2;        /* second arg */  | 
347  |  | };  | 
348  |  |  | 
349  |  | /**  | 
350  |  |  * xmlRelaxNGValidCtxt:  | 
351  |  |  *  | 
352  |  |  * A RelaxNGs validation context  | 
353  |  |  */  | 
354  |  |  | 
355  |  | struct _xmlRelaxNGValidCtxt { | 
356  |  |     void *userData;             /* user specific data block */  | 
357  |  |     xmlRelaxNGValidityErrorFunc error;  /* the callback in case of errors */  | 
358  |  |     xmlRelaxNGValidityWarningFunc warning;      /* the callback in case of warning */  | 
359  |  |     xmlStructuredErrorFunc serror;  | 
360  |  |     int nbErrors;               /* number of errors in validation */  | 
361  |  |  | 
362  |  |     xmlRelaxNGPtr schema;       /* The schema in use */  | 
363  |  |     xmlDocPtr doc;              /* the document being validated */  | 
364  |  |     int flags;                  /* validation flags */  | 
365  |  |     int depth;                  /* validation depth */  | 
366  |  |     int idref;                  /* requires idref checking */  | 
367  |  |     int errNo;                  /* the first error found */  | 
368  |  |  | 
369  |  |     /*  | 
370  |  |      * Errors accumulated in branches may have to be stacked to be  | 
371  |  |      * provided back when it's sure they affect validation.  | 
372  |  |      */  | 
373  |  |     xmlRelaxNGValidErrorPtr err;        /* Last error */  | 
374  |  |     int errNr;                  /* Depth of the error stack */  | 
375  |  |     int errMax;                 /* Max depth of the error stack */  | 
376  |  |     xmlRelaxNGValidErrorPtr errTab;     /* stack of errors */  | 
377  |  |  | 
378  |  |     xmlRelaxNGValidStatePtr state;      /* the current validation state */  | 
379  |  |     xmlRelaxNGStatesPtr states; /* the accumulated state list */  | 
380  |  |  | 
381  |  |     xmlRelaxNGStatesPtr freeState;      /* the pool of free valid states */  | 
382  |  |     int freeStatesNr;  | 
383  |  |     int freeStatesMax;  | 
384  |  |     xmlRelaxNGStatesPtr *freeStates;    /* the pool of free state groups */  | 
385  |  |  | 
386  |  |     /*  | 
387  |  |      * This is used for "progressive" validation  | 
388  |  |      */  | 
389  |  |     xmlRegExecCtxtPtr elem;     /* the current element regexp */  | 
390  |  |     int elemNr;                 /* the number of element validated */  | 
391  |  |     int elemMax;                /* the max depth of elements */  | 
392  |  |     xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */  | 
393  |  |     int pstate;                 /* progressive state */  | 
394  |  |     xmlNodePtr pnode;           /* the current node */  | 
395  |  |     xmlRelaxNGDefinePtr pdef;   /* the non-streamable definition */  | 
396  |  |     int perr;                   /* signal error in content model  | 
397  |  |                                  * outside the regexp */  | 
398  |  | };  | 
399  |  |  | 
400  |  | /**  | 
401  |  |  * xmlRelaxNGInclude:  | 
402  |  |  *  | 
403  |  |  * Structure associated to a RelaxNGs document element  | 
404  |  |  */  | 
405  |  | struct _xmlRelaxNGInclude { | 
406  |  |     xmlRelaxNGIncludePtr next;  /* keep a chain of includes */  | 
407  |  |     xmlChar *href;              /* the normalized href value */  | 
408  |  |     xmlDocPtr doc;              /* the associated XML document */  | 
409  |  |     xmlRelaxNGDefinePtr content;        /* the definitions */  | 
410  |  |     xmlRelaxNGPtr schema;       /* the schema */  | 
411  |  | };  | 
412  |  |  | 
413  |  | /**  | 
414  |  |  * xmlRelaxNGDocument:  | 
415  |  |  *  | 
416  |  |  * Structure associated to a RelaxNGs document element  | 
417  |  |  */  | 
418  |  | struct _xmlRelaxNGDocument { | 
419  |  |     xmlRelaxNGDocumentPtr next; /* keep a chain of documents */  | 
420  |  |     xmlChar *href;              /* the normalized href value */  | 
421  |  |     xmlDocPtr doc;              /* the associated XML document */  | 
422  |  |     xmlRelaxNGDefinePtr content;        /* the definitions */  | 
423  |  |     xmlRelaxNGPtr schema;       /* the schema */  | 
424  |  |     int externalRef;            /* 1 if an external ref */  | 
425  |  | };  | 
426  |  |  | 
427  |  |  | 
428  |  | /************************************************************************  | 
429  |  |  *                  *  | 
430  |  |  *    Some factorized error routines        *  | 
431  |  |  *                  *  | 
432  |  |  ************************************************************************/  | 
433  |  |  | 
434  |  | /**  | 
435  |  |  * xmlRngPErrMemory:  | 
436  |  |  * @ctxt:  an Relax-NG parser context  | 
437  |  |  * @extra:  extra information  | 
438  |  |  *  | 
439  |  |  * Handle a redefinition of attribute error  | 
440  |  |  */  | 
441  |  | static void  | 
442  |  | xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)  | 
443  | 0  | { | 
444  | 0  |     xmlStructuredErrorFunc schannel = NULL;  | 
445  | 0  |     xmlGenericErrorFunc channel = NULL;  | 
446  | 0  |     void *data = NULL;  | 
447  |  | 
  | 
448  | 0  |     if (ctxt != NULL) { | 
449  | 0  |         if (ctxt->serror != NULL)  | 
450  | 0  |       schannel = ctxt->serror;  | 
451  | 0  |   else  | 
452  | 0  |       channel = ctxt->error;  | 
453  | 0  |         data = ctxt->userData;  | 
454  | 0  |         ctxt->nbErrors++;  | 
455  | 0  |     }  | 
456  | 0  |     if (extra)  | 
457  | 0  |         __xmlRaiseError(schannel, channel, data,  | 
458  | 0  |                         NULL, NULL, XML_FROM_RELAXNGP,  | 
459  | 0  |                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,  | 
460  | 0  |                         NULL, NULL, 0, 0,  | 
461  | 0  |                         "Memory allocation failed : %s\n", extra);  | 
462  | 0  |     else  | 
463  | 0  |         __xmlRaiseError(schannel, channel, data,  | 
464  | 0  |                         NULL, NULL, XML_FROM_RELAXNGP,  | 
465  | 0  |                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,  | 
466  | 0  |                         NULL, NULL, 0, 0, "Memory allocation failed\n");  | 
467  | 0  | }  | 
468  |  |  | 
469  |  | /**  | 
470  |  |  * xmlRngVErrMemory:  | 
471  |  |  * @ctxt:  a Relax-NG validation context  | 
472  |  |  * @extra:  extra information  | 
473  |  |  *  | 
474  |  |  * Handle a redefinition of attribute error  | 
475  |  |  */  | 
476  |  | static void  | 
477  |  | xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)  | 
478  | 0  | { | 
479  | 0  |     xmlStructuredErrorFunc schannel = NULL;  | 
480  | 0  |     xmlGenericErrorFunc channel = NULL;  | 
481  | 0  |     void *data = NULL;  | 
482  |  | 
  | 
483  | 0  |     if (ctxt != NULL) { | 
484  | 0  |         if (ctxt->serror != NULL)  | 
485  | 0  |       schannel = ctxt->serror;  | 
486  | 0  |   else  | 
487  | 0  |       channel = ctxt->error;  | 
488  | 0  |         data = ctxt->userData;  | 
489  | 0  |         ctxt->nbErrors++;  | 
490  | 0  |     }  | 
491  | 0  |     if (extra)  | 
492  | 0  |         __xmlRaiseError(schannel, channel, data,  | 
493  | 0  |                         NULL, NULL, XML_FROM_RELAXNGV,  | 
494  | 0  |                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,  | 
495  | 0  |                         NULL, NULL, 0, 0,  | 
496  | 0  |                         "Memory allocation failed : %s\n", extra);  | 
497  | 0  |     else  | 
498  | 0  |         __xmlRaiseError(schannel, channel, data,  | 
499  | 0  |                         NULL, NULL, XML_FROM_RELAXNGV,  | 
500  | 0  |                         XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,  | 
501  | 0  |                         NULL, NULL, 0, 0, "Memory allocation failed\n");  | 
502  | 0  | }  | 
503  |  |  | 
504  |  | /**  | 
505  |  |  * xmlRngPErr:  | 
506  |  |  * @ctxt:  a Relax-NG parser context  | 
507  |  |  * @node:  the node raising the error  | 
508  |  |  * @error:  the error code  | 
509  |  |  * @msg:  message  | 
510  |  |  * @str1:  extra info  | 
511  |  |  * @str2:  extra info  | 
512  |  |  *  | 
513  |  |  * Handle a Relax NG Parsing error  | 
514  |  |  */  | 
515  |  | static void LIBXML_ATTR_FORMAT(4,0)  | 
516  |  | xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,  | 
517  |  |            const char *msg, const xmlChar * str1, const xmlChar * str2)  | 
518  | 0  | { | 
519  | 0  |     xmlStructuredErrorFunc schannel = NULL;  | 
520  | 0  |     xmlGenericErrorFunc channel = NULL;  | 
521  | 0  |     void *data = NULL;  | 
522  |  | 
  | 
523  | 0  |     if (ctxt != NULL) { | 
524  | 0  |         if (ctxt->serror != NULL)  | 
525  | 0  |       schannel = ctxt->serror;  | 
526  | 0  |   else  | 
527  | 0  |       channel = ctxt->error;  | 
528  | 0  |         data = ctxt->userData;  | 
529  | 0  |         ctxt->nbErrors++;  | 
530  | 0  |     }  | 
531  | 0  |     __xmlRaiseError(schannel, channel, data,  | 
532  | 0  |                     NULL, node, XML_FROM_RELAXNGP,  | 
533  | 0  |                     error, XML_ERR_ERROR, NULL, 0,  | 
534  | 0  |                     (const char *) str1, (const char *) str2, NULL, 0, 0,  | 
535  | 0  |                     msg, str1, str2);  | 
536  | 0  | }  | 
537  |  |  | 
538  |  | /**  | 
539  |  |  * xmlRngVErr:  | 
540  |  |  * @ctxt:  a Relax-NG validation context  | 
541  |  |  * @node:  the node raising the error  | 
542  |  |  * @error:  the error code  | 
543  |  |  * @msg:  message  | 
544  |  |  * @str1:  extra info  | 
545  |  |  * @str2:  extra info  | 
546  |  |  *  | 
547  |  |  * Handle a Relax NG Validation error  | 
548  |  |  */  | 
549  |  | static void LIBXML_ATTR_FORMAT(4,0)  | 
550  |  | xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,  | 
551  |  |            const char *msg, const xmlChar * str1, const xmlChar * str2)  | 
552  | 0  | { | 
553  | 0  |     xmlStructuredErrorFunc schannel = NULL;  | 
554  | 0  |     xmlGenericErrorFunc channel = NULL;  | 
555  | 0  |     void *data = NULL;  | 
556  |  | 
  | 
557  | 0  |     if (ctxt != NULL) { | 
558  | 0  |         if (ctxt->serror != NULL)  | 
559  | 0  |       schannel = ctxt->serror;  | 
560  | 0  |   else  | 
561  | 0  |       channel = ctxt->error;  | 
562  | 0  |         data = ctxt->userData;  | 
563  | 0  |         ctxt->nbErrors++;  | 
564  | 0  |     }  | 
565  | 0  |     __xmlRaiseError(schannel, channel, data,  | 
566  | 0  |                     NULL, node, XML_FROM_RELAXNGV,  | 
567  | 0  |                     error, XML_ERR_ERROR, NULL, 0,  | 
568  | 0  |                     (const char *) str1, (const char *) str2, NULL, 0, 0,  | 
569  | 0  |                     msg, str1, str2);  | 
570  | 0  | }  | 
571  |  |  | 
572  |  | /************************************************************************  | 
573  |  |  *                  *  | 
574  |  |  *    Preliminary type checking interfaces      *  | 
575  |  |  *                  *  | 
576  |  |  ************************************************************************/  | 
577  |  |  | 
578  |  | /**  | 
579  |  |  * xmlRelaxNGTypeHave:  | 
580  |  |  * @data:  data needed for the library  | 
581  |  |  * @type:  the type name  | 
582  |  |  * @value:  the value to check  | 
583  |  |  *  | 
584  |  |  * Function provided by a type library to check if a type is exported  | 
585  |  |  *  | 
586  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
587  |  |  */  | 
588  |  | typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar * type);  | 
589  |  |  | 
590  |  | /**  | 
591  |  |  * xmlRelaxNGTypeCheck:  | 
592  |  |  * @data:  data needed for the library  | 
593  |  |  * @type:  the type name  | 
594  |  |  * @value:  the value to check  | 
595  |  |  * @result:  place to store the result if needed  | 
596  |  |  *  | 
597  |  |  * Function provided by a type library to check if a value match a type  | 
598  |  |  *  | 
599  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
600  |  |  */  | 
601  |  | typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar * type,  | 
602  |  |                                     const xmlChar * value, void **result,  | 
603  |  |                                     xmlNodePtr node);  | 
604  |  |  | 
605  |  | /**  | 
606  |  |  * xmlRelaxNGFacetCheck:  | 
607  |  |  * @data:  data needed for the library  | 
608  |  |  * @type:  the type name  | 
609  |  |  * @facet:  the facet name  | 
610  |  |  * @val:  the facet value  | 
611  |  |  * @strval:  the string value  | 
612  |  |  * @value:  the value to check  | 
613  |  |  *  | 
614  |  |  * Function provided by a type library to check a value facet  | 
615  |  |  *  | 
616  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
617  |  |  */  | 
618  |  | typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar * type,  | 
619  |  |                                      const xmlChar * facet,  | 
620  |  |                                      const xmlChar * val,  | 
621  |  |                                      const xmlChar * strval, void *value);  | 
622  |  |  | 
623  |  | /**  | 
624  |  |  * xmlRelaxNGTypeFree:  | 
625  |  |  * @data:  data needed for the library  | 
626  |  |  * @result:  the value to free  | 
627  |  |  *  | 
628  |  |  * Function provided by a type library to free a returned result  | 
629  |  |  */  | 
630  |  | typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);  | 
631  |  |  | 
632  |  | /**  | 
633  |  |  * xmlRelaxNGTypeCompare:  | 
634  |  |  * @data:  data needed for the library  | 
635  |  |  * @type:  the type name  | 
636  |  |  * @value1:  the first value  | 
637  |  |  * @value2:  the second value  | 
638  |  |  *  | 
639  |  |  * Function provided by a type library to compare two values accordingly  | 
640  |  |  * to a type.  | 
641  |  |  *  | 
642  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
643  |  |  */  | 
644  |  | typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar * type,  | 
645  |  |                                       const xmlChar * value1,  | 
646  |  |                                       xmlNodePtr ctxt1,  | 
647  |  |                                       void *comp1,  | 
648  |  |                                       const xmlChar * value2,  | 
649  |  |                                       xmlNodePtr ctxt2);  | 
650  |  | typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;  | 
651  |  | typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;  | 
652  |  | struct _xmlRelaxNGTypeLibrary { | 
653  |  |     const xmlChar *namespace;   /* the datatypeLibrary value */  | 
654  |  |     void *data;                 /* data needed for the library */  | 
655  |  |     xmlRelaxNGTypeHave have;    /* the export function */  | 
656  |  |     xmlRelaxNGTypeCheck check;  /* the checking function */  | 
657  |  |     xmlRelaxNGTypeCompare comp; /* the compare function */  | 
658  |  |     xmlRelaxNGFacetCheck facet; /* the facet check function */  | 
659  |  |     xmlRelaxNGTypeFree freef;   /* the freeing function */  | 
660  |  | };  | 
661  |  |  | 
662  |  | /************************************************************************  | 
663  |  |  *                  *  | 
664  |  |  *      Allocation functions        *  | 
665  |  |  *                  *  | 
666  |  |  ************************************************************************/  | 
667  |  | static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);  | 
668  |  | static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);  | 
669  |  | static void xmlRelaxNGNormExtSpace(xmlChar * value);  | 
670  |  | static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema);  | 
671  |  | static int xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt  | 
672  |  |                                      ATTRIBUTE_UNUSED,  | 
673  |  |                                      xmlRelaxNGValidStatePtr state1,  | 
674  |  |                                      xmlRelaxNGValidStatePtr state2);  | 
675  |  | static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,  | 
676  |  |                                      xmlRelaxNGValidStatePtr state);  | 
677  |  |  | 
678  |  | /**  | 
679  |  |  * xmlRelaxNGFreeDocument:  | 
680  |  |  * @docu:  a document structure  | 
681  |  |  *  | 
682  |  |  * Deallocate a RelaxNG document structure.  | 
683  |  |  */  | 
684  |  | static void  | 
685  |  | xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu)  | 
686  | 0  | { | 
687  | 0  |     if (docu == NULL)  | 
688  | 0  |         return;  | 
689  |  |  | 
690  | 0  |     if (docu->href != NULL)  | 
691  | 0  |         xmlFree(docu->href);  | 
692  | 0  |     if (docu->doc != NULL)  | 
693  | 0  |         xmlFreeDoc(docu->doc);  | 
694  | 0  |     if (docu->schema != NULL)  | 
695  | 0  |         xmlRelaxNGFreeInnerSchema(docu->schema);  | 
696  | 0  |     xmlFree(docu);  | 
697  | 0  | }  | 
698  |  |  | 
699  |  | /**  | 
700  |  |  * xmlRelaxNGFreeDocumentList:  | 
701  |  |  * @docu:  a list of  document structure  | 
702  |  |  *  | 
703  |  |  * Deallocate a RelaxNG document structures.  | 
704  |  |  */  | 
705  |  | static void  | 
706  |  | xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu)  | 
707  | 0  | { | 
708  | 0  |     xmlRelaxNGDocumentPtr next;  | 
709  |  | 
  | 
710  | 0  |     while (docu != NULL) { | 
711  | 0  |         next = docu->next;  | 
712  | 0  |         xmlRelaxNGFreeDocument(docu);  | 
713  | 0  |         docu = next;  | 
714  | 0  |     }  | 
715  | 0  | }  | 
716  |  |  | 
717  |  | /**  | 
718  |  |  * xmlRelaxNGFreeInclude:  | 
719  |  |  * @incl:  a include structure  | 
720  |  |  *  | 
721  |  |  * Deallocate a RelaxNG include structure.  | 
722  |  |  */  | 
723  |  | static void  | 
724  |  | xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl)  | 
725  | 0  | { | 
726  | 0  |     if (incl == NULL)  | 
727  | 0  |         return;  | 
728  |  |  | 
729  | 0  |     if (incl->href != NULL)  | 
730  | 0  |         xmlFree(incl->href);  | 
731  | 0  |     if (incl->doc != NULL)  | 
732  | 0  |         xmlFreeDoc(incl->doc);  | 
733  | 0  |     if (incl->schema != NULL)  | 
734  | 0  |         xmlRelaxNGFree(incl->schema);  | 
735  | 0  |     xmlFree(incl);  | 
736  | 0  | }  | 
737  |  |  | 
738  |  | /**  | 
739  |  |  * xmlRelaxNGFreeIncludeList:  | 
740  |  |  * @incl:  a include structure list  | 
741  |  |  *  | 
742  |  |  * Deallocate a RelaxNG include structure.  | 
743  |  |  */  | 
744  |  | static void  | 
745  |  | xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl)  | 
746  | 0  | { | 
747  | 0  |     xmlRelaxNGIncludePtr next;  | 
748  |  | 
  | 
749  | 0  |     while (incl != NULL) { | 
750  | 0  |         next = incl->next;  | 
751  | 0  |         xmlRelaxNGFreeInclude(incl);  | 
752  | 0  |         incl = next;  | 
753  | 0  |     }  | 
754  | 0  | }  | 
755  |  |  | 
756  |  | /**  | 
757  |  |  * xmlRelaxNGNewRelaxNG:  | 
758  |  |  * @ctxt:  a Relax-NG validation context (optional)  | 
759  |  |  *  | 
760  |  |  * Allocate a new RelaxNG structure.  | 
761  |  |  *  | 
762  |  |  * Returns the newly allocated structure or NULL in case or error  | 
763  |  |  */  | 
764  |  | static xmlRelaxNGPtr  | 
765  |  | xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)  | 
766  | 0  | { | 
767  | 0  |     xmlRelaxNGPtr ret;  | 
768  |  | 
  | 
769  | 0  |     ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));  | 
770  | 0  |     if (ret == NULL) { | 
771  | 0  |         xmlRngPErrMemory(ctxt, NULL);  | 
772  | 0  |         return (NULL);  | 
773  | 0  |     }  | 
774  | 0  |     memset(ret, 0, sizeof(xmlRelaxNG));  | 
775  |  | 
  | 
776  | 0  |     return (ret);  | 
777  | 0  | }  | 
778  |  |  | 
779  |  | /**  | 
780  |  |  * xmlRelaxNGFreeInnerSchema:  | 
781  |  |  * @schema:  a schema structure  | 
782  |  |  *  | 
783  |  |  * Deallocate a RelaxNG schema structure.  | 
784  |  |  */  | 
785  |  | static void  | 
786  |  | xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema)  | 
787  | 0  | { | 
788  | 0  |     if (schema == NULL)  | 
789  | 0  |         return;  | 
790  |  |  | 
791  | 0  |     if (schema->doc != NULL)  | 
792  | 0  |         xmlFreeDoc(schema->doc);  | 
793  | 0  |     if (schema->defTab != NULL) { | 
794  | 0  |         int i;  | 
795  |  | 
  | 
796  | 0  |         for (i = 0; i < schema->defNr; i++)  | 
797  | 0  |             xmlRelaxNGFreeDefine(schema->defTab[i]);  | 
798  | 0  |         xmlFree(schema->defTab);  | 
799  | 0  |     }  | 
800  |  | 
  | 
801  | 0  |     xmlFree(schema);  | 
802  | 0  | }  | 
803  |  |  | 
804  |  | /**  | 
805  |  |  * xmlRelaxNGFree:  | 
806  |  |  * @schema:  a schema structure  | 
807  |  |  *  | 
808  |  |  * Deallocate a RelaxNG structure.  | 
809  |  |  */  | 
810  |  | void  | 
811  |  | xmlRelaxNGFree(xmlRelaxNGPtr schema)  | 
812  | 0  | { | 
813  | 0  |     if (schema == NULL)  | 
814  | 0  |         return;  | 
815  |  |  | 
816  | 0  |     if (schema->topgrammar != NULL)  | 
817  | 0  |         xmlRelaxNGFreeGrammar(schema->topgrammar);  | 
818  | 0  |     if (schema->doc != NULL)  | 
819  | 0  |         xmlFreeDoc(schema->doc);  | 
820  | 0  |     if (schema->documents != NULL)  | 
821  | 0  |         xmlRelaxNGFreeDocumentList(schema->documents);  | 
822  | 0  |     if (schema->includes != NULL)  | 
823  | 0  |         xmlRelaxNGFreeIncludeList(schema->includes);  | 
824  | 0  |     if (schema->defTab != NULL) { | 
825  | 0  |         int i;  | 
826  |  | 
  | 
827  | 0  |         for (i = 0; i < schema->defNr; i++)  | 
828  | 0  |             xmlRelaxNGFreeDefine(schema->defTab[i]);  | 
829  | 0  |         xmlFree(schema->defTab);  | 
830  | 0  |     }  | 
831  |  | 
  | 
832  | 0  |     xmlFree(schema);  | 
833  | 0  | }  | 
834  |  |  | 
835  |  | /**  | 
836  |  |  * xmlRelaxNGNewGrammar:  | 
837  |  |  * @ctxt:  a Relax-NG validation context (optional)  | 
838  |  |  *  | 
839  |  |  * Allocate a new RelaxNG grammar.  | 
840  |  |  *  | 
841  |  |  * Returns the newly allocated structure or NULL in case or error  | 
842  |  |  */  | 
843  |  | static xmlRelaxNGGrammarPtr  | 
844  |  | xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)  | 
845  | 0  | { | 
846  | 0  |     xmlRelaxNGGrammarPtr ret;  | 
847  |  | 
  | 
848  | 0  |     ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));  | 
849  | 0  |     if (ret == NULL) { | 
850  | 0  |         xmlRngPErrMemory(ctxt, NULL);  | 
851  | 0  |         return (NULL);  | 
852  | 0  |     }  | 
853  | 0  |     memset(ret, 0, sizeof(xmlRelaxNGGrammar));  | 
854  |  | 
  | 
855  | 0  |     return (ret);  | 
856  | 0  | }  | 
857  |  |  | 
858  |  | /**  | 
859  |  |  * xmlRelaxNGFreeGrammar:  | 
860  |  |  * @grammar:  a grammar structure  | 
861  |  |  *  | 
862  |  |  * Deallocate a RelaxNG grammar structure.  | 
863  |  |  */  | 
864  |  | static void  | 
865  |  | xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar)  | 
866  | 0  | { | 
867  | 0  |     if (grammar == NULL)  | 
868  | 0  |         return;  | 
869  |  |  | 
870  | 0  |     if (grammar->children != NULL) { | 
871  | 0  |         xmlRelaxNGFreeGrammar(grammar->children);  | 
872  | 0  |     }  | 
873  | 0  |     if (grammar->next != NULL) { | 
874  | 0  |         xmlRelaxNGFreeGrammar(grammar->next);  | 
875  | 0  |     }  | 
876  | 0  |     if (grammar->refs != NULL) { | 
877  | 0  |         xmlHashFree(grammar->refs, NULL);  | 
878  | 0  |     }  | 
879  | 0  |     if (grammar->defs != NULL) { | 
880  | 0  |         xmlHashFree(grammar->defs, NULL);  | 
881  | 0  |     }  | 
882  |  | 
  | 
883  | 0  |     xmlFree(grammar);  | 
884  | 0  | }  | 
885  |  |  | 
886  |  | /**  | 
887  |  |  * xmlRelaxNGNewDefine:  | 
888  |  |  * @ctxt:  a Relax-NG validation context  | 
889  |  |  * @node:  the node in the input document.  | 
890  |  |  *  | 
891  |  |  * Allocate a new RelaxNG define.  | 
892  |  |  *  | 
893  |  |  * Returns the newly allocated structure or NULL in case or error  | 
894  |  |  */  | 
895  |  | static xmlRelaxNGDefinePtr  | 
896  |  | xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
897  | 0  | { | 
898  | 0  |     xmlRelaxNGDefinePtr ret;  | 
899  |  | 
  | 
900  | 0  |     if (ctxt->defMax == 0) { | 
901  | 0  |         ctxt->defMax = 16;  | 
902  | 0  |         ctxt->defNr = 0;  | 
903  | 0  |         ctxt->defTab = (xmlRelaxNGDefinePtr *)  | 
904  | 0  |             xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));  | 
905  | 0  |         if (ctxt->defTab == NULL) { | 
906  | 0  |             xmlRngPErrMemory(ctxt, "allocating define\n");  | 
907  | 0  |             return (NULL);  | 
908  | 0  |         }  | 
909  | 0  |     } else if (ctxt->defMax <= ctxt->defNr) { | 
910  | 0  |         xmlRelaxNGDefinePtr *tmp;  | 
911  |  | 
  | 
912  | 0  |         ctxt->defMax *= 2;  | 
913  | 0  |         tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,  | 
914  | 0  |                                                  ctxt->defMax *  | 
915  | 0  |                                                  sizeof  | 
916  | 0  |                                                  (xmlRelaxNGDefinePtr));  | 
917  | 0  |         if (tmp == NULL) { | 
918  | 0  |             xmlRngPErrMemory(ctxt, "allocating define\n");  | 
919  | 0  |             return (NULL);  | 
920  | 0  |         }  | 
921  | 0  |         ctxt->defTab = tmp;  | 
922  | 0  |     }  | 
923  | 0  |     ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));  | 
924  | 0  |     if (ret == NULL) { | 
925  | 0  |         xmlRngPErrMemory(ctxt, "allocating define\n");  | 
926  | 0  |         return (NULL);  | 
927  | 0  |     }  | 
928  | 0  |     memset(ret, 0, sizeof(xmlRelaxNGDefine));  | 
929  | 0  |     ctxt->defTab[ctxt->defNr++] = ret;  | 
930  | 0  |     ret->node = node;  | 
931  | 0  |     ret->depth = -1;  | 
932  | 0  |     return (ret);  | 
933  | 0  | }  | 
934  |  |  | 
935  |  | /**  | 
936  |  |  * xmlRelaxNGFreePartition:  | 
937  |  |  * @partitions:  a partition set structure  | 
938  |  |  *  | 
939  |  |  * Deallocate RelaxNG partition set structures.  | 
940  |  |  */  | 
941  |  | static void  | 
942  |  | xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions)  | 
943  | 0  | { | 
944  | 0  |     xmlRelaxNGInterleaveGroupPtr group;  | 
945  | 0  |     int j;  | 
946  |  | 
  | 
947  | 0  |     if (partitions != NULL) { | 
948  | 0  |         if (partitions->groups != NULL) { | 
949  | 0  |             for (j = 0; j < partitions->nbgroups; j++) { | 
950  | 0  |                 group = partitions->groups[j];  | 
951  | 0  |                 if (group != NULL) { | 
952  | 0  |                     if (group->defs != NULL)  | 
953  | 0  |                         xmlFree(group->defs);  | 
954  | 0  |                     if (group->attrs != NULL)  | 
955  | 0  |                         xmlFree(group->attrs);  | 
956  | 0  |                     xmlFree(group);  | 
957  | 0  |                 }  | 
958  | 0  |             }  | 
959  | 0  |             xmlFree(partitions->groups);  | 
960  | 0  |         }  | 
961  | 0  |         if (partitions->triage != NULL) { | 
962  | 0  |             xmlHashFree(partitions->triage, NULL);  | 
963  | 0  |         }  | 
964  | 0  |         xmlFree(partitions);  | 
965  | 0  |     }  | 
966  | 0  | }  | 
967  |  |  | 
968  |  | /**  | 
969  |  |  * xmlRelaxNGFreeDefine:  | 
970  |  |  * @define:  a define structure  | 
971  |  |  *  | 
972  |  |  * Deallocate a RelaxNG define structure.  | 
973  |  |  */  | 
974  |  | static void  | 
975  |  | xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define)  | 
976  | 0  | { | 
977  | 0  |     if (define == NULL)  | 
978  | 0  |         return;  | 
979  |  |  | 
980  | 0  |     if ((define->type == XML_RELAXNG_VALUE) && (define->attrs != NULL)) { | 
981  | 0  |         xmlRelaxNGTypeLibraryPtr lib;  | 
982  |  | 
  | 
983  | 0  |         lib = (xmlRelaxNGTypeLibraryPtr) define->data;  | 
984  | 0  |         if ((lib != NULL) && (lib->freef != NULL))  | 
985  | 0  |             lib->freef(lib->data, (void *) define->attrs);  | 
986  | 0  |     }  | 
987  | 0  |     if ((define->data != NULL) && (define->type == XML_RELAXNG_INTERLEAVE))  | 
988  | 0  |         xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);  | 
989  | 0  |     if ((define->data != NULL) && (define->type == XML_RELAXNG_CHOICE))  | 
990  | 0  |         xmlHashFree((xmlHashTablePtr) define->data, NULL);  | 
991  | 0  |     if (define->name != NULL)  | 
992  | 0  |         xmlFree(define->name);  | 
993  | 0  |     if (define->ns != NULL)  | 
994  | 0  |         xmlFree(define->ns);  | 
995  | 0  |     if (define->value != NULL)  | 
996  | 0  |         xmlFree(define->value);  | 
997  | 0  |     if (define->contModel != NULL)  | 
998  | 0  |         xmlRegFreeRegexp(define->contModel);  | 
999  | 0  |     xmlFree(define);  | 
1000  | 0  | }  | 
1001  |  |  | 
1002  |  | /**  | 
1003  |  |  * xmlRelaxNGNewStates:  | 
1004  |  |  * @ctxt:  a Relax-NG validation context  | 
1005  |  |  * @size:  the default size for the container  | 
1006  |  |  *  | 
1007  |  |  * Allocate a new RelaxNG validation state container  | 
1008  |  |  *  | 
1009  |  |  * Returns the newly allocated structure or NULL in case or error  | 
1010  |  |  */  | 
1011  |  | static xmlRelaxNGStatesPtr  | 
1012  |  | xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)  | 
1013  | 0  | { | 
1014  | 0  |     xmlRelaxNGStatesPtr ret;  | 
1015  |  | 
  | 
1016  | 0  |     if ((ctxt != NULL) &&  | 
1017  | 0  |         (ctxt->freeStates != NULL) && (ctxt->freeStatesNr > 0)) { | 
1018  | 0  |         ctxt->freeStatesNr--;  | 
1019  | 0  |         ret = ctxt->freeStates[ctxt->freeStatesNr];  | 
1020  | 0  |         ret->nbState = 0;  | 
1021  | 0  |         return (ret);  | 
1022  | 0  |     }  | 
1023  | 0  |     if (size < 16)  | 
1024  | 0  |         size = 16;  | 
1025  |  | 
  | 
1026  | 0  |     ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +  | 
1027  | 0  |                                           (size -  | 
1028  | 0  |                                            1) *  | 
1029  | 0  |                                           sizeof(xmlRelaxNGValidStatePtr));  | 
1030  | 0  |     if (ret == NULL) { | 
1031  | 0  |         xmlRngVErrMemory(ctxt, "allocating states\n");  | 
1032  | 0  |         return (NULL);  | 
1033  | 0  |     }  | 
1034  | 0  |     ret->nbState = 0;  | 
1035  | 0  |     ret->maxState = size;  | 
1036  | 0  |     ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc((size) *  | 
1037  | 0  |                                                           sizeof  | 
1038  | 0  |                                                           (xmlRelaxNGValidStatePtr));  | 
1039  | 0  |     if (ret->tabState == NULL) { | 
1040  | 0  |         xmlRngVErrMemory(ctxt, "allocating states\n");  | 
1041  | 0  |         xmlFree(ret);  | 
1042  | 0  |         return (NULL);  | 
1043  | 0  |     }  | 
1044  | 0  |     return (ret);  | 
1045  | 0  | }  | 
1046  |  |  | 
1047  |  | /**  | 
1048  |  |  * xmlRelaxNGAddStateUniq:  | 
1049  |  |  * @ctxt:  a Relax-NG validation context  | 
1050  |  |  * @states:  the states container  | 
1051  |  |  * @state:  the validation state  | 
1052  |  |  *  | 
1053  |  |  * Add a RelaxNG validation state to the container without checking  | 
1054  |  |  * for unicity.  | 
1055  |  |  *  | 
1056  |  |  * Return 1 in case of success and 0 if this is a duplicate and -1 on error  | 
1057  |  |  */  | 
1058  |  | static int  | 
1059  |  | xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,  | 
1060  |  |                         xmlRelaxNGStatesPtr states,  | 
1061  |  |                         xmlRelaxNGValidStatePtr state)  | 
1062  | 0  | { | 
1063  | 0  |     if (state == NULL) { | 
1064  | 0  |         return (-1);  | 
1065  | 0  |     }  | 
1066  | 0  |     if (states->nbState >= states->maxState) { | 
1067  | 0  |         xmlRelaxNGValidStatePtr *tmp;  | 
1068  | 0  |         int size;  | 
1069  |  | 
  | 
1070  | 0  |         size = states->maxState * 2;  | 
1071  | 0  |         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,  | 
1072  | 0  |                                                      (size) *  | 
1073  | 0  |                                                      sizeof  | 
1074  | 0  |                                                      (xmlRelaxNGValidStatePtr));  | 
1075  | 0  |         if (tmp == NULL) { | 
1076  | 0  |             xmlRngVErrMemory(ctxt, "adding states\n");  | 
1077  | 0  |             return (-1);  | 
1078  | 0  |         }  | 
1079  | 0  |         states->tabState = tmp;  | 
1080  | 0  |         states->maxState = size;  | 
1081  | 0  |     }  | 
1082  | 0  |     states->tabState[states->nbState++] = state;  | 
1083  | 0  |     return (1);  | 
1084  | 0  | }  | 
1085  |  |  | 
1086  |  | /**  | 
1087  |  |  * xmlRelaxNGAddState:  | 
1088  |  |  * @ctxt:  a Relax-NG validation context  | 
1089  |  |  * @states:  the states container  | 
1090  |  |  * @state:  the validation state  | 
1091  |  |  *  | 
1092  |  |  * Add a RelaxNG validation state to the container  | 
1093  |  |  *  | 
1094  |  |  * Return 1 in case of success and 0 if this is a duplicate and -1 on error  | 
1095  |  |  */  | 
1096  |  | static int  | 
1097  |  | xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt,  | 
1098  |  |                     xmlRelaxNGStatesPtr states,  | 
1099  |  |                     xmlRelaxNGValidStatePtr state)  | 
1100  | 0  | { | 
1101  | 0  |     int i;  | 
1102  |  | 
  | 
1103  | 0  |     if (state == NULL || states == NULL) { | 
1104  | 0  |         return (-1);  | 
1105  | 0  |     }  | 
1106  | 0  |     if (states->nbState >= states->maxState) { | 
1107  | 0  |         xmlRelaxNGValidStatePtr *tmp;  | 
1108  | 0  |         int size;  | 
1109  |  | 
  | 
1110  | 0  |         size = states->maxState * 2;  | 
1111  | 0  |         tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,  | 
1112  | 0  |                                                      (size) *  | 
1113  | 0  |                                                      sizeof  | 
1114  | 0  |                                                      (xmlRelaxNGValidStatePtr));  | 
1115  | 0  |         if (tmp == NULL) { | 
1116  | 0  |             xmlRngVErrMemory(ctxt, "adding states\n");  | 
1117  | 0  |             return (-1);  | 
1118  | 0  |         }  | 
1119  | 0  |         states->tabState = tmp;  | 
1120  | 0  |         states->maxState = size;  | 
1121  | 0  |     }  | 
1122  | 0  |     for (i = 0; i < states->nbState; i++) { | 
1123  | 0  |         if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) { | 
1124  | 0  |             xmlRelaxNGFreeValidState(ctxt, state);  | 
1125  | 0  |             return (0);  | 
1126  | 0  |         }  | 
1127  | 0  |     }  | 
1128  | 0  |     states->tabState[states->nbState++] = state;  | 
1129  | 0  |     return (1);  | 
1130  | 0  | }  | 
1131  |  |  | 
1132  |  | /**  | 
1133  |  |  * xmlRelaxNGFreeStates:  | 
1134  |  |  * @ctxt:  a Relax-NG validation context  | 
1135  |  |  * @states:  the container  | 
1136  |  |  *  | 
1137  |  |  * Free a RelaxNG validation state container  | 
1138  |  |  */  | 
1139  |  | static void  | 
1140  |  | xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,  | 
1141  |  |                      xmlRelaxNGStatesPtr states)  | 
1142  | 0  | { | 
1143  | 0  |     if (states == NULL)  | 
1144  | 0  |         return;  | 
1145  | 0  |     if ((ctxt != NULL) && (ctxt->freeStates == NULL)) { | 
1146  | 0  |         ctxt->freeStatesMax = 40;  | 
1147  | 0  |         ctxt->freeStatesNr = 0;  | 
1148  | 0  |         ctxt->freeStates = (xmlRelaxNGStatesPtr *)  | 
1149  | 0  |             xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));  | 
1150  | 0  |         if (ctxt->freeStates == NULL) { | 
1151  | 0  |             xmlRngVErrMemory(ctxt, "storing states\n");  | 
1152  | 0  |         }  | 
1153  | 0  |     } else if ((ctxt != NULL)  | 
1154  | 0  |                && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) { | 
1155  | 0  |         xmlRelaxNGStatesPtr *tmp;  | 
1156  |  | 
  | 
1157  | 0  |         tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates,  | 
1158  | 0  |                                                  2 * ctxt->freeStatesMax *  | 
1159  | 0  |                                                  sizeof  | 
1160  | 0  |                                                  (xmlRelaxNGStatesPtr));  | 
1161  | 0  |         if (tmp == NULL) { | 
1162  | 0  |             xmlRngVErrMemory(ctxt, "storing states\n");  | 
1163  | 0  |             xmlFree(states->tabState);  | 
1164  | 0  |             xmlFree(states);  | 
1165  | 0  |             return;  | 
1166  | 0  |         }  | 
1167  | 0  |         ctxt->freeStates = tmp;  | 
1168  | 0  |         ctxt->freeStatesMax *= 2;  | 
1169  | 0  |     }  | 
1170  | 0  |     if ((ctxt == NULL) || (ctxt->freeStates == NULL)) { | 
1171  | 0  |         xmlFree(states->tabState);  | 
1172  | 0  |         xmlFree(states);  | 
1173  | 0  |     } else { | 
1174  | 0  |         ctxt->freeStates[ctxt->freeStatesNr++] = states;  | 
1175  | 0  |     }  | 
1176  | 0  | }  | 
1177  |  |  | 
1178  |  | /**  | 
1179  |  |  * xmlRelaxNGNewValidState:  | 
1180  |  |  * @ctxt:  a Relax-NG validation context  | 
1181  |  |  * @node:  the current node or NULL for the document  | 
1182  |  |  *  | 
1183  |  |  * Allocate a new RelaxNG validation state  | 
1184  |  |  *  | 
1185  |  |  * Returns the newly allocated structure or NULL in case or error  | 
1186  |  |  */  | 
1187  |  | static xmlRelaxNGValidStatePtr  | 
1188  |  | xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)  | 
1189  | 0  | { | 
1190  | 0  |     xmlRelaxNGValidStatePtr ret;  | 
1191  | 0  |     xmlAttrPtr attr;  | 
1192  | 0  |     xmlAttrPtr attrs[MAX_ATTR];  | 
1193  | 0  |     int nbAttrs = 0;  | 
1194  | 0  |     xmlNodePtr root = NULL;  | 
1195  |  | 
  | 
1196  | 0  |     if (node == NULL) { | 
1197  | 0  |         root = xmlDocGetRootElement(ctxt->doc);  | 
1198  | 0  |         if (root == NULL)  | 
1199  | 0  |             return (NULL);  | 
1200  | 0  |     } else { | 
1201  | 0  |         attr = node->properties;  | 
1202  | 0  |         while (attr != NULL) { | 
1203  | 0  |             if (nbAttrs < MAX_ATTR)  | 
1204  | 0  |                 attrs[nbAttrs++] = attr;  | 
1205  | 0  |             else  | 
1206  | 0  |                 nbAttrs++;  | 
1207  | 0  |             attr = attr->next;  | 
1208  | 0  |         }  | 
1209  | 0  |     }  | 
1210  | 0  |     if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) { | 
1211  | 0  |         ctxt->freeState->nbState--;  | 
1212  | 0  |         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];  | 
1213  | 0  |     } else { | 
1214  | 0  |         ret =  | 
1215  | 0  |             (xmlRelaxNGValidStatePtr)  | 
1216  | 0  |             xmlMalloc(sizeof(xmlRelaxNGValidState));  | 
1217  | 0  |         if (ret == NULL) { | 
1218  | 0  |             xmlRngVErrMemory(ctxt, "allocating states\n");  | 
1219  | 0  |             return (NULL);  | 
1220  | 0  |         }  | 
1221  | 0  |         memset(ret, 0, sizeof(xmlRelaxNGValidState));  | 
1222  | 0  |     }  | 
1223  | 0  |     ret->value = NULL;  | 
1224  | 0  |     ret->endvalue = NULL;  | 
1225  | 0  |     if (node == NULL) { | 
1226  | 0  |         ret->node = (xmlNodePtr) ctxt->doc;  | 
1227  | 0  |         ret->seq = root;  | 
1228  | 0  |     } else { | 
1229  | 0  |         ret->node = node;  | 
1230  | 0  |         ret->seq = node->children;  | 
1231  | 0  |     }  | 
1232  | 0  |     ret->nbAttrs = 0;  | 
1233  | 0  |     if (nbAttrs > 0) { | 
1234  | 0  |         if (ret->attrs == NULL) { | 
1235  | 0  |             if (nbAttrs < 4)  | 
1236  | 0  |                 ret->maxAttrs = 4;  | 
1237  | 0  |             else  | 
1238  | 0  |                 ret->maxAttrs = nbAttrs;  | 
1239  | 0  |             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *  | 
1240  | 0  |                                                   sizeof(xmlAttrPtr));  | 
1241  | 0  |             if (ret->attrs == NULL) { | 
1242  | 0  |                 xmlRngVErrMemory(ctxt, "allocating states\n");  | 
1243  | 0  |                 return (ret);  | 
1244  | 0  |             }  | 
1245  | 0  |         } else if (ret->maxAttrs < nbAttrs) { | 
1246  | 0  |             xmlAttrPtr *tmp;  | 
1247  |  | 
  | 
1248  | 0  |             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *  | 
1249  | 0  |                                             sizeof(xmlAttrPtr));  | 
1250  | 0  |             if (tmp == NULL) { | 
1251  | 0  |                 xmlRngVErrMemory(ctxt, "allocating states\n");  | 
1252  | 0  |                 return (ret);  | 
1253  | 0  |             }  | 
1254  | 0  |             ret->attrs = tmp;  | 
1255  | 0  |             ret->maxAttrs = nbAttrs;  | 
1256  | 0  |         }  | 
1257  | 0  |         ret->nbAttrs = nbAttrs;  | 
1258  | 0  |         if (nbAttrs < MAX_ATTR) { | 
1259  | 0  |             memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs);  | 
1260  | 0  |         } else { | 
1261  | 0  |             attr = node->properties;  | 
1262  | 0  |             nbAttrs = 0;  | 
1263  | 0  |             while (attr != NULL) { | 
1264  | 0  |                 ret->attrs[nbAttrs++] = attr;  | 
1265  | 0  |                 attr = attr->next;  | 
1266  | 0  |             }  | 
1267  | 0  |         }  | 
1268  | 0  |     }  | 
1269  | 0  |     ret->nbAttrLeft = ret->nbAttrs;  | 
1270  | 0  |     return (ret);  | 
1271  | 0  | }  | 
1272  |  |  | 
1273  |  | /**  | 
1274  |  |  * xmlRelaxNGCopyValidState:  | 
1275  |  |  * @ctxt:  a Relax-NG validation context  | 
1276  |  |  * @state:  a validation state  | 
1277  |  |  *  | 
1278  |  |  * Copy the validation state  | 
1279  |  |  *  | 
1280  |  |  * Returns the newly allocated structure or NULL in case or error  | 
1281  |  |  */  | 
1282  |  | static xmlRelaxNGValidStatePtr  | 
1283  |  | xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,  | 
1284  |  |                          xmlRelaxNGValidStatePtr state)  | 
1285  | 0  | { | 
1286  | 0  |     xmlRelaxNGValidStatePtr ret;  | 
1287  | 0  |     unsigned int maxAttrs;  | 
1288  | 0  |     xmlAttrPtr *attrs;  | 
1289  |  | 
  | 
1290  | 0  |     if (state == NULL)  | 
1291  | 0  |         return (NULL);  | 
1292  | 0  |     if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) { | 
1293  | 0  |         ctxt->freeState->nbState--;  | 
1294  | 0  |         ret = ctxt->freeState->tabState[ctxt->freeState->nbState];  | 
1295  | 0  |     } else { | 
1296  | 0  |         ret =  | 
1297  | 0  |             (xmlRelaxNGValidStatePtr)  | 
1298  | 0  |             xmlMalloc(sizeof(xmlRelaxNGValidState));  | 
1299  | 0  |         if (ret == NULL) { | 
1300  | 0  |             xmlRngVErrMemory(ctxt, "allocating states\n");  | 
1301  | 0  |             return (NULL);  | 
1302  | 0  |         }  | 
1303  | 0  |         memset(ret, 0, sizeof(xmlRelaxNGValidState));  | 
1304  | 0  |     }  | 
1305  | 0  |     attrs = ret->attrs;  | 
1306  | 0  |     maxAttrs = ret->maxAttrs;  | 
1307  | 0  |     memcpy(ret, state, sizeof(xmlRelaxNGValidState));  | 
1308  | 0  |     ret->attrs = attrs;  | 
1309  | 0  |     ret->maxAttrs = maxAttrs;  | 
1310  | 0  |     if (state->nbAttrs > 0) { | 
1311  | 0  |         if (ret->attrs == NULL) { | 
1312  | 0  |             ret->maxAttrs = state->maxAttrs;  | 
1313  | 0  |             ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *  | 
1314  | 0  |                                                   sizeof(xmlAttrPtr));  | 
1315  | 0  |             if (ret->attrs == NULL) { | 
1316  | 0  |                 xmlRngVErrMemory(ctxt, "allocating states\n");  | 
1317  | 0  |                 ret->nbAttrs = 0;  | 
1318  | 0  |                 return (ret);  | 
1319  | 0  |             }  | 
1320  | 0  |         } else if (ret->maxAttrs < state->nbAttrs) { | 
1321  | 0  |             xmlAttrPtr *tmp;  | 
1322  |  | 
  | 
1323  | 0  |             tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *  | 
1324  | 0  |                                             sizeof(xmlAttrPtr));  | 
1325  | 0  |             if (tmp == NULL) { | 
1326  | 0  |                 xmlRngVErrMemory(ctxt, "allocating states\n");  | 
1327  | 0  |                 ret->nbAttrs = 0;  | 
1328  | 0  |                 return (ret);  | 
1329  | 0  |             }  | 
1330  | 0  |             ret->maxAttrs = state->maxAttrs;  | 
1331  | 0  |             ret->attrs = tmp;  | 
1332  | 0  |         }  | 
1333  | 0  |         memcpy(ret->attrs, state->attrs,  | 
1334  | 0  |                state->nbAttrs * sizeof(xmlAttrPtr));  | 
1335  | 0  |     }  | 
1336  | 0  |     return (ret);  | 
1337  | 0  | }  | 
1338  |  |  | 
1339  |  | /**  | 
1340  |  |  * xmlRelaxNGEqualValidState:  | 
1341  |  |  * @ctxt:  a Relax-NG validation context  | 
1342  |  |  * @state1:  a validation state  | 
1343  |  |  * @state2:  a validation state  | 
1344  |  |  *  | 
1345  |  |  * Compare the validation states for equality  | 
1346  |  |  *  | 
1347  |  |  * Returns 1 if equal, 0 otherwise  | 
1348  |  |  */  | 
1349  |  | static int  | 
1350  |  | xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,  | 
1351  |  |                           xmlRelaxNGValidStatePtr state1,  | 
1352  |  |                           xmlRelaxNGValidStatePtr state2)  | 
1353  | 0  | { | 
1354  | 0  |     int i;  | 
1355  |  | 
  | 
1356  | 0  |     if ((state1 == NULL) || (state2 == NULL))  | 
1357  | 0  |         return (0);  | 
1358  | 0  |     if (state1 == state2)  | 
1359  | 0  |         return (1);  | 
1360  | 0  |     if (state1->node != state2->node)  | 
1361  | 0  |         return (0);  | 
1362  | 0  |     if (state1->seq != state2->seq)  | 
1363  | 0  |         return (0);  | 
1364  | 0  |     if (state1->nbAttrLeft != state2->nbAttrLeft)  | 
1365  | 0  |         return (0);  | 
1366  | 0  |     if (state1->nbAttrs != state2->nbAttrs)  | 
1367  | 0  |         return (0);  | 
1368  | 0  |     if (state1->endvalue != state2->endvalue)  | 
1369  | 0  |         return (0);  | 
1370  | 0  |     if ((state1->value != state2->value) &&  | 
1371  | 0  |         (!xmlStrEqual(state1->value, state2->value)))  | 
1372  | 0  |         return (0);  | 
1373  | 0  |     for (i = 0; i < state1->nbAttrs; i++) { | 
1374  | 0  |         if (state1->attrs[i] != state2->attrs[i])  | 
1375  | 0  |             return (0);  | 
1376  | 0  |     }  | 
1377  | 0  |     return (1);  | 
1378  | 0  | }  | 
1379  |  |  | 
1380  |  | /**  | 
1381  |  |  * xmlRelaxNGFreeValidState:  | 
1382  |  |  * @state:  a validation state structure  | 
1383  |  |  *  | 
1384  |  |  * Deallocate a RelaxNG validation state structure.  | 
1385  |  |  */  | 
1386  |  | static void  | 
1387  |  | xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,  | 
1388  |  |                          xmlRelaxNGValidStatePtr state)  | 
1389  | 0  | { | 
1390  | 0  |     if (state == NULL)  | 
1391  | 0  |         return;  | 
1392  |  |  | 
1393  | 0  |     if ((ctxt != NULL) && (ctxt->freeState == NULL)) { | 
1394  | 0  |         ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40);  | 
1395  | 0  |     }  | 
1396  | 0  |     if ((ctxt == NULL) || (ctxt->freeState == NULL)) { | 
1397  | 0  |         if (state->attrs != NULL)  | 
1398  | 0  |             xmlFree(state->attrs);  | 
1399  | 0  |         xmlFree(state);  | 
1400  | 0  |     } else { | 
1401  | 0  |         xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state);  | 
1402  | 0  |     }  | 
1403  | 0  | }  | 
1404  |  |  | 
1405  |  | /************************************************************************  | 
1406  |  |  *                  *  | 
1407  |  |  *      Semi internal functions       *  | 
1408  |  |  *                  *  | 
1409  |  |  ************************************************************************/  | 
1410  |  |  | 
1411  |  | /**  | 
1412  |  |  * xmlRelaxParserSetFlag:  | 
1413  |  |  * @ctxt: a RelaxNG parser context  | 
1414  |  |  * @flags: a set of flags values  | 
1415  |  |  *  | 
1416  |  |  * Semi private function used to pass information to a parser context  | 
1417  |  |  * which are a combination of xmlRelaxNGParserFlag .  | 
1418  |  |  *  | 
1419  |  |  * Returns 0 if success and -1 in case of error  | 
1420  |  |  */  | 
1421  |  | int  | 
1422  |  | xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags)  | 
1423  | 0  | { | 
1424  | 0  |     if (ctxt == NULL) return(-1);  | 
1425  | 0  |     if (flags & XML_RELAXNGP_FREE_DOC) { | 
1426  | 0  |         ctxt->crng |= XML_RELAXNGP_FREE_DOC;  | 
1427  | 0  |   flags -= XML_RELAXNGP_FREE_DOC;  | 
1428  | 0  |     }  | 
1429  | 0  |     if (flags & XML_RELAXNGP_CRNG) { | 
1430  | 0  |         ctxt->crng |= XML_RELAXNGP_CRNG;  | 
1431  | 0  |   flags -= XML_RELAXNGP_CRNG;  | 
1432  | 0  |     }  | 
1433  | 0  |     if (flags != 0) return(-1);  | 
1434  | 0  |     return(0);  | 
1435  | 0  | }  | 
1436  |  |  | 
1437  |  | /************************************************************************  | 
1438  |  |  *                  *  | 
1439  |  |  *      Document functions        *  | 
1440  |  |  *                  *  | 
1441  |  |  ************************************************************************/  | 
1442  |  | static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,  | 
1443  |  |                                       xmlDocPtr doc);  | 
1444  |  |  | 
1445  |  | /**  | 
1446  |  |  * xmlRelaxNGIncludePush:  | 
1447  |  |  * @ctxt:  the parser context  | 
1448  |  |  * @value:  the element doc  | 
1449  |  |  *  | 
1450  |  |  * Pushes a new include on top of the include stack  | 
1451  |  |  *  | 
1452  |  |  * Returns 0 in case of error, the index in the stack otherwise  | 
1453  |  |  */  | 
1454  |  | static int  | 
1455  |  | xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,  | 
1456  |  |                       xmlRelaxNGIncludePtr value)  | 
1457  | 0  | { | 
1458  | 0  |     if (ctxt->incTab == NULL) { | 
1459  | 0  |         ctxt->incMax = 4;  | 
1460  | 0  |         ctxt->incNr = 0;  | 
1461  | 0  |         ctxt->incTab =  | 
1462  | 0  |             (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *  | 
1463  | 0  |                                                sizeof(ctxt->incTab[0]));  | 
1464  | 0  |         if (ctxt->incTab == NULL) { | 
1465  | 0  |             xmlRngPErrMemory(ctxt, "allocating include\n");  | 
1466  | 0  |             return (0);  | 
1467  | 0  |         }  | 
1468  | 0  |     }  | 
1469  | 0  |     if (ctxt->incNr >= ctxt->incMax) { | 
1470  | 0  |         ctxt->incMax *= 2;  | 
1471  | 0  |         ctxt->incTab =  | 
1472  | 0  |             (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,  | 
1473  | 0  |                                                 ctxt->incMax *  | 
1474  | 0  |                                                 sizeof(ctxt->incTab[0]));  | 
1475  | 0  |         if (ctxt->incTab == NULL) { | 
1476  | 0  |             xmlRngPErrMemory(ctxt, "allocating include\n");  | 
1477  | 0  |             return (0);  | 
1478  | 0  |         }  | 
1479  | 0  |     }  | 
1480  | 0  |     ctxt->incTab[ctxt->incNr] = value;  | 
1481  | 0  |     ctxt->inc = value;  | 
1482  | 0  |     return (ctxt->incNr++);  | 
1483  | 0  | }  | 
1484  |  |  | 
1485  |  | /**  | 
1486  |  |  * xmlRelaxNGIncludePop:  | 
1487  |  |  * @ctxt: the parser context  | 
1488  |  |  *  | 
1489  |  |  * Pops the top include from the include stack  | 
1490  |  |  *  | 
1491  |  |  * Returns the include just removed  | 
1492  |  |  */  | 
1493  |  | static xmlRelaxNGIncludePtr  | 
1494  |  | xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt)  | 
1495  | 0  | { | 
1496  | 0  |     xmlRelaxNGIncludePtr ret;  | 
1497  |  | 
  | 
1498  | 0  |     if (ctxt->incNr <= 0)  | 
1499  | 0  |         return (NULL);  | 
1500  | 0  |     ctxt->incNr--;  | 
1501  | 0  |     if (ctxt->incNr > 0)  | 
1502  | 0  |         ctxt->inc = ctxt->incTab[ctxt->incNr - 1];  | 
1503  | 0  |     else  | 
1504  | 0  |         ctxt->inc = NULL;  | 
1505  | 0  |     ret = ctxt->incTab[ctxt->incNr];  | 
1506  | 0  |     ctxt->incTab[ctxt->incNr] = NULL;  | 
1507  | 0  |     return (ret);  | 
1508  | 0  | }  | 
1509  |  |  | 
1510  |  | /**  | 
1511  |  |  * xmlRelaxNGRemoveRedefine:  | 
1512  |  |  * @ctxt: the parser context  | 
1513  |  |  * @URL:  the normalized URL  | 
1514  |  |  * @target:  the included target  | 
1515  |  |  * @name:  the define name to eliminate  | 
1516  |  |  *  | 
1517  |  |  * Applies the elimination algorithm of 4.7  | 
1518  |  |  *  | 
1519  |  |  * Returns 0 in case of error, 1 in case of success.  | 
1520  |  |  */  | 
1521  |  | static int  | 
1522  |  | xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,  | 
1523  |  |                          const xmlChar * URL ATTRIBUTE_UNUSED,  | 
1524  |  |                          xmlNodePtr target, const xmlChar * name)  | 
1525  | 0  | { | 
1526  | 0  |     int found = 0;  | 
1527  | 0  |     xmlNodePtr tmp, tmp2;  | 
1528  | 0  |     xmlChar *name2;  | 
1529  |  | 
  | 
1530  |  | #ifdef DEBUG_INCLUDE  | 
1531  |  |     if (name == NULL)  | 
1532  |  |         xmlGenericError(xmlGenericErrorContext,  | 
1533  |  |                         "Elimination of <include> start from %s\n", URL);  | 
1534  |  |     else  | 
1535  |  |         xmlGenericError(xmlGenericErrorContext,  | 
1536  |  |                         "Elimination of <include> define %s from %s\n",  | 
1537  |  |                         name, URL);  | 
1538  |  | #endif  | 
1539  | 0  |     tmp = target;  | 
1540  | 0  |     while (tmp != NULL) { | 
1541  | 0  |         tmp2 = tmp->next;  | 
1542  | 0  |         if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) { | 
1543  | 0  |             found = 1;  | 
1544  | 0  |             xmlUnlinkNode(tmp);  | 
1545  | 0  |             xmlFreeNode(tmp);  | 
1546  | 0  |         } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) { | 
1547  | 0  |             name2 = xmlGetProp(tmp, BAD_CAST "name");  | 
1548  | 0  |             xmlRelaxNGNormExtSpace(name2);  | 
1549  | 0  |             if (name2 != NULL) { | 
1550  | 0  |                 if (xmlStrEqual(name, name2)) { | 
1551  | 0  |                     found = 1;  | 
1552  | 0  |                     xmlUnlinkNode(tmp);  | 
1553  | 0  |                     xmlFreeNode(tmp);  | 
1554  | 0  |                 }  | 
1555  | 0  |                 xmlFree(name2);  | 
1556  | 0  |             }  | 
1557  | 0  |         } else if (IS_RELAXNG(tmp, "include")) { | 
1558  | 0  |             xmlChar *href = NULL;  | 
1559  | 0  |             xmlRelaxNGDocumentPtr inc = tmp->psvi;  | 
1560  |  | 
  | 
1561  | 0  |             if ((inc != NULL) && (inc->doc != NULL) &&  | 
1562  | 0  |                 (inc->doc->children != NULL)) { | 
1563  |  | 
  | 
1564  | 0  |                 if (xmlStrEqual  | 
1565  | 0  |                     (inc->doc->children->name, BAD_CAST "grammar")) { | 
1566  |  | #ifdef DEBUG_INCLUDE  | 
1567  |  |                     href = xmlGetProp(tmp, BAD_CAST "href");  | 
1568  |  | #endif  | 
1569  | 0  |                     if (xmlRelaxNGRemoveRedefine(ctxt, href,  | 
1570  | 0  |                                                  xmlDocGetRootElement(inc->doc)->children,  | 
1571  | 0  |                                                  name) == 1) { | 
1572  | 0  |                         found = 1;  | 
1573  | 0  |                     }  | 
1574  |  | #ifdef DEBUG_INCLUDE  | 
1575  |  |                     if (href != NULL)  | 
1576  |  |                         xmlFree(href);  | 
1577  |  | #endif  | 
1578  | 0  |                 }  | 
1579  | 0  |             }  | 
1580  | 0  |             if (xmlRelaxNGRemoveRedefine(ctxt, URL, tmp->children, name) == 1) { | 
1581  | 0  |                 found = 1;  | 
1582  | 0  |             }  | 
1583  | 0  |         }  | 
1584  | 0  |         tmp = tmp2;  | 
1585  | 0  |     }  | 
1586  | 0  |     return (found);  | 
1587  | 0  | }  | 
1588  |  |  | 
1589  |  | /**  | 
1590  |  |  * xmlRelaxNGLoadInclude:  | 
1591  |  |  * @ctxt: the parser context  | 
1592  |  |  * @URL:  the normalized URL  | 
1593  |  |  * @node: the include node.  | 
1594  |  |  * @ns:  the namespace passed from the context.  | 
1595  |  |  *  | 
1596  |  |  * First lookup if the document is already loaded into the parser context,  | 
1597  |  |  * check against recursion. If not found the resource is loaded and  | 
1598  |  |  * the content is preprocessed before being returned back to the caller.  | 
1599  |  |  *  | 
1600  |  |  * Returns the xmlRelaxNGIncludePtr or NULL in case of error  | 
1601  |  |  */  | 
1602  |  | static xmlRelaxNGIncludePtr  | 
1603  |  | xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,  | 
1604  |  |                       xmlNodePtr node, const xmlChar * ns)  | 
1605  | 0  | { | 
1606  | 0  |     xmlRelaxNGIncludePtr ret = NULL;  | 
1607  | 0  |     xmlDocPtr doc;  | 
1608  | 0  |     int i;  | 
1609  | 0  |     xmlNodePtr root, cur;  | 
1610  |  | 
  | 
1611  |  | #ifdef DEBUG_INCLUDE  | 
1612  |  |     xmlGenericError(xmlGenericErrorContext,  | 
1613  |  |                     "xmlRelaxNGLoadInclude(%s)\n", URL);  | 
1614  |  | #endif  | 
1615  |  |  | 
1616  |  |     /*  | 
1617  |  |      * check against recursion in the stack  | 
1618  |  |      */  | 
1619  | 0  |     for (i = 0; i < ctxt->incNr; i++) { | 
1620  | 0  |         if (xmlStrEqual(ctxt->incTab[i]->href, URL)) { | 
1621  | 0  |             xmlRngPErr(ctxt, NULL, XML_RNGP_INCLUDE_RECURSE,  | 
1622  | 0  |                        "Detected an Include recursion for %s\n", URL,  | 
1623  | 0  |                        NULL);  | 
1624  | 0  |             return (NULL);  | 
1625  | 0  |         }  | 
1626  | 0  |     }  | 
1627  |  |  | 
1628  |  |     /*  | 
1629  |  |      * load the document  | 
1630  |  |      */  | 
1631  | 0  |     doc = xmlReadFile((const char *) URL,NULL,0);  | 
1632  | 0  |     if (doc == NULL) { | 
1633  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR,  | 
1634  | 0  |                    "xmlRelaxNG: could not load %s\n", URL, NULL);  | 
1635  | 0  |         return (NULL);  | 
1636  | 0  |     }  | 
1637  |  | #ifdef DEBUG_INCLUDE  | 
1638  |  |     xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL);  | 
1639  |  | #endif  | 
1640  |  |  | 
1641  |  |     /*  | 
1642  |  |      * Allocate the document structures and register it first.  | 
1643  |  |      */  | 
1644  | 0  |     ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));  | 
1645  | 0  |     if (ret == NULL) { | 
1646  | 0  |         xmlRngPErrMemory(ctxt, "allocating include\n");  | 
1647  | 0  |         xmlFreeDoc(doc);  | 
1648  | 0  |         return (NULL);  | 
1649  | 0  |     }  | 
1650  | 0  |     memset(ret, 0, sizeof(xmlRelaxNGInclude));  | 
1651  | 0  |     ret->doc = doc;  | 
1652  | 0  |     ret->href = xmlStrdup(URL);  | 
1653  | 0  |     ret->next = ctxt->includes;  | 
1654  | 0  |     ctxt->includes = ret;  | 
1655  |  |  | 
1656  |  |     /*  | 
1657  |  |      * transmit the ns if needed  | 
1658  |  |      */  | 
1659  | 0  |     if (ns != NULL) { | 
1660  | 0  |         root = xmlDocGetRootElement(doc);  | 
1661  | 0  |         if (root != NULL) { | 
1662  | 0  |             if (xmlHasProp(root, BAD_CAST "ns") == NULL) { | 
1663  | 0  |                 xmlSetProp(root, BAD_CAST "ns", ns);  | 
1664  | 0  |             }  | 
1665  | 0  |         }  | 
1666  | 0  |     }  | 
1667  |  |  | 
1668  |  |     /*  | 
1669  |  |      * push it on the stack  | 
1670  |  |      */  | 
1671  | 0  |     xmlRelaxNGIncludePush(ctxt, ret);  | 
1672  |  |  | 
1673  |  |     /*  | 
1674  |  |      * Some preprocessing of the document content, this include recursing  | 
1675  |  |      * in the include stack.  | 
1676  |  |      */  | 
1677  |  | #ifdef DEBUG_INCLUDE  | 
1678  |  |     xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL);  | 
1679  |  | #endif  | 
1680  |  | 
  | 
1681  | 0  |     doc = xmlRelaxNGCleanupDoc(ctxt, doc);  | 
1682  | 0  |     if (doc == NULL) { | 
1683  | 0  |         ctxt->inc = NULL;  | 
1684  | 0  |         return (NULL);  | 
1685  | 0  |     }  | 
1686  |  |  | 
1687  |  |     /*  | 
1688  |  |      * Pop up the include from the stack  | 
1689  |  |      */  | 
1690  | 0  |     xmlRelaxNGIncludePop(ctxt);  | 
1691  |  | 
  | 
1692  |  | #ifdef DEBUG_INCLUDE  | 
1693  |  |     xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL);  | 
1694  |  | #endif  | 
1695  |  |     /*  | 
1696  |  |      * Check that the top element is a grammar  | 
1697  |  |      */  | 
1698  | 0  |     root = xmlDocGetRootElement(doc);  | 
1699  | 0  |     if (root == NULL) { | 
1700  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_EMPTY,  | 
1701  | 0  |                    "xmlRelaxNG: included document is empty %s\n", URL,  | 
1702  | 0  |                    NULL);  | 
1703  | 0  |         return (NULL);  | 
1704  | 0  |     }  | 
1705  | 0  |     if (!IS_RELAXNG(root, "grammar")) { | 
1706  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,  | 
1707  | 0  |                    "xmlRelaxNG: included document %s root is not a grammar\n",  | 
1708  | 0  |                    URL, NULL);  | 
1709  | 0  |         return (NULL);  | 
1710  | 0  |     }  | 
1711  |  |  | 
1712  |  |     /*  | 
1713  |  |      * Elimination of redefined rules in the include.  | 
1714  |  |      */  | 
1715  | 0  |     cur = node->children;  | 
1716  | 0  |     while (cur != NULL) { | 
1717  | 0  |         if (IS_RELAXNG(cur, "start")) { | 
1718  | 0  |             int found = 0;  | 
1719  |  | 
  | 
1720  | 0  |             found =  | 
1721  | 0  |                 xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);  | 
1722  | 0  |             if (!found) { | 
1723  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING,  | 
1724  | 0  |                            "xmlRelaxNG: include %s has a start but not the included grammar\n",  | 
1725  | 0  |                            URL, NULL);  | 
1726  | 0  |             }  | 
1727  | 0  |         } else if (IS_RELAXNG(cur, "define")) { | 
1728  | 0  |             xmlChar *name;  | 
1729  |  | 
  | 
1730  | 0  |             name = xmlGetProp(cur, BAD_CAST "name");  | 
1731  | 0  |             if (name == NULL) { | 
1732  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING,  | 
1733  | 0  |                            "xmlRelaxNG: include %s has define without name\n",  | 
1734  | 0  |                            URL, NULL);  | 
1735  | 0  |             } else { | 
1736  | 0  |                 int found;  | 
1737  |  | 
  | 
1738  | 0  |                 xmlRelaxNGNormExtSpace(name);  | 
1739  | 0  |                 found = xmlRelaxNGRemoveRedefine(ctxt, URL,  | 
1740  | 0  |                                                  root->children, name);  | 
1741  | 0  |                 if (!found) { | 
1742  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING,  | 
1743  | 0  |                                "xmlRelaxNG: include %s has a define %s but not the included grammar\n",  | 
1744  | 0  |                                URL, name);  | 
1745  | 0  |                 }  | 
1746  | 0  |                 xmlFree(name);  | 
1747  | 0  |             }  | 
1748  | 0  |         }  | 
1749  | 0  |         if (IS_RELAXNG(cur, "div") && cur->children != NULL) { | 
1750  | 0  |             cur = cur->children;  | 
1751  | 0  |         } else { | 
1752  | 0  |             if (cur->next != NULL) { | 
1753  | 0  |                 cur = cur->next;  | 
1754  | 0  |             } else { | 
1755  | 0  |                 while (cur->parent != node && cur->parent->next == NULL) { | 
1756  | 0  |                     cur = cur->parent;  | 
1757  | 0  |                 }  | 
1758  | 0  |                 cur = cur->parent != node ? cur->parent->next : NULL;  | 
1759  | 0  |             }  | 
1760  | 0  |         }  | 
1761  | 0  |     }  | 
1762  |  |  | 
1763  |  | 
  | 
1764  | 0  |     return (ret);  | 
1765  | 0  | }  | 
1766  |  |  | 
1767  |  | /**  | 
1768  |  |  * xmlRelaxNGValidErrorPush:  | 
1769  |  |  * @ctxt:  the validation context  | 
1770  |  |  * @err:  the error code  | 
1771  |  |  * @arg1:  the first string argument  | 
1772  |  |  * @arg2:  the second string argument  | 
1773  |  |  * @dup:  arg need to be duplicated  | 
1774  |  |  *  | 
1775  |  |  * Pushes a new error on top of the error stack  | 
1776  |  |  *  | 
1777  |  |  * Returns 0 in case of error, the index in the stack otherwise  | 
1778  |  |  */  | 
1779  |  | static int  | 
1780  |  | xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,  | 
1781  |  |                          xmlRelaxNGValidErr err, const xmlChar * arg1,  | 
1782  |  |                          const xmlChar * arg2, int dup)  | 
1783  | 0  | { | 
1784  | 0  |     xmlRelaxNGValidErrorPtr cur;  | 
1785  |  | 
  | 
1786  |  | #ifdef DEBUG_ERROR  | 
1787  |  |     xmlGenericError(xmlGenericErrorContext,  | 
1788  |  |                     "Pushing error %d at %d on stack\n", err, ctxt->errNr);  | 
1789  |  | #endif  | 
1790  | 0  |     if (ctxt->errTab == NULL) { | 
1791  | 0  |         ctxt->errMax = 8;  | 
1792  | 0  |         ctxt->errNr = 0;  | 
1793  | 0  |         ctxt->errTab =  | 
1794  | 0  |             (xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax *  | 
1795  | 0  |                                                 sizeof  | 
1796  | 0  |                                                 (xmlRelaxNGValidError));  | 
1797  | 0  |         if (ctxt->errTab == NULL) { | 
1798  | 0  |             xmlRngVErrMemory(ctxt, "pushing error\n");  | 
1799  | 0  |             return (0);  | 
1800  | 0  |         }  | 
1801  | 0  |         ctxt->err = NULL;  | 
1802  | 0  |     }  | 
1803  | 0  |     if (ctxt->errNr >= ctxt->errMax) { | 
1804  | 0  |         ctxt->errMax *= 2;  | 
1805  | 0  |         ctxt->errTab =  | 
1806  | 0  |             (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,  | 
1807  | 0  |                                                  ctxt->errMax *  | 
1808  | 0  |                                                  sizeof  | 
1809  | 0  |                                                  (xmlRelaxNGValidError));  | 
1810  | 0  |         if (ctxt->errTab == NULL) { | 
1811  | 0  |             xmlRngVErrMemory(ctxt, "pushing error\n");  | 
1812  | 0  |             return (0);  | 
1813  | 0  |         }  | 
1814  | 0  |         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];  | 
1815  | 0  |     }  | 
1816  | 0  |     if ((ctxt->err != NULL) && (ctxt->state != NULL) &&  | 
1817  | 0  |         (ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err))  | 
1818  | 0  |         return (ctxt->errNr);  | 
1819  | 0  |     cur = &ctxt->errTab[ctxt->errNr];  | 
1820  | 0  |     cur->err = err;  | 
1821  | 0  |     if (dup) { | 
1822  | 0  |         cur->arg1 = xmlStrdup(arg1);  | 
1823  | 0  |         cur->arg2 = xmlStrdup(arg2);  | 
1824  | 0  |         cur->flags = ERROR_IS_DUP;  | 
1825  | 0  |     } else { | 
1826  | 0  |         cur->arg1 = arg1;  | 
1827  | 0  |         cur->arg2 = arg2;  | 
1828  | 0  |         cur->flags = 0;  | 
1829  | 0  |     }  | 
1830  | 0  |     if (ctxt->state != NULL) { | 
1831  | 0  |         cur->node = ctxt->state->node;  | 
1832  | 0  |         cur->seq = ctxt->state->seq;  | 
1833  | 0  |     } else { | 
1834  | 0  |         cur->node = NULL;  | 
1835  | 0  |         cur->seq = NULL;  | 
1836  | 0  |     }  | 
1837  | 0  |     ctxt->err = cur;  | 
1838  | 0  |     return (ctxt->errNr++);  | 
1839  | 0  | }  | 
1840  |  |  | 
1841  |  | /**  | 
1842  |  |  * xmlRelaxNGValidErrorPop:  | 
1843  |  |  * @ctxt: the validation context  | 
1844  |  |  *  | 
1845  |  |  * Pops the top error from the error stack  | 
1846  |  |  */  | 
1847  |  | static void  | 
1848  |  | xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)  | 
1849  | 0  | { | 
1850  | 0  |     xmlRelaxNGValidErrorPtr cur;  | 
1851  |  | 
  | 
1852  | 0  |     if (ctxt->errNr <= 0) { | 
1853  | 0  |         ctxt->err = NULL;  | 
1854  | 0  |         return;  | 
1855  | 0  |     }  | 
1856  | 0  |     ctxt->errNr--;  | 
1857  | 0  |     if (ctxt->errNr > 0)  | 
1858  | 0  |         ctxt->err = &ctxt->errTab[ctxt->errNr - 1];  | 
1859  | 0  |     else  | 
1860  | 0  |         ctxt->err = NULL;  | 
1861  | 0  |     cur = &ctxt->errTab[ctxt->errNr];  | 
1862  | 0  |     if (cur->flags & ERROR_IS_DUP) { | 
1863  | 0  |         if (cur->arg1 != NULL)  | 
1864  | 0  |             xmlFree((xmlChar *) cur->arg1);  | 
1865  | 0  |         cur->arg1 = NULL;  | 
1866  | 0  |         if (cur->arg2 != NULL)  | 
1867  | 0  |             xmlFree((xmlChar *) cur->arg2);  | 
1868  | 0  |         cur->arg2 = NULL;  | 
1869  | 0  |         cur->flags = 0;  | 
1870  | 0  |     }  | 
1871  | 0  | }  | 
1872  |  |  | 
1873  |  | /**  | 
1874  |  |  * xmlRelaxNGDocumentPush:  | 
1875  |  |  * @ctxt:  the parser context  | 
1876  |  |  * @value:  the element doc  | 
1877  |  |  *  | 
1878  |  |  * Pushes a new doc on top of the doc stack  | 
1879  |  |  *  | 
1880  |  |  * Returns 0 in case of error, the index in the stack otherwise  | 
1881  |  |  */  | 
1882  |  | static int  | 
1883  |  | xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,  | 
1884  |  |                        xmlRelaxNGDocumentPtr value)  | 
1885  | 0  | { | 
1886  | 0  |     if (ctxt->docTab == NULL) { | 
1887  | 0  |         ctxt->docMax = 4;  | 
1888  | 0  |         ctxt->docNr = 0;  | 
1889  | 0  |         ctxt->docTab =  | 
1890  | 0  |             (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *  | 
1891  | 0  |                                                 sizeof(ctxt->docTab[0]));  | 
1892  | 0  |         if (ctxt->docTab == NULL) { | 
1893  | 0  |             xmlRngPErrMemory(ctxt, "adding document\n");  | 
1894  | 0  |             return (0);  | 
1895  | 0  |         }  | 
1896  | 0  |     }  | 
1897  | 0  |     if (ctxt->docNr >= ctxt->docMax) { | 
1898  | 0  |         ctxt->docMax *= 2;  | 
1899  | 0  |         ctxt->docTab =  | 
1900  | 0  |             (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,  | 
1901  | 0  |                                                  ctxt->docMax *  | 
1902  | 0  |                                                  sizeof(ctxt->docTab[0]));  | 
1903  | 0  |         if (ctxt->docTab == NULL) { | 
1904  | 0  |             xmlRngPErrMemory(ctxt, "adding document\n");  | 
1905  | 0  |             return (0);  | 
1906  | 0  |         }  | 
1907  | 0  |     }  | 
1908  | 0  |     ctxt->docTab[ctxt->docNr] = value;  | 
1909  | 0  |     ctxt->doc = value;  | 
1910  | 0  |     return (ctxt->docNr++);  | 
1911  | 0  | }  | 
1912  |  |  | 
1913  |  | /**  | 
1914  |  |  * xmlRelaxNGDocumentPop:  | 
1915  |  |  * @ctxt: the parser context  | 
1916  |  |  *  | 
1917  |  |  * Pops the top doc from the doc stack  | 
1918  |  |  *  | 
1919  |  |  * Returns the doc just removed  | 
1920  |  |  */  | 
1921  |  | static xmlRelaxNGDocumentPtr  | 
1922  |  | xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)  | 
1923  | 0  | { | 
1924  | 0  |     xmlRelaxNGDocumentPtr ret;  | 
1925  |  | 
  | 
1926  | 0  |     if (ctxt->docNr <= 0)  | 
1927  | 0  |         return (NULL);  | 
1928  | 0  |     ctxt->docNr--;  | 
1929  | 0  |     if (ctxt->docNr > 0)  | 
1930  | 0  |         ctxt->doc = ctxt->docTab[ctxt->docNr - 1];  | 
1931  | 0  |     else  | 
1932  | 0  |         ctxt->doc = NULL;  | 
1933  | 0  |     ret = ctxt->docTab[ctxt->docNr];  | 
1934  | 0  |     ctxt->docTab[ctxt->docNr] = NULL;  | 
1935  | 0  |     return (ret);  | 
1936  | 0  | }  | 
1937  |  |  | 
1938  |  | /**  | 
1939  |  |  * xmlRelaxNGLoadExternalRef:  | 
1940  |  |  * @ctxt: the parser context  | 
1941  |  |  * @URL:  the normalized URL  | 
1942  |  |  * @ns:  the inherited ns if any  | 
1943  |  |  *  | 
1944  |  |  * First lookup if the document is already loaded into the parser context,  | 
1945  |  |  * check against recursion. If not found the resource is loaded and  | 
1946  |  |  * the content is preprocessed before being returned back to the caller.  | 
1947  |  |  *  | 
1948  |  |  * Returns the xmlRelaxNGDocumentPtr or NULL in case of error  | 
1949  |  |  */  | 
1950  |  | static xmlRelaxNGDocumentPtr  | 
1951  |  | xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,  | 
1952  |  |                           const xmlChar * URL, const xmlChar * ns)  | 
1953  | 0  | { | 
1954  | 0  |     xmlRelaxNGDocumentPtr ret = NULL;  | 
1955  | 0  |     xmlDocPtr doc;  | 
1956  | 0  |     xmlNodePtr root;  | 
1957  | 0  |     int i;  | 
1958  |  |  | 
1959  |  |     /*  | 
1960  |  |      * check against recursion in the stack  | 
1961  |  |      */  | 
1962  | 0  |     for (i = 0; i < ctxt->docNr; i++) { | 
1963  | 0  |         if (xmlStrEqual(ctxt->docTab[i]->href, URL)) { | 
1964  | 0  |             xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE,  | 
1965  | 0  |                        "Detected an externalRef recursion for %s\n", URL,  | 
1966  | 0  |                        NULL);  | 
1967  | 0  |             return (NULL);  | 
1968  | 0  |         }  | 
1969  | 0  |     }  | 
1970  |  |  | 
1971  |  |     /*  | 
1972  |  |      * load the document  | 
1973  |  |      */  | 
1974  | 0  |     doc = xmlReadFile((const char *) URL,NULL,0);  | 
1975  | 0  |     if (doc == NULL) { | 
1976  | 0  |         xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,  | 
1977  | 0  |                    "xmlRelaxNG: could not load %s\n", URL, NULL);  | 
1978  | 0  |         return (NULL);  | 
1979  | 0  |     }  | 
1980  |  |  | 
1981  |  |     /*  | 
1982  |  |      * Allocate the document structures and register it first.  | 
1983  |  |      */  | 
1984  | 0  |     ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));  | 
1985  | 0  |     if (ret == NULL) { | 
1986  | 0  |         xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,  | 
1987  | 0  |                    "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);  | 
1988  | 0  |         xmlFreeDoc(doc);  | 
1989  | 0  |         return (NULL);  | 
1990  | 0  |     }  | 
1991  | 0  |     memset(ret, 0, sizeof(xmlRelaxNGDocument));  | 
1992  | 0  |     ret->doc = doc;  | 
1993  | 0  |     ret->href = xmlStrdup(URL);  | 
1994  | 0  |     ret->next = ctxt->documents;  | 
1995  | 0  |     ret->externalRef = 1;  | 
1996  | 0  |     ctxt->documents = ret;  | 
1997  |  |  | 
1998  |  |     /*  | 
1999  |  |      * transmit the ns if needed  | 
2000  |  |      */  | 
2001  | 0  |     if (ns != NULL) { | 
2002  | 0  |         root = xmlDocGetRootElement(doc);  | 
2003  | 0  |         if (root != NULL) { | 
2004  | 0  |             if (xmlHasProp(root, BAD_CAST "ns") == NULL) { | 
2005  | 0  |                 xmlSetProp(root, BAD_CAST "ns", ns);  | 
2006  | 0  |             }  | 
2007  | 0  |         }  | 
2008  | 0  |     }  | 
2009  |  |  | 
2010  |  |     /*  | 
2011  |  |      * push it on the stack and register it in the hash table  | 
2012  |  |      */  | 
2013  | 0  |     xmlRelaxNGDocumentPush(ctxt, ret);  | 
2014  |  |  | 
2015  |  |     /*  | 
2016  |  |      * Some preprocessing of the document content  | 
2017  |  |      */  | 
2018  | 0  |     doc = xmlRelaxNGCleanupDoc(ctxt, doc);  | 
2019  | 0  |     if (doc == NULL) { | 
2020  | 0  |         ctxt->doc = NULL;  | 
2021  | 0  |         return (NULL);  | 
2022  | 0  |     }  | 
2023  |  |  | 
2024  | 0  |     xmlRelaxNGDocumentPop(ctxt);  | 
2025  |  | 
  | 
2026  | 0  |     return (ret);  | 
2027  | 0  | }  | 
2028  |  |  | 
2029  |  | /************************************************************************  | 
2030  |  |  *                  *  | 
2031  |  |  *      Error functions         *  | 
2032  |  |  *                  *  | 
2033  |  |  ************************************************************************/  | 
2034  |  |  | 
2035  | 0  | #define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);  | 
2036  | 0  | #define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);  | 
2037  | 0  | #define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);  | 
2038  | 0  | #define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);  | 
2039  | 0  | #define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);  | 
2040  |  |  | 
2041  |  | static const char *  | 
2042  |  | xmlRelaxNGDefName(xmlRelaxNGDefinePtr def)  | 
2043  | 0  | { | 
2044  | 0  |     if (def == NULL)  | 
2045  | 0  |         return ("none"); | 
2046  | 0  |     switch (def->type) { | 
2047  | 0  |         case XML_RELAXNG_EMPTY:  | 
2048  | 0  |             return ("empty"); | 
2049  | 0  |         case XML_RELAXNG_NOT_ALLOWED:  | 
2050  | 0  |             return ("notAllowed"); | 
2051  | 0  |         case XML_RELAXNG_EXCEPT:  | 
2052  | 0  |             return ("except"); | 
2053  | 0  |         case XML_RELAXNG_TEXT:  | 
2054  | 0  |             return ("text"); | 
2055  | 0  |         case XML_RELAXNG_ELEMENT:  | 
2056  | 0  |             return ("element"); | 
2057  | 0  |         case XML_RELAXNG_DATATYPE:  | 
2058  | 0  |             return ("datatype"); | 
2059  | 0  |         case XML_RELAXNG_VALUE:  | 
2060  | 0  |             return ("value"); | 
2061  | 0  |         case XML_RELAXNG_LIST:  | 
2062  | 0  |             return ("list"); | 
2063  | 0  |         case XML_RELAXNG_ATTRIBUTE:  | 
2064  | 0  |             return ("attribute"); | 
2065  | 0  |         case XML_RELAXNG_DEF:  | 
2066  | 0  |             return ("def"); | 
2067  | 0  |         case XML_RELAXNG_REF:  | 
2068  | 0  |             return ("ref"); | 
2069  | 0  |         case XML_RELAXNG_EXTERNALREF:  | 
2070  | 0  |             return ("externalRef"); | 
2071  | 0  |         case XML_RELAXNG_PARENTREF:  | 
2072  | 0  |             return ("parentRef"); | 
2073  | 0  |         case XML_RELAXNG_OPTIONAL:  | 
2074  | 0  |             return ("optional"); | 
2075  | 0  |         case XML_RELAXNG_ZEROORMORE:  | 
2076  | 0  |             return ("zeroOrMore"); | 
2077  | 0  |         case XML_RELAXNG_ONEORMORE:  | 
2078  | 0  |             return ("oneOrMore"); | 
2079  | 0  |         case XML_RELAXNG_CHOICE:  | 
2080  | 0  |             return ("choice"); | 
2081  | 0  |         case XML_RELAXNG_GROUP:  | 
2082  | 0  |             return ("group"); | 
2083  | 0  |         case XML_RELAXNG_INTERLEAVE:  | 
2084  | 0  |             return ("interleave"); | 
2085  | 0  |         case XML_RELAXNG_START:  | 
2086  | 0  |             return ("start"); | 
2087  | 0  |         case XML_RELAXNG_NOOP:  | 
2088  | 0  |             return ("noop"); | 
2089  | 0  |         case XML_RELAXNG_PARAM:  | 
2090  | 0  |             return ("param"); | 
2091  | 0  |     }  | 
2092  | 0  |     return ("unknown"); | 
2093  | 0  | }  | 
2094  |  |  | 
2095  |  | /**  | 
2096  |  |  * xmlRelaxNGGetErrorString:  | 
2097  |  |  * @err:  the error code  | 
2098  |  |  * @arg1:  the first string argument  | 
2099  |  |  * @arg2:  the second string argument  | 
2100  |  |  *  | 
2101  |  |  * computes a formatted error string for the given error code and args  | 
2102  |  |  *  | 
2103  |  |  * Returns the error string, it must be deallocated by the caller  | 
2104  |  |  */  | 
2105  |  | static xmlChar *  | 
2106  |  | xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,  | 
2107  |  |                          const xmlChar * arg2)  | 
2108  | 0  | { | 
2109  | 0  |     char msg[1000];  | 
2110  | 0  |     xmlChar *result;  | 
2111  |  | 
  | 
2112  | 0  |     if (arg1 == NULL)  | 
2113  | 0  |         arg1 = BAD_CAST "";  | 
2114  | 0  |     if (arg2 == NULL)  | 
2115  | 0  |         arg2 = BAD_CAST "";  | 
2116  |  | 
  | 
2117  | 0  |     msg[0] = 0;  | 
2118  | 0  |     switch (err) { | 
2119  | 0  |         case XML_RELAXNG_OK:  | 
2120  | 0  |             return (NULL);  | 
2121  | 0  |         case XML_RELAXNG_ERR_MEMORY:  | 
2122  | 0  |             return (xmlCharStrdup("out of memory\n")); | 
2123  | 0  |         case XML_RELAXNG_ERR_TYPE:  | 
2124  | 0  |             snprintf(msg, 1000, "failed to validate type %s\n", arg1);  | 
2125  | 0  |             break;  | 
2126  | 0  |         case XML_RELAXNG_ERR_TYPEVAL:  | 
2127  | 0  |             snprintf(msg, 1000, "Type %s doesn't allow value '%s'\n", arg1,  | 
2128  | 0  |                      arg2);  | 
2129  | 0  |             break;  | 
2130  | 0  |         case XML_RELAXNG_ERR_DUPID:  | 
2131  | 0  |             snprintf(msg, 1000, "ID %s redefined\n", arg1);  | 
2132  | 0  |             break;  | 
2133  | 0  |         case XML_RELAXNG_ERR_TYPECMP:  | 
2134  | 0  |             snprintf(msg, 1000, "failed to compare type %s\n", arg1);  | 
2135  | 0  |             break;  | 
2136  | 0  |         case XML_RELAXNG_ERR_NOSTATE:  | 
2137  | 0  |             return (xmlCharStrdup("Internal error: no state\n")); | 
2138  | 0  |         case XML_RELAXNG_ERR_NODEFINE:  | 
2139  | 0  |             return (xmlCharStrdup("Internal error: no define\n")); | 
2140  | 0  |         case XML_RELAXNG_ERR_INTERNAL:  | 
2141  | 0  |             snprintf(msg, 1000, "Internal error: %s\n", arg1);  | 
2142  | 0  |             break;  | 
2143  | 0  |         case XML_RELAXNG_ERR_LISTEXTRA:  | 
2144  | 0  |             snprintf(msg, 1000, "Extra data in list: %s\n", arg1);  | 
2145  | 0  |             break;  | 
2146  | 0  |         case XML_RELAXNG_ERR_INTERNODATA:  | 
2147  | 0  |             return (xmlCharStrdup  | 
2148  | 0  |                     ("Internal: interleave block has no data\n")); | 
2149  | 0  |         case XML_RELAXNG_ERR_INTERSEQ:  | 
2150  | 0  |             return (xmlCharStrdup("Invalid sequence in interleave\n")); | 
2151  | 0  |         case XML_RELAXNG_ERR_INTEREXTRA:  | 
2152  | 0  |             snprintf(msg, 1000, "Extra element %s in interleave\n", arg1);  | 
2153  | 0  |             break;  | 
2154  | 0  |         case XML_RELAXNG_ERR_ELEMNAME:  | 
2155  | 0  |             snprintf(msg, 1000, "Expecting element %s, got %s\n", arg1,  | 
2156  | 0  |                      arg2);  | 
2157  | 0  |             break;  | 
2158  | 0  |         case XML_RELAXNG_ERR_ELEMNONS:  | 
2159  | 0  |             snprintf(msg, 1000, "Expecting a namespace for element %s\n",  | 
2160  | 0  |                      arg1);  | 
2161  | 0  |             break;  | 
2162  | 0  |         case XML_RELAXNG_ERR_ELEMWRONGNS:  | 
2163  | 0  |             snprintf(msg, 1000,  | 
2164  | 0  |                      "Element %s has wrong namespace: expecting %s\n", arg1,  | 
2165  | 0  |                      arg2);  | 
2166  | 0  |             break;  | 
2167  | 0  |         case XML_RELAXNG_ERR_ELEMWRONG:  | 
2168  | 0  |             snprintf(msg, 1000, "Did not expect element %s there\n", arg1);  | 
2169  | 0  |             break;  | 
2170  | 0  |         case XML_RELAXNG_ERR_TEXTWRONG:  | 
2171  | 0  |             snprintf(msg, 1000,  | 
2172  | 0  |                      "Did not expect text in element %s content\n", arg1);  | 
2173  | 0  |             break;  | 
2174  | 0  |         case XML_RELAXNG_ERR_ELEMEXTRANS:  | 
2175  | 0  |             snprintf(msg, 1000, "Expecting no namespace for element %s\n",  | 
2176  | 0  |                      arg1);  | 
2177  | 0  |             break;  | 
2178  | 0  |         case XML_RELAXNG_ERR_ELEMNOTEMPTY:  | 
2179  | 0  |             snprintf(msg, 1000, "Expecting element %s to be empty\n", arg1);  | 
2180  | 0  |             break;  | 
2181  | 0  |         case XML_RELAXNG_ERR_NOELEM:  | 
2182  | 0  |             snprintf(msg, 1000, "Expecting an element %s, got nothing\n",  | 
2183  | 0  |                      arg1);  | 
2184  | 0  |             break;  | 
2185  | 0  |         case XML_RELAXNG_ERR_NOTELEM:  | 
2186  | 0  |             return (xmlCharStrdup("Expecting an element got text\n")); | 
2187  | 0  |         case XML_RELAXNG_ERR_ATTRVALID:  | 
2188  | 0  |             snprintf(msg, 1000, "Element %s failed to validate attributes\n",  | 
2189  | 0  |                      arg1);  | 
2190  | 0  |             break;  | 
2191  | 0  |         case XML_RELAXNG_ERR_CONTENTVALID:  | 
2192  | 0  |             snprintf(msg, 1000, "Element %s failed to validate content\n",  | 
2193  | 0  |                      arg1);  | 
2194  | 0  |             break;  | 
2195  | 0  |         case XML_RELAXNG_ERR_EXTRACONTENT:  | 
2196  | 0  |             snprintf(msg, 1000, "Element %s has extra content: %s\n",  | 
2197  | 0  |                      arg1, arg2);  | 
2198  | 0  |             break;  | 
2199  | 0  |         case XML_RELAXNG_ERR_INVALIDATTR:  | 
2200  | 0  |             snprintf(msg, 1000, "Invalid attribute %s for element %s\n",  | 
2201  | 0  |                      arg1, arg2);  | 
2202  | 0  |             break;  | 
2203  | 0  |         case XML_RELAXNG_ERR_LACKDATA:  | 
2204  | 0  |             snprintf(msg, 1000, "Datatype element %s contains no data\n",  | 
2205  | 0  |                      arg1);  | 
2206  | 0  |             break;  | 
2207  | 0  |         case XML_RELAXNG_ERR_DATAELEM:  | 
2208  | 0  |             snprintf(msg, 1000, "Datatype element %s has child elements\n",  | 
2209  | 0  |                      arg1);  | 
2210  | 0  |             break;  | 
2211  | 0  |         case XML_RELAXNG_ERR_VALELEM:  | 
2212  | 0  |             snprintf(msg, 1000, "Value element %s has child elements\n",  | 
2213  | 0  |                      arg1);  | 
2214  | 0  |             break;  | 
2215  | 0  |         case XML_RELAXNG_ERR_LISTELEM:  | 
2216  | 0  |             snprintf(msg, 1000, "List element %s has child elements\n",  | 
2217  | 0  |                      arg1);  | 
2218  | 0  |             break;  | 
2219  | 0  |         case XML_RELAXNG_ERR_DATATYPE:  | 
2220  | 0  |             snprintf(msg, 1000, "Error validating datatype %s\n", arg1);  | 
2221  | 0  |             break;  | 
2222  | 0  |         case XML_RELAXNG_ERR_VALUE:  | 
2223  | 0  |             snprintf(msg, 1000, "Error validating value %s\n", arg1);  | 
2224  | 0  |             break;  | 
2225  | 0  |         case XML_RELAXNG_ERR_LIST:  | 
2226  | 0  |             return (xmlCharStrdup("Error validating list\n")); | 
2227  | 0  |         case XML_RELAXNG_ERR_NOGRAMMAR:  | 
2228  | 0  |             return (xmlCharStrdup("No top grammar defined\n")); | 
2229  | 0  |         case XML_RELAXNG_ERR_EXTRADATA:  | 
2230  | 0  |             return (xmlCharStrdup("Extra data in the document\n")); | 
2231  | 0  |         default:  | 
2232  | 0  |             return (xmlCharStrdup("Unknown error !\n")); | 
2233  | 0  |     }  | 
2234  | 0  |     if (msg[0] == 0) { | 
2235  | 0  |         snprintf(msg, 1000, "Unknown error code %d\n", err);  | 
2236  | 0  |     }  | 
2237  | 0  |     msg[1000 - 1] = 0;  | 
2238  | 0  |     result = xmlCharStrdup(msg);  | 
2239  | 0  |     return (xmlEscapeFormatString(&result));  | 
2240  | 0  | }  | 
2241  |  |  | 
2242  |  | /**  | 
2243  |  |  * xmlRelaxNGShowValidError:  | 
2244  |  |  * @ctxt:  the validation context  | 
2245  |  |  * @err:  the error number  | 
2246  |  |  * @node:  the node  | 
2247  |  |  * @child:  the node child generating the problem.  | 
2248  |  |  * @arg1:  the first argument  | 
2249  |  |  * @arg2:  the second argument  | 
2250  |  |  *  | 
2251  |  |  * Show a validation error.  | 
2252  |  |  */  | 
2253  |  | static void  | 
2254  |  | xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt,  | 
2255  |  |                          xmlRelaxNGValidErr err, xmlNodePtr node,  | 
2256  |  |                          xmlNodePtr child, const xmlChar * arg1,  | 
2257  |  |                          const xmlChar * arg2)  | 
2258  | 0  | { | 
2259  | 0  |     xmlChar *msg;  | 
2260  |  | 
  | 
2261  | 0  |     if (ctxt->flags & FLAGS_NOERROR)  | 
2262  | 0  |         return;  | 
2263  |  |  | 
2264  |  | #ifdef DEBUG_ERROR  | 
2265  |  |     xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err);  | 
2266  |  | #endif  | 
2267  | 0  |     msg = xmlRelaxNGGetErrorString(err, arg1, arg2);  | 
2268  | 0  |     if (msg == NULL)  | 
2269  | 0  |         return;  | 
2270  |  |  | 
2271  | 0  |     if (ctxt->errNo == XML_RELAXNG_OK)  | 
2272  | 0  |         ctxt->errNo = err;  | 
2273  | 0  |     xmlRngVErr(ctxt, (child == NULL ? node : child), err,  | 
2274  | 0  |                (const char *) msg, arg1, arg2);  | 
2275  | 0  |     xmlFree(msg);  | 
2276  | 0  | }  | 
2277  |  |  | 
2278  |  | /**  | 
2279  |  |  * xmlRelaxNGPopErrors:  | 
2280  |  |  * @ctxt:  the validation context  | 
2281  |  |  * @level:  the error level in the stack  | 
2282  |  |  *  | 
2283  |  |  * pop and discard all errors until the given level is reached  | 
2284  |  |  */  | 
2285  |  | static void  | 
2286  |  | xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level)  | 
2287  | 0  | { | 
2288  | 0  |     int i;  | 
2289  | 0  |     xmlRelaxNGValidErrorPtr err;  | 
2290  |  | 
  | 
2291  |  | #ifdef DEBUG_ERROR  | 
2292  |  |     xmlGenericError(xmlGenericErrorContext,  | 
2293  |  |                     "Pop errors till level %d\n", level);  | 
2294  |  | #endif  | 
2295  | 0  |     for (i = level; i < ctxt->errNr; i++) { | 
2296  | 0  |         err = &ctxt->errTab[i];  | 
2297  | 0  |         if (err->flags & ERROR_IS_DUP) { | 
2298  | 0  |             if (err->arg1 != NULL)  | 
2299  | 0  |                 xmlFree((xmlChar *) err->arg1);  | 
2300  | 0  |             err->arg1 = NULL;  | 
2301  | 0  |             if (err->arg2 != NULL)  | 
2302  | 0  |                 xmlFree((xmlChar *) err->arg2);  | 
2303  | 0  |             err->arg2 = NULL;  | 
2304  | 0  |             err->flags = 0;  | 
2305  | 0  |         }  | 
2306  | 0  |     }  | 
2307  | 0  |     ctxt->errNr = level;  | 
2308  | 0  |     if (ctxt->errNr <= 0)  | 
2309  | 0  |         ctxt->err = NULL;  | 
2310  | 0  | }  | 
2311  |  |  | 
2312  |  | /**  | 
2313  |  |  * xmlRelaxNGDumpValidError:  | 
2314  |  |  * @ctxt:  the validation context  | 
2315  |  |  *  | 
2316  |  |  * Show all validation error over a given index.  | 
2317  |  |  */  | 
2318  |  | static void  | 
2319  |  | xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt)  | 
2320  | 0  | { | 
2321  | 0  |     int i, j, k;  | 
2322  | 0  |     xmlRelaxNGValidErrorPtr err, dup;  | 
2323  |  | 
  | 
2324  |  | #ifdef DEBUG_ERROR  | 
2325  |  |     xmlGenericError(xmlGenericErrorContext,  | 
2326  |  |                     "Dumping error stack %d errors\n", ctxt->errNr);  | 
2327  |  | #endif  | 
2328  | 0  |     for (i = 0, k = 0; i < ctxt->errNr; i++) { | 
2329  | 0  |         err = &ctxt->errTab[i];  | 
2330  | 0  |         if (k < MAX_ERROR) { | 
2331  | 0  |             for (j = 0; j < i; j++) { | 
2332  | 0  |                 dup = &ctxt->errTab[j];  | 
2333  | 0  |                 if ((err->err == dup->err) && (err->node == dup->node) &&  | 
2334  | 0  |                     (xmlStrEqual(err->arg1, dup->arg1)) &&  | 
2335  | 0  |                     (xmlStrEqual(err->arg2, dup->arg2))) { | 
2336  | 0  |                     goto skip;  | 
2337  | 0  |                 }  | 
2338  | 0  |             }  | 
2339  | 0  |             xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,  | 
2340  | 0  |                                      err->arg1, err->arg2);  | 
2341  | 0  |             k++;  | 
2342  | 0  |         }  | 
2343  | 0  |       skip:  | 
2344  | 0  |         if (err->flags & ERROR_IS_DUP) { | 
2345  | 0  |             if (err->arg1 != NULL)  | 
2346  | 0  |                 xmlFree((xmlChar *) err->arg1);  | 
2347  | 0  |             err->arg1 = NULL;  | 
2348  | 0  |             if (err->arg2 != NULL)  | 
2349  | 0  |                 xmlFree((xmlChar *) err->arg2);  | 
2350  | 0  |             err->arg2 = NULL;  | 
2351  | 0  |             err->flags = 0;  | 
2352  | 0  |         }  | 
2353  | 0  |     }  | 
2354  | 0  |     ctxt->errNr = 0;  | 
2355  | 0  | }  | 
2356  |  |  | 
2357  |  | /**  | 
2358  |  |  * xmlRelaxNGAddValidError:  | 
2359  |  |  * @ctxt:  the validation context  | 
2360  |  |  * @err:  the error number  | 
2361  |  |  * @arg1:  the first argument  | 
2362  |  |  * @arg2:  the second argument  | 
2363  |  |  * @dup:  need to dup the args  | 
2364  |  |  *  | 
2365  |  |  * Register a validation error, either generating it if it's sure  | 
2366  |  |  * or stacking it for later handling if unsure.  | 
2367  |  |  */  | 
2368  |  | static void  | 
2369  |  | xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt,  | 
2370  |  |                         xmlRelaxNGValidErr err, const xmlChar * arg1,  | 
2371  |  |                         const xmlChar * arg2, int dup)  | 
2372  | 0  | { | 
2373  | 0  |     if (ctxt == NULL)  | 
2374  | 0  |         return;  | 
2375  | 0  |     if (ctxt->flags & FLAGS_NOERROR)  | 
2376  | 0  |         return;  | 
2377  |  |  | 
2378  |  | #ifdef DEBUG_ERROR  | 
2379  |  |     xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err);  | 
2380  |  | #endif  | 
2381  |  |     /*  | 
2382  |  |      * generate the error directly  | 
2383  |  |      */  | 
2384  | 0  |     if (((ctxt->flags & FLAGS_IGNORABLE) == 0) ||  | 
2385  | 0  |    (ctxt->flags & FLAGS_NEGATIVE)) { | 
2386  | 0  |         xmlNodePtr node, seq;  | 
2387  |  |  | 
2388  |  |         /*  | 
2389  |  |          * Flush first any stacked error which might be the  | 
2390  |  |          * real cause of the problem.  | 
2391  |  |          */  | 
2392  | 0  |         if (ctxt->errNr != 0)  | 
2393  | 0  |             xmlRelaxNGDumpValidError(ctxt);  | 
2394  | 0  |         if (ctxt->state != NULL) { | 
2395  | 0  |             node = ctxt->state->node;  | 
2396  | 0  |             seq = ctxt->state->seq;  | 
2397  | 0  |         } else { | 
2398  | 0  |             node = seq = NULL;  | 
2399  | 0  |         }  | 
2400  | 0  |         if ((node == NULL) && (seq == NULL)) { | 
2401  | 0  |             node = ctxt->pnode;  | 
2402  | 0  |         }  | 
2403  | 0  |         xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2);  | 
2404  | 0  |     }  | 
2405  |  |     /*  | 
2406  |  |      * Stack the error for later processing if needed  | 
2407  |  |      */  | 
2408  | 0  |     else { | 
2409  | 0  |         xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);  | 
2410  | 0  |     }  | 
2411  | 0  | }  | 
2412  |  |  | 
2413  |  |  | 
2414  |  | /************************************************************************  | 
2415  |  |  *                  *  | 
2416  |  |  *      Type library hooks        *  | 
2417  |  |  *                  *  | 
2418  |  |  ************************************************************************/  | 
2419  |  | static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt,  | 
2420  |  |                                     const xmlChar * str);  | 
2421  |  |  | 
2422  |  | /**  | 
2423  |  |  * xmlRelaxNGSchemaTypeHave:  | 
2424  |  |  * @data:  data needed for the library  | 
2425  |  |  * @type:  the type name  | 
2426  |  |  *  | 
2427  |  |  * Check if the given type is provided by  | 
2428  |  |  * the W3C XMLSchema Datatype library.  | 
2429  |  |  *  | 
2430  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
2431  |  |  */  | 
2432  |  | static int  | 
2433  |  | xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar * type)  | 
2434  | 0  | { | 
2435  | 0  |     xmlSchemaTypePtr typ;  | 
2436  |  | 
  | 
2437  | 0  |     if (type == NULL)  | 
2438  | 0  |         return (-1);  | 
2439  | 0  |     typ = xmlSchemaGetPredefinedType(type,  | 
2440  | 0  |                                      BAD_CAST  | 
2441  | 0  |                                      "http://www.w3.org/2001/XMLSchema");  | 
2442  | 0  |     if (typ == NULL)  | 
2443  | 0  |         return (0);  | 
2444  | 0  |     return (1);  | 
2445  | 0  | }  | 
2446  |  |  | 
2447  |  | /**  | 
2448  |  |  * xmlRelaxNGSchemaTypeCheck:  | 
2449  |  |  * @data:  data needed for the library  | 
2450  |  |  * @type:  the type name  | 
2451  |  |  * @value:  the value to check  | 
2452  |  |  * @node:  the node  | 
2453  |  |  *  | 
2454  |  |  * Check if the given type and value are validated by  | 
2455  |  |  * the W3C XMLSchema Datatype library.  | 
2456  |  |  *  | 
2457  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
2458  |  |  */  | 
2459  |  | static int  | 
2460  |  | xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,  | 
2461  |  |                           const xmlChar * type,  | 
2462  |  |                           const xmlChar * value,  | 
2463  |  |                           void **result, xmlNodePtr node)  | 
2464  | 0  | { | 
2465  | 0  |     xmlSchemaTypePtr typ;  | 
2466  | 0  |     int ret;  | 
2467  |  | 
  | 
2468  | 0  |     if ((type == NULL) || (value == NULL))  | 
2469  | 0  |         return (-1);  | 
2470  | 0  |     typ = xmlSchemaGetPredefinedType(type,  | 
2471  | 0  |                                      BAD_CAST  | 
2472  | 0  |                                      "http://www.w3.org/2001/XMLSchema");  | 
2473  | 0  |     if (typ == NULL)  | 
2474  | 0  |         return (-1);  | 
2475  | 0  |     ret = xmlSchemaValPredefTypeNode(typ, value,  | 
2476  | 0  |                                      (xmlSchemaValPtr *) result, node);  | 
2477  | 0  |     if (ret == 2)               /* special ID error code */  | 
2478  | 0  |         return (2);  | 
2479  | 0  |     if (ret == 0)  | 
2480  | 0  |         return (1);  | 
2481  | 0  |     if (ret > 0)  | 
2482  | 0  |         return (0);  | 
2483  | 0  |     return (-1);  | 
2484  | 0  | }  | 
2485  |  |  | 
2486  |  | /**  | 
2487  |  |  * xmlRelaxNGSchemaFacetCheck:  | 
2488  |  |  * @data:  data needed for the library  | 
2489  |  |  * @type:  the type name  | 
2490  |  |  * @facet:  the facet name  | 
2491  |  |  * @val:  the facet value  | 
2492  |  |  * @strval:  the string value  | 
2493  |  |  * @value:  the value to check  | 
2494  |  |  *  | 
2495  |  |  * Function provided by a type library to check a value facet  | 
2496  |  |  *  | 
2497  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
2498  |  |  */  | 
2499  |  | static int  | 
2500  |  | xmlRelaxNGSchemaFacetCheck(void *data ATTRIBUTE_UNUSED,  | 
2501  |  |                            const xmlChar * type, const xmlChar * facetname,  | 
2502  |  |                            const xmlChar * val, const xmlChar * strval,  | 
2503  |  |                            void *value)  | 
2504  | 0  | { | 
2505  | 0  |     xmlSchemaFacetPtr facet;  | 
2506  | 0  |     xmlSchemaTypePtr typ;  | 
2507  | 0  |     int ret;  | 
2508  |  | 
  | 
2509  | 0  |     if ((type == NULL) || (strval == NULL))  | 
2510  | 0  |         return (-1);  | 
2511  | 0  |     typ = xmlSchemaGetPredefinedType(type,  | 
2512  | 0  |                                      BAD_CAST  | 
2513  | 0  |                                      "http://www.w3.org/2001/XMLSchema");  | 
2514  | 0  |     if (typ == NULL)  | 
2515  | 0  |         return (-1);  | 
2516  |  |  | 
2517  | 0  |     facet = xmlSchemaNewFacet();  | 
2518  | 0  |     if (facet == NULL)  | 
2519  | 0  |         return (-1);  | 
2520  |  |  | 
2521  | 0  |     if (xmlStrEqual(facetname, BAD_CAST "minInclusive")) { | 
2522  | 0  |         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;  | 
2523  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive")) { | 
2524  | 0  |         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;  | 
2525  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive")) { | 
2526  | 0  |         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;  | 
2527  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive")) { | 
2528  | 0  |         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;  | 
2529  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits")) { | 
2530  | 0  |         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;  | 
2531  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits")) { | 
2532  | 0  |         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;  | 
2533  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "pattern")) { | 
2534  | 0  |         facet->type = XML_SCHEMA_FACET_PATTERN;  | 
2535  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "enumeration")) { | 
2536  | 0  |         facet->type = XML_SCHEMA_FACET_ENUMERATION;  | 
2537  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace")) { | 
2538  | 0  |         facet->type = XML_SCHEMA_FACET_WHITESPACE;  | 
2539  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "length")) { | 
2540  | 0  |         facet->type = XML_SCHEMA_FACET_LENGTH;  | 
2541  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "maxLength")) { | 
2542  | 0  |         facet->type = XML_SCHEMA_FACET_MAXLENGTH;  | 
2543  | 0  |     } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) { | 
2544  | 0  |         facet->type = XML_SCHEMA_FACET_MINLENGTH;  | 
2545  | 0  |     } else { | 
2546  | 0  |         xmlSchemaFreeFacet(facet);  | 
2547  | 0  |         return (-1);  | 
2548  | 0  |     }  | 
2549  | 0  |     facet->value = val;  | 
2550  | 0  |     ret = xmlSchemaCheckFacet(facet, typ, NULL, type);  | 
2551  | 0  |     if (ret != 0) { | 
2552  | 0  |         xmlSchemaFreeFacet(facet);  | 
2553  | 0  |         return (-1);  | 
2554  | 0  |     }  | 
2555  | 0  |     ret = xmlSchemaValidateFacet(typ, facet, strval, value);  | 
2556  | 0  |     xmlSchemaFreeFacet(facet);  | 
2557  | 0  |     if (ret != 0)  | 
2558  | 0  |         return (-1);  | 
2559  | 0  |     return (0);  | 
2560  | 0  | }  | 
2561  |  |  | 
2562  |  | /**  | 
2563  |  |  * xmlRelaxNGSchemaFreeValue:  | 
2564  |  |  * @data:  data needed for the library  | 
2565  |  |  * @value:  the value to free  | 
2566  |  |  *  | 
2567  |  |  * Function provided by a type library to free a Schemas value  | 
2568  |  |  *  | 
2569  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
2570  |  |  */  | 
2571  |  | static void  | 
2572  |  | xmlRelaxNGSchemaFreeValue(void *data ATTRIBUTE_UNUSED, void *value)  | 
2573  | 0  | { | 
2574  | 0  |     xmlSchemaFreeValue(value);  | 
2575  | 0  | }  | 
2576  |  |  | 
2577  |  | /**  | 
2578  |  |  * xmlRelaxNGSchemaTypeCompare:  | 
2579  |  |  * @data:  data needed for the library  | 
2580  |  |  * @type:  the type name  | 
2581  |  |  * @value1:  the first value  | 
2582  |  |  * @value2:  the second value  | 
2583  |  |  *  | 
2584  |  |  * Compare two values for equality accordingly a type from the W3C XMLSchema  | 
2585  |  |  * Datatype library.  | 
2586  |  |  *  | 
2587  |  |  * Returns 1 if equal, 0 if no and -1 in case of error.  | 
2588  |  |  */  | 
2589  |  | static int  | 
2590  |  | xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,  | 
2591  |  |                             const xmlChar * type,  | 
2592  |  |                             const xmlChar * value1,  | 
2593  |  |                             xmlNodePtr ctxt1,  | 
2594  |  |                             void *comp1,  | 
2595  |  |                             const xmlChar * value2, xmlNodePtr ctxt2)  | 
2596  | 0  | { | 
2597  | 0  |     int ret;  | 
2598  | 0  |     xmlSchemaTypePtr typ;  | 
2599  | 0  |     xmlSchemaValPtr res1 = NULL, res2 = NULL;  | 
2600  |  | 
  | 
2601  | 0  |     if ((type == NULL) || (value1 == NULL) || (value2 == NULL))  | 
2602  | 0  |         return (-1);  | 
2603  | 0  |     typ = xmlSchemaGetPredefinedType(type,  | 
2604  | 0  |                                      BAD_CAST  | 
2605  | 0  |                                      "http://www.w3.org/2001/XMLSchema");  | 
2606  | 0  |     if (typ == NULL)  | 
2607  | 0  |         return (-1);  | 
2608  | 0  |     if (comp1 == NULL) { | 
2609  | 0  |         ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1);  | 
2610  | 0  |         if (ret != 0)  | 
2611  | 0  |             return (-1);  | 
2612  | 0  |         if (res1 == NULL)  | 
2613  | 0  |             return (-1);  | 
2614  | 0  |     } else { | 
2615  | 0  |         res1 = (xmlSchemaValPtr) comp1;  | 
2616  | 0  |     }  | 
2617  | 0  |     ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2);  | 
2618  | 0  |     if (ret != 0) { | 
2619  | 0  |   if (res1 != (xmlSchemaValPtr) comp1)  | 
2620  | 0  |       xmlSchemaFreeValue(res1);  | 
2621  | 0  |         return (-1);  | 
2622  | 0  |     }  | 
2623  | 0  |     ret = xmlSchemaCompareValues(res1, res2);  | 
2624  | 0  |     if (res1 != (xmlSchemaValPtr) comp1)  | 
2625  | 0  |         xmlSchemaFreeValue(res1);  | 
2626  | 0  |     xmlSchemaFreeValue(res2);  | 
2627  | 0  |     if (ret == -2)  | 
2628  | 0  |         return (-1);  | 
2629  | 0  |     if (ret == 0)  | 
2630  | 0  |         return (1);  | 
2631  | 0  |     return (0);  | 
2632  | 0  | }  | 
2633  |  |  | 
2634  |  | /**  | 
2635  |  |  * xmlRelaxNGDefaultTypeHave:  | 
2636  |  |  * @data:  data needed for the library  | 
2637  |  |  * @type:  the type name  | 
2638  |  |  *  | 
2639  |  |  * Check if the given type is provided by  | 
2640  |  |  * the default datatype library.  | 
2641  |  |  *  | 
2642  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
2643  |  |  */  | 
2644  |  | static int  | 
2645  |  | xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED,  | 
2646  |  |                           const xmlChar * type)  | 
2647  | 0  | { | 
2648  | 0  |     if (type == NULL)  | 
2649  | 0  |         return (-1);  | 
2650  | 0  |     if (xmlStrEqual(type, BAD_CAST "string"))  | 
2651  | 0  |         return (1);  | 
2652  | 0  |     if (xmlStrEqual(type, BAD_CAST "token"))  | 
2653  | 0  |         return (1);  | 
2654  | 0  |     return (0);  | 
2655  | 0  | }  | 
2656  |  |  | 
2657  |  | /**  | 
2658  |  |  * xmlRelaxNGDefaultTypeCheck:  | 
2659  |  |  * @data:  data needed for the library  | 
2660  |  |  * @type:  the type name  | 
2661  |  |  * @value:  the value to check  | 
2662  |  |  * @node:  the node  | 
2663  |  |  *  | 
2664  |  |  * Check if the given type and value are validated by  | 
2665  |  |  * the default datatype library.  | 
2666  |  |  *  | 
2667  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
2668  |  |  */  | 
2669  |  | static int  | 
2670  |  | xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,  | 
2671  |  |                            const xmlChar * type ATTRIBUTE_UNUSED,  | 
2672  |  |                            const xmlChar * value ATTRIBUTE_UNUSED,  | 
2673  |  |                            void **result ATTRIBUTE_UNUSED,  | 
2674  |  |                            xmlNodePtr node ATTRIBUTE_UNUSED)  | 
2675  | 0  | { | 
2676  | 0  |     if (value == NULL)  | 
2677  | 0  |         return (-1);  | 
2678  | 0  |     if (xmlStrEqual(type, BAD_CAST "string"))  | 
2679  | 0  |         return (1);  | 
2680  | 0  |     if (xmlStrEqual(type, BAD_CAST "token")) { | 
2681  | 0  |         return (1);  | 
2682  | 0  |     }  | 
2683  |  |  | 
2684  | 0  |     return (0);  | 
2685  | 0  | }  | 
2686  |  |  | 
2687  |  | /**  | 
2688  |  |  * xmlRelaxNGDefaultTypeCompare:  | 
2689  |  |  * @data:  data needed for the library  | 
2690  |  |  * @type:  the type name  | 
2691  |  |  * @value1:  the first value  | 
2692  |  |  * @value2:  the second value  | 
2693  |  |  *  | 
2694  |  |  * Compare two values accordingly a type from the default  | 
2695  |  |  * datatype library.  | 
2696  |  |  *  | 
2697  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
2698  |  |  */  | 
2699  |  | static int  | 
2700  |  | xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,  | 
2701  |  |                              const xmlChar * type,  | 
2702  |  |                              const xmlChar * value1,  | 
2703  |  |                              xmlNodePtr ctxt1 ATTRIBUTE_UNUSED,  | 
2704  |  |                              void *comp1 ATTRIBUTE_UNUSED,  | 
2705  |  |                              const xmlChar * value2,  | 
2706  |  |                              xmlNodePtr ctxt2 ATTRIBUTE_UNUSED)  | 
2707  | 0  | { | 
2708  | 0  |     int ret = -1;  | 
2709  |  | 
  | 
2710  | 0  |     if (xmlStrEqual(type, BAD_CAST "string")) { | 
2711  | 0  |         ret = xmlStrEqual(value1, value2);  | 
2712  | 0  |     } else if (xmlStrEqual(type, BAD_CAST "token")) { | 
2713  | 0  |         if (!xmlStrEqual(value1, value2)) { | 
2714  | 0  |             xmlChar *nval, *nvalue;  | 
2715  |  |  | 
2716  |  |             /*  | 
2717  |  |              * TODO: trivial optimizations are possible by  | 
2718  |  |              * computing at compile-time  | 
2719  |  |              */  | 
2720  | 0  |             nval = xmlRelaxNGNormalize(NULL, value1);  | 
2721  | 0  |             nvalue = xmlRelaxNGNormalize(NULL, value2);  | 
2722  |  | 
  | 
2723  | 0  |             if ((nval == NULL) || (nvalue == NULL))  | 
2724  | 0  |                 ret = -1;  | 
2725  | 0  |             else if (xmlStrEqual(nval, nvalue))  | 
2726  | 0  |                 ret = 1;  | 
2727  | 0  |             else  | 
2728  | 0  |                 ret = 0;  | 
2729  | 0  |             if (nval != NULL)  | 
2730  | 0  |                 xmlFree(nval);  | 
2731  | 0  |             if (nvalue != NULL)  | 
2732  | 0  |                 xmlFree(nvalue);  | 
2733  | 0  |         } else  | 
2734  | 0  |             ret = 1;  | 
2735  | 0  |     }  | 
2736  | 0  |     return (ret);  | 
2737  | 0  | }  | 
2738  |  |  | 
2739  |  | static int xmlRelaxNGTypeInitialized = 0;  | 
2740  |  | static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;  | 
2741  |  |  | 
2742  |  | /**  | 
2743  |  |  * xmlRelaxNGFreeTypeLibrary:  | 
2744  |  |  * @lib:  the type library structure  | 
2745  |  |  * @namespace:  the URI bound to the library  | 
2746  |  |  *  | 
2747  |  |  * Free the structure associated to the type library  | 
2748  |  |  */  | 
2749  |  | static void  | 
2750  |  | xmlRelaxNGFreeTypeLibrary(void *payload,  | 
2751  |  |                           const xmlChar * namespace ATTRIBUTE_UNUSED)  | 
2752  | 0  | { | 
2753  | 0  |     xmlRelaxNGTypeLibraryPtr lib = (xmlRelaxNGTypeLibraryPtr) payload;  | 
2754  | 0  |     if (lib == NULL)  | 
2755  | 0  |         return;  | 
2756  | 0  |     if (lib->namespace != NULL)  | 
2757  | 0  |         xmlFree((xmlChar *) lib->namespace);  | 
2758  | 0  |     xmlFree(lib);  | 
2759  | 0  | }  | 
2760  |  |  | 
2761  |  | /**  | 
2762  |  |  * xmlRelaxNGRegisterTypeLibrary:  | 
2763  |  |  * @namespace:  the URI bound to the library  | 
2764  |  |  * @data:  data associated to the library  | 
2765  |  |  * @have:  the provide function  | 
2766  |  |  * @check:  the checking function  | 
2767  |  |  * @comp:  the comparison function  | 
2768  |  |  *  | 
2769  |  |  * Register a new type library  | 
2770  |  |  *  | 
2771  |  |  * Returns 0 in case of success and -1 in case of error.  | 
2772  |  |  */  | 
2773  |  | static int  | 
2774  |  | xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,  | 
2775  |  |                               xmlRelaxNGTypeHave have,  | 
2776  |  |                               xmlRelaxNGTypeCheck check,  | 
2777  |  |                               xmlRelaxNGTypeCompare comp,  | 
2778  |  |                               xmlRelaxNGFacetCheck facet,  | 
2779  |  |                               xmlRelaxNGTypeFree freef)  | 
2780  | 0  | { | 
2781  | 0  |     xmlRelaxNGTypeLibraryPtr lib;  | 
2782  | 0  |     int ret;  | 
2783  |  | 
  | 
2784  | 0  |     if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||  | 
2785  | 0  |         (check == NULL) || (comp == NULL))  | 
2786  | 0  |         return (-1);  | 
2787  | 0  |     if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) { | 
2788  | 0  |         xmlGenericError(xmlGenericErrorContext,  | 
2789  | 0  |                         "Relax-NG types library '%s' already registered\n",  | 
2790  | 0  |                         namespace);  | 
2791  | 0  |         return (-1);  | 
2792  | 0  |     }  | 
2793  | 0  |     lib =  | 
2794  | 0  |         (xmlRelaxNGTypeLibraryPtr)  | 
2795  | 0  |         xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));  | 
2796  | 0  |     if (lib == NULL) { | 
2797  | 0  |         xmlRngVErrMemory(NULL, "adding types library\n");  | 
2798  | 0  |         return (-1);  | 
2799  | 0  |     }  | 
2800  | 0  |     memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));  | 
2801  | 0  |     lib->namespace = xmlStrdup(namespace);  | 
2802  | 0  |     lib->data = data;  | 
2803  | 0  |     lib->have = have;  | 
2804  | 0  |     lib->comp = comp;  | 
2805  | 0  |     lib->check = check;  | 
2806  | 0  |     lib->facet = facet;  | 
2807  | 0  |     lib->freef = freef;  | 
2808  | 0  |     ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);  | 
2809  | 0  |     if (ret < 0) { | 
2810  | 0  |         xmlGenericError(xmlGenericErrorContext,  | 
2811  | 0  |                         "Relax-NG types library failed to register '%s'\n",  | 
2812  | 0  |                         namespace);  | 
2813  | 0  |         xmlRelaxNGFreeTypeLibrary(lib, namespace);  | 
2814  | 0  |         return (-1);  | 
2815  | 0  |     }  | 
2816  | 0  |     return (0);  | 
2817  | 0  | }  | 
2818  |  |  | 
2819  |  | /**  | 
2820  |  |  * xmlRelaxNGInitTypes:  | 
2821  |  |  *  | 
2822  |  |  * Initialize the default type libraries.  | 
2823  |  |  *  | 
2824  |  |  * Returns 0 in case of success and -1 in case of error.  | 
2825  |  |  */  | 
2826  |  | int  | 
2827  |  | xmlRelaxNGInitTypes(void)  | 
2828  | 0  | { | 
2829  | 0  |     if (xmlRelaxNGTypeInitialized != 0)  | 
2830  | 0  |         return (0);  | 
2831  | 0  |     xmlRelaxNGRegisteredTypes = xmlHashCreate(10);  | 
2832  | 0  |     if (xmlRelaxNGRegisteredTypes == NULL) { | 
2833  | 0  |         xmlGenericError(xmlGenericErrorContext,  | 
2834  | 0  |                         "Failed to allocate sh table for Relax-NG types\n");  | 
2835  | 0  |         return (-1);  | 
2836  | 0  |     }  | 
2837  | 0  |     xmlRelaxNGRegisterTypeLibrary(BAD_CAST  | 
2838  | 0  |                                   "http://www.w3.org/2001/XMLSchema-datatypes",  | 
2839  | 0  |                                   NULL, xmlRelaxNGSchemaTypeHave,  | 
2840  | 0  |                                   xmlRelaxNGSchemaTypeCheck,  | 
2841  | 0  |                                   xmlRelaxNGSchemaTypeCompare,  | 
2842  | 0  |                                   xmlRelaxNGSchemaFacetCheck,  | 
2843  | 0  |                                   xmlRelaxNGSchemaFreeValue);  | 
2844  | 0  |     xmlRelaxNGRegisterTypeLibrary(xmlRelaxNGNs, NULL,  | 
2845  | 0  |                                   xmlRelaxNGDefaultTypeHave,  | 
2846  | 0  |                                   xmlRelaxNGDefaultTypeCheck,  | 
2847  | 0  |                                   xmlRelaxNGDefaultTypeCompare, NULL,  | 
2848  | 0  |                                   NULL);  | 
2849  | 0  |     xmlRelaxNGTypeInitialized = 1;  | 
2850  | 0  |     return (0);  | 
2851  | 0  | }  | 
2852  |  |  | 
2853  |  | /**  | 
2854  |  |  * xmlRelaxNGCleanupTypes:  | 
2855  |  |  *  | 
2856  |  |  * DEPRECATED: This function will be made private. Call xmlCleanupParser  | 
2857  |  |  * to free global state but see the warnings there. xmlCleanupParser  | 
2858  |  |  * should be only called once at program exit. In most cases, you don't  | 
2859  |  |  * have call cleanup functions at all.  | 
2860  |  |  *  | 
2861  |  |  * Cleanup the default Schemas type library associated to RelaxNG  | 
2862  |  |  */  | 
2863  |  | void  | 
2864  |  | xmlRelaxNGCleanupTypes(void)  | 
2865  | 0  | { | 
2866  | 0  |     xmlSchemaCleanupTypes();  | 
2867  | 0  |     if (xmlRelaxNGTypeInitialized == 0)  | 
2868  | 0  |         return;  | 
2869  | 0  |     xmlHashFree(xmlRelaxNGRegisteredTypes, xmlRelaxNGFreeTypeLibrary);  | 
2870  | 0  |     xmlRelaxNGTypeInitialized = 0;  | 
2871  | 0  | }  | 
2872  |  |  | 
2873  |  | /************************************************************************  | 
2874  |  |  *                  *  | 
2875  |  |  *    Compiling element content into regexp     *  | 
2876  |  |  *                  *  | 
2877  |  |  * Sometime the element content can be compiled into a pure regexp, *  | 
2878  |  |  * This allows a faster execution and streamability at that level *  | 
2879  |  |  *                  *  | 
2880  |  |  ************************************************************************/  | 
2881  |  |  | 
2882  |  | static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,  | 
2883  |  |                                 xmlRelaxNGDefinePtr def);  | 
2884  |  |  | 
2885  |  | /**  | 
2886  |  |  * xmlRelaxNGIsCompilable:  | 
2887  |  |  * @define:  the definition to check  | 
2888  |  |  *  | 
2889  |  |  * Check if a definition is nullable.  | 
2890  |  |  *  | 
2891  |  |  * Returns 1 if yes, 0 if no and -1 in case of error  | 
2892  |  |  */  | 
2893  |  | static int  | 
2894  |  | xmlRelaxNGIsCompilable(xmlRelaxNGDefinePtr def)  | 
2895  | 0  | { | 
2896  | 0  |     int ret = -1;  | 
2897  |  | 
  | 
2898  | 0  |     if (def == NULL) { | 
2899  | 0  |         return (-1);  | 
2900  | 0  |     }  | 
2901  | 0  |     if ((def->type != XML_RELAXNG_ELEMENT) &&  | 
2902  | 0  |         (def->dflags & IS_COMPILABLE))  | 
2903  | 0  |         return (1);  | 
2904  | 0  |     if ((def->type != XML_RELAXNG_ELEMENT) &&  | 
2905  | 0  |         (def->dflags & IS_NOT_COMPILABLE))  | 
2906  | 0  |         return (0);  | 
2907  | 0  |     switch (def->type) { | 
2908  | 0  |         case XML_RELAXNG_NOOP:  | 
2909  | 0  |             ret = xmlRelaxNGIsCompilable(def->content);  | 
2910  | 0  |             break;  | 
2911  | 0  |         case XML_RELAXNG_TEXT:  | 
2912  | 0  |         case XML_RELAXNG_EMPTY:  | 
2913  | 0  |             ret = 1;  | 
2914  | 0  |             break;  | 
2915  | 0  |         case XML_RELAXNG_ELEMENT:  | 
2916  |  |             /*  | 
2917  |  |              * Check if the element content is compilable  | 
2918  |  |              */  | 
2919  | 0  |             if (((def->dflags & IS_NOT_COMPILABLE) == 0) &&  | 
2920  | 0  |                 ((def->dflags & IS_COMPILABLE) == 0)) { | 
2921  | 0  |                 xmlRelaxNGDefinePtr list;  | 
2922  |  | 
  | 
2923  | 0  |                 list = def->content;  | 
2924  | 0  |                 while (list != NULL) { | 
2925  | 0  |                     ret = xmlRelaxNGIsCompilable(list);  | 
2926  | 0  |                     if (ret != 1)  | 
2927  | 0  |                         break;  | 
2928  | 0  |                     list = list->next;  | 
2929  | 0  |                 }  | 
2930  |  |     /*  | 
2931  |  |      * Because the routine is recursive, we must guard against  | 
2932  |  |      * discovering both COMPILABLE and NOT_COMPILABLE  | 
2933  |  |      */  | 
2934  | 0  |                 if (ret == 0) { | 
2935  | 0  |         def->dflags &= ~IS_COMPILABLE;  | 
2936  | 0  |                     def->dflags |= IS_NOT_COMPILABLE;  | 
2937  | 0  |     }  | 
2938  | 0  |                 if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE))  | 
2939  | 0  |                     def->dflags |= IS_COMPILABLE;  | 
2940  |  | #ifdef DEBUG_COMPILE  | 
2941  |  |                 if (ret == 1) { | 
2942  |  |                     xmlGenericError(xmlGenericErrorContext,  | 
2943  |  |                                     "element content for %s is compilable\n",  | 
2944  |  |                                     def->name);  | 
2945  |  |                 } else if (ret == 0) { | 
2946  |  |                     xmlGenericError(xmlGenericErrorContext,  | 
2947  |  |                                     "element content for %s is not compilable\n",  | 
2948  |  |                                     def->name);  | 
2949  |  |                 } else { | 
2950  |  |                     xmlGenericError(xmlGenericErrorContext,  | 
2951  |  |                                     "Problem in RelaxNGIsCompilable for element %s\n",  | 
2952  |  |                                     def->name);  | 
2953  |  |                 }  | 
2954  |  | #endif  | 
2955  | 0  |             }  | 
2956  |  |             /*  | 
2957  |  |              * All elements return a compilable status unless they  | 
2958  |  |              * are generic like anyName  | 
2959  |  |              */  | 
2960  | 0  |             if ((def->nameClass != NULL) || (def->name == NULL))  | 
2961  | 0  |                 ret = 0;  | 
2962  | 0  |             else  | 
2963  | 0  |                 ret = 1;  | 
2964  | 0  |             return (ret);  | 
2965  | 0  |         case XML_RELAXNG_REF:  | 
2966  | 0  |         case XML_RELAXNG_EXTERNALREF:  | 
2967  | 0  |         case XML_RELAXNG_PARENTREF:  | 
2968  | 0  |             if (def->depth == -20) { | 
2969  | 0  |                 return (1);  | 
2970  | 0  |             } else { | 
2971  | 0  |                 xmlRelaxNGDefinePtr list;  | 
2972  |  | 
  | 
2973  | 0  |                 def->depth = -20;  | 
2974  | 0  |                 list = def->content;  | 
2975  | 0  |                 while (list != NULL) { | 
2976  | 0  |                     ret = xmlRelaxNGIsCompilable(list);  | 
2977  | 0  |                     if (ret != 1)  | 
2978  | 0  |                         break;  | 
2979  | 0  |                     list = list->next;  | 
2980  | 0  |                 }  | 
2981  | 0  |             }  | 
2982  | 0  |             break;  | 
2983  | 0  |         case XML_RELAXNG_START:  | 
2984  | 0  |         case XML_RELAXNG_OPTIONAL:  | 
2985  | 0  |         case XML_RELAXNG_ZEROORMORE:  | 
2986  | 0  |         case XML_RELAXNG_ONEORMORE:  | 
2987  | 0  |         case XML_RELAXNG_CHOICE:  | 
2988  | 0  |         case XML_RELAXNG_GROUP:  | 
2989  | 0  |         case XML_RELAXNG_DEF:{ | 
2990  | 0  |                 xmlRelaxNGDefinePtr list;  | 
2991  |  | 
  | 
2992  | 0  |                 list = def->content;  | 
2993  | 0  |                 while (list != NULL) { | 
2994  | 0  |                     ret = xmlRelaxNGIsCompilable(list);  | 
2995  | 0  |                     if (ret != 1)  | 
2996  | 0  |                         break;  | 
2997  | 0  |                     list = list->next;  | 
2998  | 0  |                 }  | 
2999  | 0  |                 break;  | 
3000  | 0  |             }  | 
3001  | 0  |         case XML_RELAXNG_EXCEPT:  | 
3002  | 0  |         case XML_RELAXNG_ATTRIBUTE:  | 
3003  | 0  |         case XML_RELAXNG_INTERLEAVE:  | 
3004  | 0  |         case XML_RELAXNG_DATATYPE:  | 
3005  | 0  |         case XML_RELAXNG_LIST:  | 
3006  | 0  |         case XML_RELAXNG_PARAM:  | 
3007  | 0  |         case XML_RELAXNG_VALUE:  | 
3008  | 0  |         case XML_RELAXNG_NOT_ALLOWED:  | 
3009  | 0  |             ret = 0;  | 
3010  | 0  |             break;  | 
3011  | 0  |     }  | 
3012  | 0  |     if (ret == 0)  | 
3013  | 0  |         def->dflags |= IS_NOT_COMPILABLE;  | 
3014  | 0  |     if (ret == 1)  | 
3015  | 0  |         def->dflags |= IS_COMPILABLE;  | 
3016  |  | #ifdef DEBUG_COMPILE  | 
3017  |  |     if (ret == 1) { | 
3018  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3019  |  |                         "RelaxNGIsCompilable %s : true\n",  | 
3020  |  |                         xmlRelaxNGDefName(def));  | 
3021  |  |     } else if (ret == 0) { | 
3022  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3023  |  |                         "RelaxNGIsCompilable %s : false\n",  | 
3024  |  |                         xmlRelaxNGDefName(def));  | 
3025  |  |     } else { | 
3026  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3027  |  |                         "Problem in RelaxNGIsCompilable %s\n",  | 
3028  |  |                         xmlRelaxNGDefName(def));  | 
3029  |  |     }  | 
3030  |  | #endif  | 
3031  | 0  |     return (ret);  | 
3032  | 0  | }  | 
3033  |  |  | 
3034  |  | /**  | 
3035  |  |  * xmlRelaxNGCompile:  | 
3036  |  |  * ctxt:  the RelaxNG parser context  | 
3037  |  |  * @define:  the definition tree to compile  | 
3038  |  |  *  | 
3039  |  |  * Compile the set of definitions, it works recursively, till the  | 
3040  |  |  * element boundaries, where it tries to compile the content if possible  | 
3041  |  |  *  | 
3042  |  |  * Returns 0 if success and -1 in case of error  | 
3043  |  |  */  | 
3044  |  | static int  | 
3045  |  | xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)  | 
3046  | 0  | { | 
3047  | 0  |     int ret = 0;  | 
3048  | 0  |     xmlRelaxNGDefinePtr list;  | 
3049  |  | 
  | 
3050  | 0  |     if ((ctxt == NULL) || (def == NULL))  | 
3051  | 0  |         return (-1);  | 
3052  |  |  | 
3053  | 0  |     switch (def->type) { | 
3054  | 0  |         case XML_RELAXNG_START:  | 
3055  | 0  |             if ((xmlRelaxNGIsCompilable(def) == 1) && (def->depth != -25)) { | 
3056  | 0  |                 xmlAutomataPtr oldam = ctxt->am;  | 
3057  | 0  |                 xmlAutomataStatePtr oldstate = ctxt->state;  | 
3058  |  | 
  | 
3059  | 0  |                 def->depth = -25;  | 
3060  |  | 
  | 
3061  | 0  |                 list = def->content;  | 
3062  | 0  |                 ctxt->am = xmlNewAutomata();  | 
3063  | 0  |                 if (ctxt->am == NULL)  | 
3064  | 0  |                     return (-1);  | 
3065  |  |  | 
3066  |  |                 /*  | 
3067  |  |                  * assume identical strings but not same pointer are different  | 
3068  |  |                  * atoms, needed for non-determinism detection  | 
3069  |  |                  * That way if 2 elements with the same name are in a choice  | 
3070  |  |                  * branch the automata is found non-deterministic and  | 
3071  |  |                  * we fallback to the normal validation which does the right  | 
3072  |  |                  * thing of exploring both choices.  | 
3073  |  |                  */  | 
3074  | 0  |                 xmlAutomataSetFlags(ctxt->am, 1);  | 
3075  |  | 
  | 
3076  | 0  |                 ctxt->state = xmlAutomataGetInitState(ctxt->am);  | 
3077  | 0  |                 while (list != NULL) { | 
3078  | 0  |                     xmlRelaxNGCompile(ctxt, list);  | 
3079  | 0  |                     list = list->next;  | 
3080  | 0  |                 }  | 
3081  | 0  |                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);  | 
3082  | 0  |                 if (xmlAutomataIsDeterminist(ctxt->am))  | 
3083  | 0  |                     def->contModel = xmlAutomataCompile(ctxt->am);  | 
3084  |  | 
  | 
3085  | 0  |                 xmlFreeAutomata(ctxt->am);  | 
3086  | 0  |                 ctxt->state = oldstate;  | 
3087  | 0  |                 ctxt->am = oldam;  | 
3088  | 0  |             }  | 
3089  | 0  |             break;  | 
3090  | 0  |         case XML_RELAXNG_ELEMENT:  | 
3091  | 0  |             if ((ctxt->am != NULL) && (def->name != NULL)) { | 
3092  | 0  |                 ctxt->state = xmlAutomataNewTransition2(ctxt->am,  | 
3093  | 0  |                                                         ctxt->state, NULL,  | 
3094  | 0  |                                                         def->name, def->ns,  | 
3095  | 0  |                                                         def);  | 
3096  | 0  |             }  | 
3097  | 0  |             if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) { | 
3098  | 0  |                 xmlAutomataPtr oldam = ctxt->am;  | 
3099  | 0  |                 xmlAutomataStatePtr oldstate = ctxt->state;  | 
3100  |  | 
  | 
3101  | 0  |                 def->depth = -25;  | 
3102  |  | 
  | 
3103  | 0  |                 list = def->content;  | 
3104  | 0  |                 ctxt->am = xmlNewAutomata();  | 
3105  | 0  |                 if (ctxt->am == NULL)  | 
3106  | 0  |                     return (-1);  | 
3107  | 0  |                 xmlAutomataSetFlags(ctxt->am, 1);  | 
3108  | 0  |                 ctxt->state = xmlAutomataGetInitState(ctxt->am);  | 
3109  | 0  |                 while (list != NULL) { | 
3110  | 0  |                     xmlRelaxNGCompile(ctxt, list);  | 
3111  | 0  |                     list = list->next;  | 
3112  | 0  |                 }  | 
3113  | 0  |                 xmlAutomataSetFinalState(ctxt->am, ctxt->state);  | 
3114  | 0  |                 def->contModel = xmlAutomataCompile(ctxt->am);  | 
3115  | 0  |                 if (!xmlRegexpIsDeterminist(def->contModel)) { | 
3116  |  | #ifdef DEBUG_COMPILE  | 
3117  |  |                     xmlGenericError(xmlGenericErrorContext,  | 
3118  |  |                         "Content model not determinist %s\n",  | 
3119  |  |                                     def->name);  | 
3120  |  | #endif  | 
3121  |  |                     /*  | 
3122  |  |                      * we can only use the automata if it is determinist  | 
3123  |  |                      */  | 
3124  | 0  |                     xmlRegFreeRegexp(def->contModel);  | 
3125  | 0  |                     def->contModel = NULL;  | 
3126  | 0  |                 }  | 
3127  | 0  |                 xmlFreeAutomata(ctxt->am);  | 
3128  | 0  |                 ctxt->state = oldstate;  | 
3129  | 0  |                 ctxt->am = oldam;  | 
3130  | 0  |             } else { | 
3131  | 0  |                 xmlAutomataPtr oldam = ctxt->am;  | 
3132  |  |  | 
3133  |  |                 /*  | 
3134  |  |                  * we can't build the content model for this element content  | 
3135  |  |                  * but it still might be possible to build it for some of its  | 
3136  |  |                  * children, recurse.  | 
3137  |  |                  */  | 
3138  | 0  |                 ret = xmlRelaxNGTryCompile(ctxt, def);  | 
3139  | 0  |                 ctxt->am = oldam;  | 
3140  | 0  |             }  | 
3141  | 0  |             break;  | 
3142  | 0  |         case XML_RELAXNG_NOOP:  | 
3143  | 0  |             ret = xmlRelaxNGCompile(ctxt, def->content);  | 
3144  | 0  |             break;  | 
3145  | 0  |         case XML_RELAXNG_OPTIONAL:{ | 
3146  | 0  |                 xmlAutomataStatePtr oldstate = ctxt->state;  | 
3147  |  | 
  | 
3148  | 0  |                 list = def->content;  | 
3149  | 0  |                 while (list != NULL) { | 
3150  | 0  |                     xmlRelaxNGCompile(ctxt, list);  | 
3151  | 0  |                     list = list->next;  | 
3152  | 0  |                 }  | 
3153  | 0  |                 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);  | 
3154  | 0  |                 break;  | 
3155  | 0  |             }  | 
3156  | 0  |         case XML_RELAXNG_ZEROORMORE:{ | 
3157  | 0  |                 xmlAutomataStatePtr oldstate;  | 
3158  |  | 
  | 
3159  | 0  |                 ctxt->state =  | 
3160  | 0  |                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);  | 
3161  | 0  |                 oldstate = ctxt->state;  | 
3162  | 0  |                 list = def->content;  | 
3163  | 0  |                 while (list != NULL) { | 
3164  | 0  |                     xmlRelaxNGCompile(ctxt, list);  | 
3165  | 0  |                     list = list->next;  | 
3166  | 0  |                 }  | 
3167  | 0  |                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);  | 
3168  | 0  |                 ctxt->state =  | 
3169  | 0  |                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);  | 
3170  | 0  |                 break;  | 
3171  | 0  |             }  | 
3172  | 0  |         case XML_RELAXNG_ONEORMORE:{ | 
3173  | 0  |                 xmlAutomataStatePtr oldstate;  | 
3174  |  | 
  | 
3175  | 0  |                 list = def->content;  | 
3176  | 0  |                 while (list != NULL) { | 
3177  | 0  |                     xmlRelaxNGCompile(ctxt, list);  | 
3178  | 0  |                     list = list->next;  | 
3179  | 0  |                 }  | 
3180  | 0  |                 oldstate = ctxt->state;  | 
3181  | 0  |                 list = def->content;  | 
3182  | 0  |                 while (list != NULL) { | 
3183  | 0  |                     xmlRelaxNGCompile(ctxt, list);  | 
3184  | 0  |                     list = list->next;  | 
3185  | 0  |                 }  | 
3186  | 0  |                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);  | 
3187  | 0  |                 ctxt->state =  | 
3188  | 0  |                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);  | 
3189  | 0  |                 break;  | 
3190  | 0  |             }  | 
3191  | 0  |         case XML_RELAXNG_CHOICE:{ | 
3192  | 0  |                 xmlAutomataStatePtr target = NULL;  | 
3193  | 0  |                 xmlAutomataStatePtr oldstate = ctxt->state;  | 
3194  |  | 
  | 
3195  | 0  |                 list = def->content;  | 
3196  | 0  |                 while (list != NULL) { | 
3197  | 0  |                     ctxt->state = oldstate;  | 
3198  | 0  |                     ret = xmlRelaxNGCompile(ctxt, list);  | 
3199  | 0  |                     if (ret != 0)  | 
3200  | 0  |                         break;  | 
3201  | 0  |                     if (target == NULL)  | 
3202  | 0  |                         target = ctxt->state;  | 
3203  | 0  |                     else { | 
3204  | 0  |                         xmlAutomataNewEpsilon(ctxt->am, ctxt->state,  | 
3205  | 0  |                                               target);  | 
3206  | 0  |                     }  | 
3207  | 0  |                     list = list->next;  | 
3208  | 0  |                 }  | 
3209  | 0  |                 ctxt->state = target;  | 
3210  |  | 
  | 
3211  | 0  |                 break;  | 
3212  | 0  |             }  | 
3213  | 0  |         case XML_RELAXNG_REF:  | 
3214  | 0  |         case XML_RELAXNG_EXTERNALREF:  | 
3215  | 0  |         case XML_RELAXNG_PARENTREF:  | 
3216  | 0  |         case XML_RELAXNG_GROUP:  | 
3217  | 0  |         case XML_RELAXNG_DEF:  | 
3218  | 0  |             list = def->content;  | 
3219  | 0  |             while (list != NULL) { | 
3220  | 0  |                 ret = xmlRelaxNGCompile(ctxt, list);  | 
3221  | 0  |                 if (ret != 0)  | 
3222  | 0  |                     break;  | 
3223  | 0  |                 list = list->next;  | 
3224  | 0  |             }  | 
3225  | 0  |             break;  | 
3226  | 0  |         case XML_RELAXNG_TEXT:{ | 
3227  | 0  |                 xmlAutomataStatePtr oldstate;  | 
3228  |  | 
  | 
3229  | 0  |                 ctxt->state =  | 
3230  | 0  |                     xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);  | 
3231  | 0  |                 oldstate = ctxt->state;  | 
3232  | 0  |                 xmlRelaxNGCompile(ctxt, def->content);  | 
3233  | 0  |                 xmlAutomataNewTransition(ctxt->am, ctxt->state,  | 
3234  | 0  |                                          ctxt->state, BAD_CAST "#text",  | 
3235  | 0  |                                          NULL);  | 
3236  | 0  |                 ctxt->state =  | 
3237  | 0  |                     xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);  | 
3238  | 0  |                 break;  | 
3239  | 0  |             }  | 
3240  | 0  |         case XML_RELAXNG_EMPTY:  | 
3241  | 0  |             ctxt->state =  | 
3242  | 0  |                 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);  | 
3243  | 0  |             break;  | 
3244  | 0  |         case XML_RELAXNG_EXCEPT:  | 
3245  | 0  |         case XML_RELAXNG_ATTRIBUTE:  | 
3246  | 0  |         case XML_RELAXNG_INTERLEAVE:  | 
3247  | 0  |         case XML_RELAXNG_NOT_ALLOWED:  | 
3248  | 0  |         case XML_RELAXNG_DATATYPE:  | 
3249  | 0  |         case XML_RELAXNG_LIST:  | 
3250  | 0  |         case XML_RELAXNG_PARAM:  | 
3251  | 0  |         case XML_RELAXNG_VALUE:  | 
3252  |  |             /* This should not happen and generate an internal error */  | 
3253  | 0  |             fprintf(stderr, "RNG internal error trying to compile %s\n",  | 
3254  | 0  |                     xmlRelaxNGDefName(def));  | 
3255  | 0  |             break;  | 
3256  | 0  |     }  | 
3257  | 0  |     return (ret);  | 
3258  | 0  | }  | 
3259  |  |  | 
3260  |  | /**  | 
3261  |  |  * xmlRelaxNGTryCompile:  | 
3262  |  |  * ctxt:  the RelaxNG parser context  | 
3263  |  |  * @define:  the definition tree to compile  | 
3264  |  |  *  | 
3265  |  |  * Try to compile the set of definitions, it works recursively,  | 
3266  |  |  * possibly ignoring parts which cannot be compiled.  | 
3267  |  |  *  | 
3268  |  |  * Returns 0 if success and -1 in case of error  | 
3269  |  |  */  | 
3270  |  | static int  | 
3271  |  | xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)  | 
3272  | 0  | { | 
3273  | 0  |     int ret = 0;  | 
3274  | 0  |     xmlRelaxNGDefinePtr list;  | 
3275  |  | 
  | 
3276  | 0  |     if ((ctxt == NULL) || (def == NULL))  | 
3277  | 0  |         return (-1);  | 
3278  |  |  | 
3279  | 0  |     if ((def->type == XML_RELAXNG_START) ||  | 
3280  | 0  |         (def->type == XML_RELAXNG_ELEMENT)) { | 
3281  | 0  |         ret = xmlRelaxNGIsCompilable(def);  | 
3282  | 0  |         if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) { | 
3283  | 0  |             ctxt->am = NULL;  | 
3284  | 0  |             ret = xmlRelaxNGCompile(ctxt, def);  | 
3285  |  | #ifdef DEBUG_PROGRESSIVE  | 
3286  |  |             if (ret == 0) { | 
3287  |  |                 if (def->type == XML_RELAXNG_START)  | 
3288  |  |                     xmlGenericError(xmlGenericErrorContext,  | 
3289  |  |                                     "compiled the start\n");  | 
3290  |  |                 else  | 
3291  |  |                     xmlGenericError(xmlGenericErrorContext,  | 
3292  |  |                                     "compiled element %s\n", def->name);  | 
3293  |  |             } else { | 
3294  |  |                 if (def->type == XML_RELAXNG_START)  | 
3295  |  |                     xmlGenericError(xmlGenericErrorContext,  | 
3296  |  |                                     "failed to compile the start\n");  | 
3297  |  |                 else  | 
3298  |  |                     xmlGenericError(xmlGenericErrorContext,  | 
3299  |  |                                     "failed to compile element %s\n",  | 
3300  |  |                                     def->name);  | 
3301  |  |             }  | 
3302  |  | #endif  | 
3303  | 0  |             return (ret);  | 
3304  | 0  |         }  | 
3305  | 0  |     }  | 
3306  | 0  |     switch (def->type) { | 
3307  | 0  |         case XML_RELAXNG_NOOP:  | 
3308  | 0  |             ret = xmlRelaxNGTryCompile(ctxt, def->content);  | 
3309  | 0  |             break;  | 
3310  | 0  |         case XML_RELAXNG_TEXT:  | 
3311  | 0  |         case XML_RELAXNG_DATATYPE:  | 
3312  | 0  |         case XML_RELAXNG_LIST:  | 
3313  | 0  |         case XML_RELAXNG_PARAM:  | 
3314  | 0  |         case XML_RELAXNG_VALUE:  | 
3315  | 0  |         case XML_RELAXNG_EMPTY:  | 
3316  | 0  |         case XML_RELAXNG_ELEMENT:  | 
3317  | 0  |             ret = 0;  | 
3318  | 0  |             break;  | 
3319  | 0  |         case XML_RELAXNG_OPTIONAL:  | 
3320  | 0  |         case XML_RELAXNG_ZEROORMORE:  | 
3321  | 0  |         case XML_RELAXNG_ONEORMORE:  | 
3322  | 0  |         case XML_RELAXNG_CHOICE:  | 
3323  | 0  |         case XML_RELAXNG_GROUP:  | 
3324  | 0  |         case XML_RELAXNG_DEF:  | 
3325  | 0  |         case XML_RELAXNG_START:  | 
3326  | 0  |         case XML_RELAXNG_REF:  | 
3327  | 0  |         case XML_RELAXNG_EXTERNALREF:  | 
3328  | 0  |         case XML_RELAXNG_PARENTREF:  | 
3329  | 0  |             list = def->content;  | 
3330  | 0  |             while (list != NULL) { | 
3331  | 0  |                 ret = xmlRelaxNGTryCompile(ctxt, list);  | 
3332  | 0  |                 if (ret != 0)  | 
3333  | 0  |                     break;  | 
3334  | 0  |                 list = list->next;  | 
3335  | 0  |             }  | 
3336  | 0  |             break;  | 
3337  | 0  |         case XML_RELAXNG_EXCEPT:  | 
3338  | 0  |         case XML_RELAXNG_ATTRIBUTE:  | 
3339  | 0  |         case XML_RELAXNG_INTERLEAVE:  | 
3340  | 0  |         case XML_RELAXNG_NOT_ALLOWED:  | 
3341  | 0  |             ret = 0;  | 
3342  | 0  |             break;  | 
3343  | 0  |     }  | 
3344  | 0  |     return (ret);  | 
3345  | 0  | }  | 
3346  |  |  | 
3347  |  | /************************************************************************  | 
3348  |  |  *                  *  | 
3349  |  |  *      Parsing functions       *  | 
3350  |  |  *                  *  | 
3351  |  |  ************************************************************************/  | 
3352  |  |  | 
3353  |  | static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr  | 
3354  |  |                                                     ctxt, xmlNodePtr node);  | 
3355  |  | static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr  | 
3356  |  |                                                   ctxt, xmlNodePtr node);  | 
3357  |  | static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr  | 
3358  |  |                                                    ctxt, xmlNodePtr nodes,  | 
3359  |  |                                                    int group);  | 
3360  |  | static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr  | 
3361  |  |                                                   ctxt, xmlNodePtr node);  | 
3362  |  | static xmlRelaxNGPtr xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt,  | 
3363  |  |                                              xmlNodePtr node);  | 
3364  |  | static int xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,  | 
3365  |  |                                          xmlNodePtr nodes);  | 
3366  |  | static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr  | 
3367  |  |                                                     ctxt, xmlNodePtr node,  | 
3368  |  |                                                     xmlRelaxNGDefinePtr  | 
3369  |  |                                                     def);  | 
3370  |  | static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr  | 
3371  |  |                                                    ctxt, xmlNodePtr nodes);  | 
3372  |  | static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,  | 
3373  |  |                                   xmlRelaxNGDefinePtr define,  | 
3374  |  |                                   xmlNodePtr elem);  | 
3375  |  |  | 
3376  |  |  | 
3377  | 0  | #define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))  | 
3378  |  |  | 
3379  |  | /**  | 
3380  |  |  * xmlRelaxNGIsNullable:  | 
3381  |  |  * @define:  the definition to verify  | 
3382  |  |  *  | 
3383  |  |  * Check if a definition is nullable.  | 
3384  |  |  *  | 
3385  |  |  * Returns 1 if yes, 0 if no and -1 in case of error  | 
3386  |  |  */  | 
3387  |  | static int  | 
3388  |  | xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define)  | 
3389  | 0  | { | 
3390  | 0  |     int ret;  | 
3391  |  | 
  | 
3392  | 0  |     if (define == NULL)  | 
3393  | 0  |         return (-1);  | 
3394  |  |  | 
3395  | 0  |     if (define->dflags & IS_NULLABLE)  | 
3396  | 0  |         return (1);  | 
3397  | 0  |     if (define->dflags & IS_NOT_NULLABLE)  | 
3398  | 0  |         return (0);  | 
3399  | 0  |     switch (define->type) { | 
3400  | 0  |         case XML_RELAXNG_EMPTY:  | 
3401  | 0  |         case XML_RELAXNG_TEXT:  | 
3402  | 0  |             ret = 1;  | 
3403  | 0  |             break;  | 
3404  | 0  |         case XML_RELAXNG_NOOP:  | 
3405  | 0  |         case XML_RELAXNG_DEF:  | 
3406  | 0  |         case XML_RELAXNG_REF:  | 
3407  | 0  |         case XML_RELAXNG_EXTERNALREF:  | 
3408  | 0  |         case XML_RELAXNG_PARENTREF:  | 
3409  | 0  |         case XML_RELAXNG_ONEORMORE:  | 
3410  | 0  |             ret = xmlRelaxNGIsNullable(define->content);  | 
3411  | 0  |             break;  | 
3412  | 0  |         case XML_RELAXNG_EXCEPT:  | 
3413  | 0  |         case XML_RELAXNG_NOT_ALLOWED:  | 
3414  | 0  |         case XML_RELAXNG_ELEMENT:  | 
3415  | 0  |         case XML_RELAXNG_DATATYPE:  | 
3416  | 0  |         case XML_RELAXNG_PARAM:  | 
3417  | 0  |         case XML_RELAXNG_VALUE:  | 
3418  | 0  |         case XML_RELAXNG_LIST:  | 
3419  | 0  |         case XML_RELAXNG_ATTRIBUTE:  | 
3420  | 0  |             ret = 0;  | 
3421  | 0  |             break;  | 
3422  | 0  |         case XML_RELAXNG_CHOICE:{ | 
3423  | 0  |                 xmlRelaxNGDefinePtr list = define->content;  | 
3424  |  | 
  | 
3425  | 0  |                 while (list != NULL) { | 
3426  | 0  |                     ret = xmlRelaxNGIsNullable(list);  | 
3427  | 0  |                     if (ret != 0)  | 
3428  | 0  |                         goto done;  | 
3429  | 0  |                     list = list->next;  | 
3430  | 0  |                 }  | 
3431  | 0  |                 ret = 0;  | 
3432  | 0  |                 break;  | 
3433  | 0  |             }  | 
3434  | 0  |         case XML_RELAXNG_START:  | 
3435  | 0  |         case XML_RELAXNG_INTERLEAVE:  | 
3436  | 0  |         case XML_RELAXNG_GROUP:{ | 
3437  | 0  |                 xmlRelaxNGDefinePtr list = define->content;  | 
3438  |  | 
  | 
3439  | 0  |                 while (list != NULL) { | 
3440  | 0  |                     ret = xmlRelaxNGIsNullable(list);  | 
3441  | 0  |                     if (ret != 1)  | 
3442  | 0  |                         goto done;  | 
3443  | 0  |                     list = list->next;  | 
3444  | 0  |                 }  | 
3445  | 0  |                 return (1);  | 
3446  | 0  |             }  | 
3447  | 0  |         default:  | 
3448  | 0  |             return (-1);  | 
3449  | 0  |     }  | 
3450  | 0  |   done:  | 
3451  | 0  |     if (ret == 0)  | 
3452  | 0  |         define->dflags |= IS_NOT_NULLABLE;  | 
3453  | 0  |     if (ret == 1)  | 
3454  | 0  |         define->dflags |= IS_NULLABLE;  | 
3455  | 0  |     return (ret);  | 
3456  | 0  | }  | 
3457  |  |  | 
3458  |  | /**  | 
3459  |  |  * xmlRelaxNGIsBlank:  | 
3460  |  |  * @str:  a string  | 
3461  |  |  *  | 
3462  |  |  * Check if a string is ignorable c.f. 4.2. Whitespace  | 
3463  |  |  *  | 
3464  |  |  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise  | 
3465  |  |  */  | 
3466  |  | static int  | 
3467  |  | xmlRelaxNGIsBlank(xmlChar * str)  | 
3468  | 0  | { | 
3469  | 0  |     if (str == NULL)  | 
3470  | 0  |         return (1);  | 
3471  | 0  |     while (*str != 0) { | 
3472  | 0  |         if (!(IS_BLANK_CH(*str)))  | 
3473  | 0  |             return (0);  | 
3474  | 0  |         str++;  | 
3475  | 0  |     }  | 
3476  | 0  |     return (1);  | 
3477  | 0  | }  | 
3478  |  |  | 
3479  |  | /**  | 
3480  |  |  * xmlRelaxNGGetDataTypeLibrary:  | 
3481  |  |  * @ctxt:  a Relax-NG parser context  | 
3482  |  |  * @node:  the current data or value element  | 
3483  |  |  *  | 
3484  |  |  * Applies algorithm from 4.3. datatypeLibrary attribute  | 
3485  |  |  *  | 
3486  |  |  * Returns the datatypeLibrary value or NULL if not found  | 
3487  |  |  */  | 
3488  |  | static xmlChar *  | 
3489  |  | xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,  | 
3490  |  |                              xmlNodePtr node)  | 
3491  | 0  | { | 
3492  | 0  |     xmlChar *ret, *escape;  | 
3493  |  | 
  | 
3494  | 0  |     if (node == NULL)  | 
3495  | 0  |         return(NULL);  | 
3496  |  |  | 
3497  | 0  |     if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) { | 
3498  | 0  |         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");  | 
3499  | 0  |         if (ret != NULL) { | 
3500  | 0  |             if (ret[0] == 0) { | 
3501  | 0  |                 xmlFree(ret);  | 
3502  | 0  |                 return (NULL);  | 
3503  | 0  |             }  | 
3504  | 0  |             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");  | 
3505  | 0  |             if (escape == NULL) { | 
3506  | 0  |                 return (ret);  | 
3507  | 0  |             }  | 
3508  | 0  |             xmlFree(ret);  | 
3509  | 0  |             return (escape);  | 
3510  | 0  |         }  | 
3511  | 0  |     }  | 
3512  | 0  |     node = node->parent;  | 
3513  | 0  |     while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) { | 
3514  | 0  |         ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");  | 
3515  | 0  |         if (ret != NULL) { | 
3516  | 0  |             if (ret[0] == 0) { | 
3517  | 0  |                 xmlFree(ret);  | 
3518  | 0  |                 return (NULL);  | 
3519  | 0  |             }  | 
3520  | 0  |             escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");  | 
3521  | 0  |             if (escape == NULL) { | 
3522  | 0  |                 return (ret);  | 
3523  | 0  |             }  | 
3524  | 0  |             xmlFree(ret);  | 
3525  | 0  |             return (escape);  | 
3526  | 0  |         }  | 
3527  | 0  |         node = node->parent;  | 
3528  | 0  |     }  | 
3529  | 0  |     return (NULL);  | 
3530  | 0  | }  | 
3531  |  |  | 
3532  |  | /**  | 
3533  |  |  * xmlRelaxNGParseValue:  | 
3534  |  |  * @ctxt:  a Relax-NG parser context  | 
3535  |  |  * @node:  the data node.  | 
3536  |  |  *  | 
3537  |  |  * parse the content of a RelaxNG value node.  | 
3538  |  |  *  | 
3539  |  |  * Returns the definition pointer or NULL in case of error  | 
3540  |  |  */  | 
3541  |  | static xmlRelaxNGDefinePtr  | 
3542  |  | xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
3543  | 0  | { | 
3544  | 0  |     xmlRelaxNGDefinePtr def = NULL;  | 
3545  | 0  |     xmlRelaxNGTypeLibraryPtr lib = NULL;  | 
3546  | 0  |     xmlChar *type;  | 
3547  | 0  |     xmlChar *library;  | 
3548  | 0  |     int success = 0;  | 
3549  |  | 
  | 
3550  | 0  |     def = xmlRelaxNGNewDefine(ctxt, node);  | 
3551  | 0  |     if (def == NULL)  | 
3552  | 0  |         return (NULL);  | 
3553  | 0  |     def->type = XML_RELAXNG_VALUE;  | 
3554  |  | 
  | 
3555  | 0  |     type = xmlGetProp(node, BAD_CAST "type");  | 
3556  | 0  |     if (type != NULL) { | 
3557  | 0  |         xmlRelaxNGNormExtSpace(type);  | 
3558  | 0  |         if (xmlValidateNCName(type, 0)) { | 
3559  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,  | 
3560  | 0  |                        "value type '%s' is not an NCName\n", type, NULL);  | 
3561  | 0  |         }  | 
3562  | 0  |         library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);  | 
3563  | 0  |         if (library == NULL)  | 
3564  | 0  |             library =  | 
3565  | 0  |                 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");  | 
3566  |  | 
  | 
3567  | 0  |         def->name = type;  | 
3568  | 0  |         def->ns = library;  | 
3569  |  | 
  | 
3570  | 0  |         lib = (xmlRelaxNGTypeLibraryPtr)  | 
3571  | 0  |             xmlHashLookup(xmlRelaxNGRegisteredTypes, library);  | 
3572  | 0  |         if (lib == NULL) { | 
3573  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,  | 
3574  | 0  |                        "Use of unregistered type library '%s'\n", library,  | 
3575  | 0  |                        NULL);  | 
3576  | 0  |             def->data = NULL;  | 
3577  | 0  |         } else { | 
3578  | 0  |             def->data = lib;  | 
3579  | 0  |             if (lib->have == NULL) { | 
3580  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,  | 
3581  | 0  |                            "Internal error with type library '%s': no 'have'\n",  | 
3582  | 0  |                            library, NULL);  | 
3583  | 0  |             } else { | 
3584  | 0  |                 success = lib->have(lib->data, def->name);  | 
3585  | 0  |                 if (success != 1) { | 
3586  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,  | 
3587  | 0  |                                "Error type '%s' is not exported by type library '%s'\n",  | 
3588  | 0  |                                def->name, library);  | 
3589  | 0  |                 }  | 
3590  | 0  |             }  | 
3591  | 0  |         }  | 
3592  | 0  |     }  | 
3593  | 0  |     if (node->children == NULL) { | 
3594  | 0  |         def->value = xmlStrdup(BAD_CAST "");  | 
3595  | 0  |     } else if (((node->children->type != XML_TEXT_NODE) &&  | 
3596  | 0  |                 (node->children->type != XML_CDATA_SECTION_NODE)) ||  | 
3597  | 0  |                (node->children->next != NULL)) { | 
3598  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_TEXT_EXPECTED,  | 
3599  | 0  |                    "Expecting a single text value for <value>content\n",  | 
3600  | 0  |                    NULL, NULL);  | 
3601  | 0  |     } else if (def != NULL) { | 
3602  | 0  |         def->value = xmlNodeGetContent(node);  | 
3603  | 0  |         if (def->value == NULL) { | 
3604  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_VALUE_NO_CONTENT,  | 
3605  | 0  |                        "Element <value> has no content\n", NULL, NULL);  | 
3606  | 0  |         } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) { | 
3607  | 0  |             void *val = NULL;  | 
3608  |  | 
  | 
3609  | 0  |             success =  | 
3610  | 0  |                 lib->check(lib->data, def->name, def->value, &val, node);  | 
3611  | 0  |             if (success != 1) { | 
3612  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_VALUE,  | 
3613  | 0  |                            "Value '%s' is not acceptable for type '%s'\n",  | 
3614  | 0  |                            def->value, def->name);  | 
3615  | 0  |             } else { | 
3616  | 0  |                 if (val != NULL)  | 
3617  | 0  |                     def->attrs = val;  | 
3618  | 0  |             }  | 
3619  | 0  |         }  | 
3620  | 0  |     }  | 
3621  | 0  |     return (def);  | 
3622  | 0  | }  | 
3623  |  |  | 
3624  |  | /**  | 
3625  |  |  * xmlRelaxNGParseData:  | 
3626  |  |  * @ctxt:  a Relax-NG parser context  | 
3627  |  |  * @node:  the data node.  | 
3628  |  |  *  | 
3629  |  |  * parse the content of a RelaxNG data node.  | 
3630  |  |  *  | 
3631  |  |  * Returns the definition pointer or NULL in case of error  | 
3632  |  |  */  | 
3633  |  | static xmlRelaxNGDefinePtr  | 
3634  |  | xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
3635  | 0  | { | 
3636  | 0  |     xmlRelaxNGDefinePtr def = NULL, except;  | 
3637  | 0  |     xmlRelaxNGDefinePtr param, lastparam = NULL;  | 
3638  | 0  |     xmlRelaxNGTypeLibraryPtr lib;  | 
3639  | 0  |     xmlChar *type;  | 
3640  | 0  |     xmlChar *library;  | 
3641  | 0  |     xmlNodePtr content;  | 
3642  | 0  |     int tmp;  | 
3643  |  | 
  | 
3644  | 0  |     type = xmlGetProp(node, BAD_CAST "type");  | 
3645  | 0  |     if (type == NULL) { | 
3646  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_TYPE_MISSING, "data has no type\n", NULL,  | 
3647  | 0  |                    NULL);  | 
3648  | 0  |         return (NULL);  | 
3649  | 0  |     }  | 
3650  | 0  |     xmlRelaxNGNormExtSpace(type);  | 
3651  | 0  |     if (xmlValidateNCName(type, 0)) { | 
3652  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,  | 
3653  | 0  |                    "data type '%s' is not an NCName\n", type, NULL);  | 
3654  | 0  |     }  | 
3655  | 0  |     library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);  | 
3656  | 0  |     if (library == NULL)  | 
3657  | 0  |         library =  | 
3658  | 0  |             xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");  | 
3659  |  | 
  | 
3660  | 0  |     def = xmlRelaxNGNewDefine(ctxt, node);  | 
3661  | 0  |     if (def == NULL) { | 
3662  | 0  |         xmlFree(library);  | 
3663  | 0  |         xmlFree(type);  | 
3664  | 0  |         return (NULL);  | 
3665  | 0  |     }  | 
3666  | 0  |     def->type = XML_RELAXNG_DATATYPE;  | 
3667  | 0  |     def->name = type;  | 
3668  | 0  |     def->ns = library;  | 
3669  |  | 
  | 
3670  | 0  |     lib = (xmlRelaxNGTypeLibraryPtr)  | 
3671  | 0  |         xmlHashLookup(xmlRelaxNGRegisteredTypes, library);  | 
3672  | 0  |     if (lib == NULL) { | 
3673  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,  | 
3674  | 0  |                    "Use of unregistered type library '%s'\n", library,  | 
3675  | 0  |                    NULL);  | 
3676  | 0  |         def->data = NULL;  | 
3677  | 0  |     } else { | 
3678  | 0  |         def->data = lib;  | 
3679  | 0  |         if (lib->have == NULL) { | 
3680  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,  | 
3681  | 0  |                        "Internal error with type library '%s': no 'have'\n",  | 
3682  | 0  |                        library, NULL);  | 
3683  | 0  |         } else { | 
3684  | 0  |             tmp = lib->have(lib->data, def->name);  | 
3685  | 0  |             if (tmp != 1) { | 
3686  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,  | 
3687  | 0  |                            "Error type '%s' is not exported by type library '%s'\n",  | 
3688  | 0  |                            def->name, library);  | 
3689  | 0  |             } else  | 
3690  | 0  |                 if ((xmlStrEqual  | 
3691  | 0  |                      (library,  | 
3692  | 0  |                       BAD_CAST  | 
3693  | 0  |                       "http://www.w3.org/2001/XMLSchema-datatypes"))  | 
3694  | 0  |                     && ((xmlStrEqual(def->name, BAD_CAST "IDREF"))  | 
3695  | 0  |                         || (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) { | 
3696  | 0  |                 ctxt->idref = 1;  | 
3697  | 0  |             }  | 
3698  | 0  |         }  | 
3699  | 0  |     }  | 
3700  | 0  |     content = node->children;  | 
3701  |  |  | 
3702  |  |     /*  | 
3703  |  |      * Handle optional params  | 
3704  |  |      */  | 
3705  | 0  |     while (content != NULL) { | 
3706  | 0  |         if (!xmlStrEqual(content->name, BAD_CAST "param"))  | 
3707  | 0  |             break;  | 
3708  | 0  |         if (xmlStrEqual(library,  | 
3709  | 0  |                         BAD_CAST "http://relaxng.org/ns/structure/1.0")) { | 
3710  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_PARAM_FORBIDDEN,  | 
3711  | 0  |                        "Type library '%s' does not allow type parameters\n",  | 
3712  | 0  |                        library, NULL);  | 
3713  | 0  |             content = content->next;  | 
3714  | 0  |             while ((content != NULL) &&  | 
3715  | 0  |                    (xmlStrEqual(content->name, BAD_CAST "param")))  | 
3716  | 0  |                 content = content->next;  | 
3717  | 0  |         } else { | 
3718  | 0  |             param = xmlRelaxNGNewDefine(ctxt, node);  | 
3719  | 0  |             if (param != NULL) { | 
3720  | 0  |                 param->type = XML_RELAXNG_PARAM;  | 
3721  | 0  |                 param->name = xmlGetProp(content, BAD_CAST "name");  | 
3722  | 0  |                 if (param->name == NULL) { | 
3723  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_PARAM_NAME_MISSING,  | 
3724  | 0  |                                "param has no name\n", NULL, NULL);  | 
3725  | 0  |                 }  | 
3726  | 0  |                 param->value = xmlNodeGetContent(content);  | 
3727  | 0  |                 if (lastparam == NULL) { | 
3728  | 0  |                     def->attrs = lastparam = param;  | 
3729  | 0  |                 } else { | 
3730  | 0  |                     lastparam->next = param;  | 
3731  | 0  |                     lastparam = param;  | 
3732  | 0  |                 }  | 
3733  | 0  |                 if (lib != NULL) { | 
3734  | 0  |                 }  | 
3735  | 0  |             }  | 
3736  | 0  |             content = content->next;  | 
3737  | 0  |         }  | 
3738  | 0  |     }  | 
3739  |  |     /*  | 
3740  |  |      * Handle optional except  | 
3741  |  |      */  | 
3742  | 0  |     if ((content != NULL)  | 
3743  | 0  |         && (xmlStrEqual(content->name, BAD_CAST "except"))) { | 
3744  | 0  |         xmlNodePtr child;  | 
3745  | 0  |         xmlRelaxNGDefinePtr tmp2, last = NULL;  | 
3746  |  | 
  | 
3747  | 0  |         except = xmlRelaxNGNewDefine(ctxt, node);  | 
3748  | 0  |         if (except == NULL) { | 
3749  | 0  |             return (def);  | 
3750  | 0  |         }  | 
3751  | 0  |         except->type = XML_RELAXNG_EXCEPT;  | 
3752  | 0  |         child = content->children;  | 
3753  | 0  |   def->content = except;  | 
3754  | 0  |         if (child == NULL) { | 
3755  | 0  |             xmlRngPErr(ctxt, content, XML_RNGP_EXCEPT_NO_CONTENT,  | 
3756  | 0  |                        "except has no content\n", NULL, NULL);  | 
3757  | 0  |         }  | 
3758  | 0  |         while (child != NULL) { | 
3759  | 0  |             tmp2 = xmlRelaxNGParsePattern(ctxt, child);  | 
3760  | 0  |             if (tmp2 != NULL) { | 
3761  | 0  |                 if (last == NULL) { | 
3762  | 0  |                     except->content = last = tmp2;  | 
3763  | 0  |                 } else { | 
3764  | 0  |                     last->next = tmp2;  | 
3765  | 0  |                     last = tmp2;  | 
3766  | 0  |                 }  | 
3767  | 0  |             }  | 
3768  | 0  |             child = child->next;  | 
3769  | 0  |         }  | 
3770  | 0  |         content = content->next;  | 
3771  | 0  |     }  | 
3772  |  |     /*  | 
3773  |  |      * Check there is no unhandled data  | 
3774  |  |      */  | 
3775  | 0  |     if (content != NULL) { | 
3776  | 0  |         xmlRngPErr(ctxt, content, XML_RNGP_DATA_CONTENT,  | 
3777  | 0  |                    "Element data has unexpected content %s\n",  | 
3778  | 0  |                    content->name, NULL);  | 
3779  | 0  |     }  | 
3780  |  | 
  | 
3781  | 0  |     return (def);  | 
3782  | 0  | }  | 
3783  |  |  | 
3784  |  | static const xmlChar *invalidName = BAD_CAST "\1";  | 
3785  |  |  | 
3786  |  | /**  | 
3787  |  |  * xmlRelaxNGCompareNameClasses:  | 
3788  |  |  * @defs1:  the first element/attribute defs  | 
3789  |  |  * @defs2:  the second element/attribute defs  | 
3790  |  |  * @name:  the restriction on the name  | 
3791  |  |  * @ns:  the restriction on the namespace  | 
3792  |  |  *  | 
3793  |  |  * Compare the 2 lists of element definitions. The comparison is  | 
3794  |  |  * that if both lists do not accept the same QNames, it returns 1  | 
3795  |  |  * If the 2 lists can accept the same QName the comparison returns 0  | 
3796  |  |  *  | 
3797  |  |  * Returns 1 distinct, 0 if equal  | 
3798  |  |  */  | 
3799  |  | static int  | 
3800  |  | xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,  | 
3801  |  |                              xmlRelaxNGDefinePtr def2)  | 
3802  | 0  | { | 
3803  | 0  |     int ret = 1;  | 
3804  | 0  |     xmlNode node;  | 
3805  | 0  |     xmlNs ns;  | 
3806  | 0  |     xmlRelaxNGValidCtxt ctxt;  | 
3807  |  | 
  | 
3808  | 0  |     memset(&ctxt, 0, sizeof(xmlRelaxNGValidCtxt));  | 
3809  |  | 
  | 
3810  | 0  |     ctxt.flags = FLAGS_IGNORABLE | FLAGS_NOERROR;  | 
3811  |  | 
  | 
3812  | 0  |     if ((def1->type == XML_RELAXNG_ELEMENT) ||  | 
3813  | 0  |         (def1->type == XML_RELAXNG_ATTRIBUTE)) { | 
3814  | 0  |         if (def2->type == XML_RELAXNG_TEXT)  | 
3815  | 0  |             return (1);  | 
3816  | 0  |         if (def1->name != NULL) { | 
3817  | 0  |             node.name = def1->name;  | 
3818  | 0  |         } else { | 
3819  | 0  |             node.name = invalidName;  | 
3820  | 0  |         }  | 
3821  | 0  |         if (def1->ns != NULL) { | 
3822  | 0  |             if (def1->ns[0] == 0) { | 
3823  | 0  |                 node.ns = NULL;  | 
3824  | 0  |             } else { | 
3825  | 0  |           node.ns = &ns;  | 
3826  | 0  |                 ns.href = def1->ns;  | 
3827  | 0  |             }  | 
3828  | 0  |         } else { | 
3829  | 0  |             node.ns = NULL;  | 
3830  | 0  |         }  | 
3831  | 0  |         if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) { | 
3832  | 0  |             if (def1->nameClass != NULL) { | 
3833  | 0  |                 ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2);  | 
3834  | 0  |             } else { | 
3835  | 0  |                 ret = 0;  | 
3836  | 0  |             }  | 
3837  | 0  |         } else { | 
3838  | 0  |             ret = 1;  | 
3839  | 0  |         }  | 
3840  | 0  |     } else if (def1->type == XML_RELAXNG_TEXT) { | 
3841  | 0  |         if (def2->type == XML_RELAXNG_TEXT)  | 
3842  | 0  |             return (0);  | 
3843  | 0  |         return (1);  | 
3844  | 0  |     } else if (def1->type == XML_RELAXNG_EXCEPT) { | 
3845  | 0  |         ret = xmlRelaxNGCompareNameClasses(def1->content, def2);  | 
3846  | 0  |   if (ret == 0)  | 
3847  | 0  |       ret = 1;  | 
3848  | 0  |   else if (ret == 1)  | 
3849  | 0  |       ret = 0;  | 
3850  | 0  |     } else { | 
3851  | 0  |         TODO ret = 0;  | 
3852  | 0  |     }  | 
3853  | 0  |     if (ret == 0)  | 
3854  | 0  |         return (ret);  | 
3855  | 0  |     if ((def2->type == XML_RELAXNG_ELEMENT) ||  | 
3856  | 0  |         (def2->type == XML_RELAXNG_ATTRIBUTE)) { | 
3857  | 0  |         if (def2->name != NULL) { | 
3858  | 0  |             node.name = def2->name;  | 
3859  | 0  |         } else { | 
3860  | 0  |             node.name = invalidName;  | 
3861  | 0  |         }  | 
3862  | 0  |         node.ns = &ns;  | 
3863  | 0  |         if (def2->ns != NULL) { | 
3864  | 0  |             if (def2->ns[0] == 0) { | 
3865  | 0  |                 node.ns = NULL;  | 
3866  | 0  |             } else { | 
3867  | 0  |                 ns.href = def2->ns;  | 
3868  | 0  |             }  | 
3869  | 0  |         } else { | 
3870  | 0  |             ns.href = invalidName;  | 
3871  | 0  |         }  | 
3872  | 0  |         if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) { | 
3873  | 0  |             if (def2->nameClass != NULL) { | 
3874  | 0  |                 ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1);  | 
3875  | 0  |             } else { | 
3876  | 0  |                 ret = 0;  | 
3877  | 0  |             }  | 
3878  | 0  |         } else { | 
3879  | 0  |             ret = 1;  | 
3880  | 0  |         }  | 
3881  | 0  |     } else { | 
3882  | 0  |         TODO ret = 0;  | 
3883  | 0  |     }  | 
3884  |  | 
  | 
3885  | 0  |     return (ret);  | 
3886  | 0  | }  | 
3887  |  |  | 
3888  |  | /**  | 
3889  |  |  * xmlRelaxNGCompareElemDefLists:  | 
3890  |  |  * @ctxt:  a Relax-NG parser context  | 
3891  |  |  * @defs1:  the first list of element/attribute defs  | 
3892  |  |  * @defs2:  the second list of element/attribute defs  | 
3893  |  |  *  | 
3894  |  |  * Compare the 2 lists of element or attribute definitions. The comparison  | 
3895  |  |  * is that if both lists do not accept the same QNames, it returns 1  | 
3896  |  |  * If the 2 lists can accept the same QName the comparison returns 0  | 
3897  |  |  *  | 
3898  |  |  * Returns 1 distinct, 0 if equal  | 
3899  |  |  */  | 
3900  |  | static int  | 
3901  |  | xmlRelaxNGCompareElemDefLists(xmlRelaxNGParserCtxtPtr ctxt  | 
3902  |  |                               ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr * def1,  | 
3903  |  |                               xmlRelaxNGDefinePtr * def2)  | 
3904  | 0  | { | 
3905  | 0  |     xmlRelaxNGDefinePtr *basedef2 = def2;  | 
3906  |  | 
  | 
3907  | 0  |     if ((def1 == NULL) || (def2 == NULL))  | 
3908  | 0  |         return (1);  | 
3909  | 0  |     if ((*def1 == NULL) || (*def2 == NULL))  | 
3910  | 0  |         return (1);  | 
3911  | 0  |     while (*def1 != NULL) { | 
3912  | 0  |         while ((*def2) != NULL) { | 
3913  | 0  |             if (xmlRelaxNGCompareNameClasses(*def1, *def2) == 0)  | 
3914  | 0  |                 return (0);  | 
3915  | 0  |             def2++;  | 
3916  | 0  |         }  | 
3917  | 0  |         def2 = basedef2;  | 
3918  | 0  |         def1++;  | 
3919  | 0  |     }  | 
3920  | 0  |     return (1);  | 
3921  | 0  | }  | 
3922  |  |  | 
3923  |  | /**  | 
3924  |  |  * xmlRelaxNGGenerateAttributes:  | 
3925  |  |  * @ctxt:  a Relax-NG parser context  | 
3926  |  |  * @def:  the definition definition  | 
3927  |  |  *  | 
3928  |  |  * Check if the definition can only generate attributes  | 
3929  |  |  *  | 
3930  |  |  * Returns 1 if yes, 0 if no and -1 in case of error.  | 
3931  |  |  */  | 
3932  |  | static int  | 
3933  |  | xmlRelaxNGGenerateAttributes(xmlRelaxNGParserCtxtPtr ctxt,  | 
3934  |  |                              xmlRelaxNGDefinePtr def)  | 
3935  | 0  | { | 
3936  | 0  |     xmlRelaxNGDefinePtr parent, cur, tmp;  | 
3937  |  |  | 
3938  |  |     /*  | 
3939  |  |      * Don't run that check in case of error. Infinite recursion  | 
3940  |  |      * becomes possible.  | 
3941  |  |      */  | 
3942  | 0  |     if (ctxt->nbErrors != 0)  | 
3943  | 0  |         return (-1);  | 
3944  |  |  | 
3945  | 0  |     parent = NULL;  | 
3946  | 0  |     cur = def;  | 
3947  | 0  |     while (cur != NULL) { | 
3948  | 0  |         if ((cur->type == XML_RELAXNG_ELEMENT) ||  | 
3949  | 0  |             (cur->type == XML_RELAXNG_TEXT) ||  | 
3950  | 0  |             (cur->type == XML_RELAXNG_DATATYPE) ||  | 
3951  | 0  |             (cur->type == XML_RELAXNG_PARAM) ||  | 
3952  | 0  |             (cur->type == XML_RELAXNG_LIST) ||  | 
3953  | 0  |             (cur->type == XML_RELAXNG_VALUE) ||  | 
3954  | 0  |             (cur->type == XML_RELAXNG_EMPTY))  | 
3955  | 0  |             return (0);  | 
3956  | 0  |         if ((cur->type == XML_RELAXNG_CHOICE) ||  | 
3957  | 0  |             (cur->type == XML_RELAXNG_INTERLEAVE) ||  | 
3958  | 0  |             (cur->type == XML_RELAXNG_GROUP) ||  | 
3959  | 0  |             (cur->type == XML_RELAXNG_ONEORMORE) ||  | 
3960  | 0  |             (cur->type == XML_RELAXNG_ZEROORMORE) ||  | 
3961  | 0  |             (cur->type == XML_RELAXNG_OPTIONAL) ||  | 
3962  | 0  |             (cur->type == XML_RELAXNG_PARENTREF) ||  | 
3963  | 0  |             (cur->type == XML_RELAXNG_EXTERNALREF) ||  | 
3964  | 0  |             (cur->type == XML_RELAXNG_REF) ||  | 
3965  | 0  |             (cur->type == XML_RELAXNG_DEF)) { | 
3966  | 0  |             if (cur->content != NULL) { | 
3967  | 0  |                 parent = cur;  | 
3968  | 0  |                 cur = cur->content;  | 
3969  | 0  |                 tmp = cur;  | 
3970  | 0  |                 while (tmp != NULL) { | 
3971  | 0  |                     tmp->parent = parent;  | 
3972  | 0  |                     tmp = tmp->next;  | 
3973  | 0  |                 }  | 
3974  | 0  |                 continue;  | 
3975  | 0  |             }  | 
3976  | 0  |         }  | 
3977  | 0  |         if (cur == def)  | 
3978  | 0  |             break;  | 
3979  | 0  |         if (cur->next != NULL) { | 
3980  | 0  |             cur = cur->next;  | 
3981  | 0  |             continue;  | 
3982  | 0  |         }  | 
3983  | 0  |         do { | 
3984  | 0  |             cur = cur->parent;  | 
3985  | 0  |             if (cur == NULL)  | 
3986  | 0  |                 break;  | 
3987  | 0  |             if (cur == def)  | 
3988  | 0  |                 return (1);  | 
3989  | 0  |             if (cur->next != NULL) { | 
3990  | 0  |                 cur = cur->next;  | 
3991  | 0  |                 break;  | 
3992  | 0  |             }  | 
3993  | 0  |         } while (cur != NULL);  | 
3994  | 0  |     }  | 
3995  | 0  |     return (1);  | 
3996  | 0  | }  | 
3997  |  |  | 
3998  |  | /**  | 
3999  |  |  * xmlRelaxNGGetElements:  | 
4000  |  |  * @ctxt:  a Relax-NG parser context  | 
4001  |  |  * @def:  the definition definition  | 
4002  |  |  * @eora:  gather elements (0), attributes (1) or elements and text (2)  | 
4003  |  |  *  | 
4004  |  |  * Compute the list of top elements a definition can generate  | 
4005  |  |  *  | 
4006  |  |  * Returns a list of elements or NULL if none was found.  | 
4007  |  |  */  | 
4008  |  | static xmlRelaxNGDefinePtr *  | 
4009  |  | xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,  | 
4010  |  |                       xmlRelaxNGDefinePtr def, int eora)  | 
4011  | 0  | { | 
4012  | 0  |     xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp;  | 
4013  | 0  |     int len = 0;  | 
4014  | 0  |     int max = 0;  | 
4015  |  |  | 
4016  |  |     /*  | 
4017  |  |      * Don't run that check in case of error. Infinite recursion  | 
4018  |  |      * becomes possible.  | 
4019  |  |      */  | 
4020  | 0  |     if (ctxt->nbErrors != 0)  | 
4021  | 0  |         return (NULL);  | 
4022  |  |  | 
4023  | 0  |     parent = NULL;  | 
4024  | 0  |     cur = def;  | 
4025  | 0  |     while (cur != NULL) { | 
4026  | 0  |         if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||  | 
4027  | 0  |                              (cur->type == XML_RELAXNG_TEXT))) ||  | 
4028  | 0  |             ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE)) ||  | 
4029  | 0  |             ((eora == 2) && ((cur->type == XML_RELAXNG_DATATYPE) ||  | 
4030  | 0  |                        (cur->type == XML_RELAXNG_ELEMENT) ||  | 
4031  | 0  |            (cur->type == XML_RELAXNG_LIST) ||  | 
4032  | 0  |                              (cur->type == XML_RELAXNG_TEXT) ||  | 
4033  | 0  |            (cur->type == XML_RELAXNG_VALUE)))) { | 
4034  | 0  |             if (ret == NULL) { | 
4035  | 0  |                 max = 10;  | 
4036  | 0  |                 ret = (xmlRelaxNGDefinePtr *)  | 
4037  | 0  |                     xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr));  | 
4038  | 0  |                 if (ret == NULL) { | 
4039  | 0  |                     xmlRngPErrMemory(ctxt, "getting element list\n");  | 
4040  | 0  |                     return (NULL);  | 
4041  | 0  |                 }  | 
4042  | 0  |             } else if (max <= len) { | 
4043  | 0  |           xmlRelaxNGDefinePtr *temp;  | 
4044  |  | 
  | 
4045  | 0  |                 max *= 2;  | 
4046  | 0  |                 temp = xmlRealloc(ret,  | 
4047  | 0  |                                (max + 1) * sizeof(xmlRelaxNGDefinePtr));  | 
4048  | 0  |                 if (temp == NULL) { | 
4049  | 0  |                     xmlRngPErrMemory(ctxt, "getting element list\n");  | 
4050  | 0  |         xmlFree(ret);  | 
4051  | 0  |                     return (NULL);  | 
4052  | 0  |                 }  | 
4053  | 0  |     ret = temp;  | 
4054  | 0  |             }  | 
4055  | 0  |             ret[len++] = cur;  | 
4056  | 0  |             ret[len] = NULL;  | 
4057  | 0  |         } else if ((cur->type == XML_RELAXNG_CHOICE) ||  | 
4058  | 0  |                    (cur->type == XML_RELAXNG_INTERLEAVE) ||  | 
4059  | 0  |                    (cur->type == XML_RELAXNG_GROUP) ||  | 
4060  | 0  |                    (cur->type == XML_RELAXNG_ONEORMORE) ||  | 
4061  | 0  |                    (cur->type == XML_RELAXNG_ZEROORMORE) ||  | 
4062  | 0  |                    (cur->type == XML_RELAXNG_OPTIONAL) ||  | 
4063  | 0  |                    (cur->type == XML_RELAXNG_PARENTREF) ||  | 
4064  | 0  |                    (cur->type == XML_RELAXNG_REF) ||  | 
4065  | 0  |                    (cur->type == XML_RELAXNG_DEF) ||  | 
4066  | 0  |        (cur->type == XML_RELAXNG_EXTERNALREF)) { | 
4067  |  |             /*  | 
4068  |  |              * Don't go within elements or attributes or string values.  | 
4069  |  |              * Just gather the element top list  | 
4070  |  |              */  | 
4071  | 0  |             if (cur->content != NULL) { | 
4072  | 0  |                 parent = cur;  | 
4073  | 0  |                 cur = cur->content;  | 
4074  | 0  |                 tmp = cur;  | 
4075  | 0  |                 while (tmp != NULL) { | 
4076  | 0  |                     tmp->parent = parent;  | 
4077  | 0  |                     tmp = tmp->next;  | 
4078  | 0  |                 }  | 
4079  | 0  |                 continue;  | 
4080  | 0  |             }  | 
4081  | 0  |         }  | 
4082  | 0  |         if (cur == def)  | 
4083  | 0  |             break;  | 
4084  | 0  |         if (cur->next != NULL) { | 
4085  | 0  |             cur = cur->next;  | 
4086  | 0  |             continue;  | 
4087  | 0  |         }  | 
4088  | 0  |         do { | 
4089  | 0  |             cur = cur->parent;  | 
4090  | 0  |             if (cur == NULL)  | 
4091  | 0  |                 break;  | 
4092  | 0  |             if (cur == def)  | 
4093  | 0  |                 return (ret);  | 
4094  | 0  |             if (cur->next != NULL) { | 
4095  | 0  |                 cur = cur->next;  | 
4096  | 0  |                 break;  | 
4097  | 0  |             }  | 
4098  | 0  |         } while (cur != NULL);  | 
4099  | 0  |     }  | 
4100  | 0  |     return (ret);  | 
4101  | 0  | }  | 
4102  |  |  | 
4103  |  | /**  | 
4104  |  |  * xmlRelaxNGCheckChoiceDeterminism:  | 
4105  |  |  * @ctxt:  a Relax-NG parser context  | 
4106  |  |  * @def:  the choice definition  | 
4107  |  |  *  | 
4108  |  |  * Also used to find indeterministic pattern in choice  | 
4109  |  |  */  | 
4110  |  | static void  | 
4111  |  | xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt,  | 
4112  |  |                                  xmlRelaxNGDefinePtr def)  | 
4113  | 0  | { | 
4114  | 0  |     xmlRelaxNGDefinePtr **list;  | 
4115  | 0  |     xmlRelaxNGDefinePtr cur;  | 
4116  | 0  |     int nbchild = 0, i, j, ret;  | 
4117  | 0  |     int is_nullable = 0;  | 
4118  | 0  |     int is_indeterminist = 0;  | 
4119  | 0  |     xmlHashTablePtr triage = NULL;  | 
4120  | 0  |     int is_triable = 1;  | 
4121  |  | 
  | 
4122  | 0  |     if ((def == NULL) || (def->type != XML_RELAXNG_CHOICE))  | 
4123  | 0  |         return;  | 
4124  |  |  | 
4125  | 0  |     if (def->dflags & IS_PROCESSED)  | 
4126  | 0  |         return;  | 
4127  |  |  | 
4128  |  |     /*  | 
4129  |  |      * Don't run that check in case of error. Infinite recursion  | 
4130  |  |      * becomes possible.  | 
4131  |  |      */  | 
4132  | 0  |     if (ctxt->nbErrors != 0)  | 
4133  | 0  |         return;  | 
4134  |  |  | 
4135  | 0  |     is_nullable = xmlRelaxNGIsNullable(def);  | 
4136  |  | 
  | 
4137  | 0  |     cur = def->content;  | 
4138  | 0  |     while (cur != NULL) { | 
4139  | 0  |         nbchild++;  | 
4140  | 0  |         cur = cur->next;  | 
4141  | 0  |     }  | 
4142  |  | 
  | 
4143  | 0  |     list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *  | 
4144  | 0  |                                               sizeof(xmlRelaxNGDefinePtr  | 
4145  | 0  |                                                      *));  | 
4146  | 0  |     if (list == NULL) { | 
4147  | 0  |         xmlRngPErrMemory(ctxt, "building choice\n");  | 
4148  | 0  |         return;  | 
4149  | 0  |     }  | 
4150  | 0  |     i = 0;  | 
4151  |  |     /*  | 
4152  |  |      * a bit strong but safe  | 
4153  |  |      */  | 
4154  | 0  |     if (is_nullable == 0) { | 
4155  | 0  |         triage = xmlHashCreate(10);  | 
4156  | 0  |     } else { | 
4157  | 0  |         is_triable = 0;  | 
4158  | 0  |     }  | 
4159  | 0  |     cur = def->content;  | 
4160  | 0  |     while (cur != NULL) { | 
4161  | 0  |         list[i] = xmlRelaxNGGetElements(ctxt, cur, 0);  | 
4162  | 0  |         if ((list[i] == NULL) || (list[i][0] == NULL)) { | 
4163  | 0  |             is_triable = 0;  | 
4164  | 0  |         } else if (is_triable == 1) { | 
4165  | 0  |             xmlRelaxNGDefinePtr *tmp;  | 
4166  | 0  |             int res;  | 
4167  |  | 
  | 
4168  | 0  |             tmp = list[i];  | 
4169  | 0  |             while ((*tmp != NULL) && (is_triable == 1)) { | 
4170  | 0  |                 if ((*tmp)->type == XML_RELAXNG_TEXT) { | 
4171  | 0  |                     res = xmlHashAddEntry2(triage,  | 
4172  | 0  |                                            BAD_CAST "#text", NULL,  | 
4173  | 0  |                                            (void *) cur);  | 
4174  | 0  |                     if (res != 0)  | 
4175  | 0  |                         is_triable = -1;  | 
4176  | 0  |                 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&  | 
4177  | 0  |                            ((*tmp)->name != NULL)) { | 
4178  | 0  |                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))  | 
4179  | 0  |                         res = xmlHashAddEntry2(triage,  | 
4180  | 0  |                                                (*tmp)->name, NULL,  | 
4181  | 0  |                                                (void *) cur);  | 
4182  | 0  |                     else  | 
4183  | 0  |                         res = xmlHashAddEntry2(triage,  | 
4184  | 0  |                                                (*tmp)->name, (*tmp)->ns,  | 
4185  | 0  |                                                (void *) cur);  | 
4186  | 0  |                     if (res != 0)  | 
4187  | 0  |                         is_triable = -1;  | 
4188  | 0  |                 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) { | 
4189  | 0  |                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))  | 
4190  | 0  |                         res = xmlHashAddEntry2(triage,  | 
4191  | 0  |                                                BAD_CAST "#any", NULL,  | 
4192  | 0  |                                                (void *) cur);  | 
4193  | 0  |                     else  | 
4194  | 0  |                         res = xmlHashAddEntry2(triage,  | 
4195  | 0  |                                                BAD_CAST "#any", (*tmp)->ns,  | 
4196  | 0  |                                                (void *) cur);  | 
4197  | 0  |                     if (res != 0)  | 
4198  | 0  |                         is_triable = -1;  | 
4199  | 0  |                 } else { | 
4200  | 0  |                     is_triable = -1;  | 
4201  | 0  |                 }  | 
4202  | 0  |                 tmp++;  | 
4203  | 0  |             }  | 
4204  | 0  |         }  | 
4205  | 0  |         i++;  | 
4206  | 0  |         cur = cur->next;  | 
4207  | 0  |     }  | 
4208  |  | 
  | 
4209  | 0  |     for (i = 0; i < nbchild; i++) { | 
4210  | 0  |         if (list[i] == NULL)  | 
4211  | 0  |             continue;  | 
4212  | 0  |         for (j = 0; j < i; j++) { | 
4213  | 0  |             if (list[j] == NULL)  | 
4214  | 0  |                 continue;  | 
4215  | 0  |             ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);  | 
4216  | 0  |             if (ret == 0) { | 
4217  | 0  |                 is_indeterminist = 1;  | 
4218  | 0  |             }  | 
4219  | 0  |         }  | 
4220  | 0  |     }  | 
4221  | 0  |     for (i = 0; i < nbchild; i++) { | 
4222  | 0  |         if (list[i] != NULL)  | 
4223  | 0  |             xmlFree(list[i]);  | 
4224  | 0  |     }  | 
4225  |  | 
  | 
4226  | 0  |     xmlFree(list);  | 
4227  | 0  |     if (is_indeterminist) { | 
4228  | 0  |         def->dflags |= IS_INDETERMINIST;  | 
4229  | 0  |     }  | 
4230  | 0  |     if (is_triable == 1) { | 
4231  | 0  |         def->dflags |= IS_TRIABLE;  | 
4232  | 0  |         def->data = triage;  | 
4233  | 0  |     } else if (triage != NULL) { | 
4234  | 0  |         xmlHashFree(triage, NULL);  | 
4235  | 0  |     }  | 
4236  | 0  |     def->dflags |= IS_PROCESSED;  | 
4237  | 0  | }  | 
4238  |  |  | 
4239  |  | /**  | 
4240  |  |  * xmlRelaxNGCheckGroupAttrs:  | 
4241  |  |  * @ctxt:  a Relax-NG parser context  | 
4242  |  |  * @def:  the group definition  | 
4243  |  |  *  | 
4244  |  |  * Detects violations of rule 7.3  | 
4245  |  |  */  | 
4246  |  | static void  | 
4247  |  | xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,  | 
4248  |  |                           xmlRelaxNGDefinePtr def)  | 
4249  | 0  | { | 
4250  | 0  |     xmlRelaxNGDefinePtr **list;  | 
4251  | 0  |     xmlRelaxNGDefinePtr cur;  | 
4252  | 0  |     int nbchild = 0, i, j, ret;  | 
4253  |  | 
  | 
4254  | 0  |     if ((def == NULL) ||  | 
4255  | 0  |         ((def->type != XML_RELAXNG_GROUP) &&  | 
4256  | 0  |          (def->type != XML_RELAXNG_ELEMENT)))  | 
4257  | 0  |         return;  | 
4258  |  |  | 
4259  | 0  |     if (def->dflags & IS_PROCESSED)  | 
4260  | 0  |         return;  | 
4261  |  |  | 
4262  |  |     /*  | 
4263  |  |      * Don't run that check in case of error. Infinite recursion  | 
4264  |  |      * becomes possible.  | 
4265  |  |      */  | 
4266  | 0  |     if (ctxt->nbErrors != 0)  | 
4267  | 0  |         return;  | 
4268  |  |  | 
4269  | 0  |     cur = def->attrs;  | 
4270  | 0  |     while (cur != NULL) { | 
4271  | 0  |         nbchild++;  | 
4272  | 0  |         cur = cur->next;  | 
4273  | 0  |     }  | 
4274  | 0  |     cur = def->content;  | 
4275  | 0  |     while (cur != NULL) { | 
4276  | 0  |         nbchild++;  | 
4277  | 0  |         cur = cur->next;  | 
4278  | 0  |     }  | 
4279  |  | 
  | 
4280  | 0  |     list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *  | 
4281  | 0  |                                               sizeof(xmlRelaxNGDefinePtr  | 
4282  | 0  |                                                      *));  | 
4283  | 0  |     if (list == NULL) { | 
4284  | 0  |         xmlRngPErrMemory(ctxt, "building group\n");  | 
4285  | 0  |         return;  | 
4286  | 0  |     }  | 
4287  | 0  |     i = 0;  | 
4288  | 0  |     cur = def->attrs;  | 
4289  | 0  |     while (cur != NULL) { | 
4290  | 0  |         list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);  | 
4291  | 0  |         i++;  | 
4292  | 0  |         cur = cur->next;  | 
4293  | 0  |     }  | 
4294  | 0  |     cur = def->content;  | 
4295  | 0  |     while (cur != NULL) { | 
4296  | 0  |         list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);  | 
4297  | 0  |         i++;  | 
4298  | 0  |         cur = cur->next;  | 
4299  | 0  |     }  | 
4300  |  | 
  | 
4301  | 0  |     for (i = 0; i < nbchild; i++) { | 
4302  | 0  |         if (list[i] == NULL)  | 
4303  | 0  |             continue;  | 
4304  | 0  |         for (j = 0; j < i; j++) { | 
4305  | 0  |             if (list[j] == NULL)  | 
4306  | 0  |                 continue;  | 
4307  | 0  |             ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);  | 
4308  | 0  |             if (ret == 0) { | 
4309  | 0  |                 xmlRngPErr(ctxt, def->node, XML_RNGP_GROUP_ATTR_CONFLICT,  | 
4310  | 0  |                            "Attributes conflicts in group\n", NULL, NULL);  | 
4311  | 0  |             }  | 
4312  | 0  |         }  | 
4313  | 0  |     }  | 
4314  | 0  |     for (i = 0; i < nbchild; i++) { | 
4315  | 0  |         if (list[i] != NULL)  | 
4316  | 0  |             xmlFree(list[i]);  | 
4317  | 0  |     }  | 
4318  |  | 
  | 
4319  | 0  |     xmlFree(list);  | 
4320  | 0  |     def->dflags |= IS_PROCESSED;  | 
4321  | 0  | }  | 
4322  |  |  | 
4323  |  | /**  | 
4324  |  |  * xmlRelaxNGComputeInterleaves:  | 
4325  |  |  * @def:  the interleave definition  | 
4326  |  |  * @ctxt:  a Relax-NG parser context  | 
4327  |  |  * @name:  the definition name  | 
4328  |  |  *  | 
4329  |  |  * A lot of work for preprocessing interleave definitions  | 
4330  |  |  * is potentially needed to get a decent execution speed at runtime  | 
4331  |  |  *   - trying to get a total order on the element nodes generated  | 
4332  |  |  *     by the interleaves, order the list of interleave definitions  | 
4333  |  |  *     following that order.  | 
4334  |  |  *   - if <text/> is used to handle mixed content, it is better to  | 
4335  |  |  *     flag this in the define and simplify the runtime checking  | 
4336  |  |  *     algorithm  | 
4337  |  |  */  | 
4338  |  | static void  | 
4339  |  | xmlRelaxNGComputeInterleaves(void *payload, void *data,  | 
4340  |  |                              const xmlChar * name ATTRIBUTE_UNUSED)  | 
4341  | 0  | { | 
4342  | 0  |     xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;  | 
4343  | 0  |     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;  | 
4344  | 0  |     xmlRelaxNGDefinePtr cur, *tmp;  | 
4345  |  | 
  | 
4346  | 0  |     xmlRelaxNGPartitionPtr partitions = NULL;  | 
4347  | 0  |     xmlRelaxNGInterleaveGroupPtr *groups = NULL;  | 
4348  | 0  |     xmlRelaxNGInterleaveGroupPtr group;  | 
4349  | 0  |     int i, j, ret, res;  | 
4350  | 0  |     int nbgroups = 0;  | 
4351  | 0  |     int nbchild = 0;  | 
4352  | 0  |     int is_mixed = 0;  | 
4353  | 0  |     int is_determinist = 1;  | 
4354  |  |  | 
4355  |  |     /*  | 
4356  |  |      * Don't run that check in case of error. Infinite recursion  | 
4357  |  |      * becomes possible.  | 
4358  |  |      */  | 
4359  | 0  |     if (ctxt->nbErrors != 0)  | 
4360  | 0  |         return;  | 
4361  |  |  | 
4362  |  | #ifdef DEBUG_INTERLEAVE  | 
4363  |  |     xmlGenericError(xmlGenericErrorContext,  | 
4364  |  |                     "xmlRelaxNGComputeInterleaves(%s)\n", name);  | 
4365  |  | #endif  | 
4366  | 0  |     cur = def->content;  | 
4367  | 0  |     while (cur != NULL) { | 
4368  | 0  |         nbchild++;  | 
4369  | 0  |         cur = cur->next;  | 
4370  | 0  |     }  | 
4371  |  | 
  | 
4372  |  | #ifdef DEBUG_INTERLEAVE  | 
4373  |  |     xmlGenericError(xmlGenericErrorContext, "  %d child\n", nbchild);  | 
4374  |  | #endif  | 
4375  | 0  |     groups = (xmlRelaxNGInterleaveGroupPtr *)  | 
4376  | 0  |         xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr));  | 
4377  | 0  |     if (groups == NULL)  | 
4378  | 0  |         goto error;  | 
4379  | 0  |     cur = def->content;  | 
4380  | 0  |     while (cur != NULL) { | 
4381  | 0  |         groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr)  | 
4382  | 0  |             xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup));  | 
4383  | 0  |         if (groups[nbgroups] == NULL)  | 
4384  | 0  |             goto error;  | 
4385  | 0  |         if (cur->type == XML_RELAXNG_TEXT)  | 
4386  | 0  |             is_mixed++;  | 
4387  | 0  |         groups[nbgroups]->rule = cur;  | 
4388  | 0  |         groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 2);  | 
4389  | 0  |         groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);  | 
4390  | 0  |         nbgroups++;  | 
4391  | 0  |         cur = cur->next;  | 
4392  | 0  |     }  | 
4393  |  | #ifdef DEBUG_INTERLEAVE  | 
4394  |  |     xmlGenericError(xmlGenericErrorContext, "  %d groups\n", nbgroups);  | 
4395  |  | #endif  | 
4396  |  |  | 
4397  |  |     /*  | 
4398  |  |      * Let's check that all rules makes a partitions according to 7.4  | 
4399  |  |      */  | 
4400  | 0  |     partitions = (xmlRelaxNGPartitionPtr)  | 
4401  | 0  |         xmlMalloc(sizeof(xmlRelaxNGPartition));  | 
4402  | 0  |     if (partitions == NULL)  | 
4403  | 0  |         goto error;  | 
4404  | 0  |     memset(partitions, 0, sizeof(xmlRelaxNGPartition));  | 
4405  | 0  |     partitions->nbgroups = nbgroups;  | 
4406  | 0  |     partitions->triage = xmlHashCreate(nbgroups);  | 
4407  | 0  |     for (i = 0; i < nbgroups; i++) { | 
4408  | 0  |         group = groups[i];  | 
4409  | 0  |         for (j = i + 1; j < nbgroups; j++) { | 
4410  | 0  |             if (groups[j] == NULL)  | 
4411  | 0  |                 continue;  | 
4412  |  |  | 
4413  | 0  |             ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs,  | 
4414  | 0  |                                                 groups[j]->defs);  | 
4415  | 0  |             if (ret == 0) { | 
4416  | 0  |                 xmlRngPErr(ctxt, def->node, XML_RNGP_ELEM_TEXT_CONFLICT,  | 
4417  | 0  |                            "Element or text conflicts in interleave\n",  | 
4418  | 0  |                            NULL, NULL);  | 
4419  | 0  |             }  | 
4420  | 0  |             ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs,  | 
4421  | 0  |                                                 groups[j]->attrs);  | 
4422  | 0  |             if (ret == 0) { | 
4423  | 0  |                 xmlRngPErr(ctxt, def->node, XML_RNGP_ATTR_CONFLICT,  | 
4424  | 0  |                            "Attributes conflicts in interleave\n", NULL,  | 
4425  | 0  |                            NULL);  | 
4426  | 0  |             }  | 
4427  | 0  |         }  | 
4428  | 0  |         tmp = group->defs;  | 
4429  | 0  |         if ((tmp != NULL) && (*tmp != NULL)) { | 
4430  | 0  |             while (*tmp != NULL) { | 
4431  | 0  |                 if ((*tmp)->type == XML_RELAXNG_TEXT) { | 
4432  | 0  |                     res = xmlHashAddEntry2(partitions->triage,  | 
4433  | 0  |                                            BAD_CAST "#text", NULL,  | 
4434  | 0  |                                            (void *) (ptrdiff_t) (i + 1));  | 
4435  | 0  |                     if (res != 0)  | 
4436  | 0  |                         is_determinist = -1;  | 
4437  | 0  |                 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&  | 
4438  | 0  |                            ((*tmp)->name != NULL)) { | 
4439  | 0  |                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))  | 
4440  | 0  |                         res = xmlHashAddEntry2(partitions->triage,  | 
4441  | 0  |                                                (*tmp)->name, NULL,  | 
4442  | 0  |                                                (void *) (ptrdiff_t) (i + 1));  | 
4443  | 0  |                     else  | 
4444  | 0  |                         res = xmlHashAddEntry2(partitions->triage,  | 
4445  | 0  |                                                (*tmp)->name, (*tmp)->ns,  | 
4446  | 0  |                                                (void *) (ptrdiff_t) (i + 1));  | 
4447  | 0  |                     if (res != 0)  | 
4448  | 0  |                         is_determinist = -1;  | 
4449  | 0  |                 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) { | 
4450  | 0  |                     if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))  | 
4451  | 0  |                         res = xmlHashAddEntry2(partitions->triage,  | 
4452  | 0  |                                                BAD_CAST "#any", NULL,  | 
4453  | 0  |                                                (void *) (ptrdiff_t) (i + 1));  | 
4454  | 0  |                     else  | 
4455  | 0  |                         res = xmlHashAddEntry2(partitions->triage,  | 
4456  | 0  |                                                BAD_CAST "#any", (*tmp)->ns,  | 
4457  | 0  |                                                (void *) (ptrdiff_t) (i + 1));  | 
4458  | 0  |                     if ((*tmp)->nameClass != NULL)  | 
4459  | 0  |                         is_determinist = 2;  | 
4460  | 0  |                     if (res != 0)  | 
4461  | 0  |                         is_determinist = -1;  | 
4462  | 0  |                 } else { | 
4463  | 0  |                     is_determinist = -1;  | 
4464  | 0  |                 }  | 
4465  | 0  |                 tmp++;  | 
4466  | 0  |             }  | 
4467  | 0  |         } else { | 
4468  | 0  |             is_determinist = 0;  | 
4469  | 0  |         }  | 
4470  | 0  |     }  | 
4471  | 0  |     partitions->groups = groups;  | 
4472  |  |  | 
4473  |  |     /*  | 
4474  |  |      * and save the partition list back in the def  | 
4475  |  |      */  | 
4476  | 0  |     def->data = partitions;  | 
4477  | 0  |     if (is_mixed != 0)  | 
4478  | 0  |         def->dflags |= IS_MIXED;  | 
4479  | 0  |     if (is_determinist == 1)  | 
4480  | 0  |         partitions->flags = IS_DETERMINIST;  | 
4481  | 0  |     if (is_determinist == 2)  | 
4482  | 0  |         partitions->flags = IS_DETERMINIST | IS_NEEDCHECK;  | 
4483  | 0  |     return;  | 
4484  |  |  | 
4485  | 0  |   error:  | 
4486  | 0  |     xmlRngPErrMemory(ctxt, "in interleave computation\n");  | 
4487  | 0  |     if (groups != NULL) { | 
4488  | 0  |         for (i = 0; i < nbgroups; i++)  | 
4489  | 0  |             if (groups[i] != NULL) { | 
4490  | 0  |                 if (groups[i]->defs != NULL)  | 
4491  | 0  |                     xmlFree(groups[i]->defs);  | 
4492  | 0  |                 xmlFree(groups[i]);  | 
4493  | 0  |             }  | 
4494  | 0  |         xmlFree(groups);  | 
4495  | 0  |     }  | 
4496  | 0  |     xmlRelaxNGFreePartition(partitions);  | 
4497  | 0  | }  | 
4498  |  |  | 
4499  |  | /**  | 
4500  |  |  * xmlRelaxNGParseInterleave:  | 
4501  |  |  * @ctxt:  a Relax-NG parser context  | 
4502  |  |  * @node:  the data node.  | 
4503  |  |  *  | 
4504  |  |  * parse the content of a RelaxNG interleave node.  | 
4505  |  |  *  | 
4506  |  |  * Returns the definition pointer or NULL in case of error  | 
4507  |  |  */  | 
4508  |  | static xmlRelaxNGDefinePtr  | 
4509  |  | xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
4510  | 0  | { | 
4511  | 0  |     xmlRelaxNGDefinePtr def = NULL;  | 
4512  | 0  |     xmlRelaxNGDefinePtr last = NULL, cur;  | 
4513  | 0  |     xmlNodePtr child;  | 
4514  |  | 
  | 
4515  | 0  |     def = xmlRelaxNGNewDefine(ctxt, node);  | 
4516  | 0  |     if (def == NULL) { | 
4517  | 0  |         return (NULL);  | 
4518  | 0  |     }  | 
4519  | 0  |     def->type = XML_RELAXNG_INTERLEAVE;  | 
4520  |  | 
  | 
4521  | 0  |     if (ctxt->interleaves == NULL)  | 
4522  | 0  |         ctxt->interleaves = xmlHashCreate(10);  | 
4523  | 0  |     if (ctxt->interleaves == NULL) { | 
4524  | 0  |         xmlRngPErrMemory(ctxt, "create interleaves\n");  | 
4525  | 0  |     } else { | 
4526  | 0  |         char name[32];  | 
4527  |  | 
  | 
4528  | 0  |         snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++);  | 
4529  | 0  |         if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) { | 
4530  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_ADD,  | 
4531  | 0  |                        "Failed to add %s to hash table\n",  | 
4532  | 0  |            (const xmlChar *) name, NULL);  | 
4533  | 0  |         }  | 
4534  | 0  |     }  | 
4535  | 0  |     child = node->children;  | 
4536  | 0  |     if (child == NULL) { | 
4537  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_NO_CONTENT,  | 
4538  | 0  |                    "Element interleave is empty\n", NULL, NULL);  | 
4539  | 0  |     }  | 
4540  | 0  |     while (child != NULL) { | 
4541  | 0  |         if (IS_RELAXNG(child, "element")) { | 
4542  | 0  |             cur = xmlRelaxNGParseElement(ctxt, child);  | 
4543  | 0  |         } else { | 
4544  | 0  |             cur = xmlRelaxNGParsePattern(ctxt, child);  | 
4545  | 0  |         }  | 
4546  | 0  |         if (cur != NULL) { | 
4547  | 0  |             cur->parent = def;  | 
4548  | 0  |             if (last == NULL) { | 
4549  | 0  |                 def->content = last = cur;  | 
4550  | 0  |             } else { | 
4551  | 0  |                 last->next = cur;  | 
4552  | 0  |                 last = cur;  | 
4553  | 0  |             }  | 
4554  | 0  |         }  | 
4555  | 0  |         child = child->next;  | 
4556  | 0  |     }  | 
4557  |  | 
  | 
4558  | 0  |     return (def);  | 
4559  | 0  | }  | 
4560  |  |  | 
4561  |  | /**  | 
4562  |  |  * xmlRelaxNGParseInclude:  | 
4563  |  |  * @ctxt:  a Relax-NG parser context  | 
4564  |  |  * @node:  the include node  | 
4565  |  |  *  | 
4566  |  |  * Integrate the content of an include node in the current grammar  | 
4567  |  |  *  | 
4568  |  |  * Returns 0 in case of success or -1 in case of error  | 
4569  |  |  */  | 
4570  |  | static int  | 
4571  |  | xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
4572  | 0  | { | 
4573  | 0  |     xmlRelaxNGIncludePtr incl;  | 
4574  | 0  |     xmlNodePtr root;  | 
4575  | 0  |     int ret = 0, tmp;  | 
4576  |  | 
  | 
4577  | 0  |     incl = node->psvi;  | 
4578  | 0  |     if (incl == NULL) { | 
4579  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_INCLUDE_EMPTY,  | 
4580  | 0  |                    "Include node has no data\n", NULL, NULL);  | 
4581  | 0  |         return (-1);  | 
4582  | 0  |     }  | 
4583  | 0  |     root = xmlDocGetRootElement(incl->doc);  | 
4584  | 0  |     if (root == NULL) { | 
4585  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, "Include document is empty\n",  | 
4586  | 0  |                    NULL, NULL);  | 
4587  | 0  |         return (-1);  | 
4588  | 0  |     }  | 
4589  | 0  |     if (!xmlStrEqual(root->name, BAD_CAST "grammar")) { | 
4590  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,  | 
4591  | 0  |                    "Include document root is not a grammar\n", NULL, NULL);  | 
4592  | 0  |         return (-1);  | 
4593  | 0  |     }  | 
4594  |  |  | 
4595  |  |     /*  | 
4596  |  |      * Merge the definition from both the include and the internal list  | 
4597  |  |      */  | 
4598  | 0  |     if (root->children != NULL) { | 
4599  | 0  |         tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children);  | 
4600  | 0  |         if (tmp != 0)  | 
4601  | 0  |             ret = -1;  | 
4602  | 0  |     }  | 
4603  | 0  |     if (node->children != NULL) { | 
4604  | 0  |         tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children);  | 
4605  | 0  |         if (tmp != 0)  | 
4606  | 0  |             ret = -1;  | 
4607  | 0  |     }  | 
4608  | 0  |     return (ret);  | 
4609  | 0  | }  | 
4610  |  |  | 
4611  |  | /**  | 
4612  |  |  * xmlRelaxNGParseDefine:  | 
4613  |  |  * @ctxt:  a Relax-NG parser context  | 
4614  |  |  * @node:  the define node  | 
4615  |  |  *  | 
4616  |  |  * parse the content of a RelaxNG define element node.  | 
4617  |  |  *  | 
4618  |  |  * Returns 0 in case of success or -1 in case of error  | 
4619  |  |  */  | 
4620  |  | static int  | 
4621  |  | xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
4622  | 0  | { | 
4623  | 0  |     xmlChar *name;  | 
4624  | 0  |     int ret = 0, tmp;  | 
4625  | 0  |     xmlRelaxNGDefinePtr def;  | 
4626  | 0  |     const xmlChar *olddefine;  | 
4627  |  | 
  | 
4628  | 0  |     name = xmlGetProp(node, BAD_CAST "name");  | 
4629  | 0  |     if (name == NULL) { | 
4630  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_NAME_MISSING,  | 
4631  | 0  |                    "define has no name\n", NULL, NULL);  | 
4632  | 0  |     } else { | 
4633  | 0  |         xmlRelaxNGNormExtSpace(name);  | 
4634  | 0  |         if (xmlValidateNCName(name, 0)) { | 
4635  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_INVALID_DEFINE_NAME,  | 
4636  | 0  |                        "define name '%s' is not an NCName\n", name, NULL);  | 
4637  | 0  |         }  | 
4638  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4639  | 0  |         if (def == NULL) { | 
4640  | 0  |             xmlFree(name);  | 
4641  | 0  |             return (-1);  | 
4642  | 0  |         }  | 
4643  | 0  |         def->type = XML_RELAXNG_DEF;  | 
4644  | 0  |         def->name = name;  | 
4645  | 0  |         if (node->children == NULL) { | 
4646  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_EMPTY,  | 
4647  | 0  |                        "define has no children\n", NULL, NULL);  | 
4648  | 0  |         } else { | 
4649  | 0  |             olddefine = ctxt->define;  | 
4650  | 0  |             ctxt->define = name;  | 
4651  | 0  |             def->content =  | 
4652  | 0  |                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);  | 
4653  | 0  |             ctxt->define = olddefine;  | 
4654  | 0  |         }  | 
4655  | 0  |         if (ctxt->grammar->defs == NULL)  | 
4656  | 0  |             ctxt->grammar->defs = xmlHashCreate(10);  | 
4657  | 0  |         if (ctxt->grammar->defs == NULL) { | 
4658  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,  | 
4659  | 0  |                        "Could not create definition hash\n", NULL, NULL);  | 
4660  | 0  |             ret = -1;  | 
4661  | 0  |         } else { | 
4662  | 0  |             tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);  | 
4663  | 0  |             if (tmp < 0) { | 
4664  | 0  |                 xmlRelaxNGDefinePtr prev;  | 
4665  |  | 
  | 
4666  | 0  |                 prev = xmlHashLookup(ctxt->grammar->defs, name);  | 
4667  | 0  |                 if (prev == NULL) { | 
4668  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,  | 
4669  | 0  |                                "Internal error on define aggregation of %s\n",  | 
4670  | 0  |                                name, NULL);  | 
4671  | 0  |                     ret = -1;  | 
4672  | 0  |                 } else { | 
4673  | 0  |                     while (prev->nextHash != NULL)  | 
4674  | 0  |                         prev = prev->nextHash;  | 
4675  | 0  |                     prev->nextHash = def;  | 
4676  | 0  |                 }  | 
4677  | 0  |             }  | 
4678  | 0  |         }  | 
4679  | 0  |     }  | 
4680  | 0  |     return (ret);  | 
4681  | 0  | }  | 
4682  |  |  | 
4683  |  | /**  | 
4684  |  |  * xmlRelaxNGParseImportRef:  | 
4685  |  |  * @payload: the parser context  | 
4686  |  |  * @data: the current grammar  | 
4687  |  |  * @name: the reference name  | 
4688  |  |  *  | 
4689  |  |  * Import import one references into the current grammar  | 
4690  |  |  */  | 
4691  |  | static void  | 
4692  | 0  | xmlRelaxNGParseImportRef(void *payload, void *data, const xmlChar *name) { | 
4693  | 0  |     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;  | 
4694  | 0  |     xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload;  | 
4695  | 0  |     int tmp;  | 
4696  |  | 
  | 
4697  | 0  |     def->dflags |= IS_EXTERNAL_REF;  | 
4698  |  | 
  | 
4699  | 0  |     tmp = xmlHashAddEntry(ctxt->grammar->refs, name, def);  | 
4700  | 0  |     if (tmp < 0) { | 
4701  | 0  |         xmlRelaxNGDefinePtr prev;  | 
4702  |  | 
  | 
4703  | 0  |         prev = (xmlRelaxNGDefinePtr)  | 
4704  | 0  |             xmlHashLookup(ctxt->grammar->refs, def->name);  | 
4705  | 0  |         if (prev == NULL) { | 
4706  | 0  |             if (def->name != NULL) { | 
4707  | 0  |                 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,  | 
4708  | 0  |                            "Error refs definitions '%s'\n",  | 
4709  | 0  |                            def->name, NULL);  | 
4710  | 0  |             } else { | 
4711  | 0  |                 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,  | 
4712  | 0  |                            "Error refs definitions\n",  | 
4713  | 0  |                            NULL, NULL);  | 
4714  | 0  |             }  | 
4715  | 0  |         } else { | 
4716  | 0  |             def->nextHash = prev->nextHash;  | 
4717  | 0  |             prev->nextHash = def;  | 
4718  | 0  |         }  | 
4719  | 0  |     }  | 
4720  | 0  | }  | 
4721  |  |  | 
4722  |  | /**  | 
4723  |  |  * xmlRelaxNGParseImportRefs:  | 
4724  |  |  * @ctxt: the parser context  | 
4725  |  |  * @grammar: the sub grammar  | 
4726  |  |  *  | 
4727  |  |  * Import references from the subgrammar into the current grammar  | 
4728  |  |  *  | 
4729  |  |  * Returns 0 in case of success, -1 in case of failure  | 
4730  |  |  */  | 
4731  |  | static int  | 
4732  |  | xmlRelaxNGParseImportRefs(xmlRelaxNGParserCtxtPtr ctxt,  | 
4733  | 0  |                           xmlRelaxNGGrammarPtr grammar) { | 
4734  | 0  |     if ((ctxt == NULL) || (grammar == NULL) || (ctxt->grammar == NULL))  | 
4735  | 0  |         return(-1);  | 
4736  | 0  |     if (grammar->refs == NULL)  | 
4737  | 0  |         return(0);  | 
4738  | 0  |     if (ctxt->grammar->refs == NULL)  | 
4739  | 0  |         ctxt->grammar->refs = xmlHashCreate(10);  | 
4740  | 0  |     if (ctxt->grammar->refs == NULL) { | 
4741  | 0  |         xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED,  | 
4742  | 0  |                    "Could not create references hash\n", NULL, NULL);  | 
4743  | 0  |         return(-1);  | 
4744  | 0  |     }  | 
4745  | 0  |     xmlHashScan(grammar->refs, xmlRelaxNGParseImportRef, ctxt);  | 
4746  | 0  |     return(0);  | 
4747  | 0  | }  | 
4748  |  |  | 
4749  |  | /**  | 
4750  |  |  * xmlRelaxNGProcessExternalRef:  | 
4751  |  |  * @ctxt: the parser context  | 
4752  |  |  * @node:  the externalRef node  | 
4753  |  |  *  | 
4754  |  |  * Process and compile an externalRef node  | 
4755  |  |  *  | 
4756  |  |  * Returns the xmlRelaxNGDefinePtr or NULL in case of error  | 
4757  |  |  */  | 
4758  |  | static xmlRelaxNGDefinePtr  | 
4759  |  | xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
4760  | 0  | { | 
4761  | 0  |     xmlRelaxNGDocumentPtr docu;  | 
4762  | 0  |     xmlNodePtr root, tmp;  | 
4763  | 0  |     xmlChar *ns;  | 
4764  | 0  |     int newNs = 0, oldflags;  | 
4765  | 0  |     xmlRelaxNGDefinePtr def;  | 
4766  |  | 
  | 
4767  | 0  |     docu = node->psvi;  | 
4768  | 0  |     if (docu != NULL) { | 
4769  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4770  | 0  |         if (def == NULL)  | 
4771  | 0  |             return (NULL);  | 
4772  | 0  |         def->type = XML_RELAXNG_EXTERNALREF;  | 
4773  |  | 
  | 
4774  | 0  |         if (docu->content == NULL) { | 
4775  |  |             /*  | 
4776  |  |              * Then do the parsing for good  | 
4777  |  |              */  | 
4778  | 0  |             root = xmlDocGetRootElement(docu->doc);  | 
4779  | 0  |             if (root == NULL) { | 
4780  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_EXTERNALREF_EMTPY,  | 
4781  | 0  |                            "xmlRelaxNGParse: %s is empty\n", ctxt->URL,  | 
4782  | 0  |                            NULL);  | 
4783  | 0  |                 return (NULL);  | 
4784  | 0  |             }  | 
4785  |  |             /*  | 
4786  |  |              * ns transmission rules  | 
4787  |  |              */  | 
4788  | 0  |             ns = xmlGetProp(root, BAD_CAST "ns");  | 
4789  | 0  |             if (ns == NULL) { | 
4790  | 0  |                 tmp = node;  | 
4791  | 0  |                 while ((tmp != NULL) && (tmp->type == XML_ELEMENT_NODE)) { | 
4792  | 0  |                     ns = xmlGetProp(tmp, BAD_CAST "ns");  | 
4793  | 0  |                     if (ns != NULL) { | 
4794  | 0  |                         break;  | 
4795  | 0  |                     }  | 
4796  | 0  |                     tmp = tmp->parent;  | 
4797  | 0  |                 }  | 
4798  | 0  |                 if (ns != NULL) { | 
4799  | 0  |                     xmlSetProp(root, BAD_CAST "ns", ns);  | 
4800  | 0  |                     newNs = 1;  | 
4801  | 0  |                     xmlFree(ns);  | 
4802  | 0  |                 }  | 
4803  | 0  |             } else { | 
4804  | 0  |                 xmlFree(ns);  | 
4805  | 0  |             }  | 
4806  |  |  | 
4807  |  |             /*  | 
4808  |  |              * Parsing to get a precompiled schemas.  | 
4809  |  |              */  | 
4810  | 0  |             oldflags = ctxt->flags;  | 
4811  | 0  |             ctxt->flags |= XML_RELAXNG_IN_EXTERNALREF;  | 
4812  | 0  |             docu->schema = xmlRelaxNGParseDocument(ctxt, root);  | 
4813  | 0  |             ctxt->flags = oldflags;  | 
4814  | 0  |             if ((docu->schema != NULL) &&  | 
4815  | 0  |                 (docu->schema->topgrammar != NULL)) { | 
4816  | 0  |                 docu->content = docu->schema->topgrammar->start;  | 
4817  | 0  |                 if (docu->schema->topgrammar->refs)  | 
4818  | 0  |                     xmlRelaxNGParseImportRefs(ctxt, docu->schema->topgrammar);  | 
4819  | 0  |             }  | 
4820  |  |  | 
4821  |  |             /*  | 
4822  |  |              * the externalRef may be reused in a different ns context  | 
4823  |  |              */  | 
4824  | 0  |             if (newNs == 1) { | 
4825  | 0  |                 xmlUnsetProp(root, BAD_CAST "ns");  | 
4826  | 0  |             }  | 
4827  | 0  |         }  | 
4828  | 0  |         def->content = docu->content;  | 
4829  | 0  |     } else { | 
4830  | 0  |         def = NULL;  | 
4831  | 0  |     }  | 
4832  | 0  |     return (def);  | 
4833  | 0  | }  | 
4834  |  |  | 
4835  |  | /**  | 
4836  |  |  * xmlRelaxNGParsePattern:  | 
4837  |  |  * @ctxt:  a Relax-NG parser context  | 
4838  |  |  * @node:  the pattern node.  | 
4839  |  |  *  | 
4840  |  |  * parse the content of a RelaxNG pattern node.  | 
4841  |  |  *  | 
4842  |  |  * Returns the definition pointer or NULL in case of error or if no  | 
4843  |  |  *     pattern is generated.  | 
4844  |  |  */  | 
4845  |  | static xmlRelaxNGDefinePtr  | 
4846  |  | xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
4847  | 0  | { | 
4848  | 0  |     xmlRelaxNGDefinePtr def = NULL;  | 
4849  |  | 
  | 
4850  | 0  |     if (node == NULL) { | 
4851  | 0  |         return (NULL);  | 
4852  | 0  |     }  | 
4853  | 0  |     if (IS_RELAXNG(node, "element")) { | 
4854  | 0  |         def = xmlRelaxNGParseElement(ctxt, node);  | 
4855  | 0  |     } else if (IS_RELAXNG(node, "attribute")) { | 
4856  | 0  |         def = xmlRelaxNGParseAttribute(ctxt, node);  | 
4857  | 0  |     } else if (IS_RELAXNG(node, "empty")) { | 
4858  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4859  | 0  |         if (def == NULL)  | 
4860  | 0  |             return (NULL);  | 
4861  | 0  |         def->type = XML_RELAXNG_EMPTY;  | 
4862  | 0  |         if (node->children != NULL) { | 
4863  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_NOT_EMPTY,  | 
4864  | 0  |                        "empty: had a child node\n", NULL, NULL);  | 
4865  | 0  |         }  | 
4866  | 0  |     } else if (IS_RELAXNG(node, "text")) { | 
4867  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4868  | 0  |         if (def == NULL)  | 
4869  | 0  |             return (NULL);  | 
4870  | 0  |         def->type = XML_RELAXNG_TEXT;  | 
4871  | 0  |         if (node->children != NULL) { | 
4872  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_TEXT_HAS_CHILD,  | 
4873  | 0  |                        "text: had a child node\n", NULL, NULL);  | 
4874  | 0  |         }  | 
4875  | 0  |     } else if (IS_RELAXNG(node, "zeroOrMore")) { | 
4876  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4877  | 0  |         if (def == NULL)  | 
4878  | 0  |             return (NULL);  | 
4879  | 0  |         def->type = XML_RELAXNG_ZEROORMORE;  | 
4880  | 0  |         if (node->children == NULL) { | 
4881  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,  | 
4882  | 0  |                        "Element %s is empty\n", node->name, NULL);  | 
4883  | 0  |         } else { | 
4884  | 0  |             def->content =  | 
4885  | 0  |                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);  | 
4886  | 0  |         }  | 
4887  | 0  |     } else if (IS_RELAXNG(node, "oneOrMore")) { | 
4888  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4889  | 0  |         if (def == NULL)  | 
4890  | 0  |             return (NULL);  | 
4891  | 0  |         def->type = XML_RELAXNG_ONEORMORE;  | 
4892  | 0  |         if (node->children == NULL) { | 
4893  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,  | 
4894  | 0  |                        "Element %s is empty\n", node->name, NULL);  | 
4895  | 0  |         } else { | 
4896  | 0  |             def->content =  | 
4897  | 0  |                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);  | 
4898  | 0  |         }  | 
4899  | 0  |     } else if (IS_RELAXNG(node, "optional")) { | 
4900  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4901  | 0  |         if (def == NULL)  | 
4902  | 0  |             return (NULL);  | 
4903  | 0  |         def->type = XML_RELAXNG_OPTIONAL;  | 
4904  | 0  |         if (node->children == NULL) { | 
4905  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,  | 
4906  | 0  |                        "Element %s is empty\n", node->name, NULL);  | 
4907  | 0  |         } else { | 
4908  | 0  |             def->content =  | 
4909  | 0  |                 xmlRelaxNGParsePatterns(ctxt, node->children, 1);  | 
4910  | 0  |         }  | 
4911  | 0  |     } else if (IS_RELAXNG(node, "choice")) { | 
4912  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4913  | 0  |         if (def == NULL)  | 
4914  | 0  |             return (NULL);  | 
4915  | 0  |         def->type = XML_RELAXNG_CHOICE;  | 
4916  | 0  |         if (node->children == NULL) { | 
4917  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,  | 
4918  | 0  |                        "Element %s is empty\n", node->name, NULL);  | 
4919  | 0  |         } else { | 
4920  | 0  |             def->content =  | 
4921  | 0  |                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);  | 
4922  | 0  |         }  | 
4923  | 0  |     } else if (IS_RELAXNG(node, "group")) { | 
4924  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4925  | 0  |         if (def == NULL)  | 
4926  | 0  |             return (NULL);  | 
4927  | 0  |         def->type = XML_RELAXNG_GROUP;  | 
4928  | 0  |         if (node->children == NULL) { | 
4929  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,  | 
4930  | 0  |                        "Element %s is empty\n", node->name, NULL);  | 
4931  | 0  |         } else { | 
4932  | 0  |             def->content =  | 
4933  | 0  |                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);  | 
4934  | 0  |         }  | 
4935  | 0  |     } else if (IS_RELAXNG(node, "ref")) { | 
4936  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4937  | 0  |         if (def == NULL)  | 
4938  | 0  |             return (NULL);  | 
4939  | 0  |         def->type = XML_RELAXNG_REF;  | 
4940  | 0  |         def->name = xmlGetProp(node, BAD_CAST "name");  | 
4941  | 0  |         if (def->name == NULL) { | 
4942  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_REF_NO_NAME, "ref has no name\n",  | 
4943  | 0  |                        NULL, NULL);  | 
4944  | 0  |         } else { | 
4945  | 0  |             xmlRelaxNGNormExtSpace(def->name);  | 
4946  | 0  |             if (xmlValidateNCName(def->name, 0)) { | 
4947  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_REF_NAME_INVALID,  | 
4948  | 0  |                            "ref name '%s' is not an NCName\n", def->name,  | 
4949  | 0  |                            NULL);  | 
4950  | 0  |             }  | 
4951  | 0  |         }  | 
4952  | 0  |         if (node->children != NULL) { | 
4953  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_REF_NOT_EMPTY, "ref is not empty\n",  | 
4954  | 0  |                        NULL, NULL);  | 
4955  | 0  |         }  | 
4956  | 0  |         if (ctxt->grammar->refs == NULL)  | 
4957  | 0  |             ctxt->grammar->refs = xmlHashCreate(10);  | 
4958  | 0  |         if (ctxt->grammar->refs == NULL) { | 
4959  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,  | 
4960  | 0  |                        "Could not create references hash\n", NULL, NULL);  | 
4961  | 0  |             def = NULL;  | 
4962  | 0  |         } else { | 
4963  | 0  |             int tmp;  | 
4964  |  | 
  | 
4965  | 0  |             tmp = xmlHashAddEntry(ctxt->grammar->refs, def->name, def);  | 
4966  | 0  |             if (tmp < 0) { | 
4967  | 0  |                 xmlRelaxNGDefinePtr prev;  | 
4968  |  | 
  | 
4969  | 0  |                 prev = (xmlRelaxNGDefinePtr)  | 
4970  | 0  |                     xmlHashLookup(ctxt->grammar->refs, def->name);  | 
4971  | 0  |                 if (prev == NULL) { | 
4972  | 0  |                     if (def->name != NULL) { | 
4973  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,  | 
4974  | 0  |            "Error refs definitions '%s'\n",  | 
4975  | 0  |            def->name, NULL);  | 
4976  | 0  |                     } else { | 
4977  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,  | 
4978  | 0  |            "Error refs definitions\n",  | 
4979  | 0  |            NULL, NULL);  | 
4980  | 0  |                     }  | 
4981  | 0  |                     def = NULL;  | 
4982  | 0  |                 } else { | 
4983  | 0  |                     def->nextHash = prev->nextHash;  | 
4984  | 0  |                     prev->nextHash = def;  | 
4985  | 0  |                 }  | 
4986  | 0  |             }  | 
4987  | 0  |         }  | 
4988  | 0  |     } else if (IS_RELAXNG(node, "data")) { | 
4989  | 0  |         def = xmlRelaxNGParseData(ctxt, node);  | 
4990  | 0  |     } else if (IS_RELAXNG(node, "value")) { | 
4991  | 0  |         def = xmlRelaxNGParseValue(ctxt, node);  | 
4992  | 0  |     } else if (IS_RELAXNG(node, "list")) { | 
4993  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
4994  | 0  |         if (def == NULL)  | 
4995  | 0  |             return (NULL);  | 
4996  | 0  |         def->type = XML_RELAXNG_LIST;  | 
4997  | 0  |         if (node->children == NULL) { | 
4998  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,  | 
4999  | 0  |                        "Element %s is empty\n", node->name, NULL);  | 
5000  | 0  |         } else { | 
5001  | 0  |             def->content =  | 
5002  | 0  |                 xmlRelaxNGParsePatterns(ctxt, node->children, 0);  | 
5003  | 0  |         }  | 
5004  | 0  |     } else if (IS_RELAXNG(node, "interleave")) { | 
5005  | 0  |         def = xmlRelaxNGParseInterleave(ctxt, node);  | 
5006  | 0  |     } else if (IS_RELAXNG(node, "externalRef")) { | 
5007  | 0  |         def = xmlRelaxNGProcessExternalRef(ctxt, node);  | 
5008  | 0  |     } else if (IS_RELAXNG(node, "notAllowed")) { | 
5009  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
5010  | 0  |         if (def == NULL)  | 
5011  | 0  |             return (NULL);  | 
5012  | 0  |         def->type = XML_RELAXNG_NOT_ALLOWED;  | 
5013  | 0  |         if (node->children != NULL) { | 
5014  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_NOTALLOWED_NOT_EMPTY,  | 
5015  | 0  |                        "xmlRelaxNGParse: notAllowed element is not empty\n",  | 
5016  | 0  |                        NULL, NULL);  | 
5017  | 0  |         }  | 
5018  | 0  |     } else if (IS_RELAXNG(node, "grammar")) { | 
5019  | 0  |         xmlRelaxNGGrammarPtr grammar, old;  | 
5020  | 0  |         xmlRelaxNGGrammarPtr oldparent;  | 
5021  |  | 
  | 
5022  |  | #ifdef DEBUG_GRAMMAR  | 
5023  |  |         xmlGenericError(xmlGenericErrorContext,  | 
5024  |  |                         "Found <grammar> pattern\n");  | 
5025  |  | #endif  | 
5026  |  | 
  | 
5027  | 0  |         oldparent = ctxt->parentgrammar;  | 
5028  | 0  |         old = ctxt->grammar;  | 
5029  | 0  |         ctxt->parentgrammar = old;  | 
5030  | 0  |         grammar = xmlRelaxNGParseGrammar(ctxt, node->children);  | 
5031  | 0  |         if (old != NULL) { | 
5032  | 0  |             ctxt->grammar = old;  | 
5033  | 0  |             ctxt->parentgrammar = oldparent;  | 
5034  |  | #if 0  | 
5035  |  |             if (grammar != NULL) { | 
5036  |  |                 grammar->next = old->next;  | 
5037  |  |                 old->next = grammar;  | 
5038  |  |             }  | 
5039  |  | #endif  | 
5040  | 0  |         }  | 
5041  | 0  |         if (grammar != NULL)  | 
5042  | 0  |             def = grammar->start;  | 
5043  | 0  |         else  | 
5044  | 0  |             def = NULL;  | 
5045  | 0  |     } else if (IS_RELAXNG(node, "parentRef")) { | 
5046  | 0  |         if (ctxt->parentgrammar == NULL) { | 
5047  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_PARENT,  | 
5048  | 0  |                        "Use of parentRef without a parent grammar\n", NULL,  | 
5049  | 0  |                        NULL);  | 
5050  | 0  |             return (NULL);  | 
5051  | 0  |         }  | 
5052  | 0  |         def = xmlRelaxNGNewDefine(ctxt, node);  | 
5053  | 0  |         if (def == NULL)  | 
5054  | 0  |             return (NULL);  | 
5055  | 0  |         def->type = XML_RELAXNG_PARENTREF;  | 
5056  | 0  |         def->name = xmlGetProp(node, BAD_CAST "name");  | 
5057  | 0  |         if (def->name == NULL) { | 
5058  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_NAME,  | 
5059  | 0  |                        "parentRef has no name\n", NULL, NULL);  | 
5060  | 0  |         } else { | 
5061  | 0  |             xmlRelaxNGNormExtSpace(def->name);  | 
5062  | 0  |             if (xmlValidateNCName(def->name, 0)) { | 
5063  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NAME_INVALID,  | 
5064  | 0  |                            "parentRef name '%s' is not an NCName\n",  | 
5065  | 0  |                            def->name, NULL);  | 
5066  | 0  |             }  | 
5067  | 0  |         }  | 
5068  | 0  |         if (node->children != NULL) { | 
5069  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NOT_EMPTY,  | 
5070  | 0  |                        "parentRef is not empty\n", NULL, NULL);  | 
5071  | 0  |         }  | 
5072  | 0  |         if (ctxt->parentgrammar->refs == NULL)  | 
5073  | 0  |             ctxt->parentgrammar->refs = xmlHashCreate(10);  | 
5074  | 0  |         if (ctxt->parentgrammar->refs == NULL) { | 
5075  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,  | 
5076  | 0  |                        "Could not create references hash\n", NULL, NULL);  | 
5077  | 0  |             def = NULL;  | 
5078  | 0  |         } else if (def->name != NULL) { | 
5079  | 0  |             int tmp;  | 
5080  |  | 
  | 
5081  | 0  |             tmp =  | 
5082  | 0  |                 xmlHashAddEntry(ctxt->parentgrammar->refs, def->name, def);  | 
5083  | 0  |             if (tmp < 0) { | 
5084  | 0  |                 xmlRelaxNGDefinePtr prev;  | 
5085  |  | 
  | 
5086  | 0  |                 prev = (xmlRelaxNGDefinePtr)  | 
5087  | 0  |                     xmlHashLookup(ctxt->parentgrammar->refs, def->name);  | 
5088  | 0  |                 if (prev == NULL) { | 
5089  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,  | 
5090  | 0  |                                "Internal error parentRef definitions '%s'\n",  | 
5091  | 0  |                                def->name, NULL);  | 
5092  | 0  |                     def = NULL;  | 
5093  | 0  |                 } else { | 
5094  | 0  |                     def->nextHash = prev->nextHash;  | 
5095  | 0  |                     prev->nextHash = def;  | 
5096  | 0  |                 }  | 
5097  | 0  |             }  | 
5098  | 0  |         }  | 
5099  | 0  |     } else if (IS_RELAXNG(node, "mixed")) { | 
5100  | 0  |         if (node->children == NULL) { | 
5101  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, "Mixed is empty\n",  | 
5102  | 0  |                        NULL, NULL);  | 
5103  | 0  |             def = NULL;  | 
5104  | 0  |         } else { | 
5105  | 0  |             def = xmlRelaxNGParseInterleave(ctxt, node);  | 
5106  | 0  |             if (def != NULL) { | 
5107  | 0  |                 xmlRelaxNGDefinePtr tmp;  | 
5108  |  | 
  | 
5109  | 0  |                 if ((def->content != NULL) && (def->content->next != NULL)) { | 
5110  | 0  |                     tmp = xmlRelaxNGNewDefine(ctxt, node);  | 
5111  | 0  |                     if (tmp != NULL) { | 
5112  | 0  |                         tmp->type = XML_RELAXNG_GROUP;  | 
5113  | 0  |                         tmp->content = def->content;  | 
5114  | 0  |                         def->content = tmp;  | 
5115  | 0  |                     }  | 
5116  | 0  |                 }  | 
5117  |  | 
  | 
5118  | 0  |                 tmp = xmlRelaxNGNewDefine(ctxt, node);  | 
5119  | 0  |                 if (tmp == NULL)  | 
5120  | 0  |                     return (def);  | 
5121  | 0  |                 tmp->type = XML_RELAXNG_TEXT;  | 
5122  | 0  |                 tmp->next = def->content;  | 
5123  | 0  |                 def->content = tmp;  | 
5124  | 0  |             }  | 
5125  | 0  |         }  | 
5126  | 0  |     } else { | 
5127  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_CONSTRUCT,  | 
5128  | 0  |                    "Unexpected node %s is not a pattern\n", node->name,  | 
5129  | 0  |                    NULL);  | 
5130  | 0  |         def = NULL;  | 
5131  | 0  |     }  | 
5132  | 0  |     return (def);  | 
5133  | 0  | }  | 
5134  |  |  | 
5135  |  | /**  | 
5136  |  |  * xmlRelaxNGParseAttribute:  | 
5137  |  |  * @ctxt:  a Relax-NG parser context  | 
5138  |  |  * @node:  the element node  | 
5139  |  |  *  | 
5140  |  |  * parse the content of a RelaxNG attribute node.  | 
5141  |  |  *  | 
5142  |  |  * Returns the definition pointer or NULL in case of error.  | 
5143  |  |  */  | 
5144  |  | static xmlRelaxNGDefinePtr  | 
5145  |  | xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
5146  | 0  | { | 
5147  | 0  |     xmlRelaxNGDefinePtr ret, cur;  | 
5148  | 0  |     xmlNodePtr child;  | 
5149  | 0  |     int old_flags;  | 
5150  |  | 
  | 
5151  | 0  |     ret = xmlRelaxNGNewDefine(ctxt, node);  | 
5152  | 0  |     if (ret == NULL)  | 
5153  | 0  |         return (NULL);  | 
5154  | 0  |     ret->type = XML_RELAXNG_ATTRIBUTE;  | 
5155  | 0  |     ret->parent = ctxt->def;  | 
5156  | 0  |     child = node->children;  | 
5157  | 0  |     if (child == NULL) { | 
5158  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_EMPTY,  | 
5159  | 0  |                    "xmlRelaxNGParseattribute: attribute has no children\n",  | 
5160  | 0  |                    NULL, NULL);  | 
5161  | 0  |         return (ret);  | 
5162  | 0  |     }  | 
5163  | 0  |     old_flags = ctxt->flags;  | 
5164  | 0  |     ctxt->flags |= XML_RELAXNG_IN_ATTRIBUTE;  | 
5165  | 0  |     cur = xmlRelaxNGParseNameClass(ctxt, child, ret);  | 
5166  | 0  |     if (cur != NULL)  | 
5167  | 0  |         child = child->next;  | 
5168  |  | 
  | 
5169  | 0  |     if (child != NULL) { | 
5170  | 0  |         cur = xmlRelaxNGParsePattern(ctxt, child);  | 
5171  | 0  |         if (cur != NULL) { | 
5172  | 0  |             switch (cur->type) { | 
5173  | 0  |                 case XML_RELAXNG_EMPTY:  | 
5174  | 0  |                 case XML_RELAXNG_NOT_ALLOWED:  | 
5175  | 0  |                 case XML_RELAXNG_TEXT:  | 
5176  | 0  |                 case XML_RELAXNG_ELEMENT:  | 
5177  | 0  |                 case XML_RELAXNG_DATATYPE:  | 
5178  | 0  |                 case XML_RELAXNG_VALUE:  | 
5179  | 0  |                 case XML_RELAXNG_LIST:  | 
5180  | 0  |                 case XML_RELAXNG_REF:  | 
5181  | 0  |                 case XML_RELAXNG_PARENTREF:  | 
5182  | 0  |                 case XML_RELAXNG_EXTERNALREF:  | 
5183  | 0  |                 case XML_RELAXNG_DEF:  | 
5184  | 0  |                 case XML_RELAXNG_ONEORMORE:  | 
5185  | 0  |                 case XML_RELAXNG_ZEROORMORE:  | 
5186  | 0  |                 case XML_RELAXNG_OPTIONAL:  | 
5187  | 0  |                 case XML_RELAXNG_CHOICE:  | 
5188  | 0  |                 case XML_RELAXNG_GROUP:  | 
5189  | 0  |                 case XML_RELAXNG_INTERLEAVE:  | 
5190  | 0  |                 case XML_RELAXNG_ATTRIBUTE:  | 
5191  | 0  |                     ret->content = cur;  | 
5192  | 0  |                     cur->parent = ret;  | 
5193  | 0  |                     break;  | 
5194  | 0  |                 case XML_RELAXNG_START:  | 
5195  | 0  |                 case XML_RELAXNG_PARAM:  | 
5196  | 0  |                 case XML_RELAXNG_EXCEPT:  | 
5197  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CONTENT,  | 
5198  | 0  |                                "attribute has invalid content\n", NULL,  | 
5199  | 0  |                                NULL);  | 
5200  | 0  |                     break;  | 
5201  | 0  |                 case XML_RELAXNG_NOOP:  | 
5202  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_NOOP,  | 
5203  | 0  |                                "RNG Internal error, noop found in attribute\n",  | 
5204  | 0  |                                NULL, NULL);  | 
5205  | 0  |                     break;  | 
5206  | 0  |             }  | 
5207  | 0  |         }  | 
5208  | 0  |         child = child->next;  | 
5209  | 0  |     }  | 
5210  | 0  |     if (child != NULL) { | 
5211  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CHILDREN,  | 
5212  | 0  |                    "attribute has multiple children\n", NULL, NULL);  | 
5213  | 0  |     }  | 
5214  | 0  |     ctxt->flags = old_flags;  | 
5215  | 0  |     return (ret);  | 
5216  | 0  | }  | 
5217  |  |  | 
5218  |  | /**  | 
5219  |  |  * xmlRelaxNGParseExceptNameClass:  | 
5220  |  |  * @ctxt:  a Relax-NG parser context  | 
5221  |  |  * @node:  the except node  | 
5222  |  |  * @attr:  1 if within an attribute, 0 if within an element  | 
5223  |  |  *  | 
5224  |  |  * parse the content of a RelaxNG nameClass node.  | 
5225  |  |  *  | 
5226  |  |  * Returns the definition pointer or NULL in case of error.  | 
5227  |  |  */  | 
5228  |  | static xmlRelaxNGDefinePtr  | 
5229  |  | xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt,  | 
5230  |  |                                xmlNodePtr node, int attr)  | 
5231  | 0  | { | 
5232  | 0  |     xmlRelaxNGDefinePtr ret, cur, last = NULL;  | 
5233  | 0  |     xmlNodePtr child;  | 
5234  |  | 
  | 
5235  | 0  |     if (!IS_RELAXNG(node, "except")) { | 
5236  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MISSING,  | 
5237  | 0  |                    "Expecting an except node\n", NULL, NULL);  | 
5238  | 0  |         return (NULL);  | 
5239  | 0  |     }  | 
5240  | 0  |     if (node->next != NULL) { | 
5241  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MULTIPLE,  | 
5242  | 0  |                    "exceptNameClass allows only a single except node\n",  | 
5243  | 0  |                    NULL, NULL);  | 
5244  | 0  |     }  | 
5245  | 0  |     if (node->children == NULL) { | 
5246  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_EMPTY, "except has no content\n",  | 
5247  | 0  |                    NULL, NULL);  | 
5248  | 0  |         return (NULL);  | 
5249  | 0  |     }  | 
5250  |  |  | 
5251  | 0  |     ret = xmlRelaxNGNewDefine(ctxt, node);  | 
5252  | 0  |     if (ret == NULL)  | 
5253  | 0  |         return (NULL);  | 
5254  | 0  |     ret->type = XML_RELAXNG_EXCEPT;  | 
5255  | 0  |     child = node->children;  | 
5256  | 0  |     while (child != NULL) { | 
5257  | 0  |         cur = xmlRelaxNGNewDefine(ctxt, child);  | 
5258  | 0  |         if (cur == NULL)  | 
5259  | 0  |             break;  | 
5260  | 0  |         if (attr)  | 
5261  | 0  |             cur->type = XML_RELAXNG_ATTRIBUTE;  | 
5262  | 0  |         else  | 
5263  | 0  |             cur->type = XML_RELAXNG_ELEMENT;  | 
5264  |  | 
  | 
5265  | 0  |         if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) { | 
5266  | 0  |             if (last == NULL) { | 
5267  | 0  |                 ret->content = cur;  | 
5268  | 0  |             } else { | 
5269  | 0  |                 last->next = cur;  | 
5270  | 0  |             }  | 
5271  | 0  |             last = cur;  | 
5272  | 0  |         }  | 
5273  | 0  |         child = child->next;  | 
5274  | 0  |     }  | 
5275  |  | 
  | 
5276  | 0  |     return (ret);  | 
5277  | 0  | }  | 
5278  |  |  | 
5279  |  | /**  | 
5280  |  |  * xmlRelaxNGParseNameClass:  | 
5281  |  |  * @ctxt:  a Relax-NG parser context  | 
5282  |  |  * @node:  the nameClass node  | 
5283  |  |  * @def:  the current definition  | 
5284  |  |  *  | 
5285  |  |  * parse the content of a RelaxNG nameClass node.  | 
5286  |  |  *  | 
5287  |  |  * Returns the definition pointer or NULL in case of error.  | 
5288  |  |  */  | 
5289  |  | static xmlRelaxNGDefinePtr  | 
5290  |  | xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,  | 
5291  |  |                          xmlRelaxNGDefinePtr def)  | 
5292  | 0  | { | 
5293  | 0  |     xmlRelaxNGDefinePtr ret, tmp;  | 
5294  | 0  |     xmlChar *val;  | 
5295  |  | 
  | 
5296  | 0  |     ret = def;  | 
5297  | 0  |     if ((IS_RELAXNG(node, "name")) || (IS_RELAXNG(node, "anyName")) ||  | 
5298  | 0  |         (IS_RELAXNG(node, "nsName"))) { | 
5299  | 0  |         if ((def->type != XML_RELAXNG_ELEMENT) &&  | 
5300  | 0  |             (def->type != XML_RELAXNG_ATTRIBUTE)) { | 
5301  | 0  |             ret = xmlRelaxNGNewDefine(ctxt, node);  | 
5302  | 0  |             if (ret == NULL)  | 
5303  | 0  |                 return (NULL);  | 
5304  | 0  |             ret->parent = def;  | 
5305  | 0  |             if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE)  | 
5306  | 0  |                 ret->type = XML_RELAXNG_ATTRIBUTE;  | 
5307  | 0  |             else  | 
5308  | 0  |                 ret->type = XML_RELAXNG_ELEMENT;  | 
5309  | 0  |         }  | 
5310  | 0  |     }  | 
5311  | 0  |     if (IS_RELAXNG(node, "name")) { | 
5312  | 0  |         val = xmlNodeGetContent(node);  | 
5313  | 0  |         xmlRelaxNGNormExtSpace(val);  | 
5314  | 0  |         if (xmlValidateNCName(val, 0)) { | 
5315  | 0  |       if (node->parent != NULL)  | 
5316  | 0  |     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,  | 
5317  | 0  |          "Element %s name '%s' is not an NCName\n",  | 
5318  | 0  |          node->parent->name, val);  | 
5319  | 0  |       else  | 
5320  | 0  |     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,  | 
5321  | 0  |          "name '%s' is not an NCName\n",  | 
5322  | 0  |          val, NULL);  | 
5323  | 0  |         }  | 
5324  | 0  |         ret->name = val;  | 
5325  | 0  |         val = xmlGetProp(node, BAD_CAST "ns");  | 
5326  | 0  |         ret->ns = val;  | 
5327  | 0  |         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&  | 
5328  | 0  |             (val != NULL) &&  | 
5329  | 0  |             (xmlStrEqual(val, BAD_CAST "http://www.w3.org/2000/xmlns"))) { | 
5330  | 0  |       xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,  | 
5331  | 0  |                         "Attribute with namespace '%s' is not allowed\n",  | 
5332  | 0  |                         val, NULL);  | 
5333  | 0  |         }  | 
5334  | 0  |         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&  | 
5335  | 0  |             (val != NULL) &&  | 
5336  | 0  |             (val[0] == 0) && (xmlStrEqual(ret->name, BAD_CAST "xmlns"))) { | 
5337  | 0  |       xmlRngPErr(ctxt, node, XML_RNGP_XMLNS_NAME,  | 
5338  | 0  |                        "Attribute with QName 'xmlns' is not allowed\n",  | 
5339  | 0  |                        val, NULL);  | 
5340  | 0  |         }  | 
5341  | 0  |     } else if (IS_RELAXNG(node, "anyName")) { | 
5342  | 0  |         ret->name = NULL;  | 
5343  | 0  |         ret->ns = NULL;  | 
5344  | 0  |         if (node->children != NULL) { | 
5345  | 0  |             ret->nameClass =  | 
5346  | 0  |                 xmlRelaxNGParseExceptNameClass(ctxt, node->children,  | 
5347  | 0  |                                                (def->type ==  | 
5348  | 0  |                                                 XML_RELAXNG_ATTRIBUTE));  | 
5349  | 0  |         }  | 
5350  | 0  |     } else if (IS_RELAXNG(node, "nsName")) { | 
5351  | 0  |         ret->name = NULL;  | 
5352  | 0  |         ret->ns = xmlGetProp(node, BAD_CAST "ns");  | 
5353  | 0  |         if (ret->ns == NULL) { | 
5354  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_NSNAME_NO_NS,  | 
5355  | 0  |                        "nsName has no ns attribute\n", NULL, NULL);  | 
5356  | 0  |         }  | 
5357  | 0  |         if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&  | 
5358  | 0  |             (ret->ns != NULL) &&  | 
5359  | 0  |             (xmlStrEqual  | 
5360  | 0  |              (ret->ns, BAD_CAST "http://www.w3.org/2000/xmlns"))) { | 
5361  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,  | 
5362  | 0  |                        "Attribute with namespace '%s' is not allowed\n",  | 
5363  | 0  |                        ret->ns, NULL);  | 
5364  | 0  |         }  | 
5365  | 0  |         if (node->children != NULL) { | 
5366  | 0  |             ret->nameClass =  | 
5367  | 0  |                 xmlRelaxNGParseExceptNameClass(ctxt, node->children,  | 
5368  | 0  |                                                (def->type ==  | 
5369  | 0  |                                                 XML_RELAXNG_ATTRIBUTE));  | 
5370  | 0  |         }  | 
5371  | 0  |     } else if (IS_RELAXNG(node, "choice")) { | 
5372  | 0  |         xmlNodePtr child;  | 
5373  | 0  |         xmlRelaxNGDefinePtr last = NULL;  | 
5374  |  | 
  | 
5375  | 0  |         if (def->type == XML_RELAXNG_CHOICE) { | 
5376  | 0  |             ret = def;  | 
5377  | 0  |         } else { | 
5378  | 0  |             ret = xmlRelaxNGNewDefine(ctxt, node);  | 
5379  | 0  |             if (ret == NULL)  | 
5380  | 0  |                 return (NULL);  | 
5381  | 0  |             ret->parent = def;  | 
5382  | 0  |             ret->type = XML_RELAXNG_CHOICE;  | 
5383  | 0  |         }  | 
5384  |  |  | 
5385  | 0  |         if (node->children == NULL) { | 
5386  | 0  |             xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,  | 
5387  | 0  |                        "Element choice is empty\n", NULL, NULL);  | 
5388  | 0  |         } else { | 
5389  |  | 
  | 
5390  | 0  |             child = node->children;  | 
5391  | 0  |             while (child != NULL) { | 
5392  | 0  |                 tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);  | 
5393  | 0  |                 if (tmp != NULL) { | 
5394  | 0  |                     if (last == NULL) { | 
5395  | 0  |                         last = tmp;  | 
5396  | 0  |                     } else { | 
5397  | 0  |                         last->next = tmp;  | 
5398  | 0  |                         last = tmp;  | 
5399  | 0  |                     }  | 
5400  | 0  |                 }  | 
5401  | 0  |                 child = child->next;  | 
5402  | 0  |             }  | 
5403  | 0  |         }  | 
5404  | 0  |     } else { | 
5405  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT,  | 
5406  | 0  |                    "expecting name, anyName, nsName or choice : got %s\n",  | 
5407  | 0  |                    (node == NULL ? (const xmlChar *) "nothing" : node->name),  | 
5408  | 0  |        NULL);  | 
5409  | 0  |         return (NULL);  | 
5410  | 0  |     }  | 
5411  | 0  |     if (ret != def) { | 
5412  | 0  |         if (def->nameClass == NULL) { | 
5413  | 0  |             def->nameClass = ret;  | 
5414  | 0  |         } else { | 
5415  | 0  |             tmp = def->nameClass;  | 
5416  | 0  |             while (tmp->next != NULL) { | 
5417  | 0  |                 tmp = tmp->next;  | 
5418  | 0  |             }  | 
5419  | 0  |             tmp->next = ret;  | 
5420  | 0  |         }  | 
5421  | 0  |     }  | 
5422  | 0  |     return (ret);  | 
5423  | 0  | }  | 
5424  |  |  | 
5425  |  | /**  | 
5426  |  |  * xmlRelaxNGParseElement:  | 
5427  |  |  * @ctxt:  a Relax-NG parser context  | 
5428  |  |  * @node:  the element node  | 
5429  |  |  *  | 
5430  |  |  * parse the content of a RelaxNG element node.  | 
5431  |  |  *  | 
5432  |  |  * Returns the definition pointer or NULL in case of error.  | 
5433  |  |  */  | 
5434  |  | static xmlRelaxNGDefinePtr  | 
5435  |  | xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
5436  | 0  | { | 
5437  | 0  |     xmlRelaxNGDefinePtr ret, cur, last;  | 
5438  | 0  |     xmlNodePtr child;  | 
5439  | 0  |     const xmlChar *olddefine;  | 
5440  |  | 
  | 
5441  | 0  |     ret = xmlRelaxNGNewDefine(ctxt, node);  | 
5442  | 0  |     if (ret == NULL)  | 
5443  | 0  |         return (NULL);  | 
5444  | 0  |     ret->type = XML_RELAXNG_ELEMENT;  | 
5445  | 0  |     ret->parent = ctxt->def;  | 
5446  | 0  |     child = node->children;  | 
5447  | 0  |     if (child == NULL) { | 
5448  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_EMPTY,  | 
5449  | 0  |                    "xmlRelaxNGParseElement: element has no children\n",  | 
5450  | 0  |                    NULL, NULL);  | 
5451  | 0  |         return (ret);  | 
5452  | 0  |     }  | 
5453  | 0  |     cur = xmlRelaxNGParseNameClass(ctxt, child, ret);  | 
5454  | 0  |     if (cur != NULL)  | 
5455  | 0  |         child = child->next;  | 
5456  |  | 
  | 
5457  | 0  |     if (child == NULL) { | 
5458  | 0  |         xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NO_CONTENT,  | 
5459  | 0  |                    "xmlRelaxNGParseElement: element has no content\n",  | 
5460  | 0  |                    NULL, NULL);  | 
5461  | 0  |         return (ret);  | 
5462  | 0  |     }  | 
5463  | 0  |     olddefine = ctxt->define;  | 
5464  | 0  |     ctxt->define = NULL;  | 
5465  | 0  |     last = NULL;  | 
5466  | 0  |     while (child != NULL) { | 
5467  | 0  |         cur = xmlRelaxNGParsePattern(ctxt, child);  | 
5468  | 0  |         if (cur != NULL) { | 
5469  | 0  |             cur->parent = ret;  | 
5470  | 0  |             switch (cur->type) { | 
5471  | 0  |                 case XML_RELAXNG_EMPTY:  | 
5472  | 0  |                 case XML_RELAXNG_NOT_ALLOWED:  | 
5473  | 0  |                 case XML_RELAXNG_TEXT:  | 
5474  | 0  |                 case XML_RELAXNG_ELEMENT:  | 
5475  | 0  |                 case XML_RELAXNG_DATATYPE:  | 
5476  | 0  |                 case XML_RELAXNG_VALUE:  | 
5477  | 0  |                 case XML_RELAXNG_LIST:  | 
5478  | 0  |                 case XML_RELAXNG_REF:  | 
5479  | 0  |                 case XML_RELAXNG_PARENTREF:  | 
5480  | 0  |                 case XML_RELAXNG_EXTERNALREF:  | 
5481  | 0  |                 case XML_RELAXNG_DEF:  | 
5482  | 0  |                 case XML_RELAXNG_ZEROORMORE:  | 
5483  | 0  |                 case XML_RELAXNG_ONEORMORE:  | 
5484  | 0  |                 case XML_RELAXNG_OPTIONAL:  | 
5485  | 0  |                 case XML_RELAXNG_CHOICE:  | 
5486  | 0  |                 case XML_RELAXNG_GROUP:  | 
5487  | 0  |                 case XML_RELAXNG_INTERLEAVE:  | 
5488  | 0  |                     if (last == NULL) { | 
5489  | 0  |                         ret->content = last = cur;  | 
5490  | 0  |                     } else { | 
5491  | 0  |                         if ((last->type == XML_RELAXNG_ELEMENT) &&  | 
5492  | 0  |                             (ret->content == last)) { | 
5493  | 0  |                             ret->content = xmlRelaxNGNewDefine(ctxt, node);  | 
5494  | 0  |                             if (ret->content != NULL) { | 
5495  | 0  |                                 ret->content->type = XML_RELAXNG_GROUP;  | 
5496  | 0  |                                 ret->content->content = last;  | 
5497  | 0  |                             } else { | 
5498  | 0  |                                 ret->content = last;  | 
5499  | 0  |                             }  | 
5500  | 0  |                         }  | 
5501  | 0  |                         last->next = cur;  | 
5502  | 0  |                         last = cur;  | 
5503  | 0  |                     }  | 
5504  | 0  |                     break;  | 
5505  | 0  |                 case XML_RELAXNG_ATTRIBUTE:  | 
5506  | 0  |                     cur->next = ret->attrs;  | 
5507  | 0  |                     ret->attrs = cur;  | 
5508  | 0  |                     break;  | 
5509  | 0  |                 case XML_RELAXNG_START:  | 
5510  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,  | 
5511  | 0  |                                "RNG Internal error, start found in element\n",  | 
5512  | 0  |                                NULL, NULL);  | 
5513  | 0  |                     break;  | 
5514  | 0  |                 case XML_RELAXNG_PARAM:  | 
5515  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,  | 
5516  | 0  |                                "RNG Internal error, param found in element\n",  | 
5517  | 0  |                                NULL, NULL);  | 
5518  | 0  |                     break;  | 
5519  | 0  |                 case XML_RELAXNG_EXCEPT:  | 
5520  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,  | 
5521  | 0  |                                "RNG Internal error, except found in element\n",  | 
5522  | 0  |                                NULL, NULL);  | 
5523  | 0  |                     break;  | 
5524  | 0  |                 case XML_RELAXNG_NOOP:  | 
5525  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,  | 
5526  | 0  |                                "RNG Internal error, noop found in element\n",  | 
5527  | 0  |                                NULL, NULL);  | 
5528  | 0  |                     break;  | 
5529  | 0  |             }  | 
5530  | 0  |         }  | 
5531  | 0  |         child = child->next;  | 
5532  | 0  |     }  | 
5533  | 0  |     ctxt->define = olddefine;  | 
5534  | 0  |     return (ret);  | 
5535  | 0  | }  | 
5536  |  |  | 
5537  |  | /**  | 
5538  |  |  * xmlRelaxNGParsePatterns:  | 
5539  |  |  * @ctxt:  a Relax-NG parser context  | 
5540  |  |  * @nodes:  list of nodes  | 
5541  |  |  * @group:  use an implicit <group> for elements  | 
5542  |  |  *  | 
5543  |  |  * parse the content of a RelaxNG start node.  | 
5544  |  |  *  | 
5545  |  |  * Returns the definition pointer or NULL in case of error.  | 
5546  |  |  */  | 
5547  |  | static xmlRelaxNGDefinePtr  | 
5548  |  | xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes,  | 
5549  |  |                         int group)  | 
5550  | 0  | { | 
5551  | 0  |     xmlRelaxNGDefinePtr def = NULL, last = NULL, cur, parent;  | 
5552  |  | 
  | 
5553  | 0  |     parent = ctxt->def;  | 
5554  | 0  |     while (nodes != NULL) { | 
5555  | 0  |         if (IS_RELAXNG(nodes, "element")) { | 
5556  | 0  |             cur = xmlRelaxNGParseElement(ctxt, nodes);  | 
5557  | 0  |             if (cur == NULL)  | 
5558  | 0  |                 return (NULL);  | 
5559  | 0  |             if (def == NULL) { | 
5560  | 0  |                 def = last = cur;  | 
5561  | 0  |             } else { | 
5562  | 0  |                 if ((group == 1) && (def->type == XML_RELAXNG_ELEMENT) &&  | 
5563  | 0  |                     (def == last)) { | 
5564  | 0  |                     def = xmlRelaxNGNewDefine(ctxt, nodes);  | 
5565  | 0  |                     if (def == NULL)  | 
5566  | 0  |                         return (NULL);  | 
5567  | 0  |                     def->type = XML_RELAXNG_GROUP;  | 
5568  | 0  |                     def->content = last;  | 
5569  | 0  |                 }  | 
5570  | 0  |                 last->next = cur;  | 
5571  | 0  |                 last = cur;  | 
5572  | 0  |             }  | 
5573  | 0  |             cur->parent = parent;  | 
5574  | 0  |         } else { | 
5575  | 0  |             cur = xmlRelaxNGParsePattern(ctxt, nodes);  | 
5576  | 0  |             if (cur != NULL) { | 
5577  | 0  |                 if (def == NULL) { | 
5578  | 0  |                     def = last = cur;  | 
5579  | 0  |                 } else { | 
5580  | 0  |                     last->next = cur;  | 
5581  | 0  |                     last = cur;  | 
5582  | 0  |                 }  | 
5583  | 0  |             }  | 
5584  | 0  |         }  | 
5585  | 0  |         nodes = nodes->next;  | 
5586  | 0  |     }  | 
5587  | 0  |     return (def);  | 
5588  | 0  | }  | 
5589  |  |  | 
5590  |  | /**  | 
5591  |  |  * xmlRelaxNGParseStart:  | 
5592  |  |  * @ctxt:  a Relax-NG parser context  | 
5593  |  |  * @nodes:  start children nodes  | 
5594  |  |  *  | 
5595  |  |  * parse the content of a RelaxNG start node.  | 
5596  |  |  *  | 
5597  |  |  * Returns 0 in case of success, -1 in case of error  | 
5598  |  |  */  | 
5599  |  | static int  | 
5600  |  | xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)  | 
5601  | 0  | { | 
5602  | 0  |     int ret = 0;  | 
5603  | 0  |     xmlRelaxNGDefinePtr def = NULL, last;  | 
5604  |  | 
  | 
5605  | 0  |     if (nodes == NULL) { | 
5606  | 0  |         xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY, "start has no children\n",  | 
5607  | 0  |                    NULL, NULL);  | 
5608  | 0  |         return (-1);  | 
5609  | 0  |     }  | 
5610  | 0  |     if (IS_RELAXNG(nodes, "empty")) { | 
5611  | 0  |         def = xmlRelaxNGNewDefine(ctxt, nodes);  | 
5612  | 0  |         if (def == NULL)  | 
5613  | 0  |             return (-1);  | 
5614  | 0  |         def->type = XML_RELAXNG_EMPTY;  | 
5615  | 0  |         if (nodes->children != NULL) { | 
5616  | 0  |             xmlRngPErr(ctxt, nodes, XML_RNGP_EMPTY_CONTENT,  | 
5617  | 0  |                        "element empty is not empty\n", NULL, NULL);  | 
5618  | 0  |         }  | 
5619  | 0  |     } else if (IS_RELAXNG(nodes, "notAllowed")) { | 
5620  | 0  |         def = xmlRelaxNGNewDefine(ctxt, nodes);  | 
5621  | 0  |         if (def == NULL)  | 
5622  | 0  |             return (-1);  | 
5623  | 0  |         def->type = XML_RELAXNG_NOT_ALLOWED;  | 
5624  | 0  |         if (nodes->children != NULL) { | 
5625  | 0  |             xmlRngPErr(ctxt, nodes, XML_RNGP_NOTALLOWED_NOT_EMPTY,  | 
5626  | 0  |                        "element notAllowed is not empty\n", NULL, NULL);  | 
5627  | 0  |         }  | 
5628  | 0  |     } else { | 
5629  | 0  |         def = xmlRelaxNGParsePatterns(ctxt, nodes, 1);  | 
5630  | 0  |     }  | 
5631  | 0  |     if (ctxt->grammar->start != NULL) { | 
5632  | 0  |         last = ctxt->grammar->start;  | 
5633  | 0  |         while (last->next != NULL)  | 
5634  | 0  |             last = last->next;  | 
5635  | 0  |         last->next = def;  | 
5636  | 0  |     } else { | 
5637  | 0  |         ctxt->grammar->start = def;  | 
5638  | 0  |     }  | 
5639  | 0  |     nodes = nodes->next;  | 
5640  | 0  |     if (nodes != NULL) { | 
5641  | 0  |         xmlRngPErr(ctxt, nodes, XML_RNGP_START_CONTENT,  | 
5642  | 0  |                    "start more than one children\n", NULL, NULL);  | 
5643  | 0  |         return (-1);  | 
5644  | 0  |     }  | 
5645  | 0  |     return (ret);  | 
5646  | 0  | }  | 
5647  |  |  | 
5648  |  | /**  | 
5649  |  |  * xmlRelaxNGParseGrammarContent:  | 
5650  |  |  * @ctxt:  a Relax-NG parser context  | 
5651  |  |  * @nodes:  grammar children nodes  | 
5652  |  |  *  | 
5653  |  |  * parse the content of a RelaxNG grammar node.  | 
5654  |  |  *  | 
5655  |  |  * Returns 0 in case of success, -1 in case of error  | 
5656  |  |  */  | 
5657  |  | static int  | 
5658  |  | xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,  | 
5659  |  |                               xmlNodePtr nodes)  | 
5660  | 0  | { | 
5661  | 0  |     int ret = 0, tmp;  | 
5662  |  | 
  | 
5663  | 0  |     if (nodes == NULL) { | 
5664  | 0  |         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_EMPTY,  | 
5665  | 0  |                    "grammar has no children\n", NULL, NULL);  | 
5666  | 0  |         return (-1);  | 
5667  | 0  |     }  | 
5668  | 0  |     while (nodes != NULL) { | 
5669  | 0  |         if (IS_RELAXNG(nodes, "start")) { | 
5670  | 0  |             if (nodes->children == NULL) { | 
5671  | 0  |                 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY,  | 
5672  | 0  |                            "start has no children\n", NULL, NULL);  | 
5673  | 0  |             } else { | 
5674  | 0  |                 tmp = xmlRelaxNGParseStart(ctxt, nodes->children);  | 
5675  | 0  |                 if (tmp != 0)  | 
5676  | 0  |                     ret = -1;  | 
5677  | 0  |             }  | 
5678  | 0  |         } else if (IS_RELAXNG(nodes, "define")) { | 
5679  | 0  |             tmp = xmlRelaxNGParseDefine(ctxt, nodes);  | 
5680  | 0  |             if (tmp != 0)  | 
5681  | 0  |                 ret = -1;  | 
5682  | 0  |         } else if (IS_RELAXNG(nodes, "include")) { | 
5683  | 0  |             tmp = xmlRelaxNGParseInclude(ctxt, nodes);  | 
5684  | 0  |             if (tmp != 0)  | 
5685  | 0  |                 ret = -1;  | 
5686  | 0  |         } else { | 
5687  | 0  |             xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,  | 
5688  | 0  |                        "grammar has unexpected child %s\n", nodes->name,  | 
5689  | 0  |                        NULL);  | 
5690  | 0  |             ret = -1;  | 
5691  | 0  |         }  | 
5692  | 0  |         nodes = nodes->next;  | 
5693  | 0  |     }  | 
5694  | 0  |     return (ret);  | 
5695  | 0  | }  | 
5696  |  |  | 
5697  |  | /**  | 
5698  |  |  * xmlRelaxNGCheckReference:  | 
5699  |  |  * @ref:  the ref  | 
5700  |  |  * @ctxt:  a Relax-NG parser context  | 
5701  |  |  * @name:  the name associated to the defines  | 
5702  |  |  *  | 
5703  |  |  * Applies the 4.17. combine attribute rule for all the define  | 
5704  |  |  * element of a given grammar using the same name.  | 
5705  |  |  */  | 
5706  |  | static void  | 
5707  |  | xmlRelaxNGCheckReference(void *payload, void *data, const xmlChar * name)  | 
5708  | 0  | { | 
5709  | 0  |     xmlRelaxNGDefinePtr ref = (xmlRelaxNGDefinePtr) payload;  | 
5710  | 0  |     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;  | 
5711  | 0  |     xmlRelaxNGGrammarPtr grammar;  | 
5712  | 0  |     xmlRelaxNGDefinePtr def, cur;  | 
5713  |  |  | 
5714  |  |     /*  | 
5715  |  |      * Those rules don't apply to imported ref from xmlRelaxNGParseImportRef  | 
5716  |  |      */  | 
5717  | 0  |     if (ref->dflags & IS_EXTERNAL_REF)  | 
5718  | 0  |         return;  | 
5719  |  |  | 
5720  | 0  |     grammar = ctxt->grammar;  | 
5721  | 0  |     if (grammar == NULL) { | 
5722  | 0  |         xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,  | 
5723  | 0  |                    "Internal error: no grammar in CheckReference %s\n",  | 
5724  | 0  |                    name, NULL);  | 
5725  | 0  |         return;  | 
5726  | 0  |     }  | 
5727  | 0  |     if (ref->content != NULL) { | 
5728  | 0  |         xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,  | 
5729  | 0  |                    "Internal error: reference has content in CheckReference %s\n",  | 
5730  | 0  |                    name, NULL);  | 
5731  | 0  |         return;  | 
5732  | 0  |     }  | 
5733  | 0  |     if (grammar->defs != NULL) { | 
5734  | 0  |         def = xmlHashLookup(grammar->defs, name);  | 
5735  | 0  |         if (def != NULL) { | 
5736  | 0  |             cur = ref;  | 
5737  | 0  |             while (cur != NULL) { | 
5738  | 0  |                 cur->content = def;  | 
5739  | 0  |                 cur = cur->nextHash;  | 
5740  | 0  |             }  | 
5741  | 0  |         } else { | 
5742  | 0  |             xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,  | 
5743  | 0  |                        "Reference %s has no matching definition\n", name,  | 
5744  | 0  |                        NULL);  | 
5745  | 0  |         }  | 
5746  | 0  |     } else { | 
5747  | 0  |         xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,  | 
5748  | 0  |                    "Reference %s has no matching definition\n", name,  | 
5749  | 0  |                    NULL);  | 
5750  | 0  |     }  | 
5751  | 0  | }  | 
5752  |  |  | 
5753  |  | /**  | 
5754  |  |  * xmlRelaxNGCheckCombine:  | 
5755  |  |  * @define:  the define(s) list  | 
5756  |  |  * @ctxt:  a Relax-NG parser context  | 
5757  |  |  * @name:  the name associated to the defines  | 
5758  |  |  *  | 
5759  |  |  * Applies the 4.17. combine attribute rule for all the define  | 
5760  |  |  * element of a given grammar using the same name.  | 
5761  |  |  */  | 
5762  |  | static void  | 
5763  |  | xmlRelaxNGCheckCombine(void *payload, void *data, const xmlChar * name)  | 
5764  | 0  | { | 
5765  | 0  |     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) payload;  | 
5766  | 0  |     xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data;  | 
5767  | 0  |     xmlChar *combine;  | 
5768  | 0  |     int choiceOrInterleave = -1;  | 
5769  | 0  |     int missing = 0;  | 
5770  | 0  |     xmlRelaxNGDefinePtr cur, last, tmp, tmp2;  | 
5771  |  | 
  | 
5772  | 0  |     if (define->nextHash == NULL)  | 
5773  | 0  |         return;  | 
5774  | 0  |     cur = define;  | 
5775  | 0  |     while (cur != NULL) { | 
5776  | 0  |         combine = xmlGetProp(cur->node, BAD_CAST "combine");  | 
5777  | 0  |         if (combine != NULL) { | 
5778  | 0  |             if (xmlStrEqual(combine, BAD_CAST "choice")) { | 
5779  | 0  |                 if (choiceOrInterleave == -1)  | 
5780  | 0  |                     choiceOrInterleave = 1;  | 
5781  | 0  |                 else if (choiceOrInterleave == 0) { | 
5782  | 0  |                     xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,  | 
5783  | 0  |                                "Defines for %s use both 'choice' and 'interleave'\n",  | 
5784  | 0  |                                name, NULL);  | 
5785  | 0  |                 }  | 
5786  | 0  |             } else if (xmlStrEqual(combine, BAD_CAST "interleave")) { | 
5787  | 0  |                 if (choiceOrInterleave == -1)  | 
5788  | 0  |                     choiceOrInterleave = 0;  | 
5789  | 0  |                 else if (choiceOrInterleave == 1) { | 
5790  | 0  |                     xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,  | 
5791  | 0  |                                "Defines for %s use both 'choice' and 'interleave'\n",  | 
5792  | 0  |                                name, NULL);  | 
5793  | 0  |                 }  | 
5794  | 0  |             } else { | 
5795  | 0  |                 xmlRngPErr(ctxt, define->node, XML_RNGP_UNKNOWN_COMBINE,  | 
5796  | 0  |                            "Defines for %s use unknown combine value '%s''\n",  | 
5797  | 0  |                            name, combine);  | 
5798  | 0  |             }  | 
5799  | 0  |             xmlFree(combine);  | 
5800  | 0  |         } else { | 
5801  | 0  |             if (missing == 0)  | 
5802  | 0  |                 missing = 1;  | 
5803  | 0  |             else { | 
5804  | 0  |                 xmlRngPErr(ctxt, define->node, XML_RNGP_NEED_COMBINE,  | 
5805  | 0  |                            "Some defines for %s needs the combine attribute\n",  | 
5806  | 0  |                            name, NULL);  | 
5807  | 0  |             }  | 
5808  | 0  |         }  | 
5809  |  | 
  | 
5810  | 0  |         cur = cur->nextHash;  | 
5811  | 0  |     }  | 
5812  |  | #ifdef DEBUG  | 
5813  |  |     xmlGenericError(xmlGenericErrorContext,  | 
5814  |  |                     "xmlRelaxNGCheckCombine(): merging %s defines: %d\n",  | 
5815  |  |                     name, choiceOrInterleave);  | 
5816  |  | #endif  | 
5817  | 0  |     if (choiceOrInterleave == -1)  | 
5818  | 0  |         choiceOrInterleave = 0;  | 
5819  | 0  |     cur = xmlRelaxNGNewDefine(ctxt, define->node);  | 
5820  | 0  |     if (cur == NULL)  | 
5821  | 0  |         return;  | 
5822  | 0  |     if (choiceOrInterleave == 0)  | 
5823  | 0  |         cur->type = XML_RELAXNG_INTERLEAVE;  | 
5824  | 0  |     else  | 
5825  | 0  |         cur->type = XML_RELAXNG_CHOICE;  | 
5826  | 0  |     tmp = define;  | 
5827  | 0  |     last = NULL;  | 
5828  | 0  |     while (tmp != NULL) { | 
5829  | 0  |         if (tmp->content != NULL) { | 
5830  | 0  |             if (tmp->content->next != NULL) { | 
5831  |  |                 /*  | 
5832  |  |                  * we need first to create a wrapper.  | 
5833  |  |                  */  | 
5834  | 0  |                 tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node);  | 
5835  | 0  |                 if (tmp2 == NULL)  | 
5836  | 0  |                     break;  | 
5837  | 0  |                 tmp2->type = XML_RELAXNG_GROUP;  | 
5838  | 0  |                 tmp2->content = tmp->content;  | 
5839  | 0  |             } else { | 
5840  | 0  |                 tmp2 = tmp->content;  | 
5841  | 0  |             }  | 
5842  | 0  |             if (last == NULL) { | 
5843  | 0  |                 cur->content = tmp2;  | 
5844  | 0  |             } else { | 
5845  | 0  |                 last->next = tmp2;  | 
5846  | 0  |             }  | 
5847  | 0  |             last = tmp2;  | 
5848  | 0  |         }  | 
5849  | 0  |         tmp->content = cur;  | 
5850  | 0  |         tmp = tmp->nextHash;  | 
5851  | 0  |     }  | 
5852  | 0  |     define->content = cur;  | 
5853  | 0  |     if (choiceOrInterleave == 0) { | 
5854  | 0  |         if (ctxt->interleaves == NULL)  | 
5855  | 0  |             ctxt->interleaves = xmlHashCreate(10);  | 
5856  | 0  |         if (ctxt->interleaves == NULL) { | 
5857  | 0  |             xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,  | 
5858  | 0  |                        "Failed to create interleaves hash table\n", NULL,  | 
5859  | 0  |                        NULL);  | 
5860  | 0  |         } else { | 
5861  | 0  |             char tmpname[32];  | 
5862  |  | 
  | 
5863  | 0  |             snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);  | 
5864  | 0  |             if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <  | 
5865  | 0  |                 0) { | 
5866  | 0  |                 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,  | 
5867  | 0  |                            "Failed to add %s to hash table\n",  | 
5868  | 0  |          (const xmlChar *) tmpname, NULL);  | 
5869  | 0  |             }  | 
5870  | 0  |         }  | 
5871  | 0  |     }  | 
5872  | 0  | }  | 
5873  |  |  | 
5874  |  | /**  | 
5875  |  |  * xmlRelaxNGCombineStart:  | 
5876  |  |  * @ctxt:  a Relax-NG parser context  | 
5877  |  |  * @grammar:  the grammar  | 
5878  |  |  *  | 
5879  |  |  * Applies the 4.17. combine rule for all the start  | 
5880  |  |  * element of a given grammar.  | 
5881  |  |  */  | 
5882  |  | static void  | 
5883  |  | xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt,  | 
5884  |  |                        xmlRelaxNGGrammarPtr grammar)  | 
5885  | 0  | { | 
5886  | 0  |     xmlRelaxNGDefinePtr starts;  | 
5887  | 0  |     xmlChar *combine;  | 
5888  | 0  |     int choiceOrInterleave = -1;  | 
5889  | 0  |     int missing = 0;  | 
5890  | 0  |     xmlRelaxNGDefinePtr cur;  | 
5891  |  | 
  | 
5892  | 0  |     starts = grammar->start;  | 
5893  | 0  |     if ((starts == NULL) || (starts->next == NULL))  | 
5894  | 0  |         return;  | 
5895  | 0  |     cur = starts;  | 
5896  | 0  |     while (cur != NULL) { | 
5897  | 0  |         if ((cur->node == NULL) || (cur->node->parent == NULL) ||  | 
5898  | 0  |             (!xmlStrEqual(cur->node->parent->name, BAD_CAST "start"))) { | 
5899  | 0  |             combine = NULL;  | 
5900  | 0  |             xmlRngPErr(ctxt, cur->node, XML_RNGP_START_MISSING,  | 
5901  | 0  |                        "Internal error: start element not found\n", NULL,  | 
5902  | 0  |                        NULL);  | 
5903  | 0  |         } else { | 
5904  | 0  |             combine = xmlGetProp(cur->node->parent, BAD_CAST "combine");  | 
5905  | 0  |         }  | 
5906  |  | 
  | 
5907  | 0  |         if (combine != NULL) { | 
5908  | 0  |             if (xmlStrEqual(combine, BAD_CAST "choice")) { | 
5909  | 0  |                 if (choiceOrInterleave == -1)  | 
5910  | 0  |                     choiceOrInterleave = 1;  | 
5911  | 0  |                 else if (choiceOrInterleave == 0) { | 
5912  | 0  |                     xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,  | 
5913  | 0  |                                "<start> use both 'choice' and 'interleave'\n",  | 
5914  | 0  |                                NULL, NULL);  | 
5915  | 0  |                 }  | 
5916  | 0  |             } else if (xmlStrEqual(combine, BAD_CAST "interleave")) { | 
5917  | 0  |                 if (choiceOrInterleave == -1)  | 
5918  | 0  |                     choiceOrInterleave = 0;  | 
5919  | 0  |                 else if (choiceOrInterleave == 1) { | 
5920  | 0  |                     xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,  | 
5921  | 0  |                                "<start> use both 'choice' and 'interleave'\n",  | 
5922  | 0  |                                NULL, NULL);  | 
5923  | 0  |                 }  | 
5924  | 0  |             } else { | 
5925  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_UNKNOWN_COMBINE,  | 
5926  | 0  |                            "<start> uses unknown combine value '%s''\n",  | 
5927  | 0  |                            combine, NULL);  | 
5928  | 0  |             }  | 
5929  | 0  |             xmlFree(combine);  | 
5930  | 0  |         } else { | 
5931  | 0  |             if (missing == 0)  | 
5932  | 0  |                 missing = 1;  | 
5933  | 0  |             else { | 
5934  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_NEED_COMBINE,  | 
5935  | 0  |                            "Some <start> element miss the combine attribute\n",  | 
5936  | 0  |                            NULL, NULL);  | 
5937  | 0  |             }  | 
5938  | 0  |         }  | 
5939  |  | 
  | 
5940  | 0  |         cur = cur->next;  | 
5941  | 0  |     }  | 
5942  |  | #ifdef DEBUG  | 
5943  |  |     xmlGenericError(xmlGenericErrorContext,  | 
5944  |  |                     "xmlRelaxNGCombineStart(): merging <start>: %d\n",  | 
5945  |  |                     choiceOrInterleave);  | 
5946  |  | #endif  | 
5947  | 0  |     if (choiceOrInterleave == -1)  | 
5948  | 0  |         choiceOrInterleave = 0;  | 
5949  | 0  |     cur = xmlRelaxNGNewDefine(ctxt, starts->node);  | 
5950  | 0  |     if (cur == NULL)  | 
5951  | 0  |         return;  | 
5952  | 0  |     if (choiceOrInterleave == 0)  | 
5953  | 0  |         cur->type = XML_RELAXNG_INTERLEAVE;  | 
5954  | 0  |     else  | 
5955  | 0  |         cur->type = XML_RELAXNG_CHOICE;  | 
5956  | 0  |     cur->content = grammar->start;  | 
5957  | 0  |     grammar->start = cur;  | 
5958  | 0  |     if (choiceOrInterleave == 0) { | 
5959  | 0  |         if (ctxt->interleaves == NULL)  | 
5960  | 0  |             ctxt->interleaves = xmlHashCreate(10);  | 
5961  | 0  |         if (ctxt->interleaves == NULL) { | 
5962  | 0  |             xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,  | 
5963  | 0  |                        "Failed to create interleaves hash table\n", NULL,  | 
5964  | 0  |                        NULL);  | 
5965  | 0  |         } else { | 
5966  | 0  |             char tmpname[32];  | 
5967  |  | 
  | 
5968  | 0  |             snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);  | 
5969  | 0  |             if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <  | 
5970  | 0  |                 0) { | 
5971  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,  | 
5972  | 0  |                            "Failed to add %s to hash table\n",  | 
5973  | 0  |          (const xmlChar *) tmpname, NULL);  | 
5974  | 0  |             }  | 
5975  | 0  |         }  | 
5976  | 0  |     }  | 
5977  | 0  | }  | 
5978  |  |  | 
5979  |  | /**  | 
5980  |  |  * xmlRelaxNGCheckCycles:  | 
5981  |  |  * @ctxt:  a Relax-NG parser context  | 
5982  |  |  * @nodes:  grammar children nodes  | 
5983  |  |  * @depth:  the counter  | 
5984  |  |  *  | 
5985  |  |  * Check for cycles.  | 
5986  |  |  *  | 
5987  |  |  * Returns 0 if check passed, and -1 in case of error  | 
5988  |  |  */  | 
5989  |  | static int  | 
5990  |  | xmlRelaxNGCheckCycles(xmlRelaxNGParserCtxtPtr ctxt,  | 
5991  |  |                       xmlRelaxNGDefinePtr cur, int depth)  | 
5992  | 0  | { | 
5993  | 0  |     int ret = 0;  | 
5994  |  | 
  | 
5995  | 0  |     while ((ret == 0) && (cur != NULL)) { | 
5996  | 0  |         if ((cur->type == XML_RELAXNG_REF) ||  | 
5997  | 0  |             (cur->type == XML_RELAXNG_PARENTREF)) { | 
5998  | 0  |             if (cur->depth == -1) { | 
5999  | 0  |                 cur->depth = depth;  | 
6000  | 0  |                 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);  | 
6001  | 0  |                 cur->depth = -2;  | 
6002  | 0  |             } else if (depth == cur->depth) { | 
6003  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_CYCLE,  | 
6004  | 0  |                            "Detected a cycle in %s references\n",  | 
6005  | 0  |                            cur->name, NULL);  | 
6006  | 0  |                 return (-1);  | 
6007  | 0  |             }  | 
6008  | 0  |         } else if (cur->type == XML_RELAXNG_ELEMENT) { | 
6009  | 0  |             ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth + 1);  | 
6010  | 0  |         } else { | 
6011  | 0  |             ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);  | 
6012  | 0  |         }  | 
6013  | 0  |         cur = cur->next;  | 
6014  | 0  |     }  | 
6015  | 0  |     return (ret);  | 
6016  | 0  | }  | 
6017  |  |  | 
6018  |  | /**  | 
6019  |  |  * xmlRelaxNGTryUnlink:  | 
6020  |  |  * @ctxt:  a Relax-NG parser context  | 
6021  |  |  * @cur:  the definition to unlink  | 
6022  |  |  * @parent:  the parent definition  | 
6023  |  |  * @prev:  the previous sibling definition  | 
6024  |  |  *  | 
6025  |  |  * Try to unlink a definition. If not possible make it a NOOP  | 
6026  |  |  *  | 
6027  |  |  * Returns the new prev definition  | 
6028  |  |  */  | 
6029  |  | static xmlRelaxNGDefinePtr  | 
6030  |  | xmlRelaxNGTryUnlink(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,  | 
6031  |  |                     xmlRelaxNGDefinePtr cur,  | 
6032  |  |                     xmlRelaxNGDefinePtr parent, xmlRelaxNGDefinePtr prev)  | 
6033  | 0  | { | 
6034  | 0  |     if (prev != NULL) { | 
6035  | 0  |         prev->next = cur->next;  | 
6036  | 0  |     } else { | 
6037  | 0  |         if (parent != NULL) { | 
6038  | 0  |             if (parent->content == cur)  | 
6039  | 0  |                 parent->content = cur->next;  | 
6040  | 0  |             else if (parent->attrs == cur)  | 
6041  | 0  |                 parent->attrs = cur->next;  | 
6042  | 0  |             else if (parent->nameClass == cur)  | 
6043  | 0  |                 parent->nameClass = cur->next;  | 
6044  | 0  |         } else { | 
6045  | 0  |             cur->type = XML_RELAXNG_NOOP;  | 
6046  | 0  |             prev = cur;  | 
6047  | 0  |         }  | 
6048  | 0  |     }  | 
6049  | 0  |     return (prev);  | 
6050  | 0  | }  | 
6051  |  |  | 
6052  |  | /**  | 
6053  |  |  * xmlRelaxNGSimplify:  | 
6054  |  |  * @ctxt:  a Relax-NG parser context  | 
6055  |  |  * @nodes:  grammar children nodes  | 
6056  |  |  *  | 
6057  |  |  * Check for simplification of empty and notAllowed  | 
6058  |  |  */  | 
6059  |  | static void  | 
6060  |  | xmlRelaxNGSimplify(xmlRelaxNGParserCtxtPtr ctxt,  | 
6061  |  |                    xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent)  | 
6062  | 0  | { | 
6063  | 0  |     xmlRelaxNGDefinePtr prev = NULL;  | 
6064  |  | 
  | 
6065  | 0  |     while (cur != NULL) { | 
6066  | 0  |         if ((cur->type == XML_RELAXNG_REF) ||  | 
6067  | 0  |             (cur->type == XML_RELAXNG_PARENTREF)) { | 
6068  | 0  |             if (cur->depth != -3) { | 
6069  | 0  |                 cur->depth = -3;  | 
6070  | 0  |                 xmlRelaxNGSimplify(ctxt, cur->content, cur);  | 
6071  | 0  |             }  | 
6072  | 0  |         } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) { | 
6073  | 0  |             cur->parent = parent;  | 
6074  | 0  |             if ((parent != NULL) &&  | 
6075  | 0  |                 ((parent->type == XML_RELAXNG_ATTRIBUTE) ||  | 
6076  | 0  |                  (parent->type == XML_RELAXNG_LIST) ||  | 
6077  | 0  |                  (parent->type == XML_RELAXNG_GROUP) ||  | 
6078  | 0  |                  (parent->type == XML_RELAXNG_INTERLEAVE) ||  | 
6079  | 0  |                  (parent->type == XML_RELAXNG_ONEORMORE) ||  | 
6080  | 0  |                  (parent->type == XML_RELAXNG_ZEROORMORE))) { | 
6081  | 0  |                 parent->type = XML_RELAXNG_NOT_ALLOWED;  | 
6082  | 0  |                 break;  | 
6083  | 0  |             }  | 
6084  | 0  |             if ((parent != NULL) && (parent->type == XML_RELAXNG_CHOICE)) { | 
6085  | 0  |                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);  | 
6086  | 0  |             } else  | 
6087  | 0  |                 prev = cur;  | 
6088  | 0  |         } else if (cur->type == XML_RELAXNG_EMPTY) { | 
6089  | 0  |             cur->parent = parent;  | 
6090  | 0  |             if ((parent != NULL) &&  | 
6091  | 0  |                 ((parent->type == XML_RELAXNG_ONEORMORE) ||  | 
6092  | 0  |                  (parent->type == XML_RELAXNG_ZEROORMORE))) { | 
6093  | 0  |                 parent->type = XML_RELAXNG_EMPTY;  | 
6094  | 0  |                 break;  | 
6095  | 0  |             }  | 
6096  | 0  |             if ((parent != NULL) &&  | 
6097  | 0  |                 ((parent->type == XML_RELAXNG_GROUP) ||  | 
6098  | 0  |                  (parent->type == XML_RELAXNG_INTERLEAVE))) { | 
6099  | 0  |                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);  | 
6100  | 0  |             } else  | 
6101  | 0  |                 prev = cur;  | 
6102  | 0  |         } else { | 
6103  | 0  |             cur->parent = parent;  | 
6104  | 0  |             if (cur->content != NULL)  | 
6105  | 0  |                 xmlRelaxNGSimplify(ctxt, cur->content, cur);  | 
6106  | 0  |             if ((cur->type != XML_RELAXNG_VALUE) && (cur->attrs != NULL))  | 
6107  | 0  |                 xmlRelaxNGSimplify(ctxt, cur->attrs, cur);  | 
6108  | 0  |             if (cur->nameClass != NULL)  | 
6109  | 0  |                 xmlRelaxNGSimplify(ctxt, cur->nameClass, cur);  | 
6110  |  |             /*  | 
6111  |  |              * On Elements, try to move attribute only generating rules on  | 
6112  |  |              * the attrs rules.  | 
6113  |  |              */  | 
6114  | 0  |             if (cur->type == XML_RELAXNG_ELEMENT) { | 
6115  | 0  |                 int attronly;  | 
6116  | 0  |                 xmlRelaxNGDefinePtr tmp, pre;  | 
6117  |  | 
  | 
6118  | 0  |                 while (cur->content != NULL) { | 
6119  | 0  |                     attronly =  | 
6120  | 0  |                         xmlRelaxNGGenerateAttributes(ctxt, cur->content);  | 
6121  | 0  |                     if (attronly == 1) { | 
6122  |  |                         /*  | 
6123  |  |                          * migrate cur->content to attrs  | 
6124  |  |                          */  | 
6125  | 0  |                         tmp = cur->content;  | 
6126  | 0  |                         cur->content = tmp->next;  | 
6127  | 0  |                         tmp->next = cur->attrs;  | 
6128  | 0  |                         cur->attrs = tmp;  | 
6129  | 0  |                     } else { | 
6130  |  |                         /*  | 
6131  |  |                          * cur->content can generate elements or text  | 
6132  |  |                          */  | 
6133  | 0  |                         break;  | 
6134  | 0  |                     }  | 
6135  | 0  |                 }  | 
6136  | 0  |                 pre = cur->content;  | 
6137  | 0  |                 while ((pre != NULL) && (pre->next != NULL)) { | 
6138  | 0  |                     tmp = pre->next;  | 
6139  | 0  |                     attronly = xmlRelaxNGGenerateAttributes(ctxt, tmp);  | 
6140  | 0  |                     if (attronly == 1) { | 
6141  |  |                         /*  | 
6142  |  |                          * migrate tmp to attrs  | 
6143  |  |                          */  | 
6144  | 0  |                         pre->next = tmp->next;  | 
6145  | 0  |                         tmp->next = cur->attrs;  | 
6146  | 0  |                         cur->attrs = tmp;  | 
6147  | 0  |                     } else { | 
6148  | 0  |                         pre = tmp;  | 
6149  | 0  |                     }  | 
6150  | 0  |                 }  | 
6151  | 0  |             }  | 
6152  |  |             /*  | 
6153  |  |              * This may result in a simplification  | 
6154  |  |              */  | 
6155  | 0  |             if ((cur->type == XML_RELAXNG_GROUP) ||  | 
6156  | 0  |                 (cur->type == XML_RELAXNG_INTERLEAVE)) { | 
6157  | 0  |                 if (cur->content == NULL)  | 
6158  | 0  |                     cur->type = XML_RELAXNG_EMPTY;  | 
6159  | 0  |                 else if (cur->content->next == NULL) { | 
6160  | 0  |                     if ((parent == NULL) && (prev == NULL)) { | 
6161  | 0  |                         cur->type = XML_RELAXNG_NOOP;  | 
6162  | 0  |                     } else if (prev == NULL) { | 
6163  | 0  |                         parent->content = cur->content;  | 
6164  | 0  |                         cur->content->next = cur->next;  | 
6165  | 0  |                         cur = cur->content;  | 
6166  | 0  |                     } else { | 
6167  | 0  |                         cur->content->next = cur->next;  | 
6168  | 0  |                         prev->next = cur->content;  | 
6169  | 0  |                         cur = cur->content;  | 
6170  | 0  |                     }  | 
6171  | 0  |                 }  | 
6172  | 0  |             }  | 
6173  |  |             /*  | 
6174  |  |              * the current node may have been transformed back  | 
6175  |  |              */  | 
6176  | 0  |             if ((cur->type == XML_RELAXNG_EXCEPT) &&  | 
6177  | 0  |                 (cur->content != NULL) &&  | 
6178  | 0  |                 (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) { | 
6179  | 0  |                 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);  | 
6180  | 0  |             } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) { | 
6181  | 0  |                 if ((parent != NULL) &&  | 
6182  | 0  |                     ((parent->type == XML_RELAXNG_ATTRIBUTE) ||  | 
6183  | 0  |                      (parent->type == XML_RELAXNG_LIST) ||  | 
6184  | 0  |                      (parent->type == XML_RELAXNG_GROUP) ||  | 
6185  | 0  |                      (parent->type == XML_RELAXNG_INTERLEAVE) ||  | 
6186  | 0  |                      (parent->type == XML_RELAXNG_ONEORMORE) ||  | 
6187  | 0  |                      (parent->type == XML_RELAXNG_ZEROORMORE))) { | 
6188  | 0  |                     parent->type = XML_RELAXNG_NOT_ALLOWED;  | 
6189  | 0  |                     break;  | 
6190  | 0  |                 }  | 
6191  | 0  |                 if ((parent != NULL) &&  | 
6192  | 0  |                     (parent->type == XML_RELAXNG_CHOICE)) { | 
6193  | 0  |                     prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);  | 
6194  | 0  |                 } else  | 
6195  | 0  |                     prev = cur;  | 
6196  | 0  |             } else if (cur->type == XML_RELAXNG_EMPTY) { | 
6197  | 0  |                 if ((parent != NULL) &&  | 
6198  | 0  |                     ((parent->type == XML_RELAXNG_ONEORMORE) ||  | 
6199  | 0  |                      (parent->type == XML_RELAXNG_ZEROORMORE))) { | 
6200  | 0  |                     parent->type = XML_RELAXNG_EMPTY;  | 
6201  | 0  |                     break;  | 
6202  | 0  |                 }  | 
6203  | 0  |                 if ((parent != NULL) &&  | 
6204  | 0  |                     ((parent->type == XML_RELAXNG_GROUP) ||  | 
6205  | 0  |                      (parent->type == XML_RELAXNG_INTERLEAVE) ||  | 
6206  | 0  |                      (parent->type == XML_RELAXNG_CHOICE))) { | 
6207  | 0  |                     prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);  | 
6208  | 0  |                 } else  | 
6209  | 0  |                     prev = cur;  | 
6210  | 0  |             } else { | 
6211  | 0  |                 prev = cur;  | 
6212  | 0  |             }  | 
6213  | 0  |         }  | 
6214  | 0  |         cur = cur->next;  | 
6215  | 0  |     }  | 
6216  | 0  | }  | 
6217  |  |  | 
6218  |  | /**  | 
6219  |  |  * xmlRelaxNGGroupContentType:  | 
6220  |  |  * @ct1:  the first content type  | 
6221  |  |  * @ct2:  the second content type  | 
6222  |  |  *  | 
6223  |  |  * Try to group 2 content types  | 
6224  |  |  *  | 
6225  |  |  * Returns the content type  | 
6226  |  |  */  | 
6227  |  | static xmlRelaxNGContentType  | 
6228  |  | xmlRelaxNGGroupContentType(xmlRelaxNGContentType ct1,  | 
6229  |  |                            xmlRelaxNGContentType ct2)  | 
6230  | 0  | { | 
6231  | 0  |     if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||  | 
6232  | 0  |         (ct2 == XML_RELAXNG_CONTENT_ERROR))  | 
6233  | 0  |         return (XML_RELAXNG_CONTENT_ERROR);  | 
6234  | 0  |     if (ct1 == XML_RELAXNG_CONTENT_EMPTY)  | 
6235  | 0  |         return (ct2);  | 
6236  | 0  |     if (ct2 == XML_RELAXNG_CONTENT_EMPTY)  | 
6237  | 0  |         return (ct1);  | 
6238  | 0  |     if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) &&  | 
6239  | 0  |         (ct2 == XML_RELAXNG_CONTENT_COMPLEX))  | 
6240  | 0  |         return (XML_RELAXNG_CONTENT_COMPLEX);  | 
6241  | 0  |     return (XML_RELAXNG_CONTENT_ERROR);  | 
6242  | 0  | }  | 
6243  |  |  | 
6244  |  | /**  | 
6245  |  |  * xmlRelaxNGMaxContentType:  | 
6246  |  |  * @ct1:  the first content type  | 
6247  |  |  * @ct2:  the second content type  | 
6248  |  |  *  | 
6249  |  |  * Compute the max content-type  | 
6250  |  |  *  | 
6251  |  |  * Returns the content type  | 
6252  |  |  */  | 
6253  |  | static xmlRelaxNGContentType  | 
6254  |  | xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1,  | 
6255  |  |                          xmlRelaxNGContentType ct2)  | 
6256  | 0  | { | 
6257  | 0  |     if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||  | 
6258  | 0  |         (ct2 == XML_RELAXNG_CONTENT_ERROR))  | 
6259  | 0  |         return (XML_RELAXNG_CONTENT_ERROR);  | 
6260  | 0  |     if ((ct1 == XML_RELAXNG_CONTENT_SIMPLE) ||  | 
6261  | 0  |         (ct2 == XML_RELAXNG_CONTENT_SIMPLE))  | 
6262  | 0  |         return (XML_RELAXNG_CONTENT_SIMPLE);  | 
6263  | 0  |     if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) ||  | 
6264  | 0  |         (ct2 == XML_RELAXNG_CONTENT_COMPLEX))  | 
6265  | 0  |         return (XML_RELAXNG_CONTENT_COMPLEX);  | 
6266  | 0  |     return (XML_RELAXNG_CONTENT_EMPTY);  | 
6267  | 0  | }  | 
6268  |  |  | 
6269  |  | /**  | 
6270  |  |  * xmlRelaxNGCheckRules:  | 
6271  |  |  * @ctxt:  a Relax-NG parser context  | 
6272  |  |  * @cur:  the current definition  | 
6273  |  |  * @flags:  some accumulated flags  | 
6274  |  |  * @ptype:  the parent type  | 
6275  |  |  *  | 
6276  |  |  * Check for rules in section 7.1 and 7.2  | 
6277  |  |  *  | 
6278  |  |  * Returns the content type of @cur  | 
6279  |  |  */  | 
6280  |  | static xmlRelaxNGContentType  | 
6281  |  | xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt,  | 
6282  |  |                      xmlRelaxNGDefinePtr cur, int flags,  | 
6283  |  |                      xmlRelaxNGType ptype)  | 
6284  | 0  | { | 
6285  | 0  |     int nflags;  | 
6286  | 0  |     xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY;  | 
6287  |  | 
  | 
6288  | 0  |     while (cur != NULL) { | 
6289  | 0  |         ret = XML_RELAXNG_CONTENT_EMPTY;  | 
6290  | 0  |         if ((cur->type == XML_RELAXNG_REF) ||  | 
6291  | 0  |             (cur->type == XML_RELAXNG_PARENTREF)) { | 
6292  |  |            /*  | 
6293  |  |             * This should actually be caught by list//element(ref) at the  | 
6294  |  |             * element boundaries, c.f. Bug #159968 local refs are dropped  | 
6295  |  |             * in step 4.19.  | 
6296  |  |             */  | 
6297  |  | #if 0  | 
6298  |  |             if (flags & XML_RELAXNG_IN_LIST) { | 
6299  |  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_REF,  | 
6300  |  |                            "Found forbidden pattern list//ref\n", NULL,  | 
6301  |  |                            NULL);  | 
6302  |  |             }  | 
6303  |  | #endif  | 
6304  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6305  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_REF,  | 
6306  | 0  |                            "Found forbidden pattern data/except//ref\n",  | 
6307  | 0  |                            NULL, NULL);  | 
6308  | 0  |             }  | 
6309  | 0  |             if (cur->content == NULL) { | 
6310  | 0  |                 if (cur->type == XML_RELAXNG_PARENTREF)  | 
6311  | 0  |                     xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,  | 
6312  | 0  |                                "Internal found no define for parent refs\n",  | 
6313  | 0  |                                NULL, NULL);  | 
6314  | 0  |                 else  | 
6315  | 0  |                     xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF,  | 
6316  | 0  |                                "Internal found no define for ref %s\n",  | 
6317  | 0  |                                (cur->name ? cur->name: BAD_CAST "null"), NULL);  | 
6318  | 0  |             }  | 
6319  | 0  |             if (cur->depth > -4) { | 
6320  | 0  |                 cur->depth = -4;  | 
6321  | 0  |                 ret = xmlRelaxNGCheckRules(ctxt, cur->content,  | 
6322  | 0  |                                            flags, cur->type);  | 
6323  | 0  |                 cur->depth = ret - 15;  | 
6324  | 0  |             } else if (cur->depth == -4) { | 
6325  | 0  |                 ret = XML_RELAXNG_CONTENT_COMPLEX;  | 
6326  | 0  |             } else { | 
6327  | 0  |                 ret = (xmlRelaxNGContentType) (cur->depth + 15);  | 
6328  | 0  |             }  | 
6329  | 0  |         } else if (cur->type == XML_RELAXNG_ELEMENT) { | 
6330  |  |             /*  | 
6331  |  |              * The 7.3 Attribute derivation rule for groups is plugged there  | 
6332  |  |              */  | 
6333  | 0  |             xmlRelaxNGCheckGroupAttrs(ctxt, cur);  | 
6334  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6335  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ELEM,  | 
6336  | 0  |                            "Found forbidden pattern data/except//element(ref)\n",  | 
6337  | 0  |                            NULL, NULL);  | 
6338  | 0  |             }  | 
6339  | 0  |             if (flags & XML_RELAXNG_IN_LIST) { | 
6340  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ELEM,  | 
6341  | 0  |                            "Found forbidden pattern list//element(ref)\n",  | 
6342  | 0  |                            NULL, NULL);  | 
6343  | 0  |             }  | 
6344  | 0  |             if (flags & XML_RELAXNG_IN_ATTRIBUTE) { | 
6345  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,  | 
6346  | 0  |                            "Found forbidden pattern attribute//element(ref)\n",  | 
6347  | 0  |                            NULL, NULL);  | 
6348  | 0  |             }  | 
6349  | 0  |             if (flags & XML_RELAXNG_IN_ATTRIBUTE) { | 
6350  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,  | 
6351  | 0  |                            "Found forbidden pattern attribute//element(ref)\n",  | 
6352  | 0  |                            NULL, NULL);  | 
6353  | 0  |             }  | 
6354  |  |             /*  | 
6355  |  |              * reset since in the simple form elements are only child  | 
6356  |  |              * of grammar/define  | 
6357  |  |              */  | 
6358  | 0  |             nflags = 0;  | 
6359  | 0  |             ret =  | 
6360  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type);  | 
6361  | 0  |             if (ret != XML_RELAXNG_CONTENT_EMPTY) { | 
6362  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_EMPTY,  | 
6363  | 0  |                            "Element %s attributes have a content type error\n",  | 
6364  | 0  |                            cur->name, NULL);  | 
6365  | 0  |             }  | 
6366  | 0  |             ret =  | 
6367  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,  | 
6368  | 0  |                                      cur->type);  | 
6369  | 0  |             if (ret == XML_RELAXNG_CONTENT_ERROR) { | 
6370  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_ERROR,  | 
6371  | 0  |                            "Element %s has a content type error\n",  | 
6372  | 0  |                            cur->name, NULL);  | 
6373  | 0  |             } else { | 
6374  | 0  |                 ret = XML_RELAXNG_CONTENT_COMPLEX;  | 
6375  | 0  |             }  | 
6376  | 0  |         } else if (cur->type == XML_RELAXNG_ATTRIBUTE) { | 
6377  | 0  |             if (flags & XML_RELAXNG_IN_ATTRIBUTE) { | 
6378  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ATTR,  | 
6379  | 0  |                            "Found forbidden pattern attribute//attribute\n",  | 
6380  | 0  |                            NULL, NULL);  | 
6381  | 0  |             }  | 
6382  | 0  |             if (flags & XML_RELAXNG_IN_LIST) { | 
6383  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ATTR,  | 
6384  | 0  |                            "Found forbidden pattern list//attribute\n",  | 
6385  | 0  |                            NULL, NULL);  | 
6386  | 0  |             }  | 
6387  | 0  |             if (flags & XML_RELAXNG_IN_OOMGROUP) { | 
6388  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_GROUP_ATTR,  | 
6389  | 0  |                            "Found forbidden pattern oneOrMore//group//attribute\n",  | 
6390  | 0  |                            NULL, NULL);  | 
6391  | 0  |             }  | 
6392  | 0  |             if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) { | 
6393  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR,  | 
6394  | 0  |                            "Found forbidden pattern oneOrMore//interleave//attribute\n",  | 
6395  | 0  |                            NULL, NULL);  | 
6396  | 0  |             }  | 
6397  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6398  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ATTR,  | 
6399  | 0  |                            "Found forbidden pattern data/except//attribute\n",  | 
6400  | 0  |                            NULL, NULL);  | 
6401  | 0  |             }  | 
6402  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6403  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ATTR,  | 
6404  | 0  |                            "Found forbidden pattern start//attribute\n",  | 
6405  | 0  |                            NULL, NULL);  | 
6406  | 0  |             }  | 
6407  | 0  |             if ((!(flags & XML_RELAXNG_IN_ONEORMORE))  | 
6408  | 0  |                 && cur->name == NULL  | 
6409  |  |                 /* following is checking alternative name class readiness  | 
6410  |  |                    in case it went the "choice" route */  | 
6411  | 0  |                 && cur->nameClass == NULL) { | 
6412  | 0  |                 if (cur->ns == NULL) { | 
6413  | 0  |                     xmlRngPErr(ctxt, cur->node, XML_RNGP_ANYNAME_ATTR_ANCESTOR,  | 
6414  | 0  |                                "Found anyName attribute without oneOrMore ancestor\n",  | 
6415  | 0  |                                NULL, NULL);  | 
6416  | 0  |                 } else { | 
6417  | 0  |                     xmlRngPErr(ctxt, cur->node, XML_RNGP_NSNAME_ATTR_ANCESTOR,  | 
6418  | 0  |                                "Found nsName attribute without oneOrMore ancestor\n",  | 
6419  | 0  |                                NULL, NULL);  | 
6420  | 0  |                 }  | 
6421  | 0  |             }  | 
6422  | 0  |             nflags = flags | XML_RELAXNG_IN_ATTRIBUTE;  | 
6423  | 0  |             xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);  | 
6424  | 0  |             ret = XML_RELAXNG_CONTENT_EMPTY;  | 
6425  | 0  |         } else if ((cur->type == XML_RELAXNG_ONEORMORE) ||  | 
6426  | 0  |                    (cur->type == XML_RELAXNG_ZEROORMORE)) { | 
6427  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6428  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ONEMORE,  | 
6429  | 0  |                            "Found forbidden pattern data/except//oneOrMore\n",  | 
6430  | 0  |                            NULL, NULL);  | 
6431  | 0  |             }  | 
6432  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6433  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ONEMORE,  | 
6434  | 0  |                            "Found forbidden pattern start//oneOrMore\n",  | 
6435  | 0  |                            NULL, NULL);  | 
6436  | 0  |             }  | 
6437  | 0  |             nflags = flags | XML_RELAXNG_IN_ONEORMORE;  | 
6438  | 0  |             ret =  | 
6439  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,  | 
6440  | 0  |                                      cur->type);  | 
6441  | 0  |             ret = xmlRelaxNGGroupContentType(ret, ret);  | 
6442  | 0  |         } else if (cur->type == XML_RELAXNG_LIST) { | 
6443  | 0  |             if (flags & XML_RELAXNG_IN_LIST) { | 
6444  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_LIST,  | 
6445  | 0  |                            "Found forbidden pattern list//list\n", NULL,  | 
6446  | 0  |                            NULL);  | 
6447  | 0  |             }  | 
6448  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6449  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_LIST,  | 
6450  | 0  |                            "Found forbidden pattern data/except//list\n",  | 
6451  | 0  |                            NULL, NULL);  | 
6452  | 0  |             }  | 
6453  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6454  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_LIST,  | 
6455  | 0  |                            "Found forbidden pattern start//list\n", NULL,  | 
6456  | 0  |                            NULL);  | 
6457  | 0  |             }  | 
6458  | 0  |             nflags = flags | XML_RELAXNG_IN_LIST;  | 
6459  | 0  |             ret =  | 
6460  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,  | 
6461  | 0  |                                      cur->type);  | 
6462  | 0  |         } else if (cur->type == XML_RELAXNG_GROUP) { | 
6463  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6464  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_GROUP,  | 
6465  | 0  |                            "Found forbidden pattern data/except//group\n",  | 
6466  | 0  |                            NULL, NULL);  | 
6467  | 0  |             }  | 
6468  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6469  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_GROUP,  | 
6470  | 0  |                            "Found forbidden pattern start//group\n", NULL,  | 
6471  | 0  |                            NULL);  | 
6472  | 0  |             }  | 
6473  | 0  |             if (flags & XML_RELAXNG_IN_ONEORMORE)  | 
6474  | 0  |                 nflags = flags | XML_RELAXNG_IN_OOMGROUP;  | 
6475  | 0  |             else  | 
6476  | 0  |                 nflags = flags;  | 
6477  | 0  |             ret =  | 
6478  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,  | 
6479  | 0  |                                      cur->type);  | 
6480  |  |             /*  | 
6481  |  |              * The 7.3 Attribute derivation rule for groups is plugged there  | 
6482  |  |              */  | 
6483  | 0  |             xmlRelaxNGCheckGroupAttrs(ctxt, cur);  | 
6484  | 0  |         } else if (cur->type == XML_RELAXNG_INTERLEAVE) { | 
6485  | 0  |             if (flags & XML_RELAXNG_IN_LIST) { | 
6486  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_INTERLEAVE,  | 
6487  | 0  |                            "Found forbidden pattern list//interleave\n",  | 
6488  | 0  |                            NULL, NULL);  | 
6489  | 0  |             }  | 
6490  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6491  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,  | 
6492  | 0  |                            "Found forbidden pattern data/except//interleave\n",  | 
6493  | 0  |                            NULL, NULL);  | 
6494  | 0  |             }  | 
6495  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6496  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,  | 
6497  | 0  |                            "Found forbidden pattern start//interleave\n",  | 
6498  | 0  |                            NULL, NULL);  | 
6499  | 0  |             }  | 
6500  | 0  |             if (flags & XML_RELAXNG_IN_ONEORMORE)  | 
6501  | 0  |                 nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE;  | 
6502  | 0  |             else  | 
6503  | 0  |                 nflags = flags;  | 
6504  | 0  |             ret =  | 
6505  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,  | 
6506  | 0  |                                      cur->type);  | 
6507  | 0  |         } else if (cur->type == XML_RELAXNG_EXCEPT) { | 
6508  | 0  |             if ((cur->parent != NULL) &&  | 
6509  | 0  |                 (cur->parent->type == XML_RELAXNG_DATATYPE))  | 
6510  | 0  |                 nflags = flags | XML_RELAXNG_IN_DATAEXCEPT;  | 
6511  | 0  |             else  | 
6512  | 0  |                 nflags = flags;  | 
6513  | 0  |             ret =  | 
6514  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->content, nflags,  | 
6515  | 0  |                                      cur->type);  | 
6516  | 0  |         } else if (cur->type == XML_RELAXNG_DATATYPE) { | 
6517  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6518  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_DATA,  | 
6519  | 0  |                            "Found forbidden pattern start//data\n", NULL,  | 
6520  | 0  |                            NULL);  | 
6521  | 0  |             }  | 
6522  | 0  |             xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);  | 
6523  | 0  |             ret = XML_RELAXNG_CONTENT_SIMPLE;  | 
6524  | 0  |         } else if (cur->type == XML_RELAXNG_VALUE) { | 
6525  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6526  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_VALUE,  | 
6527  | 0  |                            "Found forbidden pattern start//value\n", NULL,  | 
6528  | 0  |                            NULL);  | 
6529  | 0  |             }  | 
6530  | 0  |             xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);  | 
6531  | 0  |             ret = XML_RELAXNG_CONTENT_SIMPLE;  | 
6532  | 0  |         } else if (cur->type == XML_RELAXNG_TEXT) { | 
6533  | 0  |             if (flags & XML_RELAXNG_IN_LIST) { | 
6534  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_TEXT,  | 
6535  | 0  |                            "Found forbidden pattern list//text\n", NULL,  | 
6536  | 0  |                            NULL);  | 
6537  | 0  |             }  | 
6538  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6539  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_TEXT,  | 
6540  | 0  |                            "Found forbidden pattern data/except//text\n",  | 
6541  | 0  |                            NULL, NULL);  | 
6542  | 0  |             }  | 
6543  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6544  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_TEXT,  | 
6545  | 0  |                            "Found forbidden pattern start//text\n", NULL,  | 
6546  | 0  |                            NULL);  | 
6547  | 0  |             }  | 
6548  | 0  |             ret = XML_RELAXNG_CONTENT_COMPLEX;  | 
6549  | 0  |         } else if (cur->type == XML_RELAXNG_EMPTY) { | 
6550  | 0  |             if (flags & XML_RELAXNG_IN_DATAEXCEPT) { | 
6551  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_EMPTY,  | 
6552  | 0  |                            "Found forbidden pattern data/except//empty\n",  | 
6553  | 0  |                            NULL, NULL);  | 
6554  | 0  |             }  | 
6555  | 0  |             if (flags & XML_RELAXNG_IN_START) { | 
6556  | 0  |                 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_EMPTY,  | 
6557  | 0  |                            "Found forbidden pattern start//empty\n", NULL,  | 
6558  | 0  |                            NULL);  | 
6559  | 0  |             }  | 
6560  | 0  |             ret = XML_RELAXNG_CONTENT_EMPTY;  | 
6561  | 0  |         } else if (cur->type == XML_RELAXNG_CHOICE) { | 
6562  | 0  |             xmlRelaxNGCheckChoiceDeterminism(ctxt, cur);  | 
6563  | 0  |             ret =  | 
6564  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);  | 
6565  | 0  |         } else { | 
6566  | 0  |             ret =  | 
6567  | 0  |                 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);  | 
6568  | 0  |         }  | 
6569  | 0  |         cur = cur->next;  | 
6570  | 0  |         if (ptype == XML_RELAXNG_GROUP) { | 
6571  | 0  |             val = xmlRelaxNGGroupContentType(val, ret);  | 
6572  | 0  |         } else if (ptype == XML_RELAXNG_INTERLEAVE) { | 
6573  |  |             /*  | 
6574  |  |              * TODO: scan complain that tmp is never used, seems on purpose  | 
6575  |  |              *       need double-checking  | 
6576  |  |              */  | 
6577  | 0  |             tmp = xmlRelaxNGGroupContentType(val, ret);  | 
6578  | 0  |             if (tmp != XML_RELAXNG_CONTENT_ERROR)  | 
6579  | 0  |                 tmp = xmlRelaxNGMaxContentType(val, ret);  | 
6580  | 0  |         } else if (ptype == XML_RELAXNG_CHOICE) { | 
6581  | 0  |             val = xmlRelaxNGMaxContentType(val, ret);  | 
6582  | 0  |         } else if (ptype == XML_RELAXNG_LIST) { | 
6583  | 0  |             val = XML_RELAXNG_CONTENT_SIMPLE;  | 
6584  | 0  |         } else if (ptype == XML_RELAXNG_EXCEPT) { | 
6585  | 0  |             if (ret == XML_RELAXNG_CONTENT_ERROR)  | 
6586  | 0  |                 val = XML_RELAXNG_CONTENT_ERROR;  | 
6587  | 0  |             else  | 
6588  | 0  |                 val = XML_RELAXNG_CONTENT_SIMPLE;  | 
6589  | 0  |         } else { | 
6590  | 0  |             val = xmlRelaxNGGroupContentType(val, ret);  | 
6591  | 0  |         }  | 
6592  |  | 
  | 
6593  | 0  |     }  | 
6594  | 0  |     return (val);  | 
6595  | 0  | }  | 
6596  |  |  | 
6597  |  | /**  | 
6598  |  |  * xmlRelaxNGParseGrammar:  | 
6599  |  |  * @ctxt:  a Relax-NG parser context  | 
6600  |  |  * @nodes:  grammar children nodes  | 
6601  |  |  *  | 
6602  |  |  * parse a Relax-NG <grammar> node  | 
6603  |  |  *  | 
6604  |  |  * Returns the internal xmlRelaxNGGrammarPtr built or  | 
6605  |  |  *         NULL in case of error  | 
6606  |  |  */  | 
6607  |  | static xmlRelaxNGGrammarPtr  | 
6608  |  | xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)  | 
6609  | 0  | { | 
6610  | 0  |     xmlRelaxNGGrammarPtr ret, tmp, old;  | 
6611  |  | 
  | 
6612  |  | #ifdef DEBUG_GRAMMAR  | 
6613  |  |     xmlGenericError(xmlGenericErrorContext, "Parsing a new grammar\n");  | 
6614  |  | #endif  | 
6615  |  | 
  | 
6616  | 0  |     ret = xmlRelaxNGNewGrammar(ctxt);  | 
6617  | 0  |     if (ret == NULL)  | 
6618  | 0  |         return (NULL);  | 
6619  |  |  | 
6620  |  |     /*  | 
6621  |  |      * Link the new grammar in the tree  | 
6622  |  |      */  | 
6623  | 0  |     ret->parent = ctxt->grammar;  | 
6624  | 0  |     if (ctxt->grammar != NULL) { | 
6625  | 0  |         tmp = ctxt->grammar->children;  | 
6626  | 0  |         if (tmp == NULL) { | 
6627  | 0  |             ctxt->grammar->children = ret;  | 
6628  | 0  |         } else { | 
6629  | 0  |             while (tmp->next != NULL)  | 
6630  | 0  |                 tmp = tmp->next;  | 
6631  | 0  |             tmp->next = ret;  | 
6632  | 0  |         }  | 
6633  | 0  |     }  | 
6634  |  | 
  | 
6635  | 0  |     old = ctxt->grammar;  | 
6636  | 0  |     ctxt->grammar = ret;  | 
6637  | 0  |     xmlRelaxNGParseGrammarContent(ctxt, nodes);  | 
6638  | 0  |     ctxt->grammar = ret;  | 
6639  | 0  |     if (ctxt->grammar == NULL) { | 
6640  | 0  |         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,  | 
6641  | 0  |                    "Failed to parse <grammar> content\n", NULL, NULL);  | 
6642  | 0  |     } else if (ctxt->grammar->start == NULL) { | 
6643  | 0  |         xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_NO_START,  | 
6644  | 0  |                    "Element <grammar> has no <start>\n", NULL, NULL);  | 
6645  | 0  |     }  | 
6646  |  |  | 
6647  |  |     /*  | 
6648  |  |      * Apply 4.17 merging rules to defines and starts  | 
6649  |  |      */  | 
6650  | 0  |     xmlRelaxNGCombineStart(ctxt, ret);  | 
6651  | 0  |     if (ret->defs != NULL) { | 
6652  | 0  |         xmlHashScan(ret->defs, xmlRelaxNGCheckCombine, ctxt);  | 
6653  | 0  |     }  | 
6654  |  |  | 
6655  |  |     /*  | 
6656  |  |      * link together defines and refs in this grammar  | 
6657  |  |      */  | 
6658  | 0  |     if (ret->refs != NULL) { | 
6659  | 0  |         xmlHashScan(ret->refs, xmlRelaxNGCheckReference, ctxt);  | 
6660  | 0  |     }  | 
6661  |  |  | 
6662  |  |  | 
6663  |  |     /* @@@@ */  | 
6664  |  | 
  | 
6665  | 0  |     ctxt->grammar = old;  | 
6666  | 0  |     return (ret);  | 
6667  | 0  | }  | 
6668  |  |  | 
6669  |  | /**  | 
6670  |  |  * xmlRelaxNGParseDocument:  | 
6671  |  |  * @ctxt:  a Relax-NG parser context  | 
6672  |  |  * @node:  the root node of the RelaxNG schema  | 
6673  |  |  *  | 
6674  |  |  * parse a Relax-NG definition resource and build an internal  | 
6675  |  |  * xmlRelaxNG structure which can be used to validate instances.  | 
6676  |  |  *  | 
6677  |  |  * Returns the internal XML RelaxNG structure built or  | 
6678  |  |  *         NULL in case of error  | 
6679  |  |  */  | 
6680  |  | static xmlRelaxNGPtr  | 
6681  |  | xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
6682  | 0  | { | 
6683  | 0  |     xmlRelaxNGPtr schema = NULL;  | 
6684  | 0  |     const xmlChar *olddefine;  | 
6685  | 0  |     xmlRelaxNGGrammarPtr old;  | 
6686  |  | 
  | 
6687  | 0  |     if ((ctxt == NULL) || (node == NULL))  | 
6688  | 0  |         return (NULL);  | 
6689  |  |  | 
6690  | 0  |     schema = xmlRelaxNGNewRelaxNG(ctxt);  | 
6691  | 0  |     if (schema == NULL)  | 
6692  | 0  |         return (NULL);  | 
6693  |  |  | 
6694  | 0  |     olddefine = ctxt->define;  | 
6695  | 0  |     ctxt->define = NULL;  | 
6696  | 0  |     if (IS_RELAXNG(node, "grammar")) { | 
6697  | 0  |         schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children);  | 
6698  | 0  |         if (schema->topgrammar == NULL) { | 
6699  | 0  |             xmlRelaxNGFree(schema);  | 
6700  | 0  |             return (NULL);  | 
6701  | 0  |         }  | 
6702  | 0  |     } else { | 
6703  | 0  |         xmlRelaxNGGrammarPtr tmp, ret;  | 
6704  |  | 
  | 
6705  | 0  |         schema->topgrammar = ret = xmlRelaxNGNewGrammar(ctxt);  | 
6706  | 0  |         if (schema->topgrammar == NULL) { | 
6707  | 0  |             xmlRelaxNGFree(schema);  | 
6708  | 0  |             return (NULL);  | 
6709  | 0  |         }  | 
6710  |  |         /*  | 
6711  |  |          * Link the new grammar in the tree  | 
6712  |  |          */  | 
6713  | 0  |         ret->parent = ctxt->grammar;  | 
6714  | 0  |         if (ctxt->grammar != NULL) { | 
6715  | 0  |             tmp = ctxt->grammar->children;  | 
6716  | 0  |             if (tmp == NULL) { | 
6717  | 0  |                 ctxt->grammar->children = ret;  | 
6718  | 0  |             } else { | 
6719  | 0  |                 while (tmp->next != NULL)  | 
6720  | 0  |                     tmp = tmp->next;  | 
6721  | 0  |                 tmp->next = ret;  | 
6722  | 0  |             }  | 
6723  | 0  |         }  | 
6724  | 0  |         old = ctxt->grammar;  | 
6725  | 0  |         ctxt->grammar = ret;  | 
6726  | 0  |         xmlRelaxNGParseStart(ctxt, node);  | 
6727  | 0  |         if (old != NULL)  | 
6728  | 0  |             ctxt->grammar = old;  | 
6729  | 0  |     }  | 
6730  | 0  |     ctxt->define = olddefine;  | 
6731  | 0  |     if (schema->topgrammar->start != NULL) { | 
6732  | 0  |         xmlRelaxNGCheckCycles(ctxt, schema->topgrammar->start, 0);  | 
6733  | 0  |         if ((ctxt->flags & XML_RELAXNG_IN_EXTERNALREF) == 0) { | 
6734  | 0  |             xmlRelaxNGSimplify(ctxt, schema->topgrammar->start, NULL);  | 
6735  | 0  |             while ((schema->topgrammar->start != NULL) &&  | 
6736  | 0  |                    (schema->topgrammar->start->type == XML_RELAXNG_NOOP) &&  | 
6737  | 0  |                    (schema->topgrammar->start->next != NULL))  | 
6738  | 0  |                 schema->topgrammar->start =  | 
6739  | 0  |                     schema->topgrammar->start->content;  | 
6740  | 0  |             xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start,  | 
6741  | 0  |                                  XML_RELAXNG_IN_START, XML_RELAXNG_NOOP);  | 
6742  | 0  |         }  | 
6743  | 0  |     }  | 
6744  |  | #ifdef DEBUG  | 
6745  |  |     if (schema == NULL)  | 
6746  |  |         xmlGenericError(xmlGenericErrorContext,  | 
6747  |  |                         "xmlRelaxNGParseDocument() failed\n");  | 
6748  |  | #endif  | 
6749  |  | 
  | 
6750  | 0  |     return (schema);  | 
6751  | 0  | }  | 
6752  |  |  | 
6753  |  | /************************************************************************  | 
6754  |  |  *                  *  | 
6755  |  |  *      Reading RelaxNGs        *  | 
6756  |  |  *                  *  | 
6757  |  |  ************************************************************************/  | 
6758  |  |  | 
6759  |  | /**  | 
6760  |  |  * xmlRelaxNGNewParserCtxt:  | 
6761  |  |  * @URL:  the location of the schema  | 
6762  |  |  *  | 
6763  |  |  * Create an XML RelaxNGs parse context for that file/resource expected  | 
6764  |  |  * to contain an XML RelaxNGs file.  | 
6765  |  |  *  | 
6766  |  |  * Returns the parser context or NULL in case of error  | 
6767  |  |  */  | 
6768  |  | xmlRelaxNGParserCtxtPtr  | 
6769  |  | xmlRelaxNGNewParserCtxt(const char *URL)  | 
6770  | 0  | { | 
6771  | 0  |     xmlRelaxNGParserCtxtPtr ret;  | 
6772  |  | 
  | 
6773  | 0  |     if (URL == NULL)  | 
6774  | 0  |         return (NULL);  | 
6775  |  |  | 
6776  | 0  |     ret =  | 
6777  | 0  |         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));  | 
6778  | 0  |     if (ret == NULL) { | 
6779  | 0  |         xmlRngPErrMemory(NULL, "building parser\n");  | 
6780  | 0  |         return (NULL);  | 
6781  | 0  |     }  | 
6782  | 0  |     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));  | 
6783  | 0  |     ret->URL = xmlStrdup((const xmlChar *) URL);  | 
6784  | 0  |     ret->error = xmlGenericError;  | 
6785  | 0  |     ret->userData = xmlGenericErrorContext;  | 
6786  | 0  |     return (ret);  | 
6787  | 0  | }  | 
6788  |  |  | 
6789  |  | /**  | 
6790  |  |  * xmlRelaxNGNewMemParserCtxt:  | 
6791  |  |  * @buffer:  a pointer to a char array containing the schemas  | 
6792  |  |  * @size:  the size of the array  | 
6793  |  |  *  | 
6794  |  |  * Create an XML RelaxNGs parse context for that memory buffer expected  | 
6795  |  |  * to contain an XML RelaxNGs file.  | 
6796  |  |  *  | 
6797  |  |  * Returns the parser context or NULL in case of error  | 
6798  |  |  */  | 
6799  |  | xmlRelaxNGParserCtxtPtr  | 
6800  |  | xmlRelaxNGNewMemParserCtxt(const char *buffer, int size)  | 
6801  | 0  | { | 
6802  | 0  |     xmlRelaxNGParserCtxtPtr ret;  | 
6803  |  | 
  | 
6804  | 0  |     if ((buffer == NULL) || (size <= 0))  | 
6805  | 0  |         return (NULL);  | 
6806  |  |  | 
6807  | 0  |     ret =  | 
6808  | 0  |         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));  | 
6809  | 0  |     if (ret == NULL) { | 
6810  | 0  |         xmlRngPErrMemory(NULL, "building parser\n");  | 
6811  | 0  |         return (NULL);  | 
6812  | 0  |     }  | 
6813  | 0  |     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));  | 
6814  | 0  |     ret->buffer = buffer;  | 
6815  | 0  |     ret->size = size;  | 
6816  | 0  |     ret->error = xmlGenericError;  | 
6817  | 0  |     ret->userData = xmlGenericErrorContext;  | 
6818  | 0  |     return (ret);  | 
6819  | 0  | }  | 
6820  |  |  | 
6821  |  | /**  | 
6822  |  |  * xmlRelaxNGNewDocParserCtxt:  | 
6823  |  |  * @doc:  a preparsed document tree  | 
6824  |  |  *  | 
6825  |  |  * Create an XML RelaxNGs parser context for that document.  | 
6826  |  |  * Note: since the process of compiling a RelaxNG schemas modifies the  | 
6827  |  |  *       document, the @doc parameter is duplicated internally.  | 
6828  |  |  *  | 
6829  |  |  * Returns the parser context or NULL in case of error  | 
6830  |  |  */  | 
6831  |  | xmlRelaxNGParserCtxtPtr  | 
6832  |  | xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc)  | 
6833  | 0  | { | 
6834  | 0  |     xmlRelaxNGParserCtxtPtr ret;  | 
6835  | 0  |     xmlDocPtr copy;  | 
6836  |  | 
  | 
6837  | 0  |     if (doc == NULL)  | 
6838  | 0  |         return (NULL);  | 
6839  | 0  |     copy = xmlCopyDoc(doc, 1);  | 
6840  | 0  |     if (copy == NULL)  | 
6841  | 0  |         return (NULL);  | 
6842  |  |  | 
6843  | 0  |     ret =  | 
6844  | 0  |         (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));  | 
6845  | 0  |     if (ret == NULL) { | 
6846  | 0  |         xmlRngPErrMemory(NULL, "building parser\n");  | 
6847  | 0  |         xmlFreeDoc(copy);  | 
6848  | 0  |         return (NULL);  | 
6849  | 0  |     }  | 
6850  | 0  |     memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));  | 
6851  | 0  |     ret->document = copy;  | 
6852  | 0  |     ret->freedoc = 1;  | 
6853  | 0  |     ret->userData = xmlGenericErrorContext;  | 
6854  | 0  |     return (ret);  | 
6855  | 0  | }  | 
6856  |  |  | 
6857  |  | /**  | 
6858  |  |  * xmlRelaxNGFreeParserCtxt:  | 
6859  |  |  * @ctxt:  the schema parser context  | 
6860  |  |  *  | 
6861  |  |  * Free the resources associated to the schema parser context  | 
6862  |  |  */  | 
6863  |  | void  | 
6864  |  | xmlRelaxNGFreeParserCtxt(xmlRelaxNGParserCtxtPtr ctxt)  | 
6865  | 0  | { | 
6866  | 0  |     if (ctxt == NULL)  | 
6867  | 0  |         return;  | 
6868  | 0  |     if (ctxt->URL != NULL)  | 
6869  | 0  |         xmlFree(ctxt->URL);  | 
6870  | 0  |     if (ctxt->doc != NULL)  | 
6871  | 0  |         xmlRelaxNGFreeDocument(ctxt->doc);  | 
6872  | 0  |     if (ctxt->interleaves != NULL)  | 
6873  | 0  |         xmlHashFree(ctxt->interleaves, NULL);  | 
6874  | 0  |     if (ctxt->documents != NULL)  | 
6875  | 0  |         xmlRelaxNGFreeDocumentList(ctxt->documents);  | 
6876  | 0  |     if (ctxt->includes != NULL)  | 
6877  | 0  |         xmlRelaxNGFreeIncludeList(ctxt->includes);  | 
6878  | 0  |     if (ctxt->docTab != NULL)  | 
6879  | 0  |         xmlFree(ctxt->docTab);  | 
6880  | 0  |     if (ctxt->incTab != NULL)  | 
6881  | 0  |         xmlFree(ctxt->incTab);  | 
6882  | 0  |     if (ctxt->defTab != NULL) { | 
6883  | 0  |         int i;  | 
6884  |  | 
  | 
6885  | 0  |         for (i = 0; i < ctxt->defNr; i++)  | 
6886  | 0  |             xmlRelaxNGFreeDefine(ctxt->defTab[i]);  | 
6887  | 0  |         xmlFree(ctxt->defTab);  | 
6888  | 0  |     }  | 
6889  | 0  |     if ((ctxt->document != NULL) && (ctxt->freedoc))  | 
6890  | 0  |         xmlFreeDoc(ctxt->document);  | 
6891  | 0  |     xmlFree(ctxt);  | 
6892  | 0  | }  | 
6893  |  |  | 
6894  |  | /**  | 
6895  |  |  * xmlRelaxNGNormExtSpace:  | 
6896  |  |  * @value:  a value  | 
6897  |  |  *  | 
6898  |  |  * Removes the leading and ending spaces of the value  | 
6899  |  |  * The string is modified "in situ"  | 
6900  |  |  */  | 
6901  |  | static void  | 
6902  |  | xmlRelaxNGNormExtSpace(xmlChar * value)  | 
6903  | 0  | { | 
6904  | 0  |     xmlChar *start = value;  | 
6905  | 0  |     xmlChar *cur = value;  | 
6906  |  | 
  | 
6907  | 0  |     if (value == NULL)  | 
6908  | 0  |         return;  | 
6909  |  |  | 
6910  | 0  |     while (IS_BLANK_CH(*cur))  | 
6911  | 0  |         cur++;  | 
6912  | 0  |     if (cur == start) { | 
6913  | 0  |         do { | 
6914  | 0  |             while ((*cur != 0) && (!IS_BLANK_CH(*cur)))  | 
6915  | 0  |                 cur++;  | 
6916  | 0  |             if (*cur == 0)  | 
6917  | 0  |                 return;  | 
6918  | 0  |             start = cur;  | 
6919  | 0  |             while (IS_BLANK_CH(*cur))  | 
6920  | 0  |                 cur++;  | 
6921  | 0  |             if (*cur == 0) { | 
6922  | 0  |                 *start = 0;  | 
6923  | 0  |                 return;  | 
6924  | 0  |             }  | 
6925  | 0  |         } while (1);  | 
6926  | 0  |     } else { | 
6927  | 0  |         do { | 
6928  | 0  |             while ((*cur != 0) && (!IS_BLANK_CH(*cur)))  | 
6929  | 0  |                 *start++ = *cur++;  | 
6930  | 0  |             if (*cur == 0) { | 
6931  | 0  |                 *start = 0;  | 
6932  | 0  |                 return;  | 
6933  | 0  |             }  | 
6934  |  |             /* don't try to normalize the inner spaces */  | 
6935  | 0  |             while (IS_BLANK_CH(*cur))  | 
6936  | 0  |                 cur++;  | 
6937  | 0  |             if (*cur == 0) { | 
6938  | 0  |                 *start = 0;  | 
6939  | 0  |                 return;  | 
6940  | 0  |             }  | 
6941  | 0  |             *start++ = *cur++;  | 
6942  | 0  |         } while (1);  | 
6943  | 0  |     }  | 
6944  | 0  | }  | 
6945  |  |  | 
6946  |  | /**  | 
6947  |  |  * xmlRelaxNGCleanupAttributes:  | 
6948  |  |  * @ctxt:  a Relax-NG parser context  | 
6949  |  |  * @node:  a Relax-NG node  | 
6950  |  |  *  | 
6951  |  |  * Check all the attributes on the given node  | 
6952  |  |  */  | 
6953  |  | static void  | 
6954  |  | xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)  | 
6955  | 0  | { | 
6956  | 0  |     xmlAttrPtr cur, next;  | 
6957  |  | 
  | 
6958  | 0  |     cur = node->properties;  | 
6959  | 0  |     while (cur != NULL) { | 
6960  | 0  |         next = cur->next;  | 
6961  | 0  |         if ((cur->ns == NULL) ||  | 
6962  | 0  |             (xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) { | 
6963  | 0  |             if (xmlStrEqual(cur->name, BAD_CAST "name")) { | 
6964  | 0  |                 if ((!xmlStrEqual(node->name, BAD_CAST "element")) &&  | 
6965  | 0  |                     (!xmlStrEqual(node->name, BAD_CAST "attribute")) &&  | 
6966  | 0  |                     (!xmlStrEqual(node->name, BAD_CAST "ref")) &&  | 
6967  | 0  |                     (!xmlStrEqual(node->name, BAD_CAST "parentRef")) &&  | 
6968  | 0  |                     (!xmlStrEqual(node->name, BAD_CAST "param")) &&  | 
6969  | 0  |                     (!xmlStrEqual(node->name, BAD_CAST "define"))) { | 
6970  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,  | 
6971  | 0  |                                "Attribute %s is not allowed on %s\n",  | 
6972  | 0  |                                cur->name, node->name);  | 
6973  | 0  |                 }  | 
6974  | 0  |             } else if (xmlStrEqual(cur->name, BAD_CAST "type")) { | 
6975  | 0  |                 if ((!xmlStrEqual(node->name, BAD_CAST "value")) &&  | 
6976  | 0  |                     (!xmlStrEqual(node->name, BAD_CAST "data"))) { | 
6977  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,  | 
6978  | 0  |                                "Attribute %s is not allowed on %s\n",  | 
6979  | 0  |                                cur->name, node->name);  | 
6980  | 0  |                 }  | 
6981  | 0  |             } else if (xmlStrEqual(cur->name, BAD_CAST "href")) { | 
6982  | 0  |                 if ((!xmlStrEqual(node->name, BAD_CAST "externalRef")) &&  | 
6983  | 0  |                     (!xmlStrEqual(node->name, BAD_CAST "include"))) { | 
6984  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,  | 
6985  | 0  |                                "Attribute %s is not allowed on %s\n",  | 
6986  | 0  |                                cur->name, node->name);  | 
6987  | 0  |                 }  | 
6988  | 0  |             } else if (xmlStrEqual(cur->name, BAD_CAST "combine")) { | 
6989  | 0  |                 if ((!xmlStrEqual(node->name, BAD_CAST "start")) &&  | 
6990  | 0  |                     (!xmlStrEqual(node->name, BAD_CAST "define"))) { | 
6991  | 0  |                     xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,  | 
6992  | 0  |                                "Attribute %s is not allowed on %s\n",  | 
6993  | 0  |                                cur->name, node->name);  | 
6994  | 0  |                 }  | 
6995  | 0  |             } else if (xmlStrEqual(cur->name, BAD_CAST "datatypeLibrary")) { | 
6996  | 0  |                 xmlChar *val;  | 
6997  | 0  |                 xmlURIPtr uri;  | 
6998  |  | 
  | 
6999  | 0  |                 val = xmlNodeListGetString(node->doc, cur->children, 1);  | 
7000  | 0  |                 if (val != NULL) { | 
7001  | 0  |                     if (val[0] != 0) { | 
7002  | 0  |                         uri = xmlParseURI((const char *) val);  | 
7003  | 0  |                         if (uri == NULL) { | 
7004  | 0  |                             xmlRngPErr(ctxt, node, XML_RNGP_INVALID_URI,  | 
7005  | 0  |                                        "Attribute %s contains invalid URI %s\n",  | 
7006  | 0  |                                        cur->name, val);  | 
7007  | 0  |                         } else { | 
7008  | 0  |                             if (uri->scheme == NULL) { | 
7009  | 0  |                                 xmlRngPErr(ctxt, node, XML_RNGP_URI_NOT_ABSOLUTE,  | 
7010  | 0  |                                            "Attribute %s URI %s is not absolute\n",  | 
7011  | 0  |                                            cur->name, val);  | 
7012  | 0  |                             }  | 
7013  | 0  |                             if (uri->fragment != NULL) { | 
7014  | 0  |                                 xmlRngPErr(ctxt, node, XML_RNGP_URI_FRAGMENT,  | 
7015  | 0  |                                            "Attribute %s URI %s has a fragment ID\n",  | 
7016  | 0  |                                            cur->name, val);  | 
7017  | 0  |                             }  | 
7018  | 0  |                             xmlFreeURI(uri);  | 
7019  | 0  |                         }  | 
7020  | 0  |                     }  | 
7021  | 0  |                     xmlFree(val);  | 
7022  | 0  |                 }  | 
7023  | 0  |             } else if (!xmlStrEqual(cur->name, BAD_CAST "ns")) { | 
7024  | 0  |                 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_ATTRIBUTE,  | 
7025  | 0  |                            "Unknown attribute %s on %s\n", cur->name,  | 
7026  | 0  |                            node->name);  | 
7027  | 0  |             }  | 
7028  | 0  |         }  | 
7029  | 0  |         cur = next;  | 
7030  | 0  |     }  | 
7031  | 0  | }  | 
7032  |  |  | 
7033  |  | /**  | 
7034  |  |  * xmlRelaxNGCleanupTree:  | 
7035  |  |  * @ctxt:  a Relax-NG parser context  | 
7036  |  |  * @root:  an xmlNodePtr subtree  | 
7037  |  |  *  | 
7038  |  |  * Cleanup the subtree from unwanted nodes for parsing, resolve  | 
7039  |  |  * Include and externalRef lookups.  | 
7040  |  |  */  | 
7041  |  | static void  | 
7042  |  | xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root)  | 
7043  | 0  | { | 
7044  | 0  |     xmlNodePtr cur, delete;  | 
7045  |  | 
  | 
7046  | 0  |     delete = NULL;  | 
7047  | 0  |     cur = root;  | 
7048  | 0  |     while (cur != NULL) { | 
7049  | 0  |         if (delete != NULL) { | 
7050  | 0  |             xmlUnlinkNode(delete);  | 
7051  | 0  |             xmlFreeNode(delete);  | 
7052  | 0  |             delete = NULL;  | 
7053  | 0  |         }  | 
7054  | 0  |         if (cur->type == XML_ELEMENT_NODE) { | 
7055  |  |             /*  | 
7056  |  |              * Simplification 4.1. Annotations  | 
7057  |  |              */  | 
7058  | 0  |             if ((cur->ns == NULL) ||  | 
7059  | 0  |                 (!xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) { | 
7060  | 0  |                 if ((cur->parent != NULL) &&  | 
7061  | 0  |                     (cur->parent->type == XML_ELEMENT_NODE) &&  | 
7062  | 0  |                     ((xmlStrEqual(cur->parent->name, BAD_CAST "name")) ||  | 
7063  | 0  |                      (xmlStrEqual(cur->parent->name, BAD_CAST "value")) ||  | 
7064  | 0  |                      (xmlStrEqual(cur->parent->name, BAD_CAST "param")))) { | 
7065  | 0  |                     xmlRngPErr(ctxt, cur, XML_RNGP_FOREIGN_ELEMENT,  | 
7066  | 0  |                                "element %s doesn't allow foreign elements\n",  | 
7067  | 0  |                                cur->parent->name, NULL);  | 
7068  | 0  |                 }  | 
7069  | 0  |                 delete = cur;  | 
7070  | 0  |                 goto skip_children;  | 
7071  | 0  |             } else { | 
7072  | 0  |                 xmlRelaxNGCleanupAttributes(ctxt, cur);  | 
7073  | 0  |                 if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) { | 
7074  | 0  |                     xmlChar *href, *ns, *base, *URL;  | 
7075  | 0  |                     xmlRelaxNGDocumentPtr docu;  | 
7076  | 0  |                     xmlNodePtr tmp;  | 
7077  | 0  |         xmlURIPtr uri;  | 
7078  |  | 
  | 
7079  | 0  |                     ns = xmlGetProp(cur, BAD_CAST "ns");  | 
7080  | 0  |                     if (ns == NULL) { | 
7081  | 0  |                         tmp = cur->parent;  | 
7082  | 0  |                         while ((tmp != NULL) &&  | 
7083  | 0  |                                (tmp->type == XML_ELEMENT_NODE)) { | 
7084  | 0  |                             ns = xmlGetProp(tmp, BAD_CAST "ns");  | 
7085  | 0  |                             if (ns != NULL)  | 
7086  | 0  |                                 break;  | 
7087  | 0  |                             tmp = tmp->parent;  | 
7088  | 0  |                         }  | 
7089  | 0  |                     }  | 
7090  | 0  |                     href = xmlGetProp(cur, BAD_CAST "href");  | 
7091  | 0  |                     if (href == NULL) { | 
7092  | 0  |                         xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,  | 
7093  | 0  |                                    "xmlRelaxNGParse: externalRef has no href attribute\n",  | 
7094  | 0  |                                    NULL, NULL);  | 
7095  | 0  |                         if (ns != NULL)  | 
7096  | 0  |                             xmlFree(ns);  | 
7097  | 0  |                         delete = cur;  | 
7098  | 0  |                         goto skip_children;  | 
7099  | 0  |                     }  | 
7100  | 0  |         uri = xmlParseURI((const char *) href);  | 
7101  | 0  |         if (uri == NULL) { | 
7102  | 0  |                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,  | 
7103  | 0  |                                    "Incorrect URI for externalRef %s\n",  | 
7104  | 0  |                                    href, NULL);  | 
7105  | 0  |                         if (ns != NULL)  | 
7106  | 0  |                             xmlFree(ns);  | 
7107  | 0  |                         if (href != NULL)  | 
7108  | 0  |                             xmlFree(href);  | 
7109  | 0  |                         delete = cur;  | 
7110  | 0  |                         goto skip_children;  | 
7111  | 0  |         }  | 
7112  | 0  |         if (uri->fragment != NULL) { | 
7113  | 0  |                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,  | 
7114  | 0  |              "Fragment forbidden in URI for externalRef %s\n",  | 
7115  | 0  |                                    href, NULL);  | 
7116  | 0  |                         if (ns != NULL)  | 
7117  | 0  |                             xmlFree(ns);  | 
7118  | 0  |             xmlFreeURI(uri);  | 
7119  | 0  |                         if (href != NULL)  | 
7120  | 0  |                             xmlFree(href);  | 
7121  | 0  |                         delete = cur;  | 
7122  | 0  |                         goto skip_children;  | 
7123  | 0  |         }  | 
7124  | 0  |         xmlFreeURI(uri);  | 
7125  | 0  |                     base = xmlNodeGetBase(cur->doc, cur);  | 
7126  | 0  |                     URL = xmlBuildURI(href, base);  | 
7127  | 0  |                     if (URL == NULL) { | 
7128  | 0  |                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,  | 
7129  | 0  |                                    "Failed to compute URL for externalRef %s\n",  | 
7130  | 0  |                                    href, NULL);  | 
7131  | 0  |                         if (ns != NULL)  | 
7132  | 0  |                             xmlFree(ns);  | 
7133  | 0  |                         if (href != NULL)  | 
7134  | 0  |                             xmlFree(href);  | 
7135  | 0  |                         if (base != NULL)  | 
7136  | 0  |                             xmlFree(base);  | 
7137  | 0  |                         delete = cur;  | 
7138  | 0  |                         goto skip_children;  | 
7139  | 0  |                     }  | 
7140  | 0  |                     if (href != NULL)  | 
7141  | 0  |                         xmlFree(href);  | 
7142  | 0  |                     if (base != NULL)  | 
7143  | 0  |                         xmlFree(base);  | 
7144  | 0  |                     docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns);  | 
7145  | 0  |                     if (docu == NULL) { | 
7146  | 0  |                         xmlRngPErr(ctxt, cur, XML_RNGP_EXTERNAL_REF_FAILURE,  | 
7147  | 0  |                                    "Failed to load externalRef %s\n", URL,  | 
7148  | 0  |                                    NULL);  | 
7149  | 0  |                         if (ns != NULL)  | 
7150  | 0  |                             xmlFree(ns);  | 
7151  | 0  |                         xmlFree(URL);  | 
7152  | 0  |                         delete = cur;  | 
7153  | 0  |                         goto skip_children;  | 
7154  | 0  |                     }  | 
7155  | 0  |                     if (ns != NULL)  | 
7156  | 0  |                         xmlFree(ns);  | 
7157  | 0  |                     xmlFree(URL);  | 
7158  | 0  |                     cur->psvi = docu;  | 
7159  | 0  |                 } else if (xmlStrEqual(cur->name, BAD_CAST "include")) { | 
7160  | 0  |                     xmlChar *href, *ns, *base, *URL;  | 
7161  | 0  |                     xmlRelaxNGIncludePtr incl;  | 
7162  | 0  |                     xmlNodePtr tmp;  | 
7163  |  | 
  | 
7164  | 0  |                     href = xmlGetProp(cur, BAD_CAST "href");  | 
7165  | 0  |                     if (href == NULL) { | 
7166  | 0  |                         xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,  | 
7167  | 0  |                                    "xmlRelaxNGParse: include has no href attribute\n",  | 
7168  | 0  |                                    NULL, NULL);  | 
7169  | 0  |                         delete = cur;  | 
7170  | 0  |                         goto skip_children;  | 
7171  | 0  |                     }  | 
7172  | 0  |                     base = xmlNodeGetBase(cur->doc, cur);  | 
7173  | 0  |                     URL = xmlBuildURI(href, base);  | 
7174  | 0  |                     if (URL == NULL) { | 
7175  | 0  |                         xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,  | 
7176  | 0  |                                    "Failed to compute URL for include %s\n",  | 
7177  | 0  |                                    href, NULL);  | 
7178  | 0  |                         if (href != NULL)  | 
7179  | 0  |                             xmlFree(href);  | 
7180  | 0  |                         if (base != NULL)  | 
7181  | 0  |                             xmlFree(base);  | 
7182  | 0  |                         delete = cur;  | 
7183  | 0  |                         goto skip_children;  | 
7184  | 0  |                     }  | 
7185  | 0  |                     if (href != NULL)  | 
7186  | 0  |                         xmlFree(href);  | 
7187  | 0  |                     if (base != NULL)  | 
7188  | 0  |                         xmlFree(base);  | 
7189  | 0  |                     ns = xmlGetProp(cur, BAD_CAST "ns");  | 
7190  | 0  |                     if (ns == NULL) { | 
7191  | 0  |                         tmp = cur->parent;  | 
7192  | 0  |                         while ((tmp != NULL) &&  | 
7193  | 0  |                                (tmp->type == XML_ELEMENT_NODE)) { | 
7194  | 0  |                             ns = xmlGetProp(tmp, BAD_CAST "ns");  | 
7195  | 0  |                             if (ns != NULL)  | 
7196  | 0  |                                 break;  | 
7197  | 0  |                             tmp = tmp->parent;  | 
7198  | 0  |                         }  | 
7199  | 0  |                     }  | 
7200  | 0  |                     incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns);  | 
7201  | 0  |                     if (ns != NULL)  | 
7202  | 0  |                         xmlFree(ns);  | 
7203  | 0  |                     if (incl == NULL) { | 
7204  | 0  |                         xmlRngPErr(ctxt, cur, XML_RNGP_INCLUDE_FAILURE,  | 
7205  | 0  |                                    "Failed to load include %s\n", URL,  | 
7206  | 0  |                                    NULL);  | 
7207  | 0  |                         xmlFree(URL);  | 
7208  | 0  |                         delete = cur;  | 
7209  | 0  |                         goto skip_children;  | 
7210  | 0  |                     }  | 
7211  | 0  |                     xmlFree(URL);  | 
7212  | 0  |                     cur->psvi = incl;  | 
7213  | 0  |                 } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) ||  | 
7214  | 0  |                            (xmlStrEqual(cur->name, BAD_CAST "attribute")))  | 
7215  | 0  |                 { | 
7216  | 0  |                     xmlChar *name, *ns;  | 
7217  | 0  |                     xmlNodePtr text = NULL;  | 
7218  |  |  | 
7219  |  |                     /*  | 
7220  |  |                      * Simplification 4.8. name attribute of element  | 
7221  |  |                      * and attribute elements  | 
7222  |  |                      */  | 
7223  | 0  |                     name = xmlGetProp(cur, BAD_CAST "name");  | 
7224  | 0  |                     if (name != NULL) { | 
7225  | 0  |                         if (cur->children == NULL) { | 
7226  | 0  |                             text =  | 
7227  | 0  |                                 xmlNewChild(cur, cur->ns, BAD_CAST "name",  | 
7228  | 0  |                                             name);  | 
7229  | 0  |                         } else { | 
7230  | 0  |                             xmlNodePtr node;  | 
7231  |  | 
  | 
7232  | 0  |                             node = xmlNewDocNode(cur->doc, cur->ns,  | 
7233  | 0  |                                BAD_CAST "name", NULL);  | 
7234  | 0  |                             if (node != NULL) { | 
7235  | 0  |                                 xmlAddPrevSibling(cur->children, node);  | 
7236  | 0  |                                 text = xmlNewDocText(node->doc, name);  | 
7237  | 0  |                                 xmlAddChild(node, text);  | 
7238  | 0  |                                 text = node;  | 
7239  | 0  |                             }  | 
7240  | 0  |                         }  | 
7241  | 0  |                         if (text == NULL) { | 
7242  | 0  |                             xmlRngPErr(ctxt, cur, XML_RNGP_CREATE_FAILURE,  | 
7243  | 0  |                                        "Failed to create a name %s element\n",  | 
7244  | 0  |                                        name, NULL);  | 
7245  | 0  |                         }  | 
7246  | 0  |                         xmlUnsetProp(cur, BAD_CAST "name");  | 
7247  | 0  |                         xmlFree(name);  | 
7248  | 0  |                         ns = xmlGetProp(cur, BAD_CAST "ns");  | 
7249  | 0  |                         if (ns != NULL) { | 
7250  | 0  |                             if (text != NULL) { | 
7251  | 0  |                                 xmlSetProp(text, BAD_CAST "ns", ns);  | 
7252  |  |                                 /* xmlUnsetProp(cur, BAD_CAST "ns"); */  | 
7253  | 0  |                             }  | 
7254  | 0  |                             xmlFree(ns);  | 
7255  | 0  |                         } else if (xmlStrEqual(cur->name,  | 
7256  | 0  |                                                BAD_CAST "attribute")) { | 
7257  | 0  |                             xmlSetProp(text, BAD_CAST "ns", BAD_CAST "");  | 
7258  | 0  |                         }  | 
7259  | 0  |                     }  | 
7260  | 0  |                 } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) ||  | 
7261  | 0  |                            (xmlStrEqual(cur->name, BAD_CAST "nsName")) ||  | 
7262  | 0  |                            (xmlStrEqual(cur->name, BAD_CAST "value"))) { | 
7263  |  |                     /*  | 
7264  |  |                      * Simplification 4.8. name attribute of element  | 
7265  |  |                      * and attribute elements  | 
7266  |  |                      */  | 
7267  | 0  |                     if (xmlHasProp(cur, BAD_CAST "ns") == NULL) { | 
7268  | 0  |                         xmlNodePtr node;  | 
7269  | 0  |                         xmlChar *ns = NULL;  | 
7270  |  | 
  | 
7271  | 0  |                         node = cur->parent;  | 
7272  | 0  |                         while ((node != NULL) &&  | 
7273  | 0  |                                (node->type == XML_ELEMENT_NODE)) { | 
7274  | 0  |                             ns = xmlGetProp(node, BAD_CAST "ns");  | 
7275  | 0  |                             if (ns != NULL) { | 
7276  | 0  |                                 break;  | 
7277  | 0  |                             }  | 
7278  | 0  |                             node = node->parent;  | 
7279  | 0  |                         }  | 
7280  | 0  |                         if (ns == NULL) { | 
7281  | 0  |                             xmlSetProp(cur, BAD_CAST "ns", BAD_CAST "");  | 
7282  | 0  |                         } else { | 
7283  | 0  |                             xmlSetProp(cur, BAD_CAST "ns", ns);  | 
7284  | 0  |                             xmlFree(ns);  | 
7285  | 0  |                         }  | 
7286  | 0  |                     }  | 
7287  | 0  |                     if (xmlStrEqual(cur->name, BAD_CAST "name")) { | 
7288  | 0  |                         xmlChar *name, *local, *prefix;  | 
7289  |  |  | 
7290  |  |                         /*  | 
7291  |  |                          * Simplification: 4.10. QNames  | 
7292  |  |                          */  | 
7293  | 0  |                         name = xmlNodeGetContent(cur);  | 
7294  | 0  |                         if (name != NULL) { | 
7295  | 0  |                             local = xmlSplitQName2(name, &prefix);  | 
7296  | 0  |                             if (local != NULL) { | 
7297  | 0  |                                 xmlNsPtr ns;  | 
7298  |  | 
  | 
7299  | 0  |                                 ns = xmlSearchNs(cur->doc, cur, prefix);  | 
7300  | 0  |                                 if (ns == NULL) { | 
7301  | 0  |                                     xmlRngPErr(ctxt, cur,  | 
7302  | 0  |                                                XML_RNGP_PREFIX_UNDEFINED,  | 
7303  | 0  |                                                "xmlRelaxNGParse: no namespace for prefix %s\n",  | 
7304  | 0  |                                                prefix, NULL);  | 
7305  | 0  |                                 } else { | 
7306  | 0  |                                     xmlSetProp(cur, BAD_CAST "ns",  | 
7307  | 0  |                                                ns->href);  | 
7308  | 0  |                                     xmlNodeSetContent(cur, local);  | 
7309  | 0  |                                 }  | 
7310  | 0  |                                 xmlFree(local);  | 
7311  | 0  |                                 xmlFree(prefix);  | 
7312  | 0  |                             }  | 
7313  | 0  |                             xmlFree(name);  | 
7314  | 0  |                         }  | 
7315  | 0  |                     }  | 
7316  |  |                     /*  | 
7317  |  |                      * 4.16  | 
7318  |  |                      */  | 
7319  | 0  |                     if (xmlStrEqual(cur->name, BAD_CAST "nsName")) { | 
7320  | 0  |                         if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) { | 
7321  | 0  |                             xmlRngPErr(ctxt, cur,  | 
7322  | 0  |                                        XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME,  | 
7323  | 0  |                                        "Found nsName/except//nsName forbidden construct\n",  | 
7324  | 0  |                                        NULL, NULL);  | 
7325  | 0  |                         }  | 
7326  | 0  |                     }  | 
7327  | 0  |                 } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) &&  | 
7328  | 0  |                            (cur != root)) { | 
7329  | 0  |                     int oldflags = ctxt->flags;  | 
7330  |  |  | 
7331  |  |                     /*  | 
7332  |  |                      * 4.16  | 
7333  |  |                      */  | 
7334  | 0  |                     if ((cur->parent != NULL) &&  | 
7335  | 0  |                         (xmlStrEqual  | 
7336  | 0  |                          (cur->parent->name, BAD_CAST "anyName"))) { | 
7337  | 0  |                         ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT;  | 
7338  | 0  |                         xmlRelaxNGCleanupTree(ctxt, cur);  | 
7339  | 0  |                         ctxt->flags = oldflags;  | 
7340  | 0  |                         goto skip_children;  | 
7341  | 0  |                     } else if ((cur->parent != NULL) &&  | 
7342  | 0  |                                (xmlStrEqual  | 
7343  | 0  |                                 (cur->parent->name, BAD_CAST "nsName"))) { | 
7344  | 0  |                         ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT;  | 
7345  | 0  |                         xmlRelaxNGCleanupTree(ctxt, cur);  | 
7346  | 0  |                         ctxt->flags = oldflags;  | 
7347  | 0  |                         goto skip_children;  | 
7348  | 0  |                     }  | 
7349  | 0  |                 } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) { | 
7350  |  |                     /*  | 
7351  |  |                      * 4.16  | 
7352  |  |                      */  | 
7353  | 0  |                     if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) { | 
7354  | 0  |                         xmlRngPErr(ctxt, cur,  | 
7355  | 0  |                                    XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME,  | 
7356  | 0  |                                    "Found anyName/except//anyName forbidden construct\n",  | 
7357  | 0  |                                    NULL, NULL);  | 
7358  | 0  |                     } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) { | 
7359  | 0  |                         xmlRngPErr(ctxt, cur,  | 
7360  | 0  |                                    XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME,  | 
7361  | 0  |                                    "Found nsName/except//anyName forbidden construct\n",  | 
7362  | 0  |                                    NULL, NULL);  | 
7363  | 0  |                     }  | 
7364  | 0  |                 }  | 
7365  |  |                 /*  | 
7366  |  |                  * This is not an else since "include" is transformed  | 
7367  |  |                  * into a div  | 
7368  |  |                  */  | 
7369  | 0  |                 if (xmlStrEqual(cur->name, BAD_CAST "div")) { | 
7370  | 0  |                     xmlChar *ns;  | 
7371  | 0  |                     xmlNodePtr child, ins, tmp;  | 
7372  |  |  | 
7373  |  |                     /*  | 
7374  |  |                      * implements rule 4.11  | 
7375  |  |                      */  | 
7376  |  | 
  | 
7377  | 0  |                     ns = xmlGetProp(cur, BAD_CAST "ns");  | 
7378  |  | 
  | 
7379  | 0  |                     child = cur->children;  | 
7380  | 0  |                     ins = cur;  | 
7381  | 0  |                     while (child != NULL) { | 
7382  | 0  |                         if (ns != NULL) { | 
7383  | 0  |                             if (!xmlHasProp(child, BAD_CAST "ns")) { | 
7384  | 0  |                                 xmlSetProp(child, BAD_CAST "ns", ns);  | 
7385  | 0  |                             }  | 
7386  | 0  |                         }  | 
7387  | 0  |                         tmp = child->next;  | 
7388  | 0  |                         xmlUnlinkNode(child);  | 
7389  | 0  |                         ins = xmlAddNextSibling(ins, child);  | 
7390  | 0  |                         child = tmp;  | 
7391  | 0  |                     }  | 
7392  | 0  |                     if (ns != NULL)  | 
7393  | 0  |                         xmlFree(ns);  | 
7394  |  |         /*  | 
7395  |  |          * Since we are about to delete cur, if its nsDef is non-NULL we  | 
7396  |  |          * need to preserve it (it contains the ns definitions for the  | 
7397  |  |          * children we just moved).  We'll just stick it on to the end  | 
7398  |  |          * of cur->parent's list, since it's never going to be re-serialized  | 
7399  |  |          * (bug 143738).  | 
7400  |  |          */  | 
7401  | 0  |         if ((cur->nsDef != NULL) && (cur->parent != NULL)) { | 
7402  | 0  |       xmlNsPtr parDef = (xmlNsPtr)&cur->parent->nsDef;  | 
7403  | 0  |       while (parDef->next != NULL)  | 
7404  | 0  |           parDef = parDef->next;  | 
7405  | 0  |       parDef->next = cur->nsDef;  | 
7406  | 0  |       cur->nsDef = NULL;  | 
7407  | 0  |         }  | 
7408  | 0  |                     delete = cur;  | 
7409  | 0  |                     goto skip_children;  | 
7410  | 0  |                 }  | 
7411  | 0  |             }  | 
7412  | 0  |         }  | 
7413  |  |         /*  | 
7414  |  |          * Simplification 4.2 whitespaces  | 
7415  |  |          */  | 
7416  | 0  |         else if ((cur->type == XML_TEXT_NODE) ||  | 
7417  | 0  |                  (cur->type == XML_CDATA_SECTION_NODE)) { | 
7418  | 0  |             if (IS_BLANK_NODE(cur)) { | 
7419  | 0  |                 if ((cur->parent != NULL) &&  | 
7420  | 0  |         (cur->parent->type == XML_ELEMENT_NODE)) { | 
7421  | 0  |                     if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value"))  | 
7422  | 0  |                         &&  | 
7423  | 0  |                         (!xmlStrEqual  | 
7424  | 0  |                          (cur->parent->name, BAD_CAST "param")))  | 
7425  | 0  |                         delete = cur;  | 
7426  | 0  |                 } else { | 
7427  | 0  |                     delete = cur;  | 
7428  | 0  |                     goto skip_children;  | 
7429  | 0  |                 }  | 
7430  | 0  |             }  | 
7431  | 0  |         } else { | 
7432  | 0  |             delete = cur;  | 
7433  | 0  |             goto skip_children;  | 
7434  | 0  |         }  | 
7435  |  |  | 
7436  |  |         /*  | 
7437  |  |          * Skip to next node  | 
7438  |  |          */  | 
7439  | 0  |         if (cur->children != NULL) { | 
7440  | 0  |             if ((cur->children->type != XML_ENTITY_DECL) &&  | 
7441  | 0  |                 (cur->children->type != XML_ENTITY_REF_NODE) &&  | 
7442  | 0  |                 (cur->children->type != XML_ENTITY_NODE)) { | 
7443  | 0  |                 cur = cur->children;  | 
7444  | 0  |                 continue;  | 
7445  | 0  |             }  | 
7446  | 0  |         }  | 
7447  | 0  |       skip_children:  | 
7448  | 0  |         if (cur->next != NULL) { | 
7449  | 0  |             cur = cur->next;  | 
7450  | 0  |             continue;  | 
7451  | 0  |         }  | 
7452  |  |  | 
7453  | 0  |         do { | 
7454  | 0  |             cur = cur->parent;  | 
7455  | 0  |             if (cur == NULL)  | 
7456  | 0  |                 break;  | 
7457  | 0  |             if (cur == root) { | 
7458  | 0  |                 cur = NULL;  | 
7459  | 0  |                 break;  | 
7460  | 0  |             }  | 
7461  | 0  |             if (cur->next != NULL) { | 
7462  | 0  |                 cur = cur->next;  | 
7463  | 0  |                 break;  | 
7464  | 0  |             }  | 
7465  | 0  |         } while (cur != NULL);  | 
7466  | 0  |     }  | 
7467  | 0  |     if (delete != NULL) { | 
7468  | 0  |         xmlUnlinkNode(delete);  | 
7469  | 0  |         xmlFreeNode(delete);  | 
7470  | 0  |         delete = NULL;  | 
7471  | 0  |     }  | 
7472  | 0  | }  | 
7473  |  |  | 
7474  |  | /**  | 
7475  |  |  * xmlRelaxNGCleanupDoc:  | 
7476  |  |  * @ctxt:  a Relax-NG parser context  | 
7477  |  |  * @doc:  an xmldocPtr document pointer  | 
7478  |  |  *  | 
7479  |  |  * Cleanup the document from unwanted nodes for parsing, resolve  | 
7480  |  |  * Include and externalRef lookups.  | 
7481  |  |  *  | 
7482  |  |  * Returns the cleaned up document or NULL in case of error  | 
7483  |  |  */  | 
7484  |  | static xmlDocPtr  | 
7485  |  | xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc)  | 
7486  | 0  | { | 
7487  | 0  |     xmlNodePtr root;  | 
7488  |  |  | 
7489  |  |     /*  | 
7490  |  |      * Extract the root  | 
7491  |  |      */  | 
7492  | 0  |     root = xmlDocGetRootElement(doc);  | 
7493  | 0  |     if (root == NULL) { | 
7494  | 0  |         xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",  | 
7495  | 0  |                    ctxt->URL, NULL);  | 
7496  | 0  |         return (NULL);  | 
7497  | 0  |     }  | 
7498  | 0  |     xmlRelaxNGCleanupTree(ctxt, root);  | 
7499  | 0  |     return (doc);  | 
7500  | 0  | }  | 
7501  |  |  | 
7502  |  | /**  | 
7503  |  |  * xmlRelaxNGParse:  | 
7504  |  |  * @ctxt:  a Relax-NG parser context  | 
7505  |  |  *  | 
7506  |  |  * parse a schema definition resource and build an internal  | 
7507  |  |  * XML Schema structure which can be used to validate instances.  | 
7508  |  |  *  | 
7509  |  |  * Returns the internal XML RelaxNG structure built from the resource or  | 
7510  |  |  *         NULL in case of error  | 
7511  |  |  */  | 
7512  |  | xmlRelaxNGPtr  | 
7513  |  | xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)  | 
7514  | 0  | { | 
7515  | 0  |     xmlRelaxNGPtr ret = NULL;  | 
7516  | 0  |     xmlDocPtr doc;  | 
7517  | 0  |     xmlNodePtr root;  | 
7518  |  | 
  | 
7519  | 0  |     xmlRelaxNGInitTypes();  | 
7520  |  | 
  | 
7521  | 0  |     if (ctxt == NULL)  | 
7522  | 0  |         return (NULL);  | 
7523  |  |  | 
7524  |  |     /*  | 
7525  |  |      * First step is to parse the input document into an DOM/Infoset  | 
7526  |  |      */  | 
7527  | 0  |     if (ctxt->URL != NULL) { | 
7528  | 0  |         doc = xmlReadFile((const char *) ctxt->URL,NULL,0);  | 
7529  | 0  |         if (doc == NULL) { | 
7530  | 0  |             xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,  | 
7531  | 0  |                        "xmlRelaxNGParse: could not load %s\n", ctxt->URL,  | 
7532  | 0  |                        NULL);  | 
7533  | 0  |             return (NULL);  | 
7534  | 0  |         }  | 
7535  | 0  |     } else if (ctxt->buffer != NULL) { | 
7536  | 0  |         doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0);  | 
7537  | 0  |         if (doc == NULL) { | 
7538  | 0  |             xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,  | 
7539  | 0  |                        "xmlRelaxNGParse: could not parse schemas\n", NULL,  | 
7540  | 0  |                        NULL);  | 
7541  | 0  |             return (NULL);  | 
7542  | 0  |         }  | 
7543  | 0  |         doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");  | 
7544  | 0  |         ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");  | 
7545  | 0  |     } else if (ctxt->document != NULL) { | 
7546  | 0  |         doc = ctxt->document;  | 
7547  | 0  |     } else { | 
7548  | 0  |         xmlRngPErr(ctxt, NULL, XML_RNGP_EMPTY,  | 
7549  | 0  |                    "xmlRelaxNGParse: nothing to parse\n", NULL, NULL);  | 
7550  | 0  |         return (NULL);  | 
7551  | 0  |     }  | 
7552  | 0  |     ctxt->document = doc;  | 
7553  |  |  | 
7554  |  |     /*  | 
7555  |  |      * Some preprocessing of the document content  | 
7556  |  |      */  | 
7557  | 0  |     doc = xmlRelaxNGCleanupDoc(ctxt, doc);  | 
7558  | 0  |     if (doc == NULL) { | 
7559  | 0  |         xmlFreeDoc(ctxt->document);  | 
7560  | 0  |         ctxt->document = NULL;  | 
7561  | 0  |         return (NULL);  | 
7562  | 0  |     }  | 
7563  |  |  | 
7564  |  |     /*  | 
7565  |  |      * Then do the parsing for good  | 
7566  |  |      */  | 
7567  | 0  |     root = xmlDocGetRootElement(doc);  | 
7568  | 0  |     if (root == NULL) { | 
7569  | 0  |         xmlRngPErr(ctxt, (xmlNodePtr) doc,  | 
7570  | 0  |              XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",  | 
7571  | 0  |                    (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL);  | 
7572  |  | 
  | 
7573  | 0  |         xmlFreeDoc(ctxt->document);  | 
7574  | 0  |         ctxt->document = NULL;  | 
7575  | 0  |         return (NULL);  | 
7576  | 0  |     }  | 
7577  | 0  |     ret = xmlRelaxNGParseDocument(ctxt, root);  | 
7578  | 0  |     if (ret == NULL) { | 
7579  | 0  |         xmlFreeDoc(ctxt->document);  | 
7580  | 0  |         ctxt->document = NULL;  | 
7581  | 0  |         return (NULL);  | 
7582  | 0  |     }  | 
7583  |  |  | 
7584  |  |     /*  | 
7585  |  |      * Check the ref/defines links  | 
7586  |  |      */  | 
7587  |  |     /*  | 
7588  |  |      * try to preprocess interleaves  | 
7589  |  |      */  | 
7590  | 0  |     if (ctxt->interleaves != NULL) { | 
7591  | 0  |         xmlHashScan(ctxt->interleaves, xmlRelaxNGComputeInterleaves, ctxt);  | 
7592  | 0  |     }  | 
7593  |  |  | 
7594  |  |     /*  | 
7595  |  |      * if there was a parsing error return NULL  | 
7596  |  |      */  | 
7597  | 0  |     if (ctxt->nbErrors > 0) { | 
7598  | 0  |         xmlRelaxNGFree(ret);  | 
7599  | 0  |         ctxt->document = NULL;  | 
7600  | 0  |         xmlFreeDoc(doc);  | 
7601  | 0  |         return (NULL);  | 
7602  | 0  |     }  | 
7603  |  |  | 
7604  |  |     /*  | 
7605  |  |      * try to compile (parts of) the schemas  | 
7606  |  |      */  | 
7607  | 0  |     if ((ret->topgrammar != NULL) && (ret->topgrammar->start != NULL)) { | 
7608  | 0  |         if (ret->topgrammar->start->type != XML_RELAXNG_START) { | 
7609  | 0  |             xmlRelaxNGDefinePtr def;  | 
7610  |  | 
  | 
7611  | 0  |             def = xmlRelaxNGNewDefine(ctxt, NULL);  | 
7612  | 0  |             if (def != NULL) { | 
7613  | 0  |                 def->type = XML_RELAXNG_START;  | 
7614  | 0  |                 def->content = ret->topgrammar->start;  | 
7615  | 0  |                 ret->topgrammar->start = def;  | 
7616  | 0  |             }  | 
7617  | 0  |         }  | 
7618  | 0  |         xmlRelaxNGTryCompile(ctxt, ret->topgrammar->start);  | 
7619  | 0  |     }  | 
7620  |  |  | 
7621  |  |     /*  | 
7622  |  |      * Transfer the pointer for cleanup at the schema level.  | 
7623  |  |      */  | 
7624  | 0  |     ret->doc = doc;  | 
7625  | 0  |     ctxt->document = NULL;  | 
7626  | 0  |     ret->documents = ctxt->documents;  | 
7627  | 0  |     ctxt->documents = NULL;  | 
7628  |  | 
  | 
7629  | 0  |     ret->includes = ctxt->includes;  | 
7630  | 0  |     ctxt->includes = NULL;  | 
7631  | 0  |     ret->defNr = ctxt->defNr;  | 
7632  | 0  |     ret->defTab = ctxt->defTab;  | 
7633  | 0  |     ctxt->defTab = NULL;  | 
7634  | 0  |     if (ctxt->idref == 1)  | 
7635  | 0  |         ret->idref = 1;  | 
7636  |  | 
  | 
7637  | 0  |     return (ret);  | 
7638  | 0  | }  | 
7639  |  |  | 
7640  |  | /**  | 
7641  |  |  * xmlRelaxNGSetParserErrors:  | 
7642  |  |  * @ctxt:  a Relax-NG validation context  | 
7643  |  |  * @err:  the error callback  | 
7644  |  |  * @warn:  the warning callback  | 
7645  |  |  * @ctx:  contextual data for the callbacks  | 
7646  |  |  *  | 
7647  |  |  * Set the callback functions used to handle errors for a validation context  | 
7648  |  |  */  | 
7649  |  | void  | 
7650  |  | xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,  | 
7651  |  |                           xmlRelaxNGValidityErrorFunc err,  | 
7652  |  |                           xmlRelaxNGValidityWarningFunc warn, void *ctx)  | 
7653  | 0  | { | 
7654  | 0  |     if (ctxt == NULL)  | 
7655  | 0  |         return;  | 
7656  | 0  |     ctxt->error = err;  | 
7657  | 0  |     ctxt->warning = warn;  | 
7658  | 0  |     ctxt->serror = NULL;  | 
7659  | 0  |     ctxt->userData = ctx;  | 
7660  | 0  | }  | 
7661  |  |  | 
7662  |  | /**  | 
7663  |  |  * xmlRelaxNGGetParserErrors:  | 
7664  |  |  * @ctxt:  a Relax-NG validation context  | 
7665  |  |  * @err:  the error callback result  | 
7666  |  |  * @warn:  the warning callback result  | 
7667  |  |  * @ctx:  contextual data for the callbacks result  | 
7668  |  |  *  | 
7669  |  |  * Get the callback information used to handle errors for a validation context  | 
7670  |  |  *  | 
7671  |  |  * Returns -1 in case of failure, 0 otherwise.  | 
7672  |  |  */  | 
7673  |  | int  | 
7674  |  | xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,  | 
7675  |  |                           xmlRelaxNGValidityErrorFunc * err,  | 
7676  |  |                           xmlRelaxNGValidityWarningFunc * warn, void **ctx)  | 
7677  | 0  | { | 
7678  | 0  |     if (ctxt == NULL)  | 
7679  | 0  |         return (-1);  | 
7680  | 0  |     if (err != NULL)  | 
7681  | 0  |         *err = ctxt->error;  | 
7682  | 0  |     if (warn != NULL)  | 
7683  | 0  |         *warn = ctxt->warning;  | 
7684  | 0  |     if (ctx != NULL)  | 
7685  | 0  |         *ctx = ctxt->userData;  | 
7686  | 0  |     return (0);  | 
7687  | 0  | }  | 
7688  |  |  | 
7689  |  | /**  | 
7690  |  |  * xmlRelaxNGSetParserStructuredErrors:  | 
7691  |  |  * @ctxt:  a Relax-NG parser context  | 
7692  |  |  * @serror:  the error callback  | 
7693  |  |  * @ctx:  contextual data for the callbacks  | 
7694  |  |  *  | 
7695  |  |  * Set the callback functions used to handle errors for a parsing context  | 
7696  |  |  */  | 
7697  |  | void  | 
7698  |  | xmlRelaxNGSetParserStructuredErrors(xmlRelaxNGParserCtxtPtr ctxt,  | 
7699  |  |             xmlStructuredErrorFunc serror,  | 
7700  |  |             void *ctx)  | 
7701  | 0  | { | 
7702  | 0  |     if (ctxt == NULL)  | 
7703  | 0  |         return;  | 
7704  | 0  |     ctxt->serror = serror;  | 
7705  | 0  |     ctxt->error = NULL;  | 
7706  | 0  |     ctxt->warning = NULL;  | 
7707  | 0  |     ctxt->userData = ctx;  | 
7708  | 0  | }  | 
7709  |  |  | 
7710  |  | #ifdef LIBXML_OUTPUT_ENABLED  | 
7711  |  |  | 
7712  |  | /************************************************************************  | 
7713  |  |  *                  *  | 
7714  |  |  *      Dump back a compiled form     *  | 
7715  |  |  *                  *  | 
7716  |  |  ************************************************************************/  | 
7717  |  | static void xmlRelaxNGDumpDefine(FILE * output,  | 
7718  |  |                                  xmlRelaxNGDefinePtr define);  | 
7719  |  |  | 
7720  |  | /**  | 
7721  |  |  * xmlRelaxNGDumpDefines:  | 
7722  |  |  * @output:  the file output  | 
7723  |  |  * @defines:  a list of define structures  | 
7724  |  |  *  | 
7725  |  |  * Dump a RelaxNG structure back  | 
7726  |  |  */  | 
7727  |  | static void  | 
7728  |  | xmlRelaxNGDumpDefines(FILE * output, xmlRelaxNGDefinePtr defines)  | 
7729  | 0  | { | 
7730  | 0  |     while (defines != NULL) { | 
7731  | 0  |         xmlRelaxNGDumpDefine(output, defines);  | 
7732  | 0  |         defines = defines->next;  | 
7733  | 0  |     }  | 
7734  | 0  | }  | 
7735  |  |  | 
7736  |  | /**  | 
7737  |  |  * xmlRelaxNGDumpDefine:  | 
7738  |  |  * @output:  the file output  | 
7739  |  |  * @define:  a define structure  | 
7740  |  |  *  | 
7741  |  |  * Dump a RelaxNG structure back  | 
7742  |  |  */  | 
7743  |  | static void  | 
7744  |  | xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define)  | 
7745  | 0  | { | 
7746  | 0  |     if (define == NULL)  | 
7747  | 0  |         return;  | 
7748  | 0  |     switch (define->type) { | 
7749  | 0  |         case XML_RELAXNG_EMPTY:  | 
7750  | 0  |             fprintf(output, "<empty/>\n");  | 
7751  | 0  |             break;  | 
7752  | 0  |         case XML_RELAXNG_NOT_ALLOWED:  | 
7753  | 0  |             fprintf(output, "<notAllowed/>\n");  | 
7754  | 0  |             break;  | 
7755  | 0  |         case XML_RELAXNG_TEXT:  | 
7756  | 0  |             fprintf(output, "<text/>\n");  | 
7757  | 0  |             break;  | 
7758  | 0  |         case XML_RELAXNG_ELEMENT:  | 
7759  | 0  |             fprintf(output, "<element>\n");  | 
7760  | 0  |             if (define->name != NULL) { | 
7761  | 0  |                 fprintf(output, "<name");  | 
7762  | 0  |                 if (define->ns != NULL)  | 
7763  | 0  |                     fprintf(output, " ns=\"%s\"", define->ns);  | 
7764  | 0  |                 fprintf(output, ">%s</name>\n", define->name);  | 
7765  | 0  |             }  | 
7766  | 0  |             xmlRelaxNGDumpDefines(output, define->attrs);  | 
7767  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7768  | 0  |             fprintf(output, "</element>\n");  | 
7769  | 0  |             break;  | 
7770  | 0  |         case XML_RELAXNG_LIST:  | 
7771  | 0  |             fprintf(output, "<list>\n");  | 
7772  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7773  | 0  |             fprintf(output, "</list>\n");  | 
7774  | 0  |             break;  | 
7775  | 0  |         case XML_RELAXNG_ONEORMORE:  | 
7776  | 0  |             fprintf(output, "<oneOrMore>\n");  | 
7777  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7778  | 0  |             fprintf(output, "</oneOrMore>\n");  | 
7779  | 0  |             break;  | 
7780  | 0  |         case XML_RELAXNG_ZEROORMORE:  | 
7781  | 0  |             fprintf(output, "<zeroOrMore>\n");  | 
7782  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7783  | 0  |             fprintf(output, "</zeroOrMore>\n");  | 
7784  | 0  |             break;  | 
7785  | 0  |         case XML_RELAXNG_CHOICE:  | 
7786  | 0  |             fprintf(output, "<choice>\n");  | 
7787  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7788  | 0  |             fprintf(output, "</choice>\n");  | 
7789  | 0  |             break;  | 
7790  | 0  |         case XML_RELAXNG_GROUP:  | 
7791  | 0  |             fprintf(output, "<group>\n");  | 
7792  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7793  | 0  |             fprintf(output, "</group>\n");  | 
7794  | 0  |             break;  | 
7795  | 0  |         case XML_RELAXNG_INTERLEAVE:  | 
7796  | 0  |             fprintf(output, "<interleave>\n");  | 
7797  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7798  | 0  |             fprintf(output, "</interleave>\n");  | 
7799  | 0  |             break;  | 
7800  | 0  |         case XML_RELAXNG_OPTIONAL:  | 
7801  | 0  |             fprintf(output, "<optional>\n");  | 
7802  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7803  | 0  |             fprintf(output, "</optional>\n");  | 
7804  | 0  |             break;  | 
7805  | 0  |         case XML_RELAXNG_ATTRIBUTE:  | 
7806  | 0  |             fprintf(output, "<attribute>\n");  | 
7807  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7808  | 0  |             fprintf(output, "</attribute>\n");  | 
7809  | 0  |             break;  | 
7810  | 0  |         case XML_RELAXNG_DEF:  | 
7811  | 0  |             fprintf(output, "<define");  | 
7812  | 0  |             if (define->name != NULL)  | 
7813  | 0  |                 fprintf(output, " name=\"%s\"", define->name);  | 
7814  | 0  |             fprintf(output, ">\n");  | 
7815  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7816  | 0  |             fprintf(output, "</define>\n");  | 
7817  | 0  |             break;  | 
7818  | 0  |         case XML_RELAXNG_REF:  | 
7819  | 0  |             fprintf(output, "<ref");  | 
7820  | 0  |             if (define->name != NULL)  | 
7821  | 0  |                 fprintf(output, " name=\"%s\"", define->name);  | 
7822  | 0  |             fprintf(output, ">\n");  | 
7823  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7824  | 0  |             fprintf(output, "</ref>\n");  | 
7825  | 0  |             break;  | 
7826  | 0  |         case XML_RELAXNG_PARENTREF:  | 
7827  | 0  |             fprintf(output, "<parentRef");  | 
7828  | 0  |             if (define->name != NULL)  | 
7829  | 0  |                 fprintf(output, " name=\"%s\"", define->name);  | 
7830  | 0  |             fprintf(output, ">\n");  | 
7831  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7832  | 0  |             fprintf(output, "</parentRef>\n");  | 
7833  | 0  |             break;  | 
7834  | 0  |         case XML_RELAXNG_EXTERNALREF:  | 
7835  | 0  |             fprintf(output, "<externalRef>");  | 
7836  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7837  | 0  |             fprintf(output, "</externalRef>\n");  | 
7838  | 0  |             break;  | 
7839  | 0  |         case XML_RELAXNG_DATATYPE:  | 
7840  | 0  |         case XML_RELAXNG_VALUE:  | 
7841  | 0  |             TODO break;  | 
7842  | 0  |         case XML_RELAXNG_START:  | 
7843  | 0  |         case XML_RELAXNG_EXCEPT:  | 
7844  | 0  |         case XML_RELAXNG_PARAM:  | 
7845  | 0  |             TODO break;  | 
7846  | 0  |         case XML_RELAXNG_NOOP:  | 
7847  | 0  |             xmlRelaxNGDumpDefines(output, define->content);  | 
7848  | 0  |             break;  | 
7849  | 0  |     }  | 
7850  | 0  | }  | 
7851  |  |  | 
7852  |  | /**  | 
7853  |  |  * xmlRelaxNGDumpGrammar:  | 
7854  |  |  * @output:  the file output  | 
7855  |  |  * @grammar:  a grammar structure  | 
7856  |  |  * @top:  is this a top grammar  | 
7857  |  |  *  | 
7858  |  |  * Dump a RelaxNG structure back  | 
7859  |  |  */  | 
7860  |  | static void  | 
7861  |  | xmlRelaxNGDumpGrammar(FILE * output, xmlRelaxNGGrammarPtr grammar, int top)  | 
7862  | 0  | { | 
7863  | 0  |     if (grammar == NULL)  | 
7864  | 0  |         return;  | 
7865  |  |  | 
7866  | 0  |     fprintf(output, "<grammar");  | 
7867  | 0  |     if (top)  | 
7868  | 0  |         fprintf(output, " xmlns=\"http://relaxng.org/ns/structure/1.0\"");  | 
7869  | 0  |     switch (grammar->combine) { | 
7870  | 0  |         case XML_RELAXNG_COMBINE_UNDEFINED:  | 
7871  | 0  |             break;  | 
7872  | 0  |         case XML_RELAXNG_COMBINE_CHOICE:  | 
7873  | 0  |             fprintf(output, " combine=\"choice\"");  | 
7874  | 0  |             break;  | 
7875  | 0  |         case XML_RELAXNG_COMBINE_INTERLEAVE:  | 
7876  | 0  |             fprintf(output, " combine=\"interleave\"");  | 
7877  | 0  |             break;  | 
7878  | 0  |         default:  | 
7879  | 0  |             fprintf(output, " <!-- invalid combine value -->");  | 
7880  | 0  |     }  | 
7881  | 0  |     fprintf(output, ">\n");  | 
7882  | 0  |     if (grammar->start == NULL) { | 
7883  | 0  |         fprintf(output, " <!-- grammar had no start -->");  | 
7884  | 0  |     } else { | 
7885  | 0  |         fprintf(output, "<start>\n");  | 
7886  | 0  |         xmlRelaxNGDumpDefine(output, grammar->start);  | 
7887  | 0  |         fprintf(output, "</start>\n");  | 
7888  | 0  |     }  | 
7889  |  |     /* TODO ? Dump the defines ? */  | 
7890  | 0  |     fprintf(output, "</grammar>\n");  | 
7891  | 0  | }  | 
7892  |  |  | 
7893  |  | /**  | 
7894  |  |  * xmlRelaxNGDump:  | 
7895  |  |  * @output:  the file output  | 
7896  |  |  * @schema:  a schema structure  | 
7897  |  |  *  | 
7898  |  |  * Dump a RelaxNG structure back  | 
7899  |  |  */  | 
7900  |  | void  | 
7901  |  | xmlRelaxNGDump(FILE * output, xmlRelaxNGPtr schema)  | 
7902  | 0  | { | 
7903  | 0  |     if (output == NULL)  | 
7904  | 0  |         return;  | 
7905  | 0  |     if (schema == NULL) { | 
7906  | 0  |         fprintf(output, "RelaxNG empty or failed to compile\n");  | 
7907  | 0  |         return;  | 
7908  | 0  |     }  | 
7909  | 0  |     fprintf(output, "RelaxNG: ");  | 
7910  | 0  |     if (schema->doc == NULL) { | 
7911  | 0  |         fprintf(output, "no document\n");  | 
7912  | 0  |     } else if (schema->doc->URL != NULL) { | 
7913  | 0  |         fprintf(output, "%s\n", schema->doc->URL);  | 
7914  | 0  |     } else { | 
7915  | 0  |         fprintf(output, "\n");  | 
7916  | 0  |     }  | 
7917  | 0  |     if (schema->topgrammar == NULL) { | 
7918  | 0  |         fprintf(output, "RelaxNG has no top grammar\n");  | 
7919  | 0  |         return;  | 
7920  | 0  |     }  | 
7921  | 0  |     xmlRelaxNGDumpGrammar(output, schema->topgrammar, 1);  | 
7922  | 0  | }  | 
7923  |  |  | 
7924  |  | /**  | 
7925  |  |  * xmlRelaxNGDumpTree:  | 
7926  |  |  * @output:  the file output  | 
7927  |  |  * @schema:  a schema structure  | 
7928  |  |  *  | 
7929  |  |  * Dump the transformed RelaxNG tree.  | 
7930  |  |  */  | 
7931  |  | void  | 
7932  |  | xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema)  | 
7933  | 0  | { | 
7934  | 0  |     if (output == NULL)  | 
7935  | 0  |         return;  | 
7936  | 0  |     if (schema == NULL) { | 
7937  | 0  |         fprintf(output, "RelaxNG empty or failed to compile\n");  | 
7938  | 0  |         return;  | 
7939  | 0  |     }  | 
7940  | 0  |     if (schema->doc == NULL) { | 
7941  | 0  |         fprintf(output, "no document\n");  | 
7942  | 0  |     } else { | 
7943  | 0  |         xmlDocDump(output, schema->doc);  | 
7944  | 0  |     }  | 
7945  | 0  | }  | 
7946  |  | #endif /* LIBXML_OUTPUT_ENABLED */  | 
7947  |  |  | 
7948  |  | /************************************************************************  | 
7949  |  |  *                  *  | 
7950  |  |  *    Validation of compiled content        *  | 
7951  |  |  *                  *  | 
7952  |  |  ************************************************************************/  | 
7953  |  | static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,  | 
7954  |  |                                         xmlRelaxNGDefinePtr define);  | 
7955  |  |  | 
7956  |  | /**  | 
7957  |  |  * xmlRelaxNGValidateCompiledCallback:  | 
7958  |  |  * @exec:  the regular expression instance  | 
7959  |  |  * @token:  the token which matched  | 
7960  |  |  * @transdata:  callback data, the define for the subelement if available  | 
7961  |  |  @ @inputdata:  callback data, the Relax NG validation context  | 
7962  |  |  *  | 
7963  |  |  * Handle the callback and if needed validate the element children.  | 
7964  |  |  */  | 
7965  |  | static void  | 
7966  |  | xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,  | 
7967  |  |                                    const xmlChar * token,  | 
7968  |  |                                    void *transdata, void *inputdata)  | 
7969  | 0  | { | 
7970  | 0  |     xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;  | 
7971  | 0  |     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;  | 
7972  | 0  |     int ret;  | 
7973  |  | 
  | 
7974  |  | #ifdef DEBUG_COMPILE  | 
7975  |  |     xmlGenericError(xmlGenericErrorContext,  | 
7976  |  |                     "Compiled callback for: '%s'\n", token);  | 
7977  |  | #endif  | 
7978  | 0  |     if (ctxt == NULL) { | 
7979  | 0  |         fprintf(stderr, "callback on %s missing context\n", token);  | 
7980  | 0  |         return;  | 
7981  | 0  |     }  | 
7982  | 0  |     if (define == NULL) { | 
7983  | 0  |         if (token[0] == '#')  | 
7984  | 0  |             return;  | 
7985  | 0  |         fprintf(stderr, "callback on %s missing define\n", token);  | 
7986  | 0  |         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))  | 
7987  | 0  |             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;  | 
7988  | 0  |         return;  | 
7989  | 0  |     }  | 
7990  | 0  |     if ((ctxt == NULL) || (define == NULL)) { | 
7991  | 0  |         fprintf(stderr, "callback on %s missing info\n", token);  | 
7992  | 0  |         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))  | 
7993  | 0  |             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;  | 
7994  | 0  |         return;  | 
7995  | 0  |     } else if (define->type != XML_RELAXNG_ELEMENT) { | 
7996  | 0  |         fprintf(stderr, "callback on %s define is not element\n", token);  | 
7997  | 0  |         if (ctxt->errNo == XML_RELAXNG_OK)  | 
7998  | 0  |             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;  | 
7999  | 0  |         return;  | 
8000  | 0  |     }  | 
8001  | 0  |     ret = xmlRelaxNGValidateDefinition(ctxt, define);  | 
8002  | 0  |     if (ret != 0)  | 
8003  | 0  |         ctxt->perr = ret;  | 
8004  | 0  | }  | 
8005  |  |  | 
8006  |  | /**  | 
8007  |  |  * xmlRelaxNGValidateCompiledContent:  | 
8008  |  |  * @ctxt:  the RelaxNG validation context  | 
8009  |  |  * @regexp:  the regular expression as compiled  | 
8010  |  |  * @content:  list of children to test against the regexp  | 
8011  |  |  *  | 
8012  |  |  * Validate the content model of an element or start using the regexp  | 
8013  |  |  *  | 
8014  |  |  * Returns 0 in case of success, -1 in case of error.  | 
8015  |  |  */  | 
8016  |  | static int  | 
8017  |  | xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt,  | 
8018  |  |                                   xmlRegexpPtr regexp, xmlNodePtr content)  | 
8019  | 0  | { | 
8020  | 0  |     xmlRegExecCtxtPtr exec;  | 
8021  | 0  |     xmlNodePtr cur;  | 
8022  | 0  |     int ret = 0;  | 
8023  | 0  |     int oldperr;  | 
8024  |  | 
  | 
8025  | 0  |     if ((ctxt == NULL) || (regexp == NULL))  | 
8026  | 0  |         return (-1);  | 
8027  | 0  |     oldperr = ctxt->perr;  | 
8028  | 0  |     exec = xmlRegNewExecCtxt(regexp,  | 
8029  | 0  |                              xmlRelaxNGValidateCompiledCallback, ctxt);  | 
8030  | 0  |     ctxt->perr = 0;  | 
8031  | 0  |     cur = content;  | 
8032  | 0  |     while (cur != NULL) { | 
8033  | 0  |         ctxt->state->seq = cur;  | 
8034  | 0  |         switch (cur->type) { | 
8035  | 0  |             case XML_TEXT_NODE:  | 
8036  | 0  |             case XML_CDATA_SECTION_NODE:  | 
8037  | 0  |                 if (xmlIsBlankNode(cur))  | 
8038  | 0  |                     break;  | 
8039  | 0  |                 ret = xmlRegExecPushString(exec, BAD_CAST "#text", ctxt);  | 
8040  | 0  |                 if (ret < 0) { | 
8041  | 0  |                     VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG,  | 
8042  | 0  |                                cur->parent->name);  | 
8043  | 0  |                 }  | 
8044  | 0  |                 break;  | 
8045  | 0  |             case XML_ELEMENT_NODE:  | 
8046  | 0  |                 if (cur->ns != NULL) { | 
8047  | 0  |                     ret = xmlRegExecPushString2(exec, cur->name,  | 
8048  | 0  |                                                 cur->ns->href, ctxt);  | 
8049  | 0  |                 } else { | 
8050  | 0  |                     ret = xmlRegExecPushString(exec, cur->name, ctxt);  | 
8051  | 0  |                 }  | 
8052  | 0  |                 if (ret < 0) { | 
8053  | 0  |                     VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, cur->name);  | 
8054  | 0  |                 }  | 
8055  | 0  |                 break;  | 
8056  | 0  |             default:  | 
8057  | 0  |                 break;  | 
8058  | 0  |         }  | 
8059  | 0  |         if (ret < 0)  | 
8060  | 0  |             break;  | 
8061  |  |         /*  | 
8062  |  |          * Switch to next element  | 
8063  |  |          */  | 
8064  | 0  |         cur = cur->next;  | 
8065  | 0  |     }  | 
8066  | 0  |     ret = xmlRegExecPushString(exec, NULL, NULL);  | 
8067  | 0  |     if (ret == 1) { | 
8068  | 0  |         ret = 0;  | 
8069  | 0  |         ctxt->state->seq = NULL;  | 
8070  | 0  |     } else if (ret == 0) { | 
8071  |  |         /*  | 
8072  |  |          * TODO: get some of the names needed to exit the current state of exec  | 
8073  |  |          */  | 
8074  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");  | 
8075  | 0  |         ret = -1;  | 
8076  | 0  |         if ((ctxt->flags & FLAGS_IGNORABLE) == 0)  | 
8077  | 0  |             xmlRelaxNGDumpValidError(ctxt);  | 
8078  | 0  |     } else { | 
8079  | 0  |         ret = -1;  | 
8080  | 0  |     }  | 
8081  | 0  |     xmlRegFreeExecCtxt(exec);  | 
8082  |  |     /*  | 
8083  |  |      * There might be content model errors outside of the pure  | 
8084  |  |      * regexp validation, e.g. for attribute values.  | 
8085  |  |      */  | 
8086  | 0  |     if ((ret == 0) && (ctxt->perr != 0)) { | 
8087  | 0  |         ret = ctxt->perr;  | 
8088  | 0  |     }  | 
8089  | 0  |     ctxt->perr = oldperr;  | 
8090  | 0  |     return (ret);  | 
8091  | 0  | }  | 
8092  |  |  | 
8093  |  | /************************************************************************  | 
8094  |  |  *                  *  | 
8095  |  |  *    Progressive validation of when possible     *  | 
8096  |  |  *                  *  | 
8097  |  |  ************************************************************************/  | 
8098  |  | static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,  | 
8099  |  |                                            xmlRelaxNGDefinePtr defines);  | 
8100  |  | static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt,  | 
8101  |  |                                         int dolog);  | 
8102  |  | static void xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt);  | 
8103  |  |  | 
8104  |  | /**  | 
8105  |  |  * xmlRelaxNGElemPush:  | 
8106  |  |  * @ctxt:  the validation context  | 
8107  |  |  * @exec:  the regexp runtime for the new content model  | 
8108  |  |  *  | 
8109  |  |  * Push a new regexp for the current node content model on the stack  | 
8110  |  |  *  | 
8111  |  |  * Returns 0 in case of success and -1 in case of error.  | 
8112  |  |  */  | 
8113  |  | static int  | 
8114  |  | xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec)  | 
8115  | 0  | { | 
8116  | 0  |     if (ctxt->elemTab == NULL) { | 
8117  | 0  |         ctxt->elemMax = 10;  | 
8118  | 0  |         ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlMalloc(ctxt->elemMax *  | 
8119  | 0  |                                                         sizeof  | 
8120  | 0  |                                                         (xmlRegExecCtxtPtr));  | 
8121  | 0  |         if (ctxt->elemTab == NULL) { | 
8122  | 0  |             xmlRngVErrMemory(ctxt, "validating\n");  | 
8123  | 0  |             return (-1);  | 
8124  | 0  |         }  | 
8125  | 0  |     }  | 
8126  | 0  |     if (ctxt->elemNr >= ctxt->elemMax) { | 
8127  | 0  |         ctxt->elemMax *= 2;  | 
8128  | 0  |         ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlRealloc(ctxt->elemTab,  | 
8129  | 0  |                                                          ctxt->elemMax *  | 
8130  | 0  |                                                          sizeof  | 
8131  | 0  |                                                          (xmlRegExecCtxtPtr));  | 
8132  | 0  |         if (ctxt->elemTab == NULL) { | 
8133  | 0  |             xmlRngVErrMemory(ctxt, "validating\n");  | 
8134  | 0  |             return (-1);  | 
8135  | 0  |         }  | 
8136  | 0  |     }  | 
8137  | 0  |     ctxt->elemTab[ctxt->elemNr++] = exec;  | 
8138  | 0  |     ctxt->elem = exec;  | 
8139  | 0  |     return (0);  | 
8140  | 0  | }  | 
8141  |  |  | 
8142  |  | /**  | 
8143  |  |  * xmlRelaxNGElemPop:  | 
8144  |  |  * @ctxt:  the validation context  | 
8145  |  |  *  | 
8146  |  |  * Pop the regexp of the current node content model from the stack  | 
8147  |  |  *  | 
8148  |  |  * Returns the exec or NULL if empty  | 
8149  |  |  */  | 
8150  |  | static xmlRegExecCtxtPtr  | 
8151  |  | xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt)  | 
8152  | 0  | { | 
8153  | 0  |     xmlRegExecCtxtPtr ret;  | 
8154  |  | 
  | 
8155  | 0  |     if (ctxt->elemNr <= 0)  | 
8156  | 0  |         return (NULL);  | 
8157  | 0  |     ctxt->elemNr--;  | 
8158  | 0  |     ret = ctxt->elemTab[ctxt->elemNr];  | 
8159  | 0  |     ctxt->elemTab[ctxt->elemNr] = NULL;  | 
8160  | 0  |     if (ctxt->elemNr > 0)  | 
8161  | 0  |         ctxt->elem = ctxt->elemTab[ctxt->elemNr - 1];  | 
8162  | 0  |     else  | 
8163  | 0  |         ctxt->elem = NULL;  | 
8164  | 0  |     return (ret);  | 
8165  | 0  | }  | 
8166  |  |  | 
8167  |  | /**  | 
8168  |  |  * xmlRelaxNGValidateProgressiveCallback:  | 
8169  |  |  * @exec:  the regular expression instance  | 
8170  |  |  * @token:  the token which matched  | 
8171  |  |  * @transdata:  callback data, the define for the subelement if available  | 
8172  |  |  @ @inputdata:  callback data, the Relax NG validation context  | 
8173  |  |  *  | 
8174  |  |  * Handle the callback and if needed validate the element children.  | 
8175  |  |  * some of the in/out information are passed via the context in @inputdata.  | 
8176  |  |  */  | 
8177  |  | static void  | 
8178  |  | xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec  | 
8179  |  |                                       ATTRIBUTE_UNUSED,  | 
8180  |  |                                       const xmlChar * token,  | 
8181  |  |                                       void *transdata, void *inputdata)  | 
8182  | 0  | { | 
8183  | 0  |     xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata;  | 
8184  | 0  |     xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata;  | 
8185  | 0  |     xmlRelaxNGValidStatePtr state, oldstate;  | 
8186  | 0  |     xmlNodePtr node;  | 
8187  | 0  |     int ret = 0, oldflags;  | 
8188  |  | 
  | 
8189  |  | #ifdef DEBUG_PROGRESSIVE  | 
8190  |  |     xmlGenericError(xmlGenericErrorContext,  | 
8191  |  |                     "Progressive callback for: '%s'\n", token);  | 
8192  |  | #endif  | 
8193  | 0  |     if (ctxt == NULL) { | 
8194  | 0  |         fprintf(stderr, "callback on %s missing context\n", token);  | 
8195  | 0  |         return;  | 
8196  | 0  |     }  | 
8197  | 0  |     node = ctxt->pnode;  | 
8198  | 0  |     ctxt->pstate = 1;  | 
8199  | 0  |     if (define == NULL) { | 
8200  | 0  |         if (token[0] == '#')  | 
8201  | 0  |             return;  | 
8202  | 0  |         fprintf(stderr, "callback on %s missing define\n", token);  | 
8203  | 0  |         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))  | 
8204  | 0  |             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;  | 
8205  | 0  |         ctxt->pstate = -1;  | 
8206  | 0  |         return;  | 
8207  | 0  |     }  | 
8208  | 0  |     if ((ctxt == NULL) || (define == NULL)) { | 
8209  | 0  |         fprintf(stderr, "callback on %s missing info\n", token);  | 
8210  | 0  |         if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK))  | 
8211  | 0  |             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;  | 
8212  | 0  |         ctxt->pstate = -1;  | 
8213  | 0  |         return;  | 
8214  | 0  |     } else if (define->type != XML_RELAXNG_ELEMENT) { | 
8215  | 0  |         fprintf(stderr, "callback on %s define is not element\n", token);  | 
8216  | 0  |         if (ctxt->errNo == XML_RELAXNG_OK)  | 
8217  | 0  |             ctxt->errNo = XML_RELAXNG_ERR_INTERNAL;  | 
8218  | 0  |         ctxt->pstate = -1;  | 
8219  | 0  |         return;  | 
8220  | 0  |     }  | 
8221  | 0  |     if (node->type != XML_ELEMENT_NODE) { | 
8222  | 0  |         VALID_ERR(XML_RELAXNG_ERR_NOTELEM);  | 
8223  | 0  |         if ((ctxt->flags & FLAGS_IGNORABLE) == 0)  | 
8224  | 0  |             xmlRelaxNGDumpValidError(ctxt);  | 
8225  | 0  |         ctxt->pstate = -1;  | 
8226  | 0  |         return;  | 
8227  | 0  |     }  | 
8228  | 0  |     if (define->contModel == NULL) { | 
8229  |  |         /*  | 
8230  |  |          * this node cannot be validated in a streamable fashion  | 
8231  |  |          */  | 
8232  |  | #ifdef DEBUG_PROGRESSIVE  | 
8233  |  |         xmlGenericError(xmlGenericErrorContext,  | 
8234  |  |                         "Element '%s' validation is not streamable\n",  | 
8235  |  |                         token);  | 
8236  |  | #endif  | 
8237  | 0  |         ctxt->pstate = 0;  | 
8238  | 0  |         ctxt->pdef = define;  | 
8239  | 0  |         return;  | 
8240  | 0  |     }  | 
8241  | 0  |     exec = xmlRegNewExecCtxt(define->contModel,  | 
8242  | 0  |                              xmlRelaxNGValidateProgressiveCallback, ctxt);  | 
8243  | 0  |     if (exec == NULL) { | 
8244  | 0  |         ctxt->pstate = -1;  | 
8245  | 0  |         return;  | 
8246  | 0  |     }  | 
8247  | 0  |     xmlRelaxNGElemPush(ctxt, exec);  | 
8248  |  |  | 
8249  |  |     /*  | 
8250  |  |      * Validate the attributes part of the content.  | 
8251  |  |      */  | 
8252  | 0  |     state = xmlRelaxNGNewValidState(ctxt, node);  | 
8253  | 0  |     if (state == NULL) { | 
8254  | 0  |         ctxt->pstate = -1;  | 
8255  | 0  |         return;  | 
8256  | 0  |     }  | 
8257  | 0  |     oldstate = ctxt->state;  | 
8258  | 0  |     ctxt->state = state;  | 
8259  | 0  |     if (define->attrs != NULL) { | 
8260  | 0  |         ret = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);  | 
8261  | 0  |         if (ret != 0) { | 
8262  | 0  |             ctxt->pstate = -1;  | 
8263  | 0  |             VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);  | 
8264  | 0  |         }  | 
8265  | 0  |     }  | 
8266  | 0  |     if (ctxt->state != NULL) { | 
8267  | 0  |         ctxt->state->seq = NULL;  | 
8268  | 0  |         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);  | 
8269  | 0  |         if (ret != 0) { | 
8270  | 0  |             ctxt->pstate = -1;  | 
8271  | 0  |         }  | 
8272  | 0  |         xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
8273  | 0  |     } else if (ctxt->states != NULL) { | 
8274  | 0  |         int tmp = -1, i;  | 
8275  |  | 
  | 
8276  | 0  |         oldflags = ctxt->flags;  | 
8277  |  | 
  | 
8278  | 0  |         for (i = 0; i < ctxt->states->nbState; i++) { | 
8279  | 0  |             state = ctxt->states->tabState[i];  | 
8280  | 0  |             ctxt->state = state;  | 
8281  | 0  |             ctxt->state->seq = NULL;  | 
8282  |  | 
  | 
8283  | 0  |             if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { | 
8284  | 0  |                 tmp = 0;  | 
8285  | 0  |                 break;  | 
8286  | 0  |             }  | 
8287  | 0  |         }  | 
8288  | 0  |         if (tmp != 0) { | 
8289  |  |             /*  | 
8290  |  |              * validation error, log the message for the "best" one  | 
8291  |  |              */  | 
8292  | 0  |             ctxt->flags |= FLAGS_IGNORABLE;  | 
8293  | 0  |             xmlRelaxNGLogBestError(ctxt);  | 
8294  | 0  |         }  | 
8295  | 0  |         for (i = 0; i < ctxt->states->nbState; i++) { | 
8296  | 0  |             xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[i]);  | 
8297  | 0  |         }  | 
8298  | 0  |         xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
8299  | 0  |         ctxt->states = NULL;  | 
8300  | 0  |         if ((ret == 0) && (tmp == -1))  | 
8301  | 0  |             ctxt->pstate = -1;  | 
8302  | 0  |         ctxt->flags = oldflags;  | 
8303  | 0  |     }  | 
8304  | 0  |     if (ctxt->pstate == -1) { | 
8305  | 0  |         if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { | 
8306  | 0  |             xmlRelaxNGDumpValidError(ctxt);  | 
8307  | 0  |         }  | 
8308  | 0  |     }  | 
8309  | 0  |     ctxt->state = oldstate;  | 
8310  | 0  | }  | 
8311  |  |  | 
8312  |  | /**  | 
8313  |  |  * xmlRelaxNGValidatePushElement:  | 
8314  |  |  * @ctxt:  the validation context  | 
8315  |  |  * @doc:  a document instance  | 
8316  |  |  * @elem:  an element instance  | 
8317  |  |  *  | 
8318  |  |  * Push a new element start on the RelaxNG validation stack.  | 
8319  |  |  *  | 
8320  |  |  * returns 1 if no validation problem was found or 0 if validating the  | 
8321  |  |  *         element requires a full node, and -1 in case of error.  | 
8322  |  |  */  | 
8323  |  | int  | 
8324  |  | xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt,  | 
8325  |  |                               xmlDocPtr doc ATTRIBUTE_UNUSED,  | 
8326  |  |                               xmlNodePtr elem)  | 
8327  | 0  | { | 
8328  | 0  |     int ret = 1;  | 
8329  |  | 
  | 
8330  | 0  |     if ((ctxt == NULL) || (elem == NULL))  | 
8331  | 0  |         return (-1);  | 
8332  |  |  | 
8333  |  | #ifdef DEBUG_PROGRESSIVE  | 
8334  |  |     xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name);  | 
8335  |  | #endif  | 
8336  | 0  |     if (ctxt->elem == 0) { | 
8337  | 0  |         xmlRelaxNGPtr schema;  | 
8338  | 0  |         xmlRelaxNGGrammarPtr grammar;  | 
8339  | 0  |         xmlRegExecCtxtPtr exec;  | 
8340  | 0  |         xmlRelaxNGDefinePtr define;  | 
8341  |  | 
  | 
8342  | 0  |         schema = ctxt->schema;  | 
8343  | 0  |         if (schema == NULL) { | 
8344  | 0  |             VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);  | 
8345  | 0  |             return (-1);  | 
8346  | 0  |         }  | 
8347  | 0  |         grammar = schema->topgrammar;  | 
8348  | 0  |         if ((grammar == NULL) || (grammar->start == NULL)) { | 
8349  | 0  |             VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);  | 
8350  | 0  |             return (-1);  | 
8351  | 0  |         }  | 
8352  | 0  |         define = grammar->start;  | 
8353  | 0  |         if (define->contModel == NULL) { | 
8354  | 0  |             ctxt->pdef = define;  | 
8355  | 0  |             return (0);  | 
8356  | 0  |         }  | 
8357  | 0  |         exec = xmlRegNewExecCtxt(define->contModel,  | 
8358  | 0  |                                  xmlRelaxNGValidateProgressiveCallback,  | 
8359  | 0  |                                  ctxt);  | 
8360  | 0  |         if (exec == NULL) { | 
8361  | 0  |             return (-1);  | 
8362  | 0  |         }  | 
8363  | 0  |         xmlRelaxNGElemPush(ctxt, exec);  | 
8364  | 0  |     }  | 
8365  | 0  |     ctxt->pnode = elem;  | 
8366  | 0  |     ctxt->pstate = 0;  | 
8367  | 0  |     if (elem->ns != NULL) { | 
8368  | 0  |         ret =  | 
8369  | 0  |             xmlRegExecPushString2(ctxt->elem, elem->name, elem->ns->href,  | 
8370  | 0  |                                   ctxt);  | 
8371  | 0  |     } else { | 
8372  | 0  |         ret = xmlRegExecPushString(ctxt->elem, elem->name, ctxt);  | 
8373  | 0  |     }  | 
8374  | 0  |     if (ret < 0) { | 
8375  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, elem->name);  | 
8376  | 0  |     } else { | 
8377  | 0  |         if (ctxt->pstate == 0)  | 
8378  | 0  |             ret = 0;  | 
8379  | 0  |         else if (ctxt->pstate < 0)  | 
8380  | 0  |             ret = -1;  | 
8381  | 0  |         else  | 
8382  | 0  |             ret = 1;  | 
8383  | 0  |     }  | 
8384  |  | #ifdef DEBUG_PROGRESSIVE  | 
8385  |  |     if (ret < 0)  | 
8386  |  |         xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n",  | 
8387  |  |                         elem->name);  | 
8388  |  | #endif  | 
8389  | 0  |     return (ret);  | 
8390  | 0  | }  | 
8391  |  |  | 
8392  |  | /**  | 
8393  |  |  * xmlRelaxNGValidatePushCData:  | 
8394  |  |  * @ctxt:  the RelaxNG validation context  | 
8395  |  |  * @data:  some character data read  | 
8396  |  |  * @len:  the length of the data  | 
8397  |  |  *  | 
8398  |  |  * check the CData parsed for validation in the current stack  | 
8399  |  |  *  | 
8400  |  |  * returns 1 if no validation problem was found or -1 otherwise  | 
8401  |  |  */  | 
8402  |  | int  | 
8403  |  | xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt,  | 
8404  |  |                             const xmlChar * data, int len ATTRIBUTE_UNUSED)  | 
8405  | 0  | { | 
8406  | 0  |     int ret = 1;  | 
8407  |  | 
  | 
8408  | 0  |     if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL))  | 
8409  | 0  |         return (-1);  | 
8410  |  |  | 
8411  |  | #ifdef DEBUG_PROGRESSIVE  | 
8412  |  |     xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len);  | 
8413  |  | #endif  | 
8414  |  |  | 
8415  | 0  |     while (*data != 0) { | 
8416  | 0  |         if (!IS_BLANK_CH(*data))  | 
8417  | 0  |             break;  | 
8418  | 0  |         data++;  | 
8419  | 0  |     }  | 
8420  | 0  |     if (*data == 0)  | 
8421  | 0  |         return (1);  | 
8422  |  |  | 
8423  | 0  |     ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt);  | 
8424  | 0  |     if (ret < 0) { | 
8425  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO ");  | 
8426  |  | #ifdef DEBUG_PROGRESSIVE  | 
8427  |  |         xmlGenericError(xmlGenericErrorContext, "CDATA failed\n");  | 
8428  |  | #endif  | 
8429  |  | 
  | 
8430  | 0  |         return (-1);  | 
8431  | 0  |     }  | 
8432  | 0  |     return (1);  | 
8433  | 0  | }  | 
8434  |  |  | 
8435  |  | /**  | 
8436  |  |  * xmlRelaxNGValidatePopElement:  | 
8437  |  |  * @ctxt:  the RelaxNG validation context  | 
8438  |  |  * @doc:  a document instance  | 
8439  |  |  * @elem:  an element instance  | 
8440  |  |  *  | 
8441  |  |  * Pop the element end from the RelaxNG validation stack.  | 
8442  |  |  *  | 
8443  |  |  * returns 1 if no validation problem was found or 0 otherwise  | 
8444  |  |  */  | 
8445  |  | int  | 
8446  |  | xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt,  | 
8447  |  |                              xmlDocPtr doc ATTRIBUTE_UNUSED,  | 
8448  |  |                              xmlNodePtr elem)  | 
8449  | 0  | { | 
8450  | 0  |     int ret;  | 
8451  | 0  |     xmlRegExecCtxtPtr exec;  | 
8452  |  | 
  | 
8453  | 0  |     if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL))  | 
8454  | 0  |         return (-1);  | 
8455  |  | #ifdef DEBUG_PROGRESSIVE  | 
8456  |  |     xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name);  | 
8457  |  | #endif  | 
8458  |  |     /*  | 
8459  |  |      * verify that we reached a terminal state of the content model.  | 
8460  |  |      */  | 
8461  | 0  |     exec = xmlRelaxNGElemPop(ctxt);  | 
8462  | 0  |     ret = xmlRegExecPushString(exec, NULL, NULL);  | 
8463  | 0  |     if (ret == 0) { | 
8464  |  |         /*  | 
8465  |  |          * TODO: get some of the names needed to exit the current state of exec  | 
8466  |  |          */  | 
8467  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST "");  | 
8468  | 0  |         ret = -1;  | 
8469  | 0  |     } else if (ret < 0) { | 
8470  | 0  |         ret = -1;  | 
8471  | 0  |     } else { | 
8472  | 0  |         ret = 1;  | 
8473  | 0  |     }  | 
8474  | 0  |     xmlRegFreeExecCtxt(exec);  | 
8475  |  | #ifdef DEBUG_PROGRESSIVE  | 
8476  |  |     if (ret < 0)  | 
8477  |  |         xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n",  | 
8478  |  |                         elem->name);  | 
8479  |  | #endif  | 
8480  | 0  |     return (ret);  | 
8481  | 0  | }  | 
8482  |  |  | 
8483  |  | /**  | 
8484  |  |  * xmlRelaxNGValidateFullElement:  | 
8485  |  |  * @ctxt:  the validation context  | 
8486  |  |  * @doc:  a document instance  | 
8487  |  |  * @elem:  an element instance  | 
8488  |  |  *  | 
8489  |  |  * Validate a full subtree when xmlRelaxNGValidatePushElement() returned  | 
8490  |  |  * 0 and the content of the node has been expanded.  | 
8491  |  |  *  | 
8492  |  |  * returns 1 if no validation problem was found or -1 in case of error.  | 
8493  |  |  */  | 
8494  |  | int  | 
8495  |  | xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt,  | 
8496  |  |                               xmlDocPtr doc ATTRIBUTE_UNUSED,  | 
8497  |  |                               xmlNodePtr elem)  | 
8498  | 0  | { | 
8499  | 0  |     int ret;  | 
8500  | 0  |     xmlRelaxNGValidStatePtr state;  | 
8501  |  | 
  | 
8502  | 0  |     if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL))  | 
8503  | 0  |         return (-1);  | 
8504  |  | #ifdef DEBUG_PROGRESSIVE  | 
8505  |  |     xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name);  | 
8506  |  | #endif  | 
8507  | 0  |     state = xmlRelaxNGNewValidState(ctxt, elem->parent);  | 
8508  | 0  |     if (state == NULL) { | 
8509  | 0  |         return (-1);  | 
8510  | 0  |     }  | 
8511  | 0  |     state->seq = elem;  | 
8512  | 0  |     ctxt->state = state;  | 
8513  | 0  |     ctxt->errNo = XML_RELAXNG_OK;  | 
8514  | 0  |     ret = xmlRelaxNGValidateDefinition(ctxt, ctxt->pdef);  | 
8515  | 0  |     if ((ret != 0) || (ctxt->errNo != XML_RELAXNG_OK))  | 
8516  | 0  |         ret = -1;  | 
8517  | 0  |     else  | 
8518  | 0  |         ret = 1;  | 
8519  | 0  |     xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
8520  | 0  |     ctxt->state = NULL;  | 
8521  |  | #ifdef DEBUG_PROGRESSIVE  | 
8522  |  |     if (ret < 0)  | 
8523  |  |         xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n",  | 
8524  |  |                         elem->name);  | 
8525  |  | #endif  | 
8526  | 0  |     return (ret);  | 
8527  | 0  | }  | 
8528  |  |  | 
8529  |  | /************************************************************************  | 
8530  |  |  *                  *  | 
8531  |  |  *    Generic interpreted validation implementation   *  | 
8532  |  |  *                  *  | 
8533  |  |  ************************************************************************/  | 
8534  |  | static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,  | 
8535  |  |                                    xmlRelaxNGDefinePtr define);  | 
8536  |  |  | 
8537  |  | /**  | 
8538  |  |  * xmlRelaxNGSkipIgnored:  | 
8539  |  |  * @ctxt:  a schema validation context  | 
8540  |  |  * @node:  the top node.  | 
8541  |  |  *  | 
8542  |  |  * Skip ignorable nodes in that context  | 
8543  |  |  *  | 
8544  |  |  * Returns the new sibling or NULL in case of error.  | 
8545  |  |  */  | 
8546  |  | static xmlNodePtr  | 
8547  |  | xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,  | 
8548  |  |                       xmlNodePtr node)  | 
8549  | 0  | { | 
8550  |  |     /*  | 
8551  |  |      * TODO complete and handle entities  | 
8552  |  |      */  | 
8553  | 0  |     while ((node != NULL) &&  | 
8554  | 0  |            ((node->type == XML_COMMENT_NODE) ||  | 
8555  | 0  |             (node->type == XML_PI_NODE) ||  | 
8556  | 0  |       (node->type == XML_XINCLUDE_START) ||  | 
8557  | 0  |       (node->type == XML_XINCLUDE_END) ||  | 
8558  | 0  |             (((node->type == XML_TEXT_NODE) ||  | 
8559  | 0  |               (node->type == XML_CDATA_SECTION_NODE)) &&  | 
8560  | 0  |              ((ctxt->flags & FLAGS_MIXED_CONTENT) ||  | 
8561  | 0  |               (IS_BLANK_NODE(node)))))) { | 
8562  | 0  |         node = node->next;  | 
8563  | 0  |     }  | 
8564  | 0  |     return (node);  | 
8565  | 0  | }  | 
8566  |  |  | 
8567  |  | /**  | 
8568  |  |  * xmlRelaxNGNormalize:  | 
8569  |  |  * @ctxt:  a schema validation context  | 
8570  |  |  * @str:  the string to normalize  | 
8571  |  |  *  | 
8572  |  |  * Implements the  normalizeWhiteSpace( s ) function from  | 
8573  |  |  * section 6.2.9 of the spec  | 
8574  |  |  *  | 
8575  |  |  * Returns the new string or NULL in case of error.  | 
8576  |  |  */  | 
8577  |  | static xmlChar *  | 
8578  |  | xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str)  | 
8579  | 0  | { | 
8580  | 0  |     xmlChar *ret, *p;  | 
8581  | 0  |     const xmlChar *tmp;  | 
8582  | 0  |     int len;  | 
8583  |  | 
  | 
8584  | 0  |     if (str == NULL)  | 
8585  | 0  |         return (NULL);  | 
8586  | 0  |     tmp = str;  | 
8587  | 0  |     while (*tmp != 0)  | 
8588  | 0  |         tmp++;  | 
8589  | 0  |     len = tmp - str;  | 
8590  |  | 
  | 
8591  | 0  |     ret = (xmlChar *) xmlMallocAtomic(len + 1);  | 
8592  | 0  |     if (ret == NULL) { | 
8593  | 0  |         xmlRngVErrMemory(ctxt, "validating\n");  | 
8594  | 0  |         return (NULL);  | 
8595  | 0  |     }  | 
8596  | 0  |     p = ret;  | 
8597  | 0  |     while (IS_BLANK_CH(*str))  | 
8598  | 0  |         str++;  | 
8599  | 0  |     while (*str != 0) { | 
8600  | 0  |         if (IS_BLANK_CH(*str)) { | 
8601  | 0  |             while (IS_BLANK_CH(*str))  | 
8602  | 0  |                 str++;  | 
8603  | 0  |             if (*str == 0)  | 
8604  | 0  |                 break;  | 
8605  | 0  |             *p++ = ' ';  | 
8606  | 0  |         } else  | 
8607  | 0  |             *p++ = *str++;  | 
8608  | 0  |     }  | 
8609  | 0  |     *p = 0;  | 
8610  | 0  |     return (ret);  | 
8611  | 0  | }  | 
8612  |  |  | 
8613  |  | /**  | 
8614  |  |  * xmlRelaxNGValidateDatatype:  | 
8615  |  |  * @ctxt:  a Relax-NG validation context  | 
8616  |  |  * @value:  the string value  | 
8617  |  |  * @type:  the datatype definition  | 
8618  |  |  * @node:  the node  | 
8619  |  |  *  | 
8620  |  |  * Validate the given value against the datatype  | 
8621  |  |  *  | 
8622  |  |  * Returns 0 if the validation succeeded or an error code.  | 
8623  |  |  */  | 
8624  |  | static int  | 
8625  |  | xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt,  | 
8626  |  |                            const xmlChar * value,  | 
8627  |  |                            xmlRelaxNGDefinePtr define, xmlNodePtr node)  | 
8628  | 0  | { | 
8629  | 0  |     int ret, tmp;  | 
8630  | 0  |     xmlRelaxNGTypeLibraryPtr lib;  | 
8631  | 0  |     void *result = NULL;  | 
8632  | 0  |     xmlRelaxNGDefinePtr cur;  | 
8633  |  | 
  | 
8634  | 0  |     if ((define == NULL) || (define->data == NULL)) { | 
8635  | 0  |         return (-1);  | 
8636  | 0  |     }  | 
8637  | 0  |     lib = (xmlRelaxNGTypeLibraryPtr) define->data;  | 
8638  | 0  |     if (lib->check != NULL) { | 
8639  | 0  |         if ((define->attrs != NULL) &&  | 
8640  | 0  |             (define->attrs->type == XML_RELAXNG_PARAM)) { | 
8641  | 0  |             ret =  | 
8642  | 0  |                 lib->check(lib->data, define->name, value, &result, node);  | 
8643  | 0  |         } else { | 
8644  | 0  |             ret = lib->check(lib->data, define->name, value, NULL, node);  | 
8645  | 0  |         }  | 
8646  | 0  |     } else  | 
8647  | 0  |         ret = -1;  | 
8648  | 0  |     if (ret < 0) { | 
8649  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_TYPE, define->name);  | 
8650  | 0  |         if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))  | 
8651  | 0  |             lib->freef(lib->data, result);  | 
8652  | 0  |         return (-1);  | 
8653  | 0  |     } else if (ret == 1) { | 
8654  | 0  |         ret = 0;  | 
8655  | 0  |     } else if (ret == 2) { | 
8656  | 0  |         VALID_ERR2P(XML_RELAXNG_ERR_DUPID, value);  | 
8657  | 0  |     } else { | 
8658  | 0  |         VALID_ERR3P(XML_RELAXNG_ERR_TYPEVAL, define->name, value);  | 
8659  | 0  |         ret = -1;  | 
8660  | 0  |     }  | 
8661  | 0  |     cur = define->attrs;  | 
8662  | 0  |     while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) { | 
8663  | 0  |         if (lib->facet != NULL) { | 
8664  | 0  |             tmp = lib->facet(lib->data, define->name, cur->name,  | 
8665  | 0  |                              cur->value, value, result);  | 
8666  | 0  |             if (tmp != 0)  | 
8667  | 0  |                 ret = -1;  | 
8668  | 0  |         }  | 
8669  | 0  |         cur = cur->next;  | 
8670  | 0  |     }  | 
8671  | 0  |     if ((ret == 0) && (define->content != NULL)) { | 
8672  | 0  |         const xmlChar *oldvalue, *oldendvalue;  | 
8673  |  | 
  | 
8674  | 0  |         oldvalue = ctxt->state->value;  | 
8675  | 0  |         oldendvalue = ctxt->state->endvalue;  | 
8676  | 0  |         ctxt->state->value = (xmlChar *) value;  | 
8677  | 0  |         ctxt->state->endvalue = NULL;  | 
8678  | 0  |         ret = xmlRelaxNGValidateValue(ctxt, define->content);  | 
8679  | 0  |         ctxt->state->value = (xmlChar *) oldvalue;  | 
8680  | 0  |         ctxt->state->endvalue = (xmlChar *) oldendvalue;  | 
8681  | 0  |     }  | 
8682  | 0  |     if ((result != NULL) && (lib != NULL) && (lib->freef != NULL))  | 
8683  | 0  |         lib->freef(lib->data, result);  | 
8684  | 0  |     return (ret);  | 
8685  | 0  | }  | 
8686  |  |  | 
8687  |  | /**  | 
8688  |  |  * xmlRelaxNGNextValue:  | 
8689  |  |  * @ctxt:  a Relax-NG validation context  | 
8690  |  |  *  | 
8691  |  |  * Skip to the next value when validating within a list  | 
8692  |  |  *  | 
8693  |  |  * Returns 0 if the operation succeeded or an error code.  | 
8694  |  |  */  | 
8695  |  | static int  | 
8696  |  | xmlRelaxNGNextValue(xmlRelaxNGValidCtxtPtr ctxt)  | 
8697  | 0  | { | 
8698  | 0  |     xmlChar *cur;  | 
8699  |  | 
  | 
8700  | 0  |     cur = ctxt->state->value;  | 
8701  | 0  |     if ((cur == NULL) || (ctxt->state->endvalue == NULL)) { | 
8702  | 0  |         ctxt->state->value = NULL;  | 
8703  | 0  |         ctxt->state->endvalue = NULL;  | 
8704  | 0  |         return (0);  | 
8705  | 0  |     }  | 
8706  | 0  |     while (*cur != 0)  | 
8707  | 0  |         cur++;  | 
8708  | 0  |     while ((cur != ctxt->state->endvalue) && (*cur == 0))  | 
8709  | 0  |         cur++;  | 
8710  | 0  |     if (cur == ctxt->state->endvalue)  | 
8711  | 0  |         ctxt->state->value = NULL;  | 
8712  | 0  |     else  | 
8713  | 0  |         ctxt->state->value = cur;  | 
8714  | 0  |     return (0);  | 
8715  | 0  | }  | 
8716  |  |  | 
8717  |  | /**  | 
8718  |  |  * xmlRelaxNGValidateValueList:  | 
8719  |  |  * @ctxt:  a Relax-NG validation context  | 
8720  |  |  * @defines:  the list of definitions to verify  | 
8721  |  |  *  | 
8722  |  |  * Validate the given set of definitions for the current value  | 
8723  |  |  *  | 
8724  |  |  * Returns 0 if the validation succeeded or an error code.  | 
8725  |  |  */  | 
8726  |  | static int  | 
8727  |  | xmlRelaxNGValidateValueList(xmlRelaxNGValidCtxtPtr ctxt,  | 
8728  |  |                             xmlRelaxNGDefinePtr defines)  | 
8729  | 0  | { | 
8730  | 0  |     int ret = 0;  | 
8731  |  | 
  | 
8732  | 0  |     while (defines != NULL) { | 
8733  | 0  |         ret = xmlRelaxNGValidateValue(ctxt, defines);  | 
8734  | 0  |         if (ret != 0)  | 
8735  | 0  |             break;  | 
8736  | 0  |         defines = defines->next;  | 
8737  | 0  |     }  | 
8738  | 0  |     return (ret);  | 
8739  | 0  | }  | 
8740  |  |  | 
8741  |  | /**  | 
8742  |  |  * xmlRelaxNGValidateValue:  | 
8743  |  |  * @ctxt:  a Relax-NG validation context  | 
8744  |  |  * @define:  the definition to verify  | 
8745  |  |  *  | 
8746  |  |  * Validate the given definition for the current value  | 
8747  |  |  *  | 
8748  |  |  * Returns 0 if the validation succeeded or an error code.  | 
8749  |  |  */  | 
8750  |  | static int  | 
8751  |  | xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt,  | 
8752  |  |                         xmlRelaxNGDefinePtr define)  | 
8753  | 0  | { | 
8754  | 0  |     int ret = 0, oldflags;  | 
8755  | 0  |     xmlChar *value;  | 
8756  |  | 
  | 
8757  | 0  |     value = ctxt->state->value;  | 
8758  | 0  |     switch (define->type) { | 
8759  | 0  |         case XML_RELAXNG_EMPTY:{ | 
8760  | 0  |                 if ((value != NULL) && (value[0] != 0)) { | 
8761  | 0  |                     int idx = 0;  | 
8762  |  | 
  | 
8763  | 0  |                     while (IS_BLANK_CH(value[idx]))  | 
8764  | 0  |                         idx++;  | 
8765  | 0  |                     if (value[idx] != 0)  | 
8766  | 0  |                         ret = -1;  | 
8767  | 0  |                 }  | 
8768  | 0  |                 break;  | 
8769  | 0  |             }  | 
8770  | 0  |         case XML_RELAXNG_TEXT:  | 
8771  | 0  |             break;  | 
8772  | 0  |         case XML_RELAXNG_VALUE:{ | 
8773  | 0  |                 if (!xmlStrEqual(value, define->value)) { | 
8774  | 0  |                     if (define->name != NULL) { | 
8775  | 0  |                         xmlRelaxNGTypeLibraryPtr lib;  | 
8776  |  | 
  | 
8777  | 0  |                         lib = (xmlRelaxNGTypeLibraryPtr) define->data;  | 
8778  | 0  |                         if ((lib != NULL) && (lib->comp != NULL)) { | 
8779  | 0  |                             ret = lib->comp(lib->data, define->name,  | 
8780  | 0  |                                             define->value, define->node,  | 
8781  | 0  |                                             (void *) define->attrs,  | 
8782  | 0  |                                             value, ctxt->state->node);  | 
8783  | 0  |                         } else  | 
8784  | 0  |                             ret = -1;  | 
8785  | 0  |                         if (ret < 0) { | 
8786  | 0  |                             VALID_ERR2(XML_RELAXNG_ERR_TYPECMP,  | 
8787  | 0  |                                        define->name);  | 
8788  | 0  |                             return (-1);  | 
8789  | 0  |                         } else if (ret == 1) { | 
8790  | 0  |                             ret = 0;  | 
8791  | 0  |                         } else { | 
8792  | 0  |                             ret = -1;  | 
8793  | 0  |                         }  | 
8794  | 0  |                     } else { | 
8795  | 0  |                         xmlChar *nval, *nvalue;  | 
8796  |  |  | 
8797  |  |                         /*  | 
8798  |  |                          * TODO: trivial optimizations are possible by  | 
8799  |  |                          * computing at compile-time  | 
8800  |  |                          */  | 
8801  | 0  |                         nval = xmlRelaxNGNormalize(ctxt, define->value);  | 
8802  | 0  |                         nvalue = xmlRelaxNGNormalize(ctxt, value);  | 
8803  |  | 
  | 
8804  | 0  |                         if ((nval == NULL) || (nvalue == NULL) ||  | 
8805  | 0  |                             (!xmlStrEqual(nval, nvalue)))  | 
8806  | 0  |                             ret = -1;  | 
8807  | 0  |                         if (nval != NULL)  | 
8808  | 0  |                             xmlFree(nval);  | 
8809  | 0  |                         if (nvalue != NULL)  | 
8810  | 0  |                             xmlFree(nvalue);  | 
8811  | 0  |                     }  | 
8812  | 0  |                 }  | 
8813  | 0  |                 if (ret == 0)  | 
8814  | 0  |                     xmlRelaxNGNextValue(ctxt);  | 
8815  | 0  |                 break;  | 
8816  | 0  |             }  | 
8817  | 0  |         case XML_RELAXNG_DATATYPE:{ | 
8818  | 0  |                 ret = xmlRelaxNGValidateDatatype(ctxt, value, define,  | 
8819  | 0  |                                                  ctxt->state->seq);  | 
8820  | 0  |                 if (ret == 0)  | 
8821  | 0  |                     xmlRelaxNGNextValue(ctxt);  | 
8822  |  | 
  | 
8823  | 0  |                 break;  | 
8824  | 0  |             }  | 
8825  | 0  |         case XML_RELAXNG_CHOICE:{ | 
8826  | 0  |                 xmlRelaxNGDefinePtr list = define->content;  | 
8827  | 0  |                 xmlChar *oldvalue;  | 
8828  |  | 
  | 
8829  | 0  |                 oldflags = ctxt->flags;  | 
8830  | 0  |                 ctxt->flags |= FLAGS_IGNORABLE;  | 
8831  |  | 
  | 
8832  | 0  |                 oldvalue = ctxt->state->value;  | 
8833  | 0  |                 while (list != NULL) { | 
8834  | 0  |                     ret = xmlRelaxNGValidateValue(ctxt, list);  | 
8835  | 0  |                     if (ret == 0) { | 
8836  | 0  |                         break;  | 
8837  | 0  |                     }  | 
8838  | 0  |                     ctxt->state->value = oldvalue;  | 
8839  | 0  |                     list = list->next;  | 
8840  | 0  |                 }  | 
8841  | 0  |                 ctxt->flags = oldflags;  | 
8842  | 0  |                 if (ret != 0) { | 
8843  | 0  |                     if ((ctxt->flags & FLAGS_IGNORABLE) == 0)  | 
8844  | 0  |                         xmlRelaxNGDumpValidError(ctxt);  | 
8845  | 0  |                 } else { | 
8846  | 0  |                     if (ctxt->errNr > 0)  | 
8847  | 0  |                         xmlRelaxNGPopErrors(ctxt, 0);  | 
8848  | 0  |                 }  | 
8849  | 0  |                 break;  | 
8850  | 0  |             }  | 
8851  | 0  |         case XML_RELAXNG_LIST:{ | 
8852  | 0  |                 xmlRelaxNGDefinePtr list = define->content;  | 
8853  | 0  |                 xmlChar *oldvalue, *oldend, *val, *cur;  | 
8854  |  | 
  | 
8855  |  | #ifdef DEBUG_LIST  | 
8856  |  |                 int nb_values = 0;  | 
8857  |  | #endif  | 
8858  |  | 
  | 
8859  | 0  |                 oldvalue = ctxt->state->value;  | 
8860  | 0  |                 oldend = ctxt->state->endvalue;  | 
8861  |  | 
  | 
8862  | 0  |                 val = xmlStrdup(oldvalue);  | 
8863  | 0  |                 if (val == NULL) { | 
8864  | 0  |                     val = xmlStrdup(BAD_CAST "");  | 
8865  | 0  |                 }  | 
8866  | 0  |                 if (val == NULL) { | 
8867  | 0  |                     VALID_ERR(XML_RELAXNG_ERR_NOSTATE);  | 
8868  | 0  |                     return (-1);  | 
8869  | 0  |                 }  | 
8870  | 0  |                 cur = val;  | 
8871  | 0  |                 while (*cur != 0) { | 
8872  | 0  |                     if (IS_BLANK_CH(*cur)) { | 
8873  | 0  |                         *cur = 0;  | 
8874  | 0  |                         cur++;  | 
8875  |  | #ifdef DEBUG_LIST  | 
8876  |  |                         nb_values++;  | 
8877  |  | #endif  | 
8878  | 0  |                         while (IS_BLANK_CH(*cur))  | 
8879  | 0  |                             *cur++ = 0;  | 
8880  | 0  |                     } else  | 
8881  | 0  |                         cur++;  | 
8882  | 0  |                 }  | 
8883  |  | #ifdef DEBUG_LIST  | 
8884  |  |                 xmlGenericError(xmlGenericErrorContext,  | 
8885  |  |                                 "list value: '%s' found %d items\n",  | 
8886  |  |                                 oldvalue, nb_values);  | 
8887  |  |                 nb_values = 0;  | 
8888  |  | #endif  | 
8889  | 0  |                 ctxt->state->endvalue = cur;  | 
8890  | 0  |                 cur = val;  | 
8891  | 0  |                 while ((*cur == 0) && (cur != ctxt->state->endvalue))  | 
8892  | 0  |                     cur++;  | 
8893  |  | 
  | 
8894  | 0  |                 ctxt->state->value = cur;  | 
8895  |  | 
  | 
8896  | 0  |                 while (list != NULL) { | 
8897  | 0  |                     if (ctxt->state->value == ctxt->state->endvalue)  | 
8898  | 0  |                         ctxt->state->value = NULL;  | 
8899  | 0  |                     ret = xmlRelaxNGValidateValue(ctxt, list);  | 
8900  | 0  |                     if (ret != 0) { | 
8901  |  | #ifdef DEBUG_LIST  | 
8902  |  |                         xmlGenericError(xmlGenericErrorContext,  | 
8903  |  |                                         "Failed to validate value: '%s' with %d rule\n",  | 
8904  |  |                                         ctxt->state->value, nb_values);  | 
8905  |  | #endif  | 
8906  | 0  |                         break;  | 
8907  | 0  |                     }  | 
8908  |  | #ifdef DEBUG_LIST  | 
8909  |  |                     nb_values++;  | 
8910  |  | #endif  | 
8911  | 0  |                     list = list->next;  | 
8912  | 0  |                 }  | 
8913  |  | 
  | 
8914  | 0  |                 if ((ret == 0) && (ctxt->state->value != NULL) &&  | 
8915  | 0  |                     (ctxt->state->value != ctxt->state->endvalue)) { | 
8916  | 0  |                     VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA,  | 
8917  | 0  |                                ctxt->state->value);  | 
8918  | 0  |                     ret = -1;  | 
8919  | 0  |                 }  | 
8920  | 0  |                 xmlFree(val);  | 
8921  | 0  |                 ctxt->state->value = oldvalue;  | 
8922  | 0  |                 ctxt->state->endvalue = oldend;  | 
8923  | 0  |                 break;  | 
8924  | 0  |             }  | 
8925  | 0  |         case XML_RELAXNG_ONEORMORE:  | 
8926  | 0  |             ret = xmlRelaxNGValidateValueList(ctxt, define->content);  | 
8927  | 0  |             if (ret != 0) { | 
8928  | 0  |                 break;  | 
8929  | 0  |             }  | 
8930  |  |             /* Falls through. */  | 
8931  | 0  |         case XML_RELAXNG_ZEROORMORE:{ | 
8932  | 0  |                 xmlChar *cur, *temp;  | 
8933  |  | 
  | 
8934  | 0  |                 if ((ctxt->state->value == NULL) ||  | 
8935  | 0  |                     (*ctxt->state->value == 0)) { | 
8936  | 0  |                     ret = 0;  | 
8937  | 0  |                     break;  | 
8938  | 0  |                 }  | 
8939  | 0  |                 oldflags = ctxt->flags;  | 
8940  | 0  |                 ctxt->flags |= FLAGS_IGNORABLE;  | 
8941  | 0  |                 cur = ctxt->state->value;  | 
8942  | 0  |                 temp = NULL;  | 
8943  | 0  |                 while ((cur != NULL) && (cur != ctxt->state->endvalue) &&  | 
8944  | 0  |                        (temp != cur)) { | 
8945  | 0  |                     temp = cur;  | 
8946  | 0  |                     ret =  | 
8947  | 0  |                         xmlRelaxNGValidateValueList(ctxt, define->content);  | 
8948  | 0  |                     if (ret != 0) { | 
8949  | 0  |                         ctxt->state->value = temp;  | 
8950  | 0  |                         ret = 0;  | 
8951  | 0  |                         break;  | 
8952  | 0  |                     }  | 
8953  | 0  |                     cur = ctxt->state->value;  | 
8954  | 0  |                 }  | 
8955  | 0  |                 ctxt->flags = oldflags;  | 
8956  | 0  |     if (ctxt->errNr > 0)  | 
8957  | 0  |         xmlRelaxNGPopErrors(ctxt, 0);  | 
8958  | 0  |                 break;  | 
8959  | 0  |             }  | 
8960  | 0  |         case XML_RELAXNG_OPTIONAL:{ | 
8961  | 0  |                 xmlChar *temp;  | 
8962  |  | 
  | 
8963  | 0  |                 if ((ctxt->state->value == NULL) ||  | 
8964  | 0  |                     (*ctxt->state->value == 0)) { | 
8965  | 0  |                     ret = 0;  | 
8966  | 0  |                     break;  | 
8967  | 0  |                 }  | 
8968  | 0  |                 oldflags = ctxt->flags;  | 
8969  | 0  |                 ctxt->flags |= FLAGS_IGNORABLE;  | 
8970  | 0  |                 temp = ctxt->state->value;  | 
8971  | 0  |                 ret = xmlRelaxNGValidateValue(ctxt, define->content);  | 
8972  | 0  |                 ctxt->flags = oldflags;  | 
8973  | 0  |                 if (ret != 0) { | 
8974  | 0  |                     ctxt->state->value = temp;  | 
8975  | 0  |                     if (ctxt->errNr > 0)  | 
8976  | 0  |                         xmlRelaxNGPopErrors(ctxt, 0);  | 
8977  | 0  |                     ret = 0;  | 
8978  | 0  |                     break;  | 
8979  | 0  |                 }  | 
8980  | 0  |     if (ctxt->errNr > 0)  | 
8981  | 0  |         xmlRelaxNGPopErrors(ctxt, 0);  | 
8982  | 0  |                 break;  | 
8983  | 0  |             }  | 
8984  | 0  |         case XML_RELAXNG_EXCEPT:{ | 
8985  | 0  |                 xmlRelaxNGDefinePtr list;  | 
8986  |  | 
  | 
8987  | 0  |                 list = define->content;  | 
8988  | 0  |                 while (list != NULL) { | 
8989  | 0  |                     ret = xmlRelaxNGValidateValue(ctxt, list);  | 
8990  | 0  |                     if (ret == 0) { | 
8991  | 0  |                         ret = -1;  | 
8992  | 0  |                         break;  | 
8993  | 0  |                     } else  | 
8994  | 0  |                         ret = 0;  | 
8995  | 0  |                     list = list->next;  | 
8996  | 0  |                 }  | 
8997  | 0  |                 break;  | 
8998  | 0  |             }  | 
8999  | 0  |         case XML_RELAXNG_DEF:  | 
9000  | 0  |         case XML_RELAXNG_GROUP:{ | 
9001  | 0  |                 xmlRelaxNGDefinePtr list;  | 
9002  |  | 
  | 
9003  | 0  |                 list = define->content;  | 
9004  | 0  |                 while (list != NULL) { | 
9005  | 0  |                     ret = xmlRelaxNGValidateValue(ctxt, list);  | 
9006  | 0  |                     if (ret != 0) { | 
9007  | 0  |                         ret = -1;  | 
9008  | 0  |                         break;  | 
9009  | 0  |                     } else  | 
9010  | 0  |                         ret = 0;  | 
9011  | 0  |                     list = list->next;  | 
9012  | 0  |                 }  | 
9013  | 0  |                 break;  | 
9014  | 0  |             }  | 
9015  | 0  |         case XML_RELAXNG_REF:  | 
9016  | 0  |         case XML_RELAXNG_PARENTREF:  | 
9017  | 0  |       if (define->content == NULL) { | 
9018  | 0  |                 VALID_ERR(XML_RELAXNG_ERR_NODEFINE);  | 
9019  | 0  |                 ret = -1;  | 
9020  | 0  |       } else { | 
9021  | 0  |                 ret = xmlRelaxNGValidateValue(ctxt, define->content);  | 
9022  | 0  |             }  | 
9023  | 0  |             break;  | 
9024  | 0  |         default:  | 
9025  | 0  |             TODO ret = -1;  | 
9026  | 0  |     }  | 
9027  | 0  |     return (ret);  | 
9028  | 0  | }  | 
9029  |  |  | 
9030  |  | /**  | 
9031  |  |  * xmlRelaxNGValidateValueContent:  | 
9032  |  |  * @ctxt:  a Relax-NG validation context  | 
9033  |  |  * @defines:  the list of definitions to verify  | 
9034  |  |  *  | 
9035  |  |  * Validate the given definitions for the current value  | 
9036  |  |  *  | 
9037  |  |  * Returns 0 if the validation succeeded or an error code.  | 
9038  |  |  */  | 
9039  |  | static int  | 
9040  |  | xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt,  | 
9041  |  |                                xmlRelaxNGDefinePtr defines)  | 
9042  | 0  | { | 
9043  | 0  |     int ret = 0;  | 
9044  |  | 
  | 
9045  | 0  |     while (defines != NULL) { | 
9046  | 0  |         ret = xmlRelaxNGValidateValue(ctxt, defines);  | 
9047  | 0  |         if (ret != 0)  | 
9048  | 0  |             break;  | 
9049  | 0  |         defines = defines->next;  | 
9050  | 0  |     }  | 
9051  | 0  |     return (ret);  | 
9052  | 0  | }  | 
9053  |  |  | 
9054  |  | /**  | 
9055  |  |  * xmlRelaxNGAttributeMatch:  | 
9056  |  |  * @ctxt:  a Relax-NG validation context  | 
9057  |  |  * @define:  the definition to check  | 
9058  |  |  * @prop:  the attribute  | 
9059  |  |  *  | 
9060  |  |  * Check if the attribute matches the definition nameClass  | 
9061  |  |  *  | 
9062  |  |  * Returns 1 if the attribute matches, 0 if no, or -1 in case of error  | 
9063  |  |  */  | 
9064  |  | static int  | 
9065  |  | xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt,  | 
9066  |  |                          xmlRelaxNGDefinePtr define, xmlAttrPtr prop)  | 
9067  | 0  | { | 
9068  | 0  |     int ret;  | 
9069  |  | 
  | 
9070  | 0  |     if (define->name != NULL) { | 
9071  | 0  |         if (!xmlStrEqual(define->name, prop->name))  | 
9072  | 0  |             return (0);  | 
9073  | 0  |     }  | 
9074  | 0  |     if (define->ns != NULL) { | 
9075  | 0  |         if (define->ns[0] == 0) { | 
9076  | 0  |             if (prop->ns != NULL)  | 
9077  | 0  |                 return (0);  | 
9078  | 0  |         } else { | 
9079  | 0  |             if ((prop->ns == NULL) ||  | 
9080  | 0  |                 (!xmlStrEqual(define->ns, prop->ns->href)))  | 
9081  | 0  |                 return (0);  | 
9082  | 0  |         }  | 
9083  | 0  |     }  | 
9084  | 0  |     if (define->nameClass == NULL)  | 
9085  | 0  |         return (1);  | 
9086  | 0  |     define = define->nameClass;  | 
9087  | 0  |     if (define->type == XML_RELAXNG_EXCEPT) { | 
9088  | 0  |         xmlRelaxNGDefinePtr list;  | 
9089  |  | 
  | 
9090  | 0  |         list = define->content;  | 
9091  | 0  |         while (list != NULL) { | 
9092  | 0  |             ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);  | 
9093  | 0  |             if (ret == 1)  | 
9094  | 0  |                 return (0);  | 
9095  | 0  |             if (ret < 0)  | 
9096  | 0  |                 return (ret);  | 
9097  | 0  |             list = list->next;  | 
9098  | 0  |         }  | 
9099  | 0  |     } else if (define->type == XML_RELAXNG_CHOICE) { | 
9100  | 0  |         xmlRelaxNGDefinePtr list;  | 
9101  |  | 
  | 
9102  | 0  |         list = define->nameClass;  | 
9103  | 0  |         while (list != NULL) { | 
9104  | 0  |             ret = xmlRelaxNGAttributeMatch(ctxt, list, prop);  | 
9105  | 0  |             if (ret == 1)  | 
9106  | 0  |                 return (1);  | 
9107  | 0  |             if (ret < 0)  | 
9108  | 0  |                 return (ret);  | 
9109  | 0  |             list = list->next;  | 
9110  | 0  |         }  | 
9111  | 0  |         return (0);  | 
9112  | 0  |     } else { | 
9113  | 0  |     TODO}  | 
9114  | 0  |     return (1);  | 
9115  | 0  | }  | 
9116  |  |  | 
9117  |  | /**  | 
9118  |  |  * xmlRelaxNGValidateAttribute:  | 
9119  |  |  * @ctxt:  a Relax-NG validation context  | 
9120  |  |  * @define:  the definition to verify  | 
9121  |  |  *  | 
9122  |  |  * Validate the given attribute definition for that node  | 
9123  |  |  *  | 
9124  |  |  * Returns 0 if the validation succeeded or an error code.  | 
9125  |  |  */  | 
9126  |  | static int  | 
9127  |  | xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt,  | 
9128  |  |                             xmlRelaxNGDefinePtr define)  | 
9129  | 0  | { | 
9130  | 0  |     int ret = 0, i;  | 
9131  | 0  |     xmlChar *value, *oldvalue;  | 
9132  | 0  |     xmlAttrPtr prop = NULL, tmp;  | 
9133  | 0  |     xmlNodePtr oldseq;  | 
9134  |  | 
  | 
9135  | 0  |     if (ctxt->state->nbAttrLeft <= 0)  | 
9136  | 0  |         return (-1);  | 
9137  | 0  |     if (define->name != NULL) { | 
9138  | 0  |         for (i = 0; i < ctxt->state->nbAttrs; i++) { | 
9139  | 0  |             tmp = ctxt->state->attrs[i];  | 
9140  | 0  |             if ((tmp != NULL) && (xmlStrEqual(define->name, tmp->name))) { | 
9141  | 0  |                 if ((((define->ns == NULL) || (define->ns[0] == 0)) &&  | 
9142  | 0  |                      (tmp->ns == NULL)) ||  | 
9143  | 0  |                     ((tmp->ns != NULL) &&  | 
9144  | 0  |                      (xmlStrEqual(define->ns, tmp->ns->href)))) { | 
9145  | 0  |                     prop = tmp;  | 
9146  | 0  |                     break;  | 
9147  | 0  |                 }  | 
9148  | 0  |             }  | 
9149  | 0  |         }  | 
9150  | 0  |         if (prop != NULL) { | 
9151  | 0  |             value = xmlNodeListGetString(prop->doc, prop->children, 1);  | 
9152  | 0  |             oldvalue = ctxt->state->value;  | 
9153  | 0  |             oldseq = ctxt->state->seq;  | 
9154  | 0  |             ctxt->state->seq = (xmlNodePtr) prop;  | 
9155  | 0  |             ctxt->state->value = value;  | 
9156  | 0  |             ctxt->state->endvalue = NULL;  | 
9157  | 0  |             ret = xmlRelaxNGValidateValueContent(ctxt, define->content);  | 
9158  | 0  |             if (ctxt->state->value != NULL)  | 
9159  | 0  |                 value = ctxt->state->value;  | 
9160  | 0  |             if (value != NULL)  | 
9161  | 0  |                 xmlFree(value);  | 
9162  | 0  |             ctxt->state->value = oldvalue;  | 
9163  | 0  |             ctxt->state->seq = oldseq;  | 
9164  | 0  |             if (ret == 0) { | 
9165  |  |                 /*  | 
9166  |  |                  * flag the attribute as processed  | 
9167  |  |                  */  | 
9168  | 0  |                 ctxt->state->attrs[i] = NULL;  | 
9169  | 0  |                 ctxt->state->nbAttrLeft--;  | 
9170  | 0  |             }  | 
9171  | 0  |         } else { | 
9172  | 0  |             ret = -1;  | 
9173  | 0  |         }  | 
9174  |  | #ifdef DEBUG  | 
9175  |  |         xmlGenericError(xmlGenericErrorContext,  | 
9176  |  |                         "xmlRelaxNGValidateAttribute(%s): %d\n",  | 
9177  |  |                         define->name, ret);  | 
9178  |  | #endif  | 
9179  | 0  |     } else { | 
9180  | 0  |         for (i = 0; i < ctxt->state->nbAttrs; i++) { | 
9181  | 0  |             tmp = ctxt->state->attrs[i];  | 
9182  | 0  |             if ((tmp != NULL) &&  | 
9183  | 0  |                 (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) { | 
9184  | 0  |                 prop = tmp;  | 
9185  | 0  |                 break;  | 
9186  | 0  |             }  | 
9187  | 0  |         }  | 
9188  | 0  |         if (prop != NULL) { | 
9189  | 0  |             value = xmlNodeListGetString(prop->doc, prop->children, 1);  | 
9190  | 0  |             oldvalue = ctxt->state->value;  | 
9191  | 0  |             oldseq = ctxt->state->seq;  | 
9192  | 0  |             ctxt->state->seq = (xmlNodePtr) prop;  | 
9193  | 0  |             ctxt->state->value = value;  | 
9194  | 0  |             ret = xmlRelaxNGValidateValueContent(ctxt, define->content);  | 
9195  | 0  |             if (ctxt->state->value != NULL)  | 
9196  | 0  |                 value = ctxt->state->value;  | 
9197  | 0  |             if (value != NULL)  | 
9198  | 0  |                 xmlFree(value);  | 
9199  | 0  |             ctxt->state->value = oldvalue;  | 
9200  | 0  |             ctxt->state->seq = oldseq;  | 
9201  | 0  |             if (ret == 0) { | 
9202  |  |                 /*  | 
9203  |  |                  * flag the attribute as processed  | 
9204  |  |                  */  | 
9205  | 0  |                 ctxt->state->attrs[i] = NULL;  | 
9206  | 0  |                 ctxt->state->nbAttrLeft--;  | 
9207  | 0  |             }  | 
9208  | 0  |         } else { | 
9209  | 0  |             ret = -1;  | 
9210  | 0  |         }  | 
9211  |  | #ifdef DEBUG  | 
9212  |  |         if (define->ns != NULL) { | 
9213  |  |             xmlGenericError(xmlGenericErrorContext,  | 
9214  |  |                             "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n",  | 
9215  |  |                             define->ns, ret);  | 
9216  |  |         } else { | 
9217  |  |             xmlGenericError(xmlGenericErrorContext,  | 
9218  |  |                             "xmlRelaxNGValidateAttribute(anyName): %d\n",  | 
9219  |  |                             ret);  | 
9220  |  |         }  | 
9221  |  | #endif  | 
9222  | 0  |     }  | 
9223  |  | 
  | 
9224  | 0  |     return (ret);  | 
9225  | 0  | }  | 
9226  |  |  | 
9227  |  | /**  | 
9228  |  |  * xmlRelaxNGValidateAttributeList:  | 
9229  |  |  * @ctxt:  a Relax-NG validation context  | 
9230  |  |  * @define:  the list of definition to verify  | 
9231  |  |  *  | 
9232  |  |  * Validate the given node against the list of attribute definitions  | 
9233  |  |  *  | 
9234  |  |  * Returns 0 if the validation succeeded or an error code.  | 
9235  |  |  */  | 
9236  |  | static int  | 
9237  |  | xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt,  | 
9238  |  |                                 xmlRelaxNGDefinePtr defines)  | 
9239  | 0  | { | 
9240  | 0  |     int ret = 0, res;  | 
9241  | 0  |     int needmore = 0;  | 
9242  | 0  |     xmlRelaxNGDefinePtr cur;  | 
9243  |  | 
  | 
9244  | 0  |     cur = defines;  | 
9245  | 0  |     while (cur != NULL) { | 
9246  | 0  |         if (cur->type == XML_RELAXNG_ATTRIBUTE) { | 
9247  | 0  |             if (xmlRelaxNGValidateAttribute(ctxt, cur) != 0)  | 
9248  | 0  |                 ret = -1;  | 
9249  | 0  |         } else  | 
9250  | 0  |             needmore = 1;  | 
9251  | 0  |         cur = cur->next;  | 
9252  | 0  |     }  | 
9253  | 0  |     if (!needmore)  | 
9254  | 0  |         return (ret);  | 
9255  | 0  |     cur = defines;  | 
9256  | 0  |     while (cur != NULL) { | 
9257  | 0  |         if (cur->type != XML_RELAXNG_ATTRIBUTE) { | 
9258  | 0  |             if ((ctxt->state != NULL) || (ctxt->states != NULL)) { | 
9259  | 0  |                 res = xmlRelaxNGValidateDefinition(ctxt, cur);  | 
9260  | 0  |                 if (res < 0)  | 
9261  | 0  |                     ret = -1;  | 
9262  | 0  |             } else { | 
9263  | 0  |                 VALID_ERR(XML_RELAXNG_ERR_NOSTATE);  | 
9264  | 0  |                 return (-1);  | 
9265  | 0  |             }  | 
9266  | 0  |             if (res == -1)      /* continues on -2 */  | 
9267  | 0  |                 break;  | 
9268  | 0  |         }  | 
9269  | 0  |         cur = cur->next;  | 
9270  | 0  |     }  | 
9271  |  |  | 
9272  | 0  |     return (ret);  | 
9273  | 0  | }  | 
9274  |  |  | 
9275  |  | /**  | 
9276  |  |  * xmlRelaxNGNodeMatchesList:  | 
9277  |  |  * @node:  the node  | 
9278  |  |  * @list:  a NULL terminated array of definitions  | 
9279  |  |  *  | 
9280  |  |  * Check if a node can be matched by one of the definitions  | 
9281  |  |  *  | 
9282  |  |  * Returns 1 if matches 0 otherwise  | 
9283  |  |  */  | 
9284  |  | static int  | 
9285  |  | xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr * list)  | 
9286  | 0  | { | 
9287  | 0  |     xmlRelaxNGDefinePtr cur;  | 
9288  | 0  |     int i = 0, tmp;  | 
9289  |  | 
  | 
9290  | 0  |     if ((node == NULL) || (list == NULL))  | 
9291  | 0  |         return (0);  | 
9292  |  |  | 
9293  | 0  |     cur = list[i++];  | 
9294  | 0  |     while (cur != NULL) { | 
9295  | 0  |         if ((node->type == XML_ELEMENT_NODE) &&  | 
9296  | 0  |             (cur->type == XML_RELAXNG_ELEMENT)) { | 
9297  | 0  |             tmp = xmlRelaxNGElementMatch(NULL, cur, node);  | 
9298  | 0  |             if (tmp == 1)  | 
9299  | 0  |                 return (1);  | 
9300  | 0  |         } else if (((node->type == XML_TEXT_NODE) ||  | 
9301  | 0  |                     (node->type == XML_CDATA_SECTION_NODE)) &&  | 
9302  | 0  |                    ((cur->type == XML_RELAXNG_DATATYPE) ||  | 
9303  | 0  |         (cur->type == XML_RELAXNG_LIST) ||  | 
9304  | 0  |                     (cur->type == XML_RELAXNG_TEXT) ||  | 
9305  | 0  |                     (cur->type == XML_RELAXNG_VALUE))) { | 
9306  | 0  |             return (1);  | 
9307  | 0  |         }  | 
9308  | 0  |         cur = list[i++];  | 
9309  | 0  |     }  | 
9310  | 0  |     return (0);  | 
9311  | 0  | }  | 
9312  |  |  | 
9313  |  | /**  | 
9314  |  |  * xmlRelaxNGValidateInterleave:  | 
9315  |  |  * @ctxt:  a Relax-NG validation context  | 
9316  |  |  * @define:  the definition to verify  | 
9317  |  |  *  | 
9318  |  |  * Validate an interleave definition for a node.  | 
9319  |  |  *  | 
9320  |  |  * Returns 0 if the validation succeeded or an error code.  | 
9321  |  |  */  | 
9322  |  | static int  | 
9323  |  | xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt,  | 
9324  |  |                              xmlRelaxNGDefinePtr define)  | 
9325  | 0  | { | 
9326  | 0  |     int ret = 0, i, nbgroups;  | 
9327  | 0  |     int errNr = ctxt->errNr;  | 
9328  | 0  |     int oldflags;  | 
9329  |  | 
  | 
9330  | 0  |     xmlRelaxNGValidStatePtr oldstate;  | 
9331  | 0  |     xmlRelaxNGPartitionPtr partitions;  | 
9332  | 0  |     xmlRelaxNGInterleaveGroupPtr group = NULL;  | 
9333  | 0  |     xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem;  | 
9334  | 0  |     xmlNodePtr *list = NULL, *lasts = NULL;  | 
9335  |  | 
  | 
9336  | 0  |     if (define->data != NULL) { | 
9337  | 0  |         partitions = (xmlRelaxNGPartitionPtr) define->data;  | 
9338  | 0  |         nbgroups = partitions->nbgroups;  | 
9339  | 0  |     } else { | 
9340  | 0  |         VALID_ERR(XML_RELAXNG_ERR_INTERNODATA);  | 
9341  | 0  |         return (-1);  | 
9342  | 0  |     }  | 
9343  |  |     /*  | 
9344  |  |      * Optimizations for MIXED  | 
9345  |  |      */  | 
9346  | 0  |     oldflags = ctxt->flags;  | 
9347  | 0  |     if (define->dflags & IS_MIXED) { | 
9348  | 0  |         ctxt->flags |= FLAGS_MIXED_CONTENT;  | 
9349  | 0  |         if (nbgroups == 2) { | 
9350  |  |             /*  | 
9351  |  |              * this is a pure <mixed> case  | 
9352  |  |              */  | 
9353  | 0  |             if (ctxt->state != NULL)  | 
9354  | 0  |                 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,  | 
9355  | 0  |                                                          ctxt->state->seq);  | 
9356  | 0  |             if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT)  | 
9357  | 0  |                 ret = xmlRelaxNGValidateDefinition(ctxt,  | 
9358  | 0  |                                                    partitions->groups[1]->  | 
9359  | 0  |                                                    rule);  | 
9360  | 0  |             else  | 
9361  | 0  |                 ret = xmlRelaxNGValidateDefinition(ctxt,  | 
9362  | 0  |                                                    partitions->groups[0]->  | 
9363  | 0  |                                                    rule);  | 
9364  | 0  |             if (ret == 0) { | 
9365  | 0  |                 if (ctxt->state != NULL)  | 
9366  | 0  |                     ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt,  | 
9367  | 0  |                                                              ctxt->state->  | 
9368  | 0  |                                                              seq);  | 
9369  | 0  |             }  | 
9370  | 0  |             ctxt->flags = oldflags;  | 
9371  | 0  |             return (ret);  | 
9372  | 0  |         }  | 
9373  | 0  |     }  | 
9374  |  |  | 
9375  |  |     /*  | 
9376  |  |      * Build arrays to store the first and last node of the chain  | 
9377  |  |      * pertaining to each group  | 
9378  |  |      */  | 
9379  | 0  |     list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));  | 
9380  | 0  |     if (list == NULL) { | 
9381  | 0  |         xmlRngVErrMemory(ctxt, "validating\n");  | 
9382  | 0  |         return (-1);  | 
9383  | 0  |     }  | 
9384  | 0  |     memset(list, 0, nbgroups * sizeof(xmlNodePtr));  | 
9385  | 0  |     lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr));  | 
9386  | 0  |     if (lasts == NULL) { | 
9387  | 0  |         xmlRngVErrMemory(ctxt, "validating\n");  | 
9388  | 0  |         return (-1);  | 
9389  | 0  |     }  | 
9390  | 0  |     memset(lasts, 0, nbgroups * sizeof(xmlNodePtr));  | 
9391  |  |  | 
9392  |  |     /*  | 
9393  |  |      * Walk the sequence of children finding the right group and  | 
9394  |  |      * sorting them in sequences.  | 
9395  |  |      */  | 
9396  | 0  |     cur = ctxt->state->seq;  | 
9397  | 0  |     cur = xmlRelaxNGSkipIgnored(ctxt, cur);  | 
9398  | 0  |     start = cur;  | 
9399  | 0  |     while (cur != NULL) { | 
9400  | 0  |         ctxt->state->seq = cur;  | 
9401  | 0  |         if ((partitions->triage != NULL) &&  | 
9402  | 0  |             (partitions->flags & IS_DETERMINIST)) { | 
9403  | 0  |             void *tmp = NULL;  | 
9404  |  | 
  | 
9405  | 0  |             if ((cur->type == XML_TEXT_NODE) ||  | 
9406  | 0  |                 (cur->type == XML_CDATA_SECTION_NODE)) { | 
9407  | 0  |                 tmp = xmlHashLookup2(partitions->triage, BAD_CAST "#text",  | 
9408  | 0  |                                      NULL);  | 
9409  | 0  |             } else if (cur->type == XML_ELEMENT_NODE) { | 
9410  | 0  |                 if (cur->ns != NULL) { | 
9411  | 0  |                     tmp = xmlHashLookup2(partitions->triage, cur->name,  | 
9412  | 0  |                                          cur->ns->href);  | 
9413  | 0  |                     if (tmp == NULL)  | 
9414  | 0  |                         tmp = xmlHashLookup2(partitions->triage,  | 
9415  | 0  |                                              BAD_CAST "#any",  | 
9416  | 0  |                                              cur->ns->href);  | 
9417  | 0  |                 } else  | 
9418  | 0  |                     tmp =  | 
9419  | 0  |                         xmlHashLookup2(partitions->triage, cur->name,  | 
9420  | 0  |                                        NULL);  | 
9421  | 0  |                 if (tmp == NULL)  | 
9422  | 0  |                     tmp =  | 
9423  | 0  |                         xmlHashLookup2(partitions->triage, BAD_CAST "#any",  | 
9424  | 0  |                                        NULL);  | 
9425  | 0  |             }  | 
9426  |  | 
  | 
9427  | 0  |             if (tmp == NULL) { | 
9428  | 0  |                 i = nbgroups;  | 
9429  | 0  |             } else { | 
9430  | 0  |                 i = ((ptrdiff_t) tmp) - 1;  | 
9431  | 0  |                 if (partitions->flags & IS_NEEDCHECK) { | 
9432  | 0  |                     group = partitions->groups[i];  | 
9433  | 0  |                     if (!xmlRelaxNGNodeMatchesList(cur, group->defs))  | 
9434  | 0  |                         i = nbgroups;  | 
9435  | 0  |                 }  | 
9436  | 0  |             }  | 
9437  | 0  |         } else { | 
9438  | 0  |             for (i = 0; i < nbgroups; i++) { | 
9439  | 0  |                 group = partitions->groups[i];  | 
9440  | 0  |                 if (group == NULL)  | 
9441  | 0  |                     continue;  | 
9442  | 0  |                 if (xmlRelaxNGNodeMatchesList(cur, group->defs))  | 
9443  | 0  |                     break;  | 
9444  | 0  |             }  | 
9445  | 0  |         }  | 
9446  |  |         /*  | 
9447  |  |          * We break as soon as an element not matched is found  | 
9448  |  |          */  | 
9449  | 0  |         if (i >= nbgroups) { | 
9450  | 0  |             break;  | 
9451  | 0  |         }  | 
9452  | 0  |         if (lasts[i] != NULL) { | 
9453  | 0  |             lasts[i]->next = cur;  | 
9454  | 0  |             lasts[i] = cur;  | 
9455  | 0  |         } else { | 
9456  | 0  |             list[i] = cur;  | 
9457  | 0  |             lasts[i] = cur;  | 
9458  | 0  |         }  | 
9459  | 0  |         if (cur->next != NULL)  | 
9460  | 0  |             lastchg = cur->next;  | 
9461  | 0  |         else  | 
9462  | 0  |             lastchg = cur;  | 
9463  | 0  |         cur = xmlRelaxNGSkipIgnored(ctxt, cur->next);  | 
9464  | 0  |     }  | 
9465  | 0  |     if (ret != 0) { | 
9466  | 0  |         VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);  | 
9467  | 0  |         ret = -1;  | 
9468  | 0  |         goto done;  | 
9469  | 0  |     }  | 
9470  | 0  |     lastelem = cur;  | 
9471  | 0  |     oldstate = ctxt->state;  | 
9472  | 0  |     for (i = 0; i < nbgroups; i++) { | 
9473  | 0  |         ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate);  | 
9474  | 0  |   if (ctxt->state == NULL) { | 
9475  | 0  |       ret = -1;  | 
9476  | 0  |       break;  | 
9477  | 0  |   }  | 
9478  | 0  |         group = partitions->groups[i];  | 
9479  | 0  |         if (lasts[i] != NULL) { | 
9480  | 0  |             last = lasts[i]->next;  | 
9481  | 0  |             lasts[i]->next = NULL;  | 
9482  | 0  |         }  | 
9483  | 0  |         ctxt->state->seq = list[i];  | 
9484  | 0  |         ret = xmlRelaxNGValidateDefinition(ctxt, group->rule);  | 
9485  | 0  |         if (ret != 0)  | 
9486  | 0  |             break;  | 
9487  | 0  |         if (ctxt->state != NULL) { | 
9488  | 0  |             cur = ctxt->state->seq;  | 
9489  | 0  |             cur = xmlRelaxNGSkipIgnored(ctxt, cur);  | 
9490  | 0  |             xmlRelaxNGFreeValidState(ctxt, oldstate);  | 
9491  | 0  |             oldstate = ctxt->state;  | 
9492  | 0  |             ctxt->state = NULL;  | 
9493  | 0  |             if (cur != NULL  | 
9494  |  |                     /* there's a nasty violation of context-free unambiguities,  | 
9495  |  |                        since in open-name-class context, interleave in the  | 
9496  |  |                        production shall finish without caring about anything  | 
9497  |  |                        else that is OK to follow in that case -- it would  | 
9498  |  |                        otherwise get marked as "extra content" and would  | 
9499  |  |                        hence fail the validation, hence this perhaps  | 
9500  |  |                        dirty attempt to rectify such a situation */  | 
9501  | 0  |                     && (define->parent->type != XML_RELAXNG_DEF  | 
9502  | 0  |                         || !xmlStrEqual(define->parent->name,  | 
9503  | 0  |                                         (const xmlChar *) "open-name-class"))) { | 
9504  | 0  |                 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);  | 
9505  | 0  |                 ret = -1;  | 
9506  | 0  |                 ctxt->state = oldstate;  | 
9507  | 0  |                 goto done;  | 
9508  | 0  |             }  | 
9509  | 0  |         } else if (ctxt->states != NULL) { | 
9510  | 0  |             int j;  | 
9511  | 0  |             int found = 0;  | 
9512  | 0  |       int best = -1;  | 
9513  | 0  |       int lowattr = -1;  | 
9514  |  |  | 
9515  |  |       /*  | 
9516  |  |        * PBM: what happen if there is attributes checks in the interleaves  | 
9517  |  |        */  | 
9518  |  | 
  | 
9519  | 0  |             for (j = 0; j < ctxt->states->nbState; j++) { | 
9520  | 0  |                 cur = ctxt->states->tabState[j]->seq;  | 
9521  | 0  |                 cur = xmlRelaxNGSkipIgnored(ctxt, cur);  | 
9522  | 0  |                 if (cur == NULL) { | 
9523  | 0  |         if (found == 0) { | 
9524  | 0  |             lowattr = ctxt->states->tabState[j]->nbAttrLeft;  | 
9525  | 0  |       best = j;  | 
9526  | 0  |         }  | 
9527  | 0  |                     found = 1;  | 
9528  | 0  |         if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) { | 
9529  |  |             /* try  to keep the latest one to mach old heuristic */  | 
9530  | 0  |             lowattr = ctxt->states->tabState[j]->nbAttrLeft;  | 
9531  | 0  |       best = j;  | 
9532  | 0  |         }  | 
9533  | 0  |                     if (lowattr == 0)  | 
9534  | 0  |             break;  | 
9535  | 0  |                 } else if (found == 0) { | 
9536  | 0  |                     if (lowattr == -1) { | 
9537  | 0  |             lowattr = ctxt->states->tabState[j]->nbAttrLeft;  | 
9538  | 0  |       best = j;  | 
9539  | 0  |         } else  | 
9540  | 0  |         if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr)  { | 
9541  |  |             /* try  to keep the latest one to mach old heuristic */  | 
9542  | 0  |             lowattr = ctxt->states->tabState[j]->nbAttrLeft;  | 
9543  | 0  |       best = j;  | 
9544  | 0  |         }  | 
9545  | 0  |     }  | 
9546  | 0  |             }  | 
9547  |  |       /*  | 
9548  |  |        * BIG PBM: here we pick only one restarting point :-(  | 
9549  |  |        */  | 
9550  | 0  |             if (ctxt->states->nbState > 0) { | 
9551  | 0  |                 xmlRelaxNGFreeValidState(ctxt, oldstate);  | 
9552  | 0  |     if (best != -1) { | 
9553  | 0  |         oldstate = ctxt->states->tabState[best];  | 
9554  | 0  |         ctxt->states->tabState[best] = NULL;  | 
9555  | 0  |     } else { | 
9556  | 0  |         oldstate =  | 
9557  | 0  |       ctxt->states->tabState[ctxt->states->nbState - 1];  | 
9558  | 0  |                     ctxt->states->tabState[ctxt->states->nbState - 1] = NULL;  | 
9559  | 0  |                     ctxt->states->nbState--;  | 
9560  | 0  |     }  | 
9561  | 0  |             }  | 
9562  | 0  |             for (j = 0; j < ctxt->states->nbState ; j++) { | 
9563  | 0  |                 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[j]);  | 
9564  | 0  |             }  | 
9565  | 0  |             xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
9566  | 0  |             ctxt->states = NULL;  | 
9567  | 0  |             if (found == 0) { | 
9568  | 0  |                 if (cur == NULL) { | 
9569  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA,  | 
9570  | 0  |              (const xmlChar *) "noname");  | 
9571  | 0  |                 } else { | 
9572  | 0  |                     VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name);  | 
9573  | 0  |                 }  | 
9574  | 0  |                 ret = -1;  | 
9575  | 0  |                 ctxt->state = oldstate;  | 
9576  | 0  |                 goto done;  | 
9577  | 0  |             }  | 
9578  | 0  |         } else { | 
9579  | 0  |             ret = -1;  | 
9580  | 0  |             break;  | 
9581  | 0  |         }  | 
9582  | 0  |         if (lasts[i] != NULL) { | 
9583  | 0  |             lasts[i]->next = last;  | 
9584  | 0  |         }  | 
9585  | 0  |     }  | 
9586  | 0  |     if (ctxt->state != NULL)  | 
9587  | 0  |         xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
9588  | 0  |     ctxt->state = oldstate;  | 
9589  | 0  |     ctxt->state->seq = lastelem;  | 
9590  | 0  |     if (ret != 0) { | 
9591  | 0  |         VALID_ERR(XML_RELAXNG_ERR_INTERSEQ);  | 
9592  | 0  |         ret = -1;  | 
9593  | 0  |         goto done;  | 
9594  | 0  |     }  | 
9595  |  |  | 
9596  | 0  |   done:  | 
9597  | 0  |     ctxt->flags = oldflags;  | 
9598  |  |     /*  | 
9599  |  |      * builds the next links chain from the prev one  | 
9600  |  |      */  | 
9601  | 0  |     cur = lastchg;  | 
9602  | 0  |     while (cur != NULL) { | 
9603  | 0  |         if ((cur == start) || (cur->prev == NULL))  | 
9604  | 0  |             break;  | 
9605  | 0  |         cur->prev->next = cur;  | 
9606  | 0  |         cur = cur->prev;  | 
9607  | 0  |     }  | 
9608  | 0  |     if (ret == 0) { | 
9609  | 0  |         if (ctxt->errNr > errNr)  | 
9610  | 0  |             xmlRelaxNGPopErrors(ctxt, errNr);  | 
9611  | 0  |     }  | 
9612  |  | 
  | 
9613  | 0  |     xmlFree(list);  | 
9614  | 0  |     xmlFree(lasts);  | 
9615  | 0  |     return (ret);  | 
9616  | 0  | }  | 
9617  |  |  | 
9618  |  | /**  | 
9619  |  |  * xmlRelaxNGValidateDefinitionList:  | 
9620  |  |  * @ctxt:  a Relax-NG validation context  | 
9621  |  |  * @define:  the list of definition to verify  | 
9622  |  |  *  | 
9623  |  |  * Validate the given node content against the (list) of definitions  | 
9624  |  |  *  | 
9625  |  |  * Returns 0 if the validation succeeded or an error code.  | 
9626  |  |  */  | 
9627  |  | static int  | 
9628  |  | xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt,  | 
9629  |  |                                  xmlRelaxNGDefinePtr defines)  | 
9630  | 0  | { | 
9631  | 0  |     int ret = 0, res;  | 
9632  |  |  | 
9633  |  | 
  | 
9634  | 0  |     if (defines == NULL) { | 
9635  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_INTERNAL,  | 
9636  | 0  |                    BAD_CAST "NULL definition list");  | 
9637  | 0  |         return (-1);  | 
9638  | 0  |     }  | 
9639  | 0  |     while (defines != NULL) { | 
9640  | 0  |         if ((ctxt->state != NULL) || (ctxt->states != NULL)) { | 
9641  | 0  |             res = xmlRelaxNGValidateDefinition(ctxt, defines);  | 
9642  | 0  |             if (res < 0)  | 
9643  | 0  |                 ret = -1;  | 
9644  | 0  |         } else { | 
9645  | 0  |             VALID_ERR(XML_RELAXNG_ERR_NOSTATE);  | 
9646  | 0  |             return (-1);  | 
9647  | 0  |         }  | 
9648  | 0  |         if (res == -1)          /* continues on -2 */  | 
9649  | 0  |             break;  | 
9650  | 0  |         defines = defines->next;  | 
9651  | 0  |     }  | 
9652  |  |  | 
9653  | 0  |     return (ret);  | 
9654  | 0  | }  | 
9655  |  |  | 
9656  |  | /**  | 
9657  |  |  * xmlRelaxNGElementMatch:  | 
9658  |  |  * @ctxt:  a Relax-NG validation context  | 
9659  |  |  * @define:  the definition to check  | 
9660  |  |  * @elem:  the element  | 
9661  |  |  *  | 
9662  |  |  * Check if the element matches the definition nameClass  | 
9663  |  |  *  | 
9664  |  |  * Returns 1 if the element matches, 0 if no, or -1 in case of error  | 
9665  |  |  */  | 
9666  |  | static int  | 
9667  |  | xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,  | 
9668  |  |                        xmlRelaxNGDefinePtr define, xmlNodePtr elem)  | 
9669  | 0  | { | 
9670  | 0  |     int ret = 0, oldflags = 0;  | 
9671  |  | 
  | 
9672  | 0  |     if (define->name != NULL) { | 
9673  | 0  |         if (!xmlStrEqual(elem->name, define->name)) { | 
9674  | 0  |             VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name);  | 
9675  | 0  |             return (0);  | 
9676  | 0  |         }  | 
9677  | 0  |     }  | 
9678  | 0  |     if ((define->ns != NULL) && (define->ns[0] != 0)) { | 
9679  | 0  |         if (elem->ns == NULL) { | 
9680  | 0  |             VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name);  | 
9681  | 0  |             return (0);  | 
9682  | 0  |         } else if (!xmlStrEqual(elem->ns->href, define->ns)) { | 
9683  | 0  |             VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS,  | 
9684  | 0  |                        elem->name, define->ns);  | 
9685  | 0  |             return (0);  | 
9686  | 0  |         }  | 
9687  | 0  |     } else if ((elem->ns != NULL) && (define->ns != NULL) &&  | 
9688  | 0  |                (define->name == NULL)) { | 
9689  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name);  | 
9690  | 0  |         return (0);  | 
9691  | 0  |     } else if ((elem->ns != NULL) && (define->name != NULL)) { | 
9692  | 0  |         VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name);  | 
9693  | 0  |         return (0);  | 
9694  | 0  |     }  | 
9695  |  |  | 
9696  | 0  |     if (define->nameClass == NULL)  | 
9697  | 0  |         return (1);  | 
9698  |  |  | 
9699  | 0  |     define = define->nameClass;  | 
9700  | 0  |     if (define->type == XML_RELAXNG_EXCEPT) { | 
9701  | 0  |         xmlRelaxNGDefinePtr list;  | 
9702  |  | 
  | 
9703  | 0  |         if (ctxt != NULL) { | 
9704  | 0  |             oldflags = ctxt->flags;  | 
9705  | 0  |             ctxt->flags |= FLAGS_IGNORABLE;  | 
9706  | 0  |         }  | 
9707  |  | 
  | 
9708  | 0  |         list = define->content;  | 
9709  | 0  |         while (list != NULL) { | 
9710  | 0  |             ret = xmlRelaxNGElementMatch(ctxt, list, elem);  | 
9711  | 0  |             if (ret == 1) { | 
9712  | 0  |                 if (ctxt != NULL)  | 
9713  | 0  |                     ctxt->flags = oldflags;  | 
9714  | 0  |                 return (0);  | 
9715  | 0  |             }  | 
9716  | 0  |             if (ret < 0) { | 
9717  | 0  |                 if (ctxt != NULL)  | 
9718  | 0  |                     ctxt->flags = oldflags;  | 
9719  | 0  |                 return (ret);  | 
9720  | 0  |             }  | 
9721  | 0  |             list = list->next;  | 
9722  | 0  |         }  | 
9723  | 0  |         ret = 1;  | 
9724  | 0  |         if (ctxt != NULL) { | 
9725  | 0  |             ctxt->flags = oldflags;  | 
9726  | 0  |         }  | 
9727  | 0  |     } else if (define->type == XML_RELAXNG_CHOICE) { | 
9728  | 0  |         xmlRelaxNGDefinePtr list;  | 
9729  |  | 
  | 
9730  | 0  |         if (ctxt != NULL) { | 
9731  | 0  |             oldflags = ctxt->flags;  | 
9732  | 0  |             ctxt->flags |= FLAGS_IGNORABLE;  | 
9733  | 0  |         }  | 
9734  |  | 
  | 
9735  | 0  |         list = define->nameClass;  | 
9736  | 0  |         while (list != NULL) { | 
9737  | 0  |             ret = xmlRelaxNGElementMatch(ctxt, list, elem);  | 
9738  | 0  |             if (ret == 1) { | 
9739  | 0  |                 if (ctxt != NULL)  | 
9740  | 0  |                     ctxt->flags = oldflags;  | 
9741  | 0  |                 return (1);  | 
9742  | 0  |             }  | 
9743  | 0  |             if (ret < 0) { | 
9744  | 0  |                 if (ctxt != NULL)  | 
9745  | 0  |                     ctxt->flags = oldflags;  | 
9746  | 0  |                 return (ret);  | 
9747  | 0  |             }  | 
9748  | 0  |             list = list->next;  | 
9749  | 0  |         }  | 
9750  | 0  |         if (ctxt != NULL) { | 
9751  | 0  |             if (ret != 0) { | 
9752  | 0  |                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)  | 
9753  | 0  |                     xmlRelaxNGDumpValidError(ctxt);  | 
9754  | 0  |             } else { | 
9755  | 0  |                 if (ctxt->errNr > 0)  | 
9756  | 0  |                     xmlRelaxNGPopErrors(ctxt, 0);  | 
9757  | 0  |             }  | 
9758  | 0  |         }  | 
9759  | 0  |         ret = 0;  | 
9760  | 0  |         if (ctxt != NULL) { | 
9761  | 0  |             ctxt->flags = oldflags;  | 
9762  | 0  |         }  | 
9763  | 0  |     } else { | 
9764  | 0  |         TODO ret = -1;  | 
9765  | 0  |     }  | 
9766  | 0  |     return (ret);  | 
9767  | 0  | }  | 
9768  |  |  | 
9769  |  | /**  | 
9770  |  |  * xmlRelaxNGBestState:  | 
9771  |  |  * @ctxt:  a Relax-NG validation context  | 
9772  |  |  *  | 
9773  |  |  * Find the "best" state in the ctxt->states list of states to report  | 
9774  |  |  * errors about. I.e. a state with no element left in the child list  | 
9775  |  |  * or the one with the less attributes left.  | 
9776  |  |  * This is called only if a validation error was detected  | 
9777  |  |  *  | 
9778  |  |  * Returns the index of the "best" state or -1 in case of error  | 
9779  |  |  */  | 
9780  |  | static int  | 
9781  |  | xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt)  | 
9782  | 0  | { | 
9783  | 0  |     xmlRelaxNGValidStatePtr state;  | 
9784  | 0  |     int i, tmp;  | 
9785  | 0  |     int best = -1;  | 
9786  | 0  |     int value = 1000000;  | 
9787  |  | 
  | 
9788  | 0  |     if ((ctxt == NULL) || (ctxt->states == NULL) ||  | 
9789  | 0  |         (ctxt->states->nbState <= 0))  | 
9790  | 0  |         return (-1);  | 
9791  |  |  | 
9792  | 0  |     for (i = 0; i < ctxt->states->nbState; i++) { | 
9793  | 0  |         state = ctxt->states->tabState[i];  | 
9794  | 0  |         if (state == NULL)  | 
9795  | 0  |             continue;  | 
9796  | 0  |         if (state->seq != NULL) { | 
9797  | 0  |             if ((best == -1) || (value > 100000)) { | 
9798  | 0  |                 value = 100000;  | 
9799  | 0  |                 best = i;  | 
9800  | 0  |             }  | 
9801  | 0  |         } else { | 
9802  | 0  |             tmp = state->nbAttrLeft;  | 
9803  | 0  |             if ((best == -1) || (value > tmp)) { | 
9804  | 0  |                 value = tmp;  | 
9805  | 0  |                 best = i;  | 
9806  | 0  |             }  | 
9807  | 0  |         }  | 
9808  | 0  |     }  | 
9809  | 0  |     return (best);  | 
9810  | 0  | }  | 
9811  |  |  | 
9812  |  | /**  | 
9813  |  |  * xmlRelaxNGLogBestError:  | 
9814  |  |  * @ctxt:  a Relax-NG validation context  | 
9815  |  |  *  | 
9816  |  |  * Find the "best" state in the ctxt->states list of states to report  | 
9817  |  |  * errors about and log it.  | 
9818  |  |  */  | 
9819  |  | static void  | 
9820  |  | xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt)  | 
9821  | 0  | { | 
9822  | 0  |     int best;  | 
9823  |  | 
  | 
9824  | 0  |     if ((ctxt == NULL) || (ctxt->states == NULL) ||  | 
9825  | 0  |         (ctxt->states->nbState <= 0))  | 
9826  | 0  |         return;  | 
9827  |  |  | 
9828  | 0  |     best = xmlRelaxNGBestState(ctxt);  | 
9829  | 0  |     if ((best >= 0) && (best < ctxt->states->nbState)) { | 
9830  | 0  |         ctxt->state = ctxt->states->tabState[best];  | 
9831  |  | 
  | 
9832  | 0  |         xmlRelaxNGValidateElementEnd(ctxt, 1);  | 
9833  | 0  |     }  | 
9834  | 0  | }  | 
9835  |  |  | 
9836  |  | /**  | 
9837  |  |  * xmlRelaxNGValidateElementEnd:  | 
9838  |  |  * @ctxt:  a Relax-NG validation context  | 
9839  |  |  * @dolog:  indicate that error logging should be done  | 
9840  |  |  *  | 
9841  |  |  * Validate the end of the element, implements check that  | 
9842  |  |  * there is nothing left not consumed in the element content  | 
9843  |  |  * or in the attribute list.  | 
9844  |  |  *  | 
9845  |  |  * Returns 0 if the validation succeeded or an error code.  | 
9846  |  |  */  | 
9847  |  | static int  | 
9848  |  | xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int dolog)  | 
9849  | 0  | { | 
9850  | 0  |     int i;  | 
9851  | 0  |     xmlRelaxNGValidStatePtr state;  | 
9852  |  | 
  | 
9853  | 0  |     state = ctxt->state;  | 
9854  | 0  |     if (state->seq != NULL) { | 
9855  | 0  |         state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq);  | 
9856  | 0  |         if (state->seq != NULL) { | 
9857  | 0  |             if (dolog) { | 
9858  | 0  |                 VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT,  | 
9859  | 0  |                            state->node->name, state->seq->name);  | 
9860  | 0  |             }  | 
9861  | 0  |             return (-1);  | 
9862  | 0  |         }  | 
9863  | 0  |     }  | 
9864  | 0  |     for (i = 0; i < state->nbAttrs; i++) { | 
9865  | 0  |         if (state->attrs[i] != NULL) { | 
9866  | 0  |             if (dolog) { | 
9867  | 0  |                 VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR,  | 
9868  | 0  |                            state->attrs[i]->name, state->node->name);  | 
9869  | 0  |             }  | 
9870  | 0  |             return (-1 - i);  | 
9871  | 0  |         }  | 
9872  | 0  |     }  | 
9873  | 0  |     return (0);  | 
9874  | 0  | }  | 
9875  |  |  | 
9876  |  | /**  | 
9877  |  |  * xmlRelaxNGValidateState:  | 
9878  |  |  * @ctxt:  a Relax-NG validation context  | 
9879  |  |  * @define:  the definition to verify  | 
9880  |  |  *  | 
9881  |  |  * Validate the current state against the definition  | 
9882  |  |  *  | 
9883  |  |  * Returns 0 if the validation succeeded or an error code.  | 
9884  |  |  */  | 
9885  |  | static int  | 
9886  |  | xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt,  | 
9887  |  |                         xmlRelaxNGDefinePtr define)  | 
9888  | 0  | { | 
9889  | 0  |     xmlNodePtr node;  | 
9890  | 0  |     int ret = 0, i, tmp, oldflags, errNr;  | 
9891  | 0  |     xmlRelaxNGValidStatePtr oldstate = NULL, state;  | 
9892  |  | 
  | 
9893  | 0  |     if (define == NULL) { | 
9894  | 0  |         VALID_ERR(XML_RELAXNG_ERR_NODEFINE);  | 
9895  | 0  |         return (-1);  | 
9896  | 0  |     }  | 
9897  |  |  | 
9898  | 0  |     if (ctxt->state != NULL) { | 
9899  | 0  |         node = ctxt->state->seq;  | 
9900  | 0  |     } else { | 
9901  | 0  |         node = NULL;  | 
9902  | 0  |     }  | 
9903  |  | #ifdef DEBUG  | 
9904  |  |     for (i = 0; i < ctxt->depth; i++)  | 
9905  |  |         xmlGenericError(xmlGenericErrorContext, " ");  | 
9906  |  |     xmlGenericError(xmlGenericErrorContext,  | 
9907  |  |                     "Start validating %s ", xmlRelaxNGDefName(define));  | 
9908  |  |     if (define->name != NULL)  | 
9909  |  |         xmlGenericError(xmlGenericErrorContext, "%s ", define->name);  | 
9910  |  |     if ((node != NULL) && (node->name != NULL))  | 
9911  |  |         xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name);  | 
9912  |  |     else  | 
9913  |  |         xmlGenericError(xmlGenericErrorContext, "\n");  | 
9914  |  | #endif  | 
9915  | 0  |     ctxt->depth++;  | 
9916  | 0  |     switch (define->type) { | 
9917  | 0  |         case XML_RELAXNG_EMPTY:  | 
9918  | 0  |             ret = 0;  | 
9919  | 0  |             break;  | 
9920  | 0  |         case XML_RELAXNG_NOT_ALLOWED:  | 
9921  | 0  |             ret = -1;  | 
9922  | 0  |             break;  | 
9923  | 0  |         case XML_RELAXNG_TEXT:  | 
9924  | 0  |             while ((node != NULL) &&  | 
9925  | 0  |                    ((node->type == XML_TEXT_NODE) ||  | 
9926  | 0  |                     (node->type == XML_COMMENT_NODE) ||  | 
9927  | 0  |                     (node->type == XML_PI_NODE) ||  | 
9928  | 0  |                     (node->type == XML_CDATA_SECTION_NODE)))  | 
9929  | 0  |                 node = node->next;  | 
9930  | 0  |             ctxt->state->seq = node;  | 
9931  | 0  |             break;  | 
9932  | 0  |         case XML_RELAXNG_ELEMENT:  | 
9933  | 0  |             errNr = ctxt->errNr;  | 
9934  | 0  |             node = xmlRelaxNGSkipIgnored(ctxt, node);  | 
9935  | 0  |             if (node == NULL) { | 
9936  | 0  |                 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name);  | 
9937  | 0  |                 ret = -1;  | 
9938  | 0  |                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)  | 
9939  | 0  |                     xmlRelaxNGDumpValidError(ctxt);  | 
9940  | 0  |                 break;  | 
9941  | 0  |             }  | 
9942  | 0  |             if (node->type != XML_ELEMENT_NODE) { | 
9943  | 0  |                 VALID_ERR(XML_RELAXNG_ERR_NOTELEM);  | 
9944  | 0  |                 ret = -1;  | 
9945  | 0  |                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)  | 
9946  | 0  |                     xmlRelaxNGDumpValidError(ctxt);  | 
9947  | 0  |                 break;  | 
9948  | 0  |             }  | 
9949  |  |             /*  | 
9950  |  |              * This node was already validated successfully against  | 
9951  |  |              * this definition.  | 
9952  |  |              */  | 
9953  | 0  |             if (node->psvi == define) { | 
9954  | 0  |                 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);  | 
9955  | 0  |                 if (ctxt->errNr > errNr)  | 
9956  | 0  |                     xmlRelaxNGPopErrors(ctxt, errNr);  | 
9957  | 0  |                 if (ctxt->errNr != 0) { | 
9958  | 0  |                     while ((ctxt->err != NULL) &&  | 
9959  | 0  |                            (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME)  | 
9960  | 0  |                              && (xmlStrEqual(ctxt->err->arg2, node->name)))  | 
9961  | 0  |                             ||  | 
9962  | 0  |                             ((ctxt->err->err ==  | 
9963  | 0  |                               XML_RELAXNG_ERR_ELEMEXTRANS)  | 
9964  | 0  |                              && (xmlStrEqual(ctxt->err->arg1, node->name)))  | 
9965  | 0  |                             || (ctxt->err->err == XML_RELAXNG_ERR_NOELEM)  | 
9966  | 0  |                             || (ctxt->err->err ==  | 
9967  | 0  |                                 XML_RELAXNG_ERR_NOTELEM)))  | 
9968  | 0  |                         xmlRelaxNGValidErrorPop(ctxt);  | 
9969  | 0  |                 }  | 
9970  | 0  |                 break;  | 
9971  | 0  |             }  | 
9972  |  |  | 
9973  | 0  |             ret = xmlRelaxNGElementMatch(ctxt, define, node);  | 
9974  | 0  |             if (ret <= 0) { | 
9975  | 0  |                 ret = -1;  | 
9976  | 0  |                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)  | 
9977  | 0  |                     xmlRelaxNGDumpValidError(ctxt);  | 
9978  | 0  |                 break;  | 
9979  | 0  |             }  | 
9980  | 0  |             ret = 0;  | 
9981  | 0  |             if (ctxt->errNr != 0) { | 
9982  | 0  |                 if (ctxt->errNr > errNr)  | 
9983  | 0  |                     xmlRelaxNGPopErrors(ctxt, errNr);  | 
9984  | 0  |                 while ((ctxt->err != NULL) &&  | 
9985  | 0  |                        (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) &&  | 
9986  | 0  |                          (xmlStrEqual(ctxt->err->arg2, node->name))) ||  | 
9987  | 0  |                         ((ctxt->err->err == XML_RELAXNG_ERR_ELEMEXTRANS) &&  | 
9988  | 0  |                          (xmlStrEqual(ctxt->err->arg1, node->name))) ||  | 
9989  | 0  |                         (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) ||  | 
9990  | 0  |                         (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM)))  | 
9991  | 0  |                     xmlRelaxNGValidErrorPop(ctxt);  | 
9992  | 0  |             }  | 
9993  | 0  |             errNr = ctxt->errNr;  | 
9994  |  | 
  | 
9995  | 0  |             oldflags = ctxt->flags;  | 
9996  | 0  |             if (ctxt->flags & FLAGS_MIXED_CONTENT) { | 
9997  | 0  |                 ctxt->flags -= FLAGS_MIXED_CONTENT;  | 
9998  | 0  |             }  | 
9999  | 0  |             state = xmlRelaxNGNewValidState(ctxt, node);  | 
10000  | 0  |             if (state == NULL) { | 
10001  | 0  |                 ret = -1;  | 
10002  | 0  |                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0)  | 
10003  | 0  |                     xmlRelaxNGDumpValidError(ctxt);  | 
10004  | 0  |                 break;  | 
10005  | 0  |             }  | 
10006  |  |  | 
10007  | 0  |             oldstate = ctxt->state;  | 
10008  | 0  |             ctxt->state = state;  | 
10009  | 0  |             if (define->attrs != NULL) { | 
10010  | 0  |                 tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs);  | 
10011  | 0  |                 if (tmp != 0) { | 
10012  | 0  |                     ret = -1;  | 
10013  | 0  |                     VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name);  | 
10014  | 0  |                 }  | 
10015  | 0  |             }  | 
10016  | 0  |             if (define->contModel != NULL) { | 
10017  | 0  |                 xmlRelaxNGValidStatePtr nstate, tmpstate = ctxt->state;  | 
10018  | 0  |                 xmlRelaxNGStatesPtr tmpstates = ctxt->states;  | 
10019  | 0  |                 xmlNodePtr nseq;  | 
10020  |  | 
  | 
10021  | 0  |                 nstate = xmlRelaxNGNewValidState(ctxt, node);  | 
10022  | 0  |                 ctxt->state = nstate;  | 
10023  | 0  |                 ctxt->states = NULL;  | 
10024  |  | 
  | 
10025  | 0  |                 tmp = xmlRelaxNGValidateCompiledContent(ctxt,  | 
10026  | 0  |                                                         define->contModel,  | 
10027  | 0  |                                                         ctxt->state->seq);  | 
10028  | 0  |                 nseq = ctxt->state->seq;  | 
10029  | 0  |                 ctxt->state = tmpstate;  | 
10030  | 0  |                 ctxt->states = tmpstates;  | 
10031  | 0  |                 xmlRelaxNGFreeValidState(ctxt, nstate);  | 
10032  |  | 
  | 
10033  |  | #ifdef DEBUG_COMPILE  | 
10034  |  |                 xmlGenericError(xmlGenericErrorContext,  | 
10035  |  |                                 "Validating content of '%s' : %d\n",  | 
10036  |  |                                 define->name, tmp);  | 
10037  |  | #endif  | 
10038  | 0  |                 if (tmp != 0)  | 
10039  | 0  |                     ret = -1;  | 
10040  |  | 
  | 
10041  | 0  |                 if (ctxt->states != NULL) { | 
10042  | 0  |                     tmp = -1;  | 
10043  |  | 
  | 
10044  | 0  |                     for (i = 0; i < ctxt->states->nbState; i++) { | 
10045  | 0  |                         state = ctxt->states->tabState[i];  | 
10046  | 0  |                         ctxt->state = state;  | 
10047  | 0  |                         ctxt->state->seq = nseq;  | 
10048  |  | 
  | 
10049  | 0  |                         if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { | 
10050  | 0  |                             tmp = 0;  | 
10051  | 0  |                             break;  | 
10052  | 0  |                         }  | 
10053  | 0  |                     }  | 
10054  | 0  |                     if (tmp != 0) { | 
10055  |  |                         /*  | 
10056  |  |                          * validation error, log the message for the "best" one  | 
10057  |  |                          */  | 
10058  | 0  |                         ctxt->flags |= FLAGS_IGNORABLE;  | 
10059  | 0  |                         xmlRelaxNGLogBestError(ctxt);  | 
10060  | 0  |                     }  | 
10061  | 0  |                     for (i = 0; i < ctxt->states->nbState; i++) { | 
10062  | 0  |                         xmlRelaxNGFreeValidState(ctxt,  | 
10063  | 0  |                                                  ctxt->states->  | 
10064  | 0  |                                                  tabState[i]);  | 
10065  | 0  |                     }  | 
10066  | 0  |                     xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
10067  | 0  |                     ctxt->flags = oldflags;  | 
10068  | 0  |                     ctxt->states = NULL;  | 
10069  | 0  |                     if ((ret == 0) && (tmp == -1))  | 
10070  | 0  |                         ret = -1;  | 
10071  | 0  |                 } else { | 
10072  | 0  |                     state = ctxt->state;  | 
10073  | 0  |         if (ctxt->state != NULL)  | 
10074  | 0  |       ctxt->state->seq = nseq;  | 
10075  | 0  |                     if (ret == 0)  | 
10076  | 0  |                         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);  | 
10077  | 0  |                     xmlRelaxNGFreeValidState(ctxt, state);  | 
10078  | 0  |                 }  | 
10079  | 0  |             } else { | 
10080  | 0  |                 if (define->content != NULL) { | 
10081  | 0  |                     tmp = xmlRelaxNGValidateDefinitionList(ctxt,  | 
10082  | 0  |                                                            define->  | 
10083  | 0  |                                                            content);  | 
10084  | 0  |                     if (tmp != 0) { | 
10085  | 0  |                         ret = -1;  | 
10086  | 0  |                         if (ctxt->state == NULL) { | 
10087  | 0  |                             ctxt->state = oldstate;  | 
10088  | 0  |                             VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,  | 
10089  | 0  |                                        node->name);  | 
10090  | 0  |                             ctxt->state = NULL;  | 
10091  | 0  |                         } else { | 
10092  | 0  |                             VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID,  | 
10093  | 0  |                                        node->name);  | 
10094  | 0  |                         }  | 
10095  |  | 
  | 
10096  | 0  |                     }  | 
10097  | 0  |                 }  | 
10098  | 0  |                 if (ctxt->states != NULL) { | 
10099  | 0  |                     tmp = -1;  | 
10100  |  | 
  | 
10101  | 0  |                     for (i = 0; i < ctxt->states->nbState; i++) { | 
10102  | 0  |                         state = ctxt->states->tabState[i];  | 
10103  | 0  |                         ctxt->state = state;  | 
10104  |  | 
  | 
10105  | 0  |                         if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { | 
10106  | 0  |                             tmp = 0;  | 
10107  | 0  |                             break;  | 
10108  | 0  |                         }  | 
10109  | 0  |                     }  | 
10110  | 0  |                     if (tmp != 0) { | 
10111  |  |                         /*  | 
10112  |  |                          * validation error, log the message for the "best" one  | 
10113  |  |                          */  | 
10114  | 0  |                         ctxt->flags |= FLAGS_IGNORABLE;  | 
10115  | 0  |                         xmlRelaxNGLogBestError(ctxt);  | 
10116  | 0  |                     }  | 
10117  | 0  |                     for (i = 0; i < ctxt->states->nbState; i++) { | 
10118  | 0  |                         xmlRelaxNGFreeValidState(ctxt,  | 
10119  | 0  |                                                  ctxt->states->tabState[i]);  | 
10120  | 0  |                         ctxt->states->tabState[i] = NULL;  | 
10121  | 0  |                     }  | 
10122  | 0  |                     xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
10123  | 0  |                     ctxt->flags = oldflags;  | 
10124  | 0  |                     ctxt->states = NULL;  | 
10125  | 0  |                     if ((ret == 0) && (tmp == -1))  | 
10126  | 0  |                         ret = -1;  | 
10127  | 0  |                 } else { | 
10128  | 0  |                     state = ctxt->state;  | 
10129  | 0  |                     if (ret == 0)  | 
10130  | 0  |                         ret = xmlRelaxNGValidateElementEnd(ctxt, 1);  | 
10131  | 0  |                     xmlRelaxNGFreeValidState(ctxt, state);  | 
10132  | 0  |                 }  | 
10133  | 0  |             }  | 
10134  | 0  |             if (ret == 0) { | 
10135  | 0  |                 node->psvi = define;  | 
10136  | 0  |             }  | 
10137  | 0  |             ctxt->flags = oldflags;  | 
10138  | 0  |             ctxt->state = oldstate;  | 
10139  | 0  |             if (oldstate != NULL)  | 
10140  | 0  |                 oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next);  | 
10141  | 0  |             if (ret != 0) { | 
10142  | 0  |                 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { | 
10143  | 0  |                     xmlRelaxNGDumpValidError(ctxt);  | 
10144  | 0  |                     ret = 0;  | 
10145  |  | #if 0  | 
10146  |  |                 } else { | 
10147  |  |                     ret = -2;  | 
10148  |  | #endif  | 
10149  | 0  |                 }  | 
10150  | 0  |             } else { | 
10151  | 0  |                 if (ctxt->errNr > errNr)  | 
10152  | 0  |                     xmlRelaxNGPopErrors(ctxt, errNr);  | 
10153  | 0  |             }  | 
10154  |  | 
  | 
10155  |  | #ifdef DEBUG  | 
10156  |  |             xmlGenericError(xmlGenericErrorContext,  | 
10157  |  |                             "xmlRelaxNGValidateDefinition(): validated %s : %d",  | 
10158  |  |                             node->name, ret);  | 
10159  |  |             if (oldstate == NULL)  | 
10160  |  |                 xmlGenericError(xmlGenericErrorContext, ": no state\n");  | 
10161  |  |             else if (oldstate->seq == NULL)  | 
10162  |  |                 xmlGenericError(xmlGenericErrorContext, ": done\n");  | 
10163  |  |             else if (oldstate->seq->type == XML_ELEMENT_NODE)  | 
10164  |  |                 xmlGenericError(xmlGenericErrorContext, ": next elem %s\n",  | 
10165  |  |                                 oldstate->seq->name);  | 
10166  |  |             else  | 
10167  |  |                 xmlGenericError(xmlGenericErrorContext, ": next %s %d\n",  | 
10168  |  |                                 oldstate->seq->name, oldstate->seq->type);  | 
10169  |  | #endif  | 
10170  | 0  |             break;  | 
10171  | 0  |         case XML_RELAXNG_OPTIONAL:{ | 
10172  | 0  |                 errNr = ctxt->errNr;  | 
10173  | 0  |                 oldflags = ctxt->flags;  | 
10174  | 0  |                 ctxt->flags |= FLAGS_IGNORABLE;  | 
10175  | 0  |                 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);  | 
10176  | 0  |                 ret =  | 
10177  | 0  |                     xmlRelaxNGValidateDefinitionList(ctxt,  | 
10178  | 0  |                                                      define->content);  | 
10179  | 0  |                 if (ret != 0) { | 
10180  | 0  |                     if (ctxt->state != NULL)  | 
10181  | 0  |                         xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10182  | 0  |                     ctxt->state = oldstate;  | 
10183  | 0  |                     ctxt->flags = oldflags;  | 
10184  | 0  |                     ret = 0;  | 
10185  | 0  |                     if (ctxt->errNr > errNr)  | 
10186  | 0  |                         xmlRelaxNGPopErrors(ctxt, errNr);  | 
10187  | 0  |                     break;  | 
10188  | 0  |                 }  | 
10189  | 0  |                 if (ctxt->states != NULL) { | 
10190  | 0  |                     xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);  | 
10191  | 0  |                 } else { | 
10192  | 0  |                     ctxt->states = xmlRelaxNGNewStates(ctxt, 1);  | 
10193  | 0  |                     if (ctxt->states == NULL) { | 
10194  | 0  |                         xmlRelaxNGFreeValidState(ctxt, oldstate);  | 
10195  | 0  |                         ctxt->flags = oldflags;  | 
10196  | 0  |                         ret = -1;  | 
10197  | 0  |                         if (ctxt->errNr > errNr)  | 
10198  | 0  |                             xmlRelaxNGPopErrors(ctxt, errNr);  | 
10199  | 0  |                         break;  | 
10200  | 0  |                     }  | 
10201  | 0  |                     xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate);  | 
10202  | 0  |                     xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state);  | 
10203  | 0  |                     ctxt->state = NULL;  | 
10204  | 0  |                 }  | 
10205  | 0  |                 ctxt->flags = oldflags;  | 
10206  | 0  |                 ret = 0;  | 
10207  | 0  |                 if (ctxt->errNr > errNr)  | 
10208  | 0  |                     xmlRelaxNGPopErrors(ctxt, errNr);  | 
10209  | 0  |                 break;  | 
10210  | 0  |             }  | 
10211  | 0  |         case XML_RELAXNG_ONEORMORE:  | 
10212  | 0  |             errNr = ctxt->errNr;  | 
10213  | 0  |             ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);  | 
10214  | 0  |             if (ret != 0) { | 
10215  | 0  |                 break;  | 
10216  | 0  |             }  | 
10217  | 0  |             if (ctxt->errNr > errNr)  | 
10218  | 0  |                 xmlRelaxNGPopErrors(ctxt, errNr);  | 
10219  |  |             /* Falls through. */  | 
10220  | 0  |         case XML_RELAXNG_ZEROORMORE:{ | 
10221  | 0  |                 int progress;  | 
10222  | 0  |                 xmlRelaxNGStatesPtr states = NULL, res = NULL;  | 
10223  | 0  |                 int base, j;  | 
10224  |  | 
  | 
10225  | 0  |                 errNr = ctxt->errNr;  | 
10226  | 0  |                 res = xmlRelaxNGNewStates(ctxt, 1);  | 
10227  | 0  |                 if (res == NULL) { | 
10228  | 0  |                     ret = -1;  | 
10229  | 0  |                     break;  | 
10230  | 0  |                 }  | 
10231  |  |                 /*  | 
10232  |  |                  * All the input states are also exit states  | 
10233  |  |                  */  | 
10234  | 0  |                 if (ctxt->state != NULL) { | 
10235  | 0  |                     xmlRelaxNGAddStates(ctxt, res,  | 
10236  | 0  |                                         xmlRelaxNGCopyValidState(ctxt,  | 
10237  | 0  |                                                                  ctxt->  | 
10238  | 0  |                                                                  state));  | 
10239  | 0  |                 } else { | 
10240  | 0  |                     for (j = 0; j < ctxt->states->nbState; j++) { | 
10241  | 0  |                         xmlRelaxNGAddStates(ctxt, res,  | 
10242  | 0  |                             xmlRelaxNGCopyValidState(ctxt,  | 
10243  | 0  |                                             ctxt->states->tabState[j]));  | 
10244  | 0  |                     }  | 
10245  | 0  |                 }  | 
10246  | 0  |                 oldflags = ctxt->flags;  | 
10247  | 0  |                 ctxt->flags |= FLAGS_IGNORABLE;  | 
10248  | 0  |                 do { | 
10249  | 0  |                     progress = 0;  | 
10250  | 0  |                     base = res->nbState;  | 
10251  |  | 
  | 
10252  | 0  |                     if (ctxt->states != NULL) { | 
10253  | 0  |                         states = ctxt->states;  | 
10254  | 0  |                         for (i = 0; i < states->nbState; i++) { | 
10255  | 0  |                             ctxt->state = states->tabState[i];  | 
10256  | 0  |                             ctxt->states = NULL;  | 
10257  | 0  |                             ret = xmlRelaxNGValidateDefinitionList(ctxt,  | 
10258  | 0  |                                                                    define->  | 
10259  | 0  |                                                                    content);  | 
10260  | 0  |                             if (ret == 0) { | 
10261  | 0  |                                 if (ctxt->state != NULL) { | 
10262  | 0  |                                     tmp = xmlRelaxNGAddStates(ctxt, res,  | 
10263  | 0  |                                                               ctxt->state);  | 
10264  | 0  |                                     ctxt->state = NULL;  | 
10265  | 0  |                                     if (tmp == 1)  | 
10266  | 0  |                                         progress = 1;  | 
10267  | 0  |                                 } else if (ctxt->states != NULL) { | 
10268  | 0  |                                     for (j = 0; j < ctxt->states->nbState;  | 
10269  | 0  |                                          j++) { | 
10270  | 0  |                                         tmp =  | 
10271  | 0  |                                             xmlRelaxNGAddStates(ctxt, res,  | 
10272  | 0  |                                                    ctxt->states->tabState[j]);  | 
10273  | 0  |                                         if (tmp == 1)  | 
10274  | 0  |                                             progress = 1;  | 
10275  | 0  |                                     }  | 
10276  | 0  |                                     xmlRelaxNGFreeStates(ctxt,  | 
10277  | 0  |                                                          ctxt->states);  | 
10278  | 0  |                                     ctxt->states = NULL;  | 
10279  | 0  |                                 }  | 
10280  | 0  |                             } else { | 
10281  | 0  |                                 if (ctxt->state != NULL) { | 
10282  | 0  |                                     xmlRelaxNGFreeValidState(ctxt,  | 
10283  | 0  |                                                              ctxt->state);  | 
10284  | 0  |                                     ctxt->state = NULL;  | 
10285  | 0  |                                 }  | 
10286  | 0  |                             }  | 
10287  | 0  |                         }  | 
10288  | 0  |                     } else { | 
10289  | 0  |                         ret = xmlRelaxNGValidateDefinitionList(ctxt,  | 
10290  | 0  |                                                                define->  | 
10291  | 0  |                                                                content);  | 
10292  | 0  |                         if (ret != 0) { | 
10293  | 0  |                             xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10294  | 0  |                             ctxt->state = NULL;  | 
10295  | 0  |                         } else { | 
10296  | 0  |                             base = res->nbState;  | 
10297  | 0  |                             if (ctxt->state != NULL) { | 
10298  | 0  |                                 tmp = xmlRelaxNGAddStates(ctxt, res,  | 
10299  | 0  |                                                           ctxt->state);  | 
10300  | 0  |                                 ctxt->state = NULL;  | 
10301  | 0  |                                 if (tmp == 1)  | 
10302  | 0  |                                     progress = 1;  | 
10303  | 0  |                             } else if (ctxt->states != NULL) { | 
10304  | 0  |                                 for (j = 0; j < ctxt->states->nbState; j++) { | 
10305  | 0  |                                     tmp = xmlRelaxNGAddStates(ctxt, res,  | 
10306  | 0  |                                                ctxt->states->tabState[j]);  | 
10307  | 0  |                                     if (tmp == 1)  | 
10308  | 0  |                                         progress = 1;  | 
10309  | 0  |                                 }  | 
10310  | 0  |                                 if (states == NULL) { | 
10311  | 0  |                                     states = ctxt->states;  | 
10312  | 0  |                                 } else { | 
10313  | 0  |                                     xmlRelaxNGFreeStates(ctxt,  | 
10314  | 0  |                                                          ctxt->states);  | 
10315  | 0  |                                 }  | 
10316  | 0  |                                 ctxt->states = NULL;  | 
10317  | 0  |                             }  | 
10318  | 0  |                         }  | 
10319  | 0  |                     }  | 
10320  | 0  |                     if (progress) { | 
10321  |  |                         /*  | 
10322  |  |                          * Collect all the new nodes added at that step  | 
10323  |  |                          * and make them the new node set  | 
10324  |  |                          */  | 
10325  | 0  |                         if (res->nbState - base == 1) { | 
10326  | 0  |                             ctxt->state = xmlRelaxNGCopyValidState(ctxt,  | 
10327  | 0  |                                                                    res->  | 
10328  | 0  |                                                                    tabState  | 
10329  | 0  |                                                                    [base]);  | 
10330  | 0  |                         } else { | 
10331  | 0  |                             if (states == NULL) { | 
10332  | 0  |                                 xmlRelaxNGNewStates(ctxt,  | 
10333  | 0  |                                                     res->nbState - base);  | 
10334  | 0  |               states = ctxt->states;  | 
10335  | 0  |         if (states == NULL) { | 
10336  | 0  |             progress = 0;  | 
10337  | 0  |             break;  | 
10338  | 0  |         }  | 
10339  | 0  |                             }  | 
10340  | 0  |                             states->nbState = 0;  | 
10341  | 0  |                             for (i = base; i < res->nbState; i++)  | 
10342  | 0  |                                 xmlRelaxNGAddStates(ctxt, states,  | 
10343  | 0  |                                                     xmlRelaxNGCopyValidState  | 
10344  | 0  |                                                     (ctxt, res->tabState[i]));  | 
10345  | 0  |                             ctxt->states = states;  | 
10346  | 0  |                         }  | 
10347  | 0  |                     }  | 
10348  | 0  |                 } while (progress == 1);  | 
10349  | 0  |                 if (states != NULL) { | 
10350  | 0  |                     xmlRelaxNGFreeStates(ctxt, states);  | 
10351  | 0  |                 }  | 
10352  | 0  |                 ctxt->states = res;  | 
10353  | 0  |                 ctxt->flags = oldflags;  | 
10354  |  | #if 0  | 
10355  |  |                 /*  | 
10356  |  |                  * errors may have to be propagated back...  | 
10357  |  |                  */  | 
10358  |  |                 if (ctxt->errNr > errNr)  | 
10359  |  |                     xmlRelaxNGPopErrors(ctxt, errNr);  | 
10360  |  | #endif  | 
10361  | 0  |                 ret = 0;  | 
10362  | 0  |                 break;  | 
10363  | 0  |             }  | 
10364  | 0  |         case XML_RELAXNG_CHOICE:{ | 
10365  | 0  |                 xmlRelaxNGDefinePtr list = NULL;  | 
10366  | 0  |                 xmlRelaxNGStatesPtr states = NULL;  | 
10367  |  | 
  | 
10368  | 0  |                 node = xmlRelaxNGSkipIgnored(ctxt, node);  | 
10369  |  | 
  | 
10370  | 0  |                 errNr = ctxt->errNr;  | 
10371  | 0  |                 if ((define->dflags & IS_TRIABLE) && (define->data != NULL) &&  | 
10372  | 0  |         (node != NULL)) { | 
10373  |  |         /*  | 
10374  |  |          * node == NULL can't be optimized since IS_TRIABLE  | 
10375  |  |          * doesn't account for choice which may lead to  | 
10376  |  |          * only attributes.  | 
10377  |  |          */  | 
10378  | 0  |                     xmlHashTablePtr triage =  | 
10379  | 0  |                         (xmlHashTablePtr) define->data;  | 
10380  |  |  | 
10381  |  |                     /*  | 
10382  |  |                      * Something we can optimize cleanly there is only one  | 
10383  |  |                      * possible branch out !  | 
10384  |  |                      */  | 
10385  | 0  |                     if ((node->type == XML_TEXT_NODE) ||  | 
10386  | 0  |                         (node->type == XML_CDATA_SECTION_NODE)) { | 
10387  | 0  |                         list =  | 
10388  | 0  |                             xmlHashLookup2(triage, BAD_CAST "#text", NULL);  | 
10389  | 0  |                     } else if (node->type == XML_ELEMENT_NODE) { | 
10390  | 0  |                         if (node->ns != NULL) { | 
10391  | 0  |                             list = xmlHashLookup2(triage, node->name,  | 
10392  | 0  |                                                   node->ns->href);  | 
10393  | 0  |                             if (list == NULL)  | 
10394  | 0  |                                 list =  | 
10395  | 0  |                                     xmlHashLookup2(triage, BAD_CAST "#any",  | 
10396  | 0  |                                                    node->ns->href);  | 
10397  | 0  |                         } else  | 
10398  | 0  |                             list =  | 
10399  | 0  |                                 xmlHashLookup2(triage, node->name, NULL);  | 
10400  | 0  |                         if (list == NULL)  | 
10401  | 0  |                             list =  | 
10402  | 0  |                                 xmlHashLookup2(triage, BAD_CAST "#any",  | 
10403  | 0  |                                                NULL);  | 
10404  | 0  |                     }  | 
10405  | 0  |                     if (list == NULL) { | 
10406  | 0  |                         ret = -1;  | 
10407  | 0  |       VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, node->name);  | 
10408  | 0  |                         break;  | 
10409  | 0  |                     }  | 
10410  | 0  |                     ret = xmlRelaxNGValidateDefinition(ctxt, list);  | 
10411  | 0  |                     if (ret == 0) { | 
10412  | 0  |                     }  | 
10413  | 0  |                     break;  | 
10414  | 0  |                 }  | 
10415  |  |  | 
10416  | 0  |                 list = define->content;  | 
10417  | 0  |                 oldflags = ctxt->flags;  | 
10418  | 0  |                 ctxt->flags |= FLAGS_IGNORABLE;  | 
10419  |  | 
  | 
10420  | 0  |                 while (list != NULL) { | 
10421  | 0  |                     oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state);  | 
10422  | 0  |                     ret = xmlRelaxNGValidateDefinition(ctxt, list);  | 
10423  | 0  |                     if (ret == 0) { | 
10424  | 0  |                         if (states == NULL) { | 
10425  | 0  |                             states = xmlRelaxNGNewStates(ctxt, 1);  | 
10426  | 0  |                         }  | 
10427  | 0  |                         if (ctxt->state != NULL) { | 
10428  | 0  |                             xmlRelaxNGAddStates(ctxt, states, ctxt->state);  | 
10429  | 0  |                         } else if (ctxt->states != NULL) { | 
10430  | 0  |                             for (i = 0; i < ctxt->states->nbState; i++) { | 
10431  | 0  |                                 xmlRelaxNGAddStates(ctxt, states,  | 
10432  | 0  |                                                     ctxt->states->  | 
10433  | 0  |                                                     tabState[i]);  | 
10434  | 0  |                             }  | 
10435  | 0  |                             xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
10436  | 0  |                             ctxt->states = NULL;  | 
10437  | 0  |                         }  | 
10438  | 0  |                     } else { | 
10439  | 0  |                         xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10440  | 0  |                     }  | 
10441  | 0  |                     ctxt->state = oldstate;  | 
10442  | 0  |                     list = list->next;  | 
10443  | 0  |                 }  | 
10444  | 0  |                 if (states != NULL) { | 
10445  | 0  |                     xmlRelaxNGFreeValidState(ctxt, oldstate);  | 
10446  | 0  |                     ctxt->states = states;  | 
10447  | 0  |                     ctxt->state = NULL;  | 
10448  | 0  |                     ret = 0;  | 
10449  | 0  |                 } else { | 
10450  | 0  |                     ctxt->states = NULL;  | 
10451  | 0  |                 }  | 
10452  | 0  |                 ctxt->flags = oldflags;  | 
10453  | 0  |                 if (ret != 0) { | 
10454  | 0  |                     if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { | 
10455  | 0  |                         xmlRelaxNGDumpValidError(ctxt);  | 
10456  | 0  |                     }  | 
10457  | 0  |                 } else { | 
10458  | 0  |                     if (ctxt->errNr > errNr)  | 
10459  | 0  |                         xmlRelaxNGPopErrors(ctxt, errNr);  | 
10460  | 0  |                 }  | 
10461  | 0  |                 break;  | 
10462  | 0  |             }  | 
10463  | 0  |         case XML_RELAXNG_DEF:  | 
10464  | 0  |         case XML_RELAXNG_GROUP:  | 
10465  | 0  |             ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content);  | 
10466  | 0  |             break;  | 
10467  | 0  |         case XML_RELAXNG_INTERLEAVE:  | 
10468  | 0  |             ret = xmlRelaxNGValidateInterleave(ctxt, define);  | 
10469  | 0  |             break;  | 
10470  | 0  |         case XML_RELAXNG_ATTRIBUTE:  | 
10471  | 0  |             ret = xmlRelaxNGValidateAttribute(ctxt, define);  | 
10472  | 0  |             break;  | 
10473  | 0  |         case XML_RELAXNG_START:  | 
10474  | 0  |         case XML_RELAXNG_NOOP:  | 
10475  | 0  |         case XML_RELAXNG_REF:  | 
10476  | 0  |         case XML_RELAXNG_EXTERNALREF:  | 
10477  | 0  |         case XML_RELAXNG_PARENTREF:  | 
10478  | 0  |             ret = xmlRelaxNGValidateDefinition(ctxt, define->content);  | 
10479  | 0  |             break;  | 
10480  | 0  |         case XML_RELAXNG_DATATYPE:{ | 
10481  | 0  |                 xmlNodePtr child;  | 
10482  | 0  |                 xmlChar *content = NULL;  | 
10483  |  | 
  | 
10484  | 0  |                 child = node;  | 
10485  | 0  |                 while (child != NULL) { | 
10486  | 0  |                     if (child->type == XML_ELEMENT_NODE) { | 
10487  | 0  |                         VALID_ERR2(XML_RELAXNG_ERR_DATAELEM,  | 
10488  | 0  |                                    node->parent->name);  | 
10489  | 0  |                         ret = -1;  | 
10490  | 0  |                         break;  | 
10491  | 0  |                     } else if ((child->type == XML_TEXT_NODE) ||  | 
10492  | 0  |                                (child->type == XML_CDATA_SECTION_NODE)) { | 
10493  | 0  |                         content = xmlStrcat(content, child->content);  | 
10494  | 0  |                     }  | 
10495  |  |                     /* TODO: handle entities ... */  | 
10496  | 0  |                     child = child->next;  | 
10497  | 0  |                 }  | 
10498  | 0  |                 if (ret == -1) { | 
10499  | 0  |                     if (content != NULL)  | 
10500  | 0  |                         xmlFree(content);  | 
10501  | 0  |                     break;  | 
10502  | 0  |                 }  | 
10503  | 0  |                 if (content == NULL) { | 
10504  | 0  |                     content = xmlStrdup(BAD_CAST "");  | 
10505  | 0  |                     if (content == NULL) { | 
10506  | 0  |                         xmlRngVErrMemory(ctxt, "validating\n");  | 
10507  | 0  |                         ret = -1;  | 
10508  | 0  |                         break;  | 
10509  | 0  |                     }  | 
10510  | 0  |                 }  | 
10511  | 0  |                 ret = xmlRelaxNGValidateDatatype(ctxt, content, define,  | 
10512  | 0  |                                                  ctxt->state->seq);  | 
10513  | 0  |                 if (ret == -1) { | 
10514  | 0  |                     VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name);  | 
10515  | 0  |                 } else if (ret == 0) { | 
10516  | 0  |                     ctxt->state->seq = NULL;  | 
10517  | 0  |                 }  | 
10518  | 0  |                 if (content != NULL)  | 
10519  | 0  |                     xmlFree(content);  | 
10520  | 0  |                 break;  | 
10521  | 0  |             }  | 
10522  | 0  |         case XML_RELAXNG_VALUE:{ | 
10523  | 0  |                 xmlChar *content = NULL;  | 
10524  | 0  |                 xmlChar *oldvalue;  | 
10525  | 0  |                 xmlNodePtr child;  | 
10526  |  | 
  | 
10527  | 0  |                 child = node;  | 
10528  | 0  |                 while (child != NULL) { | 
10529  | 0  |                     if (child->type == XML_ELEMENT_NODE) { | 
10530  | 0  |                         VALID_ERR2(XML_RELAXNG_ERR_VALELEM,  | 
10531  | 0  |                                    node->parent->name);  | 
10532  | 0  |                         ret = -1;  | 
10533  | 0  |                         break;  | 
10534  | 0  |                     } else if ((child->type == XML_TEXT_NODE) ||  | 
10535  | 0  |                                (child->type == XML_CDATA_SECTION_NODE)) { | 
10536  | 0  |                         content = xmlStrcat(content, child->content);  | 
10537  | 0  |                     }  | 
10538  |  |                     /* TODO: handle entities ... */  | 
10539  | 0  |                     child = child->next;  | 
10540  | 0  |                 }  | 
10541  | 0  |                 if (ret == -1) { | 
10542  | 0  |                     if (content != NULL)  | 
10543  | 0  |                         xmlFree(content);  | 
10544  | 0  |                     break;  | 
10545  | 0  |                 }  | 
10546  | 0  |                 if (content == NULL) { | 
10547  | 0  |                     content = xmlStrdup(BAD_CAST "");  | 
10548  | 0  |                     if (content == NULL) { | 
10549  | 0  |                         xmlRngVErrMemory(ctxt, "validating\n");  | 
10550  | 0  |                         ret = -1;  | 
10551  | 0  |                         break;  | 
10552  | 0  |                     }  | 
10553  | 0  |                 }  | 
10554  | 0  |                 oldvalue = ctxt->state->value;  | 
10555  | 0  |                 ctxt->state->value = content;  | 
10556  | 0  |                 ret = xmlRelaxNGValidateValue(ctxt, define);  | 
10557  | 0  |                 ctxt->state->value = oldvalue;  | 
10558  | 0  |                 if (ret == -1) { | 
10559  | 0  |                     VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name);  | 
10560  | 0  |                 } else if (ret == 0) { | 
10561  | 0  |                     ctxt->state->seq = NULL;  | 
10562  | 0  |                 }  | 
10563  | 0  |                 if (content != NULL)  | 
10564  | 0  |                     xmlFree(content);  | 
10565  | 0  |                 break;  | 
10566  | 0  |             }  | 
10567  | 0  |         case XML_RELAXNG_LIST:{ | 
10568  | 0  |                 xmlChar *content;  | 
10569  | 0  |                 xmlNodePtr child;  | 
10570  | 0  |                 xmlChar *oldvalue, *oldendvalue;  | 
10571  | 0  |                 int len;  | 
10572  |  |  | 
10573  |  |                 /*  | 
10574  |  |                  * Make sure it's only text nodes  | 
10575  |  |                  */  | 
10576  |  | 
  | 
10577  | 0  |                 content = NULL;  | 
10578  | 0  |                 child = node;  | 
10579  | 0  |                 while (child != NULL) { | 
10580  | 0  |                     if (child->type == XML_ELEMENT_NODE) { | 
10581  | 0  |                         VALID_ERR2(XML_RELAXNG_ERR_LISTELEM,  | 
10582  | 0  |                                    node->parent->name);  | 
10583  | 0  |                         ret = -1;  | 
10584  | 0  |                         break;  | 
10585  | 0  |                     } else if ((child->type == XML_TEXT_NODE) ||  | 
10586  | 0  |                                (child->type == XML_CDATA_SECTION_NODE)) { | 
10587  | 0  |                         content = xmlStrcat(content, child->content);  | 
10588  | 0  |                     }  | 
10589  |  |                     /* TODO: handle entities ... */  | 
10590  | 0  |                     child = child->next;  | 
10591  | 0  |                 }  | 
10592  | 0  |                 if (ret == -1) { | 
10593  | 0  |                     if (content != NULL)  | 
10594  | 0  |                         xmlFree(content);  | 
10595  | 0  |                     break;  | 
10596  | 0  |                 }  | 
10597  | 0  |                 if (content == NULL) { | 
10598  | 0  |                     content = xmlStrdup(BAD_CAST "");  | 
10599  | 0  |                     if (content == NULL) { | 
10600  | 0  |                         xmlRngVErrMemory(ctxt, "validating\n");  | 
10601  | 0  |                         ret = -1;  | 
10602  | 0  |                         break;  | 
10603  | 0  |                     }  | 
10604  | 0  |                 }  | 
10605  | 0  |                 len = xmlStrlen(content);  | 
10606  | 0  |                 oldvalue = ctxt->state->value;  | 
10607  | 0  |                 oldendvalue = ctxt->state->endvalue;  | 
10608  | 0  |                 ctxt->state->value = content;  | 
10609  | 0  |                 ctxt->state->endvalue = content + len;  | 
10610  | 0  |                 ret = xmlRelaxNGValidateValue(ctxt, define);  | 
10611  | 0  |                 ctxt->state->value = oldvalue;  | 
10612  | 0  |                 ctxt->state->endvalue = oldendvalue;  | 
10613  | 0  |                 if (ret == -1) { | 
10614  | 0  |                     VALID_ERR(XML_RELAXNG_ERR_LIST);  | 
10615  | 0  |                 } else if ((ret == 0) && (node != NULL)) { | 
10616  | 0  |                     ctxt->state->seq = node->next;  | 
10617  | 0  |                 }  | 
10618  | 0  |                 if (content != NULL)  | 
10619  | 0  |                     xmlFree(content);  | 
10620  | 0  |                 break;  | 
10621  | 0  |             }  | 
10622  | 0  |         case XML_RELAXNG_EXCEPT:  | 
10623  | 0  |         case XML_RELAXNG_PARAM:  | 
10624  | 0  |             TODO ret = -1;  | 
10625  | 0  |             break;  | 
10626  | 0  |     }  | 
10627  | 0  |     ctxt->depth--;  | 
10628  |  | #ifdef DEBUG  | 
10629  |  |     for (i = 0; i < ctxt->depth; i++)  | 
10630  |  |         xmlGenericError(xmlGenericErrorContext, " ");  | 
10631  |  |     xmlGenericError(xmlGenericErrorContext,  | 
10632  |  |                     "Validating %s ", xmlRelaxNGDefName(define));  | 
10633  |  |     if (define->name != NULL)  | 
10634  |  |         xmlGenericError(xmlGenericErrorContext, "%s ", define->name);  | 
10635  |  |     if (ret == 0)  | 
10636  |  |         xmlGenericError(xmlGenericErrorContext, "succeeded\n");  | 
10637  |  |     else  | 
10638  |  |         xmlGenericError(xmlGenericErrorContext, "failed\n");  | 
10639  |  | #endif  | 
10640  | 0  |     return (ret);  | 
10641  | 0  | }  | 
10642  |  |  | 
10643  |  | /**  | 
10644  |  |  * xmlRelaxNGValidateDefinition:  | 
10645  |  |  * @ctxt:  a Relax-NG validation context  | 
10646  |  |  * @define:  the definition to verify  | 
10647  |  |  *  | 
10648  |  |  * Validate the current node lists against the definition  | 
10649  |  |  *  | 
10650  |  |  * Returns 0 if the validation succeeded or an error code.  | 
10651  |  |  */  | 
10652  |  | static int  | 
10653  |  | xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,  | 
10654  |  |                              xmlRelaxNGDefinePtr define)  | 
10655  | 0  | { | 
10656  | 0  |     xmlRelaxNGStatesPtr states, res;  | 
10657  | 0  |     int i, j, k, ret, oldflags;  | 
10658  |  |  | 
10659  |  |     /*  | 
10660  |  |      * We should NOT have both ctxt->state and ctxt->states  | 
10661  |  |      */  | 
10662  | 0  |     if ((ctxt->state != NULL) && (ctxt->states != NULL)) { | 
10663  | 0  |         TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10664  | 0  |         ctxt->state = NULL;  | 
10665  | 0  |     }  | 
10666  |  | 
  | 
10667  | 0  |     if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) { | 
10668  | 0  |         if (ctxt->states != NULL) { | 
10669  | 0  |             ctxt->state = ctxt->states->tabState[0];  | 
10670  | 0  |             xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
10671  | 0  |             ctxt->states = NULL;  | 
10672  | 0  |         }  | 
10673  | 0  |         ret = xmlRelaxNGValidateState(ctxt, define);  | 
10674  | 0  |         if ((ctxt->state != NULL) && (ctxt->states != NULL)) { | 
10675  | 0  |             TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10676  | 0  |             ctxt->state = NULL;  | 
10677  | 0  |         }  | 
10678  | 0  |         if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) { | 
10679  | 0  |             ctxt->state = ctxt->states->tabState[0];  | 
10680  | 0  |             xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
10681  | 0  |             ctxt->states = NULL;  | 
10682  | 0  |         }  | 
10683  | 0  |         return (ret);  | 
10684  | 0  |     }  | 
10685  |  |  | 
10686  | 0  |     states = ctxt->states;  | 
10687  | 0  |     ctxt->states = NULL;  | 
10688  | 0  |     res = NULL;  | 
10689  | 0  |     j = 0;  | 
10690  | 0  |     oldflags = ctxt->flags;  | 
10691  | 0  |     ctxt->flags |= FLAGS_IGNORABLE;  | 
10692  | 0  |     for (i = 0; i < states->nbState; i++) { | 
10693  | 0  |         ctxt->state = states->tabState[i];  | 
10694  | 0  |         ctxt->states = NULL;  | 
10695  | 0  |         ret = xmlRelaxNGValidateState(ctxt, define);  | 
10696  |  |         /*  | 
10697  |  |          * We should NOT have both ctxt->state and ctxt->states  | 
10698  |  |          */  | 
10699  | 0  |         if ((ctxt->state != NULL) && (ctxt->states != NULL)) { | 
10700  | 0  |             TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10701  | 0  |             ctxt->state = NULL;  | 
10702  | 0  |         }  | 
10703  | 0  |         if (ret == 0) { | 
10704  | 0  |             if (ctxt->states == NULL) { | 
10705  | 0  |                 if (res != NULL) { | 
10706  |  |                     /* add the state to the container */  | 
10707  | 0  |                     xmlRelaxNGAddStates(ctxt, res, ctxt->state);  | 
10708  | 0  |                     ctxt->state = NULL;  | 
10709  | 0  |                 } else { | 
10710  |  |                     /* add the state directly in states */  | 
10711  | 0  |                     states->tabState[j++] = ctxt->state;  | 
10712  | 0  |                     ctxt->state = NULL;  | 
10713  | 0  |                 }  | 
10714  | 0  |             } else { | 
10715  | 0  |                 if (res == NULL) { | 
10716  |  |                     /* make it the new container and copy other results */  | 
10717  | 0  |                     res = ctxt->states;  | 
10718  | 0  |                     ctxt->states = NULL;  | 
10719  | 0  |                     for (k = 0; k < j; k++)  | 
10720  | 0  |                         xmlRelaxNGAddStates(ctxt, res,  | 
10721  | 0  |                                             states->tabState[k]);  | 
10722  | 0  |                 } else { | 
10723  |  |                     /* add all the new results to res and reff the container */  | 
10724  | 0  |                     for (k = 0; k < ctxt->states->nbState; k++)  | 
10725  | 0  |                         xmlRelaxNGAddStates(ctxt, res,  | 
10726  | 0  |                                             ctxt->states->tabState[k]);  | 
10727  | 0  |                     xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
10728  | 0  |                     ctxt->states = NULL;  | 
10729  | 0  |                 }  | 
10730  | 0  |             }  | 
10731  | 0  |         } else { | 
10732  | 0  |             if (ctxt->state != NULL) { | 
10733  | 0  |                 xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10734  | 0  |                 ctxt->state = NULL;  | 
10735  | 0  |             } else if (ctxt->states != NULL) { | 
10736  | 0  |                 for (k = 0; k < ctxt->states->nbState; k++)  | 
10737  | 0  |                     xmlRelaxNGFreeValidState(ctxt,  | 
10738  | 0  |                                              ctxt->states->tabState[k]);  | 
10739  | 0  |                 xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
10740  | 0  |                 ctxt->states = NULL;  | 
10741  | 0  |             }  | 
10742  | 0  |         }  | 
10743  | 0  |     }  | 
10744  | 0  |     ctxt->flags = oldflags;  | 
10745  | 0  |     if (res != NULL) { | 
10746  | 0  |         xmlRelaxNGFreeStates(ctxt, states);  | 
10747  | 0  |         ctxt->states = res;  | 
10748  | 0  |         ret = 0;  | 
10749  | 0  |     } else if (j > 1) { | 
10750  | 0  |         states->nbState = j;  | 
10751  | 0  |         ctxt->states = states;  | 
10752  | 0  |         ret = 0;  | 
10753  | 0  |     } else if (j == 1) { | 
10754  | 0  |         ctxt->state = states->tabState[0];  | 
10755  | 0  |         xmlRelaxNGFreeStates(ctxt, states);  | 
10756  | 0  |         ret = 0;  | 
10757  | 0  |     } else { | 
10758  | 0  |         ret = -1;  | 
10759  | 0  |         xmlRelaxNGFreeStates(ctxt, states);  | 
10760  | 0  |         if (ctxt->states != NULL) { | 
10761  | 0  |             xmlRelaxNGFreeStates(ctxt, ctxt->states);  | 
10762  | 0  |             ctxt->states = NULL;  | 
10763  | 0  |         }  | 
10764  | 0  |     }  | 
10765  | 0  |     if ((ctxt->state != NULL) && (ctxt->states != NULL)) { | 
10766  | 0  |         TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10767  | 0  |         ctxt->state = NULL;  | 
10768  | 0  |     }  | 
10769  | 0  |     return (ret);  | 
10770  | 0  | }  | 
10771  |  |  | 
10772  |  | /**  | 
10773  |  |  * xmlRelaxNGValidateDocument:  | 
10774  |  |  * @ctxt:  a Relax-NG validation context  | 
10775  |  |  * @doc:  the document  | 
10776  |  |  *  | 
10777  |  |  * Validate the given document  | 
10778  |  |  *  | 
10779  |  |  * Returns 0 if the validation succeeded or an error code.  | 
10780  |  |  */  | 
10781  |  | static int  | 
10782  |  | xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)  | 
10783  | 0  | { | 
10784  | 0  |     int ret;  | 
10785  | 0  |     xmlRelaxNGPtr schema;  | 
10786  | 0  |     xmlRelaxNGGrammarPtr grammar;  | 
10787  | 0  |     xmlRelaxNGValidStatePtr state;  | 
10788  | 0  |     xmlNodePtr node;  | 
10789  |  | 
  | 
10790  | 0  |     if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL))  | 
10791  | 0  |         return (-1);  | 
10792  |  |  | 
10793  | 0  |     ctxt->errNo = XML_RELAXNG_OK;  | 
10794  | 0  |     schema = ctxt->schema;  | 
10795  | 0  |     grammar = schema->topgrammar;  | 
10796  | 0  |     if (grammar == NULL) { | 
10797  | 0  |         VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR);  | 
10798  | 0  |         return (-1);  | 
10799  | 0  |     }  | 
10800  | 0  |     state = xmlRelaxNGNewValidState(ctxt, NULL);  | 
10801  | 0  |     ctxt->state = state;  | 
10802  | 0  |     ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start);  | 
10803  | 0  |     if ((ctxt->state != NULL) && (state->seq != NULL)) { | 
10804  | 0  |         state = ctxt->state;  | 
10805  | 0  |         node = state->seq;  | 
10806  | 0  |         node = xmlRelaxNGSkipIgnored(ctxt, node);  | 
10807  | 0  |         if (node != NULL) { | 
10808  | 0  |             if (ret != -1) { | 
10809  | 0  |                 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);  | 
10810  | 0  |                 ret = -1;  | 
10811  | 0  |             }  | 
10812  | 0  |         }  | 
10813  | 0  |     } else if (ctxt->states != NULL) { | 
10814  | 0  |         int i;  | 
10815  | 0  |         int tmp = -1;  | 
10816  |  | 
  | 
10817  | 0  |         for (i = 0; i < ctxt->states->nbState; i++) { | 
10818  | 0  |             state = ctxt->states->tabState[i];  | 
10819  | 0  |             node = state->seq;  | 
10820  | 0  |             node = xmlRelaxNGSkipIgnored(ctxt, node);  | 
10821  | 0  |             if (node == NULL)  | 
10822  | 0  |                 tmp = 0;  | 
10823  | 0  |             xmlRelaxNGFreeValidState(ctxt, state);  | 
10824  | 0  |         }  | 
10825  | 0  |         if (tmp == -1) { | 
10826  | 0  |             if (ret != -1) { | 
10827  | 0  |                 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA);  | 
10828  | 0  |                 ret = -1;  | 
10829  | 0  |             }  | 
10830  | 0  |         }  | 
10831  | 0  |     }  | 
10832  | 0  |     if (ctxt->state != NULL) { | 
10833  | 0  |         xmlRelaxNGFreeValidState(ctxt, ctxt->state);  | 
10834  | 0  |         ctxt->state = NULL;  | 
10835  | 0  |     }  | 
10836  | 0  |     if (ret != 0)  | 
10837  | 0  |         xmlRelaxNGDumpValidError(ctxt);  | 
10838  |  | #ifdef DEBUG  | 
10839  |  |     else if (ctxt->errNr != 0) { | 
10840  |  |         ctxt->error(ctxt->userData,  | 
10841  |  |                     "%d Extra error messages left on stack !\n",  | 
10842  |  |                     ctxt->errNr);  | 
10843  |  |         xmlRelaxNGDumpValidError(ctxt);  | 
10844  |  |     }  | 
10845  |  | #endif  | 
10846  | 0  | #ifdef LIBXML_VALID_ENABLED  | 
10847  | 0  |     if (ctxt->idref == 1) { | 
10848  | 0  |         xmlValidCtxt vctxt;  | 
10849  |  | 
  | 
10850  | 0  |         memset(&vctxt, 0, sizeof(xmlValidCtxt));  | 
10851  | 0  |         vctxt.valid = 1;  | 
10852  | 0  |         vctxt.error = ctxt->error;  | 
10853  | 0  |         vctxt.warning = ctxt->warning;  | 
10854  | 0  |         vctxt.userData = ctxt->userData;  | 
10855  |  | 
  | 
10856  | 0  |         if (xmlValidateDocumentFinal(&vctxt, doc) != 1)  | 
10857  | 0  |             ret = -1;  | 
10858  | 0  |     }  | 
10859  | 0  | #endif /* LIBXML_VALID_ENABLED */  | 
10860  | 0  |     if ((ret == 0) && (ctxt->errNo != XML_RELAXNG_OK))  | 
10861  | 0  |         ret = -1;  | 
10862  |  | 
  | 
10863  | 0  |     return (ret);  | 
10864  | 0  | }  | 
10865  |  |  | 
10866  |  | /**  | 
10867  |  |  * xmlRelaxNGCleanPSVI:  | 
10868  |  |  * @node:  an input element or document  | 
10869  |  |  *  | 
10870  |  |  * Call this routine to speed up XPath computation on static documents.  | 
10871  |  |  * This stamps all the element nodes with the document order  | 
10872  |  |  * Like for line information, the order is kept in the element->content  | 
10873  |  |  * field, the value stored is actually - the node number (starting at -1)  | 
10874  |  |  * to be able to differentiate from line numbers.  | 
10875  |  |  *  | 
10876  |  |  * Returns the number of elements found in the document or -1 in case  | 
10877  |  |  *    of error.  | 
10878  |  |  */  | 
10879  |  | static void  | 
10880  | 0  | xmlRelaxNGCleanPSVI(xmlNodePtr node) { | 
10881  | 0  |     xmlNodePtr cur;  | 
10882  |  | 
  | 
10883  | 0  |     if ((node == NULL) ||  | 
10884  | 0  |         ((node->type != XML_ELEMENT_NODE) &&  | 
10885  | 0  |          (node->type != XML_DOCUMENT_NODE) &&  | 
10886  | 0  |          (node->type != XML_HTML_DOCUMENT_NODE)))  | 
10887  | 0  |   return;  | 
10888  | 0  |     if (node->type == XML_ELEMENT_NODE)  | 
10889  | 0  |         node->psvi = NULL;  | 
10890  |  | 
  | 
10891  | 0  |     cur = node->children;  | 
10892  | 0  |     while (cur != NULL) { | 
10893  | 0  |   if (cur->type == XML_ELEMENT_NODE) { | 
10894  | 0  |       cur->psvi = NULL;  | 
10895  | 0  |       if (cur->children != NULL) { | 
10896  | 0  |     cur = cur->children;  | 
10897  | 0  |     continue;  | 
10898  | 0  |       }  | 
10899  | 0  |   }  | 
10900  | 0  |   if (cur->next != NULL) { | 
10901  | 0  |       cur = cur->next;  | 
10902  | 0  |       continue;  | 
10903  | 0  |   }  | 
10904  | 0  |   do { | 
10905  | 0  |       cur = cur->parent;  | 
10906  | 0  |       if (cur == NULL)  | 
10907  | 0  |     break;  | 
10908  | 0  |       if (cur == node) { | 
10909  | 0  |     cur = NULL;  | 
10910  | 0  |     break;  | 
10911  | 0  |       }  | 
10912  | 0  |       if (cur->next != NULL) { | 
10913  | 0  |     cur = cur->next;  | 
10914  | 0  |     break;  | 
10915  | 0  |       }  | 
10916  | 0  |   } while (cur != NULL);  | 
10917  | 0  |     }  | 
10918  | 0  |     return;  | 
10919  | 0  | }  | 
10920  |  | /************************************************************************  | 
10921  |  |  *                  *  | 
10922  |  |  *      Validation interfaces       *  | 
10923  |  |  *                  *  | 
10924  |  |  ************************************************************************/  | 
10925  |  |  | 
10926  |  | /**  | 
10927  |  |  * xmlRelaxNGNewValidCtxt:  | 
10928  |  |  * @schema:  a precompiled XML RelaxNGs  | 
10929  |  |  *  | 
10930  |  |  * Create an XML RelaxNGs validation context based on the given schema  | 
10931  |  |  *  | 
10932  |  |  * Returns the validation context or NULL in case of error  | 
10933  |  |  */  | 
10934  |  | xmlRelaxNGValidCtxtPtr  | 
10935  |  | xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema)  | 
10936  | 0  | { | 
10937  | 0  |     xmlRelaxNGValidCtxtPtr ret;  | 
10938  |  | 
  | 
10939  | 0  |     ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt));  | 
10940  | 0  |     if (ret == NULL) { | 
10941  | 0  |         xmlRngVErrMemory(NULL, "building context\n");  | 
10942  | 0  |         return (NULL);  | 
10943  | 0  |     }  | 
10944  | 0  |     memset(ret, 0, sizeof(xmlRelaxNGValidCtxt));  | 
10945  | 0  |     ret->schema = schema;  | 
10946  | 0  |     ret->error = xmlGenericError;  | 
10947  | 0  |     ret->userData = xmlGenericErrorContext;  | 
10948  | 0  |     ret->errNr = 0;  | 
10949  | 0  |     ret->errMax = 0;  | 
10950  | 0  |     ret->err = NULL;  | 
10951  | 0  |     ret->errTab = NULL;  | 
10952  | 0  |     if (schema != NULL)  | 
10953  | 0  |   ret->idref = schema->idref;  | 
10954  | 0  |     ret->states = NULL;  | 
10955  | 0  |     ret->freeState = NULL;  | 
10956  | 0  |     ret->freeStates = NULL;  | 
10957  | 0  |     ret->errNo = XML_RELAXNG_OK;  | 
10958  | 0  |     return (ret);  | 
10959  | 0  | }  | 
10960  |  |  | 
10961  |  | /**  | 
10962  |  |  * xmlRelaxNGFreeValidCtxt:  | 
10963  |  |  * @ctxt:  the schema validation context  | 
10964  |  |  *  | 
10965  |  |  * Free the resources associated to the schema validation context  | 
10966  |  |  */  | 
10967  |  | void  | 
10968  |  | xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt)  | 
10969  | 0  | { | 
10970  | 0  |     int k;  | 
10971  |  | 
  | 
10972  | 0  |     if (ctxt == NULL)  | 
10973  | 0  |         return;  | 
10974  | 0  |     if (ctxt->states != NULL)  | 
10975  | 0  |         xmlRelaxNGFreeStates(NULL, ctxt->states);  | 
10976  | 0  |     if (ctxt->freeState != NULL) { | 
10977  | 0  |         for (k = 0; k < ctxt->freeState->nbState; k++) { | 
10978  | 0  |             xmlRelaxNGFreeValidState(NULL, ctxt->freeState->tabState[k]);  | 
10979  | 0  |         }  | 
10980  | 0  |         xmlRelaxNGFreeStates(NULL, ctxt->freeState);  | 
10981  | 0  |     }  | 
10982  | 0  |     if (ctxt->freeStates != NULL) { | 
10983  | 0  |         for (k = 0; k < ctxt->freeStatesNr; k++) { | 
10984  | 0  |             xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]);  | 
10985  | 0  |         }  | 
10986  | 0  |         xmlFree(ctxt->freeStates);  | 
10987  | 0  |     }  | 
10988  | 0  |     if (ctxt->errTab != NULL)  | 
10989  | 0  |         xmlFree(ctxt->errTab);  | 
10990  | 0  |     if (ctxt->elemTab != NULL) { | 
10991  | 0  |         xmlRegExecCtxtPtr exec;  | 
10992  |  | 
  | 
10993  | 0  |         exec = xmlRelaxNGElemPop(ctxt);  | 
10994  | 0  |         while (exec != NULL) { | 
10995  | 0  |             xmlRegFreeExecCtxt(exec);  | 
10996  | 0  |             exec = xmlRelaxNGElemPop(ctxt);  | 
10997  | 0  |         }  | 
10998  | 0  |         xmlFree(ctxt->elemTab);  | 
10999  | 0  |     }  | 
11000  | 0  |     xmlFree(ctxt);  | 
11001  | 0  | }  | 
11002  |  |  | 
11003  |  | /**  | 
11004  |  |  * xmlRelaxNGSetValidErrors:  | 
11005  |  |  * @ctxt:  a Relax-NG validation context  | 
11006  |  |  * @err:  the error function  | 
11007  |  |  * @warn: the warning function  | 
11008  |  |  * @ctx: the functions context  | 
11009  |  |  *  | 
11010  |  |  * Set the error and warning callback information  | 
11011  |  |  */  | 
11012  |  | void  | 
11013  |  | xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,  | 
11014  |  |                          xmlRelaxNGValidityErrorFunc err,  | 
11015  |  |                          xmlRelaxNGValidityWarningFunc warn, void *ctx)  | 
11016  | 0  | { | 
11017  | 0  |     if (ctxt == NULL)  | 
11018  | 0  |         return;  | 
11019  | 0  |     ctxt->error = err;  | 
11020  | 0  |     ctxt->warning = warn;  | 
11021  | 0  |     ctxt->userData = ctx;  | 
11022  | 0  |     ctxt->serror = NULL;  | 
11023  | 0  | }  | 
11024  |  |  | 
11025  |  | /**  | 
11026  |  |  * xmlRelaxNGSetValidStructuredErrors:  | 
11027  |  |  * @ctxt:  a Relax-NG validation context  | 
11028  |  |  * @serror:  the structured error function  | 
11029  |  |  * @ctx: the functions context  | 
11030  |  |  *  | 
11031  |  |  * Set the structured error callback  | 
11032  |  |  */  | 
11033  |  | void  | 
11034  |  | xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt,  | 
11035  |  |                                    xmlStructuredErrorFunc serror, void *ctx)  | 
11036  | 0  | { | 
11037  | 0  |     if (ctxt == NULL)  | 
11038  | 0  |         return;  | 
11039  | 0  |     ctxt->serror = serror;  | 
11040  | 0  |     ctxt->error = NULL;  | 
11041  | 0  |     ctxt->warning = NULL;  | 
11042  | 0  |     ctxt->userData = ctx;  | 
11043  | 0  | }  | 
11044  |  |  | 
11045  |  | /**  | 
11046  |  |  * xmlRelaxNGGetValidErrors:  | 
11047  |  |  * @ctxt:  a Relax-NG validation context  | 
11048  |  |  * @err:  the error function result  | 
11049  |  |  * @warn: the warning function result  | 
11050  |  |  * @ctx: the functions context result  | 
11051  |  |  *  | 
11052  |  |  * Get the error and warning callback information  | 
11053  |  |  *  | 
11054  |  |  * Returns -1 in case of error and 0 otherwise  | 
11055  |  |  */  | 
11056  |  | int  | 
11057  |  | xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt,  | 
11058  |  |                          xmlRelaxNGValidityErrorFunc * err,  | 
11059  |  |                          xmlRelaxNGValidityWarningFunc * warn, void **ctx)  | 
11060  | 0  | { | 
11061  | 0  |     if (ctxt == NULL)  | 
11062  | 0  |         return (-1);  | 
11063  | 0  |     if (err != NULL)  | 
11064  | 0  |         *err = ctxt->error;  | 
11065  | 0  |     if (warn != NULL)  | 
11066  | 0  |         *warn = ctxt->warning;  | 
11067  | 0  |     if (ctx != NULL)  | 
11068  | 0  |         *ctx = ctxt->userData;  | 
11069  | 0  |     return (0);  | 
11070  | 0  | }  | 
11071  |  |  | 
11072  |  | /**  | 
11073  |  |  * xmlRelaxNGValidateDoc:  | 
11074  |  |  * @ctxt:  a Relax-NG validation context  | 
11075  |  |  * @doc:  a parsed document tree  | 
11076  |  |  *  | 
11077  |  |  * Validate a document tree in memory.  | 
11078  |  |  *  | 
11079  |  |  * Returns 0 if the document is valid, a positive error code  | 
11080  |  |  *     number otherwise and -1 in case of internal or API error.  | 
11081  |  |  */  | 
11082  |  | int  | 
11083  |  | xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc)  | 
11084  | 0  | { | 
11085  | 0  |     int ret;  | 
11086  |  | 
  | 
11087  | 0  |     if ((ctxt == NULL) || (doc == NULL))  | 
11088  | 0  |         return (-1);  | 
11089  |  |  | 
11090  | 0  |     ctxt->doc = doc;  | 
11091  |  | 
  | 
11092  | 0  |     ret = xmlRelaxNGValidateDocument(ctxt, doc);  | 
11093  |  |     /*  | 
11094  |  |      * Remove all left PSVI  | 
11095  |  |      */  | 
11096  | 0  |     xmlRelaxNGCleanPSVI((xmlNodePtr) doc);  | 
11097  |  |  | 
11098  |  |     /*  | 
11099  |  |      * TODO: build error codes  | 
11100  |  |      */  | 
11101  | 0  |     if (ret == -1)  | 
11102  | 0  |         return (1);  | 
11103  | 0  |     return (ret);  | 
11104  | 0  | }  | 
11105  |  |  | 
11106  |  | #endif /* LIBXML_SCHEMAS_ENABLED */  |