Skip to content
Snippets Groups Projects
Commit 71968b621cec authored by William M. Brack's avatar William M. Brack
Browse files

fixed problem in internal XPath compilation of patterns including

* libxslt/pattern.c: fixed problem in internal XPath compilation
  of patterns including variables, fixes #316861
parent c233c1b495f9
Branches
No related tags found
No related merge requests found
Thu Sep 22 21:51:22 HKT 2005 William Brack <wbrack@mmm.com.hk>
* libxslt/pattern.c: fixed problem in internal XPath compilation
of patterns including variables, fixes #316861
Wed Sep 14 14:30:03 CEST 2005 Daniel Veillard <daniel@veillard.com>
* libxslt/transform.c: removed a superfluous second sorting of
......
......@@ -268,6 +268,7 @@
* @op: an op
* @value: the first value
* @value2: the second value
* @novar: flag to set XML_XPATH_NOVAR
*
* Add an step to an XSLT Compiled Match
*
......@@ -275,7 +276,7 @@
*/
static int
xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp,
xsltOp op, xmlChar * value, xmlChar * value2)
xsltOp op, xmlChar * value, xmlChar * value2, int novar)
{
if (comp->nbStep >= 40) {
xsltTransformError(NULL, NULL, NULL,
......@@ -308,6 +309,7 @@
else
xctxt = xmlXPathNewContext(NULL);
#ifdef XML_XPATH_NOVAR
if (novar != 0)
xctxt->flags = XML_XPATH_NOVAR;
#endif
if (ctxt->style != NULL)
......@@ -317,6 +319,7 @@
if (comp->steps[comp->nbStep].comp == NULL) {
xsltTransformError(NULL, ctxt->style, ctxt->elem,
"Failed to compile predicate\n");
if (ctxt->style != NULL)
ctxt->style->errors++;
}
}
......@@ -1181,8 +1184,8 @@
#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
#define PUSH(op, val, val2) \
if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error;
#define PUSH(op, val, val2, novar) \
if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto error;
#define SWAP() \
xsltSwapTopCompMatch(ctxt->comp);
......@@ -1358,6 +1361,7 @@
* @ctxt: the compilation context
* @name: a preparsed name
* @aid: whether id/key are allowed there
* @novar: flag to prohibit xslt var
*
* Compile the XSLT LocationIdKeyPattern
* [3] IdKeyPattern ::= 'id' '(' Literal ')'
......@@ -1370,7 +1374,8 @@
* | 'processing-instruction' '(' Literal ')'
*/
static void
xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, int aid) {
xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
int aid, int novar) {
xmlChar *lit = NULL;
xmlChar *lit2 = NULL;
......@@ -1394,7 +1399,7 @@
return;
}
NEXT;
PUSH(XSLT_OP_ID, lit, NULL);
PUSH(XSLT_OP_ID, lit, NULL, novar);
} else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) {
NEXT;
SKIP_BLANKS;
......@@ -1422,7 +1427,7 @@
}
NEXT;
/* TODO: support namespace in keys */
PUSH(XSLT_OP_KEY, lit, lit2);
PUSH(XSLT_OP_KEY, lit, lit2, novar);
} else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {
NEXT;
SKIP_BLANKS;
......@@ -1439,7 +1444,7 @@
}
}
NEXT;
PUSH(XSLT_OP_PI, lit, NULL);
PUSH(XSLT_OP_PI, lit, NULL, novar);
} else if (xmlStrEqual(name, (const xmlChar *)"text")) {
NEXT;
SKIP_BLANKS;
......@@ -1450,7 +1455,7 @@
return;
}
NEXT;
PUSH(XSLT_OP_TEXT, NULL, NULL);
PUSH(XSLT_OP_TEXT, NULL, NULL, novar);
} else if (xmlStrEqual(name, (const xmlChar *)"comment")) {
NEXT;
SKIP_BLANKS;
......@@ -1461,7 +1466,7 @@
return;
}
NEXT;
PUSH(XSLT_OP_COMMENT, NULL, NULL);
PUSH(XSLT_OP_COMMENT, NULL, NULL, novar);
} else if (xmlStrEqual(name, (const xmlChar *)"node")) {
NEXT;
SKIP_BLANKS;
......@@ -1472,7 +1477,7 @@
return;
}
NEXT;
PUSH(XSLT_OP_NODE, NULL, NULL);
PUSH(XSLT_OP_NODE, NULL, NULL, novar);
} else if (aid) {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n");
......@@ -1493,6 +1498,7 @@
* xsltCompileStepPattern:
* @ctxt: the compilation context
* @token: a posible precompiled name
* @novar: flag to prohibit xslt variables from pattern
*
* Compile the XSLT StepPattern and generates a precompiled
* form suitable for fast matching.
......@@ -1511,7 +1517,7 @@
*/
static void
xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token) {
xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar) {
xmlChar *name = NULL;
const xmlChar *URI = NULL;
xmlChar *URL = NULL;
......@@ -1524,7 +1530,7 @@
NEXT;
if (CUR == '*') {
NEXT;
PUSH(XSLT_OP_ATTR, NULL, NULL);
PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
goto parse_predicate;
}
token = xsltScanQName(ctxt, &prefix);
......@@ -1544,7 +1550,7 @@
if (token == NULL) {
if (CUR == '*') {
NEXT;
PUSH(XSLT_OP_ATTR, NULL, URL);
PUSH(XSLT_OP_ATTR, NULL, URL, novar);
return;
}
xsltTransformError(NULL, NULL, NULL,
......@@ -1552,7 +1558,7 @@
ctxt->error = 1;
goto error;
}
PUSH(XSLT_OP_ATTR, token, URL);
PUSH(XSLT_OP_ATTR, token, URL, novar);
goto parse_predicate;
}
if (token == NULL)
......@@ -1560,7 +1566,7 @@
if (token == NULL) {
if (CUR == '*') {
NEXT;
PUSH(XSLT_OP_ALL, token, NULL);
PUSH(XSLT_OP_ALL, token, NULL, novar);
goto parse_predicate;
} else {
xsltTransformError(NULL, NULL, NULL,
......@@ -1573,7 +1579,7 @@
SKIP_BLANKS;
if (CUR == '(') {
xsltCompileIdKeyPattern(ctxt, token, 0);
xsltCompileIdKeyPattern(ctxt, token, 0, novar);
if (ctxt->error)
goto error;
} else if (CUR == ':') {
......@@ -1600,7 +1606,7 @@
if (token == NULL) {
if (CUR == '*') {
NEXT;
PUSH(XSLT_OP_NS, URL, NULL);
PUSH(XSLT_OP_NS, URL, NULL, novar);
} else {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileStepPattern : Name expected\n");
......@@ -1608,7 +1614,7 @@
goto error;
}
} else {
PUSH(XSLT_OP_ELEM, token, URL);
PUSH(XSLT_OP_ELEM, token, URL, novar);
}
} else {
NEXT;
......@@ -1618,7 +1624,7 @@
if (token == NULL) {
if (CUR == '*') {
NEXT;
PUSH(XSLT_OP_ALL, token, NULL);
PUSH(XSLT_OP_ALL, token, NULL, novar);
goto parse_predicate;
} else {
xsltTransformError(NULL, NULL, NULL,
......@@ -1636,7 +1642,7 @@
if (URI != NULL)
URL = xmlStrdup(URI);
}
PUSH(XSLT_OP_CHILD, name, URL);
PUSH(XSLT_OP_CHILD, name, URL, novar);
} else if (xmlStrEqual(token, (const xmlChar *) "attribute")) {
xmlFree(token);
token = xsltScanName(ctxt);
......@@ -1655,7 +1661,7 @@
if (URI != NULL)
URL = xmlStrdup(URI);
}
PUSH(XSLT_OP_ATTR, name, URL);
PUSH(XSLT_OP_ATTR, name, URL, novar);
} else {
xsltTransformError(NULL, NULL, NULL,
"xsltCompileStepPattern : 'child' or 'attribute' expected\n");
......@@ -1666,7 +1672,7 @@
}
} else if (CUR == '*') {
NEXT;
PUSH(XSLT_OP_ALL, token, NULL);
PUSH(XSLT_OP_ALL, token, NULL, novar);
} else {
URI = xsltGetQNameURI(ctxt->elem, &token);
if (token == NULL) {
......@@ -1675,7 +1681,7 @@
}
if (URI != NULL)
URL = xmlStrdup(URI);
PUSH(XSLT_OP_ELEM, token, URL);
PUSH(XSLT_OP_ELEM, token, URL, novar);
}
parse_predicate:
SKIP_BLANKS;
......@@ -1713,7 +1719,7 @@
return;
}
ret = xmlStrndup(q, CUR_PTR - q);
PUSH(XSLT_OP_PREDICATE, ret, NULL);
PUSH(XSLT_OP_PREDICATE, ret, NULL, novar);
/* push the predicate lower than local test */
SWAP();
NEXT;
......@@ -1731,6 +1737,7 @@
* xsltCompileRelativePathPattern:
* @comp: the compilation context
* @token: a posible precompiled name
* @novar: flag to prohibit xslt variables
*
* Compile the XSLT RelativePathPattern and generates a precompiled
* form suitable for fast matching.
......@@ -1740,10 +1747,10 @@
* | RelativePathPattern '//' StepPattern
*/
static void
xsltCompileRelativePathPattern(xsltParserContextPtr ctxt, xmlChar *token) {
xsltCompileStepPattern(ctxt, token);
xsltCompileRelativePathPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar) {
xsltCompileStepPattern(ctxt, token, novar);
if (ctxt->error)
goto error;
SKIP_BLANKS;
while ((CUR != 0) && (CUR != '|')) {
if ((CUR == '/') && (NXT(1) == '/')) {
......@@ -1745,9 +1752,9 @@
if (ctxt->error)
goto error;
SKIP_BLANKS;
while ((CUR != 0) && (CUR != '|')) {
if ((CUR == '/') && (NXT(1) == '/')) {
PUSH(XSLT_OP_ANCESTOR, NULL, NULL);
PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
NEXT;
NEXT;
SKIP_BLANKS;
......@@ -1751,5 +1758,5 @@
NEXT;
NEXT;
SKIP_BLANKS;
xsltCompileStepPattern(ctxt, NULL);
xsltCompileStepPattern(ctxt, NULL, novar);
} else if (CUR == '/') {
......@@ -1755,5 +1762,5 @@
} else if (CUR == '/') {
PUSH(XSLT_OP_PARENT, NULL, NULL);
PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
NEXT;
SKIP_BLANKS;
if ((CUR != 0) && (CUR != '|')) {
......@@ -1757,7 +1764,7 @@
NEXT;
SKIP_BLANKS;
if ((CUR != 0) && (CUR != '|')) {
xsltCompileRelativePathPattern(ctxt, NULL);
xsltCompileRelativePathPattern(ctxt, NULL, novar);
}
} else {
ctxt->error = 1;
......@@ -1773,6 +1780,7 @@
/**
* xsltCompileLocationPathPattern:
* @ctxt: the compilation context
* @novar: flag to prohibit xslt variables
*
* Compile the XSLT LocationPathPattern and generates a precompiled
* form suitable for fast matching.
......@@ -1782,7 +1790,7 @@
* | '//'? RelativePathPattern
*/
static void
xsltCompileLocationPathPattern(xsltParserContextPtr ctxt) {
xsltCompileLocationPathPattern(xsltParserContextPtr ctxt, int novar) {
SKIP_BLANKS;
if ((CUR == '/') && (NXT(1) == '/')) {
/*
......@@ -1792,10 +1800,10 @@
NEXT;
NEXT;
ctxt->comp->priority = 0.5; /* '//' means not 0 priority */
xsltCompileRelativePathPattern(ctxt, NULL);
xsltCompileRelativePathPattern(ctxt, NULL, novar);
} else if (CUR == '/') {
/*
* We need to find root as the parent
*/
NEXT;
SKIP_BLANKS;
......@@ -1796,8 +1804,8 @@
} else if (CUR == '/') {
/*
* We need to find root as the parent
*/
NEXT;
SKIP_BLANKS;
PUSH(XSLT_OP_ROOT, NULL, NULL);
PUSH(XSLT_OP_ROOT, NULL, NULL, novar);
if ((CUR != 0) && (CUR != '|')) {
......@@ -1803,5 +1811,5 @@
if ((CUR != 0) && (CUR != '|')) {
PUSH(XSLT_OP_PARENT, NULL, NULL);
xsltCompileRelativePathPattern(ctxt, NULL);
PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
xsltCompileRelativePathPattern(ctxt, NULL, novar);
}
} else if (CUR == '*') {
......@@ -1806,4 +1814,4 @@
}
} else if (CUR == '*') {
xsltCompileRelativePathPattern(ctxt, NULL);
xsltCompileRelativePathPattern(ctxt, NULL, novar);
} else if (CUR == '@') {
......@@ -1809,5 +1817,5 @@
} else if (CUR == '@') {
xsltCompileRelativePathPattern(ctxt, NULL);
xsltCompileRelativePathPattern(ctxt, NULL, novar);
} else {
xmlChar *name;
name = xsltScanName(ctxt);
......@@ -1819,5 +1827,5 @@
}
SKIP_BLANKS;
if ((CUR == '(') && !xmlXPathIsNodeType(name)) {
xsltCompileIdKeyPattern(ctxt, name, 1);
xsltCompileIdKeyPattern(ctxt, name, 1, novar);
if ((CUR == '/') && (NXT(1) == '/')) {
......@@ -1823,5 +1831,5 @@
if ((CUR == '/') && (NXT(1) == '/')) {
PUSH(XSLT_OP_ANCESTOR, NULL, NULL);
PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
NEXT;
NEXT;
SKIP_BLANKS;
......@@ -1825,5 +1833,5 @@
NEXT;
NEXT;
SKIP_BLANKS;
xsltCompileRelativePathPattern(ctxt, NULL);
xsltCompileRelativePathPattern(ctxt, NULL, novar);
} else if (CUR == '/') {
......@@ -1829,4 +1837,4 @@
} else if (CUR == '/') {
PUSH(XSLT_OP_PARENT, NULL, NULL);
PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
NEXT;
SKIP_BLANKS;
......@@ -1831,6 +1839,6 @@
NEXT;
SKIP_BLANKS;
xsltCompileRelativePathPattern(ctxt, NULL);
xsltCompileRelativePathPattern(ctxt, NULL, novar);
}
return;
}
......@@ -1834,10 +1842,10 @@
}
return;
}
xsltCompileRelativePathPattern(ctxt, name);
xsltCompileRelativePathPattern(ctxt, name, novar);
}
error:
return;
}
/**
......@@ -1838,12 +1846,12 @@
}
error:
return;
}
/**
* xsltCompilePattern:
* xsltCompilePatternInternal:
* @pattern: an XSLT pattern
* @doc: the containing document
* @node: the containing element
* @style: the stylesheet
* @runtime: the transformation context, if done at run-time
......@@ -1845,8 +1853,9 @@
* @pattern: an XSLT pattern
* @doc: the containing document
* @node: the containing element
* @style: the stylesheet
* @runtime: the transformation context, if done at run-time
* @novar: flag to prohibit xslt variables
*
* Compile the XSLT pattern and generates a list of precompiled form suitable
* for fast matching.
......@@ -1856,6 +1865,6 @@
* Returns the generated pattern list or NULL in case of failure
*/
xsltCompMatchPtr
xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc,
static xsltCompMatchPtr
xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc,
xmlNodePtr node, xsltStylesheetPtr style,
......@@ -1861,5 +1870,5 @@
xmlNodePtr node, xsltStylesheetPtr style,
xsltTransformContextPtr runtime) {
xsltTransformContextPtr runtime, int novar) {
xsltParserContextPtr ctxt = NULL;
xsltCompMatchPtr element, first = NULL, previous = NULL;
int current, start, end, level, j;
......@@ -1938,7 +1947,7 @@
This may be changed by xsltCompileLocationPathPattern.
*/
element->priority = 0;
xsltCompileLocationPathPattern(ctxt);
xsltCompileLocationPathPattern(ctxt, novar);
if (ctxt->error) {
xsltTransformError(NULL, style, node,
"xsltCompilePattern : failed to compile '%s'\n",
......@@ -2013,6 +2022,29 @@
return(NULL);
}
/**
* xsltCompilePattern:
* @pattern: an XSLT pattern
* @doc: the containing document
* @node: the containing element
* @style: the stylesheet
* @runtime: the transformation context, if done at run-time
*
* Compile the XSLT pattern and generates a list of precompiled form suitable
* for fast matching.
*
* [1] Pattern ::= LocationPathPattern | Pattern '|' LocationPathPattern
*
* Returns the generated pattern list or NULL in case of failure
*/
xsltCompMatchPtr
xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc,
xmlNodePtr node, xsltStylesheetPtr style,
xsltTransformContextPtr runtime) {
return (xsltCompilePatternInternal(pattern, doc, node, style, runtime, 0));
}
/************************************************************************
* *
* Module interfaces *
......@@ -2041,7 +2073,8 @@
return(-1);
priority = cur->priority;
pat = xsltCompilePattern(cur->match, style->doc, cur->elem, style, NULL);
pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem,
style, NULL, 1);
while (pat) {
next = pat->next;
pat->next = NULL;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment