diff options
Diffstat (limited to 'libexslt/functions.c')
-rw-r--r-- | libexslt/functions.c | 80 |
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); } |