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