diff --git a/libexslt/functions.c b/libexslt/functions.c
index 2b83ca34..b7b968f8 100644
--- a/libexslt/functions.c
+++ b/libexslt/functions.c
@@ -426,7 +426,15 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
}
}
/*
- * actual processing
+ * Actual processing. Note that contextVariable is set to NULL which
+ * means that RVTs returned from functions always end up as local RVTs,
+ * not as variable fragments if the function is called in the select
+ * expression of an xsl:variable. This is a hack that only works because
+ * xsltReleaseLocalRVTs isn't called after processing xsl:variable.
+ *
+ * It would probably be better to remove the fragile contextVariable
+ * logic and make xsltEvalVariable move the required RVTs into the
+ * variable manually.
*/
fake = xmlNewDocNode(tctxt->output, NULL,
(const xmlChar *)"fake", NULL);
@@ -766,6 +774,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
return;
}
/* Mark as function result. */
+ xsltRegisterLocalRVT(ctxt, container);
container->psvi = XSLT_RVT_FUNC_RESULT;
oldInsert = ctxt->insert;
diff --git a/libxslt/transform.c b/libxslt/transform.c
index 90d2731d..d7af31f1 100644
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -2295,6 +2295,7 @@ static void
xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
{
xmlDocPtr cur = ctxt->localRVT, tmp;
+ xmlDocPtr prev = NULL;
if (cur == base)
return;
@@ -2308,16 +2309,26 @@ xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
xsltReleaseRVT(ctxt, tmp);
} else if (tmp->psvi == XSLT_RVT_GLOBAL) {
xsltRegisterPersistRVT(ctxt, tmp);
- } else if (tmp->psvi != XSLT_RVT_FUNC_RESULT) {
+ } else if (tmp->psvi == XSLT_RVT_FUNC_RESULT) {
+ if (prev == NULL)
+ ctxt->localRVT = tmp;
+ else
+ prev->next = (xmlNodePtr) tmp;
+ tmp->prev = (xmlNodePtr) prev;
+ prev = tmp;
+ } else {
xmlGenericError(xmlGenericErrorContext,
"xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
tmp->psvi);
}
} while (cur != base);
+ if (prev == NULL)
+ ctxt->localRVT = base;
+ else
+ prev->next = (xmlNodePtr) base;
if (base != NULL)
- base->prev = NULL;
- ctxt->localRVT = base;
+ base->prev = (xmlNodePtr) prev;
}
/**
diff --git a/libxslt/variables.c b/libxslt/variables.c
index fe6f299c..8f88e573 100644
--- a/libxslt/variables.c
+++ b/libxslt/variables.c
@@ -123,7 +123,7 @@ xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
return(-1);
RVT->prev = NULL;
- RVT->psvi = XSLT_RVT_VARIABLE;
+ RVT->psvi = XSLT_RVT_LOCAL;
/*
* We'll restrict the lifetime of user-created fragments
@@ -163,6 +163,7 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
return(-1);
RVT->prev = NULL;
+ RVT->psvi = XSLT_RVT_LOCAL;
/*
* When evaluating "select" expressions of xsl:variable
@@ -173,7 +174,6 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
if ((ctxt->contextVariable != NULL) &&
(XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT))
{
- RVT->psvi = XSLT_RVT_VARIABLE;
RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
return(0);
@@ -183,7 +183,6 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
* If not reference by a returning instruction (like EXSLT's function),
* then this fragment will be freed, when the instruction exits.
*/
- RVT->psvi = XSLT_RVT_LOCAL;
RVT->next = (xmlNodePtr) ctxt->localRVT;
if (ctxt->localRVT != NULL)
ctxt->localRVT->prev = (xmlNodePtr) RVT;
@@ -314,14 +313,8 @@ xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
#endif
if (val == XSLT_RVT_LOCAL) {
- if (doc->psvi != XSLT_RVT_FUNC_RESULT) {
- xmlGenericError(xmlGenericErrorContext,
- "xsltFlagRVTs: Invalid transition %p => LOCAL\n",
- doc->psvi);
- return(-1);
- }
-
- xsltRegisterLocalRVT(ctxt, doc);
+ if (doc->psvi == XSLT_RVT_FUNC_RESULT)
+ doc->psvi = XSLT_RVT_LOCAL;
} else if (val == XSLT_RVT_GLOBAL) {
if (doc->psvi != XSLT_RVT_LOCAL) {
xmlGenericError(xmlGenericErrorContext,
@@ -585,10 +578,12 @@ xsltFreeStackElem(xsltStackElemPtr elem) {
cur = elem->fragment;
elem->fragment = (xmlDocPtr) cur->next;
- if (cur->psvi == XSLT_RVT_VARIABLE) {
- xsltReleaseRVT((xsltTransformContextPtr) elem->context,
- cur);
- } else if (cur->psvi != XSLT_RVT_FUNC_RESULT) {
+ if (cur->psvi == XSLT_RVT_LOCAL) {
+ xsltReleaseRVT(elem->context, cur);
+ } else if (cur->psvi == XSLT_RVT_FUNC_RESULT) {
+ xsltRegisterLocalRVT(elem->context, cur);
+ cur->psvi = XSLT_RVT_FUNC_RESULT;
+ } else {
xmlGenericError(xmlGenericErrorContext,
"xsltFreeStackElem: Unexpected RVT flag %p\n",
cur->psvi);
@@ -992,7 +987,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
* the Result Tree Fragment.
*/
variable->fragment = container;
- container->psvi = XSLT_RVT_VARIABLE;
+ container->psvi = XSLT_RVT_LOCAL;
oldOutput = ctxt->output;
oldInsert = ctxt->insert;
diff --git a/libxslt/variables.h b/libxslt/variables.h
index 24acf8d1..039288fb 100644
--- a/libxslt/variables.h
+++ b/libxslt/variables.h
@@ -45,14 +45,6 @@ extern "C" {
*/
#define XSLT_RVT_LOCAL ((void *)1)
-/**
- * XSLT_RVT_VARIABLE:
- *
- * RVT is part of a local variable and destroyed after the variable goes out
- * of scope.
- */
-#define XSLT_RVT_VARIABLE ((void *)2)
-
/**
* XSLT_RVT_FUNC_RESULT:
*
@@ -60,14 +52,14 @@ extern "C" {
* destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or
* XSLT_RVT_VARIABLE in the template that receives the return value.
*/
-#define XSLT_RVT_FUNC_RESULT ((void *)3)
+#define XSLT_RVT_FUNC_RESULT ((void *)2)
/**
* XSLT_RVT_GLOBAL:
*
* RVT is part of a global variable.
*/
-#define XSLT_RVT_GLOBAL ((void *)4)
+#define XSLT_RVT_GLOBAL ((void *)3)
/*
* Interfaces for the variable module.
diff --git a/tests/docs/bug-210.xml b/tests/docs/bug-210.xml
new file mode 100644
index 00000000..69d62f2c
--- /dev/null
+++ b/tests/docs/bug-210.xml
@@ -0,0 +1 @@
+
diff --git a/tests/docs/bug-211.xml b/tests/docs/bug-211.xml
new file mode 100644
index 00000000..69d62f2c
--- /dev/null
+++ b/tests/docs/bug-211.xml
@@ -0,0 +1 @@
+
diff --git a/tests/general/bug-210.out b/tests/general/bug-210.out
new file mode 100644
index 00000000..445906d6
--- /dev/null
+++ b/tests/general/bug-210.out
@@ -0,0 +1,2 @@
+
+value
diff --git a/tests/general/bug-210.xsl b/tests/general/bug-210.xsl
new file mode 100644
index 00000000..1915171d
--- /dev/null
+++ b/tests/general/bug-210.xsl
@@ -0,0 +1,20 @@
+
+
+
+
+ value
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/general/bug-211.out b/tests/general/bug-211.out
new file mode 100644
index 00000000..7b3cf11c
--- /dev/null
+++ b/tests/general/bug-211.out
@@ -0,0 +1,2 @@
+
+__
diff --git a/tests/general/bug-211.xsl b/tests/general/bug-211.xsl
new file mode 100644
index 00000000..557f5fb3
--- /dev/null
+++ b/tests/general/bug-211.xsl
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+