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