From 89ecc93992b90fb100f8d159908625cd3fe778d7 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 13 Nov 2007 20:23:26 +0000 Subject: [PATCH] dos2unix git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6242 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/applications/mod_expr/conio.h | 322 +-- src/mod/applications/mod_expr/exprconf.h | 58 +- src/mod/applications/mod_expr/expreval.c | 536 ++-- src/mod/applications/mod_expr/expreval.h | 254 +- src/mod/applications/mod_expr/exprfunc.c | 658 ++--- src/mod/applications/mod_expr/exprilfs.h | 2128 +++++++-------- src/mod/applications/mod_expr/exprincl.h | 224 +- src/mod/applications/mod_expr/exprinit.c | 230 +- src/mod/applications/mod_expr/exprmem.c | 78 +- src/mod/applications/mod_expr/exprmem.h | 42 +- src/mod/applications/mod_expr/exprobj.c | 474 ++-- src/mod/applications/mod_expr/exprpars.c | 3116 +++++++++++----------- src/mod/applications/mod_expr/exprpriv.h | 430 +-- src/mod/applications/mod_expr/exprutil.c | 86 +- src/mod/applications/mod_expr/exprval.c | 790 +++--- 15 files changed, 4713 insertions(+), 4713 deletions(-) diff --git a/src/mod/applications/mod_expr/conio.h b/src/mod/applications/mod_expr/conio.h index 5f40a21722..65d0678622 100644 --- a/src/mod/applications/mod_expr/conio.h +++ b/src/mod/applications/mod_expr/conio.h @@ -1,161 +1,161 @@ -/* A conio implementation for Mingw/Dev-C++. - * - * Written by: - * Hongli Lai - * tkorrovi on 2002/02/26. - * Andrew Westcott - * - * Offered for use in the public domain without any warranty. - */ - -#ifndef _CONIO_H_ -#define _CONIO_H_ - - -#include - -#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 - * - * 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_ */ +/* A conio implementation for Mingw/Dev-C++. + * + * Written by: + * Hongli Lai + * tkorrovi on 2002/02/26. + * Andrew Westcott + * + * Offered for use in the public domain without any warranty. + */ + +#ifndef _CONIO_H_ +#define _CONIO_H_ + + +#include + +#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 + * + * 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_ */ diff --git a/src/mod/applications/mod_expr/exprconf.h b/src/mod/applications/mod_expr/exprconf.h index b4c187b323..4bda3795ef 100644 --- a/src/mod/applications/mod_expr/exprconf.h +++ b/src/mod/applications/mod_expr/exprconf.h @@ -1,29 +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 */ +/* + 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 */ diff --git a/src/mod/applications/mod_expr/expreval.c b/src/mod/applications/mod_expr/expreval.c index 30a77fb640..9166779876 100644 --- a/src/mod/applications/mod_expr/expreval.c +++ b/src/mod/applications/mod_expr/expreval.c @@ -1,268 +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 - -#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; - } - - - +/* + 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 + +#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; + } + + + diff --git a/src/mod/applications/mod_expr/expreval.h b/src/mod/applications/mod_expr/expreval.h index d8b59031cc..a39bda8618 100644 --- a/src/mod/applications/mod_expr/expreval.h +++ b/src/mod/applications/mod_expr/expreval.h @@ -1,127 +1,127 @@ -/* - File: expreval.h - Auth: Brian Allen Vanderburg II - Date: Thursday, April 24, 2003 - Desc: Main include file for ExprEval library - - This file is part of ExprEval. -*/ - - -/* Include once */ -#ifndef __BAVII_EXPREVAL_H -#define __BAVII_EXPREVAL_H - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Define type of data to use */ -typedef double EXPRTYPE; - -/* Defines for various things */ - -/* Max id size */ -#define EXPR_MAXIDENTSIZE 255 - -/* Error values */ -enum - { - EXPR_ERROR_UNKNOWN = -1, /* Unknown error */ - EXPR_ERROR_NOERROR = 0, /* No Error */ - EXPR_ERROR_MEMORY, /* Memory allocation failed */ - EXPR_ERROR_NULLPOINTER, /* Null pointer passed to function */ - EXPR_ERROR_NOTFOUND, /* Item not found in a list */ - EXPR_ERROR_UNMATCHEDCOMMENT, /* Unmatched comment tags */ - EXPR_ERROR_INVALIDCHAR, /* Invalid characters in expression */ - EXPR_ERROR_ALREADYEXISTS, /* An item already called create */ - EXPR_ERROR_ALREADYPARSEDBAD, /* Expression parsed already, but unsuccessfully. call free or clear */ - EXPR_ERROR_ALREADYPARSEDGOOD, /* Expression parsed already, successfully, call free or clear */ - EXPR_ERROR_EMPTYEXPR, /* Empty expression string passed to parse */ - EXPR_ERROR_UNMATCHEDPAREN, /* Unmatched parenthesis */ - EXPR_ERROR_SYNTAX, /* Syntax error in expression */ - EXPR_ERROR_MISSINGSEMICOLON, /* Missing semicolon at end of expression */ - EXPR_ERROR_BADIDENTIFIER, /* Identifier was to big or not formed right */ - EXPR_ERROR_NOSUCHFUNCTION, /* Function does not exist in function list */ - EXPR_ERROR_BADNUMBERARGUMENTS, /* Bad number of arguments in a function call */ - EXPR_ERROR_BADEXPR, /* This is a bad expression to evaluate. It has not been parsed or has unsuccessfully */ - EXPR_ERROR_UNABLETOASSIGN, /* Unable to do an assignment, maybe no variable list */ - EXPR_ERROR_DIVBYZERO, /* Attempted a division by zero */ - EXPR_ERROR_NOVARLIST, /* No variable list found but one is needed */ - EXPR_ERROR_BREAK, /* Expression was broken by break function */ - EXPR_ERROR_CONSTANTASSIGN, /* Assignment to a constant */ - EXPR_ERROR_REFCONSTANT, /* Constant used as a reference parameter */ - EXPR_ERROR_OUTOFRANGE, /* A bad value was passed to a function */ - - EXPR_ERROR_USER /* Custom errors should be larger than this */ - }; - -/* Macros */ - -/* Forward declarations */ -typedef struct _exprNode exprNode; -typedef struct _exprFuncList exprFuncList; -typedef struct _exprValList exprValList; -typedef struct _exprObj exprObj; - -/* Function types */ -typedef int (*exprFuncType)(exprObj *obj, exprNode *nodes, int nodecount, EXPRTYPE **refs, int refcount, EXPRTYPE *val); -typedef int (*exprBreakFuncType)(exprObj *obj); - - - -/* Functions */ - -/* Version information function */ -void exprGetVersion(int *major, int *minor); - -/* Functions for function lists */ -int exprFuncListCreate(exprFuncList **flist); -int exprFuncListAdd(exprFuncList *flist, char *name, exprFuncType ptr, int min, int max, int refmin, int refmax); -int exprFuncListFree(exprFuncList *flist); -int exprFuncListClear(exprFuncList *flist); -int exprFuncListInit(exprFuncList *flist); - -/* Functions for value lists */ -int exprValListCreate(exprValList **vlist); -int exprValListAdd(exprValList *vlist, char *name, EXPRTYPE val); -int exprValListSet(exprValList *vlist, char *name, EXPRTYPE val); -int exprValListGet(exprValList *vlist, char *name, EXPRTYPE *val); -int exprValListAddAddress(exprValList *vlist, char *name, EXPRTYPE *addr); -int exprValListGetAddress(exprValList *vlist, char *name, EXPRTYPE **addr); -void *exprValListGetNext(exprValList *vlist, char **name, EXPRTYPE *value, EXPRTYPE** addr, void *cookie); -int exprValListFree(exprValList *vlist); -int exprValListClear(exprValList *vlist); -int exprValListInit(exprValList *vlist); - -/* Functions for expression objects */ -int exprCreate(exprObj **obj, exprFuncList *flist, exprValList *vlist, exprValList *clist, - exprBreakFuncType breaker, void *userdata); -int exprFree(exprObj *obj); -int exprClear(exprObj *obj); -int exprParse(exprObj *obj, char *expr); -int exprEval(exprObj *obj, EXPRTYPE *val); -int exprEvalNode(exprObj *obj, exprNode *nodes, int curnode, EXPRTYPE *val); -exprFuncList *exprGetFuncList(exprObj *obj); -exprValList *exprGetVarList(exprObj *obj); -exprValList *exprGetConstList(exprObj *obj); -exprBreakFuncType exprGetBreakFunc(exprObj *obj); -int exprGetBreakResult(exprObj *obj); -void* exprGetUserData(exprObj *obj); -void exprSetUserData(exprObj *obj, void *userdata); -void exprSetBreakCount(exprObj *obj, int count); -void exprGetErrorPosition(exprObj *obj, int *start, int *end); - -/* Other useful routines */ -int exprValidIdent(char *name); - -/* Name mangling */ -#ifdef __cplusplus -} -#endif - - - -#endif /* __BAVII_EXPREVAL_H */ +/* + File: 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 */ diff --git a/src/mod/applications/mod_expr/exprfunc.c b/src/mod/applications/mod_expr/exprfunc.c index 80cdc0f10e..c0b6becedd 100644 --- a/src/mod/applications/mod_expr/exprfunc.c +++ b/src/mod/applications/mod_expr/exprfunc.c @@ -1,329 +1,329 @@ -/* - File: exprfunc.c - Auth: Brian Allen Vanderburg II - Date: Thursday, April 24, 2003 - Desc: Expression function list routines - - This file is part of ExprEval. -*/ - - - -/* Includes */ -#include "exprincl.h" - -#include "exprpriv.h" -#include "exprmem.h" - -/* Internal functions */ -static exprFunc *exprCreateFunc(char *name, exprFuncType ptr, int type, int min, int max, int refmin, int refmax); -static void exprFuncListFreeData(exprFunc *func); - - -/* This function creates the function list, */ -int exprFuncListCreate(exprFuncList **flist) - { - exprFuncList *tmp; - - if(flist == NULL) - return EXPR_ERROR_NULLPOINTER; - - *flist = NULL; /* Set to NULL initially */ - - tmp = exprAllocMem(sizeof(exprFuncList)); - - if(tmp == NULL) - return EXPR_ERROR_MEMORY; /* Could not allocate memory */ - - /* Update pointer */ - *flist = tmp; - - return EXPR_ERROR_NOERROR; - } - -/* Add a function to the list */ -int exprFuncListAdd(exprFuncList *flist, char *name, exprFuncType ptr, int min, int max, int refmin, int refmax) - { - exprFunc *tmp; - exprFunc *cur; - int result; - - if(flist == NULL) - return EXPR_ERROR_NULLPOINTER; - - /* Make sure the name is valid */ - if(!exprValidIdent(name)) - return EXPR_ERROR_BADIDENTIFIER; - - /* Fix values only if none are negative (negative values mean no limit) */ - - /* if both are neg, no min or max number of args */ - /* if min is neg, max pos, no min number of args but a maximum */ - /* if min is pos, max neg, there is a min number of args, but no max */ - /* if both pos, then a min and max limit. We swap to make sure it works - right. I.E. Min of 3 and max of 2 would make function unusable */ - if(min >= 0 && max >= 0) - { - if(min > max) - { - result = min; - min = max; - max = result; - } - } - - if(refmin >= 0 && refmax >= 0) - { - if(refmin > refmax) - { - result = refmin; - refmin = max; - refmax = result; - } - } - - if(flist->head == NULL) - { - /* Create the node right here */ - tmp = exprCreateFunc(name, ptr, EXPR_NODETYPE_FUNCTION, min, max, refmin, refmax); - - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - flist->head = tmp; - return EXPR_ERROR_NOERROR; - } - - /* See if it already exists */ - cur = flist->head; - - while(cur) - { - result = strcmp(name, cur->fname); - - if(result == 0) - return EXPR_ERROR_ALREADYEXISTS; - - cur = cur->next; - } - - /* It did not exist, so add it at the head */ - tmp = exprCreateFunc(name, ptr, EXPR_NODETYPE_FUNCTION, min, max, refmin, refmax); - - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - tmp->next = flist->head; - flist->head = tmp; - return EXPR_ERROR_NOERROR; - } - -/* Add a function node type to the list - This works pretty much the same way, except the function - pointer is NULL and the node type specifies the function - to do. exprEvalNode handles this, instead of calling - a function solver. */ -int exprFuncListAddType(exprFuncList *flist, char *name, int type, int min, int max, int refmin, int refmax) - { - exprFunc *tmp; - exprFunc *cur; - int result; - - if(flist == NULL) - return EXPR_ERROR_NULLPOINTER; - - /* Make sure the name is valid */ - if(!exprValidIdent(name)) - return EXPR_ERROR_BADIDENTIFIER; - - /* Fix values only if none are negative (negative values mean no limit) */ - - /* if both are neg, no min or max number of args */ - /* if min is neg, max pos, no min number of args but a maximum */ - /* if min is pos, max neg, there is a min number of args, but no max */ - /* if both pos, then a min and max limit. We swap to make sure it works - right. I.E. Min of 3 and max of 2 would make function unusable */ - if(min >= 0 && max >= 0) - { - if(min > max) - { - result = min; - min = max; - max = result; - } - } - - if(refmin >= 0 && refmax >= 0) - { - if(refmin > refmax) - { - result = refmin; - refmin = max; - refmax = result; - } - } - - if(flist->head == NULL) - { - /* Create the node right here */ - tmp = exprCreateFunc(name, NULL, type, min, max, refmin, refmax); - - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - flist->head = tmp; - return EXPR_ERROR_NOERROR; - } - - /* See if it already exists */ - cur = flist->head; - - while(cur) - { - result = strcmp(name, cur->fname); - - if(result == 0) - return EXPR_ERROR_ALREADYEXISTS; - - cur = cur->next; - } - - /* It did not exist, so add it at the head */ - tmp = exprCreateFunc(name, NULL, type, min, max, refmin, refmax); - - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - tmp->next = flist->head; - flist->head = tmp; - return EXPR_ERROR_NOERROR; - } - - -/* Get the function from a list along with it's min an max data */ -int exprFuncListGet(exprFuncList *flist, char *name, exprFuncType *ptr, int *type, int *min, int *max, int *refmin, int *refmax) - { - exprFunc *cur; - int result; - - if(flist == NULL) - return EXPR_ERROR_NULLPOINTER; - - if(name == NULL || name[0] == '\0') - return EXPR_ERROR_NOTFOUND; - - /* Search for the item */ - cur = flist->head; - - while(cur) - { - result = strcmp(name, cur->fname); - - if(result == 0) - { - /* We found it. */ - *ptr = cur->fptr; - *min = cur->min; - *max = cur->max; - *refmin = cur->refmin; - *refmax = cur->refmax; - *type = cur->type; - - /* return now */ - return EXPR_ERROR_NOERROR; - } - - cur = cur->next; - } - - /* If we got here, we did not find the item in the list */ - return EXPR_ERROR_NOTFOUND; - } - -/* This routine will free the function list */ -int exprFuncListFree(exprFuncList *flist) - { - /* Make sure it exists, if not it is not error */ - if(flist == NULL) - return EXPR_ERROR_NOERROR; - - /* Free the nodes */ - exprFuncListFreeData(flist->head); - - /* Free the container */ - exprFreeMem(flist); - - return EXPR_ERROR_NOERROR; - } - -/* This routine will clear the function list */ -int exprFuncListClear(exprFuncList *flist) - { - if(flist == NULL) - return EXPR_ERROR_NOERROR; - - /* Free the nodes only */ - if(flist->head) - { - exprFuncListFreeData(flist->head); - - flist->head = NULL; - } - - return EXPR_ERROR_NOERROR; - } - -/* This routine will free any child nodes, and then free itself */ -void exprFuncListFreeData(exprFunc *func) - { - exprFunc *next; - - while(func) - { - /* Remember the next item */ - next = func->next; - - /* Free name */ - exprFreeMem(func->fname); - - /* Free ourself */ - exprFreeMem(func); - - func = next; - } - } - -/* This routine will create the function object */ -exprFunc *exprCreateFunc(char *name, exprFuncType ptr, int type, int min, int max, int refmin, int refmax) - { - exprFunc *tmp; - char *vtmp; - - /* We already checked the name in exprFuncListAdd */ - - /* Create it */ - tmp = exprAllocMem(sizeof(exprFunc)); - if(tmp == NULL) - return NULL; - - /* Allocate space for the name */ - vtmp = exprAllocMem(strlen(name) + 1); - - if(vtmp == NULL) - { - exprFreeMem(tmp); - return NULL; - } - - /* Copy the data over */ - strcpy(vtmp, name); - tmp->fname = vtmp; - tmp->fptr = ptr; - tmp->min = min; - tmp->max = max; - tmp->refmin = refmin; - tmp->refmax = refmax; - tmp->type = type; - - return tmp; - } +/* + File: 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; + } diff --git a/src/mod/applications/mod_expr/exprilfs.h b/src/mod/applications/mod_expr/exprilfs.h index 1ca466c86b..472317a3c2 100644 --- a/src/mod/applications/mod_expr/exprilfs.h +++ b/src/mod/applications/mod_expr/exprilfs.h @@ -1,1064 +1,1064 @@ -/* - File: exprilfs.h - Auth: Brian Allen Vanderburg II - Date: Tuesday, February 28, 2006 - Desc: Inline Function Solvers for exprEvalNode - - This file is part of ExprEval. -*/ - -/* - This is here to help prevent expreval.c from getting - too crowded. - - Provided variables: - obj: expression object point - nodes: function node with paramters - d1, d2: variables - err: error - val: value pointer for resuld - pos: integer - - Also EXPR_RESET_ERR() and EXPR_CHECK_ERR() - - The chunks below are included inside a statement that looks like this: - - switch(nodes->data.function.type) - { - #include "exprilfs.h" - - default: - { - return EXPR_ERROR_UNKNOWN; - } - } -*/ - - - -/* abs */ -case EXPR_NODEFUNC_ABS: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - if(d1 >= 0) - *val = d1; - else - *val = -d1; - } - else - return err; - - break; - } - -/* mod */ -case EXPR_NODEFUNC_MOD: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - *val = fmod(d1, d2); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* ipart */ -case EXPR_NODEFUNC_IPART: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - modf(d1, val); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* fpart */ -case EXPR_NODEFUNC_FPART: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = modf(d1, &d2); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* min */ -case EXPR_NODEFUNC_MIN: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - for(pos = 1; pos < nodes->data.function.nodecount; pos++) - { - err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d2); - if(!err) - { - if(d2 < d1) - d1 = d2; - } - else - return err; - } - } - else - return err; - - *val = d1; - - break; - } - -/* max */ -case EXPR_NODEFUNC_MAX: - { - int pos; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - for(pos = 1; pos < nodes->data.function.nodecount; pos++) - { - err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d2); - if(!err) - { - if(d2 > d1) - d1 = d2; - } - else - return err; - } - } - else - return err; - - *val = d1; - - break; - } - -/* pow */ -case EXPR_NODEFUNC_POW: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - *val = pow(d1, d2); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* sqrt */ -case EXPR_NODEFUNC_SQRT: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = sqrt(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* sin */ -case EXPR_NODEFUNC_SIN: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = sin(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* sinh */ -case EXPR_NODEFUNC_SINH: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = sinh(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* asin */ -case EXPR_NODEFUNC_ASIN: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = asin(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* cos */ -case EXPR_NODEFUNC_COS: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = cos(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* cosh */ -case EXPR_NODEFUNC_COSH: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = cosh(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* acos */ -case EXPR_NODEFUNC_ACOS: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = acos(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* tan */ -case EXPR_NODEFUNC_TAN: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = tan(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* tanh */ -case EXPR_NODEFUNC_TANH: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = tanh(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* atan */ -case EXPR_NODEFUNC_ATAN: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = atan(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* atan2 */ -case EXPR_NODEFUNC_ATAN2: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - *val = atan2(d1, d2); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* log */ -case EXPR_NODEFUNC_LOG: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = log10(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* pow10 */ -case EXPR_NODEFUNC_POW10: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = pow(10.0, d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* ln */ -case EXPR_NODEFUNC_LN: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = log(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* exp */ -case EXPR_NODEFUNC_EXP: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - EXPR_RESET_ERR(); - *val = exp(d1); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -case EXPR_NODEFUNC_LOGN: - { - EXPRTYPE l1, l2; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - l1 = log(d1); - EXPR_CHECK_ERR(); - l2 = log(d2); - EXPR_CHECK_ERR(); - - - if(l2 == 0.0) - { -#if(EXPR_ERROR_LEVEL >= EXPR_ERROR_LEVEL_CHECK) - return EXPR_ERROR_OUTOFRANGE; -#else - *val = 0.0; - return EXPR_ERROR_NOERROR; -#endif - } - - *val = l1 / l2; - } - else - return err; - - break; - } - -/* ceil */ -case EXPR_NODEFUNC_CEIL: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - *val = ceil(d1); - } - else - return err; - - break; - } - -/* floor */ -case EXPR_NODEFUNC_FLOOR: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - *val = floor(d1); - } - else - return err; - - break; - } - -/* rand */ -case EXPR_NODEFUNC_RAND: - { - long a; - - /* Perform random routine directly */ - a = ((long)(*(nodes->data.function.refs[0]))) * 214013L + 2531011L; - *(nodes->data.function.refs[0]) = (EXPRTYPE)a; - - *val = (EXPRTYPE)((a >> 16) & 0x7FFF) / (EXPRTYPE)(32768); - break; - } - -/* random */ -case EXPR_NODEFUNC_RANDOM: - { - EXPRTYPE diff, rval; - long a; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - diff = d2 - d1; - - /* Perform random routine directly */ - a = ((long)(*(nodes->data.function.refs[0]))) * 214013L + 2531011L; - *(nodes->data.function.refs[0]) = (EXPRTYPE)a; - - rval = (EXPRTYPE)((a >> 16) & 0x7FFF) / (EXPRTYPE)(32767); - - *val = (rval * diff) + d1; - } - else - return err; - - break; - } - -/* randomize */ -case EXPR_NODEFUNC_RANDOMIZE: - { - static int curcall = 0; - - curcall++; - - *(nodes->data.function.refs[0]) = (EXPRTYPE)((clock() + 1024 + curcall) * time(NULL)); - - break; - } - -/* deg */ -case EXPR_NODEFUNC_DEG: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - *val = (180.0 * d1) / M_PI; - } - else - return err; - - break; - } - -/* rad */ -case EXPR_NODEFUNC_RAD: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - *val = (M_PI * d1) / 180.0; - } - else - return err; - - break; - } - -/* recttopolr */ -case EXPR_NODEFUNC_RECTTOPOLR: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - *val = sqrt((d1 * d1) + (d2 * d2)); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* recttopola */ -case EXPR_NODEFUNC_RECTTOPOLA: - { - EXPRTYPE tmp; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - tmp = atan2(d2, d1); - EXPR_CHECK_ERR(); - - if(tmp < 0.0) - *val = tmp = (2.0 * M_PI); - else - *val = tmp; - } - else - return err; - - break; - } - -/* poltorectx */ -case EXPR_NODEFUNC_POLTORECTX: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - *val = d1 * cos(d2); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* poltorecty */ -case EXPR_NODEFUNC_POLTORECTY: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - *val = d1 * sin(d2); - EXPR_CHECK_ERR(); - } - else - return err; - - break; - } - -/* if */ -case EXPR_NODEFUNC_IF: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - if(d1 != 0.0) - { - err = exprEvalNode(obj, nodes->data.function.nodes, 1, val); - if(err) - return err; - } - else - { - err = exprEvalNode(obj, nodes->data.function.nodes, 2, val); - if(err) - return err; - } - } - else - return err; - - break; - } - -/* select */ -case EXPR_NODEFUNC_SELECT: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - if(d1 < 0.0) - { - err = exprEvalNode(obj, nodes->data.function.nodes, 1, val); - if(err) - return err; - } - else if(d1 == 0.0) - { - err = exprEvalNode(obj, nodes->data.function.nodes, 2, val); - if(err) - return err; - } - else - { - if(nodes->data.function.nodecount == 3) - { - err = exprEvalNode(obj, nodes->data.function.nodes, 2, val); - if(err) - return err; - } - else - { - err = exprEvalNode(obj, nodes->data.function.nodes, 3, val); - if(err) - return err; - } - } - } - else - return err; - - break; - } - -/* equal */ -case EXPR_NODEFUNC_EQUAL: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - *val = (d1 == d2) ? 1.0 : 0.0; - } - else - return err; - - break; - } - -/* above */ -case EXPR_NODEFUNC_ABOVE: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - *val = (d1 > d2) ? 1.0 : 0.0; - } - else - return err; - - break; - } - -/* below */ -case EXPR_NODEFUNC_BELOW: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - *val = (d1 < d2) ? 1.0 : 0.0; - } - else - return err; - - break; - } - -/* avg */ -case EXPR_NODEFUNC_AVG: - { - d2 = 0.0; - - for(pos = 0; pos < nodes->data.function.nodecount; pos++) - { - err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d1); - if(!err) - { - d2 += d1; - } - else - return err; - } - - *val = d2 / (EXPRTYPE)(nodes->data.function.nodecount); - - break; - } - -/* clip */ -case EXPR_NODEFUNC_CLIP: - { - EXPRTYPE v; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &v); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - if(v < d1) - *val = d1; - else if(v > d2) - *val = d2; - else - *val = v; - } - else - return err; - - break; - } - -/* clamp */ -case EXPR_NODEFUNC_CLAMP: - { - EXPRTYPE v, tmp; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &v); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - EXPR_RESET_ERR(); - tmp = fmod(v - d1, d2 - d1); - EXPR_CHECK_ERR(); - - if(tmp < 0.0) - *val = tmp * d2; - else - *val = tmp + d1; - } - else - return err; - - break; - } - -/* pntchange */ -case EXPR_NODEFUNC_PNTCHANGE: - { - EXPRTYPE n1, n2, pnt; - EXPRTYPE odiff, ndiff, perc; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 2, &n1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 3, &n2); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 4, &pnt); - - if(!err) - { - odiff = d2 - d1; - ndiff = n2 - n1; - - if(odiff == 0.0) - { - *val = d1; - return EXPR_ERROR_NOERROR; - } - - perc = (pnt - d1) / odiff; - - *val = n1 + (perc * ndiff); - } - else - return err; - - break; - } - -/* poly */ -case EXPR_NODEFUNC_POLY: - { - EXPRTYPE total, curpow; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - curpow = (EXPRTYPE)(nodes->data.function.nodecount) - 2.0; - total = 0.0; - - for(pos = 1; pos < nodes->data.function.nodecount; pos++) - { - err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d2); - if(err) - return err; - - EXPR_RESET_ERR(); - total = total + (d2 * pow(d1, curpow)); - EXPR_CHECK_ERR(); - - curpow = curpow - 1.0; - } - } - else - return err; - - *val = total; - break; - } - -/* and */ -case EXPR_NODEFUNC_AND: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - if(d1 == 0.0 || d2 == 0.0) - *val = 0.0; - else - *val = 1.0; - } - else - return err; - - break; - } - -/* or */ -case EXPR_NODEFUNC_OR: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); - - if(!err) - { - if(d1 != 0.0 || d2 != 0.0) - *val = 1.0; - else - *val = 0.0; - } - else - return err; - - break; - } - -/* not */ -case EXPR_NODEFUNC_NOT: - { - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - { - if(d1 != 0.0) - *val = 0.0; - else - *val = 1.0; - } - else - return err; - - break; - } - -/* for */ -case EXPR_NODEFUNC_FOR: - { - int pos; - EXPRTYPE test; - - err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); - - if(!err) - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &test); - - if(!err) - { - while(test != 0.0) - { - for(pos = 3; pos < nodes->data.function.nodecount; pos++) - { - err = exprEvalNode(obj, nodes->data.function.nodes, pos, val); - if(err) - return err; - } - - err = exprEvalNode(obj, nodes->data.function.nodes, 2, &d1); - if(err) - return err; - - err = exprEvalNode(obj, nodes->data.function.nodes, 1, &test); - if(err) - return err; - } - } - else - return err; - - break; - } - -/* many */ -case EXPR_NODEFUNC_MANY: - { - for(pos = 0; pos < nodes->data.function.nodecount; pos++) - { - err = exprEvalNode(obj, nodes->data.function.nodes, pos, val); - if(err) - return err; - } - - break; - } - +/* + File: exprilfs.h + Auth: Brian Allen Vanderburg II + Date: Tuesday, February 28, 2006 + Desc: Inline Function Solvers for exprEvalNode + + This file is part of ExprEval. +*/ + +/* + This is here to help prevent expreval.c from getting + too crowded. + + Provided variables: + obj: expression object point + nodes: function node with paramters + d1, d2: variables + err: error + val: value pointer for resuld + pos: integer + + Also EXPR_RESET_ERR() and EXPR_CHECK_ERR() + + The chunks below are included inside a statement that looks like this: + + switch(nodes->data.function.type) + { + #include "exprilfs.h" + + default: + { + return EXPR_ERROR_UNKNOWN; + } + } +*/ + + + +/* abs */ +case EXPR_NODEFUNC_ABS: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + if(d1 >= 0) + *val = d1; + else + *val = -d1; + } + else + return err; + + break; + } + +/* mod */ +case EXPR_NODEFUNC_MOD: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + *val = fmod(d1, d2); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* ipart */ +case EXPR_NODEFUNC_IPART: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + modf(d1, val); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* fpart */ +case EXPR_NODEFUNC_FPART: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = modf(d1, &d2); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* min */ +case EXPR_NODEFUNC_MIN: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + for(pos = 1; pos < nodes->data.function.nodecount; pos++) + { + err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d2); + if(!err) + { + if(d2 < d1) + d1 = d2; + } + else + return err; + } + } + else + return err; + + *val = d1; + + break; + } + +/* max */ +case EXPR_NODEFUNC_MAX: + { + int pos; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + for(pos = 1; pos < nodes->data.function.nodecount; pos++) + { + err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d2); + if(!err) + { + if(d2 > d1) + d1 = d2; + } + else + return err; + } + } + else + return err; + + *val = d1; + + break; + } + +/* pow */ +case EXPR_NODEFUNC_POW: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + *val = pow(d1, d2); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* sqrt */ +case EXPR_NODEFUNC_SQRT: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = sqrt(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* sin */ +case EXPR_NODEFUNC_SIN: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = sin(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* sinh */ +case EXPR_NODEFUNC_SINH: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = sinh(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* asin */ +case EXPR_NODEFUNC_ASIN: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = asin(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* cos */ +case EXPR_NODEFUNC_COS: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = cos(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* cosh */ +case EXPR_NODEFUNC_COSH: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = cosh(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* acos */ +case EXPR_NODEFUNC_ACOS: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = acos(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* tan */ +case EXPR_NODEFUNC_TAN: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = tan(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* tanh */ +case EXPR_NODEFUNC_TANH: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = tanh(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* atan */ +case EXPR_NODEFUNC_ATAN: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = atan(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* atan2 */ +case EXPR_NODEFUNC_ATAN2: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + *val = atan2(d1, d2); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* log */ +case EXPR_NODEFUNC_LOG: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = log10(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* pow10 */ +case EXPR_NODEFUNC_POW10: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = pow(10.0, d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* ln */ +case EXPR_NODEFUNC_LN: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = log(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* exp */ +case EXPR_NODEFUNC_EXP: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + EXPR_RESET_ERR(); + *val = exp(d1); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +case EXPR_NODEFUNC_LOGN: + { + EXPRTYPE l1, l2; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + l1 = log(d1); + EXPR_CHECK_ERR(); + l2 = log(d2); + EXPR_CHECK_ERR(); + + + if(l2 == 0.0) + { +#if(EXPR_ERROR_LEVEL >= EXPR_ERROR_LEVEL_CHECK) + return EXPR_ERROR_OUTOFRANGE; +#else + *val = 0.0; + return EXPR_ERROR_NOERROR; +#endif + } + + *val = l1 / l2; + } + else + return err; + + break; + } + +/* ceil */ +case EXPR_NODEFUNC_CEIL: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + *val = ceil(d1); + } + else + return err; + + break; + } + +/* floor */ +case EXPR_NODEFUNC_FLOOR: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + *val = floor(d1); + } + else + return err; + + break; + } + +/* rand */ +case EXPR_NODEFUNC_RAND: + { + long a; + + /* Perform random routine directly */ + a = ((long)(*(nodes->data.function.refs[0]))) * 214013L + 2531011L; + *(nodes->data.function.refs[0]) = (EXPRTYPE)a; + + *val = (EXPRTYPE)((a >> 16) & 0x7FFF) / (EXPRTYPE)(32768); + break; + } + +/* random */ +case EXPR_NODEFUNC_RANDOM: + { + EXPRTYPE diff, rval; + long a; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + diff = d2 - d1; + + /* Perform random routine directly */ + a = ((long)(*(nodes->data.function.refs[0]))) * 214013L + 2531011L; + *(nodes->data.function.refs[0]) = (EXPRTYPE)a; + + rval = (EXPRTYPE)((a >> 16) & 0x7FFF) / (EXPRTYPE)(32767); + + *val = (rval * diff) + d1; + } + else + return err; + + break; + } + +/* randomize */ +case EXPR_NODEFUNC_RANDOMIZE: + { + static int curcall = 0; + + curcall++; + + *(nodes->data.function.refs[0]) = (EXPRTYPE)((clock() + 1024 + curcall) * time(NULL)); + + break; + } + +/* deg */ +case EXPR_NODEFUNC_DEG: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + *val = (180.0 * d1) / M_PI; + } + else + return err; + + break; + } + +/* rad */ +case EXPR_NODEFUNC_RAD: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + *val = (M_PI * d1) / 180.0; + } + else + return err; + + break; + } + +/* recttopolr */ +case EXPR_NODEFUNC_RECTTOPOLR: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + *val = sqrt((d1 * d1) + (d2 * d2)); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* recttopola */ +case EXPR_NODEFUNC_RECTTOPOLA: + { + EXPRTYPE tmp; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + tmp = atan2(d2, d1); + EXPR_CHECK_ERR(); + + if(tmp < 0.0) + *val = tmp = (2.0 * M_PI); + else + *val = tmp; + } + else + return err; + + break; + } + +/* poltorectx */ +case EXPR_NODEFUNC_POLTORECTX: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + *val = d1 * cos(d2); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* poltorecty */ +case EXPR_NODEFUNC_POLTORECTY: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + *val = d1 * sin(d2); + EXPR_CHECK_ERR(); + } + else + return err; + + break; + } + +/* if */ +case EXPR_NODEFUNC_IF: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + if(d1 != 0.0) + { + err = exprEvalNode(obj, nodes->data.function.nodes, 1, val); + if(err) + return err; + } + else + { + err = exprEvalNode(obj, nodes->data.function.nodes, 2, val); + if(err) + return err; + } + } + else + return err; + + break; + } + +/* select */ +case EXPR_NODEFUNC_SELECT: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + if(d1 < 0.0) + { + err = exprEvalNode(obj, nodes->data.function.nodes, 1, val); + if(err) + return err; + } + else if(d1 == 0.0) + { + err = exprEvalNode(obj, nodes->data.function.nodes, 2, val); + if(err) + return err; + } + else + { + if(nodes->data.function.nodecount == 3) + { + err = exprEvalNode(obj, nodes->data.function.nodes, 2, val); + if(err) + return err; + } + else + { + err = exprEvalNode(obj, nodes->data.function.nodes, 3, val); + if(err) + return err; + } + } + } + else + return err; + + break; + } + +/* equal */ +case EXPR_NODEFUNC_EQUAL: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + *val = (d1 == d2) ? 1.0 : 0.0; + } + else + return err; + + break; + } + +/* above */ +case EXPR_NODEFUNC_ABOVE: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + *val = (d1 > d2) ? 1.0 : 0.0; + } + else + return err; + + break; + } + +/* below */ +case EXPR_NODEFUNC_BELOW: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + *val = (d1 < d2) ? 1.0 : 0.0; + } + else + return err; + + break; + } + +/* avg */ +case EXPR_NODEFUNC_AVG: + { + d2 = 0.0; + + for(pos = 0; pos < nodes->data.function.nodecount; pos++) + { + err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d1); + if(!err) + { + d2 += d1; + } + else + return err; + } + + *val = d2 / (EXPRTYPE)(nodes->data.function.nodecount); + + break; + } + +/* clip */ +case EXPR_NODEFUNC_CLIP: + { + EXPRTYPE v; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &v); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + if(v < d1) + *val = d1; + else if(v > d2) + *val = d2; + else + *val = v; + } + else + return err; + + break; + } + +/* clamp */ +case EXPR_NODEFUNC_CLAMP: + { + EXPRTYPE v, tmp; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &v); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + EXPR_RESET_ERR(); + tmp = fmod(v - d1, d2 - d1); + EXPR_CHECK_ERR(); + + if(tmp < 0.0) + *val = tmp * d2; + else + *val = tmp + d1; + } + else + return err; + + break; + } + +/* pntchange */ +case EXPR_NODEFUNC_PNTCHANGE: + { + EXPRTYPE n1, n2, pnt; + EXPRTYPE odiff, ndiff, perc; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 2, &n1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 3, &n2); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 4, &pnt); + + if(!err) + { + odiff = d2 - d1; + ndiff = n2 - n1; + + if(odiff == 0.0) + { + *val = d1; + return EXPR_ERROR_NOERROR; + } + + perc = (pnt - d1) / odiff; + + *val = n1 + (perc * ndiff); + } + else + return err; + + break; + } + +/* poly */ +case EXPR_NODEFUNC_POLY: + { + EXPRTYPE total, curpow; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + curpow = (EXPRTYPE)(nodes->data.function.nodecount) - 2.0; + total = 0.0; + + for(pos = 1; pos < nodes->data.function.nodecount; pos++) + { + err = exprEvalNode(obj, nodes->data.function.nodes, pos, &d2); + if(err) + return err; + + EXPR_RESET_ERR(); + total = total + (d2 * pow(d1, curpow)); + EXPR_CHECK_ERR(); + + curpow = curpow - 1.0; + } + } + else + return err; + + *val = total; + break; + } + +/* and */ +case EXPR_NODEFUNC_AND: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + if(d1 == 0.0 || d2 == 0.0) + *val = 0.0; + else + *val = 1.0; + } + else + return err; + + break; + } + +/* or */ +case EXPR_NODEFUNC_OR: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &d2); + + if(!err) + { + if(d1 != 0.0 || d2 != 0.0) + *val = 1.0; + else + *val = 0.0; + } + else + return err; + + break; + } + +/* not */ +case EXPR_NODEFUNC_NOT: + { + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + { + if(d1 != 0.0) + *val = 0.0; + else + *val = 1.0; + } + else + return err; + + break; + } + +/* for */ +case EXPR_NODEFUNC_FOR: + { + int pos; + EXPRTYPE test; + + err = exprEvalNode(obj, nodes->data.function.nodes, 0, &d1); + + if(!err) + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &test); + + if(!err) + { + while(test != 0.0) + { + for(pos = 3; pos < nodes->data.function.nodecount; pos++) + { + err = exprEvalNode(obj, nodes->data.function.nodes, pos, val); + if(err) + return err; + } + + err = exprEvalNode(obj, nodes->data.function.nodes, 2, &d1); + if(err) + return err; + + err = exprEvalNode(obj, nodes->data.function.nodes, 1, &test); + if(err) + return err; + } + } + else + return err; + + break; + } + +/* many */ +case EXPR_NODEFUNC_MANY: + { + for(pos = 0; pos < nodes->data.function.nodecount; pos++) + { + err = exprEvalNode(obj, nodes->data.function.nodes, pos, val); + if(err) + return err; + } + + break; + } + diff --git a/src/mod/applications/mod_expr/exprincl.h b/src/mod/applications/mod_expr/exprincl.h index e91b2261b1..768671b13a 100644 --- a/src/mod/applications/mod_expr/exprincl.h +++ b/src/mod/applications/mod_expr/exprincl.h @@ -1,112 +1,112 @@ -/* - 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 */ - -#ifdef _MSC_VER -#if (_MSC_VER >= 1400) // VC8+ -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif -#endif // VC8+ -#endif - -/* Memory routines. memory.h for VC++, mem.h for BC++ */ -#ifdef __TURBOC__ -#include -#else -#include -#endif - -/* Memory allocation */ -#include - -/* String routines */ -#include - -/* Character manipulation routines */ -#include - -/* Standard routines */ -#include - -/* Math routines */ -#include - -/* Time */ -#include - - -/* 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 */ +/* + 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 */ + +#ifdef _MSC_VER +#if (_MSC_VER >= 1400) // VC8+ +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE +#endif +#endif // VC8+ +#endif + +/* Memory routines. memory.h for VC++, mem.h for BC++ */ +#ifdef __TURBOC__ +#include +#else +#include +#endif + +/* Memory allocation */ +#include + +/* String routines */ +#include + +/* Character manipulation routines */ +#include + +/* Standard routines */ +#include + +/* Math routines */ +#include + +/* Time */ +#include + + +/* 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 */ diff --git a/src/mod/applications/mod_expr/exprinit.c b/src/mod/applications/mod_expr/exprinit.c index c716c94911..37b326c8a9 100644 --- a/src/mod/applications/mod_expr/exprinit.c +++ b/src/mod/applications/mod_expr/exprinit.c @@ -1,115 +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; - } - - +/* + 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; + } + + diff --git a/src/mod/applications/mod_expr/exprmem.c b/src/mod/applications/mod_expr/exprmem.c index fdb92fe2fc..f6eeec1e93 100644 --- a/src/mod/applications/mod_expr/exprmem.c +++ b/src/mod/applications/mod_expr/exprmem.c @@ -1,39 +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)); - } +/* + 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)); + } diff --git a/src/mod/applications/mod_expr/exprmem.h b/src/mod/applications/mod_expr/exprmem.h index 53a1071e4d..befeefe4b1 100644 --- a/src/mod/applications/mod_expr/exprmem.h +++ b/src/mod/applications/mod_expr/exprmem.h @@ -1,21 +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 */ +/* + 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 */ diff --git a/src/mod/applications/mod_expr/exprobj.c b/src/mod/applications/mod_expr/exprobj.c index 92568360ed..c43c040e44 100644 --- a/src/mod/applications/mod_expr/exprobj.c +++ b/src/mod/applications/mod_expr/exprobj.c @@ -1,237 +1,237 @@ -/* - File: exprobj.c - Auth: Brian Allen Vanderburg II - Date: Tuesday, April 29, 2003 - Desc: Functions for the exprObj type - - This file is part of ExprEval. -*/ - -/* Includes */ -#include "exprincl.h" - -#include "exprpriv.h" -#include "exprmem.h" - -/* Internal functions */ -static void exprFreeNodeData(exprNode *node); - - -/* Function to create an expression object */ -int exprCreate(exprObj **obj, exprFuncList *flist, exprValList *vlist, exprValList *clist, - exprBreakFuncType breaker, void *userdata) - { - exprObj *tmp; - - /* Allocate memory for the object */ - tmp = exprAllocMem(sizeof(exprObj)); - - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - - /* Assign data */ - tmp->flist = flist; - tmp->vlist = vlist; - tmp->clist = clist; - tmp->breakerfunc = breaker; - tmp->userdata = userdata; - tmp->breakcount = 100000; /* Default breaker count setting */ - tmp->breakcur = 0; - - /* Update pointer */ - *obj = tmp; - - return EXPR_ERROR_NOERROR; - } - - -/* Free the expression */ -int exprFree(exprObj *obj) - { - if(obj == NULL) - return EXPR_ERROR_NOERROR; - - /* First free the node data */ - exprFreeNodeData(obj->headnode); - exprFreeMem(obj->headnode); - - /* Free ourself */ - exprFreeMem(obj); - - return EXPR_ERROR_NOERROR; - } - -/* Clear expression, keep lists, etc */ -int exprClear(exprObj *obj) - { - if(obj == NULL) - return EXPR_ERROR_NOERROR; - - /* Free the node data only, keep function, variable, constant lists */ - exprFreeNodeData(obj->headnode); - exprFreeMem(obj->headnode); - - obj->headnode = NULL; - obj->parsedbad = 0; - obj->parsedgood = 0; - - return EXPR_ERROR_NOERROR; - } - - -/* Get functions to get information about the expression object */ - -/* Get the function list */ -exprFuncList *exprGetFuncList(exprObj *obj) - { - return (obj == NULL) ? NULL : obj->flist; - } - -/* Get the variable list */ -exprValList *exprGetVarList(exprObj *obj) - { - return (obj == NULL) ? NULL : obj->vlist; - } - -/* Get the constant list */ -exprValList *exprGetConstList(exprObj *obj) - { - return (obj == NULL) ? NULL : obj->clist; - } - -/* Get the breaker function */ -exprBreakFuncType exprGetBreakFunc(exprObj *obj) - { - return (obj == NULL) ? NULL : obj->breakerfunc; - } - -/* Check for break status */ -int exprGetBreakResult(exprObj *obj) - { - if(obj == NULL) - return 0; - - if(obj->breakerfunc == NULL) - return 0; - - return (*(obj->breakerfunc))(obj); - } - -/* Get the user data */ -void *exprGetUserData(exprObj *obj) - { - return (obj == NULL) ? NULL : obj->userdata; - } - - -/* Set functions to set certain data */ - -/* Set user data */ -void exprSetUserData(exprObj *obj, void *userdata) - { - if(obj) - obj->userdata = userdata; - } - - -/* Set breaker count */ -void exprSetBreakCount(exprObj *obj, int count) - { - if(obj) - { - /* If count is negative, make it positive */ - if(count < 0) - count = -count; - - obj->breakcount = count; - - /* Make sure the current value is not bigger than count */ - if(obj->breakcur > count) - obj->breakcur = count; - } - } - -/* Get error position */ -void exprGetErrorPosition(exprObj *obj, int *start, int *end) - { - if(obj) - { - if(start) - *start = obj->starterr; - - if(end) - *end = obj->enderr; - } - } - -/* This function will free a node's data */ -static void exprFreeNodeData(exprNode *node) - { - int pos; - - if(node == NULL) - return; - - /* free data based on type */ - switch(node->type) - { - case EXPR_NODETYPE_ADD: - case EXPR_NODETYPE_SUBTRACT: - case EXPR_NODETYPE_MULTIPLY: - case EXPR_NODETYPE_DIVIDE: - case EXPR_NODETYPE_EXPONENT: - case EXPR_NODETYPE_NEGATE: - case EXPR_NODETYPE_MULTI: - /* Free operation data */ - if(node->data.oper.nodes) - { - for(pos = 0; pos < node->data.oper.nodecount; pos++) - exprFreeNodeData(&(node->data.oper.nodes[pos])); - - exprFreeMem(node->data.oper.nodes); - } - - break; - - - case EXPR_NODETYPE_VALUE: - /* Nothing to free for value */ - break; - - case EXPR_NODETYPE_VARIABLE: - /* Nothing to free for variable */ - break; - - case EXPR_NODETYPE_FUNCTION: - /* Free data of each subnode */ - if(node->data.function.nodes) - { - for(pos = 0; pos < node->data.function.nodecount; pos++) - exprFreeNodeData(&(node->data.function.nodes[pos])); - - /* Free the subnode array */ - exprFreeMem(node->data.function.nodes); - } - - /* Free reference variable list */ - if(node->data.function.refs) - exprFreeMem(node->data.function.refs); - - break; - - case EXPR_NODETYPE_ASSIGN: - /* Free subnode data */ - if(node->data.assign.node) - { - exprFreeNodeData(node->data.assign.node); - - /* Free the subnode */ - exprFreeMem(node->data.assign.node); - } - - break; - } - } - - +/* + File: 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; + } + } + + diff --git a/src/mod/applications/mod_expr/exprpars.c b/src/mod/applications/mod_expr/exprpars.c index 81caf0bfbd..9a49f3d016 100644 --- a/src/mod/applications/mod_expr/exprpars.c +++ b/src/mod/applications/mod_expr/exprpars.c @@ -1,1558 +1,1558 @@ -/* - File: exprpars.c - Auth: Brian Allen Vanderburg II - Date: Wednesday, April 30, 2003 - Desc: Actual parsing routines for this library - - This file is part of ExprEval. -*/ - -/* Includes */ -#include "exprincl.h" - -#include "exprpriv.h" -#include "exprmem.h" - -/* Data structure used by parser */ -typedef struct _exprToken - { - int type; /* token type */ - int start; /* token start position */ - int end; /* token end position */ - - union _tdata - { - char *str; /* string data */ - EXPRTYPE val; /* value data */ - } data; - } exprToken; - -/* Defines for token types */ -#define EXPR_TOKEN_UNKNOWN 0 -#define EXPR_TOKEN_OPAREN 1 -#define EXPR_TOKEN_CPAREN 2 -#define EXPR_TOKEN_IDENTIFIER 3 -#define EXPR_TOKEN_VALUE 4 -#define EXPR_TOKEN_PLUS 5 -#define EXPR_TOKEN_HYPHEN 6 -#define EXPR_TOKEN_ASTERISK 7 -#define EXPR_TOKEN_FSLASH 8 -#define EXPR_TOKEN_AMPERSAND 9 -#define EXPR_TOKEN_SEMICOLON 10 -#define EXPR_TOKEN_COMMA 11 -#define EXPR_TOKEN_EQUAL 12 -#define EXPR_TOKEN_HAT 13 - -/* Internal functions */ -int exprMultiParse(exprObj *obj, exprNode *node, exprToken *tokens, int count); -int exprInternalParse(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end); -int exprInternalParseAssign(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); -int exprInternalParseAdd(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); -int exprInternalParseSub(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); -int exprInternalParseMul(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); -int exprInternalParseDiv(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); -int exprInternalParsePosNeg(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); -int exprInternalParseExp(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); -int exprInternalParseFunction(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int p1, int p2); -int exprInternalParseVarVal(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end); -int exprStringToTokenList(exprObj *obj, char *expr, exprToken **tokens, int *count); -void exprFreeTokenList(exprToken *tokens, int count); - -/* This frees a token list */ -void exprFreeTokenList(exprToken *tokens, int count) - { - int pos; - - if(tokens == NULL) - return; - - for(pos = 0; pos < count; pos++) - { - if(tokens[pos].type == EXPR_TOKEN_IDENTIFIER) - exprFreeMem(tokens[pos].data.str); - } - - exprFreeMem(tokens); - } - -/* This converts an expression string to a token list */ -int exprStringToTokenList(exprObj *obj, char *expr, exprToken **tokens, int *count) - { - int found; - exprToken *list; - int pass; - int pos, len; - int tpos; - int comment; /* Is a comment active */ - int start, ilen; - char buf[EXPR_MAXIDENTSIZE + 1]; - - /* Set initial variables */ - found = 0; - tpos = 0; - list = NULL; - comment = 0; - *tokens = NULL; - *count = 0; - - - /* Check string length */ - len = (int)strlen(expr); - if(len == 0) - return EXPR_ERROR_EMPTYEXPR; - - /* Two passes, one to count, one to tokenize */ - for(pass = 0; pass <= 1; pass++) - { - for(pos = 0; pos < len; pos++) - { - switch(expr[pos]) - { - /* Comment */ - case '#': - { - /* Only set it if a comment is not already active */ - if(!comment) - comment = 1; - - break; - } - - /* Newline characters turn off comments */ - case '\r': - case '\n': - { - /* If a comment is active, unset it */ - if(comment) - comment = 0; - - break; - } - - /* Open parenthesis */ - case '(': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_OPAREN; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Close parenthesis */ - case ')': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_CPAREN; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Plus */ - case '+': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_PLUS; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Hyphen */ - case '-': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_HYPHEN; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Asterisk */ - case '*': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_ASTERISK; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Forward slash */ - case '/': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_FSLASH; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Hat */ - case '^': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_HAT; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Ampersand */ - case '&': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_AMPERSAND; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Semicolon */ - case ';': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_SEMICOLON; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Comma */ - case ',': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_COMMA; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Equal sign */ - case '=': - { - if(!comment) - { - if(pass == 0) - found++; - else - { - list[tpos].type = EXPR_TOKEN_EQUAL; - list[tpos].start = pos; - list[tpos].end = pos; - tpos++; - } - } - - break; - } - - /* Identifiers and values */ - default: - { - if(!comment) - { - if(expr[pos] == '.' || isdigit(expr[pos])) - { - /* Value */ - start = pos; - - /* Find digits before a period */ - while(isdigit(expr[pos])) - pos++; - - /* Find a period */ - if(expr[pos] == '.') - pos++; - - /* Find digits after a period */ - while(isdigit(expr[pos])) - pos++; - - /* pos is AFTER last item, back up */ - pos--; - - if(pass == 0) - found++; - else - { - ilen = pos - start + 1; - - /* Is the value to large */ - if(ilen > EXPR_MAXIDENTSIZE) - { - obj->starterr = start; - obj->enderr = pos; - exprFreeTokenList(list, found); - return EXPR_ERROR_BADIDENTIFIER; - } - - /* Create value token */ - strncpy(buf, expr + start, ilen); - buf[ilen] = '\0'; - - list[tpos].type = EXPR_TOKEN_VALUE; - list[tpos].start = start; - list[tpos].end = pos; - list[tpos].data.val = (EXPRTYPE)atof(buf); - tpos++; - } - } - else if(expr[pos] == '_' || isalpha(expr[pos])) - { - /* Identifier */ - start = pos; - - /* Find rest of identifier */ - while(expr[pos] == '_' || isalnum(expr[pos])) - pos++; - - /* pos is AFTER last item, back up */ - pos--; - - if(pass == 0) - found++; - else - { - ilen = pos - start + 1; - - /* Is the value to large */ - if(ilen > EXPR_MAXIDENTSIZE) - { - obj->starterr = start; - obj->enderr = pos; - exprFreeTokenList(list, found); - return EXPR_ERROR_BADIDENTIFIER; - } - - /* Create value token */ - strncpy(buf, expr + start, ilen); - buf[ilen] = '\0'; - - /* Allocate memory for identifier */ - list[tpos].data.str = exprAllocMem(ilen + 1); - if(list[tpos].data.str == NULL) - { - exprFreeTokenList(list, found); - return EXPR_ERROR_MEMORY; - } - - list[tpos].type = EXPR_TOKEN_IDENTIFIER; - list[tpos].start = start; - list[tpos].end = pos; - strcpy(list[tpos].data.str, buf); - tpos++; - } - } - else if(isspace(expr[pos])) - { - /* Spaces are ignored, do nothing */ - } - else - { - /* Unknown */ - obj->starterr = obj->enderr = pos; - exprFreeTokenList(list, found); - return EXPR_ERROR_INVALIDCHAR; - } - } - - break; - } - } - } - - /* If pass is 0, allocate memory for next pass */ - if(pass == 0) - { - /* First, make sure all comments were ended */ - if(comment) - comment = 0; - - /* Make sure the expression is not empty */ - if(found == 0) - return EXPR_ERROR_EMPTYEXPR; - - /* Allocate memory for token list */ - list = exprAllocMem(found * sizeof(exprToken)); - if(list == NULL) - return EXPR_ERROR_MEMORY; - - tpos = 0; - } - } - - *count = found; - *tokens = list; - return EXPR_ERROR_NOERROR; - } - - -/* This is the main parsing routine */ -int exprParse(exprObj *obj, char *expr) - { - exprToken *tokens; - int count; - int err; - exprNode *tmp; - - /* Make sure an object was passed */ - if(obj == NULL) - return EXPR_ERROR_NULLPOINTER; - - /* Clear expression error position */ - obj->starterr = obj->enderr = -1; - - /* Have we already been parsed? */ - if(obj->parsedbad != 0) - return EXPR_ERROR_ALREADYPARSEDBAD; - - if(obj->parsedgood != 0) - return EXPR_ERROR_ALREADYPARSEDGOOD; - - /* Make sure an expression was passed */ - if(expr == NULL) - return EXPR_ERROR_NULLPOINTER; - - /* Create token list */ - err = exprStringToTokenList(obj, expr, &tokens, &count); - if(err != EXPR_ERROR_NOERROR) - return err; - - /* Create head pointer */ - tmp = exprAllocNodes(1); - if(tmp == NULL) - { - exprFreeTokenList(tokens, count); - return EXPR_ERROR_MEMORY; - } - - obj->headnode = tmp; - - /* Call the multiparse routine to parse subexpressions */ - err = exprMultiParse(obj, tmp, tokens, count); - - /* Free the token list */ - exprFreeTokenList(tokens, count); - - /* successful parse? */ - if(err == EXPR_ERROR_NOERROR) - { - obj->parsedgood = 1; - obj->parsedbad = 0; - } - else - { - obj->parsedbad = 1; - obj->parsedgood = 0; - } - - return err; - } - - -/* Parse the subexpressions, each ending with semicolons */ -int exprMultiParse(exprObj *obj, exprNode *node, exprToken *tokens, int count) - { - int pos, plevel, last; - int num, cur, err; - exprNode *tmp; - - plevel = 0; - num = 0; - last = -1; - - /* First count the number of arguments */ - for(pos = 0; pos < count; pos++) - { - switch(tokens[pos].type) - { - case EXPR_TOKEN_OPAREN: - /* increase plevel */ - plevel++; - break; - - case EXPR_TOKEN_CPAREN: - /* decrease plevel */ - plevel--; - - if(plevel < 0) - { - obj->starterr = tokens[pos].start; - obj->enderr = tokens[pos].end; - return EXPR_ERROR_UNMATCHEDPAREN; - } - - break; - - case EXPR_TOKEN_SEMICOLON: - if(plevel == 0) - { - if(last == pos - 1 || pos == 0) - { - /* last semicolon is before us or we are at the start */ - obj->starterr = tokens[pos].start; - obj->enderr = tokens[pos].end; - return EXPR_ERROR_SYNTAX; - } - else - { - /* last semicolon is not right before us */ - num++; - } - } - else - { - /* Semicolon should not be in a parenthesis */ - obj->starterr = tokens[pos].start; - obj->enderr = tokens[pos].end; - return EXPR_ERROR_SYNTAX; - } - - last = pos; /* update position of last semicolon */ - break; - } - } - - /* plevel should be zero now */ - if(plevel != 0) - return EXPR_ERROR_UNMATCHEDPAREN; - - /* the last character should be a semicolon */ - if(last != pos - 1) - return EXPR_ERROR_MISSINGSEMICOLON; - - /* Now we know how many arguments there are */ - - /* Allocate array of subnodes */ - tmp = exprAllocNodes(num); - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - /* Set the current node's data */ - node->type = EXPR_NODETYPE_MULTI; - node->data.oper.nodes = tmp; - node->data.oper.nodecount = num; - - /* now we parse each subexpression */ - last = 0; /* Not for last semicolon, but for first char of subexpr */ - cur = 0; - - for(pos = 0; pos < count; pos++) - { - if(tokens[pos].type == EXPR_TOKEN_SEMICOLON) - { - /* Everything from last up to pos - 1 is a parameter */ - err = exprInternalParse(obj, &(tmp[cur]), tokens, last, pos - 1); - if(err != EXPR_ERROR_NOERROR) - return err; - - /* Update last position and current argument */ - last = pos + 1; - cur++; - } - } - - return EXPR_ERROR_NOERROR; - } - -/* This function parses each subnode and recurses if needed */ -int exprInternalParse(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end) - { - int pos; - int plevel = 0; /* Paren level */ - int fgopen = -1; /* First paren group open index */ - int fgclose = -1; /* First paren group close index */ - int assignindex = -1; /* First = at plevel 0 for assignment */ - int addsubindex = -1; /* Last + or - at plevel 0 for adding or subtracting */ - int muldivindex = -1; /* Last * or / at plevel 0 for multiplying or dividing */ - int expindex = -1; /* Last ^ fount at plevel 0 for exponents */ - int posnegindex = -1; /* First +,- at plevel 0 for positive,negative */ - - /* Make sure some conditions are right */ - if(start > end) - return EXPR_ERROR_UNKNOWN; - - /* Scan the string for certain characters */ - for(pos = start; pos <= end; pos++) - { - switch(tokens[pos].type) - { - case EXPR_TOKEN_OPAREN: - plevel++; - - /* First group open? */ - if(plevel == 1 && fgopen == -1) - fgopen = pos; - break; - - case EXPR_TOKEN_CPAREN: - plevel--; - - /* First group close? */ - if(plevel == 0 && fgclose == -1) - fgclose = pos; - - if(plevel < 0) - { - obj->starterr = tokens[pos].start; - obj->enderr = tokens[pos].end; - return EXPR_ERROR_UNMATCHEDPAREN; - } - break; - - case EXPR_TOKEN_EQUAL: - /* Assignment found */ - if(plevel == 0) - { - if(assignindex == -1) - assignindex = pos; - } - break; - - case EXPR_TOKEN_ASTERISK: - case EXPR_TOKEN_FSLASH: - /* Multiplication or division */ - if(plevel == 0) - muldivindex = pos; - break; - - case EXPR_TOKEN_HAT: - /* Exponent */ - if(plevel == 0) - expindex = pos; - break; - - - case EXPR_TOKEN_PLUS: - case EXPR_TOKEN_HYPHEN: - /* Addition or positive or subtraction or negative*/ - if(plevel == 0) - { - if(pos == start) - { - /* At the start area, positive/negative */ - if(posnegindex == -1) - posnegindex = pos; - } - else - { - /* Not at start, check item in front */ - switch(tokens[pos - 1].type) - { - case EXPR_TOKEN_EQUAL: /* Equal sign */ - case EXPR_TOKEN_PLUS: /* Add/positive sign */ - case EXPR_TOKEN_HYPHEN: /* Subtract/negative sign */ - case EXPR_TOKEN_ASTERISK: /* Multiply sign */ - case EXPR_TOKEN_FSLASH: /* Divide sign */ - case EXPR_TOKEN_HAT: /* Exponent sign */ - - /* After theses, it is positive/negative */ - if(posnegindex == -1) - posnegindex = pos; - - break; - - default: - /* Otherwise it is addition/subtraction */ - addsubindex = pos; - break; - } - } - } - break; - - } - } - - /* plevel should now be zero */ - if(plevel != 0) - return EXPR_ERROR_UNMATCHEDPAREN; - - /* We must parse the data in a certain order to maintain the - correct order of operators at evaluation time */ - - /* First, take care of assignment */ - if(assignindex != -1) - return exprInternalParseAssign(obj, node, tokens, start, end, assignindex); - - /* Addition or subtraction is next */ - if(addsubindex != -1) - { - if(tokens[addsubindex].type == EXPR_TOKEN_PLUS) - return exprInternalParseAdd(obj, node, tokens, start, end, addsubindex); - else - return exprInternalParseSub(obj, node, tokens, start, end, addsubindex); - } - - - /* Multiplycation or division */ - if(muldivindex != -1) - { - if(tokens[muldivindex].type == EXPR_TOKEN_ASTERISK) - return exprInternalParseMul(obj, node, tokens, start, end, muldivindex); - else - return exprInternalParseDiv(obj, node, tokens, start, end, muldivindex); - } - - /* Exponent */ - if(expindex != -1) - return exprInternalParseExp(obj, node, tokens, start, end, expindex); - - /* Negation */ - if(posnegindex != -1) - return exprInternalParsePosNeg(obj, node, tokens, start, end, posnegindex); - - - /* Grouped parenthesis */ - if(fgopen == start) - { - /* Closing paren. should be at the end */ - if(fgclose == end) - { - /* Anything between them */ - if(fgclose > fgopen + 1) - { - return exprInternalParse(obj, node, tokens, fgopen + 1, fgclose - 1); - } - else - { - /* Nothing between them */ - obj->starterr = tokens[fgopen].start; - obj->enderr = tokens[fgclose].end; - return EXPR_ERROR_SYNTAX; - } - } - else /* Closing paren not at the end */ - return EXPR_ERROR_SYNTAX; - } - - /* Functions */ - if(fgopen > start) - { - /* Closing paren should be at end */ - if(fgclose == end) - { - return exprInternalParseFunction(obj, node, tokens, start, end, fgopen, fgclose); - } - else /* Closing paren not at end */ - return EXPR_ERROR_SYNTAX; - } - - /* If it was none of the above, it must be a variable or value */ - return exprInternalParseVarVal(obj, node, tokens, start, end); - } - -/* Function to parse an assignment node */ -int exprInternalParseAssign(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) - { - exprNode *tmp; - exprValList *l; - EXPRTYPE *addr; - - /* Make sure the equal sign is not at the start or end */ - if(index != start + 1 || index >= end) - { - obj->starterr = tokens[index].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_SYNTAX; - } - - /* Make sure item before equal sign is an identifier */ - if(tokens[index - 1].type != EXPR_TOKEN_IDENTIFIER) - { - obj->starterr = tokens[index - 1].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_SYNTAX; - } - - /* Create expression subnode */ - tmp = exprAllocNodes(1); - if(tmp == NULL) - { - return EXPR_ERROR_MEMORY; - } - - - /* Set the data */ - node->type = EXPR_NODETYPE_ASSIGN; - node->data.assign.node = tmp; - - - /* - The fast access method directly accesses the memory address - of the variable's value at evaluation time. Because of this, - we must make sure the variable does exists in the variable list. - */ - - /* Make sure name is not a constant name */ - l = exprGetConstList(obj); - if(l) - { - exprValListGetAddress(l, tokens[index - 1].data.str, &addr); - if(addr) - { - obj->starterr = tokens[index - 1].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_CONSTANTASSIGN; - } - } - - /* Get the variable list */ - l = exprGetVarList(obj); - if(l == NULL) - return EXPR_ERROR_NOVARLIST; - - /* Get variable address if already in the list */ - exprValListGetAddress(l, tokens[index - 1].data.str, &addr); - if(addr == NULL) /* Variable not in the list, add it */ - { - exprValListAdd(l, tokens[index - 1].data.str, 0.0); - - /* Try to get address again */ - exprValListGetAddress(l, tokens[index - 1].data.str, &addr); - if(addr == NULL) /* Could not add variable */ - return EXPR_ERROR_MEMORY; /* Could not add variable to list */ - } - - node->data.assign.vaddr = addr; - - /* Parse the subnode */ - return exprInternalParse(obj, tmp, tokens, index + 1, end); - } - -/* Function to parse an addition operator */ -int exprInternalParseAdd(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) - { - exprNode *tmp; - int err; - - /* Make sure plus sign is at a good place */ - if(index <= start || index >= end) - { - obj->starterr = tokens[index].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_SYNTAX; - } - - /* Allocate space for 2 subnodes */ - tmp = exprAllocNodes(2); - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - - /* Set the data */ - node->type = EXPR_NODETYPE_ADD; - node->data.oper.nodes = tmp; - node->data.oper.nodecount = 2; - - /* parse the left side */ - err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); - if(err != EXPR_ERROR_NOERROR) - return err; - - /* parse the right side */ - return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); - } - -/* Function to parse a subtraction operator */ -int exprInternalParseSub(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) - { - exprNode *tmp; - int err; - - /* Make sure minus sign is at a good place */ - if(index <= start || index >= end) - { - obj->starterr = tokens[index].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_SYNTAX; - } - - /* Allocate space for 2 subnodes */ - tmp = exprAllocNodes(2); - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - - /* Set the data */ - node->type = EXPR_NODETYPE_SUBTRACT; - node->data.oper.nodes = tmp; - node->data.oper.nodecount = 2; - - /* parse the left side */ - err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); - if(err != EXPR_ERROR_NOERROR) - return err; - - /* parse the right side */ - return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); - } - -/* Function to parse a multiplication operator */ -int exprInternalParseMul(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) - { - exprNode *tmp; - int err; - - /* Make sure times sign is at a good place */ - if(index <= start || index >= end) - { - obj->starterr = tokens[index].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_SYNTAX; - } - - - /* Allocate space for 2 subnodes */ - tmp = exprAllocNodes(2); - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - - /* Set the data */ - node->type = EXPR_NODETYPE_MULTIPLY; - node->data.oper.nodes = tmp; - node->data.oper.nodecount = 2; - - /* parse the left side */ - err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); - if(err != EXPR_ERROR_NOERROR) - return err; - - /* parse the right side */ - return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); - } - -/* Function to parse a division operator */ -int exprInternalParseDiv(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) - { - exprNode *tmp; - int err; - - /* Make sure slash sign is at a good place */ - if(index <= start || index >= end) - { - obj->starterr = tokens[index].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_SYNTAX; - } - - - /* Allocate space for 2 subnodes */ - tmp = exprAllocNodes(2); - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - - /* Set the data */ - node->type = EXPR_NODETYPE_DIVIDE; - node->data.oper.nodes = tmp; - node->data.oper.nodecount = 2; - - /* parse the left side */ - err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); - if(err != EXPR_ERROR_NOERROR) - return err; - - /* parse the right side */ - return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); - } - -/* Function to parse an exponent operator */ -int exprInternalParseExp(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) - { - exprNode *tmp; - int err; - - /* Make sure exponent sign is at a good place */ - if(index <= start || index >= end) - { - obj->starterr = tokens[index].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_SYNTAX; - } - - - /* Allocate space for 2 subnodes */ - tmp = exprAllocNodes(2); - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - - - /* Set the data */ - node->type = EXPR_NODETYPE_EXPONENT; - node->data.oper.nodes = tmp; - node->data.oper.nodecount = 2; - - /* parse the left side */ - err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); - if(err != EXPR_ERROR_NOERROR) - return err; - - /* parse the right side */ - return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); - } - -/* Function to parse for positive and negative */ -int exprInternalParsePosNeg(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) - { - exprNode *tmp; - - /* Position should be the same as start */ - if(index != start) - { - obj->starterr = tokens[index].start; - obj->enderr = tokens[index].end; - return EXPR_ERROR_UNKNOWN; - } - - /* If it is a positive, just parse the internal of it */ - if(tokens[index].type == EXPR_TOKEN_PLUS) - return exprInternalParse(obj, node, tokens, index + 1, end); - else - { - /* Allocate subnode */ - tmp = exprAllocNodes(1); - if(tmp == NULL) - return EXPR_ERROR_NOERROR; - - - /* Set data */ - node->type = EXPR_NODETYPE_NEGATE; - node->data.oper.nodes = tmp; - node->data.oper.nodecount = 1; - - /* Parse the subnode */ - return exprInternalParse(obj, tmp, tokens, index + 1, end); - } - } - -/* Function will parse a call to a function */ -int exprInternalParseFunction(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int p1, int p2) - { - int pos; - int num, cur; - int refnum, refcur; - int plevel = 0; - int lv, err; - exprNode *tmp; - exprFuncType fptr; - int argmin, argmax; - int refargmin, refargmax; - int type; - exprFuncList *l; - exprValList *vars; - EXPRTYPE *addr; - EXPRTYPE **reftmp; - - /* We should have a function list */ - l = exprGetFuncList(obj); - if(l == NULL) - return EXPR_ERROR_NOSUCHFUNCTION; - - /* check paren. location */ - if(p2 <= p1) - return EXPR_ERROR_SYNTAX; - - /* second paren. should not be after the end */ - if(p2 > end) - return EXPR_ERROR_SYNTAX; - - /* Item before parenthesis should be an identifier */ - if(tokens[p1 - 1].type != EXPR_TOKEN_IDENTIFIER) - { - obj->starterr = tokens[p1 - 1].start; - obj->enderr = tokens[p1].end; - return EXPR_ERROR_SYNTAX; - } - - - /* Look up the function */ - err = exprFuncListGet(l, tokens[p1 - 1].data.str, &fptr, &type, &argmin, &argmax, &refargmin, &refargmax); - if(err != EXPR_ERROR_NOERROR) - { - if(err == EXPR_ERROR_NOTFOUND) - { - obj->starterr = tokens[p1 - 1].start; - obj->enderr = tokens[p1 - 1].end; - return EXPR_ERROR_NOSUCHFUNCTION; - } - else - return err; - } - - /* Make sure the function exists */ - if(fptr == NULL && type == 0) - { - obj->starterr = tokens[p1 - 1].start; - obj->enderr = tokens[p1 - 1].end; - return EXPR_ERROR_NOSUCHFUNCTION; - } - - /* Count arguments */ - if(p2 == p1 + 1) - { - num = 0; - refnum = 0; - } - else - { - num = 1; - refnum = 0; - - - /* count commas */ - for(pos = p1 + 1; pos < p2; pos++) - { - switch(tokens[pos].type) - { - case EXPR_TOKEN_OPAREN: - plevel++; - break; - - case EXPR_TOKEN_CPAREN: - plevel--; - if(plevel < 0) - { - obj->starterr = tokens[pos].start; - obj->enderr = tokens[pos].end; - return EXPR_ERROR_UNMATCHEDPAREN; - } - break; - - case EXPR_TOKEN_COMMA: - /* Found comma */ - if(plevel == 0) - num++; - break; - - case EXPR_TOKEN_AMPERSAND: - /* Found reference mark */ - if(plevel == 0) - { - /* This may only occur after the open parenthesis or comma */ - if(tokens[pos - 1].type == EXPR_TOKEN_OPAREN || tokens[pos - 1].type == EXPR_TOKEN_COMMA) - refnum++; - else - return EXPR_ERROR_SYNTAX; - } - break; - } - } - - /* plevel should be zero */ - if(plevel != 0) - return EXPR_ERROR_UNMATCHEDPAREN; - } - - /* We now have the number of total arguments and - number of ref arguments. Get number of normal - arguments */ - num = num - refnum; - - /* Make sure number of arguments is correct */ - /* Here we make sure the limits are greater - or equal to zero because any negative number - could be used to specify no limit */ - if(argmin >= 0 && num < argmin) - { - obj->starterr = tokens[p1 - 1].start; - obj->enderr = tokens[p2].end; - return EXPR_ERROR_BADNUMBERARGUMENTS; - } - - if(argmax >= 0 && num > argmax) - { - obj->starterr = tokens[p1 - 1].start; - obj->enderr = tokens[p2].end; - return EXPR_ERROR_BADNUMBERARGUMENTS; - } - - if(refargmin >= 0 && refnum < refargmin) - { - obj->starterr = tokens[p1 - 1].start; - obj->enderr = tokens[p2].end; - return EXPR_ERROR_BADNUMBERARGUMENTS; - } - - if(refargmax >= 0 && refnum > refargmax) - { - obj->starterr = tokens[p1 - 1].start; - obj->enderr = tokens[p2].end; - return EXPR_ERROR_BADNUMBERARGUMENTS; - } - - /* Set tmp to null in case of no arguments */ - tmp = NULL; - reftmp = NULL; - - if(num > 0) - { - /* Allocate subnodes */ - tmp = exprAllocNodes(num); - if(tmp == NULL) - return EXPR_ERROR_MEMORY; - } - - if(refnum > 0) - { - /* Allocate ref pointers */ - reftmp = exprAllocMem(sizeof(EXPRTYPE*) * refnum); - if(reftmp == NULL) - { - exprFreeMem(tmp); - return EXPR_ERROR_MEMORY; - } - } - - - - /* Set this node's data */ - node->type = EXPR_NODETYPE_FUNCTION; - node->data.function.fptr = fptr; - node->data.function.nodecount = num; - node->data.function.nodes = tmp; - node->data.function.refcount = refnum; - node->data.function.refs = reftmp; - node->data.function.type = type; - - /* parse each subnode */ - if(num + refnum > 0) - { - plevel = 0; - cur = 0; - refcur = 0; - lv = p1 + 1; - - /* look for commas if more than 1 arg */ - if(num + refnum > 1) - { - for(pos = p1 + 1; pos < p2; pos++) - { - switch(tokens[pos].type) - { - case EXPR_TOKEN_OPAREN: - plevel++; - break; - - case EXPR_TOKEN_CPAREN: - plevel--; - break; /* Already checked paren nesting above */ - - case EXPR_TOKEN_COMMA: - /* Found comma */ - if(plevel == 0) - { - /* parse inside */ - if(tokens[lv].type == EXPR_TOKEN_AMPERSAND) - { - if(lv != pos - 2) - { - obj->starterr = tokens[lv].start; - obj->enderr = tokens[pos].end; - return EXPR_ERROR_SYNTAX; - } - - /* It is a reference */ - if(tokens[lv + 1].type != EXPR_TOKEN_IDENTIFIER) - { - obj->starterr = tokens[lv].start; - obj->enderr = tokens[lv + 1].end; - return EXPR_ERROR_SYNTAX; - } - - - /* Make sure it is not a constant */ - vars = exprGetConstList(obj); - if(vars) - { - exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); - if(addr) - { - obj->starterr = tokens[lv].start; - obj->enderr = tokens[lv + 1].start; - return EXPR_ERROR_REFCONSTANT; - } - } - - /* Get variable list */ - vars = exprGetVarList(obj); - if(vars == NULL) - return EXPR_ERROR_NOVARLIST; - - /* Get variable address */ - exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); - if(addr == NULL) - { - /* Add variable to list */ - exprValListAdd(vars, tokens[lv + 1].data.str, 0.0); - - /* Try to get address again */ - exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); - if(addr == NULL) - return EXPR_ERROR_MEMORY; /* Could not add variable */ - } - - /* Set reference item */ - reftmp[refcur] = addr; - - /* increase ref arg number and lv position*/ - refcur++; - lv = pos + 1; - } - else - { - err = exprInternalParse(obj, &(tmp[cur]), tokens, lv, pos - 1); - if(err != EXPR_ERROR_NOERROR) - return err; - - /* increase arg number and lv position*/ - lv = pos + 1; - cur++; - } - } - break; - } - } - } - - /* lv should point after the last comma, or open paren. if only 1 arg */ - if(tokens[lv].type == EXPR_TOKEN_AMPERSAND) - { - if(lv != p2 - 2) - { - obj->starterr = tokens[lv].start; - obj->enderr = tokens[p2].end; - return EXPR_ERROR_SYNTAX; - } - - /* It is a reference */ - if(tokens[lv + 1].type != EXPR_TOKEN_IDENTIFIER) - { - obj->starterr = tokens[lv].start; - obj->enderr = tokens[lv + 1].end; - return EXPR_ERROR_SYNTAX; - } - - /* Make sure it is not a constant */ - vars = exprGetConstList(obj); - if(vars) - { - exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); - if(addr) - { - obj->starterr = tokens[lv].start; - obj->enderr = tokens[lv + 1].start; - return EXPR_ERROR_REFCONSTANT; - } - } - - /* Get variable list */ - vars = exprGetVarList(obj); - if(vars == NULL) - return EXPR_ERROR_NOVARLIST; - - /* Get variable address */ - exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); - if(addr == NULL) - { - /* Add variable to list */ - exprValListAdd(vars, tokens[lv + 1].data.str, 0.0); - - /* Try to get address again */ - exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); - if(addr == NULL) - return EXPR_ERROR_MEMORY; /* Could not add variable */ - } - - /* Set reference item */ - reftmp[refcur] = addr; - } - else - { - err = exprInternalParse(obj, &(tmp[cur]), tokens, lv, p2 - 1); - if(err != EXPR_ERROR_NOERROR) - return err; - } - } - - - return EXPR_ERROR_NOERROR; - } - -/* Parse a variable or value */ -int exprInternalParseVarVal(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end) - { - exprValList *l; - EXPRTYPE *addr; - - - /* Make sure positions are correct */ - if(start != end) - { - return EXPR_ERROR_UNKNOWN; - } - - - /* Are we an identifier */ - if(tokens[start].type == EXPR_TOKEN_IDENTIFIER) - { - /* we are an identifier */ - - /* check to see if it is a constant */ - l = exprGetConstList(obj); - if(l != NULL) - { - if(exprValListGetAddress(l, tokens[start].data.str, &addr) == EXPR_ERROR_NOERROR) - { - /* We found it in the constant list */ - - /* - Treat is like a variable node so application can change - constant value and it will reflect in expression - */ - - node->type = EXPR_NODETYPE_VARIABLE; - node->data.variable.vaddr = addr; - return EXPR_ERROR_NOERROR; - } - } - - /* Not found in the constant list, so it must be a variable */ - - /* Set node type */ - node->type = EXPR_NODETYPE_VARIABLE; - - /* - The fast access method directly accesses the memory address - of the variable's value at evaluation time. Because of this, - we must make sure the variable does exists in the variable list. - */ - - /* Get the variable list */ - l = exprGetVarList(obj); - if(l == NULL) - return EXPR_ERROR_NOVARLIST; - - /* Get variable address if already in the list */ - exprValListGetAddress(l, tokens[start].data.str, &addr); - if(addr == NULL) /* Variable not in the list, add it */ - { - exprValListAdd(l, tokens[start].data.str, 0.0); - - /* Try to get address again */ - exprValListGetAddress(l, tokens[start].data.str, &addr); - if(addr == NULL) /* Could not add variable */ - return EXPR_ERROR_MEMORY; /* Could not add variable to list */ - } - - node->data.variable.vaddr = addr; - - return EXPR_ERROR_NOERROR; - } - else if(tokens[start].type == EXPR_TOKEN_VALUE) - { - /* we are a value */ - node->type = EXPR_NODETYPE_VALUE; - node->data.value.value = tokens[start].data.val; - return EXPR_ERROR_NOERROR; - } - else - { - obj->starterr = tokens[start].start; - obj->enderr = tokens[end].end; - return EXPR_ERROR_UNKNOWN; - } - } +/* + File: exprpars.c + Auth: Brian Allen Vanderburg II + Date: Wednesday, April 30, 2003 + Desc: Actual parsing routines for this library + + This file is part of ExprEval. +*/ + +/* Includes */ +#include "exprincl.h" + +#include "exprpriv.h" +#include "exprmem.h" + +/* Data structure used by parser */ +typedef struct _exprToken + { + int type; /* token type */ + int start; /* token start position */ + int end; /* token end position */ + + union _tdata + { + char *str; /* string data */ + EXPRTYPE val; /* value data */ + } data; + } exprToken; + +/* Defines for token types */ +#define EXPR_TOKEN_UNKNOWN 0 +#define EXPR_TOKEN_OPAREN 1 +#define EXPR_TOKEN_CPAREN 2 +#define EXPR_TOKEN_IDENTIFIER 3 +#define EXPR_TOKEN_VALUE 4 +#define EXPR_TOKEN_PLUS 5 +#define EXPR_TOKEN_HYPHEN 6 +#define EXPR_TOKEN_ASTERISK 7 +#define EXPR_TOKEN_FSLASH 8 +#define EXPR_TOKEN_AMPERSAND 9 +#define EXPR_TOKEN_SEMICOLON 10 +#define EXPR_TOKEN_COMMA 11 +#define EXPR_TOKEN_EQUAL 12 +#define EXPR_TOKEN_HAT 13 + +/* Internal functions */ +int exprMultiParse(exprObj *obj, exprNode *node, exprToken *tokens, int count); +int exprInternalParse(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end); +int exprInternalParseAssign(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); +int exprInternalParseAdd(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); +int exprInternalParseSub(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); +int exprInternalParseMul(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); +int exprInternalParseDiv(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); +int exprInternalParsePosNeg(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); +int exprInternalParseExp(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index); +int exprInternalParseFunction(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int p1, int p2); +int exprInternalParseVarVal(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end); +int exprStringToTokenList(exprObj *obj, char *expr, exprToken **tokens, int *count); +void exprFreeTokenList(exprToken *tokens, int count); + +/* This frees a token list */ +void exprFreeTokenList(exprToken *tokens, int count) + { + int pos; + + if(tokens == NULL) + return; + + for(pos = 0; pos < count; pos++) + { + if(tokens[pos].type == EXPR_TOKEN_IDENTIFIER) + exprFreeMem(tokens[pos].data.str); + } + + exprFreeMem(tokens); + } + +/* This converts an expression string to a token list */ +int exprStringToTokenList(exprObj *obj, char *expr, exprToken **tokens, int *count) + { + int found; + exprToken *list; + int pass; + int pos, len; + int tpos; + int comment; /* Is a comment active */ + int start, ilen; + char buf[EXPR_MAXIDENTSIZE + 1]; + + /* Set initial variables */ + found = 0; + tpos = 0; + list = NULL; + comment = 0; + *tokens = NULL; + *count = 0; + + + /* Check string length */ + len = (int)strlen(expr); + if(len == 0) + return EXPR_ERROR_EMPTYEXPR; + + /* Two passes, one to count, one to tokenize */ + for(pass = 0; pass <= 1; pass++) + { + for(pos = 0; pos < len; pos++) + { + switch(expr[pos]) + { + /* Comment */ + case '#': + { + /* Only set it if a comment is not already active */ + if(!comment) + comment = 1; + + break; + } + + /* Newline characters turn off comments */ + case '\r': + case '\n': + { + /* If a comment is active, unset it */ + if(comment) + comment = 0; + + break; + } + + /* Open parenthesis */ + case '(': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_OPAREN; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Close parenthesis */ + case ')': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_CPAREN; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Plus */ + case '+': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_PLUS; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Hyphen */ + case '-': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_HYPHEN; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Asterisk */ + case '*': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_ASTERISK; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Forward slash */ + case '/': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_FSLASH; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Hat */ + case '^': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_HAT; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Ampersand */ + case '&': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_AMPERSAND; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Semicolon */ + case ';': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_SEMICOLON; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Comma */ + case ',': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_COMMA; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Equal sign */ + case '=': + { + if(!comment) + { + if(pass == 0) + found++; + else + { + list[tpos].type = EXPR_TOKEN_EQUAL; + list[tpos].start = pos; + list[tpos].end = pos; + tpos++; + } + } + + break; + } + + /* Identifiers and values */ + default: + { + if(!comment) + { + if(expr[pos] == '.' || isdigit(expr[pos])) + { + /* Value */ + start = pos; + + /* Find digits before a period */ + while(isdigit(expr[pos])) + pos++; + + /* Find a period */ + if(expr[pos] == '.') + pos++; + + /* Find digits after a period */ + while(isdigit(expr[pos])) + pos++; + + /* pos is AFTER last item, back up */ + pos--; + + if(pass == 0) + found++; + else + { + ilen = pos - start + 1; + + /* Is the value to large */ + if(ilen > EXPR_MAXIDENTSIZE) + { + obj->starterr = start; + obj->enderr = pos; + exprFreeTokenList(list, found); + return EXPR_ERROR_BADIDENTIFIER; + } + + /* Create value token */ + strncpy(buf, expr + start, ilen); + buf[ilen] = '\0'; + + list[tpos].type = EXPR_TOKEN_VALUE; + list[tpos].start = start; + list[tpos].end = pos; + list[tpos].data.val = (EXPRTYPE)atof(buf); + tpos++; + } + } + else if(expr[pos] == '_' || isalpha(expr[pos])) + { + /* Identifier */ + start = pos; + + /* Find rest of identifier */ + while(expr[pos] == '_' || isalnum(expr[pos])) + pos++; + + /* pos is AFTER last item, back up */ + pos--; + + if(pass == 0) + found++; + else + { + ilen = pos - start + 1; + + /* Is the value to large */ + if(ilen > EXPR_MAXIDENTSIZE) + { + obj->starterr = start; + obj->enderr = pos; + exprFreeTokenList(list, found); + return EXPR_ERROR_BADIDENTIFIER; + } + + /* Create value token */ + strncpy(buf, expr + start, ilen); + buf[ilen] = '\0'; + + /* Allocate memory for identifier */ + list[tpos].data.str = exprAllocMem(ilen + 1); + if(list[tpos].data.str == NULL) + { + exprFreeTokenList(list, found); + return EXPR_ERROR_MEMORY; + } + + list[tpos].type = EXPR_TOKEN_IDENTIFIER; + list[tpos].start = start; + list[tpos].end = pos; + strcpy(list[tpos].data.str, buf); + tpos++; + } + } + else if(isspace(expr[pos])) + { + /* Spaces are ignored, do nothing */ + } + else + { + /* Unknown */ + obj->starterr = obj->enderr = pos; + exprFreeTokenList(list, found); + return EXPR_ERROR_INVALIDCHAR; + } + } + + break; + } + } + } + + /* If pass is 0, allocate memory for next pass */ + if(pass == 0) + { + /* First, make sure all comments were ended */ + if(comment) + comment = 0; + + /* Make sure the expression is not empty */ + if(found == 0) + return EXPR_ERROR_EMPTYEXPR; + + /* Allocate memory for token list */ + list = exprAllocMem(found * sizeof(exprToken)); + if(list == NULL) + return EXPR_ERROR_MEMORY; + + tpos = 0; + } + } + + *count = found; + *tokens = list; + return EXPR_ERROR_NOERROR; + } + + +/* This is the main parsing routine */ +int exprParse(exprObj *obj, char *expr) + { + exprToken *tokens; + int count; + int err; + exprNode *tmp; + + /* Make sure an object was passed */ + if(obj == NULL) + return EXPR_ERROR_NULLPOINTER; + + /* Clear expression error position */ + obj->starterr = obj->enderr = -1; + + /* Have we already been parsed? */ + if(obj->parsedbad != 0) + return EXPR_ERROR_ALREADYPARSEDBAD; + + if(obj->parsedgood != 0) + return EXPR_ERROR_ALREADYPARSEDGOOD; + + /* Make sure an expression was passed */ + if(expr == NULL) + return EXPR_ERROR_NULLPOINTER; + + /* Create token list */ + err = exprStringToTokenList(obj, expr, &tokens, &count); + if(err != EXPR_ERROR_NOERROR) + return err; + + /* Create head pointer */ + tmp = exprAllocNodes(1); + if(tmp == NULL) + { + exprFreeTokenList(tokens, count); + return EXPR_ERROR_MEMORY; + } + + obj->headnode = tmp; + + /* Call the multiparse routine to parse subexpressions */ + err = exprMultiParse(obj, tmp, tokens, count); + + /* Free the token list */ + exprFreeTokenList(tokens, count); + + /* successful parse? */ + if(err == EXPR_ERROR_NOERROR) + { + obj->parsedgood = 1; + obj->parsedbad = 0; + } + else + { + obj->parsedbad = 1; + obj->parsedgood = 0; + } + + return err; + } + + +/* Parse the subexpressions, each ending with semicolons */ +int exprMultiParse(exprObj *obj, exprNode *node, exprToken *tokens, int count) + { + int pos, plevel, last; + int num, cur, err; + exprNode *tmp; + + plevel = 0; + num = 0; + last = -1; + + /* First count the number of arguments */ + for(pos = 0; pos < count; pos++) + { + switch(tokens[pos].type) + { + case EXPR_TOKEN_OPAREN: + /* increase plevel */ + plevel++; + break; + + case EXPR_TOKEN_CPAREN: + /* decrease plevel */ + plevel--; + + if(plevel < 0) + { + obj->starterr = tokens[pos].start; + obj->enderr = tokens[pos].end; + return EXPR_ERROR_UNMATCHEDPAREN; + } + + break; + + case EXPR_TOKEN_SEMICOLON: + if(plevel == 0) + { + if(last == pos - 1 || pos == 0) + { + /* last semicolon is before us or we are at the start */ + obj->starterr = tokens[pos].start; + obj->enderr = tokens[pos].end; + return EXPR_ERROR_SYNTAX; + } + else + { + /* last semicolon is not right before us */ + num++; + } + } + else + { + /* Semicolon should not be in a parenthesis */ + obj->starterr = tokens[pos].start; + obj->enderr = tokens[pos].end; + return EXPR_ERROR_SYNTAX; + } + + last = pos; /* update position of last semicolon */ + break; + } + } + + /* plevel should be zero now */ + if(plevel != 0) + return EXPR_ERROR_UNMATCHEDPAREN; + + /* the last character should be a semicolon */ + if(last != pos - 1) + return EXPR_ERROR_MISSINGSEMICOLON; + + /* Now we know how many arguments there are */ + + /* Allocate array of subnodes */ + tmp = exprAllocNodes(num); + if(tmp == NULL) + return EXPR_ERROR_MEMORY; + + /* Set the current node's data */ + node->type = EXPR_NODETYPE_MULTI; + node->data.oper.nodes = tmp; + node->data.oper.nodecount = num; + + /* now we parse each subexpression */ + last = 0; /* Not for last semicolon, but for first char of subexpr */ + cur = 0; + + for(pos = 0; pos < count; pos++) + { + if(tokens[pos].type == EXPR_TOKEN_SEMICOLON) + { + /* Everything from last up to pos - 1 is a parameter */ + err = exprInternalParse(obj, &(tmp[cur]), tokens, last, pos - 1); + if(err != EXPR_ERROR_NOERROR) + return err; + + /* Update last position and current argument */ + last = pos + 1; + cur++; + } + } + + return EXPR_ERROR_NOERROR; + } + +/* This function parses each subnode and recurses if needed */ +int exprInternalParse(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end) + { + int pos; + int plevel = 0; /* Paren level */ + int fgopen = -1; /* First paren group open index */ + int fgclose = -1; /* First paren group close index */ + int assignindex = -1; /* First = at plevel 0 for assignment */ + int addsubindex = -1; /* Last + or - at plevel 0 for adding or subtracting */ + int muldivindex = -1; /* Last * or / at plevel 0 for multiplying or dividing */ + int expindex = -1; /* Last ^ fount at plevel 0 for exponents */ + int posnegindex = -1; /* First +,- at plevel 0 for positive,negative */ + + /* Make sure some conditions are right */ + if(start > end) + return EXPR_ERROR_UNKNOWN; + + /* Scan the string for certain characters */ + for(pos = start; pos <= end; pos++) + { + switch(tokens[pos].type) + { + case EXPR_TOKEN_OPAREN: + plevel++; + + /* First group open? */ + if(plevel == 1 && fgopen == -1) + fgopen = pos; + break; + + case EXPR_TOKEN_CPAREN: + plevel--; + + /* First group close? */ + if(plevel == 0 && fgclose == -1) + fgclose = pos; + + if(plevel < 0) + { + obj->starterr = tokens[pos].start; + obj->enderr = tokens[pos].end; + return EXPR_ERROR_UNMATCHEDPAREN; + } + break; + + case EXPR_TOKEN_EQUAL: + /* Assignment found */ + if(plevel == 0) + { + if(assignindex == -1) + assignindex = pos; + } + break; + + case EXPR_TOKEN_ASTERISK: + case EXPR_TOKEN_FSLASH: + /* Multiplication or division */ + if(plevel == 0) + muldivindex = pos; + break; + + case EXPR_TOKEN_HAT: + /* Exponent */ + if(plevel == 0) + expindex = pos; + break; + + + case EXPR_TOKEN_PLUS: + case EXPR_TOKEN_HYPHEN: + /* Addition or positive or subtraction or negative*/ + if(plevel == 0) + { + if(pos == start) + { + /* At the start area, positive/negative */ + if(posnegindex == -1) + posnegindex = pos; + } + else + { + /* Not at start, check item in front */ + switch(tokens[pos - 1].type) + { + case EXPR_TOKEN_EQUAL: /* Equal sign */ + case EXPR_TOKEN_PLUS: /* Add/positive sign */ + case EXPR_TOKEN_HYPHEN: /* Subtract/negative sign */ + case EXPR_TOKEN_ASTERISK: /* Multiply sign */ + case EXPR_TOKEN_FSLASH: /* Divide sign */ + case EXPR_TOKEN_HAT: /* Exponent sign */ + + /* After theses, it is positive/negative */ + if(posnegindex == -1) + posnegindex = pos; + + break; + + default: + /* Otherwise it is addition/subtraction */ + addsubindex = pos; + break; + } + } + } + break; + + } + } + + /* plevel should now be zero */ + if(plevel != 0) + return EXPR_ERROR_UNMATCHEDPAREN; + + /* We must parse the data in a certain order to maintain the + correct order of operators at evaluation time */ + + /* First, take care of assignment */ + if(assignindex != -1) + return exprInternalParseAssign(obj, node, tokens, start, end, assignindex); + + /* Addition or subtraction is next */ + if(addsubindex != -1) + { + if(tokens[addsubindex].type == EXPR_TOKEN_PLUS) + return exprInternalParseAdd(obj, node, tokens, start, end, addsubindex); + else + return exprInternalParseSub(obj, node, tokens, start, end, addsubindex); + } + + + /* Multiplycation or division */ + if(muldivindex != -1) + { + if(tokens[muldivindex].type == EXPR_TOKEN_ASTERISK) + return exprInternalParseMul(obj, node, tokens, start, end, muldivindex); + else + return exprInternalParseDiv(obj, node, tokens, start, end, muldivindex); + } + + /* Exponent */ + if(expindex != -1) + return exprInternalParseExp(obj, node, tokens, start, end, expindex); + + /* Negation */ + if(posnegindex != -1) + return exprInternalParsePosNeg(obj, node, tokens, start, end, posnegindex); + + + /* Grouped parenthesis */ + if(fgopen == start) + { + /* Closing paren. should be at the end */ + if(fgclose == end) + { + /* Anything between them */ + if(fgclose > fgopen + 1) + { + return exprInternalParse(obj, node, tokens, fgopen + 1, fgclose - 1); + } + else + { + /* Nothing between them */ + obj->starterr = tokens[fgopen].start; + obj->enderr = tokens[fgclose].end; + return EXPR_ERROR_SYNTAX; + } + } + else /* Closing paren not at the end */ + return EXPR_ERROR_SYNTAX; + } + + /* Functions */ + if(fgopen > start) + { + /* Closing paren should be at end */ + if(fgclose == end) + { + return exprInternalParseFunction(obj, node, tokens, start, end, fgopen, fgclose); + } + else /* Closing paren not at end */ + return EXPR_ERROR_SYNTAX; + } + + /* If it was none of the above, it must be a variable or value */ + return exprInternalParseVarVal(obj, node, tokens, start, end); + } + +/* Function to parse an assignment node */ +int exprInternalParseAssign(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) + { + exprNode *tmp; + exprValList *l; + EXPRTYPE *addr; + + /* Make sure the equal sign is not at the start or end */ + if(index != start + 1 || index >= end) + { + obj->starterr = tokens[index].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_SYNTAX; + } + + /* Make sure item before equal sign is an identifier */ + if(tokens[index - 1].type != EXPR_TOKEN_IDENTIFIER) + { + obj->starterr = tokens[index - 1].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_SYNTAX; + } + + /* Create expression subnode */ + tmp = exprAllocNodes(1); + if(tmp == NULL) + { + return EXPR_ERROR_MEMORY; + } + + + /* Set the data */ + node->type = EXPR_NODETYPE_ASSIGN; + node->data.assign.node = tmp; + + + /* + The fast access method directly accesses the memory address + of the variable's value at evaluation time. Because of this, + we must make sure the variable does exists in the variable list. + */ + + /* Make sure name is not a constant name */ + l = exprGetConstList(obj); + if(l) + { + exprValListGetAddress(l, tokens[index - 1].data.str, &addr); + if(addr) + { + obj->starterr = tokens[index - 1].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_CONSTANTASSIGN; + } + } + + /* Get the variable list */ + l = exprGetVarList(obj); + if(l == NULL) + return EXPR_ERROR_NOVARLIST; + + /* Get variable address if already in the list */ + exprValListGetAddress(l, tokens[index - 1].data.str, &addr); + if(addr == NULL) /* Variable not in the list, add it */ + { + exprValListAdd(l, tokens[index - 1].data.str, 0.0); + + /* Try to get address again */ + exprValListGetAddress(l, tokens[index - 1].data.str, &addr); + if(addr == NULL) /* Could not add variable */ + return EXPR_ERROR_MEMORY; /* Could not add variable to list */ + } + + node->data.assign.vaddr = addr; + + /* Parse the subnode */ + return exprInternalParse(obj, tmp, tokens, index + 1, end); + } + +/* Function to parse an addition operator */ +int exprInternalParseAdd(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) + { + exprNode *tmp; + int err; + + /* Make sure plus sign is at a good place */ + if(index <= start || index >= end) + { + obj->starterr = tokens[index].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_SYNTAX; + } + + /* Allocate space for 2 subnodes */ + tmp = exprAllocNodes(2); + if(tmp == NULL) + return EXPR_ERROR_MEMORY; + + + /* Set the data */ + node->type = EXPR_NODETYPE_ADD; + node->data.oper.nodes = tmp; + node->data.oper.nodecount = 2; + + /* parse the left side */ + err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); + if(err != EXPR_ERROR_NOERROR) + return err; + + /* parse the right side */ + return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); + } + +/* Function to parse a subtraction operator */ +int exprInternalParseSub(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) + { + exprNode *tmp; + int err; + + /* Make sure minus sign is at a good place */ + if(index <= start || index >= end) + { + obj->starterr = tokens[index].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_SYNTAX; + } + + /* Allocate space for 2 subnodes */ + tmp = exprAllocNodes(2); + if(tmp == NULL) + return EXPR_ERROR_MEMORY; + + + /* Set the data */ + node->type = EXPR_NODETYPE_SUBTRACT; + node->data.oper.nodes = tmp; + node->data.oper.nodecount = 2; + + /* parse the left side */ + err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); + if(err != EXPR_ERROR_NOERROR) + return err; + + /* parse the right side */ + return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); + } + +/* Function to parse a multiplication operator */ +int exprInternalParseMul(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) + { + exprNode *tmp; + int err; + + /* Make sure times sign is at a good place */ + if(index <= start || index >= end) + { + obj->starterr = tokens[index].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_SYNTAX; + } + + + /* Allocate space for 2 subnodes */ + tmp = exprAllocNodes(2); + if(tmp == NULL) + return EXPR_ERROR_MEMORY; + + + /* Set the data */ + node->type = EXPR_NODETYPE_MULTIPLY; + node->data.oper.nodes = tmp; + node->data.oper.nodecount = 2; + + /* parse the left side */ + err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); + if(err != EXPR_ERROR_NOERROR) + return err; + + /* parse the right side */ + return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); + } + +/* Function to parse a division operator */ +int exprInternalParseDiv(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) + { + exprNode *tmp; + int err; + + /* Make sure slash sign is at a good place */ + if(index <= start || index >= end) + { + obj->starterr = tokens[index].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_SYNTAX; + } + + + /* Allocate space for 2 subnodes */ + tmp = exprAllocNodes(2); + if(tmp == NULL) + return EXPR_ERROR_MEMORY; + + + /* Set the data */ + node->type = EXPR_NODETYPE_DIVIDE; + node->data.oper.nodes = tmp; + node->data.oper.nodecount = 2; + + /* parse the left side */ + err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); + if(err != EXPR_ERROR_NOERROR) + return err; + + /* parse the right side */ + return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); + } + +/* Function to parse an exponent operator */ +int exprInternalParseExp(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) + { + exprNode *tmp; + int err; + + /* Make sure exponent sign is at a good place */ + if(index <= start || index >= end) + { + obj->starterr = tokens[index].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_SYNTAX; + } + + + /* Allocate space for 2 subnodes */ + tmp = exprAllocNodes(2); + if(tmp == NULL) + return EXPR_ERROR_MEMORY; + + + /* Set the data */ + node->type = EXPR_NODETYPE_EXPONENT; + node->data.oper.nodes = tmp; + node->data.oper.nodecount = 2; + + /* parse the left side */ + err = exprInternalParse(obj, &(tmp[0]), tokens, start, index - 1); + if(err != EXPR_ERROR_NOERROR) + return err; + + /* parse the right side */ + return exprInternalParse(obj, &(tmp[1]), tokens, index + 1, end); + } + +/* Function to parse for positive and negative */ +int exprInternalParsePosNeg(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int index) + { + exprNode *tmp; + + /* Position should be the same as start */ + if(index != start) + { + obj->starterr = tokens[index].start; + obj->enderr = tokens[index].end; + return EXPR_ERROR_UNKNOWN; + } + + /* If it is a positive, just parse the internal of it */ + if(tokens[index].type == EXPR_TOKEN_PLUS) + return exprInternalParse(obj, node, tokens, index + 1, end); + else + { + /* Allocate subnode */ + tmp = exprAllocNodes(1); + if(tmp == NULL) + return EXPR_ERROR_NOERROR; + + + /* Set data */ + node->type = EXPR_NODETYPE_NEGATE; + node->data.oper.nodes = tmp; + node->data.oper.nodecount = 1; + + /* Parse the subnode */ + return exprInternalParse(obj, tmp, tokens, index + 1, end); + } + } + +/* Function will parse a call to a function */ +int exprInternalParseFunction(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int p1, int p2) + { + int pos; + int num, cur; + int refnum, refcur; + int plevel = 0; + int lv, err; + exprNode *tmp; + exprFuncType fptr; + int argmin, argmax; + int refargmin, refargmax; + int type; + exprFuncList *l; + exprValList *vars; + EXPRTYPE *addr; + EXPRTYPE **reftmp; + + /* We should have a function list */ + l = exprGetFuncList(obj); + if(l == NULL) + return EXPR_ERROR_NOSUCHFUNCTION; + + /* check paren. location */ + if(p2 <= p1) + return EXPR_ERROR_SYNTAX; + + /* second paren. should not be after the end */ + if(p2 > end) + return EXPR_ERROR_SYNTAX; + + /* Item before parenthesis should be an identifier */ + if(tokens[p1 - 1].type != EXPR_TOKEN_IDENTIFIER) + { + obj->starterr = tokens[p1 - 1].start; + obj->enderr = tokens[p1].end; + return EXPR_ERROR_SYNTAX; + } + + + /* Look up the function */ + err = exprFuncListGet(l, tokens[p1 - 1].data.str, &fptr, &type, &argmin, &argmax, &refargmin, &refargmax); + if(err != EXPR_ERROR_NOERROR) + { + if(err == EXPR_ERROR_NOTFOUND) + { + obj->starterr = tokens[p1 - 1].start; + obj->enderr = tokens[p1 - 1].end; + return EXPR_ERROR_NOSUCHFUNCTION; + } + else + return err; + } + + /* Make sure the function exists */ + if(fptr == NULL && type == 0) + { + obj->starterr = tokens[p1 - 1].start; + obj->enderr = tokens[p1 - 1].end; + return EXPR_ERROR_NOSUCHFUNCTION; + } + + /* Count arguments */ + if(p2 == p1 + 1) + { + num = 0; + refnum = 0; + } + else + { + num = 1; + refnum = 0; + + + /* count commas */ + for(pos = p1 + 1; pos < p2; pos++) + { + switch(tokens[pos].type) + { + case EXPR_TOKEN_OPAREN: + plevel++; + break; + + case EXPR_TOKEN_CPAREN: + plevel--; + if(plevel < 0) + { + obj->starterr = tokens[pos].start; + obj->enderr = tokens[pos].end; + return EXPR_ERROR_UNMATCHEDPAREN; + } + break; + + case EXPR_TOKEN_COMMA: + /* Found comma */ + if(plevel == 0) + num++; + break; + + case EXPR_TOKEN_AMPERSAND: + /* Found reference mark */ + if(plevel == 0) + { + /* This may only occur after the open parenthesis or comma */ + if(tokens[pos - 1].type == EXPR_TOKEN_OPAREN || tokens[pos - 1].type == EXPR_TOKEN_COMMA) + refnum++; + else + return EXPR_ERROR_SYNTAX; + } + break; + } + } + + /* plevel should be zero */ + if(plevel != 0) + return EXPR_ERROR_UNMATCHEDPAREN; + } + + /* We now have the number of total arguments and + number of ref arguments. Get number of normal + arguments */ + num = num - refnum; + + /* Make sure number of arguments is correct */ + /* Here we make sure the limits are greater + or equal to zero because any negative number + could be used to specify no limit */ + if(argmin >= 0 && num < argmin) + { + obj->starterr = tokens[p1 - 1].start; + obj->enderr = tokens[p2].end; + return EXPR_ERROR_BADNUMBERARGUMENTS; + } + + if(argmax >= 0 && num > argmax) + { + obj->starterr = tokens[p1 - 1].start; + obj->enderr = tokens[p2].end; + return EXPR_ERROR_BADNUMBERARGUMENTS; + } + + if(refargmin >= 0 && refnum < refargmin) + { + obj->starterr = tokens[p1 - 1].start; + obj->enderr = tokens[p2].end; + return EXPR_ERROR_BADNUMBERARGUMENTS; + } + + if(refargmax >= 0 && refnum > refargmax) + { + obj->starterr = tokens[p1 - 1].start; + obj->enderr = tokens[p2].end; + return EXPR_ERROR_BADNUMBERARGUMENTS; + } + + /* Set tmp to null in case of no arguments */ + tmp = NULL; + reftmp = NULL; + + if(num > 0) + { + /* Allocate subnodes */ + tmp = exprAllocNodes(num); + if(tmp == NULL) + return EXPR_ERROR_MEMORY; + } + + if(refnum > 0) + { + /* Allocate ref pointers */ + reftmp = exprAllocMem(sizeof(EXPRTYPE*) * refnum); + if(reftmp == NULL) + { + exprFreeMem(tmp); + return EXPR_ERROR_MEMORY; + } + } + + + + /* Set this node's data */ + node->type = EXPR_NODETYPE_FUNCTION; + node->data.function.fptr = fptr; + node->data.function.nodecount = num; + node->data.function.nodes = tmp; + node->data.function.refcount = refnum; + node->data.function.refs = reftmp; + node->data.function.type = type; + + /* parse each subnode */ + if(num + refnum > 0) + { + plevel = 0; + cur = 0; + refcur = 0; + lv = p1 + 1; + + /* look for commas if more than 1 arg */ + if(num + refnum > 1) + { + for(pos = p1 + 1; pos < p2; pos++) + { + switch(tokens[pos].type) + { + case EXPR_TOKEN_OPAREN: + plevel++; + break; + + case EXPR_TOKEN_CPAREN: + plevel--; + break; /* Already checked paren nesting above */ + + case EXPR_TOKEN_COMMA: + /* Found comma */ + if(plevel == 0) + { + /* parse inside */ + if(tokens[lv].type == EXPR_TOKEN_AMPERSAND) + { + if(lv != pos - 2) + { + obj->starterr = tokens[lv].start; + obj->enderr = tokens[pos].end; + return EXPR_ERROR_SYNTAX; + } + + /* It is a reference */ + if(tokens[lv + 1].type != EXPR_TOKEN_IDENTIFIER) + { + obj->starterr = tokens[lv].start; + obj->enderr = tokens[lv + 1].end; + return EXPR_ERROR_SYNTAX; + } + + + /* Make sure it is not a constant */ + vars = exprGetConstList(obj); + if(vars) + { + exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); + if(addr) + { + obj->starterr = tokens[lv].start; + obj->enderr = tokens[lv + 1].start; + return EXPR_ERROR_REFCONSTANT; + } + } + + /* Get variable list */ + vars = exprGetVarList(obj); + if(vars == NULL) + return EXPR_ERROR_NOVARLIST; + + /* Get variable address */ + exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); + if(addr == NULL) + { + /* Add variable to list */ + exprValListAdd(vars, tokens[lv + 1].data.str, 0.0); + + /* Try to get address again */ + exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); + if(addr == NULL) + return EXPR_ERROR_MEMORY; /* Could not add variable */ + } + + /* Set reference item */ + reftmp[refcur] = addr; + + /* increase ref arg number and lv position*/ + refcur++; + lv = pos + 1; + } + else + { + err = exprInternalParse(obj, &(tmp[cur]), tokens, lv, pos - 1); + if(err != EXPR_ERROR_NOERROR) + return err; + + /* increase arg number and lv position*/ + lv = pos + 1; + cur++; + } + } + break; + } + } + } + + /* lv should point after the last comma, or open paren. if only 1 arg */ + if(tokens[lv].type == EXPR_TOKEN_AMPERSAND) + { + if(lv != p2 - 2) + { + obj->starterr = tokens[lv].start; + obj->enderr = tokens[p2].end; + return EXPR_ERROR_SYNTAX; + } + + /* It is a reference */ + if(tokens[lv + 1].type != EXPR_TOKEN_IDENTIFIER) + { + obj->starterr = tokens[lv].start; + obj->enderr = tokens[lv + 1].end; + return EXPR_ERROR_SYNTAX; + } + + /* Make sure it is not a constant */ + vars = exprGetConstList(obj); + if(vars) + { + exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); + if(addr) + { + obj->starterr = tokens[lv].start; + obj->enderr = tokens[lv + 1].start; + return EXPR_ERROR_REFCONSTANT; + } + } + + /* Get variable list */ + vars = exprGetVarList(obj); + if(vars == NULL) + return EXPR_ERROR_NOVARLIST; + + /* Get variable address */ + exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); + if(addr == NULL) + { + /* Add variable to list */ + exprValListAdd(vars, tokens[lv + 1].data.str, 0.0); + + /* Try to get address again */ + exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr); + if(addr == NULL) + return EXPR_ERROR_MEMORY; /* Could not add variable */ + } + + /* Set reference item */ + reftmp[refcur] = addr; + } + else + { + err = exprInternalParse(obj, &(tmp[cur]), tokens, lv, p2 - 1); + if(err != EXPR_ERROR_NOERROR) + return err; + } + } + + + return EXPR_ERROR_NOERROR; + } + +/* Parse a variable or value */ +int exprInternalParseVarVal(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end) + { + exprValList *l; + EXPRTYPE *addr; + + + /* Make sure positions are correct */ + if(start != end) + { + return EXPR_ERROR_UNKNOWN; + } + + + /* Are we an identifier */ + if(tokens[start].type == EXPR_TOKEN_IDENTIFIER) + { + /* we are an identifier */ + + /* check to see if it is a constant */ + l = exprGetConstList(obj); + if(l != NULL) + { + if(exprValListGetAddress(l, tokens[start].data.str, &addr) == EXPR_ERROR_NOERROR) + { + /* We found it in the constant list */ + + /* + Treat is like a variable node so application can change + constant value and it will reflect in expression + */ + + node->type = EXPR_NODETYPE_VARIABLE; + node->data.variable.vaddr = addr; + return EXPR_ERROR_NOERROR; + } + } + + /* Not found in the constant list, so it must be a variable */ + + /* Set node type */ + node->type = EXPR_NODETYPE_VARIABLE; + + /* + The fast access method directly accesses the memory address + of the variable's value at evaluation time. Because of this, + we must make sure the variable does exists in the variable list. + */ + + /* Get the variable list */ + l = exprGetVarList(obj); + if(l == NULL) + return EXPR_ERROR_NOVARLIST; + + /* Get variable address if already in the list */ + exprValListGetAddress(l, tokens[start].data.str, &addr); + if(addr == NULL) /* Variable not in the list, add it */ + { + exprValListAdd(l, tokens[start].data.str, 0.0); + + /* Try to get address again */ + exprValListGetAddress(l, tokens[start].data.str, &addr); + if(addr == NULL) /* Could not add variable */ + return EXPR_ERROR_MEMORY; /* Could not add variable to list */ + } + + node->data.variable.vaddr = addr; + + return EXPR_ERROR_NOERROR; + } + else if(tokens[start].type == EXPR_TOKEN_VALUE) + { + /* we are a value */ + node->type = EXPR_NODETYPE_VALUE; + node->data.value.value = tokens[start].data.val; + return EXPR_ERROR_NOERROR; + } + else + { + obj->starterr = tokens[start].start; + obj->enderr = tokens[end].end; + return EXPR_ERROR_UNKNOWN; + } + } diff --git a/src/mod/applications/mod_expr/exprpriv.h b/src/mod/applications/mod_expr/exprpriv.h index 582ea89f85..b3d6d1d714 100644 --- a/src/mod/applications/mod_expr/exprpriv.h +++ b/src/mod/applications/mod_expr/exprpriv.h @@ -1,215 +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 - -/* 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 */ - +/* + 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 + +/* 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 */ + diff --git a/src/mod/applications/mod_expr/exprutil.c b/src/mod/applications/mod_expr/exprutil.c index 19f43b9192..659f79f189 100644 --- a/src/mod/applications/mod_expr/exprutil.c +++ b/src/mod/applications/mod_expr/exprutil.c @@ -1,43 +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; - } - - +/* + 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; + } + + diff --git a/src/mod/applications/mod_expr/exprval.c b/src/mod/applications/mod_expr/exprval.c index efec690293..1aec69ab81 100644 --- a/src/mod/applications/mod_expr/exprval.c +++ b/src/mod/applications/mod_expr/exprval.c @@ -1,395 +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; - } +/* + 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; + }