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