Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrelaxng.c
Go to the documentation of this file.
00001 /* 00002 * relaxng.c : implementation of the Relax-NG handling and validity checking 00003 * 00004 * See Copyright for the status of this software. 00005 * 00006 * Daniel Veillard <veillard@redhat.com> 00007 */ 00008 00016 #define IN_LIBXML 00017 #include "libxml.h" 00018 00019 #ifdef LIBXML_SCHEMAS_ENABLED 00020 00021 #include <string.h> 00022 #include <stdio.h> 00023 #include <libxml/xmlmemory.h> 00024 #include <libxml/parser.h> 00025 #include <libxml/parserInternals.h> 00026 #include <libxml/hash.h> 00027 #include <libxml/uri.h> 00028 00029 #include <libxml/relaxng.h> 00030 00031 #include <libxml/xmlschemastypes.h> 00032 #include <libxml/xmlautomata.h> 00033 #include <libxml/xmlregexp.h> 00034 #include <libxml/xmlschemastypes.h> 00035 00036 /* 00037 * The Relax-NG namespace 00038 */ 00039 static const xmlChar *xmlRelaxNGNs = (const xmlChar *) 00040 "http://relaxng.org/ns/structure/1.0"; 00041 00042 #define IS_RELAXNG(node, type) \ 00043 ((node != NULL) && (node->ns != NULL) && \ 00044 (xmlStrEqual(node->name, (const xmlChar *) type)) && \ 00045 (xmlStrEqual(node->ns->href, xmlRelaxNGNs))) 00046 00047 00048 #if 0 00049 #define DEBUG 1 00050 00051 #define DEBUG_GRAMMAR 1 00052 00053 #define DEBUG_CONTENT 1 00054 00055 #define DEBUG_TYPE 1 00056 00057 #define DEBUG_VALID 1 00058 00059 #define DEBUG_INTERLEAVE 1 00060 00061 #define DEBUG_LIST 1 00062 00063 #define DEBUG_INCLUDE 1 00064 00065 #define DEBUG_ERROR 1 00066 00067 #define DEBUG_COMPILE 1 00068 00069 #define DEBUG_PROGRESSIVE 1 00070 #endif 00071 00072 #define MAX_ERROR 5 00073 00074 #define TODO \ 00075 xmlGenericError(xmlGenericErrorContext, \ 00076 "Unimplemented block at %s:%d\n", \ 00077 __FILE__, __LINE__); 00078 00079 typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema; 00080 typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr; 00081 00082 typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine; 00083 typedef xmlRelaxNGDefine *xmlRelaxNGDefinePtr; 00084 00085 typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument; 00086 typedef xmlRelaxNGDocument *xmlRelaxNGDocumentPtr; 00087 00088 typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude; 00089 typedef xmlRelaxNGInclude *xmlRelaxNGIncludePtr; 00090 00091 typedef enum { 00092 XML_RELAXNG_COMBINE_UNDEFINED = 0, /* undefined */ 00093 XML_RELAXNG_COMBINE_CHOICE, /* choice */ 00094 XML_RELAXNG_COMBINE_INTERLEAVE /* interleave */ 00095 } xmlRelaxNGCombine; 00096 00097 typedef enum { 00098 XML_RELAXNG_CONTENT_ERROR = -1, 00099 XML_RELAXNG_CONTENT_EMPTY = 0, 00100 XML_RELAXNG_CONTENT_SIMPLE, 00101 XML_RELAXNG_CONTENT_COMPLEX 00102 } xmlRelaxNGContentType; 00103 00104 typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar; 00105 typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr; 00106 00107 struct _xmlRelaxNGGrammar { 00108 xmlRelaxNGGrammarPtr parent; /* the parent grammar if any */ 00109 xmlRelaxNGGrammarPtr children; /* the children grammar if any */ 00110 xmlRelaxNGGrammarPtr next; /* the next grammar if any */ 00111 xmlRelaxNGDefinePtr start; /* <start> content */ 00112 xmlRelaxNGCombine combine; /* the default combine value */ 00113 xmlRelaxNGDefinePtr startList; /* list of <start> definitions */ 00114 xmlHashTablePtr defs; /* define* */ 00115 xmlHashTablePtr refs; /* references */ 00116 }; 00117 00118 00119 typedef enum { 00120 XML_RELAXNG_NOOP = -1, /* a no operation from simplification */ 00121 XML_RELAXNG_EMPTY = 0, /* an empty pattern */ 00122 XML_RELAXNG_NOT_ALLOWED, /* not allowed top */ 00123 XML_RELAXNG_EXCEPT, /* except present in nameclass defs */ 00124 XML_RELAXNG_TEXT, /* textual content */ 00125 XML_RELAXNG_ELEMENT, /* an element */ 00126 XML_RELAXNG_DATATYPE, /* extenal data type definition */ 00127 XML_RELAXNG_PARAM, /* extenal data type parameter */ 00128 XML_RELAXNG_VALUE, /* value from an extenal data type definition */ 00129 XML_RELAXNG_LIST, /* a list of patterns */ 00130 XML_RELAXNG_ATTRIBUTE, /* an attrbute following a pattern */ 00131 XML_RELAXNG_DEF, /* a definition */ 00132 XML_RELAXNG_REF, /* reference to a definition */ 00133 XML_RELAXNG_EXTERNALREF, /* reference to an external def */ 00134 XML_RELAXNG_PARENTREF, /* reference to a def in the parent grammar */ 00135 XML_RELAXNG_OPTIONAL, /* optional patterns */ 00136 XML_RELAXNG_ZEROORMORE, /* zero or more non empty patterns */ 00137 XML_RELAXNG_ONEORMORE, /* one or more non empty patterns */ 00138 XML_RELAXNG_CHOICE, /* a choice between non empty patterns */ 00139 XML_RELAXNG_GROUP, /* a pair/group of non empty patterns */ 00140 XML_RELAXNG_INTERLEAVE, /* interleaving choice of non-empty patterns */ 00141 XML_RELAXNG_START /* Used to keep track of starts on grammars */ 00142 } xmlRelaxNGType; 00143 00144 #define IS_NULLABLE (1 << 0) 00145 #define IS_NOT_NULLABLE (1 << 1) 00146 #define IS_INDETERMINIST (1 << 2) 00147 #define IS_MIXED (1 << 3) 00148 #define IS_TRIABLE (1 << 4) 00149 #define IS_PROCESSED (1 << 5) 00150 #define IS_COMPILABLE (1 << 6) 00151 #define IS_NOT_COMPILABLE (1 << 7) 00152 #define IS_EXTERNAL_REF (1 << 8) 00153 00154 struct _xmlRelaxNGDefine { 00155 xmlRelaxNGType type; /* the type of definition */ 00156 xmlNodePtr node; /* the node in the source */ 00157 xmlChar *name; /* the element local name if present */ 00158 xmlChar *ns; /* the namespace local name if present */ 00159 xmlChar *value; /* value when available */ 00160 void *data; /* data lib or specific pointer */ 00161 xmlRelaxNGDefinePtr content; /* the expected content */ 00162 xmlRelaxNGDefinePtr parent; /* the parent definition, if any */ 00163 xmlRelaxNGDefinePtr next; /* list within grouping sequences */ 00164 xmlRelaxNGDefinePtr attrs; /* list of attributes for elements */ 00165 xmlRelaxNGDefinePtr nameClass; /* the nameClass definition if any */ 00166 xmlRelaxNGDefinePtr nextHash; /* next define in defs/refs hash tables */ 00167 short depth; /* used for the cycle detection */ 00168 short dflags; /* define related flags */ 00169 xmlRegexpPtr contModel; /* a compiled content model if available */ 00170 }; 00171 00177 struct _xmlRelaxNG { 00178 void *_private; /* unused by the library for users or bindings */ 00179 xmlRelaxNGGrammarPtr topgrammar; 00180 xmlDocPtr doc; 00181 00182 int idref; /* requires idref checking */ 00183 00184 xmlHashTablePtr defs; /* define */ 00185 xmlHashTablePtr refs; /* references */ 00186 xmlRelaxNGDocumentPtr documents; /* all the documents loaded */ 00187 xmlRelaxNGIncludePtr includes; /* all the includes loaded */ 00188 int defNr; /* number of defines used */ 00189 xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */ 00190 00191 }; 00192 00193 #define XML_RELAXNG_IN_ATTRIBUTE (1 << 0) 00194 #define XML_RELAXNG_IN_ONEORMORE (1 << 1) 00195 #define XML_RELAXNG_IN_LIST (1 << 2) 00196 #define XML_RELAXNG_IN_DATAEXCEPT (1 << 3) 00197 #define XML_RELAXNG_IN_START (1 << 4) 00198 #define XML_RELAXNG_IN_OOMGROUP (1 << 5) 00199 #define XML_RELAXNG_IN_OOMINTERLEAVE (1 << 6) 00200 #define XML_RELAXNG_IN_EXTERNALREF (1 << 7) 00201 #define XML_RELAXNG_IN_ANYEXCEPT (1 << 8) 00202 #define XML_RELAXNG_IN_NSEXCEPT (1 << 9) 00203 00204 struct _xmlRelaxNGParserCtxt { 00205 void *userData; /* user specific data block */ 00206 xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */ 00207 xmlRelaxNGValidityWarningFunc warning; /* the callback in case of warning */ 00208 xmlStructuredErrorFunc serror; 00209 xmlRelaxNGValidErr err; 00210 00211 xmlRelaxNGPtr schema; /* The schema in use */ 00212 xmlRelaxNGGrammarPtr grammar; /* the current grammar */ 00213 xmlRelaxNGGrammarPtr parentgrammar; /* the parent grammar */ 00214 int flags; /* parser flags */ 00215 int nbErrors; /* number of errors at parse time */ 00216 int nbWarnings; /* number of warnings at parse time */ 00217 const xmlChar *define; /* the current define scope */ 00218 xmlRelaxNGDefinePtr def; /* the current define */ 00219 00220 int nbInterleaves; 00221 xmlHashTablePtr interleaves; /* keep track of all the interleaves */ 00222 00223 xmlRelaxNGDocumentPtr documents; /* all the documents loaded */ 00224 xmlRelaxNGIncludePtr includes; /* all the includes loaded */ 00225 xmlChar *URL; 00226 xmlDocPtr document; 00227 00228 int defNr; /* number of defines used */ 00229 int defMax; /* number of defines aloocated */ 00230 xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */ 00231 00232 const char *buffer; 00233 int size; 00234 00235 /* the document stack */ 00236 xmlRelaxNGDocumentPtr doc; /* Current parsed external ref */ 00237 int docNr; /* Depth of the parsing stack */ 00238 int docMax; /* Max depth of the parsing stack */ 00239 xmlRelaxNGDocumentPtr *docTab; /* array of docs */ 00240 00241 /* the include stack */ 00242 xmlRelaxNGIncludePtr inc; /* Current parsed include */ 00243 int incNr; /* Depth of the include parsing stack */ 00244 int incMax; /* Max depth of the parsing stack */ 00245 xmlRelaxNGIncludePtr *incTab; /* array of incs */ 00246 00247 int idref; /* requires idref checking */ 00248 00249 /* used to compile content models */ 00250 xmlAutomataPtr am; /* the automata */ 00251 xmlAutomataStatePtr state; /* used to build the automata */ 00252 00253 int crng; /* compact syntax and other flags */ 00254 int freedoc; /* need to free the document */ 00255 }; 00256 00257 #define FLAGS_IGNORABLE 1 00258 #define FLAGS_NEGATIVE 2 00259 #define FLAGS_MIXED_CONTENT 4 00260 #define FLAGS_NOERROR 8 00261 00267 typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup; 00268 typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr; 00269 struct _xmlRelaxNGInterleaveGroup { 00270 xmlRelaxNGDefinePtr rule; /* the rule to satisfy */ 00271 xmlRelaxNGDefinePtr *defs; /* the array of element definitions */ 00272 xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */ 00273 }; 00274 00275 #define IS_DETERMINIST 1 00276 #define IS_NEEDCHECK 2 00277 00283 typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition; 00284 typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr; 00285 struct _xmlRelaxNGPartition { 00286 int nbgroups; /* number of groups in the partitions */ 00287 xmlHashTablePtr triage; /* hash table used to direct nodes to the 00288 * right group when possible */ 00289 int flags; /* determinist ? */ 00290 xmlRelaxNGInterleaveGroupPtr *groups; 00291 }; 00292 00298 #define MAX_ATTR 20 00299 typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState; 00300 typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr; 00301 struct _xmlRelaxNGValidState { 00302 xmlNodePtr node; /* the current node */ 00303 xmlNodePtr seq; /* the sequence of children left to validate */ 00304 int nbAttrs; /* the number of attributes */ 00305 int maxAttrs; /* the size of attrs */ 00306 int nbAttrLeft; /* the number of attributes left to validate */ 00307 xmlChar *value; /* the value when operating on string */ 00308 xmlChar *endvalue; /* the end value when operating on string */ 00309 xmlAttrPtr *attrs; /* the array of attributes */ 00310 }; 00311 00317 typedef struct _xmlRelaxNGStates xmlRelaxNGStates; 00318 typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr; 00319 struct _xmlRelaxNGStates { 00320 int nbState; /* the number of states */ 00321 int maxState; /* the size of the array */ 00322 xmlRelaxNGValidStatePtr *tabState; 00323 }; 00324 00325 #define ERROR_IS_DUP 1 00326 00332 typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError; 00333 typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr; 00334 struct _xmlRelaxNGValidError { 00335 xmlRelaxNGValidErr err; /* the error number */ 00336 int flags; /* flags */ 00337 xmlNodePtr node; /* the current node */ 00338 xmlNodePtr seq; /* the current child */ 00339 const xmlChar *arg1; /* first arg */ 00340 const xmlChar *arg2; /* second arg */ 00341 }; 00342 00349 struct _xmlRelaxNGValidCtxt { 00350 void *userData; /* user specific data block */ 00351 xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */ 00352 xmlRelaxNGValidityWarningFunc warning; /* the callback in case of warning */ 00353 xmlStructuredErrorFunc serror; 00354 int nbErrors; /* number of errors in validation */ 00355 00356 xmlRelaxNGPtr schema; /* The schema in use */ 00357 xmlDocPtr doc; /* the document being validated */ 00358 int flags; /* validation flags */ 00359 int depth; /* validation depth */ 00360 int idref; /* requires idref checking */ 00361 int errNo; /* the first error found */ 00362 00363 /* 00364 * Errors accumulated in branches may have to be stacked to be 00365 * provided back when it's sure they affect validation. 00366 */ 00367 xmlRelaxNGValidErrorPtr err; /* Last error */ 00368 int errNr; /* Depth of the error stack */ 00369 int errMax; /* Max depth of the error stack */ 00370 xmlRelaxNGValidErrorPtr errTab; /* stack of errors */ 00371 00372 xmlRelaxNGValidStatePtr state; /* the current validation state */ 00373 xmlRelaxNGStatesPtr states; /* the accumulated state list */ 00374 00375 xmlRelaxNGStatesPtr freeState; /* the pool of free valid states */ 00376 int freeStatesNr; 00377 int freeStatesMax; 00378 xmlRelaxNGStatesPtr *freeStates; /* the pool of free state groups */ 00379 00380 /* 00381 * This is used for "progressive" validation 00382 */ 00383 xmlRegExecCtxtPtr elem; /* the current element regexp */ 00384 int elemNr; /* the number of element validated */ 00385 int elemMax; /* the max depth of elements */ 00386 xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */ 00387 int pstate; /* progressive state */ 00388 xmlNodePtr pnode; /* the current node */ 00389 xmlRelaxNGDefinePtr pdef; /* the non-streamable definition */ 00390 int perr; /* signal error in content model 00391 * outside the regexp */ 00392 }; 00393 00399 struct _xmlRelaxNGInclude { 00400 xmlRelaxNGIncludePtr next; /* keep a chain of includes */ 00401 xmlChar *href; /* the normalized href value */ 00402 xmlDocPtr doc; /* the associated XML document */ 00403 xmlRelaxNGDefinePtr content; /* the definitions */ 00404 xmlRelaxNGPtr schema; /* the schema */ 00405 }; 00406 00412 struct _xmlRelaxNGDocument { 00413 xmlRelaxNGDocumentPtr next; /* keep a chain of documents */ 00414 xmlChar *href; /* the normalized href value */ 00415 xmlDocPtr doc; /* the associated XML document */ 00416 xmlRelaxNGDefinePtr content; /* the definitions */ 00417 xmlRelaxNGPtr schema; /* the schema */ 00418 int externalRef; /* 1 if an external ref */ 00419 }; 00420 00421 00422 /************************************************************************ 00423 * * 00424 * Some factorized error routines * 00425 * * 00426 ************************************************************************/ 00427 00435 static void 00436 xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra) 00437 { 00438 xmlStructuredErrorFunc schannel = NULL; 00439 xmlGenericErrorFunc channel = NULL; 00440 void *data = NULL; 00441 00442 if (ctxt != NULL) { 00443 if (ctxt->serror != NULL) 00444 schannel = ctxt->serror; 00445 else 00446 channel = ctxt->error; 00447 data = ctxt->userData; 00448 ctxt->nbErrors++; 00449 } 00450 if (extra) 00451 __xmlRaiseError(schannel, channel, data, 00452 NULL, NULL, XML_FROM_RELAXNGP, 00453 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, 00454 NULL, NULL, 0, 0, 00455 "Memory allocation failed : %s\n", extra); 00456 else 00457 __xmlRaiseError(schannel, channel, data, 00458 NULL, NULL, XML_FROM_RELAXNGP, 00459 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, 00460 NULL, NULL, 0, 0, "Memory allocation failed\n"); 00461 } 00462 00470 static void 00471 xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra) 00472 { 00473 xmlStructuredErrorFunc schannel = NULL; 00474 xmlGenericErrorFunc channel = NULL; 00475 void *data = NULL; 00476 00477 if (ctxt != NULL) { 00478 if (ctxt->serror != NULL) 00479 schannel = ctxt->serror; 00480 else 00481 channel = ctxt->error; 00482 data = ctxt->userData; 00483 ctxt->nbErrors++; 00484 } 00485 if (extra) 00486 __xmlRaiseError(schannel, channel, data, 00487 NULL, NULL, XML_FROM_RELAXNGV, 00488 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra, 00489 NULL, NULL, 0, 0, 00490 "Memory allocation failed : %s\n", extra); 00491 else 00492 __xmlRaiseError(schannel, channel, data, 00493 NULL, NULL, XML_FROM_RELAXNGV, 00494 XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL, 00495 NULL, NULL, 0, 0, "Memory allocation failed\n"); 00496 } 00497 00509 static void 00510 xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error, 00511 const char *msg, const xmlChar * str1, const xmlChar * str2) 00512 { 00513 xmlStructuredErrorFunc schannel = NULL; 00514 xmlGenericErrorFunc channel = NULL; 00515 void *data = NULL; 00516 00517 if (ctxt != NULL) { 00518 if (ctxt->serror != NULL) 00519 schannel = ctxt->serror; 00520 else 00521 channel = ctxt->error; 00522 data = ctxt->userData; 00523 ctxt->nbErrors++; 00524 } 00525 __xmlRaiseError(schannel, channel, data, 00526 NULL, node, XML_FROM_RELAXNGP, 00527 error, XML_ERR_ERROR, NULL, 0, 00528 (const char *) str1, (const char *) str2, NULL, 0, 0, 00529 msg, str1, str2); 00530 } 00531 00543 static void 00544 xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error, 00545 const char *msg, const xmlChar * str1, const xmlChar * str2) 00546 { 00547 xmlStructuredErrorFunc schannel = NULL; 00548 xmlGenericErrorFunc channel = NULL; 00549 void *data = NULL; 00550 00551 if (ctxt != NULL) { 00552 if (ctxt->serror != NULL) 00553 schannel = ctxt->serror; 00554 else 00555 channel = ctxt->error; 00556 data = ctxt->userData; 00557 ctxt->nbErrors++; 00558 } 00559 __xmlRaiseError(schannel, channel, data, 00560 NULL, node, XML_FROM_RELAXNGV, 00561 error, XML_ERR_ERROR, NULL, 0, 00562 (const char *) str1, (const char *) str2, NULL, 0, 0, 00563 msg, str1, str2); 00564 } 00565 00566 /************************************************************************ 00567 * * 00568 * Preliminary type checking interfaces * 00569 * * 00570 ************************************************************************/ 00571 00582 typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar * type); 00583 00595 typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar * type, 00596 const xmlChar * value, void **result, 00597 xmlNodePtr node); 00598 00612 typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar * type, 00613 const xmlChar * facet, 00614 const xmlChar * val, 00615 const xmlChar * strval, void *value); 00616 00624 typedef void (*xmlRelaxNGTypeFree) (void *data, void *result); 00625 00638 typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar * type, 00639 const xmlChar * value1, 00640 xmlNodePtr ctxt1, 00641 void *comp1, 00642 const xmlChar * value2, 00643 xmlNodePtr ctxt2); 00644 typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary; 00645 typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr; 00646 struct _xmlRelaxNGTypeLibrary { 00647 const xmlChar *namespace; /* the datatypeLibrary value */ 00648 void *data; /* data needed for the library */ 00649 xmlRelaxNGTypeHave have; /* the export function */ 00650 xmlRelaxNGTypeCheck check; /* the checking function */ 00651 xmlRelaxNGTypeCompare comp; /* the compare function */ 00652 xmlRelaxNGFacetCheck facet; /* the facet check function */ 00653 xmlRelaxNGTypeFree freef; /* the freeing function */ 00654 }; 00655 00656 /************************************************************************ 00657 * * 00658 * Allocation functions * 00659 * * 00660 ************************************************************************/ 00661 static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar); 00662 static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define); 00663 static void xmlRelaxNGNormExtSpace(xmlChar * value); 00664 static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema); 00665 static int xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt 00666 ATTRIBUTE_UNUSED, 00667 xmlRelaxNGValidStatePtr state1, 00668 xmlRelaxNGValidStatePtr state2); 00669 static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt, 00670 xmlRelaxNGValidStatePtr state); 00671 00678 static void 00679 xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu) 00680 { 00681 if (docu == NULL) 00682 return; 00683 00684 if (docu->href != NULL) 00685 xmlFree(docu->href); 00686 if (docu->doc != NULL) 00687 xmlFreeDoc(docu->doc); 00688 if (docu->schema != NULL) 00689 xmlRelaxNGFreeInnerSchema(docu->schema); 00690 xmlFree(docu); 00691 } 00692 00699 static void 00700 xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu) 00701 { 00702 xmlRelaxNGDocumentPtr next; 00703 00704 while (docu != NULL) { 00705 next = docu->next; 00706 xmlRelaxNGFreeDocument(docu); 00707 docu = next; 00708 } 00709 } 00710 00717 static void 00718 xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl) 00719 { 00720 if (incl == NULL) 00721 return; 00722 00723 if (incl->href != NULL) 00724 xmlFree(incl->href); 00725 if (incl->doc != NULL) 00726 xmlFreeDoc(incl->doc); 00727 if (incl->schema != NULL) 00728 xmlRelaxNGFree(incl->schema); 00729 xmlFree(incl); 00730 } 00731 00738 static void 00739 xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl) 00740 { 00741 xmlRelaxNGIncludePtr next; 00742 00743 while (incl != NULL) { 00744 next = incl->next; 00745 xmlRelaxNGFreeInclude(incl); 00746 incl = next; 00747 } 00748 } 00749 00758 static xmlRelaxNGPtr 00759 xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt) 00760 { 00761 xmlRelaxNGPtr ret; 00762 00763 ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG)); 00764 if (ret == NULL) { 00765 xmlRngPErrMemory(ctxt, NULL); 00766 return (NULL); 00767 } 00768 memset(ret, 0, sizeof(xmlRelaxNG)); 00769 00770 return (ret); 00771 } 00772 00779 static void 00780 xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema) 00781 { 00782 if (schema == NULL) 00783 return; 00784 00785 if (schema->doc != NULL) 00786 xmlFreeDoc(schema->doc); 00787 if (schema->defTab != NULL) { 00788 int i; 00789 00790 for (i = 0; i < schema->defNr; i++) 00791 xmlRelaxNGFreeDefine(schema->defTab[i]); 00792 xmlFree(schema->defTab); 00793 } 00794 00795 xmlFree(schema); 00796 } 00797 00804 void 00805 xmlRelaxNGFree(xmlRelaxNGPtr schema) 00806 { 00807 if (schema == NULL) 00808 return; 00809 00810 if (schema->topgrammar != NULL) 00811 xmlRelaxNGFreeGrammar(schema->topgrammar); 00812 if (schema->doc != NULL) 00813 xmlFreeDoc(schema->doc); 00814 if (schema->documents != NULL) 00815 xmlRelaxNGFreeDocumentList(schema->documents); 00816 if (schema->includes != NULL) 00817 xmlRelaxNGFreeIncludeList(schema->includes); 00818 if (schema->defTab != NULL) { 00819 int i; 00820 00821 for (i = 0; i < schema->defNr; i++) 00822 xmlRelaxNGFreeDefine(schema->defTab[i]); 00823 xmlFree(schema->defTab); 00824 } 00825 00826 xmlFree(schema); 00827 } 00828 00837 static xmlRelaxNGGrammarPtr 00838 xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt) 00839 { 00840 xmlRelaxNGGrammarPtr ret; 00841 00842 ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar)); 00843 if (ret == NULL) { 00844 xmlRngPErrMemory(ctxt, NULL); 00845 return (NULL); 00846 } 00847 memset(ret, 0, sizeof(xmlRelaxNGGrammar)); 00848 00849 return (ret); 00850 } 00851 00858 static void 00859 xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar) 00860 { 00861 if (grammar == NULL) 00862 return; 00863 00864 if (grammar->children != NULL) { 00865 xmlRelaxNGFreeGrammar(grammar->children); 00866 } 00867 if (grammar->next != NULL) { 00868 xmlRelaxNGFreeGrammar(grammar->next); 00869 } 00870 if (grammar->refs != NULL) { 00871 xmlHashFree(grammar->refs, NULL); 00872 } 00873 if (grammar->defs != NULL) { 00874 xmlHashFree(grammar->defs, NULL); 00875 } 00876 00877 xmlFree(grammar); 00878 } 00879 00889 static xmlRelaxNGDefinePtr 00890 xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 00891 { 00892 xmlRelaxNGDefinePtr ret; 00893 00894 if (ctxt->defMax == 0) { 00895 ctxt->defMax = 16; 00896 ctxt->defNr = 0; 00897 ctxt->defTab = (xmlRelaxNGDefinePtr *) 00898 xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr)); 00899 if (ctxt->defTab == NULL) { 00900 xmlRngPErrMemory(ctxt, "allocating define\n"); 00901 return (NULL); 00902 } 00903 } else if (ctxt->defMax <= ctxt->defNr) { 00904 xmlRelaxNGDefinePtr *tmp; 00905 00906 ctxt->defMax *= 2; 00907 tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab, 00908 ctxt->defMax * 00909 sizeof 00910 (xmlRelaxNGDefinePtr)); 00911 if (tmp == NULL) { 00912 xmlRngPErrMemory(ctxt, "allocating define\n"); 00913 return (NULL); 00914 } 00915 ctxt->defTab = tmp; 00916 } 00917 ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine)); 00918 if (ret == NULL) { 00919 xmlRngPErrMemory(ctxt, "allocating define\n"); 00920 return (NULL); 00921 } 00922 memset(ret, 0, sizeof(xmlRelaxNGDefine)); 00923 ctxt->defTab[ctxt->defNr++] = ret; 00924 ret->node = node; 00925 ret->depth = -1; 00926 return (ret); 00927 } 00928 00935 static void 00936 xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions) 00937 { 00938 xmlRelaxNGInterleaveGroupPtr group; 00939 int j; 00940 00941 if (partitions != NULL) { 00942 if (partitions->groups != NULL) { 00943 for (j = 0; j < partitions->nbgroups; j++) { 00944 group = partitions->groups[j]; 00945 if (group != NULL) { 00946 if (group->defs != NULL) 00947 xmlFree(group->defs); 00948 if (group->attrs != NULL) 00949 xmlFree(group->attrs); 00950 xmlFree(group); 00951 } 00952 } 00953 xmlFree(partitions->groups); 00954 } 00955 if (partitions->triage != NULL) { 00956 xmlHashFree(partitions->triage, NULL); 00957 } 00958 xmlFree(partitions); 00959 } 00960 } 00961 00968 static void 00969 xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define) 00970 { 00971 if (define == NULL) 00972 return; 00973 00974 if ((define->type == XML_RELAXNG_VALUE) && (define->attrs != NULL)) { 00975 xmlRelaxNGTypeLibraryPtr lib; 00976 00977 lib = (xmlRelaxNGTypeLibraryPtr) define->data; 00978 if ((lib != NULL) && (lib->freef != NULL)) 00979 lib->freef(lib->data, (void *) define->attrs); 00980 } 00981 if ((define->data != NULL) && (define->type == XML_RELAXNG_INTERLEAVE)) 00982 xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data); 00983 if ((define->data != NULL) && (define->type == XML_RELAXNG_CHOICE)) 00984 xmlHashFree((xmlHashTablePtr) define->data, NULL); 00985 if (define->name != NULL) 00986 xmlFree(define->name); 00987 if (define->ns != NULL) 00988 xmlFree(define->ns); 00989 if (define->value != NULL) 00990 xmlFree(define->value); 00991 if (define->contModel != NULL) 00992 xmlRegFreeRegexp(define->contModel); 00993 xmlFree(define); 00994 } 00995 01005 static xmlRelaxNGStatesPtr 01006 xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size) 01007 { 01008 xmlRelaxNGStatesPtr ret; 01009 01010 if ((ctxt != NULL) && 01011 (ctxt->freeStates != NULL) && (ctxt->freeStatesNr > 0)) { 01012 ctxt->freeStatesNr--; 01013 ret = ctxt->freeStates[ctxt->freeStatesNr]; 01014 ret->nbState = 0; 01015 return (ret); 01016 } 01017 if (size < 16) 01018 size = 16; 01019 01020 ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) + 01021 (size - 01022 1) * 01023 sizeof(xmlRelaxNGValidStatePtr)); 01024 if (ret == NULL) { 01025 xmlRngVErrMemory(ctxt, "allocating states\n"); 01026 return (NULL); 01027 } 01028 ret->nbState = 0; 01029 ret->maxState = size; 01030 ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc((size) * 01031 sizeof 01032 (xmlRelaxNGValidStatePtr)); 01033 if (ret->tabState == NULL) { 01034 xmlRngVErrMemory(ctxt, "allocating states\n"); 01035 xmlFree(ret); 01036 return (NULL); 01037 } 01038 return (ret); 01039 } 01040 01052 static int 01053 xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt, 01054 xmlRelaxNGStatesPtr states, 01055 xmlRelaxNGValidStatePtr state) 01056 { 01057 if (state == NULL) { 01058 return (-1); 01059 } 01060 if (states->nbState >= states->maxState) { 01061 xmlRelaxNGValidStatePtr *tmp; 01062 int size; 01063 01064 size = states->maxState * 2; 01065 tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState, 01066 (size) * 01067 sizeof 01068 (xmlRelaxNGValidStatePtr)); 01069 if (tmp == NULL) { 01070 xmlRngVErrMemory(ctxt, "adding states\n"); 01071 return (-1); 01072 } 01073 states->tabState = tmp; 01074 states->maxState = size; 01075 } 01076 states->tabState[states->nbState++] = state; 01077 return (1); 01078 } 01079 01090 static int 01091 xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt, 01092 xmlRelaxNGStatesPtr states, 01093 xmlRelaxNGValidStatePtr state) 01094 { 01095 int i; 01096 01097 if (state == NULL) { 01098 return (-1); 01099 } 01100 if (states->nbState >= states->maxState) { 01101 xmlRelaxNGValidStatePtr *tmp; 01102 int size; 01103 01104 size = states->maxState * 2; 01105 tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState, 01106 (size) * 01107 sizeof 01108 (xmlRelaxNGValidStatePtr)); 01109 if (tmp == NULL) { 01110 xmlRngVErrMemory(ctxt, "adding states\n"); 01111 return (-1); 01112 } 01113 states->tabState = tmp; 01114 states->maxState = size; 01115 } 01116 for (i = 0; i < states->nbState; i++) { 01117 if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) { 01118 xmlRelaxNGFreeValidState(ctxt, state); 01119 return (0); 01120 } 01121 } 01122 states->tabState[states->nbState++] = state; 01123 return (1); 01124 } 01125 01133 static void 01134 xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt, 01135 xmlRelaxNGStatesPtr states) 01136 { 01137 if (states == NULL) 01138 return; 01139 if ((ctxt != NULL) && (ctxt->freeStates == NULL)) { 01140 ctxt->freeStatesMax = 40; 01141 ctxt->freeStatesNr = 0; 01142 ctxt->freeStates = (xmlRelaxNGStatesPtr *) 01143 xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr)); 01144 if (ctxt->freeStates == NULL) { 01145 xmlRngVErrMemory(ctxt, "storing states\n"); 01146 } 01147 } else if ((ctxt != NULL) 01148 && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) { 01149 xmlRelaxNGStatesPtr *tmp; 01150 01151 tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates, 01152 2 * ctxt->freeStatesMax * 01153 sizeof 01154 (xmlRelaxNGStatesPtr)); 01155 if (tmp == NULL) { 01156 xmlRngVErrMemory(ctxt, "storing states\n"); 01157 xmlFree(states->tabState); 01158 xmlFree(states); 01159 return; 01160 } 01161 ctxt->freeStates = tmp; 01162 ctxt->freeStatesMax *= 2; 01163 } 01164 if ((ctxt == NULL) || (ctxt->freeStates == NULL)) { 01165 xmlFree(states->tabState); 01166 xmlFree(states); 01167 } else { 01168 ctxt->freeStates[ctxt->freeStatesNr++] = states; 01169 } 01170 } 01171 01181 static xmlRelaxNGValidStatePtr 01182 xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node) 01183 { 01184 xmlRelaxNGValidStatePtr ret; 01185 xmlAttrPtr attr; 01186 xmlAttrPtr attrs[MAX_ATTR]; 01187 int nbAttrs = 0; 01188 xmlNodePtr root = NULL; 01189 01190 if (node == NULL) { 01191 root = xmlDocGetRootElement(ctxt->doc); 01192 if (root == NULL) 01193 return (NULL); 01194 } else { 01195 attr = node->properties; 01196 while (attr != NULL) { 01197 if (nbAttrs < MAX_ATTR) 01198 attrs[nbAttrs++] = attr; 01199 else 01200 nbAttrs++; 01201 attr = attr->next; 01202 } 01203 } 01204 if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) { 01205 ctxt->freeState->nbState--; 01206 ret = ctxt->freeState->tabState[ctxt->freeState->nbState]; 01207 } else { 01208 ret = 01209 (xmlRelaxNGValidStatePtr) 01210 xmlMalloc(sizeof(xmlRelaxNGValidState)); 01211 if (ret == NULL) { 01212 xmlRngVErrMemory(ctxt, "allocating states\n"); 01213 return (NULL); 01214 } 01215 memset(ret, 0, sizeof(xmlRelaxNGValidState)); 01216 } 01217 ret->value = NULL; 01218 ret->endvalue = NULL; 01219 if (node == NULL) { 01220 ret->node = (xmlNodePtr) ctxt->doc; 01221 ret->seq = root; 01222 } else { 01223 ret->node = node; 01224 ret->seq = node->children; 01225 } 01226 ret->nbAttrs = 0; 01227 if (nbAttrs > 0) { 01228 if (ret->attrs == NULL) { 01229 if (nbAttrs < 4) 01230 ret->maxAttrs = 4; 01231 else 01232 ret->maxAttrs = nbAttrs; 01233 ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs * 01234 sizeof(xmlAttrPtr)); 01235 if (ret->attrs == NULL) { 01236 xmlRngVErrMemory(ctxt, "allocating states\n"); 01237 return (ret); 01238 } 01239 } else if (ret->maxAttrs < nbAttrs) { 01240 xmlAttrPtr *tmp; 01241 01242 tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs * 01243 sizeof(xmlAttrPtr)); 01244 if (tmp == NULL) { 01245 xmlRngVErrMemory(ctxt, "allocating states\n"); 01246 return (ret); 01247 } 01248 ret->attrs = tmp; 01249 ret->maxAttrs = nbAttrs; 01250 } 01251 ret->nbAttrs = nbAttrs; 01252 if (nbAttrs < MAX_ATTR) { 01253 memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs); 01254 } else { 01255 attr = node->properties; 01256 nbAttrs = 0; 01257 while (attr != NULL) { 01258 ret->attrs[nbAttrs++] = attr; 01259 attr = attr->next; 01260 } 01261 } 01262 } 01263 ret->nbAttrLeft = ret->nbAttrs; 01264 return (ret); 01265 } 01266 01276 static xmlRelaxNGValidStatePtr 01277 xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt, 01278 xmlRelaxNGValidStatePtr state) 01279 { 01280 xmlRelaxNGValidStatePtr ret; 01281 unsigned int maxAttrs; 01282 xmlAttrPtr *attrs; 01283 01284 if (state == NULL) 01285 return (NULL); 01286 if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) { 01287 ctxt->freeState->nbState--; 01288 ret = ctxt->freeState->tabState[ctxt->freeState->nbState]; 01289 } else { 01290 ret = 01291 (xmlRelaxNGValidStatePtr) 01292 xmlMalloc(sizeof(xmlRelaxNGValidState)); 01293 if (ret == NULL) { 01294 xmlRngVErrMemory(ctxt, "allocating states\n"); 01295 return (NULL); 01296 } 01297 memset(ret, 0, sizeof(xmlRelaxNGValidState)); 01298 } 01299 attrs = ret->attrs; 01300 maxAttrs = ret->maxAttrs; 01301 memcpy(ret, state, sizeof(xmlRelaxNGValidState)); 01302 ret->attrs = attrs; 01303 ret->maxAttrs = maxAttrs; 01304 if (state->nbAttrs > 0) { 01305 if (ret->attrs == NULL) { 01306 ret->maxAttrs = state->maxAttrs; 01307 ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs * 01308 sizeof(xmlAttrPtr)); 01309 if (ret->attrs == NULL) { 01310 xmlRngVErrMemory(ctxt, "allocating states\n"); 01311 ret->nbAttrs = 0; 01312 return (ret); 01313 } 01314 } else if (ret->maxAttrs < state->nbAttrs) { 01315 xmlAttrPtr *tmp; 01316 01317 tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs * 01318 sizeof(xmlAttrPtr)); 01319 if (tmp == NULL) { 01320 xmlRngVErrMemory(ctxt, "allocating states\n"); 01321 ret->nbAttrs = 0; 01322 return (ret); 01323 } 01324 ret->maxAttrs = state->maxAttrs; 01325 ret->attrs = tmp; 01326 } 01327 memcpy(ret->attrs, state->attrs, 01328 state->nbAttrs * sizeof(xmlAttrPtr)); 01329 } 01330 return (ret); 01331 } 01332 01343 static int 01344 xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, 01345 xmlRelaxNGValidStatePtr state1, 01346 xmlRelaxNGValidStatePtr state2) 01347 { 01348 int i; 01349 01350 if ((state1 == NULL) || (state2 == NULL)) 01351 return (0); 01352 if (state1 == state2) 01353 return (1); 01354 if (state1->node != state2->node) 01355 return (0); 01356 if (state1->seq != state2->seq) 01357 return (0); 01358 if (state1->nbAttrLeft != state2->nbAttrLeft) 01359 return (0); 01360 if (state1->nbAttrs != state2->nbAttrs) 01361 return (0); 01362 if (state1->endvalue != state2->endvalue) 01363 return (0); 01364 if ((state1->value != state2->value) && 01365 (!xmlStrEqual(state1->value, state2->value))) 01366 return (0); 01367 for (i = 0; i < state1->nbAttrs; i++) { 01368 if (state1->attrs[i] != state2->attrs[i]) 01369 return (0); 01370 } 01371 return (1); 01372 } 01373 01380 static void 01381 xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt, 01382 xmlRelaxNGValidStatePtr state) 01383 { 01384 if (state == NULL) 01385 return; 01386 01387 if ((ctxt != NULL) && (ctxt->freeState == NULL)) { 01388 ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40); 01389 } 01390 if ((ctxt == NULL) || (ctxt->freeState == NULL)) { 01391 if (state->attrs != NULL) 01392 xmlFree(state->attrs); 01393 xmlFree(state); 01394 } else { 01395 xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state); 01396 } 01397 } 01398 01399 /************************************************************************ 01400 * * 01401 * Semi internal functions * 01402 * * 01403 ************************************************************************/ 01404 01415 int 01416 xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags) 01417 { 01418 if (ctxt == NULL) return(-1); 01419 if (flags & XML_RELAXNGP_FREE_DOC) { 01420 ctxt->crng |= XML_RELAXNGP_FREE_DOC; 01421 flags -= XML_RELAXNGP_FREE_DOC; 01422 } 01423 if (flags & XML_RELAXNGP_CRNG) { 01424 ctxt->crng |= XML_RELAXNGP_CRNG; 01425 flags -= XML_RELAXNGP_CRNG; 01426 } 01427 if (flags != 0) return(-1); 01428 return(0); 01429 } 01430 01431 /************************************************************************ 01432 * * 01433 * Document functions * 01434 * * 01435 ************************************************************************/ 01436 static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, 01437 xmlDocPtr doc); 01438 01448 static int 01449 xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, 01450 xmlRelaxNGIncludePtr value) 01451 { 01452 if (ctxt->incTab == NULL) { 01453 ctxt->incMax = 4; 01454 ctxt->incNr = 0; 01455 ctxt->incTab = 01456 (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax * 01457 sizeof(ctxt->incTab[0])); 01458 if (ctxt->incTab == NULL) { 01459 xmlRngPErrMemory(ctxt, "allocating include\n"); 01460 return (0); 01461 } 01462 } 01463 if (ctxt->incNr >= ctxt->incMax) { 01464 ctxt->incMax *= 2; 01465 ctxt->incTab = 01466 (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab, 01467 ctxt->incMax * 01468 sizeof(ctxt->incTab[0])); 01469 if (ctxt->incTab == NULL) { 01470 xmlRngPErrMemory(ctxt, "allocating include\n"); 01471 return (0); 01472 } 01473 } 01474 ctxt->incTab[ctxt->incNr] = value; 01475 ctxt->inc = value; 01476 return (ctxt->incNr++); 01477 } 01478 01487 static xmlRelaxNGIncludePtr 01488 xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt) 01489 { 01490 xmlRelaxNGIncludePtr ret; 01491 01492 if (ctxt->incNr <= 0) 01493 return (NULL); 01494 ctxt->incNr--; 01495 if (ctxt->incNr > 0) 01496 ctxt->inc = ctxt->incTab[ctxt->incNr - 1]; 01497 else 01498 ctxt->inc = NULL; 01499 ret = ctxt->incTab[ctxt->incNr]; 01500 ctxt->incTab[ctxt->incNr] = NULL; 01501 return (ret); 01502 } 01503 01515 static int 01516 xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt, 01517 const xmlChar * URL ATTRIBUTE_UNUSED, 01518 xmlNodePtr target, const xmlChar * name) 01519 { 01520 int found = 0; 01521 xmlNodePtr tmp, tmp2; 01522 xmlChar *name2; 01523 01524 #ifdef DEBUG_INCLUDE 01525 if (name == NULL) 01526 xmlGenericError(xmlGenericErrorContext, 01527 "Elimination of <include> start from %s\n", URL); 01528 else 01529 xmlGenericError(xmlGenericErrorContext, 01530 "Elimination of <include> define %s from %s\n", 01531 name, URL); 01532 #endif 01533 tmp = target; 01534 while (tmp != NULL) { 01535 tmp2 = tmp->next; 01536 if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) { 01537 found = 1; 01538 xmlUnlinkNode(tmp); 01539 xmlFreeNode(tmp); 01540 } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) { 01541 name2 = xmlGetProp(tmp, BAD_CAST "name"); 01542 xmlRelaxNGNormExtSpace(name2); 01543 if (name2 != NULL) { 01544 if (xmlStrEqual(name, name2)) { 01545 found = 1; 01546 xmlUnlinkNode(tmp); 01547 xmlFreeNode(tmp); 01548 } 01549 xmlFree(name2); 01550 } 01551 } else if (IS_RELAXNG(tmp, "include")) { 01552 xmlChar *href = NULL; 01553 xmlRelaxNGDocumentPtr inc = tmp->psvi; 01554 01555 if ((inc != NULL) && (inc->doc != NULL) && 01556 (inc->doc->children != NULL)) { 01557 01558 if (xmlStrEqual 01559 (inc->doc->children->name, BAD_CAST "grammar")) { 01560 #ifdef DEBUG_INCLUDE 01561 href = xmlGetProp(tmp, BAD_CAST "href"); 01562 #endif 01563 if (xmlRelaxNGRemoveRedefine(ctxt, href, 01564 inc->doc->children-> 01565 children, name) == 1) { 01566 found = 1; 01567 } 01568 #ifdef DEBUG_INCLUDE 01569 if (href != NULL) 01570 xmlFree(href); 01571 #endif 01572 } 01573 } 01574 } 01575 tmp = tmp2; 01576 } 01577 return (found); 01578 } 01579 01593 static xmlRelaxNGIncludePtr 01594 xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, 01595 xmlNodePtr node, const xmlChar * ns) 01596 { 01597 xmlRelaxNGIncludePtr ret = NULL; 01598 xmlDocPtr doc; 01599 int i; 01600 xmlNodePtr root, cur; 01601 01602 #ifdef DEBUG_INCLUDE 01603 xmlGenericError(xmlGenericErrorContext, 01604 "xmlRelaxNGLoadInclude(%s)\n", URL); 01605 #endif 01606 01607 /* 01608 * check against recursion in the stack 01609 */ 01610 for (i = 0; i < ctxt->incNr; i++) { 01611 if (xmlStrEqual(ctxt->incTab[i]->href, URL)) { 01612 xmlRngPErr(ctxt, NULL, XML_RNGP_INCLUDE_RECURSE, 01613 "Detected an Include recursion for %s\n", URL, 01614 NULL); 01615 return (NULL); 01616 } 01617 } 01618 01619 /* 01620 * load the document 01621 */ 01622 doc = xmlReadFile((const char *) URL,NULL,0); 01623 if (doc == NULL) { 01624 xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR, 01625 "xmlRelaxNG: could not load %s\n", URL, NULL); 01626 return (NULL); 01627 } 01628 #ifdef DEBUG_INCLUDE 01629 xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL); 01630 #endif 01631 01632 /* 01633 * Allocate the document structures and register it first. 01634 */ 01635 ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude)); 01636 if (ret == NULL) { 01637 xmlRngPErrMemory(ctxt, "allocating include\n"); 01638 xmlFreeDoc(doc); 01639 return (NULL); 01640 } 01641 memset(ret, 0, sizeof(xmlRelaxNGInclude)); 01642 ret->doc = doc; 01643 ret->href = xmlStrdup(URL); 01644 ret->next = ctxt->includes; 01645 ctxt->includes = ret; 01646 01647 /* 01648 * transmit the ns if needed 01649 */ 01650 if (ns != NULL) { 01651 root = xmlDocGetRootElement(doc); 01652 if (root != NULL) { 01653 if (xmlHasProp(root, BAD_CAST "ns") == NULL) { 01654 xmlSetProp(root, BAD_CAST "ns", ns); 01655 } 01656 } 01657 } 01658 01659 /* 01660 * push it on the stack 01661 */ 01662 xmlRelaxNGIncludePush(ctxt, ret); 01663 01664 /* 01665 * Some preprocessing of the document content, this include recursing 01666 * in the include stack. 01667 */ 01668 #ifdef DEBUG_INCLUDE 01669 xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL); 01670 #endif 01671 01672 doc = xmlRelaxNGCleanupDoc(ctxt, doc); 01673 if (doc == NULL) { 01674 ctxt->inc = NULL; 01675 return (NULL); 01676 } 01677 01678 /* 01679 * Pop up the include from the stack 01680 */ 01681 xmlRelaxNGIncludePop(ctxt); 01682 01683 #ifdef DEBUG_INCLUDE 01684 xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL); 01685 #endif 01686 /* 01687 * Check that the top element is a grammar 01688 */ 01689 root = xmlDocGetRootElement(doc); 01690 if (root == NULL) { 01691 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, 01692 "xmlRelaxNG: included document is empty %s\n", URL, 01693 NULL); 01694 return (NULL); 01695 } 01696 if (!IS_RELAXNG(root, "grammar")) { 01697 xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING, 01698 "xmlRelaxNG: included document %s root is not a grammar\n", 01699 URL, NULL); 01700 return (NULL); 01701 } 01702 01703 /* 01704 * Elimination of redefined rules in the include. 01705 */ 01706 cur = node->children; 01707 while (cur != NULL) { 01708 if (IS_RELAXNG(cur, "start")) { 01709 int found = 0; 01710 01711 found = 01712 xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL); 01713 if (!found) { 01714 xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING, 01715 "xmlRelaxNG: include %s has a start but not the included grammar\n", 01716 URL, NULL); 01717 } 01718 } else if (IS_RELAXNG(cur, "define")) { 01719 xmlChar *name; 01720 01721 name = xmlGetProp(cur, BAD_CAST "name"); 01722 if (name == NULL) { 01723 xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING, 01724 "xmlRelaxNG: include %s has define without name\n", 01725 URL, NULL); 01726 } else { 01727 int found; 01728 01729 xmlRelaxNGNormExtSpace(name); 01730 found = xmlRelaxNGRemoveRedefine(ctxt, URL, 01731 root->children, name); 01732 if (!found) { 01733 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING, 01734 "xmlRelaxNG: include %s has a define %s but not the included grammar\n", 01735 URL, name); 01736 } 01737 xmlFree(name); 01738 } 01739 } 01740 cur = cur->next; 01741 } 01742 01743 01744 return (ret); 01745 } 01746 01759 static int 01760 xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt, 01761 xmlRelaxNGValidErr err, const xmlChar * arg1, 01762 const xmlChar * arg2, int dup) 01763 { 01764 xmlRelaxNGValidErrorPtr cur; 01765 01766 #ifdef DEBUG_ERROR 01767 xmlGenericError(xmlGenericErrorContext, 01768 "Pushing error %d at %d on stack\n", err, ctxt->errNr); 01769 #endif 01770 if (ctxt->errTab == NULL) { 01771 ctxt->errMax = 8; 01772 ctxt->errNr = 0; 01773 ctxt->errTab = 01774 (xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax * 01775 sizeof 01776 (xmlRelaxNGValidError)); 01777 if (ctxt->errTab == NULL) { 01778 xmlRngVErrMemory(ctxt, "pushing error\n"); 01779 return (0); 01780 } 01781 ctxt->err = NULL; 01782 } 01783 if (ctxt->errNr >= ctxt->errMax) { 01784 ctxt->errMax *= 2; 01785 ctxt->errTab = 01786 (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab, 01787 ctxt->errMax * 01788 sizeof 01789 (xmlRelaxNGValidError)); 01790 if (ctxt->errTab == NULL) { 01791 xmlRngVErrMemory(ctxt, "pushing error\n"); 01792 return (0); 01793 } 01794 ctxt->err = &ctxt->errTab[ctxt->errNr - 1]; 01795 } 01796 if ((ctxt->err != NULL) && (ctxt->state != NULL) && 01797 (ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err)) 01798 return (ctxt->errNr); 01799 cur = &ctxt->errTab[ctxt->errNr]; 01800 cur->err = err; 01801 if (dup) { 01802 cur->arg1 = xmlStrdup(arg1); 01803 cur->arg2 = xmlStrdup(arg2); 01804 cur->flags = ERROR_IS_DUP; 01805 } else { 01806 cur->arg1 = arg1; 01807 cur->arg2 = arg2; 01808 cur->flags = 0; 01809 } 01810 if (ctxt->state != NULL) { 01811 cur->node = ctxt->state->node; 01812 cur->seq = ctxt->state->seq; 01813 } else { 01814 cur->node = NULL; 01815 cur->seq = NULL; 01816 } 01817 ctxt->err = cur; 01818 return (ctxt->errNr++); 01819 } 01820 01827 static void 01828 xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt) 01829 { 01830 xmlRelaxNGValidErrorPtr cur; 01831 01832 if (ctxt->errNr <= 0) { 01833 ctxt->err = NULL; 01834 return; 01835 } 01836 ctxt->errNr--; 01837 if (ctxt->errNr > 0) 01838 ctxt->err = &ctxt->errTab[ctxt->errNr - 1]; 01839 else 01840 ctxt->err = NULL; 01841 cur = &ctxt->errTab[ctxt->errNr]; 01842 if (cur->flags & ERROR_IS_DUP) { 01843 if (cur->arg1 != NULL) 01844 xmlFree((xmlChar *) cur->arg1); 01845 cur->arg1 = NULL; 01846 if (cur->arg2 != NULL) 01847 xmlFree((xmlChar *) cur->arg2); 01848 cur->arg2 = NULL; 01849 cur->flags = 0; 01850 } 01851 } 01852 01862 static int 01863 xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt, 01864 xmlRelaxNGDocumentPtr value) 01865 { 01866 if (ctxt->docTab == NULL) { 01867 ctxt->docMax = 4; 01868 ctxt->docNr = 0; 01869 ctxt->docTab = 01870 (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax * 01871 sizeof(ctxt->docTab[0])); 01872 if (ctxt->docTab == NULL) { 01873 xmlRngPErrMemory(ctxt, "adding document\n"); 01874 return (0); 01875 } 01876 } 01877 if (ctxt->docNr >= ctxt->docMax) { 01878 ctxt->docMax *= 2; 01879 ctxt->docTab = 01880 (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab, 01881 ctxt->docMax * 01882 sizeof(ctxt->docTab[0])); 01883 if (ctxt->docTab == NULL) { 01884 xmlRngPErrMemory(ctxt, "adding document\n"); 01885 return (0); 01886 } 01887 } 01888 ctxt->docTab[ctxt->docNr] = value; 01889 ctxt->doc = value; 01890 return (ctxt->docNr++); 01891 } 01892 01901 static xmlRelaxNGDocumentPtr 01902 xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt) 01903 { 01904 xmlRelaxNGDocumentPtr ret; 01905 01906 if (ctxt->docNr <= 0) 01907 return (NULL); 01908 ctxt->docNr--; 01909 if (ctxt->docNr > 0) 01910 ctxt->doc = ctxt->docTab[ctxt->docNr - 1]; 01911 else 01912 ctxt->doc = NULL; 01913 ret = ctxt->docTab[ctxt->docNr]; 01914 ctxt->docTab[ctxt->docNr] = NULL; 01915 return (ret); 01916 } 01917 01930 static xmlRelaxNGDocumentPtr 01931 xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt, 01932 const xmlChar * URL, const xmlChar * ns) 01933 { 01934 xmlRelaxNGDocumentPtr ret = NULL; 01935 xmlDocPtr doc; 01936 xmlNodePtr root; 01937 int i; 01938 01939 /* 01940 * check against recursion in the stack 01941 */ 01942 for (i = 0; i < ctxt->docNr; i++) { 01943 if (xmlStrEqual(ctxt->docTab[i]->href, URL)) { 01944 xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE, 01945 "Detected an externalRef recursion for %s\n", URL, 01946 NULL); 01947 return (NULL); 01948 } 01949 } 01950 01951 /* 01952 * load the document 01953 */ 01954 doc = xmlReadFile((const char *) URL,NULL,0); 01955 if (doc == NULL) { 01956 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR, 01957 "xmlRelaxNG: could not load %s\n", URL, NULL); 01958 return (NULL); 01959 } 01960 01961 /* 01962 * Allocate the document structures and register it first. 01963 */ 01964 ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument)); 01965 if (ret == NULL) { 01966 xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY, 01967 "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL); 01968 xmlFreeDoc(doc); 01969 return (NULL); 01970 } 01971 memset(ret, 0, sizeof(xmlRelaxNGDocument)); 01972 ret->doc = doc; 01973 ret->href = xmlStrdup(URL); 01974 ret->next = ctxt->documents; 01975 ret->externalRef = 1; 01976 ctxt->documents = ret; 01977 01978 /* 01979 * transmit the ns if needed 01980 */ 01981 if (ns != NULL) { 01982 root = xmlDocGetRootElement(doc); 01983 if (root != NULL) { 01984 if (xmlHasProp(root, BAD_CAST "ns") == NULL) { 01985 xmlSetProp(root, BAD_CAST "ns", ns); 01986 } 01987 } 01988 } 01989 01990 /* 01991 * push it on the stack and register it in the hash table 01992 */ 01993 xmlRelaxNGDocumentPush(ctxt, ret); 01994 01995 /* 01996 * Some preprocessing of the document content 01997 */ 01998 doc = xmlRelaxNGCleanupDoc(ctxt, doc); 01999 if (doc == NULL) { 02000 ctxt->doc = NULL; 02001 return (NULL); 02002 } 02003 02004 xmlRelaxNGDocumentPop(ctxt); 02005 02006 return (ret); 02007 } 02008 02009 /************************************************************************ 02010 * * 02011 * Error functions * 02012 * * 02013 ************************************************************************/ 02014 02015 #define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0); 02016 #define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0); 02017 #define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0); 02018 #define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1); 02019 #define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1); 02020 02021 static const char * 02022 xmlRelaxNGDefName(xmlRelaxNGDefinePtr def) 02023 { 02024 if (def == NULL) 02025 return ("none"); 02026 switch (def->type) { 02027 case XML_RELAXNG_EMPTY: 02028 return ("empty"); 02029 case XML_RELAXNG_NOT_ALLOWED: 02030 return ("notAllowed"); 02031 case XML_RELAXNG_EXCEPT: 02032 return ("except"); 02033 case XML_RELAXNG_TEXT: 02034 return ("text"); 02035 case XML_RELAXNG_ELEMENT: 02036 return ("element"); 02037 case XML_RELAXNG_DATATYPE: 02038 return ("datatype"); 02039 case XML_RELAXNG_VALUE: 02040 return ("value"); 02041 case XML_RELAXNG_LIST: 02042 return ("list"); 02043 case XML_RELAXNG_ATTRIBUTE: 02044 return ("attribute"); 02045 case XML_RELAXNG_DEF: 02046 return ("def"); 02047 case XML_RELAXNG_REF: 02048 return ("ref"); 02049 case XML_RELAXNG_EXTERNALREF: 02050 return ("externalRef"); 02051 case XML_RELAXNG_PARENTREF: 02052 return ("parentRef"); 02053 case XML_RELAXNG_OPTIONAL: 02054 return ("optional"); 02055 case XML_RELAXNG_ZEROORMORE: 02056 return ("zeroOrMore"); 02057 case XML_RELAXNG_ONEORMORE: 02058 return ("oneOrMore"); 02059 case XML_RELAXNG_CHOICE: 02060 return ("choice"); 02061 case XML_RELAXNG_GROUP: 02062 return ("group"); 02063 case XML_RELAXNG_INTERLEAVE: 02064 return ("interleave"); 02065 case XML_RELAXNG_START: 02066 return ("start"); 02067 case XML_RELAXNG_NOOP: 02068 return ("noop"); 02069 case XML_RELAXNG_PARAM: 02070 return ("param"); 02071 } 02072 return ("unknown"); 02073 } 02074 02085 static xmlChar * 02086 xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1, 02087 const xmlChar * arg2) 02088 { 02089 char msg[1000]; 02090 02091 if (arg1 == NULL) 02092 arg1 = BAD_CAST ""; 02093 if (arg2 == NULL) 02094 arg2 = BAD_CAST ""; 02095 02096 msg[0] = 0; 02097 switch (err) { 02098 case XML_RELAXNG_OK: 02099 return (NULL); 02100 case XML_RELAXNG_ERR_MEMORY: 02101 return (xmlCharStrdup("out of memory\n")); 02102 case XML_RELAXNG_ERR_TYPE: 02103 snprintf(msg, 1000, "failed to validate type %s\n", arg1); 02104 break; 02105 case XML_RELAXNG_ERR_TYPEVAL: 02106 snprintf(msg, 1000, "Type %s doesn't allow value '%s'\n", arg1, 02107 arg2); 02108 break; 02109 case XML_RELAXNG_ERR_DUPID: 02110 snprintf(msg, 1000, "ID %s redefined\n", arg1); 02111 break; 02112 case XML_RELAXNG_ERR_TYPECMP: 02113 snprintf(msg, 1000, "failed to compare type %s\n", arg1); 02114 break; 02115 case XML_RELAXNG_ERR_NOSTATE: 02116 return (xmlCharStrdup("Internal error: no state\n")); 02117 case XML_RELAXNG_ERR_NODEFINE: 02118 return (xmlCharStrdup("Internal error: no define\n")); 02119 case XML_RELAXNG_ERR_INTERNAL: 02120 snprintf(msg, 1000, "Internal error: %s\n", arg1); 02121 break; 02122 case XML_RELAXNG_ERR_LISTEXTRA: 02123 snprintf(msg, 1000, "Extra data in list: %s\n", arg1); 02124 break; 02125 case XML_RELAXNG_ERR_INTERNODATA: 02126 return (xmlCharStrdup 02127 ("Internal: interleave block has no data\n")); 02128 case XML_RELAXNG_ERR_INTERSEQ: 02129 return (xmlCharStrdup("Invalid sequence in interleave\n")); 02130 case XML_RELAXNG_ERR_INTEREXTRA: 02131 snprintf(msg, 1000, "Extra element %s in interleave\n", arg1); 02132 break; 02133 case XML_RELAXNG_ERR_ELEMNAME: 02134 snprintf(msg, 1000, "Expecting element %s, got %s\n", arg1, 02135 arg2); 02136 break; 02137 case XML_RELAXNG_ERR_ELEMNONS: 02138 snprintf(msg, 1000, "Expecting a namespace for element %s\n", 02139 arg1); 02140 break; 02141 case XML_RELAXNG_ERR_ELEMWRONGNS: 02142 snprintf(msg, 1000, 02143 "Element %s has wrong namespace: expecting %s\n", arg1, 02144 arg2); 02145 break; 02146 case XML_RELAXNG_ERR_ELEMWRONG: 02147 snprintf(msg, 1000, "Did not expect element %s there\n", arg1); 02148 break; 02149 case XML_RELAXNG_ERR_TEXTWRONG: 02150 snprintf(msg, 1000, 02151 "Did not expect text in element %s content\n", arg1); 02152 break; 02153 case XML_RELAXNG_ERR_ELEMEXTRANS: 02154 snprintf(msg, 1000, "Expecting no namespace for element %s\n", 02155 arg1); 02156 break; 02157 case XML_RELAXNG_ERR_ELEMNOTEMPTY: 02158 snprintf(msg, 1000, "Expecting element %s to be empty\n", arg1); 02159 break; 02160 case XML_RELAXNG_ERR_NOELEM: 02161 snprintf(msg, 1000, "Expecting an element %s, got nothing\n", 02162 arg1); 02163 break; 02164 case XML_RELAXNG_ERR_NOTELEM: 02165 return (xmlCharStrdup("Expecting an element got text\n")); 02166 case XML_RELAXNG_ERR_ATTRVALID: 02167 snprintf(msg, 1000, "Element %s failed to validate attributes\n", 02168 arg1); 02169 break; 02170 case XML_RELAXNG_ERR_CONTENTVALID: 02171 snprintf(msg, 1000, "Element %s failed to validate content\n", 02172 arg1); 02173 break; 02174 case XML_RELAXNG_ERR_EXTRACONTENT: 02175 snprintf(msg, 1000, "Element %s has extra content: %s\n", 02176 arg1, arg2); 02177 break; 02178 case XML_RELAXNG_ERR_INVALIDATTR: 02179 snprintf(msg, 1000, "Invalid attribute %s for element %s\n", 02180 arg1, arg2); 02181 break; 02182 case XML_RELAXNG_ERR_LACKDATA: 02183 snprintf(msg, 1000, "Datatype element %s contains no data\n", 02184 arg1); 02185 break; 02186 case XML_RELAXNG_ERR_DATAELEM: 02187 snprintf(msg, 1000, "Datatype element %s has child elements\n", 02188 arg1); 02189 break; 02190 case XML_RELAXNG_ERR_VALELEM: 02191 snprintf(msg, 1000, "Value element %s has child elements\n", 02192 arg1); 02193 break; 02194 case XML_RELAXNG_ERR_LISTELEM: 02195 snprintf(msg, 1000, "List element %s has child elements\n", 02196 arg1); 02197 break; 02198 case XML_RELAXNG_ERR_DATATYPE: 02199 snprintf(msg, 1000, "Error validating datatype %s\n", arg1); 02200 break; 02201 case XML_RELAXNG_ERR_VALUE: 02202 snprintf(msg, 1000, "Error validating value %s\n", arg1); 02203 break; 02204 case XML_RELAXNG_ERR_LIST: 02205 return (xmlCharStrdup("Error validating list\n")); 02206 case XML_RELAXNG_ERR_NOGRAMMAR: 02207 return (xmlCharStrdup("No top grammar defined\n")); 02208 case XML_RELAXNG_ERR_EXTRADATA: 02209 return (xmlCharStrdup("Extra data in the document\n")); 02210 default: 02211 return (xmlCharStrdup("Unknown error !\n")); 02212 } 02213 if (msg[0] == 0) { 02214 snprintf(msg, 1000, "Unknown error code %d\n", err); 02215 } 02216 msg[1000 - 1] = 0; 02217 return (xmlStrdup((xmlChar *) msg)); 02218 } 02219 02231 static void 02232 xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt, 02233 xmlRelaxNGValidErr err, xmlNodePtr node, 02234 xmlNodePtr child, const xmlChar * arg1, 02235 const xmlChar * arg2) 02236 { 02237 xmlChar *msg; 02238 02239 if (ctxt->flags & FLAGS_NOERROR) 02240 return; 02241 02242 #ifdef DEBUG_ERROR 02243 xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err); 02244 #endif 02245 msg = xmlRelaxNGGetErrorString(err, arg1, arg2); 02246 if (msg == NULL) 02247 return; 02248 02249 if (ctxt->errNo == XML_RELAXNG_OK) 02250 ctxt->errNo = err; 02251 xmlRngVErr(ctxt, (child == NULL ? node : child), err, 02252 (const char *) msg, arg1, arg2); 02253 xmlFree(msg); 02254 } 02255 02263 static void 02264 xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level) 02265 { 02266 int i; 02267 xmlRelaxNGValidErrorPtr err; 02268 02269 #ifdef DEBUG_ERROR 02270 xmlGenericError(xmlGenericErrorContext, 02271 "Pop errors till level %d\n", level); 02272 #endif 02273 for (i = level; i < ctxt->errNr; i++) { 02274 err = &ctxt->errTab[i]; 02275 if (err->flags & ERROR_IS_DUP) { 02276 if (err->arg1 != NULL) 02277 xmlFree((xmlChar *) err->arg1); 02278 err->arg1 = NULL; 02279 if (err->arg2 != NULL) 02280 xmlFree((xmlChar *) err->arg2); 02281 err->arg2 = NULL; 02282 err->flags = 0; 02283 } 02284 } 02285 ctxt->errNr = level; 02286 if (ctxt->errNr <= 0) 02287 ctxt->err = NULL; 02288 } 02289 02296 static void 02297 xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt) 02298 { 02299 int i, j, k; 02300 xmlRelaxNGValidErrorPtr err, dup; 02301 02302 #ifdef DEBUG_ERROR 02303 xmlGenericError(xmlGenericErrorContext, 02304 "Dumping error stack %d errors\n", ctxt->errNr); 02305 #endif 02306 for (i = 0, k = 0; i < ctxt->errNr; i++) { 02307 err = &ctxt->errTab[i]; 02308 if (k < MAX_ERROR) { 02309 for (j = 0; j < i; j++) { 02310 dup = &ctxt->errTab[j]; 02311 if ((err->err == dup->err) && (err->node == dup->node) && 02312 (xmlStrEqual(err->arg1, dup->arg1)) && 02313 (xmlStrEqual(err->arg2, dup->arg2))) { 02314 goto skip; 02315 } 02316 } 02317 xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq, 02318 err->arg1, err->arg2); 02319 k++; 02320 } 02321 skip: 02322 if (err->flags & ERROR_IS_DUP) { 02323 if (err->arg1 != NULL) 02324 xmlFree((xmlChar *) err->arg1); 02325 err->arg1 = NULL; 02326 if (err->arg2 != NULL) 02327 xmlFree((xmlChar *) err->arg2); 02328 err->arg2 = NULL; 02329 err->flags = 0; 02330 } 02331 } 02332 ctxt->errNr = 0; 02333 } 02334 02346 static void 02347 xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt, 02348 xmlRelaxNGValidErr err, const xmlChar * arg1, 02349 const xmlChar * arg2, int dup) 02350 { 02351 if (ctxt == NULL) 02352 return; 02353 if (ctxt->flags & FLAGS_NOERROR) 02354 return; 02355 02356 #ifdef DEBUG_ERROR 02357 xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err); 02358 #endif 02359 /* 02360 * generate the error directly 02361 */ 02362 if (((ctxt->flags & FLAGS_IGNORABLE) == 0) || 02363 (ctxt->flags & FLAGS_NEGATIVE)) { 02364 xmlNodePtr node, seq; 02365 02366 /* 02367 * Flush first any stacked error which might be the 02368 * real cause of the problem. 02369 */ 02370 if (ctxt->errNr != 0) 02371 xmlRelaxNGDumpValidError(ctxt); 02372 if (ctxt->state != NULL) { 02373 node = ctxt->state->node; 02374 seq = ctxt->state->seq; 02375 } else { 02376 node = seq = NULL; 02377 } 02378 if ((node == NULL) && (seq == NULL)) { 02379 node = ctxt->pnode; 02380 } 02381 xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2); 02382 } 02383 /* 02384 * Stack the error for later processing if needed 02385 */ 02386 else { 02387 xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup); 02388 } 02389 } 02390 02391 02392 /************************************************************************ 02393 * * 02394 * Type library hooks * 02395 * * 02396 ************************************************************************/ 02397 static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, 02398 const xmlChar * str); 02399 02410 static int 02411 xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar * type) 02412 { 02413 xmlSchemaTypePtr typ; 02414 02415 if (type == NULL) 02416 return (-1); 02417 typ = xmlSchemaGetPredefinedType(type, 02418 BAD_CAST 02419 "http://www.w3.org/2001/XMLSchema"); 02420 if (typ == NULL) 02421 return (0); 02422 return (1); 02423 } 02424 02437 static int 02438 xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED, 02439 const xmlChar * type, 02440 const xmlChar * value, 02441 void **result, xmlNodePtr node) 02442 { 02443 xmlSchemaTypePtr typ; 02444 int ret; 02445 02446 if ((type == NULL) || (value == NULL)) 02447 return (-1); 02448 typ = xmlSchemaGetPredefinedType(type, 02449 BAD_CAST 02450 "http://www.w3.org/2001/XMLSchema"); 02451 if (typ == NULL) 02452 return (-1); 02453 ret = xmlSchemaValPredefTypeNode(typ, value, 02454 (xmlSchemaValPtr *) result, node); 02455 if (ret == 2) /* special ID error code */ 02456 return (2); 02457 if (ret == 0) 02458 return (1); 02459 if (ret > 0) 02460 return (0); 02461 return (-1); 02462 } 02463 02477 static int 02478 xmlRelaxNGSchemaFacetCheck(void *data ATTRIBUTE_UNUSED, 02479 const xmlChar * type, const xmlChar * facetname, 02480 const xmlChar * val, const xmlChar * strval, 02481 void *value) 02482 { 02483 xmlSchemaFacetPtr facet; 02484 xmlSchemaTypePtr typ; 02485 int ret; 02486 02487 if ((type == NULL) || (strval == NULL)) 02488 return (-1); 02489 typ = xmlSchemaGetPredefinedType(type, 02490 BAD_CAST 02491 "http://www.w3.org/2001/XMLSchema"); 02492 if (typ == NULL) 02493 return (-1); 02494 02495 facet = xmlSchemaNewFacet(); 02496 if (facet == NULL) 02497 return (-1); 02498 02499 if (xmlStrEqual(facetname, BAD_CAST "minInclusive")) { 02500 facet->type = XML_SCHEMA_FACET_MININCLUSIVE; 02501 } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive")) { 02502 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE; 02503 } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive")) { 02504 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE; 02505 } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive")) { 02506 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE; 02507 } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits")) { 02508 facet->type = XML_SCHEMA_FACET_TOTALDIGITS; 02509 } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits")) { 02510 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS; 02511 } else if (xmlStrEqual(facetname, BAD_CAST "pattern")) { 02512 facet->type = XML_SCHEMA_FACET_PATTERN; 02513 } else if (xmlStrEqual(facetname, BAD_CAST "enumeration")) { 02514 facet->type = XML_SCHEMA_FACET_ENUMERATION; 02515 } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace")) { 02516 facet->type = XML_SCHEMA_FACET_WHITESPACE; 02517 } else if (xmlStrEqual(facetname, BAD_CAST "length")) { 02518 facet->type = XML_SCHEMA_FACET_LENGTH; 02519 } else if (xmlStrEqual(facetname, BAD_CAST "maxLength")) { 02520 facet->type = XML_SCHEMA_FACET_MAXLENGTH; 02521 } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) { 02522 facet->type = XML_SCHEMA_FACET_MINLENGTH; 02523 } else { 02524 xmlSchemaFreeFacet(facet); 02525 return (-1); 02526 } 02527 facet->value = val; 02528 ret = xmlSchemaCheckFacet(facet, typ, NULL, type); 02529 if (ret != 0) { 02530 xmlSchemaFreeFacet(facet); 02531 return (-1); 02532 } 02533 ret = xmlSchemaValidateFacet(typ, facet, strval, value); 02534 xmlSchemaFreeFacet(facet); 02535 if (ret != 0) 02536 return (-1); 02537 return (0); 02538 } 02539 02549 static void 02550 xmlRelaxNGSchemaFreeValue(void *data ATTRIBUTE_UNUSED, void *value) 02551 { 02552 xmlSchemaFreeValue(value); 02553 } 02554 02567 static int 02568 xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED, 02569 const xmlChar * type, 02570 const xmlChar * value1, 02571 xmlNodePtr ctxt1, 02572 void *comp1, 02573 const xmlChar * value2, xmlNodePtr ctxt2) 02574 { 02575 int ret; 02576 xmlSchemaTypePtr typ; 02577 xmlSchemaValPtr res1 = NULL, res2 = NULL; 02578 02579 if ((type == NULL) || (value1 == NULL) || (value2 == NULL)) 02580 return (-1); 02581 typ = xmlSchemaGetPredefinedType(type, 02582 BAD_CAST 02583 "http://www.w3.org/2001/XMLSchema"); 02584 if (typ == NULL) 02585 return (-1); 02586 if (comp1 == NULL) { 02587 ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1); 02588 if (ret != 0) 02589 return (-1); 02590 if (res1 == NULL) 02591 return (-1); 02592 } else { 02593 res1 = (xmlSchemaValPtr) comp1; 02594 } 02595 ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2); 02596 if (ret != 0) { 02597 if ((comp1 == NULL) && (res1 != NULL)) 02598 xmlSchemaFreeValue(res1); 02599 return (-1); 02600 } 02601 if (res1 == NULL) { 02602 return (-1); 02603 } 02604 ret = xmlSchemaCompareValues(res1, res2); 02605 if (res1 != (xmlSchemaValPtr) comp1) 02606 xmlSchemaFreeValue(res1); 02607 xmlSchemaFreeValue(res2); 02608 if (ret == -2) 02609 return (-1); 02610 if (ret == 0) 02611 return (1); 02612 return (0); 02613 } 02614 02625 static int 02626 xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED, 02627 const xmlChar * type) 02628 { 02629 if (type == NULL) 02630 return (-1); 02631 if (xmlStrEqual(type, BAD_CAST "string")) 02632 return (1); 02633 if (xmlStrEqual(type, BAD_CAST "token")) 02634 return (1); 02635 return (0); 02636 } 02637 02650 static int 02651 xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED, 02652 const xmlChar * type ATTRIBUTE_UNUSED, 02653 const xmlChar * value ATTRIBUTE_UNUSED, 02654 void **result ATTRIBUTE_UNUSED, 02655 xmlNodePtr node ATTRIBUTE_UNUSED) 02656 { 02657 if (value == NULL) 02658 return (-1); 02659 if (xmlStrEqual(type, BAD_CAST "string")) 02660 return (1); 02661 if (xmlStrEqual(type, BAD_CAST "token")) { 02662 return (1); 02663 } 02664 02665 return (0); 02666 } 02667 02680 static int 02681 xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED, 02682 const xmlChar * type, 02683 const xmlChar * value1, 02684 xmlNodePtr ctxt1 ATTRIBUTE_UNUSED, 02685 void *comp1 ATTRIBUTE_UNUSED, 02686 const xmlChar * value2, 02687 xmlNodePtr ctxt2 ATTRIBUTE_UNUSED) 02688 { 02689 int ret = -1; 02690 02691 if (xmlStrEqual(type, BAD_CAST "string")) { 02692 ret = xmlStrEqual(value1, value2); 02693 } else if (xmlStrEqual(type, BAD_CAST "token")) { 02694 if (!xmlStrEqual(value1, value2)) { 02695 xmlChar *nval, *nvalue; 02696 02697 /* 02698 * TODO: trivial optimizations are possible by 02699 * computing at compile-time 02700 */ 02701 nval = xmlRelaxNGNormalize(NULL, value1); 02702 nvalue = xmlRelaxNGNormalize(NULL, value2); 02703 02704 if ((nval == NULL) || (nvalue == NULL)) 02705 ret = -1; 02706 else if (xmlStrEqual(nval, nvalue)) 02707 ret = 1; 02708 else 02709 ret = 0; 02710 if (nval != NULL) 02711 xmlFree(nval); 02712 if (nvalue != NULL) 02713 xmlFree(nvalue); 02714 } else 02715 ret = 1; 02716 } 02717 return (ret); 02718 } 02719 02720 static int xmlRelaxNGTypeInitialized = 0; 02721 static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL; 02722 02730 static void 02731 xmlRelaxNGFreeTypeLibrary(xmlRelaxNGTypeLibraryPtr lib, 02732 const xmlChar * namespace ATTRIBUTE_UNUSED) 02733 { 02734 if (lib == NULL) 02735 return; 02736 if (lib->namespace != NULL) 02737 xmlFree((xmlChar *) lib->namespace); 02738 xmlFree(lib); 02739 } 02740 02753 static int 02754 xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data, 02755 xmlRelaxNGTypeHave have, 02756 xmlRelaxNGTypeCheck check, 02757 xmlRelaxNGTypeCompare comp, 02758 xmlRelaxNGFacetCheck facet, 02759 xmlRelaxNGTypeFree freef) 02760 { 02761 xmlRelaxNGTypeLibraryPtr lib; 02762 int ret; 02763 02764 if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) || 02765 (check == NULL) || (comp == NULL)) 02766 return (-1); 02767 if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) { 02768 xmlGenericError(xmlGenericErrorContext, 02769 "Relax-NG types library '%s' already registered\n", 02770 namespace); 02771 return (-1); 02772 } 02773 lib = 02774 (xmlRelaxNGTypeLibraryPtr) 02775 xmlMalloc(sizeof(xmlRelaxNGTypeLibrary)); 02776 if (lib == NULL) { 02777 xmlRngVErrMemory(NULL, "adding types library\n"); 02778 return (-1); 02779 } 02780 memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary)); 02781 lib->namespace = xmlStrdup(namespace); 02782 lib->data = data; 02783 lib->have = have; 02784 lib->comp = comp; 02785 lib->check = check; 02786 lib->facet = facet; 02787 lib->freef = freef; 02788 ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib); 02789 if (ret < 0) { 02790 xmlGenericError(xmlGenericErrorContext, 02791 "Relax-NG types library failed to register '%s'\n", 02792 namespace); 02793 xmlRelaxNGFreeTypeLibrary(lib, namespace); 02794 return (-1); 02795 } 02796 return (0); 02797 } 02798 02806 int 02807 xmlRelaxNGInitTypes(void) 02808 { 02809 if (xmlRelaxNGTypeInitialized != 0) 02810 return (0); 02811 xmlRelaxNGRegisteredTypes = xmlHashCreate(10); 02812 if (xmlRelaxNGRegisteredTypes == NULL) { 02813 xmlGenericError(xmlGenericErrorContext, 02814 "Failed to allocate sh table for Relax-NG types\n"); 02815 return (-1); 02816 } 02817 xmlRelaxNGRegisterTypeLibrary(BAD_CAST 02818 "http://www.w3.org/2001/XMLSchema-datatypes", 02819 NULL, xmlRelaxNGSchemaTypeHave, 02820 xmlRelaxNGSchemaTypeCheck, 02821 xmlRelaxNGSchemaTypeCompare, 02822 xmlRelaxNGSchemaFacetCheck, 02823 xmlRelaxNGSchemaFreeValue); 02824 xmlRelaxNGRegisterTypeLibrary(xmlRelaxNGNs, NULL, 02825 xmlRelaxNGDefaultTypeHave, 02826 xmlRelaxNGDefaultTypeCheck, 02827 xmlRelaxNGDefaultTypeCompare, NULL, 02828 NULL); 02829 xmlRelaxNGTypeInitialized = 1; 02830 return (0); 02831 } 02832 02838 void 02839 xmlRelaxNGCleanupTypes(void) 02840 { 02841 xmlSchemaCleanupTypes(); 02842 if (xmlRelaxNGTypeInitialized == 0) 02843 return; 02844 xmlHashFree(xmlRelaxNGRegisteredTypes, (xmlHashDeallocator) 02845 xmlRelaxNGFreeTypeLibrary); 02846 xmlRelaxNGTypeInitialized = 0; 02847 } 02848 02849 /************************************************************************ 02850 * * 02851 * Compiling element content into regexp * 02852 * * 02853 * Sometime the element content can be compiled into a pure regexp, * 02854 * This allows a faster execution and streamability at that level * 02855 * * 02856 ************************************************************************/ 02857 02858 /* from automata.c but not exported */ 02859 void xmlAutomataSetFlags(xmlAutomataPtr am, int flags); 02860 02861 02862 static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, 02863 xmlRelaxNGDefinePtr def); 02864 02873 static int 02874 xmlRelaxNGIsCompileable(xmlRelaxNGDefinePtr def) 02875 { 02876 int ret = -1; 02877 02878 if (def == NULL) { 02879 return (-1); 02880 } 02881 if ((def->type != XML_RELAXNG_ELEMENT) && 02882 (def->dflags & IS_COMPILABLE)) 02883 return (1); 02884 if ((def->type != XML_RELAXNG_ELEMENT) && 02885 (def->dflags & IS_NOT_COMPILABLE)) 02886 return (0); 02887 switch (def->type) { 02888 case XML_RELAXNG_NOOP: 02889 ret = xmlRelaxNGIsCompileable(def->content); 02890 break; 02891 case XML_RELAXNG_TEXT: 02892 case XML_RELAXNG_EMPTY: 02893 ret = 1; 02894 break; 02895 case XML_RELAXNG_ELEMENT: 02896 /* 02897 * Check if the element content is compileable 02898 */ 02899 if (((def->dflags & IS_NOT_COMPILABLE) == 0) && 02900 ((def->dflags & IS_COMPILABLE) == 0)) { 02901 xmlRelaxNGDefinePtr list; 02902 02903 list = def->content; 02904 while (list != NULL) { 02905 ret = xmlRelaxNGIsCompileable(list); 02906 if (ret != 1) 02907 break; 02908 list = list->next; 02909 } 02910 /* 02911 * Because the routine is recursive, we must guard against 02912 * discovering both COMPILABLE and NOT_COMPILABLE 02913 */ 02914 if (ret == 0) { 02915 def->dflags &= ~IS_COMPILABLE; 02916 def->dflags |= IS_NOT_COMPILABLE; 02917 } 02918 if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE)) 02919 def->dflags |= IS_COMPILABLE; 02920 #ifdef DEBUG_COMPILE 02921 if (ret == 1) { 02922 xmlGenericError(xmlGenericErrorContext, 02923 "element content for %s is compilable\n", 02924 def->name); 02925 } else if (ret == 0) { 02926 xmlGenericError(xmlGenericErrorContext, 02927 "element content for %s is not compilable\n", 02928 def->name); 02929 } else { 02930 xmlGenericError(xmlGenericErrorContext, 02931 "Problem in RelaxNGIsCompileable for element %s\n", 02932 def->name); 02933 } 02934 #endif 02935 } 02936 /* 02937 * All elements return a compileable status unless they 02938 * are generic like anyName 02939 */ 02940 if ((def->nameClass != NULL) || (def->name == NULL)) 02941 ret = 0; 02942 else 02943 ret = 1; 02944 return (ret); 02945 case XML_RELAXNG_REF: 02946 case XML_RELAXNG_EXTERNALREF: 02947 case XML_RELAXNG_PARENTREF: 02948 if (def->depth == -20) { 02949 return (1); 02950 } else { 02951 xmlRelaxNGDefinePtr list; 02952 02953 def->depth = -20; 02954 list = def->content; 02955 while (list != NULL) { 02956 ret = xmlRelaxNGIsCompileable(list); 02957 if (ret != 1) 02958 break; 02959 list = list->next; 02960 } 02961 } 02962 break; 02963 case XML_RELAXNG_START: 02964 case XML_RELAXNG_OPTIONAL: 02965 case XML_RELAXNG_ZEROORMORE: 02966 case XML_RELAXNG_ONEORMORE: 02967 case XML_RELAXNG_CHOICE: 02968 case XML_RELAXNG_GROUP: 02969 case XML_RELAXNG_DEF:{ 02970 xmlRelaxNGDefinePtr list; 02971 02972 list = def->content; 02973 while (list != NULL) { 02974 ret = xmlRelaxNGIsCompileable(list); 02975 if (ret != 1) 02976 break; 02977 list = list->next; 02978 } 02979 break; 02980 } 02981 case XML_RELAXNG_EXCEPT: 02982 case XML_RELAXNG_ATTRIBUTE: 02983 case XML_RELAXNG_INTERLEAVE: 02984 case XML_RELAXNG_DATATYPE: 02985 case XML_RELAXNG_LIST: 02986 case XML_RELAXNG_PARAM: 02987 case XML_RELAXNG_VALUE: 02988 case XML_RELAXNG_NOT_ALLOWED: 02989 ret = 0; 02990 break; 02991 } 02992 if (ret == 0) 02993 def->dflags |= IS_NOT_COMPILABLE; 02994 if (ret == 1) 02995 def->dflags |= IS_COMPILABLE; 02996 #ifdef DEBUG_COMPILE 02997 if (ret == 1) { 02998 xmlGenericError(xmlGenericErrorContext, 02999 "RelaxNGIsCompileable %s : true\n", 03000 xmlRelaxNGDefName(def)); 03001 } else if (ret == 0) { 03002 xmlGenericError(xmlGenericErrorContext, 03003 "RelaxNGIsCompileable %s : false\n", 03004 xmlRelaxNGDefName(def)); 03005 } else { 03006 xmlGenericError(xmlGenericErrorContext, 03007 "Problem in RelaxNGIsCompileable %s\n", 03008 xmlRelaxNGDefName(def)); 03009 } 03010 #endif 03011 return (ret); 03012 } 03013 03024 static int 03025 xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) 03026 { 03027 int ret = 0; 03028 xmlRelaxNGDefinePtr list; 03029 03030 if ((ctxt == NULL) || (def == NULL)) 03031 return (-1); 03032 03033 switch (def->type) { 03034 case XML_RELAXNG_START: 03035 if ((xmlRelaxNGIsCompileable(def) == 1) && (def->depth != -25)) { 03036 xmlAutomataPtr oldam = ctxt->am; 03037 xmlAutomataStatePtr oldstate = ctxt->state; 03038 03039 def->depth = -25; 03040 03041 list = def->content; 03042 ctxt->am = xmlNewAutomata(); 03043 if (ctxt->am == NULL) 03044 return (-1); 03045 03046 /* 03047 * assume identical strings but not same pointer are different 03048 * atoms, needed for non-determinism detection 03049 * That way if 2 elements with the same name are in a choice 03050 * branch the automata is found non-deterministic and 03051 * we fallback to the normal validation which does the right 03052 * thing of exploring both choices. 03053 */ 03054 xmlAutomataSetFlags(ctxt->am, 1); 03055 03056 ctxt->state = xmlAutomataGetInitState(ctxt->am); 03057 while (list != NULL) { 03058 xmlRelaxNGCompile(ctxt, list); 03059 list = list->next; 03060 } 03061 xmlAutomataSetFinalState(ctxt->am, ctxt->state); 03062 def->contModel = xmlAutomataCompile(ctxt->am); 03063 xmlRegexpIsDeterminist(def->contModel); 03064 03065 xmlFreeAutomata(ctxt->am); 03066 ctxt->state = oldstate; 03067 ctxt->am = oldam; 03068 } 03069 break; 03070 case XML_RELAXNG_ELEMENT: 03071 if ((ctxt->am != NULL) && (def->name != NULL)) { 03072 ctxt->state = xmlAutomataNewTransition2(ctxt->am, 03073 ctxt->state, NULL, 03074 def->name, def->ns, 03075 def); 03076 } 03077 if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) { 03078 xmlAutomataPtr oldam = ctxt->am; 03079 xmlAutomataStatePtr oldstate = ctxt->state; 03080 03081 def->depth = -25; 03082 03083 list = def->content; 03084 ctxt->am = xmlNewAutomata(); 03085 if (ctxt->am == NULL) 03086 return (-1); 03087 xmlAutomataSetFlags(ctxt->am, 1); 03088 ctxt->state = xmlAutomataGetInitState(ctxt->am); 03089 while (list != NULL) { 03090 xmlRelaxNGCompile(ctxt, list); 03091 list = list->next; 03092 } 03093 xmlAutomataSetFinalState(ctxt->am, ctxt->state); 03094 def->contModel = xmlAutomataCompile(ctxt->am); 03095 if (!xmlRegexpIsDeterminist(def->contModel)) { 03096 #ifdef DEBUG_COMPILE 03097 xmlGenericError(xmlGenericErrorContext, 03098 "Content model not determinist %s\n", 03099 def->name); 03100 #endif 03101 /* 03102 * we can only use the automata if it is determinist 03103 */ 03104 xmlRegFreeRegexp(def->contModel); 03105 def->contModel = NULL; 03106 } 03107 xmlFreeAutomata(ctxt->am); 03108 ctxt->state = oldstate; 03109 ctxt->am = oldam; 03110 } else { 03111 xmlAutomataPtr oldam = ctxt->am; 03112 03113 /* 03114 * we can't build the content model for this element content 03115 * but it still might be possible to build it for some of its 03116 * children, recurse. 03117 */ 03118 ret = xmlRelaxNGTryCompile(ctxt, def); 03119 ctxt->am = oldam; 03120 } 03121 break; 03122 case XML_RELAXNG_NOOP: 03123 ret = xmlRelaxNGCompile(ctxt, def->content); 03124 break; 03125 case XML_RELAXNG_OPTIONAL:{ 03126 xmlAutomataStatePtr oldstate = ctxt->state; 03127 03128 list = def->content; 03129 while (list != NULL) { 03130 xmlRelaxNGCompile(ctxt, list); 03131 list = list->next; 03132 } 03133 xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state); 03134 break; 03135 } 03136 case XML_RELAXNG_ZEROORMORE:{ 03137 xmlAutomataStatePtr oldstate; 03138 03139 ctxt->state = 03140 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL); 03141 oldstate = ctxt->state; 03142 list = def->content; 03143 while (list != NULL) { 03144 xmlRelaxNGCompile(ctxt, list); 03145 list = list->next; 03146 } 03147 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate); 03148 ctxt->state = 03149 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL); 03150 break; 03151 } 03152 case XML_RELAXNG_ONEORMORE:{ 03153 xmlAutomataStatePtr oldstate; 03154 03155 list = def->content; 03156 while (list != NULL) { 03157 xmlRelaxNGCompile(ctxt, list); 03158 list = list->next; 03159 } 03160 oldstate = ctxt->state; 03161 list = def->content; 03162 while (list != NULL) { 03163 xmlRelaxNGCompile(ctxt, list); 03164 list = list->next; 03165 } 03166 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate); 03167 ctxt->state = 03168 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL); 03169 break; 03170 } 03171 case XML_RELAXNG_CHOICE:{ 03172 xmlAutomataStatePtr target = NULL; 03173 xmlAutomataStatePtr oldstate = ctxt->state; 03174 03175 list = def->content; 03176 while (list != NULL) { 03177 ctxt->state = oldstate; 03178 ret = xmlRelaxNGCompile(ctxt, list); 03179 if (ret != 0) 03180 break; 03181 if (target == NULL) 03182 target = ctxt->state; 03183 else { 03184 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, 03185 target); 03186 } 03187 list = list->next; 03188 } 03189 ctxt->state = target; 03190 03191 break; 03192 } 03193 case XML_RELAXNG_REF: 03194 case XML_RELAXNG_EXTERNALREF: 03195 case XML_RELAXNG_PARENTREF: 03196 case XML_RELAXNG_GROUP: 03197 case XML_RELAXNG_DEF: 03198 list = def->content; 03199 while (list != NULL) { 03200 ret = xmlRelaxNGCompile(ctxt, list); 03201 if (ret != 0) 03202 break; 03203 list = list->next; 03204 } 03205 break; 03206 case XML_RELAXNG_TEXT:{ 03207 xmlAutomataStatePtr oldstate; 03208 03209 ctxt->state = 03210 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL); 03211 oldstate = ctxt->state; 03212 xmlRelaxNGCompile(ctxt, def->content); 03213 xmlAutomataNewTransition(ctxt->am, ctxt->state, 03214 ctxt->state, BAD_CAST "#text", 03215 NULL); 03216 ctxt->state = 03217 xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL); 03218 break; 03219 } 03220 case XML_RELAXNG_EMPTY: 03221 ctxt->state = 03222 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL); 03223 break; 03224 case XML_RELAXNG_EXCEPT: 03225 case XML_RELAXNG_ATTRIBUTE: 03226 case XML_RELAXNG_INTERLEAVE: 03227 case XML_RELAXNG_NOT_ALLOWED: 03228 case XML_RELAXNG_DATATYPE: 03229 case XML_RELAXNG_LIST: 03230 case XML_RELAXNG_PARAM: 03231 case XML_RELAXNG_VALUE: 03232 /* This should not happen and generate an internal error */ 03233 fprintf(stderr, "RNG internal error trying to compile %s\n", 03234 xmlRelaxNGDefName(def)); 03235 break; 03236 } 03237 return (ret); 03238 } 03239 03250 static int 03251 xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) 03252 { 03253 int ret = 0; 03254 xmlRelaxNGDefinePtr list; 03255 03256 if ((ctxt == NULL) || (def == NULL)) 03257 return (-1); 03258 03259 if ((def->type == XML_RELAXNG_START) || 03260 (def->type == XML_RELAXNG_ELEMENT)) { 03261 ret = xmlRelaxNGIsCompileable(def); 03262 if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) { 03263 ctxt->am = NULL; 03264 ret = xmlRelaxNGCompile(ctxt, def); 03265 #ifdef DEBUG_PROGRESSIVE 03266 if (ret == 0) { 03267 if (def->type == XML_RELAXNG_START) 03268 xmlGenericError(xmlGenericErrorContext, 03269 "compiled the start\n"); 03270 else 03271 xmlGenericError(xmlGenericErrorContext, 03272 "compiled element %s\n", def->name); 03273 } else { 03274 if (def->type == XML_RELAXNG_START) 03275 xmlGenericError(xmlGenericErrorContext, 03276 "failed to compile the start\n"); 03277 else 03278 xmlGenericError(xmlGenericErrorContext, 03279 "failed to compile element %s\n", 03280 def->name); 03281 } 03282 #endif 03283 return (ret); 03284 } 03285 } 03286 switch (def->type) { 03287 case XML_RELAXNG_NOOP: 03288 ret = xmlRelaxNGTryCompile(ctxt, def->content); 03289 break; 03290 case XML_RELAXNG_TEXT: 03291 case XML_RELAXNG_DATATYPE: 03292 case XML_RELAXNG_LIST: 03293 case XML_RELAXNG_PARAM: 03294 case XML_RELAXNG_VALUE: 03295 case XML_RELAXNG_EMPTY: 03296 case XML_RELAXNG_ELEMENT: 03297 ret = 0; 03298 break; 03299 case XML_RELAXNG_OPTIONAL: 03300 case XML_RELAXNG_ZEROORMORE: 03301 case XML_RELAXNG_ONEORMORE: 03302 case XML_RELAXNG_CHOICE: 03303 case XML_RELAXNG_GROUP: 03304 case XML_RELAXNG_DEF: 03305 case XML_RELAXNG_START: 03306 case XML_RELAXNG_REF: 03307 case XML_RELAXNG_EXTERNALREF: 03308 case XML_RELAXNG_PARENTREF: 03309 list = def->content; 03310 while (list != NULL) { 03311 ret = xmlRelaxNGTryCompile(ctxt, list); 03312 if (ret != 0) 03313 break; 03314 list = list->next; 03315 } 03316 break; 03317 case XML_RELAXNG_EXCEPT: 03318 case XML_RELAXNG_ATTRIBUTE: 03319 case XML_RELAXNG_INTERLEAVE: 03320 case XML_RELAXNG_NOT_ALLOWED: 03321 ret = 0; 03322 break; 03323 } 03324 return (ret); 03325 } 03326 03327 /************************************************************************ 03328 * * 03329 * Parsing functions * 03330 * * 03331 ************************************************************************/ 03332 03333 static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr 03334 ctxt, xmlNodePtr node); 03335 static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr 03336 ctxt, xmlNodePtr node); 03337 static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr 03338 ctxt, xmlNodePtr nodes, 03339 int group); 03340 static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr 03341 ctxt, xmlNodePtr node); 03342 static xmlRelaxNGPtr xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, 03343 xmlNodePtr node); 03344 static int xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt, 03345 xmlNodePtr nodes); 03346 static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr 03347 ctxt, xmlNodePtr node, 03348 xmlRelaxNGDefinePtr 03349 def); 03350 static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr 03351 ctxt, xmlNodePtr nodes); 03352 static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt, 03353 xmlRelaxNGDefinePtr define, 03354 xmlNodePtr elem); 03355 03356 03357 #define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content)) 03358 03367 static int 03368 xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define) 03369 { 03370 int ret; 03371 03372 if (define == NULL) 03373 return (-1); 03374 03375 if (define->dflags & IS_NULLABLE) 03376 return (1); 03377 if (define->dflags & IS_NOT_NULLABLE) 03378 return (0); 03379 switch (define->type) { 03380 case XML_RELAXNG_EMPTY: 03381 case XML_RELAXNG_TEXT: 03382 ret = 1; 03383 break; 03384 case XML_RELAXNG_NOOP: 03385 case XML_RELAXNG_DEF: 03386 case XML_RELAXNG_REF: 03387 case XML_RELAXNG_EXTERNALREF: 03388 case XML_RELAXNG_PARENTREF: 03389 case XML_RELAXNG_ONEORMORE: 03390 ret = xmlRelaxNGIsNullable(define->content); 03391 break; 03392 case XML_RELAXNG_EXCEPT: 03393 case XML_RELAXNG_NOT_ALLOWED: 03394 case XML_RELAXNG_ELEMENT: 03395 case XML_RELAXNG_DATATYPE: 03396 case XML_RELAXNG_PARAM: 03397 case XML_RELAXNG_VALUE: 03398 case XML_RELAXNG_LIST: 03399 case XML_RELAXNG_ATTRIBUTE: 03400 ret = 0; 03401 break; 03402 case XML_RELAXNG_CHOICE:{ 03403 xmlRelaxNGDefinePtr list = define->content; 03404 03405 while (list != NULL) { 03406 ret = xmlRelaxNGIsNullable(list); 03407 if (ret != 0) 03408 goto done; 03409 list = list->next; 03410 } 03411 ret = 0; 03412 break; 03413 } 03414 case XML_RELAXNG_START: 03415 case XML_RELAXNG_INTERLEAVE: 03416 case XML_RELAXNG_GROUP:{ 03417 xmlRelaxNGDefinePtr list = define->content; 03418 03419 while (list != NULL) { 03420 ret = xmlRelaxNGIsNullable(list); 03421 if (ret != 1) 03422 goto done; 03423 list = list->next; 03424 } 03425 return (1); 03426 } 03427 default: 03428 return (-1); 03429 } 03430 done: 03431 if (ret == 0) 03432 define->dflags |= IS_NOT_NULLABLE; 03433 if (ret == 1) 03434 define->dflags |= IS_NULLABLE; 03435 return (ret); 03436 } 03437 03446 static int 03447 xmlRelaxNGIsBlank(xmlChar * str) 03448 { 03449 if (str == NULL) 03450 return (1); 03451 while (*str != 0) { 03452 if (!(IS_BLANK_CH(*str))) 03453 return (0); 03454 str++; 03455 } 03456 return (1); 03457 } 03458 03468 static xmlChar * 03469 xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, 03470 xmlNodePtr node) 03471 { 03472 xmlChar *ret, *escape; 03473 03474 if (node == NULL) 03475 return(NULL); 03476 03477 if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) { 03478 ret = xmlGetProp(node, BAD_CAST "datatypeLibrary"); 03479 if (ret != NULL) { 03480 if (ret[0] == 0) { 03481 xmlFree(ret); 03482 return (NULL); 03483 } 03484 escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?"); 03485 if (escape == NULL) { 03486 return (ret); 03487 } 03488 xmlFree(ret); 03489 return (escape); 03490 } 03491 } 03492 node = node->parent; 03493 while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) { 03494 ret = xmlGetProp(node, BAD_CAST "datatypeLibrary"); 03495 if (ret != NULL) { 03496 if (ret[0] == 0) { 03497 xmlFree(ret); 03498 return (NULL); 03499 } 03500 escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?"); 03501 if (escape == NULL) { 03502 return (ret); 03503 } 03504 xmlFree(ret); 03505 return (escape); 03506 } 03507 node = node->parent; 03508 } 03509 return (NULL); 03510 } 03511 03521 static xmlRelaxNGDefinePtr 03522 xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 03523 { 03524 xmlRelaxNGDefinePtr def = NULL; 03525 xmlRelaxNGTypeLibraryPtr lib = NULL; 03526 xmlChar *type; 03527 xmlChar *library; 03528 int success = 0; 03529 03530 def = xmlRelaxNGNewDefine(ctxt, node); 03531 if (def == NULL) 03532 return (NULL); 03533 def->type = XML_RELAXNG_VALUE; 03534 03535 type = xmlGetProp(node, BAD_CAST "type"); 03536 if (type != NULL) { 03537 xmlRelaxNGNormExtSpace(type); 03538 if (xmlValidateNCName(type, 0)) { 03539 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE, 03540 "value type '%s' is not an NCName\n", type, NULL); 03541 } 03542 library = xmlRelaxNGGetDataTypeLibrary(ctxt, node); 03543 if (library == NULL) 03544 library = 03545 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0"); 03546 03547 def->name = type; 03548 def->ns = library; 03549 03550 lib = (xmlRelaxNGTypeLibraryPtr) 03551 xmlHashLookup(xmlRelaxNGRegisteredTypes, library); 03552 if (lib == NULL) { 03553 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB, 03554 "Use of unregistered type library '%s'\n", library, 03555 NULL); 03556 def->data = NULL; 03557 } else { 03558 def->data = lib; 03559 if (lib->have == NULL) { 03560 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB, 03561 "Internal error with type library '%s': no 'have'\n", 03562 library, NULL); 03563 } else { 03564 success = lib->have(lib->data, def->name); 03565 if (success != 1) { 03566 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND, 03567 "Error type '%s' is not exported by type library '%s'\n", 03568 def->name, library); 03569 } 03570 } 03571 } 03572 } 03573 if (node->children == NULL) { 03574 def->value = xmlStrdup(BAD_CAST ""); 03575 } else if (((node->children->type != XML_TEXT_NODE) && 03576 (node->children->type != XML_CDATA_SECTION_NODE)) || 03577 (node->children->next != NULL)) { 03578 xmlRngPErr(ctxt, node, XML_RNGP_TEXT_EXPECTED, 03579 "Expecting a single text value for <value>content\n", 03580 NULL, NULL); 03581 } else if (def != NULL) { 03582 def->value = xmlNodeGetContent(node); 03583 if (def->value == NULL) { 03584 xmlRngPErr(ctxt, node, XML_RNGP_VALUE_NO_CONTENT, 03585 "Element <value> has no content\n", NULL, NULL); 03586 } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) { 03587 void *val = NULL; 03588 03589 success = 03590 lib->check(lib->data, def->name, def->value, &val, node); 03591 if (success != 1) { 03592 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_VALUE, 03593 "Value '%s' is not acceptable for type '%s'\n", 03594 def->value, def->name); 03595 } else { 03596 if (val != NULL) 03597 def->attrs = val; 03598 } 03599 } 03600 } 03601 return (def); 03602 } 03603 03613 static xmlRelaxNGDefinePtr 03614 xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 03615 { 03616 xmlRelaxNGDefinePtr def = NULL, except; 03617 xmlRelaxNGDefinePtr param, lastparam = NULL; 03618 xmlRelaxNGTypeLibraryPtr lib; 03619 xmlChar *type; 03620 xmlChar *library; 03621 xmlNodePtr content; 03622 int tmp; 03623 03624 type = xmlGetProp(node, BAD_CAST "type"); 03625 if (type == NULL) { 03626 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_MISSING, "data has no type\n", NULL, 03627 NULL); 03628 return (NULL); 03629 } 03630 xmlRelaxNGNormExtSpace(type); 03631 if (xmlValidateNCName(type, 0)) { 03632 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE, 03633 "data type '%s' is not an NCName\n", type, NULL); 03634 } 03635 library = xmlRelaxNGGetDataTypeLibrary(ctxt, node); 03636 if (library == NULL) 03637 library = 03638 xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0"); 03639 03640 def = xmlRelaxNGNewDefine(ctxt, node); 03641 if (def == NULL) { 03642 xmlFree(type); 03643 return (NULL); 03644 } 03645 def->type = XML_RELAXNG_DATATYPE; 03646 def->name = type; 03647 def->ns = library; 03648 03649 lib = (xmlRelaxNGTypeLibraryPtr) 03650 xmlHashLookup(xmlRelaxNGRegisteredTypes, library); 03651 if (lib == NULL) { 03652 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB, 03653 "Use of unregistered type library '%s'\n", library, 03654 NULL); 03655 def->data = NULL; 03656 } else { 03657 def->data = lib; 03658 if (lib->have == NULL) { 03659 xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB, 03660 "Internal error with type library '%s': no 'have'\n", 03661 library, NULL); 03662 } else { 03663 tmp = lib->have(lib->data, def->name); 03664 if (tmp != 1) { 03665 xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND, 03666 "Error type '%s' is not exported by type library '%s'\n", 03667 def->name, library); 03668 } else 03669 if ((xmlStrEqual 03670 (library, 03671 BAD_CAST 03672 "http://www.w3.org/2001/XMLSchema-datatypes")) 03673 && ((xmlStrEqual(def->name, BAD_CAST "IDREF")) 03674 || (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) { 03675 ctxt->idref = 1; 03676 } 03677 } 03678 } 03679 content = node->children; 03680 03681 /* 03682 * Handle optional params 03683 */ 03684 while (content != NULL) { 03685 if (!xmlStrEqual(content->name, BAD_CAST "param")) 03686 break; 03687 if (xmlStrEqual(library, 03688 BAD_CAST "http://relaxng.org/ns/structure/1.0")) { 03689 xmlRngPErr(ctxt, node, XML_RNGP_PARAM_FORBIDDEN, 03690 "Type library '%s' does not allow type parameters\n", 03691 library, NULL); 03692 content = content->next; 03693 while ((content != NULL) && 03694 (xmlStrEqual(content->name, BAD_CAST "param"))) 03695 content = content->next; 03696 } else { 03697 param = xmlRelaxNGNewDefine(ctxt, node); 03698 if (param != NULL) { 03699 param->type = XML_RELAXNG_PARAM; 03700 param->name = xmlGetProp(content, BAD_CAST "name"); 03701 if (param->name == NULL) { 03702 xmlRngPErr(ctxt, node, XML_RNGP_PARAM_NAME_MISSING, 03703 "param has no name\n", NULL, NULL); 03704 } 03705 param->value = xmlNodeGetContent(content); 03706 if (lastparam == NULL) { 03707 def->attrs = lastparam = param; 03708 } else { 03709 lastparam->next = param; 03710 lastparam = param; 03711 } 03712 if (lib != NULL) { 03713 } 03714 } 03715 content = content->next; 03716 } 03717 } 03718 /* 03719 * Handle optional except 03720 */ 03721 if ((content != NULL) 03722 && (xmlStrEqual(content->name, BAD_CAST "except"))) { 03723 xmlNodePtr child; 03724 xmlRelaxNGDefinePtr tmp2, last = NULL; 03725 03726 except = xmlRelaxNGNewDefine(ctxt, node); 03727 if (except == NULL) { 03728 return (def); 03729 } 03730 except->type = XML_RELAXNG_EXCEPT; 03731 child = content->children; 03732 def->content = except; 03733 if (child == NULL) { 03734 xmlRngPErr(ctxt, content, XML_RNGP_EXCEPT_NO_CONTENT, 03735 "except has no content\n", NULL, NULL); 03736 } 03737 while (child != NULL) { 03738 tmp2 = xmlRelaxNGParsePattern(ctxt, child); 03739 if (tmp2 != NULL) { 03740 if (last == NULL) { 03741 except->content = last = tmp2; 03742 } else { 03743 last->next = tmp2; 03744 last = tmp2; 03745 } 03746 } 03747 child = child->next; 03748 } 03749 content = content->next; 03750 } 03751 /* 03752 * Check there is no unhandled data 03753 */ 03754 if (content != NULL) { 03755 xmlRngPErr(ctxt, content, XML_RNGP_DATA_CONTENT, 03756 "Element data has unexpected content %s\n", 03757 content->name, NULL); 03758 } 03759 03760 return (def); 03761 } 03762 03763 static const xmlChar *invalidName = BAD_CAST "\1"; 03764 03778 static int 03779 xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1, 03780 xmlRelaxNGDefinePtr def2) 03781 { 03782 int ret = 1; 03783 xmlNode node; 03784 xmlNs ns; 03785 xmlRelaxNGValidCtxt ctxt; 03786 03787 memset(&ctxt, 0, sizeof(xmlRelaxNGValidCtxt)); 03788 03789 ctxt.flags = FLAGS_IGNORABLE | FLAGS_NOERROR; 03790 03791 if ((def1->type == XML_RELAXNG_ELEMENT) || 03792 (def1->type == XML_RELAXNG_ATTRIBUTE)) { 03793 if (def2->type == XML_RELAXNG_TEXT) 03794 return (1); 03795 if (def1->name != NULL) { 03796 node.name = def1->name; 03797 } else { 03798 node.name = invalidName; 03799 } 03800 if (def1->ns != NULL) { 03801 if (def1->ns[0] == 0) { 03802 node.ns = NULL; 03803 } else { 03804 node.ns = &ns; 03805 ns.href = def1->ns; 03806 } 03807 } else { 03808 node.ns = NULL; 03809 } 03810 if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) { 03811 if (def1->nameClass != NULL) { 03812 ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2); 03813 } else { 03814 ret = 0; 03815 } 03816 } else { 03817 ret = 1; 03818 } 03819 } else if (def1->type == XML_RELAXNG_TEXT) { 03820 if (def2->type == XML_RELAXNG_TEXT) 03821 return (0); 03822 return (1); 03823 } else if (def1->type == XML_RELAXNG_EXCEPT) { 03824 TODO ret = 0; 03825 } else { 03826 TODO ret = 0; 03827 } 03828 if (ret == 0) 03829 return (ret); 03830 if ((def2->type == XML_RELAXNG_ELEMENT) || 03831 (def2->type == XML_RELAXNG_ATTRIBUTE)) { 03832 if (def2->name != NULL) { 03833 node.name = def2->name; 03834 } else { 03835 node.name = invalidName; 03836 } 03837 node.ns = &ns; 03838 if (def2->ns != NULL) { 03839 if (def2->ns[0] == 0) { 03840 node.ns = NULL; 03841 } else { 03842 ns.href = def2->ns; 03843 } 03844 } else { 03845 ns.href = invalidName; 03846 } 03847 if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) { 03848 if (def2->nameClass != NULL) { 03849 ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1); 03850 } else { 03851 ret = 0; 03852 } 03853 } else { 03854 ret = 1; 03855 } 03856 } else { 03857 TODO ret = 0; 03858 } 03859 03860 return (ret); 03861 } 03862 03875 static int 03876 xmlRelaxNGCompareElemDefLists(xmlRelaxNGParserCtxtPtr ctxt 03877 ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr * def1, 03878 xmlRelaxNGDefinePtr * def2) 03879 { 03880 xmlRelaxNGDefinePtr *basedef2 = def2; 03881 03882 if ((def1 == NULL) || (def2 == NULL)) 03883 return (1); 03884 if ((*def1 == NULL) || (*def2 == NULL)) 03885 return (1); 03886 while (*def1 != NULL) { 03887 while ((*def2) != NULL) { 03888 if (xmlRelaxNGCompareNameClasses(*def1, *def2) == 0) 03889 return (0); 03890 def2++; 03891 } 03892 def2 = basedef2; 03893 def1++; 03894 } 03895 return (1); 03896 } 03897 03907 static int 03908 xmlRelaxNGGenerateAttributes(xmlRelaxNGParserCtxtPtr ctxt, 03909 xmlRelaxNGDefinePtr def) 03910 { 03911 xmlRelaxNGDefinePtr parent, cur, tmp; 03912 03913 /* 03914 * Don't run that check in case of error. Infinite recursion 03915 * becomes possible. 03916 */ 03917 if (ctxt->nbErrors != 0) 03918 return (-1); 03919 03920 parent = NULL; 03921 cur = def; 03922 while (cur != NULL) { 03923 if ((cur->type == XML_RELAXNG_ELEMENT) || 03924 (cur->type == XML_RELAXNG_TEXT) || 03925 (cur->type == XML_RELAXNG_DATATYPE) || 03926 (cur->type == XML_RELAXNG_PARAM) || 03927 (cur->type == XML_RELAXNG_LIST) || 03928 (cur->type == XML_RELAXNG_VALUE) || 03929 (cur->type == XML_RELAXNG_EMPTY)) 03930 return (0); 03931 if ((cur->type == XML_RELAXNG_CHOICE) || 03932 (cur->type == XML_RELAXNG_INTERLEAVE) || 03933 (cur->type == XML_RELAXNG_GROUP) || 03934 (cur->type == XML_RELAXNG_ONEORMORE) || 03935 (cur->type == XML_RELAXNG_ZEROORMORE) || 03936 (cur->type == XML_RELAXNG_OPTIONAL) || 03937 (cur->type == XML_RELAXNG_PARENTREF) || 03938 (cur->type == XML_RELAXNG_EXTERNALREF) || 03939 (cur->type == XML_RELAXNG_REF) || 03940 (cur->type == XML_RELAXNG_DEF)) { 03941 if (cur->content != NULL) { 03942 parent = cur; 03943 cur = cur->content; 03944 tmp = cur; 03945 while (tmp != NULL) { 03946 tmp->parent = parent; 03947 tmp = tmp->next; 03948 } 03949 continue; 03950 } 03951 } 03952 if (cur == def) 03953 break; 03954 if (cur->next != NULL) { 03955 cur = cur->next; 03956 continue; 03957 } 03958 do { 03959 cur = cur->parent; 03960 if (cur == NULL) 03961 break; 03962 if (cur == def) 03963 return (1); 03964 if (cur->next != NULL) { 03965 cur = cur->next; 03966 break; 03967 } 03968 } while (cur != NULL); 03969 } 03970 return (1); 03971 } 03972 03983 static xmlRelaxNGDefinePtr * 03984 xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt, 03985 xmlRelaxNGDefinePtr def, int eora) 03986 { 03987 xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp; 03988 int len = 0; 03989 int max = 0; 03990 03991 /* 03992 * Don't run that check in case of error. Infinite recursion 03993 * becomes possible. 03994 */ 03995 if (ctxt->nbErrors != 0) 03996 return (NULL); 03997 03998 parent = NULL; 03999 cur = def; 04000 while (cur != NULL) { 04001 if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) || 04002 (cur->type == XML_RELAXNG_TEXT))) || 04003 ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE))) { 04004 if (ret == NULL) { 04005 max = 10; 04006 ret = (xmlRelaxNGDefinePtr *) 04007 xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr)); 04008 if (ret == NULL) { 04009 xmlRngPErrMemory(ctxt, "getting element list\n"); 04010 return (NULL); 04011 } 04012 } else if (max <= len) { 04013 xmlRelaxNGDefinePtr *temp; 04014 04015 max *= 2; 04016 temp = xmlRealloc(ret, 04017 (max + 1) * sizeof(xmlRelaxNGDefinePtr)); 04018 if (temp == NULL) { 04019 xmlRngPErrMemory(ctxt, "getting element list\n"); 04020 xmlFree(ret); 04021 return (NULL); 04022 } 04023 ret = temp; 04024 } 04025 ret[len++] = cur; 04026 ret[len] = NULL; 04027 } else if ((cur->type == XML_RELAXNG_CHOICE) || 04028 (cur->type == XML_RELAXNG_INTERLEAVE) || 04029 (cur->type == XML_RELAXNG_GROUP) || 04030 (cur->type == XML_RELAXNG_ONEORMORE) || 04031 (cur->type == XML_RELAXNG_ZEROORMORE) || 04032 (cur->type == XML_RELAXNG_OPTIONAL) || 04033 (cur->type == XML_RELAXNG_PARENTREF) || 04034 (cur->type == XML_RELAXNG_REF) || 04035 (cur->type == XML_RELAXNG_DEF) || 04036 (cur->type == XML_RELAXNG_EXTERNALREF)) { 04037 /* 04038 * Don't go within elements or attributes or string values. 04039 * Just gather the element top list 04040 */ 04041 if (cur->content != NULL) { 04042 parent = cur; 04043 cur = cur->content; 04044 tmp = cur; 04045 while (tmp != NULL) { 04046 tmp->parent = parent; 04047 tmp = tmp->next; 04048 } 04049 continue; 04050 } 04051 } 04052 if (cur == def) 04053 break; 04054 if (cur->next != NULL) { 04055 cur = cur->next; 04056 continue; 04057 } 04058 do { 04059 cur = cur->parent; 04060 if (cur == NULL) 04061 break; 04062 if (cur == def) 04063 return (ret); 04064 if (cur->next != NULL) { 04065 cur = cur->next; 04066 break; 04067 } 04068 } while (cur != NULL); 04069 } 04070 return (ret); 04071 } 04072 04080 static void 04081 xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt, 04082 xmlRelaxNGDefinePtr def) 04083 { 04084 xmlRelaxNGDefinePtr **list; 04085 xmlRelaxNGDefinePtr cur; 04086 int nbchild = 0, i, j, ret; 04087 int is_nullable = 0; 04088 int is_indeterminist = 0; 04089 xmlHashTablePtr triage = NULL; 04090 int is_triable = 1; 04091 04092 if ((def == NULL) || (def->type != XML_RELAXNG_CHOICE)) 04093 return; 04094 04095 if (def->dflags & IS_PROCESSED) 04096 return; 04097 04098 /* 04099 * Don't run that check in case of error. Infinite recursion 04100 * becomes possible. 04101 */ 04102 if (ctxt->nbErrors != 0) 04103 return; 04104 04105 is_nullable = xmlRelaxNGIsNullable(def); 04106 04107 cur = def->content; 04108 while (cur != NULL) { 04109 nbchild++; 04110 cur = cur->next; 04111 } 04112 04113 list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild * 04114 sizeof(xmlRelaxNGDefinePtr 04115 *)); 04116 if (list == NULL) { 04117 xmlRngPErrMemory(ctxt, "building choice\n"); 04118 return; 04119 } 04120 i = 0; 04121 /* 04122 * a bit strong but safe 04123 */ 04124 if (is_nullable == 0) { 04125 triage = xmlHashCreate(10); 04126 } else { 04127 is_triable = 0; 04128 } 04129 cur = def->content; 04130 while (cur != NULL) { 04131 list[i] = xmlRelaxNGGetElements(ctxt, cur, 0); 04132 if ((list[i] == NULL) || (list[i][0] == NULL)) { 04133 is_triable = 0; 04134 } else if (is_triable == 1) { 04135 xmlRelaxNGDefinePtr *tmp; 04136 int res; 04137 04138 tmp = list[i]; 04139 while ((*tmp != NULL) && (is_triable == 1)) { 04140 if ((*tmp)->type == XML_RELAXNG_TEXT) { 04141 res = xmlHashAddEntry2(triage, 04142 BAD_CAST "#text", NULL, 04143 (void *) cur); 04144 if (res != 0) 04145 is_triable = -1; 04146 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) && 04147 ((*tmp)->name != NULL)) { 04148 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0)) 04149 res = xmlHashAddEntry2(triage, 04150 (*tmp)->name, NULL, 04151 (void *) cur); 04152 else 04153 res = xmlHashAddEntry2(triage, 04154 (*tmp)->name, (*tmp)->ns, 04155 (void *) cur); 04156 if (res != 0) 04157 is_triable = -1; 04158 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) { 04159 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0)) 04160 res = xmlHashAddEntry2(triage, 04161 BAD_CAST "#any", NULL, 04162 (void *) cur); 04163 else 04164 res = xmlHashAddEntry2(triage, 04165 BAD_CAST "#any", (*tmp)->ns, 04166 (void *) cur); 04167 if (res != 0) 04168 is_triable = -1; 04169 } else { 04170 is_triable = -1; 04171 } 04172 tmp++; 04173 } 04174 } 04175 i++; 04176 cur = cur->next; 04177 } 04178 04179 for (i = 0; i < nbchild; i++) { 04180 if (list[i] == NULL) 04181 continue; 04182 for (j = 0; j < i; j++) { 04183 if (list[j] == NULL) 04184 continue; 04185 ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]); 04186 if (ret == 0) { 04187 is_indeterminist = 1; 04188 } 04189 } 04190 } 04191 for (i = 0; i < nbchild; i++) { 04192 if (list[i] != NULL) 04193 xmlFree(list[i]); 04194 } 04195 04196 xmlFree(list); 04197 if (is_indeterminist) { 04198 def->dflags |= IS_INDETERMINIST; 04199 } 04200 if (is_triable == 1) { 04201 def->dflags |= IS_TRIABLE; 04202 def->data = triage; 04203 } else if (triage != NULL) { 04204 xmlHashFree(triage, NULL); 04205 } 04206 def->dflags |= IS_PROCESSED; 04207 } 04208 04216 static void 04217 xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt, 04218 xmlRelaxNGDefinePtr def) 04219 { 04220 xmlRelaxNGDefinePtr **list; 04221 xmlRelaxNGDefinePtr cur; 04222 int nbchild = 0, i, j, ret; 04223 04224 if ((def == NULL) || 04225 ((def->type != XML_RELAXNG_GROUP) && 04226 (def->type != XML_RELAXNG_ELEMENT))) 04227 return; 04228 04229 if (def->dflags & IS_PROCESSED) 04230 return; 04231 04232 /* 04233 * Don't run that check in case of error. Infinite recursion 04234 * becomes possible. 04235 */ 04236 if (ctxt->nbErrors != 0) 04237 return; 04238 04239 cur = def->attrs; 04240 while (cur != NULL) { 04241 nbchild++; 04242 cur = cur->next; 04243 } 04244 cur = def->content; 04245 while (cur != NULL) { 04246 nbchild++; 04247 cur = cur->next; 04248 } 04249 04250 list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild * 04251 sizeof(xmlRelaxNGDefinePtr 04252 *)); 04253 if (list == NULL) { 04254 xmlRngPErrMemory(ctxt, "building group\n"); 04255 return; 04256 } 04257 i = 0; 04258 cur = def->attrs; 04259 while (cur != NULL) { 04260 list[i] = xmlRelaxNGGetElements(ctxt, cur, 1); 04261 i++; 04262 cur = cur->next; 04263 } 04264 cur = def->content; 04265 while (cur != NULL) { 04266 list[i] = xmlRelaxNGGetElements(ctxt, cur, 1); 04267 i++; 04268 cur = cur->next; 04269 } 04270 04271 for (i = 0; i < nbchild; i++) { 04272 if (list[i] == NULL) 04273 continue; 04274 for (j = 0; j < i; j++) { 04275 if (list[j] == NULL) 04276 continue; 04277 ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]); 04278 if (ret == 0) { 04279 xmlRngPErr(ctxt, def->node, XML_RNGP_GROUP_ATTR_CONFLICT, 04280 "Attributes conflicts in group\n", NULL, NULL); 04281 } 04282 } 04283 } 04284 for (i = 0; i < nbchild; i++) { 04285 if (list[i] != NULL) 04286 xmlFree(list[i]); 04287 } 04288 04289 xmlFree(list); 04290 def->dflags |= IS_PROCESSED; 04291 } 04292 04308 static void 04309 xmlRelaxNGComputeInterleaves(xmlRelaxNGDefinePtr def, 04310 xmlRelaxNGParserCtxtPtr ctxt, 04311 xmlChar * name ATTRIBUTE_UNUSED) 04312 { 04313 xmlRelaxNGDefinePtr cur, *tmp; 04314 04315 xmlRelaxNGPartitionPtr partitions = NULL; 04316 xmlRelaxNGInterleaveGroupPtr *groups = NULL; 04317 xmlRelaxNGInterleaveGroupPtr group; 04318 int i, j, ret, res; 04319 int nbgroups = 0; 04320 int nbchild = 0; 04321 int is_mixed = 0; 04322 int is_determinist = 1; 04323 04324 /* 04325 * Don't run that check in case of error. Infinite recursion 04326 * becomes possible. 04327 */ 04328 if (ctxt->nbErrors != 0) 04329 return; 04330 04331 #ifdef DEBUG_INTERLEAVE 04332 xmlGenericError(xmlGenericErrorContext, 04333 "xmlRelaxNGComputeInterleaves(%s)\n", name); 04334 #endif 04335 cur = def->content; 04336 while (cur != NULL) { 04337 nbchild++; 04338 cur = cur->next; 04339 } 04340 04341 #ifdef DEBUG_INTERLEAVE 04342 xmlGenericError(xmlGenericErrorContext, " %d child\n", nbchild); 04343 #endif 04344 groups = (xmlRelaxNGInterleaveGroupPtr *) 04345 xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr)); 04346 if (groups == NULL) 04347 goto error; 04348 cur = def->content; 04349 while (cur != NULL) { 04350 groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr) 04351 xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup)); 04352 if (groups[nbgroups] == NULL) 04353 goto error; 04354 if (cur->type == XML_RELAXNG_TEXT) 04355 is_mixed++; 04356 groups[nbgroups]->rule = cur; 04357 groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 0); 04358 groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1); 04359 nbgroups++; 04360 cur = cur->next; 04361 } 04362 #ifdef DEBUG_INTERLEAVE 04363 xmlGenericError(xmlGenericErrorContext, " %d groups\n", nbgroups); 04364 #endif 04365 04366 /* 04367 * Let's check that all rules makes a partitions according to 7.4 04368 */ 04369 partitions = (xmlRelaxNGPartitionPtr) 04370 xmlMalloc(sizeof(xmlRelaxNGPartition)); 04371 if (partitions == NULL) 04372 goto error; 04373 memset(partitions, 0, sizeof(xmlRelaxNGPartition)); 04374 partitions->nbgroups = nbgroups; 04375 partitions->triage = xmlHashCreate(nbgroups); 04376 for (i = 0; i < nbgroups; i++) { 04377 group = groups[i]; 04378 for (j = i + 1; j < nbgroups; j++) { 04379 if (groups[j] == NULL) 04380 continue; 04381 04382 ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs, 04383 groups[j]->defs); 04384 if (ret == 0) { 04385 xmlRngPErr(ctxt, def->node, XML_RNGP_ELEM_TEXT_CONFLICT, 04386 "Element or text conflicts in interleave\n", 04387 NULL, NULL); 04388 } 04389 ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs, 04390 groups[j]->attrs); 04391 if (ret == 0) { 04392 xmlRngPErr(ctxt, def->node, XML_RNGP_ATTR_CONFLICT, 04393 "Attributes conflicts in interleave\n", NULL, 04394 NULL); 04395 } 04396 } 04397 tmp = group->defs; 04398 if ((tmp != NULL) && (*tmp != NULL)) { 04399 while (*tmp != NULL) { 04400 if ((*tmp)->type == XML_RELAXNG_TEXT) { 04401 res = xmlHashAddEntry2(partitions->triage, 04402 BAD_CAST "#text", NULL, 04403 (void *) (long) (i + 1)); 04404 if (res != 0) 04405 is_determinist = -1; 04406 } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) && 04407 ((*tmp)->name != NULL)) { 04408 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0)) 04409 res = xmlHashAddEntry2(partitions->triage, 04410 (*tmp)->name, NULL, 04411 (void *) (long) (i + 1)); 04412 else 04413 res = xmlHashAddEntry2(partitions->triage, 04414 (*tmp)->name, (*tmp)->ns, 04415 (void *) (long) (i + 1)); 04416 if (res != 0) 04417 is_determinist = -1; 04418 } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) { 04419 if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0)) 04420 res = xmlHashAddEntry2(partitions->triage, 04421 BAD_CAST "#any", NULL, 04422 (void *) (long) (i + 1)); 04423 else 04424 res = xmlHashAddEntry2(partitions->triage, 04425 BAD_CAST "#any", (*tmp)->ns, 04426 (void *) (long) (i + 1)); 04427 if ((*tmp)->nameClass != NULL) 04428 is_determinist = 2; 04429 if (res != 0) 04430 is_determinist = -1; 04431 } else { 04432 is_determinist = -1; 04433 } 04434 tmp++; 04435 } 04436 } else { 04437 is_determinist = 0; 04438 } 04439 } 04440 partitions->groups = groups; 04441 04442 /* 04443 * and save the partition list back in the def 04444 */ 04445 def->data = partitions; 04446 if (is_mixed != 0) 04447 def->dflags |= IS_MIXED; 04448 if (is_determinist == 1) 04449 partitions->flags = IS_DETERMINIST; 04450 if (is_determinist == 2) 04451 partitions->flags = IS_DETERMINIST | IS_NEEDCHECK; 04452 return; 04453 04454 error: 04455 xmlRngPErrMemory(ctxt, "in interleave computation\n"); 04456 if (groups != NULL) { 04457 for (i = 0; i < nbgroups; i++) 04458 if (groups[i] != NULL) { 04459 if (groups[i]->defs != NULL) 04460 xmlFree(groups[i]->defs); 04461 xmlFree(groups[i]); 04462 } 04463 xmlFree(groups); 04464 } 04465 xmlRelaxNGFreePartition(partitions); 04466 } 04467 04477 static xmlRelaxNGDefinePtr 04478 xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 04479 { 04480 xmlRelaxNGDefinePtr def = NULL; 04481 xmlRelaxNGDefinePtr last = NULL, cur; 04482 xmlNodePtr child; 04483 04484 def = xmlRelaxNGNewDefine(ctxt, node); 04485 if (def == NULL) { 04486 return (NULL); 04487 } 04488 def->type = XML_RELAXNG_INTERLEAVE; 04489 04490 if (ctxt->interleaves == NULL) 04491 ctxt->interleaves = xmlHashCreate(10); 04492 if (ctxt->interleaves == NULL) { 04493 xmlRngPErrMemory(ctxt, "create interleaves\n"); 04494 } else { 04495 char name[32]; 04496 04497 snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++); 04498 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) { 04499 xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_ADD, 04500 "Failed to add %s to hash table\n", 04501 (const xmlChar *) name, NULL); 04502 } 04503 } 04504 child = node->children; 04505 if (child == NULL) { 04506 xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_NO_CONTENT, 04507 "Element interleave is empty\n", NULL, NULL); 04508 } 04509 while (child != NULL) { 04510 if (IS_RELAXNG(child, "element")) { 04511 cur = xmlRelaxNGParseElement(ctxt, child); 04512 } else { 04513 cur = xmlRelaxNGParsePattern(ctxt, child); 04514 } 04515 if (cur != NULL) { 04516 cur->parent = def; 04517 if (last == NULL) { 04518 def->content = last = cur; 04519 } else { 04520 last->next = cur; 04521 last = cur; 04522 } 04523 } 04524 child = child->next; 04525 } 04526 04527 return (def); 04528 } 04529 04539 static int 04540 xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 04541 { 04542 xmlRelaxNGIncludePtr incl; 04543 xmlNodePtr root; 04544 int ret = 0, tmp; 04545 04546 incl = node->psvi; 04547 if (incl == NULL) { 04548 xmlRngPErr(ctxt, node, XML_RNGP_INCLUDE_EMPTY, 04549 "Include node has no data\n", NULL, NULL); 04550 return (-1); 04551 } 04552 root = xmlDocGetRootElement(incl->doc); 04553 if (root == NULL) { 04554 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, "Include document is empty\n", 04555 NULL, NULL); 04556 return (-1); 04557 } 04558 if (!xmlStrEqual(root->name, BAD_CAST "grammar")) { 04559 xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING, 04560 "Include document root is not a grammar\n", NULL, NULL); 04561 return (-1); 04562 } 04563 04564 /* 04565 * Merge the definition from both the include and the internal list 04566 */ 04567 if (root->children != NULL) { 04568 tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children); 04569 if (tmp != 0) 04570 ret = -1; 04571 } 04572 if (node->children != NULL) { 04573 tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children); 04574 if (tmp != 0) 04575 ret = -1; 04576 } 04577 return (ret); 04578 } 04579 04589 static int 04590 xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 04591 { 04592 xmlChar *name; 04593 int ret = 0, tmp; 04594 xmlRelaxNGDefinePtr def; 04595 const xmlChar *olddefine; 04596 04597 name = xmlGetProp(node, BAD_CAST "name"); 04598 if (name == NULL) { 04599 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_NAME_MISSING, 04600 "define has no name\n", NULL, NULL); 04601 } else { 04602 xmlRelaxNGNormExtSpace(name); 04603 if (xmlValidateNCName(name, 0)) { 04604 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_DEFINE_NAME, 04605 "define name '%s' is not an NCName\n", name, NULL); 04606 } 04607 def = xmlRelaxNGNewDefine(ctxt, node); 04608 if (def == NULL) { 04609 xmlFree(name); 04610 return (-1); 04611 } 04612 def->type = XML_RELAXNG_DEF; 04613 def->name = name; 04614 if (node->children == NULL) { 04615 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_EMPTY, 04616 "define has no children\n", NULL, NULL); 04617 } else { 04618 olddefine = ctxt->define; 04619 ctxt->define = name; 04620 def->content = 04621 xmlRelaxNGParsePatterns(ctxt, node->children, 0); 04622 ctxt->define = olddefine; 04623 } 04624 if (ctxt->grammar->defs == NULL) 04625 ctxt->grammar->defs = xmlHashCreate(10); 04626 if (ctxt->grammar->defs == NULL) { 04627 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED, 04628 "Could not create definition hash\n", NULL, NULL); 04629 ret = -1; 04630 } else { 04631 tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def); 04632 if (tmp < 0) { 04633 xmlRelaxNGDefinePtr prev; 04634 04635 prev = xmlHashLookup(ctxt->grammar->defs, name); 04636 if (prev == NULL) { 04637 xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED, 04638 "Internal error on define aggregation of %s\n", 04639 name, NULL); 04640 ret = -1; 04641 } else { 04642 while (prev->nextHash != NULL) 04643 prev = prev->nextHash; 04644 prev->nextHash = def; 04645 } 04646 } 04647 } 04648 } 04649 return (ret); 04650 } 04651 04660 static void 04661 xmlRelaxNGParseImportRef(void *payload, void *data, xmlChar *name) { 04662 xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data; 04663 xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload; 04664 int tmp; 04665 04666 def->dflags |= IS_EXTERNAL_REF; 04667 04668 tmp = xmlHashAddEntry(ctxt->grammar->refs, name, def); 04669 if (tmp < 0) { 04670 xmlRelaxNGDefinePtr prev; 04671 04672 prev = (xmlRelaxNGDefinePtr) 04673 xmlHashLookup(ctxt->grammar->refs, def->name); 04674 if (prev == NULL) { 04675 if (def->name != NULL) { 04676 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED, 04677 "Error refs definitions '%s'\n", 04678 def->name, NULL); 04679 } else { 04680 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED, 04681 "Error refs definitions\n", 04682 NULL, NULL); 04683 } 04684 } else { 04685 def->nextHash = prev->nextHash; 04686 prev->nextHash = def; 04687 } 04688 } 04689 } 04690 04700 static int 04701 xmlRelaxNGParseImportRefs(xmlRelaxNGParserCtxtPtr ctxt, 04702 xmlRelaxNGGrammarPtr grammar) { 04703 if ((ctxt == NULL) || (grammar == NULL) || (ctxt->grammar == NULL)) 04704 return(-1); 04705 if (grammar->refs == NULL) 04706 return(0); 04707 if (ctxt->grammar->refs == NULL) 04708 ctxt->grammar->refs = xmlHashCreate(10); 04709 if (ctxt->grammar->refs == NULL) { 04710 xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED, 04711 "Could not create references hash\n", NULL, NULL); 04712 return(-1); 04713 } 04714 xmlHashScan(grammar->refs, xmlRelaxNGParseImportRef, ctxt); 04715 return(0); 04716 } 04717 04727 static xmlRelaxNGDefinePtr 04728 xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 04729 { 04730 xmlRelaxNGDocumentPtr docu; 04731 xmlNodePtr root, tmp; 04732 xmlChar *ns; 04733 int newNs = 0, oldflags; 04734 xmlRelaxNGDefinePtr def; 04735 04736 docu = node->psvi; 04737 if (docu != NULL) { 04738 def = xmlRelaxNGNewDefine(ctxt, node); 04739 if (def == NULL) 04740 return (NULL); 04741 def->type = XML_RELAXNG_EXTERNALREF; 04742 04743 if (docu->content == NULL) { 04744 /* 04745 * Then do the parsing for good 04746 */ 04747 root = xmlDocGetRootElement(docu->doc); 04748 if (root == NULL) { 04749 xmlRngPErr(ctxt, node, XML_RNGP_EXTERNALREF_EMTPY, 04750 "xmlRelaxNGParse: %s is empty\n", ctxt->URL, 04751 NULL); 04752 return (NULL); 04753 } 04754 /* 04755 * ns transmission rules 04756 */ 04757 ns = xmlGetProp(root, BAD_CAST "ns"); 04758 if (ns == NULL) { 04759 tmp = node; 04760 while ((tmp != NULL) && (tmp->type == XML_ELEMENT_NODE)) { 04761 ns = xmlGetProp(tmp, BAD_CAST "ns"); 04762 if (ns != NULL) { 04763 break; 04764 } 04765 tmp = tmp->parent; 04766 } 04767 if (ns != NULL) { 04768 xmlSetProp(root, BAD_CAST "ns", ns); 04769 newNs = 1; 04770 xmlFree(ns); 04771 } 04772 } else { 04773 xmlFree(ns); 04774 } 04775 04776 /* 04777 * Parsing to get a precompiled schemas. 04778 */ 04779 oldflags = ctxt->flags; 04780 ctxt->flags |= XML_RELAXNG_IN_EXTERNALREF; 04781 docu->schema = xmlRelaxNGParseDocument(ctxt, root); 04782 ctxt->flags = oldflags; 04783 if ((docu->schema != NULL) && 04784 (docu->schema->topgrammar != NULL)) { 04785 docu->content = docu->schema->topgrammar->start; 04786 if (docu->schema->topgrammar->refs) 04787 xmlRelaxNGParseImportRefs(ctxt, docu->schema->topgrammar); 04788 } 04789 04790 /* 04791 * the externalRef may be reused in a different ns context 04792 */ 04793 if (newNs == 1) { 04794 xmlUnsetProp(root, BAD_CAST "ns"); 04795 } 04796 } 04797 def->content = docu->content; 04798 } else { 04799 def = NULL; 04800 } 04801 return (def); 04802 } 04803 04814 static xmlRelaxNGDefinePtr 04815 xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 04816 { 04817 xmlRelaxNGDefinePtr def = NULL; 04818 04819 if (node == NULL) { 04820 return (NULL); 04821 } 04822 if (IS_RELAXNG(node, "element")) { 04823 def = xmlRelaxNGParseElement(ctxt, node); 04824 } else if (IS_RELAXNG(node, "attribute")) { 04825 def = xmlRelaxNGParseAttribute(ctxt, node); 04826 } else if (IS_RELAXNG(node, "empty")) { 04827 def = xmlRelaxNGNewDefine(ctxt, node); 04828 if (def == NULL) 04829 return (NULL); 04830 def->type = XML_RELAXNG_EMPTY; 04831 if (node->children != NULL) { 04832 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_NOT_EMPTY, 04833 "empty: had a child node\n", NULL, NULL); 04834 } 04835 } else if (IS_RELAXNG(node, "text")) { 04836 def = xmlRelaxNGNewDefine(ctxt, node); 04837 if (def == NULL) 04838 return (NULL); 04839 def->type = XML_RELAXNG_TEXT; 04840 if (node->children != NULL) { 04841 xmlRngPErr(ctxt, node, XML_RNGP_TEXT_HAS_CHILD, 04842 "text: had a child node\n", NULL, NULL); 04843 } 04844 } else if (IS_RELAXNG(node, "zeroOrMore")) { 04845 def = xmlRelaxNGNewDefine(ctxt, node); 04846 if (def == NULL) 04847 return (NULL); 04848 def->type = XML_RELAXNG_ZEROORMORE; 04849 if (node->children == NULL) { 04850 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, 04851 "Element %s is empty\n", node->name, NULL); 04852 } else { 04853 def->content = 04854 xmlRelaxNGParsePatterns(ctxt, node->children, 1); 04855 } 04856 } else if (IS_RELAXNG(node, "oneOrMore")) { 04857 def = xmlRelaxNGNewDefine(ctxt, node); 04858 if (def == NULL) 04859 return (NULL); 04860 def->type = XML_RELAXNG_ONEORMORE; 04861 if (node->children == NULL) { 04862 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, 04863 "Element %s is empty\n", node->name, NULL); 04864 } else { 04865 def->content = 04866 xmlRelaxNGParsePatterns(ctxt, node->children, 1); 04867 } 04868 } else if (IS_RELAXNG(node, "optional")) { 04869 def = xmlRelaxNGNewDefine(ctxt, node); 04870 if (def == NULL) 04871 return (NULL); 04872 def->type = XML_RELAXNG_OPTIONAL; 04873 if (node->children == NULL) { 04874 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, 04875 "Element %s is empty\n", node->name, NULL); 04876 } else { 04877 def->content = 04878 xmlRelaxNGParsePatterns(ctxt, node->children, 1); 04879 } 04880 } else if (IS_RELAXNG(node, "choice")) { 04881 def = xmlRelaxNGNewDefine(ctxt, node); 04882 if (def == NULL) 04883 return (NULL); 04884 def->type = XML_RELAXNG_CHOICE; 04885 if (node->children == NULL) { 04886 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, 04887 "Element %s is empty\n", node->name, NULL); 04888 } else { 04889 def->content = 04890 xmlRelaxNGParsePatterns(ctxt, node->children, 0); 04891 } 04892 } else if (IS_RELAXNG(node, "group")) { 04893 def = xmlRelaxNGNewDefine(ctxt, node); 04894 if (def == NULL) 04895 return (NULL); 04896 def->type = XML_RELAXNG_GROUP; 04897 if (node->children == NULL) { 04898 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, 04899 "Element %s is empty\n", node->name, NULL); 04900 } else { 04901 def->content = 04902 xmlRelaxNGParsePatterns(ctxt, node->children, 0); 04903 } 04904 } else if (IS_RELAXNG(node, "ref")) { 04905 def = xmlRelaxNGNewDefine(ctxt, node); 04906 if (def == NULL) 04907 return (NULL); 04908 def->type = XML_RELAXNG_REF; 04909 def->name = xmlGetProp(node, BAD_CAST "name"); 04910 if (def->name == NULL) { 04911 xmlRngPErr(ctxt, node, XML_RNGP_REF_NO_NAME, "ref has no name\n", 04912 NULL, NULL); 04913 } else { 04914 xmlRelaxNGNormExtSpace(def->name); 04915 if (xmlValidateNCName(def->name, 0)) { 04916 xmlRngPErr(ctxt, node, XML_RNGP_REF_NAME_INVALID, 04917 "ref name '%s' is not an NCName\n", def->name, 04918 NULL); 04919 } 04920 } 04921 if (node->children != NULL) { 04922 xmlRngPErr(ctxt, node, XML_RNGP_REF_NOT_EMPTY, "ref is not empty\n", 04923 NULL, NULL); 04924 } 04925 if (ctxt->grammar->refs == NULL) 04926 ctxt->grammar->refs = xmlHashCreate(10); 04927 if (ctxt->grammar->refs == NULL) { 04928 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED, 04929 "Could not create references hash\n", NULL, NULL); 04930 def = NULL; 04931 } else { 04932 int tmp; 04933 04934 tmp = xmlHashAddEntry(ctxt->grammar->refs, def->name, def); 04935 if (tmp < 0) { 04936 xmlRelaxNGDefinePtr prev; 04937 04938 prev = (xmlRelaxNGDefinePtr) 04939 xmlHashLookup(ctxt->grammar->refs, def->name); 04940 if (prev == NULL) { 04941 if (def->name != NULL) { 04942 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED, 04943 "Error refs definitions '%s'\n", 04944 def->name, NULL); 04945 } else { 04946 xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED, 04947 "Error refs definitions\n", 04948 NULL, NULL); 04949 } 04950 def = NULL; 04951 } else { 04952 def->nextHash = prev->nextHash; 04953 prev->nextHash = def; 04954 } 04955 } 04956 } 04957 } else if (IS_RELAXNG(node, "data")) { 04958 def = xmlRelaxNGParseData(ctxt, node); 04959 } else if (IS_RELAXNG(node, "value")) { 04960 def = xmlRelaxNGParseValue(ctxt, node); 04961 } else if (IS_RELAXNG(node, "list")) { 04962 def = xmlRelaxNGNewDefine(ctxt, node); 04963 if (def == NULL) 04964 return (NULL); 04965 def->type = XML_RELAXNG_LIST; 04966 if (node->children == NULL) { 04967 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, 04968 "Element %s is empty\n", node->name, NULL); 04969 } else { 04970 def->content = 04971 xmlRelaxNGParsePatterns(ctxt, node->children, 0); 04972 } 04973 } else if (IS_RELAXNG(node, "interleave")) { 04974 def = xmlRelaxNGParseInterleave(ctxt, node); 04975 } else if (IS_RELAXNG(node, "externalRef")) { 04976 def = xmlRelaxNGProcessExternalRef(ctxt, node); 04977 } else if (IS_RELAXNG(node, "notAllowed")) { 04978 def = xmlRelaxNGNewDefine(ctxt, node); 04979 if (def == NULL) 04980 return (NULL); 04981 def->type = XML_RELAXNG_NOT_ALLOWED; 04982 if (node->children != NULL) { 04983 xmlRngPErr(ctxt, node, XML_RNGP_NOTALLOWED_NOT_EMPTY, 04984 "xmlRelaxNGParse: notAllowed element is not empty\n", 04985 NULL, NULL); 04986 } 04987 } else if (IS_RELAXNG(node, "grammar")) { 04988 xmlRelaxNGGrammarPtr grammar, old; 04989 xmlRelaxNGGrammarPtr oldparent; 04990 04991 #ifdef DEBUG_GRAMMAR 04992 xmlGenericError(xmlGenericErrorContext, 04993 "Found <grammar> pattern\n"); 04994 #endif 04995 04996 oldparent = ctxt->parentgrammar; 04997 old = ctxt->grammar; 04998 ctxt->parentgrammar = old; 04999 grammar = xmlRelaxNGParseGrammar(ctxt, node->children); 05000 if (old != NULL) { 05001 ctxt->grammar = old; 05002 ctxt->parentgrammar = oldparent; 05003 #if 0 05004 if (grammar != NULL) { 05005 grammar->next = old->next; 05006 old->next = grammar; 05007 } 05008 #endif 05009 } 05010 if (grammar != NULL) 05011 def = grammar->start; 05012 else 05013 def = NULL; 05014 } else if (IS_RELAXNG(node, "parentRef")) { 05015 if (ctxt->parentgrammar == NULL) { 05016 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_PARENT, 05017 "Use of parentRef without a parent grammar\n", NULL, 05018 NULL); 05019 return (NULL); 05020 } 05021 def = xmlRelaxNGNewDefine(ctxt, node); 05022 if (def == NULL) 05023 return (NULL); 05024 def->type = XML_RELAXNG_PARENTREF; 05025 def->name = xmlGetProp(node, BAD_CAST "name"); 05026 if (def->name == NULL) { 05027 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_NAME, 05028 "parentRef has no name\n", NULL, NULL); 05029 } else { 05030 xmlRelaxNGNormExtSpace(def->name); 05031 if (xmlValidateNCName(def->name, 0)) { 05032 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NAME_INVALID, 05033 "parentRef name '%s' is not an NCName\n", 05034 def->name, NULL); 05035 } 05036 } 05037 if (node->children != NULL) { 05038 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NOT_EMPTY, 05039 "parentRef is not empty\n", NULL, NULL); 05040 } 05041 if (ctxt->parentgrammar->refs == NULL) 05042 ctxt->parentgrammar->refs = xmlHashCreate(10); 05043 if (ctxt->parentgrammar->refs == NULL) { 05044 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED, 05045 "Could not create references hash\n", NULL, NULL); 05046 def = NULL; 05047 } else if (def->name != NULL) { 05048 int tmp; 05049 05050 tmp = 05051 xmlHashAddEntry(ctxt->parentgrammar->refs, def->name, def); 05052 if (tmp < 0) { 05053 xmlRelaxNGDefinePtr prev; 05054 05055 prev = (xmlRelaxNGDefinePtr) 05056 xmlHashLookup(ctxt->parentgrammar->refs, def->name); 05057 if (prev == NULL) { 05058 xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED, 05059 "Internal error parentRef definitions '%s'\n", 05060 def->name, NULL); 05061 def = NULL; 05062 } else { 05063 def->nextHash = prev->nextHash; 05064 prev->nextHash = def; 05065 } 05066 } 05067 } 05068 } else if (IS_RELAXNG(node, "mixed")) { 05069 if (node->children == NULL) { 05070 xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, "Mixed is empty\n", 05071 NULL, NULL); 05072 def = NULL; 05073 } else { 05074 def = xmlRelaxNGParseInterleave(ctxt, node); 05075 if (def != NULL) { 05076 xmlRelaxNGDefinePtr tmp; 05077 05078 if ((def->content != NULL) && (def->content->next != NULL)) { 05079 tmp = xmlRelaxNGNewDefine(ctxt, node); 05080 if (tmp != NULL) { 05081 tmp->type = XML_RELAXNG_GROUP; 05082 tmp->content = def->content; 05083 def->content = tmp; 05084 } 05085 } 05086 05087 tmp = xmlRelaxNGNewDefine(ctxt, node); 05088 if (tmp == NULL) 05089 return (def); 05090 tmp->type = XML_RELAXNG_TEXT; 05091 tmp->next = def->content; 05092 def->content = tmp; 05093 } 05094 } 05095 } else { 05096 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_CONSTRUCT, 05097 "Unexpected node %s is not a pattern\n", node->name, 05098 NULL); 05099 def = NULL; 05100 } 05101 return (def); 05102 } 05103 05113 static xmlRelaxNGDefinePtr 05114 xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 05115 { 05116 xmlRelaxNGDefinePtr ret, cur; 05117 xmlNodePtr child; 05118 int old_flags; 05119 05120 ret = xmlRelaxNGNewDefine(ctxt, node); 05121 if (ret == NULL) 05122 return (NULL); 05123 ret->type = XML_RELAXNG_ATTRIBUTE; 05124 ret->parent = ctxt->def; 05125 child = node->children; 05126 if (child == NULL) { 05127 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_EMPTY, 05128 "xmlRelaxNGParseattribute: attribute has no children\n", 05129 NULL, NULL); 05130 return (ret); 05131 } 05132 old_flags = ctxt->flags; 05133 ctxt->flags |= XML_RELAXNG_IN_ATTRIBUTE; 05134 cur = xmlRelaxNGParseNameClass(ctxt, child, ret); 05135 if (cur != NULL) 05136 child = child->next; 05137 05138 if (child != NULL) { 05139 cur = xmlRelaxNGParsePattern(ctxt, child); 05140 if (cur != NULL) { 05141 switch (cur->type) { 05142 case XML_RELAXNG_EMPTY: 05143 case XML_RELAXNG_NOT_ALLOWED: 05144 case XML_RELAXNG_TEXT: 05145 case XML_RELAXNG_ELEMENT: 05146 case XML_RELAXNG_DATATYPE: 05147 case XML_RELAXNG_VALUE: 05148 case XML_RELAXNG_LIST: 05149 case XML_RELAXNG_REF: 05150 case XML_RELAXNG_PARENTREF: 05151 case XML_RELAXNG_EXTERNALREF: 05152 case XML_RELAXNG_DEF: 05153 case XML_RELAXNG_ONEORMORE: 05154 case XML_RELAXNG_ZEROORMORE: 05155 case XML_RELAXNG_OPTIONAL: 05156 case XML_RELAXNG_CHOICE: 05157 case XML_RELAXNG_GROUP: 05158 case XML_RELAXNG_INTERLEAVE: 05159 case XML_RELAXNG_ATTRIBUTE: 05160 ret->content = cur; 05161 cur->parent = ret; 05162 break; 05163 case XML_RELAXNG_START: 05164 case XML_RELAXNG_PARAM: 05165 case XML_RELAXNG_EXCEPT: 05166 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CONTENT, 05167 "attribute has invalid content\n", NULL, 05168 NULL); 05169 break; 05170 case XML_RELAXNG_NOOP: 05171 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_NOOP, 05172 "RNG Internal error, noop found in attribute\n", 05173 NULL, NULL); 05174 break; 05175 } 05176 } 05177 child = child->next; 05178 } 05179 if (child != NULL) { 05180 xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CHILDREN, 05181 "attribute has multiple children\n", NULL, NULL); 05182 } 05183 ctxt->flags = old_flags; 05184 return (ret); 05185 } 05186 05197 static xmlRelaxNGDefinePtr 05198 xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt, 05199 xmlNodePtr node, int attr) 05200 { 05201 xmlRelaxNGDefinePtr ret, cur, last = NULL; 05202 xmlNodePtr child; 05203 05204 if (!IS_RELAXNG(node, "except")) { 05205 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MISSING, 05206 "Expecting an except node\n", NULL, NULL); 05207 return (NULL); 05208 } 05209 if (node->next != NULL) { 05210 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MULTIPLE, 05211 "exceptNameClass allows only a single except node\n", 05212 NULL, NULL); 05213 } 05214 if (node->children == NULL) { 05215 xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_EMPTY, "except has no content\n", 05216 NULL, NULL); 05217 return (NULL); 05218 } 05219 05220 ret = xmlRelaxNGNewDefine(ctxt, node); 05221 if (ret == NULL) 05222 return (NULL); 05223 ret->type = XML_RELAXNG_EXCEPT; 05224 child = node->children; 05225 while (child != NULL) { 05226 cur = xmlRelaxNGNewDefine(ctxt, child); 05227 if (cur == NULL) 05228 break; 05229 if (attr) 05230 cur->type = XML_RELAXNG_ATTRIBUTE; 05231 else 05232 cur->type = XML_RELAXNG_ELEMENT; 05233 05234 if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) { 05235 if (last == NULL) { 05236 ret->content = cur; 05237 } else { 05238 last->next = cur; 05239 } 05240 last = cur; 05241 } 05242 child = child->next; 05243 } 05244 05245 return (ret); 05246 } 05247 05258 static xmlRelaxNGDefinePtr 05259 xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, 05260 xmlRelaxNGDefinePtr def) 05261 { 05262 xmlRelaxNGDefinePtr ret, tmp; 05263 xmlChar *val; 05264 05265 ret = def; 05266 if ((IS_RELAXNG(node, "name")) || (IS_RELAXNG(node, "anyName")) || 05267 (IS_RELAXNG(node, "nsName"))) { 05268 if ((def->type != XML_RELAXNG_ELEMENT) && 05269 (def->type != XML_RELAXNG_ATTRIBUTE)) { 05270 ret = xmlRelaxNGNewDefine(ctxt, node); 05271 if (ret == NULL) 05272 return (NULL); 05273 ret->parent = def; 05274 if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) 05275 ret->type = XML_RELAXNG_ATTRIBUTE; 05276 else 05277 ret->type = XML_RELAXNG_ELEMENT; 05278 } 05279 } 05280 if (IS_RELAXNG(node, "name")) { 05281 val = xmlNodeGetContent(node); 05282 xmlRelaxNGNormExtSpace(val); 05283 if (xmlValidateNCName(val, 0)) { 05284 if (node->parent != NULL) 05285 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME, 05286 "Element %s name '%s' is not an NCName\n", 05287 node->parent->name, val); 05288 else 05289 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME, 05290 "name '%s' is not an NCName\n", 05291 val, NULL); 05292 } 05293 ret->name = val; 05294 val = xmlGetProp(node, BAD_CAST "ns"); 05295 ret->ns = val; 05296 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) && 05297 (val != NULL) && 05298 (xmlStrEqual(val, BAD_CAST "http://www.w3.org/2000/xmlns"))) { 05299 xmlRngPErr(ctxt, node, XML_RNGP_XML_NS, 05300 "Attribute with namespace '%s' is not allowed\n", 05301 val, NULL); 05302 } 05303 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) && 05304 (val != NULL) && 05305 (val[0] == 0) && (xmlStrEqual(ret->name, BAD_CAST "xmlns"))) { 05306 xmlRngPErr(ctxt, node, XML_RNGP_XMLNS_NAME, 05307 "Attribute with QName 'xmlns' is not allowed\n", 05308 val, NULL); 05309 } 05310 } else if (IS_RELAXNG(node, "anyName")) { 05311 ret->name = NULL; 05312 ret->ns = NULL; 05313 if (node->children != NULL) { 05314 ret->nameClass = 05315 xmlRelaxNGParseExceptNameClass(ctxt, node->children, 05316 (def->type == 05317 XML_RELAXNG_ATTRIBUTE)); 05318 } 05319 } else if (IS_RELAXNG(node, "nsName")) { 05320 ret->name = NULL; 05321 ret->ns = xmlGetProp(node, BAD_CAST "ns"); 05322 if (ret->ns == NULL) { 05323 xmlRngPErr(ctxt, node, XML_RNGP_NSNAME_NO_NS, 05324 "nsName has no ns attribute\n", NULL, NULL); 05325 } 05326 if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) && 05327 (ret->ns != NULL) && 05328 (xmlStrEqual 05329 (ret->ns, BAD_CAST "http://www.w3.org/2000/xmlns"))) { 05330 xmlRngPErr(ctxt, node, XML_RNGP_XML_NS, 05331 "Attribute with namespace '%s' is not allowed\n", 05332 ret->ns, NULL); 05333 } 05334 if (node->children != NULL) { 05335 ret->nameClass = 05336 xmlRelaxNGParseExceptNameClass(ctxt, node->children, 05337 (def->type == 05338 XML_RELAXNG_ATTRIBUTE)); 05339 } 05340 } else if (IS_RELAXNG(node, "choice")) { 05341 xmlNodePtr child; 05342 xmlRelaxNGDefinePtr last = NULL; 05343 05344 ret = xmlRelaxNGNewDefine(ctxt, node); 05345 if (ret == NULL) 05346 return (NULL); 05347 ret->parent = def; 05348 ret->type = XML_RELAXNG_CHOICE; 05349 05350 if (node->children == NULL) { 05351 xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY, 05352 "Element choice is empty\n", NULL, NULL); 05353 } else { 05354 05355 child = node->children; 05356 while (child != NULL) { 05357 tmp = xmlRelaxNGParseNameClass(ctxt, child, ret); 05358 if (tmp != NULL) { 05359 if (last == NULL) { 05360 last = ret->nameClass = tmp; 05361 } else { 05362 last->next = tmp; 05363 last = tmp; 05364 } 05365 } 05366 child = child->next; 05367 } 05368 } 05369 } else { 05370 xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT, 05371 "expecting name, anyName, nsName or choice : got %s\n", 05372 (node == NULL ? (const xmlChar *) "nothing" : node->name), 05373 NULL); 05374 return (NULL); 05375 } 05376 if (ret != def) { 05377 if (def->nameClass == NULL) { 05378 def->nameClass = ret; 05379 } else { 05380 tmp = def->nameClass; 05381 while (tmp->next != NULL) { 05382 tmp = tmp->next; 05383 } 05384 tmp->next = ret; 05385 } 05386 } 05387 return (ret); 05388 } 05389 05399 static xmlRelaxNGDefinePtr 05400 xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 05401 { 05402 xmlRelaxNGDefinePtr ret, cur, last; 05403 xmlNodePtr child; 05404 const xmlChar *olddefine; 05405 05406 ret = xmlRelaxNGNewDefine(ctxt, node); 05407 if (ret == NULL) 05408 return (NULL); 05409 ret->type = XML_RELAXNG_ELEMENT; 05410 ret->parent = ctxt->def; 05411 child = node->children; 05412 if (child == NULL) { 05413 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_EMPTY, 05414 "xmlRelaxNGParseElement: element has no children\n", 05415 NULL, NULL); 05416 return (ret); 05417 } 05418 cur = xmlRelaxNGParseNameClass(ctxt, child, ret); 05419 if (cur != NULL) 05420 child = child->next; 05421 05422 if (child == NULL) { 05423 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NO_CONTENT, 05424 "xmlRelaxNGParseElement: element has no content\n", 05425 NULL, NULL); 05426 return (ret); 05427 } 05428 olddefine = ctxt->define; 05429 ctxt->define = NULL; 05430 last = NULL; 05431 while (child != NULL) { 05432 cur = xmlRelaxNGParsePattern(ctxt, child); 05433 if (cur != NULL) { 05434 cur->parent = ret; 05435 switch (cur->type) { 05436 case XML_RELAXNG_EMPTY: 05437 case XML_RELAXNG_NOT_ALLOWED: 05438 case XML_RELAXNG_TEXT: 05439 case XML_RELAXNG_ELEMENT: 05440 case XML_RELAXNG_DATATYPE: 05441 case XML_RELAXNG_VALUE: 05442 case XML_RELAXNG_LIST: 05443 case XML_RELAXNG_REF: 05444 case XML_RELAXNG_PARENTREF: 05445 case XML_RELAXNG_EXTERNALREF: 05446 case XML_RELAXNG_DEF: 05447 case XML_RELAXNG_ZEROORMORE: 05448 case XML_RELAXNG_ONEORMORE: 05449 case XML_RELAXNG_OPTIONAL: 05450 case XML_RELAXNG_CHOICE: 05451 case XML_RELAXNG_GROUP: 05452 case XML_RELAXNG_INTERLEAVE: 05453 if (last == NULL) { 05454 ret->content = last = cur; 05455 } else { 05456 if ((last->type == XML_RELAXNG_ELEMENT) && 05457 (ret->content == last)) { 05458 ret->content = xmlRelaxNGNewDefine(ctxt, node); 05459 if (ret->content != NULL) { 05460 ret->content->type = XML_RELAXNG_GROUP; 05461 ret->content->content = last; 05462 } else { 05463 ret->content = last; 05464 } 05465 } 05466 last->next = cur; 05467 last = cur; 05468 } 05469 break; 05470 case XML_RELAXNG_ATTRIBUTE: 05471 cur->next = ret->attrs; 05472 ret->attrs = cur; 05473 break; 05474 case XML_RELAXNG_START: 05475 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT, 05476 "RNG Internal error, start found in element\n", 05477 NULL, NULL); 05478 break; 05479 case XML_RELAXNG_PARAM: 05480 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT, 05481 "RNG Internal error, param found in element\n", 05482 NULL, NULL); 05483 break; 05484 case XML_RELAXNG_EXCEPT: 05485 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT, 05486 "RNG Internal error, except found in element\n", 05487 NULL, NULL); 05488 break; 05489 case XML_RELAXNG_NOOP: 05490 xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT, 05491 "RNG Internal error, noop found in element\n", 05492 NULL, NULL); 05493 break; 05494 } 05495 } 05496 child = child->next; 05497 } 05498 ctxt->define = olddefine; 05499 return (ret); 05500 } 05501 05512 static xmlRelaxNGDefinePtr 05513 xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes, 05514 int group) 05515 { 05516 xmlRelaxNGDefinePtr def = NULL, last = NULL, cur, parent; 05517 05518 parent = ctxt->def; 05519 while (nodes != NULL) { 05520 if (IS_RELAXNG(nodes, "element")) { 05521 cur = xmlRelaxNGParseElement(ctxt, nodes); 05522 if (def == NULL) { 05523 def = last = cur; 05524 } else { 05525 if ((group == 1) && (def->type == XML_RELAXNG_ELEMENT) && 05526 (def == last)) { 05527 def = xmlRelaxNGNewDefine(ctxt, nodes); 05528 def->type = XML_RELAXNG_GROUP; 05529 def->content = last; 05530 } 05531 last->next = cur; 05532 last = cur; 05533 } 05534 cur->parent = parent; 05535 } else { 05536 cur = xmlRelaxNGParsePattern(ctxt, nodes); 05537 if (cur != NULL) { 05538 if (def == NULL) { 05539 def = last = cur; 05540 } else { 05541 last->next = cur; 05542 last = cur; 05543 } 05544 } 05545 } 05546 nodes = nodes->next; 05547 } 05548 return (def); 05549 } 05550 05560 static int 05561 xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes) 05562 { 05563 int ret = 0; 05564 xmlRelaxNGDefinePtr def = NULL, last; 05565 05566 if (nodes == NULL) { 05567 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY, "start has no children\n", 05568 NULL, NULL); 05569 return (-1); 05570 } 05571 if (IS_RELAXNG(nodes, "empty")) { 05572 def = xmlRelaxNGNewDefine(ctxt, nodes); 05573 if (def == NULL) 05574 return (-1); 05575 def->type = XML_RELAXNG_EMPTY; 05576 if (nodes->children != NULL) { 05577 xmlRngPErr(ctxt, nodes, XML_RNGP_EMPTY_CONTENT, 05578 "element empty is not empty\n", NULL, NULL); 05579 } 05580 } else if (IS_RELAXNG(nodes, "notAllowed")) { 05581 def = xmlRelaxNGNewDefine(ctxt, nodes); 05582 if (def == NULL) 05583 return (-1); 05584 def->type = XML_RELAXNG_NOT_ALLOWED; 05585 if (nodes->children != NULL) { 05586 xmlRngPErr(ctxt, nodes, XML_RNGP_NOTALLOWED_NOT_EMPTY, 05587 "element notAllowed is not empty\n", NULL, NULL); 05588 } 05589 } else { 05590 def = xmlRelaxNGParsePatterns(ctxt, nodes, 1); 05591 } 05592 if (ctxt->grammar->start != NULL) { 05593 last = ctxt->grammar->start; 05594 while (last->next != NULL) 05595 last = last->next; 05596 last->next = def; 05597 } else { 05598 ctxt->grammar->start = def; 05599 } 05600 nodes = nodes->next; 05601 if (nodes != NULL) { 05602 xmlRngPErr(ctxt, nodes, XML_RNGP_START_CONTENT, 05603 "start more than one children\n", NULL, NULL); 05604 return (-1); 05605 } 05606 return (ret); 05607 } 05608 05618 static int 05619 xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt, 05620 xmlNodePtr nodes) 05621 { 05622 int ret = 0, tmp; 05623 05624 if (nodes == NULL) { 05625 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_EMPTY, 05626 "grammar has no children\n", NULL, NULL); 05627 return (-1); 05628 } 05629 while (nodes != NULL) { 05630 if (IS_RELAXNG(nodes, "start")) { 05631 if (nodes->children == NULL) { 05632 xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY, 05633 "start has no children\n", NULL, NULL); 05634 } else { 05635 tmp = xmlRelaxNGParseStart(ctxt, nodes->children); 05636 if (tmp != 0) 05637 ret = -1; 05638 } 05639 } else if (IS_RELAXNG(nodes, "define")) { 05640 tmp = xmlRelaxNGParseDefine(ctxt, nodes); 05641 if (tmp != 0) 05642 ret = -1; 05643 } else if (IS_RELAXNG(nodes, "include")) { 05644 tmp = xmlRelaxNGParseInclude(ctxt, nodes); 05645 if (tmp != 0) 05646 ret = -1; 05647 } else { 05648 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT, 05649 "grammar has unexpected child %s\n", nodes->name, 05650 NULL); 05651 ret = -1; 05652 } 05653 nodes = nodes->next; 05654 } 05655 return (ret); 05656 } 05657 05667 static void 05668 xmlRelaxNGCheckReference(xmlRelaxNGDefinePtr ref, 05669 xmlRelaxNGParserCtxtPtr ctxt, 05670 const xmlChar * name) 05671 { 05672 xmlRelaxNGGrammarPtr grammar; 05673 xmlRelaxNGDefinePtr def, cur; 05674 05675 /* 05676 * Those rules don't apply to imported ref from xmlRelaxNGParseImportRef 05677 */ 05678 if (ref->dflags & IS_EXTERNAL_REF) 05679 return; 05680 05681 grammar = ctxt->grammar; 05682 if (grammar == NULL) { 05683 xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR, 05684 "Internal error: no grammar in CheckReference %s\n", 05685 name, NULL); 05686 return; 05687 } 05688 if (ref->content != NULL) { 05689 xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR, 05690 "Internal error: reference has content in CheckReference %s\n", 05691 name, NULL); 05692 return; 05693 } 05694 if (grammar->defs != NULL) { 05695 def = xmlHashLookup(grammar->defs, name); 05696 if (def != NULL) { 05697 cur = ref; 05698 while (cur != NULL) { 05699 cur->content = def; 05700 cur = cur->nextHash; 05701 } 05702 } else { 05703 xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF, 05704 "Reference %s has no matching definition\n", name, 05705 NULL); 05706 } 05707 } else { 05708 xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF, 05709 "Reference %s has no matching definition\n", name, 05710 NULL); 05711 } 05712 } 05713 05723 static void 05724 xmlRelaxNGCheckCombine(xmlRelaxNGDefinePtr define, 05725 xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * name) 05726 { 05727 xmlChar *combine; 05728 int choiceOrInterleave = -1; 05729 int missing = 0; 05730 xmlRelaxNGDefinePtr cur, last, tmp, tmp2; 05731 05732 if (define->nextHash == NULL) 05733 return; 05734 cur = define; 05735 while (cur != NULL) { 05736 combine = xmlGetProp(cur->node, BAD_CAST "combine"); 05737 if (combine != NULL) { 05738 if (xmlStrEqual(combine, BAD_CAST "choice")) { 05739 if (choiceOrInterleave == -1) 05740 choiceOrInterleave = 1; 05741 else if (choiceOrInterleave == 0) { 05742 xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE, 05743 "Defines for %s use both 'choice' and 'interleave'\n", 05744 name, NULL); 05745 } 05746 } else if (xmlStrEqual(combine, BAD_CAST "interleave")) { 05747 if (choiceOrInterleave == -1) 05748 choiceOrInterleave = 0; 05749 else if (choiceOrInterleave == 1) { 05750 xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE, 05751 "Defines for %s use both 'choice' and 'interleave'\n", 05752 name, NULL); 05753 } 05754 } else { 05755 xmlRngPErr(ctxt, define->node, XML_RNGP_UNKNOWN_COMBINE, 05756 "Defines for %s use unknown combine value '%s''\n", 05757 name, combine); 05758 } 05759 xmlFree(combine); 05760 } else { 05761 if (missing == 0) 05762 missing = 1; 05763 else { 05764 xmlRngPErr(ctxt, define->node, XML_RNGP_NEED_COMBINE, 05765 "Some defines for %s needs the combine attribute\n", 05766 name, NULL); 05767 } 05768 } 05769 05770 cur = cur->nextHash; 05771 } 05772 #ifdef DEBUG 05773 xmlGenericError(xmlGenericErrorContext, 05774 "xmlRelaxNGCheckCombine(): merging %s defines: %d\n", 05775 name, choiceOrInterleave); 05776 #endif 05777 if (choiceOrInterleave == -1) 05778 choiceOrInterleave = 0; 05779 cur = xmlRelaxNGNewDefine(ctxt, define->node); 05780 if (cur == NULL) 05781 return; 05782 if (choiceOrInterleave == 0) 05783 cur->type = XML_RELAXNG_INTERLEAVE; 05784 else 05785 cur->type = XML_RELAXNG_CHOICE; 05786 tmp = define; 05787 last = NULL; 05788 while (tmp != NULL) { 05789 if (tmp->content != NULL) { 05790 if (tmp->content->next != NULL) { 05791 /* 05792 * we need first to create a wrapper. 05793 */ 05794 tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node); 05795 if (tmp2 == NULL) 05796 break; 05797 tmp2->type = XML_RELAXNG_GROUP; 05798 tmp2->content = tmp->content; 05799 } else { 05800 tmp2 = tmp->content; 05801 } 05802 if (last == NULL) { 05803 cur->content = tmp2; 05804 } else { 05805 last->next = tmp2; 05806 } 05807 last = tmp2; 05808 } 05809 tmp->content = cur; 05810 tmp = tmp->nextHash; 05811 } 05812 define->content = cur; 05813 if (choiceOrInterleave == 0) { 05814 if (ctxt->interleaves == NULL) 05815 ctxt->interleaves = xmlHashCreate(10); 05816 if (ctxt->interleaves == NULL) { 05817 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED, 05818 "Failed to create interleaves hash table\n", NULL, 05819 NULL); 05820 } else { 05821 char tmpname[32]; 05822 05823 snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++); 05824 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) < 05825 0) { 05826 xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED, 05827 "Failed to add %s to hash table\n", 05828 (const xmlChar *) tmpname, NULL); 05829 } 05830 } 05831 } 05832 } 05833 05842 static void 05843 xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt, 05844 xmlRelaxNGGrammarPtr grammar) 05845 { 05846 xmlRelaxNGDefinePtr starts; 05847 xmlChar *combine; 05848 int choiceOrInterleave = -1; 05849 int missing = 0; 05850 xmlRelaxNGDefinePtr cur; 05851 05852 starts = grammar->start; 05853 if ((starts == NULL) || (starts->next == NULL)) 05854 return; 05855 cur = starts; 05856 while (cur != NULL) { 05857 if ((cur->node == NULL) || (cur->node->parent == NULL) || 05858 (!xmlStrEqual(cur->node->parent->name, BAD_CAST "start"))) { 05859 combine = NULL; 05860 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_MISSING, 05861 "Internal error: start element not found\n", NULL, 05862 NULL); 05863 } else { 05864 combine = xmlGetProp(cur->node->parent, BAD_CAST "combine"); 05865 } 05866 05867 if (combine != NULL) { 05868 if (xmlStrEqual(combine, BAD_CAST "choice")) { 05869 if (choiceOrInterleave == -1) 05870 choiceOrInterleave = 1; 05871 else if (choiceOrInterleave == 0) { 05872 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE, 05873 "<start> use both 'choice' and 'interleave'\n", 05874 NULL, NULL); 05875 } 05876 } else if (xmlStrEqual(combine, BAD_CAST "interleave")) { 05877 if (choiceOrInterleave == -1) 05878 choiceOrInterleave = 0; 05879 else if (choiceOrInterleave == 1) { 05880 xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE, 05881 "<start> use both 'choice' and 'interleave'\n", 05882 NULL, NULL); 05883 } 05884 } else { 05885 xmlRngPErr(ctxt, cur->node, XML_RNGP_UNKNOWN_COMBINE, 05886 "<start> uses unknown combine value '%s''\n", 05887 combine, NULL); 05888 } 05889 xmlFree(combine); 05890 } else { 05891 if (missing == 0) 05892 missing = 1; 05893 else { 05894 xmlRngPErr(ctxt, cur->node, XML_RNGP_NEED_COMBINE, 05895 "Some <start> element miss the combine attribute\n", 05896 NULL, NULL); 05897 } 05898 } 05899 05900 cur = cur->next; 05901 } 05902 #ifdef DEBUG 05903 xmlGenericError(xmlGenericErrorContext, 05904 "xmlRelaxNGCombineStart(): merging <start>: %d\n", 05905 choiceOrInterleave); 05906 #endif 05907 if (choiceOrInterleave == -1) 05908 choiceOrInterleave = 0; 05909 cur = xmlRelaxNGNewDefine(ctxt, starts->node); 05910 if (cur == NULL) 05911 return; 05912 if (choiceOrInterleave == 0) 05913 cur->type = XML_RELAXNG_INTERLEAVE; 05914 else 05915 cur->type = XML_RELAXNG_CHOICE; 05916 cur->content = grammar->start; 05917 grammar->start = cur; 05918 if (choiceOrInterleave == 0) { 05919 if (ctxt->interleaves == NULL) 05920 ctxt->interleaves = xmlHashCreate(10); 05921 if (ctxt->interleaves == NULL) { 05922 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED, 05923 "Failed to create interleaves hash table\n", NULL, 05924 NULL); 05925 } else { 05926 char tmpname[32]; 05927 05928 snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++); 05929 if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) < 05930 0) { 05931 xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED, 05932 "Failed to add %s to hash table\n", 05933 (const xmlChar *) tmpname, NULL); 05934 } 05935 } 05936 } 05937 } 05938 05949 static int 05950 xmlRelaxNGCheckCycles(xmlRelaxNGParserCtxtPtr ctxt, 05951 xmlRelaxNGDefinePtr cur, int depth) 05952 { 05953 int ret = 0; 05954 05955 while ((ret == 0) && (cur != NULL)) { 05956 if ((cur->type == XML_RELAXNG_REF) || 05957 (cur->type == XML_RELAXNG_PARENTREF)) { 05958 if (cur->depth == -1) { 05959 cur->depth = depth; 05960 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth); 05961 cur->depth = -2; 05962 } else if (depth == cur->depth) { 05963 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_CYCLE, 05964 "Detected a cycle in %s references\n", 05965 cur->name, NULL); 05966 return (-1); 05967 } 05968 } else if (cur->type == XML_RELAXNG_ELEMENT) { 05969 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth + 1); 05970 } else { 05971 ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth); 05972 } 05973 cur = cur->next; 05974 } 05975 return (ret); 05976 } 05977 05989 static xmlRelaxNGDefinePtr 05990 xmlRelaxNGTryUnlink(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, 05991 xmlRelaxNGDefinePtr cur, 05992 xmlRelaxNGDefinePtr parent, xmlRelaxNGDefinePtr prev) 05993 { 05994 if (prev != NULL) { 05995 prev->next = cur->next; 05996 } else { 05997 if (parent != NULL) { 05998 if (parent->content == cur) 05999 parent->content = cur->next; 06000 else if (parent->attrs == cur) 06001 parent->attrs = cur->next; 06002 else if (parent->nameClass == cur) 06003 parent->nameClass = cur->next; 06004 } else { 06005 cur->type = XML_RELAXNG_NOOP; 06006 prev = cur; 06007 } 06008 } 06009 return (prev); 06010 } 06011 06019 static void 06020 xmlRelaxNGSimplify(xmlRelaxNGParserCtxtPtr ctxt, 06021 xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent) 06022 { 06023 xmlRelaxNGDefinePtr prev = NULL; 06024 06025 while (cur != NULL) { 06026 if ((cur->type == XML_RELAXNG_REF) || 06027 (cur->type == XML_RELAXNG_PARENTREF)) { 06028 if (cur->depth != -3) { 06029 cur->depth = -3; 06030 xmlRelaxNGSimplify(ctxt, cur->content, cur); 06031 } 06032 } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) { 06033 cur->parent = parent; 06034 if ((parent != NULL) && 06035 ((parent->type == XML_RELAXNG_ATTRIBUTE) || 06036 (parent->type == XML_RELAXNG_LIST) || 06037 (parent->type == XML_RELAXNG_GROUP) || 06038 (parent->type == XML_RELAXNG_INTERLEAVE) || 06039 (parent->type == XML_RELAXNG_ONEORMORE) || 06040 (parent->type == XML_RELAXNG_ZEROORMORE))) { 06041 parent->type = XML_RELAXNG_NOT_ALLOWED; 06042 break; 06043 } 06044 if ((parent != NULL) && (parent->type == XML_RELAXNG_CHOICE)) { 06045 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); 06046 } else 06047 prev = cur; 06048 } else if (cur->type == XML_RELAXNG_EMPTY) { 06049 cur->parent = parent; 06050 if ((parent != NULL) && 06051 ((parent->type == XML_RELAXNG_ONEORMORE) || 06052 (parent->type == XML_RELAXNG_ZEROORMORE))) { 06053 parent->type = XML_RELAXNG_EMPTY; 06054 break; 06055 } 06056 if ((parent != NULL) && 06057 ((parent->type == XML_RELAXNG_GROUP) || 06058 (parent->type == XML_RELAXNG_INTERLEAVE))) { 06059 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); 06060 } else 06061 prev = cur; 06062 } else { 06063 cur->parent = parent; 06064 if (cur->content != NULL) 06065 xmlRelaxNGSimplify(ctxt, cur->content, cur); 06066 if ((cur->type != XML_RELAXNG_VALUE) && (cur->attrs != NULL)) 06067 xmlRelaxNGSimplify(ctxt, cur->attrs, cur); 06068 if (cur->nameClass != NULL) 06069 xmlRelaxNGSimplify(ctxt, cur->nameClass, cur); 06070 /* 06071 * On Elements, try to move attribute only generating rules on 06072 * the attrs rules. 06073 */ 06074 if (cur->type == XML_RELAXNG_ELEMENT) { 06075 int attronly; 06076 xmlRelaxNGDefinePtr tmp, pre; 06077 06078 while (cur->content != NULL) { 06079 attronly = 06080 xmlRelaxNGGenerateAttributes(ctxt, cur->content); 06081 if (attronly == 1) { 06082 /* 06083 * migrate cur->content to attrs 06084 */ 06085 tmp = cur->content; 06086 cur->content = tmp->next; 06087 tmp->next = cur->attrs; 06088 cur->attrs = tmp; 06089 } else { 06090 /* 06091 * cur->content can generate elements or text 06092 */ 06093 break; 06094 } 06095 } 06096 pre = cur->content; 06097 while ((pre != NULL) && (pre->next != NULL)) { 06098 tmp = pre->next; 06099 attronly = xmlRelaxNGGenerateAttributes(ctxt, tmp); 06100 if (attronly == 1) { 06101 /* 06102 * migrate tmp to attrs 06103 */ 06104 pre->next = tmp->next; 06105 tmp->next = cur->attrs; 06106 cur->attrs = tmp; 06107 } else { 06108 pre = tmp; 06109 } 06110 } 06111 } 06112 /* 06113 * This may result in a simplification 06114 */ 06115 if ((cur->type == XML_RELAXNG_GROUP) || 06116 (cur->type == XML_RELAXNG_INTERLEAVE)) { 06117 if (cur->content == NULL) 06118 cur->type = XML_RELAXNG_EMPTY; 06119 else if (cur->content->next == NULL) { 06120 if ((parent == NULL) && (prev == NULL)) { 06121 cur->type = XML_RELAXNG_NOOP; 06122 } else if (prev == NULL) { 06123 parent->content = cur->content; 06124 cur->content->next = cur->next; 06125 cur = cur->content; 06126 } else { 06127 cur->content->next = cur->next; 06128 prev->next = cur->content; 06129 cur = cur->content; 06130 } 06131 } 06132 } 06133 /* 06134 * the current node may have been transformed back 06135 */ 06136 if ((cur->type == XML_RELAXNG_EXCEPT) && 06137 (cur->content != NULL) && 06138 (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) { 06139 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); 06140 } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) { 06141 if ((parent != NULL) && 06142 ((parent->type == XML_RELAXNG_ATTRIBUTE) || 06143 (parent->type == XML_RELAXNG_LIST) || 06144 (parent->type == XML_RELAXNG_GROUP) || 06145 (parent->type == XML_RELAXNG_INTERLEAVE) || 06146 (parent->type == XML_RELAXNG_ONEORMORE) || 06147 (parent->type == XML_RELAXNG_ZEROORMORE))) { 06148 parent->type = XML_RELAXNG_NOT_ALLOWED; 06149 break; 06150 } 06151 if ((parent != NULL) && 06152 (parent->type == XML_RELAXNG_CHOICE)) { 06153 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); 06154 } else 06155 prev = cur; 06156 } else if (cur->type == XML_RELAXNG_EMPTY) { 06157 if ((parent != NULL) && 06158 ((parent->type == XML_RELAXNG_ONEORMORE) || 06159 (parent->type == XML_RELAXNG_ZEROORMORE))) { 06160 parent->type = XML_RELAXNG_EMPTY; 06161 break; 06162 } 06163 if ((parent != NULL) && 06164 ((parent->type == XML_RELAXNG_GROUP) || 06165 (parent->type == XML_RELAXNG_INTERLEAVE) || 06166 (parent->type == XML_RELAXNG_CHOICE))) { 06167 prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev); 06168 } else 06169 prev = cur; 06170 } else { 06171 prev = cur; 06172 } 06173 } 06174 cur = cur->next; 06175 } 06176 } 06177 06187 static xmlRelaxNGContentType 06188 xmlRelaxNGGroupContentType(xmlRelaxNGContentType ct1, 06189 xmlRelaxNGContentType ct2) 06190 { 06191 if ((ct1 == XML_RELAXNG_CONTENT_ERROR) || 06192 (ct2 == XML_RELAXNG_CONTENT_ERROR)) 06193 return (XML_RELAXNG_CONTENT_ERROR); 06194 if (ct1 == XML_RELAXNG_CONTENT_EMPTY) 06195 return (ct2); 06196 if (ct2 == XML_RELAXNG_CONTENT_EMPTY) 06197 return (ct1); 06198 if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) && 06199 (ct2 == XML_RELAXNG_CONTENT_COMPLEX)) 06200 return (XML_RELAXNG_CONTENT_COMPLEX); 06201 return (XML_RELAXNG_CONTENT_ERROR); 06202 } 06203 06213 static xmlRelaxNGContentType 06214 xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1, 06215 xmlRelaxNGContentType ct2) 06216 { 06217 if ((ct1 == XML_RELAXNG_CONTENT_ERROR) || 06218 (ct2 == XML_RELAXNG_CONTENT_ERROR)) 06219 return (XML_RELAXNG_CONTENT_ERROR); 06220 if ((ct1 == XML_RELAXNG_CONTENT_SIMPLE) || 06221 (ct2 == XML_RELAXNG_CONTENT_SIMPLE)) 06222 return (XML_RELAXNG_CONTENT_SIMPLE); 06223 if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) || 06224 (ct2 == XML_RELAXNG_CONTENT_COMPLEX)) 06225 return (XML_RELAXNG_CONTENT_COMPLEX); 06226 return (XML_RELAXNG_CONTENT_EMPTY); 06227 } 06228 06240 static xmlRelaxNGContentType 06241 xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt, 06242 xmlRelaxNGDefinePtr cur, int flags, 06243 xmlRelaxNGType ptype) 06244 { 06245 int nflags; 06246 xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY; 06247 06248 while (cur != NULL) { 06249 ret = XML_RELAXNG_CONTENT_EMPTY; 06250 if ((cur->type == XML_RELAXNG_REF) || 06251 (cur->type == XML_RELAXNG_PARENTREF)) { 06252 /* 06253 * This should actually be caught by list//element(ref) at the 06254 * element boundaries, c.f. Bug #159968 local refs are dropped 06255 * in step 4.19. 06256 */ 06257 #if 0 06258 if (flags & XML_RELAXNG_IN_LIST) { 06259 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_REF, 06260 "Found forbidden pattern list//ref\n", NULL, 06261 NULL); 06262 } 06263 #endif 06264 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06265 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_REF, 06266 "Found forbidden pattern data/except//ref\n", 06267 NULL, NULL); 06268 } 06269 if (cur->content == NULL) { 06270 if (cur->type == XML_RELAXNG_PARENTREF) 06271 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF, 06272 "Internal found no define for parent refs\n", 06273 NULL, NULL); 06274 else 06275 xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF, 06276 "Internal found no define for ref %s\n", 06277 (cur->name ? cur->name: BAD_CAST "null"), NULL); 06278 } 06279 if (cur->depth > -4) { 06280 cur->depth = -4; 06281 ret = xmlRelaxNGCheckRules(ctxt, cur->content, 06282 flags, cur->type); 06283 cur->depth = ret - 15; 06284 } else if (cur->depth == -4) { 06285 ret = XML_RELAXNG_CONTENT_COMPLEX; 06286 } else { 06287 ret = (xmlRelaxNGContentType) (cur->depth + 15); 06288 } 06289 } else if (cur->type == XML_RELAXNG_ELEMENT) { 06290 /* 06291 * The 7.3 Attribute derivation rule for groups is plugged there 06292 */ 06293 xmlRelaxNGCheckGroupAttrs(ctxt, cur); 06294 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06295 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ELEM, 06296 "Found forbidden pattern data/except//element(ref)\n", 06297 NULL, NULL); 06298 } 06299 if (flags & XML_RELAXNG_IN_LIST) { 06300 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ELEM, 06301 "Found forbidden pattern list//element(ref)\n", 06302 NULL, NULL); 06303 } 06304 if (flags & XML_RELAXNG_IN_ATTRIBUTE) { 06305 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM, 06306 "Found forbidden pattern attribute//element(ref)\n", 06307 NULL, NULL); 06308 } 06309 if (flags & XML_RELAXNG_IN_ATTRIBUTE) { 06310 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM, 06311 "Found forbidden pattern attribute//element(ref)\n", 06312 NULL, NULL); 06313 } 06314 /* 06315 * reset since in the simple form elements are only child 06316 * of grammar/define 06317 */ 06318 nflags = 0; 06319 ret = 06320 xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type); 06321 if (ret != XML_RELAXNG_CONTENT_EMPTY) { 06322 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_EMPTY, 06323 "Element %s attributes have a content type error\n", 06324 cur->name, NULL); 06325 } 06326 ret = 06327 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, 06328 cur->type); 06329 if (ret == XML_RELAXNG_CONTENT_ERROR) { 06330 xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_ERROR, 06331 "Element %s has a content type error\n", 06332 cur->name, NULL); 06333 } else { 06334 ret = XML_RELAXNG_CONTENT_COMPLEX; 06335 } 06336 } else if (cur->type == XML_RELAXNG_ATTRIBUTE) { 06337 if (flags & XML_RELAXNG_IN_ATTRIBUTE) { 06338 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ATTR, 06339 "Found forbidden pattern attribute//attribute\n", 06340 NULL, NULL); 06341 } 06342 if (flags & XML_RELAXNG_IN_LIST) { 06343 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ATTR, 06344 "Found forbidden pattern list//attribute\n", 06345 NULL, NULL); 06346 } 06347 if (flags & XML_RELAXNG_IN_OOMGROUP) { 06348 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_GROUP_ATTR, 06349 "Found forbidden pattern oneOrMore//group//attribute\n", 06350 NULL, NULL); 06351 } 06352 if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) { 06353 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR, 06354 "Found forbidden pattern oneOrMore//interleave//attribute\n", 06355 NULL, NULL); 06356 } 06357 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06358 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ATTR, 06359 "Found forbidden pattern data/except//attribute\n", 06360 NULL, NULL); 06361 } 06362 if (flags & XML_RELAXNG_IN_START) { 06363 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ATTR, 06364 "Found forbidden pattern start//attribute\n", 06365 NULL, NULL); 06366 } 06367 if ((!(flags & XML_RELAXNG_IN_ONEORMORE)) 06368 && (cur->name == NULL)) { 06369 if (cur->ns == NULL) { 06370 xmlRngPErr(ctxt, cur->node, XML_RNGP_ANYNAME_ATTR_ANCESTOR, 06371 "Found anyName attribute without oneOrMore ancestor\n", 06372 NULL, NULL); 06373 } else { 06374 xmlRngPErr(ctxt, cur->node, XML_RNGP_NSNAME_ATTR_ANCESTOR, 06375 "Found nsName attribute without oneOrMore ancestor\n", 06376 NULL, NULL); 06377 } 06378 } 06379 nflags = flags | XML_RELAXNG_IN_ATTRIBUTE; 06380 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type); 06381 ret = XML_RELAXNG_CONTENT_EMPTY; 06382 } else if ((cur->type == XML_RELAXNG_ONEORMORE) || 06383 (cur->type == XML_RELAXNG_ZEROORMORE)) { 06384 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06385 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ONEMORE, 06386 "Found forbidden pattern data/except//oneOrMore\n", 06387 NULL, NULL); 06388 } 06389 if (flags & XML_RELAXNG_IN_START) { 06390 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ONEMORE, 06391 "Found forbidden pattern start//oneOrMore\n", 06392 NULL, NULL); 06393 } 06394 nflags = flags | XML_RELAXNG_IN_ONEORMORE; 06395 ret = 06396 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, 06397 cur->type); 06398 ret = xmlRelaxNGGroupContentType(ret, ret); 06399 } else if (cur->type == XML_RELAXNG_LIST) { 06400 if (flags & XML_RELAXNG_IN_LIST) { 06401 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_LIST, 06402 "Found forbidden pattern list//list\n", NULL, 06403 NULL); 06404 } 06405 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06406 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_LIST, 06407 "Found forbidden pattern data/except//list\n", 06408 NULL, NULL); 06409 } 06410 if (flags & XML_RELAXNG_IN_START) { 06411 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_LIST, 06412 "Found forbidden pattern start//list\n", NULL, 06413 NULL); 06414 } 06415 nflags = flags | XML_RELAXNG_IN_LIST; 06416 ret = 06417 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, 06418 cur->type); 06419 } else if (cur->type == XML_RELAXNG_GROUP) { 06420 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06421 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_GROUP, 06422 "Found forbidden pattern data/except//group\n", 06423 NULL, NULL); 06424 } 06425 if (flags & XML_RELAXNG_IN_START) { 06426 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_GROUP, 06427 "Found forbidden pattern start//group\n", NULL, 06428 NULL); 06429 } 06430 if (flags & XML_RELAXNG_IN_ONEORMORE) 06431 nflags = flags | XML_RELAXNG_IN_OOMGROUP; 06432 else 06433 nflags = flags; 06434 ret = 06435 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, 06436 cur->type); 06437 /* 06438 * The 7.3 Attribute derivation rule for groups is plugged there 06439 */ 06440 xmlRelaxNGCheckGroupAttrs(ctxt, cur); 06441 } else if (cur->type == XML_RELAXNG_INTERLEAVE) { 06442 if (flags & XML_RELAXNG_IN_LIST) { 06443 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_INTERLEAVE, 06444 "Found forbidden pattern list//interleave\n", 06445 NULL, NULL); 06446 } 06447 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06448 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE, 06449 "Found forbidden pattern data/except//interleave\n", 06450 NULL, NULL); 06451 } 06452 if (flags & XML_RELAXNG_IN_START) { 06453 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE, 06454 "Found forbidden pattern start//interleave\n", 06455 NULL, NULL); 06456 } 06457 if (flags & XML_RELAXNG_IN_ONEORMORE) 06458 nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE; 06459 else 06460 nflags = flags; 06461 ret = 06462 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, 06463 cur->type); 06464 } else if (cur->type == XML_RELAXNG_EXCEPT) { 06465 if ((cur->parent != NULL) && 06466 (cur->parent->type == XML_RELAXNG_DATATYPE)) 06467 nflags = flags | XML_RELAXNG_IN_DATAEXCEPT; 06468 else 06469 nflags = flags; 06470 ret = 06471 xmlRelaxNGCheckRules(ctxt, cur->content, nflags, 06472 cur->type); 06473 } else if (cur->type == XML_RELAXNG_DATATYPE) { 06474 if (flags & XML_RELAXNG_IN_START) { 06475 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_DATA, 06476 "Found forbidden pattern start//data\n", NULL, 06477 NULL); 06478 } 06479 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type); 06480 ret = XML_RELAXNG_CONTENT_SIMPLE; 06481 } else if (cur->type == XML_RELAXNG_VALUE) { 06482 if (flags & XML_RELAXNG_IN_START) { 06483 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_VALUE, 06484 "Found forbidden pattern start//value\n", NULL, 06485 NULL); 06486 } 06487 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type); 06488 ret = XML_RELAXNG_CONTENT_SIMPLE; 06489 } else if (cur->type == XML_RELAXNG_TEXT) { 06490 if (flags & XML_RELAXNG_IN_LIST) { 06491 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_TEXT, 06492 "Found forbidden pattern list//text\n", NULL, 06493 NULL); 06494 } 06495 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06496 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_TEXT, 06497 "Found forbidden pattern data/except//text\n", 06498 NULL, NULL); 06499 } 06500 if (flags & XML_RELAXNG_IN_START) { 06501 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_TEXT, 06502 "Found forbidden pattern start//text\n", NULL, 06503 NULL); 06504 } 06505 ret = XML_RELAXNG_CONTENT_COMPLEX; 06506 } else if (cur->type == XML_RELAXNG_EMPTY) { 06507 if (flags & XML_RELAXNG_IN_DATAEXCEPT) { 06508 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_EMPTY, 06509 "Found forbidden pattern data/except//empty\n", 06510 NULL, NULL); 06511 } 06512 if (flags & XML_RELAXNG_IN_START) { 06513 xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_EMPTY, 06514 "Found forbidden pattern start//empty\n", NULL, 06515 NULL); 06516 } 06517 ret = XML_RELAXNG_CONTENT_EMPTY; 06518 } else if (cur->type == XML_RELAXNG_CHOICE) { 06519 xmlRelaxNGCheckChoiceDeterminism(ctxt, cur); 06520 ret = 06521 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type); 06522 } else { 06523 ret = 06524 xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type); 06525 } 06526 cur = cur->next; 06527 if (ptype == XML_RELAXNG_GROUP) { 06528 val = xmlRelaxNGGroupContentType(val, ret); 06529 } else if (ptype == XML_RELAXNG_INTERLEAVE) { 06530 /* 06531 * TODO: scan complain that tmp is never used, seems on purpose 06532 * need double-checking 06533 */ 06534 tmp = xmlRelaxNGGroupContentType(val, ret); 06535 if (tmp != XML_RELAXNG_CONTENT_ERROR) 06536 tmp = xmlRelaxNGMaxContentType(val, ret); 06537 } else if (ptype == XML_RELAXNG_CHOICE) { 06538 val = xmlRelaxNGMaxContentType(val, ret); 06539 } else if (ptype == XML_RELAXNG_LIST) { 06540 val = XML_RELAXNG_CONTENT_SIMPLE; 06541 } else if (ptype == XML_RELAXNG_EXCEPT) { 06542 if (ret == XML_RELAXNG_CONTENT_ERROR) 06543 val = XML_RELAXNG_CONTENT_ERROR; 06544 else 06545 val = XML_RELAXNG_CONTENT_SIMPLE; 06546 } else { 06547 val = xmlRelaxNGGroupContentType(val, ret); 06548 } 06549 06550 } 06551 return (val); 06552 } 06553 06564 static xmlRelaxNGGrammarPtr 06565 xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes) 06566 { 06567 xmlRelaxNGGrammarPtr ret, tmp, old; 06568 06569 #ifdef DEBUG_GRAMMAR 06570 xmlGenericError(xmlGenericErrorContext, "Parsing a new grammar\n"); 06571 #endif 06572 06573 ret = xmlRelaxNGNewGrammar(ctxt); 06574 if (ret == NULL) 06575 return (NULL); 06576 06577 /* 06578 * Link the new grammar in the tree 06579 */ 06580 ret->parent = ctxt->grammar; 06581 if (ctxt->grammar != NULL) { 06582 tmp = ctxt->grammar->children; 06583 if (tmp == NULL) { 06584 ctxt->grammar->children = ret; 06585 } else { 06586 while (tmp->next != NULL) 06587 tmp = tmp->next; 06588 tmp->next = ret; 06589 } 06590 } 06591 06592 old = ctxt->grammar; 06593 ctxt->grammar = ret; 06594 xmlRelaxNGParseGrammarContent(ctxt, nodes); 06595 ctxt->grammar = ret; 06596 if (ctxt->grammar == NULL) { 06597 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT, 06598 "Failed to parse <grammar> content\n", NULL, NULL); 06599 } else if (ctxt->grammar->start == NULL) { 06600 xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_NO_START, 06601 "Element <grammar> has no <start>\n", NULL, NULL); 06602 } 06603 06604 /* 06605 * Apply 4.17 mergingd rules to defines and starts 06606 */ 06607 xmlRelaxNGCombineStart(ctxt, ret); 06608 if (ret->defs != NULL) { 06609 xmlHashScan(ret->defs, (xmlHashScanner) xmlRelaxNGCheckCombine, 06610 ctxt); 06611 } 06612 06613 /* 06614 * link together defines and refs in this grammar 06615 */ 06616 if (ret->refs != NULL) { 06617 xmlHashScan(ret->refs, (xmlHashScanner) xmlRelaxNGCheckReference, 06618 ctxt); 06619 } 06620 06621 06622 /* @@@@ */ 06623 06624 ctxt->grammar = old; 06625 return (ret); 06626 } 06627 06639 static xmlRelaxNGPtr 06640 xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 06641 { 06642 xmlRelaxNGPtr schema = NULL; 06643 const xmlChar *olddefine; 06644 xmlRelaxNGGrammarPtr old; 06645 06646 if ((ctxt == NULL) || (node == NULL)) 06647 return (NULL); 06648 06649 schema = xmlRelaxNGNewRelaxNG(ctxt); 06650 if (schema == NULL) 06651 return (NULL); 06652 06653 olddefine = ctxt->define; 06654 ctxt->define = NULL; 06655 if (IS_RELAXNG(node, "grammar")) { 06656 schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children); 06657 } else { 06658 xmlRelaxNGGrammarPtr tmp, ret; 06659 06660 schema->topgrammar = ret = xmlRelaxNGNewGrammar(ctxt); 06661 if (schema->topgrammar == NULL) { 06662 return (schema); 06663 } 06664 /* 06665 * Link the new grammar in the tree 06666 */ 06667 ret->parent = ctxt->grammar; 06668 if (ctxt->grammar != NULL) { 06669 tmp = ctxt->grammar->children; 06670 if (tmp == NULL) { 06671 ctxt->grammar->children = ret; 06672 } else { 06673 while (tmp->next != NULL) 06674 tmp = tmp->next; 06675 tmp->next = ret; 06676 } 06677 } 06678 old = ctxt->grammar; 06679 ctxt->grammar = ret; 06680 xmlRelaxNGParseStart(ctxt, node); 06681 if (old != NULL) 06682 ctxt->grammar = old; 06683 } 06684 ctxt->define = olddefine; 06685 if (schema->topgrammar->start != NULL) { 06686 xmlRelaxNGCheckCycles(ctxt, schema->topgrammar->start, 0); 06687 if ((ctxt->flags & XML_RELAXNG_IN_EXTERNALREF) == 0) { 06688 xmlRelaxNGSimplify(ctxt, schema->topgrammar->start, NULL); 06689 while ((schema->topgrammar->start != NULL) && 06690 (schema->topgrammar->start->type == XML_RELAXNG_NOOP) && 06691 (schema->topgrammar->start->next != NULL)) 06692 schema->topgrammar->start = 06693 schema->topgrammar->start->content; 06694 xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start, 06695 XML_RELAXNG_IN_START, XML_RELAXNG_NOOP); 06696 } 06697 } 06698 #ifdef DEBUG 06699 if (schema == NULL) 06700 xmlGenericError(xmlGenericErrorContext, 06701 "xmlRelaxNGParseDocument() failed\n"); 06702 #endif 06703 06704 return (schema); 06705 } 06706 06707 /************************************************************************ 06708 * * 06709 * Reading RelaxNGs * 06710 * * 06711 ************************************************************************/ 06712 06722 xmlRelaxNGParserCtxtPtr 06723 xmlRelaxNGNewParserCtxt(const char *URL) 06724 { 06725 xmlRelaxNGParserCtxtPtr ret; 06726 06727 if (URL == NULL) 06728 return (NULL); 06729 06730 ret = 06731 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt)); 06732 if (ret == NULL) { 06733 xmlRngPErrMemory(NULL, "building parser\n"); 06734 return (NULL); 06735 } 06736 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt)); 06737 ret->URL = xmlStrdup((const xmlChar *) URL); 06738 ret->error = xmlGenericError; 06739 ret->userData = xmlGenericErrorContext; 06740 return (ret); 06741 } 06742 06753 xmlRelaxNGParserCtxtPtr 06754 xmlRelaxNGNewMemParserCtxt(const char *buffer, int size) 06755 { 06756 xmlRelaxNGParserCtxtPtr ret; 06757 06758 if ((buffer == NULL) || (size <= 0)) 06759 return (NULL); 06760 06761 ret = 06762 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt)); 06763 if (ret == NULL) { 06764 xmlRngPErrMemory(NULL, "building parser\n"); 06765 return (NULL); 06766 } 06767 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt)); 06768 ret->buffer = buffer; 06769 ret->size = size; 06770 ret->error = xmlGenericError; 06771 ret->userData = xmlGenericErrorContext; 06772 return (ret); 06773 } 06774 06785 xmlRelaxNGParserCtxtPtr 06786 xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc) 06787 { 06788 xmlRelaxNGParserCtxtPtr ret; 06789 xmlDocPtr copy; 06790 06791 if (doc == NULL) 06792 return (NULL); 06793 copy = xmlCopyDoc(doc, 1); 06794 if (copy == NULL) 06795 return (NULL); 06796 06797 ret = 06798 (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt)); 06799 if (ret == NULL) { 06800 xmlRngPErrMemory(NULL, "building parser\n"); 06801 return (NULL); 06802 } 06803 memset(ret, 0, sizeof(xmlRelaxNGParserCtxt)); 06804 ret->document = copy; 06805 ret->freedoc = 1; 06806 ret->userData = xmlGenericErrorContext; 06807 return (ret); 06808 } 06809 06816 void 06817 xmlRelaxNGFreeParserCtxt(xmlRelaxNGParserCtxtPtr ctxt) 06818 { 06819 if (ctxt == NULL) 06820 return; 06821 if (ctxt->URL != NULL) 06822 xmlFree(ctxt->URL); 06823 if (ctxt->doc != NULL) 06824 xmlRelaxNGFreeDocument(ctxt->doc); 06825 if (ctxt->interleaves != NULL) 06826 xmlHashFree(ctxt->interleaves, NULL); 06827 if (ctxt->documents != NULL) 06828 xmlRelaxNGFreeDocumentList(ctxt->documents); 06829 if (ctxt->includes != NULL) 06830 xmlRelaxNGFreeIncludeList(ctxt->includes); 06831 if (ctxt->docTab != NULL) 06832 xmlFree(ctxt->docTab); 06833 if (ctxt->incTab != NULL) 06834 xmlFree(ctxt->incTab); 06835 if (ctxt->defTab != NULL) { 06836 int i; 06837 06838 for (i = 0; i < ctxt->defNr; i++) 06839 xmlRelaxNGFreeDefine(ctxt->defTab[i]); 06840 xmlFree(ctxt->defTab); 06841 } 06842 if ((ctxt->document != NULL) && (ctxt->freedoc)) 06843 xmlFreeDoc(ctxt->document); 06844 xmlFree(ctxt); 06845 } 06846 06854 static void 06855 xmlRelaxNGNormExtSpace(xmlChar * value) 06856 { 06857 xmlChar *start = value; 06858 xmlChar *cur = value; 06859 06860 if (value == NULL) 06861 return; 06862 06863 while (IS_BLANK_CH(*cur)) 06864 cur++; 06865 if (cur == start) { 06866 do { 06867 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) 06868 cur++; 06869 if (*cur == 0) 06870 return; 06871 start = cur; 06872 while (IS_BLANK_CH(*cur)) 06873 cur++; 06874 if (*cur == 0) { 06875 *start = 0; 06876 return; 06877 } 06878 } while (1); 06879 } else { 06880 do { 06881 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) 06882 *start++ = *cur++; 06883 if (*cur == 0) { 06884 *start = 0; 06885 return; 06886 } 06887 /* don't try to normalize the inner spaces */ 06888 while (IS_BLANK_CH(*cur)) 06889 cur++; 06890 if (*cur == 0) { 06891 *start = 0; 06892 return; 06893 } 06894 *start++ = *cur++; 06895 } while (1); 06896 } 06897 } 06898 06906 static void 06907 xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) 06908 { 06909 xmlAttrPtr cur, next; 06910 06911 cur = node->properties; 06912 while (cur != NULL) { 06913 next = cur->next; 06914 if ((cur->ns == NULL) || 06915 (xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) { 06916 if (xmlStrEqual(cur->name, BAD_CAST "name")) { 06917 if ((!xmlStrEqual(node->name, BAD_CAST "element")) && 06918 (!xmlStrEqual(node->name, BAD_CAST "attribute")) && 06919 (!xmlStrEqual(node->name, BAD_CAST "ref")) && 06920 (!xmlStrEqual(node->name, BAD_CAST "parentRef")) && 06921 (!xmlStrEqual(node->name, BAD_CAST "param")) && 06922 (!xmlStrEqual(node->name, BAD_CAST "define"))) { 06923 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE, 06924 "Attribute %s is not allowed on %s\n", 06925 cur->name, node->name); 06926 } 06927 } else if (xmlStrEqual(cur->name, BAD_CAST "type")) { 06928 if ((!xmlStrEqual(node->name, BAD_CAST "value")) && 06929 (!xmlStrEqual(node->name, BAD_CAST "data"))) { 06930 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE, 06931 "Attribute %s is not allowed on %s\n", 06932 cur->name, node->name); 06933 } 06934 } else if (xmlStrEqual(cur->name, BAD_CAST "href")) { 06935 if ((!xmlStrEqual(node->name, BAD_CAST "externalRef")) && 06936 (!xmlStrEqual(node->name, BAD_CAST "include"))) { 06937 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE, 06938 "Attribute %s is not allowed on %s\n", 06939 cur->name, node->name); 06940 } 06941 } else if (xmlStrEqual(cur->name, BAD_CAST "combine")) { 06942 if ((!xmlStrEqual(node->name, BAD_CAST "start")) && 06943 (!xmlStrEqual(node->name, BAD_CAST "define"))) { 06944 xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE, 06945 "Attribute %s is not allowed on %s\n", 06946 cur->name, node->name); 06947 } 06948 } else if (xmlStrEqual(cur->name, BAD_CAST "datatypeLibrary")) { 06949 xmlChar *val; 06950 xmlURIPtr uri; 06951 06952 val = xmlNodeListGetString(node->doc, cur->children, 1); 06953 if (val != NULL) { 06954 if (val[0] != 0) { 06955 uri = xmlParseURI((const char *) val); 06956 if (uri == NULL) { 06957 xmlRngPErr(ctxt, node, XML_RNGP_INVALID_URI, 06958 "Attribute %s contains invalid URI %s\n", 06959 cur->name, val); 06960 } else { 06961 if (uri->scheme == NULL) { 06962 xmlRngPErr(ctxt, node, XML_RNGP_URI_NOT_ABSOLUTE, 06963 "Attribute %s URI %s is not absolute\n", 06964 cur->name, val); 06965 } 06966 if (uri->fragment != NULL) { 06967 xmlRngPErr(ctxt, node, XML_RNGP_URI_FRAGMENT, 06968 "Attribute %s URI %s has a fragment ID\n", 06969 cur->name, val); 06970 } 06971 xmlFreeURI(uri); 06972 } 06973 } 06974 xmlFree(val); 06975 } 06976 } else if (!xmlStrEqual(cur->name, BAD_CAST "ns")) { 06977 xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_ATTRIBUTE, 06978 "Unknown attribute %s on %s\n", cur->name, 06979 node->name); 06980 } 06981 } 06982 cur = next; 06983 } 06984 } 06985 06994 static void 06995 xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root) 06996 { 06997 xmlNodePtr cur, delete; 06998 06999 delete = NULL; 07000 cur = root; 07001 while (cur != NULL) { 07002 if (delete != NULL) { 07003 xmlUnlinkNode(delete); 07004 xmlFreeNode(delete); 07005 delete = NULL; 07006 } 07007 if (cur->type == XML_ELEMENT_NODE) { 07008 /* 07009 * Simplification 4.1. Annotations 07010 */ 07011 if ((cur->ns == NULL) || 07012 (!xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) { 07013 if ((cur->parent != NULL) && 07014 (cur->parent->type == XML_ELEMENT_NODE) && 07015 ((xmlStrEqual(cur->parent->name, BAD_CAST "name")) || 07016 (xmlStrEqual(cur->parent->name, BAD_CAST "value")) || 07017 (xmlStrEqual(cur->parent->name, BAD_CAST "param")))) { 07018 xmlRngPErr(ctxt, cur, XML_RNGP_FOREIGN_ELEMENT, 07019 "element %s doesn't allow foreign elements\n", 07020 cur->parent->name, NULL); 07021 } 07022 delete = cur; 07023 goto skip_children; 07024 } else { 07025 xmlRelaxNGCleanupAttributes(ctxt, cur); 07026 if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) { 07027 xmlChar *href, *ns, *base, *URL; 07028 xmlRelaxNGDocumentPtr docu; 07029 xmlNodePtr tmp; 07030 xmlURIPtr uri; 07031 07032 ns = xmlGetProp(cur, BAD_CAST "ns"); 07033 if (ns == NULL) { 07034 tmp = cur->parent; 07035 while ((tmp != NULL) && 07036 (tmp->type == XML_ELEMENT_NODE)) { 07037 ns = xmlGetProp(tmp, BAD_CAST "ns"); 07038 if (ns != NULL) 07039 break; 07040 tmp = tmp->parent; 07041 } 07042 } 07043 href = xmlGetProp(cur, BAD_CAST "href"); 07044 if (href == NULL) { 07045 xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF, 07046 "xmlRelaxNGParse: externalRef has no href attribute\n", 07047 NULL, NULL); 07048 if (ns != NULL) 07049 xmlFree(ns); 07050 delete = cur; 07051 goto skip_children; 07052 } 07053 uri = xmlParseURI((const char *) href); 07054 if (uri == NULL) { 07055 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR, 07056 "Incorrect URI for externalRef %s\n", 07057 href, NULL); 07058 if (ns != NULL) 07059 xmlFree(ns); 07060 if (href != NULL) 07061 xmlFree(href); 07062 delete = cur; 07063 goto skip_children; 07064 } 07065 if (uri->fragment != NULL) { 07066 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR, 07067 "Fragment forbidden in URI for externalRef %s\n", 07068 href, NULL); 07069 if (ns != NULL) 07070 xmlFree(ns); 07071 xmlFreeURI(uri); 07072 if (href != NULL) 07073 xmlFree(href); 07074 delete = cur; 07075 goto skip_children; 07076 } 07077 xmlFreeURI(uri); 07078 base = xmlNodeGetBase(cur->doc, cur); 07079 URL = xmlBuildURI(href, base); 07080 if (URL == NULL) { 07081 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR, 07082 "Failed to compute URL for externalRef %s\n", 07083 href, NULL); 07084 if (ns != NULL) 07085 xmlFree(ns); 07086 if (href != NULL) 07087 xmlFree(href); 07088 if (base != NULL) 07089 xmlFree(base); 07090 delete = cur; 07091 goto skip_children; 07092 } 07093 if (href != NULL) 07094 xmlFree(href); 07095 if (base != NULL) 07096 xmlFree(base); 07097 docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns); 07098 if (docu == NULL) { 07099 xmlRngPErr(ctxt, cur, XML_RNGP_EXTERNAL_REF_FAILURE, 07100 "Failed to load externalRef %s\n", URL, 07101 NULL); 07102 if (ns != NULL) 07103 xmlFree(ns); 07104 xmlFree(URL); 07105 delete = cur; 07106 goto skip_children; 07107 } 07108 if (ns != NULL) 07109 xmlFree(ns); 07110 xmlFree(URL); 07111 cur->psvi = docu; 07112 } else if (xmlStrEqual(cur->name, BAD_CAST "include")) { 07113 xmlChar *href, *ns, *base, *URL; 07114 xmlRelaxNGIncludePtr incl; 07115 xmlNodePtr tmp; 07116 07117 href = xmlGetProp(cur, BAD_CAST "href"); 07118 if (href == NULL) { 07119 xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF, 07120 "xmlRelaxNGParse: include has no href attribute\n", 07121 NULL, NULL); 07122 delete = cur; 07123 goto skip_children; 07124 } 07125 base = xmlNodeGetBase(cur->doc, cur); 07126 URL = xmlBuildURI(href, base); 07127 if (URL == NULL) { 07128 xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR, 07129 "Failed to compute URL for include %s\n", 07130 href, NULL); 07131 if (href != NULL) 07132 xmlFree(href); 07133 if (base != NULL) 07134 xmlFree(base); 07135 delete = cur; 07136 goto skip_children; 07137 } 07138 if (href != NULL) 07139 xmlFree(href); 07140 if (base != NULL) 07141 xmlFree(base); 07142 ns = xmlGetProp(cur, BAD_CAST "ns"); 07143 if (ns == NULL) { 07144 tmp = cur->parent; 07145 while ((tmp != NULL) && 07146 (tmp->type == XML_ELEMENT_NODE)) { 07147 ns = xmlGetProp(tmp, BAD_CAST "ns"); 07148 if (ns != NULL) 07149 break; 07150 tmp = tmp->parent; 07151 } 07152 } 07153 incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns); 07154 if (ns != NULL) 07155 xmlFree(ns); 07156 if (incl == NULL) { 07157 xmlRngPErr(ctxt, cur, XML_RNGP_INCLUDE_FAILURE, 07158 "Failed to load include %s\n", URL, 07159 NULL); 07160 xmlFree(URL); 07161 delete = cur; 07162 goto skip_children; 07163 } 07164 xmlFree(URL); 07165 cur->psvi = incl; 07166 } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) || 07167 (xmlStrEqual(cur->name, BAD_CAST "attribute"))) 07168 { 07169 xmlChar *name, *ns; 07170 xmlNodePtr text = NULL; 07171 07172 /* 07173 * Simplification 4.8. name attribute of element 07174 * and attribute elements 07175 */ 07176 name = xmlGetProp(cur, BAD_CAST "name"); 07177 if (name != NULL) { 07178 if (cur->children == NULL) { 07179 text = 07180 xmlNewChild(cur, cur->ns, BAD_CAST "name", 07181 name); 07182 } else { 07183 xmlNodePtr node; 07184 07185 node = xmlNewDocNode(cur->doc, cur->ns, 07186 BAD_CAST "name", NULL); 07187 if (node != NULL) { 07188 xmlAddPrevSibling(cur->children, node); 07189 text = xmlNewText(name); 07190 xmlAddChild(node, text); 07191 text = node; 07192 } 07193 } 07194 if (text == NULL) { 07195 xmlRngPErr(ctxt, cur, XML_RNGP_CREATE_FAILURE, 07196 "Failed to create a name %s element\n", 07197 name, NULL); 07198 } 07199 xmlUnsetProp(cur, BAD_CAST "name"); 07200 xmlFree(name); 07201 ns = xmlGetProp(cur, BAD_CAST "ns"); 07202 if (ns != NULL) { 07203 if (text != NULL) { 07204 xmlSetProp(text, BAD_CAST "ns", ns); 07205 /* xmlUnsetProp(cur, BAD_CAST "ns"); */ 07206 } 07207 xmlFree(ns); 07208 } else if (xmlStrEqual(cur->name, 07209 BAD_CAST "attribute")) { 07210 xmlSetProp(text, BAD_CAST "ns", BAD_CAST ""); 07211 } 07212 } 07213 } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) || 07214 (xmlStrEqual(cur->name, BAD_CAST "nsName")) || 07215 (xmlStrEqual(cur->name, BAD_CAST "value"))) { 07216 /* 07217 * Simplification 4.8. name attribute of element 07218 * and attribute elements 07219 */ 07220 if (xmlHasProp(cur, BAD_CAST "ns") == NULL) { 07221 xmlNodePtr node; 07222 xmlChar *ns = NULL; 07223 07224 node = cur->parent; 07225 while ((node != NULL) && 07226 (node->type == XML_ELEMENT_NODE)) { 07227 ns = xmlGetProp(node, BAD_CAST "ns"); 07228 if (ns != NULL) { 07229 break; 07230 } 07231 node = node->parent; 07232 } 07233 if (ns == NULL) { 07234 xmlSetProp(cur, BAD_CAST "ns", BAD_CAST ""); 07235 } else { 07236 xmlSetProp(cur, BAD_CAST "ns", ns); 07237 xmlFree(ns); 07238 } 07239 } 07240 if (xmlStrEqual(cur->name, BAD_CAST "name")) { 07241 xmlChar *name, *local, *prefix; 07242 07243 /* 07244 * Simplification: 4.10. QNames 07245 */ 07246 name = xmlNodeGetContent(cur); 07247 if (name != NULL) { 07248 local = xmlSplitQName2(name, &prefix); 07249 if (local != NULL) { 07250 xmlNsPtr ns; 07251 07252 ns = xmlSearchNs(cur->doc, cur, prefix); 07253 if (ns == NULL) { 07254 xmlRngPErr(ctxt, cur, 07255 XML_RNGP_PREFIX_UNDEFINED, 07256 "xmlRelaxNGParse: no namespace for prefix %s\n", 07257 prefix, NULL); 07258 } else { 07259 xmlSetProp(cur, BAD_CAST "ns", 07260 ns->href); 07261 xmlNodeSetContent(cur, local); 07262 } 07263 xmlFree(local); 07264 xmlFree(prefix); 07265 } 07266 xmlFree(name); 07267 } 07268 } 07269 /* 07270 * 4.16 07271 */ 07272 if (xmlStrEqual(cur->name, BAD_CAST "nsName")) { 07273 if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) { 07274 xmlRngPErr(ctxt, cur, 07275 XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME, 07276 "Found nsName/except//nsName forbidden construct\n", 07277 NULL, NULL); 07278 } 07279 } 07280 } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) && 07281 (cur != root)) { 07282 int oldflags = ctxt->flags; 07283 07284 /* 07285 * 4.16 07286 */ 07287 if ((cur->parent != NULL) && 07288 (xmlStrEqual 07289 (cur->parent->name, BAD_CAST "anyName"))) { 07290 ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT; 07291 xmlRelaxNGCleanupTree(ctxt, cur); 07292 ctxt->flags = oldflags; 07293 goto skip_children; 07294 } else if ((cur->parent != NULL) && 07295 (xmlStrEqual 07296 (cur->parent->name, BAD_CAST "nsName"))) { 07297 ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT; 07298 xmlRelaxNGCleanupTree(ctxt, cur); 07299 ctxt->flags = oldflags; 07300 goto skip_children; 07301 } 07302 } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) { 07303 /* 07304 * 4.16 07305 */ 07306 if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) { 07307 xmlRngPErr(ctxt, cur, 07308 XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME, 07309 "Found anyName/except//anyName forbidden construct\n", 07310 NULL, NULL); 07311 } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) { 07312 xmlRngPErr(ctxt, cur, 07313 XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME, 07314 "Found nsName/except//anyName forbidden construct\n", 07315 NULL, NULL); 07316 } 07317 } 07318 /* 07319 * Thisd is not an else since "include" is transformed 07320 * into a div 07321 */ 07322 if (xmlStrEqual(cur->name, BAD_CAST "div")) { 07323 xmlChar *ns; 07324 xmlNodePtr child, ins, tmp; 07325 07326 /* 07327 * implements rule 4.11 07328 */ 07329 07330 ns = xmlGetProp(cur, BAD_CAST "ns"); 07331 07332 child = cur->children; 07333 ins = cur; 07334 while (child != NULL) { 07335 if (ns != NULL) { 07336 if (!xmlHasProp(child, BAD_CAST "ns")) { 07337 xmlSetProp(child, BAD_CAST "ns", ns); 07338 } 07339 } 07340 tmp = child->next; 07341 xmlUnlinkNode(child); 07342 ins = xmlAddNextSibling(ins, child); 07343 child = tmp; 07344 } 07345 if (ns != NULL) 07346 xmlFree(ns); 07347 /* 07348 * Since we are about to delete cur, if it's nsDef is non-NULL we 07349 * need to preserve it (it contains the ns definitions for the 07350 * children we just moved). We'll just stick it on to the end 07351 * of cur->parent's list, since it's never going to be re-serialized 07352 * (bug 143738). 07353 */ 07354 if (cur->nsDef != NULL) { 07355 xmlNsPtr parDef = (xmlNsPtr)&cur->parent->nsDef; 07356 while (parDef->next != NULL) 07357 parDef = parDef->next; 07358 parDef->next = cur->nsDef; 07359 cur->nsDef = NULL; 07360 } 07361 delete = cur; 07362 goto skip_children; 07363 } 07364 } 07365 } 07366 /* 07367 * Simplification 4.2 whitespaces 07368 */ 07369 else if ((cur->type == XML_TEXT_NODE) || 07370 (cur->type == XML_CDATA_SECTION_NODE)) { 07371 if (IS_BLANK_NODE(cur)) { 07372 if (cur->parent->type == XML_ELEMENT_NODE) { 07373 if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value")) 07374 && 07375 (!xmlStrEqual 07376 (cur->parent->name, BAD_CAST "param"))) 07377 delete = cur; 07378 } else { 07379 delete = cur; 07380 goto skip_children; 07381 } 07382 } 07383 } else { 07384 delete = cur; 07385 goto skip_children; 07386 } 07387 07388 /* 07389 * Skip to next node 07390 */ 07391 if (cur->children != NULL) { 07392 if ((cur->children->type != XML_ENTITY_DECL) && 07393 (cur->children->type != XML_ENTITY_REF_NODE) && 07394 (cur->children->type != XML_ENTITY_NODE)) { 07395 cur = cur->children; 07396 continue; 07397 } 07398 } 07399 skip_children: 07400 if (cur->next != NULL) { 07401 cur = cur->next; 07402 continue; 07403 } 07404 07405 do { 07406 cur = cur->parent; 07407 if (cur == NULL) 07408 break; 07409 if (cur == root) { 07410 cur = NULL; 07411 break; 07412 } 07413 if (cur->next != NULL) { 07414 cur = cur->next; 07415 break; 07416 } 07417 } while (cur != NULL); 07418 } 07419 if (delete != NULL) { 07420 xmlUnlinkNode(delete); 07421 xmlFreeNode(delete); 07422 delete = NULL; 07423 } 07424 } 07425 07436 static xmlDocPtr 07437 xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc) 07438 { 07439 xmlNodePtr root; 07440 07441 /* 07442 * Extract the root 07443 */ 07444 root = xmlDocGetRootElement(doc); 07445 if (root == NULL) { 07446 xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n", 07447 ctxt->URL, NULL); 07448 return (NULL); 07449 } 07450 xmlRelaxNGCleanupTree(ctxt, root); 07451 return (doc); 07452 } 07453 07464 xmlRelaxNGPtr 07465 xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt) 07466 { 07467 xmlRelaxNGPtr ret = NULL; 07468 xmlDocPtr doc; 07469 xmlNodePtr root; 07470 07471 xmlRelaxNGInitTypes(); 07472 07473 if (ctxt == NULL) 07474 return (NULL); 07475 07476 /* 07477 * First step is to parse the input document into an DOM/Infoset 07478 */ 07479 if (ctxt->URL != NULL) { 07480 doc = xmlReadFile((const char *) ctxt->URL,NULL,0); 07481 if (doc == NULL) { 07482 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR, 07483 "xmlRelaxNGParse: could not load %s\n", ctxt->URL, 07484 NULL); 07485 return (NULL); 07486 } 07487 } else if (ctxt->buffer != NULL) { 07488 doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0); 07489 if (doc == NULL) { 07490 xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR, 07491 "xmlRelaxNGParse: could not parse schemas\n", NULL, 07492 NULL); 07493 return (NULL); 07494 } 07495 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer"); 07496 ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer"); 07497 } else if (ctxt->document != NULL) { 07498 doc = ctxt->document; 07499 } else { 07500 xmlRngPErr(ctxt, NULL, XML_RNGP_EMPTY, 07501 "xmlRelaxNGParse: nothing to parse\n", NULL, NULL); 07502 return (NULL); 07503 } 07504 ctxt->document = doc; 07505 07506 /* 07507 * Some preprocessing of the document content 07508 */ 07509 doc = xmlRelaxNGCleanupDoc(ctxt, doc); 07510 if (doc == NULL) { 07511 xmlFreeDoc(ctxt->document); 07512 ctxt->document = NULL; 07513 return (NULL); 07514 } 07515 07516 /* 07517 * Then do the parsing for good 07518 */ 07519 root = xmlDocGetRootElement(doc); 07520 if (root == NULL) { 07521 xmlRngPErr(ctxt, (xmlNodePtr) doc, 07522 XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n", 07523 (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL); 07524 07525 xmlFreeDoc(ctxt->document); 07526 ctxt->document = NULL; 07527 return (NULL); 07528 } 07529 ret = xmlRelaxNGParseDocument(ctxt, root); 07530 if (ret == NULL) { 07531 xmlFreeDoc(ctxt->document); 07532 ctxt->document = NULL; 07533 return (NULL); 07534 } 07535 07536 /* 07537 * Check the ref/defines links 07538 */ 07539 /* 07540 * try to preprocess interleaves 07541 */ 07542 if (ctxt->interleaves != NULL) { 07543 xmlHashScan(ctxt->interleaves, 07544 (xmlHashScanner) xmlRelaxNGComputeInterleaves, ctxt); 07545 } 07546 07547 /* 07548 * if there was a parsing error return NULL 07549 */ 07550 if (ctxt->nbErrors > 0) { 07551 xmlRelaxNGFree(ret); 07552 ctxt->document = NULL; 07553 xmlFreeDoc(doc); 07554 return (NULL); 07555 } 07556 07557 /* 07558 * try to compile (parts of) the schemas 07559 */ 07560 if ((ret->topgrammar != NULL) && (ret->topgrammar->start != NULL)) { 07561 if (ret->topgrammar->start->type != XML_RELAXNG_START) { 07562 xmlRelaxNGDefinePtr def; 07563 07564 def = xmlRelaxNGNewDefine(ctxt, NULL); 07565 if (def != NULL) { 07566 def->type = XML_RELAXNG_START; 07567 def->content = ret->topgrammar->start; 07568 ret->topgrammar->start = def; 07569 } 07570 } 07571 xmlRelaxNGTryCompile(ctxt, ret->topgrammar->start); 07572 } 07573 07574 /* 07575 * Transfer the pointer for cleanup at the schema level. 07576 */ 07577 ret->doc = doc; 07578 ctxt->document = NULL; 07579 ret->documents = ctxt->documents; 07580 ctxt->documents = NULL; 07581 07582 ret->includes = ctxt->includes; 07583 ctxt->includes = NULL; 07584 ret->defNr = ctxt->defNr; 07585 ret->defTab = ctxt->defTab; 07586 ctxt->defTab = NULL; 07587 if (ctxt->idref == 1) 07588 ret->idref = 1; 07589 07590 return (ret); 07591 } 07592 07602 void 07603 xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, 07604 xmlRelaxNGValidityErrorFunc err, 07605 xmlRelaxNGValidityWarningFunc warn, void *ctx) 07606 { 07607 if (ctxt == NULL) 07608 return; 07609 ctxt->error = err; 07610 ctxt->warning = warn; 07611 ctxt->serror = NULL; 07612 ctxt->userData = ctx; 07613 } 07614 07626 int 07627 xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, 07628 xmlRelaxNGValidityErrorFunc * err, 07629 xmlRelaxNGValidityWarningFunc * warn, void **ctx) 07630 { 07631 if (ctxt == NULL) 07632 return (-1); 07633 if (err != NULL) 07634 *err = ctxt->error; 07635 if (warn != NULL) 07636 *warn = ctxt->warning; 07637 if (ctx != NULL) 07638 *ctx = ctxt->userData; 07639 return (0); 07640 } 07641 07650 void 07651 xmlRelaxNGSetParserStructuredErrors(xmlRelaxNGParserCtxtPtr ctxt, 07652 xmlStructuredErrorFunc serror, 07653 void *ctx) 07654 { 07655 if (ctxt == NULL) 07656 return; 07657 ctxt->serror = serror; 07658 ctxt->error = NULL; 07659 ctxt->warning = NULL; 07660 ctxt->userData = ctx; 07661 } 07662 07663 #ifdef LIBXML_OUTPUT_ENABLED 07664 07665 /************************************************************************ 07666 * * 07667 * Dump back a compiled form * 07668 * * 07669 ************************************************************************/ 07670 static void xmlRelaxNGDumpDefine(FILE * output, 07671 xmlRelaxNGDefinePtr define); 07672 07680 static void 07681 xmlRelaxNGDumpDefines(FILE * output, xmlRelaxNGDefinePtr defines) 07682 { 07683 while (defines != NULL) { 07684 xmlRelaxNGDumpDefine(output, defines); 07685 defines = defines->next; 07686 } 07687 } 07688 07696 static void 07697 xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define) 07698 { 07699 if (define == NULL) 07700 return; 07701 switch (define->type) { 07702 case XML_RELAXNG_EMPTY: 07703 fprintf(output, "<empty/>\n"); 07704 break; 07705 case XML_RELAXNG_NOT_ALLOWED: 07706 fprintf(output, "<notAllowed/>\n"); 07707 break; 07708 case XML_RELAXNG_TEXT: 07709 fprintf(output, "<text/>\n"); 07710 break; 07711 case XML_RELAXNG_ELEMENT: 07712 fprintf(output, "<element>\n"); 07713 if (define->name != NULL) { 07714 fprintf(output, "<name"); 07715 if (define->ns != NULL) 07716 fprintf(output, " ns=\"%s\"", define->ns); 07717 fprintf(output, ">%s</name>\n", define->name); 07718 } 07719 xmlRelaxNGDumpDefines(output, define->attrs); 07720 xmlRelaxNGDumpDefines(output, define->content); 07721 fprintf(output, "</element>\n"); 07722 break; 07723 case XML_RELAXNG_LIST: 07724 fprintf(output, "<list>\n"); 07725 xmlRelaxNGDumpDefines(output, define->content); 07726 fprintf(output, "</list>\n"); 07727 break; 07728 case XML_RELAXNG_ONEORMORE: 07729 fprintf(output, "<oneOrMore>\n"); 07730 xmlRelaxNGDumpDefines(output, define->content); 07731 fprintf(output, "</oneOrMore>\n"); 07732 break; 07733 case XML_RELAXNG_ZEROORMORE: 07734 fprintf(output, "<zeroOrMore>\n"); 07735 xmlRelaxNGDumpDefines(output, define->content); 07736 fprintf(output, "</zeroOrMore>\n"); 07737 break; 07738 case XML_RELAXNG_CHOICE: 07739 fprintf(output, "<choice>\n"); 07740 xmlRelaxNGDumpDefines(output, define->content); 07741 fprintf(output, "</choice>\n"); 07742 break; 07743 case XML_RELAXNG_GROUP: 07744 fprintf(output, "<group>\n"); 07745 xmlRelaxNGDumpDefines(output, define->content); 07746 fprintf(output, "</group>\n"); 07747 break; 07748 case XML_RELAXNG_INTERLEAVE: 07749 fprintf(output, "<interleave>\n"); 07750 xmlRelaxNGDumpDefines(output, define->content); 07751 fprintf(output, "</interleave>\n"); 07752 break; 07753 case XML_RELAXNG_OPTIONAL: 07754 fprintf(output, "<optional>\n"); 07755 xmlRelaxNGDumpDefines(output, define->content); 07756 fprintf(output, "</optional>\n"); 07757 break; 07758 case XML_RELAXNG_ATTRIBUTE: 07759 fprintf(output, "<attribute>\n"); 07760 xmlRelaxNGDumpDefines(output, define->content); 07761 fprintf(output, "</attribute>\n"); 07762 break; 07763 case XML_RELAXNG_DEF: 07764 fprintf(output, "<define"); 07765 if (define->name != NULL) 07766 fprintf(output, " name=\"%s\"", define->name); 07767 fprintf(output, ">\n"); 07768 xmlRelaxNGDumpDefines(output, define->content); 07769 fprintf(output, "</define>\n"); 07770 break; 07771 case XML_RELAXNG_REF: 07772 fprintf(output, "<ref"); 07773 if (define->name != NULL) 07774 fprintf(output, " name=\"%s\"", define->name); 07775 fprintf(output, ">\n"); 07776 xmlRelaxNGDumpDefines(output, define->content); 07777 fprintf(output, "</ref>\n"); 07778 break; 07779 case XML_RELAXNG_PARENTREF: 07780 fprintf(output, "<parentRef"); 07781 if (define->name != NULL) 07782 fprintf(output, " name=\"%s\"", define->name); 07783 fprintf(output, ">\n"); 07784 xmlRelaxNGDumpDefines(output, define->content); 07785 fprintf(output, "</parentRef>\n"); 07786 break; 07787 case XML_RELAXNG_EXTERNALREF: 07788 fprintf(output, "<externalRef>"); 07789 xmlRelaxNGDumpDefines(output, define->content); 07790 fprintf(output, "</externalRef>\n"); 07791 break; 07792 case XML_RELAXNG_DATATYPE: 07793 case XML_RELAXNG_VALUE: 07794 TODO break; 07795 case XML_RELAXNG_START: 07796 case XML_RELAXNG_EXCEPT: 07797 case XML_RELAXNG_PARAM: 07798 TODO break; 07799 case XML_RELAXNG_NOOP: 07800 xmlRelaxNGDumpDefines(output, define->content); 07801 break; 07802 } 07803 } 07804 07813 static void 07814 xmlRelaxNGDumpGrammar(FILE * output, xmlRelaxNGGrammarPtr grammar, int top) 07815 { 07816 if (grammar == NULL) 07817 return; 07818 07819 fprintf(output, "<grammar"); 07820 if (top) 07821 fprintf(output, " xmlns=\"http://relaxng.org/ns/structure/1.0\""); 07822 switch (grammar->combine) { 07823 case XML_RELAXNG_COMBINE_UNDEFINED: 07824 break; 07825 case XML_RELAXNG_COMBINE_CHOICE: 07826 fprintf(output, " combine=\"choice\""); 07827 break; 07828 case XML_RELAXNG_COMBINE_INTERLEAVE: 07829 fprintf(output, " combine=\"interleave\""); 07830 break; 07831 default: 07832 fprintf(output, " <!-- invalid combine value -->"); 07833 } 07834 fprintf(output, ">\n"); 07835 if (grammar->start == NULL) { 07836 fprintf(output, " <!-- grammar had no start -->"); 07837 } else { 07838 fprintf(output, "<start>\n"); 07839 xmlRelaxNGDumpDefine(output, grammar->start); 07840 fprintf(output, "</start>\n"); 07841 } 07842 /* TODO ? Dump the defines ? */ 07843 fprintf(output, "</grammar>\n"); 07844 } 07845 07853 void 07854 xmlRelaxNGDump(FILE * output, xmlRelaxNGPtr schema) 07855 { 07856 if (output == NULL) 07857 return; 07858 if (schema == NULL) { 07859 fprintf(output, "RelaxNG empty or failed to compile\n"); 07860 return; 07861 } 07862 fprintf(output, "RelaxNG: "); 07863 if (schema->doc == NULL) { 07864 fprintf(output, "no document\n"); 07865 } else if (schema->doc->URL != NULL) { 07866 fprintf(output, "%s\n", schema->doc->URL); 07867 } else { 07868 fprintf(output, "\n"); 07869 } 07870 if (schema->topgrammar == NULL) { 07871 fprintf(output, "RelaxNG has no top grammar\n"); 07872 return; 07873 } 07874 xmlRelaxNGDumpGrammar(output, schema->topgrammar, 1); 07875 } 07876 07884 void 07885 xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema) 07886 { 07887 if (output == NULL) 07888 return; 07889 if (schema == NULL) { 07890 fprintf(output, "RelaxNG empty or failed to compile\n"); 07891 return; 07892 } 07893 if (schema->doc == NULL) { 07894 fprintf(output, "no document\n"); 07895 } else { 07896 xmlDocDump(output, schema->doc); 07897 } 07898 } 07899 #endif /* LIBXML_OUTPUT_ENABLED */ 07900 07901 /************************************************************************ 07902 * * 07903 * Validation of compiled content * 07904 * * 07905 ************************************************************************/ 07906 static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, 07907 xmlRelaxNGDefinePtr define); 07908 07918 static void 07919 xmlRelaxNGValidateCompiledCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED, 07920 const xmlChar * token, 07921 void *transdata, void *inputdata) 07922 { 07923 xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata; 07924 xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata; 07925 int ret; 07926 07927 #ifdef DEBUG_COMPILE 07928 xmlGenericError(xmlGenericErrorContext, 07929 "Compiled callback for: '%s'\n", token); 07930 #endif 07931 if (ctxt == NULL) { 07932 fprintf(stderr, "callback on %s missing context\n", token); 07933 return; 07934 } 07935 if (define == NULL) { 07936 if (token[0] == '#') 07937 return; 07938 fprintf(stderr, "callback on %s missing define\n", token); 07939 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) 07940 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; 07941 return; 07942 } 07943 if ((ctxt == NULL) || (define == NULL)) { 07944 fprintf(stderr, "callback on %s missing info\n", token); 07945 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) 07946 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; 07947 return; 07948 } else if (define->type != XML_RELAXNG_ELEMENT) { 07949 fprintf(stderr, "callback on %s define is not element\n", token); 07950 if (ctxt->errNo == XML_RELAXNG_OK) 07951 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; 07952 return; 07953 } 07954 ret = xmlRelaxNGValidateDefinition(ctxt, define); 07955 if (ret != 0) 07956 ctxt->perr = ret; 07957 } 07958 07969 static int 07970 xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt, 07971 xmlRegexpPtr regexp, xmlNodePtr content) 07972 { 07973 xmlRegExecCtxtPtr exec; 07974 xmlNodePtr cur; 07975 int ret = 0; 07976 int oldperr; 07977 07978 if ((ctxt == NULL) || (regexp == NULL)) 07979 return (-1); 07980 oldperr = ctxt->perr; 07981 exec = xmlRegNewExecCtxt(regexp, 07982 xmlRelaxNGValidateCompiledCallback, ctxt); 07983 ctxt->perr = 0; 07984 cur = content; 07985 while (cur != NULL) { 07986 ctxt->state->seq = cur; 07987 switch (cur->type) { 07988 case XML_TEXT_NODE: 07989 case XML_CDATA_SECTION_NODE: 07990 if (xmlIsBlankNode(cur)) 07991 break; 07992 ret = xmlRegExecPushString(exec, BAD_CAST "#text", ctxt); 07993 if (ret < 0) { 07994 VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, 07995 cur->parent->name); 07996 } 07997 break; 07998 case XML_ELEMENT_NODE: 07999 if (cur->ns != NULL) { 08000 ret = xmlRegExecPushString2(exec, cur->name, 08001 cur->ns->href, ctxt); 08002 } else { 08003 ret = xmlRegExecPushString(exec, cur->name, ctxt); 08004 } 08005 if (ret < 0) { 08006 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, cur->name); 08007 } 08008 break; 08009 default: 08010 break; 08011 } 08012 if (ret < 0) 08013 break; 08014 /* 08015 * Switch to next element 08016 */ 08017 cur = cur->next; 08018 } 08019 ret = xmlRegExecPushString(exec, NULL, NULL); 08020 if (ret == 1) { 08021 ret = 0; 08022 ctxt->state->seq = NULL; 08023 } else if (ret == 0) { 08024 /* 08025 * TODO: get some of the names needed to exit the current state of exec 08026 */ 08027 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST ""); 08028 ret = -1; 08029 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) 08030 xmlRelaxNGDumpValidError(ctxt); 08031 } else { 08032 ret = -1; 08033 } 08034 xmlRegFreeExecCtxt(exec); 08035 /* 08036 * There might be content model errors outside of the pure 08037 * regexp validation, e.g. for attribute values. 08038 */ 08039 if ((ret == 0) && (ctxt->perr != 0)) { 08040 ret = ctxt->perr; 08041 } 08042 ctxt->perr = oldperr; 08043 return (ret); 08044 } 08045 08046 /************************************************************************ 08047 * * 08048 * Progressive validation of when possible * 08049 * * 08050 ************************************************************************/ 08051 static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt, 08052 xmlRelaxNGDefinePtr defines); 08053 static int xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, 08054 int dolog); 08055 static void xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt); 08056 08066 static int 08067 xmlRelaxNGElemPush(xmlRelaxNGValidCtxtPtr ctxt, xmlRegExecCtxtPtr exec) 08068 { 08069 if (ctxt->elemTab == NULL) { 08070 ctxt->elemMax = 10; 08071 ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlMalloc(ctxt->elemMax * 08072 sizeof 08073 (xmlRegExecCtxtPtr)); 08074 if (ctxt->elemTab == NULL) { 08075 xmlRngVErrMemory(ctxt, "validating\n"); 08076 return (-1); 08077 } 08078 } 08079 if (ctxt->elemNr >= ctxt->elemMax) { 08080 ctxt->elemMax *= 2; 08081 ctxt->elemTab = (xmlRegExecCtxtPtr *) xmlRealloc(ctxt->elemTab, 08082 ctxt->elemMax * 08083 sizeof 08084 (xmlRegExecCtxtPtr)); 08085 if (ctxt->elemTab == NULL) { 08086 xmlRngVErrMemory(ctxt, "validating\n"); 08087 return (-1); 08088 } 08089 } 08090 ctxt->elemTab[ctxt->elemNr++] = exec; 08091 ctxt->elem = exec; 08092 return (0); 08093 } 08094 08103 static xmlRegExecCtxtPtr 08104 xmlRelaxNGElemPop(xmlRelaxNGValidCtxtPtr ctxt) 08105 { 08106 xmlRegExecCtxtPtr ret; 08107 08108 if (ctxt->elemNr <= 0) 08109 return (NULL); 08110 ctxt->elemNr--; 08111 ret = ctxt->elemTab[ctxt->elemNr]; 08112 ctxt->elemTab[ctxt->elemNr] = NULL; 08113 if (ctxt->elemNr > 0) 08114 ctxt->elem = ctxt->elemTab[ctxt->elemNr - 1]; 08115 else 08116 ctxt->elem = NULL; 08117 return (ret); 08118 } 08119 08130 static void 08131 xmlRelaxNGValidateProgressiveCallback(xmlRegExecCtxtPtr exec 08132 ATTRIBUTE_UNUSED, 08133 const xmlChar * token, 08134 void *transdata, void *inputdata) 08135 { 08136 xmlRelaxNGValidCtxtPtr ctxt = (xmlRelaxNGValidCtxtPtr) inputdata; 08137 xmlRelaxNGDefinePtr define = (xmlRelaxNGDefinePtr) transdata; 08138 xmlRelaxNGValidStatePtr state, oldstate; 08139 xmlNodePtr node; 08140 int ret = 0, oldflags; 08141 08142 #ifdef DEBUG_PROGRESSIVE 08143 xmlGenericError(xmlGenericErrorContext, 08144 "Progressive callback for: '%s'\n", token); 08145 #endif 08146 if (ctxt == NULL) { 08147 fprintf(stderr, "callback on %s missing context\n", token); 08148 return; 08149 } 08150 node = ctxt->pnode; 08151 ctxt->pstate = 1; 08152 if (define == NULL) { 08153 if (token[0] == '#') 08154 return; 08155 fprintf(stderr, "callback on %s missing define\n", token); 08156 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) 08157 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; 08158 ctxt->pstate = -1; 08159 return; 08160 } 08161 if ((ctxt == NULL) || (define == NULL)) { 08162 fprintf(stderr, "callback on %s missing info\n", token); 08163 if ((ctxt != NULL) && (ctxt->errNo == XML_RELAXNG_OK)) 08164 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; 08165 ctxt->pstate = -1; 08166 return; 08167 } else if (define->type != XML_RELAXNG_ELEMENT) { 08168 fprintf(stderr, "callback on %s define is not element\n", token); 08169 if (ctxt->errNo == XML_RELAXNG_OK) 08170 ctxt->errNo = XML_RELAXNG_ERR_INTERNAL; 08171 ctxt->pstate = -1; 08172 return; 08173 } 08174 if (node->type != XML_ELEMENT_NODE) { 08175 VALID_ERR(XML_RELAXNG_ERR_NOTELEM); 08176 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) 08177 xmlRelaxNGDumpValidError(ctxt); 08178 ctxt->pstate = -1; 08179 return; 08180 } 08181 if (define->contModel == NULL) { 08182 /* 08183 * this node cannot be validated in a streamable fashion 08184 */ 08185 #ifdef DEBUG_PROGRESSIVE 08186 xmlGenericError(xmlGenericErrorContext, 08187 "Element '%s' validation is not streamable\n", 08188 token); 08189 #endif 08190 ctxt->pstate = 0; 08191 ctxt->pdef = define; 08192 return; 08193 } 08194 exec = xmlRegNewExecCtxt(define->contModel, 08195 xmlRelaxNGValidateProgressiveCallback, ctxt); 08196 if (exec == NULL) { 08197 ctxt->pstate = -1; 08198 return; 08199 } 08200 xmlRelaxNGElemPush(ctxt, exec); 08201 08202 /* 08203 * Validate the attributes part of the content. 08204 */ 08205 state = xmlRelaxNGNewValidState(ctxt, node); 08206 if (state == NULL) { 08207 ctxt->pstate = -1; 08208 return; 08209 } 08210 oldstate = ctxt->state; 08211 ctxt->state = state; 08212 if (define->attrs != NULL) { 08213 ret = xmlRelaxNGValidateAttributeList(ctxt, define->attrs); 08214 if (ret != 0) { 08215 ctxt->pstate = -1; 08216 VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name); 08217 } 08218 } 08219 if (ctxt->state != NULL) { 08220 ctxt->state->seq = NULL; 08221 ret = xmlRelaxNGValidateElementEnd(ctxt, 1); 08222 if (ret != 0) { 08223 ctxt->pstate = -1; 08224 } 08225 xmlRelaxNGFreeValidState(ctxt, ctxt->state); 08226 } else if (ctxt->states != NULL) { 08227 int tmp = -1, i; 08228 08229 oldflags = ctxt->flags; 08230 08231 for (i = 0; i < ctxt->states->nbState; i++) { 08232 state = ctxt->states->tabState[i]; 08233 ctxt->state = state; 08234 ctxt->state->seq = NULL; 08235 08236 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { 08237 tmp = 0; 08238 break; 08239 } 08240 } 08241 if (tmp != 0) { 08242 /* 08243 * validation error, log the message for the "best" one 08244 */ 08245 ctxt->flags |= FLAGS_IGNORABLE; 08246 xmlRelaxNGLogBestError(ctxt); 08247 } 08248 for (i = 0; i < ctxt->states->nbState; i++) { 08249 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[i]); 08250 } 08251 xmlRelaxNGFreeStates(ctxt, ctxt->states); 08252 ctxt->states = NULL; 08253 if ((ret == 0) && (tmp == -1)) 08254 ctxt->pstate = -1; 08255 ctxt->flags = oldflags; 08256 } 08257 if (ctxt->pstate == -1) { 08258 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { 08259 xmlRelaxNGDumpValidError(ctxt); 08260 } 08261 } 08262 ctxt->state = oldstate; 08263 } 08264 08276 int 08277 xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt, 08278 xmlDocPtr doc ATTRIBUTE_UNUSED, 08279 xmlNodePtr elem) 08280 { 08281 int ret = 1; 08282 08283 if ((ctxt == NULL) || (elem == NULL)) 08284 return (-1); 08285 08286 #ifdef DEBUG_PROGRESSIVE 08287 xmlGenericError(xmlGenericErrorContext, "PushElem %s\n", elem->name); 08288 #endif 08289 if (ctxt->elem == 0) { 08290 xmlRelaxNGPtr schema; 08291 xmlRelaxNGGrammarPtr grammar; 08292 xmlRegExecCtxtPtr exec; 08293 xmlRelaxNGDefinePtr define; 08294 08295 schema = ctxt->schema; 08296 if (schema == NULL) { 08297 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR); 08298 return (-1); 08299 } 08300 grammar = schema->topgrammar; 08301 if ((grammar == NULL) || (grammar->start == NULL)) { 08302 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR); 08303 return (-1); 08304 } 08305 define = grammar->start; 08306 if (define->contModel == NULL) { 08307 ctxt->pdef = define; 08308 return (0); 08309 } 08310 exec = xmlRegNewExecCtxt(define->contModel, 08311 xmlRelaxNGValidateProgressiveCallback, 08312 ctxt); 08313 if (exec == NULL) { 08314 return (-1); 08315 } 08316 xmlRelaxNGElemPush(ctxt, exec); 08317 } 08318 ctxt->pnode = elem; 08319 ctxt->pstate = 0; 08320 if (elem->ns != NULL) { 08321 ret = 08322 xmlRegExecPushString2(ctxt->elem, elem->name, elem->ns->href, 08323 ctxt); 08324 } else { 08325 ret = xmlRegExecPushString(ctxt->elem, elem->name, ctxt); 08326 } 08327 if (ret < 0) { 08328 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, elem->name); 08329 } else { 08330 if (ctxt->pstate == 0) 08331 ret = 0; 08332 else if (ctxt->pstate < 0) 08333 ret = -1; 08334 else 08335 ret = 1; 08336 } 08337 #ifdef DEBUG_PROGRESSIVE 08338 if (ret < 0) 08339 xmlGenericError(xmlGenericErrorContext, "PushElem %s failed\n", 08340 elem->name); 08341 #endif 08342 return (ret); 08343 } 08344 08355 int 08356 xmlRelaxNGValidatePushCData(xmlRelaxNGValidCtxtPtr ctxt, 08357 const xmlChar * data, int len ATTRIBUTE_UNUSED) 08358 { 08359 int ret = 1; 08360 08361 if ((ctxt == NULL) || (ctxt->elem == NULL) || (data == NULL)) 08362 return (-1); 08363 08364 #ifdef DEBUG_PROGRESSIVE 08365 xmlGenericError(xmlGenericErrorContext, "CDATA %s %d\n", data, len); 08366 #endif 08367 08368 while (*data != 0) { 08369 if (!IS_BLANK_CH(*data)) 08370 break; 08371 data++; 08372 } 08373 if (*data == 0) 08374 return (1); 08375 08376 ret = xmlRegExecPushString(ctxt->elem, BAD_CAST "#text", ctxt); 08377 if (ret < 0) { 08378 VALID_ERR2(XML_RELAXNG_ERR_TEXTWRONG, BAD_CAST " TODO "); 08379 #ifdef DEBUG_PROGRESSIVE 08380 xmlGenericError(xmlGenericErrorContext, "CDATA failed\n"); 08381 #endif 08382 08383 return (-1); 08384 } 08385 return (1); 08386 } 08387 08398 int 08399 xmlRelaxNGValidatePopElement(xmlRelaxNGValidCtxtPtr ctxt, 08400 xmlDocPtr doc ATTRIBUTE_UNUSED, 08401 xmlNodePtr elem) 08402 { 08403 int ret; 08404 xmlRegExecCtxtPtr exec; 08405 08406 if ((ctxt == NULL) || (ctxt->elem == NULL) || (elem == NULL)) 08407 return (-1); 08408 #ifdef DEBUG_PROGRESSIVE 08409 xmlGenericError(xmlGenericErrorContext, "PopElem %s\n", elem->name); 08410 #endif 08411 /* 08412 * verify that we reached a terminal state of the content model. 08413 */ 08414 exec = xmlRelaxNGElemPop(ctxt); 08415 ret = xmlRegExecPushString(exec, NULL, NULL); 08416 if (ret == 0) { 08417 /* 08418 * TODO: get some of the names needed to exit the current state of exec 08419 */ 08420 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, BAD_CAST ""); 08421 ret = -1; 08422 } else if (ret < 0) { 08423 ret = -1; 08424 } else { 08425 ret = 1; 08426 } 08427 xmlRegFreeExecCtxt(exec); 08428 #ifdef DEBUG_PROGRESSIVE 08429 if (ret < 0) 08430 xmlGenericError(xmlGenericErrorContext, "PopElem %s failed\n", 08431 elem->name); 08432 #endif 08433 return (ret); 08434 } 08435 08447 int 08448 xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt, 08449 xmlDocPtr doc ATTRIBUTE_UNUSED, 08450 xmlNodePtr elem) 08451 { 08452 int ret; 08453 xmlRelaxNGValidStatePtr state; 08454 08455 if ((ctxt == NULL) || (ctxt->pdef == NULL) || (elem == NULL)) 08456 return (-1); 08457 #ifdef DEBUG_PROGRESSIVE 08458 xmlGenericError(xmlGenericErrorContext, "FullElem %s\n", elem->name); 08459 #endif 08460 state = xmlRelaxNGNewValidState(ctxt, elem->parent); 08461 if (state == NULL) { 08462 return (-1); 08463 } 08464 state->seq = elem; 08465 ctxt->state = state; 08466 ctxt->errNo = XML_RELAXNG_OK; 08467 ret = xmlRelaxNGValidateDefinition(ctxt, ctxt->pdef); 08468 if ((ret != 0) || (ctxt->errNo != XML_RELAXNG_OK)) 08469 ret = -1; 08470 else 08471 ret = 1; 08472 xmlRelaxNGFreeValidState(ctxt, ctxt->state); 08473 ctxt->state = NULL; 08474 #ifdef DEBUG_PROGRESSIVE 08475 if (ret < 0) 08476 xmlGenericError(xmlGenericErrorContext, "FullElem %s failed\n", 08477 elem->name); 08478 #endif 08479 return (ret); 08480 } 08481 08482 /************************************************************************ 08483 * * 08484 * Generic interpreted validation implementation * 08485 * * 08486 ************************************************************************/ 08487 static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, 08488 xmlRelaxNGDefinePtr define); 08489 08499 static xmlNodePtr 08500 xmlRelaxNGSkipIgnored(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED, 08501 xmlNodePtr node) 08502 { 08503 /* 08504 * TODO complete and handle entities 08505 */ 08506 while ((node != NULL) && 08507 ((node->type == XML_COMMENT_NODE) || 08508 (node->type == XML_PI_NODE) || 08509 (node->type == XML_XINCLUDE_START) || 08510 (node->type == XML_XINCLUDE_END) || 08511 (((node->type == XML_TEXT_NODE) || 08512 (node->type == XML_CDATA_SECTION_NODE)) && 08513 ((ctxt->flags & FLAGS_MIXED_CONTENT) || 08514 (IS_BLANK_NODE(node)))))) { 08515 node = node->next; 08516 } 08517 return (node); 08518 } 08519 08530 static xmlChar * 08531 xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str) 08532 { 08533 xmlChar *ret, *p; 08534 const xmlChar *tmp; 08535 int len; 08536 08537 if (str == NULL) 08538 return (NULL); 08539 tmp = str; 08540 while (*tmp != 0) 08541 tmp++; 08542 len = tmp - str; 08543 08544 ret = (xmlChar *) xmlMallocAtomic((len + 1) * sizeof(xmlChar)); 08545 if (ret == NULL) { 08546 xmlRngVErrMemory(ctxt, "validating\n"); 08547 return (NULL); 08548 } 08549 p = ret; 08550 while (IS_BLANK_CH(*str)) 08551 str++; 08552 while (*str != 0) { 08553 if (IS_BLANK_CH(*str)) { 08554 while (IS_BLANK_CH(*str)) 08555 str++; 08556 if (*str == 0) 08557 break; 08558 *p++ = ' '; 08559 } else 08560 *p++ = *str++; 08561 } 08562 *p = 0; 08563 return (ret); 08564 } 08565 08577 static int 08578 xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, 08579 const xmlChar * value, 08580 xmlRelaxNGDefinePtr define, xmlNodePtr node) 08581 { 08582 int ret, tmp; 08583 xmlRelaxNGTypeLibraryPtr lib; 08584 void *result = NULL; 08585 xmlRelaxNGDefinePtr cur; 08586 08587 if ((define == NULL) || (define->data == NULL)) { 08588 return (-1); 08589 } 08590 lib = (xmlRelaxNGTypeLibraryPtr) define->data; 08591 if (lib->check != NULL) { 08592 if ((define->attrs != NULL) && 08593 (define->attrs->type == XML_RELAXNG_PARAM)) { 08594 ret = 08595 lib->check(lib->data, define->name, value, &result, node); 08596 } else { 08597 ret = lib->check(lib->data, define->name, value, NULL, node); 08598 } 08599 } else 08600 ret = -1; 08601 if (ret < 0) { 08602 VALID_ERR2(XML_RELAXNG_ERR_TYPE, define->name); 08603 if ((result != NULL) && (lib != NULL) && (lib->freef != NULL)) 08604 lib->freef(lib->data, result); 08605 return (-1); 08606 } else if (ret == 1) { 08607 ret = 0; 08608 } else if (ret == 2) { 08609 VALID_ERR2P(XML_RELAXNG_ERR_DUPID, value); 08610 } else { 08611 VALID_ERR3P(XML_RELAXNG_ERR_TYPEVAL, define->name, value); 08612 ret = -1; 08613 } 08614 cur = define->attrs; 08615 while ((ret == 0) && (cur != NULL) && (cur->type == XML_RELAXNG_PARAM)) { 08616 if (lib->facet != NULL) { 08617 tmp = lib->facet(lib->data, define->name, cur->name, 08618 cur->value, value, result); 08619 if (tmp != 0) 08620 ret = -1; 08621 } 08622 cur = cur->next; 08623 } 08624 if ((ret == 0) && (define->content != NULL)) { 08625 const xmlChar *oldvalue, *oldendvalue; 08626 08627 oldvalue = ctxt->state->value; 08628 oldendvalue = ctxt->state->endvalue; 08629 ctxt->state->value = (xmlChar *) value; 08630 ctxt->state->endvalue = NULL; 08631 ret = xmlRelaxNGValidateValue(ctxt, define->content); 08632 ctxt->state->value = (xmlChar *) oldvalue; 08633 ctxt->state->endvalue = (xmlChar *) oldendvalue; 08634 } 08635 if ((result != NULL) && (lib != NULL) && (lib->freef != NULL)) 08636 lib->freef(lib->data, result); 08637 return (ret); 08638 } 08639 08648 static int 08649 xmlRelaxNGNextValue(xmlRelaxNGValidCtxtPtr ctxt) 08650 { 08651 xmlChar *cur; 08652 08653 cur = ctxt->state->value; 08654 if ((cur == NULL) || (ctxt->state->endvalue == NULL)) { 08655 ctxt->state->value = NULL; 08656 ctxt->state->endvalue = NULL; 08657 return (0); 08658 } 08659 while (*cur != 0) 08660 cur++; 08661 while ((cur != ctxt->state->endvalue) && (*cur == 0)) 08662 cur++; 08663 if (cur == ctxt->state->endvalue) 08664 ctxt->state->value = NULL; 08665 else 08666 ctxt->state->value = cur; 08667 return (0); 08668 } 08669 08679 static int 08680 xmlRelaxNGValidateValueList(xmlRelaxNGValidCtxtPtr ctxt, 08681 xmlRelaxNGDefinePtr defines) 08682 { 08683 int ret = 0; 08684 08685 while (defines != NULL) { 08686 ret = xmlRelaxNGValidateValue(ctxt, defines); 08687 if (ret != 0) 08688 break; 08689 defines = defines->next; 08690 } 08691 return (ret); 08692 } 08693 08703 static int 08704 xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, 08705 xmlRelaxNGDefinePtr define) 08706 { 08707 int ret = 0, oldflags; 08708 xmlChar *value; 08709 08710 value = ctxt->state->value; 08711 switch (define->type) { 08712 case XML_RELAXNG_EMPTY:{ 08713 if ((value != NULL) && (value[0] != 0)) { 08714 int idx = 0; 08715 08716 while (IS_BLANK_CH(value[idx])) 08717 idx++; 08718 if (value[idx] != 0) 08719 ret = -1; 08720 } 08721 break; 08722 } 08723 case XML_RELAXNG_TEXT: 08724 break; 08725 case XML_RELAXNG_VALUE:{ 08726 if (!xmlStrEqual(value, define->value)) { 08727 if (define->name != NULL) { 08728 xmlRelaxNGTypeLibraryPtr lib; 08729 08730 lib = (xmlRelaxNGTypeLibraryPtr) define->data; 08731 if ((lib != NULL) && (lib->comp != NULL)) { 08732 ret = lib->comp(lib->data, define->name, 08733 define->value, define->node, 08734 (void *) define->attrs, 08735 value, ctxt->state->node); 08736 } else 08737 ret = -1; 08738 if (ret < 0) { 08739 VALID_ERR2(XML_RELAXNG_ERR_TYPECMP, 08740 define->name); 08741 return (-1); 08742 } else if (ret == 1) { 08743 ret = 0; 08744 } else { 08745 ret = -1; 08746 } 08747 } else { 08748 xmlChar *nval, *nvalue; 08749 08750 /* 08751 * TODO: trivial optimizations are possible by 08752 * computing at compile-time 08753 */ 08754 nval = xmlRelaxNGNormalize(ctxt, define->value); 08755 nvalue = xmlRelaxNGNormalize(ctxt, value); 08756 08757 if ((nval == NULL) || (nvalue == NULL) || 08758 (!xmlStrEqual(nval, nvalue))) 08759 ret = -1; 08760 if (nval != NULL) 08761 xmlFree(nval); 08762 if (nvalue != NULL) 08763 xmlFree(nvalue); 08764 } 08765 } 08766 if (ret == 0) 08767 xmlRelaxNGNextValue(ctxt); 08768 break; 08769 } 08770 case XML_RELAXNG_DATATYPE:{ 08771 ret = xmlRelaxNGValidateDatatype(ctxt, value, define, 08772 ctxt->state->seq); 08773 if (ret == 0) 08774 xmlRelaxNGNextValue(ctxt); 08775 08776 break; 08777 } 08778 case XML_RELAXNG_CHOICE:{ 08779 xmlRelaxNGDefinePtr list = define->content; 08780 xmlChar *oldvalue; 08781 08782 oldflags = ctxt->flags; 08783 ctxt->flags |= FLAGS_IGNORABLE; 08784 08785 oldvalue = ctxt->state->value; 08786 while (list != NULL) { 08787 ret = xmlRelaxNGValidateValue(ctxt, list); 08788 if (ret == 0) { 08789 break; 08790 } 08791 ctxt->state->value = oldvalue; 08792 list = list->next; 08793 } 08794 ctxt->flags = oldflags; 08795 if (ret != 0) { 08796 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) 08797 xmlRelaxNGDumpValidError(ctxt); 08798 } else { 08799 if (ctxt->errNr > 0) 08800 xmlRelaxNGPopErrors(ctxt, 0); 08801 } 08802 break; 08803 } 08804 case XML_RELAXNG_LIST:{ 08805 xmlRelaxNGDefinePtr list = define->content; 08806 xmlChar *oldvalue, *oldend, *val, *cur; 08807 08808 #ifdef DEBUG_LIST 08809 int nb_values = 0; 08810 #endif 08811 08812 oldvalue = ctxt->state->value; 08813 oldend = ctxt->state->endvalue; 08814 08815 val = xmlStrdup(oldvalue); 08816 if (val == NULL) { 08817 val = xmlStrdup(BAD_CAST ""); 08818 } 08819 if (val == NULL) { 08820 VALID_ERR(XML_RELAXNG_ERR_NOSTATE); 08821 return (-1); 08822 } 08823 cur = val; 08824 while (*cur != 0) { 08825 if (IS_BLANK_CH(*cur)) { 08826 *cur = 0; 08827 cur++; 08828 #ifdef DEBUG_LIST 08829 nb_values++; 08830 #endif 08831 while (IS_BLANK_CH(*cur)) 08832 *cur++ = 0; 08833 } else 08834 cur++; 08835 } 08836 #ifdef DEBUG_LIST 08837 xmlGenericError(xmlGenericErrorContext, 08838 "list value: '%s' found %d items\n", 08839 oldvalue, nb_values); 08840 nb_values = 0; 08841 #endif 08842 ctxt->state->endvalue = cur; 08843 cur = val; 08844 while ((*cur == 0) && (cur != ctxt->state->endvalue)) 08845 cur++; 08846 08847 ctxt->state->value = cur; 08848 08849 while (list != NULL) { 08850 if (ctxt->state->value == ctxt->state->endvalue) 08851 ctxt->state->value = NULL; 08852 ret = xmlRelaxNGValidateValue(ctxt, list); 08853 if (ret != 0) { 08854 #ifdef DEBUG_LIST 08855 xmlGenericError(xmlGenericErrorContext, 08856 "Failed to validate value: '%s' with %d rule\n", 08857 ctxt->state->value, nb_values); 08858 #endif 08859 break; 08860 } 08861 #ifdef DEBUG_LIST 08862 nb_values++; 08863 #endif 08864 list = list->next; 08865 } 08866 08867 if ((ret == 0) && (ctxt->state->value != NULL) && 08868 (ctxt->state->value != ctxt->state->endvalue)) { 08869 VALID_ERR2(XML_RELAXNG_ERR_LISTEXTRA, 08870 ctxt->state->value); 08871 ret = -1; 08872 } 08873 xmlFree(val); 08874 ctxt->state->value = oldvalue; 08875 ctxt->state->endvalue = oldend; 08876 break; 08877 } 08878 case XML_RELAXNG_ONEORMORE: 08879 ret = xmlRelaxNGValidateValueList(ctxt, define->content); 08880 if (ret != 0) { 08881 break; 08882 } 08883 /* no break on purpose */ 08884 case XML_RELAXNG_ZEROORMORE:{ 08885 xmlChar *cur, *temp; 08886 08887 oldflags = ctxt->flags; 08888 ctxt->flags |= FLAGS_IGNORABLE; 08889 cur = ctxt->state->value; 08890 temp = NULL; 08891 while ((cur != NULL) && (cur != ctxt->state->endvalue) && 08892 (temp != cur)) { 08893 temp = cur; 08894 ret = 08895 xmlRelaxNGValidateValueList(ctxt, define->content); 08896 if (ret != 0) { 08897 ctxt->state->value = temp; 08898 ret = 0; 08899 break; 08900 } 08901 cur = ctxt->state->value; 08902 } 08903 ctxt->flags = oldflags; 08904 if (ctxt->errNr > 0) 08905 xmlRelaxNGPopErrors(ctxt, 0); 08906 break; 08907 } 08908 case XML_RELAXNG_EXCEPT:{ 08909 xmlRelaxNGDefinePtr list; 08910 08911 list = define->content; 08912 while (list != NULL) { 08913 ret = xmlRelaxNGValidateValue(ctxt, list); 08914 if (ret == 0) { 08915 ret = -1; 08916 break; 08917 } else 08918 ret = 0; 08919 list = list->next; 08920 } 08921 break; 08922 } 08923 case XML_RELAXNG_DEF: 08924 case XML_RELAXNG_GROUP:{ 08925 xmlRelaxNGDefinePtr list; 08926 08927 list = define->content; 08928 while (list != NULL) { 08929 ret = xmlRelaxNGValidateValue(ctxt, list); 08930 if (ret != 0) { 08931 ret = -1; 08932 break; 08933 } else 08934 ret = 0; 08935 list = list->next; 08936 } 08937 break; 08938 } 08939 case XML_RELAXNG_REF: 08940 case XML_RELAXNG_PARENTREF: 08941 if (define->content == NULL) { 08942 VALID_ERR(XML_RELAXNG_ERR_NODEFINE); 08943 ret = -1; 08944 } else { 08945 ret = xmlRelaxNGValidateValue(ctxt, define->content); 08946 } 08947 break; 08948 default: 08949 TODO ret = -1; 08950 } 08951 return (ret); 08952 } 08953 08963 static int 08964 xmlRelaxNGValidateValueContent(xmlRelaxNGValidCtxtPtr ctxt, 08965 xmlRelaxNGDefinePtr defines) 08966 { 08967 int ret = 0; 08968 08969 while (defines != NULL) { 08970 ret = xmlRelaxNGValidateValue(ctxt, defines); 08971 if (ret != 0) 08972 break; 08973 defines = defines->next; 08974 } 08975 return (ret); 08976 } 08977 08988 static int 08989 xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt, 08990 xmlRelaxNGDefinePtr define, xmlAttrPtr prop) 08991 { 08992 int ret; 08993 08994 if (define->name != NULL) { 08995 if (!xmlStrEqual(define->name, prop->name)) 08996 return (0); 08997 } 08998 if (define->ns != NULL) { 08999 if (define->ns[0] == 0) { 09000 if (prop->ns != NULL) 09001 return (0); 09002 } else { 09003 if ((prop->ns == NULL) || 09004 (!xmlStrEqual(define->ns, prop->ns->href))) 09005 return (0); 09006 } 09007 } 09008 if (define->nameClass == NULL) 09009 return (1); 09010 define = define->nameClass; 09011 if (define->type == XML_RELAXNG_EXCEPT) { 09012 xmlRelaxNGDefinePtr list; 09013 09014 list = define->content; 09015 while (list != NULL) { 09016 ret = xmlRelaxNGAttributeMatch(ctxt, list, prop); 09017 if (ret == 1) 09018 return (0); 09019 if (ret < 0) 09020 return (ret); 09021 list = list->next; 09022 } 09023 } else { 09024 TODO} 09025 return (1); 09026 } 09027 09037 static int 09038 xmlRelaxNGValidateAttribute(xmlRelaxNGValidCtxtPtr ctxt, 09039 xmlRelaxNGDefinePtr define) 09040 { 09041 int ret = 0, i; 09042 xmlChar *value, *oldvalue; 09043 xmlAttrPtr prop = NULL, tmp; 09044 xmlNodePtr oldseq; 09045 09046 if (ctxt->state->nbAttrLeft <= 0) 09047 return (-1); 09048 if (define->name != NULL) { 09049 for (i = 0; i < ctxt->state->nbAttrs; i++) { 09050 tmp = ctxt->state->attrs[i]; 09051 if ((tmp != NULL) && (xmlStrEqual(define->name, tmp->name))) { 09052 if ((((define->ns == NULL) || (define->ns[0] == 0)) && 09053 (tmp->ns == NULL)) || 09054 ((tmp->ns != NULL) && 09055 (xmlStrEqual(define->ns, tmp->ns->href)))) { 09056 prop = tmp; 09057 break; 09058 } 09059 } 09060 } 09061 if (prop != NULL) { 09062 value = xmlNodeListGetString(prop->doc, prop->children, 1); 09063 oldvalue = ctxt->state->value; 09064 oldseq = ctxt->state->seq; 09065 ctxt->state->seq = (xmlNodePtr) prop; 09066 ctxt->state->value = value; 09067 ctxt->state->endvalue = NULL; 09068 ret = xmlRelaxNGValidateValueContent(ctxt, define->content); 09069 if (ctxt->state->value != NULL) 09070 value = ctxt->state->value; 09071 if (value != NULL) 09072 xmlFree(value); 09073 ctxt->state->value = oldvalue; 09074 ctxt->state->seq = oldseq; 09075 if (ret == 0) { 09076 /* 09077 * flag the attribute as processed 09078 */ 09079 ctxt->state->attrs[i] = NULL; 09080 ctxt->state->nbAttrLeft--; 09081 } 09082 } else { 09083 ret = -1; 09084 } 09085 #ifdef DEBUG 09086 xmlGenericError(xmlGenericErrorContext, 09087 "xmlRelaxNGValidateAttribute(%s): %d\n", 09088 define->name, ret); 09089 #endif 09090 } else { 09091 for (i = 0; i < ctxt->state->nbAttrs; i++) { 09092 tmp = ctxt->state->attrs[i]; 09093 if ((tmp != NULL) && 09094 (xmlRelaxNGAttributeMatch(ctxt, define, tmp) == 1)) { 09095 prop = tmp; 09096 break; 09097 } 09098 } 09099 if (prop != NULL) { 09100 value = xmlNodeListGetString(prop->doc, prop->children, 1); 09101 oldvalue = ctxt->state->value; 09102 oldseq = ctxt->state->seq; 09103 ctxt->state->seq = (xmlNodePtr) prop; 09104 ctxt->state->value = value; 09105 ret = xmlRelaxNGValidateValueContent(ctxt, define->content); 09106 if (ctxt->state->value != NULL) 09107 value = ctxt->state->value; 09108 if (value != NULL) 09109 xmlFree(value); 09110 ctxt->state->value = oldvalue; 09111 ctxt->state->seq = oldseq; 09112 if (ret == 0) { 09113 /* 09114 * flag the attribute as processed 09115 */ 09116 ctxt->state->attrs[i] = NULL; 09117 ctxt->state->nbAttrLeft--; 09118 } 09119 } else { 09120 ret = -1; 09121 } 09122 #ifdef DEBUG 09123 if (define->ns != NULL) { 09124 xmlGenericError(xmlGenericErrorContext, 09125 "xmlRelaxNGValidateAttribute(nsName ns = %s): %d\n", 09126 define->ns, ret); 09127 } else { 09128 xmlGenericError(xmlGenericErrorContext, 09129 "xmlRelaxNGValidateAttribute(anyName): %d\n", 09130 ret); 09131 } 09132 #endif 09133 } 09134 09135 return (ret); 09136 } 09137 09147 static int 09148 xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt, 09149 xmlRelaxNGDefinePtr defines) 09150 { 09151 int ret = 0, res; 09152 int needmore = 0; 09153 xmlRelaxNGDefinePtr cur; 09154 09155 cur = defines; 09156 while (cur != NULL) { 09157 if (cur->type == XML_RELAXNG_ATTRIBUTE) { 09158 if (xmlRelaxNGValidateAttribute(ctxt, cur) != 0) 09159 ret = -1; 09160 } else 09161 needmore = 1; 09162 cur = cur->next; 09163 } 09164 if (!needmore) 09165 return (ret); 09166 cur = defines; 09167 while (cur != NULL) { 09168 if (cur->type != XML_RELAXNG_ATTRIBUTE) { 09169 if ((ctxt->state != NULL) || (ctxt->states != NULL)) { 09170 res = xmlRelaxNGValidateDefinition(ctxt, cur); 09171 if (res < 0) 09172 ret = -1; 09173 } else { 09174 VALID_ERR(XML_RELAXNG_ERR_NOSTATE); 09175 return (-1); 09176 } 09177 if (res == -1) /* continues on -2 */ 09178 break; 09179 } 09180 cur = cur->next; 09181 } 09182 09183 return (ret); 09184 } 09185 09195 static int 09196 xmlRelaxNGNodeMatchesList(xmlNodePtr node, xmlRelaxNGDefinePtr * list) 09197 { 09198 xmlRelaxNGDefinePtr cur; 09199 int i = 0, tmp; 09200 09201 if ((node == NULL) || (list == NULL)) 09202 return (0); 09203 09204 cur = list[i++]; 09205 while (cur != NULL) { 09206 if ((node->type == XML_ELEMENT_NODE) && 09207 (cur->type == XML_RELAXNG_ELEMENT)) { 09208 tmp = xmlRelaxNGElementMatch(NULL, cur, node); 09209 if (tmp == 1) 09210 return (1); 09211 } else if (((node->type == XML_TEXT_NODE) || 09212 (node->type == XML_CDATA_SECTION_NODE)) && 09213 (cur->type == XML_RELAXNG_TEXT)) { 09214 return (1); 09215 } 09216 cur = list[i++]; 09217 } 09218 return (0); 09219 } 09220 09230 static int 09231 xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt, 09232 xmlRelaxNGDefinePtr define) 09233 { 09234 int ret = 0, i, nbgroups; 09235 int errNr = ctxt->errNr; 09236 int oldflags; 09237 09238 xmlRelaxNGValidStatePtr oldstate; 09239 xmlRelaxNGPartitionPtr partitions; 09240 xmlRelaxNGInterleaveGroupPtr group = NULL; 09241 xmlNodePtr cur, start, last = NULL, lastchg = NULL, lastelem; 09242 xmlNodePtr *list = NULL, *lasts = NULL; 09243 09244 if (define->data != NULL) { 09245 partitions = (xmlRelaxNGPartitionPtr) define->data; 09246 nbgroups = partitions->nbgroups; 09247 } else { 09248 VALID_ERR(XML_RELAXNG_ERR_INTERNODATA); 09249 return (-1); 09250 } 09251 /* 09252 * Optimizations for MIXED 09253 */ 09254 oldflags = ctxt->flags; 09255 if (define->dflags & IS_MIXED) { 09256 ctxt->flags |= FLAGS_MIXED_CONTENT; 09257 if (nbgroups == 2) { 09258 /* 09259 * this is a pure <mixed> case 09260 */ 09261 if (ctxt->state != NULL) 09262 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, 09263 ctxt->state->seq); 09264 if (partitions->groups[0]->rule->type == XML_RELAXNG_TEXT) 09265 ret = xmlRelaxNGValidateDefinition(ctxt, 09266 partitions->groups[1]-> 09267 rule); 09268 else 09269 ret = xmlRelaxNGValidateDefinition(ctxt, 09270 partitions->groups[0]-> 09271 rule); 09272 if (ret == 0) { 09273 if (ctxt->state != NULL) 09274 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, 09275 ctxt->state-> 09276 seq); 09277 } 09278 ctxt->flags = oldflags; 09279 return (ret); 09280 } 09281 } 09282 09283 /* 09284 * Build arrays to store the first and last node of the chain 09285 * pertaining to each group 09286 */ 09287 list = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr)); 09288 if (list == NULL) { 09289 xmlRngVErrMemory(ctxt, "validating\n"); 09290 return (-1); 09291 } 09292 memset(list, 0, nbgroups * sizeof(xmlNodePtr)); 09293 lasts = (xmlNodePtr *) xmlMalloc(nbgroups * sizeof(xmlNodePtr)); 09294 if (lasts == NULL) { 09295 xmlRngVErrMemory(ctxt, "validating\n"); 09296 return (-1); 09297 } 09298 memset(lasts, 0, nbgroups * sizeof(xmlNodePtr)); 09299 09300 /* 09301 * Walk the sequence of children finding the right group and 09302 * sorting them in sequences. 09303 */ 09304 cur = ctxt->state->seq; 09305 cur = xmlRelaxNGSkipIgnored(ctxt, cur); 09306 start = cur; 09307 while (cur != NULL) { 09308 ctxt->state->seq = cur; 09309 if ((partitions->triage != NULL) && 09310 (partitions->flags & IS_DETERMINIST)) { 09311 void *tmp = NULL; 09312 09313 if ((cur->type == XML_TEXT_NODE) || 09314 (cur->type == XML_CDATA_SECTION_NODE)) { 09315 tmp = xmlHashLookup2(partitions->triage, BAD_CAST "#text", 09316 NULL); 09317 } else if (cur->type == XML_ELEMENT_NODE) { 09318 if (cur->ns != NULL) { 09319 tmp = xmlHashLookup2(partitions->triage, cur->name, 09320 cur->ns->href); 09321 if (tmp == NULL) 09322 tmp = xmlHashLookup2(partitions->triage, 09323 BAD_CAST "#any", 09324 cur->ns->href); 09325 } else 09326 tmp = 09327 xmlHashLookup2(partitions->triage, cur->name, 09328 NULL); 09329 if (tmp == NULL) 09330 tmp = 09331 xmlHashLookup2(partitions->triage, BAD_CAST "#any", 09332 NULL); 09333 } 09334 09335 if (tmp == NULL) { 09336 i = nbgroups; 09337 } else { 09338 i = ((long) tmp) - 1; 09339 if (partitions->flags & IS_NEEDCHECK) { 09340 group = partitions->groups[i]; 09341 if (!xmlRelaxNGNodeMatchesList(cur, group->defs)) 09342 i = nbgroups; 09343 } 09344 } 09345 } else { 09346 for (i = 0; i < nbgroups; i++) { 09347 group = partitions->groups[i]; 09348 if (group == NULL) 09349 continue; 09350 if (xmlRelaxNGNodeMatchesList(cur, group->defs)) 09351 break; 09352 } 09353 } 09354 /* 09355 * We break as soon as an element not matched is found 09356 */ 09357 if (i >= nbgroups) { 09358 break; 09359 } 09360 if (lasts[i] != NULL) { 09361 lasts[i]->next = cur; 09362 lasts[i] = cur; 09363 } else { 09364 list[i] = cur; 09365 lasts[i] = cur; 09366 } 09367 if (cur->next != NULL) 09368 lastchg = cur->next; 09369 else 09370 lastchg = cur; 09371 cur = xmlRelaxNGSkipIgnored(ctxt, cur->next); 09372 } 09373 if (ret != 0) { 09374 VALID_ERR(XML_RELAXNG_ERR_INTERSEQ); 09375 ret = -1; 09376 goto done; 09377 } 09378 lastelem = cur; 09379 oldstate = ctxt->state; 09380 for (i = 0; i < nbgroups; i++) { 09381 ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate); 09382 group = partitions->groups[i]; 09383 if (lasts[i] != NULL) { 09384 last = lasts[i]->next; 09385 lasts[i]->next = NULL; 09386 } 09387 ctxt->state->seq = list[i]; 09388 ret = xmlRelaxNGValidateDefinition(ctxt, group->rule); 09389 if (ret != 0) 09390 break; 09391 if (ctxt->state != NULL) { 09392 cur = ctxt->state->seq; 09393 cur = xmlRelaxNGSkipIgnored(ctxt, cur); 09394 xmlRelaxNGFreeValidState(ctxt, oldstate); 09395 oldstate = ctxt->state; 09396 ctxt->state = NULL; 09397 if (cur != NULL) { 09398 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name); 09399 ret = -1; 09400 ctxt->state = oldstate; 09401 goto done; 09402 } 09403 } else if (ctxt->states != NULL) { 09404 int j; 09405 int found = 0; 09406 int best = -1; 09407 int lowattr = -1; 09408 09409 /* 09410 * PBM: what happen if there is attributes checks in the interleaves 09411 */ 09412 09413 for (j = 0; j < ctxt->states->nbState; j++) { 09414 cur = ctxt->states->tabState[j]->seq; 09415 cur = xmlRelaxNGSkipIgnored(ctxt, cur); 09416 if (cur == NULL) { 09417 if (found == 0) { 09418 lowattr = ctxt->states->tabState[j]->nbAttrLeft; 09419 best = j; 09420 } 09421 found = 1; 09422 if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) { 09423 /* try to keep the latest one to mach old heuristic */ 09424 lowattr = ctxt->states->tabState[j]->nbAttrLeft; 09425 best = j; 09426 } 09427 if (lowattr == 0) 09428 break; 09429 } else if (found == 0) { 09430 if (lowattr == -1) { 09431 lowattr = ctxt->states->tabState[j]->nbAttrLeft; 09432 best = j; 09433 } else 09434 if (ctxt->states->tabState[j]->nbAttrLeft <= lowattr) { 09435 /* try to keep the latest one to mach old heuristic */ 09436 lowattr = ctxt->states->tabState[j]->nbAttrLeft; 09437 best = j; 09438 } 09439 } 09440 } 09441 /* 09442 * BIG PBM: here we pick only one restarting point :-( 09443 */ 09444 if (ctxt->states->nbState > 0) { 09445 xmlRelaxNGFreeValidState(ctxt, oldstate); 09446 if (best != -1) { 09447 oldstate = ctxt->states->tabState[best]; 09448 ctxt->states->tabState[best] = NULL; 09449 } else { 09450 oldstate = 09451 ctxt->states->tabState[ctxt->states->nbState - 1]; 09452 ctxt->states->tabState[ctxt->states->nbState - 1] = NULL; 09453 ctxt->states->nbState--; 09454 } 09455 } 09456 for (j = 0; j < ctxt->states->nbState ; j++) { 09457 xmlRelaxNGFreeValidState(ctxt, ctxt->states->tabState[j]); 09458 } 09459 xmlRelaxNGFreeStates(ctxt, ctxt->states); 09460 ctxt->states = NULL; 09461 if (found == 0) { 09462 if (cur == NULL) { 09463 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, 09464 (const xmlChar *) "noname"); 09465 } else { 09466 VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name); 09467 } 09468 ret = -1; 09469 ctxt->state = oldstate; 09470 goto done; 09471 } 09472 } else { 09473 ret = -1; 09474 break; 09475 } 09476 if (lasts[i] != NULL) { 09477 lasts[i]->next = last; 09478 } 09479 } 09480 if (ctxt->state != NULL) 09481 xmlRelaxNGFreeValidState(ctxt, ctxt->state); 09482 ctxt->state = oldstate; 09483 ctxt->state->seq = lastelem; 09484 if (ret != 0) { 09485 VALID_ERR(XML_RELAXNG_ERR_INTERSEQ); 09486 ret = -1; 09487 goto done; 09488 } 09489 09490 done: 09491 ctxt->flags = oldflags; 09492 /* 09493 * builds the next links chain from the prev one 09494 */ 09495 cur = lastchg; 09496 while (cur != NULL) { 09497 if ((cur == start) || (cur->prev == NULL)) 09498 break; 09499 cur->prev->next = cur; 09500 cur = cur->prev; 09501 } 09502 if (ret == 0) { 09503 if (ctxt->errNr > errNr) 09504 xmlRelaxNGPopErrors(ctxt, errNr); 09505 } 09506 09507 xmlFree(list); 09508 xmlFree(lasts); 09509 return (ret); 09510 } 09511 09521 static int 09522 xmlRelaxNGValidateDefinitionList(xmlRelaxNGValidCtxtPtr ctxt, 09523 xmlRelaxNGDefinePtr defines) 09524 { 09525 int ret = 0, res; 09526 09527 09528 if (defines == NULL) { 09529 VALID_ERR2(XML_RELAXNG_ERR_INTERNAL, 09530 BAD_CAST "NULL definition list"); 09531 return (-1); 09532 } 09533 while (defines != NULL) { 09534 if ((ctxt->state != NULL) || (ctxt->states != NULL)) { 09535 res = xmlRelaxNGValidateDefinition(ctxt, defines); 09536 if (res < 0) 09537 ret = -1; 09538 } else { 09539 VALID_ERR(XML_RELAXNG_ERR_NOSTATE); 09540 return (-1); 09541 } 09542 if (res == -1) /* continues on -2 */ 09543 break; 09544 defines = defines->next; 09545 } 09546 09547 return (ret); 09548 } 09549 09560 static int 09561 xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt, 09562 xmlRelaxNGDefinePtr define, xmlNodePtr elem) 09563 { 09564 int ret = 0, oldflags = 0; 09565 09566 if (define->name != NULL) { 09567 if (!xmlStrEqual(elem->name, define->name)) { 09568 VALID_ERR3(XML_RELAXNG_ERR_ELEMNAME, define->name, elem->name); 09569 return (0); 09570 } 09571 } 09572 if ((define->ns != NULL) && (define->ns[0] != 0)) { 09573 if (elem->ns == NULL) { 09574 VALID_ERR2(XML_RELAXNG_ERR_ELEMNONS, elem->name); 09575 return (0); 09576 } else if (!xmlStrEqual(elem->ns->href, define->ns)) { 09577 VALID_ERR3(XML_RELAXNG_ERR_ELEMWRONGNS, 09578 elem->name, define->ns); 09579 return (0); 09580 } 09581 } else if ((elem->ns != NULL) && (define->ns != NULL) && 09582 (define->name == NULL)) { 09583 VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, elem->name); 09584 return (0); 09585 } else if ((elem->ns != NULL) && (define->name != NULL)) { 09586 VALID_ERR2(XML_RELAXNG_ERR_ELEMEXTRANS, define->name); 09587 return (0); 09588 } 09589 09590 if (define->nameClass == NULL) 09591 return (1); 09592 09593 define = define->nameClass; 09594 if (define->type == XML_RELAXNG_EXCEPT) { 09595 xmlRelaxNGDefinePtr list; 09596 09597 if (ctxt != NULL) { 09598 oldflags = ctxt->flags; 09599 ctxt->flags |= FLAGS_IGNORABLE; 09600 } 09601 09602 list = define->content; 09603 while (list != NULL) { 09604 ret = xmlRelaxNGElementMatch(ctxt, list, elem); 09605 if (ret == 1) { 09606 if (ctxt != NULL) 09607 ctxt->flags = oldflags; 09608 return (0); 09609 } 09610 if (ret < 0) { 09611 if (ctxt != NULL) 09612 ctxt->flags = oldflags; 09613 return (ret); 09614 } 09615 list = list->next; 09616 } 09617 ret = 1; 09618 if (ctxt != NULL) { 09619 ctxt->flags = oldflags; 09620 } 09621 } else if (define->type == XML_RELAXNG_CHOICE) { 09622 xmlRelaxNGDefinePtr list; 09623 09624 if (ctxt != NULL) { 09625 oldflags = ctxt->flags; 09626 ctxt->flags |= FLAGS_IGNORABLE; 09627 } 09628 09629 list = define->nameClass; 09630 while (list != NULL) { 09631 ret = xmlRelaxNGElementMatch(ctxt, list, elem); 09632 if (ret == 1) { 09633 if (ctxt != NULL) 09634 ctxt->flags = oldflags; 09635 return (1); 09636 } 09637 if (ret < 0) { 09638 if (ctxt != NULL) 09639 ctxt->flags = oldflags; 09640 return (ret); 09641 } 09642 list = list->next; 09643 } 09644 if (ctxt != NULL) { 09645 if (ret != 0) { 09646 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) 09647 xmlRelaxNGDumpValidError(ctxt); 09648 } else { 09649 if (ctxt->errNr > 0) 09650 xmlRelaxNGPopErrors(ctxt, 0); 09651 } 09652 } 09653 ret = 0; 09654 if (ctxt != NULL) { 09655 ctxt->flags = oldflags; 09656 } 09657 } else { 09658 TODO ret = -1; 09659 } 09660 return (ret); 09661 } 09662 09674 static int 09675 xmlRelaxNGBestState(xmlRelaxNGValidCtxtPtr ctxt) 09676 { 09677 xmlRelaxNGValidStatePtr state; 09678 int i, tmp; 09679 int best = -1; 09680 int value = 1000000; 09681 09682 if ((ctxt == NULL) || (ctxt->states == NULL) || 09683 (ctxt->states->nbState <= 0)) 09684 return (-1); 09685 09686 for (i = 0; i < ctxt->states->nbState; i++) { 09687 state = ctxt->states->tabState[i]; 09688 if (state == NULL) 09689 continue; 09690 if (state->seq != NULL) { 09691 if ((best == -1) || (value > 100000)) { 09692 value = 100000; 09693 best = i; 09694 } 09695 } else { 09696 tmp = state->nbAttrLeft; 09697 if ((best == -1) || (value > tmp)) { 09698 value = tmp; 09699 best = i; 09700 } 09701 } 09702 } 09703 return (best); 09704 } 09705 09713 static void 09714 xmlRelaxNGLogBestError(xmlRelaxNGValidCtxtPtr ctxt) 09715 { 09716 int best; 09717 09718 if ((ctxt == NULL) || (ctxt->states == NULL) || 09719 (ctxt->states->nbState <= 0)) 09720 return; 09721 09722 best = xmlRelaxNGBestState(ctxt); 09723 if ((best >= 0) && (best < ctxt->states->nbState)) { 09724 ctxt->state = ctxt->states->tabState[best]; 09725 09726 xmlRelaxNGValidateElementEnd(ctxt, 1); 09727 } 09728 } 09729 09741 static int 09742 xmlRelaxNGValidateElementEnd(xmlRelaxNGValidCtxtPtr ctxt, int dolog) 09743 { 09744 int i; 09745 xmlRelaxNGValidStatePtr state; 09746 09747 state = ctxt->state; 09748 if (state->seq != NULL) { 09749 state->seq = xmlRelaxNGSkipIgnored(ctxt, state->seq); 09750 if (state->seq != NULL) { 09751 if (dolog) { 09752 VALID_ERR3(XML_RELAXNG_ERR_EXTRACONTENT, 09753 state->node->name, state->seq->name); 09754 } 09755 return (-1); 09756 } 09757 } 09758 for (i = 0; i < state->nbAttrs; i++) { 09759 if (state->attrs[i] != NULL) { 09760 if (dolog) { 09761 VALID_ERR3(XML_RELAXNG_ERR_INVALIDATTR, 09762 state->attrs[i]->name, state->node->name); 09763 } 09764 return (-1 - i); 09765 } 09766 } 09767 return (0); 09768 } 09769 09779 static int 09780 xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, 09781 xmlRelaxNGDefinePtr define) 09782 { 09783 xmlNodePtr node; 09784 int ret = 0, i, tmp, oldflags, errNr; 09785 xmlRelaxNGValidStatePtr oldstate = NULL, state; 09786 09787 if (define == NULL) { 09788 VALID_ERR(XML_RELAXNG_ERR_NODEFINE); 09789 return (-1); 09790 } 09791 09792 if (ctxt->state != NULL) { 09793 node = ctxt->state->seq; 09794 } else { 09795 node = NULL; 09796 } 09797 #ifdef DEBUG 09798 for (i = 0; i < ctxt->depth; i++) 09799 xmlGenericError(xmlGenericErrorContext, " "); 09800 xmlGenericError(xmlGenericErrorContext, 09801 "Start validating %s ", xmlRelaxNGDefName(define)); 09802 if (define->name != NULL) 09803 xmlGenericError(xmlGenericErrorContext, "%s ", define->name); 09804 if ((node != NULL) && (node->name != NULL)) 09805 xmlGenericError(xmlGenericErrorContext, "on %s\n", node->name); 09806 else 09807 xmlGenericError(xmlGenericErrorContext, "\n"); 09808 #endif 09809 ctxt->depth++; 09810 switch (define->type) { 09811 case XML_RELAXNG_EMPTY: 09812 node = xmlRelaxNGSkipIgnored(ctxt, node); 09813 ret = 0; 09814 break; 09815 case XML_RELAXNG_NOT_ALLOWED: 09816 ret = -1; 09817 break; 09818 case XML_RELAXNG_TEXT: 09819 while ((node != NULL) && 09820 ((node->type == XML_TEXT_NODE) || 09821 (node->type == XML_COMMENT_NODE) || 09822 (node->type == XML_PI_NODE) || 09823 (node->type == XML_CDATA_SECTION_NODE))) 09824 node = node->next; 09825 ctxt->state->seq = node; 09826 break; 09827 case XML_RELAXNG_ELEMENT: 09828 errNr = ctxt->errNr; 09829 node = xmlRelaxNGSkipIgnored(ctxt, node); 09830 if (node == NULL) { 09831 VALID_ERR2(XML_RELAXNG_ERR_NOELEM, define->name); 09832 ret = -1; 09833 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) 09834 xmlRelaxNGDumpValidError(ctxt); 09835 break; 09836 } 09837 if (node->type != XML_ELEMENT_NODE) { 09838 VALID_ERR(XML_RELAXNG_ERR_NOTELEM); 09839 ret = -1; 09840 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) 09841 xmlRelaxNGDumpValidError(ctxt); 09842 break; 09843 } 09844 /* 09845 * This node was already validated successfully against 09846 * this definition. 09847 */ 09848 if (node->psvi == define) { 09849 ctxt->state->seq = xmlRelaxNGSkipIgnored(ctxt, node->next); 09850 if (ctxt->errNr > errNr) 09851 xmlRelaxNGPopErrors(ctxt, errNr); 09852 if (ctxt->errNr != 0) { 09853 while ((ctxt->err != NULL) && 09854 (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) 09855 && (xmlStrEqual(ctxt->err->arg2, node->name))) 09856 || 09857 ((ctxt->err->err == 09858 XML_RELAXNG_ERR_ELEMEXTRANS) 09859 && (xmlStrEqual(ctxt->err->arg1, node->name))) 09860 || (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) 09861 || (ctxt->err->err == 09862 XML_RELAXNG_ERR_NOTELEM))) 09863 xmlRelaxNGValidErrorPop(ctxt); 09864 } 09865 break; 09866 } 09867 09868 ret = xmlRelaxNGElementMatch(ctxt, define, node); 09869 if (ret <= 0) { 09870 ret = -1; 09871 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) 09872 xmlRelaxNGDumpValidError(ctxt); 09873 break; 09874 } 09875 ret = 0; 09876 if (ctxt->errNr != 0) { 09877 if (ctxt->errNr > errNr) 09878 xmlRelaxNGPopErrors(ctxt, errNr); 09879 while ((ctxt->err != NULL) && 09880 (((ctxt->err->err == XML_RELAXNG_ERR_ELEMNAME) && 09881 (xmlStrEqual(ctxt->err->arg2, node->name))) || 09882 ((ctxt->err->err == XML_RELAXNG_ERR_ELEMEXTRANS) && 09883 (xmlStrEqual(ctxt->err->arg1, node->name))) || 09884 (ctxt->err->err == XML_RELAXNG_ERR_NOELEM) || 09885 (ctxt->err->err == XML_RELAXNG_ERR_NOTELEM))) 09886 xmlRelaxNGValidErrorPop(ctxt); 09887 } 09888 errNr = ctxt->errNr; 09889 09890 oldflags = ctxt->flags; 09891 if (ctxt->flags & FLAGS_MIXED_CONTENT) { 09892 ctxt->flags -= FLAGS_MIXED_CONTENT; 09893 } 09894 state = xmlRelaxNGNewValidState(ctxt, node); 09895 if (state == NULL) { 09896 ret = -1; 09897 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) 09898 xmlRelaxNGDumpValidError(ctxt); 09899 break; 09900 } 09901 09902 oldstate = ctxt->state; 09903 ctxt->state = state; 09904 if (define->attrs != NULL) { 09905 tmp = xmlRelaxNGValidateAttributeList(ctxt, define->attrs); 09906 if (tmp != 0) { 09907 ret = -1; 09908 VALID_ERR2(XML_RELAXNG_ERR_ATTRVALID, node->name); 09909 } 09910 } 09911 if (define->contModel != NULL) { 09912 xmlRelaxNGValidStatePtr nstate, tmpstate = ctxt->state; 09913 xmlRelaxNGStatesPtr tmpstates = ctxt->states; 09914 xmlNodePtr nseq; 09915 09916 nstate = xmlRelaxNGNewValidState(ctxt, node); 09917 ctxt->state = nstate; 09918 ctxt->states = NULL; 09919 09920 tmp = xmlRelaxNGValidateCompiledContent(ctxt, 09921 define->contModel, 09922 ctxt->state->seq); 09923 nseq = ctxt->state->seq; 09924 ctxt->state = tmpstate; 09925 ctxt->states = tmpstates; 09926 xmlRelaxNGFreeValidState(ctxt, nstate); 09927 09928 #ifdef DEBUG_COMPILE 09929 xmlGenericError(xmlGenericErrorContext, 09930 "Validating content of '%s' : %d\n", 09931 define->name, tmp); 09932 #endif 09933 if (tmp != 0) 09934 ret = -1; 09935 09936 if (ctxt->states != NULL) { 09937 tmp = -1; 09938 09939 for (i = 0; i < ctxt->states->nbState; i++) { 09940 state = ctxt->states->tabState[i]; 09941 ctxt->state = state; 09942 ctxt->state->seq = nseq; 09943 09944 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { 09945 tmp = 0; 09946 break; 09947 } 09948 } 09949 if (tmp != 0) { 09950 /* 09951 * validation error, log the message for the "best" one 09952 */ 09953 ctxt->flags |= FLAGS_IGNORABLE; 09954 xmlRelaxNGLogBestError(ctxt); 09955 } 09956 for (i = 0; i < ctxt->states->nbState; i++) { 09957 xmlRelaxNGFreeValidState(ctxt, 09958 ctxt->states-> 09959 tabState[i]); 09960 } 09961 xmlRelaxNGFreeStates(ctxt, ctxt->states); 09962 ctxt->flags = oldflags; 09963 ctxt->states = NULL; 09964 if ((ret == 0) && (tmp == -1)) 09965 ret = -1; 09966 } else { 09967 state = ctxt->state; 09968 if (ctxt->state != NULL) 09969 ctxt->state->seq = nseq; 09970 if (ret == 0) 09971 ret = xmlRelaxNGValidateElementEnd(ctxt, 1); 09972 xmlRelaxNGFreeValidState(ctxt, state); 09973 } 09974 } else { 09975 if (define->content != NULL) { 09976 tmp = xmlRelaxNGValidateDefinitionList(ctxt, 09977 define-> 09978 content); 09979 if (tmp != 0) { 09980 ret = -1; 09981 if (ctxt->state == NULL) { 09982 ctxt->state = oldstate; 09983 VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID, 09984 node->name); 09985 ctxt->state = NULL; 09986 } else { 09987 VALID_ERR2(XML_RELAXNG_ERR_CONTENTVALID, 09988 node->name); 09989 } 09990 09991 } 09992 } 09993 if (ctxt->states != NULL) { 09994 tmp = -1; 09995 09996 for (i = 0; i < ctxt->states->nbState; i++) { 09997 state = ctxt->states->tabState[i]; 09998 ctxt->state = state; 09999 10000 if (xmlRelaxNGValidateElementEnd(ctxt, 0) == 0) { 10001 tmp = 0; 10002 break; 10003 } 10004 } 10005 if (tmp != 0) { 10006 /* 10007 * validation error, log the message for the "best" one 10008 */ 10009 ctxt->flags |= FLAGS_IGNORABLE; 10010 xmlRelaxNGLogBestError(ctxt); 10011 } 10012 for (i = 0; i < ctxt->states->nbState; i++) { 10013 xmlRelaxNGFreeValidState(ctxt, 10014 ctxt->states->tabState[i]); 10015 ctxt->states->tabState[i] = NULL; 10016 } 10017 xmlRelaxNGFreeStates(ctxt, ctxt->states); 10018 ctxt->flags = oldflags; 10019 ctxt->states = NULL; 10020 if ((ret == 0) && (tmp == -1)) 10021 ret = -1; 10022 } else { 10023 state = ctxt->state; 10024 if (ret == 0) 10025 ret = xmlRelaxNGValidateElementEnd(ctxt, 1); 10026 xmlRelaxNGFreeValidState(ctxt, state); 10027 } 10028 } 10029 if (ret == 0) { 10030 node->psvi = define; 10031 } 10032 ctxt->flags = oldflags; 10033 ctxt->state = oldstate; 10034 if (oldstate != NULL) 10035 oldstate->seq = xmlRelaxNGSkipIgnored(ctxt, node->next); 10036 if (ret != 0) { 10037 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { 10038 xmlRelaxNGDumpValidError(ctxt); 10039 ret = 0; 10040 #if 0 10041 } else { 10042 ret = -2; 10043 #endif 10044 } 10045 } else { 10046 if (ctxt->errNr > errNr) 10047 xmlRelaxNGPopErrors(ctxt, errNr); 10048 } 10049 10050 #ifdef DEBUG 10051 xmlGenericError(xmlGenericErrorContext, 10052 "xmlRelaxNGValidateDefinition(): validated %s : %d", 10053 node->name, ret); 10054 if (oldstate == NULL) 10055 xmlGenericError(xmlGenericErrorContext, ": no state\n"); 10056 else if (oldstate->seq == NULL) 10057 xmlGenericError(xmlGenericErrorContext, ": done\n"); 10058 else if (oldstate->seq->type == XML_ELEMENT_NODE) 10059 xmlGenericError(xmlGenericErrorContext, ": next elem %s\n", 10060 oldstate->seq->name); 10061 else 10062 xmlGenericError(xmlGenericErrorContext, ": next %s %d\n", 10063 oldstate->seq->name, oldstate->seq->type); 10064 #endif 10065 break; 10066 case XML_RELAXNG_OPTIONAL:{ 10067 errNr = ctxt->errNr; 10068 oldflags = ctxt->flags; 10069 ctxt->flags |= FLAGS_IGNORABLE; 10070 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state); 10071 ret = 10072 xmlRelaxNGValidateDefinitionList(ctxt, 10073 define->content); 10074 if (ret != 0) { 10075 if (ctxt->state != NULL) 10076 xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10077 ctxt->state = oldstate; 10078 ctxt->flags = oldflags; 10079 ret = 0; 10080 if (ctxt->errNr > errNr) 10081 xmlRelaxNGPopErrors(ctxt, errNr); 10082 break; 10083 } 10084 if (ctxt->states != NULL) { 10085 xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate); 10086 } else { 10087 ctxt->states = xmlRelaxNGNewStates(ctxt, 1); 10088 if (ctxt->states == NULL) { 10089 xmlRelaxNGFreeValidState(ctxt, oldstate); 10090 ctxt->flags = oldflags; 10091 ret = -1; 10092 if (ctxt->errNr > errNr) 10093 xmlRelaxNGPopErrors(ctxt, errNr); 10094 break; 10095 } 10096 xmlRelaxNGAddStates(ctxt, ctxt->states, oldstate); 10097 xmlRelaxNGAddStates(ctxt, ctxt->states, ctxt->state); 10098 ctxt->state = NULL; 10099 } 10100 ctxt->flags = oldflags; 10101 ret = 0; 10102 if (ctxt->errNr > errNr) 10103 xmlRelaxNGPopErrors(ctxt, errNr); 10104 break; 10105 } 10106 case XML_RELAXNG_ONEORMORE: 10107 errNr = ctxt->errNr; 10108 ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content); 10109 if (ret != 0) { 10110 break; 10111 } 10112 if (ctxt->errNr > errNr) 10113 xmlRelaxNGPopErrors(ctxt, errNr); 10114 /* no break on purpose */ 10115 case XML_RELAXNG_ZEROORMORE:{ 10116 int progress; 10117 xmlRelaxNGStatesPtr states = NULL, res = NULL; 10118 int base, j; 10119 10120 errNr = ctxt->errNr; 10121 res = xmlRelaxNGNewStates(ctxt, 1); 10122 if (res == NULL) { 10123 ret = -1; 10124 break; 10125 } 10126 /* 10127 * All the input states are also exit states 10128 */ 10129 if (ctxt->state != NULL) { 10130 xmlRelaxNGAddStates(ctxt, res, 10131 xmlRelaxNGCopyValidState(ctxt, 10132 ctxt-> 10133 state)); 10134 } else { 10135 for (j = 0; j < ctxt->states->nbState; j++) { 10136 xmlRelaxNGAddStates(ctxt, res, 10137 xmlRelaxNGCopyValidState(ctxt, 10138 ctxt->states->tabState[j])); 10139 } 10140 } 10141 oldflags = ctxt->flags; 10142 ctxt->flags |= FLAGS_IGNORABLE; 10143 do { 10144 progress = 0; 10145 base = res->nbState; 10146 10147 if (ctxt->states != NULL) { 10148 states = ctxt->states; 10149 for (i = 0; i < states->nbState; i++) { 10150 ctxt->state = states->tabState[i]; 10151 ctxt->states = NULL; 10152 ret = xmlRelaxNGValidateDefinitionList(ctxt, 10153 define-> 10154 content); 10155 if (ret == 0) { 10156 if (ctxt->state != NULL) { 10157 tmp = xmlRelaxNGAddStates(ctxt, res, 10158 ctxt->state); 10159 ctxt->state = NULL; 10160 if (tmp == 1) 10161 progress = 1; 10162 } else if (ctxt->states != NULL) { 10163 for (j = 0; j < ctxt->states->nbState; 10164 j++) { 10165 tmp = 10166 xmlRelaxNGAddStates(ctxt, res, 10167 ctxt->states->tabState[j]); 10168 if (tmp == 1) 10169 progress = 1; 10170 } 10171 xmlRelaxNGFreeStates(ctxt, 10172 ctxt->states); 10173 ctxt->states = NULL; 10174 } 10175 } else { 10176 if (ctxt->state != NULL) { 10177 xmlRelaxNGFreeValidState(ctxt, 10178 ctxt->state); 10179 ctxt->state = NULL; 10180 } 10181 } 10182 } 10183 } else { 10184 ret = xmlRelaxNGValidateDefinitionList(ctxt, 10185 define-> 10186 content); 10187 if (ret != 0) { 10188 xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10189 ctxt->state = NULL; 10190 } else { 10191 base = res->nbState; 10192 if (ctxt->state != NULL) { 10193 tmp = xmlRelaxNGAddStates(ctxt, res, 10194 ctxt->state); 10195 ctxt->state = NULL; 10196 if (tmp == 1) 10197 progress = 1; 10198 } else if (ctxt->states != NULL) { 10199 for (j = 0; j < ctxt->states->nbState; j++) { 10200 tmp = xmlRelaxNGAddStates(ctxt, res, 10201 ctxt->states->tabState[j]); 10202 if (tmp == 1) 10203 progress = 1; 10204 } 10205 if (states == NULL) { 10206 states = ctxt->states; 10207 } else { 10208 xmlRelaxNGFreeStates(ctxt, 10209 ctxt->states); 10210 } 10211 ctxt->states = NULL; 10212 } 10213 } 10214 } 10215 if (progress) { 10216 /* 10217 * Collect all the new nodes added at that step 10218 * and make them the new node set 10219 */ 10220 if (res->nbState - base == 1) { 10221 ctxt->state = xmlRelaxNGCopyValidState(ctxt, 10222 res-> 10223 tabState 10224 [base]); 10225 } else { 10226 if (states == NULL) { 10227 xmlRelaxNGNewStates(ctxt, 10228 res->nbState - base); 10229 states = ctxt->states; 10230 if (states == NULL) { 10231 progress = 0; 10232 break; 10233 } 10234 } 10235 states->nbState = 0; 10236 for (i = base; i < res->nbState; i++) 10237 xmlRelaxNGAddStates(ctxt, states, 10238 xmlRelaxNGCopyValidState 10239 (ctxt, res->tabState[i])); 10240 ctxt->states = states; 10241 } 10242 } 10243 } while (progress == 1); 10244 if (states != NULL) { 10245 xmlRelaxNGFreeStates(ctxt, states); 10246 } 10247 ctxt->states = res; 10248 ctxt->flags = oldflags; 10249 #if 0 10250 /* 10251 * errors may have to be propagated back... 10252 */ 10253 if (ctxt->errNr > errNr) 10254 xmlRelaxNGPopErrors(ctxt, errNr); 10255 #endif 10256 ret = 0; 10257 break; 10258 } 10259 case XML_RELAXNG_CHOICE:{ 10260 xmlRelaxNGDefinePtr list = NULL; 10261 xmlRelaxNGStatesPtr states = NULL; 10262 10263 node = xmlRelaxNGSkipIgnored(ctxt, node); 10264 10265 errNr = ctxt->errNr; 10266 if ((define->dflags & IS_TRIABLE) && (define->data != NULL) && 10267 (node != NULL)) { 10268 /* 10269 * node == NULL can't be optimized since IS_TRIABLE 10270 * doesn't account for choice which may lead to 10271 * only attributes. 10272 */ 10273 xmlHashTablePtr triage = 10274 (xmlHashTablePtr) define->data; 10275 10276 /* 10277 * Something we can optimize cleanly there is only one 10278 * possble branch out ! 10279 */ 10280 if ((node->type == XML_TEXT_NODE) || 10281 (node->type == XML_CDATA_SECTION_NODE)) { 10282 list = 10283 xmlHashLookup2(triage, BAD_CAST "#text", NULL); 10284 } else if (node->type == XML_ELEMENT_NODE) { 10285 if (node->ns != NULL) { 10286 list = xmlHashLookup2(triage, node->name, 10287 node->ns->href); 10288 if (list == NULL) 10289 list = 10290 xmlHashLookup2(triage, BAD_CAST "#any", 10291 node->ns->href); 10292 } else 10293 list = 10294 xmlHashLookup2(triage, node->name, NULL); 10295 if (list == NULL) 10296 list = 10297 xmlHashLookup2(triage, BAD_CAST "#any", 10298 NULL); 10299 } 10300 if (list == NULL) { 10301 ret = -1; 10302 VALID_ERR2(XML_RELAXNG_ERR_ELEMWRONG, node->name); 10303 break; 10304 } 10305 ret = xmlRelaxNGValidateDefinition(ctxt, list); 10306 if (ret == 0) { 10307 } 10308 break; 10309 } 10310 10311 list = define->content; 10312 oldflags = ctxt->flags; 10313 ctxt->flags |= FLAGS_IGNORABLE; 10314 10315 while (list != NULL) { 10316 oldstate = xmlRelaxNGCopyValidState(ctxt, ctxt->state); 10317 ret = xmlRelaxNGValidateDefinition(ctxt, list); 10318 if (ret == 0) { 10319 if (states == NULL) { 10320 states = xmlRelaxNGNewStates(ctxt, 1); 10321 } 10322 if (ctxt->state != NULL) { 10323 xmlRelaxNGAddStates(ctxt, states, ctxt->state); 10324 } else if (ctxt->states != NULL) { 10325 for (i = 0; i < ctxt->states->nbState; i++) { 10326 xmlRelaxNGAddStates(ctxt, states, 10327 ctxt->states-> 10328 tabState[i]); 10329 } 10330 xmlRelaxNGFreeStates(ctxt, ctxt->states); 10331 ctxt->states = NULL; 10332 } 10333 } else { 10334 xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10335 } 10336 ctxt->state = oldstate; 10337 list = list->next; 10338 } 10339 if (states != NULL) { 10340 xmlRelaxNGFreeValidState(ctxt, oldstate); 10341 ctxt->states = states; 10342 ctxt->state = NULL; 10343 ret = 0; 10344 } else { 10345 ctxt->states = NULL; 10346 } 10347 ctxt->flags = oldflags; 10348 if (ret != 0) { 10349 if ((ctxt->flags & FLAGS_IGNORABLE) == 0) { 10350 xmlRelaxNGDumpValidError(ctxt); 10351 } 10352 } else { 10353 if (ctxt->errNr > errNr) 10354 xmlRelaxNGPopErrors(ctxt, errNr); 10355 } 10356 break; 10357 } 10358 case XML_RELAXNG_DEF: 10359 case XML_RELAXNG_GROUP: 10360 ret = xmlRelaxNGValidateDefinitionList(ctxt, define->content); 10361 break; 10362 case XML_RELAXNG_INTERLEAVE: 10363 ret = xmlRelaxNGValidateInterleave(ctxt, define); 10364 break; 10365 case XML_RELAXNG_ATTRIBUTE: 10366 ret = xmlRelaxNGValidateAttribute(ctxt, define); 10367 break; 10368 case XML_RELAXNG_START: 10369 case XML_RELAXNG_NOOP: 10370 case XML_RELAXNG_REF: 10371 case XML_RELAXNG_EXTERNALREF: 10372 case XML_RELAXNG_PARENTREF: 10373 ret = xmlRelaxNGValidateDefinition(ctxt, define->content); 10374 break; 10375 case XML_RELAXNG_DATATYPE:{ 10376 xmlNodePtr child; 10377 xmlChar *content = NULL; 10378 10379 child = node; 10380 while (child != NULL) { 10381 if (child->type == XML_ELEMENT_NODE) { 10382 VALID_ERR2(XML_RELAXNG_ERR_DATAELEM, 10383 node->parent->name); 10384 ret = -1; 10385 break; 10386 } else if ((child->type == XML_TEXT_NODE) || 10387 (child->type == XML_CDATA_SECTION_NODE)) { 10388 content = xmlStrcat(content, child->content); 10389 } 10390 /* TODO: handle entities ... */ 10391 child = child->next; 10392 } 10393 if (ret == -1) { 10394 if (content != NULL) 10395 xmlFree(content); 10396 break; 10397 } 10398 if (content == NULL) { 10399 content = xmlStrdup(BAD_CAST ""); 10400 if (content == NULL) { 10401 xmlRngVErrMemory(ctxt, "validating\n"); 10402 ret = -1; 10403 break; 10404 } 10405 } 10406 ret = xmlRelaxNGValidateDatatype(ctxt, content, define, 10407 ctxt->state->seq); 10408 if (ret == -1) { 10409 VALID_ERR2(XML_RELAXNG_ERR_DATATYPE, define->name); 10410 } else if (ret == 0) { 10411 ctxt->state->seq = NULL; 10412 } 10413 if (content != NULL) 10414 xmlFree(content); 10415 break; 10416 } 10417 case XML_RELAXNG_VALUE:{ 10418 xmlChar *content = NULL; 10419 xmlChar *oldvalue; 10420 xmlNodePtr child; 10421 10422 child = node; 10423 while (child != NULL) { 10424 if (child->type == XML_ELEMENT_NODE) { 10425 VALID_ERR2(XML_RELAXNG_ERR_VALELEM, 10426 node->parent->name); 10427 ret = -1; 10428 break; 10429 } else if ((child->type == XML_TEXT_NODE) || 10430 (child->type == XML_CDATA_SECTION_NODE)) { 10431 content = xmlStrcat(content, child->content); 10432 } 10433 /* TODO: handle entities ... */ 10434 child = child->next; 10435 } 10436 if (ret == -1) { 10437 if (content != NULL) 10438 xmlFree(content); 10439 break; 10440 } 10441 if (content == NULL) { 10442 content = xmlStrdup(BAD_CAST ""); 10443 if (content == NULL) { 10444 xmlRngVErrMemory(ctxt, "validating\n"); 10445 ret = -1; 10446 break; 10447 } 10448 } 10449 oldvalue = ctxt->state->value; 10450 ctxt->state->value = content; 10451 ret = xmlRelaxNGValidateValue(ctxt, define); 10452 ctxt->state->value = oldvalue; 10453 if (ret == -1) { 10454 VALID_ERR2(XML_RELAXNG_ERR_VALUE, define->name); 10455 } else if (ret == 0) { 10456 ctxt->state->seq = NULL; 10457 } 10458 if (content != NULL) 10459 xmlFree(content); 10460 break; 10461 } 10462 case XML_RELAXNG_LIST:{ 10463 xmlChar *content; 10464 xmlNodePtr child; 10465 xmlChar *oldvalue, *oldendvalue; 10466 int len; 10467 10468 /* 10469 * Make sure it's only text nodes 10470 */ 10471 10472 content = NULL; 10473 child = node; 10474 while (child != NULL) { 10475 if (child->type == XML_ELEMENT_NODE) { 10476 VALID_ERR2(XML_RELAXNG_ERR_LISTELEM, 10477 node->parent->name); 10478 ret = -1; 10479 break; 10480 } else if ((child->type == XML_TEXT_NODE) || 10481 (child->type == XML_CDATA_SECTION_NODE)) { 10482 content = xmlStrcat(content, child->content); 10483 } 10484 /* TODO: handle entities ... */ 10485 child = child->next; 10486 } 10487 if (ret == -1) { 10488 if (content != NULL) 10489 xmlFree(content); 10490 break; 10491 } 10492 if (content == NULL) { 10493 content = xmlStrdup(BAD_CAST ""); 10494 if (content == NULL) { 10495 xmlRngVErrMemory(ctxt, "validating\n"); 10496 ret = -1; 10497 break; 10498 } 10499 } 10500 len = xmlStrlen(content); 10501 oldvalue = ctxt->state->value; 10502 oldendvalue = ctxt->state->endvalue; 10503 ctxt->state->value = content; 10504 ctxt->state->endvalue = content + len; 10505 ret = xmlRelaxNGValidateValue(ctxt, define); 10506 ctxt->state->value = oldvalue; 10507 ctxt->state->endvalue = oldendvalue; 10508 if (ret == -1) { 10509 VALID_ERR(XML_RELAXNG_ERR_LIST); 10510 } else if ((ret == 0) && (node != NULL)) { 10511 ctxt->state->seq = node->next; 10512 } 10513 if (content != NULL) 10514 xmlFree(content); 10515 break; 10516 } 10517 case XML_RELAXNG_EXCEPT: 10518 case XML_RELAXNG_PARAM: 10519 TODO ret = -1; 10520 break; 10521 } 10522 ctxt->depth--; 10523 #ifdef DEBUG 10524 for (i = 0; i < ctxt->depth; i++) 10525 xmlGenericError(xmlGenericErrorContext, " "); 10526 xmlGenericError(xmlGenericErrorContext, 10527 "Validating %s ", xmlRelaxNGDefName(define)); 10528 if (define->name != NULL) 10529 xmlGenericError(xmlGenericErrorContext, "%s ", define->name); 10530 if (ret == 0) 10531 xmlGenericError(xmlGenericErrorContext, "suceeded\n"); 10532 else 10533 xmlGenericError(xmlGenericErrorContext, "failed\n"); 10534 #endif 10535 return (ret); 10536 } 10537 10547 static int 10548 xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, 10549 xmlRelaxNGDefinePtr define) 10550 { 10551 xmlRelaxNGStatesPtr states, res; 10552 int i, j, k, ret, oldflags; 10553 10554 /* 10555 * We should NOT have both ctxt->state and ctxt->states 10556 */ 10557 if ((ctxt->state != NULL) && (ctxt->states != NULL)) { 10558 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10559 ctxt->state = NULL; 10560 } 10561 10562 if ((ctxt->states == NULL) || (ctxt->states->nbState == 1)) { 10563 if (ctxt->states != NULL) { 10564 ctxt->state = ctxt->states->tabState[0]; 10565 xmlRelaxNGFreeStates(ctxt, ctxt->states); 10566 ctxt->states = NULL; 10567 } 10568 ret = xmlRelaxNGValidateState(ctxt, define); 10569 if ((ctxt->state != NULL) && (ctxt->states != NULL)) { 10570 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10571 ctxt->state = NULL; 10572 } 10573 if ((ctxt->states != NULL) && (ctxt->states->nbState == 1)) { 10574 ctxt->state = ctxt->states->tabState[0]; 10575 xmlRelaxNGFreeStates(ctxt, ctxt->states); 10576 ctxt->states = NULL; 10577 } 10578 return (ret); 10579 } 10580 10581 states = ctxt->states; 10582 ctxt->states = NULL; 10583 res = NULL; 10584 j = 0; 10585 oldflags = ctxt->flags; 10586 ctxt->flags |= FLAGS_IGNORABLE; 10587 for (i = 0; i < states->nbState; i++) { 10588 ctxt->state = states->tabState[i]; 10589 ctxt->states = NULL; 10590 ret = xmlRelaxNGValidateState(ctxt, define); 10591 /* 10592 * We should NOT have both ctxt->state and ctxt->states 10593 */ 10594 if ((ctxt->state != NULL) && (ctxt->states != NULL)) { 10595 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10596 ctxt->state = NULL; 10597 } 10598 if (ret == 0) { 10599 if (ctxt->states == NULL) { 10600 if (res != NULL) { 10601 /* add the state to the container */ 10602 xmlRelaxNGAddStates(ctxt, res, ctxt->state); 10603 ctxt->state = NULL; 10604 } else { 10605 /* add the state directly in states */ 10606 states->tabState[j++] = ctxt->state; 10607 ctxt->state = NULL; 10608 } 10609 } else { 10610 if (res == NULL) { 10611 /* make it the new container and copy other results */ 10612 res = ctxt->states; 10613 ctxt->states = NULL; 10614 for (k = 0; k < j; k++) 10615 xmlRelaxNGAddStates(ctxt, res, 10616 states->tabState[k]); 10617 } else { 10618 /* add all the new results to res and reff the container */ 10619 for (k = 0; k < ctxt->states->nbState; k++) 10620 xmlRelaxNGAddStates(ctxt, res, 10621 ctxt->states->tabState[k]); 10622 xmlRelaxNGFreeStates(ctxt, ctxt->states); 10623 ctxt->states = NULL; 10624 } 10625 } 10626 } else { 10627 if (ctxt->state != NULL) { 10628 xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10629 ctxt->state = NULL; 10630 } else if (ctxt->states != NULL) { 10631 for (k = 0; k < ctxt->states->nbState; k++) 10632 xmlRelaxNGFreeValidState(ctxt, 10633 ctxt->states->tabState[k]); 10634 xmlRelaxNGFreeStates(ctxt, ctxt->states); 10635 ctxt->states = NULL; 10636 } 10637 } 10638 } 10639 ctxt->flags = oldflags; 10640 if (res != NULL) { 10641 xmlRelaxNGFreeStates(ctxt, states); 10642 ctxt->states = res; 10643 ret = 0; 10644 } else if (j > 1) { 10645 states->nbState = j; 10646 ctxt->states = states; 10647 ret = 0; 10648 } else if (j == 1) { 10649 ctxt->state = states->tabState[0]; 10650 xmlRelaxNGFreeStates(ctxt, states); 10651 ret = 0; 10652 } else { 10653 ret = -1; 10654 xmlRelaxNGFreeStates(ctxt, states); 10655 if (ctxt->states != NULL) { 10656 xmlRelaxNGFreeStates(ctxt, ctxt->states); 10657 ctxt->states = NULL; 10658 } 10659 } 10660 if ((ctxt->state != NULL) && (ctxt->states != NULL)) { 10661 TODO xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10662 ctxt->state = NULL; 10663 } 10664 return (ret); 10665 } 10666 10676 static int 10677 xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) 10678 { 10679 int ret; 10680 xmlRelaxNGPtr schema; 10681 xmlRelaxNGGrammarPtr grammar; 10682 xmlRelaxNGValidStatePtr state; 10683 xmlNodePtr node; 10684 10685 if ((ctxt == NULL) || (ctxt->schema == NULL) || (doc == NULL)) 10686 return (-1); 10687 10688 ctxt->errNo = XML_RELAXNG_OK; 10689 schema = ctxt->schema; 10690 grammar = schema->topgrammar; 10691 if (grammar == NULL) { 10692 VALID_ERR(XML_RELAXNG_ERR_NOGRAMMAR); 10693 return (-1); 10694 } 10695 state = xmlRelaxNGNewValidState(ctxt, NULL); 10696 ctxt->state = state; 10697 ret = xmlRelaxNGValidateDefinition(ctxt, grammar->start); 10698 if ((ctxt->state != NULL) && (state->seq != NULL)) { 10699 state = ctxt->state; 10700 node = state->seq; 10701 node = xmlRelaxNGSkipIgnored(ctxt, node); 10702 if (node != NULL) { 10703 if (ret != -1) { 10704 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA); 10705 ret = -1; 10706 } 10707 } 10708 } else if (ctxt->states != NULL) { 10709 int i; 10710 int tmp = -1; 10711 10712 for (i = 0; i < ctxt->states->nbState; i++) { 10713 state = ctxt->states->tabState[i]; 10714 node = state->seq; 10715 node = xmlRelaxNGSkipIgnored(ctxt, node); 10716 if (node == NULL) 10717 tmp = 0; 10718 xmlRelaxNGFreeValidState(ctxt, state); 10719 } 10720 if (tmp == -1) { 10721 if (ret != -1) { 10722 VALID_ERR(XML_RELAXNG_ERR_EXTRADATA); 10723 ret = -1; 10724 } 10725 } 10726 } 10727 if (ctxt->state != NULL) { 10728 xmlRelaxNGFreeValidState(ctxt, ctxt->state); 10729 ctxt->state = NULL; 10730 } 10731 if (ret != 0) 10732 xmlRelaxNGDumpValidError(ctxt); 10733 #ifdef DEBUG 10734 else if (ctxt->errNr != 0) { 10735 ctxt->error(ctxt->userData, 10736 "%d Extra error messages left on stack !\n", 10737 ctxt->errNr); 10738 xmlRelaxNGDumpValidError(ctxt); 10739 } 10740 #endif 10741 #ifdef LIBXML_VALID_ENABLED 10742 if (ctxt->idref == 1) { 10743 xmlValidCtxt vctxt; 10744 10745 memset(&vctxt, 0, sizeof(xmlValidCtxt)); 10746 vctxt.valid = 1; 10747 vctxt.error = ctxt->error; 10748 vctxt.warning = ctxt->warning; 10749 vctxt.userData = ctxt->userData; 10750 10751 if (xmlValidateDocumentFinal(&vctxt, doc) != 1) 10752 ret = -1; 10753 } 10754 #endif /* LIBXML_VALID_ENABLED */ 10755 if ((ret == 0) && (ctxt->errNo != XML_RELAXNG_OK)) 10756 ret = -1; 10757 10758 return (ret); 10759 } 10760 10774 static void 10775 xmlRelaxNGCleanPSVI(xmlNodePtr node) { 10776 xmlNodePtr cur; 10777 10778 if ((node == NULL) || 10779 ((node->type != XML_ELEMENT_NODE) && 10780 (node->type != XML_DOCUMENT_NODE) && 10781 (node->type != XML_HTML_DOCUMENT_NODE))) 10782 return; 10783 if (node->type == XML_ELEMENT_NODE) 10784 node->psvi = NULL; 10785 10786 cur = node->children; 10787 while (cur != NULL) { 10788 if (cur->type == XML_ELEMENT_NODE) { 10789 cur->psvi = NULL; 10790 if (cur->children != NULL) { 10791 cur = cur->children; 10792 continue; 10793 } 10794 } 10795 if (cur->next != NULL) { 10796 cur = cur->next; 10797 continue; 10798 } 10799 do { 10800 cur = cur->parent; 10801 if (cur == NULL) 10802 break; 10803 if (cur == node) { 10804 cur = NULL; 10805 break; 10806 } 10807 if (cur->next != NULL) { 10808 cur = cur->next; 10809 break; 10810 } 10811 } while (cur != NULL); 10812 } 10813 return; 10814 } 10815 /************************************************************************ 10816 * * 10817 * Validation interfaces * 10818 * * 10819 ************************************************************************/ 10820 10829 xmlRelaxNGValidCtxtPtr 10830 xmlRelaxNGNewValidCtxt(xmlRelaxNGPtr schema) 10831 { 10832 xmlRelaxNGValidCtxtPtr ret; 10833 10834 ret = (xmlRelaxNGValidCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGValidCtxt)); 10835 if (ret == NULL) { 10836 xmlRngVErrMemory(NULL, "building context\n"); 10837 return (NULL); 10838 } 10839 memset(ret, 0, sizeof(xmlRelaxNGValidCtxt)); 10840 ret->schema = schema; 10841 ret->error = xmlGenericError; 10842 ret->userData = xmlGenericErrorContext; 10843 ret->errNr = 0; 10844 ret->errMax = 0; 10845 ret->err = NULL; 10846 ret->errTab = NULL; 10847 if (schema != NULL) 10848 ret->idref = schema->idref; 10849 ret->states = NULL; 10850 ret->freeState = NULL; 10851 ret->freeStates = NULL; 10852 ret->errNo = XML_RELAXNG_OK; 10853 return (ret); 10854 } 10855 10862 void 10863 xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxtPtr ctxt) 10864 { 10865 int k; 10866 10867 if (ctxt == NULL) 10868 return; 10869 if (ctxt->states != NULL) 10870 xmlRelaxNGFreeStates(NULL, ctxt->states); 10871 if (ctxt->freeState != NULL) { 10872 for (k = 0; k < ctxt->freeState->nbState; k++) { 10873 xmlRelaxNGFreeValidState(NULL, ctxt->freeState->tabState[k]); 10874 } 10875 xmlRelaxNGFreeStates(NULL, ctxt->freeState); 10876 } 10877 if (ctxt->freeStates != NULL) { 10878 for (k = 0; k < ctxt->freeStatesNr; k++) { 10879 xmlRelaxNGFreeStates(NULL, ctxt->freeStates[k]); 10880 } 10881 xmlFree(ctxt->freeStates); 10882 } 10883 if (ctxt->errTab != NULL) 10884 xmlFree(ctxt->errTab); 10885 if (ctxt->elemTab != NULL) { 10886 xmlRegExecCtxtPtr exec; 10887 10888 exec = xmlRelaxNGElemPop(ctxt); 10889 while (exec != NULL) { 10890 xmlRegFreeExecCtxt(exec); 10891 exec = xmlRelaxNGElemPop(ctxt); 10892 } 10893 xmlFree(ctxt->elemTab); 10894 } 10895 xmlFree(ctxt); 10896 } 10897 10907 void 10908 xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, 10909 xmlRelaxNGValidityErrorFunc err, 10910 xmlRelaxNGValidityWarningFunc warn, void *ctx) 10911 { 10912 if (ctxt == NULL) 10913 return; 10914 ctxt->error = err; 10915 ctxt->warning = warn; 10916 ctxt->userData = ctx; 10917 ctxt->serror = NULL; 10918 } 10919 10928 void 10929 xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt, 10930 xmlStructuredErrorFunc serror, void *ctx) 10931 { 10932 if (ctxt == NULL) 10933 return; 10934 ctxt->serror = serror; 10935 ctxt->error = NULL; 10936 ctxt->warning = NULL; 10937 ctxt->userData = ctx; 10938 } 10939 10951 int 10952 xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, 10953 xmlRelaxNGValidityErrorFunc * err, 10954 xmlRelaxNGValidityWarningFunc * warn, void **ctx) 10955 { 10956 if (ctxt == NULL) 10957 return (-1); 10958 if (err != NULL) 10959 *err = ctxt->error; 10960 if (warn != NULL) 10961 *warn = ctxt->warning; 10962 if (ctx != NULL) 10963 *ctx = ctxt->userData; 10964 return (0); 10965 } 10966 10977 int 10978 xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) 10979 { 10980 int ret; 10981 10982 if ((ctxt == NULL) || (doc == NULL)) 10983 return (-1); 10984 10985 ctxt->doc = doc; 10986 10987 ret = xmlRelaxNGValidateDocument(ctxt, doc); 10988 /* 10989 * Remove all left PSVI 10990 */ 10991 xmlRelaxNGCleanPSVI((xmlNodePtr) doc); 10992 10993 /* 10994 * TODO: build error codes 10995 */ 10996 if (ret == -1) 10997 return (1); 10998 return (ret); 10999 } 11000 11001 #define bottom_relaxng 11002 #include "elfgcchack.h" 11003 #endif /* LIBXML_SCHEMAS_ENABLED */ Generated on Thu May 24 2012 04:34:58 for ReactOS by
1.7.6.1
|