func_math.c File Reference

Math related dialplan function. More...

#include "asterisk.h"
#include <math.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/config.h"
#include "asterisk/test.h"

Include dependency graph for func_math.c:

Go to the source code of this file.

Enumerations

enum  TypeOfFunctions {
  ADDFUNCTION, DIVIDEFUNCTION, MULTIPLYFUNCTION, SUBTRACTFUNCTION,
  MODULUSFUNCTION, POWFUNCTION, SHLEFTFUNCTION, SHRIGHTFUNCTION,
  BITWISEANDFUNCTION, BITWISEXORFUNCTION, BITWISEORFUNCTION, GTFUNCTION,
  LTFUNCTION, GTEFUNCTION, LTEFUNCTION, EQFUNCTION
}
enum  TypeOfResult { FLOAT_RESULT, INT_RESULT, HEX_RESULT, CHAR_RESULT }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int crement_function_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int load_module (void)
static int math (struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Mathematical dialplan function" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_custom_function decrement_function
static struct ast_custom_function increment_function
static struct ast_custom_function math_function


Detailed Description

Math related dialplan function.

Author:
Andy Powell

Mark Spencer <markster@digium.com>

Nir Simionovich <nirs@greenfieldtech.net>

Definition in file func_math.c.


Enumeration Type Documentation

Enumerator:
ADDFUNCTION 
DIVIDEFUNCTION 
MULTIPLYFUNCTION 
SUBTRACTFUNCTION 
MODULUSFUNCTION 
POWFUNCTION 
SHLEFTFUNCTION 
SHRIGHTFUNCTION 
BITWISEANDFUNCTION 
BITWISEXORFUNCTION 
BITWISEORFUNCTION 
GTFUNCTION 
LTFUNCTION 
GTEFUNCTION 
LTEFUNCTION 
EQFUNCTION 

Definition at line 112 of file func_math.c.

Enumerator:
FLOAT_RESULT 
INT_RESULT 
HEX_RESULT 
CHAR_RESULT 

Definition at line 131 of file func_math.c.

00131                   {
00132    FLOAT_RESULT,
00133    INT_RESULT,
00134    HEX_RESULT,
00135    CHAR_RESULT
00136 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 540 of file func_math.c.

static void __unreg_module ( void   )  [static]

Definition at line 540 of file func_math.c.

static int crement_function_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 381 of file func_math.c.

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log, ast_strlen_zero, LOG_NOTICE, LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and var.

00383 {
00384    int ret = -1;
00385    int int_value = 0;
00386    int modify_orig = 0;
00387    const char *var;
00388    char endchar = 0, returnvar[12]; /* If you need a variable longer than 11 digits - something is way wrong */
00389 
00390    if (ast_strlen_zero(data)) {
00391       ast_log(LOG_WARNING, "Syntax: %s(<data>) - missing argument!\n", cmd);
00392       return -1;
00393    }
00394 
00395    if (!chan) {
00396       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
00397       return -1;
00398    }
00399 
00400    ast_channel_lock(chan);
00401 
00402    if (!(var = pbx_builtin_getvar_helper(chan, data))) {
00403       ast_log(LOG_NOTICE, "Failed to obtain variable %s, bailing out\n", data);
00404       ast_channel_unlock(chan);
00405       return -1;
00406    }
00407 
00408    if (ast_strlen_zero(var)) {
00409       ast_log(LOG_NOTICE, "Variable %s doesn't exist - are you sure you wrote it correctly?\n", data);
00410       ast_channel_unlock(chan);
00411       return -1;
00412    }
00413 
00414    if (sscanf(var, "%30d%1c", &int_value, &endchar) == 0 || endchar != 0) {
00415       ast_log(LOG_NOTICE, "The content of ${%s} is not a numeric value - bailing out!\n", data);
00416       ast_channel_unlock(chan);
00417       return -1;
00418    }
00419 
00420    /* now we'll actually do something useful */
00421    if (!strcasecmp(cmd, "INC")) {              /* Increment variable */
00422       int_value++;
00423       modify_orig = 1;
00424    } else if (!strcasecmp(cmd, "DEC")) {       /* Decrement variable */
00425       int_value--;
00426       modify_orig = 1;
00427    }
00428 
00429    if (snprintf(returnvar, sizeof(returnvar), "%d", int_value) > 0) {
00430       pbx_builtin_setvar_helper(chan, data, returnvar);
00431       if (modify_orig) {
00432          ast_copy_string(buf, returnvar, len);
00433       }
00434       ret = 0;
00435    } else {
00436       pbx_builtin_setvar_helper(chan, data, "0");
00437       if (modify_orig) {
00438          ast_copy_string(buf, "0", len);
00439       }
00440       ast_log(LOG_NOTICE, "Variable %s refused to be %sREMENTED, setting value to 0", data, cmd);
00441       ret = 0;
00442    }
00443 
00444    ast_channel_unlock(chan);
00445 
00446    return ret;
00447 }

static int load_module ( void   )  [static]

Definition at line 528 of file func_math.c.

References ast_custom_function_register, and AST_TEST_REGISTER.

00529 {
00530    int res = 0;
00531 
00532    res |= ast_custom_function_register(&math_function);
00533    res |= ast_custom_function_register(&increment_function);
00534    res |= ast_custom_function_register(&decrement_function);
00535    AST_TEST_REGISTER(test_MATH_function);
00536 
00537    return res;
00538 }

static int math ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
size_t  len 
) [static]

Definition at line 138 of file func_math.c.

References ADDFUNCTION, args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strlen_zero, BITWISEANDFUNCTION, BITWISEORFUNCTION, BITWISEXORFUNCTION, CHAR_RESULT, DIVIDEFUNCTION, EQFUNCTION, FLOAT_RESULT, GTEFUNCTION, GTFUNCTION, HEX_RESULT, INT_RESULT, LOG_WARNING, LTEFUNCTION, LTFUNCTION, MODULUSFUNCTION, MULTIPLYFUNCTION, NULL, POWFUNCTION, SHLEFTFUNCTION, SHRIGHTFUNCTION, and SUBTRACTFUNCTION.

00140 {
00141    double fnum1;
00142    double fnum2;
00143    double ftmp = 0;
00144    char *op;
00145    int iaction = -1;
00146    int type_of_result = FLOAT_RESULT;
00147    char *mvalue1, *mvalue2 = NULL, *mtype_of_result;
00148    int negvalue1 = 0;
00149    AST_DECLARE_APP_ARGS(args,
00150               AST_APP_ARG(argv0);
00151               AST_APP_ARG(argv1);
00152    );
00153 
00154    if (ast_strlen_zero(parse)) {
00155       ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00156       return -1;
00157    }
00158 
00159    AST_STANDARD_APP_ARGS(args, parse);
00160 
00161    if (args.argc < 1) {
00162       ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00163       return -1;
00164    }
00165 
00166    mvalue1 = args.argv0;
00167 
00168    if (mvalue1[0] == '-') {
00169       negvalue1 = 1;
00170       mvalue1++;
00171    }
00172 
00173    if ((op = strchr(mvalue1, '*'))) {
00174       iaction = MULTIPLYFUNCTION;
00175       *op = '\0';
00176    } else if ((op = strchr(mvalue1, '/'))) {
00177       iaction = DIVIDEFUNCTION;
00178       *op = '\0';
00179    } else if ((op = strchr(mvalue1, '%'))) {
00180       iaction = MODULUSFUNCTION;
00181       *op = '\0';
00182    } else if ((op = strchr(mvalue1, '^'))) {
00183       iaction = POWFUNCTION;
00184       *op = '\0';
00185    } else if ((op = strstr(mvalue1, "AND"))) {
00186       iaction = BITWISEANDFUNCTION;
00187       *op = '\0';
00188       op += 2;
00189    } else if ((op = strstr(mvalue1, "XOR"))) {
00190       iaction = BITWISEXORFUNCTION;
00191       *op = '\0';
00192       op += 2;
00193    } else if ((op = strstr(mvalue1, "OR"))) {
00194       iaction = BITWISEORFUNCTION;
00195       *op = '\0';
00196       ++op;
00197    } else if ((op = strchr(mvalue1, '>'))) {
00198       iaction = GTFUNCTION;
00199       *op = '\0';
00200       if (*(op + 1) == '=') {
00201          iaction = GTEFUNCTION;
00202          ++op;
00203       } else if (*(op + 1) == '>') {
00204          iaction = SHRIGHTFUNCTION;
00205          ++op;
00206       }
00207    } else if ((op = strchr(mvalue1, '<'))) {
00208       iaction = LTFUNCTION;
00209       *op = '\0';
00210       if (*(op + 1) == '=') {
00211          iaction = LTEFUNCTION;
00212          ++op;
00213       } else if (*(op + 1) == '<') {
00214          iaction = SHLEFTFUNCTION;
00215          ++op;
00216       }
00217    } else if ((op = strchr(mvalue1, '='))) {
00218       *op = '\0';
00219       if (*(op + 1) == '=') {
00220          iaction = EQFUNCTION;
00221          ++op;
00222       } else
00223          op = NULL;
00224    } else if ((op = strchr(mvalue1, '+'))) {
00225       iaction = ADDFUNCTION;
00226       *op = '\0';
00227    } else if ((op = strchr(mvalue1, '-'))) { /* subtraction MUST always be last, in case we have a negative second number */
00228       iaction = SUBTRACTFUNCTION;
00229       *op = '\0';
00230    }
00231 
00232    if (op)
00233       mvalue2 = op + 1;
00234 
00235    /* detect wanted type of result */
00236    mtype_of_result = args.argv1;
00237    if (mtype_of_result) {
00238       if (!strcasecmp(mtype_of_result, "float")
00239           || !strcasecmp(mtype_of_result, "f"))
00240          type_of_result = FLOAT_RESULT;
00241       else if (!strcasecmp(mtype_of_result, "int")
00242           || !strcasecmp(mtype_of_result, "i"))
00243          type_of_result = INT_RESULT;
00244       else if (!strcasecmp(mtype_of_result, "hex")
00245           || !strcasecmp(mtype_of_result, "h"))
00246          type_of_result = HEX_RESULT;
00247       else if (!strcasecmp(mtype_of_result, "char")
00248           || !strcasecmp(mtype_of_result, "c"))
00249          type_of_result = CHAR_RESULT;
00250       else {
00251          ast_log(LOG_WARNING, "Unknown type of result requested '%s'.\n",
00252                mtype_of_result);
00253          return -1;
00254       }
00255    }
00256 
00257    if (!mvalue2) {
00258       ast_log(LOG_WARNING,
00259             "Supply all the parameters - just this once, please\n");
00260       return -1;
00261    }
00262 
00263    if (sscanf(mvalue1, "%30lf", &fnum1) != 1) {
00264       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
00265       return -1;
00266    }
00267 
00268    if (sscanf(mvalue2, "%30lf", &fnum2) != 1) {
00269       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
00270       return -1;
00271    }
00272 
00273    if (negvalue1)
00274       fnum1 = 0 - fnum1;
00275 
00276    switch (iaction) {
00277    case ADDFUNCTION:
00278       ftmp = fnum1 + fnum2;
00279       break;
00280    case DIVIDEFUNCTION:
00281       if (fnum2 <= 0)
00282          ftmp = 0;         /* can't do a divide by 0 */
00283       else
00284          ftmp = (fnum1 / fnum2);
00285       break;
00286    case MULTIPLYFUNCTION:
00287       ftmp = (fnum1 * fnum2);
00288       break;
00289    case SUBTRACTFUNCTION:
00290       ftmp = (fnum1 - fnum2);
00291       break;
00292    case MODULUSFUNCTION:
00293       {
00294          int inum1 = fnum1;
00295          int inum2 = fnum2;
00296 
00297          if (inum2 == 0) {
00298             ftmp = 0;
00299          } else {
00300             ftmp = (inum1 % inum2);
00301          }
00302 
00303          break;
00304       }
00305    case POWFUNCTION:
00306       ftmp = pow(fnum1, fnum2);
00307       break;
00308    case SHLEFTFUNCTION:
00309       {
00310          int inum1 = fnum1;
00311          int inum2 = fnum2;
00312 
00313          ftmp = (inum1 << inum2);
00314          break;
00315       }
00316    case SHRIGHTFUNCTION:
00317       {
00318          int inum1 = fnum1;
00319          int inum2 = fnum2;
00320 
00321          ftmp = (inum1 >> inum2);
00322          break;
00323       }
00324    case BITWISEANDFUNCTION:
00325       {
00326          int inum1 = fnum1;
00327          int inum2 = fnum2;
00328          ftmp = (inum1 & inum2);
00329          break;
00330       }
00331    case BITWISEXORFUNCTION:
00332       {
00333          int inum1 = fnum1;
00334          int inum2 = fnum2;
00335          ftmp = (inum1 ^ inum2);
00336          break;
00337       }
00338    case BITWISEORFUNCTION:
00339       {
00340          int inum1 = fnum1;
00341          int inum2 = fnum2;
00342          ftmp = (inum1 | inum2);
00343          break;
00344       }
00345    case GTFUNCTION:
00346       ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
00347       break;
00348    case LTFUNCTION:
00349       ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
00350       break;
00351    case GTEFUNCTION:
00352       ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
00353       break;
00354    case LTEFUNCTION:
00355       ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
00356       break;
00357    case EQFUNCTION:
00358       ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
00359       break;
00360    default:
00361       ast_log(LOG_WARNING,
00362             "Something happened that neither of us should be proud of %d\n",
00363             iaction);
00364       return -1;
00365    }
00366 
00367    if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
00368       if (type_of_result == FLOAT_RESULT)
00369          snprintf(buf, len, "%f", ftmp);
00370       else if (type_of_result == INT_RESULT)
00371          snprintf(buf, len, "%i", (int) ftmp);
00372       else if (type_of_result == HEX_RESULT)
00373          snprintf(buf, len, "%x", (unsigned int) ftmp);
00374       else if (type_of_result == CHAR_RESULT)
00375          snprintf(buf, len, "%c", (unsigned char) ftmp);
00376    }
00377 
00378    return 0;
00379 }

static int unload_module ( void   )  [static]

Definition at line 516 of file func_math.c.

References ast_custom_function_unregister(), and AST_TEST_UNREGISTER.

00517 {
00518    int res = 0;
00519 
00520    res |= ast_custom_function_unregister(&math_function);
00521    res |= ast_custom_function_unregister(&increment_function);
00522    res |= ast_custom_function_unregister(&decrement_function);
00523    AST_TEST_UNREGISTER(test_MATH_function);
00524 
00525    return res;
00526 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Mathematical dialplan function" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, } [static]

Definition at line 540 of file func_math.c.

Definition at line 540 of file func_math.c.

Initial value:

 {
   .name = "DEC",
   .read = crement_function_read,
}

Definition at line 460 of file func_math.c.

Initial value:

 {
   .name = "INC",
   .read = crement_function_read,
}

Definition at line 455 of file func_math.c.

Initial value:

 {
   .name = "MATH",
   .read = math
}

Definition at line 450 of file func_math.c.


Generated on Thu Apr 16 06:31:20 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6