| #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> |
| |
| #ifdef HAVE_MATH_H |
| #include <math.h> |
| #endif |
| |
| #ifdef HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| |
| #include "exslt.h" |
| |
| /** |
| * exsltMathMin: |
| * @ns: a node-set |
| * |
| * Implements the EXSLT - Math min() function: |
| * number math:min (node-set) |
| * |
| * Returns the minimum value of the nodes passed as the argument, or |
| * xmlXPathNAN if @ns is NULL or empty or if one of the nodes |
| * turns into NaN. |
| */ |
| static double |
| exsltMathMin (xmlNodeSetPtr ns) { |
| double ret, cur; |
| int i; |
| |
| if ((ns == NULL) || (ns->nodeNr == 0)) |
| return(xmlXPathNAN); |
| ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]); |
| if (xmlXPathIsNaN(ret)) |
| return(xmlXPathNAN); |
| for (i = 1; i < ns->nodeNr; i++) { |
| cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]); |
| if (xmlXPathIsNaN(cur)) |
| return(xmlXPathNAN); |
| if (cur < ret) |
| ret = cur; |
| } |
| return(ret); |
| } |
| |
| /** |
| * exsltMathMinFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathMin for use by the XPath processor. |
| */ |
| static void |
| exsltMathMinFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlNodeSetPtr ns; |
| double ret; |
| void *user = NULL; |
| |
| if (nargs != 1) { |
| xsltGenericError(xsltGenericErrorContext, |
| "math:min: invalid number of arguments\n"); |
| ctxt->error = XPATH_INVALID_ARITY; |
| return; |
| } |
| /* We need to delay the freeing of value->user */ |
| if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { |
| user = ctxt->value->user; |
| ctxt->value->boolval = 0; |
| ctxt->value->user = NULL; |
| } |
| ns = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathMin(ns); |
| |
| xmlXPathFreeNodeSet(ns); |
| if (user != NULL) |
| xmlFreeNodeList((xmlNodePtr)user); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathMax: |
| * @ns: a node-set |
| * |
| * Implements the EXSLT - Math max() function: |
| * number math:max (node-set) |
| * |
| * Returns the maximum value of the nodes passed as arguments, or |
| * xmlXPathNAN if @ns is NULL or empty or if one of the nodes |
| * turns into NaN. |
| */ |
| static double |
| exsltMathMax (xmlNodeSetPtr ns) { |
| double ret, cur; |
| int i; |
| |
| if ((ns == NULL) || (ns->nodeNr == 0)) |
| return(xmlXPathNAN); |
| ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]); |
| if (xmlXPathIsNaN(ret)) |
| return(xmlXPathNAN); |
| for (i = 1; i < ns->nodeNr; i++) { |
| cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]); |
| if (xmlXPathIsNaN(cur)) |
| return(xmlXPathNAN); |
| if (cur > ret) |
| ret = cur; |
| } |
| return(ret); |
| } |
| |
| /** |
| * exsltMathMaxFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathMax for use by the XPath processor. |
| */ |
| static void |
| exsltMathMaxFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlNodeSetPtr ns; |
| double ret; |
| void *user = NULL; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| /* We need to delay the freeing of value->user */ |
| if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { |
| user = ctxt->value->user; |
| ctxt->value->boolval = 0; |
| ctxt->value->user = 0; |
| } |
| ns = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathMax(ns); |
| |
| xmlXPathFreeNodeSet(ns); |
| |
| if (user != NULL) |
| xmlFreeNodeList((xmlNodePtr)user); |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathHighest: |
| * @ns: a node-set |
| * |
| * Implements the EXSLT - Math highest() function: |
| * node-set math:highest (node-set) |
| * |
| * Returns the nodes in the node-set whose value is the maximum value |
| * for the node-set. |
| */ |
| static xmlNodeSetPtr |
| exsltMathHighest (xmlNodeSetPtr ns) { |
| xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL); |
| double max, cur; |
| int i; |
| |
| if ((ns == NULL) || (ns->nodeNr == 0)) |
| return(ret); |
| |
| max = xmlXPathCastNodeToNumber(ns->nodeTab[0]); |
| if (xmlXPathIsNaN(max)) |
| return(ret); |
| else |
| xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]); |
| |
| for (i = 1; i < ns->nodeNr; i++) { |
| cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]); |
| if (xmlXPathIsNaN(cur)) { |
| xmlXPathEmptyNodeSet(ret); |
| return(ret); |
| } |
| if (cur < max) |
| continue; |
| if (cur > max) { |
| max = cur; |
| xmlXPathEmptyNodeSet(ret); |
| xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]); |
| continue; |
| } |
| xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]); |
| } |
| return(ret); |
| } |
| |
| /** |
| * exsltMathHighestFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathHighest for use by the XPath processor |
| */ |
| static void |
| exsltMathHighestFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlNodeSetPtr ns, ret; |
| void *user = NULL; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| /* We need to delay the freeing of value->user */ |
| if ((ctxt->value != NULL) && ctxt->value->boolval != 0) { |
| user = ctxt->value->user; |
| ctxt->value->boolval = 0; |
| ctxt->value->user = NULL; |
| } |
| ns = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathHighest(ns); |
| |
| xmlXPathFreeNodeSet(ns); |
| if (user != NULL) |
| xmlFreeNodeList((xmlNodePtr)user); |
| |
| xmlXPathReturnNodeSet(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathLowest: |
| * @ns: a node-set |
| * |
| * Implements the EXSLT - Math lowest() function |
| * node-set math:lowest (node-set) |
| * |
| * Returns the nodes in the node-set whose value is the minimum value |
| * for the node-set. |
| */ |
| static xmlNodeSetPtr |
| exsltMathLowest (xmlNodeSetPtr ns) { |
| xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL); |
| double min, cur; |
| int i; |
| |
| if ((ns == NULL) || (ns->nodeNr == 0)) |
| return(ret); |
| |
| min = xmlXPathCastNodeToNumber(ns->nodeTab[0]); |
| if (xmlXPathIsNaN(min)) |
| return(ret); |
| else |
| xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]); |
| |
| for (i = 1; i < ns->nodeNr; i++) { |
| cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]); |
| if (xmlXPathIsNaN(cur)) { |
| xmlXPathEmptyNodeSet(ret); |
| return(ret); |
| } |
| if (cur > min) |
| continue; |
| if (cur < min) { |
| min = cur; |
| xmlXPathEmptyNodeSet(ret); |
| xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]); |
| continue; |
| } |
| xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]); |
| } |
| return(ret); |
| } |
| |
| /** |
| * exsltMathLowestFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathLowest for use by the XPath processor |
| */ |
| static void |
| exsltMathLowestFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlNodeSetPtr ns, ret; |
| void *user = NULL; |
| |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| /* We need to delay the freeing of value->user */ |
| if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { |
| user = ctxt->value->user; |
| ctxt->value->boolval = 0; |
| ctxt->value->user = NULL; |
| } |
| ns = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathLowest(ns); |
| |
| xmlXPathFreeNodeSet(ns); |
| if (user != NULL) |
| xmlFreeNodeList((xmlNodePtr)user); |
| |
| xmlXPathReturnNodeSet(ctxt, ret); |
| } |
| |
| /* math other functions */ |
| |
| /* constant values */ |
| #define EXSLT_PI (const xmlChar *) \ |
| "3.1415926535897932384626433832795028841971693993751" |
| #define EXSLT_E (const xmlChar *) \ |
| "2.71828182845904523536028747135266249775724709369996" |
| #define EXSLT_SQRRT2 (const xmlChar *) \ |
| "1.41421356237309504880168872420969807856967187537694" |
| #define EXSLT_LN2 (const xmlChar *) \ |
| "0.69314718055994530941723212145817656807550013436025" |
| #define EXSLT_LN10 (const xmlChar *) \ |
| "2.30258509299404568402" |
| #define EXSLT_LOG2E (const xmlChar *) \ |
| "1.4426950408889634074" |
| #define EXSLT_SQRT1_2 (const xmlChar *) \ |
| "0.70710678118654752440" |
| |
| /** |
| * exsltMathConstant |
| * @name: string |
| * @precision: number |
| * |
| * Implements the EXSLT - Math constant function: |
| * number math:constant(string, number) |
| * |
| * Returns a number value of the given constant with the given precision or |
| * xmlXPathNAN if name is unknown. |
| * The constants are PI, E, SQRRT2, LN2, LN10, LOG2E, and SQRT1_2 |
| */ |
| static double |
| exsltMathConstant (xmlChar *name, double precision) { |
| xmlChar *str; |
| double ret; |
| |
| if ((name == NULL) || (xmlXPathIsNaN(precision)) || (precision < 1.0)) { |
| return xmlXPathNAN; |
| } |
| |
| if (xmlStrEqual(name, BAD_CAST "PI")) { |
| int len = xmlStrlen(EXSLT_PI); |
| |
| if (precision <= len) |
| len = (int)precision; |
| |
| str = xmlStrsub(EXSLT_PI, 0, len); |
| |
| } else if (xmlStrEqual(name, BAD_CAST "E")) { |
| int len = xmlStrlen(EXSLT_E); |
| |
| if (precision <= len) |
| len = (int)precision; |
| |
| str = xmlStrsub(EXSLT_E, 0, len); |
| |
| } else if (xmlStrEqual(name, BAD_CAST "SQRRT2")) { |
| int len = xmlStrlen(EXSLT_SQRRT2); |
| |
| if (precision <= len) |
| len = (int)precision; |
| |
| str = xmlStrsub(EXSLT_SQRRT2, 0, len); |
| |
| } else if (xmlStrEqual(name, BAD_CAST "LN2")) { |
| int len = xmlStrlen(EXSLT_LN2); |
| |
| if (precision <= len) |
| len = (int)precision; |
| |
| str = xmlStrsub(EXSLT_LN2, 0, len); |
| |
| } else if (xmlStrEqual(name, BAD_CAST "LN10")) { |
| int len = xmlStrlen(EXSLT_LN10); |
| |
| if (precision <= len) |
| len = (int)precision; |
| |
| str = xmlStrsub(EXSLT_LN10, 0, len); |
| |
| } else if (xmlStrEqual(name, BAD_CAST "LOG2E")) { |
| int len = xmlStrlen(EXSLT_LOG2E); |
| |
| if (precision <= len) |
| len = (int)precision; |
| |
| str = xmlStrsub(EXSLT_LOG2E, 0, len); |
| |
| } else if (xmlStrEqual(name, BAD_CAST "SQRT1_2")) { |
| int len = xmlStrlen(EXSLT_SQRT1_2); |
| |
| if (precision <= len) |
| len = (int)precision; |
| |
| str = xmlStrsub(EXSLT_SQRT1_2, 0, len); |
| |
| } else { |
| str = NULL; |
| } |
| if (str == NULL) |
| return xmlXPathNAN; |
| ret = xmlXPathCastStringToNumber(str); |
| xmlFree(str); |
| return ret; |
| } |
| |
| /** |
| * exsltMathConstantFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathConstant for use by the XPath processor. |
| */ |
| static void |
| exsltMathConstantFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| xmlChar *name; |
| |
| if (nargs != 2) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| name = xmlXPathPopString(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathConstant(name, ret); |
| if (name != NULL) |
| xmlFree(name); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| #if defined(HAVE_STDLIB_H) && defined(RAND_MAX) |
| |
| /** |
| * exsltMathRandom: |
| * |
| * Implements the EXSLT - Math random() function: |
| * number math:random () |
| * |
| * Returns a random number between 0 and 1 inclusive. |
| */ |
| static double |
| exsltMathRandom (void) { |
| double ret; |
| int num; |
| |
| num = rand(); |
| ret = (double)num / (double)RAND_MAX; |
| return(ret); |
| } |
| |
| /** |
| * exsltMathRandomFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathRandom for use by the XPath processor. |
| */ |
| static void |
| exsltMathRandomFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 0) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| ret = exsltMathRandom(); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| #endif /* defined(HAVE_STDLIB_H) && defined(RAND_MAX) */ |
| |
| #if HAVE_MATH_H |
| |
| /** |
| * exsltMathAbs: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math abs() function: |
| * number math:abs (number) |
| * |
| * Returns the absolute value of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathAbs (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = fabs(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathAbsFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathAbs for use by the XPath processor. |
| */ |
| static void |
| exsltMathAbsFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathAbs(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathSqrt: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math sqrt() function: |
| * number math:sqrt (number) |
| * |
| * Returns the square root of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathSqrt (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = sqrt(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathSqrtFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathSqrt for use by the XPath processor. |
| */ |
| static void |
| exsltMathSqrtFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathSqrt(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathPower: |
| * @base: a double |
| * @power: a double |
| * |
| * Implements the EXSLT - Math power() function: |
| * number math:power (number, number) |
| * |
| * Returns the power base and power arguments, or xmlXPathNAN |
| * if either @base or @power is Nan. |
| */ |
| static double |
| exsltMathPower (double base, double power) { |
| double ret; |
| |
| if ((xmlXPathIsNaN(base) || xmlXPathIsNaN(power))) |
| return(xmlXPathNAN); |
| ret = pow(base, power); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathPower: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathPower for use by the XPath processor. |
| */ |
| static void |
| exsltMathPowerFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret, base; |
| |
| if (nargs != 2) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| /* power */ |
| base = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathPower(base, ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathLog: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math log() function: |
| * number math:log (number) |
| * |
| * Returns the natural log of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathLog (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = log(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathLogFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathLog for use by the XPath processor. |
| */ |
| static void |
| exsltMathLogFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathLog(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathSin: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math sin() function: |
| * number math:sin (number) |
| * |
| * Returns the sine of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathSin (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = sin(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathSinFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathSin for use by the XPath processor. |
| */ |
| static void |
| exsltMathSinFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathSin(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathCos: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math cos() function: |
| * number math:cos (number) |
| * |
| * Returns the cosine of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathCos (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = cos(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathCosFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathCos for use by the XPath processor. |
| */ |
| static void |
| exsltMathCosFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathCos(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathTan: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math tan() function: |
| * number math:tan (number) |
| * |
| * Returns the tangent of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathTan (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = tan(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathTanFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathTan for use by the XPath processor. |
| */ |
| static void |
| exsltMathTanFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathTan(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathAsin: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math asin() function: |
| * number math:asin (number) |
| * |
| * Returns the arc sine of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathAsin (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = asin(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathAsinFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathAsin for use by the XPath processor. |
| */ |
| static void |
| exsltMathAsinFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathAsin(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathAcos: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math acos() function: |
| * number math:acos (number) |
| * |
| * Returns the arc cosine of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathAcos (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = acos(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathAcosFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathAcos for use by the XPath processor. |
| */ |
| static void |
| exsltMathAcosFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathAcos(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathAtan: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math atan() function: |
| * number math:atan (number) |
| * |
| * Returns the arc tangent of the argument, or xmlXPathNAN if @num is Nan. |
| */ |
| static double |
| exsltMathAtan (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = atan(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathAtanFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathAtan for use by the XPath processor. |
| */ |
| static void |
| exsltMathAtanFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathAtan(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathAtan2: |
| * @y: a double |
| * @x: a double |
| * |
| * Implements the EXSLT - Math atan2() function: |
| * number math:atan2 (number, number) |
| * |
| * Returns the arc tangent function of the y/x arguments, or xmlXPathNAN |
| * if either @y or @x is Nan. |
| */ |
| static double |
| exsltMathAtan2 (double y, double x) { |
| double ret; |
| |
| if ((xmlXPathIsNaN(y) || xmlXPathIsNaN(x))) |
| return(xmlXPathNAN); |
| ret = atan2(y, x); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathAtan2Function: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathAtan2 for use by the XPath processor. |
| */ |
| static void |
| exsltMathAtan2Function (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret, x; |
| |
| if (nargs != 2) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| x = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| /* y */ |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathAtan2(ret, x); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| /** |
| * exsltMathExp: |
| * @num: a double |
| * |
| * Implements the EXSLT - Math exp() function: |
| * number math:exp (number) |
| * |
| * Returns the exponential function of the argument, or xmlXPathNAN if |
| * @num is Nan. |
| */ |
| static double |
| exsltMathExp (double num) { |
| double ret; |
| |
| if (xmlXPathIsNaN(num)) |
| return(xmlXPathNAN); |
| ret = exp(num); |
| return(ret); |
| } |
| |
| /** |
| * exsltMathExpFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #exsltMathExp for use by the XPath processor. |
| */ |
| static void |
| exsltMathExpFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| double ret; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| ret = xmlXPathPopNumber(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| ret = exsltMathExp(ret); |
| |
| xmlXPathReturnNumber(ctxt, ret); |
| } |
| |
| #endif /* HAVE_MATH_H */ |
| |
| /** |
| * exsltMathRegister: |
| * |
| * Registers the EXSLT - Math module |
| */ |
| |
| void |
| exsltMathRegister (void) { |
| xsltRegisterExtModuleFunction ((const xmlChar *) "min", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathMinFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "max", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathMaxFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "highest", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathHighestFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "lowest", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathLowestFunction); |
| /* register other math functions */ |
| xsltRegisterExtModuleFunction ((const xmlChar *) "constant", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathConstantFunction); |
| #ifdef HAVE_STDLIB_H |
| xsltRegisterExtModuleFunction ((const xmlChar *) "random", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathRandomFunction); |
| #endif |
| #if HAVE_MATH_H |
| xsltRegisterExtModuleFunction ((const xmlChar *) "abs", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathAbsFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "sqrt", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathSqrtFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "power", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathPowerFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "log", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathLogFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "sin", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathSinFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "cos", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathCosFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "tan", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathTanFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "asin", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathAsinFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "acos", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathAcosFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "atan", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathAtanFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "atan2", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathAtan2Function); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "exp", |
| EXSLT_MATH_NAMESPACE, |
| exsltMathExpFunction); |
| #endif |
| } |
| |
| /** |
| * exsltMathXpathCtxtRegister: |
| * |
| * Registers the EXSLT - Math module for use outside XSLT |
| */ |
| int |
| exsltMathXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix) |
| { |
| if (ctxt |
| && prefix |
| && !xmlXPathRegisterNs(ctxt, |
| prefix, |
| (const xmlChar *) EXSLT_MATH_NAMESPACE) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "min", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathMinFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "max", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathMaxFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "highest", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathHighestFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "lowest", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathLowestFunction) |
| #ifdef HAVE_STDLIB_H |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "random", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathRandomFunction) |
| #endif |
| #if HAVE_MATH_H |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "abs", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathAbsFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "sqrt", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathSqrtFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "power", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathPowerFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "log", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathLogFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "sin", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathSinFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "cos", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathCosFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "tan", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathTanFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "asin", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathAsinFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "acos", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathAcosFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "atan", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathAtanFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "atan2", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathAtan2Function) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "exp", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathExpFunction) |
| #endif |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "constant", |
| (const xmlChar *) EXSLT_MATH_NAMESPACE, |
| exsltMathConstantFunction)) { |
| return 0; |
| } |
| return -1; |
| } |