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