summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--libexslt/functions.c86
-rw-r--r--libxslt/transform.c23
-rw-r--r--libxslt/transform.h10
-rw-r--r--tests/exslt/functions/Makefile.am3
-rw-r--r--tests/exslt/functions/function.9.out6
-rw-r--r--tests/exslt/functions/function.9.xml9
-rw-r--r--tests/exslt/functions/function.9.xsl22
8 files changed, 121 insertions, 48 deletions
diff --git a/ChangeLog b/ChangeLog
index 2e057141..a9b2f80f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Sat Dec 9 15:22:34 PST 2006 William Brack <wbrack@mmm.com.hk>
+
+ * libexslt/functions.c: changed handling of function params
+ to fix bug #381319
+ * libxslt/transform.[ch]: exposed xsltLocalVariablePush and
+ xsltLocalVariablePop as global entries so that they could
+ be used from within libexslt/functions.c
+ * tests/exslt/functions/function.9.[xsl,xml,out] added to
+ regression tests
+
Tue Dec 5 10:45:04 CET 2006 Daniel Veillard <daniel@veillard.com>
* libxslt/extensions.c: applied patch from Marcus Meissner removing
diff --git a/libexslt/functions.c b/libexslt/functions.c
index bbeb182a..58bd71e4 100644
--- a/libexslt/functions.c
+++ b/libexslt/functions.c
@@ -281,7 +281,7 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
int oldBase;
xsltStackElemPtr params = NULL, param;
xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
- int i;
+ int i, notSet;;
/*
* retrieve func:function template
@@ -316,46 +316,47 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
"param == NULL\n");
return;
}
- /*
- * Process xsl:param instructions which were not set by the
- * invoking function call.
- */
- for (i = func->nargs; (i > nargs) && (paramNode != NULL); i--) {
+ /*
+ * In order to give the function params and variables a new 'scope'
+ * we change varsBase in the context.
+ */
+ oldBase = tctxt->varsBase;
+ tctxt->varsBase = tctxt->varsNr;
+
+ /* If there are any parameters */
+ if (paramNode != NULL) {
/*
- * Those are the xsl:param instructions, which were not
- * set by the calling function.
- */
- param = xsltParseStylesheetCallerParam (tctxt, paramNode);
- param->next = params;
- params = param;
- paramNode = paramNode->prev;
- }
- /*
- * Process xsl:param instructions which are set by the
- * invoking function call.
- */
- while ((i-- > 0) && (paramNode != NULL)) {
- obj = valuePop(ctxt);
+ * We need to process params which have been set by the invoking
+ * function call before those which were not (in case the set values
+ * are used within non-set 'select' default values), so we position
+ * to the beginning of the params.
+ */
+ for (i = 1; i <= func->nargs; i++) {
+ if (paramNode->prev == NULL)
+ break;
+ paramNode = paramNode->prev;
+ }
/*
- * TODO: Using xsltParseStylesheetCallerParam() is actually
- * not correct, since we are processing an xsl:param; but
- * using xsltParseStylesheetParam() won't work, as it puts
- * the param on the varible stack and does not give access to
- * the created xsltStackElemPtr.
- * It's also not correct, as xsltParseStylesheetCallerParam()
- * will report error messages indicating an "xsl:with-param" and
- * not the actual "xsl:param".
- */
- param = xsltParseStylesheetCallerParam (tctxt, paramNode);
- param->computed = 1;
- if (param->value != NULL)
- xmlXPathFreeObject(param->value);
- param->value = obj;
- param->next = params;
- params = param;
- paramNode = paramNode->prev;
+ * i has total # params found, nargs is number which are present
+ * as arguments from the caller
+ */
+ notSet = func->nargs - nargs;
+ for (; i > 0; i--) {
+ if (i > notSet) /* if parameter value set */
+ obj = valuePop(ctxt);
+ param = xsltParseStylesheetCallerParam (tctxt, paramNode);
+ if (i > notSet) { /* if parameter value set */
+ param->computed = 1;
+ if (param->value != NULL)
+ xmlXPathFreeObject(param->value);
+ param->value = obj;
+ }
+ xsltLocalVariablePush(tctxt, param, -1);
+ param->next = params;
+ params = param;
+ paramNode = paramNode->next;
+ }
}
-
/*
* actual processing
*/
@@ -363,14 +364,9 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
(const xmlChar *)"fake", NULL);
oldInsert = tctxt->insert;
tctxt->insert = fake;
- /*
- * In order to give the function variables a new 'scope' we
- * change varsBase in the context.
- */
- oldBase = tctxt->varsBase;
- tctxt->varsBase = tctxt->varsNr;
xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt),
- func->content, NULL, params);
+ func->content, NULL, NULL);
+ xsltLocalVariablePop(tctxt, tctxt->varsBase, -2);
tctxt->insert = oldInsert;
tctxt->varsBase = oldBase; /* restore original scope */
if (params != NULL)
diff --git a/libxslt/transform.c b/libxslt/transform.c
index 1c4f5c79..07f8d283 100644
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -173,8 +173,10 @@ templPop(xsltTransformContextPtr ctxt)
* Pops all variable values at the given @depth from the stack.
*
* Returns the stored variable value
+ * **NOTE:**
+ * This is an internal routine and should not be called by users!
*/
-static void
+void
xsltLocalVariablePop(xsltTransformContextPtr ctxt, int limitNr, int level)
{
xsltStackElemPtr variable;
@@ -2067,7 +2069,19 @@ xsltDebuggerStartSequenceConstructor(xsltTransformContextPtr ctxt,
return(debugedNode);
}
-static int
+/**
+ * xsltVariablePush:
+ * @ctxt: the transformation context
+ * @variable: variable to be pushed to the variable stack
+ * @level: new value for variable's level
+ *
+ * Places the variable onto the local variable stack
+ *
+ * Returns: 0 for success, -1 for any error
+ * **NOTE:**
+ * This is an internal routine and should not be called by users!
+ */
+int
xsltLocalVariablePush(xsltTransformContextPtr ctxt,
xsltStackElemPtr variable,
int level)
@@ -3132,6 +3146,11 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt,
CHECK_STOPPED;
if (params) {
+ /*
+ * This code should be obsolete - was previously used
+ * by libexslt/functions.c, but due to bug 381319 the
+ * logic there was changed.
+ */
int oldVarsNr = ctxt->varsNr;
/*
diff --git a/libxslt/transform.h b/libxslt/transform.h
index 1e030d2f..105ac2d9 100644
--- a/libxslt/transform.h
+++ b/libxslt/transform.h
@@ -176,6 +176,16 @@ XSLTPUBFUN xmlNodePtr XSLTCALL
xmlNodePtr target,
const xmlChar *string,
int noescape);
+
+/* Following 2 functions needed for libexslt/functions.c */
+XSLTPUBFUN void XSLTCALL
+ xsltLocalVariablePop (xsltTransformContextPtr ctxt,
+ int limitNr,
+ int level);
+XSLTPUBFUN int XSLTCALL
+ xsltLocalVariablePush (xsltTransformContextPtr ctxt,
+ xsltStackElemPtr variable,
+ int level);
/*
* Hook for the debugger if activated.
*/
diff --git a/tests/exslt/functions/Makefile.am b/tests/exslt/functions/Makefile.am
index d5dc12fc..d1787460 100644
--- a/tests/exslt/functions/Makefile.am
+++ b/tests/exslt/functions/Makefile.am
@@ -11,7 +11,8 @@ EXTRA_DIST = \
function.5.out function.5.xml function.5.xsl \
function.6.out function.6.xml function.6.xsl \
function.7.out function.7.xml function.7.xsl \
- function.8.out function.8.xml function.8.xsl
+ function.8.out function.8.xml function.8.xsl \
+ function.9.out function.9.xml function.9.xsl
all:
diff --git a/tests/exslt/functions/function.9.out b/tests/exslt/functions/function.9.out
new file mode 100644
index 00000000..1224d967
--- /dev/null
+++ b/tests/exslt/functions/function.9.out
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+
+
+ a
+
+
diff --git a/tests/exslt/functions/function.9.xml b/tests/exslt/functions/function.9.xml
new file mode 100644
index 00000000..6a3c717b
--- /dev/null
+++ b/tests/exslt/functions/function.9.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <table>
+ <tr>
+ <td align="center">a</td>
+ </tr>
+ </table>
+</root>
+
diff --git a/tests/exslt/functions/function.9.xsl b/tests/exslt/functions/function.9.xsl
new file mode 100644
index 00000000..72d9599c
--- /dev/null
+++ b/tests/exslt/functions/function.9.xsl
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:math="http://exslt.org/math"
+ xmlns:mg="mg"
+ extension-element-prefixes="exsl func">
+
+ <xsl:template match="table">
+ <xsl:variable name="cols" select="mg:function(.)"/>
+ <xsl:value-of select="$cols"/>
+ </xsl:template>
+
+ <func:function name="mg:function">
+ <xsl:param name="table"/>
+ <xsl:param name="tr" select="$table/tr[1]"/>
+ <func:result select="$tr"/>
+ </func:function>
+</xsl:stylesheet>
+
+