⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arithm_eval.c

📁 Source code for an Numeric Cmputer
💻 C
字号:
/* Classic Ladder Project *//* Copyright (C) 2001 Marc Le Douarain *//* mavati@club-internet.fr *//* http://www.multimania.com/mavati/classicladder *//* October 2001 *//* Last update : 14 April 2003 *//* ------------------------------- *//* Arithmetic expression evaluator *//* ------------------------------- *//* This library is free software; you can redistribute it and/or *//* modify it under the terms of the GNU Lesser General Public *//* License as published by the Free Software Foundation; either *//* version 2.1 of the License, or (at your option) any later version. *//* This library is distributed in the hope that it will be useful, *//* but WITHOUT ANY WARRANTY; without even the implied warranty of *//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *//* Lesser General Public License for more details. *//* You should have received a copy of the GNU Lesser General Public *//* License along with this library; if not, write to the Free Software *//* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#ifndef MODULE#include <stdio.h>#include <stdlib.h>#include <string.h>#endif#include "rtapi.h"#include "classicladder.h"#include "global.h"#include "vars_access.h"#include "arithm_eval.h"char *Expr;char *ErrorDesc;char *VerifyErrorDesc;int UnderVerify;#ifdef MODULEint atoi(const char *p){    int n = 0;    while (*p >= '0' && *p <= '9')	n = n * 10 + *p++ - '0';    return n;}#endifint pow_int(int a, int b){    int x;    for (x = 1; x <= b; x++)	a = a * a;    return a;}void SyntaxError(void){    if (UnderVerify)	VerifyErrorDesc = ErrorDesc;    else	rtapi_print_msg(RTAPI_MSG_ERR, "Syntax error : '%s' , at %s !!!!!\n",	    ErrorDesc, Expr);}arithmtype Constant(void){    arithmtype Res = 0;    char cIsNeg = FALSE;    /* negative constant ? */    if (*Expr == '-') {	cIsNeg = TRUE;	Expr++;    }    if (*Expr == '$') {	Expr++;	/* hexa number */	while ((*Expr >= '0' && *Expr <= '9') || (*Expr >= 'A'		&& *Expr <= 'F') || (*Expr >= 'a' && *Expr <= 'f')) {	    char Carac = *Expr;	    if (Carac >= 'A' && Carac <= 'F')		Carac = Carac - 'A' + 10;	    else if (Carac >= 'a' && Carac <= 'f')		Carac = Carac - 'a' + 10;	    else		Carac = Carac - '0';	    Res = 16 * Res + Carac;	    Expr++;	}    } else {	/* decimal number */	while (*Expr >= '0' && *Expr <= '9') {	    Res = 10 * Res + (*Expr - '0');	    Expr++;	}    }    if (cIsNeg)	Res = Res * -1;    return Res;}/* return TRUE if okay */int IdentifyVariable(char *StartExpr, int *ResType, int *ResOffset){    int VarType, VarOffset;    char *SearchSep = StartExpr;    StartExpr++;    do {	SearchSep++;    }    while ((*SearchSep != '/') && (*SearchSep != '\0'));    if (*SearchSep == '/') {	VarType = atoi(StartExpr);	SearchSep++;	StartExpr = SearchSep;	/* ???????? */	do {	    StartExpr++;	}	while ((*StartExpr != '@') && (*StartExpr != '\0'));	if (*StartExpr == '@') {	    VarOffset = atoi(SearchSep);	    *ResType = VarType;	    *ResOffset = VarOffset;	    return TRUE;	} else {	    ErrorDesc = "Bad var coding 1, should be @xx/yy@";	    SyntaxError();	}    } else {	ErrorDesc = "Bad var coding 2, should be @xx/yy@";	SyntaxError();    }    return FALSE;}arithmtype Variable(void){    int VarType, VarOffset;    if (IdentifyVariable(Expr, &VarType, &VarOffset)) {	/* flush var found */	Expr++;	do {	    Expr++;	}	while ((*Expr != '@') && (*Expr != '\0'));	Expr++;	/* return var value */	return (arithmtype) ReadVar(VarType, VarOffset);    } else {	return 0;    }}arithmtype Function(void){    char tcFonc[20], *pFonc;    int Res = 0;    /* which function ? */    pFonc = tcFonc;    while ((unsigned int) (pFonc - tcFonc) < sizeof(tcFonc) - 1	&& *Expr >= 'A' && *Expr <= 'Z') {	*pFonc++ = *Expr;	Expr++;    }    *pFonc = '\0';    /* functions with one parameter = variable */    if (!strcmp(tcFonc, "ABS")) {	Expr++;			/* ( */	Res = Variable();	if (Res < 0)	    Res = Res * -1;	Expr++;			/* ) */	return Res;    }    /* functions with many parameters = many variables separated per ',' */    if (!strcmp(tcFonc, "MINI")) {	Res = 0x7FFFFFFF;	do {	    int iValVar;	    Expr++;		/* ( -ou- , */	    iValVar = Variable();	    if (iValVar < Res)		Res = iValVar;	}	while (*Expr != ')');	Expr++;			/* ) */	return Res;    }    if (!strcmp(tcFonc, "MAXI")) {	Res = 0x80000000;	do {	    int iValVar;	    Expr++;		/* ( -or- , */	    iValVar = Variable();	    if (iValVar > Res)		Res = iValVar;	}	while (*Expr != ')');	Expr++;			/* ) */	return Res;    }    if (!strcmp(tcFonc, "MOY")) {	int NbrVars = 0;	do {	    int ValVar;	    Expr++;		/* ( -or- , */	    ValVar = Variable();	    NbrVars++;	    Res = Res + ValVar;	}	while (*Expr != ')');	Expr++;			/* ) */	Res = Res / NbrVars;	return Res;    }    /* functions with parameter = term *///      int iValeurTerm = Term();//      if ( !strcmp(tcFonc, "") )//      {//      }    ErrorDesc = "Unknown function";    SyntaxError();    return 0;}arithmtype Term(void){    if (*Expr == '(') {	arithmtype Res;	Expr++;	Res = AddSub();	if (*Expr != ')') {	    ErrorDesc = "Missing parenthesis";	    SyntaxError();	}	Expr++;	return Res;    } else if ((*Expr >= '0' && *Expr <= '9') || (*Expr == '$')	|| (*Expr == '-'))	return Constant();    else if (*Expr >= 'A' && *Expr <= 'Z')	return Function();    else if (*Expr == '@') {	return Variable();    } else {	if (*Expr == '!') {	    Expr++;	    return Term()? 0 : 1;	} else {	    ErrorDesc = "Unknown term";	    SyntaxError();	}    }    return 0;}arithmtype Pow(void){    arithmtype Q, Res = Term();    while (*Expr == '^') {	Expr++;	Q = Pow();	Res = pow_int(Res, Q);    }    return Res;}arithmtype MulDivMod(void){    arithmtype Res = Pow();    while (1) {	if (*Expr == '*') {	    Expr++;	    Res = Res * Pow();	} else if (*Expr == '/') {	    Expr++;	    Res = Res / Pow();	} else if (*Expr == '%') {	    Expr++;	    Res = Res % Pow();	} else {	    break;	}    }    return Res;}arithmtype AddSub(void){    arithmtype Res = MulDivMod();    while (1) {	if (*Expr == '+') {	    Expr++;	    Res = Res + MulDivMod();	} else if (*Expr == '-') {	    Expr++;	    Res = Res - MulDivMod();	} else {	    break;	}    }    return Res;}arithmtype And(void){    arithmtype Res = AddSub();    while (1) {	if (*Expr == '&') {	    Expr++;	    Res = Res & AddSub();	} else {	    break;	}    }    return Res;}arithmtype Xor(void){    arithmtype Res = And();    while (1) {	if (*Expr == '^') {	    Expr++;	    Res = Res ^ And();	} else {	    break;	}    }    return Res;}arithmtype Or(void){    arithmtype Res = Xor();    while (1) {	if (*Expr == '|') {	    Expr++;	    Res = Res | Xor();	} else {	    break;	}    }    return Res;}arithmtype EvalExpression(char *ExprString){    arithmtype Res;    Expr = ExprString;//    Res = AddSub();    Res = Or();    return Res;}/* Result of the comparison of 2 arithmetics expressions : *//* Expr1 ... Expr2 where ... can be : < , > , = , <= , >= , <> */int EvalCompare(char *CompareString){    char *FirstExpr, *SecondExpr = NULL;    char StrCopy[ARITHM_EXPR_SIZE + 1];	/* used for putting null char after					   first expr */    char *SearchSep;    char *CutFirst;    int Found = FALSE;    int BoolRes = 0;    /* null expression ? */    if (*CompareString == '\0')	return BoolRes;    strcpy(StrCopy, CompareString);    /* search for '>' or '<' or '=' or '>=' or '<=' */    CutFirst = FirstExpr = StrCopy;    SearchSep = CompareString;    do {	if ((*SearchSep == '>') || (*SearchSep == '<') || (*SearchSep == '=')) {	    Found = TRUE;	    *CutFirst = '\0';	    CutFirst++;	    SecondExpr = CutFirst;	    /* 2 chars if '>=' or '<=' or '<>' */	    if (*CutFirst == '=' || *CutFirst == '>') {		CutFirst++;		SecondExpr = CutFirst;	    }	} else {	    SearchSep++;	    CutFirst++;	}    }    while (*SearchSep != '\0' && !Found);    if (Found) {	arithmtype EvalFirst, EvalSecond;//rtapi_print_msg(RTAPI_MSG_ERR, "EvalCompare FirstString=%s , SecondString=%s\n",FirstExpr,SecondExpr);	EvalFirst = EvalExpression(FirstExpr);	EvalSecond = EvalExpression(SecondExpr);//rtapi_print_msg(RTAPI_MSG_ERR, "EvalCompare ResultFirst=%d , ResultSecond=%d\n",EvalFirst,EvalSecond);	/* verify if compare is true */	if (*SearchSep == '>' && EvalFirst > EvalSecond)	    BoolRes = 1;	if (*SearchSep == '<' && *(SearchSep + 1) != '>'	    && EvalFirst < EvalSecond)	    BoolRes = 1;	if (*SearchSep == '<' && *(SearchSep + 1) == '>'	    && EvalFirst != EvalSecond)	    BoolRes = 1;	if ((*SearchSep == '=' || *(SearchSep + 1) == '=')	    && EvalFirst == EvalSecond)	    BoolRes = 1;    } else {	ErrorDesc = "Missing < or > or = or ... to make comparison";	SyntaxError();    }//rtapi_print_msg(RTAPI_MSG_ERR, "Eval FinalBoolResult = %d\n",BoolRes);    return BoolRes;}/* Calc the new value of a variable from an arithmetic expression : *//* VarDest := ArithmExpr */void MakeCalc(char *CalcString, int VerifyMode){    char StrCopy[ARITHM_EXPR_SIZE + 1];	/* used for putting null char after					   first expr */    int VarType, VarOffset;    int Found = FALSE;    /* null expression ? */    if (*CalcString == '\0')	return;    strcpy(StrCopy, CalcString);    Expr = StrCopy;    if (IdentifyVariable(Expr, &VarType, &VarOffset)) {	/* flush var found */	Expr++;	do {	    Expr++;	}	while ((*Expr != '@') && (*Expr != '\0'));	Expr++;	/* verify if there is the '=' or ':=' */	do {	    if (*Expr == ':')		Expr++;	    if (*Expr == '=') {		Found = TRUE;		Expr++;	    }	    if (*Expr == ' ')		Expr++;	}	while (!Found && *Expr != '\0');	while (*Expr == ' ')	    Expr++;	if (Found) {	    arithmtype EvalExpr;//rtapi_print_msg(RTAPI_MSG_ERR, "Calc - Eval String=%s\n",Expr);	    EvalExpr = EvalExpression(Expr);//rtapi_print_msg(RTAPI_MSG_ERR, "Calc - Result=%d\n",EvalExpr);	    if (!VerifyMode)		WriteVar(VarType, VarOffset, (int) EvalExpr);	} else {	    ErrorDesc = "Missing := to make operate";	    SyntaxError();	}    }}/* Used one time after user input to verify syntax only *//* return NULL if ok, else pointer on error description */char *VerifySyntaxForEvalCompare(char *StringToVerify){    UnderVerify = TRUE;    VerifyErrorDesc = NULL;    EvalCompare(StringToVerify);    UnderVerify = FALSE;    return VerifyErrorDesc;}/* Used one time after user input to verify syntax only *//* return NULL if ok, else pointer on error description */char *VerifySyntaxForMakeCalc(char *StringToVerify){    UnderVerify = TRUE;    VerifyErrorDesc = NULL;    MakeCalc(StringToVerify, TRUE /* verify mode */ );    UnderVerify = FALSE;    return VerifyErrorDesc;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -