1#define IN_LIBEXSLT 2#include "libexslt/libexslt.h" 3 4#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__) 5#include <win32config.h> 6#else 7#include "config.h" 8#endif 9 10#include <libxml/tree.h> 11#include <libxml/xpath.h> 12#include <libxml/xpathInternals.h> 13 14#include <libxslt/xsltconfig.h> 15#include <libxslt/xsltutils.h> 16#include <libxslt/xsltInternals.h> 17#include <libxslt/extensions.h> 18 19#ifdef HAVE_MATH_H 20#include <math.h> 21#endif 22 23#ifdef HAVE_STDLIB_H 24#include <stdlib.h> 25#endif 26 27#include "exslt.h" 28 29/** 30 * exsltMathMin: 31 * @ns: a node-set 32 * 33 * Implements the EXSLT - Math min() function: 34 * number math:min (node-set) 35 * 36 * Returns the minimum value of the nodes passed as the argument, or 37 * xmlXPathNAN if @ns is NULL or empty or if one of the nodes 38 * turns into NaN. 39 */ 40static double 41exsltMathMin (xmlNodeSetPtr ns) { 42 double ret, cur; 43 int i; 44 45 if ((ns == NULL) || (ns->nodeNr == 0)) 46 return(xmlXPathNAN); 47 ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]); 48 if (xmlXPathIsNaN(ret)) 49 return(xmlXPathNAN); 50 for (i = 1; i < ns->nodeNr; i++) { 51 cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]); 52 if (xmlXPathIsNaN(cur)) 53 return(xmlXPathNAN); 54 if (cur < ret) 55 ret = cur; 56 } 57 return(ret); 58} 59 60/** 61 * exsltMathMinFunction: 62 * @ctxt: an XPath parser context 63 * @nargs: the number of arguments 64 * 65 * Wraps #exsltMathMin for use by the XPath processor. 66 */ 67static void 68exsltMathMinFunction (xmlXPathParserContextPtr ctxt, int nargs) { 69 xmlNodeSetPtr ns; 70 double ret; 71 void *user = NULL; 72 73 if (nargs != 1) { 74 xsltGenericError(xsltGenericErrorContext, 75 "math:min: invalid number of arguments\n"); 76 ctxt->error = XPATH_INVALID_ARITY; 77 return; 78 } 79 /* We need to delay the freeing of value->user */ 80 if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { 81 user = ctxt->value->user; 82 ctxt->value->boolval = 0; 83 ctxt->value->user = NULL; 84 } 85 ns = xmlXPathPopNodeSet(ctxt); 86 if (xmlXPathCheckError(ctxt)) 87 return; 88 89 ret = exsltMathMin(ns); 90 91 xmlXPathFreeNodeSet(ns); 92 if (user != NULL) 93 xmlFreeNodeList((xmlNodePtr)user); 94 95 xmlXPathReturnNumber(ctxt, ret); 96} 97 98/** 99 * exsltMathMax: 100 * @ns: a node-set 101 * 102 * Implements the EXSLT - Math max() function: 103 * number math:max (node-set) 104 * 105 * Returns the maximum value of the nodes passed as arguments, or 106 * xmlXPathNAN if @ns is NULL or empty or if one of the nodes 107 * turns into NaN. 108 */ 109static double 110exsltMathMax (xmlNodeSetPtr ns) { 111 double ret, cur; 112 int i; 113 114 if ((ns == NULL) || (ns->nodeNr == 0)) 115 return(xmlXPathNAN); 116 ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]); 117 if (xmlXPathIsNaN(ret)) 118 return(xmlXPathNAN); 119 for (i = 1; i < ns->nodeNr; i++) { 120 cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]); 121 if (xmlXPathIsNaN(cur)) 122 return(xmlXPathNAN); 123 if (cur > ret) 124 ret = cur; 125 } 126 return(ret); 127} 128 129/** 130 * exsltMathMaxFunction: 131 * @ctxt: an XPath parser context 132 * @nargs: the number of arguments 133 * 134 * Wraps #exsltMathMax for use by the XPath processor. 135 */ 136static void 137exsltMathMaxFunction (xmlXPathParserContextPtr ctxt, int nargs) { 138 xmlNodeSetPtr ns; 139 double ret; 140 void *user = NULL; 141 142 if (nargs != 1) { 143 xmlXPathSetArityError(ctxt); 144 return; 145 } 146 147 /* We need to delay the freeing of value->user */ 148 if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { 149 user = ctxt->value->user; 150 ctxt->value->boolval = 0; 151 ctxt->value->user = 0; 152 } 153 ns = xmlXPathPopNodeSet(ctxt); 154 if (xmlXPathCheckError(ctxt)) 155 return; 156 157 ret = exsltMathMax(ns); 158 159 xmlXPathFreeNodeSet(ns); 160 161 if (user != NULL) 162 xmlFreeNodeList((xmlNodePtr)user); 163 xmlXPathReturnNumber(ctxt, ret); 164} 165 166/** 167 * exsltMathHighest: 168 * @ns: a node-set 169 * 170 * Implements the EXSLT - Math highest() function: 171 * node-set math:highest (node-set) 172 * 173 * Returns the nodes in the node-set whose value is the maximum value 174 * for the node-set. 175 */ 176static xmlNodeSetPtr 177exsltMathHighest (xmlNodeSetPtr ns) { 178 xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL); 179 double max, cur; 180 int i; 181 182 if ((ns == NULL) || (ns->nodeNr == 0)) 183 return(ret); 184 185 max = xmlXPathCastNodeToNumber(ns->nodeTab[0]); 186 if (xmlXPathIsNaN(max)) 187 return(ret); 188 else 189 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]); 190 191 for (i = 1; i < ns->nodeNr; i++) { 192 cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]); 193 if (xmlXPathIsNaN(cur)) { 194 xmlXPathEmptyNodeSet(ret); 195 return(ret); 196 } 197 if (cur < max) 198 continue; 199 if (cur > max) { 200 max = cur; 201 xmlXPathEmptyNodeSet(ret); 202 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]); 203 continue; 204 } 205 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]); 206 } 207 return(ret); 208} 209 210/** 211 * exsltMathHighestFunction: 212 * @ctxt: an XPath parser context 213 * @nargs: the number of arguments 214 * 215 * Wraps #exsltMathHighest for use by the XPath processor 216 */ 217static void 218exsltMathHighestFunction (xmlXPathParserContextPtr ctxt, int nargs) { 219 xmlNodeSetPtr ns, ret; 220 void *user = NULL; 221 222 if (nargs != 1) { 223 xmlXPathSetArityError(ctxt); 224 return; 225 } 226 227 /* We need to delay the freeing of value->user */ 228 if ((ctxt->value != NULL) && ctxt->value->boolval != 0) { 229 user = ctxt->value->user; 230 ctxt->value->boolval = 0; 231 ctxt->value->user = NULL; 232 } 233 ns = xmlXPathPopNodeSet(ctxt); 234 if (xmlXPathCheckError(ctxt)) 235 return; 236 237 ret = exsltMathHighest(ns); 238 239 xmlXPathFreeNodeSet(ns); 240 if (user != NULL) 241 xmlFreeNodeList((xmlNodePtr)user); 242 243 xmlXPathReturnNodeSet(ctxt, ret); 244} 245 246/** 247 * exsltMathLowest: 248 * @ns: a node-set 249 * 250 * Implements the EXSLT - Math lowest() function 251 * node-set math:lowest (node-set) 252 * 253 * Returns the nodes in the node-set whose value is the minimum value 254 * for the node-set. 255 */ 256static xmlNodeSetPtr 257exsltMathLowest (xmlNodeSetPtr ns) { 258 xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL); 259 double min, cur; 260 int i; 261 262 if ((ns == NULL) || (ns->nodeNr == 0)) 263 return(ret); 264 265 min = xmlXPathCastNodeToNumber(ns->nodeTab[0]); 266 if (xmlXPathIsNaN(min)) 267 return(ret); 268 else 269 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]); 270 271 for (i = 1; i < ns->nodeNr; i++) { 272 cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]); 273 if (xmlXPathIsNaN(cur)) { 274 xmlXPathEmptyNodeSet(ret); 275 return(ret); 276 } 277 if (cur > min) 278 continue; 279 if (cur < min) { 280 min = cur; 281 xmlXPathEmptyNodeSet(ret); 282 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]); 283 continue; 284 } 285 xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]); 286 } 287 return(ret); 288} 289 290/** 291 * exsltMathLowestFunction: 292 * @ctxt: an XPath parser context 293 * @nargs: the number of arguments 294 * 295 * Wraps #exsltMathLowest for use by the XPath processor 296 */ 297static void 298exsltMathLowestFunction (xmlXPathParserContextPtr ctxt, int nargs) { 299 xmlNodeSetPtr ns, ret; 300 void *user = NULL; 301 302 303 if (nargs != 1) { 304 xmlXPathSetArityError(ctxt); 305 return; 306 } 307 308 /* We need to delay the freeing of value->user */ 309 if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) { 310 user = ctxt->value->user; 311 ctxt->value->boolval = 0; 312 ctxt->value->user = NULL; 313 } 314 ns = xmlXPathPopNodeSet(ctxt); 315 if (xmlXPathCheckError(ctxt)) 316 return; 317 318 ret = exsltMathLowest(ns); 319 320 xmlXPathFreeNodeSet(ns); 321 if (user != NULL) 322 xmlFreeNodeList((xmlNodePtr)user); 323 324 xmlXPathReturnNodeSet(ctxt, ret); 325} 326 327/* math other functions */ 328 329/* constant values */ 330#define EXSLT_PI (const xmlChar *) \ 331 "3.1415926535897932384626433832795028841971693993751" 332#define EXSLT_E (const xmlChar *) \ 333 "2.71828182845904523536028747135266249775724709369996" 334#define EXSLT_SQRRT2 (const xmlChar *) \ 335 "1.41421356237309504880168872420969807856967187537694" 336#define EXSLT_LN2 (const xmlChar *) \ 337 "0.69314718055994530941723212145817656807550013436025" 338#define EXSLT_LN10 (const xmlChar *) \ 339 "2.30258509299404568402" 340#define EXSLT_LOG2E (const xmlChar *) \ 341 "1.4426950408889634074" 342#define EXSLT_SQRT1_2 (const xmlChar *) \ 343 "0.70710678118654752440" 344 345/** 346 * exsltMathConstant 347 * @name: string 348 * @precision: number 349 * 350 * Implements the EXSLT - Math constant function: 351 * number math:constant(string, number) 352 * 353 * Returns a number value of the given constant with the given precision or 354 * xmlXPathNAN if name is unknown. 355 * The constants are PI, E, SQRRT2, LN2, LN10, LOG2E, and SQRT1_2 356 */ 357static double 358exsltMathConstant (xmlChar *name, double precision) { 359 xmlChar *str; 360 361 if ((name == NULL) || (xmlXPathIsNaN(precision)) || (precision < 1.0)) { 362 return xmlXPathNAN; 363 } 364 365 if (xmlStrEqual(name, BAD_CAST "PI")) { 366 int len = xmlStrlen(EXSLT_PI); 367 368 if (precision <= len) 369 len = (int)precision; 370 371 str = xmlStrsub(EXSLT_PI, 0, len); 372 if (str == NULL) 373 return xmlXPathNAN; 374 375 return xmlXPathCastStringToNumber(str); 376 377 } else if (xmlStrEqual(name, BAD_CAST "E")) { 378 int len = xmlStrlen(EXSLT_E); 379 380 if (precision <= len) 381 len = (int)precision; 382 383 str = xmlStrsub(EXSLT_E, 0, len); 384 if (str == NULL) 385 return xmlXPathNAN; 386 387 return xmlXPathCastStringToNumber(str); 388 389 } else if (xmlStrEqual(name, BAD_CAST "SQRRT2")) { 390 int len = xmlStrlen(EXSLT_SQRRT2); 391 392 if (precision <= len) 393 len = (int)precision; 394 395 str = xmlStrsub(EXSLT_SQRRT2, 0, len); 396 if (str == NULL) 397 return xmlXPathNAN; 398 399 return xmlXPathCastStringToNumber(str); 400 401 } else if (xmlStrEqual(name, BAD_CAST "LN2")) { 402 int len = xmlStrlen(EXSLT_LN2); 403 404 if (precision <= len) 405 len = (int)precision; 406 407 str = xmlStrsub(EXSLT_LN2, 0, len); 408 if (str == NULL) 409 return xmlXPathNAN; 410 411 return xmlXPathCastStringToNumber(str); 412 413 } else if (xmlStrEqual(name, BAD_CAST "LN10")) { 414 int len = xmlStrlen(EXSLT_LN10); 415 416 if (precision <= len) 417 len = (int)precision; 418 419 str = xmlStrsub(EXSLT_LN10, 0, len); 420 if (str == NULL) 421 return xmlXPathNAN; 422 423 return xmlXPathCastStringToNumber(str); 424 425 } else if (xmlStrEqual(name, BAD_CAST "LOG2E")) { 426 int len = xmlStrlen(EXSLT_LOG2E); 427 428 if (precision <= len) 429 len = (int)precision; 430 431 str = xmlStrsub(EXSLT_LOG2E, 0, len); 432 if (str == NULL) 433 return xmlXPathNAN; 434 435 return xmlXPathCastStringToNumber(str); 436 437 } else if (xmlStrEqual(name, BAD_CAST "SQRT1_2")) { 438 int len = xmlStrlen(EXSLT_SQRT1_2); 439 440 if (precision <= len) 441 len = (int)precision; 442 443 str = xmlStrsub(EXSLT_SQRT1_2, 0, len); 444 if (str == NULL) 445 return xmlXPathNAN; 446 447 return xmlXPathCastStringToNumber(str); 448 449 } else { 450 return xmlXPathNAN; 451 } 452} 453 454/** 455 * exsltMathConstantFunction: 456 * @ctxt: an XPath parser context 457 * @nargs: the number of arguments 458 * 459 * Wraps #exsltMathConstant for use by the XPath processor. 460 */ 461static void 462exsltMathConstantFunction (xmlXPathParserContextPtr ctxt, int nargs) { 463 double ret; 464 xmlChar *name; 465 466 if (nargs != 2) { 467 xmlXPathSetArityError(ctxt); 468 return; 469 } 470 ret = xmlXPathPopNumber(ctxt); 471 if (xmlXPathCheckError(ctxt)) 472 return; 473 474 name = xmlXPathPopString(ctxt); 475 if (xmlXPathCheckError(ctxt)) 476 return; 477 478 ret = exsltMathConstant(name, ret); 479 480 xmlXPathReturnNumber(ctxt, ret); 481} 482 483#if defined(HAVE_STDLIB_H) && defined(RAND_MAX) 484 485/** 486 * exsltMathRandom: 487 * 488 * Implements the EXSLT - Math random() function: 489 * number math:random () 490 * 491 * Returns a random number between 0 and 1 inclusive. 492 */ 493static double 494exsltMathRandom (void) { 495 double ret; 496 int num; 497 498 num = rand(); 499 ret = (double)num / (double)RAND_MAX; 500 return(ret); 501} 502 503/** 504 * exsltMathRandomFunction: 505 * @ctxt: an XPath parser context 506 * @nargs: the number of arguments 507 * 508 * Wraps #exsltMathRandom for use by the XPath processor. 509 */ 510static void 511exsltMathRandomFunction (xmlXPathParserContextPtr ctxt, int nargs) { 512 double ret; 513 514 if (nargs != 0) { 515 xmlXPathSetArityError(ctxt); 516 return; 517 } 518 519 ret = exsltMathRandom(); 520 521 xmlXPathReturnNumber(ctxt, ret); 522} 523 524#endif /* defined(HAVE_STDLIB_H) && defined(RAND_MAX) */ 525 526#if HAVE_MATH_H 527 528/** 529 * exsltMathAbs: 530 * @num: a double 531 * 532 * Implements the EXSLT - Math abs() function: 533 * number math:abs (number) 534 * 535 * Returns the absolute value of the argument, or xmlXPathNAN if @num is Nan. 536 */ 537static double 538exsltMathAbs (double num) { 539 double ret; 540 541 if (xmlXPathIsNaN(num)) 542 return(xmlXPathNAN); 543 ret = fabs(num); 544 return(ret); 545} 546 547/** 548 * exsltMathAbsFunction: 549 * @ctxt: an XPath parser context 550 * @nargs: the number of arguments 551 * 552 * Wraps #exsltMathAbs for use by the XPath processor. 553 */ 554static void 555exsltMathAbsFunction (xmlXPathParserContextPtr ctxt, int nargs) { 556 double ret; 557 558 if (nargs != 1) { 559 xmlXPathSetArityError(ctxt); 560 return; 561 } 562 ret = xmlXPathPopNumber(ctxt); 563 if (xmlXPathCheckError(ctxt)) 564 return; 565 566 ret = exsltMathAbs(ret); 567 568 xmlXPathReturnNumber(ctxt, ret); 569} 570 571/** 572 * exsltMathSqrt: 573 * @num: a double 574 * 575 * Implements the EXSLT - Math sqrt() function: 576 * number math:sqrt (number) 577 * 578 * Returns the square root of the argument, or xmlXPathNAN if @num is Nan. 579 */ 580static double 581exsltMathSqrt (double num) { 582 double ret; 583 584 if (xmlXPathIsNaN(num)) 585 return(xmlXPathNAN); 586 ret = sqrt(num); 587 return(ret); 588} 589 590/** 591 * exsltMathSqrtFunction: 592 * @ctxt: an XPath parser context 593 * @nargs: the number of arguments 594 * 595 * Wraps #exsltMathSqrt for use by the XPath processor. 596 */ 597static void 598exsltMathSqrtFunction (xmlXPathParserContextPtr ctxt, int nargs) { 599 double ret; 600 601 if (nargs != 1) { 602 xmlXPathSetArityError(ctxt); 603 return; 604 } 605 ret = xmlXPathPopNumber(ctxt); 606 if (xmlXPathCheckError(ctxt)) 607 return; 608 609 ret = exsltMathSqrt(ret); 610 611 xmlXPathReturnNumber(ctxt, ret); 612} 613 614/** 615 * exsltMathPower: 616 * @base: a double 617 * @power: a double 618 * 619 * Implements the EXSLT - Math power() function: 620 * number math:power (number, number) 621 * 622 * Returns the power base and power arguments, or xmlXPathNAN 623 * if either @base or @power is Nan. 624 */ 625static double 626exsltMathPower (double base, double power) { 627 double ret; 628 629 if ((xmlXPathIsNaN(base) || xmlXPathIsNaN(power))) 630 return(xmlXPathNAN); 631 ret = pow(base, power); 632 return(ret); 633} 634 635/** 636 * exsltMathPower: 637 * @ctxt: an XPath parser context 638 * @nargs: the number of arguments 639 * 640 * Wraps #exsltMathPower for use by the XPath processor. 641 */ 642static void 643exsltMathPowerFunction (xmlXPathParserContextPtr ctxt, int nargs) { 644 double ret, base; 645 646 if (nargs != 2) { 647 xmlXPathSetArityError(ctxt); 648 return; 649 } 650 ret = xmlXPathPopNumber(ctxt); 651 if (xmlXPathCheckError(ctxt)) 652 return; 653 654 /* power */ 655 base = xmlXPathPopNumber(ctxt); 656 if (xmlXPathCheckError(ctxt)) 657 return; 658 659 ret = exsltMathPower(base, ret); 660 661 xmlXPathReturnNumber(ctxt, ret); 662} 663 664/** 665 * exsltMathLog: 666 * @num: a double 667 * 668 * Implements the EXSLT - Math log() function: 669 * number math:log (number) 670 * 671 * Returns the natural log of the argument, or xmlXPathNAN if @num is Nan. 672 */ 673static double 674exsltMathLog (double num) { 675 double ret; 676 677 if (xmlXPathIsNaN(num)) 678 return(xmlXPathNAN); 679 ret = log(num); 680 return(ret); 681} 682 683/** 684 * exsltMathLogFunction: 685 * @ctxt: an XPath parser context 686 * @nargs: the number of arguments 687 * 688 * Wraps #exsltMathLog for use by the XPath processor. 689 */ 690static void 691exsltMathLogFunction (xmlXPathParserContextPtr ctxt, int nargs) { 692 double ret; 693 694 if (nargs != 1) { 695 xmlXPathSetArityError(ctxt); 696 return; 697 } 698 ret = xmlXPathPopNumber(ctxt); 699 if (xmlXPathCheckError(ctxt)) 700 return; 701 702 ret = exsltMathLog(ret); 703 704 xmlXPathReturnNumber(ctxt, ret); 705} 706 707/** 708 * exsltMathSin: 709 * @num: a double 710 * 711 * Implements the EXSLT - Math sin() function: 712 * number math:sin (number) 713 * 714 * Returns the sine of the argument, or xmlXPathNAN if @num is Nan. 715 */ 716static double 717exsltMathSin (double num) { 718 double ret; 719 720 if (xmlXPathIsNaN(num)) 721 return(xmlXPathNAN); 722 ret = sin(num); 723 return(ret); 724} 725 726/** 727 * exsltMathSinFunction: 728 * @ctxt: an XPath parser context 729 * @nargs: the number of arguments 730 * 731 * Wraps #exsltMathSin for use by the XPath processor. 732 */ 733static void 734exsltMathSinFunction (xmlXPathParserContextPtr ctxt, int nargs) { 735 double ret; 736 737 if (nargs != 1) { 738 xmlXPathSetArityError(ctxt); 739 return; 740 } 741 ret = xmlXPathPopNumber(ctxt); 742 if (xmlXPathCheckError(ctxt)) 743 return; 744 745 ret = exsltMathSin(ret); 746 747 xmlXPathReturnNumber(ctxt, ret); 748} 749 750/** 751 * exsltMathCos: 752 * @num: a double 753 * 754 * Implements the EXSLT - Math cos() function: 755 * number math:cos (number) 756 * 757 * Returns the cosine of the argument, or xmlXPathNAN if @num is Nan. 758 */ 759static double 760exsltMathCos (double num) { 761 double ret; 762 763 if (xmlXPathIsNaN(num)) 764 return(xmlXPathNAN); 765 ret = cos(num); 766 return(ret); 767} 768 769/** 770 * exsltMathCosFunction: 771 * @ctxt: an XPath parser context 772 * @nargs: the number of arguments 773 * 774 * Wraps #exsltMathCos for use by the XPath processor. 775 */ 776static void 777exsltMathCosFunction (xmlXPathParserContextPtr ctxt, int nargs) { 778 double ret; 779 780 if (nargs != 1) { 781 xmlXPathSetArityError(ctxt); 782 return; 783 } 784 ret = xmlXPathPopNumber(ctxt); 785 if (xmlXPathCheckError(ctxt)) 786 return; 787 788 ret = exsltMathCos(ret); 789 790 xmlXPathReturnNumber(ctxt, ret); 791} 792 793/** 794 * exsltMathTan: 795 * @num: a double 796 * 797 * Implements the EXSLT - Math tan() function: 798 * number math:tan (number) 799 * 800 * Returns the tangent of the argument, or xmlXPathNAN if @num is Nan. 801 */ 802static double 803exsltMathTan (double num) { 804 double ret; 805 806 if (xmlXPathIsNaN(num)) 807 return(xmlXPathNAN); 808 ret = tan(num); 809 return(ret); 810} 811 812/** 813 * exsltMathTanFunction: 814 * @ctxt: an XPath parser context 815 * @nargs: the number of arguments 816 * 817 * Wraps #exsltMathTan for use by the XPath processor. 818 */ 819static void 820exsltMathTanFunction (xmlXPathParserContextPtr ctxt, int nargs) { 821 double ret; 822 823 if (nargs != 1) { 824 xmlXPathSetArityError(ctxt); 825 return; 826 } 827 ret = xmlXPathPopNumber(ctxt); 828 if (xmlXPathCheckError(ctxt)) 829 return; 830 831 ret = exsltMathTan(ret); 832 833 xmlXPathReturnNumber(ctxt, ret); 834} 835 836/** 837 * exsltMathAsin: 838 * @num: a double 839 * 840 * Implements the EXSLT - Math asin() function: 841 * number math:asin (number) 842 * 843 * Returns the arc sine of the argument, or xmlXPathNAN if @num is Nan. 844 */ 845static double 846exsltMathAsin (double num) { 847 double ret; 848 849 if (xmlXPathIsNaN(num)) 850 return(xmlXPathNAN); 851 ret = asin(num); 852 return(ret); 853} 854 855/** 856 * exsltMathAsinFunction: 857 * @ctxt: an XPath parser context 858 * @nargs: the number of arguments 859 * 860 * Wraps #exsltMathAsin for use by the XPath processor. 861 */ 862static void 863exsltMathAsinFunction (xmlXPathParserContextPtr ctxt, int nargs) { 864 double ret; 865 866 if (nargs != 1) { 867 xmlXPathSetArityError(ctxt); 868 return; 869 } 870 ret = xmlXPathPopNumber(ctxt); 871 if (xmlXPathCheckError(ctxt)) 872 return; 873 874 ret = exsltMathAsin(ret); 875 876 xmlXPathReturnNumber(ctxt, ret); 877} 878 879/** 880 * exsltMathAcos: 881 * @num: a double 882 * 883 * Implements the EXSLT - Math acos() function: 884 * number math:acos (number) 885 * 886 * Returns the arc cosine of the argument, or xmlXPathNAN if @num is Nan. 887 */ 888static double 889exsltMathAcos (double num) { 890 double ret; 891 892 if (xmlXPathIsNaN(num)) 893 return(xmlXPathNAN); 894 ret = acos(num); 895 return(ret); 896} 897 898/** 899 * exsltMathAcosFunction: 900 * @ctxt: an XPath parser context 901 * @nargs: the number of arguments 902 * 903 * Wraps #exsltMathAcos for use by the XPath processor. 904 */ 905static void 906exsltMathAcosFunction (xmlXPathParserContextPtr ctxt, int nargs) { 907 double ret; 908 909 if (nargs != 1) { 910 xmlXPathSetArityError(ctxt); 911 return; 912 } 913 ret = xmlXPathPopNumber(ctxt); 914 if (xmlXPathCheckError(ctxt)) 915 return; 916 917 ret = exsltMathAcos(ret); 918 919 xmlXPathReturnNumber(ctxt, ret); 920} 921 922/** 923 * exsltMathAtan: 924 * @num: a double 925 * 926 * Implements the EXSLT - Math atan() function: 927 * number math:atan (number) 928 * 929 * Returns the arc tangent of the argument, or xmlXPathNAN if @num is Nan. 930 */ 931static double 932exsltMathAtan (double num) { 933 double ret; 934 935 if (xmlXPathIsNaN(num)) 936 return(xmlXPathNAN); 937 ret = atan(num); 938 return(ret); 939} 940 941/** 942 * exsltMathAtanFunction: 943 * @ctxt: an XPath parser context 944 * @nargs: the number of arguments 945 * 946 * Wraps #exsltMathAtan for use by the XPath processor. 947 */ 948static void 949exsltMathAtanFunction (xmlXPathParserContextPtr ctxt, int nargs) { 950 double ret; 951 952 if (nargs != 1) { 953 xmlXPathSetArityError(ctxt); 954 return; 955 } 956 ret = xmlXPathPopNumber(ctxt); 957 if (xmlXPathCheckError(ctxt)) 958 return; 959 960 ret = exsltMathAtan(ret); 961 962 xmlXPathReturnNumber(ctxt, ret); 963} 964 965/** 966 * exsltMathAtan2: 967 * @y: a double 968 * @x: a double 969 * 970 * Implements the EXSLT - Math atan2() function: 971 * number math:atan2 (number, number) 972 * 973 * Returns the arc tangent function of the y/x arguments, or xmlXPathNAN 974 * if either @y or @x is Nan. 975 */ 976static double 977exsltMathAtan2 (double y, double x) { 978 double ret; 979 980 if ((xmlXPathIsNaN(y) || xmlXPathIsNaN(x))) 981 return(xmlXPathNAN); 982 ret = atan2(y, x); 983 return(ret); 984} 985 986/** 987 * exsltMathAtan2Function: 988 * @ctxt: an XPath parser context 989 * @nargs: the number of arguments 990 * 991 * Wraps #exsltMathAtan2 for use by the XPath processor. 992 */ 993static void 994exsltMathAtan2Function (xmlXPathParserContextPtr ctxt, int nargs) { 995 double ret, y; 996 997 if (nargs != 2) { 998 xmlXPathSetArityError(ctxt); 999 return; 1000 } 1001 y = xmlXPathPopNumber(ctxt); 1002 if (xmlXPathCheckError(ctxt)) 1003 return; 1004 1005 /* x */ 1006 ret = xmlXPathPopNumber(ctxt); 1007 if (xmlXPathCheckError(ctxt)) 1008 return; 1009 1010 ret = exsltMathAtan2(y, ret); 1011 1012 xmlXPathReturnNumber(ctxt, ret); 1013} 1014 1015/** 1016 * exsltMathExp: 1017 * @num: a double 1018 * 1019 * Implements the EXSLT - Math exp() function: 1020 * number math:exp (number) 1021 * 1022 * Returns the exponential function of the argument, or xmlXPathNAN if 1023 * @num is Nan. 1024 */ 1025static double 1026exsltMathExp (double num) { 1027 double ret; 1028 1029 if (xmlXPathIsNaN(num)) 1030 return(xmlXPathNAN); 1031 ret = exp(num); 1032 return(ret); 1033} 1034 1035/** 1036 * exsltMathExpFunction: 1037 * @ctxt: an XPath parser context 1038 * @nargs: the number of arguments 1039 * 1040 * Wraps #exsltMathExp for use by the XPath processor. 1041 */ 1042static void 1043exsltMathExpFunction (xmlXPathParserContextPtr ctxt, int nargs) { 1044 double ret; 1045 1046 if (nargs != 1) { 1047 xmlXPathSetArityError(ctxt); 1048 return; 1049 } 1050 ret = xmlXPathPopNumber(ctxt); 1051 if (xmlXPathCheckError(ctxt)) 1052 return; 1053 1054 ret = exsltMathExp(ret); 1055 1056 xmlXPathReturnNumber(ctxt, ret); 1057} 1058 1059#endif /* HAVE_MATH_H */ 1060 1061/** 1062 * exsltMathRegister: 1063 * 1064 * Registers the EXSLT - Math module 1065 */ 1066 1067void 1068exsltMathRegister (void) { 1069 xsltRegisterExtModuleFunction ((const xmlChar *) "min", 1070 EXSLT_MATH_NAMESPACE, 1071 exsltMathMinFunction); 1072 xsltRegisterExtModuleFunction ((const xmlChar *) "max", 1073 EXSLT_MATH_NAMESPACE, 1074 exsltMathMaxFunction); 1075 xsltRegisterExtModuleFunction ((const xmlChar *) "highest", 1076 EXSLT_MATH_NAMESPACE, 1077 exsltMathHighestFunction); 1078 xsltRegisterExtModuleFunction ((const xmlChar *) "lowest", 1079 EXSLT_MATH_NAMESPACE, 1080 exsltMathLowestFunction); 1081 /* register other math functions */ 1082 xsltRegisterExtModuleFunction ((const xmlChar *) "constant", 1083 EXSLT_MATH_NAMESPACE, 1084 exsltMathConstantFunction); 1085#ifdef HAVE_STDLIB_H 1086 xsltRegisterExtModuleFunction ((const xmlChar *) "random", 1087 EXSLT_MATH_NAMESPACE, 1088 exsltMathRandomFunction); 1089#endif 1090#if HAVE_MATH_H 1091 xsltRegisterExtModuleFunction ((const xmlChar *) "abs", 1092 EXSLT_MATH_NAMESPACE, 1093 exsltMathAbsFunction); 1094 xsltRegisterExtModuleFunction ((const xmlChar *) "sqrt", 1095 EXSLT_MATH_NAMESPACE, 1096 exsltMathSqrtFunction); 1097 xsltRegisterExtModuleFunction ((const xmlChar *) "power", 1098 EXSLT_MATH_NAMESPACE, 1099 exsltMathPowerFunction); 1100 xsltRegisterExtModuleFunction ((const xmlChar *) "log", 1101 EXSLT_MATH_NAMESPACE, 1102 exsltMathLogFunction); 1103 xsltRegisterExtModuleFunction ((const xmlChar *) "sin", 1104 EXSLT_MATH_NAMESPACE, 1105 exsltMathSinFunction); 1106 xsltRegisterExtModuleFunction ((const xmlChar *) "cos", 1107 EXSLT_MATH_NAMESPACE, 1108 exsltMathCosFunction); 1109 xsltRegisterExtModuleFunction ((const xmlChar *) "tan", 1110 EXSLT_MATH_NAMESPACE, 1111 exsltMathTanFunction); 1112 xsltRegisterExtModuleFunction ((const xmlChar *) "asin", 1113 EXSLT_MATH_NAMESPACE, 1114 exsltMathAsinFunction); 1115 xsltRegisterExtModuleFunction ((const xmlChar *) "acos", 1116 EXSLT_MATH_NAMESPACE, 1117 exsltMathAcosFunction); 1118 xsltRegisterExtModuleFunction ((const xmlChar *) "atan", 1119 EXSLT_MATH_NAMESPACE, 1120 exsltMathAtanFunction); 1121 xsltRegisterExtModuleFunction ((const xmlChar *) "atan2", 1122 EXSLT_MATH_NAMESPACE, 1123 exsltMathAtan2Function); 1124 xsltRegisterExtModuleFunction ((const xmlChar *) "exp", 1125 EXSLT_MATH_NAMESPACE, 1126 exsltMathExpFunction); 1127#endif 1128} 1129