mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-07-15 11:29:56 +00:00
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:
parent
19bc1197ee
commit
713afbd975
@ -7,6 +7,7 @@ applications/mod_enum
|
||||
applications/mod_fifo
|
||||
applications/mod_voicemail
|
||||
applications/mod_limit
|
||||
applications/mod_expr
|
||||
#applications/mod_ivrtest
|
||||
#applications/mod_soundtouch
|
||||
#applications/mod_rss
|
||||
|
@ -36,6 +36,7 @@
|
||||
<load module="mod_commands"/>
|
||||
<load module="mod_conference"/>
|
||||
<load module="mod_dptools"/>
|
||||
<load module="mod_expr"/>
|
||||
<load module="mod_fifo"/>
|
||||
<load module="mod_voicemail"/>
|
||||
<load module="mod_limit"/>
|
||||
|
@ -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(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(switch_bool_t) switch_is_lan_addr(const char *ip);
|
||||
|
||||
/*!
|
||||
\brief Escape a string by prefixing a list of characters with an escape character
|
||||
|
@ -40,6 +40,138 @@
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load);
|
||||
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)
|
||||
{
|
||||
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_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, "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 */
|
||||
return SWITCH_STATUS_NOUNLOAD;
|
||||
|
6
src/mod/applications/mod_expr/Makefile
Normal file
6
src/mod/applications/mod_expr/Makefile
Normal 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
|
||||
|
161
src/mod/applications/mod_expr/conio.h
Normal file
161
src/mod/applications/mod_expr/conio.h
Normal 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_ */
|
29
src/mod/applications/mod_expr/exprconf.h
Normal file
29
src/mod/applications/mod_expr/exprconf.h
Normal 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 */
|
268
src/mod/applications/mod_expr/expreval.c
Normal file
268
src/mod/applications/mod_expr/expreval.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
164
src/mod/applications/mod_expr/expreval.dsp
Normal file
164
src/mod/applications/mod_expr/expreval.dsp
Normal 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
|
59
src/mod/applications/mod_expr/expreval.dsw
Normal file
59
src/mod/applications/mod_expr/expreval.dsw
Normal 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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
127
src/mod/applications/mod_expr/expreval.h
Normal file
127
src/mod/applications/mod_expr/expreval.h
Normal 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 */
|
1334
src/mod/applications/mod_expr/expreval.html
Normal file
1334
src/mod/applications/mod_expr/expreval.html
Normal file
File diff suppressed because it is too large
Load Diff
329
src/mod/applications/mod_expr/exprfunc.c
Normal file
329
src/mod/applications/mod_expr/exprfunc.c
Normal 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;
|
||||
}
|
1064
src/mod/applications/mod_expr/exprilfs.h
Normal file
1064
src/mod/applications/mod_expr/exprilfs.h
Normal file
File diff suppressed because it is too large
Load Diff
101
src/mod/applications/mod_expr/exprincl.h
Normal file
101
src/mod/applications/mod_expr/exprincl.h
Normal 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 */
|
115
src/mod/applications/mod_expr/exprinit.c
Normal file
115
src/mod/applications/mod_expr/exprinit.c
Normal 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;
|
||||
}
|
||||
|
||||
|
39
src/mod/applications/mod_expr/exprmem.c
Normal file
39
src/mod/applications/mod_expr/exprmem.c
Normal 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));
|
||||
}
|
21
src/mod/applications/mod_expr/exprmem.h
Normal file
21
src/mod/applications/mod_expr/exprmem.h
Normal 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 */
|
237
src/mod/applications/mod_expr/exprobj.c
Normal file
237
src/mod/applications/mod_expr/exprobj.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
1558
src/mod/applications/mod_expr/exprpars.c
Normal file
1558
src/mod/applications/mod_expr/exprpars.c
Normal file
File diff suppressed because it is too large
Load Diff
215
src/mod/applications/mod_expr/exprpriv.h
Normal file
215
src/mod/applications/mod_expr/exprpriv.h
Normal 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 */
|
||||
|
828
src/mod/applications/mod_expr/exprtmpl.html
Normal file
828
src/mod/applications/mod_expr/exprtmpl.html
Normal 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>π</td>
|
||||
<td>3.14159265358979323846</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>M_PI_2</td>
|
||||
<td>π/2</td>
|
||||
<td>1.57079632679489661923</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>M_PI_4</td>
|
||||
<td>π/4</td>
|
||||
<td>0.78539816339744830962</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>M_1_PI</td>
|
||||
<td>1/π</td>
|
||||
<td>0.31830988618379067154</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>M_2_PI</td>
|
||||
<td>2/π</td>
|
||||
<td>0.63661977236758134308</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>M_1_SQRTPI</td>
|
||||
<td>1/√(π)</td>
|
||||
<td>0.56418958354776</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>M_2_SQRTPI</td>
|
||||
<td>2/√(π)</td>
|
||||
<td>1.12837916709551257390</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>M_SQRT2</td>
|
||||
<td>√(2)</td>
|
||||
<td>1.41421356237309504880</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>M_1_SQRT2</td>
|
||||
<td>1/√(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>
|
||||
|
||||
|
43
src/mod/applications/mod_expr/exprutil.c
Normal file
43
src/mod/applications/mod_expr/exprutil.c
Normal 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;
|
||||
}
|
||||
|
||||
|
395
src/mod/applications/mod_expr/exprval.c
Normal file
395
src/mod/applications/mod_expr/exprval.c
Normal 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;
|
||||
}
|
21
src/mod/applications/mod_expr/license.txt
Normal file
21
src/mod/applications/mod_expr/license.txt
Normal 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.
|
||||
|
198
src/mod/applications/mod_expr/mod_expr.c
Normal file
198
src/mod/applications/mod_expr/mod_expr.c
Normal 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:
|
||||
*/
|
170
src/mod/applications/mod_expr/readme.txt
Normal file
170
src/mod/applications/mod_expr/readme.txt
Normal 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.
|
@ -1374,9 +1374,20 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
|
||||
while(*e == ' ') {
|
||||
*e-- = '\0';
|
||||
}
|
||||
if ((e = strchr(vval, ')'))) {
|
||||
e = vval;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1462,6 +1473,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
|
||||
}
|
||||
}
|
||||
free(indup);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -197,6 +197,67 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(char *to, char *from, char *he
|
||||
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)
|
||||
{
|
||||
@ -536,8 +597,7 @@ SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char
|
||||
int argc;
|
||||
char *ptr;
|
||||
int quot = 0;
|
||||
char qc = '"';
|
||||
char *e;
|
||||
char qc = '\'';
|
||||
int x;
|
||||
|
||||
if (!buf || !array || !arraylen) {
|
||||
@ -568,13 +628,21 @@ SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char
|
||||
array[argc++] = ptr;
|
||||
}
|
||||
|
||||
/* strip quotes */
|
||||
/* strip quotes and leading / trailing spaces */
|
||||
for (x = 0; x < argc; x++) {
|
||||
if (*(array[x]) == qc) {
|
||||
char *p;
|
||||
|
||||
while(*(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';
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user