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: 146799 $")
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, "%lf", &fnum1) != 1) {
00169 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
00170 return -1;
00171 }
00172
00173 if (sscanf(mvalue2, "%lf", &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 ftmp = (inum1 % inum2);
00203
00204 break;
00205 }
00206 case GTFUNCTION:
00207 ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
00208 break;
00209 case LTFUNCTION:
00210 ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
00211 break;
00212 case GTEFUNCTION:
00213 ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
00214 break;
00215 case LTEFUNCTION:
00216 ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
00217 break;
00218 case EQFUNCTION:
00219 ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
00220 break;
00221 default:
00222 ast_log(LOG_WARNING,
00223 "Something happened that neither of us should be proud of %d\n",
00224 iaction);
00225 return -1;
00226 }
00227
00228 if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
00229 if (type_of_result == FLOAT_RESULT)
00230 snprintf(buf, len, "%f", ftmp);
00231 else if (type_of_result == INT_RESULT)
00232 snprintf(buf, len, "%i", (int) ftmp);
00233 else if (type_of_result == HEX_RESULT)
00234 snprintf(buf, len, "%x", (unsigned int) ftmp);
00235 else if (type_of_result == CHAR_RESULT)
00236 snprintf(buf, len, "%c", (unsigned char) ftmp);
00237 }
00238
00239 return 0;
00240 }
00241
00242 static struct ast_custom_function math_function = {
00243 .name = "MATH",
00244 .synopsis = "Performs Mathematical Functions",
00245 .syntax = "MATH(<number1><op><number 2>[,<type_of_result>])",
00246 .desc = "Perform calculation on number 1 to number 2. Valid ops are: \n"
00247 " +,-,/,*,%,<,>,>=,<=,==\n"
00248 "and behave as their C equivalents.\n"
00249 "<type_of_result> - wanted type of result:\n"
00250 " f, float - float(default)\n"
00251 " i, int - integer,\n"
00252 " h, hex - hex,\n"
00253 " c, char - char\n"
00254 "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
00255 .read = math
00256 };
00257
00258 static int unload_module(void)
00259 {
00260 return ast_custom_function_unregister(&math_function);
00261 }
00262
00263 static int load_module(void)
00264 {
00265 return ast_custom_function_register(&math_function);
00266 }
00267
00268 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");