00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "asterisk.h"
00030
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 89425 $")
00032
00033 #include <math.h>
00034
00035 #include "asterisk/module.h"
00036 #include "asterisk/channel.h"
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/utils.h"
00039 #include "asterisk/app.h"
00040 #include "asterisk/config.h"
00041
00042 enum TypeOfFunctions {
00043 ADDFUNCTION,
00044 DIVIDEFUNCTION,
00045 MULTIPLYFUNCTION,
00046 SUBTRACTFUNCTION,
00047 MODULUSFUNCTION,
00048 POWFUNCTION,
00049 SHLEFTFUNCTION,
00050 SHRIGHTFUNCTION,
00051 BITWISEANDFUNCTION,
00052 BITWISEXORFUNCTION,
00053 BITWISEORFUNCTION,
00054 GTFUNCTION,
00055 LTFUNCTION,
00056 GTEFUNCTION,
00057 LTEFUNCTION,
00058 EQFUNCTION
00059 };
00060
00061 enum TypeOfResult {
00062 FLOAT_RESULT,
00063 INT_RESULT,
00064 HEX_RESULT,
00065 CHAR_RESULT
00066 };
00067
00068 static int math(struct ast_channel *chan, const char *cmd, char *parse,
00069 char *buf, size_t len)
00070 {
00071 double fnum1;
00072 double fnum2;
00073 double ftmp = 0;
00074 char *op;
00075 int iaction = -1;
00076 int type_of_result = FLOAT_RESULT;
00077 char *mvalue1, *mvalue2 = NULL, *mtype_of_result;
00078 int negvalue1 = 0;
00079 AST_DECLARE_APP_ARGS(args,
00080 AST_APP_ARG(argv0);
00081 AST_APP_ARG(argv1);
00082 );
00083
00084 if (ast_strlen_zero(parse)) {
00085 ast_log(LOG_WARNING, "Syntax: Math(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00086 return -1;
00087 }
00088
00089 AST_STANDARD_APP_ARGS(args, parse);
00090
00091 if (args.argc < 1) {
00092 ast_log(LOG_WARNING, "Syntax: Math(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00093 return -1;
00094 }
00095
00096 mvalue1 = args.argv0;
00097
00098 if (mvalue1[0] == '-') {
00099 negvalue1 = 1;
00100 mvalue1++;
00101 }
00102
00103 if ((op = strchr(mvalue1, '*'))) {
00104 iaction = MULTIPLYFUNCTION;
00105 *op = '\0';
00106 } else if ((op = strchr(mvalue1, '/'))) {
00107 iaction = DIVIDEFUNCTION;
00108 *op = '\0';
00109 } else if ((op = strchr(mvalue1, '%'))) {
00110 iaction = MODULUSFUNCTION;
00111 *op = '\0';
00112 } else if ((op = strchr(mvalue1, '^'))) {
00113 iaction = POWFUNCTION;
00114 *op = '\0';
00115 } else if ((op = strstr(mvalue1, "AND"))) {
00116 iaction = BITWISEANDFUNCTION;
00117 op += 3;
00118 *op = '\0';
00119 } else if ((op = strstr(mvalue1, "XOR"))) {
00120 iaction = BITWISEXORFUNCTION;
00121 op += 3;
00122 *op = '\0';
00123 } else if ((op = strstr(mvalue1, "OR"))) {
00124 iaction = BITWISEORFUNCTION;
00125 op += 2;
00126 *op = '\0';
00127 } else if ((op = strchr(mvalue1, '>'))) {
00128 iaction = GTFUNCTION;
00129 *op = '\0';
00130 if (*(op + 1) == '=') {
00131 *++op = '\0';
00132 iaction = GTEFUNCTION;
00133 } else if (*(op + 1) == '>') {
00134 *++op = '\0';
00135 iaction = SHRIGHTFUNCTION;
00136 }
00137 } else if ((op = strchr(mvalue1, '<'))) {
00138 iaction = LTFUNCTION;
00139 *op = '\0';
00140 if (*(op + 1) == '=') {
00141 *++op = '\0';
00142 iaction = LTEFUNCTION;
00143 } else if (*(op + 1) == '<') {
00144 *++op = '\0';
00145 iaction = SHLEFTFUNCTION;
00146 }
00147 } else if ((op = strchr(mvalue1, '='))) {
00148 *op = '\0';
00149 if (*(op + 1) == '=') {
00150 *++op = '\0';
00151 iaction = EQFUNCTION;
00152 } else
00153 op = NULL;
00154 } else if ((op = strchr(mvalue1, '+'))) {
00155 iaction = ADDFUNCTION;
00156 *op = '\0';
00157 } else if ((op = strchr(mvalue1, '-'))) {
00158 iaction = SUBTRACTFUNCTION;
00159 *op = '\0';
00160 }
00161
00162 if (op)
00163 mvalue2 = op + 1;
00164
00165
00166 mtype_of_result = args.argv1;
00167 if (mtype_of_result) {
00168 if (!strcasecmp(mtype_of_result, "float")
00169 || !strcasecmp(mtype_of_result, "f"))
00170 type_of_result = FLOAT_RESULT;
00171 else if (!strcasecmp(mtype_of_result, "int")
00172 || !strcasecmp(mtype_of_result, "i"))
00173 type_of_result = INT_RESULT;
00174 else if (!strcasecmp(mtype_of_result, "hex")
00175 || !strcasecmp(mtype_of_result, "h"))
00176 type_of_result = HEX_RESULT;
00177 else if (!strcasecmp(mtype_of_result, "char")
00178 || !strcasecmp(mtype_of_result, "c"))
00179 type_of_result = CHAR_RESULT;
00180 else {
00181 ast_log(LOG_WARNING, "Unknown type of result requested '%s'.\n",
00182 mtype_of_result);
00183 return -1;
00184 }
00185 }
00186
00187 if (!mvalue1 || !mvalue2) {
00188 ast_log(LOG_WARNING,
00189 "Supply all the parameters - just this once, please\n");
00190 return -1;
00191 }
00192
00193 if (sscanf(mvalue1, "%lf", &fnum1) != 1) {
00194 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
00195 return -1;
00196 }
00197
00198 if (sscanf(mvalue2, "%lf", &fnum2) != 1) {
00199 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
00200 return -1;
00201 }
00202
00203 if (negvalue1)
00204 fnum1 = 0 - fnum1;
00205
00206 switch (iaction) {
00207 case ADDFUNCTION:
00208 ftmp = fnum1 + fnum2;
00209 break;
00210 case DIVIDEFUNCTION:
00211 if (fnum2 <= 0)
00212 ftmp = 0;
00213 else
00214 ftmp = (fnum1 / fnum2);
00215 break;
00216 case MULTIPLYFUNCTION:
00217 ftmp = (fnum1 * fnum2);
00218 break;
00219 case SUBTRACTFUNCTION:
00220 ftmp = (fnum1 - fnum2);
00221 break;
00222 case MODULUSFUNCTION:
00223 {
00224 int inum1 = fnum1;
00225 int inum2 = fnum2;
00226
00227 ftmp = (inum1 % inum2);
00228
00229 break;
00230 }
00231 case POWFUNCTION:
00232 ftmp = pow(fnum1, fnum2);
00233 break;
00234 case SHLEFTFUNCTION:
00235 {
00236 int inum1 = fnum1;
00237 int inum2 = fnum2;
00238
00239 ftmp = (inum1 << inum2);
00240 break;
00241 }
00242 case SHRIGHTFUNCTION:
00243 {
00244 int inum1 = fnum1;
00245 int inum2 = fnum2;
00246
00247 ftmp = (inum1 >> inum2);
00248 break;
00249 }
00250 case BITWISEANDFUNCTION:
00251 {
00252 int inum1 = fnum1;
00253 int inum2 = fnum2;
00254 ftmp = (inum1 & inum2);
00255 break;
00256 }
00257 case BITWISEXORFUNCTION:
00258 {
00259 int inum1 = fnum1;
00260 int inum2 = fnum2;
00261 ftmp = (inum1 ^ inum2);
00262 break;
00263 }
00264 case BITWISEORFUNCTION:
00265 {
00266 int inum1 = fnum1;
00267 int inum2 = fnum2;
00268 ftmp = (inum1 | inum2);
00269 break;
00270 }
00271 case GTFUNCTION:
00272 ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
00273 break;
00274 case LTFUNCTION:
00275 ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
00276 break;
00277 case GTEFUNCTION:
00278 ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
00279 break;
00280 case LTEFUNCTION:
00281 ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
00282 break;
00283 case EQFUNCTION:
00284 ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
00285 break;
00286 default:
00287 ast_log(LOG_WARNING,
00288 "Something happened that neither of us should be proud of %d\n",
00289 iaction);
00290 return -1;
00291 }
00292
00293 if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
00294 if (type_of_result == FLOAT_RESULT)
00295 snprintf(buf, len, "%f", ftmp);
00296 else if (type_of_result == INT_RESULT)
00297 snprintf(buf, len, "%i", (int) ftmp);
00298 else if (type_of_result == HEX_RESULT)
00299 snprintf(buf, len, "%x", (unsigned int) ftmp);
00300 else if (type_of_result == CHAR_RESULT)
00301 snprintf(buf, len, "%c", (unsigned char) ftmp);
00302 }
00303
00304 return 0;
00305 }
00306
00307 static struct ast_custom_function math_function = {
00308 .name = "MATH",
00309 .synopsis = "Performs Mathematical Functions",
00310 .syntax = "MATH(<number1><op><number2>[,<type_of_result>])",
00311 .desc = "Perform calculation on number1 to number2. Valid ops are: \n"
00312 " +,-,/,*,%,<<,>>,^,AND,OR,XOR,<,>,>=,<=,==\n"
00313 "and behave as their C equivalents.\n"
00314 "<type_of_result> - wanted type of result:\n"
00315 " f, float - float(default)\n"
00316 " i, int - integer,\n"
00317 " h, hex - hex,\n"
00318 " c, char - char\n"
00319 "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
00320 .read = math
00321 };
00322
00323 static int unload_module(void)
00324 {
00325 return ast_custom_function_unregister(&math_function);
00326 }
00327
00328 static int load_module(void)
00329 {
00330 return ast_custom_function_register(&math_function);
00331 }
00332
00333 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");