add some logic tools

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6189 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2007-11-08 23:46:26 +00:00
parent 19bc1197ee
commit 713afbd975
29 changed files with 7711 additions and 10 deletions

View File

@ -7,6 +7,7 @@ applications/mod_enum
applications/mod_fifo applications/mod_fifo
applications/mod_voicemail applications/mod_voicemail
applications/mod_limit applications/mod_limit
applications/mod_expr
#applications/mod_ivrtest #applications/mod_ivrtest
#applications/mod_soundtouch #applications/mod_soundtouch
#applications/mod_rss #applications/mod_rss

View File

@ -36,6 +36,7 @@
<load module="mod_commands"/> <load module="mod_commands"/>
<load module="mod_conference"/> <load module="mod_conference"/>
<load module="mod_dptools"/> <load module="mod_dptools"/>
<load module="mod_expr"/>
<load module="mod_fifo"/> <load module="mod_fifo"/>
<load module="mod_voicemail"/> <load module="mod_voicemail"/>
<load module="mod_limit"/> <load module="mod_limit"/>

View File

@ -298,7 +298,10 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
*/ */
SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen); SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen);
SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
SWITCH_DECLARE(char *) switch_strip_spaces(const char *str);
SWITCH_DECLARE(const char *) switch_stristr(const char *str, const char *instr); SWITCH_DECLARE(const char *) switch_stristr(const char *str, const char *instr);
SWITCH_DECLARE(switch_bool_t) switch_is_lan_addr(const char *ip);
/*! /*!
\brief Escape a string by prefixing a list of characters with an escape character \brief Escape a string by prefixing a list of characters with an escape character

View File

@ -40,6 +40,138 @@
SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load); SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load);
SWITCH_MODULE_DEFINITION(mod_commands, mod_commands_load, NULL, NULL); SWITCH_MODULE_DEFINITION(mod_commands, mod_commands_load, NULL, NULL);
typedef enum {
O_NONE,
O_EQ,
O_NE,
O_GT,
O_GE,
O_LT,
O_LE
} o_t;
SWITCH_STANDARD_API(qq_function)
{
int argc;
char *mydata = NULL, *argv[3];
char *expr;
char *a, *b;
float a_f = 0.0, b_f = 0.0;
o_t o = O_NONE;
int is_true = 0;
char *p;
if (!cmd) {
goto error;
}
mydata = strdup(cmd);
assert(mydata);
if ((p = strchr(mydata, '?'))) {
*p = ':';
} else {
goto error;
}
argc = switch_separate_string(mydata, ':', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc != 3) {
goto error;
}
a = argv[0];
if ((expr = strchr(a, '!'))) {
*expr++ = '\0';
if (*expr == '=') {
o = O_NE;
}
} else if ((expr = strchr(a, '>'))) {
if (*(expr+1) == '=') {
*expr++ = '\0';
o = O_GE;
} else {
o = O_GT;
}
} else if ((expr = strchr(a, '<'))) {
if (*(expr+1) == '=') {
*expr++ = '\0';
o = O_LE;
} else {
o = O_LT;
}
} else if ((expr = strchr(a, '='))) {
*expr++ = '\0';
if (*expr == '=') {
o = O_EQ;
}
}
if (o) {
char *s_a = NULL, *s_b = NULL;
int a_is_num, b_is_num;
*expr++ = '\0';
b = expr;
s_a = switch_strip_spaces(a);
s_b = switch_strip_spaces(b);
a_is_num = switch_is_number(s_a);
b_is_num = switch_is_number(s_b);
a_f = a_is_num ? atof(s_a) : (float) strlen(s_a);
b_f = b_is_num ? atof(s_b) : (float) strlen(s_b);
switch (o) {
case O_EQ:
if (!a_is_num && !b_is_num) {
is_true = !strcmp(s_a, s_b);
} else {
is_true = a_f == b_f;
}
break;
case O_NE:
is_true = a_f != b_f;
break;
case O_GT:
is_true = a_f > b_f;
break;
case O_GE:
is_true = a_f >= b_f;
break;
case O_LT:
is_true = a_f < b_f;
break;
case O_LE:
is_true = a_f <= b_f;
break;
default:
break;
}
switch_safe_free(s_a);
switch_safe_free(s_b);
stream->write_function(stream, "%s", is_true ? argv[1] : argv[2]);
goto ok;
}
error:
stream->write_function(stream, "!err!");
ok:
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(lan_addr_function)
{
stream->write_function(stream, "%s", switch_is_lan_addr(cmd) ? "yes" : "no");
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(status_function) SWITCH_STANDARD_API(status_function)
{ {
uint8_t html = 0; uint8_t html = 0;
@ -1502,6 +1634,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "sched_api", "Schedule an api command", sched_api_function, "[+]<time> <group_name> <command_string>"); SWITCH_ADD_API(commands_api_interface, "sched_api", "Schedule an api command", sched_api_function, "[+]<time> <group_name> <command_string>");
SWITCH_ADD_API(commands_api_interface, "sched_del", "Delete a Scheduled task", sched_del_function, "<task_id>|<group_id>"); SWITCH_ADD_API(commands_api_interface, "sched_del", "Delete a Scheduled task", sched_del_function, "<task_id>|<group_id>");
SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, "<command> <args>"); SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, "<command> <args>");
SWITCH_ADD_API(commands_api_interface, "is_lan_addr", "see if an ip is a lan addr", lan_addr_function, "<ip>");
SWITCH_ADD_API(commands_api_interface, "qq", "Eval a conditional", qq_function, "<expr> ? <true val> : <false val>");
/* indicate that the module should continue to be loaded */ /* indicate that the module should continue to be loaded */
return SWITCH_STATUS_NOUNLOAD; return SWITCH_STATUS_NOUNLOAD;

View File

@ -0,0 +1,6 @@
BASE=../../../..
LOCAL_SOURCES=expreval.c exprinit.c exprobj.c exprutil.c exprfunc.c exprmem.c exprpars.c exprval.c
LOCAL_OBJS=expreval.o exprinit.o exprobj.o exprutil.o exprfunc.o exprmem.o exprpars.o exprval.o
LOCAL_LIBADD=-lm
include $(BASE)/build/modmake.rules

View File

@ -0,0 +1,161 @@
/* A conio implementation for Mingw/Dev-C++.
*
* Written by:
* Hongli Lai <hongli@telekabel.nl>
* tkorrovi <tkorrovi@altavista.net> on 2002/02/26.
* Andrew Westcott <ajwestco@users.sourceforge.net>
*
* Offered for use in the public domain without any warranty.
*/
#ifndef _CONIO_H_
#define _CONIO_H_
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#define BLINK 0
typedef enum
{
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY,
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
} COLORS;
#define cgets _cgets
#define cprintf _cprintf
#define cputs _cputs
#define cscanf _cscanf
#define ScreenClear clrscr
/* blinkvideo */
void clreol (void);
void clrscr (void);
int _conio_gettext (int left, int top, int right, int bottom,
char *str);
/* _conio_kbhit */
void delline (void);
/* gettextinfo */
void gotoxy(int x, int y);
/*
highvideo
insline
intensevideo
lowvideo
movetext
normvideo
*/
void gotoxy(int x, int y);
void puttext (int left, int top, int right, int bottom, char *str);
// Screen Variables
/* ScreenCols
ScreenGetChar
ScreenGetCursor
ScreenMode
ScreenPutChar
ScreenPutString
ScreenRetrieve
ScreenRows
ScreenSetCursor
ScreenUpdate
ScreenUpdateLine
ScreenVisualBell
_set_screen_lines */
void _setcursortype (int type);
void textattr (int _attr);
void textbackground (int color);
void textcolor (int color);
/* textmode */
int wherex (void);
int wherey (void);
/* window */
/* The code below was part of Mingw's conio.h */
/*
* conio.h
*
* Low level console I/O functions. Pretty please try to use the ANSI
* standard ones if you are writing new code.
*
* This file is part of the Mingw32 package.
*
* Contributors:
* Created by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* $Revision: 1.4 $
* $Author: hongli $
* $Date: 2002/04/26 19:31:25 $
*
*/
char* _cgets (char*);
int _cprintf (const char*, ...);
int _cputs (const char*);
int _cscanf (char*, ...);
int _getch (void);
int _getche (void);
int _kbhit (void);
int _putch (int);
int _ungetch (int);
int getch (void);
int getche (void);
int kbhit (void);
int putch (int);
int ungetch (int);
#ifdef __cplusplus
}
#endif
#endif /* _CONIO_H_ */

View File

@ -0,0 +1,29 @@
/*
File: exprconf.h
Auth: Brian Allen Vanderburg II
Date: Thursday, October 20, 2005
Desc: Configuration for ExprEval
This file is part of ExprEval.
*/
#ifndef __BAVII_EXPRCONF_H
#define __BAVII_EXPRCONF_H
/*
Error checking level
0: Don't check any errors (don't use errno). Divide by 0
is avoided and the part that divides by 0 is 0. For example
'4+1/0' is 4.
1: Check math errors.
*/
#define EXPR_ERROR_LEVEL_NONE 0
#define EXPR_ERROR_LEVEL_CHECK 1
#ifndef EXPR_ERROR_LEVEL
#define EXPR_ERROR_LEVEL EXPR_ERROR_LEVEL_CHECK
#endif
#endif /* __BAVII_EXPRCONF_H */

View File

@ -0,0 +1,268 @@
/*
File: expreval.c
Auth: Brian Allen Vanderburg II
Date: Wednesday, April 30, 2003
Desc: Evaluation routines for the ExprEval library
This file is part of ExprEval.
*/
/* Includes */
#include "exprincl.h"
#include "exprpriv.h"
/* Defines for error checking */
#include <errno.h>
#if(EXPR_ERROR_LEVEL >= EXPR_ERROR_LEVEL_CHECK)
#define EXPR_RESET_ERR() errno = 0
#define EXPR_CHECK_ERR() if(errno) return EXPR_ERROR_OUTOFRANGE
#else
#define EXPR_RESET_ERR()
#define EXPR_CHECK_ERR()
#endif
/* This routine will evaluate an expression */
int exprEval(exprObj *obj, EXPRTYPE *val)
{
EXPRTYPE dummy;
if(val == NULL)
val = &dummy;
/* Make sure it was parsed successfully */
if(!obj->parsedbad && obj->parsedgood && obj->headnode)
{
/* Do NOT reset the break count. Let is accumulate
between calls until breaker function is called */
return exprEvalNode(obj, obj->headnode, 0, val);
}
else
return EXPR_ERROR_BADEXPR;
}
/* Evaluate a node */
int exprEvalNode(exprObj *obj, exprNode *nodes, int curnode, EXPRTYPE *val)
{
int err;
int pos;
EXPRTYPE d1, d2;
if(obj == NULL || nodes == NULL)
return EXPR_ERROR_NULLPOINTER;
/* Update n to point to correct node */
nodes += curnode;
/* Check breaker count */
if(obj->breakcur-- <= 0)
{
/* Reset count before returning */
obj->breakcur = obj->breakcount;
if(exprGetBreakResult(obj))
{
return EXPR_ERROR_BREAK;
}
}
switch(nodes->type)
{
case EXPR_NODETYPE_MULTI:
{
/* Multi for multiple expressions in one string */
for(pos = 0; pos < nodes->data.oper.nodecount; pos++)
{
err = exprEvalNode(obj, nodes->data.oper.nodes, pos, val);
if(err)
return err;
}
break;
}
case EXPR_NODETYPE_ADD:
{
/* Addition */
err = exprEvalNode(obj, nodes->data.oper.nodes, 0, &d1);
if(!err)
err = exprEvalNode(obj, nodes->data.oper.nodes, 1, &d2);
if(!err)
*val = d1 + d2;
else
return err;
break;
}
case EXPR_NODETYPE_SUBTRACT:
{
/* Subtraction */
err = exprEvalNode(obj, nodes->data.oper.nodes, 0, &d1);
if(!err)
err = exprEvalNode(obj, nodes->data.oper.nodes, 1, &d2);
if(!err)
*val = d1 - d2;
else
return err;
break;
}
case EXPR_NODETYPE_MULTIPLY:
{
/* Multiplication */
err = exprEvalNode(obj, nodes->data.oper.nodes, 0, &d1);
if(!err)
err = exprEvalNode(obj, nodes->data.oper.nodes, 1, &d2);
if(!err)
*val = d1 * d2;
else
return err;
break;
}
case EXPR_NODETYPE_DIVIDE:
{
/* Division */
err = exprEvalNode(obj, nodes->data.oper.nodes, 0, &d1);
if(!err)
err = exprEvalNode(obj, nodes->data.oper.nodes, 1, &d2);
if(!err)
{
if(d2 != 0.0)
*val = d1 / d2;
else
{
#if(EXPR_ERROR_LEVEL >= EXPR_ERROR_LEVEL_CHECK)
return EXPR_ERROR_DIVBYZERO;
#else
*val = 0.0;
return EXPR_ERROR_NOERROR;
#endif
}
}
else
return err;
break;
}
case EXPR_NODETYPE_EXPONENT:
{
/* Exponent */
err = exprEvalNode(obj, nodes->data.oper.nodes, 0, &d1);
if(!err)
err = exprEvalNode(obj, nodes->data.oper.nodes, 1, &d2);
if(!err)
{
EXPR_RESET_ERR();
*val = pow(d1, d2);
EXPR_CHECK_ERR();
}
else
return err;
break;
}
case EXPR_NODETYPE_NEGATE:
{
/* Negative value */
err = exprEvalNode(obj, nodes->data.oper.nodes, 0, &d1);
if(!err)
*val = -d1;
else
return err;
break;
}
case EXPR_NODETYPE_VALUE:
{
/* Directly access the value */
*val = nodes->data.value.value;
break;
}
case EXPR_NODETYPE_VARIABLE:
{
/* Directly access the variable or constant */
*val = *(nodes->data.variable.vaddr);
break;
}
case EXPR_NODETYPE_ASSIGN:
{
/* Evaluate assignment subnode */
err = exprEvalNode(obj, nodes->data.assign.node, 0, val);
if(!err)
{
/* Directly assign the variable */
*(nodes->data.assign.vaddr) = *val;
}
else
return err;
break;
}
case EXPR_NODETYPE_FUNCTION:
{
/* Evaluate the function */
if(nodes->data.function.fptr == NULL)
{
/* No function pointer means we are not using
function solvers. See if the function has a
type to solve directly. */
switch(nodes->data.function.type)
{
/* This is to keep the file from being too crowded.
See exprilfs.h for the definitions. */
#include "exprilfs.h"
default:
{
return EXPR_ERROR_UNKNOWN;
}
}
}
else
{
/* Call the correct function */
return (*(nodes->data.function.fptr))(obj,
nodes->data.function.nodes, nodes->data.function.nodecount,
nodes->data.function.refs, nodes->data.function.refcount, val);
}
break;
}
default:
{
/* Unknown node type */
return EXPR_ERROR_UNKNOWN;
}
}
return EXPR_ERROR_NOERROR;
}

View File

@ -0,0 +1,164 @@
# Microsoft Developer Studio Project File - Name="expreval" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=expreval - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "expreval.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "expreval.mak" CFG="expreval - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "expreval - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "expreval - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "expreval - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /Op /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "expreval - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /G6 /MTd /Za /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "expreval - Win32 Release"
# Name "expreval - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\expreval.c
# End Source File
# Begin Source File
SOURCE=.\exprfunc.c
# End Source File
# Begin Source File
SOURCE=.\exprinit.c
# End Source File
# Begin Source File
SOURCE=.\exprmem.c
# End Source File
# Begin Source File
SOURCE=.\exprobj.c
# End Source File
# Begin Source File
SOURCE=.\exprpars.c
# End Source File
# Begin Source File
SOURCE=.\exprutil.c
# End Source File
# Begin Source File
SOURCE=.\exprval.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\exprconf.h
# End Source File
# Begin Source File
SOURCE=.\expreval.h
# End Source File
# Begin Source File
SOURCE=.\exprilfs.h
# End Source File
# Begin Source File
SOURCE=.\exprincl.h
# End Source File
# Begin Source File
SOURCE=.\exprmem.h
# End Source File
# Begin Source File
SOURCE=.\exprpriv.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\expreval.html
# End Source File
# Begin Source File
SOURCE=.\exprtmpl.html
# End Source File
# Begin Source File
SOURCE=.\license.txt
# End Source File
# Begin Source File
SOURCE=.\readme.txt
# End Source File
# End Target
# End Project

View File

@ -0,0 +1,59 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "expreval"=.\expreval.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "imagegen"=.\imagegen\imagegen.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name expreval
End Project Dependency
}}}
###############################################################################
Project: "test"=.\test\test.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name expreval
End Project Dependency
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@ -0,0 +1,127 @@
/*
File: expreval.h
Auth: Brian Allen Vanderburg II
Date: Thursday, April 24, 2003
Desc: Main include file for ExprEval library
This file is part of ExprEval.
*/
/* Include once */
#ifndef __BAVII_EXPREVAL_H
#define __BAVII_EXPREVAL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Define type of data to use */
typedef double EXPRTYPE;
/* Defines for various things */
/* Max id size */
#define EXPR_MAXIDENTSIZE 255
/* Error values */
enum
{
EXPR_ERROR_UNKNOWN = -1, /* Unknown error */
EXPR_ERROR_NOERROR = 0, /* No Error */
EXPR_ERROR_MEMORY, /* Memory allocation failed */
EXPR_ERROR_NULLPOINTER, /* Null pointer passed to function */
EXPR_ERROR_NOTFOUND, /* Item not found in a list */
EXPR_ERROR_UNMATCHEDCOMMENT, /* Unmatched comment tags */
EXPR_ERROR_INVALIDCHAR, /* Invalid characters in expression */
EXPR_ERROR_ALREADYEXISTS, /* An item already called create */
EXPR_ERROR_ALREADYPARSEDBAD, /* Expression parsed already, but unsuccessfully. call free or clear */
EXPR_ERROR_ALREADYPARSEDGOOD, /* Expression parsed already, successfully, call free or clear */
EXPR_ERROR_EMPTYEXPR, /* Empty expression string passed to parse */
EXPR_ERROR_UNMATCHEDPAREN, /* Unmatched parenthesis */
EXPR_ERROR_SYNTAX, /* Syntax error in expression */
EXPR_ERROR_MISSINGSEMICOLON, /* Missing semicolon at end of expression */
EXPR_ERROR_BADIDENTIFIER, /* Identifier was to big or not formed right */
EXPR_ERROR_NOSUCHFUNCTION, /* Function does not exist in function list */
EXPR_ERROR_BADNUMBERARGUMENTS, /* Bad number of arguments in a function call */
EXPR_ERROR_BADEXPR, /* This is a bad expression to evaluate. It has not been parsed or has unsuccessfully */
EXPR_ERROR_UNABLETOASSIGN, /* Unable to do an assignment, maybe no variable list */
EXPR_ERROR_DIVBYZERO, /* Attempted a division by zero */
EXPR_ERROR_NOVARLIST, /* No variable list found but one is needed */
EXPR_ERROR_BREAK, /* Expression was broken by break function */
EXPR_ERROR_CONSTANTASSIGN, /* Assignment to a constant */
EXPR_ERROR_REFCONSTANT, /* Constant used as a reference parameter */
EXPR_ERROR_OUTOFRANGE, /* A bad value was passed to a function */
EXPR_ERROR_USER /* Custom errors should be larger than this */
};
/* Macros */
/* Forward declarations */
typedef struct _exprNode exprNode;
typedef struct _exprFuncList exprFuncList;
typedef struct _exprValList exprValList;
typedef struct _exprObj exprObj;
/* Function types */
typedef int (*exprFuncType)(exprObj *obj, exprNode *nodes, int nodecount, EXPRTYPE **refs, int refcount, EXPRTYPE *val);
typedef int (*exprBreakFuncType)(exprObj *obj);
/* Functions */
/* Version information function */
void exprGetVersion(int *major, int *minor);
/* Functions for function lists */
int exprFuncListCreate(exprFuncList **flist);
int exprFuncListAdd(exprFuncList *flist, char *name, exprFuncType ptr, int min, int max, int refmin, int refmax);
int exprFuncListFree(exprFuncList *flist);
int exprFuncListClear(exprFuncList *flist);
int exprFuncListInit(exprFuncList *flist);
/* Functions for value lists */
int exprValListCreate(exprValList **vlist);
int exprValListAdd(exprValList *vlist, char *name, EXPRTYPE val);
int exprValListSet(exprValList *vlist, char *name, EXPRTYPE val);
int exprValListGet(exprValList *vlist, char *name, EXPRTYPE *val);
int exprValListAddAddress(exprValList *vlist, char *name, EXPRTYPE *addr);
int exprValListGetAddress(exprValList *vlist, char *name, EXPRTYPE **addr);
void *exprValListGetNext(exprValList *vlist, char **name, EXPRTYPE *value, EXPRTYPE** addr, void *cookie);
int exprValListFree(exprValList *vlist);
int exprValListClear(exprValList *vlist);
int exprValListInit(exprValList *vlist);
/* Functions for expression objects */
int exprCreate(exprObj **obj, exprFuncList *flist, exprValList *vlist, exprValList *clist,
exprBreakFuncType breaker, void *userdata);
int exprFree(exprObj *obj);
int exprClear(exprObj *obj);
int exprParse(exprObj *obj, char *expr);
int exprEval(exprObj *obj, EXPRTYPE *val);
int exprEvalNode(exprObj *obj, exprNode *nodes, int curnode, EXPRTYPE *val);
exprFuncList *exprGetFuncList(exprObj *obj);
exprValList *exprGetVarList(exprObj *obj);
exprValList *exprGetConstList(exprObj *obj);
exprBreakFuncType exprGetBreakFunc(exprObj *obj);
int exprGetBreakResult(exprObj *obj);
void* exprGetUserData(exprObj *obj);
void exprSetUserData(exprObj *obj, void *userdata);
void exprSetBreakCount(exprObj *obj, int count);
void exprGetErrorPosition(exprObj *obj, int *start, int *end);
/* Other useful routines */
int exprValidIdent(char *name);
/* Name mangling */
#ifdef __cplusplus
}
#endif
#endif /* __BAVII_EXPREVAL_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,329 @@
/*
File: exprfunc.c
Auth: Brian Allen Vanderburg II
Date: Thursday, April 24, 2003
Desc: Expression function list routines
This file is part of ExprEval.
*/
/* Includes */
#include "exprincl.h"
#include "exprpriv.h"
#include "exprmem.h"
/* Internal functions */
static exprFunc *exprCreateFunc(char *name, exprFuncType ptr, int type, int min, int max, int refmin, int refmax);
static void exprFuncListFreeData(exprFunc *func);
/* This function creates the function list, */
int exprFuncListCreate(exprFuncList **flist)
{
exprFuncList *tmp;
if(flist == NULL)
return EXPR_ERROR_NULLPOINTER;
*flist = NULL; /* Set to NULL initially */
tmp = exprAllocMem(sizeof(exprFuncList));
if(tmp == NULL)
return EXPR_ERROR_MEMORY; /* Could not allocate memory */
/* Update pointer */
*flist = tmp;
return EXPR_ERROR_NOERROR;
}
/* Add a function to the list */
int exprFuncListAdd(exprFuncList *flist, char *name, exprFuncType ptr, int min, int max, int refmin, int refmax)
{
exprFunc *tmp;
exprFunc *cur;
int result;
if(flist == NULL)
return EXPR_ERROR_NULLPOINTER;
/* Make sure the name is valid */
if(!exprValidIdent(name))
return EXPR_ERROR_BADIDENTIFIER;
/* Fix values only if none are negative (negative values mean no limit) */
/* if both are neg, no min or max number of args */
/* if min is neg, max pos, no min number of args but a maximum */
/* if min is pos, max neg, there is a min number of args, but no max */
/* if both pos, then a min and max limit. We swap to make sure it works
right. I.E. Min of 3 and max of 2 would make function unusable */
if(min >= 0 && max >= 0)
{
if(min > max)
{
result = min;
min = max;
max = result;
}
}
if(refmin >= 0 && refmax >= 0)
{
if(refmin > refmax)
{
result = refmin;
refmin = max;
refmax = result;
}
}
if(flist->head == NULL)
{
/* Create the node right here */
tmp = exprCreateFunc(name, ptr, EXPR_NODETYPE_FUNCTION, min, max, refmin, refmax);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
flist->head = tmp;
return EXPR_ERROR_NOERROR;
}
/* See if it already exists */
cur = flist->head;
while(cur)
{
result = strcmp(name, cur->fname);
if(result == 0)
return EXPR_ERROR_ALREADYEXISTS;
cur = cur->next;
}
/* It did not exist, so add it at the head */
tmp = exprCreateFunc(name, ptr, EXPR_NODETYPE_FUNCTION, min, max, refmin, refmax);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
tmp->next = flist->head;
flist->head = tmp;
return EXPR_ERROR_NOERROR;
}
/* Add a function node type to the list
This works pretty much the same way, except the function
pointer is NULL and the node type specifies the function
to do. exprEvalNode handles this, instead of calling
a function solver. */
int exprFuncListAddType(exprFuncList *flist, char *name, int type, int min, int max, int refmin, int refmax)
{
exprFunc *tmp;
exprFunc *cur;
int result;
if(flist == NULL)
return EXPR_ERROR_NULLPOINTER;
/* Make sure the name is valid */
if(!exprValidIdent(name))
return EXPR_ERROR_BADIDENTIFIER;
/* Fix values only if none are negative (negative values mean no limit) */
/* if both are neg, no min or max number of args */
/* if min is neg, max pos, no min number of args but a maximum */
/* if min is pos, max neg, there is a min number of args, but no max */
/* if both pos, then a min and max limit. We swap to make sure it works
right. I.E. Min of 3 and max of 2 would make function unusable */
if(min >= 0 && max >= 0)
{
if(min > max)
{
result = min;
min = max;
max = result;
}
}
if(refmin >= 0 && refmax >= 0)
{
if(refmin > refmax)
{
result = refmin;
refmin = max;
refmax = result;
}
}
if(flist->head == NULL)
{
/* Create the node right here */
tmp = exprCreateFunc(name, NULL, type, min, max, refmin, refmax);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
flist->head = tmp;
return EXPR_ERROR_NOERROR;
}
/* See if it already exists */
cur = flist->head;
while(cur)
{
result = strcmp(name, cur->fname);
if(result == 0)
return EXPR_ERROR_ALREADYEXISTS;
cur = cur->next;
}
/* It did not exist, so add it at the head */
tmp = exprCreateFunc(name, NULL, type, min, max, refmin, refmax);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
tmp->next = flist->head;
flist->head = tmp;
return EXPR_ERROR_NOERROR;
}
/* Get the function from a list along with it's min an max data */
int exprFuncListGet(exprFuncList *flist, char *name, exprFuncType *ptr, int *type, int *min, int *max, int *refmin, int *refmax)
{
exprFunc *cur;
int result;
if(flist == NULL)
return EXPR_ERROR_NULLPOINTER;
if(name == NULL || name[0] == '\0')
return EXPR_ERROR_NOTFOUND;
/* Search for the item */
cur = flist->head;
while(cur)
{
result = strcmp(name, cur->fname);
if(result == 0)
{
/* We found it. */
*ptr = cur->fptr;
*min = cur->min;
*max = cur->max;
*refmin = cur->refmin;
*refmax = cur->refmax;
*type = cur->type;
/* return now */
return EXPR_ERROR_NOERROR;
}
cur = cur->next;
}
/* If we got here, we did not find the item in the list */
return EXPR_ERROR_NOTFOUND;
}
/* This routine will free the function list */
int exprFuncListFree(exprFuncList *flist)
{
/* Make sure it exists, if not it is not error */
if(flist == NULL)
return EXPR_ERROR_NOERROR;
/* Free the nodes */
exprFuncListFreeData(flist->head);
/* Free the container */
exprFreeMem(flist);
return EXPR_ERROR_NOERROR;
}
/* This routine will clear the function list */
int exprFuncListClear(exprFuncList *flist)
{
if(flist == NULL)
return EXPR_ERROR_NOERROR;
/* Free the nodes only */
if(flist->head)
{
exprFuncListFreeData(flist->head);
flist->head = NULL;
}
return EXPR_ERROR_NOERROR;
}
/* This routine will free any child nodes, and then free itself */
void exprFuncListFreeData(exprFunc *func)
{
exprFunc *next;
while(func)
{
/* Remember the next item */
next = func->next;
/* Free name */
exprFreeMem(func->fname);
/* Free ourself */
exprFreeMem(func);
func = next;
}
}
/* This routine will create the function object */
exprFunc *exprCreateFunc(char *name, exprFuncType ptr, int type, int min, int max, int refmin, int refmax)
{
exprFunc *tmp;
char *vtmp;
/* We already checked the name in exprFuncListAdd */
/* Create it */
tmp = exprAllocMem(sizeof(exprFunc));
if(tmp == NULL)
return NULL;
/* Allocate space for the name */
vtmp = exprAllocMem(strlen(name) + 1);
if(vtmp == NULL)
{
exprFreeMem(tmp);
return NULL;
}
/* Copy the data over */
strcpy(vtmp, name);
tmp->fname = vtmp;
tmp->fptr = ptr;
tmp->min = min;
tmp->max = max;
tmp->refmin = refmin;
tmp->refmax = refmax;
tmp->type = type;
return tmp;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,101 @@
/*
File: exprincl.h
Auth: Brian Allen Vanderburg II
Date: Thursday, April 24, 2003
Desc: Includes, macros, etc needed by this library
This file is part of ExprEval.
*/
#ifndef __BAVII_EXPRINCL_H
#define __BAVII_EXPRINCL_H
/* Includes and macros and whatnot for building the library */
/* Memory routines. memory.h for VC++, mem.h for BC++ */
#ifdef __TURBOC__
#include <mem.h>
#else
#include <memory.h>
#endif
/* Memory allocation */
#include <malloc.h>
/* String routines */
#include <string.h>
/* Character manipulation routines */
#include <ctype.h>
/* Standard routines */
#include <stdlib.h>
/* Math routines */
#include <math.h>
/* Time */
#include <time.h>
/* Math constants. VC++ does not seem to have these */
#ifndef M_E
#define M_E 2.7182818284590452354
#endif
#ifndef M_LOG2E
#define M_LOG2E 1.4426950408889634074
#endif
#ifndef M_LOG10E
#define M_LOG10E 0.43429448190325182765
#endif
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif
#ifndef M_LN10
#define M_LN10 2.30258509299404568402
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
#ifndef M_PI_4
#define M_PI_4 0.78539816339744830962
#endif
#ifndef M_1_PI
#define M_1_PI 0.31830988618379067154
#endif
#ifndef M_2_PI
#define M_2_PI 0.63661977236758134308
#endif
#ifndef M_1_SQRTPI
#define M_1_SQRTPI 0.56418958354776
#endif
#ifndef M_2_SQRTPI
#define M_2_SQRTPI 1.12837916709551257390
#endif
#ifndef M_SQRT2
#define M_SQRT2 1.41421356237309504880
#endif
#ifndef M_1_SQRT2
#define M_1_SQRT2 0.70710678118654752440
#endif
#endif /* __BAVII_EXPRINCL_H */

View File

@ -0,0 +1,115 @@
/*
File: exprinit.c
Auth: Brian Allen Vanderburg II
Date: Thursday, May 1, 2003
Desc: Extra functions and routines for ExprEval
This file is part of ExprEval.
*/
/* Include files */
#include "exprincl.h"
#include "exprpriv.h"
/* Macro for adding a function node type */
#define EXPR_ADDFUNC_TYPE(name, type, argmin, argmax, refmin, refmax) \
err = exprFuncListAddType(flist, name, type, argmin, argmax, refmin, refmax); \
if(err != EXPR_ERROR_NOERROR) \
return err;
/* Macro for adding a constant */
#define EXPR_ADDCONST(name, val) \
err = exprValListAdd(vlist, name, val); \
if(err != EXPR_ERROR_NOERROR) \
return err;
/* Call this function to initialize these functions into a function list */
int exprFuncListInit(exprFuncList *flist)
{
int err;
if(flist == NULL)
return EXPR_ERROR_NULLPOINTER;
EXPR_ADDFUNC_TYPE("abs", EXPR_NODEFUNC_ABS, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("mod", EXPR_NODEFUNC_MOD, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("ipart", EXPR_NODEFUNC_IPART, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("fpart", EXPR_NODEFUNC_FPART, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("min", EXPR_NODEFUNC_MIN, 1, -1, 0, 0);
EXPR_ADDFUNC_TYPE("max", EXPR_NODEFUNC_MAX, 1, -1, 0, 0);
EXPR_ADDFUNC_TYPE("pow", EXPR_NODEFUNC_POW, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("sqrt", EXPR_NODEFUNC_SQRT, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("sin", EXPR_NODEFUNC_SIN, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("sinh", EXPR_NODEFUNC_SINH, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("asin", EXPR_NODEFUNC_ASIN, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("cos", EXPR_NODEFUNC_COS, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("cosh", EXPR_NODEFUNC_COSH, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("acos", EXPR_NODEFUNC_ACOS, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("tan", EXPR_NODEFUNC_TAN, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("tanh", EXPR_NODEFUNC_TANH, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("atan", EXPR_NODEFUNC_ATAN, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("atan2", EXPR_NODEFUNC_ATAN2, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("log", EXPR_NODEFUNC_LOG, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("pow10", EXPR_NODEFUNC_POW10, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("ln", EXPR_NODEFUNC_LN, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("exp", EXPR_NODEFUNC_EXP, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("logn", EXPR_NODEFUNC_LOGN, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("ceil", EXPR_NODEFUNC_CEIL, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("floor", EXPR_NODEFUNC_FLOOR, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("rand", EXPR_NODEFUNC_RAND, 0, 0, 1, 1);
EXPR_ADDFUNC_TYPE("random", EXPR_NODEFUNC_RANDOM, 2, 2, 1, 1);
EXPR_ADDFUNC_TYPE("randomize", EXPR_NODEFUNC_RANDOMIZE, 0, 0, 1, 1);
EXPR_ADDFUNC_TYPE("deg", EXPR_NODEFUNC_DEG, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("rad", EXPR_NODEFUNC_RAD, 1, 1, 0, 0);
EXPR_ADDFUNC_TYPE("recttopolr", EXPR_NODEFUNC_RECTTOPOLR, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("recttopola", EXPR_NODEFUNC_RECTTOPOLA, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("poltorectx", EXPR_NODEFUNC_POLTORECTX, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("poltorecty", EXPR_NODEFUNC_POLTORECTY, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("if", EXPR_NODEFUNC_IF, 3, 3, 0, 0);
EXPR_ADDFUNC_TYPE("select", EXPR_NODEFUNC_SELECT, 3, 4, 0, 0);
EXPR_ADDFUNC_TYPE("equal", EXPR_NODEFUNC_EQUAL, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("above", EXPR_NODEFUNC_ABOVE, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("below", EXPR_NODEFUNC_BELOW, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("avg", EXPR_NODEFUNC_AVG, 1, -1, 0, 0);
EXPR_ADDFUNC_TYPE("clip", EXPR_NODEFUNC_CLIP, 3, 3, 0, 0);
EXPR_ADDFUNC_TYPE("clamp", EXPR_NODEFUNC_CLAMP, 3, 3, 0, 0);
EXPR_ADDFUNC_TYPE("pntchange", EXPR_NODEFUNC_PNTCHANGE, 5, 5, 0, 0);
EXPR_ADDFUNC_TYPE("poly", EXPR_NODEFUNC_POLY, 2, -1, 0, 0);
EXPR_ADDFUNC_TYPE("and", EXPR_NODEFUNC_AND, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("or", EXPR_NODEFUNC_OR, 2, 2, 0, 0);
EXPR_ADDFUNC_TYPE("not", EXPR_NODEFUNC_NOT, 1 ,1, 0, 0);
EXPR_ADDFUNC_TYPE("for", EXPR_NODEFUNC_FOR, 4, -1, 0, 0);
EXPR_ADDFUNC_TYPE("many", EXPR_NODEFUNC_MANY, 1, -1, 0, 0);
return EXPR_ERROR_NOERROR;
}
/* Call this function to initialize some constants into a value list */
int exprValListInit(exprValList *vlist)
{
int err;
if(vlist == NULL)
return EXPR_ERROR_NULLPOINTER;
EXPR_ADDCONST("M_E", M_E);
EXPR_ADDCONST("M_LOG2E", M_LOG2E);
EXPR_ADDCONST("M_LOG10E", M_LOG10E);
EXPR_ADDCONST("M_LN2", M_LN2);
EXPR_ADDCONST("M_LN10", M_LN10);
EXPR_ADDCONST("M_PI", M_PI);
EXPR_ADDCONST("M_PI_2", M_PI_2);
EXPR_ADDCONST("M_PI_4", M_PI_4);
EXPR_ADDCONST("M_1_PI", M_1_PI);
EXPR_ADDCONST("M_2_PI", M_2_PI);
EXPR_ADDCONST("M_1_SQRTPI", M_1_SQRTPI);
EXPR_ADDCONST("M_2_SQRTPI", M_2_SQRTPI);
EXPR_ADDCONST("M_SQRT2", M_SQRT2);
EXPR_ADDCONST("M_1_SQRT2", M_1_SQRT2);
return EXPR_ERROR_NOERROR;
}

View File

@ -0,0 +1,39 @@
/*
File: exprmem.c
Auth: Brian Allen Vanderburg II
Date: Wednesday, April 30, 2003
Desc: Memory functions for ExprEval
This file is part of ExprEval.
*/
/* Includes */
#include "exprincl.h"
#include "exprmem.h"
/* Allocate memory and zero it */
void* exprAllocMem(size_t size)
{
void *data = malloc(size);
if(data)
{
memset(data, 0, size);
}
return data;
}
/* Free memory */
void exprFreeMem(void *data)
{
if(data)
free(data);
}
/* Allocate a list of nodes */
exprNode *exprAllocNodes(size_t count)
{
return exprAllocMem(count * sizeof(exprNode));
}

View File

@ -0,0 +1,21 @@
/*
File: exprmem.h
Auth: Brian Allen Vanderburg II
Date: Wednesday, April 30, 2003
Desc: Memory functions for ExprEval
This file is part of ExprEval.
*/
#ifndef __BAVII_EXPRMEM_H
#define __BAVII_EXPRMEM_H
/* Needed for exprNode */
#include "exprpriv.h"
void* exprAllocMem(size_t size);
void exprFreeMem(void *data);
exprNode *exprAllocNodes(size_t count);
#endif /* __BAVII_EXPRMEM_H */

View File

@ -0,0 +1,237 @@
/*
File: exprobj.c
Auth: Brian Allen Vanderburg II
Date: Tuesday, April 29, 2003
Desc: Functions for the exprObj type
This file is part of ExprEval.
*/
/* Includes */
#include "exprincl.h"
#include "exprpriv.h"
#include "exprmem.h"
/* Internal functions */
static void exprFreeNodeData(exprNode *node);
/* Function to create an expression object */
int exprCreate(exprObj **obj, exprFuncList *flist, exprValList *vlist, exprValList *clist,
exprBreakFuncType breaker, void *userdata)
{
exprObj *tmp;
/* Allocate memory for the object */
tmp = exprAllocMem(sizeof(exprObj));
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
/* Assign data */
tmp->flist = flist;
tmp->vlist = vlist;
tmp->clist = clist;
tmp->breakerfunc = breaker;
tmp->userdata = userdata;
tmp->breakcount = 100000; /* Default breaker count setting */
tmp->breakcur = 0;
/* Update pointer */
*obj = tmp;
return EXPR_ERROR_NOERROR;
}
/* Free the expression */
int exprFree(exprObj *obj)
{
if(obj == NULL)
return EXPR_ERROR_NOERROR;
/* First free the node data */
exprFreeNodeData(obj->headnode);
exprFreeMem(obj->headnode);
/* Free ourself */
exprFreeMem(obj);
return EXPR_ERROR_NOERROR;
}
/* Clear expression, keep lists, etc */
int exprClear(exprObj *obj)
{
if(obj == NULL)
return EXPR_ERROR_NOERROR;
/* Free the node data only, keep function, variable, constant lists */
exprFreeNodeData(obj->headnode);
exprFreeMem(obj->headnode);
obj->headnode = NULL;
obj->parsedbad = 0;
obj->parsedgood = 0;
return EXPR_ERROR_NOERROR;
}
/* Get functions to get information about the expression object */
/* Get the function list */
exprFuncList *exprGetFuncList(exprObj *obj)
{
return (obj == NULL) ? NULL : obj->flist;
}
/* Get the variable list */
exprValList *exprGetVarList(exprObj *obj)
{
return (obj == NULL) ? NULL : obj->vlist;
}
/* Get the constant list */
exprValList *exprGetConstList(exprObj *obj)
{
return (obj == NULL) ? NULL : obj->clist;
}
/* Get the breaker function */
exprBreakFuncType exprGetBreakFunc(exprObj *obj)
{
return (obj == NULL) ? NULL : obj->breakerfunc;
}
/* Check for break status */
int exprGetBreakResult(exprObj *obj)
{
if(obj == NULL)
return 0;
if(obj->breakerfunc == NULL)
return 0;
return (*(obj->breakerfunc))(obj);
}
/* Get the user data */
void *exprGetUserData(exprObj *obj)
{
return (obj == NULL) ? NULL : obj->userdata;
}
/* Set functions to set certain data */
/* Set user data */
void exprSetUserData(exprObj *obj, void *userdata)
{
if(obj)
obj->userdata = userdata;
}
/* Set breaker count */
void exprSetBreakCount(exprObj *obj, int count)
{
if(obj)
{
/* If count is negative, make it positive */
if(count < 0)
count = -count;
obj->breakcount = count;
/* Make sure the current value is not bigger than count */
if(obj->breakcur > count)
obj->breakcur = count;
}
}
/* Get error position */
void exprGetErrorPosition(exprObj *obj, int *start, int *end)
{
if(obj)
{
if(start)
*start = obj->starterr;
if(end)
*end = obj->enderr;
}
}
/* This function will free a node's data */
static void exprFreeNodeData(exprNode *node)
{
int pos;
if(node == NULL)
return;
/* free data based on type */
switch(node->type)
{
case EXPR_NODETYPE_ADD:
case EXPR_NODETYPE_SUBTRACT:
case EXPR_NODETYPE_MULTIPLY:
case EXPR_NODETYPE_DIVIDE:
case EXPR_NODETYPE_EXPONENT:
case EXPR_NODETYPE_NEGATE:
case EXPR_NODETYPE_MULTI:
/* Free operation data */
if(node->data.oper.nodes)
{
for(pos = 0; pos < node->data.oper.nodecount; pos++)
exprFreeNodeData(&(node->data.oper.nodes[pos]));
exprFreeMem(node->data.oper.nodes);
}
break;
case EXPR_NODETYPE_VALUE:
/* Nothing to free for value */
break;
case EXPR_NODETYPE_VARIABLE:
/* Nothing to free for variable */
break;
case EXPR_NODETYPE_FUNCTION:
/* Free data of each subnode */
if(node->data.function.nodes)
{
for(pos = 0; pos < node->data.function.nodecount; pos++)
exprFreeNodeData(&(node->data.function.nodes[pos]));
/* Free the subnode array */
exprFreeMem(node->data.function.nodes);
}
/* Free reference variable list */
if(node->data.function.refs)
exprFreeMem(node->data.function.refs);
break;
case EXPR_NODETYPE_ASSIGN:
/* Free subnode data */
if(node->data.assign.node)
{
exprFreeNodeData(node->data.assign.node);
/* Free the subnode */
exprFreeMem(node->data.assign.node);
}
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
/*
File: exprpriv.h
Auth: Brian Allen Vanderburg II
Date: Tuesday, February 28, 2006
Desc: Private include file for ExprEval library
This file is part of ExprEval.
*/
/* Include once */
#ifndef __BAVII_EXPRPRIV_H
#define __BAVII_EXPRPRIV_H
/* Need some definitions, NULL, etc */
#include <stddef.h>
/* Include config and main expreval header */
#include "expreval.h"
#include "exprconf.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
Version number
*/
#define EXPR_VERSIONMAJOR 2
#define EXPR_VERSIONMINOR 7
/* Node types */
enum
{
EXPR_NODETYPE_UNKNOWN = 0,
EXPR_NODETYPE_MULTI,
EXPR_NODETYPE_ADD,
EXPR_NODETYPE_SUBTRACT,
EXPR_NODETYPE_MULTIPLY,
EXPR_NODETYPE_DIVIDE,
EXPR_NODETYPE_EXPONENT,
EXPR_NODETYPE_NEGATE,
EXPR_NODETYPE_VALUE,
EXPR_NODETYPE_VARIABLE,
EXPR_NODETYPE_ASSIGN,
EXPR_NODETYPE_FUNCTION
};
/* Functions can be evaluated directly in EXPREVAL. If fptr
is NULL, type is used to determine what the function is */
enum
{
EXPR_NODEFUNC_UNKNOWN = 0,
EXPR_NODEFUNC_ABS,
EXPR_NODEFUNC_MOD,
EXPR_NODEFUNC_IPART,
EXPR_NODEFUNC_FPART,
EXPR_NODEFUNC_MIN,
EXPR_NODEFUNC_MAX,
EXPR_NODEFUNC_POW,
EXPR_NODEFUNC_SQRT,
EXPR_NODEFUNC_SIN,
EXPR_NODEFUNC_SINH,
EXPR_NODEFUNC_ASIN,
EXPR_NODEFUNC_COS,
EXPR_NODEFUNC_COSH,
EXPR_NODEFUNC_ACOS,
EXPR_NODEFUNC_TAN,
EXPR_NODEFUNC_TANH,
EXPR_NODEFUNC_ATAN,
EXPR_NODEFUNC_ATAN2,
EXPR_NODEFUNC_LOG,
EXPR_NODEFUNC_POW10,
EXPR_NODEFUNC_LN,
EXPR_NODEFUNC_EXP,
EXPR_NODEFUNC_LOGN,
EXPR_NODEFUNC_CEIL,
EXPR_NODEFUNC_FLOOR,
EXPR_NODEFUNC_RAND,
EXPR_NODEFUNC_RANDOM,
EXPR_NODEFUNC_RANDOMIZE,
EXPR_NODEFUNC_DEG,
EXPR_NODEFUNC_RAD,
EXPR_NODEFUNC_RECTTOPOLR,
EXPR_NODEFUNC_RECTTOPOLA,
EXPR_NODEFUNC_POLTORECTX,
EXPR_NODEFUNC_POLTORECTY,
EXPR_NODEFUNC_IF,
EXPR_NODEFUNC_SELECT,
EXPR_NODEFUNC_EQUAL,
EXPR_NODEFUNC_ABOVE,
EXPR_NODEFUNC_BELOW,
EXPR_NODEFUNC_AVG,
EXPR_NODEFUNC_CLIP,
EXPR_NODEFUNC_CLAMP,
EXPR_NODEFUNC_PNTCHANGE,
EXPR_NODEFUNC_POLY,
EXPR_NODEFUNC_AND,
EXPR_NODEFUNC_OR,
EXPR_NODEFUNC_NOT,
EXPR_NODEFUNC_FOR,
EXPR_NODEFUNC_MANY
};
/* Forward declarations */
typedef struct _exprFunc exprFunc;
typedef struct _exprVal exprVal;
/* Expression object */
struct _exprObj
{
struct _exprFuncList *flist; /* Functions */
struct _exprValList *vlist; /* Variables */
struct _exprValList *clist; /* Constants */
struct _exprNode *headnode; /* Head parsed node */
exprBreakFuncType breakerfunc; /* Break function type */
void *userdata; /* User data, can be any 32 bit value */
int parsedgood; /* non-zero if successfully parsed */
int parsedbad; /* non-zero if parsed but unsuccessful */
int breakcount; /* how often to check the breaker function */
int breakcur; /* do we check the breaker function yet */
int starterr; /* start position of an error */
int enderr; /* end position of an error */
};
/* Object for a function */
struct _exprFunc
{
char *fname; /* Name of the function */
exprFuncType fptr; /* Function pointer */
int min, max; /* Min and max args for the function. */
int refmin, refmax; /* Min and max ref. variables for the function */
int type; /* Function node type. exprEvalNOde solves the function */
struct _exprFunc *next; /* For linked list */
};
/* Function list object */
struct _exprFuncList
{
struct _exprFunc *head;
};
/* Object for values */
struct _exprVal
{
char *vname; /* Name of the value */
EXPRTYPE vval; /* Value of the value */
EXPRTYPE *vptr; /* Pointer to a value. Used only if not NULL */
struct _exprVal *next; /* For linked list */
};
/* Value list */
struct _exprValList
{
struct _exprVal *head;
};
/* Expression node type */
struct _exprNode
{
int type; /* Node type */
union _data /* Union of info for various types */
{
struct _oper
{
struct _exprNode *nodes; /* Operation arguments */
int nodecount; /* Number of arguments */
} oper;
struct _variable
{
EXPRTYPE *vaddr; /* Used if EXPR_FAST_VAR_ACCESS defined */
} variable;
struct _value
{
EXPRTYPE value; /* Value if type is value */
} value;
struct _assign /* Assignment struct */
{
EXPRTYPE *vaddr; /* Used if EXPR_FAST_VAR_ACCESS defined */
struct _exprNode *node; /* Node to evaluate */
} assign;
struct _function
{
exprFuncType fptr; /* Function pointer */
struct _exprNode *nodes; /* Array of argument nodes */
int nodecount; /* Number of argument nodes */
EXPRTYPE **refs; /* Reference variables */
int refcount; /* Number of variable references (not a reference counter) */
int type; /* Type of function for exprEvalNode if fptr is NULL */
} function;
} data;
};
/* Functions for function lists */
int exprFuncListAddType(exprFuncList *flist, char *name, int type, int min, int max, int refmin, int refmax);
int exprFuncListGet(exprFuncList *flist, char *name, exprFuncType *ptr, int *type, int *min, int *max, int *refmin, int *refmax);
#ifdef __cplusplus
}
#endif
#endif /* __BAVII_EXPRPRIV_H */

View File

@ -0,0 +1,828 @@
<html>
<head>
<title>Expression Help</title>
<style type="text/css">
.valid {
color: #00AA00;
}
.invalid {
color: #FF0000;
}
.excomment {
color: #0000FF;
}
.container {
margin-top: 10px;
margin-bottom: 10px;
padding-left: 4px;
padding-right: 4px;
border-top: 1px solid #000000;
border-right: 1px solid #000000;
border-bottom: 1px solid #000000;
border-left: 1px solid #000000;
background-color: #BBBBBB;
}
body {
background-color: #AAAAAA;
}
</style>
</head>
<body>
<div align="center">
<h1>Expression Help</h1>
<hr>
</div>
<div align="left" class="container">
<h2>Contents</h2>
<h3>
<ul>
<li><a href="#Syntax">Expression Syntax</a></li>
<li><a href="#Operators">Order of Operators</a></li>
<li><a href="#InternalFunc">ExprEval Internal Functions</a></li>
<li><a href="#InternalConst">ExprEval Internal Constants</a></li>
<li><a href="#AppFunc">Application Internal Functions</a></li>
<li><a href="#AppConst">Application Internal Constants</a></li>
<li><a href="#AppVar">Application Internal Variables</a></li>
</ul>
</h3>
</div>
<div align="left" class="container">
<h2><a name="Syntax">Expression Syntax</a></h2>
<blockquote>
<p>Expressions have pretty much the same syntax as they
would have on paper, with the following exceptions:
<ul>
<li>Each expression must end with a semicolon. This
is because the expression string can actually
contain multiple expressions. The semicolon is
used to mark the end of the expression.<br>
<b>Examples:</b>
<ul>
<li>4*x+5;</li>
<li>y=5+2;g=4+6;</li>
<li>y=r*sin(a);x=r*cos(a);</li>
</ul>
</li>
<li>The asterisk '*' must be used to multiply.<br>
<b>Examples:</b>
<ul>
<li>y=5*6; <b class="valid">Valid</b></li>
<li>g=(x+1)*(x-1); <b class="valid">Valid</b></li>
<li>g=(x+1)(x-1); <b class="invalid">Invalid</b></li>
</ul>
</li>
</ul>
</p>
<p>More than one expression may be contained within an expression string.
As shown above, each expression must end with a semicolon, even if
only one expression is in the string. The value of an expression
string is the value of the last expression in the string.<br>
<b>Examlples:</b>
<ul>
<li>g=7; <b class="excomment">Value: 7</b></li>
<li>k=z+1; <b class="excomment">Value: z+1</b></li>
<li>r=4;k=6;o=9+r-k; <b class="excomment">Value: 9+r-k</b></li>
</ul>
</p>
<p>Some functions may take reference parameters. These parameters are
references to other variables. You can mix reference parameters
with normal parameters. The order of the normal parameters must
remain the same and the order of the reference parameters must
remain the same.<br>
<b>Examples:</b>
<ul>
<li>min(1,2,3,4,&mval); <b class="excomment">&mval is a reference to a variable mval</b></li>
<li>min(1,2,&mval,3,4); <b class="excomment">You may mix them inside like this.</b></li>
<li>min(1,2,(&mval),3,4); <b class="invalid">You may not nest reference parameters in any way</b></li>
</ul>
</p>
<p>Expressions may also be nested with parenthesis.<br>
<b>Examples:</b>
<ul>
<li>y=sin(x-cos(5+max(4,5,6*x)));</li>
<li>6+(5-2*(x+y));</li>
</ul>
</p>
<p>Expressions may also have whitespace characters and comments.
Whitespace characters such as newlines, linefeeds, carriage
returns, spaces, and tabs are ignored. Comments begin with
the pound sign '#' and end at the end of the line.<br>
<b>Example:</b>
<ul>
<pre>
#Set the x value
x = d * cos(r);
#Set the y value
y = d * sin(r);
</pre>
</ul>
</p>
<p>If a variable is used in an expression, but that variable does not exist,
it is considered zero. If it does exist then its value is used instead.
</p>
<p><b>Notice:</b> An expression can <b>NOT</b> assign to a constant and an
expression can <b>NOT</b> use a constant as a reference parameter.
</p>
</blockquote>
</div>
<div align="left" class="container">
<h2><a name="Operators">Order of operators.</a></h2>
<blockquote>
<p>The order of operators are processed correctly in ExprEval.
The parameters to functions may be evaluated out of order, depending
on the function itself.</p>
The following illustrates the order of operators:
<table align="center" border="1" width="75%">
<tr>
<td align="center"><b>Operator</b></td>
<td align="center"><b>Direction</b></td>
<td align="center"><b>Example</b></td>
</tr>
<tr>
<td>Functions and Parenthesis</td>
<td>N/A</td>
<td>(x + 5) * sin(d);</td>
</tr>
<tr>
<td>Negation</td>
<td>Right to Left</td>
<td>y = -2;</td>
</tr>
<tr>
<td>Exponents</td>
<td>Left to Right</td>
<td>y = x ^ 2;</td>
</tr>
<tr>
<td>Multiplication and Division</td>
<td>Left to Right</td>
<td>x * 5 / y;</td>
</tr>
<tr>
<td>Addition and Subtraction</td>
<td>Left to Right</td>
<td>4 + 5 - 3;</td>
</tr>
<tr>
<td>Assignment</td>
<td>Right to Left</td>
<td>x = y = z = 0;</td>
</tr>
</table>
</blockquote>
</div>
<div align="left" class="container">
<h2><a name="InternalFunc">ExprEval Internal Functions</a></h2>
<blockquote>
The following functions are provided with ExprEval:
<table align="center" border="1" width="75%">
<tr>
<td align="center"><b>Function</b></td>
<td align="center"><b>Min. Args</b></td>
<td align="center"><b>Max. Args</b></td>
<td align="center"><b>Min. Ref Args</b></td>
<td align="center"><b>Max. Ref Args</b></td>
<td align="center"><b>Result/Comment</b></td>
</tr>
<tr>
<td>abs(v)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>Absolute value of v.<br>
abs(-4.3) returns 4.3</td>
</tr>
<tr>
<td>mod(v,d)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Remainder of v/d.<br>
mod(5.2,2.5) return 0.2</td>
</tr>
<tr>
<td>ipart(v)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The integer part of v.<br>
ipart(3.2) returns 3</td>
</tr>
<tr>
<td>fpart(v)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The fractional part of v.<br>
fpart(3.2) returns 0.2</td>
</tr>
<tr>
<td>min(v,...)</td>
<td>1</td>
<td>None</td>
<td>0</td>
<td>0</td>
<td>The minimum number passed.<br>
min(3,2,-5,-2,7) returns -5</td>
</tr>
<tr>
<td>max(v,...)</td>
<td>1</td>
<td>None</td>
<td>0</td>
<td>0</td>
<td>The maximum number passed.<br>
max(3,2,-5,-2,7) returns 7</td>
</tr>
<tr>
<td>pow(a,b)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>The value a raised to the power b.<br>
pow(3.2,1.7) returns 3.2<sup>1.7</sup></td>
</tr>
<tr>
<td>sqrt(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The square root of a.</br>
sqrt(16) returns 4</td>
</tr>
<tr>
<td>sin(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The sine of a radians.<br>
sin(1.5) returns around 0.997</td>
</tr>
<tr>
<td>sinh(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The hyperbolic sine of a.<br>
sinh(1.5) returns around 2.129</td>
</tr>
<tr>
<td>asin(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The arc-sine of a in radians.<br>
asin(0.5) returns around 0.524</td>
</tr>
<tr>
<td>cos(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The cosine of a radians.<br>
cos(1.5) returns around 0.0707</td>
</tr>
<tr>
<td>cosh(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The hyperbolic cosine of a.</br>
cosh(1.5) returns around 2.352</td>
</tr>
<tr>
<td>acos(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The arc-cosine of a in radians.<br>
acos(0.5) returns around 1.047</td>
</tr>
<tr>
<td>tan(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The tangent of a radians.<br>
tan(1.5) returns around 14.101</td>
</tr>
<tr>
<td>tanh(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The hyperbolic tangent of a.</br>
tanh(1.5) returns around 0.905</td>
</tr>
<tr>
<td>atan(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The arc-tangent of a in radians.<br>
atan(0.3) returns about 0.291</td>
</tr>
<tr>
<td>atan2(y,x)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>The arc-tangent of y/x, with quadrant correction.<br>
atan2(4,3) returns about 0.927</td>
</tr>
<tr>
<td>log(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The base 10 logarithm of a.<br>
log(100) returns 2</td>
</tr>
<tr>
<td>pow10(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>10 raised to the power of a.<br>
pow10(2) returns 100</td>
</tr>
<tr>
<td>ln(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>The base e logarithm of a.<br>
ln(2.8) returns around 1.030</td>
</tr>
<tr>
<td>exp(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>e raised to the power of a.<br>
exp(2) returns around 7.389</td>
</tr>
<tr>
<td>logn(a,b)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>The base b logarithm of a.<br>
logn(16,2) returns 4</td>
</tr>
<tr>
<td>ceil(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>Rounds a up to the nearest integer.<br>
ceil(3.2) returns 4</td>
</tr>
<tr>
<td>floor(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>Rounds a down to the nearest integer.<br>
floor(3.2) returns 3</td>
</tr>
<tr>
<td>rand(&seed)</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>Returns a number between 0 up to but not including 1.</td>
</tr>
<tr>
<td>random(a,b,&seed)</td>
<td>2</td>
<td>2</td>
<td>1</td>
<td>1</td>
<td>Returns a number between a up to and including b.</td>
</tr>
<tr>
<td>randomize(&seed)</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>Seed the random number generator with a value
based on the current time.<br>
Return value is unknown</td>
</tr>
<tr>
<td>deg(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>Returns a radians converted to degrees.<br>
deg(3.14) returns around 179.909</td>
</tr>
<tr>
<td>rad(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>Returns a degrees converted to radians.<br>
rad(180) returns around 3.142</td>
</tr>
<tr>
<td>recttopolr(x,y)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns the polar radius of the rectangular co-ordinates.<br>
recttopolr(2,3) returns around 3.606</td>
</tr>
<tr>
<td>recttopola(x,y)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns the polar angle (0...2PI) in radians of the rectangular co-ordinates.<br>
recttopola(2,3) returns around 0.588</td>
</tr>
<tr>
<td>poltorectx(r,a)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns the x rectangular co-ordinate of the polar
co-ordinates.<br>
poltorectx(3,1.5) returns around 0.212</td>
</tr>
<tr>
<td>poltorecty(r,a)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns the y rectangular co-ordinate of the polar
co-ordinates.<br>
poltorecty(3,1.5) returns around 2.992</td>
</tr>
<tr>
<td>if(c,t,f)</td>
<td>3</td>
<td>3</td>
<td>0</td>
<td>0</td>
<td>Evaluates and returns t if c is not 0.0.
Else evaluates and returns f.<br>
if(0.1,2.1,3.9) returns 2.1</td>
</tr>
<tr>
<td>select(c,n,z[,p])</td>
<td>3</td>
<td>4</td>
<td>0</td>
<td>0</td>
<td>Returns n if c is less than 0.0. Returns z
if c is 0.0. If c is greater than 0.0 and only
three arguments were passed, returns z. If c
is greater than 0.0 and four arguments were passed,
return p.<br>
select(3,1,4,5) returns 5</td>
</tr>
<tr>
<td>equal(a,b)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns 1.0 if a is equal to b. Else returns 0.0<br>
equal(3,2) returns 0.0</td>
</tr>
<tr>
<td>above(a,b)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns 1.0 if a is above b. Else returns 0.0<br>
above(3,2) returns 1.0</td>
</tr>
<tr>
<td>below(a,b)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns 1.0 if a is below b. Else returns 0.0<br>
below(3,2) returns 0.0</td>
</tr>
<tr>
<td>avg(a,...)</td>
<td>1</td>
<td>None</td>
<td>0</td>
<td>0</td>
<td>Returns the average of the values passed.<br>
avg(3,3,6) returns 4</td>
</tr>
<tr>
<td>clip(v,min,max)</td>
<td>3</td>
<td>3</td>
<td>0</td>
<td>0</td>
<td>Clips v to the range from min to max. If v is less
than min, it returns min. If v is greater than
max it returns max. Otherwise it returns v.<br>
clip(3,1,2) returns 2</td>
</tr>
<tr>
<td>clamp(v,min,max)</td>
<td>3</td>
<td>3</td>
<td>0</td>
<td>0</td>
<td>Clamps v to the range from min to max, looping
if needed.<br>
clamp(8.2,1.3,4.7) returns 1.4</td>
</tr>
<tr>
<td>pntchange(side1old, side2old, side1new, side2new, oldpnt)</td>
<td>5</td>
<td>5</td>
<td>0</td>
<td>0</td>
<td>This is used to translate points from different
scale. It works no matter the orientation as long
as the sides are lined up correctly.<br>
pntchange(-1,1,0,480,-0.5) returns 120 (x example)<br>
pntchange(-1,1,480,0,-0.5) returns 360 (y example)</td>
</tr>
<tr>
<td>poly(x,c1,...)</td>
<td>2</td>
<td>None</td>
<td>0</td>
<td>0</td>
<td>This function calculates the polynomial. x is the value
to use in the polynomial. c1 and on are the coefficients.<br>
poly(4,6,9,3,1,4) returns 2168<br>
same as 6*4<sup>4</sup> + 9*4<sup>3</sup> + 3*4<sup>2</sup> + 1*4<sup>1</sup> + 4*4<sup>0</sup></td>
</tr>
<tr>
<td>and(a,b)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns 0.0 if either a or b are 0.0 Else returns 1.0<br>
and(2.1,0.0) returns 0.0</td>
</tr>
<tr>
<td>or(a,b)</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>Returns 0.0 if both a and b are 0.0 Else returns 1.0<br>
or(2.1,0.0) returns 1.0</td>
</tr>
<tr>
<td>not(a)</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>Returns 1.0 if a is 0.0 Else returns 0.0<br>
not(0.3) returns 0.0</td>
</tr>
<tr>
<td>for(init,test,inc,a1,...)</td>
<td>4</td>
<td>None</td>
<td>0</td>
<td>0</td>
<td>This function acts like a for loop in C. First init is
evaluated. Then test is evaluated. As long as the
test is not 0.0, the action statements (a1 to an) are
evaluated, the inc statement is evaluated, and the test
is evaluated again. The result is the result of the
final action statement.<br>
for(x=0,below(x,11),x=x+1,y=y+x) returns 55.0 (if y was
initially 0.0)</td>
</tr>
<tr>
<td>many(expr,...)</td>
<td>1</td>
<td>None</td>
<td>0</td>
<td>0</td>
<td>This function treats many subexpressions as a single object
(function). It is mainly for the 'for' function.<br>
for(many(j=5,k=1),above(j*k,0.001),many(j=j+5,k=k/2),0)</td>
</tr>
</table>
</blockquote>
</div>
<div align="left" class="container">
<h2><a name="InternalConst">ExprEval Internal Constants</a></h2>
<blockquote>
The following constants are provided with ExprEval:
<table align="center" border="1" width="75%">
<tr>
<td align="center"><b>Constant</b></td>
<td align="center"><b>Math Form</b></td>
<td align="center"><b>Value</b></td>
</tr>
<tr>
<td>M_E</td>
<td>e</td>
<td>2.7182818284590452354</td>
</tr>
<tr>
<td>M_LOG2E</td>
<td>log<sub>2</sub>(e)</td>
<td>1.4426950408889634074</td>
</tr>
<tr>
<td>M_LOG10E</td>
<td>log<sub>10</sub>(e)</td>
<td>0.43429448190325182765</td>
</tr>
<tr>
<td>M_LN2</td>
<td>ln(2)</td>
<td>0.69314718055994530942</td>
</tr>
<tr>
<td>M_LN10</td>
<td>ln(10)</td>
<td>2.30258509299404568402</td>
</tr>
<tr>
<td>M_PI</td>
<td>&#960;</td>
<td>3.14159265358979323846</td>
</tr>
<tr>
<td>M_PI_2</td>
<td>&#960;/2</td>
<td>1.57079632679489661923</td>
</tr>
<tr>
<td>M_PI_4</td>
<td>&#960;/4</td>
<td>0.78539816339744830962</td>
</tr>
<tr>
<td>M_1_PI</td>
<td>1/&#960;</td>
<td>0.31830988618379067154</td>
</tr>
<tr>
<td>M_2_PI</td>
<td>2/&#960;</td>
<td>0.63661977236758134308</td>
</tr>
<tr>
<td>M_1_SQRTPI</td>
<td>1/&#8730;(&#960;)</td>
<td>0.56418958354776</td>
</tr>
<tr>
<td>M_2_SQRTPI</td>
<td>2/&#8730;(&#960;)</td>
<td>1.12837916709551257390</td>
</tr>
<tr>
<td>M_SQRT2</td>
<td>&#8730;(2)</td>
<td>1.41421356237309504880</td>
</tr>
<tr>
<td>M_1_SQRT2</td>
<td>1/&#8730;(2)</td>
<td>0.70710678118654752440</td>
</tr>
</table>
</blockquote>
</div>
<div align="left" class="container">
<h2><a name="AppFunc">Application Internal Functions</a></h2>
<blockquote>
Application defined expression functions go here.
<table align="center" border="1" width="75%">
<tr>
<td align="center"><b>Function</b></td>
<td align="center"><b>Min. Args</b></td>
<td align="center"><b>Max. Args</b></td>
<td align="center"><b>Min. Ref Args</b></td>
<td align="center"><b>Max. Ref Args</b></td>
<td align="center"><b>Result/Comment</b></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</blockquote>
</div>
<div align="left" class="container">
<h2><a name="AppConst">Application Internal Constants</a></h2>
<blockquote>
Application defined expression constants go here.
<table align="center" border="1" width="75%">
<tr>
<td align="center"><b>Constant</b></td>
<td align="center"><b>Math Form</b></td>
<td align="center"><b>Value</b></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</blockquote>
</div>
<div align="left" class="container">
<h2><a name="AppVar">Application Internal Variables</a></h2>
<blockquote>
Application defined expression variables go here.
<table align="center" border="1" width="75%">
<tr>
<td align="center"><b>Variable</b></td>
<td align="center"><b>Math Form</b></td>
<td align="center"><b>Value</b></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</blockquote>
</div>
</body>
</html>

View File

@ -0,0 +1,43 @@
/*
File: exprutil.c
Auth: Brian Allen Vanderburg II
Date: Monday, April 28, 2003
Desc: Utility functions for use by this library
This file is part of ExprEval.
*/
/* Include files */
#include "exprincl.h"
#include "exprpriv.h"
/* Return the version number */
void exprGetVersion(int *major, int *minor)
{
*major = EXPR_VERSIONMAJOR;
*minor = EXPR_VERSIONMINOR;
}
/* This utility function determines if an identifier is valid */
int exprValidIdent(char *name)
{
if(name == NULL) /* Null string */
return 0;
/* First must be letter or underscore */
if(isalpha(*name) || *name == '_')
name++; /* Point to next letter */
else
return 0; /* Not letter or underscore, maybe empty*/
/* others can be letter, number, or underscore */
while(isalnum(*name) || *name == '_')
name++;
/* When the while breaks out, we should be at the end */
return (*name == '\0') ? 1 : 0;
}

View File

@ -0,0 +1,395 @@
/*
File: exprval.c
Auth: Brian Allen Vanderburg II
Date: Thursday, April 24, 2003
Desc: Value lists for variables and constants
This file is part of ExprEval.
*/
/* Includes */
#include "exprincl.h"
#include "exprpriv.h"
#include "exprmem.h"
/* Internal functions */
static exprVal *exprCreateVal(char *name, EXPRTYPE val, EXPRTYPE *addr);
static void exprValListFreeData(exprVal *val);
static void exprValListResetData(exprVal *val);
/* This function creates the value list, */
int exprValListCreate(exprValList **vlist)
{
exprValList *tmp;
if(vlist == NULL)
return EXPR_ERROR_NULLPOINTER;
*vlist = NULL; /* Set to NULL initially */
tmp = exprAllocMem(sizeof(exprValList));
if(tmp == NULL)
return EXPR_ERROR_MEMORY; /* Could not allocate memory */
/* Update pointer */
*vlist = tmp;
return EXPR_ERROR_NOERROR;
}
/* Add a value to the list */
int exprValListAdd(exprValList *vlist, char *name, EXPRTYPE val)
{
exprVal *tmp;
exprVal *cur;
int result;
if(vlist == NULL)
return EXPR_ERROR_NULLPOINTER;
/* Make sure the name is valid */
if(!exprValidIdent(name))
return EXPR_ERROR_BADIDENTIFIER;
if(vlist->head == NULL)
{
/* Create the node right here */
tmp = exprCreateVal(name, val, NULL);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
vlist->head = tmp;
return EXPR_ERROR_NOERROR;
}
/* See if already exists */
cur = vlist->head;
while(cur)
{
result = strcmp(name, cur->vname);
if(result == 0)
return EXPR_ERROR_ALREADYEXISTS;
cur = cur->next;
}
/* We did not find it, create it and add it to the beginning */
tmp = exprCreateVal(name, val, NULL);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
tmp->next = vlist->head;
vlist->head = tmp;
return EXPR_ERROR_NOERROR;
}
/* Set a value in the list */
int exprValListSet(exprValList *vlist, char *name, EXPRTYPE val)
{
exprVal *cur;
int result;
if(vlist == NULL)
return EXPR_ERROR_NULLPOINTER;
if(name == NULL || name[0] == '\0')
return EXPR_ERROR_NOTFOUND;
/* Find and set it */
cur = vlist->head;
while(cur)
{
result = strcmp(name, cur->vname);
if(result == 0)
{
if(cur->vptr)
*(cur->vptr) = val;
else
cur->vval = val;
return EXPR_ERROR_NOERROR;
}
cur = cur->next;
}
return EXPR_ERROR_NOTFOUND;
}
/* Get the value from a list */
int exprValListGet(exprValList *vlist, char *name, EXPRTYPE *val)
{
exprVal *cur;
int result;
if(vlist == NULL)
return EXPR_ERROR_NULLPOINTER;
if(name == NULL || name[0] == '\0')
return EXPR_ERROR_NOTFOUND;
/* Search for the item */
cur = vlist->head;
while(cur)
{
result = strcmp(name, cur->vname);
if(result == 0)
{
/* We found it. */
if(cur->vptr)
*val = *(cur->vptr);
else
*val = cur->vval;
/* return now */
return EXPR_ERROR_NOERROR;
}
cur = cur->next;
}
/* If we got here, we did not find the item in the list */
return EXPR_ERROR_NOTFOUND;
}
/* Add an address to the list */
int exprValListAddAddress(exprValList *vlist, char *name, EXPRTYPE *addr)
{
exprVal *tmp;
exprVal *cur;
int result;
if(vlist == NULL)
return EXPR_ERROR_NULLPOINTER;
/* Make sure the name is valid */
if(!exprValidIdent(name))
return EXPR_ERROR_BADIDENTIFIER;
if(vlist->head == NULL)
{
/* Create the node right here */
tmp = exprCreateVal(name, (EXPRTYPE)0.0, addr);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
vlist->head = tmp;
return EXPR_ERROR_NOERROR;
}
/* See if it already exists */
cur = vlist->head;
while(cur)
{
result = strcmp(name, cur->vname);
if(result == 0)
return EXPR_ERROR_ALREADYEXISTS;
cur = cur->next;
}
/* Add it to the list */
tmp = exprCreateVal(name, (EXPRTYPE)0.0, addr);
if(tmp == NULL)
return EXPR_ERROR_MEMORY;
tmp->next = vlist->head;
vlist->head = tmp;
return EXPR_ERROR_NOERROR;
}
/* Get memory address of a variable value in a value list */
int exprValListGetAddress(exprValList *vlist, char *name, EXPRTYPE **addr)
{
exprVal *cur;
int result;
/* Not found yet */
*addr = NULL;
if(vlist == NULL || addr == NULL)
return EXPR_ERROR_NULLPOINTER;
if(name == NULL || name[0] == '\0')
return EXPR_ERROR_NOTFOUND;
/* Search for the item */
cur = vlist->head;
while(cur)
{
result = strcmp(name, cur->vname);
if(result == 0)
{
/* We found it. */
if(cur->vptr)
*addr = cur->vptr;
else
*addr = &(cur->vval);
/* return now */
return EXPR_ERROR_NOERROR;
}
cur = cur->next;
}
/* If we got here, we did not find it in the list */
return EXPR_ERROR_NOTFOUND;
}
/* This function is used to enumerate the values in a value list */
void *exprValListGetNext(exprValList *vlist, char **name, EXPRTYPE *value, EXPRTYPE** addr, void *cookie)
{
exprVal *cur;
if(vlist == NULL)
return NULL;
/* Get the current item */
cur = (exprVal*)cookie;
/* Find the next item */
if(cur == NULL)
cur = vlist->head;
else
cur = cur->next;
/* Set up the data */
if(cur)
{
if(name)
*name = cur->vname;
if(value)
{
if(cur->vptr)
*value = *(cur->vptr);
else
*value = cur->vval;
}
if(addr)
{
if(cur->vptr)
*addr = cur->vptr;
else
*addr = &(cur->vval);
}
}
/* If there was no value, return NULL, otherwise, return the item */
return (void*)cur;
}
/* This routine will free the value list */
int exprValListFree(exprValList *vlist)
{
/* Make sure it exists, if not it is not error */
if(vlist == NULL)
return EXPR_ERROR_NOERROR;
/* Free the nodes */
exprValListFreeData(vlist->head);
/* Freethe container */
exprFreeMem(vlist);
return EXPR_ERROR_NOERROR;
}
/* This routine will reset the value list to 0.0 */
int exprValListClear(exprValList *vlist)
{
if(vlist == NULL)
return EXPR_ERROR_NOERROR;
exprValListResetData(vlist->head);
return EXPR_ERROR_NOERROR;
}
/* This routine will free any child nodes, and then free itself */
static void exprValListFreeData(exprVal *val)
{
exprVal *next;
while(val)
{
/* Remember the next */
next = val->next;
/* Free name */
exprFreeMem(val->vname);
/* Free ourself */
exprFreeMem(val);
val = next;
}
}
/* This routine will reset variables to 0.0 */
static void exprValListResetData(exprVal *val)
{
while(val)
{
/* Reset data */
if(val->vptr)
*(val->vptr) = 0.0;
val->vval = 0.0;
val = val->next;
}
}
/* This routine will create the value object */
static exprVal *exprCreateVal(char *name, EXPRTYPE val, EXPRTYPE *addr)
{
exprVal *tmp;
char *vtmp;
/* Name already tested in exprValListAdd */
/* Create it */
tmp = exprAllocMem(sizeof(exprVal));
if(tmp == NULL)
return NULL;
/* Allocate space for the name */
vtmp = exprAllocMem(strlen(name) + 1);
if(vtmp == NULL)
{
exprFreeMem(tmp);
return NULL;
}
/* Copy the data over */
strcpy(vtmp, name);
tmp->vname = vtmp;
tmp->vval = val;
tmp->vptr = addr;
return tmp;
}

View File

@ -0,0 +1,21 @@
ExprEval - Expression Evaluation Library
Version 2.0
Copyright (C) 2004 Brian Allen Vanderburg II
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -0,0 +1,198 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthmct@yahoo.com>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthmct@yahoo.com>
*
* mod_expr.c -- Framework Demo Module
*
*/
#include <switch.h>
#include "expreval.h"
/* Breaker function to break out of long expression functions
such as the 'for' function */
int breaker(exprObj *o)
{
/* Return nonzero to break out */
return -1;
}
SWITCH_STANDARD_API(expr_function)
{
exprObj *e = NULL;
exprFuncList *f = NULL;
exprValList *v = NULL;
exprValList *c = NULL;
EXPRTYPE last_expr;
const char *expr;
int err;
char val[512] = "", *p;
char *m_cmd = NULL;
size_t len = strlen(cmd) + 3;
m_cmd = malloc(len);
assert(m_cmd);
switch_copy_string(m_cmd, cmd, len);
for (p = m_cmd; p && *p; p++) {
if (*p == '|') {
*p = ';';
}
}
p = m_cmd + (strlen(m_cmd) - 1);
if (*p != ';') {
p++;
*p = ';';
p++;
*p = '\0';
}
expr = m_cmd;
/* Create function list */
err = exprFuncListCreate(&f);
if(err != EXPR_ERROR_NOERROR)
goto error;
/* Init function list with internal functions */
err = exprFuncListInit(f);
if(err != EXPR_ERROR_NOERROR)
goto error;
/* Add custom function */
//err = exprFuncListAdd(f, my_func, "myfunc", 1, 1, 1, 1);
//if(err != EXPR_ERROR_NOERROR)
//goto error;
/* Create constant list */
err = exprValListCreate(&c);
if(err != EXPR_ERROR_NOERROR)
goto error;
/* Init constant list with internal constants */
err = exprValListInit(c);
if(err != EXPR_ERROR_NOERROR)
goto error;
/* Create variable list */
err = exprValListCreate(&v);
if(err != EXPR_ERROR_NOERROR)
goto error;
/* Create expression object */
err = exprCreate(&e, f, v, c, breaker, NULL);
if(err != EXPR_ERROR_NOERROR)
goto error;
/* Parse expression */
err = exprParse(e, (char *)expr);
printf("WTF %s\n", expr);
if(err != EXPR_ERROR_NOERROR)
goto error;
/* Enable soft errors */
//exprSetSoftErrors(e, 1);
do {
err = exprEval(e, &last_expr);
} while (err);
snprintf(val, sizeof(val), "%0.10f", last_expr);
for (p = (val + strlen(val) - 1); p != val; p--) {
if (*p != '0') {
*(p+1) = '\0';
break;
}
}
p = val + strlen(val) - 1;
if (*p == '.') {
*p = '\0';
}
stream->write_function(stream, "%s", val);
goto done;
error:
/* Alert user of error */
stream->write_function(stream, "!err!");
done:
/* Do cleanup */
if(e) {
exprFree(e);
}
if(f) {
exprFuncListFree(f);
}
if(v) {
exprValListFree(v);
}
if(c) {
exprValListFree(c);
}
switch_safe_free(m_cmd);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_expr_load);
SWITCH_MODULE_DEFINITION(mod_expr, mod_expr_load, NULL, NULL);
SWITCH_MODULE_LOAD_FUNCTION(mod_expr_load)
{
switch_api_interface_t *commands_api_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_API(commands_api_interface, "expr", "Eval an expession", expr_function, "<expr>");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:nil
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
*/

View File

@ -0,0 +1,170 @@
ExprEval - A C/C++ based expression evaluation library
Written by: Brian Allen Vanderburg II
Licensed under the ExprEval License
------------------------------------------------------
ExprEval is a mostly a C based expression evaluation
library. The only C++ part is the C++ Wrapper which
encapsulates the complexity of the library usage.
ExprEval supports the parsing of multiple expressions
in a single expression string. Each sub-expression
must end with a semicolon. It also supports the use
of variables, constants, and functions. Functions
can take multiple arguments. These arguments can
also be expressions.
ExprEval is very fast. It first parses the expression
string into a tree of actions to take. After it has
been parsed, an expression can be evaluated many times
over an over.
Functions, variables, and constants are stored in
their own seperate lists. This makes is where the
lists can be shared among multiple expression objects.
A function list can add all the functions needed, and
then be added to each expression object, instead of
added each needed function to each object. The same
goes for constant lists. Variable lists make it where
one expression can depend on a variable set in another.
Saturday, July 1, 2006
----------------------
Version 2.6
* Added a new value list function 'exprValListGetNext' that can be used to
enumerate the items in a value list. Any of the items not needed (name,
value, or address) can be NULL. For example:
char *name;
EXPRTYPE val;
void *cookie;
cookie = exprValListGetNext(vlist, &name, &value, NULL, NULL);
while(cookie)
{
/* Do something with name and value */
cookie = exprValListGetNext(vlist, &name, &value, NULL, cookie);
}
You must make sure not to actually edit the returned name, because it is a
pointer into the value list to the name. This can also be used to have one
value list store globals. Global variables can be added to a value list, then
additional lists can be created, and before any variables are added
or the expression is parsed, the global list can be enumerated for name and
address and the exprValListAddAddress can be used to add them. This way,
expressions can have their own private list, but some variables may be shared
on each expression through the global list. This is useful especially if the
globals are not known at compile time, but can be adjusted by the user.
For example:
exprValList *globals;
exprValList *v1;
exprValList *v2;
char *name;
EXPRTYPE *addr;
void *cookie;
exprValListCreate(&globals);
/* Add variables to the list, perhaps read from a user file or something */
exprValListCreate(&v1);
cookie = exprValListGetNext(globals, &name, NULL, &addr, NULL);
while(cookie)
{
exprValListAddAddress(v1, name, addr);
cookie = exprValListGetNext(globals, &name, NULL, &addr, cookie);
}
Friday, June 30, 2006
---------------------
Version 2.5
* Added a new value list function 'exprValListAddAddress'. This function adds
a named value to the list, but uses the addresss of a stack variable. The
stack variable is then used to set/get the value instead of the internal list
value. You must ensure that the stack variable exists as long as it is used
by the expression. This can permit, for example, a value name to be shared
with two different value lists like such:
EXPRTYPE global_value;
exprValListAddAddress(vlist, "global", &global_value);
exprValListAddAddress(vlist2, "global", &global_value);
Like this, the value can be directly accessed by the application, and each
value list will share it. This can also be used to replace code from this:
EXPRTYPE *a;
exprValListAdd(vlist, "var", 0.0);
exprValListGetAddress(vlist, "var", &a);
To look like this:
EXPRTYPE a;
exprValListAddAddress(vlist, "var", &a);
* Added a value list function exprValListSet to set the value of a variable
(using the slow search method). This is because the add functions now return
and error if the item (function/value) already exists instead of setting the
value of the item. You can still use the fast direct access method.
* Changed internal lists for function and value lists from binary trees to
linked lists.
Thursday, May 4, 2006
---------------------
Version 2.0
* All internal functions are evaluated directly in the exprEvalNode call.
This gives some speed increase.
* Removed parameter and reference count macros as well as functin creation
macro. Parameter and reference count information can be set when adding
a function solver.
* Removed exprMsgFuncType, since it is unused by the library.
* Changed much of the internal names from one-letter variable names to
more meaningful names.
Thursday, December 1, 2005
--------------------------
Version 1.8
* Added support for the ^ operator to raise to a power.
The pow function can still be used.
* Moved basic math code (add,subtract,multiply,divide,negate,exponent)
and multiple expression support from function solvers to the exprEvalNode
function.
Tuesday, November 22, 2005
--------------------------
I still haven't been keeping up with history much.
* Removed < and > as comments. Instead use # as a
comment to the end of the line
* Added function exprGetErrorPosition to get start and
end position of parse error.
Monday, May 3, 2004: Version 1.0
---------------------------------
This is a pretty bad time to start the history part since
ExprEval is pretty much up and running and very operational.
* Added macro EXPR_MAJORVERSION
* Added macro EXPR_MINORVERSION
* Added function exprGetVersion
* Added macro to make declaring functions easy:
EXPR_FUNCTIONSOLVER(func_name)
* Added support for passing variable references to functions
with the ampersand. Example: minmax(1,2,3,&min,&max)
* Added macros for reference support:
EXPR_REQUIREREFCOUNT
EXPR_REQUIREREFCOUNTMIN
EXPR_REQUIREREFCOUNTMAX
EXPR_REQUIREREFCOUNTRANGE
* Added feature to disable assigning to a variable with the
same name as a constant.
* Added feature to enable applications to change the value of
a constant while the expression can not. You must add
any constants to the constant list BEFORE you parse the
expression.

View File

@ -1374,9 +1374,20 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
while(*e == ' ') { while(*e == ' ') {
*e-- = '\0'; *e-- = '\0';
} }
if ((e = strchr(vval, ')'))) { e = vval;
*e = '\0'; br = 1;
while(e && *e) {
if (*e == '(') {
br++;
} else if (br > 1 && *e == ')') {
br--;
} else if (br == 1 && *e == ')') {
*e = '\0';
break;
}
e++;
} }
vtype = 2; vtype = 2;
} }
@ -1398,7 +1409,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
if (stream.data) { if (stream.data) {
char *expanded_vname = NULL; char *expanded_vname = NULL;
if ((expanded_vname = switch_channel_expand_variables(channel, (char *)vname)) == vname) { if ((expanded_vname = switch_channel_expand_variables(channel, (char *)vname)) == vname) {
expanded_vname = NULL; expanded_vname = NULL;
} else { } else {
@ -1462,6 +1473,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
} }
} }
free(indup); free(indup);
return data; return data;
} }

View File

@ -197,6 +197,67 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(char *to, char *from, char *he
return SWITCH_TRUE; return SWITCH_TRUE;
} }
SWITCH_DECLARE(switch_bool_t) switch_is_lan_addr(const char *ip)
{
return (
strncmp(ip, "10.", 3) &&
strncmp(ip, "192.168.", 8) &&
strncmp(ip, "127.", 4) &&
strncmp(ip, "255.", 4) &&
strncmp(ip, "0.", 2) &&
strncmp(ip, "1.", 2) &&
strncmp(ip, "2.", 2) &&
strncmp(ip, "172.16.", 7) &&
strncmp(ip, "172.17.", 7) &&
strncmp(ip, "172.18.", 7) &&
strncmp(ip, "172.19.", 7) &&
strncmp(ip, "172.2", 5) &&
strncmp(ip, "172.30.", 7) &&
strncmp(ip, "172.31.", 7) &&
strncmp(ip, "192.0.2.", 8) &&
strncmp(ip, "169.254.", 8)
) ? SWITCH_FALSE : SWITCH_TRUE;
}
SWITCH_DECLARE(char *) switch_strip_spaces(const char *str)
{
const char *sp = str;
char *p, *s = NULL;
while(sp && *sp && *sp == ' ') {
sp++;
}
s = strdup(sp);
p = s + (strlen(s) - 1);
while(*p == ' ') {
*p-- = '\0';
}
return s;
}
SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str)
{
const char *p;
switch_bool_t r = SWITCH_TRUE;
for (p = str; p && *p; p++) {
if (!(*p == '.' || (*p > 47 && *p < 58))) {
r = SWITCH_FALSE;
break;
}
}
return r;
}
SWITCH_DECLARE(const char *) switch_stristr(const char *str, const char *instr) SWITCH_DECLARE(const char *) switch_stristr(const char *str, const char *instr)
{ {
@ -536,8 +597,7 @@ SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char
int argc; int argc;
char *ptr; char *ptr;
int quot = 0; int quot = 0;
char qc = '"'; char qc = '\'';
char *e;
int x; int x;
if (!buf || !array || !arraylen) { if (!buf || !array || !arraylen) {
@ -568,13 +628,21 @@ SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char
array[argc++] = ptr; array[argc++] = ptr;
} }
/* strip quotes */ /* strip quotes and leading / trailing spaces */
for (x = 0; x < argc; x++) { for (x = 0; x < argc; x++) {
if (*(array[x]) == qc) { char *p;
while(*(array[x]) == ' ') {
(array[x])++; (array[x])++;
if ((e = strchr(array[x], qc))) { }
*e = '\0'; p = array[x];
} while((p = strchr(array[x], qc))) {
memmove(p, p+1, strlen(p));
p++;
}
p = array[x] + (strlen(array[x]) - 1);
while(*p == ' ') {
*p-- = '\0';
} }
} }