Index: third_party/libxslt/libxslt/pattern.c |
=================================================================== |
--- third_party/libxslt/libxslt/pattern.c (revision 39981) |
+++ third_party/libxslt/libxslt/pattern.c (working copy) |
@@ -46,7 +46,6 @@ |
XSLT_OP_END=0, |
XSLT_OP_ROOT, |
XSLT_OP_ELEM, |
- XSLT_OP_CHILD, |
XSLT_OP_ATTR, |
XSLT_OP_PARENT, |
XSLT_OP_ANCESTOR, |
@@ -61,6 +60,11 @@ |
XSLT_OP_PREDICATE |
} xsltOp; |
+typedef enum { |
+ AXIS_CHILD=1, |
+ AXIS_ATTRIBUTE |
+} xsltAxis; |
+ |
typedef struct _xsltStepState xsltStepState; |
typedef xsltStepState *xsltStepStatePtr; |
struct _xsltStepState { |
@@ -697,32 +701,6 @@ |
goto rollback; |
} |
continue; |
- case XSLT_OP_CHILD: { |
- xmlNodePtr lst; |
- |
- if ((node->type != XML_ELEMENT_NODE) && |
- (node->type != XML_DOCUMENT_NODE) && |
-#ifdef LIBXML_DOCB_ENABLED |
- (node->type != XML_DOCB_DOCUMENT_NODE) && |
-#endif |
- (node->type != XML_HTML_DOCUMENT_NODE)) |
- goto rollback; |
- |
- lst = node->children; |
- |
- if (step->value != NULL) { |
- while (lst != NULL) { |
- if ((lst->type == XML_ELEMENT_NODE) && |
- (step->value[0] == lst->name[0]) && |
- (xmlStrEqual(step->value, lst->name))) |
- break; |
- lst = lst->next; |
- } |
- if (lst != NULL) |
- continue; |
- } |
- goto rollback; |
- } |
case XSLT_OP_ATTR: |
if (node->type != XML_ATTRIBUTE_NODE) |
goto rollback; |
@@ -984,9 +962,11 @@ |
/* |
* recompute the index |
*/ |
- xmlNodePtr siblings = node->parent->children; |
xmlNodePtr parent = node->parent; |
+ xmlNodePtr siblings = NULL; |
+ if (parent) siblings = parent->children; |
+ |
while (siblings != NULL) { |
if (siblings->type == XML_ELEMENT_NODE) { |
if (siblings == node) { |
@@ -1088,9 +1068,11 @@ |
/* |
* recompute the index |
*/ |
- xmlNodePtr siblings = node->parent->children; |
xmlNodePtr parent = node->parent; |
+ xmlNodePtr siblings = NULL; |
+ if (parent) siblings = parent->children; |
+ |
while (siblings != NULL) { |
if (siblings->type == XML_ELEMENT_NODE) { |
len++; |
@@ -1326,46 +1308,6 @@ |
} |
/** |
- * xsltScanName: |
- * @ctxt: the XPath Parser context |
- * |
- * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | |
- * CombiningChar | Extender |
- * |
- * [5] Name ::= (Letter | '_' | ':') (NameChar)* |
- * |
- * [6] Names ::= Name (S Name)* |
- * |
- * Returns the Name parsed or NULL |
- */ |
- |
-static xmlChar * |
-xsltScanName(xsltParserContextPtr ctxt) { |
- const xmlChar *q, *cur; |
- xmlChar *ret = NULL; |
- int val, len; |
- |
- SKIP_BLANKS; |
- |
- cur = q = CUR_PTR; |
- val = xmlStringCurrentChar(NULL, cur, &len); |
- if (!IS_LETTER(val) && (val != '_') && (val != ':')) |
- return(NULL); |
- |
- while ((IS_LETTER(val)) || (IS_DIGIT(val)) || |
- (val == '.') || (val == '-') || |
- (val == '_') || |
- (IS_COMBINING(val)) || |
- (IS_EXTENDER(val))) { |
- cur += len; |
- val = xmlStringCurrentChar(NULL, cur, &len); |
- } |
- ret = xmlStrndup(q, cur - q); |
- CUR_PTR = cur; |
- return(ret); |
-} |
- |
-/** |
* xsltScanNCName: |
* @ctxt: the XPath Parser context |
* |
@@ -1400,30 +1342,6 @@ |
return(ret); |
} |
-/** |
- * xsltScanQName: |
- * @ctxt: the XPath Parser context |
- * @prefix: the place to store the prefix |
- * |
- * Parse a qualified name |
- * |
- * Returns the Name parsed or NULL |
- */ |
- |
-static xmlChar * |
-xsltScanQName(xsltParserContextPtr ctxt, xmlChar **prefix) { |
- xmlChar *ret = NULL; |
- |
- *prefix = NULL; |
- ret = xsltScanNCName(ctxt); |
- if (CUR == ':') { |
- *prefix = ret; |
- NEXT; |
- ret = xsltScanNCName(ctxt); |
- } |
- return(ret); |
-} |
- |
/* |
* xsltCompileIdKeyPattern: |
* @ctxt: the compilation context |
@@ -1443,7 +1361,7 @@ |
*/ |
static void |
xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, |
- int aid, int novar) { |
+ int aid, int novar, xsltAxis axis) { |
xmlChar *lit = NULL; |
xmlChar *lit2 = NULL; |
@@ -1454,6 +1372,12 @@ |
return; |
} |
if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) { |
+ if (axis != 0) { |
+ xsltTransformError(NULL, NULL, NULL, |
+ "xsltCompileIdKeyPattern : NodeTest expected\n"); |
+ ctxt->error = 1; |
+ return; |
+ } |
NEXT; |
SKIP_BLANKS; |
lit = xsltScanLiteral(ctxt); |
@@ -1469,6 +1393,12 @@ |
NEXT; |
PUSH(XSLT_OP_ID, lit, NULL, novar); |
} else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) { |
+ if (axis != 0) { |
+ xsltTransformError(NULL, NULL, NULL, |
+ "xsltCompileIdKeyPattern : NodeTest expected\n"); |
+ ctxt->error = 1; |
+ return; |
+ } |
NEXT; |
SKIP_BLANKS; |
lit = xsltScanLiteral(ctxt); |
@@ -1545,7 +1475,12 @@ |
return; |
} |
NEXT; |
- PUSH(XSLT_OP_NODE, NULL, NULL, novar); |
+ if (axis == AXIS_ATTRIBUTE) { |
+ PUSH(XSLT_OP_ATTR, NULL, NULL, novar); |
+ } |
+ else { |
+ PUSH(XSLT_OP_NODE, NULL, NULL, novar); |
+ } |
} else if (aid) { |
xsltTransformError(NULL, NULL, NULL, |
"xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n"); |
@@ -1590,51 +1525,25 @@ |
const xmlChar *URI = NULL; |
xmlChar *URL = NULL; |
int level; |
+ xsltAxis axis = 0; |
SKIP_BLANKS; |
if ((token == NULL) && (CUR == '@')) { |
- xmlChar *prefix = NULL; |
- |
NEXT; |
- if (CUR == '*') { |
- NEXT; |
- PUSH(XSLT_OP_ATTR, NULL, NULL, novar); |
- goto parse_predicate; |
- } |
- token = xsltScanQName(ctxt, &prefix); |
- if (prefix != NULL) { |
- xmlNsPtr ns; |
- |
- ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix); |
- if (ns == NULL) { |
- xsltTransformError(NULL, NULL, NULL, |
- "xsltCompileStepPattern : no namespace bound to prefix %s\n", |
- prefix); |
- } else { |
- URL = xmlStrdup(ns->href); |
- } |
- xmlFree(prefix); |
- } |
- if (token == NULL) { |
- if (CUR == '*') { |
- NEXT; |
- PUSH(XSLT_OP_ATTR, NULL, URL, novar); |
- return; |
- } |
- xsltTransformError(NULL, NULL, NULL, |
- "xsltCompileStepPattern : Name expected\n"); |
- ctxt->error = 1; |
- goto error; |
- } |
- PUSH(XSLT_OP_ATTR, token, URL, novar); |
- goto parse_predicate; |
+ axis = AXIS_ATTRIBUTE; |
} |
+parse_node_test: |
if (token == NULL) |
- token = xsltScanName(ctxt); |
+ token = xsltScanNCName(ctxt); |
if (token == NULL) { |
if (CUR == '*') { |
NEXT; |
- PUSH(XSLT_OP_ALL, token, NULL, novar); |
+ if (axis == AXIS_ATTRIBUTE) { |
+ PUSH(XSLT_OP_ATTR, NULL, NULL, novar); |
+ } |
+ else { |
+ PUSH(XSLT_OP_ALL, NULL, NULL, novar); |
+ } |
goto parse_predicate; |
} else { |
xsltTransformError(NULL, NULL, NULL, |
@@ -1647,7 +1556,7 @@ |
SKIP_BLANKS; |
if (CUR == '(') { |
- xsltCompileIdKeyPattern(ctxt, token, 0, novar); |
+ xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis); |
if (ctxt->error) |
goto error; |
} else if (CUR == ':') { |
@@ -1659,12 +1568,13 @@ |
/* |
* This is a namespace match |
*/ |
- token = xsltScanName(ctxt); |
+ token = xsltScanNCName(ctxt); |
ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix); |
if (ns == NULL) { |
xsltTransformError(NULL, NULL, NULL, |
"xsltCompileStepPattern : no namespace bound to prefix %s\n", |
prefix); |
+ xmlFree(prefix); |
ctxt->error = 1; |
goto error; |
} else { |
@@ -1674,7 +1584,12 @@ |
if (token == NULL) { |
if (CUR == '*') { |
NEXT; |
- PUSH(XSLT_OP_NS, URL, NULL, novar); |
+ if (axis == AXIS_ATTRIBUTE) { |
+ PUSH(XSLT_OP_ATTR, NULL, URL, novar); |
+ } |
+ else { |
+ PUSH(XSLT_OP_NS, URL, NULL, novar); |
+ } |
} else { |
xsltTransformError(NULL, NULL, NULL, |
"xsltCompileStepPattern : Name expected\n"); |
@@ -1682,54 +1597,25 @@ |
goto error; |
} |
} else { |
- PUSH(XSLT_OP_ELEM, token, URL, novar); |
+ if (axis == AXIS_ATTRIBUTE) { |
+ PUSH(XSLT_OP_ATTR, token, URL, novar); |
+ } |
+ else { |
+ PUSH(XSLT_OP_ELEM, token, URL, novar); |
+ } |
} |
} else { |
+ if (axis != 0) { |
+ xsltTransformError(NULL, NULL, NULL, |
+ "xsltCompileStepPattern : NodeTest expected\n"); |
+ ctxt->error = 1; |
+ goto error; |
+ } |
NEXT; |
if (xmlStrEqual(token, (const xmlChar *) "child")) { |
- xmlFree(token); |
- token = xsltScanName(ctxt); |
- if (token == NULL) { |
- if (CUR == '*') { |
- NEXT; |
- PUSH(XSLT_OP_ALL, token, NULL, novar); |
- goto parse_predicate; |
- } else { |
- xsltTransformError(NULL, NULL, NULL, |
- "xsltCompileStepPattern : QName expected\n"); |
- ctxt->error = 1; |
- goto error; |
- } |
- } |
- URI = xsltGetQNameURI(ctxt->elem, &token); |
- if (token == NULL) { |
- ctxt->error = 1; |
- goto error; |
- } else { |
- name = xmlStrdup(token); |
- if (URI != NULL) |
- URL = xmlStrdup(URI); |
- } |
- PUSH(XSLT_OP_CHILD, name, URL, novar); |
+ axis = AXIS_CHILD; |
} else if (xmlStrEqual(token, (const xmlChar *) "attribute")) { |
- xmlFree(token); |
- token = xsltScanName(ctxt); |
- if (token == NULL) { |
- xsltTransformError(NULL, NULL, NULL, |
- "xsltCompileStepPattern : QName expected\n"); |
- ctxt->error = 1; |
- goto error; |
- } |
- URI = xsltGetQNameURI(ctxt->elem, &token); |
- if (token == NULL) { |
- ctxt->error = 1; |
- goto error; |
- } else { |
- name = xmlStrdup(token); |
- if (URI != NULL) |
- URL = xmlStrdup(URI); |
- } |
- PUSH(XSLT_OP_ATTR, name, URL, novar); |
+ axis = AXIS_ATTRIBUTE; |
} else { |
xsltTransformError(NULL, NULL, NULL, |
"xsltCompileStepPattern : 'child' or 'attribute' expected\n"); |
@@ -1737,10 +1623,10 @@ |
goto error; |
} |
xmlFree(token); |
+ SKIP_BLANKS; |
+ token = xsltScanNCName(ctxt); |
+ goto parse_node_test; |
} |
- } else if (CUR == '*') { |
- NEXT; |
- PUSH(XSLT_OP_ALL, token, NULL, novar); |
} else { |
URI = xsltGetQNameURI(ctxt->elem, &token); |
if (token == NULL) { |
@@ -1749,7 +1635,12 @@ |
} |
if (URI != NULL) |
URL = xmlStrdup(URI); |
- PUSH(XSLT_OP_ELEM, token, URL, novar); |
+ if (axis == AXIS_ATTRIBUTE) { |
+ PUSH(XSLT_OP_ATTR, token, URL, novar); |
+ } |
+ else { |
+ PUSH(XSLT_OP_ELEM, token, URL, novar); |
+ } |
} |
parse_predicate: |
SKIP_BLANKS; |
@@ -1886,7 +1777,7 @@ |
xsltCompileRelativePathPattern(ctxt, NULL, novar); |
} else { |
xmlChar *name; |
- name = xsltScanName(ctxt); |
+ name = xsltScanNCName(ctxt); |
if (name == NULL) { |
xsltTransformError(NULL, NULL, NULL, |
"xsltCompileLocationPathPattern : Name expected\n"); |
@@ -1895,7 +1786,7 @@ |
} |
SKIP_BLANKS; |
if ((CUR == '(') && !xmlXPathIsNodeType(name)) { |
- xsltCompileIdKeyPattern(ctxt, name, 1, novar); |
+ xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0); |
if ((CUR == '/') && (NXT(1) == '/')) { |
PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar); |
NEXT; |
@@ -2173,7 +2064,6 @@ |
else |
top = &(style->attrMatch); |
break; |
- case XSLT_OP_CHILD: |
case XSLT_OP_PARENT: |
case XSLT_OP_ANCESTOR: |
top = &(style->elemMatch); |