* any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
*/
+#ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
+/**
+ * xmlXPathCmpNodesExt:
+ * @node1: the first node
+ * @node2: the second node
+ *
+ * Compare two nodes w.r.t document order.
+ * This one is optimized for handling of non-element nodes.
+ *
+ * Returns -2 in case of error 1 if first point < second point, 0 if
+ * it's the same node, -1 otherwise
+ */
+static int
+xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
+ int depth1, depth2;
+ int misc = 0, precedence1 = 0, precedence2 = 0;
+ xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
+ xmlNodePtr cur, root;
+ long l1, l2;
+
+ if ((node1 == NULL) || (node2 == NULL))
+ return(-2);
+
+ if (node1 == node2)
+ return(0);
+
+ /*
+ * a couple of optimizations which will avoid computations in most cases
+ */
+ switch (node1->type) {
+ case XML_ELEMENT_NODE:
+ if (node2->type == XML_ELEMENT_NODE) {
+ if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice here? */
+ (0 > (long) node2->content) &&
+ (node1->doc == node2->doc))
+ {
+ l1 = -((long) node1->content);
+ l2 = -((long) node2->content);
+ if (l1 < l2)
+ return(1);
+ if (l1 > l2)
+ return(-1);
+ } else
+ goto turtle_comparison;
+ }
+ break;
+ case XML_ATTRIBUTE_NODE:
+ precedence1 = 1; /* element is owner */
+ miscNode1 = node1;
+ node1 = node1->parent;
+ misc = 1;
+ break;
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_COMMENT_NODE:
+ case XML_PI_NODE: {
+ miscNode1 = node1;
+ /*
+ * Find nearest element node.
+ */
+ if (node1->prev != NULL) {
+ do {
+ node1 = node1->prev;
+ if (node1->type == XML_ELEMENT_NODE) {
+ precedence1 = 3; /* element in prev-sibl axis */
+ break;
+ }
+ if (node1->prev == NULL) {
+ precedence1 = 2; /* element is parent */
+ /*
+ * URGENT TODO: Are there any cases, where the
+ * parent of such a node is not an element node?
+ */
+ node1 = node1->parent;
+ break;
+ }
+ } while (1);
+ } else {
+ precedence1 = 2; /* element is parent */
+ node1 = node1->parent;
+ }
+ if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
+ (0 <= (long) node1->content)) {
+ /*
+ * Fallback for whatever case.
+ */
+ node1 = miscNode1;
+ precedence1 = 0;
+ } else
+ misc = 1;
+ }
+ break;
+ case XML_NAMESPACE_DECL:
+ /*
+ * TODO: why do we return 1 for namespace nodes?
+ */
+ return(1);
+ default:
+ break;
+ }
+ switch (node2->type) {
+ case XML_ELEMENT_NODE:
+ break;
+ case XML_ATTRIBUTE_NODE:
+ precedence2 = 1; /* element is owner */
+ miscNode2 = node2;
+ node2 = node2->parent;
+ misc = 1;
+ break;
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_COMMENT_NODE:
+ case XML_PI_NODE: {
+ miscNode2 = node2;
+ if (node2->prev != NULL) {
+ do {
+ node2 = node2->prev;
+ if (node2->type == XML_ELEMENT_NODE) {
+ precedence2 = 3; /* element in prev-sibl axis */
+ break;
+ }
+ if (node2->prev == NULL) {
+ precedence2 = 2; /* element is parent */
+ node2 = node2->parent;
+ break;
+ }
+ } while (1);
+ } else {
+ precedence2 = 2; /* element is parent */
+ node2 = node2->parent;
+ }
+ if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
+ (0 <= (long) node2->content))
+ {
+ node2 = miscNode2;
+ precedence2 = 0;
+ } else
+ misc = 1;
+ }
+ break;
+ case XML_NAMESPACE_DECL:
+ return(1);
+ default:
+ break;
+ }
+ if (misc) {
+ if (node1 == node2) {
+ if (precedence1 == precedence2) {
+ /*
+ * The ugly case; but normally there aren't many
+ * adjacent non-element nodes around.
+ */
+ cur = miscNode2->prev;
+ while (cur != NULL) {
+ if (cur == miscNode1)
+ return(1);
+ if (cur->type == XML_ELEMENT_NODE)
+ return(-1);
+ cur = cur->prev;
+ }
+ return (-1);
+ } else {
+ /*
+ * Evaluate based on higher precedence wrt to the element.
+ * TODO: This assumes attributes are sorted before content.
+ * Is this 100% correct?
+ */
+ if (precedence1 < precedence2)
+ return(1);
+ else
+ return(-1);
+ }
+ }
+ /*
+ * Special case: One of the helper-elements is contained by the other.
+ * <foo>
+ * <node2>
+ * <node1>Text-1(precedence1 == 2)</node1>
+ * </node2>
+ * Text-6(precedence2 == 3)
+ * </foo>
+ */
+ if ((precedence2 == 3) && (precedence1 > 1)) {
+ cur = node1->parent;
+ while (cur) {
+ if (cur == node2)
+ return(1);
+ cur = cur->parent;
+ }
+ }
+ if ((precedence1 == 3) && (precedence2 > 1)) {
+ cur = node2->parent;
+ while (cur) {
+ if (cur == node1)
+ return(-1);
+ cur = cur->parent;
+ }
+ }
+ }
+
+ /*
+ * Speedup using document order if availble.
+ */
+ if ((node1->type == XML_ELEMENT_NODE) &&
+ (node2->type == XML_ELEMENT_NODE) &&
+ (0 > (long) node1->content) &&
+ (0 > (long) node2->content) &&
+ (node1->doc == node2->doc)) {
+
+ l1 = -((long) node1->content);
+ l2 = -((long) node2->content);
+ if (l1 < l2)
+ return(1);
+ if (l1 > l2)
+ return(-1);
+ }
+
+turtle_comparison:
+
+ if (node1 == node2->prev)
+ return(1);
+ if (node1 == node2->next)
+ return(-1);
+ /*
+ * compute depth to root
+ */
+ for (depth2 = 0, cur = node2; cur->parent != NULL; cur = cur->parent) {
+ if (cur->parent == node1)
+ return(1);
+ depth2++;
+ }
+ root = cur;
+ for (depth1 = 0, cur = node1; cur->parent != NULL; cur = cur->parent) {
+ if (cur->parent == node2)
+ return(-1);
+ depth1++;
+ }
+ /*
+ * Distinct document (or distinct entities :-( ) case.
+ */
+ if (root != cur) {
+ return(-2);
+ }
+ /*
+ * get the nearest common ancestor.
+ */
+ while (depth1 > depth2) {
+ depth1--;
+ node1 = node1->parent;
+ }
+ while (depth2 > depth1) {
+ depth2--;
+ node2 = node2->parent;
+ }
+ while (node1->parent != node2->parent) {
+ node1 = node1->parent;
+ node2 = node2->parent;
+ /* should not happen but just in case ... */
+ if ((node1 == NULL) || (node2 == NULL))
+ return(-2);
+ }
+ /*
+ * Find who's first.
+ */
+ if (node1 == node2->prev)
+ return(1);
+ if (node1 == node2->next)
+ return(-1);
+ /*
+ * Speedup using document order if availble.
+ */
+ if ((node1->type == XML_ELEMENT_NODE) &&
+ (node2->type == XML_ELEMENT_NODE) &&
+ (0 > (long) node1->content) &&
+ (0 > (long) node2->content) &&
+ (node1->doc == node2->doc)) {
+
+ l1 = -((long) node1->content);
+ l2 = -((long) node2->content);
+ if (l1 < l2)
+ return(1);
+ if (l1 > l2)
+ return(-1);
+ }
+
+ for (cur = node1->next;cur != NULL;cur = cur->next)
+ if (cur == node2)
+ return(1);
+ return(-1); /* assume there is no sibling list corruption */
+}
+#endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */
+
/*
* Wrapper for the Timsort argorithm from timsort.h
*/
static
int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
#ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
- static int xmlXPathCmpNodesExt(xmlNodePtr, xmlNodePtr);
static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
{
int res = xmlXPathCmpNodesExt(x, y);
"Encoding error\n",
"Char out of XML range\n",
"Invalid or incomplete context\n",
- "Stack usage errror\n",
+ "Stack usage error\n",
"Forbidden variable\n",
"?? Unknown error ??\n" /* Must be last in the list! */
};
xmlChar buf[200];
xmlStrPrintf(buf, 200,
- BAD_CAST "Memory allocation failed : %s\n",
+ "Memory allocation failed : %s\n",
extra);
ctxt->lastError.message = (char *) xmlStrdup(buf);
} else {
xmlXPathStepOp *steps; /* ops for computation of this expression */
int last; /* index of last step in expression */
xmlChar *expr; /* the expression being computed */
- xmlDictPtr dict; /* the dictionnary to use if any */
+ xmlDictPtr dict; /* the dictionary to use if any */
#ifdef DEBUG_EVAL_COUNTS
int nb;
xmlChar *string;
fraction_place, number);
}
+ /* Remove leading spaces sometimes inserted by snprintf */
+ while (work[0] == ' ') {
+ for (ptr = &work[0];(ptr[0] = ptr[1]);ptr++);
+ size--;
+ }
+
/* Remove fractional trailing zeroes */
after_fraction = work + size;
ptr = after_fraction;
* it's the same node, -1 otherwise
*/
int
-xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
- int depth1, depth2;
- int attr1 = 0, attr2 = 0;
- xmlNodePtr attrNode1 = NULL, attrNode2 = NULL;
- xmlNodePtr cur, root;
-
- if ((node1 == NULL) || (node2 == NULL))
- return(-2);
- /*
- * a couple of optimizations which will avoid computations in most cases
- */
- if (node1 == node2) /* trivial case */
- return(0);
- if (node1->type == XML_ATTRIBUTE_NODE) {
- attr1 = 1;
- attrNode1 = node1;
- node1 = node1->parent;
- }
- if (node2->type == XML_ATTRIBUTE_NODE) {
- attr2 = 1;
- attrNode2 = node2;
- node2 = node2->parent;
- }
- if (node1 == node2) {
- if (attr1 == attr2) {
- /* not required, but we keep attributes in order */
- if (attr1 != 0) {
- cur = attrNode2->prev;
- while (cur != NULL) {
- if (cur == attrNode1)
- return (1);
- cur = cur->prev;
- }
- return (-1);
- }
- return(0);
- }
- if (attr2 == 1)
- return(1);
- return(-1);
- }
- if ((node1->type == XML_NAMESPACE_DECL) ||
- (node2->type == XML_NAMESPACE_DECL))
- return(1);
- if (node1 == node2->prev)
- return(1);
- if (node1 == node2->next)
- return(-1);
-
- /*
- * Speedup using document order if availble.
- */
- if ((node1->type == XML_ELEMENT_NODE) &&
- (node2->type == XML_ELEMENT_NODE) &&
- (0 > (long) node1->content) &&
- (0 > (long) node2->content) &&
- (node1->doc == node2->doc)) {
- long l1, l2;
-
- l1 = -((long) node1->content);
- l2 = -((long) node2->content);
- if (l1 < l2)
- return(1);
- if (l1 > l2)
- return(-1);
- }
-
- /*
- * compute depth to root
- */
- for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
- if (cur == node1)
- return(1);
- depth2++;
- }
- root = cur;
- for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
- if (cur == node2)
- return(-1);
- depth1++;
- }
- /*
- * Distinct document (or distinct entities :-( ) case.
- */
- if (root != cur) {
- return(-2);
- }
- /*
- * get the nearest common ancestor.
- */
- while (depth1 > depth2) {
- depth1--;
- node1 = node1->parent;
- }
- while (depth2 > depth1) {
- depth2--;
- node2 = node2->parent;
- }
- while (node1->parent != node2->parent) {
- node1 = node1->parent;
- node2 = node2->parent;
- /* should not happen but just in case ... */
- if ((node1 == NULL) || (node2 == NULL))
- return(-2);
- }
- /*
- * Find who's first.
- */
- if (node1 == node2->prev)
- return(1);
- if (node1 == node2->next)
- return(-1);
- /*
- * Speedup using document order if availble.
- */
- if ((node1->type == XML_ELEMENT_NODE) &&
- (node2->type == XML_ELEMENT_NODE) &&
- (0 > (long) node1->content) &&
- (0 > (long) node2->content) &&
- (node1->doc == node2->doc)) {
- long l1, l2;
-
- l1 = -((long) node1->content);
- l2 = -((long) node2->content);
- if (l1 < l2)
- return(1);
- if (l1 > l2)
- return(-1);
- }
-
- for (cur = node1->next;cur != NULL;cur = cur->next)
- if (cur == node2)
- return(1);
- return(-1); /* assume there is no sibling list corruption */
-}
-
-#ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
-/**
- * xmlXPathCmpNodesExt:
- * @node1: the first node
- * @node2: the second node
- *
- * Compare two nodes w.r.t document order.
- * This one is optimized for handling of non-element nodes.
- *
- * Returns -2 in case of error 1 if first point < second point, 0 if
- * it's the same node, -1 otherwise
- */
-static int
-xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
+xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
int depth1, depth2;
- int misc = 0, precedence1 = 0, precedence2 = 0;
- xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
+ int attr1 = 0, attr2 = 0;
+ xmlNodePtr attrNode1 = NULL, attrNode2 = NULL;
xmlNodePtr cur, root;
- long l1, l2;
if ((node1 == NULL) || (node2 == NULL))
return(-2);
-
- if (node1 == node2)
- return(0);
-
/*
* a couple of optimizations which will avoid computations in most cases
*/
- switch (node1->type) {
- case XML_ELEMENT_NODE:
- if (node2->type == XML_ELEMENT_NODE) {
- if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice here? */
- (0 > (long) node2->content) &&
- (node1->doc == node2->doc))
- {
- l1 = -((long) node1->content);
- l2 = -((long) node2->content);
- if (l1 < l2)
- return(1);
- if (l1 > l2)
- return(-1);
- } else
- goto turtle_comparison;
- }
- break;
- case XML_ATTRIBUTE_NODE:
- precedence1 = 1; /* element is owner */
- miscNode1 = node1;
- node1 = node1->parent;
- misc = 1;
- break;
- case XML_TEXT_NODE:
- case XML_CDATA_SECTION_NODE:
- case XML_COMMENT_NODE:
- case XML_PI_NODE: {
- miscNode1 = node1;
- /*
- * Find nearest element node.
- */
- if (node1->prev != NULL) {
- do {
- node1 = node1->prev;
- if (node1->type == XML_ELEMENT_NODE) {
- precedence1 = 3; /* element in prev-sibl axis */
- break;
- }
- if (node1->prev == NULL) {
- precedence1 = 2; /* element is parent */
- /*
- * URGENT TODO: Are there any cases, where the
- * parent of such a node is not an element node?
- */
- node1 = node1->parent;
- break;
- }
- } while (1);
- } else {
- precedence1 = 2; /* element is parent */
- node1 = node1->parent;
- }
- if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
- (0 <= (long) node1->content)) {
- /*
- * Fallback for whatever case.
- */
- node1 = miscNode1;
- precedence1 = 0;
- } else
- misc = 1;
- }
- break;
- case XML_NAMESPACE_DECL:
- /*
- * TODO: why do we return 1 for namespace nodes?
- */
- return(1);
- default:
- break;
+ if (node1 == node2) /* trivial case */
+ return(0);
+ if (node1->type == XML_ATTRIBUTE_NODE) {
+ attr1 = 1;
+ attrNode1 = node1;
+ node1 = node1->parent;
}
- switch (node2->type) {
- case XML_ELEMENT_NODE:
- break;
- case XML_ATTRIBUTE_NODE:
- precedence2 = 1; /* element is owner */
- miscNode2 = node2;
- node2 = node2->parent;
- misc = 1;
- break;
- case XML_TEXT_NODE:
- case XML_CDATA_SECTION_NODE:
- case XML_COMMENT_NODE:
- case XML_PI_NODE: {
- miscNode2 = node2;
- if (node2->prev != NULL) {
- do {
- node2 = node2->prev;
- if (node2->type == XML_ELEMENT_NODE) {
- precedence2 = 3; /* element in prev-sibl axis */
- break;
- }
- if (node2->prev == NULL) {
- precedence2 = 2; /* element is parent */
- node2 = node2->parent;
- break;
- }
- } while (1);
- } else {
- precedence2 = 2; /* element is parent */
- node2 = node2->parent;
- }
- if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
- (0 <= (long) node1->content))
- {
- node2 = miscNode2;
- precedence2 = 0;
- } else
- misc = 1;
- }
- break;
- case XML_NAMESPACE_DECL:
- return(1);
- default:
- break;
+ if (node2->type == XML_ATTRIBUTE_NODE) {
+ attr2 = 1;
+ attrNode2 = node2;
+ node2 = node2->parent;
}
- if (misc) {
- if (node1 == node2) {
- if (precedence1 == precedence2) {
- /*
- * The ugly case; but normally there aren't many
- * adjacent non-element nodes around.
- */
- cur = miscNode2->prev;
+ if (node1 == node2) {
+ if (attr1 == attr2) {
+ /* not required, but we keep attributes in order */
+ if (attr1 != 0) {
+ cur = attrNode2->prev;
while (cur != NULL) {
- if (cur == miscNode1)
- return(1);
- if (cur->type == XML_ELEMENT_NODE)
- return(-1);
+ if (cur == attrNode1)
+ return (1);
cur = cur->prev;
}
return (-1);
- } else {
- /*
- * Evaluate based on higher precedence wrt to the element.
- * TODO: This assumes attributes are sorted before content.
- * Is this 100% correct?
- */
- if (precedence1 < precedence2)
- return(1);
- else
- return(-1);
- }
- }
- /*
- * Special case: One of the helper-elements is contained by the other.
- * <foo>
- * <node2>
- * <node1>Text-1(precedence1 == 2)</node1>
- * </node2>
- * Text-6(precedence2 == 3)
- * </foo>
- */
- if ((precedence2 == 3) && (precedence1 > 1)) {
- cur = node1->parent;
- while (cur) {
- if (cur == node2)
- return(1);
- cur = cur->parent;
- }
- }
- if ((precedence1 == 3) && (precedence2 > 1)) {
- cur = node2->parent;
- while (cur) {
- if (cur == node1)
- return(-1);
- cur = cur->parent;
}
+ return(0);
}
+ if (attr2 == 1)
+ return(1);
+ return(-1);
}
+ if ((node1->type == XML_NAMESPACE_DECL) ||
+ (node2->type == XML_NAMESPACE_DECL))
+ return(1);
+ if (node1 == node2->prev)
+ return(1);
+ if (node1 == node2->next)
+ return(-1);
/*
* Speedup using document order if availble.
(0 > (long) node1->content) &&
(0 > (long) node2->content) &&
(node1->doc == node2->doc)) {
+ long l1, l2;
l1 = -((long) node1->content);
l2 = -((long) node2->content);
return(-1);
}
-turtle_comparison:
-
- if (node1 == node2->prev)
- return(1);
- if (node1 == node2->next)
- return(-1);
/*
* compute depth to root
*/
(0 > (long) node1->content) &&
(0 > (long) node2->content) &&
(node1->doc == node2->doc)) {
+ long l1, l2;
l1 = -((long) node1->content);
l2 = -((long) node2->content);
return(1);
return(-1); /* assume there is no sibling list corruption */
}
-#endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */
/**
* xmlXPathNodeSetSort:
/* @@ with_ns to check whether namespace nodes should be looked at @@ */
/*
- * prevent duplcates
+ * prevent duplicates
*/
for (i = 0;i < cur->nodeNr;i++)
if (cur->nodeTab[i] == val) return(0);
xmlNodePtr
xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
- if (cur == NULL) {
- if (ctxt->context->node == NULL)
- return(NULL);
- if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
- (ctxt->context->node->type == XML_NAMESPACE_DECL))
- return(NULL);
+ if (cur == NULL)
return(ctxt->context->node);
- }
+
+ if (ctxt->context->node == NULL)
+ return(NULL);
+ if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
+ (ctxt->context->node->type == XML_NAMESPACE_DECL))
+ return(NULL);
return(xmlXPathNextDescendant(ctxt, cur));
}
xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
- if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) {
+ if (cur == NULL) {
if (ctxt->context->tmpNsList != NULL)
xmlFree(ctxt->context->tmpNsList);
ctxt->context->tmpNsList =
(c == '[') || (c == ']') || (c == '@') || /* accelerators */
(c == '*') || /* accelerators */
(!IS_LETTER(c) && (c != '_') &&
- ((qualified) && (c != ':')))) {
+ ((!qualified) || (c != ':')))) {
return(NULL);
}
STRANGE
goto error;
case NODE_TEST_TYPE:
- /*
- * TODO: Don't we need to use
- * xmlXPathNodeSetAddNs() for namespace nodes here?
- * Surprisingly, some c14n tests fail, if we do this.
- */
if (type == NODE_TYPE_NODE) {
switch (cur->type) {
case XML_DOCUMENT_NODE:
case XML_COMMENT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_TEXT_NODE:
- case XML_NAMESPACE_DECL:
XP_TEST_HIT
break;
+ case XML_NAMESPACE_DECL: {
+ if (axis == AXIS_NAMESPACE) {
+ XP_TEST_HIT_NS
+ } else {
+ hasNsNodes = 1;
+ XP_TEST_HIT
+ }
+ break;
+ }
default:
break;
}
if (axis == AXIS_ATTRIBUTE) {
if (cur->type == XML_ATTRIBUTE_NODE)
{
- XP_TEST_HIT
+ if (prefix == NULL)
+ {
+ XP_TEST_HIT
+ } else if ((cur->ns != NULL) &&
+ (xmlStrEqual(URI, cur->ns->href)))
+ {
+ XP_TEST_HIT
+ }
}
} else if (axis == AXIS_NAMESPACE) {
if (cur->type == XML_NAMESPACE_DECL)
* Reset the context node.
*/
xpctxt->node = oldContextNode;
+ /*
+ * When traversing the namespace axis in "toBool" mode, it's
+ * possible that tmpNsList wasn't freed.
+ */
+ if (xpctxt->tmpNsList != NULL) {
+ xmlFree(xpctxt->tmpNsList);
+ xpctxt->tmpNsList = NULL;
+ }
#ifdef DEBUG_STEP
xmlGenericError(xmlGenericErrorContext,
int frame;
frame = xmlXPathSetFrame(ctxt);
- if (op->ch1 != -1)
+ if (op->ch1 != -1) {
total +=
xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- if (ctxt->valueNr < op->value) {
+ if (ctxt->error != XPATH_EXPRESSION_OK) {
+ xmlXPathPopFrame(ctxt, frame);
+ return (total);
+ }
+ }
+ if (ctxt->valueNr < ctxt->valueFrame + op->value) {
xmlGenericError(xmlGenericErrorContext,
"xmlXPathCompOpEval: parameter error\n");
ctxt->error = XPATH_INVALID_OPERAND;
bak = ctxt->context->node;
pp = ctxt->context->proximityPosition;
cs = ctxt->context->contextSize;
- if (op->ch1 != -1)
+ if (op->ch1 != -1) {
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- ctxt->context->contextSize = cs;
- ctxt->context->proximityPosition = pp;
- ctxt->context->node = bak;
- ctxt->context->doc = bakd;
- CHECK_ERROR0;
+ ctxt->context->contextSize = cs;
+ ctxt->context->proximityPosition = pp;
+ ctxt->context->node = bak;
+ ctxt->context->doc = bakd;
+ CHECK_ERROR0;
+ }
if (op->ch2 != -1) {
total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
- ctxt->context->doc = bakd;
- ctxt->context->node = bak;
+ ctxt->context->contextSize = cs;
+ ctxt->context->proximityPosition = pp;
+ ctxt->context->node = bak;
+ ctxt->context->doc = bakd;
CHECK_ERROR0;
}
return (total);
* internal representation.
*/
- if ((op->ch1 != -1) &&
- (op->op == XPATH_OP_COLLECT /* 11 */))
+ if ((op->op == XPATH_OP_COLLECT /* 11 */) &&
+ (op->ch1 != -1) &&
+ (op->ch2 == -1 /* no predicate */))
{
xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
}
}
+ /* OP_VALUE has invalid ch1. */
+ if (op->op == XPATH_OP_VALUE)
+ return;
+
/* Recurse */
if (op->ch1 != -1)
xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]);