Mon May 14 04:42:56 2007

Asterisk developer's documentation


func_math.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2004 - 2006, Andy Powell 
00005  *
00006  * Updated by Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Math related dialplan function
00022  *
00023  * \author Andy Powell
00024  * \author Mark Spencer <markster@digium.com>
00025  *
00026  * \ingroup functions
00027  */
00028 
00029 #include "asterisk.h"
00030 
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00032 
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <math.h>
00037 #include <sys/types.h>
00038 
00039 #include "asterisk/module.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/logger.h"
00043 #include "asterisk/utils.h"
00044 #include "asterisk/app.h"
00045 #include "asterisk/config.h"
00046 
00047 enum TypeOfFunctions {
00048    ADDFUNCTION,
00049    DIVIDEFUNCTION,
00050    MULTIPLYFUNCTION,
00051    SUBTRACTFUNCTION,
00052    MODULUSFUNCTION,
00053    POWFUNCTION,
00054    SHLEFTFUNCTION,
00055    SHRIGHTFUNCTION,
00056    GTFUNCTION,
00057    LTFUNCTION,
00058    GTEFUNCTION,
00059    LTEFUNCTION,
00060    EQFUNCTION
00061 };
00062 
00063 enum TypeOfResult {
00064    FLOAT_RESULT,
00065    INT_RESULT,
00066    HEX_RESULT,
00067    CHAR_RESULT
00068 };
00069 
00070 static int math(struct ast_channel *chan, char *cmd, char *parse,
00071       char *buf, size_t len)
00072 {
00073    float fnum1;
00074    float fnum2;
00075    float ftmp = 0;
00076    char *op;
00077    int iaction = -1;
00078    int type_of_result = FLOAT_RESULT;
00079    char *mvalue1, *mvalue2 = NULL, *mtype_of_result;
00080    AST_DECLARE_APP_ARGS(args,
00081               AST_APP_ARG(argv0);
00082               AST_APP_ARG(argv1);
00083    );
00084 
00085    if (ast_strlen_zero(parse)) {
00086       ast_log(LOG_WARNING, "Syntax: Math(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00087       return -1;
00088    }
00089 
00090    AST_STANDARD_APP_ARGS(args, parse);
00091 
00092    if (args.argc < 1) {
00093       ast_log(LOG_WARNING, "Syntax: Math(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00094       return -1;
00095    }
00096 
00097    mvalue1 = args.argv0;
00098 
00099    if ((op = strchr(mvalue1, '+'))) {
00100       iaction = ADDFUNCTION;
00101       *op = '\0';
00102    } else if ((op = strchr(mvalue1, '-'))) {
00103       iaction = SUBTRACTFUNCTION;
00104       *op = '\0';
00105    } else if ((op = strchr(mvalue1, '*'))) {
00106       iaction = MULTIPLYFUNCTION;
00107       *op = '\0';
00108    } else if ((op = strchr(mvalue1, '/'))) {
00109       iaction = DIVIDEFUNCTION;
00110       *op = '\0';
00111    } else if ((op = strchr(mvalue1, '%'))) {
00112       iaction = MODULUSFUNCTION;
00113       *op = '\0';
00114    } else if ((op = strchr(mvalue1, '^'))) {
00115       iaction = POWFUNCTION;
00116       *op = '\0';
00117    } else if ((op = strchr(mvalue1, '>'))) {
00118       iaction = GTFUNCTION;
00119       *op = '\0';
00120       if (*(op + 1) == '=') {
00121          *++op = '\0';
00122          iaction = GTEFUNCTION;
00123       } else if (*(op + 1) == '>') {
00124          *++op = '\0';
00125          iaction = SHRIGHTFUNCTION;
00126       }
00127    } else if ((op = strchr(mvalue1, '<'))) {
00128       iaction = LTFUNCTION;
00129       *op = '\0';
00130       if (*(op + 1) == '=') {
00131          *++op = '\0';
00132          iaction = LTEFUNCTION;
00133       } else if (*(op + 1) == '<') {
00134          *++op = '\0';
00135          iaction = SHLEFTFUNCTION;
00136       }
00137    } else if ((op = strchr(mvalue1, '='))) {
00138       *op = '\0';
00139       if (*(op + 1) == '=') {
00140          *++op = '\0';
00141          iaction = EQFUNCTION;
00142       } else
00143          op = NULL;
00144    }
00145 
00146    if (op)
00147       mvalue2 = op + 1;
00148 
00149    /* detect wanted type of result */
00150    mtype_of_result = args.argv1;
00151    if (mtype_of_result) {
00152       if (!strcasecmp(mtype_of_result, "float")
00153           || !strcasecmp(mtype_of_result, "f"))
00154          type_of_result = FLOAT_RESULT;
00155       else if (!strcasecmp(mtype_of_result, "int")
00156           || !strcasecmp(mtype_of_result, "i"))
00157          type_of_result = INT_RESULT;
00158       else if (!strcasecmp(mtype_of_result, "hex")
00159           || !strcasecmp(mtype_of_result, "h"))
00160          type_of_result = HEX_RESULT;
00161       else if (!strcasecmp(mtype_of_result, "char")
00162           || !strcasecmp(mtype_of_result, "c"))
00163          type_of_result = CHAR_RESULT;
00164       else {
00165          ast_log(LOG_WARNING, "Unknown type of result requested '%s'.\n",
00166                mtype_of_result);
00167          return -1;
00168       }
00169    }
00170 
00171    if (!mvalue1 || !mvalue2) {
00172       ast_log(LOG_WARNING,
00173             "Supply all the parameters - just this once, please\n");
00174       return -1;
00175    }
00176 
00177    if (sscanf(mvalue1, "%f", &fnum1) != 1) {
00178       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
00179       return -1;
00180    }
00181 
00182    if (sscanf(mvalue2, "%f", &fnum2) != 1) {
00183       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
00184       return -1;
00185    }
00186 
00187    switch (iaction) {
00188    case ADDFUNCTION:
00189       ftmp = fnum1 + fnum2;
00190       break;
00191    case DIVIDEFUNCTION:
00192       if (fnum2 <= 0)
00193          ftmp = 0;         /* can't do a divide by 0 */
00194       else
00195          ftmp = (fnum1 / fnum2);
00196       break;
00197    case MULTIPLYFUNCTION:
00198       ftmp = (fnum1 * fnum2);
00199       break;
00200    case SUBTRACTFUNCTION:
00201       ftmp = (fnum1 - fnum2);
00202       break;
00203    case MODULUSFUNCTION:
00204       {
00205          int inum1 = fnum1;
00206          int inum2 = fnum2;
00207 
00208          ftmp = (inum1 % inum2);
00209 
00210          break;
00211       }
00212    case POWFUNCTION:
00213       ftmp = pow(fnum1, fnum2);
00214       break;
00215    case SHLEFTFUNCTION:
00216       {
00217          int inum1 = fnum1;
00218          int inum2 = fnum2;
00219 
00220          ftmp = (inum1 << inum2);
00221          break;
00222       }
00223    case SHRIGHTFUNCTION:
00224       {
00225          int inum1 = fnum1;
00226          int inum2 = fnum2;
00227 
00228          ftmp = (inum1 >> inum2);
00229          break;
00230       }
00231    case GTFUNCTION:
00232       ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
00233       break;
00234    case LTFUNCTION:
00235       ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
00236       break;
00237    case GTEFUNCTION:
00238       ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
00239       break;
00240    case LTEFUNCTION:
00241       ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
00242       break;
00243    case EQFUNCTION:
00244       ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
00245       break;
00246    default:
00247       ast_log(LOG_WARNING,
00248             "Something happened that neither of us should be proud of %d\n",
00249             iaction);
00250       return -1;
00251    }
00252 
00253    if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
00254       if (type_of_result == FLOAT_RESULT)
00255          snprintf(buf, len, "%f", ftmp);
00256       else if (type_of_result == INT_RESULT)
00257          snprintf(buf, len, "%i", (int) ftmp);
00258       else if (type_of_result == HEX_RESULT)
00259          snprintf(buf, len, "%x", (unsigned int) ftmp);
00260       else if (type_of_result == CHAR_RESULT)
00261          snprintf(buf, len, "%c", (unsigned char) ftmp);
00262    }
00263 
00264    return 0;
00265 }
00266 
00267 static struct ast_custom_function math_function = {
00268    .name = "MATH",
00269    .synopsis = "Performs Mathematical Functions",
00270    .syntax = "MATH(<number1><op><number2>[,<type_of_result>])",
00271    .desc = "Perform calculation on number1 to number2. Valid ops are: \n"
00272       "    +,-,/,*,%,<<,>>,^,<,>,>=,<=,==\n"
00273       "and behave as their C equivalents.\n"
00274       "<type_of_result> - wanted type of result:\n"
00275       "  f, float - float(default)\n"
00276       "  i, int - integer,\n"
00277       "  h, hex - hex,\n"
00278       "  c, char - char\n"
00279       "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
00280    .read = math
00281 };
00282 
00283 static int unload_module(void)
00284 {
00285    return ast_custom_function_unregister(&math_function);
00286 }
00287 
00288 static int load_module(void)
00289 {
00290    return ast_custom_function_register(&math_function);
00291 }
00292 
00293 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");

Generated on Mon May 14 04:42:56 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1