OLD | NEW |
| (Empty) |
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 } | |
OLD | NEW |