/* $Id: evaluator.c,v 1.3 2003/10/11 06:01:52 reinelt Exp $ * * expression evaluation * * based on EE (Expression Evaluator) which is * (c) 1992 Mark Morley * * heavily modified 2003 by Michael Reinelt * * FIXME: GPL or not GPL???? * * $Log: evaluator.c,v $ * Revision 1.3 2003/10/11 06:01:52 reinelt * * renamed expression.{c,h} to client.{c,h} * added config file client * new functions 'AddNumericVariable()' and 'AddStringVariable()' * new parameter '-i' for interactive mode * * Revision 1.2 2003/10/06 05:47:27 reinelt * operators: ==, \!=, <=, >= * * Revision 1.1 2003/10/06 04:34:06 reinelt * expression evaluator added * */ /*************************************************************************** ** ** ** EE.C Expression Evaluator ** ** ** ** AUTHOR: Mark Morley ** ** COPYRIGHT: (c) 1992 by Mark Morley ** ** DATE: December 1991 ** ** HISTORY: Jan 1992 - Made it squash all command line arguments ** ** into one big long string. ** ** - It now can set/get VMS symbols as if they ** ** were variables. ** ** - Changed max variable name length from 5 to 15 ** ** Jun 1992 - Updated comments and docs ** ** ** ** You are free to incorporate this code into your own works, even if it ** ** is a commercial application. However, you may not charge anyone else ** ** for the use of this code! If you intend to distribute your code, ** ** I'd appreciate it if you left this message intact. I'd like to ** ** receive credit wherever it is appropriate. Thanks! ** ** ** ** I don't promise that this code does what you think it does... ** ** ** ** Please mail any bug reports/fixes/enhancments to me at: ** ** morley@camosun.bc.ca ** ** or ** ** Mark Morley ** ** 3889 Mildred Street ** ** Victoria, BC Canada ** ** V8Z 7G1 ** ** (604) 479-7861 ** ** ** ***************************************************************************/ /* * exported functions: * * int AddNumericVariable(char *name, double value) * adds a numerical variable to the evaluator * * int AddStringVariable(char *name, char *value) * adds a numerical variable to the evaluator * * int AddFunction (char *name, int args, void (*func)()) * adds a function to the evaluator * * RESULT* SetResult (RESULT **result, int type, void *value) * initializes a result * * double R2N (RESULT *result) * converts a result into a number * * char* R2S (RESULT *result) * converts a result into a string * * int Eval (char* expression, RESULT *result) * evaluates an expression * */ #include #include #include #include #include #include #include "debug.h" #include "evaluator.h" // Token types #define T_DELIMITER 1 #define T_NUMBER 2 #define T_STRING 3 #define T_NAME 4 #define is_blank(c) (c==' ' || c=='\t
# Sweden - Ragunda
[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 474000000
	BANDWIDTH_HZ = 8000000

[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 618000000
	BANDWIDTH_HZ = 8000000

[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 538000000
	BANDWIDTH_HZ = 8000000

[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 562000000
	BANDWIDTH_HZ = 8000000

[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 786000000
	BANDWIDTH_HZ = 8000000

[CHANNEL]
	DELIVERY_SYSTEM = DVBT2
	FREQUENCY = 490000000
	BANDWIDTH_HZ = 8000000

[CHANNEL]
	DELIVERY_SYSTEM = DVBT2
	FREQUENCY = 778000000
	BANDWIDTH_HZ = 8000000
} else if (is_name(*Expression)) { Type=T_NAME; start=Expression; while (is_name(*Expression)) Expression++; Token=strndup(start, Expression-start); } else if (*Expression=='\'') { Type=T_STRING; start=++Expression; while (*Expression && *Expression!='\'') Expression++; Token=strndup(start, Expression-start); if (*Expression=='\'') Expression++; } else if (*Expression) { ERROR(E_SYNTAX); } while(is_blank(*Expression)) Expression++; // empty token if (Token==NULL) Token=strdup(""); } // expression lists static void Level01 (RESULT *result) { do { while (*Token==';') Parse(); Level02(result); } while (*Token==';'); } // variable assignments static void Level02 (RESULT *result) { char *name; if (Type==T_NAME) { if (Expression[0]=='=' && Expression[1]!='=') { name=strdup(Token); Parse(); Parse(); if (*Token && *Token!=';') { Level03(result); SetVariable(name, result); } else { DelVariable(name); } free (name); return; } } Level03(result); } // logical 'or' static void Level03 (RESULT *result) { RESULT operand; double value; Level04(result); while(*Token=='|') { Parse(); Level04 (&operand); value = (R2N(result)!=0.0) || (R2N(&operand)!=0.0); SetResult(&result, R_NUMBER, &value); } } // logical 'and' static void Level04 (RESULT *result) { RESULT operand; double value; Level05(result); while(*Token=='&') { Parse(); Level05 (&operand); value = (R2N(result)!=0.0) && (R2N(&operand)!=0.0); SetResult(&result, R_NUMBER, &value); } } // equal, not equal static void Level05 (RESULT *result) { char operator; RESULT operand = {0, 0.0, NULL}; double value; Level06 (result); if (((operator=Token[0])=='=' || operator=='!') && Token[1]=='=') { Parse(); Level06 (&operand); if (operator=='=') value = (R2N(result) == R2N(&operand)); else value = (R2N(result) != R2N(&operand)); SetResult(&result, R_NUMBER, &value); } } // relational operators static void Level06 (RESULT *result) { char operator[2]; RESULT operand = {0, 0.0, NULL}; double value; Level07 (result); if (*Token=='<' || *Token=='>') { operator[0]=Token[0]; operator[1]=Token[1]; Parse(); Level07 (&operand); if (operator[0]=='<') if (operator[1]=='=') value = (R2N(result) <= R2N(&operand)); else value = (R2N(result) < R2N(&operand)); else if (operator[1]=='=') value = (R2N(result) >= R2N(&operand)); else value = (R2N(result) > R2N(&operand)); SetResult(&result, R_NUMBER, &value); } } // addition, subtraction, concatenation static void Level07 (RESULT *result) { char operator; RESULT operand = {0, 0.0, NULL}; double value; Level08(result); while((operator=*Token)=='+' || operator=='-' || operator=='.') { Parse(); Level08 (&operand); if (operator=='+') { value = (R2N(result) + R2N(&operand)); SetResult(&result, R_NUMBER, &value); } else if (operator=='-') { value = (R2N(result) - R2N(&operand)); SetResult(&result, R_NUMBER, &value); } else { char *s1=R2S(result); char *s2=R2S(&operand); char *s3=malloc(strlen(s1)+strlen(s2)+1); strcpy (s3, s1); strcat (s3, s2); SetResult (&result, R_STRING, s3); free (s3); } } } // multiplication, division, modulo static void Level08 (RESULT *result) { char operator; RESULT operand = {0, 0.0, NULL}; double value; Level09 (result); while((operator=*Token)=='*' || operator=='/' || operator=='%') { Parse(); Level09(&operand); if (operator == '*') { value = (R2N(result) * R2N(&operand)); } else if (operator == '/') { if (R2N(&operand) == 0.0) ERROR (E_DIVZERO); value = (R2N(result) / R2N(&operand)); } else { if (R2N(&operand) == 0.0) ERROR (E_DIVZERO); value = fmod(R2N(result), R2N(&operand)); } SetResult(&result, R_NUMBER, &value); } } // x^y static void Level09 (RESULT *result) { RESULT exponent = {0, 0.0, NULL}; double value; Level10 (result); if (*Token == '^') { Parse(); Level10 (&exponent); value = pow(R2N(result), R2N(&exponent)); SetResult(&result, R_NUMBER, &value); } } // unary + or - signs or logical 'not' static void Level10 (RESULT *result) { char sign=0; double value; if (*Token=='+' || *Token=='-' || *Token=='!') { sign=*Token; Parse(); } Level11 (result); if (sign == '-') { value = -R2N(result); SetResult(&result, R_NUMBER, &value); } else if (sign == '!') { value = (R2N(result)==0.0); SetResult(&result, R_NUMBER, &value); } } // literal numbers, variables, functions static void Level11 (RESULT *result) { RESULT param[10]; if (*Token == '(') { Parse(); if (*Token == ')') ERROR (E_NOARG); Level01(result); if (*Token != ')') ERROR (E_UNBALAN); Parse(); } else { if (Type == T_NUMBER) { double value=atof(Token); SetResult(&result, R_NUMBER, &value); Parse(); } else if (Type == T_STRING) { SetResult(&result, R_STRING, Token); Parse(); } else if (Type == T_NAME) { if (*Expression == '(') { FUNCTION *F=bsearch(Token, Function, nFunction, sizeof(FUNCTION), f_lookup); if (F!=NULL) { int n=0; Parse(); do { Parse(); if (*Token == ')' || *Token == ',') ERROR (E_NOARG); param[n].type=0; param[n].string=NULL; Level01(&(param[n])); n++; } while (n < 10 && *Token == ','); Parse(); if (n != F->args) ERROR (E_NUMARGS); F->func(result, ¶m[0], ¶m[1], ¶m[2], ¶m[3], ¶m[4], ¶m[5], ¶m[6], ¶m[7], ¶m[8], ¶m[9]); return; } else { ERROR(E_BADFUNC); } } else { if (!GetVariable(Token, result)) ERROR(E_UNKNOWN); } Parse(); } else { ERROR(E_SYNTAX); } } } int AddNumericVariable (char *name, double value) { RESULT result; result.type=R_NUMBER; result.number=value; result.string=NULL; return SetVariable (name, &result); } int AddStringVariable (char *name, char *value) { RESULT result; result.type=R_STRING; result.number=0.0; result.string=strdup(value); return SetVariable (name, &result); } int AddFunction (char *name, int args, void (*func)()) { FUNCTION *F; F=bsearch(name, Function, nFunction, sizeof(FUNCTION), f_lookup); if (F!=NULL) { if (F->name) free (F->name); F->name=strdup(name); F->args=args; F->func=func; return 1; } // Fixme: we append the func at the end and re-sort // the whole array! This should be optimized... nFunction++; Function=realloc(Function, nFunction*sizeof(FUNCTION)); Function[nFunction-1].name=strdup(name); Function[nFunction-1].args=args; Function[nFunction-1].func=func; qsort(Function, nFunction, sizeof(FUNCTION), f_sort); return 0; } int Eval (char* expression, RESULT *result) { int err; if ((err=setjmp(jb))) { error ("Error: %s in expression <%s>", ErrMsg[err], expression); return -1; } Expression=expression; DelResult (result); Parse(); if (*Token=='\0') ERROR (E_EMPTY); Level01(result); if (*Token!='\0') ERROR (E_SYNTAX); return 0; }