Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
func_math.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2004 - 2006, Andy Powell
5 *
6 * Updated by Mark Spencer <markster@digium.com>
7 * Updated by Nir Simionovich <nirs@greenfieldtech.net>
8 * Updated by Naveen Albert <asterisk@phreaknet.org>
9 *
10 * See http://www.asterisk.org for more information about
11 * the Asterisk project. Please do not directly contact
12 * any of the maintainers of this project for assistance;
13 * the project provides a web site, mailing lists and IRC
14 * channels for your use.
15 *
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License Version 2. See the LICENSE file
18 * at the top of the source tree.
19 */
20
21/*! \file
22 *
23 * \brief Math related dialplan function
24 *
25 * \author Andy Powell
26 * \author Mark Spencer <markster@digium.com>
27 * \author Nir Simionovich <nirs@greenfieldtech.net>
28 * \author Naveen Albert <asterisk@phreaknet.org>
29 *
30 * \ingroup functions
31 */
32
33/*** MODULEINFO
34 <support_level>core</support_level>
35 ***/
36
37#include "asterisk.h"
38
39#include <math.h>
40
41#include "asterisk/module.h"
42#include "asterisk/channel.h"
43#include "asterisk/pbx.h"
44#include "asterisk/utils.h"
46#include "asterisk/app.h"
47#include "asterisk/config.h"
48#include "asterisk/test.h"
49
50/*** DOCUMENTATION
51 <function name="MATH" language="en_US">
52 <since>
53 <version>1.2.0</version>
54 </since>
55 <synopsis>
56 Performs Mathematical Functions.
57 </synopsis>
58 <syntax>
59 <parameter name="expression" required="true">
60 <para>Is of the form:
61 <replaceable>number1</replaceable><replaceable>op</replaceable><replaceable>number2</replaceable>
62 where the possible values for <replaceable>op</replaceable>
63 are:</para>
64 <para>+,-,/,*,%,&lt;&lt;,&gt;&gt;,^,AND,OR,XOR,&lt;,&gt;,&lt;=,&gt;=,== (and behave as their C equivalents)</para>
65 </parameter>
66 <parameter name="type">
67 <para>Wanted type of result:</para>
68 <para>f, float - float(default)</para>
69 <para>i, int - integer</para>
70 <para>h, hex - hex</para>
71 <para>c, char - char</para>
72 </parameter>
73 </syntax>
74 <description>
75 <para>Performs mathematical functions based on two parameters and an operator. The returned
76 value type is <replaceable>type</replaceable></para>
77 <example title="Sets var i to 11">
78 same => n,Set(i=${MATH(123%16,int)})
79 </example>
80 </description>
81 </function>
82 <function name="INC" language="en_US">
83 <since>
84 <version>1.8.0</version>
85 </since>
86 <synopsis>
87 Increments the value of a variable, while returning the updated value to the dialplan
88 </synopsis>
89 <syntax>
90 <parameter name="variable" required="true">
91 <para>
92 The variable name to be manipulated, without the braces.
93 </para>
94 </parameter>
95 </syntax>
96 <description>
97 <para>Increments the value of a variable, while returning the updated value to the dialplan</para>
98 <para>Example: INC(MyVAR) - Increments MyVar</para>
99 <para>Note: INC(${MyVAR}) - Is wrong, as INC expects the variable name, not its value</para>
100 </description>
101 </function>
102 <function name="DEC" language="en_US">
103 <since>
104 <version>1.8.0</version>
105 </since>
106 <synopsis>
107 Decrements the value of a variable, while returning the updated value to the dialplan
108 </synopsis>
109 <syntax>
110 <parameter name="variable" required="true">
111 <para>
112 The variable name to be manipulated, without the braces.
113 </para>
114 </parameter>
115 </syntax>
116 <description>
117 <para>Decrements the value of a variable, while returning the updated value to the dialplan</para>
118 <example title="Decrements MyVAR">
119 same => n,NoOp(${DEC(MyVAR)})
120 </example>
121 <note><para>DEC(${MyVAR}) is wrong, as DEC expects the variable name, not its value</para></note>
122 </description>
123 </function>
124 <function name="MIN" language="en_US">
125 <since>
126 <version>16.19.0</version>
127 <version>18.5.0</version>
128 </since>
129 <synopsis>
130 Returns the minimum of two numbers.
131 </synopsis>
132 <syntax>
133 <parameter name="num1" />
134 <parameter name="num2" />
135 </syntax>
136 <description>
137 <para>Returns the minimum of two numbers <replaceable>num1</replaceable> and <replaceable>num2</replaceable>.</para>
138 <example title="Sets the min variable equal to 4">
139 same => n,Set(min=${MIN(7,4)})
140 </example>
141 </description>
142 </function>
143 <function name="MAX" language="en_US">
144 <since>
145 <version>16.19.0</version>
146 <version>18.5.0</version>
147 </since>
148 <synopsis>
149 Returns the maximum of two numbers.
150 </synopsis>
151 <syntax>
152 <parameter name="num1" />
153 <parameter name="num2" />
154 </syntax>
155 <description>
156 <para>Returns the maximum of two numbers <replaceable>num1</replaceable> and <replaceable>num2</replaceable>.</para>
157 <example title="Sets the max variable equal to 13">
158 same => n,Set(max=${MAX(4,7)})
159 </example>
160 </description>
161 </function>
162 <function name="ABS" language="en_US">
163 <since>
164 <version>16.19.0</version>
165 <version>18.5.0</version>
166 </since>
167 <synopsis>
168 Returns absolute value of a number.
169 </synopsis>
170 <syntax>
171 <parameter name="num" />
172 </syntax>
173 <description>
174 <para>Returns the absolute value of a number <replaceable>num</replaceable>.</para>
175 <example title="Sets the absval variable equal to 13">
176 same => n,Set(absval=${ABS(-13)})
177 </example>
178 </description>
179 </function>
180 <function name="DIGIT_SUM" language="en_US">
181 <since>
182 <version>23.1.0</version>
183 <version>22.7.0</version>
184 <version>20.17.0</version>
185 </since>
186 <synopsis>
187 Returns the sum of all the digits in a number.
188 </synopsis>
189 <syntax>
190 <parameter name="num" />
191 </syntax>
192 <description>
193 <para>Returns the numeric sum of all the individual digits in a number, summed up.</para>
194 <para>This can be useful for computing checksums based on the number,
195 where errors are typically digits being off by one.</para>
196 <example title="Get the sum of digits in 859">
197 same => n,Set(digitsum=${DIGIT_SUM(859)}) ; assigns digitsum=22
198 same => n,Set(checksum=$[${digitsum} % 10]) ; assigns checksum=2
199 </example>
200 </description>
201 </function>
202 ***/
203
222
229
230static int math(struct ast_channel *chan, const char *cmd, char *parse,
231 char *buf, size_t len)
232{
233 double fnum1;
234 double fnum2;
235 double ftmp = 0;
236 char *op;
237 int iaction = -1;
238 int type_of_result = FLOAT_RESULT;
239 char *mvalue1, *mvalue2 = NULL, *mtype_of_result;
240 int negvalue1 = 0;
242 AST_APP_ARG(argv0);
243 AST_APP_ARG(argv1);
244 );
245
246 if (ast_strlen_zero(parse)) {
247 ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
248 return -1;
249 }
250
252
253 if (args.argc < 1) {
254 ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
255 return -1;
256 }
257
258 mvalue1 = args.argv0;
259
260 if (mvalue1[0] == '-') {
261 negvalue1 = 1;
262 mvalue1++;
263 }
264
265 if ((op = strchr(mvalue1, '*'))) {
266 iaction = MULTIPLYFUNCTION;
267 *op = '\0';
268 } else if ((op = strchr(mvalue1, '/'))) {
269 iaction = DIVIDEFUNCTION;
270 *op = '\0';
271 } else if ((op = strchr(mvalue1, '%'))) {
272 iaction = MODULUSFUNCTION;
273 *op = '\0';
274 } else if ((op = strchr(mvalue1, '^'))) {
275 iaction = POWFUNCTION;
276 *op = '\0';
277 } else if ((op = strstr(mvalue1, "AND"))) {
278 iaction = BITWISEANDFUNCTION;
279 *op = '\0';
280 op += 2;
281 } else if ((op = strstr(mvalue1, "XOR"))) {
282 iaction = BITWISEXORFUNCTION;
283 *op = '\0';
284 op += 2;
285 } else if ((op = strstr(mvalue1, "OR"))) {
286 iaction = BITWISEORFUNCTION;
287 *op = '\0';
288 ++op;
289 } else if ((op = strchr(mvalue1, '>'))) {
290 iaction = GTFUNCTION;
291 *op = '\0';
292 if (*(op + 1) == '=') {
293 iaction = GTEFUNCTION;
294 ++op;
295 } else if (*(op + 1) == '>') {
296 iaction = SHRIGHTFUNCTION;
297 ++op;
298 }
299 } else if ((op = strchr(mvalue1, '<'))) {
300 iaction = LTFUNCTION;
301 *op = '\0';
302 if (*(op + 1) == '=') {
303 iaction = LTEFUNCTION;
304 ++op;
305 } else if (*(op + 1) == '<') {
306 iaction = SHLEFTFUNCTION;
307 ++op;
308 }
309 } else if ((op = strchr(mvalue1, '='))) {
310 *op = '\0';
311 if (*(op + 1) == '=') {
312 iaction = EQFUNCTION;
313 ++op;
314 } else
315 op = NULL;
316 } else if ((op = strchr(mvalue1, '+'))) {
317 iaction = ADDFUNCTION;
318 *op = '\0';
319 } else if ((op = strchr(mvalue1, '-'))) { /* subtraction MUST always be last, in case we have a negative second number */
320 iaction = SUBTRACTFUNCTION;
321 *op = '\0';
322 }
323
324 if (op)
325 mvalue2 = op + 1;
326
327 /* detect wanted type of result */
328 mtype_of_result = args.argv1;
329 if (mtype_of_result) {
330 if (!strcasecmp(mtype_of_result, "float")
331 || !strcasecmp(mtype_of_result, "f"))
332 type_of_result = FLOAT_RESULT;
333 else if (!strcasecmp(mtype_of_result, "int")
334 || !strcasecmp(mtype_of_result, "i"))
335 type_of_result = INT_RESULT;
336 else if (!strcasecmp(mtype_of_result, "hex")
337 || !strcasecmp(mtype_of_result, "h"))
338 type_of_result = HEX_RESULT;
339 else if (!strcasecmp(mtype_of_result, "char")
340 || !strcasecmp(mtype_of_result, "c"))
341 type_of_result = CHAR_RESULT;
342 else {
343 ast_log(LOG_WARNING, "Unknown type of result requested '%s'.\n",
344 mtype_of_result);
345 return -1;
346 }
347 }
348
349 if (!mvalue2) {
351 "Supply all the parameters - just this once, please\n");
352 return -1;
353 }
354
355 if (sscanf(mvalue1, "%30lf", &fnum1) != 1) {
356 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
357 return -1;
358 }
359
360 if (sscanf(mvalue2, "%30lf", &fnum2) != 1) {
361 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
362 return -1;
363 }
364
365 if (negvalue1)
366 fnum1 = 0 - fnum1;
367
368 switch (iaction) {
369 case ADDFUNCTION:
370 ftmp = fnum1 + fnum2;
371 break;
372 case DIVIDEFUNCTION:
373 if (fnum2 <= 0)
374 ftmp = 0; /* can't do a divide by 0 */
375 else
376 ftmp = (fnum1 / fnum2);
377 break;
378 case MULTIPLYFUNCTION:
379 ftmp = (fnum1 * fnum2);
380 break;
381 case SUBTRACTFUNCTION:
382 ftmp = (fnum1 - fnum2);
383 break;
384 case MODULUSFUNCTION:
385 {
386 int inum1 = fnum1;
387 int inum2 = fnum2;
388
389 if (inum2 == 0) {
390 ftmp = 0;
391 } else {
392 ftmp = (inum1 % inum2);
393 }
394
395 break;
396 }
397 case POWFUNCTION:
398 ftmp = pow(fnum1, fnum2);
399 break;
400 case SHLEFTFUNCTION:
401 {
402 int inum1 = fnum1;
403 int inum2 = fnum2;
404
405 ftmp = (inum1 << inum2);
406 break;
407 }
408 case SHRIGHTFUNCTION:
409 {
410 int inum1 = fnum1;
411 int inum2 = fnum2;
412
413 ftmp = (inum1 >> inum2);
414 break;
415 }
417 {
418 int inum1 = fnum1;
419 int inum2 = fnum2;
420 ftmp = (inum1 & inum2);
421 break;
422 }
424 {
425 int inum1 = fnum1;
426 int inum2 = fnum2;
427 ftmp = (inum1 ^ inum2);
428 break;
429 }
431 {
432 int inum1 = fnum1;
433 int inum2 = fnum2;
434 ftmp = (inum1 | inum2);
435 break;
436 }
437 case GTFUNCTION:
438 ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
439 break;
440 case LTFUNCTION:
441 ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
442 break;
443 case GTEFUNCTION:
444 ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
445 break;
446 case LTEFUNCTION:
447 ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
448 break;
449 case EQFUNCTION:
450 ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
451 break;
452 default:
454 "Something happened that neither of us should be proud of %d\n",
455 iaction);
456 return -1;
457 }
458
459 if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
460 if (type_of_result == FLOAT_RESULT)
461 snprintf(buf, len, "%f", ftmp);
462 else if (type_of_result == INT_RESULT)
463 snprintf(buf, len, "%i", (int) ftmp);
464 else if (type_of_result == HEX_RESULT)
465 snprintf(buf, len, "%x", (unsigned int) ftmp);
466 else if (type_of_result == CHAR_RESULT)
467 snprintf(buf, len, "%c", (unsigned char) ftmp);
468 }
469
470 return 0;
471}
472
473static int crement_function_read(struct ast_channel *chan, const char *cmd,
474 char *data, char *buf, size_t len)
475{
476 int ret = -1;
477 int int_value = 0;
478 int modify_orig = 0;
479 const char *var;
480 char endchar = 0, returnvar[12]; /* If you need a variable longer than 11 digits - something is way wrong */
481
482 if (ast_strlen_zero(data)) {
483 ast_log(LOG_WARNING, "Syntax: %s(<data>) - missing argument!\n", cmd);
484 return -1;
485 }
486
487 if (!chan) {
488 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
489 return -1;
490 }
491
492 ast_channel_lock(chan);
493
494 if (!(var = pbx_builtin_getvar_helper(chan, data))) {
495 ast_log(LOG_NOTICE, "Failed to obtain variable %s, bailing out\n", data);
496 ast_channel_unlock(chan);
497 return -1;
498 }
499
500 if (ast_strlen_zero(var)) {
501 ast_log(LOG_NOTICE, "Variable %s doesn't exist - are you sure you wrote it correctly?\n", data);
502 ast_channel_unlock(chan);
503 return -1;
504 }
505
506 if (sscanf(var, "%30d%1c", &int_value, &endchar) == 0 || endchar != 0) {
507 ast_log(LOG_NOTICE, "The content of ${%s} is not a numeric value - bailing out!\n", data);
508 ast_channel_unlock(chan);
509 return -1;
510 }
511
512 /* now we'll actually do something useful */
513 if (!strcasecmp(cmd, "INC")) { /* Increment variable */
514 int_value++;
515 modify_orig = 1;
516 } else if (!strcasecmp(cmd, "DEC")) { /* Decrement variable */
517 int_value--;
518 modify_orig = 1;
519 }
520
521 if (snprintf(returnvar, sizeof(returnvar), "%d", int_value) > 0) {
522 pbx_builtin_setvar_helper(chan, data, returnvar);
523 if (modify_orig) {
524 ast_copy_string(buf, returnvar, len);
525 }
526 ret = 0;
527 } else {
528 pbx_builtin_setvar_helper(chan, data, "0");
529 if (modify_orig) {
530 ast_copy_string(buf, "0", len);
531 }
532 ast_log(LOG_NOTICE, "Variable %s refused to be %sREMENTED, setting value to 0", data, cmd);
533 ret = 0;
534 }
535
536 ast_channel_unlock(chan);
537
538 return ret;
539}
540
541static int acf_min_exec(struct ast_channel *chan, const char *cmd,
542 char *parse, char *buffer, size_t buflen)
543{
544 double num1, num2, response_num = 0;
546 AST_APP_ARG(num1);
547 AST_APP_ARG(num2);
548 );
549
551
552 if (ast_strlen_zero(args.num1) && ast_strlen_zero(args.num2)) {
553 ast_log(LOG_ERROR, "Missing argument for number(s).");
554 return -1;
555 }
556
557 if (ast_strlen_zero(args.num1)) {
558 response_num = -1; /* couldn't read num1 successfully */
559 } else if (sscanf(args.num1, "%30lf", &num1) != 1) {
560 ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num1);
561 return -1;
562 }
563
564 if (ast_strlen_zero(args.num2)) {
565 num2 = num1; /* num1 must be a valid integer here */
566 } else if (sscanf(args.num2, "%30lf", &num2) != 1) {
567 ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num2);
568 return -1;
569 }
570
571 if (response_num == -1) { /* could only read num2 */
572 response_num = num2;
573 } else {
574 response_num = (num1 > num2) ? num2 : num1;
575 }
576
577 ast_debug(1, "%f is the minimum of [%f,%f]\n", response_num, num1, num2);
578 if ((int) response_num == response_num) {
579 snprintf(buffer, buflen, "%d", (int) response_num);
580 } else {
581 snprintf(buffer, buflen, "%f", response_num);
582 }
583
584 return 0;
585}
586
587static int acf_max_exec(struct ast_channel *chan, const char *cmd,
588 char *parse, char *buffer, size_t buflen)
589{
590 double num1, num2, response_num = 0;
592 AST_APP_ARG(num1);
593 AST_APP_ARG(num2);
594 );
595
597
598 if (ast_strlen_zero(args.num1) && ast_strlen_zero(args.num2)) {
599 ast_log(LOG_ERROR, "Missing argument for number(s).");
600 return -1;
601 }
602
603 if (ast_strlen_zero(args.num1)) {
604 response_num = -1; /* couldn't read num1 successfully */
605 } else if (sscanf(args.num1, "%30lf", &num1) != 1) {
606 ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num1);
607 return -1;
608 }
609
610 if (ast_strlen_zero(args.num2)) {
611 num2 = num1; /* num1 must be a valid integer here */
612 } else if (sscanf(args.num2, "%30lf", &num2) != 1) {
613 ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num2);
614 return -1;
615 }
616
617 if (response_num == -1) { /* could only read num2 */
618 response_num = num2;
619 } else {
620 response_num = (num1 < num2) ? num2 : num1;
621 }
622
623 ast_debug(1, "%f is the maximum of [%f,%f]\n", response_num, num1, num2);
624 if ((int) response_num == response_num) {
625 snprintf(buffer, buflen, "%d", (int) response_num);
626 } else {
627 snprintf(buffer, buflen, "%f", response_num);
628 }
629
630 return 0;
631}
632
633static int acf_abs_exec(struct ast_channel *chan, const char *cmd,
634 char *parse, char *buffer, size_t buflen)
635{
636 double num1, response_num;
638 AST_APP_ARG(num1);
639 );
640
642
643 if (ast_strlen_zero(args.num1) || sscanf(args.num1, "%30lf", &num1) != 1) {
644 ast_log(LOG_WARNING, "Bad or missing argument for number: %s", args.num1);
645 return -1;
646 }
647
648 response_num = fabs(num1);
649 ast_debug(1, "%f is the absolute value of %f\n", response_num, num1);
650 if ((int) response_num == response_num) {
651 snprintf(buffer, buflen, "%d", (int) response_num);
652 } else {
653 snprintf(buffer, buflen, "%f", response_num);
654 }
655
656 return 0;
657}
658
659static int acf_digit_sum_exec(struct ast_channel *chan, const char *cmd,
660 char *parse, char *buffer, size_t buflen)
661{
662 int sum = 0;
663
664 if (ast_strlen_zero(parse)) {
665 ast_log(LOG_WARNING, "Missing argument for number\n");
666 return -1;
667 }
668
669 for (; *parse; parse++) {
670 if (*parse < '0' || *parse > '9') {
671 continue;
672 }
673 sum += (*parse - '0');
674 }
675
676 snprintf(buffer, buflen, "%d", sum);
677 return 0;
678}
679
681 .name = "MATH",
682 .read = math
683};
684
686 .name = "INC",
687 .read = crement_function_read,
688};
689
691 .name = "DEC",
692 .read = crement_function_read,
693};
694
696 .name = "MIN",
697 .read = acf_min_exec,
698 .read_max = 12,
699};
700
702 .name = "MAX",
703 .read = acf_max_exec,
704 .read_max = 12,
705};
706
708 .name = "ABS",
709 .read = acf_abs_exec,
710 .read_max = 12,
711};
712
714 .name = "DIGIT_SUM",
715 .read = acf_digit_sum_exec,
716};
717
718#ifdef TEST_FRAMEWORK
719AST_TEST_DEFINE(test_MATH_function)
720{
722 struct ast_str *expr, *result;
723
724 switch (cmd) {
725 case TEST_INIT:
726 info->name = "test_MATH_function";
727 info->category = "/main/pbx/";
728 info->summary = "Test MATH function substitution";
729 info->description =
730 "Executes a series of variable substitutions using the MATH function and ensures that the expected results are received.";
731 return AST_TEST_NOT_RUN;
732 case TEST_EXECUTE:
733 break;
734 }
735
736 ast_test_status_update(test, "Testing MATH() substitution ...\n");
737
738 if (!(expr = ast_str_create(16))) {
739 return AST_TEST_FAIL;
740 }
741 if (!(result = ast_str_create(16))) {
742 ast_free(expr);
743 return AST_TEST_FAIL;
744 }
745
746 ast_str_set(&expr, 0, "${MATH(170 AND 63,i)}");
748 if (strcmp(ast_str_buffer(result), "42") != 0) {
749 ast_test_status_update(test, "Expected result '42' not returned! ('%s')\n",
751 res = AST_TEST_FAIL;
752 }
753
754 ast_str_set(&expr, 0, "${MATH(170AND63,i)}");
756 if (strcmp(ast_str_buffer(result), "42") != 0) {
757 ast_test_status_update(test, "Expected result '42' not returned! ('%s')\n",
759 res = AST_TEST_FAIL;
760 }
761
762 ast_free(expr);
764
765 return res;
766}
767#endif
768
784
800
801AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");
#define var
Definition ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition astmm.h:180
#define ast_log
Definition astobj2.c:42
static PGresult * result
Definition cel_pgsql.c:84
General Asterisk PBX channel definitions.
#define ast_channel_lock(chan)
Definition channel.h:2982
#define ast_channel_unlock(chan)
Definition channel.h:2983
Conversion utility functions.
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static int acf_abs_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
Definition func_math.c:633
TypeOfResult
Definition func_math.c:223
@ CHAR_RESULT
Definition func_math.c:227
@ INT_RESULT
Definition func_math.c:225
@ FLOAT_RESULT
Definition func_math.c:224
@ HEX_RESULT
Definition func_math.c:226
TypeOfFunctions
Definition func_math.c:204
@ EQFUNCTION
Definition func_math.c:220
@ BITWISEORFUNCTION
Definition func_math.c:215
@ BITWISEANDFUNCTION
Definition func_math.c:213
@ LTEFUNCTION
Definition func_math.c:219
@ SHRIGHTFUNCTION
Definition func_math.c:212
@ POWFUNCTION
Definition func_math.c:210
@ MODULUSFUNCTION
Definition func_math.c:209
@ ADDFUNCTION
Definition func_math.c:205
@ SHLEFTFUNCTION
Definition func_math.c:211
@ GTEFUNCTION
Definition func_math.c:218
@ BITWISEXORFUNCTION
Definition func_math.c:214
@ DIVIDEFUNCTION
Definition func_math.c:206
@ MULTIPLYFUNCTION
Definition func_math.c:207
@ GTFUNCTION
Definition func_math.c:216
@ LTFUNCTION
Definition func_math.c:217
@ SUBTRACTFUNCTION
Definition func_math.c:208
static struct ast_custom_function increment_function
Definition func_math.c:685
static int math(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition func_math.c:230
static int acf_digit_sum_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
Definition func_math.c:659
static struct ast_custom_function math_function
Definition func_math.c:680
static int acf_max_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
Definition func_math.c:587
static struct ast_custom_function decrement_function
Definition func_math.c:690
static struct ast_custom_function acf_min
Definition func_math.c:695
static int acf_min_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
Definition func_math.c:541
static struct ast_custom_function acf_abs
Definition func_math.c:707
static int load_module(void)
Definition func_math.c:785
static struct ast_custom_function acf_max
Definition func_math.c:701
static int unload_module(void)
Definition func_math.c:769
static struct ast_custom_function acf_digit_sum
Definition func_math.c:713
static int crement_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition func_math.c:473
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
Configuration File Parser.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition module.h:46
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1562
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static struct @519 args
#define NULL
Definition resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Definition pbx.h:118
const char * name
Definition pbx.h:119
Support for dynamic strings.
Definition strings.h:623
Test Framework API.
@ TEST_INIT
Definition test.h:200
@ TEST_EXECUTE
Definition test.h:201
#define AST_TEST_REGISTER(cb)
Definition test.h:127
#define ast_test_status_update(a, b, c...)
Definition test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition test.h:128
#define AST_TEST_DEFINE(hdr)
Definition test.h:126
ast_test_result_state
Definition test.h:193
@ AST_TEST_PASS
Definition test.h:195
@ AST_TEST_FAIL
Definition test.h:196
@ AST_TEST_NOT_RUN
Definition test.h:194
Utility functions.