2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2004 - 2006, Andy Powell
6 * Updated by Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Math related dialplan function
24 * \author Mark Spencer <markster@digium.com>
29 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
34 #include <sys/types.h>
36 #include "asterisk/module.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/pbx.h"
39 #include "asterisk/logger.h"
40 #include "asterisk/utils.h"
41 #include "asterisk/app.h"
42 #include "asterisk/config.h"
44 enum TypeOfFunctions
{
64 static int math(struct ast_channel
*chan
, char *cmd
, char *parse
,
65 char *buf
, size_t len
)
72 int type_of_result
= FLOAT_RESULT
;
73 char *mvalue1
, *mvalue2
= NULL
, *mtype_of_result
;
75 AST_DECLARE_APP_ARGS(args
,
80 if (ast_strlen_zero(parse
)) {
81 ast_log(LOG_WARNING
, "Syntax: Math(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
85 AST_STANDARD_APP_ARGS(args
, parse
);
88 ast_log(LOG_WARNING
, "Syntax: Math(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
94 if (mvalue1
[0] == '-') {
99 if ((op
= strchr(mvalue1
, '*'))) {
100 iaction
= MULTIPLYFUNCTION
;
102 } else if ((op
= strchr(mvalue1
, '/'))) {
103 iaction
= DIVIDEFUNCTION
;
105 } else if ((op
= strchr(mvalue1
, '%'))) {
106 iaction
= MODULUSFUNCTION
;
108 } else if ((op
= strchr(mvalue1
, '>'))) {
109 iaction
= GTFUNCTION
;
111 if (*(op
+ 1) == '=') {
113 iaction
= GTEFUNCTION
;
115 } else if ((op
= strchr(mvalue1
, '<'))) {
116 iaction
= LTFUNCTION
;
118 if (*(op
+ 1) == '=') {
120 iaction
= LTEFUNCTION
;
122 } else if ((op
= strchr(mvalue1
, '='))) {
124 if (*(op
+ 1) == '=') {
126 iaction
= EQFUNCTION
;
129 } else if ((op
= strchr(mvalue1
, '+'))) {
130 iaction
= ADDFUNCTION
;
132 } else if ((op
= strchr(mvalue1
, '-'))) { /* subtraction MUST always be last, in case we have a negative first number */
133 iaction
= SUBTRACTFUNCTION
;
140 /* detect wanted type of result */
141 mtype_of_result
= args
.argv1
;
142 if (mtype_of_result
) {
143 if (!strcasecmp(mtype_of_result
, "float")
144 || !strcasecmp(mtype_of_result
, "f"))
145 type_of_result
= FLOAT_RESULT
;
146 else if (!strcasecmp(mtype_of_result
, "int")
147 || !strcasecmp(mtype_of_result
, "i"))
148 type_of_result
= INT_RESULT
;
149 else if (!strcasecmp(mtype_of_result
, "hex")
150 || !strcasecmp(mtype_of_result
, "h"))
151 type_of_result
= HEX_RESULT
;
152 else if (!strcasecmp(mtype_of_result
, "char")
153 || !strcasecmp(mtype_of_result
, "c"))
154 type_of_result
= CHAR_RESULT
;
156 ast_log(LOG_WARNING
, "Unknown type of result requested '%s'.\n",
162 if (!mvalue1
|| !mvalue2
) {
164 "Supply all the parameters - just this once, please\n");
168 if (sscanf(mvalue1
, "%lf", &fnum1
) != 1) {
169 ast_log(LOG_WARNING
, "'%s' is not a valid number\n", mvalue1
);
173 if (sscanf(mvalue2
, "%lf", &fnum2
) != 1) {
174 ast_log(LOG_WARNING
, "'%s' is not a valid number\n", mvalue2
);
183 ftmp
= fnum1
+ fnum2
;
187 ftmp
= 0; /* can't do a divide by 0 */
189 ftmp
= (fnum1
/ fnum2
);
191 case MULTIPLYFUNCTION
:
192 ftmp
= (fnum1
* fnum2
);
194 case SUBTRACTFUNCTION
:
195 ftmp
= (fnum1
- fnum2
);
197 case MODULUSFUNCTION
:
202 ftmp
= (inum1
% inum2
);
207 ast_copy_string(buf
, (fnum1
> fnum2
) ? "TRUE" : "FALSE", len
);
210 ast_copy_string(buf
, (fnum1
< fnum2
) ? "TRUE" : "FALSE", len
);
213 ast_copy_string(buf
, (fnum1
>= fnum2
) ? "TRUE" : "FALSE", len
);
216 ast_copy_string(buf
, (fnum1
<= fnum2
) ? "TRUE" : "FALSE", len
);
219 ast_copy_string(buf
, (fnum1
== fnum2
) ? "TRUE" : "FALSE", len
);
223 "Something happened that neither of us should be proud of %d\n",
228 if (iaction
< GTFUNCTION
|| iaction
> EQFUNCTION
) {
229 if (type_of_result
== FLOAT_RESULT
)
230 snprintf(buf
, len
, "%f", ftmp
);
231 else if (type_of_result
== INT_RESULT
)
232 snprintf(buf
, len
, "%i", (int) ftmp
);
233 else if (type_of_result
== HEX_RESULT
)
234 snprintf(buf
, len
, "%x", (unsigned int) ftmp
);
235 else if (type_of_result
== CHAR_RESULT
)
236 snprintf(buf
, len
, "%c", (unsigned char) ftmp
);
242 static struct ast_custom_function math_function
= {
244 .synopsis
= "Performs Mathematical Functions",
245 .syntax
= "MATH(<number1><op><number 2>[,<type_of_result>])",
246 .desc
= "Perform calculation on number 1 to number 2. Valid ops are: \n"
247 " +,-,/,*,%,<,>,>=,<=,==\n"
248 "and behave as their C equivalents.\n"
249 "<type_of_result> - wanted type of result:\n"
250 " f, float - float(default)\n"
251 " i, int - integer,\n"
254 "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
258 static int unload_module(void)
260 return ast_custom_function_unregister(&math_function
);
263 static int load_module(void)
265 return ast_custom_function_register(&math_function
);
268 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Mathematical dialplan function");