diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | libexslt/functions.c | 86 | ||||
-rw-r--r-- | libxslt/transform.c | 23 | ||||
-rw-r--r-- | libxslt/transform.h | 10 | ||||
-rw-r--r-- | tests/exslt/functions/Makefile.am | 3 | ||||
-rw-r--r-- | tests/exslt/functions/function.9.out | 6 | ||||
-rw-r--r-- | tests/exslt/functions/function.9.xml | 9 | ||||
-rw-r--r-- | tests/exslt/functions/function.9.xsl | 22 |
8 files changed, 121 insertions, 48 deletions
@@ -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> + + |