summaryrefslogtreecommitdiff
path: root/libexslt/functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexslt/functions.c')
-rw-r--r--libexslt/functions.c80
1 files changed, 56 insertions, 24 deletions
diff --git a/libexslt/functions.c b/libexslt/functions.c
index dc794e3d..2f744311 100644
--- a/libexslt/functions.c
+++ b/libexslt/functions.c
@@ -34,6 +34,7 @@ typedef struct _exsltFuncData exsltFuncData;
struct _exsltFuncData {
xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
xmlXPathObjectPtr result; /* returned by func:result */
+ xsltStackElemPtr ctxtVar; /* context variable */
int error; /* did an error occur? */
};
@@ -68,10 +69,12 @@ static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
* Registers a function declared by a func:function element
*/
static void
-exsltFuncRegisterFunc (exsltFuncFunctionData *data,
- xsltTransformContextPtr ctxt,
+exsltFuncRegisterFunc (void *payload, void *vctxt,
const xmlChar *URI, const xmlChar *name,
ATTRIBUTE_UNUSED const xmlChar *ignored) {
+ exsltFuncFunctionData *data = (exsltFuncFunctionData *) payload;
+ xsltTransformContextPtr ctxt = (xsltTransformContextPtr) vctxt;
+
if ((data == NULL) || (ctxt == NULL) || (URI == NULL) || (name == NULL))
return;
@@ -93,10 +96,11 @@ exsltFuncRegisterFunc (exsltFuncFunctionData *data,
* stylesheet. If not, copies function data and registers function
*/
static void
-exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
- exsltFuncImportRegData *ch,
+exsltFuncRegisterImportFunc (void *payload, void *vctxt,
const xmlChar *URI, const xmlChar *name,
ATTRIBUTE_UNUSED const xmlChar *ignored) {
+ exsltFuncFunctionData *data = (exsltFuncFunctionData *) payload;
+ exsltFuncImportRegData *ch = (exsltFuncImportRegData *) vctxt;
exsltFuncFunctionData *func=NULL;
if ((data == NULL) || (ch == NULL) || (URI == NULL) || (name == NULL))
@@ -139,7 +143,7 @@ exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
*
* Returns the data for this transformation
*/
-static exsltFuncData *
+static void *
exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
exsltFuncData *ret;
xsltStylesheetPtr tmp;
@@ -159,14 +163,13 @@ exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
ch.hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);
ret->funcs = ch.hash;
- xmlHashScanFull(ch.hash, (xmlHashScannerFull) exsltFuncRegisterFunc, ctxt);
+ xmlHashScanFull(ch.hash, exsltFuncRegisterFunc, ctxt);
tmp = ctxt->style;
ch.ctxt = ctxt;
while ((tmp=xsltNextImport(tmp))!=NULL) {
hash = xsltGetExtInfo(tmp, URI);
if (hash != NULL) {
- xmlHashScanFull(hash,
- (xmlHashScannerFull) exsltFuncRegisterImportFunc, &ch);
+ xmlHashScanFull(hash, exsltFuncRegisterImportFunc, &ch);
}
}
@@ -185,7 +188,9 @@ exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
static void
exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
const xmlChar *URI ATTRIBUTE_UNUSED,
- exsltFuncData *data) {
+ void *vdata) {
+ exsltFuncData *data = (exsltFuncData *) vdata;
+
if (data->result != NULL)
xmlXPathFreeObject(data->result);
xmlFree(data);
@@ -201,12 +206,17 @@ exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
*
* Returns the allocated data
*/
-static xmlHashTablePtr
+static void *
exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
const xmlChar *URI ATTRIBUTE_UNUSED) {
return xmlHashCreate(1);
}
+static void
+exsltFuncFreeDataEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
+ xmlFree(payload);
+}
+
/**
* exsltFuncStyleShutdown:
* @style: an XSLT stylesheet
@@ -219,8 +229,9 @@ exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
static void
exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
const xmlChar *URI ATTRIBUTE_UNUSED,
- xmlHashTablePtr data) {
- xmlHashFree(data, (xmlHashDeallocator) xmlFree);
+ void *vdata) {
+ xmlHashTablePtr data = (xmlHashTablePtr) vdata;
+ xmlHashFree(data, exsltFuncFreeDataEntry);
}
/**
@@ -255,7 +266,9 @@ exsltFuncNewFunctionData (void) {
* Deallocates an #exsltFuncResultPreComp
*/
static void
-exsltFreeFuncResultPreComp (exsltFuncResultPreComp *comp) {
+exsltFreeFuncResultPreComp (xsltElemPreCompPtr ecomp) {
+ exsltFuncResultPreComp *comp = (exsltFuncResultPreComp *) ecomp;
+
if (comp == NULL)
return;
@@ -278,8 +291,9 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr oldResult, ret;
exsltFuncData *data;
exsltFuncFunctionData *func;
- xmlNodePtr paramNode, oldInsert, fake;
+ xmlNodePtr paramNode, oldInsert, oldXPNode, fake;
int oldBase;
+ void *oldCtxtVar;
xsltStackElemPtr params = NULL, param;
xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
int i, notSet;
@@ -346,6 +360,9 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
}
tctxt->depth++;
+ /* Evaluating templates can change the XPath context node. */
+ oldXPNode = tctxt->xpathCtxt->node;
+
/*
* We have a problem with the evaluation of function parameters.
* The original library code did not evaluate XPath expressions until
@@ -413,19 +430,26 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
}
}
/*
- * actual processing
+ * Actual processing. The context variable is cleared and restored
+ * when func:result is evaluated.
*/
fake = xmlNewDocNode(tctxt->output, NULL,
(const xmlChar *)"fake", NULL);
oldInsert = tctxt->insert;
+ oldCtxtVar = data->ctxtVar;
+ data->ctxtVar = tctxt->contextVariable;
tctxt->insert = fake;
+ tctxt->contextVariable = NULL;
xsltApplyOneTemplate (tctxt, tctxt->node,
func->content, NULL, NULL);
xsltLocalVariablePop(tctxt, tctxt->varsBase, -2);
tctxt->insert = oldInsert;
+ tctxt->contextVariable = data->ctxtVar;
tctxt->varsBase = oldBase; /* restore original scope */
+ data->ctxtVar = oldCtxtVar;
if (params != NULL)
xsltFreeStackElemList(params);
+ tctxt->xpathCtxt->node = oldXPNode;
if (data->error != 0)
goto error;
@@ -456,6 +480,7 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
"executing a function\n",
ctxt->context->functionURI, ctxt->context->function);
xmlFreeNode(fake);
+ xmlXPathFreeObject(ret);
goto error;
}
xmlFreeNode(fake);
@@ -641,7 +666,7 @@ exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
memset(ret, 0, sizeof(exsltFuncResultPreComp));
xsltInitElemPreComp ((xsltElemPreCompPtr) ret, style, inst, function,
- (xsltElemPreCompDeallocator) exsltFreeFuncResultPreComp);
+ exsltFreeFuncResultPreComp);
ret->select = NULL;
/*
@@ -649,7 +674,7 @@ exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
*/
sel = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);
if (sel != NULL) {
- ret->select = xmlXPathCompile (sel);
+ ret->select = xsltXPathCompileFlags(style, sel, 0);
xmlFree(sel);
}
/*
@@ -668,7 +693,8 @@ exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
static void
exsltFuncResultElem (xsltTransformContextPtr ctxt,
xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
- exsltFuncResultPreComp *comp) {
+ xsltElemPreCompPtr ecomp) {
+ exsltFuncResultPreComp *comp = (exsltFuncResultPreComp *) ecomp;
exsltFuncData *data;
xmlXPathObjectPtr ret;
@@ -690,6 +716,11 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
return;
}
/*
+ * Restore context variable, so that it will receive the function
+ * result RVTs.
+ */
+ ctxt->contextVariable = data->ctxtVar;
+ /*
* Processing
*/
if (comp->select != NULL) {
@@ -749,6 +780,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
return;
}
/* Mark as function result. */
+ xsltRegisterLocalRVT(ctxt, container);
container->psvi = XSLT_RVT_FUNC_RESULT;
oldInsert = ctxt->insert;
@@ -783,16 +815,16 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
void
exsltFuncRegister (void) {
xsltRegisterExtModuleFull (EXSLT_FUNCTIONS_NAMESPACE,
- (xsltExtInitFunction) exsltFuncInit,
- (xsltExtShutdownFunction) exsltFuncShutdown,
- (xsltStyleExtInitFunction) exsltFuncStyleInit,
- (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown);
+ exsltFuncInit,
+ exsltFuncShutdown,
+ exsltFuncStyleInit,
+ exsltFuncStyleShutdown);
xsltRegisterExtModuleTopLevel ((const xmlChar *) "function",
EXSLT_FUNCTIONS_NAMESPACE,
exsltFuncFunctionComp);
xsltRegisterExtModuleElement ((const xmlChar *) "result",
EXSLT_FUNCTIONS_NAMESPACE,
- (xsltPreComputeFunction)exsltFuncResultComp,
- (xsltTransformFunction) exsltFuncResultElem);
+ exsltFuncResultComp,
+ exsltFuncResultElem);
}