summaryrefslogtreecommitdiff
path: root/libexslt
diff options
context:
space:
mode:
authorKasimier T. Buchcik <kbuchcik@src.gnome.org>2006-07-14 16:18:32 +0000
committerKasimier T. Buchcik <kbuchcik@src.gnome.org>2006-07-14 16:18:32 +0000
commit7662584ea19f746955775ad77f4fc959568495cb (patch)
tree8978a6c6e206b7e56dba85cc17296db0a2f3cb41 /libexslt
parent90d2d1c28995e327dacccf820c5fb8ca90b6dc0b (diff)
downloadlibxslt-7662584ea19f746955775ad77f4fc959568495cb.tar.gz
libxslt-7662584ea19f746955775ad77f4fc959568495cb.tar.bz2
libxslt-7662584ea19f746955775ad77f4fc959568495cb.zip
Committing again, since I forgot to switch from win to linux linebreaks in
* libxslt/attributes.c libxslt/documents.c libxslt/functions.c libxslt/keys.c libxslt/namespaces.c libxslt/pattern.c libxslt/preproc.c libxslt/templates.c libxslt/templates.h libxslt/transform.c libxslt/variables.c libxslt/xslt.c libxslt/xsltInternals.h libxslt/xsltutils.c libxslt/xsltutils.h libexslt/common.c libexslt/dynamic.c libexslt/functions.c libexslt/strings.c: Committing again, since I forgot to switch from win to linux linebreaks in the files.
Diffstat (limited to 'libexslt')
-rw-r--r--libexslt/common.c262
-rw-r--r--libexslt/dynamic.c548
-rw-r--r--libexslt/functions.c1458
-rw-r--r--libexslt/strings.c1052
4 files changed, 1660 insertions, 1660 deletions
diff --git a/libexslt/common.c b/libexslt/common.c
index 7b07ea28..ba57fa5b 100644
--- a/libexslt/common.c
+++ b/libexslt/common.c
@@ -1,131 +1,131 @@
-#define IN_LIBEXSLT
-#include "libexslt/libexslt.h"
-
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
-#include <win32config.h>
-#else
-#include "config.h"
-#endif
-
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-
-#include <libxslt/xsltconfig.h>
-#include <libxslt/xsltutils.h>
-#include <libxslt/xsltInternals.h>
-#include <libxslt/extensions.h>
-#include <libxslt/transform.h>
-#include <libxslt/extra.h>
-#include <libxslt/preproc.h>
-
-#include "exslt.h"
-
-static void
-exsltNodeSetFunction (xmlXPathParserContextPtr ctxt, int nargs) {
- if (nargs != 1) {
- xmlXPathSetArityError(ctxt);
- return;
- }
- if (xmlXPathStackIsNodeSet (ctxt)) {
- xsltFunctionNodeSet (ctxt, nargs);
- return;
- } else {
- xmlDocPtr fragment;
- xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
- xmlNodePtr txt;
- xmlChar *strval;
- xmlXPathObjectPtr obj;
- /*
- * SPEC EXSLT:
- * "You can also use this function to turn a string into a text
- * node, which is helpful if you want to pass a string to a
- * function that only accepts a node-set."
- */
- fragment = xsltCreateRVT(tctxt);
- if (fragment == NULL) {
- xsltTransformError(tctxt, NULL, tctxt->inst,
- "exsltNodeSetFunction: Failed to create a tree fragment.\n");
- tctxt->state = XSLT_STATE_STOPPED;
- return;
- }
- xsltRegisterLocalRVT(tctxt, fragment);
-
- strval = xmlXPathPopString (ctxt);
-
- txt = xmlNewDocText (fragment, strval);
- xmlAddChild((xmlNodePtr) fragment, txt);
- obj = xmlXPathNewNodeSet(txt);
- if (obj == NULL) {
- xsltTransformError(tctxt, NULL, tctxt->inst,
- "exsltNodeSetFunction: Failed to create a node set object.\n");
- tctxt->state = XSLT_STATE_STOPPED;
- }
- if (strval != NULL)
- xmlFree (strval);
-
- valuePush (ctxt, obj);
- }
-}
-
-static void
-exsltObjectTypeFunction (xmlXPathParserContextPtr ctxt, int nargs) {
- xmlXPathObjectPtr obj, ret;
-
- if (nargs != 1) {
- xmlXPathSetArityError(ctxt);
- return;
- }
-
- obj = valuePop(ctxt);
-
- switch (obj->type) {
- case XPATH_STRING:
- ret = xmlXPathNewCString("string");
- break;
- case XPATH_NUMBER:
- ret = xmlXPathNewCString("number");
- break;
- case XPATH_BOOLEAN:
- ret = xmlXPathNewCString("boolean");
- break;
- case XPATH_NODESET:
- ret = xmlXPathNewCString("node-set");
- break;
- case XPATH_XSLT_TREE:
- ret = xmlXPathNewCString("RTF");
- break;
- case XPATH_USERS:
- ret = xmlXPathNewCString("external");
- break;
- default:
- xsltGenericError(xsltGenericErrorContext,
- "object-type() invalid arg\n");
- ctxt->error = XPATH_INVALID_TYPE;
- xmlXPathFreeObject(obj);
- return;
- }
- xmlXPathFreeObject(obj);
- valuePush(ctxt, ret);
-}
-
-
-/**
- * exsltCommonRegister:
- *
- * Registers the EXSLT - Common module
- */
-
-void
-exsltCommonRegister (void) {
- xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
- EXSLT_COMMON_NAMESPACE,
- exsltNodeSetFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "object-type",
- EXSLT_COMMON_NAMESPACE,
- exsltObjectTypeFunction);
- xsltRegisterExtModuleElement((const xmlChar *) "document",
- EXSLT_COMMON_NAMESPACE,
- (xsltPreComputeFunction) xsltDocumentComp,
- (xsltTransformFunction) xsltDocumentElem);
-}
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+#include <libxslt/transform.h>
+#include <libxslt/extra.h>
+#include <libxslt/preproc.h>
+
+#include "exslt.h"
+
+static void
+exsltNodeSetFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ if (nargs != 1) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+ if (xmlXPathStackIsNodeSet (ctxt)) {
+ xsltFunctionNodeSet (ctxt, nargs);
+ return;
+ } else {
+ xmlDocPtr fragment;
+ xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
+ xmlNodePtr txt;
+ xmlChar *strval;
+ xmlXPathObjectPtr obj;
+ /*
+ * SPEC EXSLT:
+ * "You can also use this function to turn a string into a text
+ * node, which is helpful if you want to pass a string to a
+ * function that only accepts a node-set."
+ */
+ fragment = xsltCreateRVT(tctxt);
+ if (fragment == NULL) {
+ xsltTransformError(tctxt, NULL, tctxt->inst,
+ "exsltNodeSetFunction: Failed to create a tree fragment.\n");
+ tctxt->state = XSLT_STATE_STOPPED;
+ return;
+ }
+ xsltRegisterLocalRVT(tctxt, fragment);
+
+ strval = xmlXPathPopString (ctxt);
+
+ txt = xmlNewDocText (fragment, strval);
+ xmlAddChild((xmlNodePtr) fragment, txt);
+ obj = xmlXPathNewNodeSet(txt);
+ if (obj == NULL) {
+ xsltTransformError(tctxt, NULL, tctxt->inst,
+ "exsltNodeSetFunction: Failed to create a node set object.\n");
+ tctxt->state = XSLT_STATE_STOPPED;
+ }
+ if (strval != NULL)
+ xmlFree (strval);
+
+ valuePush (ctxt, obj);
+ }
+}
+
+static void
+exsltObjectTypeFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlXPathObjectPtr obj, ret;
+
+ if (nargs != 1) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ obj = valuePop(ctxt);
+
+ switch (obj->type) {
+ case XPATH_STRING:
+ ret = xmlXPathNewCString("string");
+ break;
+ case XPATH_NUMBER:
+ ret = xmlXPathNewCString("number");
+ break;
+ case XPATH_BOOLEAN:
+ ret = xmlXPathNewCString("boolean");
+ break;
+ case XPATH_NODESET:
+ ret = xmlXPathNewCString("node-set");
+ break;
+ case XPATH_XSLT_TREE:
+ ret = xmlXPathNewCString("RTF");
+ break;
+ case XPATH_USERS:
+ ret = xmlXPathNewCString("external");
+ break;
+ default:
+ xsltGenericError(xsltGenericErrorContext,
+ "object-type() invalid arg\n");
+ ctxt->error = XPATH_INVALID_TYPE;
+ xmlXPathFreeObject(obj);
+ return;
+ }
+ xmlXPathFreeObject(obj);
+ valuePush(ctxt, ret);
+}
+
+
+/**
+ * exsltCommonRegister:
+ *
+ * Registers the EXSLT - Common module
+ */
+
+void
+exsltCommonRegister (void) {
+ xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
+ EXSLT_COMMON_NAMESPACE,
+ exsltNodeSetFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "object-type",
+ EXSLT_COMMON_NAMESPACE,
+ exsltObjectTypeFunction);
+ xsltRegisterExtModuleElement((const xmlChar *) "document",
+ EXSLT_COMMON_NAMESPACE,
+ (xsltPreComputeFunction) xsltDocumentComp,
+ (xsltTransformFunction) xsltDocumentElem);
+}
diff --git a/libexslt/dynamic.c b/libexslt/dynamic.c
index 87ef8da3..11c291b0 100644
--- a/libexslt/dynamic.c
+++ b/libexslt/dynamic.c
@@ -1,274 +1,274 @@
-/*
- * dynamic.c: Implementation of the EXSLT -- Dynamic module
- *
- * References:
- * http://www.exslt.org/dyn/dyn.html
- *
- * See Copyright for the status of this software.
- *
- * Authors:
- * Mark Vakoc <mark_vakoc@jdedwards.com>
- * Thomas Broyer <tbroyer@ltgt.net>
- *
- * TODO:
- * elements:
- * functions:
- * min
- * max
- * sum
- * map
- * closure
- */
-
-#define IN_LIBEXSLT
-#include "libexslt/libexslt.h"
-
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
-#include <win32config.h>
-#else
-#include "config.h"
-#endif
-
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-
-#include <libxslt/xsltconfig.h>
-#include <libxslt/xsltutils.h>
-#include <libxslt/xsltInternals.h>
-#include <libxslt/extensions.h>
-
-#include "exslt.h"
-
-/**
- * exsltDynEvaluateFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Evaluates the string as an XPath expression and returns the result
- * value, which may be a boolean, number, string, node set, result tree
- * fragment or external object.
- */
-
-static void
-exsltDynEvaluateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
- xmlChar *str = NULL;
- xmlXPathObjectPtr ret = NULL;
-
- if (ctxt == NULL)
- return;
- if (nargs != 1) {
- xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
- xsltGenericError(xsltGenericErrorContext,
- "dyn:evalute() : invalid number of args %d\n", nargs);
- ctxt->error = XPATH_INVALID_ARITY;
- return;
- }
- str = xmlXPathPopString(ctxt);
- /* return an empty node-set if an empty string is passed in */
- if (!str||!xmlStrlen(str)) {
- if (str) xmlFree(str);
- valuePush(ctxt,xmlXPathNewNodeSet(NULL));
- return;
- }
- ret = xmlXPathEval(str,ctxt->context);
- if (ret)
- valuePush(ctxt,ret);
- else {
- xsltGenericError(xsltGenericErrorContext,
- "dyn:evaluate() : unable to evaluate expression '%s'\n",str);
- valuePush(ctxt,xmlXPathNewNodeSet(NULL));
- }
- xmlFree(str);
- return;
-}
-
-/**
- * exsltDynMapFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Evaluates the string as an XPath expression and returns the result
- * value, which may be a boolean, number, string, node set, result tree
- * fragment or external object.
- */
-
-static void
-exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
-{
- xmlChar *str = NULL;
- xmlNodeSetPtr nodeset = NULL;
- xmlXPathCompExprPtr comp = NULL;
- xmlXPathObjectPtr ret = NULL;
- xmlDocPtr oldDoc, container;
- xmlNodePtr oldNode;
- int oldContextSize;
- int oldProximityPosition;
- int i, j;
-
-
- if (nargs != 2) {
- xmlXPathSetArityError(ctxt);
- return;
- }
- str = xmlXPathPopString(ctxt);
- if (xmlXPathCheckError(ctxt)) {
- xmlXPathSetTypeError(ctxt);
- return;
- }
-
- nodeset = xmlXPathPopNodeSet(ctxt);
- if (xmlXPathCheckError(ctxt)) {
- xmlXPathSetTypeError(ctxt);
- return;
- }
- if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) {
- if (nodeset != NULL)
- xmlXPathFreeNodeSet(nodeset);
- if (str != NULL)
- xmlFree(str);
- valuePush(ctxt, xmlXPathNewNodeSet(NULL));
- return;
- }
-
- ret = xmlXPathNewNodeSet(NULL);
- if (ret == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltDynMapFunctoin: ret == NULL\n");
- goto cleanup;
- }
-
- oldDoc = ctxt->context->doc;
- oldNode = ctxt->context->node;
- oldContextSize = ctxt->context->contextSize;
- oldProximityPosition = ctxt->context->proximityPosition;
-
- /**
- * since we really don't know we're going to be adding node(s)
- * down the road we create the RVT regardless
- */
- container = xsltCreateRVT(xsltXPathGetTransformContext(ctxt));
- if (container != NULL)
- xsltRegisterLocalRVT(xsltXPathGetTransformContext(ctxt), container);
-
- if (nodeset && nodeset->nodeNr > 0) {
- xmlXPathNodeSetSort(nodeset);
- ctxt->context->contextSize = nodeset->nodeNr;
- ctxt->context->proximityPosition = 0;
- for (i = 0; i < nodeset->nodeNr; i++) {
- xmlXPathObjectPtr subResult = NULL;
-
- ctxt->context->proximityPosition++;
- ctxt->context->node = nodeset->nodeTab[i];
- ctxt->context->doc = nodeset->nodeTab[i]->doc;
-
- subResult = xmlXPathCompiledEval(comp, ctxt->context);
- if (subResult != NULL) {
- switch (subResult->type) {
- case XPATH_NODESET:
- if (subResult->nodesetval != NULL)
- for (j = 0; j < subResult->nodesetval->nodeNr;
- j++)
- xmlXPathNodeSetAdd(ret->nodesetval,
- subResult->nodesetval->
- nodeTab[j]);
- break;
- case XPATH_BOOLEAN:
- if (container != NULL) {
- xmlNodePtr cur =
- xmlNewChild((xmlNodePtr) container, NULL,
- BAD_CAST "boolean",
- BAD_CAST (subResult->
- boolval ? "true" : ""));
- if (cur != NULL) {
- cur->ns =
- xmlNewNs(cur,
- BAD_CAST
- "http://exslt.org/common",
- BAD_CAST "exsl");
- xmlXPathNodeSetAddUnique(ret->nodesetval,
- cur);
- }
- }
- break;
- case XPATH_NUMBER:
- if (container != NULL) {
- xmlChar *val =
- xmlXPathCastNumberToString(subResult->
- floatval);
- xmlNodePtr cur =
- xmlNewChild((xmlNodePtr) container, NULL,
- BAD_CAST "number", val);
- if (val != NULL)
- xmlFree(val);
-
- if (cur != NULL) {
- cur->ns =
- xmlNewNs(cur,
- BAD_CAST
- "http://exslt.org/common",
- BAD_CAST "exsl");
- xmlXPathNodeSetAddUnique(ret->nodesetval,
- cur);
- }
- }
- break;
- case XPATH_STRING:
- if (container != NULL) {
- xmlNodePtr cur =
- xmlNewChild((xmlNodePtr) container, NULL,
- BAD_CAST "string",
- subResult->stringval);
- if (cur != NULL) {
- cur->ns =
- xmlNewNs(cur,
- BAD_CAST
- "http://exslt.org/common",
- BAD_CAST "exsl");
- xmlXPathNodeSetAddUnique(ret->nodesetval,
- cur);
- }
- }
- break;
- default:
- break;
- }
- xmlXPathFreeObject(subResult);
- }
- }
- }
- ctxt->context->doc = oldDoc;
- ctxt->context->node = oldNode;
- ctxt->context->contextSize = oldContextSize;
- ctxt->context->proximityPosition = oldProximityPosition;
-
-
- cleanup:
- /* restore the xpath context */
- if (comp != NULL)
- xmlXPathFreeCompExpr(comp);
- if (nodeset != NULL)
- xmlXPathFreeNodeSet(nodeset);
- if (str != NULL)
- xmlFree(str);
- valuePush(ctxt, ret);
- return;
-}
-
-
-/**
- * exsltDynRegister:
- *
- * Registers the EXSLT - Dynamic module
- */
-
-void
-exsltDynRegister (void) {
- xsltRegisterExtModuleFunction ((const xmlChar *) "evaluate",
- EXSLT_DYNAMIC_NAMESPACE,
- exsltDynEvaluateFunction);
- xsltRegisterExtModuleFunction ((const xmlChar *) "map",
- EXSLT_DYNAMIC_NAMESPACE,
- exsltDynMapFunction);
-
-}
+/*
+ * dynamic.c: Implementation of the EXSLT -- Dynamic module
+ *
+ * References:
+ * http://www.exslt.org/dyn/dyn.html
+ *
+ * See Copyright for the status of this software.
+ *
+ * Authors:
+ * Mark Vakoc <mark_vakoc@jdedwards.com>
+ * Thomas Broyer <tbroyer@ltgt.net>
+ *
+ * TODO:
+ * elements:
+ * functions:
+ * min
+ * max
+ * sum
+ * map
+ * closure
+ */
+
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+
+#include "exslt.h"
+
+/**
+ * exsltDynEvaluateFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Evaluates the string as an XPath expression and returns the result
+ * value, which may be a boolean, number, string, node set, result tree
+ * fragment or external object.
+ */
+
+static void
+exsltDynEvaluateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlChar *str = NULL;
+ xmlXPathObjectPtr ret = NULL;
+
+ if (ctxt == NULL)
+ return;
+ if (nargs != 1) {
+ xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
+ xsltGenericError(xsltGenericErrorContext,
+ "dyn:evalute() : invalid number of args %d\n", nargs);
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ str = xmlXPathPopString(ctxt);
+ /* return an empty node-set if an empty string is passed in */
+ if (!str||!xmlStrlen(str)) {
+ if (str) xmlFree(str);
+ valuePush(ctxt,xmlXPathNewNodeSet(NULL));
+ return;
+ }
+ ret = xmlXPathEval(str,ctxt->context);
+ if (ret)
+ valuePush(ctxt,ret);
+ else {
+ xsltGenericError(xsltGenericErrorContext,
+ "dyn:evaluate() : unable to evaluate expression '%s'\n",str);
+ valuePush(ctxt,xmlXPathNewNodeSet(NULL));
+ }
+ xmlFree(str);
+ return;
+}
+
+/**
+ * exsltDynMapFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Evaluates the string as an XPath expression and returns the result
+ * value, which may be a boolean, number, string, node set, result tree
+ * fragment or external object.
+ */
+
+static void
+exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ xmlChar *str = NULL;
+ xmlNodeSetPtr nodeset = NULL;
+ xmlXPathCompExprPtr comp = NULL;
+ xmlXPathObjectPtr ret = NULL;
+ xmlDocPtr oldDoc, container;
+ xmlNodePtr oldNode;
+ int oldContextSize;
+ int oldProximityPosition;
+ int i, j;
+
+
+ if (nargs != 2) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+ str = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ nodeset = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+ if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) {
+ if (nodeset != NULL)
+ xmlXPathFreeNodeSet(nodeset);
+ if (str != NULL)
+ xmlFree(str);
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+ return;
+ }
+
+ ret = xmlXPathNewNodeSet(NULL);
+ if (ret == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltDynMapFunctoin: ret == NULL\n");
+ goto cleanup;
+ }
+
+ oldDoc = ctxt->context->doc;
+ oldNode = ctxt->context->node;
+ oldContextSize = ctxt->context->contextSize;
+ oldProximityPosition = ctxt->context->proximityPosition;
+
+ /**
+ * since we really don't know we're going to be adding node(s)
+ * down the road we create the RVT regardless
+ */
+ container = xsltCreateRVT(xsltXPathGetTransformContext(ctxt));
+ if (container != NULL)
+ xsltRegisterLocalRVT(xsltXPathGetTransformContext(ctxt), container);
+
+ if (nodeset && nodeset->nodeNr > 0) {
+ xmlXPathNodeSetSort(nodeset);
+ ctxt->context->contextSize = nodeset->nodeNr;
+ ctxt->context->proximityPosition = 0;
+ for (i = 0; i < nodeset->nodeNr; i++) {
+ xmlXPathObjectPtr subResult = NULL;
+
+ ctxt->context->proximityPosition++;
+ ctxt->context->node = nodeset->nodeTab[i];
+ ctxt->context->doc = nodeset->nodeTab[i]->doc;
+
+ subResult = xmlXPathCompiledEval(comp, ctxt->context);
+ if (subResult != NULL) {
+ switch (subResult->type) {
+ case XPATH_NODESET:
+ if (subResult->nodesetval != NULL)
+ for (j = 0; j < subResult->nodesetval->nodeNr;
+ j++)
+ xmlXPathNodeSetAdd(ret->nodesetval,
+ subResult->nodesetval->
+ nodeTab[j]);
+ break;
+ case XPATH_BOOLEAN:
+ if (container != NULL) {
+ xmlNodePtr cur =
+ xmlNewChild((xmlNodePtr) container, NULL,
+ BAD_CAST "boolean",
+ BAD_CAST (subResult->
+ boolval ? "true" : ""));
+ if (cur != NULL) {
+ cur->ns =
+ xmlNewNs(cur,
+ BAD_CAST
+ "http://exslt.org/common",
+ BAD_CAST "exsl");
+ xmlXPathNodeSetAddUnique(ret->nodesetval,
+ cur);
+ }
+ }
+ break;
+ case XPATH_NUMBER:
+ if (container != NULL) {
+ xmlChar *val =
+ xmlXPathCastNumberToString(subResult->
+ floatval);
+ xmlNodePtr cur =
+ xmlNewChild((xmlNodePtr) container, NULL,
+ BAD_CAST "number", val);
+ if (val != NULL)
+ xmlFree(val);
+
+ if (cur != NULL) {
+ cur->ns =
+ xmlNewNs(cur,
+ BAD_CAST
+ "http://exslt.org/common",
+ BAD_CAST "exsl");
+ xmlXPathNodeSetAddUnique(ret->nodesetval,
+ cur);
+ }
+ }
+ break;
+ case XPATH_STRING:
+ if (container != NULL) {
+ xmlNodePtr cur =
+ xmlNewChild((xmlNodePtr) container, NULL,
+ BAD_CAST "string",
+ subResult->stringval);
+ if (cur != NULL) {
+ cur->ns =
+ xmlNewNs(cur,
+ BAD_CAST
+ "http://exslt.org/common",
+ BAD_CAST "exsl");
+ xmlXPathNodeSetAddUnique(ret->nodesetval,
+ cur);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ xmlXPathFreeObject(subResult);
+ }
+ }
+ }
+ ctxt->context->doc = oldDoc;
+ ctxt->context->node = oldNode;
+ ctxt->context->contextSize = oldContextSize;
+ ctxt->context->proximityPosition = oldProximityPosition;
+
+
+ cleanup:
+ /* restore the xpath context */
+ if (comp != NULL)
+ xmlXPathFreeCompExpr(comp);
+ if (nodeset != NULL)
+ xmlXPathFreeNodeSet(nodeset);
+ if (str != NULL)
+ xmlFree(str);
+ valuePush(ctxt, ret);
+ return;
+}
+
+
+/**
+ * exsltDynRegister:
+ *
+ * Registers the EXSLT - Dynamic module
+ */
+
+void
+exsltDynRegister (void) {
+ xsltRegisterExtModuleFunction ((const xmlChar *) "evaluate",
+ EXSLT_DYNAMIC_NAMESPACE,
+ exsltDynEvaluateFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "map",
+ EXSLT_DYNAMIC_NAMESPACE,
+ exsltDynMapFunction);
+
+}
diff --git a/libexslt/functions.c b/libexslt/functions.c
index 4d904c9e..2cf7249d 100644
--- a/libexslt/functions.c
+++ b/libexslt/functions.c
@@ -1,729 +1,729 @@
-#define IN_LIBEXSLT
-#include "libexslt/libexslt.h"
-
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
-#include <win32config.h>
-#else
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-#include <libxml/hash.h>
-#include <libxml/debugXML.h>
-
-#include <libxslt/xsltutils.h>
-#include <libxslt/variables.h>
-#include <libxslt/xsltInternals.h>
-#include <libxslt/extensions.h>
-#include <libxslt/transform.h>
-#include <libxslt/imports.h>
-
-#include "exslt.h"
-
-typedef struct _exsltFuncFunctionData exsltFuncFunctionData;
-struct _exsltFuncFunctionData {
- int nargs; /* number of arguments to the function */
- xmlNodePtr content; /* the func:fuction template content */
-};
-
-typedef struct _exsltFuncData exsltFuncData;
-struct _exsltFuncData {
- xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
- xmlXPathObjectPtr result; /* returned by func:result */
- int error; /* did an error occur? */
- xmlDocPtr RVT; /* result tree fragment */
-};
-
-typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
-struct _exsltFuncResultPreComp {
- xsltElemPreComp comp;
- xmlXPathCompExprPtr select;
- xmlNsPtr *nsList;
- int nsNr;
-};
-
-/* Used for callback function in exsltInitFunc */
-typedef struct _exsltFuncImportRegData exsltFuncImportRegData;
-struct _exsltFuncImportRegData {
- xsltTransformContextPtr ctxt;
- xmlHashTablePtr hash;
-};
-
-static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
- int nargs);
-static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
-
-static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";
-
-/**
- * exsltFuncRegisterFunc:
- * @func: the #exsltFuncFunctionData for the function
- * @ctxt: an XSLT transformation context
- * @URI: the function namespace URI
- * @name: the function name
- *
- * Registers a function declared by a func:function element
- */
-static void
-exsltFuncRegisterFunc (exsltFuncFunctionData *data,
- xsltTransformContextPtr ctxt,
- const xmlChar *URI, const xmlChar *name,
- ATTRIBUTE_UNUSED const xmlChar *ignored) {
- if ((data == NULL) || (ctxt == NULL) || (URI == NULL) || (name == NULL))
- return;
-
- xsltGenericDebug(xsltGenericDebugContext,
- "exsltFuncRegisterFunc: register {%s}%s\n",
- URI, name);
- xsltRegisterExtFunction(ctxt, name, URI,
- exsltFuncFunctionFunction);
-}
-
-/*
- * exsltFuncRegisterImportFunc
- * @data: the exsltFuncFunctionData for the function
- * @ch: structure containing context and hash table
- * @URI: the function namespace URI
- * @name: the function name
- *
- * Checks if imported function is already registered in top-level
- * stylesheet. If not, copies function data and registers function
- */
-static void
-exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
- exsltFuncImportRegData *ch,
- const xmlChar *URI, const xmlChar *name,
- ATTRIBUTE_UNUSED const xmlChar *ignored) {
- exsltFuncFunctionData *func=NULL;
-
- if ((data == NULL) || (ch == NULL) || (URI == NULL) || (name == NULL))
- return;
-
- if (ch->ctxt == NULL || ch->hash == NULL)
- return;
-
- /* Check if already present */
- func = (exsltFuncFunctionData*)xmlHashLookup2(ch->hash, URI, name);
- if (func == NULL) { /* Not yet present - copy it in */
- func = exsltFuncNewFunctionData();
- memcpy(func, data, sizeof(exsltFuncFunctionData));
- if (xmlHashAddEntry2(ch->hash, URI, name, func) < 0) {
- xsltGenericError(xsltGenericErrorContext,
- "Failed to register function {%s}%s\n",
- URI, name);
- } else { /* Do the registration */
- xsltGenericDebug(xsltGenericDebugContext,
- "exsltFuncRegisterImportFunc: register {%s}%s\n",
- URI, name);
- xsltRegisterExtFunction(ch->ctxt, name, URI,
- exsltFuncFunctionFunction);
- }
- }
-}
-
-/**
- * exsltFuncInit:
- * @ctxt: an XSLT transformation context
- * @URI: the namespace URI for the extension
- *
- * Initializes the EXSLT - Functions module.
- * Called at transformation-time; merges all
- * functions declared in the import tree taking
- * import precedence into account, i.e. overriding
- * functions with lower import precedence.
- *
- * Returns the data for this transformation
- */
-static exsltFuncData *
-exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
- exsltFuncData *ret;
- xsltStylesheetPtr tmp;
- exsltFuncImportRegData ch;
- xmlHashTablePtr hash;
-
- ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));
- if (ret == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncInit: not enough memory\n");
- return(NULL);
- }
- memset(ret, 0, sizeof(exsltFuncData));
-
- ret->result = NULL;
- ret->error = 0;
-
- ch.hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);
- ret->funcs = ch.hash;
- xmlHashScanFull(ch.hash, (xmlHashScannerFull) 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);
- }
- }
-
- return(ret);
-}
-
-/**
- * exsltFuncShutdown:
- * @ctxt: an XSLT transformation context
- * @URI: the namespace URI for the extension
- * @data: the module data to free up
- *
- * Shutdown the EXSLT - Functions module
- * Called at transformation-time.
- */
-static void
-exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
- const xmlChar *URI ATTRIBUTE_UNUSED,
- exsltFuncData *data) {
- if (data->result != NULL)
- xmlXPathFreeObject(data->result);
- xmlFree(data);
-}
-
-/**
- * exsltFuncStyleInit:
- * @style: an XSLT stylesheet
- * @URI: the namespace URI for the extension
- *
- * Allocates the stylesheet data for EXSLT - Function
- * Called at compile-time.
- *
- * Returns the allocated data
- */
-static xmlHashTablePtr
-exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
- const xmlChar *URI ATTRIBUTE_UNUSED) {
- return xmlHashCreate(1);
-}
-
-/**
- * exsltFuncStyleShutdown:
- * @style: an XSLT stylesheet
- * @URI: the namespace URI for the extension
- * @data: the stylesheet data to free up
- *
- * Shutdown the EXSLT - Function module
- * Called at compile-time.
- */
-static void
-exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
- const xmlChar *URI ATTRIBUTE_UNUSED,
- xmlHashTablePtr data) {
- xmlHashFree(data, (xmlHashDeallocator) xmlFree);
-}
-
-/**
- * exsltFuncNewFunctionData:
- *
- * Allocates an #exslFuncFunctionData object
- *
- * Returns the new structure
- */
-static exsltFuncFunctionData *
-exsltFuncNewFunctionData (void) {
- exsltFuncFunctionData *ret;
-
- ret = (exsltFuncFunctionData *) xmlMalloc (sizeof(exsltFuncFunctionData));
- if (ret == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncNewFunctionData: not enough memory\n");
- return (NULL);
- }
- memset(ret, 0, sizeof(exsltFuncFunctionData));
-
- ret->nargs = 0;
- ret->content = NULL;
-
- return(ret);
-}
-
-/**
- * exsltFreeFuncResultPreComp:
- * @comp: the #exsltFuncResultPreComp to free up
- *
- * Deallocates an #exsltFuncResultPreComp
- */
-static void
-exsltFreeFuncResultPreComp (exsltFuncResultPreComp *comp) {
- if (comp == NULL)
- return;
-
- if (comp->select != NULL)
- xmlXPathFreeCompExpr (comp->select);
- if (comp->nsList != NULL)
- xmlFree(comp->nsList);
- xmlFree(comp);
-}
-
-/**
- * exsltFuncFunctionFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Evaluates the func:function element that defines the called function.
- */
-static void
-exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
- xmlXPathObjectPtr obj, oldResult, ret;
- exsltFuncData *data;
- exsltFuncFunctionData *func;
- xmlNodePtr paramNode, oldInsert, fake;
- int oldBase;
- xsltStackElemPtr params = NULL, param;
- xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
- int i;
-
- /*
- * retrieve func:function template
- */
- data = (exsltFuncData *) xsltGetExtData (tctxt,
- EXSLT_FUNCTIONS_NAMESPACE);
- oldResult = data->result;
- data->result = NULL;
-
- func = (exsltFuncFunctionData*) xmlHashLookup2 (data->funcs,
- ctxt->context->functionURI,
- ctxt->context->function);
-
- /*
- * params handling
- */
- if (nargs > func->nargs) {
- xsltGenericError(xsltGenericErrorContext,
- "{%s}%s: called with too many arguments\n",
- ctxt->context->functionURI, ctxt->context->function);
- ctxt->error = XPATH_INVALID_ARITY;
- return;
- }
- if (func->content != NULL) {
- paramNode = func->content->prev;
- }
- else
- paramNode = NULL;
- if ((paramNode == NULL) && (func->nargs != 0)) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncFunctionFunction: nargs != 0 and "
- "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--) {
- /*
- * 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);
- /*
- * 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;
- }
-
- /*
- * actual processing
- */
- fake = xmlNewDocNode(tctxt->output, NULL,
- (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);
- tctxt->insert = oldInsert;
- tctxt->varsBase = oldBase; /* restore original scope */
- if (params != NULL)
- xsltFreeStackElemList(params);
-
- if (data->error != 0)
- goto error;
-
- if (data->result != NULL) {
- ret = data->result;
- } else
- ret = xmlXPathNewCString("");
-
- data->result = oldResult;
-
- /*
- * It is an error if the instantiation of the template results in
- * the generation of result nodes.
- */
- if (fake->children != NULL) {
-#ifdef LIBXML_DEBUG_ENABLED
- xmlDebugDumpNode (stderr, fake, 1);
-#endif
- xsltGenericError(xsltGenericErrorContext,
- "{%s}%s: cannot write to result tree while "
- "executing a function\n",
- ctxt->context->functionURI, ctxt->context->function);
- xmlFreeNode(fake);
- goto error;
- }
- xmlFreeNode(fake);
- valuePush(ctxt, ret);
-
-error:
- /*
- * IMPORTANT: This enables previously tree fragments marked as
- * being results of a function, to be garbage-collected after
- * the calling process exits.
- */
- xsltExtensionInstructionResultFinalize(tctxt);
-}
-
-
-static void
-exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
- xmlChar *name, *prefix;
- xmlNsPtr ns;
- xmlHashTablePtr data;
- exsltFuncFunctionData *func;
-
- if ((style == NULL) || (inst == NULL))
- return;
-
-
- {
- xmlChar *qname;
-
- qname = xmlGetProp(inst, (const xmlChar *) "name");
- name = xmlSplitQName2 (qname, &prefix);
- xmlFree(qname);
- }
- if ((name == NULL) || (prefix == NULL)) {
- xsltGenericError(xsltGenericErrorContext,
- "func:function: not a QName\n");
- if (name != NULL)
- xmlFree(name);
- return;
- }
- /* namespace lookup */
- ns = xmlSearchNs (inst->doc, inst, prefix);
- if (ns == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "func:function: undeclared prefix %s\n",
- prefix);
- xmlFree(name);
- xmlFree(prefix);
- return;
- }
- xmlFree(prefix);
-
- /*
- * Create function data
- */
- func = exsltFuncNewFunctionData();
- func->content = inst->children;
- while (IS_XSLT_ELEM(func->content) &&
- IS_XSLT_NAME(func->content, "param")) {
- func->content = func->content->next;
- func->nargs++;
- }
-
- xsltParseTemplateContent(style, inst);
-
- /*
- * Register the function data such that it can be retrieved
- * by exslFuncFunctionFunction
- */
-#ifdef XSLT_REFACTORED
- /*
- * Ensure that the hash table will be stored in the *current*
- * stylesheet level in order to correctly evaluate the
- * import precedence.
- */
- data = (xmlHashTablePtr)
- xsltStyleStylesheetLevelGetExtData(style,
- EXSLT_FUNCTIONS_NAMESPACE);
-#else
- data = (xmlHashTablePtr)
- xsltStyleGetExtData (style, EXSLT_FUNCTIONS_NAMESPACE);
-#endif
- if (data == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncFunctionComp: no stylesheet data\n");
- xmlFree(name);
- return;
- }
-
- if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {
- xsltTransformError(NULL, style, inst,
- "Failed to register function {%s}%s\n",
- ns->href, name);
- style->errors++;
- } else {
- xsltGenericDebug(xsltGenericDebugContext,
- "exsltFuncFunctionComp: register {%s}%s\n",
- ns->href, name);
- }
- xmlFree(name);
-}
-
-static xsltElemPreCompPtr
-exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
- xsltTransformFunction function) {
- xmlNodePtr test;
- xmlChar *sel;
- exsltFuncResultPreComp *ret;
-
- /*
- * "Validity" checking
- */
- /* it is an error to have any following sibling elements aside
- * from the xsl:fallback element.
- */
- for (test = inst->next; test != NULL; test = test->next) {
- if (test->type != XML_ELEMENT_NODE)
- continue;
- if (IS_XSLT_ELEM(test) && IS_XSLT_NAME(test, "fallback"))
- continue;
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncResultElem: only xsl:fallback is "
- "allowed to follow func:result\n");
- return (NULL);
- }
- /* it is an error for a func:result element to not be a descendant
- * of func:function.
- * it is an error if a func:result occurs within a func:result
- * element.
- * it is an error if instanciating the content of a variable
- * binding element (i.e. xsl:variable, xsl:param) results in the
- * instanciation of a func:result element.
- */
- for (test = inst->parent; test != NULL; test = test->parent) {
- if ((test->ns != NULL) &&
- (xmlStrEqual(test->ns->href, EXSLT_FUNCTIONS_NAMESPACE))) {
- if (xmlStrEqual(test->name, (const xmlChar *) "function")) {
- break;
- }
- if (xmlStrEqual(test->name, (const xmlChar *) "result")) {
- xsltGenericError(xsltGenericErrorContext,
- "func:result element not allowed within"
- " another func:result element\n");
- return (NULL);
- }
- }
- if (IS_XSLT_ELEM(test) &&
- (IS_XSLT_NAME(test, "variable") ||
- IS_XSLT_NAME(test, "param"))) {
- xsltGenericError(xsltGenericErrorContext,
- "func:result element not allowed within"
- " a variable binding element\n");
- return (NULL);
- }
- }
-
- /*
- * Precomputation
- */
- ret = (exsltFuncResultPreComp *)
- xmlMalloc (sizeof(exsltFuncResultPreComp));
- if (ret == NULL) {
- xsltPrintErrorContext(NULL, NULL, NULL);
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncResultComp : malloc failed\n");
- return (NULL);
- }
- memset(ret, 0, sizeof(exsltFuncResultPreComp));
-
- xsltInitElemPreComp ((xsltElemPreCompPtr) ret, style, inst, function,
- (xsltElemPreCompDeallocator) exsltFreeFuncResultPreComp);
- ret->select = NULL;
-
- /*
- * Precompute the select attribute
- */
- sel = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);
- if (sel != NULL) {
- ret->select = xmlXPathCompile (sel);
- xmlFree(sel);
- }
- /*
- * Precompute the namespace list
- */
- ret->nsList = xmlGetNsList(inst->doc, inst);
- if (ret->nsList != NULL) {
- int i = 0;
- while (ret->nsList[i] != NULL)
- i++;
- ret->nsNr = i;
- }
- return ((xsltElemPreCompPtr) ret);
-}
-
-static void
-exsltFuncResultElem (xsltTransformContextPtr ctxt,
- xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
- exsltFuncResultPreComp *comp) {
- exsltFuncData *data;
- xmlXPathObjectPtr ret;
-
-
- /* It is an error if instantiating the content of the
- * func:function element results in the instantiation of more than
- * one func:result elements.
- */
- data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE);
- if (data == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncReturnElem: data == NULL\n");
- return;
- }
- if (data->result != NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "func:result already instanciated\n");
- data->error = 1;
- return;
- }
- /*
- * Processing
- */
- if (comp->select != NULL) {
- xmlNsPtr *oldXPNsList;
- int oldXPNsNr;
- xmlNodePtr oldXPContextNode;
- /* If the func:result element has a select attribute, then the
- * value of the attribute must be an expression and the
- * returned value is the object that results from evaluating
- * the expression. In this case, the content must be empty.
- */
- if (inst->children != NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "func:result content must be empty if it"
- " has a select attribute\n");
- data->error = 1;
- return;
- }
- oldXPNsList = ctxt->xpathCtxt->namespaces;
- oldXPNsNr = ctxt->xpathCtxt->nsNr;
- oldXPContextNode = ctxt->xpathCtxt->node;
-
- ctxt->xpathCtxt->namespaces = comp->nsList;
- ctxt->xpathCtxt->nsNr = comp->nsNr;
-
- ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
-
- ctxt->xpathCtxt->node = oldXPContextNode;
- ctxt->xpathCtxt->nsNr = oldXPNsNr;
- ctxt->xpathCtxt->namespaces = oldXPNsList;
-
- if (ret == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncResultElem: ret == NULL\n");
- return;
- }
- /*
- * Mark it as a function result in order to avoid garbage
- * collecting of tree fragments before the function exits.
- */
- xsltExtensionInstructionResultRegister(ctxt, ret);
- } else if (inst->children != NULL) {
- /* If the func:result element does not have a select attribute
- * and has non-empty content (i.e. the func:result element has
- * one or more child nodes), then the content of the
- * func:result element specifies the value.
- */
- xmlNodePtr oldInsert;
- xmlDocPtr container;
-
- container = xsltCreateRVT(ctxt);
- if (container == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncResultElem: out of memory\n");
- data->error = 1;
- return;
- }
- xsltRegisterLocalRVT(ctxt, container);
-
- oldInsert = ctxt->insert;
- ctxt->insert = (xmlNodePtr) container;
- xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
- inst->children, NULL, NULL);
- ctxt->insert = oldInsert;
-
- ret = xmlXPathNewValueTree((xmlNodePtr) container);
- if (ret == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltFuncResultElem: ret == NULL\n");
- data->error = 1;
- } else {
- ret->boolval = 0; /* Freeing is not handled there anymore */
- /*
- * Mark it as a function result in order to avoid garbage
- * collecting of tree fragments before the function exits.
- */
- xsltExtensionInstructionResultRegister(ctxt, ret);
- }
- } else {
- /* If the func:result element has empty content and does not
- * have a select attribute, then the returned value is an
- * empty string.
- */
- ret = xmlXPathNewCString("");
- }
- data->result = ret;
-}
-
-/**
- * exsltFuncRegister:
- *
- * Registers the EXSLT - Functions module
- */
-void
-exsltFuncRegister (void) {
- xsltRegisterExtModuleFull (EXSLT_FUNCTIONS_NAMESPACE,
- (xsltExtInitFunction) exsltFuncInit,
- (xsltExtShutdownFunction) exsltFuncShutdown,
- (xsltStyleExtInitFunction) exsltFuncStyleInit,
- (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown);
-
- xsltRegisterExtModuleTopLevel ((const xmlChar *) "function",
- EXSLT_FUNCTIONS_NAMESPACE,
- exsltFuncFunctionComp);
- xsltRegisterExtModuleElement ((const xmlChar *) "result",
- EXSLT_FUNCTIONS_NAMESPACE,
- (xsltPreComputeFunction)exsltFuncResultComp,
- (xsltTransformFunction) exsltFuncResultElem);
-}
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/hash.h>
+#include <libxml/debugXML.h>
+
+#include <libxslt/xsltutils.h>
+#include <libxslt/variables.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+#include <libxslt/transform.h>
+#include <libxslt/imports.h>
+
+#include "exslt.h"
+
+typedef struct _exsltFuncFunctionData exsltFuncFunctionData;
+struct _exsltFuncFunctionData {
+ int nargs; /* number of arguments to the function */
+ xmlNodePtr content; /* the func:fuction template content */
+};
+
+typedef struct _exsltFuncData exsltFuncData;
+struct _exsltFuncData {
+ xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
+ xmlXPathObjectPtr result; /* returned by func:result */
+ int error; /* did an error occur? */
+ xmlDocPtr RVT; /* result tree fragment */
+};
+
+typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
+struct _exsltFuncResultPreComp {
+ xsltElemPreComp comp;
+ xmlXPathCompExprPtr select;
+ xmlNsPtr *nsList;
+ int nsNr;
+};
+
+/* Used for callback function in exsltInitFunc */
+typedef struct _exsltFuncImportRegData exsltFuncImportRegData;
+struct _exsltFuncImportRegData {
+ xsltTransformContextPtr ctxt;
+ xmlHashTablePtr hash;
+};
+
+static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
+ int nargs);
+static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
+
+static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";
+
+/**
+ * exsltFuncRegisterFunc:
+ * @func: the #exsltFuncFunctionData for the function
+ * @ctxt: an XSLT transformation context
+ * @URI: the function namespace URI
+ * @name: the function name
+ *
+ * Registers a function declared by a func:function element
+ */
+static void
+exsltFuncRegisterFunc (exsltFuncFunctionData *data,
+ xsltTransformContextPtr ctxt,
+ const xmlChar *URI, const xmlChar *name,
+ ATTRIBUTE_UNUSED const xmlChar *ignored) {
+ if ((data == NULL) || (ctxt == NULL) || (URI == NULL) || (name == NULL))
+ return;
+
+ xsltGenericDebug(xsltGenericDebugContext,
+ "exsltFuncRegisterFunc: register {%s}%s\n",
+ URI, name);
+ xsltRegisterExtFunction(ctxt, name, URI,
+ exsltFuncFunctionFunction);
+}
+
+/*
+ * exsltFuncRegisterImportFunc
+ * @data: the exsltFuncFunctionData for the function
+ * @ch: structure containing context and hash table
+ * @URI: the function namespace URI
+ * @name: the function name
+ *
+ * Checks if imported function is already registered in top-level
+ * stylesheet. If not, copies function data and registers function
+ */
+static void
+exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
+ exsltFuncImportRegData *ch,
+ const xmlChar *URI, const xmlChar *name,
+ ATTRIBUTE_UNUSED const xmlChar *ignored) {
+ exsltFuncFunctionData *func=NULL;
+
+ if ((data == NULL) || (ch == NULL) || (URI == NULL) || (name == NULL))
+ return;
+
+ if (ch->ctxt == NULL || ch->hash == NULL)
+ return;
+
+ /* Check if already present */
+ func = (exsltFuncFunctionData*)xmlHashLookup2(ch->hash, URI, name);
+ if (func == NULL) { /* Not yet present - copy it in */
+ func = exsltFuncNewFunctionData();
+ memcpy(func, data, sizeof(exsltFuncFunctionData));
+ if (xmlHashAddEntry2(ch->hash, URI, name, func) < 0) {
+ xsltGenericError(xsltGenericErrorContext,
+ "Failed to register function {%s}%s\n",
+ URI, name);
+ } else { /* Do the registration */
+ xsltGenericDebug(xsltGenericDebugContext,
+ "exsltFuncRegisterImportFunc: register {%s}%s\n",
+ URI, name);
+ xsltRegisterExtFunction(ch->ctxt, name, URI,
+ exsltFuncFunctionFunction);
+ }
+ }
+}
+
+/**
+ * exsltFuncInit:
+ * @ctxt: an XSLT transformation context
+ * @URI: the namespace URI for the extension
+ *
+ * Initializes the EXSLT - Functions module.
+ * Called at transformation-time; merges all
+ * functions declared in the import tree taking
+ * import precedence into account, i.e. overriding
+ * functions with lower import precedence.
+ *
+ * Returns the data for this transformation
+ */
+static exsltFuncData *
+exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
+ exsltFuncData *ret;
+ xsltStylesheetPtr tmp;
+ exsltFuncImportRegData ch;
+ xmlHashTablePtr hash;
+
+ ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));
+ if (ret == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncInit: not enough memory\n");
+ return(NULL);
+ }
+ memset(ret, 0, sizeof(exsltFuncData));
+
+ ret->result = NULL;
+ ret->error = 0;
+
+ ch.hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);
+ ret->funcs = ch.hash;
+ xmlHashScanFull(ch.hash, (xmlHashScannerFull) 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);
+ }
+ }
+
+ return(ret);
+}
+
+/**
+ * exsltFuncShutdown:
+ * @ctxt: an XSLT transformation context
+ * @URI: the namespace URI for the extension
+ * @data: the module data to free up
+ *
+ * Shutdown the EXSLT - Functions module
+ * Called at transformation-time.
+ */
+static void
+exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
+ const xmlChar *URI ATTRIBUTE_UNUSED,
+ exsltFuncData *data) {
+ if (data->result != NULL)
+ xmlXPathFreeObject(data->result);
+ xmlFree(data);
+}
+
+/**
+ * exsltFuncStyleInit:
+ * @style: an XSLT stylesheet
+ * @URI: the namespace URI for the extension
+ *
+ * Allocates the stylesheet data for EXSLT - Function
+ * Called at compile-time.
+ *
+ * Returns the allocated data
+ */
+static xmlHashTablePtr
+exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
+ const xmlChar *URI ATTRIBUTE_UNUSED) {
+ return xmlHashCreate(1);
+}
+
+/**
+ * exsltFuncStyleShutdown:
+ * @style: an XSLT stylesheet
+ * @URI: the namespace URI for the extension
+ * @data: the stylesheet data to free up
+ *
+ * Shutdown the EXSLT - Function module
+ * Called at compile-time.
+ */
+static void
+exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
+ const xmlChar *URI ATTRIBUTE_UNUSED,
+ xmlHashTablePtr data) {
+ xmlHashFree(data, (xmlHashDeallocator) xmlFree);
+}
+
+/**
+ * exsltFuncNewFunctionData:
+ *
+ * Allocates an #exslFuncFunctionData object
+ *
+ * Returns the new structure
+ */
+static exsltFuncFunctionData *
+exsltFuncNewFunctionData (void) {
+ exsltFuncFunctionData *ret;
+
+ ret = (exsltFuncFunctionData *) xmlMalloc (sizeof(exsltFuncFunctionData));
+ if (ret == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncNewFunctionData: not enough memory\n");
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(exsltFuncFunctionData));
+
+ ret->nargs = 0;
+ ret->content = NULL;
+
+ return(ret);
+}
+
+/**
+ * exsltFreeFuncResultPreComp:
+ * @comp: the #exsltFuncResultPreComp to free up
+ *
+ * Deallocates an #exsltFuncResultPreComp
+ */
+static void
+exsltFreeFuncResultPreComp (exsltFuncResultPreComp *comp) {
+ if (comp == NULL)
+ return;
+
+ if (comp->select != NULL)
+ xmlXPathFreeCompExpr (comp->select);
+ if (comp->nsList != NULL)
+ xmlFree(comp->nsList);
+ xmlFree(comp);
+}
+
+/**
+ * exsltFuncFunctionFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Evaluates the func:function element that defines the called function.
+ */
+static void
+exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlXPathObjectPtr obj, oldResult, ret;
+ exsltFuncData *data;
+ exsltFuncFunctionData *func;
+ xmlNodePtr paramNode, oldInsert, fake;
+ int oldBase;
+ xsltStackElemPtr params = NULL, param;
+ xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
+ int i;
+
+ /*
+ * retrieve func:function template
+ */
+ data = (exsltFuncData *) xsltGetExtData (tctxt,
+ EXSLT_FUNCTIONS_NAMESPACE);
+ oldResult = data->result;
+ data->result = NULL;
+
+ func = (exsltFuncFunctionData*) xmlHashLookup2 (data->funcs,
+ ctxt->context->functionURI,
+ ctxt->context->function);
+
+ /*
+ * params handling
+ */
+ if (nargs > func->nargs) {
+ xsltGenericError(xsltGenericErrorContext,
+ "{%s}%s: called with too many arguments\n",
+ ctxt->context->functionURI, ctxt->context->function);
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ if (func->content != NULL) {
+ paramNode = func->content->prev;
+ }
+ else
+ paramNode = NULL;
+ if ((paramNode == NULL) && (func->nargs != 0)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncFunctionFunction: nargs != 0 and "
+ "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--) {
+ /*
+ * 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);
+ /*
+ * 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;
+ }
+
+ /*
+ * actual processing
+ */
+ fake = xmlNewDocNode(tctxt->output, NULL,
+ (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);
+ tctxt->insert = oldInsert;
+ tctxt->varsBase = oldBase; /* restore original scope */
+ if (params != NULL)
+ xsltFreeStackElemList(params);
+
+ if (data->error != 0)
+ goto error;
+
+ if (data->result != NULL) {
+ ret = data->result;
+ } else
+ ret = xmlXPathNewCString("");
+
+ data->result = oldResult;
+
+ /*
+ * It is an error if the instantiation of the template results in
+ * the generation of result nodes.
+ */
+ if (fake->children != NULL) {
+#ifdef LIBXML_DEBUG_ENABLED
+ xmlDebugDumpNode (stderr, fake, 1);
+#endif
+ xsltGenericError(xsltGenericErrorContext,
+ "{%s}%s: cannot write to result tree while "
+ "executing a function\n",
+ ctxt->context->functionURI, ctxt->context->function);
+ xmlFreeNode(fake);
+ goto error;
+ }
+ xmlFreeNode(fake);
+ valuePush(ctxt, ret);
+
+error:
+ /*
+ * IMPORTANT: This enables previously tree fragments marked as
+ * being results of a function, to be garbage-collected after
+ * the calling process exits.
+ */
+ xsltExtensionInstructionResultFinalize(tctxt);
+}
+
+
+static void
+exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
+ xmlChar *name, *prefix;
+ xmlNsPtr ns;
+ xmlHashTablePtr data;
+ exsltFuncFunctionData *func;
+
+ if ((style == NULL) || (inst == NULL))
+ return;
+
+
+ {
+ xmlChar *qname;
+
+ qname = xmlGetProp(inst, (const xmlChar *) "name");
+ name = xmlSplitQName2 (qname, &prefix);
+ xmlFree(qname);
+ }
+ if ((name == NULL) || (prefix == NULL)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "func:function: not a QName\n");
+ if (name != NULL)
+ xmlFree(name);
+ return;
+ }
+ /* namespace lookup */
+ ns = xmlSearchNs (inst->doc, inst, prefix);
+ if (ns == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "func:function: undeclared prefix %s\n",
+ prefix);
+ xmlFree(name);
+ xmlFree(prefix);
+ return;
+ }
+ xmlFree(prefix);
+
+ /*
+ * Create function data
+ */
+ func = exsltFuncNewFunctionData();
+ func->content = inst->children;
+ while (IS_XSLT_ELEM(func->content) &&
+ IS_XSLT_NAME(func->content, "param")) {
+ func->content = func->content->next;
+ func->nargs++;
+ }
+
+ xsltParseTemplateContent(style, inst);
+
+ /*
+ * Register the function data such that it can be retrieved
+ * by exslFuncFunctionFunction
+ */
+#ifdef XSLT_REFACTORED
+ /*
+ * Ensure that the hash table will be stored in the *current*
+ * stylesheet level in order to correctly evaluate the
+ * import precedence.
+ */
+ data = (xmlHashTablePtr)
+ xsltStyleStylesheetLevelGetExtData(style,
+ EXSLT_FUNCTIONS_NAMESPACE);
+#else
+ data = (xmlHashTablePtr)
+ xsltStyleGetExtData (style, EXSLT_FUNCTIONS_NAMESPACE);
+#endif
+ if (data == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncFunctionComp: no stylesheet data\n");
+ xmlFree(name);
+ return;
+ }
+
+ if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {
+ xsltTransformError(NULL, style, inst,
+ "Failed to register function {%s}%s\n",
+ ns->href, name);
+ style->errors++;
+ } else {
+ xsltGenericDebug(xsltGenericDebugContext,
+ "exsltFuncFunctionComp: register {%s}%s\n",
+ ns->href, name);
+ }
+ xmlFree(name);
+}
+
+static xsltElemPreCompPtr
+exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
+ xsltTransformFunction function) {
+ xmlNodePtr test;
+ xmlChar *sel;
+ exsltFuncResultPreComp *ret;
+
+ /*
+ * "Validity" checking
+ */
+ /* it is an error to have any following sibling elements aside
+ * from the xsl:fallback element.
+ */
+ for (test = inst->next; test != NULL; test = test->next) {
+ if (test->type != XML_ELEMENT_NODE)
+ continue;
+ if (IS_XSLT_ELEM(test) && IS_XSLT_NAME(test, "fallback"))
+ continue;
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncResultElem: only xsl:fallback is "
+ "allowed to follow func:result\n");
+ return (NULL);
+ }
+ /* it is an error for a func:result element to not be a descendant
+ * of func:function.
+ * it is an error if a func:result occurs within a func:result
+ * element.
+ * it is an error if instanciating the content of a variable
+ * binding element (i.e. xsl:variable, xsl:param) results in the
+ * instanciation of a func:result element.
+ */
+ for (test = inst->parent; test != NULL; test = test->parent) {
+ if ((test->ns != NULL) &&
+ (xmlStrEqual(test->ns->href, EXSLT_FUNCTIONS_NAMESPACE))) {
+ if (xmlStrEqual(test->name, (const xmlChar *) "function")) {
+ break;
+ }
+ if (xmlStrEqual(test->name, (const xmlChar *) "result")) {
+ xsltGenericError(xsltGenericErrorContext,
+ "func:result element not allowed within"
+ " another func:result element\n");
+ return (NULL);
+ }
+ }
+ if (IS_XSLT_ELEM(test) &&
+ (IS_XSLT_NAME(test, "variable") ||
+ IS_XSLT_NAME(test, "param"))) {
+ xsltGenericError(xsltGenericErrorContext,
+ "func:result element not allowed within"
+ " a variable binding element\n");
+ return (NULL);
+ }
+ }
+
+ /*
+ * Precomputation
+ */
+ ret = (exsltFuncResultPreComp *)
+ xmlMalloc (sizeof(exsltFuncResultPreComp));
+ if (ret == NULL) {
+ xsltPrintErrorContext(NULL, NULL, NULL);
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncResultComp : malloc failed\n");
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(exsltFuncResultPreComp));
+
+ xsltInitElemPreComp ((xsltElemPreCompPtr) ret, style, inst, function,
+ (xsltElemPreCompDeallocator) exsltFreeFuncResultPreComp);
+ ret->select = NULL;
+
+ /*
+ * Precompute the select attribute
+ */
+ sel = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);
+ if (sel != NULL) {
+ ret->select = xmlXPathCompile (sel);
+ xmlFree(sel);
+ }
+ /*
+ * Precompute the namespace list
+ */
+ ret->nsList = xmlGetNsList(inst->doc, inst);
+ if (ret->nsList != NULL) {
+ int i = 0;
+ while (ret->nsList[i] != NULL)
+ i++;
+ ret->nsNr = i;
+ }
+ return ((xsltElemPreCompPtr) ret);
+}
+
+static void
+exsltFuncResultElem (xsltTransformContextPtr ctxt,
+ xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
+ exsltFuncResultPreComp *comp) {
+ exsltFuncData *data;
+ xmlXPathObjectPtr ret;
+
+
+ /* It is an error if instantiating the content of the
+ * func:function element results in the instantiation of more than
+ * one func:result elements.
+ */
+ data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE);
+ if (data == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncReturnElem: data == NULL\n");
+ return;
+ }
+ if (data->result != NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "func:result already instanciated\n");
+ data->error = 1;
+ return;
+ }
+ /*
+ * Processing
+ */
+ if (comp->select != NULL) {
+ xmlNsPtr *oldXPNsList;
+ int oldXPNsNr;
+ xmlNodePtr oldXPContextNode;
+ /* If the func:result element has a select attribute, then the
+ * value of the attribute must be an expression and the
+ * returned value is the object that results from evaluating
+ * the expression. In this case, the content must be empty.
+ */
+ if (inst->children != NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "func:result content must be empty if it"
+ " has a select attribute\n");
+ data->error = 1;
+ return;
+ }
+ oldXPNsList = ctxt->xpathCtxt->namespaces;
+ oldXPNsNr = ctxt->xpathCtxt->nsNr;
+ oldXPContextNode = ctxt->xpathCtxt->node;
+
+ ctxt->xpathCtxt->namespaces = comp->nsList;
+ ctxt->xpathCtxt->nsNr = comp->nsNr;
+
+ ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
+
+ ctxt->xpathCtxt->node = oldXPContextNode;
+ ctxt->xpathCtxt->nsNr = oldXPNsNr;
+ ctxt->xpathCtxt->namespaces = oldXPNsList;
+
+ if (ret == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncResultElem: ret == NULL\n");
+ return;
+ }
+ /*
+ * Mark it as a function result in order to avoid garbage
+ * collecting of tree fragments before the function exits.
+ */
+ xsltExtensionInstructionResultRegister(ctxt, ret);
+ } else if (inst->children != NULL) {
+ /* If the func:result element does not have a select attribute
+ * and has non-empty content (i.e. the func:result element has
+ * one or more child nodes), then the content of the
+ * func:result element specifies the value.
+ */
+ xmlNodePtr oldInsert;
+ xmlDocPtr container;
+
+ container = xsltCreateRVT(ctxt);
+ if (container == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncResultElem: out of memory\n");
+ data->error = 1;
+ return;
+ }
+ xsltRegisterLocalRVT(ctxt, container);
+
+ oldInsert = ctxt->insert;
+ ctxt->insert = (xmlNodePtr) container;
+ xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
+ inst->children, NULL, NULL);
+ ctxt->insert = oldInsert;
+
+ ret = xmlXPathNewValueTree((xmlNodePtr) container);
+ if (ret == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltFuncResultElem: ret == NULL\n");
+ data->error = 1;
+ } else {
+ ret->boolval = 0; /* Freeing is not handled there anymore */
+ /*
+ * Mark it as a function result in order to avoid garbage
+ * collecting of tree fragments before the function exits.
+ */
+ xsltExtensionInstructionResultRegister(ctxt, ret);
+ }
+ } else {
+ /* If the func:result element has empty content and does not
+ * have a select attribute, then the returned value is an
+ * empty string.
+ */
+ ret = xmlXPathNewCString("");
+ }
+ data->result = ret;
+}
+
+/**
+ * exsltFuncRegister:
+ *
+ * Registers the EXSLT - Functions module
+ */
+void
+exsltFuncRegister (void) {
+ xsltRegisterExtModuleFull (EXSLT_FUNCTIONS_NAMESPACE,
+ (xsltExtInitFunction) exsltFuncInit,
+ (xsltExtShutdownFunction) exsltFuncShutdown,
+ (xsltStyleExtInitFunction) exsltFuncStyleInit,
+ (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown);
+
+ xsltRegisterExtModuleTopLevel ((const xmlChar *) "function",
+ EXSLT_FUNCTIONS_NAMESPACE,
+ exsltFuncFunctionComp);
+ xsltRegisterExtModuleElement ((const xmlChar *) "result",
+ EXSLT_FUNCTIONS_NAMESPACE,
+ (xsltPreComputeFunction)exsltFuncResultComp,
+ (xsltTransformFunction) exsltFuncResultElem);
+}
diff --git a/libexslt/strings.c b/libexslt/strings.c
index 484310a8..c867f9cb 100644
--- a/libexslt/strings.c
+++ b/libexslt/strings.c
@@ -1,526 +1,526 @@
-#define IN_LIBEXSLT
-#include "libexslt/libexslt.h"
-
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
-#include <win32config.h>
-#else
-#include "config.h"
-#endif
-
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-#include <libxml/parser.h>
-#include <libxml/encoding.h>
-#include <libxml/uri.h>
-
-#include <libxslt/xsltconfig.h>
-#include <libxslt/xsltutils.h>
-#include <libxslt/xsltInternals.h>
-#include <libxslt/extensions.h>
-
-#include "exslt.h"
-
-/**
- * exsltStrTokenizeFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Splits up a string on the characters of the delimiter string and returns a
- * node set of token elements, each containing one token from the string.
- */
-static void
-exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
-{
- xsltTransformContextPtr tctxt;
- xmlChar *str, *delimiters, *cur;
- const xmlChar *token, *delimiter;
- xmlNodePtr node;
- xmlDocPtr container;
- xmlXPathObjectPtr ret = NULL;
- int clen;
-
- if ((nargs < 1) || (nargs > 2)) {
- xmlXPathSetArityError(ctxt);
- return;
- }
-
- if (nargs == 2) {
- delimiters = xmlXPathPopString(ctxt);
- if (xmlXPathCheckError(ctxt))
- return;
- } else {
- delimiters = xmlStrdup((const xmlChar *) "\t\r\n ");
- }
- if (delimiters == NULL)
- return;
-
- str = xmlXPathPopString(ctxt);
- if (xmlXPathCheckError(ctxt) || (str == NULL)) {
- xmlFree(delimiters);
- return;
- }
-
- /* Return a result tree fragment */
- tctxt = xsltXPathGetTransformContext(ctxt);
- if (tctxt == NULL) {
- xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
- "exslt:tokenize : internal error tctxt == NULL\n");
- goto fail;
- }
-
- container = xsltCreateRVT(tctxt);
- if (container != NULL) {
- xsltRegisterLocalRVT(tctxt, container);
- ret = xmlXPathNewNodeSet(NULL);
- if (ret != NULL) {
- for (cur = str, token = str; *cur != 0; cur += clen) {
- clen = xmlUTF8Size(cur);
- if (*delimiters == 0) { /* empty string case */
- xmlChar ctmp;
- ctmp = *(cur+clen);
- *(cur+clen) = 0;
- node = xmlNewDocRawNode(container, NULL,
- (const xmlChar *) "token", cur);
- xmlAddChild((xmlNodePtr) container, node);
- xmlXPathNodeSetAddUnique(ret->nodesetval, node);
- *(cur+clen) = ctmp; /* restore the changed byte */
- token = cur + clen;
- } else for (delimiter = delimiters; *delimiter != 0;
- delimiter += xmlUTF8Size(delimiter)) {
- if (!xmlUTF8Charcmp(cur, delimiter)) {
- if (cur == token) {
- /* discard empty tokens */
- token = cur + clen;
- break;
- }
- *cur = 0; /* terminate the token */
- node = xmlNewDocRawNode(container, NULL,
- (const xmlChar *) "token", token);
- xmlAddChild((xmlNodePtr) container, node);
- xmlXPathNodeSetAddUnique(ret->nodesetval, node);
- *cur = *delimiter; /* restore the changed byte */
- token = cur + clen;
- break;
- }
- }
- }
- if (token != cur) {
- node = xmlNewDocRawNode(container, NULL,
- (const xmlChar *) "token", token);
- xmlAddChild((xmlNodePtr) container, node);
- xmlXPathNodeSetAddUnique(ret->nodesetval, node);
- }
- }
- }
-
-fail:
- if (str != NULL)
- xmlFree(str);
- if (delimiters != NULL)
- xmlFree(delimiters);
- if (ret != NULL)
- valuePush(ctxt, ret);
- else
- valuePush(ctxt, xmlXPathNewNodeSet(NULL));
-}
-
-/**
- * exsltStrSplitFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Splits up a string on a delimiting string and returns a node set of token
- * elements, each containing one token from the string.
- */
-static void
-exsltStrSplitFunction(xmlXPathParserContextPtr ctxt, int nargs) {
- xsltTransformContextPtr tctxt;
- xmlChar *str, *delimiter, *cur;
- const xmlChar *token;
- xmlNodePtr node;
- xmlDocPtr container;
- xmlXPathObjectPtr ret = NULL;
- int delimiterLength;
-
- if ((nargs < 1) || (nargs > 2)) {
- xmlXPathSetArityError(ctxt);
- return;
- }
-
- if (nargs == 2) {
- delimiter = xmlXPathPopString(ctxt);
- if (xmlXPathCheckError(ctxt))
- return;
- } else {
- delimiter = xmlStrdup((const xmlChar *) " ");
- }
- if (delimiter == NULL)
- return;
- delimiterLength = xmlStrlen (delimiter);
-
- str = xmlXPathPopString(ctxt);
- if (xmlXPathCheckError(ctxt) || (str == NULL)) {
- xmlFree(delimiter);
- return;
- }
-
- /* Return a result tree fragment */
- tctxt = xsltXPathGetTransformContext(ctxt);
- if (tctxt == NULL) {
- xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
- "exslt:tokenize : internal error tctxt == NULL\n");
- goto fail;
- }
-
- /*
- * OPTIMIZE TODO: We are creating an xmlDoc for every split!
- */
- container = xsltCreateRVT(tctxt);
- if (container != NULL) {
- xsltRegisterLocalRVT(tctxt, container);
- ret = xmlXPathNewNodeSet(NULL);
- if (ret != NULL) {
- for (cur = str, token = str; *cur != 0; cur++) {
- if (delimiterLength == 0) {
- if (cur != token) {
- xmlChar tmp = *cur;
- *cur = 0;
- node = xmlNewDocRawNode(container, NULL,
- (const xmlChar *) "token", token);
- xmlAddChild((xmlNodePtr) container, node);
- xmlXPathNodeSetAddUnique(ret->nodesetval, node);
- *cur = tmp;
- token++;
- }
- }
- else if (!xmlStrncasecmp(cur, delimiter, delimiterLength)) {
- if (cur == token) {
- /* discard empty tokens */
- cur = cur + delimiterLength - 1;
- token = cur + 1;
- continue;
- }
- *cur = 0;
- node = xmlNewDocRawNode(container, NULL,
- (const xmlChar *) "token", token);
- xmlAddChild((xmlNodePtr) container, node);
- xmlXPathNodeSetAddUnique(ret->nodesetval, node);
- *cur = *delimiter;
- cur = cur + delimiterLength - 1;
- token = cur + 1;
- }
- }
- if (token != cur) {
- node = xmlNewDocRawNode(container, NULL,
- (const xmlChar *) "token", token);
- xmlAddChild((xmlNodePtr) container, node);
- xmlXPathNodeSetAddUnique(ret->nodesetval, node);
- }
- }
- }
-
-fail:
- if (str != NULL)
- xmlFree(str);
- if (delimiter != NULL)
- xmlFree(delimiter);
- if (ret != NULL)
- valuePush(ctxt, ret);
- else
- valuePush(ctxt, xmlXPathNewNodeSet(NULL));
-}
-
-/**
- * exsltStrEncodeUriFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * URI-Escapes a string
- */
-static void
-exsltStrEncodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {
- int escape_all = 1, str_len = 0;
- xmlChar *str = NULL, *ret = NULL, *tmp;
-
- if ((nargs < 2) || (nargs > 3)) {
- xmlXPathSetArityError(ctxt);
- return;
- }
-
- if (nargs >= 3) {
- /* check for UTF-8 if encoding was explicitly given;
- we don't support anything else yet */
- tmp = xmlXPathPopString(ctxt);
- if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {
- xmlXPathReturnEmptyString(ctxt);
- xmlFree(tmp);
- return;
- }
- xmlFree(tmp);
- }
-
- escape_all = xmlXPathPopBoolean(ctxt);
-
- str = xmlXPathPopString(ctxt);
- str_len = xmlUTF8Strlen(str);
-
- if (str_len == 0) {
- xmlXPathReturnEmptyString(ctxt);
- xmlFree(str);
- return;
- }
-
- ret = xmlURIEscapeStr(str,(const xmlChar *)(escape_all?"-_.!~*'()":"-_.!~*'();/?:@&=+$,[]"));
- xmlXPathReturnString(ctxt, ret);
-
- if (str != NULL)
- xmlFree(str);
-}
-
-/**
- * exsltStrDecodeUriFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * reverses URI-Escaping of a string
- */
-static void
-exsltStrDecodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {
- int str_len = 0;
- xmlChar *str = NULL, *ret = NULL, *tmp;
-
- if ((nargs < 1) || (nargs > 2)) {
- xmlXPathSetArityError(ctxt);
- return;
- }
-
- if (nargs >= 2) {
- /* check for UTF-8 if encoding was explicitly given;
- we don't support anything else yet */
- tmp = xmlXPathPopString(ctxt);
- if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {
- xmlXPathReturnEmptyString(ctxt);
- xmlFree(tmp);
- return;
- }
- xmlFree(tmp);
- }
-
- str = xmlXPathPopString(ctxt);
- str_len = xmlUTF8Strlen(str);
-
- if (str_len == 0) {
- xmlXPathReturnEmptyString(ctxt);
- xmlFree(str);
- return;
- }
-
- ret = (xmlChar *) xmlURIUnescapeString((const char *)str,0,NULL);
- if (!xmlCheckUTF8(ret)) {
- /* FIXME: instead of throwing away the whole URI, we should
- only discard the invalid sequence(s). How to do that? */
- xmlXPathReturnEmptyString(ctxt);
- xmlFree(str);
- xmlFree(ret);
- return;
- }
-
- xmlXPathReturnString(ctxt, ret);
-
- if (str != NULL)
- xmlFree(str);
-}
-
-/**
- * exsltStrPaddingFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Creates a padding string of a certain length.
- */
-static void
-exsltStrPaddingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
- int number, str_len = 0;
- xmlChar *str = NULL, *ret = NULL, *tmp;
-
- if ((nargs < 1) || (nargs > 2)) {
- xmlXPathSetArityError(ctxt);
- return;
- }
-
- if (nargs == 2) {
- str = xmlXPathPopString(ctxt);
- str_len = xmlUTF8Strlen(str);
- }
- if (str_len == 0) {
- if (str != NULL) xmlFree(str);
- str = xmlStrdup((const xmlChar *) " ");
- str_len = 1;
- }
-
- number = (int) xmlXPathPopNumber(ctxt);
-
- if (number <= 0) {
- xmlXPathReturnEmptyString(ctxt);
- xmlFree(str);
- return;
- }
-
- while (number >= str_len) {
- ret = xmlStrncat(ret, str, str_len);
- number -= str_len;
- }
- tmp = xmlUTF8Strndup (str, number);
- ret = xmlStrcat(ret, tmp);
- if (tmp != NULL)
- xmlFree (tmp);
-
- xmlXPathReturnString(ctxt, ret);
-
- if (str != NULL)
- xmlFree(str);
-}
-
-/**
- * exsltStrAlignFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Aligns a string within another string.
- */
-static void
-exsltStrAlignFunction (xmlXPathParserContextPtr ctxt, int nargs) {
- xmlChar *str, *padding, *alignment, *ret;
- int str_l, padding_l;
-
- if ((nargs < 2) || (nargs > 3)) {
- xmlXPathSetArityError(ctxt);
- return;
- }
-
- if (nargs == 3)
- alignment = xmlXPathPopString(ctxt);
- else
- alignment = NULL;
-
- padding = xmlXPathPopString(ctxt);
- str = xmlXPathPopString(ctxt);
-
- str_l = xmlUTF8Strlen (str);
- padding_l = xmlUTF8Strlen (padding);
-
- if (str_l == padding_l) {
- xmlXPathReturnString (ctxt, str);
- xmlFree(padding);
- xmlFree(alignment);
- return;
- }
-
- if (str_l > padding_l) {
- ret = xmlUTF8Strndup (str, padding_l);
- } else {
- if (xmlStrEqual(alignment, (const xmlChar *) "right")) {
- ret = xmlUTF8Strndup (padding, padding_l - str_l);
- ret = xmlStrcat (ret, str);
- } else if (xmlStrEqual(alignment, (const xmlChar *) "center")) {
- int left = (padding_l - str_l) / 2;
- int right_start;
-
- ret = xmlUTF8Strndup (padding, left);
- ret = xmlStrcat (ret, str);
-
- right_start = xmlUTF8Strsize (padding, left + str_l);
- ret = xmlStrcat (ret, padding + right_start);
- } else {
- int str_s;
-
- str_s = xmlStrlen (str);
- ret = xmlStrdup (str);
- ret = xmlStrcat (ret, padding + str_s);
- }
- }
-
- xmlXPathReturnString (ctxt, ret);
-
- xmlFree(str);
- xmlFree(padding);
- xmlFree(alignment);
-}
-
-/**
- * exsltStrConcatFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Takes a node set and returns the concatenation of the string values
- * of the nodes in that node set. If the node set is empty, it
- * returns an empty string.
- */
-static void
-exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) {
- xmlXPathObjectPtr obj;
- xmlChar *ret = NULL;
- int i;
-
- if (nargs != 1) {
- xmlXPathSetArityError(ctxt);
- return;
- }
-
- if (!xmlXPathStackIsNodeSet(ctxt)) {
- xmlXPathSetTypeError(ctxt);
- return;
- }
-
- obj = valuePop (ctxt);
-
- if (xmlXPathNodeSetIsEmpty(obj->nodesetval)) {
- xmlXPathReturnEmptyString(ctxt);
- return;
- }
-
- for (i = 0; i < obj->nodesetval->nodeNr; i++) {
- xmlChar *tmp;
- tmp = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
-
- ret = xmlStrcat (ret, tmp);
-
- xmlFree(tmp);
- }
-
- xmlXPathFreeObject (obj);
-
- xmlXPathReturnString(ctxt, ret);
-}
-
-/**
- * exsltStrRegister:
- *
- * Registers the EXSLT - Strings module
- */
-
-void
-exsltStrRegister (void) {
- xsltRegisterExtModuleFunction ((const xmlChar *) "tokenize",
- EXSLT_STRINGS_NAMESPACE,
- exsltStrTokenizeFunction);
- xsltRegisterExtModuleFunction ((const xmlChar *) "split",
- EXSLT_STRINGS_NAMESPACE,
- exsltStrSplitFunction);
- xsltRegisterExtModuleFunction ((const xmlChar *) "encode-uri",
- EXSLT_STRINGS_NAMESPACE,
- exsltStrEncodeUriFunction);
- xsltRegisterExtModuleFunction ((const xmlChar *) "decode-uri",
- EXSLT_STRINGS_NAMESPACE,
- exsltStrDecodeUriFunction);
- xsltRegisterExtModuleFunction ((const xmlChar *) "padding",
- EXSLT_STRINGS_NAMESPACE,
- exsltStrPaddingFunction);
- xsltRegisterExtModuleFunction ((const xmlChar *) "align",
- EXSLT_STRINGS_NAMESPACE,
- exsltStrAlignFunction);
- xsltRegisterExtModuleFunction ((const xmlChar *) "concat",
- EXSLT_STRINGS_NAMESPACE,
- exsltStrConcatFunction);
-}
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/parser.h>
+#include <libxml/encoding.h>
+#include <libxml/uri.h>
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+
+#include "exslt.h"
+
+/**
+ * exsltStrTokenizeFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Splits up a string on the characters of the delimiter string and returns a
+ * node set of token elements, each containing one token from the string.
+ */
+static void
+exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ xsltTransformContextPtr tctxt;
+ xmlChar *str, *delimiters, *cur;
+ const xmlChar *token, *delimiter;
+ xmlNodePtr node;
+ xmlDocPtr container;
+ xmlXPathObjectPtr ret = NULL;
+ int clen;
+
+ if ((nargs < 1) || (nargs > 2)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ if (nargs == 2) {
+ delimiters = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt))
+ return;
+ } else {
+ delimiters = xmlStrdup((const xmlChar *) "\t\r\n ");
+ }
+ if (delimiters == NULL)
+ return;
+
+ str = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (str == NULL)) {
+ xmlFree(delimiters);
+ return;
+ }
+
+ /* Return a result tree fragment */
+ tctxt = xsltXPathGetTransformContext(ctxt);
+ if (tctxt == NULL) {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:tokenize : internal error tctxt == NULL\n");
+ goto fail;
+ }
+
+ container = xsltCreateRVT(tctxt);
+ if (container != NULL) {
+ xsltRegisterLocalRVT(tctxt, container);
+ ret = xmlXPathNewNodeSet(NULL);
+ if (ret != NULL) {
+ for (cur = str, token = str; *cur != 0; cur += clen) {
+ clen = xmlUTF8Size(cur);
+ if (*delimiters == 0) { /* empty string case */
+ xmlChar ctmp;
+ ctmp = *(cur+clen);
+ *(cur+clen) = 0;
+ node = xmlNewDocRawNode(container, NULL,
+ (const xmlChar *) "token", cur);
+ xmlAddChild((xmlNodePtr) container, node);
+ xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+ *(cur+clen) = ctmp; /* restore the changed byte */
+ token = cur + clen;
+ } else for (delimiter = delimiters; *delimiter != 0;
+ delimiter += xmlUTF8Size(delimiter)) {
+ if (!xmlUTF8Charcmp(cur, delimiter)) {
+ if (cur == token) {
+ /* discard empty tokens */
+ token = cur + clen;
+ break;
+ }
+ *cur = 0; /* terminate the token */
+ node = xmlNewDocRawNode(container, NULL,
+ (const xmlChar *) "token", token);
+ xmlAddChild((xmlNodePtr) container, node);
+ xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+ *cur = *delimiter; /* restore the changed byte */
+ token = cur + clen;
+ break;
+ }
+ }
+ }
+ if (token != cur) {
+ node = xmlNewDocRawNode(container, NULL,
+ (const xmlChar *) "token", token);
+ xmlAddChild((xmlNodePtr) container, node);
+ xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+ }
+ }
+ }
+
+fail:
+ if (str != NULL)
+ xmlFree(str);
+ if (delimiters != NULL)
+ xmlFree(delimiters);
+ if (ret != NULL)
+ valuePush(ctxt, ret);
+ else
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+}
+
+/**
+ * exsltStrSplitFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Splits up a string on a delimiting string and returns a node set of token
+ * elements, each containing one token from the string.
+ */
+static void
+exsltStrSplitFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+ xsltTransformContextPtr tctxt;
+ xmlChar *str, *delimiter, *cur;
+ const xmlChar *token;
+ xmlNodePtr node;
+ xmlDocPtr container;
+ xmlXPathObjectPtr ret = NULL;
+ int delimiterLength;
+
+ if ((nargs < 1) || (nargs > 2)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ if (nargs == 2) {
+ delimiter = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt))
+ return;
+ } else {
+ delimiter = xmlStrdup((const xmlChar *) " ");
+ }
+ if (delimiter == NULL)
+ return;
+ delimiterLength = xmlStrlen (delimiter);
+
+ str = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt) || (str == NULL)) {
+ xmlFree(delimiter);
+ return;
+ }
+
+ /* Return a result tree fragment */
+ tctxt = xsltXPathGetTransformContext(ctxt);
+ if (tctxt == NULL) {
+ xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+ "exslt:tokenize : internal error tctxt == NULL\n");
+ goto fail;
+ }
+
+ /*
+ * OPTIMIZE TODO: We are creating an xmlDoc for every split!
+ */
+ container = xsltCreateRVT(tctxt);
+ if (container != NULL) {
+ xsltRegisterLocalRVT(tctxt, container);
+ ret = xmlXPathNewNodeSet(NULL);
+ if (ret != NULL) {
+ for (cur = str, token = str; *cur != 0; cur++) {
+ if (delimiterLength == 0) {
+ if (cur != token) {
+ xmlChar tmp = *cur;
+ *cur = 0;
+ node = xmlNewDocRawNode(container, NULL,
+ (const xmlChar *) "token", token);
+ xmlAddChild((xmlNodePtr) container, node);
+ xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+ *cur = tmp;
+ token++;
+ }
+ }
+ else if (!xmlStrncasecmp(cur, delimiter, delimiterLength)) {
+ if (cur == token) {
+ /* discard empty tokens */
+ cur = cur + delimiterLength - 1;
+ token = cur + 1;
+ continue;
+ }
+ *cur = 0;
+ node = xmlNewDocRawNode(container, NULL,
+ (const xmlChar *) "token", token);
+ xmlAddChild((xmlNodePtr) container, node);
+ xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+ *cur = *delimiter;
+ cur = cur + delimiterLength - 1;
+ token = cur + 1;
+ }
+ }
+ if (token != cur) {
+ node = xmlNewDocRawNode(container, NULL,
+ (const xmlChar *) "token", token);
+ xmlAddChild((xmlNodePtr) container, node);
+ xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+ }
+ }
+ }
+
+fail:
+ if (str != NULL)
+ xmlFree(str);
+ if (delimiter != NULL)
+ xmlFree(delimiter);
+ if (ret != NULL)
+ valuePush(ctxt, ret);
+ else
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+}
+
+/**
+ * exsltStrEncodeUriFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * URI-Escapes a string
+ */
+static void
+exsltStrEncodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ int escape_all = 1, str_len = 0;
+ xmlChar *str = NULL, *ret = NULL, *tmp;
+
+ if ((nargs < 2) || (nargs > 3)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ if (nargs >= 3) {
+ /* check for UTF-8 if encoding was explicitly given;
+ we don't support anything else yet */
+ tmp = xmlXPathPopString(ctxt);
+ if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(tmp);
+ return;
+ }
+ xmlFree(tmp);
+ }
+
+ escape_all = xmlXPathPopBoolean(ctxt);
+
+ str = xmlXPathPopString(ctxt);
+ str_len = xmlUTF8Strlen(str);
+
+ if (str_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ return;
+ }
+
+ ret = xmlURIEscapeStr(str,(const xmlChar *)(escape_all?"-_.!~*'()":"-_.!~*'();/?:@&=+$,[]"));
+ xmlXPathReturnString(ctxt, ret);
+
+ if (str != NULL)
+ xmlFree(str);
+}
+
+/**
+ * exsltStrDecodeUriFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * reverses URI-Escaping of a string
+ */
+static void
+exsltStrDecodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ int str_len = 0;
+ xmlChar *str = NULL, *ret = NULL, *tmp;
+
+ if ((nargs < 1) || (nargs > 2)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ if (nargs >= 2) {
+ /* check for UTF-8 if encoding was explicitly given;
+ we don't support anything else yet */
+ tmp = xmlXPathPopString(ctxt);
+ if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(tmp);
+ return;
+ }
+ xmlFree(tmp);
+ }
+
+ str = xmlXPathPopString(ctxt);
+ str_len = xmlUTF8Strlen(str);
+
+ if (str_len == 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ return;
+ }
+
+ ret = (xmlChar *) xmlURIUnescapeString((const char *)str,0,NULL);
+ if (!xmlCheckUTF8(ret)) {
+ /* FIXME: instead of throwing away the whole URI, we should
+ only discard the invalid sequence(s). How to do that? */
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ xmlFree(ret);
+ return;
+ }
+
+ xmlXPathReturnString(ctxt, ret);
+
+ if (str != NULL)
+ xmlFree(str);
+}
+
+/**
+ * exsltStrPaddingFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Creates a padding string of a certain length.
+ */
+static void
+exsltStrPaddingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ int number, str_len = 0;
+ xmlChar *str = NULL, *ret = NULL, *tmp;
+
+ if ((nargs < 1) || (nargs > 2)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ if (nargs == 2) {
+ str = xmlXPathPopString(ctxt);
+ str_len = xmlUTF8Strlen(str);
+ }
+ if (str_len == 0) {
+ if (str != NULL) xmlFree(str);
+ str = xmlStrdup((const xmlChar *) " ");
+ str_len = 1;
+ }
+
+ number = (int) xmlXPathPopNumber(ctxt);
+
+ if (number <= 0) {
+ xmlXPathReturnEmptyString(ctxt);
+ xmlFree(str);
+ return;
+ }
+
+ while (number >= str_len) {
+ ret = xmlStrncat(ret, str, str_len);
+ number -= str_len;
+ }
+ tmp = xmlUTF8Strndup (str, number);
+ ret = xmlStrcat(ret, tmp);
+ if (tmp != NULL)
+ xmlFree (tmp);
+
+ xmlXPathReturnString(ctxt, ret);
+
+ if (str != NULL)
+ xmlFree(str);
+}
+
+/**
+ * exsltStrAlignFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Aligns a string within another string.
+ */
+static void
+exsltStrAlignFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlChar *str, *padding, *alignment, *ret;
+ int str_l, padding_l;
+
+ if ((nargs < 2) || (nargs > 3)) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ if (nargs == 3)
+ alignment = xmlXPathPopString(ctxt);
+ else
+ alignment = NULL;
+
+ padding = xmlXPathPopString(ctxt);
+ str = xmlXPathPopString(ctxt);
+
+ str_l = xmlUTF8Strlen (str);
+ padding_l = xmlUTF8Strlen (padding);
+
+ if (str_l == padding_l) {
+ xmlXPathReturnString (ctxt, str);
+ xmlFree(padding);
+ xmlFree(alignment);
+ return;
+ }
+
+ if (str_l > padding_l) {
+ ret = xmlUTF8Strndup (str, padding_l);
+ } else {
+ if (xmlStrEqual(alignment, (const xmlChar *) "right")) {
+ ret = xmlUTF8Strndup (padding, padding_l - str_l);
+ ret = xmlStrcat (ret, str);
+ } else if (xmlStrEqual(alignment, (const xmlChar *) "center")) {
+ int left = (padding_l - str_l) / 2;
+ int right_start;
+
+ ret = xmlUTF8Strndup (padding, left);
+ ret = xmlStrcat (ret, str);
+
+ right_start = xmlUTF8Strsize (padding, left + str_l);
+ ret = xmlStrcat (ret, padding + right_start);
+ } else {
+ int str_s;
+
+ str_s = xmlStrlen (str);
+ ret = xmlStrdup (str);
+ ret = xmlStrcat (ret, padding + str_s);
+ }
+ }
+
+ xmlXPathReturnString (ctxt, ret);
+
+ xmlFree(str);
+ xmlFree(padding);
+ xmlFree(alignment);
+}
+
+/**
+ * exsltStrConcatFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Takes a node set and returns the concatenation of the string values
+ * of the nodes in that node set. If the node set is empty, it
+ * returns an empty string.
+ */
+static void
+exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlXPathObjectPtr obj;
+ xmlChar *ret = NULL;
+ int i;
+
+ if (nargs != 1) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ if (!xmlXPathStackIsNodeSet(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ obj = valuePop (ctxt);
+
+ if (xmlXPathNodeSetIsEmpty(obj->nodesetval)) {
+ xmlXPathReturnEmptyString(ctxt);
+ return;
+ }
+
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ xmlChar *tmp;
+ tmp = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
+
+ ret = xmlStrcat (ret, tmp);
+
+ xmlFree(tmp);
+ }
+
+ xmlXPathFreeObject (obj);
+
+ xmlXPathReturnString(ctxt, ret);
+}
+
+/**
+ * exsltStrRegister:
+ *
+ * Registers the EXSLT - Strings module
+ */
+
+void
+exsltStrRegister (void) {
+ xsltRegisterExtModuleFunction ((const xmlChar *) "tokenize",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrTokenizeFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "split",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrSplitFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "encode-uri",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrEncodeUriFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "decode-uri",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrDecodeUriFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "padding",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrPaddingFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "align",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrAlignFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "concat",
+ EXSLT_STRINGS_NAMESPACE,
+ exsltStrConcatFunction);
+}