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 double fnum1;
00071 double fnum2;
00072 double 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 *op = '\0';
00128 if (*(op+1) == '=') {
00129 *++op = '\0';
00130 iaction = EQFUNCTION;
00131 } else
00132 op = NULL;
00133 }
00134
00135 if (op)
00136 mvalue2 = op + 1;
00137
00138
00139 mtype_of_result = argv[1];
00140 if (mtype_of_result)
00141 {
00142 if (!strcasecmp(mtype_of_result,"float") || !strcasecmp(mtype_of_result,"f"))
00143 type_of_result=FLOAT_RESULT;
00144 else if (!strcasecmp(mtype_of_result,"int") || !strcasecmp(mtype_of_result,"i"))
00145 type_of_result=INT_RESULT;
00146 else if (!strcasecmp(mtype_of_result,"hex") || !strcasecmp(mtype_of_result,"h"))
00147 type_of_result=HEX_RESULT;
00148 else if (!strcasecmp(mtype_of_result,"char") || !strcasecmp(mtype_of_result,"c"))
00149 type_of_result=CHAR_RESULT;
00150 else
00151 {
00152 ast_log(LOG_WARNING, "Unknown type of result requested '%s'.\n", mtype_of_result);
00153 return NULL;
00154 }
00155 }
00156
00157 if (!mvalue1 || !mvalue2) {
00158 ast_log(LOG_WARNING, "Supply all the parameters - just this once, please\n");
00159 return NULL;
00160 }
00161
00162 if (sscanf(mvalue1, "%30lf", &fnum1) != 1) {
00163 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
00164 return NULL;
00165 }
00166
00167 if (sscanf(mvalue2, "%30lf", &fnum2) != 1) {
00168 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
00169 return NULL;
00170 }
00171
00172 switch (iaction) {
00173 case ADDFUNCTION :
00174 ftmp = fnum1 + fnum2;
00175 break;
00176 case DIVIDEFUNCTION :
00177 if (fnum2 <= 0)
00178 ftmp = 0;
00179 else
00180 ftmp = (fnum1 / fnum2);
00181 break;
00182 case MULTIPLYFUNCTION :
00183 ftmp = (fnum1 * fnum2);
00184 break;
00185 case SUBTRACTFUNCTION :
00186 ftmp = (fnum1 - fnum2);
00187 break;
00188 case MODULUSFUNCTION :
00189 {
00190 int inum1 = fnum1;
00191 int inum2 = fnum2;
00192
00193 ftmp = (inum1 % inum2);
00194
00195 break;
00196 }
00197 case GTFUNCTION :
00198 ast_copy_string (user_result, (fnum1 > fnum2)?"TRUE":"FALSE", sizeof (user_result));
00199 break;
00200 case LTFUNCTION :
00201 ast_copy_string (user_result, (fnum1 < fnum2)?"TRUE":"FALSE", sizeof (user_result));
00202 break;
00203 case GTEFUNCTION :
00204 ast_copy_string (user_result, (fnum1 >= fnum2)?"TRUE":"FALSE", sizeof (user_result));
00205 break;
00206 case LTEFUNCTION :
00207 ast_copy_string (user_result, (fnum1 <= fnum2)?"TRUE":"FALSE", sizeof (user_result));
00208 break;
00209 case EQFUNCTION :
00210 ast_copy_string (user_result, (fnum1 == fnum2)?"TRUE":"FALSE", sizeof (user_result));
00211 break;
00212 default :
00213 ast_log(LOG_WARNING, "Something happened that neither of us should be proud of %d\n", iaction);
00214 return NULL;
00215 }
00216
00217 if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
00218 if (type_of_result == FLOAT_RESULT)
00219 snprintf(user_result, sizeof(user_result), "%f", ftmp);
00220 else if (type_of_result == INT_RESULT)
00221 snprintf(user_result, sizeof(user_result), "%i", (int) ftmp);
00222 else if (type_of_result == HEX_RESULT)
00223 snprintf(user_result, sizeof(user_result), "%x", (unsigned int) ftmp);
00224 else if (type_of_result == CHAR_RESULT)
00225 snprintf(user_result, sizeof(user_result), "%c", (unsigned char) ftmp);
00226 }
00227
00228 ast_copy_string(buf, user_result, len);
00229
00230 return buf;
00231 }
00232
00233 #ifndef BUILTIN_FUNC
00234 static
00235 #endif
00236 struct ast_custom_function math_function = {
00237 .name = "MATH",
00238 .synopsis = "Performs Mathematical Functions",
00239 .syntax = "MATH(<number1><op><number 2>[,<type_of_result>])",
00240 .desc = "Perform calculation on number 1 to number 2. Valid ops are: \n"
00241 " +,-,/,*,%,<,>,>=,<=,==\n"
00242 "and behave as their C equivalents.\n"
00243 "<type_of_result> - wanted type of result:\n"
00244 " f, float - float(default)\n"
00245 " i, int - integer,\n"
00246 " h, hex - hex,\n"
00247 " c, char - char\n"
00248 "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
00249 .read = builtin_function_math
00250 };