-<html>\r
-<head>\r
-<title>ExprEval Library</title>\r
-<style type="text/css">\r
-.valid {\r
- color: #00AA00;\r
-}\r
-.invalid {\r
- color: #FF0000;\r
-}\r
-.excomment {\r
- color: #0000FF;\r
-}\r
-.container {\r
- margin-top: 10px;\r
- margin-bottom: 10px;\r
- padding-left: 4px;\r
- padding-right: 4px;\r
- border-top: 1px solid #000000;\r
- border-right: 1px solid #000000;\r
- border-bottom: 1px solid #000000;\r
- border-left: 1px solid #000000;\r
- background-color: #BBBBBB;\r
-}\r
-body {\r
- background-color: #AAAAAA;\r
-}\r
-</style>\r
-</head>\r
-<body>\r
-\r
-<div align="center">\r
- <h1>ExprEval Library</h1>\r
- <hr>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2>Contents</h2>\r
- <h3>\r
- <ul>\r
- <a href="#Introduction">Introduction</a><br>\r
- <a href="#License">License</a><br>\r
- <a href="#Syntax">Expression Syntax</a><br>\r
- <a href="#Using">Using ExprEval in an Application</a><br>\r
- <a href="#FastVar">Fast Variable Access</a><br>\r
- <a href="#InternalFuncConst">Using the Internal Functions and Constants</a><br>\r
- <a href="#CustomFunc">Creating Custom Functions</a><br>\r
- <a href="#Reference">Reference</a><br>\r
- <a href="#Compiling">Compiling the ExprEval Library</a><br>\r
- <a href="#Drawbacks">Drawbacks/Problems</a><br>\r
- <a href="#Solutions">Problems and Solutions</a><br>\r
- <a href="#Example">Example Use</a><br>\r
- </ul>\r
- </h3>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Introduction">Introduction</a></h2>\r
- <blockquote>\r
- <p>ExprEval Help document. This document is probably full of\r
- bugs and mispellings. I may get around to proofreading\r
- it later.</p>\r
- <p>ExprEval is a C based expression evaluation library.\r
- It is entirely C based, but can be used in C++ programs\r
- as well.. The source code is provided for the library\r
- so that it can be recompiled for the specific system\r
- or compiler.</p>\r
- <p>ExprEval makes adding mathematical expression support to\r
- an application easy. It takes an expression string and\r
- parses it, and then it can evaluate it over and over.\r
- This library also has support for functions, constants,\r
- and variables. All of these items are stored in\r
- seperate lists so they can be shared among expressions or\r
- they can be private to a single expression or any mix and\r
- match. It is up to the developer how to link them together.\r
- You can also create your own custom functions.</p>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="License">License</a></h2>\r
- <blockquote>\r
- <p>This library is licensed under the\r
- <a href="license.txt">ExprEval License.</a>\r
- </p>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Syntax">Expression Syntax</a></h2>\r
- <blockquote>\r
- <p>Expressions have pretty much the same syntax as they\r
- would have on paper, with the following exceptions:\r
- <ul>\r
- <li>Each expression must end with a semicolon. This\r
- is because the expression string can actually\r
- contain multiple expressions. The semicolon is\r
- used to mark the end of the expression.<br>\r
- <b>Examples:</b>\r
- <ul>\r
- <li>4*x+5;</li>\r
- <li>y=5+2;g=4+6;</li>\r
- <li>y=r*sin(a);x=r*cos(a);</li>\r
- </ul>\r
- </li>\r
- <li>The asterisk '*' must be used to multiply.<br>\r
- <b>Examples:</b>\r
- <ul>\r
- <li>y=5*6; <b class="valid">Valid</b></li>\r
- <li>g=(x+1)*(x-1); <b class="valid">Valid</b></li>\r
- <li>g=(x+1)(x-1); <b class="invalid">Invalid</b></li>\r
- </ul>\r
- </li>\r
- </ul>\r
- </p>\r
- <p>More than one expression may be contained within an expression string.\r
- As shown above, each expression must end with a semicolon, even if\r
- only one expression is in the string. The value of an expression\r
- string is the value of the last expression in the string.<br>\r
- <b>Examlples:</b>\r
- <ul>\r
- <li>g=7; <b class="excomment">Value: 7</b></li>\r
- <li>k=z+1; <b class="excomment">Value: z+1</b></li>\r
- <li>r=4;k=6;o=9+r-k; <b class="excomment">Value: 9+r-k</b></li>\r
- </ul>\r
- </p>\r
- <p>Some functions may take reference parameters. These parameters are\r
- references to other variables. You can mix reference parameters\r
- with normal parameters. The order of the normal parameters must\r
- remain the same and the order of the reference parameters must\r
- remain the same.<br>\r
- <b>Examples:</b>\r
- <ul>\r
- <li>min(1,2,3,4,&mval); <b class="excomment">&mval is a reference to a variable mval</b></li>\r
- <li>min(1,2,&mval,3,4); <b class="excomment">You may mix them inside like this.</b></li>\r
- <li>min(1,2,(&mval),3,4); <b class="invalid">You may not nest reference parameters in any way</b></li>\r
- </ul>\r
- </p>\r
- <p>Expressions may also be nested with parenthesis.<br>\r
- <b>Examples:</b>\r
- <ul>\r
- <li>y=sin(x-cos(5+max(4,5,6*x)));</li>\r
- <li>6+(5-2*(x+y));</li>\r
- </ul>\r
- </p>\r
- <p>Expressions may also have whitespace characters and comments.\r
- Whitespace characters such as newlines, linefeeds, carriage\r
- returns, spaces, and tabs are ignored. Comments begin with\r
- the pound sign '#' and end at the end of the line.<br>\r
- <b>Example:</b>\r
- <ul>\r
- <pre>\r
-#Set the x value\r
-x = d * cos(r);\r
-\r
-#Set the y value\r
-y = d * sin(r);\r
- </pre>\r
- </ul>\r
- </p>\r
- <p>If a variable is used in an expression, but that variable does not exist,\r
- it is considered zero. If it does exist then its value is used instead.\r
- </p>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Using">Using ExprEval in an Application</a></h2>\r
- <blockquote>\r
- <p>Using ExprEval in an application can be a little difficult.\r
- You generally follow these steps:\r
- <ul>\r
- <li>Create function, variable, and constant lists</li>\r
- <li>Create the expression object</li>\r
- <li>Parse the expression</li>\r
- <li>Evaluate the expression as needed</li>\r
- <li>Free the expression object</li>\r
- <li>Free the function, variable, and constant lists</li>\r
- </ul>\r
- You can manipulate the lists in any order after their creation.\r
- However, functions are translated during the parse, so after\r
- parsing an expression, manipulating the function list will make\r
- no change to an expression. Variables and constants can be\r
- manipulated after a parse to change the result of an expression.\r
- However, you must add any constants to be used by an expression\r
- to the constant list <b>BEFORE</b> parsing the expression,\r
- otherwise it will be seen as a variable. Applications can change\r
- both variables and constants, however the expression can only\r
- change variables. Expressions may <b>NOT</b> assign to a constant\r
- and expressions may <b>NOT</b> use constants as a reference parameter.</p>\r
- <p><b>Function, variable, and constant list example:</b>\r
- <ul>\r
- <pre>\r
-exprFuncList *flist;\r
-exprValList *vlist;\r
-exprValList *clist;\r
-exprObj *obj;\r
-EXPRTYPE result;\r
-int err;\r
-\r
-/* Create function list */\r
-err = exprFuncListCreate(&flist);\r
-if(err != EXPR_ERROR_NOERROR)\r
- {\r
- ...\r
- }\r
-\r
-/* Initialize internal functions */\r
-err = exprFuncListInit(flist);\r
-if(err != EXPR_ERROR_NOERROR)\r
- {\r
- ...\r
- }\r
-\r
-/* Create variable list */\r
-err = exprValListCreate(&vlist);\r
-if(err != EXPR_ERROR_NOERROR)\r
- {\r
- ...\r
- }\r
-\r
-/* Create the constant list */\r
-err = exprValListCreate(&clist);\r
-if(err != EXPR_ERROR_NOERROR)\r
- {\r
- ...\r
- }\r
-\r
-/* Initialize internal constants */\r
-err = exprValListInit(clist);\r
-if(err != EXPR_ERROR_NOERROR)\r
- {\r
- ...\r
- }\r
-\r
-/* Add any application defined functions, constants, or variables to the lists here or down below */\r
- </pre>\r
- </ul>\r
- </p>\r
- <p><b>Expression object example:</b>\r
- <ul>\r
- <pre>\r
-err = exprCreate(&obj, flist, vlist, clist, NULL, 0);\r
-if(err != EXPR_ERROR_NOERROR)\r
- {\r
- ...\r
- }\r
-\r
-/* Add any application defined functions, constants, or variables to the lists here or down below.\r
- This is the last time you can for the functions or constants. */\r
- </pre>\r
- </ul>\r
- </p>\r
- <p><b>Expression parse example:</b>\r
- <ul>\r
- <pre>\r
-/* Functions and constants may be added or changed here */\r
-\r
-err = exprParse(obj, "2+sin(M_PI)+3*x;");\r
-if(err != EXPR_ERROR_NOERROR)\r
- {\r
- ...\r
- }\r
-\r
-/* Changes to the function or constant lists do not change the expression now */\r
- </pre>\r
- </ul>\r
- </p>\r
- <p><b>Expression evaluation example:</b>\r
- <ul>\r
- <pre>\r
-/* Add or change any variables */\r
-\r
-err = exprEval(obj, &result);\r
-if(err != EXPR_ERROR_NOERRO)\r
- {\r
- ...\r
- }\r
-else\r
- {\r
- printf("Expression Result: %f\n", result);\r
- }\r
- </pre>\r
- </ul>\r
- </p>\r
- <p><b>Free the expression object and lists example:</b>\r
- <ul>\r
- <pre>\r
-exprFree(obj);\r
-exprValListFree(vlist);\r
-exprValListFree(clist);\r
-exprFuncListFree(flist);\r
- </pre>\r
- </ul>\r
- </p>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="FastVar">Fast Variable Access</a></h2>\r
- <blockquote>\r
- <p>A new feature in ExprEval is fast variable access. This\r
- is simply a technique of quickly accessing variables\r
- by directly accessing their memory locations instead\r
- of using the value list functions. Fast variable access\r
- is always used internally in ExprEval. You must\r
- NOT clear a variable list until after all expressions\r
- using it are completely finished evaluating. Then you\r
- must reparse the expressions before using them again.\r
- The reason is simple. When fast variable access is used,\r
- the variable memory location is directly accessed If you\r
- clear a variable list and then evaluate an expression,\r
- it will access invalid memory.</p>\r
- <p>You can also use fast variable access in you application\r
- to dramatically speed up loops. This is accomplished as\r
- follows:\r
- <ul>\r
- <li>Add the desired variable to the variable list</li>\r
- <li>Get the address of the variable with exprValListGetAddress</li>\r
- <li>In the loop(s), directly set/get the variable any time needed: *var = 0.0;</li>\r
- </ul>\r
- </p>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="InternalFuncConst">Using the Internal Functions and Constants</a></h2>\r
- <blockquote>\r
- <p>To use the internal functions, they must first be initialized\r
- into a function list with exprFuncListInit. To use the\r
- internal constants, they must first be initialized into a\r
- value list with exprValListInit. For a list of the\r
- internal functions and constants, see the application\r
- help template file: <a href="exprtmpl.html">ExprTmpl.html</a>\r
- You may use this file in your own applications so you don't\r
- have to write a detail on the functions in ExprEval. All\r
- you have to do is add you own functions and constants to\r
- the file if there are any.\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="CustomFunc">Creating Custom Functions</a></h2>\r
- <blockquote>\r
- <p>Custom functions can be created for use by the library.\r
- This is how a function should look\r
- <ul>\r
- <pre>\r
-int custom_func(exprObj *obj, exprNode *nodes, int nodecount, EXPRTYPE **refs, int refcount, EXPRTYPE *val)\r
- {\r
- }\r
- </pre>\r
- </ul>\r
-\r
- obj is a pointer to the expression object that called\r
- the function, nodes is a pointer to an array of nodes\r
- that are the parameters of this function, nodecount is\r
- the number of items in the array (the number of parameters),\r
- refs is an array of pointers to referenced variables,\r
- refcount is the number of referenced variables,\r
- and val is a pointer to a variable to recieve the result\r
- of the function. The function should return an error value\r
- indicating the error status of the function.\r
- </p>\r
- <p>Solving a function typically goes as follows:\r
- <ul>\r
- <li>Verifiy the number of arguments, if needed</li>\r
- <li>Evaluate the subnodes that you need. You do not have to\r
- evaluate every subnode if you do not need it</li>\r
- <li>Check for possible error conditions (division by zero)</li>\r
- <li>Clear math errors (If function uses any math routines)</li>\r
- <li>Calculate the result</li>\r
- <li>Check for math errors (If the function uses any math routines)</li>\r
- <li>return EXPR_ERROR_NOERROR</li>\r
- </ul>\r
- </p>\r
- <p><b>Example:</b>\r
- <ul>\r
- <pre>\r
-int custom_func(exprObj *obj, exprNode *nodes, int count, EXPRTYPE **refs, int refcount, EXPRTYPE *val)\r
- {\r
- int err;\r
- EXPRTYPE d1, d2;\r
-\r
- /* Need 2 arguments */\r
- if(nodecount != 2)\r
- return EXPR_ERROR_BADNUMBERARGUMENTS;\r
-\r
- /* Eval arg 1 */\r
- err = exprEvalNode(obj, nodes, 0, &d1);\r
- if(err != EXPR_ERROR_NOERROR)\r
- return err;\r
-\r
- /* Eval arg 2 */\r
- err = exprEvalNode(obj, nodes, 1, &d2);\r
- if(err != EXPR_ERROR_NOERROR)\r
- return err;\r
-\r
- /* Make sure arg 2 is not 0.0 */\r
- if(d2 == 0.0)\r
- {\r
- *val = 0.0;\r
- return EXPR_ERROR_NOERROR;\r
- }\r
-\r
- /* Do math */\r
- *val = atan(d1 / d2); /* No need to worry about divide by zero */\r
-\r
-\r
- return EXPR_ERROR_NOERROR;\r
- }\r
- </pre>\r
- </ul>\r
- </p>\r
- <p>In order to use a custom function, it must be added to\r
- a function list before the expression is parsed by using\r
- exprFuncListAdd</p>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Reference">Reference</a></h2>\r
- <blockquote>\r
- <p><b>Headers:</b>\r
- <ul>\r
- <li>expreval.h - Include file</li>\r
- </ul>\r
- <p>\r
- <p><b>Defines:</b>\r
- <ul>\r
- <li>EXPR_MAXIDENTSIZE - Maximum identifier, constant,\r
- or function name size</li>\r
- <li>EXPR_ERROR_NOERROR - No error has occurred</li>\r
- <li>EXPR_ERROR_MEMORY - A memory allocation error occured.\r
- For function and value lists, the name may have been\r
- invalid</li>\r
- <li>EXPR_ERROR_NULLPOINTER - A null pointer was passed to\r
- a function that needed a valid pointer.</li>\r
- <li>EXPR_ERROR_NOTFOUND - An item was not found in the\r
- function or value list</li>\r
- <li>EXPR_ERROR_UNMATHEDCOMMENT - Comment is missing opening\r
- or closing mark.</li>\r
- <li>EXPR_ERROR_INVALIDCHAR - Invalid characters were found\r
- in the expression</li>\r
- <li>EXPR_ERROR_ALREADYEXISTS - An item already exists or created.</li>\r
- <li>EXPR_ERROR_ALREADYPARSEDBAD - An expression was already\r
- parsed into this object, but unsuccessfully. Free the\r
- expression before creating and parsing again</li>\r
- <li>EXPR_ERROR_ALREADYPARSEDGOOD - An expression was already\r
- parsed into this object successfully. Free the expression\r
- before creating and parsing again</li>\r
- <li>EXPR_ERROR_EMPTYEXPR - An empty expression string was passed\r
- to be parsed</li>\r
- <li>EXPR_ERROR_UNMATHEDPAREN - Unmathed opening or closing\r
- parenthesis were found</li>\r
- <li>EXPR_ERROR_SYNTAX - A syntax error is in the expression</li>\r
- <li>EXPR_ERROR_MISSINGSEMICOLON - An expression is missing a\r
- semicolon</li>\r
- <li>EXPR_ERROR_BADIDENTIFIER - A bad identifier was used in\r
- the expression</li>\r
- <li>EXPR_ERROR_NOSUCHFUNCTION - Function used in the expression\r
- does not exist in the function list</li>\r
- <li>EXPR_ERROR_BADNUMBERARGUMENTS - A bad number of arguments\r
- was passed to the expression function</li>\r
- <li>EXPR_ERROR_BADEXPR - Can not evaluate an expression because\r
- it does not exist or has not been parsed successfully.</li>\r
- <li>EXPR_ERROR_UNABLETOASSIGN - Unable to do an assignment because\r
- a variable list has not been associated with the expression object</li>\r
- <li>EXPR_ERROR_DIVBYZERO - An attemp to divide by zero has occured</li>\r
- <li>EXPR_ERROR_NOVARLIST - No variable list for the expression</li>\r
- <li>EXPR_ERROR_BREAK - The expression was broken by the break function</li>\r
- <li>EXPR_ERROR_CONSTANTASSIGN - The expresion attempted to assign to a constant.</li>\r
- <li>EXPR_ERROR_REFCONSTANT - The expression attempted to pass a constant as a\r
- reference parameter.</li>\r
- <li>EXPR_ERROR_OUTOFRANGE - A bad value was passed to a function.</li>\r
- <li>EXPR_ERROR_USER - Custom error values need to be larger than this.</li>\r
- </ul>\r
- </p>\r
- <p><b>Objects:</b>\r
- <ul>\r
- <li>exprObj - The expression object</li>\r
- <li>exprFuncList - A function lists for the expresions</li>\r
- <li>exprValList - A value list for constants or variables</li>\r
- <li>exprNode - An individual node in a parsed expression tree</li>\r
- </ul>\r
- </p>\r
- <p><b>Types:</b>\r
- <ul>\r
- <li>EXPRTYPE - Type for the value of an expression (double)</li>\r
- <li>exprFuncType - Custom function type. Defined as:<br>\r
- typedef int (*exprFuncType)(exprObj *obj, exprNode *nodes, int nodecount, EXPRTYPE **refs, int refcount, EXPRTYPE *val);</li>\r
- <li>exprBreakFuncType - Breaker function pointer to stop evaluation if the result is nonzero.\r
- Defined as:<br>\r
- typedef int (*exprBreakFuncType)(exprObj *o);</li>\r
- </ul>\r
- </p>\r
- <p><b>Version information functions:</b>\r
- <ul>\r
- <li>void exprGetVersion(int *major, int *mino);<br>\r
- Comments:\r
- <ul>\r
- <li>Gets the version of the ExprEval library</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*major - Pointer to int to get major version number</li>\r
- <li>*minor - Pointer to int to get minor version number</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Nothing</li>\r
- </ul>\r
- </li>\r
- </ul>\r
- </p>\r
- <p><b>Function list functions:</b>\r
- <ul>\r
- <li>int exprFuncListCreate(exprFuncList **flist);<br>\r
- Comments:\r
- <ul>\r
- <li>Creates a function lists and updates a pointer to point to it</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>**flist - Pointer to a pointer to the function list</li>\r
- </ul>\r
- Returns\r
- <ul>\r
- <li>Error code of the function. On success, the pointer\r
- passed by address will point to the new function list</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprFuncListAdd(exprFuncList *flist, exprFuncType ptr, char *name, int min, int max, int refmin, int refmax);<br>\r
- Comments:\r
- <ul>\r
- <li>Adds a function to the function list. Returns error if\r
- the function already exists.</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*flist - Pointer to an already created function list</li>\r
- <li>ptr - Pointer to a custom function</li>\r
- <li>*name - Name of the custom function</li>\r
- <li>min - Minimum number of arguments for the function, negative for no minimum</li>\r
- <li>max - Maximum number of arguments for the function, negative for no maximum</li>\r
- <li>refmin - Minimum number of ref arguments</li>\r
- <li>refmax - Maxmimum number of ref arguments</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprFuncListFree(exprFuncList *flist);<br>\r
- Comments:\r
- <ul>\r
- <li>Free the function list entirely</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*flist - Pointer to the function list to free</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprFuncListClear(exprFuncList *flist);<br>\r
- Comments:\r
- <ul>\r
- <li>Clear the functions from the function list</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*flist - Pointer to the function list to clear</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprFuncListInit(exprFuncList *flist);<br>\r
- Comments:\r
- <ul>\r
- <li>Initializes internal functions into the funtion list</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*flist - Function list to initialize</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li>\r
- </ul>\r
- </p>\r
- <p><b>Value list functions:</b>\r
- <ul>\r
- <li>int exprValListCreate(exprValList **vlist);<br>\r
- Comments:\r
- <ul>\r
- <li>Creates a value list for variables or constants</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>**vlist - Pointer to a pointer to the value list.</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function. On success, the pointer will\r
- be updated to point to the value list</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprValListAdd(exprValList *vlist, char *name, EXPRTYPE val);<br>\r
- Comments:\r
- <ul>\r
- <li>Add a value in a value list. Returns error if value\r
- already exists.</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*vlist - Value list to add a value to</li>\r
- <li>*name - Name of the value to add</li>\r
- <li>val - Value of the value to add</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprValListSet(exprValList *vlist, char *name, EXPRTYPE val);<br>\r
- Comments:\r
- <ul>\r
- <li>Set a value in a value list.</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*vlist - Value list to set a value in</li>\r
- <li>*name - Name of the value to set</li>\r
- <li>val - Value of the value to set</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprValListGet(exprValList *vlist, char *name, EXPRTYPE *val)<br>\r
- Comment:\r
- <ul>\r
- <li>Get the value of a variable or constant in a value list</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*vlist - Value list to use</li>\r
- <li>*name - Name of the value to get</li>\r
- <li>*val - Pointer to variable to get the value</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprValListAddAddress(exprValList *vlist, char *name, EXPRTYPE *addr)<br>\r
- Comment:\r
- <ul>\r
- <li>This function is used to add a named value to the value list, but\r
- uses an outside variable such as a stack variable to store the\r
- value. This outside variable is used to set/get the value instead\r
- of the internal list value. You must ensure that this outside\r
- variable exists as long as the expression is using it's address.</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*vlist - Value list to use</li>\r
- <li>*name - Name of the value to add</li>\r
- <li>*addr - Address of the value being added</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprValListGetAddress(exprValList *vlist, char *name, EXPRTYPE **addr)<br>\r
- Comment:\r
- <ul>\r
- <li>Get the memory address of a variable in a value list</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*vlist - Value list to use</li>\r
- <li>*name - Name of the value to get</li>\r
- <li>**addr - Pointer to a pointer to store the address of the value\r
- This will be NULL if the name is not in the list.</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>void *exprValListGetNext(exprValList *vlist, char **name, EXPRTYPE *value, EXPRTYPE** addr, void *cookie);<br>\r
- Comment:\r
- <ul>\r
- <li>This is used to enumerate the items in the value list.\r
- Do NOT change the list while enumerating the items. Any\r
- of the information items can be NULL if it is not needed.</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*vlist - Value list to use</li>\r
- <li>**name - Address of a pointer that will point to the\r
- name. Do not edit the name.</li>\r
- <li>*value - The current value of the item.</li>\r
- <li>**addr - Address of a pointer to store the address of the value.</li>\r
- <li>*cookie - NULL to find the first item, the return value to find\r
- subsequent items.</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>NULL if the item could not be found. Otherwise a cookie\r
- to be used to find additional items.</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprValListFree(exprValList *vlist);<br>\r
- Comments:\r
- <ul>\r
- <li>Completely free the value list</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*vlist - Value list to free</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprValListClear(exprValList *vlist);<br>\r
- Comments:\r
- <ul>\r
- <li>Set the values in the list to 0.0</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*vlist - Value list to reset</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprValListInit(exprValList *vlist);<br>\r
- Comments:\r
- <ul>\r
- <li>Initialize internal constants into a value list</li>\r
- </ul>\r
- Paramters:\r
- <ul>\r
- <li>*vlist - Value list to initialize</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li>\r
- </ul>\r
- </p>\r
- <p><b>Expression functions:</b>\r
- <ul>\r
- <li>int exprCreate(exprObj **obj, exprFuncList *flist, exprValList *vlist, exprValList *clist, exprBreakFuncType breaker, void *userdata);<br>\r
- Comments:\r
- <ul>\r
- <li>Create an expression object to use</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>**obj - Pointer to a pointer to an expression object</li>\r
- <li>*flist - Function list to associate with the expression</li>\r
- <li>*vlist - Variable value list to associate with the expression</li>\r
- <li>*clist - Constant value list to associate with the expression</li>\r
- <li>breaker - Breaker function callback to associate with the expression.\r
- Used by functions that may be infinite loops (such as the for function)</li>\r
- <li>userdata - User data to associate with the expression</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprFree(exprObj *obj);<br>\r
- Comments:\r
- <ul>\r
- <li>Completely free the expression object</li>\r
- </ul>\r
- Paramters:\r
- <ul>\r
- <li>*obj - Expression object to free</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprClear(exprObj *obj);<br>\r
- Comments:\r
- <ul>\r
- <li>Clear an expression, but keep list and callback associations.\r
- You can then parse another expression without calling create</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - Expression object to clear</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprParse(exprObj *obj, char *expr);<br>\r
- Comments:\r
- <ul>\r
- <li>Parse an expression string into an expression object</li>\r
- </ul>\r
- Paramters:\r
- <ul>\r
- <li>*obj - Expression object to use</li>\r
- <li>*expr - Expression string to parse</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprEval(exprObj *obj, EXPRTYPE *val);<br>\r
- Comments:\r
- <ul>\r
- <li>Evaluate a parsed expression. This function does not\r
- reset the breaker count at each call, but instead accumulates\r
- the count until the breaker function is called. Then the count\r
- is reset to the value specified in exprSetBreakerCount.</li>\r
- </ul>\r
- Paramters:\r
- <ul>\r
- <li>*obj - Expression object to evaluate</li>\r
- <li>*val = Pointer to variable to get result of evaluation.\r
- This can be NULL if the result is not needed.</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprEvalNode(exprObj *obj, exprNode *nodes, int curnode, EXPRTYPE *val);<br>\r
- Comments:\r
- <ul>\r
- <li>Evaluate a node of an expression.\r
- Used by custom functions</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - Expression object being used</li>\r
- <li>*nodes - Pointer to a node or list of nodes</li>\r
- <li>curnode - Index to the node to evaluate</li>\r
- <li>*val - Pointer to variable to get evaluation result</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Error code of the function</li>\r
- </ul>\r
- </li><br>\r
- <li>exprFuncList *exprGetFuncList(exprObj *obj);<br>\r
- Comments:\r
- <ul>\r
- <li>Gets the function list associated with an expression</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expression object</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Pointer fo an exprFuncList object or NULL</li>\r
- </ul>\r
- </li><br>\r
- <li>exprValList *exprGetVarList(exprObj *obj);<br>\r
- Comments:\r
- <ul>\r
- <li>Gets the variable list associated with an expression</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expression object</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Pointer to an exprValList object or NULL</li>\r
- </ul>\r
- </li><br>\r
- <li>exprValList *exprGetConstList(exprObj *obj);<br>\r
- Comments:\r
- <ul>\r
- <li>Gets the constant list associated with an expression</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expression object</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Pointer to an exprValList object or NULL</li>\r
- </ul>\r
- </li><br>\r
- <li>exprBreakFuncType exprGetBreakFunc(exprObj *obj);<br>\r
- Comments:\r
- <ul>\r
- <li>Gets the breaker callback of the expression</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expression object</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Pointer to the callback function or NULL</li>\r
- </ul>\r
- </li><br>\r
- <li>int exprGetBreakResult(exprObj *obj);<br>\r
- Comments:\r
- <ul>\r
- <li>Get the result of the breaker function</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expression object</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>zero to continue, nonzero to break</li>\r
- </ul>\r
- </li><br>\r
- <li>void* exprGetUserData(exprObj *obj);<br>\r
- Comments:\r
- <ul>\r
- <li>Gets the user data associated with an expression</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expression object</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>User data</li>\r
- </ul>\r
- </li><br>\r
- <li>void exprSetUserData(exprObj *obj, void *userdata);<br>\r
- Comments:\r
- <ul>\r
- <li>Sets the user data of an expression</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expresion object</li>\r
- <li>userdata - user data to set</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Nothing</li>\r
- </ul>\r
- </li><br>\r
- <li>void exprSetBreakCount(exprObj *obj, int count);<br>\r
- Comments:\r
- <ul>\r
- <li>Set how often the breaker function is tested.\r
- The default is 100000. This means the breaker\r
- function is tested once every 100000 times the\r
- exprEvalNode function is called for an expression.\r
- A smaller value tests the breaker function more often\r
- and a larger value tests the breaker function less. The\r
- breaker value is NOT reset during each call to exprEval,\r
- but is accumulated across calles to exprEval\r
- until the breaker function is finally called.</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expression object</li>\r
- <li>count - how many times exprEvalNode gets called before the\r
- breaker function is tested</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Nothing</li>\r
- </ul>\r
- </li><br>\r
- <li>void exprGetErrorPosition(exprObj *obj, int *start, int *end);<br>\r
- Comments:\r
- <ul>\r
- <li>Gets the start and ending positions in the expression string\r
- of the last parse error. The positions include any newline\r
- characters that may be in the string.</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*obj - expression object</li>\r
- <li>*start - pointer to an integer to get the start error position,\r
- -1 if unknown</li>\r
- <li>*end - pointer to an integer to get the end error position,\r
- -1 if unknown</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>Nothing</li>\r
- </ul>\r
- </ul>\r
- </p>\r
- <p><b>Some useful functions</b>\r
- <ul>\r
- <li>int exprValidIdent(char *name);<br>\r
- Comments:\r
- <ul>\r
- <li>Determine if an identifier is valid</li>\r
- </ul>\r
- Parameters:\r
- <ul>\r
- <li>*name - identifier to check</li>\r
- </ul>\r
- Returns:\r
- <ul>\r
- <li>0 on invalid. anything else on valid</li>\r
- </ul>\r
- </li><br>\r
- </ul>\r
- </p>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Compiling">Compiling the ExprEval library</a></h2>\r
- <p>Compiling the ExprEval library is pretty simple. Just\r
- compile all of the source files (*.c) and link them into\r
- a library. You need to keep "expreval.h" for the header file.</p>\r
- <p>You may have to make some changes to the library. I've\r
- tried to make doing so as simple as possible. If you\r
- need to change the include files or some macros or whatnot,\r
- edit the file "exprincl.h" This file includes any other files\r
- needed. You should not have to change to much. I have\r
- tried to stick as close to ANSI/ISO C as I can.</p>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Drawbacks">Drawbacks/Problems</a></h2>\r
- <p>The following is a list of some basic drawbacks of this\r
- library:\r
- <ul>\r
- <li>This library is an expression evaluator, and nothing\r
- else. It does not simplify expressions and it\r
- does not do advanced math such as calculating the\r
- integrals and differentials of expression.</li>\r
- <li>This library has no way of detecting overflows\r
- except for those caused by the internal math\r
- routines. Adding two very very large numbers\r
- may cause an overflow to occur.</li>\r
- <li>This library is not super easy to use in an application.\r
- It has been designed to give much control to the\r
- developer. Because of this, the function/value lists\r
- are seperate from the expression objects, allowing\r
- the developer to use them however they need.</li>\r
- <li>There is no way to delete a single function, variable,\r
- or constant from a list. This is because I see no\r
- real need to do so because of the way the library\r
- works. There is no need to delete function from\r
- a function list or constants from a constant list.\r
- There are are also no decent reasons to delete\r
- variables from a variable list until you are completely\r
- done and delete all of them.</li>\r
- </ul>\r
- </p>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Solutions">Problems and Solutions</a></h2>\r
- \r
- <ul>\r
- <li><b>Variables do not seem to change in a release/optimized build.</b><br>\r
- I have noticed a small problem with this. Rarely, a variable may not\r
- appear to change in a release build. The reason is to do with compiler\r
- optimizations. For example, look at the following code:\r
- <blockquote>\r
- <pre>\r
-EXPRTYPE k;\r
-\r
-/* Add variable to the list */\r
-exprValListAddAddress(list, "k", &k);\r
-\r
-k = 0.0;\r
-\r
-/* Evaluate expression */\r
-for(int x = 0; x < 100; x++)\r
- {\r
- exprEval(expr, &result);\r
- \r
- doSomething(k);\r
- }\r
- </pre>\r
- </blockquote>\r
- Inside the loop, the variable 'k' does not appear to be changing, so\r
- the compiler may optimize it by loading it into a register before the\r
- loop and not accessing it from memory during the loop, even if\r
- the expression does change it. One way to avoid this is to use the\r
- 'volatile' keyword with the variable. Then the compiler must\r
- accesss it from memory each time it is accessed.\r
- <blockquote>\r
- <pre>\r
-volatile EXPRTYPE k;\r
-\r
-/* Add variable to the list */\r
-exprValListAddAddress(list, "k", (EXPRTYPE*)&k);\r
-\r
-k = 0.0;\r
-\r
-/* Evaluate expression */\r
-for(int x = 0; x < 100; x++)\r
- {\r
- exprEval(expr, &result);\r
- \r
- doSomething(k);\r
- }\r
- </pre>\r
- </blockquote>\r
- </li>\r
- \r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Example">Example Use with Fast Variable Access</a></h2>\r
-\r
- <p>This is an example application of this library. It is a\r
- graphics program that calculates the color value of a\r
- pixel based on it's X,Y co-ordinate. It uses a made-up\r
- image library called graphic-lib. It uses faster variable\r
- access by using the exprValListGetAddress function.</p>\r
- <p>Note that this codes has not actually been tested. See the\r
- test applications (test and imagegen) for other examples.</p>\r
-\r
- <blockquote>\r
- <pre>\r
-/* Include files */\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <setjmp.h>\r
-#include "graphiclib.h"\r
-#include "expreval.h"\r
-\r
-char *transerr(int err)\r
- {\r
- /* Translate error code into message */\r
- }\r
-\r
-void gen_image(char *name, int w, int h, char *expr);\r
- {\r
- exprFuncList *f = NULL;\r
- exprValList *v = NULL;\r
- exprValList *c = NULL;\r
- exprObj *o = NULL;\r
- int x, y, err;\r
- jmp_buf jumper;\r
- int image;\r
- EXPRTYPE *v_x, *v_y;\r
- EXPRTYPE *v_r, *v_g, *v_b;\r
- EXPRTYPE global_value;\r
-\r
- /* Error handling */\r
- err = setjmp(jumper);\r
- if(err)\r
- {\r
- if(err != ID_IMAGENOERROR)\r
- printf("Error %d occurred: %s\n", err, transerr(err));\r
-\r
- exprFree(o);\r
- exprFreeFuncList(f);\r
- exprFreeValList(v);\r
- exprFreeValList(c);\r
-\r
- image_free(image);\r
- return;\r
- }\r
-\r
- /* Set up lists */\r
-\r
- /* Function list */\r
- err = exprFuncListCreate(&f);\r
- if(err != EXPR_ERROR_NOERROR)\r
- longjmp(jumper, err);\r
-\r
- err = exprFuncListInit(f);\r
- if(err != EXPR_ERROR_NOERROR)\r
- {\r
- printf("Function list init error. Functions may not be available.\n");\r
- }\r
-\r
- /* Variable list */\r
- err = exprValListCreate(&v);\r
- if(err != EXPR_ERROR_NOERROR)\r
- longjmp(jumper, err);\r
-\r
- /* Constant list */\r
- err = exprValListCreate(&c);\r
- if(err != EXPR_ERROR_NOERROR)\r
- {\r
- printf("Constants not available\n");\r
- }\r
- else\r
- {\r
- err = exprValListInit(c);\r
- if(err != EXPR_ERROR_NOERROR)\r
- printf("Constant list init error. Constants may not be available.\n");\r
- }\r
-\r
- /* Create and parse the expression */\r
-\r
- /* Create */\r
- err = exprCreate(&o, f, v, c, NULL, 0);\r
- if(err != EXPR_ERROR_NOERROR)\r
- longjmp(jumper, err);\r
-\r
- /* Parse expression */\r
- err = exprParse(o, expr);\r
- if(err != EXPR_ERROR_NOERROR)\r
- longjmp(jumper, err);\r
-\r
-\r
- /* Create the image */\r
- image = image_create(w, h);\r
- if(image == 0)\r
- {\r
- longjmp(jumper, ID_IMAGECREATEERROR);\r
- }\r
-\r
- /* Add width and height to variable list */\r
- exprValListAdd(v, "w", (EXPRTYPE)w);\r
- exprValListAdd(v, "h", (EXPRTYPE)h);\r
-\r
- /* Add x and y to the list */\r
- exprValListAdd(v, "x", 0.0);\r
- exprValListAdd(v, "y", 0.0);\r
-\r
- /* Add r, g, and b to the list */\r
- exprValListAdd(v, "r", 0.0);\r
- exprValListAdd(v, "g", 0.0);\r
- exprValListAdd(b, "b", 0.0);\r
-\r
- /* Get addresses. Assume no error */\r
- exprValListGetAddress(v, "x", &v_x);\r
- exprValListGetAddress(v, "y", &v_y);\r
-\r
- exprValListGetAddress(v, "r", &v_r);\r
- exprValListGetAddress(v, "g", &v_g);\r
- exprValListGetAddress(v, "g", &v_b);\r
- \r
- /* A way to add global variables that can be used by two different lists. */\r
- exprValListAddAddress(v, "global", &global_value);\r
- /* exprValListAddAddress(v2, "global", &global_value); */\r
- \r
- /* Also, exprValListAddAddress can be used to add variables directly.\r
- Instead of:\r
- \r
- EXPRTYPE *a;\r
- \r
- exprValListAdd(v, "a", 0.0);\r
- exprValListGetAddresss(v, "a", &a);\r
- \r
- You can do:\r
- \r
- EXPRTYPE a;\r
- \r
- exprValListAddAddresss(v, "a", &a);\r
- \r
- If you do this, you must ensure that the stack variable exists as long\r
- as it is used by expression, otherwise it may cause a memory access\r
- violation. */\r
- \r
-\r
- for(y = 0; y < h; y++)\r
- {\r
- for(x = 0; x < w; x++)\r
- {\r
- /* Directly set the x and y variables */\r
- *v_x = (EXPRTYPE)x;\r
- *v_y = (EXPRTYPE)y;\r
-\r
- /* Eval expression, ignoring errors */\r
- exprEval(o);\r
-\r
- /* Set pixel, using variables directly */\r
- image_setpixel(image, x, y, (int)(*v_r), (int)(*v_g), (int)(*v_b));\r
- }\r
- }\r
-\r
- /* Save image */\r
- image_save(image, name);\r
-\r
- /* Done */\r
- longjmp(jumper, ID_IMAGENOERROR);\r
- }\r
-\r
-void main(void)\r
- {\r
- char name[MAXPATH]\r
- char tmp[10];\r
- char expr[4096];\r
- int sx, sy;\r
-\r
- printf("Image name to save: ");\r
- gets(name);\r
-\r
- printf("Image width: ");\r
- gets(tmp);\r
- sx = atoi(tmp);\r
-\r
- printf("Image height: ");\r
- gets(tmp);\r
- sy = atoi(tmp);\r
-\r
- printf("Color Expression (Use x, y, w, h Set r, g, b): ");\r
- gets(expr);\r
-\r
- gen_image(name, sx, sy, expr);\r
- }\r
-\r
- </pre>\r
- </blockquote>\r
-</div>\r
-\r
-</body>\r
-</html>\r
+<html>
+<head>
+<title>ExprEval Library</title>
+<style type="text/css">
+.valid {
+ color: #00AA00;
+}
+.invalid {
+ color: #FF0000;
+}
+.excomment {
+ color: #0000FF;
+}
+.container {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding-left: 4px;
+ padding-right: 4px;
+ border-top: 1px solid #000000;
+ border-right: 1px solid #000000;
+ border-bottom: 1px solid #000000;
+ border-left: 1px solid #000000;
+ background-color: #BBBBBB;
+}
+body {
+ background-color: #AAAAAA;
+}
+</style>
+</head>
+<body>
+
+<div align="center">
+ <h1>ExprEval Library</h1>
+ <hr>
+</div>
+
+<div align="left" class="container">
+ <h2>Contents</h2>
+ <h3>
+ <ul>
+ <a href="#Introduction">Introduction</a><br>
+ <a href="#License">License</a><br>
+ <a href="#Syntax">Expression Syntax</a><br>
+ <a href="#Using">Using ExprEval in an Application</a><br>
+ <a href="#FastVar">Fast Variable Access</a><br>
+ <a href="#InternalFuncConst">Using the Internal Functions and Constants</a><br>
+ <a href="#CustomFunc">Creating Custom Functions</a><br>
+ <a href="#Reference">Reference</a><br>
+ <a href="#Compiling">Compiling the ExprEval Library</a><br>
+ <a href="#Drawbacks">Drawbacks/Problems</a><br>
+ <a href="#Solutions">Problems and Solutions</a><br>
+ <a href="#Example">Example Use</a><br>
+ </ul>
+ </h3>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Introduction">Introduction</a></h2>
+ <blockquote>
+ <p>ExprEval Help document. This document is probably full of
+ bugs and mispellings. I may get around to proofreading
+ it later.</p>
+ <p>ExprEval is a C based expression evaluation library.
+ It is entirely C based, but can be used in C++ programs
+ as well.. The source code is provided for the library
+ so that it can be recompiled for the specific system
+ or compiler.</p>
+ <p>ExprEval makes adding mathematical expression support to
+ an application easy. It takes an expression string and
+ parses it, and then it can evaluate it over and over.
+ This library also has support for functions, constants,
+ and variables. All of these items are stored in
+ seperate lists so they can be shared among expressions or
+ they can be private to a single expression or any mix and
+ match. It is up to the developer how to link them together.
+ You can also create your own custom functions.</p>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="License">License</a></h2>
+ <blockquote>
+ <p>This library is licensed under the
+ <a href="license.txt">ExprEval License.</a>
+ </p>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Syntax">Expression Syntax</a></h2>
+ <blockquote>
+ <p>Expressions have pretty much the same syntax as they
+ would have on paper, with the following exceptions:
+ <ul>
+ <li>Each expression must end with a semicolon. This
+ is because the expression string can actually
+ contain multiple expressions. The semicolon is
+ used to mark the end of the expression.<br>
+ <b>Examples:</b>
+ <ul>
+ <li>4*x+5;</li>
+ <li>y=5+2;g=4+6;</li>
+ <li>y=r*sin(a);x=r*cos(a);</li>
+ </ul>
+ </li>
+ <li>The asterisk '*' must be used to multiply.<br>
+ <b>Examples:</b>
+ <ul>
+ <li>y=5*6; <b class="valid">Valid</b></li>
+ <li>g=(x+1)*(x-1); <b class="valid">Valid</b></li>
+ <li>g=(x+1)(x-1); <b class="invalid">Invalid</b></li>
+ </ul>
+ </li>
+ </ul>
+ </p>
+ <p>More than one expression may be contained within an expression string.
+ As shown above, each expression must end with a semicolon, even if
+ only one expression is in the string. The value of an expression
+ string is the value of the last expression in the string.<br>
+ <b>Examlples:</b>
+ <ul>
+ <li>g=7; <b class="excomment">Value: 7</b></li>
+ <li>k=z+1; <b class="excomment">Value: z+1</b></li>
+ <li>r=4;k=6;o=9+r-k; <b class="excomment">Value: 9+r-k</b></li>
+ </ul>
+ </p>
+ <p>Some functions may take reference parameters. These parameters are
+ references to other variables. You can mix reference parameters
+ with normal parameters. The order of the normal parameters must
+ remain the same and the order of the reference parameters must
+ remain the same.<br>
+ <b>Examples:</b>
+ <ul>
+ <li>min(1,2,3,4,&mval); <b class="excomment">&mval is a reference to a variable mval</b></li>
+ <li>min(1,2,&mval,3,4); <b class="excomment">You may mix them inside like this.</b></li>
+ <li>min(1,2,(&mval),3,4); <b class="invalid">You may not nest reference parameters in any way</b></li>
+ </ul>
+ </p>
+ <p>Expressions may also be nested with parenthesis.<br>
+ <b>Examples:</b>
+ <ul>
+ <li>y=sin(x-cos(5+max(4,5,6*x)));</li>
+ <li>6+(5-2*(x+y));</li>
+ </ul>
+ </p>
+ <p>Expressions may also have whitespace characters and comments.
+ Whitespace characters such as newlines, linefeeds, carriage
+ returns, spaces, and tabs are ignored. Comments begin with
+ the pound sign '#' and end at the end of the line.<br>
+ <b>Example:</b>
+ <ul>
+ <pre>
+#Set the x value
+x = d * cos(r);
+
+#Set the y value
+y = d * sin(r);
+ </pre>
+ </ul>
+ </p>
+ <p>If a variable is used in an expression, but that variable does not exist,
+ it is considered zero. If it does exist then its value is used instead.
+ </p>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Using">Using ExprEval in an Application</a></h2>
+ <blockquote>
+ <p>Using ExprEval in an application can be a little difficult.
+ You generally follow these steps:
+ <ul>
+ <li>Create function, variable, and constant lists</li>
+ <li>Create the expression object</li>
+ <li>Parse the expression</li>
+ <li>Evaluate the expression as needed</li>
+ <li>Free the expression object</li>
+ <li>Free the function, variable, and constant lists</li>
+ </ul>
+ You can manipulate the lists in any order after their creation.
+ However, functions are translated during the parse, so after
+ parsing an expression, manipulating the function list will make
+ no change to an expression. Variables and constants can be
+ manipulated after a parse to change the result of an expression.
+ However, you must add any constants to be used by an expression
+ to the constant list <b>BEFORE</b> parsing the expression,
+ otherwise it will be seen as a variable. Applications can change
+ both variables and constants, however the expression can only
+ change variables. Expressions may <b>NOT</b> assign to a constant
+ and expressions may <b>NOT</b> use constants as a reference parameter.</p>
+ <p><b>Function, variable, and constant list example:</b>
+ <ul>
+ <pre>
+exprFuncList *flist;
+exprValList *vlist;
+exprValList *clist;
+exprObj *obj;
+EXPRTYPE result;
+int err;
+
+/* Create function list */
+err = exprFuncListCreate(&flist);
+if(err != EXPR_ERROR_NOERROR)
+ {
+ ...
+ }
+
+/* Initialize internal functions */
+err = exprFuncListInit(flist);
+if(err != EXPR_ERROR_NOERROR)
+ {
+ ...
+ }
+
+/* Create variable list */
+err = exprValListCreate(&vlist);
+if(err != EXPR_ERROR_NOERROR)
+ {
+ ...
+ }
+
+/* Create the constant list */
+err = exprValListCreate(&clist);
+if(err != EXPR_ERROR_NOERROR)
+ {
+ ...
+ }
+
+/* Initialize internal constants */
+err = exprValListInit(clist);
+if(err != EXPR_ERROR_NOERROR)
+ {
+ ...
+ }
+
+/* Add any application defined functions, constants, or variables to the lists here or down below */
+ </pre>
+ </ul>
+ </p>
+ <p><b>Expression object example:</b>
+ <ul>
+ <pre>
+err = exprCreate(&obj, flist, vlist, clist, NULL, 0);
+if(err != EXPR_ERROR_NOERROR)
+ {
+ ...
+ }
+
+/* Add any application defined functions, constants, or variables to the lists here or down below.
+ This is the last time you can for the functions or constants. */
+ </pre>
+ </ul>
+ </p>
+ <p><b>Expression parse example:</b>
+ <ul>
+ <pre>
+/* Functions and constants may be added or changed here */
+
+err = exprParse(obj, "2+sin(M_PI)+3*x;");
+if(err != EXPR_ERROR_NOERROR)
+ {
+ ...
+ }
+
+/* Changes to the function or constant lists do not change the expression now */
+ </pre>
+ </ul>
+ </p>
+ <p><b>Expression evaluation example:</b>
+ <ul>
+ <pre>
+/* Add or change any variables */
+
+err = exprEval(obj, &result);
+if(err != EXPR_ERROR_NOERRO)
+ {
+ ...
+ }
+else
+ {
+ printf("Expression Result: %f\n", result);
+ }
+ </pre>
+ </ul>
+ </p>
+ <p><b>Free the expression object and lists example:</b>
+ <ul>
+ <pre>
+exprFree(obj);
+exprValListFree(vlist);
+exprValListFree(clist);
+exprFuncListFree(flist);
+ </pre>
+ </ul>
+ </p>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="FastVar">Fast Variable Access</a></h2>
+ <blockquote>
+ <p>A new feature in ExprEval is fast variable access. This
+ is simply a technique of quickly accessing variables
+ by directly accessing their memory locations instead
+ of using the value list functions. Fast variable access
+ is always used internally in ExprEval. You must
+ NOT clear a variable list until after all expressions
+ using it are completely finished evaluating. Then you
+ must reparse the expressions before using them again.
+ The reason is simple. When fast variable access is used,
+ the variable memory location is directly accessed If you
+ clear a variable list and then evaluate an expression,
+ it will access invalid memory.</p>
+ <p>You can also use fast variable access in you application
+ to dramatically speed up loops. This is accomplished as
+ follows:
+ <ul>
+ <li>Add the desired variable to the variable list</li>
+ <li>Get the address of the variable with exprValListGetAddress</li>
+ <li>In the loop(s), directly set/get the variable any time needed: *var = 0.0;</li>
+ </ul>
+ </p>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="InternalFuncConst">Using the Internal Functions and Constants</a></h2>
+ <blockquote>
+ <p>To use the internal functions, they must first be initialized
+ into a function list with exprFuncListInit. To use the
+ internal constants, they must first be initialized into a
+ value list with exprValListInit. For a list of the
+ internal functions and constants, see the application
+ help template file: <a href="exprtmpl.html">ExprTmpl.html</a>
+ You may use this file in your own applications so you don't
+ have to write a detail on the functions in ExprEval. All
+ you have to do is add you own functions and constants to
+ the file if there are any.
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="CustomFunc">Creating Custom Functions</a></h2>
+ <blockquote>
+ <p>Custom functions can be created for use by the library.
+ This is how a function should look
+ <ul>
+ <pre>
+int custom_func(exprObj *obj, exprNode *nodes, int nodecount, EXPRTYPE **refs, int refcount, EXPRTYPE *val)
+ {
+ }
+ </pre>
+ </ul>
+
+ obj is a pointer to the expression object that called
+ the function, nodes is a pointer to an array of nodes
+ that are the parameters of this function, nodecount is
+ the number of items in the array (the number of parameters),
+ refs is an array of pointers to referenced variables,
+ refcount is the number of referenced variables,
+ and val is a pointer to a variable to recieve the result
+ of the function. The function should return an error value
+ indicating the error status of the function.
+ </p>
+ <p>Solving a function typically goes as follows:
+ <ul>
+ <li>Verifiy the number of arguments, if needed</li>
+ <li>Evaluate the subnodes that you need. You do not have to
+ evaluate every subnode if you do not need it</li>
+ <li>Check for possible error conditions (division by zero)</li>
+ <li>Clear math errors (If function uses any math routines)</li>
+ <li>Calculate the result</li>
+ <li>Check for math errors (If the function uses any math routines)</li>
+ <li>return EXPR_ERROR_NOERROR</li>
+ </ul>
+ </p>
+ <p><b>Example:</b>
+ <ul>
+ <pre>
+int custom_func(exprObj *obj, exprNode *nodes, int count, EXPRTYPE **refs, int refcount, EXPRTYPE *val)
+ {
+ int err;
+ EXPRTYPE d1, d2;
+
+ /* Need 2 arguments */
+ if(nodecount != 2)
+ return EXPR_ERROR_BADNUMBERARGUMENTS;
+
+ /* Eval arg 1 */
+ err = exprEvalNode(obj, nodes, 0, &d1);
+ if(err != EXPR_ERROR_NOERROR)
+ return err;
+
+ /* Eval arg 2 */
+ err = exprEvalNode(obj, nodes, 1, &d2);
+ if(err != EXPR_ERROR_NOERROR)
+ return err;
+
+ /* Make sure arg 2 is not 0.0 */
+ if(d2 == 0.0)
+ {
+ *val = 0.0;
+ return EXPR_ERROR_NOERROR;
+ }
+
+ /* Do math */
+ *val = atan(d1 / d2); /* No need to worry about divide by zero */
+
+
+ return EXPR_ERROR_NOERROR;
+ }
+ </pre>
+ </ul>
+ </p>
+ <p>In order to use a custom function, it must be added to
+ a function list before the expression is parsed by using
+ exprFuncListAdd</p>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Reference">Reference</a></h2>
+ <blockquote>
+ <p><b>Headers:</b>
+ <ul>
+ <li>expreval.h - Include file</li>
+ </ul>
+ <p>
+ <p><b>Defines:</b>
+ <ul>
+ <li>EXPR_MAXIDENTSIZE - Maximum identifier, constant,
+ or function name size</li>
+ <li>EXPR_ERROR_NOERROR - No error has occurred</li>
+ <li>EXPR_ERROR_MEMORY - A memory allocation error occured.
+ For function and value lists, the name may have been
+ invalid</li>
+ <li>EXPR_ERROR_NULLPOINTER - A null pointer was passed to
+ a function that needed a valid pointer.</li>
+ <li>EXPR_ERROR_NOTFOUND - An item was not found in the
+ function or value list</li>
+ <li>EXPR_ERROR_UNMATHEDCOMMENT - Comment is missing opening
+ or closing mark.</li>
+ <li>EXPR_ERROR_INVALIDCHAR - Invalid characters were found
+ in the expression</li>
+ <li>EXPR_ERROR_ALREADYEXISTS - An item already exists or created.</li>
+ <li>EXPR_ERROR_ALREADYPARSEDBAD - An expression was already
+ parsed into this object, but unsuccessfully. Free the
+ expression before creating and parsing again</li>
+ <li>EXPR_ERROR_ALREADYPARSEDGOOD - An expression was already
+ parsed into this object successfully. Free the expression
+ before creating and parsing again</li>
+ <li>EXPR_ERROR_EMPTYEXPR - An empty expression string was passed
+ to be parsed</li>
+ <li>EXPR_ERROR_UNMATHEDPAREN - Unmathed opening or closing
+ parenthesis were found</li>
+ <li>EXPR_ERROR_SYNTAX - A syntax error is in the expression</li>
+ <li>EXPR_ERROR_MISSINGSEMICOLON - An expression is missing a
+ semicolon</li>
+ <li>EXPR_ERROR_BADIDENTIFIER - A bad identifier was used in
+ the expression</li>
+ <li>EXPR_ERROR_NOSUCHFUNCTION - Function used in the expression
+ does not exist in the function list</li>
+ <li>EXPR_ERROR_BADNUMBERARGUMENTS - A bad number of arguments
+ was passed to the expression function</li>
+ <li>EXPR_ERROR_BADEXPR - Can not evaluate an expression because
+ it does not exist or has not been parsed successfully.</li>
+ <li>EXPR_ERROR_UNABLETOASSIGN - Unable to do an assignment because
+ a variable list has not been associated with the expression object</li>
+ <li>EXPR_ERROR_DIVBYZERO - An attemp to divide by zero has occured</li>
+ <li>EXPR_ERROR_NOVARLIST - No variable list for the expression</li>
+ <li>EXPR_ERROR_BREAK - The expression was broken by the break function</li>
+ <li>EXPR_ERROR_CONSTANTASSIGN - The expresion attempted to assign to a constant.</li>
+ <li>EXPR_ERROR_REFCONSTANT - The expression attempted to pass a constant as a
+ reference parameter.</li>
+ <li>EXPR_ERROR_OUTOFRANGE - A bad value was passed to a function.</li>
+ <li>EXPR_ERROR_USER - Custom error values need to be larger than this.</li>
+ </ul>
+ </p>
+ <p><b>Objects:</b>
+ <ul>
+ <li>exprObj - The expression object</li>
+ <li>exprFuncList - A function lists for the expresions</li>
+ <li>exprValList - A value list for constants or variables</li>
+ <li>exprNode - An individual node in a parsed expression tree</li>
+ </ul>
+ </p>
+ <p><b>Types:</b>
+ <ul>
+ <li>EXPRTYPE - Type for the value of an expression (double)</li>
+ <li>exprFuncType - Custom function type. Defined as:<br>
+ typedef int (*exprFuncType)(exprObj *obj, exprNode *nodes, int nodecount, EXPRTYPE **refs, int refcount, EXPRTYPE *val);</li>
+ <li>exprBreakFuncType - Breaker function pointer to stop evaluation if the result is nonzero.
+ Defined as:<br>
+ typedef int (*exprBreakFuncType)(exprObj *o);</li>
+ </ul>
+ </p>
+ <p><b>Version information functions:</b>
+ <ul>
+ <li>void exprGetVersion(int *major, int *mino);<br>
+ Comments:
+ <ul>
+ <li>Gets the version of the ExprEval library</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*major - Pointer to int to get major version number</li>
+ <li>*minor - Pointer to int to get minor version number</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Nothing</li>
+ </ul>
+ </li>
+ </ul>
+ </p>
+ <p><b>Function list functions:</b>
+ <ul>
+ <li>int exprFuncListCreate(exprFuncList **flist);<br>
+ Comments:
+ <ul>
+ <li>Creates a function lists and updates a pointer to point to it</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>**flist - Pointer to a pointer to the function list</li>
+ </ul>
+ Returns
+ <ul>
+ <li>Error code of the function. On success, the pointer
+ passed by address will point to the new function list</li>
+ </ul>
+ </li><br>
+ <li>int exprFuncListAdd(exprFuncList *flist, exprFuncType ptr, char *name, int min, int max, int refmin, int refmax);<br>
+ Comments:
+ <ul>
+ <li>Adds a function to the function list. Returns error if
+ the function already exists.</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*flist - Pointer to an already created function list</li>
+ <li>ptr - Pointer to a custom function</li>
+ <li>*name - Name of the custom function</li>
+ <li>min - Minimum number of arguments for the function, negative for no minimum</li>
+ <li>max - Maximum number of arguments for the function, negative for no maximum</li>
+ <li>refmin - Minimum number of ref arguments</li>
+ <li>refmax - Maxmimum number of ref arguments</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprFuncListFree(exprFuncList *flist);<br>
+ Comments:
+ <ul>
+ <li>Free the function list entirely</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*flist - Pointer to the function list to free</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprFuncListClear(exprFuncList *flist);<br>
+ Comments:
+ <ul>
+ <li>Clear the functions from the function list</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*flist - Pointer to the function list to clear</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprFuncListInit(exprFuncList *flist);<br>
+ Comments:
+ <ul>
+ <li>Initializes internal functions into the funtion list</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*flist - Function list to initialize</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li>
+ </ul>
+ </p>
+ <p><b>Value list functions:</b>
+ <ul>
+ <li>int exprValListCreate(exprValList **vlist);<br>
+ Comments:
+ <ul>
+ <li>Creates a value list for variables or constants</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>**vlist - Pointer to a pointer to the value list.</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function. On success, the pointer will
+ be updated to point to the value list</li>
+ </ul>
+ </li><br>
+ <li>int exprValListAdd(exprValList *vlist, char *name, EXPRTYPE val);<br>
+ Comments:
+ <ul>
+ <li>Add a value in a value list. Returns error if value
+ already exists.</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*vlist - Value list to add a value to</li>
+ <li>*name - Name of the value to add</li>
+ <li>val - Value of the value to add</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprValListSet(exprValList *vlist, char *name, EXPRTYPE val);<br>
+ Comments:
+ <ul>
+ <li>Set a value in a value list.</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*vlist - Value list to set a value in</li>
+ <li>*name - Name of the value to set</li>
+ <li>val - Value of the value to set</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprValListGet(exprValList *vlist, char *name, EXPRTYPE *val)<br>
+ Comment:
+ <ul>
+ <li>Get the value of a variable or constant in a value list</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*vlist - Value list to use</li>
+ <li>*name - Name of the value to get</li>
+ <li>*val - Pointer to variable to get the value</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprValListAddAddress(exprValList *vlist, char *name, EXPRTYPE *addr)<br>
+ Comment:
+ <ul>
+ <li>This function is used to add a named value to the value list, but
+ uses an outside variable such as a stack variable to store the
+ value. This outside variable is used to set/get the value instead
+ of the internal list value. You must ensure that this outside
+ variable exists as long as the expression is using it's address.</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*vlist - Value list to use</li>
+ <li>*name - Name of the value to add</li>
+ <li>*addr - Address of the value being added</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprValListGetAddress(exprValList *vlist, char *name, EXPRTYPE **addr)<br>
+ Comment:
+ <ul>
+ <li>Get the memory address of a variable in a value list</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*vlist - Value list to use</li>
+ <li>*name - Name of the value to get</li>
+ <li>**addr - Pointer to a pointer to store the address of the value
+ This will be NULL if the name is not in the list.</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>void *exprValListGetNext(exprValList *vlist, char **name, EXPRTYPE *value, EXPRTYPE** addr, void *cookie);<br>
+ Comment:
+ <ul>
+ <li>This is used to enumerate the items in the value list.
+ Do NOT change the list while enumerating the items. Any
+ of the information items can be NULL if it is not needed.</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*vlist - Value list to use</li>
+ <li>**name - Address of a pointer that will point to the
+ name. Do not edit the name.</li>
+ <li>*value - The current value of the item.</li>
+ <li>**addr - Address of a pointer to store the address of the value.</li>
+ <li>*cookie - NULL to find the first item, the return value to find
+ subsequent items.</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>NULL if the item could not be found. Otherwise a cookie
+ to be used to find additional items.</li>
+ </ul>
+ </li><br>
+ <li>int exprValListFree(exprValList *vlist);<br>
+ Comments:
+ <ul>
+ <li>Completely free the value list</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*vlist - Value list to free</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprValListClear(exprValList *vlist);<br>
+ Comments:
+ <ul>
+ <li>Set the values in the list to 0.0</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*vlist - Value list to reset</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprValListInit(exprValList *vlist);<br>
+ Comments:
+ <ul>
+ <li>Initialize internal constants into a value list</li>
+ </ul>
+ Paramters:
+ <ul>
+ <li>*vlist - Value list to initialize</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li>
+ </ul>
+ </p>
+ <p><b>Expression functions:</b>
+ <ul>
+ <li>int exprCreate(exprObj **obj, exprFuncList *flist, exprValList *vlist, exprValList *clist, exprBreakFuncType breaker, void *userdata);<br>
+ Comments:
+ <ul>
+ <li>Create an expression object to use</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>**obj - Pointer to a pointer to an expression object</li>
+ <li>*flist - Function list to associate with the expression</li>
+ <li>*vlist - Variable value list to associate with the expression</li>
+ <li>*clist - Constant value list to associate with the expression</li>
+ <li>breaker - Breaker function callback to associate with the expression.
+ Used by functions that may be infinite loops (such as the for function)</li>
+ <li>userdata - User data to associate with the expression</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprFree(exprObj *obj);<br>
+ Comments:
+ <ul>
+ <li>Completely free the expression object</li>
+ </ul>
+ Paramters:
+ <ul>
+ <li>*obj - Expression object to free</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprClear(exprObj *obj);<br>
+ Comments:
+ <ul>
+ <li>Clear an expression, but keep list and callback associations.
+ You can then parse another expression without calling create</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - Expression object to clear</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprParse(exprObj *obj, char *expr);<br>
+ Comments:
+ <ul>
+ <li>Parse an expression string into an expression object</li>
+ </ul>
+ Paramters:
+ <ul>
+ <li>*obj - Expression object to use</li>
+ <li>*expr - Expression string to parse</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprEval(exprObj *obj, EXPRTYPE *val);<br>
+ Comments:
+ <ul>
+ <li>Evaluate a parsed expression. This function does not
+ reset the breaker count at each call, but instead accumulates
+ the count until the breaker function is called. Then the count
+ is reset to the value specified in exprSetBreakerCount.</li>
+ </ul>
+ Paramters:
+ <ul>
+ <li>*obj - Expression object to evaluate</li>
+ <li>*val = Pointer to variable to get result of evaluation.
+ This can be NULL if the result is not needed.</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>int exprEvalNode(exprObj *obj, exprNode *nodes, int curnode, EXPRTYPE *val);<br>
+ Comments:
+ <ul>
+ <li>Evaluate a node of an expression.
+ Used by custom functions</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - Expression object being used</li>
+ <li>*nodes - Pointer to a node or list of nodes</li>
+ <li>curnode - Index to the node to evaluate</li>
+ <li>*val - Pointer to variable to get evaluation result</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Error code of the function</li>
+ </ul>
+ </li><br>
+ <li>exprFuncList *exprGetFuncList(exprObj *obj);<br>
+ Comments:
+ <ul>
+ <li>Gets the function list associated with an expression</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expression object</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Pointer fo an exprFuncList object or NULL</li>
+ </ul>
+ </li><br>
+ <li>exprValList *exprGetVarList(exprObj *obj);<br>
+ Comments:
+ <ul>
+ <li>Gets the variable list associated with an expression</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expression object</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Pointer to an exprValList object or NULL</li>
+ </ul>
+ </li><br>
+ <li>exprValList *exprGetConstList(exprObj *obj);<br>
+ Comments:
+ <ul>
+ <li>Gets the constant list associated with an expression</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expression object</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Pointer to an exprValList object or NULL</li>
+ </ul>
+ </li><br>
+ <li>exprBreakFuncType exprGetBreakFunc(exprObj *obj);<br>
+ Comments:
+ <ul>
+ <li>Gets the breaker callback of the expression</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expression object</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Pointer to the callback function or NULL</li>
+ </ul>
+ </li><br>
+ <li>int exprGetBreakResult(exprObj *obj);<br>
+ Comments:
+ <ul>
+ <li>Get the result of the breaker function</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expression object</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>zero to continue, nonzero to break</li>
+ </ul>
+ </li><br>
+ <li>void* exprGetUserData(exprObj *obj);<br>
+ Comments:
+ <ul>
+ <li>Gets the user data associated with an expression</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expression object</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>User data</li>
+ </ul>
+ </li><br>
+ <li>void exprSetUserData(exprObj *obj, void *userdata);<br>
+ Comments:
+ <ul>
+ <li>Sets the user data of an expression</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expresion object</li>
+ <li>userdata - user data to set</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Nothing</li>
+ </ul>
+ </li><br>
+ <li>void exprSetBreakCount(exprObj *obj, int count);<br>
+ Comments:
+ <ul>
+ <li>Set how often the breaker function is tested.
+ The default is 100000. This means the breaker
+ function is tested once every 100000 times the
+ exprEvalNode function is called for an expression.
+ A smaller value tests the breaker function more often
+ and a larger value tests the breaker function less. The
+ breaker value is NOT reset during each call to exprEval,
+ but is accumulated across calles to exprEval
+ until the breaker function is finally called.</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expression object</li>
+ <li>count - how many times exprEvalNode gets called before the
+ breaker function is tested</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Nothing</li>
+ </ul>
+ </li><br>
+ <li>void exprGetErrorPosition(exprObj *obj, int *start, int *end);<br>
+ Comments:
+ <ul>
+ <li>Gets the start and ending positions in the expression string
+ of the last parse error. The positions include any newline
+ characters that may be in the string.</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*obj - expression object</li>
+ <li>*start - pointer to an integer to get the start error position,
+ -1 if unknown</li>
+ <li>*end - pointer to an integer to get the end error position,
+ -1 if unknown</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>Nothing</li>
+ </ul>
+ </ul>
+ </p>
+ <p><b>Some useful functions</b>
+ <ul>
+ <li>int exprValidIdent(char *name);<br>
+ Comments:
+ <ul>
+ <li>Determine if an identifier is valid</li>
+ </ul>
+ Parameters:
+ <ul>
+ <li>*name - identifier to check</li>
+ </ul>
+ Returns:
+ <ul>
+ <li>0 on invalid. anything else on valid</li>
+ </ul>
+ </li><br>
+ </ul>
+ </p>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Compiling">Compiling the ExprEval library</a></h2>
+ <p>Compiling the ExprEval library is pretty simple. Just
+ compile all of the source files (*.c) and link them into
+ a library. You need to keep "expreval.h" for the header file.</p>
+ <p>You may have to make some changes to the library. I've
+ tried to make doing so as simple as possible. If you
+ need to change the include files or some macros or whatnot,
+ edit the file "exprincl.h" This file includes any other files
+ needed. You should not have to change to much. I have
+ tried to stick as close to ANSI/ISO C as I can.</p>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Drawbacks">Drawbacks/Problems</a></h2>
+ <p>The following is a list of some basic drawbacks of this
+ library:
+ <ul>
+ <li>This library is an expression evaluator, and nothing
+ else. It does not simplify expressions and it
+ does not do advanced math such as calculating the
+ integrals and differentials of expression.</li>
+ <li>This library has no way of detecting overflows
+ except for those caused by the internal math
+ routines. Adding two very very large numbers
+ may cause an overflow to occur.</li>
+ <li>This library is not super easy to use in an application.
+ It has been designed to give much control to the
+ developer. Because of this, the function/value lists
+ are seperate from the expression objects, allowing
+ the developer to use them however they need.</li>
+ <li>There is no way to delete a single function, variable,
+ or constant from a list. This is because I see no
+ real need to do so because of the way the library
+ works. There is no need to delete function from
+ a function list or constants from a constant list.
+ There are are also no decent reasons to delete
+ variables from a variable list until you are completely
+ done and delete all of them.</li>
+ </ul>
+ </p>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Solutions">Problems and Solutions</a></h2>
+
+ <ul>
+ <li><b>Variables do not seem to change in a release/optimized build.</b><br>
+ I have noticed a small problem with this. Rarely, a variable may not
+ appear to change in a release build. The reason is to do with compiler
+ optimizations. For example, look at the following code:
+ <blockquote>
+ <pre>
+EXPRTYPE k;
+
+/* Add variable to the list */
+exprValListAddAddress(list, "k", &k);
+
+k = 0.0;
+
+/* Evaluate expression */
+for(int x = 0; x < 100; x++)
+ {
+ exprEval(expr, &result);
+
+ doSomething(k);
+ }
+ </pre>
+ </blockquote>
+ Inside the loop, the variable 'k' does not appear to be changing, so
+ the compiler may optimize it by loading it into a register before the
+ loop and not accessing it from memory during the loop, even if
+ the expression does change it. One way to avoid this is to use the
+ 'volatile' keyword with the variable. Then the compiler must
+ accesss it from memory each time it is accessed.
+ <blockquote>
+ <pre>
+volatile EXPRTYPE k;
+
+/* Add variable to the list */
+exprValListAddAddress(list, "k", (EXPRTYPE*)&k);
+
+k = 0.0;
+
+/* Evaluate expression */
+for(int x = 0; x < 100; x++)
+ {
+ exprEval(expr, &result);
+
+ doSomething(k);
+ }
+ </pre>
+ </blockquote>
+ </li>
+
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Example">Example Use with Fast Variable Access</a></h2>
+
+ <p>This is an example application of this library. It is a
+ graphics program that calculates the color value of a
+ pixel based on it's X,Y co-ordinate. It uses a made-up
+ image library called graphic-lib. It uses faster variable
+ access by using the exprValListGetAddress function.</p>
+ <p>Note that this codes has not actually been tested. See the
+ test applications (test and imagegen) for other examples.</p>
+
+ <blockquote>
+ <pre>
+/* Include files */
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include "graphiclib.h"
+#include "expreval.h"
+
+char *transerr(int err)
+ {
+ /* Translate error code into message */
+ }
+
+void gen_image(char *name, int w, int h, char *expr);
+ {
+ exprFuncList *f = NULL;
+ exprValList *v = NULL;
+ exprValList *c = NULL;
+ exprObj *o = NULL;
+ int x, y, err;
+ jmp_buf jumper;
+ int image;
+ EXPRTYPE *v_x, *v_y;
+ EXPRTYPE *v_r, *v_g, *v_b;
+ EXPRTYPE global_value;
+
+ /* Error handling */
+ err = setjmp(jumper);
+ if(err)
+ {
+ if(err != ID_IMAGENOERROR)
+ printf("Error %d occurred: %s\n", err, transerr(err));
+
+ exprFree(o);
+ exprFreeFuncList(f);
+ exprFreeValList(v);
+ exprFreeValList(c);
+
+ image_free(image);
+ return;
+ }
+
+ /* Set up lists */
+
+ /* Function list */
+ err = exprFuncListCreate(&f);
+ if(err != EXPR_ERROR_NOERROR)
+ longjmp(jumper, err);
+
+ err = exprFuncListInit(f);
+ if(err != EXPR_ERROR_NOERROR)
+ {
+ printf("Function list init error. Functions may not be available.\n");
+ }
+
+ /* Variable list */
+ err = exprValListCreate(&v);
+ if(err != EXPR_ERROR_NOERROR)
+ longjmp(jumper, err);
+
+ /* Constant list */
+ err = exprValListCreate(&c);
+ if(err != EXPR_ERROR_NOERROR)
+ {
+ printf("Constants not available\n");
+ }
+ else
+ {
+ err = exprValListInit(c);
+ if(err != EXPR_ERROR_NOERROR)
+ printf("Constant list init error. Constants may not be available.\n");
+ }
+
+ /* Create and parse the expression */
+
+ /* Create */
+ err = exprCreate(&o, f, v, c, NULL, 0);
+ if(err != EXPR_ERROR_NOERROR)
+ longjmp(jumper, err);
+
+ /* Parse expression */
+ err = exprParse(o, expr);
+ if(err != EXPR_ERROR_NOERROR)
+ longjmp(jumper, err);
+
+
+ /* Create the image */
+ image = image_create(w, h);
+ if(image == 0)
+ {
+ longjmp(jumper, ID_IMAGECREATEERROR);
+ }
+
+ /* Add width and height to variable list */
+ exprValListAdd(v, "w", (EXPRTYPE)w);
+ exprValListAdd(v, "h", (EXPRTYPE)h);
+
+ /* Add x and y to the list */
+ exprValListAdd(v, "x", 0.0);
+ exprValListAdd(v, "y", 0.0);
+
+ /* Add r, g, and b to the list */
+ exprValListAdd(v, "r", 0.0);
+ exprValListAdd(v, "g", 0.0);
+ exprValListAdd(b, "b", 0.0);
+
+ /* Get addresses. Assume no error */
+ exprValListGetAddress(v, "x", &v_x);
+ exprValListGetAddress(v, "y", &v_y);
+
+ exprValListGetAddress(v, "r", &v_r);
+ exprValListGetAddress(v, "g", &v_g);
+ exprValListGetAddress(v, "g", &v_b);
+
+ /* A way to add global variables that can be used by two different lists. */
+ exprValListAddAddress(v, "global", &global_value);
+ /* exprValListAddAddress(v2, "global", &global_value); */
+
+ /* Also, exprValListAddAddress can be used to add variables directly.
+ Instead of:
+
+ EXPRTYPE *a;
+
+ exprValListAdd(v, "a", 0.0);
+ exprValListGetAddresss(v, "a", &a);
+
+ You can do:
+
+ EXPRTYPE a;
+
+ exprValListAddAddresss(v, "a", &a);
+
+ If you do this, you must ensure that the stack variable exists as long
+ as it is used by expression, otherwise it may cause a memory access
+ violation. */
+
+
+ for(y = 0; y < h; y++)
+ {
+ for(x = 0; x < w; x++)
+ {
+ /* Directly set the x and y variables */
+ *v_x = (EXPRTYPE)x;
+ *v_y = (EXPRTYPE)y;
+
+ /* Eval expression, ignoring errors */
+ exprEval(o);
+
+ /* Set pixel, using variables directly */
+ image_setpixel(image, x, y, (int)(*v_r), (int)(*v_g), (int)(*v_b));
+ }
+ }
+
+ /* Save image */
+ image_save(image, name);
+
+ /* Done */
+ longjmp(jumper, ID_IMAGENOERROR);
+ }
+
+void main(void)
+ {
+ char name[MAXPATH]
+ char tmp[10];
+ char expr[4096];
+ int sx, sy;
+
+ printf("Image name to save: ");
+ gets(name);
+
+ printf("Image width: ");
+ gets(tmp);
+ sx = atoi(tmp);
+
+ printf("Image height: ");
+ gets(tmp);
+ sy = atoi(tmp);
+
+ printf("Color Expression (Use x, y, w, h Set r, g, b): ");
+ gets(expr);
+
+ gen_image(name, sx, sy, expr);
+ }
+
+ </pre>
+ </blockquote>
+</div>
+
+</body>
+</html>
-<html>\r
-\r
-<head>\r
-<title>Expression Help</title>\r
-<style type="text/css">\r
-.valid {\r
- color: #00AA00;\r
-}\r
-.invalid {\r
- color: #FF0000;\r
-}\r
-.excomment {\r
- color: #0000FF;\r
-}\r
-.container {\r
- margin-top: 10px;\r
- margin-bottom: 10px;\r
- padding-left: 4px;\r
- padding-right: 4px;\r
- border-top: 1px solid #000000;\r
- border-right: 1px solid #000000;\r
- border-bottom: 1px solid #000000;\r
- border-left: 1px solid #000000;\r
- background-color: #BBBBBB;\r
-}\r
-body {\r
- background-color: #AAAAAA;\r
-}\r
-</style>\r
-</head>\r
-\r
-<body>\r
-\r
-<div align="center">\r
- <h1>Expression Help</h1>\r
- <hr>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2>Contents</h2>\r
- <h3>\r
- <ul>\r
- <li><a href="#Syntax">Expression Syntax</a></li>\r
- <li><a href="#Operators">Order of Operators</a></li>\r
- <li><a href="#InternalFunc">ExprEval Internal Functions</a></li>\r
- <li><a href="#InternalConst">ExprEval Internal Constants</a></li>\r
- <li><a href="#AppFunc">Application Internal Functions</a></li>\r
- <li><a href="#AppConst">Application Internal Constants</a></li>\r
- <li><a href="#AppVar">Application Internal Variables</a></li>\r
- </ul>\r
- </h3>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Syntax">Expression Syntax</a></h2>\r
- <blockquote>\r
- <p>Expressions have pretty much the same syntax as they\r
- would have on paper, with the following exceptions:\r
- <ul>\r
- <li>Each expression must end with a semicolon. This\r
- is because the expression string can actually\r
- contain multiple expressions. The semicolon is\r
- used to mark the end of the expression.<br>\r
- <b>Examples:</b>\r
- <ul>\r
- <li>4*x+5;</li>\r
- <li>y=5+2;g=4+6;</li>\r
- <li>y=r*sin(a);x=r*cos(a);</li>\r
- </ul>\r
- </li>\r
- <li>The asterisk '*' must be used to multiply.<br>\r
- <b>Examples:</b>\r
- <ul>\r
- <li>y=5*6; <b class="valid">Valid</b></li>\r
- <li>g=(x+1)*(x-1); <b class="valid">Valid</b></li>\r
- <li>g=(x+1)(x-1); <b class="invalid">Invalid</b></li>\r
- </ul>\r
- </li>\r
- </ul>\r
- </p>\r
- <p>More than one expression may be contained within an expression string.\r
- As shown above, each expression must end with a semicolon, even if\r
- only one expression is in the string. The value of an expression\r
- string is the value of the last expression in the string.<br>\r
- <b>Examlples:</b>\r
- <ul>\r
- <li>g=7; <b class="excomment">Value: 7</b></li>\r
- <li>k=z+1; <b class="excomment">Value: z+1</b></li>\r
- <li>r=4;k=6;o=9+r-k; <b class="excomment">Value: 9+r-k</b></li>\r
- </ul>\r
- </p>\r
- <p>Some functions may take reference parameters. These parameters are\r
- references to other variables. You can mix reference parameters\r
- with normal parameters. The order of the normal parameters must\r
- remain the same and the order of the reference parameters must\r
- remain the same.<br>\r
- <b>Examples:</b>\r
- <ul>\r
- <li>min(1,2,3,4,&mval); <b class="excomment">&mval is a reference to a variable mval</b></li>\r
- <li>min(1,2,&mval,3,4); <b class="excomment">You may mix them inside like this.</b></li>\r
- <li>min(1,2,(&mval),3,4); <b class="invalid">You may not nest reference parameters in any way</b></li>\r
- </ul>\r
- </p>\r
- <p>Expressions may also be nested with parenthesis.<br>\r
- <b>Examples:</b>\r
- <ul>\r
- <li>y=sin(x-cos(5+max(4,5,6*x)));</li>\r
- <li>6+(5-2*(x+y));</li>\r
- </ul>\r
- </p>\r
- <p>Expressions may also have whitespace characters and comments.\r
- Whitespace characters such as newlines, linefeeds, carriage\r
- returns, spaces, and tabs are ignored. Comments begin with\r
- the pound sign '#' and end at the end of the line.<br>\r
- <b>Example:</b>\r
- <ul>\r
- <pre>\r
-#Set the x value\r
-x = d * cos(r);\r
-\r
-#Set the y value\r
-y = d * sin(r);\r
- </pre>\r
- </ul>\r
- </p>\r
- <p>If a variable is used in an expression, but that variable does not exist,\r
- it is considered zero. If it does exist then its value is used instead.\r
- </p>\r
- <p><b>Notice:</b> An expression can <b>NOT</b> assign to a constant and an\r
- expression can <b>NOT</b> use a constant as a reference parameter.\r
- </p>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="Operators">Order of operators.</a></h2>\r
- <blockquote>\r
- <p>The order of operators are processed correctly in ExprEval.\r
- The parameters to functions may be evaluated out of order, depending\r
- on the function itself.</p>\r
-\r
- The following illustrates the order of operators:\r
- <table align="center" border="1" width="75%">\r
- <tr>\r
- <td align="center"><b>Operator</b></td>\r
- <td align="center"><b>Direction</b></td>\r
- <td align="center"><b>Example</b></td>\r
- </tr>\r
- <tr>\r
- <td>Functions and Parenthesis</td>\r
- <td>N/A</td>\r
- <td>(x + 5) * sin(d);</td>\r
- </tr>\r
- <tr>\r
- <td>Negation</td>\r
- <td>Right to Left</td>\r
- <td>y = -2;</td>\r
- </tr>\r
- <tr>\r
- <td>Exponents</td>\r
- <td>Left to Right</td>\r
- <td>y = x ^ 2;</td>\r
- </tr>\r
- <tr>\r
- <td>Multiplication and Division</td>\r
- <td>Left to Right</td>\r
- <td>x * 5 / y;</td>\r
- </tr>\r
- <tr>\r
- <td>Addition and Subtraction</td>\r
- <td>Left to Right</td>\r
- <td>4 + 5 - 3;</td>\r
- </tr>\r
- <tr>\r
- <td>Assignment</td>\r
- <td>Right to Left</td>\r
- <td>x = y = z = 0;</td>\r
- </tr>\r
- </table>\r
-\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="InternalFunc">ExprEval Internal Functions</a></h2>\r
- <blockquote>\r
- The following functions are provided with ExprEval:\r
- <table align="center" border="1" width="75%">\r
- <tr>\r
- <td align="center"><b>Function</b></td>\r
- <td align="center"><b>Min. Args</b></td>\r
- <td align="center"><b>Max. Args</b></td>\r
- <td align="center"><b>Min. Ref Args</b></td>\r
- <td align="center"><b>Max. Ref Args</b></td>\r
- <td align="center"><b>Result/Comment</b></td>\r
- </tr>\r
- <tr>\r
- <td>abs(v)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Absolute value of v.<br>\r
- abs(-4.3) returns 4.3</td>\r
- </tr>\r
- <tr>\r
- <td>mod(v,d)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Remainder of v/d.<br>\r
- mod(5.2,2.5) return 0.2</td>\r
- </tr>\r
- <tr>\r
- <td>ipart(v)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The integer part of v.<br>\r
- ipart(3.2) returns 3</td>\r
- </tr>\r
- <tr>\r
- <td>fpart(v)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The fractional part of v.<br>\r
- fpart(3.2) returns 0.2</td>\r
- </tr>\r
- <tr>\r
- <td>min(v,...)</td>\r
- <td>1</td>\r
- <td>None</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The minimum number passed.<br>\r
- min(3,2,-5,-2,7) returns -5</td>\r
- </tr>\r
- <tr>\r
- <td>max(v,...)</td>\r
- <td>1</td>\r
- <td>None</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The maximum number passed.<br>\r
- max(3,2,-5,-2,7) returns 7</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>pow(a,b)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The value a raised to the power b.<br>\r
- pow(3.2,1.7) returns 3.2<sup>1.7</sup></td>\r
- </tr>\r
- <tr>\r
- <td>sqrt(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The square root of a.</br>\r
- sqrt(16) returns 4</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>sin(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The sine of a radians.<br>\r
- sin(1.5) returns around 0.997</td>\r
- </tr>\r
- <tr>\r
- <td>sinh(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The hyperbolic sine of a.<br>\r
- sinh(1.5) returns around 2.129</td>\r
- </tr>\r
- <tr>\r
- <td>asin(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The arc-sine of a in radians.<br>\r
- asin(0.5) returns around 0.524</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>cos(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The cosine of a radians.<br>\r
- cos(1.5) returns around 0.0707</td>\r
- </tr>\r
- <tr>\r
- <td>cosh(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The hyperbolic cosine of a.</br>\r
- cosh(1.5) returns around 2.352</td>\r
- </tr>\r
- <tr>\r
- <td>acos(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The arc-cosine of a in radians.<br>\r
- acos(0.5) returns around 1.047</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>tan(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The tangent of a radians.<br>\r
- tan(1.5) returns around 14.101</td>\r
- </tr>\r
- <tr>\r
- <td>tanh(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The hyperbolic tangent of a.</br>\r
- tanh(1.5) returns around 0.905</td>\r
- </tr>\r
- <tr>\r
- <td>atan(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The arc-tangent of a in radians.<br>\r
- atan(0.3) returns about 0.291</td>\r
- </tr>\r
- <tr>\r
- <td>atan2(y,x)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The arc-tangent of y/x, with quadrant correction.<br>\r
- atan2(4,3) returns about 0.927</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>log(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The base 10 logarithm of a.<br>\r
- log(100) returns 2</td>\r
- </tr>\r
- <tr>\r
- <td>pow10(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>10 raised to the power of a.<br>\r
- pow10(2) returns 100</td>\r
- </tr>\r
- <tr>\r
- <td>ln(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The base e logarithm of a.<br>\r
- ln(2.8) returns around 1.030</td>\r
- </tr>\r
- <tr>\r
- <td>exp(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>e raised to the power of a.<br>\r
- exp(2) returns around 7.389</td>\r
- </tr>\r
- <tr>\r
- <td>logn(a,b)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>The base b logarithm of a.<br>\r
- logn(16,2) returns 4</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>ceil(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Rounds a up to the nearest integer.<br>\r
- ceil(3.2) returns 4</td>\r
- </tr>\r
- <tr>\r
- <td>floor(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Rounds a down to the nearest integer.<br>\r
- floor(3.2) returns 3</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>rand(&seed)</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>Returns a number between 0 up to but not including 1.</td>\r
- </tr>\r
- <tr>\r
- <td>random(a,b,&seed)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>Returns a number between a up to and including b.</td>\r
- </tr>\r
- <tr>\r
- <td>randomize(&seed)</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>Seed the random number generator with a value\r
- based on the current time.<br>\r
- Return value is unknown</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>deg(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns a radians converted to degrees.<br>\r
- deg(3.14) returns around 179.909</td>\r
- </tr>\r
- <tr>\r
- <td>rad(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns a degrees converted to radians.<br>\r
- rad(180) returns around 3.142</td>\r
- </tr>\r
- <tr>\r
- <td>recttopolr(x,y)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns the polar radius of the rectangular co-ordinates.<br>\r
- recttopolr(2,3) returns around 3.606</td>\r
- </tr>\r
- <tr>\r
- <td>recttopola(x,y)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns the polar angle (0...2PI) in radians of the rectangular co-ordinates.<br>\r
- recttopola(2,3) returns around 0.588</td>\r
- </tr>\r
- <tr>\r
- <td>poltorectx(r,a)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns the x rectangular co-ordinate of the polar\r
- co-ordinates.<br>\r
- poltorectx(3,1.5) returns around 0.212</td>\r
- </tr>\r
- <tr>\r
- <td>poltorecty(r,a)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns the y rectangular co-ordinate of the polar\r
- co-ordinates.<br>\r
- poltorecty(3,1.5) returns around 2.992</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>if(c,t,f)</td>\r
- <td>3</td>\r
- <td>3</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Evaluates and returns t if c is not 0.0.\r
- Else evaluates and returns f.<br>\r
- if(0.1,2.1,3.9) returns 2.1</td>\r
- </tr>\r
- <tr>\r
- <td>select(c,n,z[,p])</td>\r
- <td>3</td>\r
- <td>4</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns n if c is less than 0.0. Returns z\r
- if c is 0.0. If c is greater than 0.0 and only\r
- three arguments were passed, returns z. If c\r
- is greater than 0.0 and four arguments were passed,\r
- return p.<br>\r
- select(3,1,4,5) returns 5</td>\r
- </tr>\r
- <tr>\r
- <td>equal(a,b)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns 1.0 if a is equal to b. Else returns 0.0<br>\r
- equal(3,2) returns 0.0</td>\r
- </tr>\r
- <tr>\r
- <td>above(a,b)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns 1.0 if a is above b. Else returns 0.0<br>\r
- above(3,2) returns 1.0</td>\r
- </tr>\r
- <tr>\r
- <td>below(a,b)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns 1.0 if a is below b. Else returns 0.0<br>\r
- below(3,2) returns 0.0</td>\r
- </tr>\r
-\r
- <tr>\r
- <td>avg(a,...)</td>\r
- <td>1</td>\r
- <td>None</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns the average of the values passed.<br>\r
- avg(3,3,6) returns 4</td>\r
- </tr>\r
- <tr>\r
- <td>clip(v,min,max)</td>\r
- <td>3</td>\r
- <td>3</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Clips v to the range from min to max. If v is less\r
- than min, it returns min. If v is greater than\r
- max it returns max. Otherwise it returns v.<br>\r
- clip(3,1,2) returns 2</td>\r
- </tr>\r
- <tr>\r
- <td>clamp(v,min,max)</td>\r
- <td>3</td>\r
- <td>3</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Clamps v to the range from min to max, looping\r
- if needed.<br>\r
- clamp(8.2,1.3,4.7) returns 1.4</td>\r
- </tr>\r
- <tr>\r
- <td>pntchange(side1old, side2old, side1new, side2new, oldpnt)</td>\r
- <td>5</td>\r
- <td>5</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>This is used to translate points from different\r
- scale. It works no matter the orientation as long\r
- as the sides are lined up correctly.<br>\r
- pntchange(-1,1,0,480,-0.5) returns 120 (x example)<br>\r
- pntchange(-1,1,480,0,-0.5) returns 360 (y example)</td>\r
- </tr>\r
- <tr>\r
- <td>poly(x,c1,...)</td>\r
- <td>2</td>\r
- <td>None</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>This function calculates the polynomial. x is the value\r
- to use in the polynomial. c1 and on are the coefficients.<br>\r
- poly(4,6,9,3,1,4) returns 2168<br>\r
- same as 6*4<sup>4</sup> + 9*4<sup>3</sup> + 3*4<sup>2</sup> + 1*4<sup>1</sup> + 4*4<sup>0</sup></td>\r
- </tr>\r
-\r
- <tr>\r
- <td>and(a,b)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns 0.0 if either a or b are 0.0 Else returns 1.0<br>\r
- and(2.1,0.0) returns 0.0</td>\r
- </tr>\r
- <tr>\r
- <td>or(a,b)</td>\r
- <td>2</td>\r
- <td>2</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns 0.0 if both a and b are 0.0 Else returns 1.0<br>\r
- or(2.1,0.0) returns 1.0</td>\r
- </tr>\r
- <tr>\r
- <td>not(a)</td>\r
- <td>1</td>\r
- <td>1</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>Returns 1.0 if a is 0.0 Else returns 0.0<br>\r
- not(0.3) returns 0.0</td>\r
- </tr>\r
- <tr>\r
- <td>for(init,test,inc,a1,...)</td>\r
- <td>4</td>\r
- <td>None</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>This function acts like a for loop in C. First init is\r
- evaluated. Then test is evaluated. As long as the\r
- test is not 0.0, the action statements (a1 to an) are\r
- evaluated, the inc statement is evaluated, and the test\r
- is evaluated again. The result is the result of the\r
- final action statement.<br>\r
- for(x=0,below(x,11),x=x+1,y=y+x) returns 55.0 (if y was\r
- initially 0.0)</td>\r
- </tr>\r
- <tr>\r
- <td>many(expr,...)</td>\r
- <td>1</td>\r
- <td>None</td>\r
- <td>0</td>\r
- <td>0</td>\r
- <td>This function treats many subexpressions as a single object\r
- (function). It is mainly for the 'for' function.<br>\r
- for(many(j=5,k=1),above(j*k,0.001),many(j=j+5,k=k/2),0)</td>\r
- </tr>\r
-\r
-\r
- </table>\r
-\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="InternalConst">ExprEval Internal Constants</a></h2>\r
- <blockquote>\r
- The following constants are provided with ExprEval:\r
- <table align="center" border="1" width="75%">\r
- <tr>\r
- <td align="center"><b>Constant</b></td>\r
- <td align="center"><b>Math Form</b></td>\r
- <td align="center"><b>Value</b></td>\r
- </tr>\r
- <tr>\r
- <td>M_E</td>\r
- <td>e</td>\r
- <td>2.7182818284590452354</td>\r
- </tr>\r
- <tr>\r
- <td>M_LOG2E</td>\r
- <td>log<sub>2</sub>(e)</td>\r
- <td>1.4426950408889634074</td>\r
- </tr>\r
- <tr>\r
- <td>M_LOG10E</td>\r
- <td>log<sub>10</sub>(e)</td>\r
- <td>0.43429448190325182765</td>\r
- </tr>\r
- <tr>\r
- <td>M_LN2</td>\r
- <td>ln(2)</td>\r
- <td>0.69314718055994530942</td>\r
- </tr>\r
- <tr>\r
- <td>M_LN10</td>\r
- <td>ln(10)</td>\r
- <td>2.30258509299404568402</td>\r
- </tr>\r
- <tr>\r
- <td>M_PI</td>\r
- <td>π</td>\r
- <td>3.14159265358979323846</td>\r
- </tr>\r
- <tr>\r
- <td>M_PI_2</td>\r
- <td>π/2</td>\r
- <td>1.57079632679489661923</td>\r
- </tr>\r
- <tr>\r
- <td>M_PI_4</td>\r
- <td>π/4</td>\r
- <td>0.78539816339744830962</td>\r
- </tr>\r
- <tr>\r
- <td>M_1_PI</td>\r
- <td>1/π</td>\r
- <td>0.31830988618379067154</td>\r
- </tr>\r
- <tr>\r
- <td>M_2_PI</td>\r
- <td>2/π</td>\r
- <td>0.63661977236758134308</td>\r
- </tr>\r
- <tr>\r
- <td>M_1_SQRTPI</td>\r
- <td>1/√(π)</td>\r
- <td>0.56418958354776</td>\r
- </tr>\r
- <tr>\r
- <td>M_2_SQRTPI</td>\r
- <td>2/√(π)</td>\r
- <td>1.12837916709551257390</td>\r
- </tr>\r
- <tr>\r
- <td>M_SQRT2</td>\r
- <td>√(2)</td>\r
- <td>1.41421356237309504880</td>\r
- </tr>\r
- <tr>\r
- <td>M_1_SQRT2</td>\r
- <td>1/√(2)</td>\r
- <td>0.70710678118654752440</td>\r
- </tr>\r
- </table>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="AppFunc">Application Internal Functions</a></h2>\r
- <blockquote>\r
- Application defined expression functions go here.\r
- <table align="center" border="1" width="75%">\r
- <tr>\r
- <td align="center"><b>Function</b></td>\r
- <td align="center"><b>Min. Args</b></td>\r
- <td align="center"><b>Max. Args</b></td>\r
- <td align="center"><b>Min. Ref Args</b></td>\r
- <td align="center"><b>Max. Ref Args</b></td>\r
- <td align="center"><b>Result/Comment</b></td>\r
- </tr>\r
- <tr>\r
- <td></td>\r
- <td></td>\r
- <td></td>\r
- <td></td>\r
- <td></td>\r
- <td></td>\r
- </tr>\r
- </table>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="AppConst">Application Internal Constants</a></h2>\r
- <blockquote>\r
- Application defined expression constants go here.\r
- <table align="center" border="1" width="75%">\r
- <tr>\r
- <td align="center"><b>Constant</b></td>\r
- <td align="center"><b>Math Form</b></td>\r
- <td align="center"><b>Value</b></td>\r
- </tr>\r
- <tr>\r
- <td></td>\r
- <td></td>\r
- <td></td>\r
- </tr>\r
- </table>\r
- </blockquote>\r
-</div>\r
-\r
-<div align="left" class="container">\r
- <h2><a name="AppVar">Application Internal Variables</a></h2>\r
- <blockquote>\r
- Application defined expression variables go here.\r
- <table align="center" border="1" width="75%">\r
- <tr>\r
- <td align="center"><b>Variable</b></td>\r
- <td align="center"><b>Math Form</b></td>\r
- <td align="center"><b>Value</b></td>\r
- </tr>\r
- <tr>\r
- <td></td>\r
- <td></td>\r
- <td></td>\r
- </tr>\r
- </table>\r
- </blockquote>\r
-</div>\r
-\r
-</body>\r
-\r
-</html>\r
-\r
-\r
+<html>
+
+<head>
+<title>Expression Help</title>
+<style type="text/css">
+.valid {
+ color: #00AA00;
+}
+.invalid {
+ color: #FF0000;
+}
+.excomment {
+ color: #0000FF;
+}
+.container {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding-left: 4px;
+ padding-right: 4px;
+ border-top: 1px solid #000000;
+ border-right: 1px solid #000000;
+ border-bottom: 1px solid #000000;
+ border-left: 1px solid #000000;
+ background-color: #BBBBBB;
+}
+body {
+ background-color: #AAAAAA;
+}
+</style>
+</head>
+
+<body>
+
+<div align="center">
+ <h1>Expression Help</h1>
+ <hr>
+</div>
+
+<div align="left" class="container">
+ <h2>Contents</h2>
+ <h3>
+ <ul>
+ <li><a href="#Syntax">Expression Syntax</a></li>
+ <li><a href="#Operators">Order of Operators</a></li>
+ <li><a href="#InternalFunc">ExprEval Internal Functions</a></li>
+ <li><a href="#InternalConst">ExprEval Internal Constants</a></li>
+ <li><a href="#AppFunc">Application Internal Functions</a></li>
+ <li><a href="#AppConst">Application Internal Constants</a></li>
+ <li><a href="#AppVar">Application Internal Variables</a></li>
+ </ul>
+ </h3>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Syntax">Expression Syntax</a></h2>
+ <blockquote>
+ <p>Expressions have pretty much the same syntax as they
+ would have on paper, with the following exceptions:
+ <ul>
+ <li>Each expression must end with a semicolon. This
+ is because the expression string can actually
+ contain multiple expressions. The semicolon is
+ used to mark the end of the expression.<br>
+ <b>Examples:</b>
+ <ul>
+ <li>4*x+5;</li>
+ <li>y=5+2;g=4+6;</li>
+ <li>y=r*sin(a);x=r*cos(a);</li>
+ </ul>
+ </li>
+ <li>The asterisk '*' must be used to multiply.<br>
+ <b>Examples:</b>
+ <ul>
+ <li>y=5*6; <b class="valid">Valid</b></li>
+ <li>g=(x+1)*(x-1); <b class="valid">Valid</b></li>
+ <li>g=(x+1)(x-1); <b class="invalid">Invalid</b></li>
+ </ul>
+ </li>
+ </ul>
+ </p>
+ <p>More than one expression may be contained within an expression string.
+ As shown above, each expression must end with a semicolon, even if
+ only one expression is in the string. The value of an expression
+ string is the value of the last expression in the string.<br>
+ <b>Examlples:</b>
+ <ul>
+ <li>g=7; <b class="excomment">Value: 7</b></li>
+ <li>k=z+1; <b class="excomment">Value: z+1</b></li>
+ <li>r=4;k=6;o=9+r-k; <b class="excomment">Value: 9+r-k</b></li>
+ </ul>
+ </p>
+ <p>Some functions may take reference parameters. These parameters are
+ references to other variables. You can mix reference parameters
+ with normal parameters. The order of the normal parameters must
+ remain the same and the order of the reference parameters must
+ remain the same.<br>
+ <b>Examples:</b>
+ <ul>
+ <li>min(1,2,3,4,&mval); <b class="excomment">&mval is a reference to a variable mval</b></li>
+ <li>min(1,2,&mval,3,4); <b class="excomment">You may mix them inside like this.</b></li>
+ <li>min(1,2,(&mval),3,4); <b class="invalid">You may not nest reference parameters in any way</b></li>
+ </ul>
+ </p>
+ <p>Expressions may also be nested with parenthesis.<br>
+ <b>Examples:</b>
+ <ul>
+ <li>y=sin(x-cos(5+max(4,5,6*x)));</li>
+ <li>6+(5-2*(x+y));</li>
+ </ul>
+ </p>
+ <p>Expressions may also have whitespace characters and comments.
+ Whitespace characters such as newlines, linefeeds, carriage
+ returns, spaces, and tabs are ignored. Comments begin with
+ the pound sign '#' and end at the end of the line.<br>
+ <b>Example:</b>
+ <ul>
+ <pre>
+#Set the x value
+x = d * cos(r);
+
+#Set the y value
+y = d * sin(r);
+ </pre>
+ </ul>
+ </p>
+ <p>If a variable is used in an expression, but that variable does not exist,
+ it is considered zero. If it does exist then its value is used instead.
+ </p>
+ <p><b>Notice:</b> An expression can <b>NOT</b> assign to a constant and an
+ expression can <b>NOT</b> use a constant as a reference parameter.
+ </p>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="Operators">Order of operators.</a></h2>
+ <blockquote>
+ <p>The order of operators are processed correctly in ExprEval.
+ The parameters to functions may be evaluated out of order, depending
+ on the function itself.</p>
+
+ The following illustrates the order of operators:
+ <table align="center" border="1" width="75%">
+ <tr>
+ <td align="center"><b>Operator</b></td>
+ <td align="center"><b>Direction</b></td>
+ <td align="center"><b>Example</b></td>
+ </tr>
+ <tr>
+ <td>Functions and Parenthesis</td>
+ <td>N/A</td>
+ <td>(x + 5) * sin(d);</td>
+ </tr>
+ <tr>
+ <td>Negation</td>
+ <td>Right to Left</td>
+ <td>y = -2;</td>
+ </tr>
+ <tr>
+ <td>Exponents</td>
+ <td>Left to Right</td>
+ <td>y = x ^ 2;</td>
+ </tr>
+ <tr>
+ <td>Multiplication and Division</td>
+ <td>Left to Right</td>
+ <td>x * 5 / y;</td>
+ </tr>
+ <tr>
+ <td>Addition and Subtraction</td>
+ <td>Left to Right</td>
+ <td>4 + 5 - 3;</td>
+ </tr>
+ <tr>
+ <td>Assignment</td>
+ <td>Right to Left</td>
+ <td>x = y = z = 0;</td>
+ </tr>
+ </table>
+
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="InternalFunc">ExprEval Internal Functions</a></h2>
+ <blockquote>
+ The following functions are provided with ExprEval:
+ <table align="center" border="1" width="75%">
+ <tr>
+ <td align="center"><b>Function</b></td>
+ <td align="center"><b>Min. Args</b></td>
+ <td align="center"><b>Max. Args</b></td>
+ <td align="center"><b>Min. Ref Args</b></td>
+ <td align="center"><b>Max. Ref Args</b></td>
+ <td align="center"><b>Result/Comment</b></td>
+ </tr>
+ <tr>
+ <td>abs(v)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Absolute value of v.<br>
+ abs(-4.3) returns 4.3</td>
+ </tr>
+ <tr>
+ <td>mod(v,d)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Remainder of v/d.<br>
+ mod(5.2,2.5) return 0.2</td>
+ </tr>
+ <tr>
+ <td>ipart(v)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The integer part of v.<br>
+ ipart(3.2) returns 3</td>
+ </tr>
+ <tr>
+ <td>fpart(v)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The fractional part of v.<br>
+ fpart(3.2) returns 0.2</td>
+ </tr>
+ <tr>
+ <td>min(v,...)</td>
+ <td>1</td>
+ <td>None</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The minimum number passed.<br>
+ min(3,2,-5,-2,7) returns -5</td>
+ </tr>
+ <tr>
+ <td>max(v,...)</td>
+ <td>1</td>
+ <td>None</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The maximum number passed.<br>
+ max(3,2,-5,-2,7) returns 7</td>
+ </tr>
+
+ <tr>
+ <td>pow(a,b)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The value a raised to the power b.<br>
+ pow(3.2,1.7) returns 3.2<sup>1.7</sup></td>
+ </tr>
+ <tr>
+ <td>sqrt(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The square root of a.</br>
+ sqrt(16) returns 4</td>
+ </tr>
+
+ <tr>
+ <td>sin(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The sine of a radians.<br>
+ sin(1.5) returns around 0.997</td>
+ </tr>
+ <tr>
+ <td>sinh(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The hyperbolic sine of a.<br>
+ sinh(1.5) returns around 2.129</td>
+ </tr>
+ <tr>
+ <td>asin(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The arc-sine of a in radians.<br>
+ asin(0.5) returns around 0.524</td>
+ </tr>
+
+ <tr>
+ <td>cos(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The cosine of a radians.<br>
+ cos(1.5) returns around 0.0707</td>
+ </tr>
+ <tr>
+ <td>cosh(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The hyperbolic cosine of a.</br>
+ cosh(1.5) returns around 2.352</td>
+ </tr>
+ <tr>
+ <td>acos(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The arc-cosine of a in radians.<br>
+ acos(0.5) returns around 1.047</td>
+ </tr>
+
+ <tr>
+ <td>tan(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The tangent of a radians.<br>
+ tan(1.5) returns around 14.101</td>
+ </tr>
+ <tr>
+ <td>tanh(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The hyperbolic tangent of a.</br>
+ tanh(1.5) returns around 0.905</td>
+ </tr>
+ <tr>
+ <td>atan(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The arc-tangent of a in radians.<br>
+ atan(0.3) returns about 0.291</td>
+ </tr>
+ <tr>
+ <td>atan2(y,x)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The arc-tangent of y/x, with quadrant correction.<br>
+ atan2(4,3) returns about 0.927</td>
+ </tr>
+
+ <tr>
+ <td>log(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The base 10 logarithm of a.<br>
+ log(100) returns 2</td>
+ </tr>
+ <tr>
+ <td>pow10(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>10 raised to the power of a.<br>
+ pow10(2) returns 100</td>
+ </tr>
+ <tr>
+ <td>ln(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The base e logarithm of a.<br>
+ ln(2.8) returns around 1.030</td>
+ </tr>
+ <tr>
+ <td>exp(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>e raised to the power of a.<br>
+ exp(2) returns around 7.389</td>
+ </tr>
+ <tr>
+ <td>logn(a,b)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>The base b logarithm of a.<br>
+ logn(16,2) returns 4</td>
+ </tr>
+
+ <tr>
+ <td>ceil(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Rounds a up to the nearest integer.<br>
+ ceil(3.2) returns 4</td>
+ </tr>
+ <tr>
+ <td>floor(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Rounds a down to the nearest integer.<br>
+ floor(3.2) returns 3</td>
+ </tr>
+
+ <tr>
+ <td>rand(&seed)</td>
+ <td>0</td>
+ <td>0</td>
+ <td>1</td>
+ <td>1</td>
+ <td>Returns a number between 0 up to but not including 1.</td>
+ </tr>
+ <tr>
+ <td>random(a,b,&seed)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>1</td>
+ <td>1</td>
+ <td>Returns a number between a up to and including b.</td>
+ </tr>
+ <tr>
+ <td>randomize(&seed)</td>
+ <td>0</td>
+ <td>0</td>
+ <td>1</td>
+ <td>1</td>
+ <td>Seed the random number generator with a value
+ based on the current time.<br>
+ Return value is unknown</td>
+ </tr>
+
+ <tr>
+ <td>deg(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns a radians converted to degrees.<br>
+ deg(3.14) returns around 179.909</td>
+ </tr>
+ <tr>
+ <td>rad(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns a degrees converted to radians.<br>
+ rad(180) returns around 3.142</td>
+ </tr>
+ <tr>
+ <td>recttopolr(x,y)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns the polar radius of the rectangular co-ordinates.<br>
+ recttopolr(2,3) returns around 3.606</td>
+ </tr>
+ <tr>
+ <td>recttopola(x,y)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns the polar angle (0...2PI) in radians of the rectangular co-ordinates.<br>
+ recttopola(2,3) returns around 0.588</td>
+ </tr>
+ <tr>
+ <td>poltorectx(r,a)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns the x rectangular co-ordinate of the polar
+ co-ordinates.<br>
+ poltorectx(3,1.5) returns around 0.212</td>
+ </tr>
+ <tr>
+ <td>poltorecty(r,a)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns the y rectangular co-ordinate of the polar
+ co-ordinates.<br>
+ poltorecty(3,1.5) returns around 2.992</td>
+ </tr>
+
+ <tr>
+ <td>if(c,t,f)</td>
+ <td>3</td>
+ <td>3</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Evaluates and returns t if c is not 0.0.
+ Else evaluates and returns f.<br>
+ if(0.1,2.1,3.9) returns 2.1</td>
+ </tr>
+ <tr>
+ <td>select(c,n,z[,p])</td>
+ <td>3</td>
+ <td>4</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns n if c is less than 0.0. Returns z
+ if c is 0.0. If c is greater than 0.0 and only
+ three arguments were passed, returns z. If c
+ is greater than 0.0 and four arguments were passed,
+ return p.<br>
+ select(3,1,4,5) returns 5</td>
+ </tr>
+ <tr>
+ <td>equal(a,b)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns 1.0 if a is equal to b. Else returns 0.0<br>
+ equal(3,2) returns 0.0</td>
+ </tr>
+ <tr>
+ <td>above(a,b)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns 1.0 if a is above b. Else returns 0.0<br>
+ above(3,2) returns 1.0</td>
+ </tr>
+ <tr>
+ <td>below(a,b)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns 1.0 if a is below b. Else returns 0.0<br>
+ below(3,2) returns 0.0</td>
+ </tr>
+
+ <tr>
+ <td>avg(a,...)</td>
+ <td>1</td>
+ <td>None</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns the average of the values passed.<br>
+ avg(3,3,6) returns 4</td>
+ </tr>
+ <tr>
+ <td>clip(v,min,max)</td>
+ <td>3</td>
+ <td>3</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Clips v to the range from min to max. If v is less
+ than min, it returns min. If v is greater than
+ max it returns max. Otherwise it returns v.<br>
+ clip(3,1,2) returns 2</td>
+ </tr>
+ <tr>
+ <td>clamp(v,min,max)</td>
+ <td>3</td>
+ <td>3</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Clamps v to the range from min to max, looping
+ if needed.<br>
+ clamp(8.2,1.3,4.7) returns 1.4</td>
+ </tr>
+ <tr>
+ <td>pntchange(side1old, side2old, side1new, side2new, oldpnt)</td>
+ <td>5</td>
+ <td>5</td>
+ <td>0</td>
+ <td>0</td>
+ <td>This is used to translate points from different
+ scale. It works no matter the orientation as long
+ as the sides are lined up correctly.<br>
+ pntchange(-1,1,0,480,-0.5) returns 120 (x example)<br>
+ pntchange(-1,1,480,0,-0.5) returns 360 (y example)</td>
+ </tr>
+ <tr>
+ <td>poly(x,c1,...)</td>
+ <td>2</td>
+ <td>None</td>
+ <td>0</td>
+ <td>0</td>
+ <td>This function calculates the polynomial. x is the value
+ to use in the polynomial. c1 and on are the coefficients.<br>
+ poly(4,6,9,3,1,4) returns 2168<br>
+ same as 6*4<sup>4</sup> + 9*4<sup>3</sup> + 3*4<sup>2</sup> + 1*4<sup>1</sup> + 4*4<sup>0</sup></td>
+ </tr>
+
+ <tr>
+ <td>and(a,b)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns 0.0 if either a or b are 0.0 Else returns 1.0<br>
+ and(2.1,0.0) returns 0.0</td>
+ </tr>
+ <tr>
+ <td>or(a,b)</td>
+ <td>2</td>
+ <td>2</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns 0.0 if both a and b are 0.0 Else returns 1.0<br>
+ or(2.1,0.0) returns 1.0</td>
+ </tr>
+ <tr>
+ <td>not(a)</td>
+ <td>1</td>
+ <td>1</td>
+ <td>0</td>
+ <td>0</td>
+ <td>Returns 1.0 if a is 0.0 Else returns 0.0<br>
+ not(0.3) returns 0.0</td>
+ </tr>
+ <tr>
+ <td>for(init,test,inc,a1,...)</td>
+ <td>4</td>
+ <td>None</td>
+ <td>0</td>
+ <td>0</td>
+ <td>This function acts like a for loop in C. First init is
+ evaluated. Then test is evaluated. As long as the
+ test is not 0.0, the action statements (a1 to an) are
+ evaluated, the inc statement is evaluated, and the test
+ is evaluated again. The result is the result of the
+ final action statement.<br>
+ for(x=0,below(x,11),x=x+1,y=y+x) returns 55.0 (if y was
+ initially 0.0)</td>
+ </tr>
+ <tr>
+ <td>many(expr,...)</td>
+ <td>1</td>
+ <td>None</td>
+ <td>0</td>
+ <td>0</td>
+ <td>This function treats many subexpressions as a single object
+ (function). It is mainly for the 'for' function.<br>
+ for(many(j=5,k=1),above(j*k,0.001),many(j=j+5,k=k/2),0)</td>
+ </tr>
+
+
+ </table>
+
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="InternalConst">ExprEval Internal Constants</a></h2>
+ <blockquote>
+ The following constants are provided with ExprEval:
+ <table align="center" border="1" width="75%">
+ <tr>
+ <td align="center"><b>Constant</b></td>
+ <td align="center"><b>Math Form</b></td>
+ <td align="center"><b>Value</b></td>
+ </tr>
+ <tr>
+ <td>M_E</td>
+ <td>e</td>
+ <td>2.7182818284590452354</td>
+ </tr>
+ <tr>
+ <td>M_LOG2E</td>
+ <td>log<sub>2</sub>(e)</td>
+ <td>1.4426950408889634074</td>
+ </tr>
+ <tr>
+ <td>M_LOG10E</td>
+ <td>log<sub>10</sub>(e)</td>
+ <td>0.43429448190325182765</td>
+ </tr>
+ <tr>
+ <td>M_LN2</td>
+ <td>ln(2)</td>
+ <td>0.69314718055994530942</td>
+ </tr>
+ <tr>
+ <td>M_LN10</td>
+ <td>ln(10)</td>
+ <td>2.30258509299404568402</td>
+ </tr>
+ <tr>
+ <td>M_PI</td>
+ <td>π</td>
+ <td>3.14159265358979323846</td>
+ </tr>
+ <tr>
+ <td>M_PI_2</td>
+ <td>π/2</td>
+ <td>1.57079632679489661923</td>
+ </tr>
+ <tr>
+ <td>M_PI_4</td>
+ <td>π/4</td>
+ <td>0.78539816339744830962</td>
+ </tr>
+ <tr>
+ <td>M_1_PI</td>
+ <td>1/π</td>
+ <td>0.31830988618379067154</td>
+ </tr>
+ <tr>
+ <td>M_2_PI</td>
+ <td>2/π</td>
+ <td>0.63661977236758134308</td>
+ </tr>
+ <tr>
+ <td>M_1_SQRTPI</td>
+ <td>1/√(π)</td>
+ <td>0.56418958354776</td>
+ </tr>
+ <tr>
+ <td>M_2_SQRTPI</td>
+ <td>2/√(π)</td>
+ <td>1.12837916709551257390</td>
+ </tr>
+ <tr>
+ <td>M_SQRT2</td>
+ <td>√(2)</td>
+ <td>1.41421356237309504880</td>
+ </tr>
+ <tr>
+ <td>M_1_SQRT2</td>
+ <td>1/√(2)</td>
+ <td>0.70710678118654752440</td>
+ </tr>
+ </table>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="AppFunc">Application Internal Functions</a></h2>
+ <blockquote>
+ Application defined expression functions go here.
+ <table align="center" border="1" width="75%">
+ <tr>
+ <td align="center"><b>Function</b></td>
+ <td align="center"><b>Min. Args</b></td>
+ <td align="center"><b>Max. Args</b></td>
+ <td align="center"><b>Min. Ref Args</b></td>
+ <td align="center"><b>Max. Ref Args</b></td>
+ <td align="center"><b>Result/Comment</b></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </table>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="AppConst">Application Internal Constants</a></h2>
+ <blockquote>
+ Application defined expression constants go here.
+ <table align="center" border="1" width="75%">
+ <tr>
+ <td align="center"><b>Constant</b></td>
+ <td align="center"><b>Math Form</b></td>
+ <td align="center"><b>Value</b></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </table>
+ </blockquote>
+</div>
+
+<div align="left" class="container">
+ <h2><a name="AppVar">Application Internal Variables</a></h2>
+ <blockquote>
+ Application defined expression variables go here.
+ <table align="center" border="1" width="75%">
+ <tr>
+ <td align="center"><b>Variable</b></td>
+ <td align="center"><b>Math Form</b></td>
+ <td align="center"><b>Value</b></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </table>
+ </blockquote>
+</div>
+
+</body>
+
+</html>
+
+