X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gettext-tools%2Fgnulib-lib%2Flibxml%2Frelaxng.c;h=5779e7fc5f49e2b99c60f7ceb141ef1b79536825;hb=refs%2Fchanges%2F82%2F71082%2F1;hp=16527cc5928edb868d5fbc674ac47dc07916f090;hpb=90a3363ce7c017439e9953fd5e832fbef8db0dd5;p=platform%2Fupstream%2Fgettext.git diff --git a/gettext-tools/gnulib-lib/libxml/relaxng.c b/gettext-tools/gnulib-lib/libxml/relaxng.c index 16527cc..5779e7f 100644 --- a/gettext-tools/gnulib-lib/libxml/relaxng.c +++ b/gettext-tools/gnulib-lib/libxml/relaxng.c @@ -39,9 +39,10 @@ static const xmlChar *xmlRelaxNGNs = (const xmlChar *) "http://relaxng.org/ns/structure/1.0"; -#define IS_RELAXNG(node, type) \ +#define IS_RELAXNG(node, typ) \ ((node != NULL) && (node->ns != NULL) && \ - (xmlStrEqual(node->name, (const xmlChar *) type)) && \ + (node->type == XML_ELEMENT_NODE) && \ + (xmlStrEqual(node->name, (const xmlChar *) typ)) && \ (xmlStrEqual(node->ns->href, xmlRelaxNGNs))) @@ -60,7 +61,7 @@ static const xmlChar *xmlRelaxNGNs = (const xmlChar *) #define DEBUG_LIST 1 -#define DEBUG_INCLUDE 1 +#define DEBUG_INCLUDE 1 #define DEBUG_ERROR 1 @@ -71,7 +72,7 @@ static const xmlChar *xmlRelaxNGNs = (const xmlChar *) #define MAX_ERROR 5 -#define TODO \ +#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__); @@ -149,6 +150,7 @@ typedef enum { #define IS_PROCESSED (1 << 5) #define IS_COMPILABLE (1 << 6) #define IS_NOT_COMPILABLE (1 << 7) +#define IS_EXTERNAL_REF (1 << 8) struct _xmlRelaxNGDefine { xmlRelaxNGType type; /* the type of definition */ @@ -414,12 +416,13 @@ struct _xmlRelaxNGDocument { xmlDocPtr doc; /* the associated XML document */ xmlRelaxNGDefinePtr content; /* the definitions */ xmlRelaxNGPtr schema; /* the schema */ + int externalRef; /* 1 if an external ref */ }; /************************************************************************ * * - * Some factorized error routines * + * Some factorized error routines * * * ************************************************************************/ @@ -562,9 +565,9 @@ xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error, } /************************************************************************ - * * - * Preliminary type checking interfaces * - * * + * * + * Preliminary type checking interfaces * + * * ************************************************************************/ /** @@ -652,9 +655,9 @@ struct _xmlRelaxNGTypeLibrary { }; /************************************************************************ - * * - * Allocation functions * - * * + * * + * Allocation functions * + * * ************************************************************************/ static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar); static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define); @@ -1006,7 +1009,7 @@ xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size) xmlRelaxNGStatesPtr ret; if ((ctxt != NULL) && - (ctxt->freeState != NULL) && (ctxt->freeStatesNr > 0)) { + (ctxt->freeStates != NULL) && (ctxt->freeStatesNr > 0)) { ctxt->freeStatesNr--; ret = ctxt->freeStates[ctxt->freeStatesNr]; ret->nbState = 0; @@ -1092,7 +1095,7 @@ xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt, { int i; - if (state == NULL) { + if (state == NULL || states == NULL) { return (-1); } if (states->nbState >= states->maxState) { @@ -1395,9 +1398,9 @@ xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt, } /************************************************************************ - * * - * Semi internal functions * - * * + * * + * Semi internal functions * + * * ************************************************************************/ /** @@ -1427,9 +1430,9 @@ xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags) } /************************************************************************ - * * - * Document functions * - * * + * * + * Document functions * + * * ************************************************************************/ static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc); @@ -1559,8 +1562,8 @@ xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt, href = xmlGetProp(tmp, BAD_CAST "href"); #endif if (xmlRelaxNGRemoveRedefine(ctxt, href, - inc->doc->children-> - children, name) == 1) { + xmlDocGetRootElement(inc->doc)->children, + name) == 1) { found = 1; } #ifdef DEBUG_INCLUDE @@ -1970,6 +1973,7 @@ xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt, ret->doc = doc; ret->href = xmlStrdup(URL); ret->next = ctxt->documents; + ret->externalRef = 1; ctxt->documents = ret; /* @@ -2004,9 +2008,9 @@ xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt, } /************************************************************************ - * * - * Error functions * - * * + * * + * Error functions * + * * ************************************************************************/ #define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0); @@ -2357,7 +2361,7 @@ xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt, * generate the error directly */ if (((ctxt->flags & FLAGS_IGNORABLE) == 0) || - (ctxt->flags & FLAGS_NEGATIVE)) { + (ctxt->flags & FLAGS_NEGATIVE)) { xmlNodePtr node, seq; /* @@ -2372,6 +2376,9 @@ xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt, } else { node = seq = NULL; } + if ((node == NULL) && (seq == NULL)) { + node = ctxt->pnode; + } xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2); } /* @@ -2384,9 +2391,9 @@ xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt, /************************************************************************ - * * - * Type library hooks * - * * + * * + * Type library hooks * + * * ************************************************************************/ static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar * str); @@ -2588,13 +2595,10 @@ xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED, } ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2); if (ret != 0) { - if ((comp1 == NULL) && (res1 != NULL)) + if (res1 != (xmlSchemaValPtr) comp1) xmlSchemaFreeValue(res1); return (-1); } - if (res1 == NULL) { - return (-1); - } ret = xmlSchemaCompareValues(res1, res2); if (res1 != (xmlSchemaValPtr) comp1) xmlSchemaFreeValue(res1); @@ -2841,14 +2845,18 @@ xmlRelaxNGCleanupTypes(void) } /************************************************************************ - * * - * Compiling element content into regexp * - * * + * * + * Compiling element content into regexp * + * * * Sometime the element content can be compiled into a pure regexp, * * This allows a faster execution and streamability at that level * - * * + * * ************************************************************************/ +/* from automata.c but not exported */ +void xmlAutomataSetFlags(xmlAutomataPtr am, int flags); + + static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def); @@ -3032,14 +3040,25 @@ xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) ctxt->am = xmlNewAutomata(); if (ctxt->am == NULL) return (-1); + + /* + * assume identical strings but not same pointer are different + * atoms, needed for non-determinism detection + * That way if 2 elements with the same name are in a choice + * branch the automata is found non-deterministic and + * we fallback to the normal validation which does the right + * thing of exploring both choices. + */ + xmlAutomataSetFlags(ctxt->am, 1); + ctxt->state = xmlAutomataGetInitState(ctxt->am); while (list != NULL) { xmlRelaxNGCompile(ctxt, list); list = list->next; } xmlAutomataSetFinalState(ctxt->am, ctxt->state); - def->contModel = xmlAutomataCompile(ctxt->am); - xmlRegexpIsDeterminist(def->contModel); + if (xmlAutomataIsDeterminist(ctxt->am)) + def->contModel = xmlAutomataCompile(ctxt->am); xmlFreeAutomata(ctxt->am); ctxt->state = oldstate; @@ -3063,6 +3082,7 @@ xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) ctxt->am = xmlNewAutomata(); if (ctxt->am == NULL) return (-1); + xmlAutomataSetFlags(ctxt->am, 1); ctxt->state = xmlAutomataGetInitState(ctxt->am); while (list != NULL) { xmlRelaxNGCompile(ctxt, list); @@ -3071,6 +3091,11 @@ xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) xmlAutomataSetFinalState(ctxt->am, ctxt->state); def->contModel = xmlAutomataCompile(ctxt->am); if (!xmlRegexpIsDeterminist(def->contModel)) { +#ifdef DEBUG_COMPILE + xmlGenericError(xmlGenericErrorContext, + "Content model not determinist %s\n", + def->name); +#endif /* * we can only use the automata if it is determinist */ @@ -3098,7 +3123,11 @@ xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) case XML_RELAXNG_OPTIONAL:{ xmlAutomataStatePtr oldstate = ctxt->state; - xmlRelaxNGCompile(ctxt, def->content); + list = def->content; + while (list != NULL) { + xmlRelaxNGCompile(ctxt, list); + list = list->next; + } xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state); break; } @@ -3294,9 +3323,9 @@ xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def) } /************************************************************************ - * * - * Parsing functions * - * * + * * + * Parsing functions * + * * ************************************************************************/ static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr @@ -3440,6 +3469,9 @@ xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED, { xmlChar *ret, *escape; + if (node == NULL) + return(NULL); + if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) { ret = xmlGetProp(node, BAD_CAST "datatypeLibrary"); if (ret != NULL) { @@ -3787,7 +3819,11 @@ xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1, return (0); return (1); } else if (def1->type == XML_RELAXNG_EXCEPT) { - TODO ret = 0; + ret = xmlRelaxNGCompareNameClasses(def1->content, def2); + if (ret == 0) + ret = 1; + else if (ret == 1) + ret = 0; } else { TODO ret = 0; } @@ -4616,6 +4652,72 @@ xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) } /** + * xmlRelaxNGParseImportRef: + * @payload: the parser context + * @data: the current grammar + * @name: the reference name + * + * Import import one references into the current grammar + */ +static void +xmlRelaxNGParseImportRef(void *payload, void *data, xmlChar *name) { + xmlRelaxNGParserCtxtPtr ctxt = (xmlRelaxNGParserCtxtPtr) data; + xmlRelaxNGDefinePtr def = (xmlRelaxNGDefinePtr) payload; + int tmp; + + def->dflags |= IS_EXTERNAL_REF; + + tmp = xmlHashAddEntry(ctxt->grammar->refs, name, def); + if (tmp < 0) { + xmlRelaxNGDefinePtr prev; + + prev = (xmlRelaxNGDefinePtr) + xmlHashLookup(ctxt->grammar->refs, def->name); + if (prev == NULL) { + if (def->name != NULL) { + xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED, + "Error refs definitions '%s'\n", + def->name, NULL); + } else { + xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED, + "Error refs definitions\n", + NULL, NULL); + } + } else { + def->nextHash = prev->nextHash; + prev->nextHash = def; + } + } +} + +/** + * xmlRelaxNGParseImportRefs: + * @ctxt: the parser context + * @grammar: the sub grammar + * + * Import references from the subgrammar into the current grammar + * + * Returns 0 in case of success, -1 in case of failure + */ +static int +xmlRelaxNGParseImportRefs(xmlRelaxNGParserCtxtPtr ctxt, + xmlRelaxNGGrammarPtr grammar) { + if ((ctxt == NULL) || (grammar == NULL) || (ctxt->grammar == NULL)) + return(-1); + if (grammar->refs == NULL) + return(0); + if (ctxt->grammar->refs == NULL) + ctxt->grammar->refs = xmlHashCreate(10); + if (ctxt->grammar->refs == NULL) { + xmlRngPErr(ctxt, NULL, XML_RNGP_REF_CREATE_FAILED, + "Could not create references hash\n", NULL, NULL); + return(-1); + } + xmlHashScan(grammar->refs, xmlRelaxNGParseImportRef, ctxt); + return(0); +} + +/** * xmlRelaxNGProcessExternalRef: * @ctxt: the parser context * @node: the externlRef node @@ -4683,6 +4785,8 @@ xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) if ((docu->schema != NULL) && (docu->schema->topgrammar != NULL)) { docu->content = docu->schema->topgrammar->start; + if (docu->schema->topgrammar->refs) + xmlRelaxNGParseImportRefs(ctxt, docu->schema->topgrammar); } /* @@ -5267,7 +5371,8 @@ xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, } else { xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT, "expecting name, anyName, nsName or choice : got %s\n", - node->name, NULL); + (node == NULL ? (const xmlChar *) "nothing" : node->name), + NULL); return (NULL); } if (ret != def) { @@ -5569,6 +5674,12 @@ xmlRelaxNGCheckReference(xmlRelaxNGDefinePtr ref, xmlRelaxNGGrammarPtr grammar; xmlRelaxNGDefinePtr def, cur; + /* + * Those rules don't apply to imported ref from xmlRelaxNGParseImportRef + */ + if (ref->dflags & IS_EXTERNAL_REF) + return; + grammar = ctxt->grammar; if (grammar == NULL) { xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR, @@ -6133,7 +6244,7 @@ xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr cur, int flags, xmlRelaxNGType ptype) { - int nflags = flags; + int nflags; xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY; while (cur != NULL) { @@ -6157,6 +6268,16 @@ xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt, "Found forbidden pattern data/except//ref\n", NULL, NULL); } + if (cur->content == NULL) { + if (cur->type == XML_RELAXNG_PARENTREF) + xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF, + "Internal found no define for parent refs\n", + NULL, NULL); + else + xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_NO_DEF, + "Internal found no define for ref %s\n", + (cur->name ? cur->name: BAD_CAST "null"), NULL); + } if (cur->depth > -4) { cur->depth = -4; ret = xmlRelaxNGCheckRules(ctxt, cur->content, @@ -6408,6 +6529,10 @@ xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt, if (ptype == XML_RELAXNG_GROUP) { val = xmlRelaxNGGroupContentType(val, ret); } else if (ptype == XML_RELAXNG_INTERLEAVE) { + /* + * TODO: scan complain that tmp is never used, seems on purpose + * need double-checking + */ tmp = xmlRelaxNGGroupContentType(val, ret); if (tmp != XML_RELAXNG_CONTENT_ERROR) tmp = xmlRelaxNGMaxContentType(val, ret); @@ -6479,7 +6604,7 @@ xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes) } /* - * Apply 4.17 mergingd rules to defines and starts + * Apply 4.17 merging rules to defines and starts */ xmlRelaxNGCombineStart(ctxt, ret); if (ret->defs != NULL) { @@ -6495,6 +6620,9 @@ xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes) ctxt); } + + /* @@@@ */ + ctxt->grammar = old; return (ret); } @@ -6528,12 +6656,17 @@ xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) ctxt->define = NULL; if (IS_RELAXNG(node, "grammar")) { schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children); + if (schema->topgrammar == NULL) { + xmlRelaxNGFree(schema); + return (NULL); + } } else { xmlRelaxNGGrammarPtr tmp, ret; schema->topgrammar = ret = xmlRelaxNGNewGrammar(ctxt); if (schema->topgrammar == NULL) { - return (schema); + xmlRelaxNGFree(schema); + return (NULL); } /* * Link the new grammar in the tree @@ -6579,9 +6712,9 @@ xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) } /************************************************************************ - * * - * Reading RelaxNGs * - * * + * * + * Reading RelaxNGs * + * * ************************************************************************/ /** @@ -7190,7 +7323,7 @@ xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root) } } /* - * Thisd is not an else since "include" is transformed + * This is not an else since "include" is transformed * into a div */ if (xmlStrEqual(cur->name, BAD_CAST "div")) { @@ -7219,13 +7352,13 @@ xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root) if (ns != NULL) xmlFree(ns); /* - * Since we are about to delete cur, if it's nsDef is non-NULL we + * Since we are about to delete cur, if its nsDef is non-NULL we * need to preserve it (it contains the ns definitions for the * children we just moved). We'll just stick it on to the end * of cur->parent's list, since it's never going to be re-serialized * (bug 143738). */ - if (cur->nsDef != NULL) { + if ((cur->nsDef != NULL) && (cur->parent != NULL)) { xmlNsPtr parDef = (xmlNsPtr)&cur->parent->nsDef; while (parDef->next != NULL) parDef = parDef->next; @@ -7243,7 +7376,8 @@ xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root) else if ((cur->type == XML_TEXT_NODE) || (cur->type == XML_CDATA_SECTION_NODE)) { if (IS_BLANK_NODE(cur)) { - if (cur->parent->type == XML_ELEMENT_NODE) { + if ((cur->parent != NULL) && + (cur->parent->type == XML_ELEMENT_NODE)) { if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value")) && (!xmlStrEqual @@ -7395,7 +7529,7 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt) xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n", (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL); - + xmlFreeDoc(ctxt->document); ctxt->document = NULL; return (NULL); @@ -7537,9 +7671,9 @@ xmlRelaxNGSetParserStructuredErrors(xmlRelaxNGParserCtxtPtr ctxt, #ifdef LIBXML_OUTPUT_ENABLED /************************************************************************ - * * - * Dump back a compiled form * - * * + * * + * Dump back a compiled form * + * * ************************************************************************/ static void xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define); @@ -7680,7 +7814,7 @@ xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define) * xmlRelaxNGDumpGrammar: * @output: the file output * @grammar: a grammar structure - * @top: is this a top grammar + * @top: is this a top grammar * * Dump a RelaxNG structure back */ @@ -7773,9 +7907,9 @@ xmlRelaxNGDumpTree(FILE * output, xmlRelaxNGPtr schema) #endif /* LIBXML_OUTPUT_ENABLED */ /************************************************************************ - * * - * Validation of compiled content * - * * + * * + * Validation of compiled content * + * * ************************************************************************/ static int xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define); @@ -7918,9 +8052,9 @@ xmlRelaxNGValidateCompiledContent(xmlRelaxNGValidCtxtPtr ctxt, } /************************************************************************ - * * - * Progressive validation of when possible * - * * + * * + * Progressive validation of when possible * + * * ************************************************************************/ static int xmlRelaxNGValidateAttributeList(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr defines); @@ -8220,7 +8354,7 @@ xmlRelaxNGValidatePushElement(xmlRelaxNGValidCtxtPtr ctxt, * xmlRelaxNGValidatePushCData: * @ctxt: the RelaxNG validation context * @data: some character data read - * @len: the lenght of the data + * @len: the length of the data * * check the CData parsed for validation in the current stack * @@ -8343,7 +8477,7 @@ xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt, ret = -1; else ret = 1; - xmlRelaxNGFreeValidState(ctxt, state); + xmlRelaxNGFreeValidState(ctxt, ctxt->state); ctxt->state = NULL; #ifdef DEBUG_PROGRESSIVE if (ret < 0) @@ -8354,9 +8488,9 @@ xmlRelaxNGValidateFullElement(xmlRelaxNGValidCtxtPtr ctxt, } /************************************************************************ - * * - * Generic interpreted validation implementation * - * * + * * + * Generic interpreted validation implementation * + * * ************************************************************************/ static int xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGDefinePtr define); @@ -8758,6 +8892,11 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, case XML_RELAXNG_ZEROORMORE:{ xmlChar *cur, *temp; + if ((ctxt->state->value == NULL) || + (*ctxt->state->value == 0)) { + ret = 0; + break; + } oldflags = ctxt->flags; ctxt->flags |= FLAGS_IGNORABLE; cur = ctxt->state->value; @@ -8779,6 +8918,30 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGPopErrors(ctxt, 0); break; } + case XML_RELAXNG_OPTIONAL:{ + xmlChar *temp; + + if ((ctxt->state->value == NULL) || + (*ctxt->state->value == 0)) { + ret = 0; + break; + } + oldflags = ctxt->flags; + ctxt->flags |= FLAGS_IGNORABLE; + temp = ctxt->state->value; + ret = xmlRelaxNGValidateValue(ctxt, define->content); + ctxt->flags = oldflags; + if (ret != 0) { + ctxt->state->value = temp; + if (ctxt->errNr > 0) + xmlRelaxNGPopErrors(ctxt, 0); + ret = 0; + break; + } + if (ctxt->errNr > 0) + xmlRelaxNGPopErrors(ctxt, 0); + break; + } case XML_RELAXNG_EXCEPT:{ xmlRelaxNGDefinePtr list; @@ -8812,7 +8975,12 @@ xmlRelaxNGValidateValue(xmlRelaxNGValidCtxtPtr ctxt, } case XML_RELAXNG_REF: case XML_RELAXNG_PARENTREF: - ret = xmlRelaxNGValidateValue(ctxt, define->content); + if (define->content == NULL) { + VALID_ERR(XML_RELAXNG_ERR_NODEFINE); + ret = -1; + } else { + ret = xmlRelaxNGValidateValue(ctxt, define->content); + } break; default: TODO ret = -1; @@ -8889,6 +9057,19 @@ xmlRelaxNGAttributeMatch(xmlRelaxNGValidCtxtPtr ctxt, return (ret); list = list->next; } + } else if (define->type == XML_RELAXNG_CHOICE) { + xmlRelaxNGDefinePtr list; + + list = define->nameClass; + while (list != NULL) { + ret = xmlRelaxNGAttributeMatch(ctxt, list, prop); + if (ret == 1) + return (1); + if (ret < 0) + return (ret); + list = list->next; + } + return (0); } else { TODO} return (1); @@ -9248,6 +9429,10 @@ xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt, oldstate = ctxt->state; for (i = 0; i < nbgroups; i++) { ctxt->state = xmlRelaxNGCopyValidState(ctxt, oldstate); + if (ctxt->state == NULL) { + ret = -1; + break; + } group = partitions->groups[i]; if (lasts[i] != NULL) { last = lasts[i]->next; @@ -9319,6 +9504,7 @@ xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt, oldstate = ctxt->states->tabState[ctxt->states->nbState - 1]; ctxt->states->tabState[ctxt->states->nbState - 1] = NULL; + ctxt->states->nbState--; } } for (j = 0; j < ctxt->states->nbState ; j++) { @@ -9327,7 +9513,12 @@ xmlRelaxNGValidateInterleave(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGFreeStates(ctxt, ctxt->states); ctxt->states = NULL; if (found == 0) { - VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name); + if (cur == NULL) { + VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, + (const xmlChar *) "noname"); + } else { + VALID_ERR2(XML_RELAXNG_ERR_INTEREXTRA, cur->name); + } ret = -1; ctxt->state = oldstate; goto done; @@ -9672,7 +9863,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, ctxt->depth++; switch (define->type) { case XML_RELAXNG_EMPTY: - node = xmlRelaxNGSkipIgnored(ctxt, node); + xmlRelaxNGSkipIgnored(ctxt, node); ret = 0; break; case XML_RELAXNG_NOT_ALLOWED: @@ -9828,7 +10019,8 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, ret = -1; } else { state = ctxt->state; - ctxt->state->seq = nseq; + if (ctxt->state != NULL) + ctxt->state->seq = nseq; if (ret == 0) ret = xmlRelaxNGValidateElementEnd(ctxt, 1); xmlRelaxNGFreeValidState(ctxt, state); @@ -9873,8 +10065,8 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, } for (i = 0; i < ctxt->states->nbState; i++) { xmlRelaxNGFreeValidState(ctxt, - ctxt->states-> - tabState[i]); + ctxt->states->tabState[i]); + ctxt->states->tabState[i] = NULL; } xmlRelaxNGFreeStates(ctxt, ctxt->states); ctxt->flags = oldflags; @@ -9996,11 +10188,8 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, } else { for (j = 0; j < ctxt->states->nbState; j++) { xmlRelaxNGAddStates(ctxt, res, - xmlRelaxNGCopyValidState(ctxt, - ctxt-> - states-> - tabState - [j])); + xmlRelaxNGCopyValidState(ctxt, + ctxt->states->tabState[j])); } } oldflags = ctxt->flags; @@ -10029,10 +10218,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, j++) { tmp = xmlRelaxNGAddStates(ctxt, res, - ctxt-> - states-> - tabState - [j]); + ctxt->states->tabState[j]); if (tmp == 1) progress = 1; } @@ -10066,9 +10252,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, } else if (ctxt->states != NULL) { for (j = 0; j < ctxt->states->nbState; j++) { tmp = xmlRelaxNGAddStates(ctxt, res, - ctxt-> - states-> - tabState[j]); + ctxt->states->tabState[j]); if (tmp == 1) progress = 1; } @@ -10106,8 +10290,7 @@ xmlRelaxNGValidateState(xmlRelaxNGValidCtxtPtr ctxt, for (i = base; i < res->nbState; i++) xmlRelaxNGAddStates(ctxt, states, xmlRelaxNGCopyValidState - (ctxt, - res->tabState[i])); + (ctxt, res->tabState[i])); ctxt->states = states; } } @@ -10629,10 +10812,64 @@ xmlRelaxNGValidateDocument(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) return (ret); } +/** + * xmlRelaxNGCleanPSVI: + * @node: an input element or document + * + * Call this routine to speed up XPath computation on static documents. + * This stamps all the element nodes with the document order + * Like for line information, the order is kept in the element->content + * field, the value stored is actually - the node number (starting at -1) + * to be able to differentiate from line numbers. + * + * Returns the number of elements found in the document or -1 in case + * of error. + */ +static void +xmlRelaxNGCleanPSVI(xmlNodePtr node) { + xmlNodePtr cur; + + if ((node == NULL) || + ((node->type != XML_ELEMENT_NODE) && + (node->type != XML_DOCUMENT_NODE) && + (node->type != XML_HTML_DOCUMENT_NODE))) + return; + if (node->type == XML_ELEMENT_NODE) + node->psvi = NULL; + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + cur->psvi = NULL; + if (cur->children != NULL) { + cur = cur->children; + continue; + } + } + if (cur->next != NULL) { + cur = cur->next; + continue; + } + do { + cur = cur->parent; + if (cur == NULL) + break; + if (cur == node) { + cur = NULL; + break; + } + if (cur->next != NULL) { + cur = cur->next; + break; + } + } while (cur != NULL); + } + return; +} /************************************************************************ - * * - * Validation interfaces * - * * + * * + * Validation interfaces * + * * ************************************************************************/ /** @@ -10803,6 +11040,11 @@ xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc) ret = xmlRelaxNGValidateDocument(ctxt, doc); /* + * Remove all left PSVI + */ + xmlRelaxNGCleanPSVI((xmlNodePtr) doc); + + /* * TODO: build error codes */ if (ret == -1)