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