1 #include "libexslt/libexslt.h"
3 #if defined(WIN32) && !defined (__CYGWIN__)
4 #include <win32config.h>
9 #include <libxml/tree.h>
10 #include <libxml/xpath.h>
11 #include <libxml/xpathInternals.h>
13 #include <libxslt/xsltconfig.h>
14 #include <libxslt/xsltutils.h>
15 #include <libxslt/xsltInternals.h>
16 #include <libxslt/extensions.h>
32 * Implements the EXSLT - Math min() function:
33 * number math:min (node-set)
35 * Returns the minimum value of the nodes passed as the argument, or
36 * xmlXPathNAN if @ns is NULL or empty or if one of the nodes
40 exsltMathMin (xmlNodeSetPtr ns) {
44 if ((ns == NULL) || (ns->nodeNr == 0))
46 ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
47 if (xmlXPathIsNaN(ret))
49 for (i = 1; i < ns->nodeNr; i++) {
50 cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
51 if (xmlXPathIsNaN(cur))
60 * exsltMathMinFunction:
61 * @ctxt: an XPath parser context
62 * @nargs: the number of arguments
64 * Wraps #exsltMathMin for use by the XPath processor.
67 exsltMathMinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
72 xsltGenericError(xsltGenericErrorContext,
73 "math:min: invalid number of arguments\n");
74 ctxt->error = XPATH_INVALID_ARITY;
77 ns = xmlXPathPopNodeSet(ctxt);
78 if (xmlXPathCheckError(ctxt))
81 ret = exsltMathMin(ns);
83 xmlXPathFreeNodeSet(ns);
85 xmlXPathReturnNumber(ctxt, ret);
92 * Implements the EXSLT - Math max() function:
93 * number math:max (node-set)
95 * Returns the maximum value of the nodes passed as arguments, or
96 * xmlXPathNAN if @ns is NULL or empty or if one of the nodes
100 exsltMathMax (xmlNodeSetPtr ns) {
104 if ((ns == NULL) || (ns->nodeNr == 0))
106 ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
107 if (xmlXPathIsNaN(ret))
109 for (i = 1; i < ns->nodeNr; i++) {
110 cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
111 if (xmlXPathIsNaN(cur))
120 * exsltMathMaxFunction:
121 * @ctxt: an XPath parser context
122 * @nargs: the number of arguments
124 * Wraps #exsltMathMax for use by the XPath processor.
127 exsltMathMaxFunction (xmlXPathParserContextPtr ctxt, int nargs) {
132 xmlXPathSetArityError(ctxt);
135 ns = xmlXPathPopNodeSet(ctxt);
136 if (xmlXPathCheckError(ctxt))
139 ret = exsltMathMax(ns);
141 xmlXPathFreeNodeSet(ns);
143 xmlXPathReturnNumber(ctxt, ret);
150 * Implements the EXSLT - Math highest() function:
151 * node-set math:highest (node-set)
153 * Returns the nodes in the node-set whose value is the maximum value
157 exsltMathHighest (xmlNodeSetPtr ns) {
158 xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
162 if ((ns == NULL) || (ns->nodeNr == 0))
165 max = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
166 if (xmlXPathIsNaN(max))
169 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]);
171 for (i = 1; i < ns->nodeNr; i++) {
172 cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
173 if (xmlXPathIsNaN(cur)) {
174 xmlXPathEmptyNodeSet(ret);
181 xmlXPathEmptyNodeSet(ret);
182 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
185 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
191 * exsltMathHighestFunction:
192 * @ctxt: an XPath parser context
193 * @nargs: the number of arguments
195 * Wraps #exsltMathHighest for use by the XPath processor
198 exsltMathHighestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
199 xmlNodeSetPtr ns, ret;
202 xmlXPathSetArityError(ctxt);
206 ns = xmlXPathPopNodeSet(ctxt);
207 if (xmlXPathCheckError(ctxt))
210 ret = exsltMathHighest(ns);
212 xmlXPathFreeNodeSet(ns);
214 xmlXPathReturnNodeSet(ctxt, ret);
221 * Implements the EXSLT - Math lowest() function
222 * node-set math:lowest (node-set)
224 * Returns the nodes in the node-set whose value is the minimum value
228 exsltMathLowest (xmlNodeSetPtr ns) {
229 xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
233 if ((ns == NULL) || (ns->nodeNr == 0))
236 min = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
237 if (xmlXPathIsNaN(min))
240 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]);
242 for (i = 1; i < ns->nodeNr; i++) {
243 cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
244 if (xmlXPathIsNaN(cur)) {
245 xmlXPathEmptyNodeSet(ret);
252 xmlXPathEmptyNodeSet(ret);
253 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
256 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
262 * exsltMathLowestFunction:
263 * @ctxt: an XPath parser context
264 * @nargs: the number of arguments
266 * Wraps #exsltMathLowest for use by the XPath processor
269 exsltMathLowestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
270 xmlNodeSetPtr ns, ret;
273 xmlXPathSetArityError(ctxt);
277 ns = xmlXPathPopNodeSet(ctxt);
278 if (xmlXPathCheckError(ctxt))
281 ret = exsltMathLowest(ns);
283 xmlXPathFreeNodeSet(ns);
285 xmlXPathReturnNodeSet(ctxt, ret);
288 /* math other functions */
290 /* constant values */
291 #define EXSLT_PI (const xmlChar *) \
292 "3.1415926535897932384626433832795028841971693993751"
293 #define EXSLT_E (const xmlChar *) \
294 "2.71828182845904523536028747135266249775724709369996"
295 #define EXSLT_SQRRT2 (const xmlChar *) \
296 "1.41421356237309504880168872420969807856967187537694"
297 #define EXSLT_LN2 (const xmlChar *) \
298 "0.69314718055994530941723212145817656807550013436025"
299 #define EXSLT_LN10 (const xmlChar *) \
300 "2.30258509299404568402"
301 #define EXSLT_LOG2E (const xmlChar *) \
302 "1.4426950408889634074"
303 #define EXSLT_SQRT1_2 (const xmlChar *) \
304 "0.70710678118654752440"
311 * Implements the EXSLT - Math constant function:
312 * number math:constant(string, number)
314 * Returns a number value of the given constant with the given precision or
315 * xmlXPathNAN if name is unknown.
316 * The constants are PI, E, SQRRT2, LN2, LN10, LOG2E, and SQRT1_2
319 exsltMathConstant (xmlChar *name, double precision) {
322 if ((name == NULL) || (xmlXPathIsNaN(precision)) || (precision < 1.0)) {
326 if (xmlStrEqual(name, BAD_CAST "PI")) {
327 int len = xmlStrlen(EXSLT_PI);
329 if (precision <= len)
330 len = (int)precision;
332 str = xmlStrsub(EXSLT_PI, 0, len);
336 return xmlXPathCastStringToNumber(str);
338 } else if (xmlStrEqual(name, BAD_CAST "E")) {
339 int len = xmlStrlen(EXSLT_E);
341 if (precision <= len)
342 len = (int)precision;
344 str = xmlStrsub(EXSLT_E, 0, len);
348 return xmlXPathCastStringToNumber(str);
350 } else if (xmlStrEqual(name, BAD_CAST "SQRRT2")) {
351 int len = xmlStrlen(EXSLT_SQRRT2);
353 if (precision <= len)
354 len = (int)precision;
356 str = xmlStrsub(EXSLT_SQRRT2, 0, len);
360 return xmlXPathCastStringToNumber(str);
362 } else if (xmlStrEqual(name, BAD_CAST "LN2")) {
363 int len = xmlStrlen(EXSLT_LN2);
365 if (precision <= len)
366 len = (int)precision;
368 str = xmlStrsub(EXSLT_LN2, 0, len);
372 return xmlXPathCastStringToNumber(str);
374 } else if (xmlStrEqual(name, BAD_CAST "LN10")) {
375 int len = xmlStrlen(EXSLT_LN10);
377 if (precision <= len)
378 len = (int)precision;
380 str = xmlStrsub(EXSLT_LN10, 0, len);
384 return xmlXPathCastStringToNumber(str);
386 } else if (xmlStrEqual(name, BAD_CAST "LOG2E")) {
387 int len = xmlStrlen(EXSLT_LOG2E);
389 if (precision <= len)
390 len = (int)precision;
392 str = xmlStrsub(EXSLT_LOG2E, 0, len);
396 return xmlXPathCastStringToNumber(str);
398 } else if (xmlStrEqual(name, BAD_CAST "SQRT1_2")) {
399 int len = xmlStrlen(EXSLT_SQRT1_2);
401 if (precision <= len)
402 len = (int)precision;
404 str = xmlStrsub(EXSLT_SQRT1_2, 0, len);
408 return xmlXPathCastStringToNumber(str);
416 * exsltMathConstantFunction:
417 * @ctxt: an XPath parser context
418 * @nargs: the number of arguments
420 * Wraps #exsltMathConstant for use by the XPath processor.
423 exsltMathConstantFunction (xmlXPathParserContextPtr ctxt, int nargs) {
428 xmlXPathSetArityError(ctxt);
431 ret = xmlXPathPopNumber(ctxt);
432 if (xmlXPathCheckError(ctxt))
435 name = xmlXPathPopString(ctxt);
436 if (xmlXPathCheckError(ctxt))
439 ret = exsltMathConstant(name, ret);
441 xmlXPathReturnNumber(ctxt, ret);
444 #if defined(HAVE_STDLIB_H) && defined(RAND_MAX)
449 * Implements the EXSLT - Math random() function:
450 * number math:random ()
452 * Returns a random number between 0 and 1 inclusive.
455 exsltMathRandom (void) {
460 ret = (double)num / (double)RAND_MAX;
465 * exsltMathRandomFunction:
466 * @ctxt: an XPath parser context
467 * @nargs: the number of arguments
469 * Wraps #exsltMathRandom for use by the XPath processor.
472 exsltMathRandomFunction (xmlXPathParserContextPtr ctxt, int nargs) {
476 xmlXPathSetArityError(ctxt);
480 ret = exsltMathRandom();
482 xmlXPathReturnNumber(ctxt, ret);
485 #endif /* defined(HAVE_STDLIB_H) && defined(RAND_MAX) */
493 * Implements the EXSLT - Math abs() function:
494 * number math:abs (number)
496 * Returns the absolute value of the argument, or xmlXPathNAN if @num is Nan.
499 exsltMathAbs (double num) {
502 if (xmlXPathIsNaN(num))
509 * exsltMathAbsFunction:
510 * @ctxt: an XPath parser context
511 * @nargs: the number of arguments
513 * Wraps #exsltMathAbs for use by the XPath processor.
516 exsltMathAbsFunction (xmlXPathParserContextPtr ctxt, int nargs) {
520 xmlXPathSetArityError(ctxt);
523 ret = xmlXPathPopNumber(ctxt);
524 if (xmlXPathCheckError(ctxt))
527 ret = exsltMathAbs(ret);
529 xmlXPathReturnNumber(ctxt, ret);
536 * Implements the EXSLT - Math sqrt() function:
537 * number math:sqrt (number)
539 * Returns the square root of the argument, or xmlXPathNAN if @num is Nan.
542 exsltMathSqrt (double num) {
545 if (xmlXPathIsNaN(num))
552 * exsltMathSqrtFunction:
553 * @ctxt: an XPath parser context
554 * @nargs: the number of arguments
556 * Wraps #exsltMathSqrt for use by the XPath processor.
559 exsltMathSqrtFunction (xmlXPathParserContextPtr ctxt, int nargs) {
563 xmlXPathSetArityError(ctxt);
566 ret = xmlXPathPopNumber(ctxt);
567 if (xmlXPathCheckError(ctxt))
570 ret = exsltMathSqrt(ret);
572 xmlXPathReturnNumber(ctxt, ret);
580 * Implements the EXSLT - Math power() function:
581 * number math:power (number, number)
583 * Returns the power base and power arguments, or xmlXPathNAN
584 * if either @base or @power is Nan.
587 exsltMathPower (double base, double power) {
590 if ((xmlXPathIsNaN(base) || xmlXPathIsNaN(power)))
592 ret = pow(base, power);
598 * @ctxt: an XPath parser context
599 * @nargs: the number of arguments
601 * Wraps #exsltMathPower for use by the XPath processor.
604 exsltMathPowerFunction (xmlXPathParserContextPtr ctxt, int nargs) {
608 xmlXPathSetArityError(ctxt);
611 base = xmlXPathPopNumber(ctxt);
612 if (xmlXPathCheckError(ctxt))
616 ret = xmlXPathPopNumber(ctxt);
617 if (xmlXPathCheckError(ctxt))
620 ret = exsltMathPower(base, ret);
622 xmlXPathReturnNumber(ctxt, ret);
629 * Implements the EXSLT - Math log() function:
630 * number math:log (number)
632 * Returns the natural log of the argument, or xmlXPathNAN if @num is Nan.
635 exsltMathLog (double num) {
638 if (xmlXPathIsNaN(num))
645 * exsltMathLogFunction:
646 * @ctxt: an XPath parser context
647 * @nargs: the number of arguments
649 * Wraps #exsltMathLog for use by the XPath processor.
652 exsltMathLogFunction (xmlXPathParserContextPtr ctxt, int nargs) {
656 xmlXPathSetArityError(ctxt);
659 ret = xmlXPathPopNumber(ctxt);
660 if (xmlXPathCheckError(ctxt))
663 ret = exsltMathLog(ret);
665 xmlXPathReturnNumber(ctxt, ret);
672 * Implements the EXSLT - Math sin() function:
673 * number math:sin (number)
675 * Returns the sine of the argument, or xmlXPathNAN if @num is Nan.
678 exsltMathSin (double num) {
681 if (xmlXPathIsNaN(num))
688 * exsltMathSinFunction:
689 * @ctxt: an XPath parser context
690 * @nargs: the number of arguments
692 * Wraps #exsltMathSin for use by the XPath processor.
695 exsltMathSinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
699 xmlXPathSetArityError(ctxt);
702 ret = xmlXPathPopNumber(ctxt);
703 if (xmlXPathCheckError(ctxt))
706 ret = exsltMathSin(ret);
708 xmlXPathReturnNumber(ctxt, ret);
715 * Implements the EXSLT - Math cos() function:
716 * number math:cos (number)
718 * Returns the cosine of the argument, or xmlXPathNAN if @num is Nan.
721 exsltMathCos (double num) {
724 if (xmlXPathIsNaN(num))
731 * exsltMathCosFunction:
732 * @ctxt: an XPath parser context
733 * @nargs: the number of arguments
735 * Wraps #exsltMathCos for use by the XPath processor.
738 exsltMathCosFunction (xmlXPathParserContextPtr ctxt, int nargs) {
742 xmlXPathSetArityError(ctxt);
745 ret = xmlXPathPopNumber(ctxt);
746 if (xmlXPathCheckError(ctxt))
749 ret = exsltMathCos(ret);
751 xmlXPathReturnNumber(ctxt, ret);
758 * Implements the EXSLT - Math tan() function:
759 * number math:tan (number)
761 * Returns the tangent of the argument, or xmlXPathNAN if @num is Nan.
764 exsltMathTan (double num) {
767 if (xmlXPathIsNaN(num))
774 * exsltMathTanFunction:
775 * @ctxt: an XPath parser context
776 * @nargs: the number of arguments
778 * Wraps #exsltMathTan for use by the XPath processor.
781 exsltMathTanFunction (xmlXPathParserContextPtr ctxt, int nargs) {
785 xmlXPathSetArityError(ctxt);
788 ret = xmlXPathPopNumber(ctxt);
789 if (xmlXPathCheckError(ctxt))
792 ret = exsltMathTan(ret);
794 xmlXPathReturnNumber(ctxt, ret);
801 * Implements the EXSLT - Math asin() function:
802 * number math:asin (number)
804 * Returns the arc sine of the argument, or xmlXPathNAN if @num is Nan.
807 exsltMathAsin (double num) {
810 if (xmlXPathIsNaN(num))
817 * exsltMathAsinFunction:
818 * @ctxt: an XPath parser context
819 * @nargs: the number of arguments
821 * Wraps #exsltMathAsin for use by the XPath processor.
824 exsltMathAsinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
828 xmlXPathSetArityError(ctxt);
831 ret = xmlXPathPopNumber(ctxt);
832 if (xmlXPathCheckError(ctxt))
835 ret = exsltMathAsin(ret);
837 xmlXPathReturnNumber(ctxt, ret);
844 * Implements the EXSLT - Math acos() function:
845 * number math:acos (number)
847 * Returns the arc cosine of the argument, or xmlXPathNAN if @num is Nan.
850 exsltMathAcos (double num) {
853 if (xmlXPathIsNaN(num))
860 * exsltMathAcosFunction:
861 * @ctxt: an XPath parser context
862 * @nargs: the number of arguments
864 * Wraps #exsltMathAcos for use by the XPath processor.
867 exsltMathAcosFunction (xmlXPathParserContextPtr ctxt, int nargs) {
871 xmlXPathSetArityError(ctxt);
874 ret = xmlXPathPopNumber(ctxt);
875 if (xmlXPathCheckError(ctxt))
878 ret = exsltMathAcos(ret);
880 xmlXPathReturnNumber(ctxt, ret);
887 * Implements the EXSLT - Math atan() function:
888 * number math:atan (number)
890 * Returns the arc tangent of the argument, or xmlXPathNAN if @num is Nan.
893 exsltMathAtan (double num) {
896 if (xmlXPathIsNaN(num))
903 * exsltMathAtanFunction:
904 * @ctxt: an XPath parser context
905 * @nargs: the number of arguments
907 * Wraps #exsltMathAtan for use by the XPath processor.
910 exsltMathAtanFunction (xmlXPathParserContextPtr ctxt, int nargs) {
914 xmlXPathSetArityError(ctxt);
917 ret = xmlXPathPopNumber(ctxt);
918 if (xmlXPathCheckError(ctxt))
921 ret = exsltMathAtan(ret);
923 xmlXPathReturnNumber(ctxt, ret);
931 * Implements the EXSLT - Math atan2() function:
932 * number math:atan2 (number, number)
934 * Returns the arc tangent function of the y/x arguments, or xmlXPathNAN
935 * if either @y or @x is Nan.
938 exsltMathAtan2 (double y, double x) {
941 if ((xmlXPathIsNaN(y) || xmlXPathIsNaN(x)))
948 * exsltMathAtan2Function:
949 * @ctxt: an XPath parser context
950 * @nargs: the number of arguments
952 * Wraps #exsltMathAtan2 for use by the XPath processor.
955 exsltMathAtan2Function (xmlXPathParserContextPtr ctxt, int nargs) {
959 xmlXPathSetArityError(ctxt);
962 y = xmlXPathPopNumber(ctxt);
963 if (xmlXPathCheckError(ctxt))
967 ret = xmlXPathPopNumber(ctxt);
968 if (xmlXPathCheckError(ctxt))
971 ret = exsltMathAtan2(y, ret);
973 xmlXPathReturnNumber(ctxt, ret);
980 * Implements the EXSLT - Math exp() function:
981 * number math:exp (number)
983 * Returns the exponential function of the argument, or xmlXPathNAN if
987 exsltMathExp (double num) {
990 if (xmlXPathIsNaN(num))
997 * exsltMathExpFunction:
998 * @ctxt: an XPath parser context
999 * @nargs: the number of arguments
1001 * Wraps #exsltMathExp for use by the XPath processor.
1004 exsltMathExpFunction (xmlXPathParserContextPtr ctxt, int nargs) {
1008 xmlXPathSetArityError(ctxt);
1011 ret = xmlXPathPopNumber(ctxt);
1012 if (xmlXPathCheckError(ctxt))
1015 ret = exsltMathExp(ret);
1017 xmlXPathReturnNumber(ctxt, ret);
1020 #endif /* HAVE_MATH_H */
1023 * exsltMathRegister:
1025 * Registers the EXSLT - Math module
1029 exsltMathRegister (void) {
1030 xsltRegisterExtModuleFunction ((const xmlChar *) "min",
1031 EXSLT_MATH_NAMESPACE,
1032 exsltMathMinFunction);
1033 xsltRegisterExtModuleFunction ((const xmlChar *) "max",
1034 EXSLT_MATH_NAMESPACE,
1035 exsltMathMaxFunction);
1036 xsltRegisterExtModuleFunction ((const xmlChar *) "highest",
1037 EXSLT_MATH_NAMESPACE,
1038 exsltMathHighestFunction);
1039 xsltRegisterExtModuleFunction ((const xmlChar *) "lowest",
1040 EXSLT_MATH_NAMESPACE,
1041 exsltMathLowestFunction);
1042 /* register other math functions */
1043 xsltRegisterExtModuleFunction ((const xmlChar *) "constant",
1044 EXSLT_MATH_NAMESPACE,
1045 exsltMathConstantFunction);
1047 xsltRegisterExtModuleFunction ((const xmlChar *) "random",
1048 EXSLT_MATH_NAMESPACE,
1049 exsltMathRandomFunction);
1052 xsltRegisterExtModuleFunction ((const xmlChar *) "abs",
1053 EXSLT_MATH_NAMESPACE,
1054 exsltMathAbsFunction);
1055 xsltRegisterExtModuleFunction ((const xmlChar *) "sqrt",
1056 EXSLT_MATH_NAMESPACE,
1057 exsltMathSqrtFunction);
1058 xsltRegisterExtModuleFunction ((const xmlChar *) "power",
1059 EXSLT_MATH_NAMESPACE,
1060 exsltMathPowerFunction);
1061 xsltRegisterExtModuleFunction ((const xmlChar *) "log",
1062 EXSLT_MATH_NAMESPACE,
1063 exsltMathLogFunction);
1064 xsltRegisterExtModuleFunction ((const xmlChar *) "sin",
1065 EXSLT_MATH_NAMESPACE,
1066 exsltMathSinFunction);
1067 xsltRegisterExtModuleFunction ((const xmlChar *) "cos",
1068 EXSLT_MATH_NAMESPACE,
1069 exsltMathCosFunction);
1070 xsltRegisterExtModuleFunction ((const xmlChar *) "tan",
1071 EXSLT_MATH_NAMESPACE,
1072 exsltMathTanFunction);
1073 xsltRegisterExtModuleFunction ((const xmlChar *) "asin",
1074 EXSLT_MATH_NAMESPACE,
1075 exsltMathAsinFunction);
1076 xsltRegisterExtModuleFunction ((const xmlChar *) "acos",
1077 EXSLT_MATH_NAMESPACE,
1078 exsltMathAcosFunction);
1079 xsltRegisterExtModuleFunction ((const xmlChar *) "atan",
1080 EXSLT_MATH_NAMESPACE,
1081 exsltMathAtanFunction);
1082 xsltRegisterExtModuleFunction ((const xmlChar *) "atan2",
1083 EXSLT_MATH_NAMESPACE,
1084 exsltMathAtan2Function);
1085 xsltRegisterExtModuleFunction ((const xmlChar *) "exp",
1086 EXSLT_MATH_NAMESPACE,
1087 exsltMathExpFunction);