Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / third_party / libxslt / libexslt / functions.c
blob13fd06ee1df43eb380766ac3c5ee571e9692bb44
1 #define IN_LIBEXSLT
2 #include "libexslt/libexslt.h"
4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5 #include <win32config.h>
6 #else
7 #include "config.h"
8 #endif
10 #include <string.h>
12 #include <libxml/tree.h>
13 #include <libxml/xpath.h>
14 #include <libxml/xpathInternals.h>
15 #include <libxml/hash.h>
16 #include <libxml/debugXML.h>
18 #include <libxslt/xsltutils.h>
19 #include <libxslt/variables.h>
20 #include <libxslt/xsltInternals.h>
21 #include <libxslt/extensions.h>
22 #include <libxslt/transform.h>
23 #include <libxslt/imports.h>
25 #include "exslt.h"
27 typedef struct _exsltFuncFunctionData exsltFuncFunctionData;
28 struct _exsltFuncFunctionData {
29 int nargs; /* number of arguments to the function */
30 xmlNodePtr content; /* the func:fuction template content */
33 typedef struct _exsltFuncData exsltFuncData;
34 struct _exsltFuncData {
35 xmlHashTablePtr funcs; /* pointer to the stylesheet module data */
36 xmlXPathObjectPtr result; /* returned by func:result */
37 int error; /* did an error occur? */
38 xmlDocPtr RVT; /* result tree fragment */
41 typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
42 struct _exsltFuncResultPreComp {
43 xsltElemPreComp comp;
44 xmlXPathCompExprPtr select;
45 xmlNsPtr *nsList;
46 int nsNr;
49 /* Used for callback function in exsltInitFunc */
50 typedef struct _exsltFuncImportRegData exsltFuncImportRegData;
51 struct _exsltFuncImportRegData {
52 xsltTransformContextPtr ctxt;
53 xmlHashTablePtr hash;
56 static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
57 int nargs);
58 static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
60 #define MAX_FUNC_RECURSION 1000
62 /*static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";*/
64 /**
65 * exsltFuncRegisterFunc:
66 * @func: the #exsltFuncFunctionData for the function
67 * @ctxt: an XSLT transformation context
68 * @URI: the function namespace URI
69 * @name: the function name
71 * Registers a function declared by a func:function element
73 static void
74 exsltFuncRegisterFunc (exsltFuncFunctionData *data,
75 xsltTransformContextPtr ctxt,
76 const xmlChar *URI, const xmlChar *name,
77 ATTRIBUTE_UNUSED const xmlChar *ignored) {
78 if ((data == NULL) || (ctxt == NULL) || (URI == NULL) || (name == NULL))
79 return;
81 xsltGenericDebug(xsltGenericDebugContext,
82 "exsltFuncRegisterFunc: register {%s}%s\n",
83 URI, name);
84 xsltRegisterExtFunction(ctxt, name, URI,
85 exsltFuncFunctionFunction);
89 * exsltFuncRegisterImportFunc
90 * @data: the exsltFuncFunctionData for the function
91 * @ch: structure containing context and hash table
92 * @URI: the function namespace URI
93 * @name: the function name
95 * Checks if imported function is already registered in top-level
96 * stylesheet. If not, copies function data and registers function
98 static void
99 exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
100 exsltFuncImportRegData *ch,
101 const xmlChar *URI, const xmlChar *name,
102 ATTRIBUTE_UNUSED const xmlChar *ignored) {
103 exsltFuncFunctionData *func=NULL;
105 if ((data == NULL) || (ch == NULL) || (URI == NULL) || (name == NULL))
106 return;
108 if (ch->ctxt == NULL || ch->hash == NULL)
109 return;
111 /* Check if already present */
112 func = (exsltFuncFunctionData*)xmlHashLookup2(ch->hash, URI, name);
113 if (func == NULL) { /* Not yet present - copy it in */
114 func = exsltFuncNewFunctionData();
115 memcpy(func, data, sizeof(exsltFuncFunctionData));
116 if (xmlHashAddEntry2(ch->hash, URI, name, func) < 0) {
117 xsltGenericError(xsltGenericErrorContext,
118 "Failed to register function {%s}%s\n",
119 URI, name);
120 } else { /* Do the registration */
121 xsltGenericDebug(xsltGenericDebugContext,
122 "exsltFuncRegisterImportFunc: register {%s}%s\n",
123 URI, name);
124 xsltRegisterExtFunction(ch->ctxt, name, URI,
125 exsltFuncFunctionFunction);
131 * exsltFuncInit:
132 * @ctxt: an XSLT transformation context
133 * @URI: the namespace URI for the extension
135 * Initializes the EXSLT - Functions module.
136 * Called at transformation-time; merges all
137 * functions declared in the import tree taking
138 * import precedence into account, i.e. overriding
139 * functions with lower import precedence.
141 * Returns the data for this transformation
143 static exsltFuncData *
144 exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
145 exsltFuncData *ret;
146 xsltStylesheetPtr tmp;
147 exsltFuncImportRegData ch;
148 xmlHashTablePtr hash;
150 ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));
151 if (ret == NULL) {
152 xsltGenericError(xsltGenericErrorContext,
153 "exsltFuncInit: not enough memory\n");
154 return(NULL);
156 memset(ret, 0, sizeof(exsltFuncData));
158 ret->result = NULL;
159 ret->error = 0;
161 ch.hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);
162 ret->funcs = ch.hash;
163 xmlHashScanFull(ch.hash, (xmlHashScannerFull) exsltFuncRegisterFunc, ctxt);
164 tmp = ctxt->style;
165 ch.ctxt = ctxt;
166 while ((tmp=xsltNextImport(tmp))!=NULL) {
167 hash = xsltGetExtInfo(tmp, URI);
168 if (hash != NULL) {
169 xmlHashScanFull(hash,
170 (xmlHashScannerFull) exsltFuncRegisterImportFunc, &ch);
174 return(ret);
178 * exsltFuncShutdown:
179 * @ctxt: an XSLT transformation context
180 * @URI: the namespace URI for the extension
181 * @data: the module data to free up
183 * Shutdown the EXSLT - Functions module
184 * Called at transformation-time.
186 static void
187 exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
188 const xmlChar *URI ATTRIBUTE_UNUSED,
189 exsltFuncData *data) {
190 if (data->result != NULL)
191 xmlXPathFreeObject(data->result);
192 xmlFree(data);
196 * exsltFuncStyleInit:
197 * @style: an XSLT stylesheet
198 * @URI: the namespace URI for the extension
200 * Allocates the stylesheet data for EXSLT - Function
201 * Called at compile-time.
203 * Returns the allocated data
205 static xmlHashTablePtr
206 exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
207 const xmlChar *URI ATTRIBUTE_UNUSED) {
208 return xmlHashCreate(1);
212 * exsltFuncStyleShutdown:
213 * @style: an XSLT stylesheet
214 * @URI: the namespace URI for the extension
215 * @data: the stylesheet data to free up
217 * Shutdown the EXSLT - Function module
218 * Called at compile-time.
220 static void
221 exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
222 const xmlChar *URI ATTRIBUTE_UNUSED,
223 xmlHashTablePtr data) {
224 xmlHashFree(data, (xmlHashDeallocator) xmlFree);
228 * exsltFuncNewFunctionData:
230 * Allocates an #exslFuncFunctionData object
232 * Returns the new structure
234 static exsltFuncFunctionData *
235 exsltFuncNewFunctionData (void) {
236 exsltFuncFunctionData *ret;
238 ret = (exsltFuncFunctionData *) xmlMalloc (sizeof(exsltFuncFunctionData));
239 if (ret == NULL) {
240 xsltGenericError(xsltGenericErrorContext,
241 "exsltFuncNewFunctionData: not enough memory\n");
242 return (NULL);
244 memset(ret, 0, sizeof(exsltFuncFunctionData));
246 ret->nargs = 0;
247 ret->content = NULL;
249 return(ret);
253 * exsltFreeFuncResultPreComp:
254 * @comp: the #exsltFuncResultPreComp to free up
256 * Deallocates an #exsltFuncResultPreComp
258 static void
259 exsltFreeFuncResultPreComp (exsltFuncResultPreComp *comp) {
260 if (comp == NULL)
261 return;
263 if (comp->select != NULL)
264 xmlXPathFreeCompExpr (comp->select);
265 if (comp->nsList != NULL)
266 xmlFree(comp->nsList);
267 xmlFree(comp);
271 * exsltFuncFunctionFunction:
272 * @ctxt: an XPath parser context
273 * @nargs: the number of arguments
275 * Evaluates the func:function element that defines the called function.
277 static void
278 exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
279 xmlXPathObjectPtr oldResult, ret;
280 exsltFuncData *data;
281 exsltFuncFunctionData *func;
282 xmlNodePtr paramNode, oldInsert, fake;
283 int oldBase;
284 xsltStackElemPtr params = NULL, param;
285 xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
286 int i, notSet;
287 struct objChain {
288 struct objChain *next;
289 xmlXPathObjectPtr obj;
291 struct objChain *savedObjChain = NULL, *savedObj;
294 * retrieve func:function template
296 data = (exsltFuncData *) xsltGetExtData (tctxt,
297 EXSLT_FUNCTIONS_NAMESPACE);
298 oldResult = data->result;
299 data->result = NULL;
301 func = (exsltFuncFunctionData*) xmlHashLookup2 (data->funcs,
302 ctxt->context->functionURI,
303 ctxt->context->function);
306 * params handling
308 if (nargs > func->nargs) {
309 xsltGenericError(xsltGenericErrorContext,
310 "{%s}%s: called with too many arguments\n",
311 ctxt->context->functionURI, ctxt->context->function);
312 ctxt->error = XPATH_INVALID_ARITY;
313 return;
315 if (func->content != NULL) {
316 paramNode = func->content->prev;
318 else
319 paramNode = NULL;
320 if ((paramNode == NULL) && (func->nargs != 0)) {
321 xsltGenericError(xsltGenericErrorContext,
322 "exsltFuncFunctionFunction: nargs != 0 and "
323 "param == NULL\n");
324 return;
326 if (tctxt->funcLevel > MAX_FUNC_RECURSION) {
327 xsltGenericError(xsltGenericErrorContext,
328 "{%s}%s: detected a recursion\n",
329 ctxt->context->functionURI, ctxt->context->function);
330 ctxt->error = XPATH_MEMORY_ERROR;
331 return;
333 tctxt->funcLevel++;
336 * We have a problem with the evaluation of function parameters.
337 * The original library code did not evaluate XPath expressions until
338 * the last moment. After version 1.1.17 of the libxslt, the logic
339 * of other parts of the library was changed, and the evaluation of
340 * XPath expressions within parameters now takes place as soon as the
341 * parameter is parsed/evaluated (xsltParseStylesheetCallerParam).
342 * This means that the parameters need to be evaluated in lexical
343 * order (since a variable is "in scope" as soon as it is declared).
344 * However, on entry to this routine, the values (from the caller) are
345 * in reverse order (held on the XPath context variable stack). To
346 * accomplish what is required, I have added code to pop the XPath
347 * objects off of the stack at the beginning and save them, then use
348 * them (in the reverse order) as the params are evaluated. This
349 * requires an xmlMalloc/xmlFree for each param set by the caller,
350 * which is not very nice. There is probably a much better solution
351 * (like change other code to delay the evaluation).
354 * In order to give the function params and variables a new 'scope'
355 * we change varsBase in the context.
357 oldBase = tctxt->varsBase;
358 tctxt->varsBase = tctxt->varsNr;
359 /* If there are any parameters */
360 if (paramNode != NULL) {
361 /* Fetch the stored argument values from the caller */
362 for (i = 0; i < nargs; i++) {
363 savedObj = xmlMalloc(sizeof(struct objChain));
364 savedObj->next = savedObjChain;
365 savedObj->obj = valuePop(ctxt);
366 savedObjChain = savedObj;
370 * Prepare to process params in reverse order. First, go to
371 * the beginning of the param chain.
373 for (i = 1; i <= func->nargs; i++) {
374 if (paramNode->prev == NULL)
375 break;
376 paramNode = paramNode->prev;
379 * i has total # params found, nargs is number which are present
380 * as arguments from the caller
381 * Calculate the number of un-set parameters
383 notSet = func->nargs - nargs;
384 for (; i > 0; i--) {
385 param = xsltParseStylesheetCallerParam (tctxt, paramNode);
386 if (i > notSet) { /* if parameter value set */
387 param->computed = 1;
388 if (param->value != NULL)
389 xmlXPathFreeObject(param->value);
390 savedObj = savedObjChain; /* get next val from chain */
391 param->value = savedObj->obj;
392 savedObjChain = savedObjChain->next;
393 xmlFree(savedObj);
395 xsltLocalVariablePush(tctxt, param, -1);
396 param->next = params;
397 params = param;
398 paramNode = paramNode->next;
402 * actual processing
404 fake = xmlNewDocNode(tctxt->output, NULL,
405 (const xmlChar *)"fake", NULL);
406 oldInsert = tctxt->insert;
407 tctxt->insert = fake;
408 xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt),
409 func->content, NULL, NULL);
410 xsltLocalVariablePop(tctxt, tctxt->varsBase, -2);
411 tctxt->insert = oldInsert;
412 tctxt->varsBase = oldBase; /* restore original scope */
413 if (params != NULL)
414 xsltFreeStackElemList(params);
416 if (data->error != 0)
417 goto error;
419 if (data->result != NULL) {
420 ret = data->result;
421 } else
422 ret = xmlXPathNewCString("");
424 data->result = oldResult;
427 * It is an error if the instantiation of the template results in
428 * the generation of result nodes.
430 if (fake->children != NULL) {
431 #ifdef LIBXML_DEBUG_ENABLED
432 xmlDebugDumpNode (stderr, fake, 1);
433 #endif
434 xsltGenericError(xsltGenericErrorContext,
435 "{%s}%s: cannot write to result tree while "
436 "executing a function\n",
437 ctxt->context->functionURI, ctxt->context->function);
438 xmlFreeNode(fake);
439 goto error;
441 xmlFreeNode(fake);
442 valuePush(ctxt, ret);
444 error:
446 * IMPORTANT: This enables previously tree fragments marked as
447 * being results of a function, to be garbage-collected after
448 * the calling process exits.
450 xsltExtensionInstructionResultFinalize(tctxt);
451 tctxt->funcLevel--;
455 static void
456 exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
457 xmlChar *name, *prefix;
458 xmlNsPtr ns;
459 xmlHashTablePtr data;
460 exsltFuncFunctionData *func;
462 if ((style == NULL) || (inst == NULL))
463 return;
467 xmlChar *qname;
469 qname = xmlGetProp(inst, (const xmlChar *) "name");
470 name = xmlSplitQName2 (qname, &prefix);
471 xmlFree(qname);
473 if ((name == NULL) || (prefix == NULL)) {
474 xsltGenericError(xsltGenericErrorContext,
475 "func:function: not a QName\n");
476 if (name != NULL)
477 xmlFree(name);
478 return;
480 /* namespace lookup */
481 ns = xmlSearchNs (inst->doc, inst, prefix);
482 if (ns == NULL) {
483 xsltGenericError(xsltGenericErrorContext,
484 "func:function: undeclared prefix %s\n",
485 prefix);
486 xmlFree(name);
487 xmlFree(prefix);
488 return;
490 xmlFree(prefix);
493 * Create function data
495 func = exsltFuncNewFunctionData();
496 func->content = inst->children;
497 while (IS_XSLT_ELEM(func->content) &&
498 IS_XSLT_NAME(func->content, "param")) {
499 func->content = func->content->next;
500 func->nargs++;
503 xsltParseTemplateContent(style, inst);
506 * Register the function data such that it can be retrieved
507 * by exslFuncFunctionFunction
509 #ifdef XSLT_REFACTORED
511 * Ensure that the hash table will be stored in the *current*
512 * stylesheet level in order to correctly evaluate the
513 * import precedence.
515 data = (xmlHashTablePtr)
516 xsltStyleStylesheetLevelGetExtData(style,
517 EXSLT_FUNCTIONS_NAMESPACE);
518 #else
519 data = (xmlHashTablePtr)
520 xsltStyleGetExtData (style, EXSLT_FUNCTIONS_NAMESPACE);
521 #endif
522 if (data == NULL) {
523 xsltGenericError(xsltGenericErrorContext,
524 "exsltFuncFunctionComp: no stylesheet data\n");
525 xmlFree(name);
526 return;
529 if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {
530 xsltTransformError(NULL, style, inst,
531 "Failed to register function {%s}%s\n",
532 ns->href, name);
533 style->errors++;
534 } else {
535 xsltGenericDebug(xsltGenericDebugContext,
536 "exsltFuncFunctionComp: register {%s}%s\n",
537 ns->href, name);
539 xmlFree(name);
542 static xsltElemPreCompPtr
543 exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
544 xsltTransformFunction function) {
545 xmlNodePtr test;
546 xmlChar *sel;
547 exsltFuncResultPreComp *ret;
550 * "Validity" checking
552 /* it is an error to have any following sibling elements aside
553 * from the xsl:fallback element.
555 for (test = inst->next; test != NULL; test = test->next) {
556 if (test->type != XML_ELEMENT_NODE)
557 continue;
558 if (IS_XSLT_ELEM(test) && IS_XSLT_NAME(test, "fallback"))
559 continue;
560 xsltGenericError(xsltGenericErrorContext,
561 "exsltFuncResultElem: only xsl:fallback is "
562 "allowed to follow func:result\n");
563 return (NULL);
565 /* it is an error for a func:result element to not be a descendant
566 * of func:function.
567 * it is an error if a func:result occurs within a func:result
568 * element.
569 * it is an error if instanciating the content of a variable
570 * binding element (i.e. xsl:variable, xsl:param) results in the
571 * instanciation of a func:result element.
573 for (test = inst->parent; test != NULL; test = test->parent) {
574 if (IS_XSLT_ELEM(test) &&
575 IS_XSLT_NAME(test, "stylesheet")) {
576 xsltGenericError(xsltGenericErrorContext,
577 "func:result element not a descendant "
578 "of a func:function\n");
579 return (NULL);
581 if ((test->ns != NULL) &&
582 (xmlStrEqual(test->ns->href, EXSLT_FUNCTIONS_NAMESPACE))) {
583 if (xmlStrEqual(test->name, (const xmlChar *) "function")) {
584 break;
586 if (xmlStrEqual(test->name, (const xmlChar *) "result")) {
587 xsltGenericError(xsltGenericErrorContext,
588 "func:result element not allowed within"
589 " another func:result element\n");
590 return (NULL);
593 if (IS_XSLT_ELEM(test) &&
594 (IS_XSLT_NAME(test, "variable") ||
595 IS_XSLT_NAME(test, "param"))) {
596 xsltGenericError(xsltGenericErrorContext,
597 "func:result element not allowed within"
598 " a variable binding element\n");
599 return (NULL);
604 * Precomputation
606 ret = (exsltFuncResultPreComp *)
607 xmlMalloc (sizeof(exsltFuncResultPreComp));
608 if (ret == NULL) {
609 xsltPrintErrorContext(NULL, NULL, NULL);
610 xsltGenericError(xsltGenericErrorContext,
611 "exsltFuncResultComp : malloc failed\n");
612 return (NULL);
614 memset(ret, 0, sizeof(exsltFuncResultPreComp));
616 xsltInitElemPreComp ((xsltElemPreCompPtr) ret, style, inst, function,
617 (xsltElemPreCompDeallocator) exsltFreeFuncResultPreComp);
618 ret->select = NULL;
621 * Precompute the select attribute
623 sel = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);
624 if (sel != NULL) {
625 ret->select = xmlXPathCompile (sel);
626 xmlFree(sel);
629 * Precompute the namespace list
631 ret->nsList = xmlGetNsList(inst->doc, inst);
632 if (ret->nsList != NULL) {
633 int i = 0;
634 while (ret->nsList[i] != NULL)
635 i++;
636 ret->nsNr = i;
638 return ((xsltElemPreCompPtr) ret);
641 static void
642 exsltFuncResultElem (xsltTransformContextPtr ctxt,
643 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
644 exsltFuncResultPreComp *comp) {
645 exsltFuncData *data;
646 xmlXPathObjectPtr ret;
649 /* It is an error if instantiating the content of the
650 * func:function element results in the instantiation of more than
651 * one func:result elements.
653 data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE);
654 if (data == NULL) {
655 xsltGenericError(xsltGenericErrorContext,
656 "exsltFuncReturnElem: data == NULL\n");
657 return;
659 if (data->result != NULL) {
660 xsltGenericError(xsltGenericErrorContext,
661 "func:result already instanciated\n");
662 data->error = 1;
663 return;
666 * Processing
668 if (comp->select != NULL) {
669 xmlNsPtr *oldXPNsList;
670 int oldXPNsNr;
671 xmlNodePtr oldXPContextNode;
672 /* If the func:result element has a select attribute, then the
673 * value of the attribute must be an expression and the
674 * returned value is the object that results from evaluating
675 * the expression. In this case, the content must be empty.
677 if (inst->children != NULL) {
678 xsltGenericError(xsltGenericErrorContext,
679 "func:result content must be empty if"
680 " the function has a select attribute\n");
681 data->error = 1;
682 return;
684 oldXPNsList = ctxt->xpathCtxt->namespaces;
685 oldXPNsNr = ctxt->xpathCtxt->nsNr;
686 oldXPContextNode = ctxt->xpathCtxt->node;
688 ctxt->xpathCtxt->namespaces = comp->nsList;
689 ctxt->xpathCtxt->nsNr = comp->nsNr;
691 ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
693 ctxt->xpathCtxt->node = oldXPContextNode;
694 ctxt->xpathCtxt->nsNr = oldXPNsNr;
695 ctxt->xpathCtxt->namespaces = oldXPNsList;
697 if (ret == NULL) {
698 xsltGenericError(xsltGenericErrorContext,
699 "exsltFuncResultElem: ret == NULL\n");
700 return;
703 * Mark it as a function result in order to avoid garbage
704 * collecting of tree fragments before the function exits.
706 xsltExtensionInstructionResultRegister(ctxt, ret);
707 } else if (inst->children != NULL) {
708 /* If the func:result element does not have a select attribute
709 * and has non-empty content (i.e. the func:result element has
710 * one or more child nodes), then the content of the
711 * func:result element specifies the value.
713 xmlNodePtr oldInsert;
714 xmlDocPtr container;
716 container = xsltCreateRVT(ctxt);
717 if (container == NULL) {
718 xsltGenericError(xsltGenericErrorContext,
719 "exsltFuncResultElem: out of memory\n");
720 data->error = 1;
721 return;
723 xsltRegisterLocalRVT(ctxt, container);
725 oldInsert = ctxt->insert;
726 ctxt->insert = (xmlNodePtr) container;
727 xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
728 inst->children, NULL, NULL);
729 ctxt->insert = oldInsert;
731 ret = xmlXPathNewValueTree((xmlNodePtr) container);
732 if (ret == NULL) {
733 xsltGenericError(xsltGenericErrorContext,
734 "exsltFuncResultElem: ret == NULL\n");
735 data->error = 1;
736 } else {
737 ret->boolval = 0; /* Freeing is not handled there anymore */
739 * Mark it as a function result in order to avoid garbage
740 * collecting of tree fragments before the function exits.
742 xsltExtensionInstructionResultRegister(ctxt, ret);
744 } else {
745 /* If the func:result element has empty content and does not
746 * have a select attribute, then the returned value is an
747 * empty string.
749 ret = xmlXPathNewCString("");
751 data->result = ret;
755 * exsltFuncRegister:
757 * Registers the EXSLT - Functions module
759 void
760 exsltFuncRegister (void) {
761 xsltRegisterExtModuleFull (EXSLT_FUNCTIONS_NAMESPACE,
762 (xsltExtInitFunction) exsltFuncInit,
763 (xsltExtShutdownFunction) exsltFuncShutdown,
764 (xsltStyleExtInitFunction) exsltFuncStyleInit,
765 (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown);
767 xsltRegisterExtModuleTopLevel ((const xmlChar *) "function",
768 EXSLT_FUNCTIONS_NAMESPACE,
769 exsltFuncFunctionComp);
770 xsltRegisterExtModuleElement ((const xmlChar *) "result",
771 EXSLT_FUNCTIONS_NAMESPACE,
772 (xsltPreComputeFunction)exsltFuncResultComp,
773 (xsltTransformFunction) exsltFuncResultElem);