OLD | NEW |
1 #define IN_LIBEXSLT | 1 #define IN_LIBEXSLT |
2 #include "libexslt/libexslt.h" | 2 #include "libexslt/libexslt.h" |
3 | 3 |
4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__) | 4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__) |
5 #include <win32config.h> | 5 #include <win32config.h> |
6 #else | 6 #else |
7 #include "config.h" | 7 #include "config.h" |
8 #endif | 8 #endif |
9 | 9 |
10 #include <string.h> | 10 #include <string.h> |
(...skipping 17 matching lines...) Expand all Loading... |
28 struct _exsltFuncFunctionData { | 28 struct _exsltFuncFunctionData { |
29 int nargs; /* number of arguments to the function */ | 29 int nargs; /* number of arguments to the function */ |
30 xmlNodePtr content; /* the func:fuction template content */ | 30 xmlNodePtr content; /* the func:fuction template content */ |
31 }; | 31 }; |
32 | 32 |
33 typedef struct _exsltFuncData exsltFuncData; | 33 typedef struct _exsltFuncData exsltFuncData; |
34 struct _exsltFuncData { | 34 struct _exsltFuncData { |
35 xmlHashTablePtr funcs; /* pointer to the stylesheet module data */ | 35 xmlHashTablePtr funcs; /* pointer to the stylesheet module data */ |
36 xmlXPathObjectPtr result; /* returned by func:result */ | 36 xmlXPathObjectPtr result; /* returned by func:result */ |
37 int error; /* did an error occur? */ | 37 int error; /* did an error occur? */ |
38 xmlDocPtr RVT; /* result tree fragment */ | |
39 }; | 38 }; |
40 | 39 |
41 typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp; | 40 typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp; |
42 struct _exsltFuncResultPreComp { | 41 struct _exsltFuncResultPreComp { |
43 xsltElemPreComp comp; | 42 xsltElemPreComp comp; |
44 xmlXPathCompExprPtr select; | 43 xmlXPathCompExprPtr select; |
45 xmlNsPtr *nsList; | 44 xmlNsPtr *nsList; |
46 int nsNr; | 45 int nsNr; |
47 }; | 46 }; |
48 | 47 |
49 /* Used for callback function in exsltInitFunc */ | 48 /* Used for callback function in exsltInitFunc */ |
50 typedef struct _exsltFuncImportRegData exsltFuncImportRegData; | 49 typedef struct _exsltFuncImportRegData exsltFuncImportRegData; |
51 struct _exsltFuncImportRegData { | 50 struct _exsltFuncImportRegData { |
52 xsltTransformContextPtr ctxt; | 51 xsltTransformContextPtr ctxt; |
53 xmlHashTablePtr hash; | 52 xmlHashTablePtr hash; |
54 }; | 53 }; |
55 | 54 |
56 static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, | 55 static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, |
57 int nargs); | 56 int nargs); |
58 static exsltFuncFunctionData *exsltFuncNewFunctionData(void); | 57 static exsltFuncFunctionData *exsltFuncNewFunctionData(void); |
59 | 58 |
60 #define MAX_FUNC_RECURSION 1000 | |
61 | |
62 /*static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";*/ | 59 /*static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";*/ |
63 | 60 |
64 /** | 61 /** |
65 * exsltFuncRegisterFunc: | 62 * exsltFuncRegisterFunc: |
66 * @func: the #exsltFuncFunctionData for the function | 63 * @func: the #exsltFuncFunctionData for the function |
67 * @ctxt: an XSLT transformation context | 64 * @ctxt: an XSLT transformation context |
68 * @URI: the function namespace URI | 65 * @URI: the function namespace URI |
69 * @name: the function name | 66 * @name: the function name |
70 * | 67 * |
71 * Registers a function declared by a func:function element | 68 * Registers a function declared by a func:function element |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 paramNode = func->content->prev; | 323 paramNode = func->content->prev; |
327 } | 324 } |
328 else | 325 else |
329 paramNode = NULL; | 326 paramNode = NULL; |
330 if ((paramNode == NULL) && (func->nargs != 0)) { | 327 if ((paramNode == NULL) && (func->nargs != 0)) { |
331 xsltGenericError(xsltGenericErrorContext, | 328 xsltGenericError(xsltGenericErrorContext, |
332 "exsltFuncFunctionFunction: nargs != 0 and " | 329 "exsltFuncFunctionFunction: nargs != 0 and " |
333 "param == NULL\n"); | 330 "param == NULL\n"); |
334 return; | 331 return; |
335 } | 332 } |
336 if (tctxt->funcLevel > MAX_FUNC_RECURSION) { | |
337 xsltGenericError(xsltGenericErrorContext, | |
338 "{%s}%s: detected a recursion\n", | |
339 ctxt->context->functionURI, ctxt->context->function); | |
340 ctxt->error = XPATH_MEMORY_ERROR; | |
341 return; | |
342 } | |
343 tctxt->funcLevel++; | |
344 | 333 |
345 /* | 334 /* |
346 * We have a problem with the evaluation of function parameters. | 335 * We have a problem with the evaluation of function parameters. |
347 * The original library code did not evaluate XPath expressions until | 336 * The original library code did not evaluate XPath expressions until |
348 * the last moment. After version 1.1.17 of the libxslt, the logic | 337 * the last moment. After version 1.1.17 of the libxslt, the logic |
349 * of other parts of the library was changed, and the evaluation of | 338 * of other parts of the library was changed, and the evaluation of |
350 * XPath expressions within parameters now takes place as soon as the | 339 * XPath expressions within parameters now takes place as soon as the |
351 * parameter is parsed/evaluated (xsltParseStylesheetCallerParam). | 340 * parameter is parsed/evaluated (xsltParseStylesheetCallerParam). |
352 * This means that the parameters need to be evaluated in lexical | 341 * This means that the parameters need to be evaluated in lexical |
353 * order (since a variable is "in scope" as soon as it is declared). | 342 * order (since a variable is "in scope" as soon as it is declared). |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 tctxt->insert = fake; | 406 tctxt->insert = fake; |
418 xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt), | 407 xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt), |
419 func->content, NULL, NULL); | 408 func->content, NULL, NULL); |
420 xsltLocalVariablePop(tctxt, tctxt->varsBase, -2); | 409 xsltLocalVariablePop(tctxt, tctxt->varsBase, -2); |
421 tctxt->insert = oldInsert; | 410 tctxt->insert = oldInsert; |
422 tctxt->varsBase = oldBase; /* restore original scope */ | 411 tctxt->varsBase = oldBase; /* restore original scope */ |
423 if (params != NULL) | 412 if (params != NULL) |
424 xsltFreeStackElemList(params); | 413 xsltFreeStackElemList(params); |
425 | 414 |
426 if (data->error != 0) | 415 if (data->error != 0) |
427 » goto error; | 416 » return; |
428 | 417 |
429 if (data->result != NULL) { | 418 if (data->result != NULL) { |
430 ret = data->result; | 419 ret = data->result; |
| 420 /* |
| 421 * IMPORTANT: This enables previously tree fragments marked as |
| 422 * being results of a function, to be garbage-collected after |
| 423 * the calling process exits. |
| 424 */ |
| 425 xsltFlagRVTs(tctxt, ret, XSLT_RVT_LOCAL); |
431 } else | 426 } else |
432 ret = xmlXPathNewCString(""); | 427 ret = xmlXPathNewCString(""); |
433 | 428 |
434 data->result = oldResult; | 429 data->result = oldResult; |
435 | 430 |
436 /* | 431 /* |
437 * It is an error if the instantiation of the template results in | 432 * It is an error if the instantiation of the template results in |
438 * the generation of result nodes. | 433 * the generation of result nodes. |
439 */ | 434 */ |
440 if (fake->children != NULL) { | 435 if (fake->children != NULL) { |
441 #ifdef LIBXML_DEBUG_ENABLED | 436 #ifdef LIBXML_DEBUG_ENABLED |
442 xmlDebugDumpNode (stderr, fake, 1); | 437 xmlDebugDumpNode (stderr, fake, 1); |
443 #endif | 438 #endif |
444 xsltGenericError(xsltGenericErrorContext, | 439 xsltGenericError(xsltGenericErrorContext, |
445 "{%s}%s: cannot write to result tree while " | 440 "{%s}%s: cannot write to result tree while " |
446 "executing a function\n", | 441 "executing a function\n", |
447 ctxt->context->functionURI, ctxt->context->function); | 442 ctxt->context->functionURI, ctxt->context->function); |
448 xmlFreeNode(fake); | 443 xmlFreeNode(fake); |
449 » goto error; | 444 » return; |
450 } | 445 } |
451 xmlFreeNode(fake); | 446 xmlFreeNode(fake); |
452 valuePush(ctxt, ret); | 447 valuePush(ctxt, ret); |
453 | |
454 error: | |
455 /* | |
456 * IMPORTANT: This enables previously tree fragments marked as | |
457 * being results of a function, to be garbage-collected after | |
458 * the calling process exits. | |
459 */ | |
460 xsltExtensionInstructionResultFinalize(tctxt); | |
461 tctxt->funcLevel--; | |
462 } | 448 } |
463 | 449 |
464 | 450 |
465 static void | 451 static void |
466 exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) { | 452 exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) { |
467 xmlChar *name, *prefix; | 453 xmlChar *name, *prefix; |
468 xmlNsPtr ns; | 454 xmlNsPtr ns; |
469 xmlHashTablePtr data; | 455 xmlHashTablePtr data; |
470 exsltFuncFunctionData *func; | 456 exsltFuncFunctionData *func; |
471 | 457 |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 | 703 |
718 if (ret == NULL) { | 704 if (ret == NULL) { |
719 xsltGenericError(xsltGenericErrorContext, | 705 xsltGenericError(xsltGenericErrorContext, |
720 "exsltFuncResultElem: ret == NULL\n"); | 706 "exsltFuncResultElem: ret == NULL\n"); |
721 return; | 707 return; |
722 } | 708 } |
723 /* | 709 /* |
724 * Mark it as a function result in order to avoid garbage | 710 * Mark it as a function result in order to avoid garbage |
725 * collecting of tree fragments before the function exits. | 711 * collecting of tree fragments before the function exits. |
726 */ | 712 */ |
727 » xsltExtensionInstructionResultRegister(ctxt, ret); | 713 » xsltFlagRVTs(ctxt, ret, XSLT_RVT_FUNC_RESULT); |
728 } else if (inst->children != NULL) { | 714 } else if (inst->children != NULL) { |
729 /* If the func:result element does not have a select attribute | 715 /* If the func:result element does not have a select attribute |
730 * and has non-empty content (i.e. the func:result element has | 716 * and has non-empty content (i.e. the func:result element has |
731 * one or more child nodes), then the content of the | 717 * one or more child nodes), then the content of the |
732 * func:result element specifies the value. | 718 * func:result element specifies the value. |
733 */ | 719 */ |
734 xmlNodePtr oldInsert; | 720 xmlNodePtr oldInsert; |
735 xmlDocPtr container; | 721 xmlDocPtr container; |
736 | 722 |
737 container = xsltCreateRVT(ctxt); | 723 container = xsltCreateRVT(ctxt); |
738 if (container == NULL) { | 724 if (container == NULL) { |
739 xsltGenericError(xsltGenericErrorContext, | 725 xsltGenericError(xsltGenericErrorContext, |
740 "exsltFuncResultElem: out of memory\n"); | 726 "exsltFuncResultElem: out of memory\n"); |
741 data->error = 1; | 727 data->error = 1; |
742 return; | 728 return; |
743 } | 729 } |
744 » xsltRegisterLocalRVT(ctxt, container); | 730 /* Mark as function result. */ |
| 731 container->psvi = XSLT_RVT_FUNC_RESULT; |
745 | 732 |
746 oldInsert = ctxt->insert; | 733 oldInsert = ctxt->insert; |
747 ctxt->insert = (xmlNodePtr) container; | 734 ctxt->insert = (xmlNodePtr) container; |
748 xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node, | 735 xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node, |
749 inst->children, NULL, NULL); | 736 inst->children, NULL, NULL); |
750 ctxt->insert = oldInsert; | 737 ctxt->insert = oldInsert; |
751 | 738 |
752 ret = xmlXPathNewValueTree((xmlNodePtr) container); | 739 ret = xmlXPathNewValueTree((xmlNodePtr) container); |
753 if (ret == NULL) { | 740 if (ret == NULL) { |
754 xsltGenericError(xsltGenericErrorContext, | 741 xsltGenericError(xsltGenericErrorContext, |
755 "exsltFuncResultElem: ret == NULL\n"); | 742 "exsltFuncResultElem: ret == NULL\n"); |
756 data->error = 1; | 743 data->error = 1; |
757 } else { | 744 } else { |
758 ret->boolval = 0; /* Freeing is not handled there anymore */ | 745 ret->boolval = 0; /* Freeing is not handled there anymore */ |
759 /* | |
760 * Mark it as a function result in order to avoid garbage | |
761 * collecting of tree fragments before the function exits. | |
762 */ | |
763 xsltExtensionInstructionResultRegister(ctxt, ret); | |
764 } | 746 } |
765 } else { | 747 } else { |
766 /* If the func:result element has empty content and does not | 748 /* If the func:result element has empty content and does not |
767 * have a select attribute, then the returned value is an | 749 * have a select attribute, then the returned value is an |
768 * empty string. | 750 * empty string. |
769 */ | 751 */ |
770 ret = xmlXPathNewCString(""); | 752 ret = xmlXPathNewCString(""); |
771 } | 753 } |
772 data->result = ret; | 754 data->result = ret; |
773 } | 755 } |
(...skipping 12 matching lines...) Expand all Loading... |
786 (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown); | 768 (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown); |
787 | 769 |
788 xsltRegisterExtModuleTopLevel ((const xmlChar *) "function", | 770 xsltRegisterExtModuleTopLevel ((const xmlChar *) "function", |
789 EXSLT_FUNCTIONS_NAMESPACE, | 771 EXSLT_FUNCTIONS_NAMESPACE, |
790 exsltFuncFunctionComp); | 772 exsltFuncFunctionComp); |
791 xsltRegisterExtModuleElement ((const xmlChar *) "result", | 773 xsltRegisterExtModuleElement ((const xmlChar *) "result", |
792 EXSLT_FUNCTIONS_NAMESPACE, | 774 EXSLT_FUNCTIONS_NAMESPACE, |
793 (xsltPreComputeFunction)exsltFuncResultComp, | 775 (xsltPreComputeFunction)exsltFuncResultComp, |
794 (xsltTransformFunction) exsltFuncResultElem); | 776 (xsltTransformFunction) exsltFuncResultElem); |
795 } | 777 } |
OLD | NEW |