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 */ 40 static double 41 exsltMathMin (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 */ 67 static void 68 exsltMathMinFunction (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 */ 109 static double 110 exsltMathMax (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 */ 136 static void 137 exsltMathMaxFunction (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 */ 176 static xmlNodeSetPtr 177 exsltMathHighest (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 */ 217 static void 218 exsltMathHighestFunction (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 */ 256 static xmlNodeSetPtr 257 exsltMathLowest (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 */ 297 static void 298 exsltMathLowestFunction (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 */ 357 static double 358 exsltMathConstant (xmlChar *name, double precision) { 359 xmlChar *str; 360 double ret; 361 362 if ((name == NULL) || (xmlXPathIsNaN(precision)) || (precision < 1.0)) { 363 return xmlXPathNAN; 364 } 365 366 if (xmlStrEqual(name, BAD_CAST "PI")) { 367 int len = xmlStrlen(EXSLT_PI); 368 369 if (precision <= len) 370 len = (int)precision; 371 372 str = xmlStrsub(EXSLT_PI, 0, len); 373 374 } else if (xmlStrEqual(name, BAD_CAST "E")) { 375 int len = xmlStrlen(EXSLT_E); 376 377 if (precision <= len) 378 len = (int)precision; 379 380 str = xmlStrsub(EXSLT_E, 0, len); 381 382 } else if (xmlStrEqual(name, BAD_CAST "SQRRT2")) { 383 int len = xmlStrlen(EXSLT_SQRRT2); 384 385 if (precision <= len) 386 len = (int)precision; 387 388 str = xmlStrsub(EXSLT_SQRRT2, 0, len); 389 390 } else if (xmlStrEqual(name, BAD_CAST "LN2")) { 391 int len = xmlStrlen(EXSLT_LN2); 392 393 if (precision <= len) 394 len = (int)precision; 395 396 str = xmlStrsub(EXSLT_LN2, 0, len); 397 398 } else if (xmlStrEqual(name, BAD_CAST "LN10")) { 399 int len = xmlStrlen(EXSLT_LN10); 400 401 if (precision <= len) 402 len = (int)precision; 403 404 str = xmlStrsub(EXSLT_LN10, 0, len); 405 406 } else if (xmlStrEqual(name, BAD_CAST "LOG2E")) { 407 int len = xmlStrlen(EXSLT_LOG2E); 408 409 if (precision <= len) 410 len = (int)precision; 411 412 str = xmlStrsub(EXSLT_LOG2E, 0, len); 413 414 } else if (xmlStrEqual(name, BAD_CAST "SQRT1_2")) { 415 int len = xmlStrlen(EXSLT_SQRT1_2); 416 417 if (precision <= len) 418 len = (int)precision; 419 420 str = xmlStrsub(EXSLT_SQRT1_2, 0, len); 421 422 } else { 423 str = NULL; 424 } 425 if (str == NULL) 426 return xmlXPathNAN; 427 ret = xmlXPathCastStringToNumber(str); 428 xmlFree(str); 429 return ret; 430 } 431 432 /** 433 * exsltMathConstantFunction: 434 * @ctxt: an XPath parser context 435 * @nargs: the number of arguments 436 * 437 * Wraps #exsltMathConstant for use by the XPath processor. 438 */ 439 static void 440 exsltMathConstantFunction (xmlXPathParserContextPtr ctxt, int nargs) { 441 double ret; 442 xmlChar *name; 443 444 if (nargs != 2) { 445 xmlXPathSetArityError(ctxt); 446 return; 447 } 448 ret = xmlXPathPopNumber(ctxt); 449 if (xmlXPathCheckError(ctxt)) 450 return; 451 452 name = xmlXPathPopString(ctxt); 453 if (xmlXPathCheckError(ctxt)) 454 return; 455 456 ret = exsltMathConstant(name, ret); 457 if (name != NULL) 458 xmlFree(name); 459 460 xmlXPathReturnNumber(ctxt, ret); 461 } 462 463 #if defined(HAVE_STDLIB_H) && defined(RAND_MAX) 464 465 /** 466 * exsltMathRandom: 467 * 468 * Implements the EXSLT - Math random() function: 469 * number math:random () 470 * 471 * Returns a random number between 0 and 1 inclusive. 472 */ 473 static double 474 exsltMathRandom (void) { 475 double ret; 476 int num; 477 478 num = rand(); 479 ret = (double)num / (double)RAND_MAX; 480 return(ret); 481 } 482 483 /** 484 * exsltMathRandomFunction: 485 * @ctxt: an XPath parser context 486 * @nargs: the number of arguments 487 * 488 * Wraps #exsltMathRandom for use by the XPath processor. 489 */ 490 static void 491 exsltMathRandomFunction (xmlXPathParserContextPtr ctxt, int nargs) { 492 double ret; 493 494 if (nargs != 0) { 495 xmlXPathSetArityError(ctxt); 496 return; 497 } 498 499 ret = exsltMathRandom(); 500 501 xmlXPathReturnNumber(ctxt, ret); 502 } 503 504 #endif /* defined(HAVE_STDLIB_H) && defined(RAND_MAX) */ 505 506 #if HAVE_MATH_H 507 508 /** 509 * exsltMathAbs: 510 * @num: a double 511 * 512 * Implements the EXSLT - Math abs() function: 513 * number math:abs (number) 514 * 515 * Returns the absolute value of the argument, or xmlXPathNAN if @num is Nan. 516 */ 517 static double 518 exsltMathAbs (double num) { 519 double ret; 520 521 if (xmlXPathIsNaN(num)) 522 return(xmlXPathNAN); 523 ret = fabs(num); 524 return(ret); 525 } 526 527 /** 528 * exsltMathAbsFunction: 529 * @ctxt: an XPath parser context 530 * @nargs: the number of arguments 531 * 532 * Wraps #exsltMathAbs for use by the XPath processor. 533 */ 534 static void 535 exsltMathAbsFunction (xmlXPathParserContextPtr ctxt, int nargs) { 536 double ret; 537 538 if (nargs != 1) { 539 xmlXPathSetArityError(ctxt); 540 return; 541 } 542 ret = xmlXPathPopNumber(ctxt); 543 if (xmlXPathCheckError(ctxt)) 544 return; 545 546 ret = exsltMathAbs(ret); 547 548 xmlXPathReturnNumber(ctxt, ret); 549 } 550 551 /** 552 * exsltMathSqrt: 553 * @num: a double 554 * 555 * Implements the EXSLT - Math sqrt() function: 556 * number math:sqrt (number) 557 * 558 * Returns the square root of the argument, or xmlXPathNAN if @num is Nan. 559 */ 560 static double 561 exsltMathSqrt (double num) { 562 double ret; 563 564 if (xmlXPathIsNaN(num)) 565 return(xmlXPathNAN); 566 ret = sqrt(num); 567 return(ret); 568 } 569 570 /** 571 * exsltMathSqrtFunction: 572 * @ctxt: an XPath parser context 573 * @nargs: the number of arguments 574 * 575 * Wraps #exsltMathSqrt for use by the XPath processor. 576 */ 577 static void 578 exsltMathSqrtFunction (xmlXPathParserContextPtr ctxt, int nargs) { 579 double ret; 580 581 if (nargs != 1) { 582 xmlXPathSetArityError(ctxt); 583 return; 584 } 585 ret = xmlXPathPopNumber(ctxt); 586 if (xmlXPathCheckError(ctxt)) 587 return; 588 589 ret = exsltMathSqrt(ret); 590 591 xmlXPathReturnNumber(ctxt, ret); 592 } 593 594 /** 595 * exsltMathPower: 596 * @base: a double 597 * @power: a double 598 * 599 * Implements the EXSLT - Math power() function: 600 * number math:power (number, number) 601 * 602 * Returns the power base and power arguments, or xmlXPathNAN 603 * if either @base or @power is Nan. 604 */ 605 static double 606 exsltMathPower (double base, double power) { 607 double ret; 608 609 if ((xmlXPathIsNaN(base) || xmlXPathIsNaN(power))) 610 return(xmlXPathNAN); 611 ret = pow(base, power); 612 return(ret); 613 } 614 615 /** 616 * exsltMathPower: 617 * @ctxt: an XPath parser context 618 * @nargs: the number of arguments 619 * 620 * Wraps #exsltMathPower for use by the XPath processor. 621 */ 622 static void 623 exsltMathPowerFunction (xmlXPathParserContextPtr ctxt, int nargs) { 624 double ret, base; 625 626 if (nargs != 2) { 627 xmlXPathSetArityError(ctxt); 628 return; 629 } 630 ret = xmlXPathPopNumber(ctxt); 631 if (xmlXPathCheckError(ctxt)) 632 return; 633 634 /* power */ 635 base = xmlXPathPopNumber(ctxt); 636 if (xmlXPathCheckError(ctxt)) 637 return; 638 639 ret = exsltMathPower(base, ret); 640 641 xmlXPathReturnNumber(ctxt, ret); 642 } 643 644 /** 645 * exsltMathLog: 646 * @num: a double 647 * 648 * Implements the EXSLT - Math log() function: 649 * number math:log (number) 650 * 651 * Returns the natural log of the argument, or xmlXPathNAN if @num is Nan. 652 */ 653 static double 654 exsltMathLog (double num) { 655 double ret; 656 657 if (xmlXPathIsNaN(num)) 658 return(xmlXPathNAN); 659 ret = log(num); 660 return(ret); 661 } 662 663 /** 664 * exsltMathLogFunction: 665 * @ctxt: an XPath parser context 666 * @nargs: the number of arguments 667 * 668 * Wraps #exsltMathLog for use by the XPath processor. 669 */ 670 static void 671 exsltMathLogFunction (xmlXPathParserContextPtr ctxt, int nargs) { 672 double ret; 673 674 if (nargs != 1) { 675 xmlXPathSetArityError(ctxt); 676 return; 677 } 678 ret = xmlXPathPopNumber(ctxt); 679 if (xmlXPathCheckError(ctxt)) 680 return; 681 682 ret = exsltMathLog(ret); 683 684 xmlXPathReturnNumber(ctxt, ret); 685 } 686 687 /** 688 * exsltMathSin: 689 * @num: a double 690 * 691 * Implements the EXSLT - Math sin() function: 692 * number math:sin (number) 693 * 694 * Returns the sine of the argument, or xmlXPathNAN if @num is Nan. 695 */ 696 static double 697 exsltMathSin (double num) { 698 double ret; 699 700 if (xmlXPathIsNaN(num)) 701 return(xmlXPathNAN); 702 ret = sin(num); 703 return(ret); 704 } 705 706 /** 707 * exsltMathSinFunction: 708 * @ctxt: an XPath parser context 709 * @nargs: the number of arguments 710 * 711 * Wraps #exsltMathSin for use by the XPath processor. 712 */ 713 static void 714 exsltMathSinFunction (xmlXPathParserContextPtr ctxt, int nargs) { 715 double ret; 716 717 if (nargs != 1) { 718 xmlXPathSetArityError(ctxt); 719 return; 720 } 721 ret = xmlXPathPopNumber(ctxt); 722 if (xmlXPathCheckError(ctxt)) 723 return; 724 725 ret = exsltMathSin(ret); 726 727 xmlXPathReturnNumber(ctxt, ret); 728 } 729 730 /** 731 * exsltMathCos: 732 * @num: a double 733 * 734 * Implements the EXSLT - Math cos() function: 735 * number math:cos (number) 736 * 737 * Returns the cosine of the argument, or xmlXPathNAN if @num is Nan. 738 */ 739 static double 740 exsltMathCos (double num) { 741 double ret; 742 743 if (xmlXPathIsNaN(num)) 744 return(xmlXPathNAN); 745 ret = cos(num); 746 return(ret); 747 } 748 749 /** 750 * exsltMathCosFunction: 751 * @ctxt: an XPath parser context 752 * @nargs: the number of arguments 753 * 754 * Wraps #exsltMathCos for use by the XPath processor. 755 */ 756 static void 757 exsltMathCosFunction (xmlXPathParserContextPtr ctxt, int nargs) { 758 double ret; 759 760 if (nargs != 1) { 761 xmlXPathSetArityError(ctxt); 762 return; 763 } 764 ret = xmlXPathPopNumber(ctxt); 765 if (xmlXPathCheckError(ctxt)) 766 return; 767 768 ret = exsltMathCos(ret); 769 770 xmlXPathReturnNumber(ctxt, ret); 771 } 772 773 /** 774 * exsltMathTan: 775 * @num: a double 776 * 777 * Implements the EXSLT - Math tan() function: 778 * number math:tan (number) 779 * 780 * Returns the tangent of the argument, or xmlXPathNAN if @num is Nan. 781 */ 782 static double 783 exsltMathTan (double num) { 784 double ret; 785 786 if (xmlXPathIsNaN(num)) 787 return(xmlXPathNAN); 788 ret = tan(num); 789 return(ret); 790 } 791 792 /** 793 * exsltMathTanFunction: 794 * @ctxt: an XPath parser context 795 * @nargs: the number of arguments 796 * 797 * Wraps #exsltMathTan for use by the XPath processor. 798 */ 799 static void 800 exsltMathTanFunction (xmlXPathParserContextPtr ctxt, int nargs) { 801 double ret; 802 803 if (nargs != 1) { 804 xmlXPathSetArityError(ctxt); 805 return; 806 } 807 ret = xmlXPathPopNumber(ctxt); 808 if (xmlXPathCheckError(ctxt)) 809 return; 810 811 ret = exsltMathTan(ret); 812 813 xmlXPathReturnNumber(ctxt, ret); 814 } 815 816 /** 817 * exsltMathAsin: 818 * @num: a double 819 * 820 * Implements the EXSLT - Math asin() function: 821 * number math:asin (number) 822 * 823 * Returns the arc sine of the argument, or xmlXPathNAN if @num is Nan. 824 */ 825 static double 826 exsltMathAsin (double num) { 827 double ret; 828 829 if (xmlXPathIsNaN(num)) 830 return(xmlXPathNAN); 831 ret = asin(num); 832 return(ret); 833 } 834 835 /** 836 * exsltMathAsinFunction: 837 * @ctxt: an XPath parser context 838 * @nargs: the number of arguments 839 * 840 * Wraps #exsltMathAsin for use by the XPath processor. 841 */ 842 static void 843 exsltMathAsinFunction (xmlXPathParserContextPtr ctxt, int nargs) { 844 double ret; 845 846 if (nargs != 1) { 847 xmlXPathSetArityError(ctxt); 848 return; 849 } 850 ret = xmlXPathPopNumber(ctxt); 851 if (xmlXPathCheckError(ctxt)) 852 return; 853 854 ret = exsltMathAsin(ret); 855 856 xmlXPathReturnNumber(ctxt, ret); 857 } 858 859 /** 860 * exsltMathAcos: 861 * @num: a double 862 * 863 * Implements the EXSLT - Math acos() function: 864 * number math:acos (number) 865 * 866 * Returns the arc cosine of the argument, or xmlXPathNAN if @num is Nan. 867 */ 868 static double 869 exsltMathAcos (double num) { 870 double ret; 871 872 if (xmlXPathIsNaN(num)) 873 return(xmlXPathNAN); 874 ret = acos(num); 875 return(ret); 876 } 877 878 /** 879 * exsltMathAcosFunction: 880 * @ctxt: an XPath parser context 881 * @nargs: the number of arguments 882 * 883 * Wraps #exsltMathAcos for use by the XPath processor. 884 */ 885 static void 886 exsltMathAcosFunction (xmlXPathParserContextPtr ctxt, int nargs) { 887 double ret; 888 889 if (nargs != 1) { 890 xmlXPathSetArityError(ctxt); 891 return; 892 } 893 ret = xmlXPathPopNumber(ctxt); 894 if (xmlXPathCheckError(ctxt)) 895 return; 896 897 ret = exsltMathAcos(ret); 898 899 xmlXPathReturnNumber(ctxt, ret); 900 } 901 902 /** 903 * exsltMathAtan: 904 * @num: a double 905 * 906 * Implements the EXSLT - Math atan() function: 907 * number math:atan (number) 908 * 909 * Returns the arc tangent of the argument, or xmlXPathNAN if @num is Nan. 910 */ 911 static double 912 exsltMathAtan (double num) { 913 double ret; 914 915 if (xmlXPathIsNaN(num)) 916 return(xmlXPathNAN); 917 ret = atan(num); 918 return(ret); 919 } 920 921 /** 922 * exsltMathAtanFunction: 923 * @ctxt: an XPath parser context 924 * @nargs: the number of arguments 925 * 926 * Wraps #exsltMathAtan for use by the XPath processor. 927 */ 928 static void 929 exsltMathAtanFunction (xmlXPathParserContextPtr ctxt, int nargs) { 930 double ret; 931 932 if (nargs != 1) { 933 xmlXPathSetArityError(ctxt); 934 return; 935 } 936 ret = xmlXPathPopNumber(ctxt); 937 if (xmlXPathCheckError(ctxt)) 938 return; 939 940 ret = exsltMathAtan(ret); 941 942 xmlXPathReturnNumber(ctxt, ret); 943 } 944 945 /** 946 * exsltMathAtan2: 947 * @y: a double 948 * @x: a double 949 * 950 * Implements the EXSLT - Math atan2() function: 951 * number math:atan2 (number, number) 952 * 953 * Returns the arc tangent function of the y/x arguments, or xmlXPathNAN 954 * if either @y or @x is Nan. 955 */ 956 static double 957 exsltMathAtan2 (double y, double x) { 958 double ret; 959 960 if ((xmlXPathIsNaN(y) || xmlXPathIsNaN(x))) 961 return(xmlXPathNAN); 962 ret = atan2(y, x); 963 return(ret); 964 } 965 966 /** 967 * exsltMathAtan2Function: 968 * @ctxt: an XPath parser context 969 * @nargs: the number of arguments 970 * 971 * Wraps #exsltMathAtan2 for use by the XPath processor. 972 */ 973 static void 974 exsltMathAtan2Function (xmlXPathParserContextPtr ctxt, int nargs) { 975 double ret, x; 976 977 if (nargs != 2) { 978 xmlXPathSetArityError(ctxt); 979 return; 980 } 981 x = xmlXPathPopNumber(ctxt); 982 if (xmlXPathCheckError(ctxt)) 983 return; 984 985 /* y */ 986 ret = xmlXPathPopNumber(ctxt); 987 if (xmlXPathCheckError(ctxt)) 988 return; 989 990 ret = exsltMathAtan2(ret, x); 991 992 xmlXPathReturnNumber(ctxt, ret); 993 } 994 995 /** 996 * exsltMathExp: 997 * @num: a double 998 * 999 * Implements the EXSLT - Math exp() function: 1000 * number math:exp (number) 1001 * 1002 * Returns the exponential function of the argument, or xmlXPathNAN if 1003 * @num is Nan. 1004 */ 1005 static double 1006 exsltMathExp (double num) { 1007 double ret; 1008 1009 if (xmlXPathIsNaN(num)) 1010 return(xmlXPathNAN); 1011 ret = exp(num); 1012 return(ret); 1013 } 1014 1015 /** 1016 * exsltMathExpFunction: 1017 * @ctxt: an XPath parser context 1018 * @nargs: the number of arguments 1019 * 1020 * Wraps #exsltMathExp for use by the XPath processor. 1021 */ 1022 static void 1023 exsltMathExpFunction (xmlXPathParserContextPtr ctxt, int nargs) { 1024 double ret; 1025 1026 if (nargs != 1) { 1027 xmlXPathSetArityError(ctxt); 1028 return; 1029 } 1030 ret = xmlXPathPopNumber(ctxt); 1031 if (xmlXPathCheckError(ctxt)) 1032 return; 1033 1034 ret = exsltMathExp(ret); 1035 1036 xmlXPathReturnNumber(ctxt, ret); 1037 } 1038 1039 #endif /* HAVE_MATH_H */ 1040 1041 /** 1042 * exsltMathRegister: 1043 * 1044 * Registers the EXSLT - Math module 1045 */ 1046 1047 void 1048 exsltMathRegister (void) { 1049 xsltRegisterExtModuleFunction ((const xmlChar *) "min", 1050 EXSLT_MATH_NAMESPACE, 1051 exsltMathMinFunction); 1052 xsltRegisterExtModuleFunction ((const xmlChar *) "max", 1053 EXSLT_MATH_NAMESPACE, 1054 exsltMathMaxFunction); 1055 xsltRegisterExtModuleFunction ((const xmlChar *) "highest", 1056 EXSLT_MATH_NAMESPACE, 1057 exsltMathHighestFunction); 1058 xsltRegisterExtModuleFunction ((const xmlChar *) "lowest", 1059 EXSLT_MATH_NAMESPACE, 1060 exsltMathLowestFunction); 1061 /* register other math functions */ 1062 xsltRegisterExtModuleFunction ((const xmlChar *) "constant", 1063 EXSLT_MATH_NAMESPACE, 1064 exsltMathConstantFunction); 1065 #ifdef HAVE_STDLIB_H 1066 xsltRegisterExtModuleFunction ((const xmlChar *) "random", 1067 EXSLT_MATH_NAMESPACE, 1068 exsltMathRandomFunction); 1069 #endif 1070 #if HAVE_MATH_H 1071 xsltRegisterExtModuleFunction ((const xmlChar *) "abs", 1072 EXSLT_MATH_NAMESPACE, 1073 exsltMathAbsFunction); 1074 xsltRegisterExtModuleFunction ((const xmlChar *) "sqrt", 1075 EXSLT_MATH_NAMESPACE, 1076 exsltMathSqrtFunction); 1077 xsltRegisterExtModuleFunction ((const xmlChar *) "power", 1078 EXSLT_MATH_NAMESPACE, 1079 exsltMathPowerFunction); 1080 xsltRegisterExtModuleFunction ((const xmlChar *) "log", 1081 EXSLT_MATH_NAMESPACE, 1082 exsltMathLogFunction); 1083 xsltRegisterExtModuleFunction ((const xmlChar *) "sin", 1084 EXSLT_MATH_NAMESPACE, 1085 exsltMathSinFunction); 1086 xsltRegisterExtModuleFunction ((const xmlChar *) "cos", 1087 EXSLT_MATH_NAMESPACE, 1088 exsltMathCosFunction); 1089 xsltRegisterExtModuleFunction ((const xmlChar *) "tan", 1090 EXSLT_MATH_NAMESPACE, 1091 exsltMathTanFunction); 1092 xsltRegisterExtModuleFunction ((const xmlChar *) "asin", 1093 EXSLT_MATH_NAMESPACE, 1094 exsltMathAsinFunction); 1095 xsltRegisterExtModuleFunction ((const xmlChar *) "acos", 1096 EXSLT_MATH_NAMESPACE, 1097 exsltMathAcosFunction); 1098 xsltRegisterExtModuleFunction ((const xmlChar *) "atan", 1099 EXSLT_MATH_NAMESPACE, 1100 exsltMathAtanFunction); 1101 xsltRegisterExtModuleFunction ((const xmlChar *) "atan2", 1102 EXSLT_MATH_NAMESPACE, 1103 exsltMathAtan2Function); 1104 xsltRegisterExtModuleFunction ((const xmlChar *) "exp", 1105 EXSLT_MATH_NAMESPACE, 1106 exsltMathExpFunction); 1107 #endif 1108 } 1109 1110 /** 1111 * exsltMathXpathCtxtRegister: 1112 * 1113 * Registers the EXSLT - Math module for use outside XSLT 1114 */ 1115 int 1116 exsltMathXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix) 1117 { 1118 if (ctxt 1119 && prefix 1120 && !xmlXPathRegisterNs(ctxt, 1121 prefix, 1122 (const xmlChar *) EXSLT_MATH_NAMESPACE) 1123 && !xmlXPathRegisterFuncNS(ctxt, 1124 (const xmlChar *) "min", 1125 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1126 exsltMathMinFunction) 1127 && !xmlXPathRegisterFuncNS(ctxt, 1128 (const xmlChar *) "max", 1129 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1130 exsltMathMaxFunction) 1131 && !xmlXPathRegisterFuncNS(ctxt, 1132 (const xmlChar *) "highest", 1133 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1134 exsltMathHighestFunction) 1135 && !xmlXPathRegisterFuncNS(ctxt, 1136 (const xmlChar *) "lowest", 1137 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1138 exsltMathLowestFunction) 1139 #ifdef HAVE_STDLIB_H 1140 && !xmlXPathRegisterFuncNS(ctxt, 1141 (const xmlChar *) "random", 1142 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1143 exsltMathRandomFunction) 1144 #endif 1145 #if HAVE_MATH_H 1146 && !xmlXPathRegisterFuncNS(ctxt, 1147 (const xmlChar *) "abs", 1148 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1149 exsltMathAbsFunction) 1150 && !xmlXPathRegisterFuncNS(ctxt, 1151 (const xmlChar *) "sqrt", 1152 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1153 exsltMathSqrtFunction) 1154 && !xmlXPathRegisterFuncNS(ctxt, 1155 (const xmlChar *) "power", 1156 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1157 exsltMathPowerFunction) 1158 && !xmlXPathRegisterFuncNS(ctxt, 1159 (const xmlChar *) "log", 1160 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1161 exsltMathLogFunction) 1162 && !xmlXPathRegisterFuncNS(ctxt, 1163 (const xmlChar *) "sin", 1164 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1165 exsltMathSinFunction) 1166 && !xmlXPathRegisterFuncNS(ctxt, 1167 (const xmlChar *) "cos", 1168 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1169 exsltMathCosFunction) 1170 && !xmlXPathRegisterFuncNS(ctxt, 1171 (const xmlChar *) "tan", 1172 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1173 exsltMathTanFunction) 1174 && !xmlXPathRegisterFuncNS(ctxt, 1175 (const xmlChar *) "asin", 1176 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1177 exsltMathAsinFunction) 1178 && !xmlXPathRegisterFuncNS(ctxt, 1179 (const xmlChar *) "acos", 1180 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1181 exsltMathAcosFunction) 1182 && !xmlXPathRegisterFuncNS(ctxt, 1183 (const xmlChar *) "atan", 1184 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1185 exsltMathAtanFunction) 1186 && !xmlXPathRegisterFuncNS(ctxt, 1187 (const xmlChar *) "atan2", 1188 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1189 exsltMathAtan2Function) 1190 && !xmlXPathRegisterFuncNS(ctxt, 1191 (const xmlChar *) "exp", 1192 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1193 exsltMathExpFunction) 1194 #endif 1195 && !xmlXPathRegisterFuncNS(ctxt, 1196 (const xmlChar *) "constant", 1197 (const xmlChar *) EXSLT_MATH_NAMESPACE, 1198 exsltMathConstantFunction)) { 1199 return 0; 1200 } 1201 return -1; 1202 } 1203