diff --git a/src/dbStatic/dbStaticLib.c b/src/dbStatic/dbStaticLib.c index 470214806..b55235927 100644 --- a/src/dbStatic/dbStaticLib.c +++ b/src/dbStatic/dbStaticLib.c @@ -30,7 +30,6 @@ #include "gpHash.h" #include "dbmf.h" #include "postfix.h" -#include "sCalcPostfix.h" #include "osiFileName.h" #define epicsExportSharedSymbols @@ -1995,14 +1994,9 @@ long epicsShareAPI dbPutString(DBENTRY *pdbentry,const char *pstring) strncpy((char *)pfield, pstring,pflddes->size); if((pflddes->special == SPC_CALC) && !stringHasMacro) { char rpcl[RPCL_LEN]; - char *psCalcrpcl = 0; short error_number; status = postfix(pstring,rpcl,&error_number); - if(status) { - status = sCalcPostfix(pstring,&psCalcrpcl,&error_number); - free((void *)psCalcrpcl); - } if(status) status = S_dbLib_badField; } if((short)strlen(pstring) >= pflddes->size) status = S_dbLib_strLen; @@ -2375,15 +2369,10 @@ char * epicsShareAPI dbVerify(DBENTRY *pdbentry,const char *pstring) } if((pflddes->special == SPC_CALC) && !stringHasMacro) { char rpcl[RPCL_LEN]; - char *psCalcrpcl = 0; short error_number; long status; status = postfix(pstring,rpcl,&error_number); - if(status) { - status = sCalcPostfix(pstring,&psCalcrpcl,&error_number); - free((void *)psCalcrpcl); - } if(status) { sprintf(message,"Illegal Calculation String"); return(message); diff --git a/src/libCom/Makefile b/src/libCom/Makefile index 25580224a..033765393 100644 --- a/src/libCom/Makefile +++ b/src/libCom/Makefile @@ -31,13 +31,10 @@ SRCS += epicsRingPointer.cpp SRCS += epicsRingBytes.c SRC_DIRS += $(LIBCOM)/calc -#following needed for locating postfixPvt.h and sCalcPostfixPvt.h +#following needed for locating postfixPvt.h INC += postfix.h -INC += sCalcPostfix.h SRCS += postfix.c SRCS += calcPerform.c -SRCS += sCalcPostfix.c -SRCS += sCalcPerform.c SRC_DIRS += $(LIBCOM)/cvtFast INC += cvtFast.h diff --git a/src/libCom/calc/sCalcPerform.c b/src/libCom/calc/sCalcPerform.c deleted file mode 100644 index 2c5bc1eda..000000000 --- a/src/libCom/calc/sCalcPerform.c +++ /dev/null @@ -1,1435 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* $Id$ */ -/* - * Author: Julie Sander and Bob Dalesio - * Date: 07-27-87 - */ - -/* This module contains the code for processing the arithmetic - * expressions defined in calculation records. postfix must be called - * to convert a valid infix expression to postfix. sCalcPerform - * calculates the postfix expression. - * - * Subroutines - * - * Public - * - * sCalcPerform perform the calculation - * args - * double *parg address of arguments - * int numArgs number of arguments in pargs array - * double *psarg address of string arguments - * int numSArgs number of string arguments in psargs array - * double *presult address of double result - * char *psresult address of string-result buffer - * int lenSresult length of string-result buffer - * char *rpcl address of postfix buffer - * returns - * 0 fetched successfully - * -1 fetch failed - * - * Private routine for sCalcPerform - * local_random random number generator - * returns - * double value between 0.00 and 1.00 - */ - -#include -#include -#include -#include "epicsMath.h" - -#include "dbDefs.h" -#define epicsExportSharedSymbols -#include "cvtFast.h" -#include "sCalcPostfix.h" -#include "sCalcPostfixPvt.h" - -static double local_random(void); - -#define myNINT(a) ((int)((a) >= 0 ? (a)+0.5 : (a)-0.5)) -#ifndef PI -#define PI 3.141592654 -#endif -#define MAX(a,b) (a)>(b)?(a):(b) -#define MIN(a,b) (a)<(b)?(a):(b) - - -#define STACKSIZE 30 /* <-------------------------<<<<<<< */ - -struct stackElement { - double d; - char *s; -}; - -#define OVERRIDESTDCALC 0 -#define DEBUG 0 -volatile int sCalcPerformDebug = 0; -#if DEBUG -int sCalcStackHW = 0; -int sCalcStackLW = 0; -#define INC(ps) {if ((int)(++(ps)-top) > sCalcStackHW) sCalcStackHW = (int)((ps)-top);} -#define DEC(ps) {if ((int)(--(ps)-top) < sCalcStackLW) sCalcStackLW = (int)((ps)-top);} -#else -#define INC(ps) ++ps -#define DEC(ps) ps-- -#endif - - -#define isDouble(ps) ((ps)->s==NULL) -#define isString(ps) ((ps)->s) - -#define cleanStringElement(ps) {free((ps)->s); (ps)->s=NULL;} - -static void cleanStackElement(struct stackElement *ps) -{ - if (isString(ps)) { - free(ps->s); - ps->s = NULL; - } -} - -static void cleanup(struct stackElement *ps, struct stackElement *pe) -{ - for (; ps <= pe; ps++) { - if (isString(ps)) { - free(ps->s); - ps->s = NULL; - } - } -} - -#define toDouble(ps) {if (isString(ps)) to_double(ps);} - -/* convert stack element to double */ -static void to_double(struct stackElement *ps) -{ - ps->d = atof(ps->s); - free(ps->s); - ps->s = NULL; -} - -#define toString(ps) {if (isDouble(ps)) to_string(ps);} - -/* convert stack element to string */ -static void to_string(struct stackElement *ps) -{ - ps->s = calloc(20, 1); - /* any precision greater than 8 results in (slow) sprintf call */ - if (isnan(ps->d)) { - strcpy(ps->s,"nan"); - } else if (isinf(ps->d)) { - strcpy(ps->s,"inf"); - } else { - (void)cvtDoubleToString(ps->d, ps->s, 8); - } -} - -static char *findConversionIndicator(char *s) -{ - char *cc=NULL, *s1, *retval; - - while (s && *s) { - if ((s1 = strstr(s, "%%")) != NULL) { - /* not a conversion/assignment indicator; skip over */ - s = s1+2; continue; - } - if ((s = strchr(s, (int)'%')) == NULL) { - return(NULL); - } - if ((cc = strpbrk(s, "pwn$c[deEfgGiousxX")) == NULL) { - return(NULL); - } - /* - * (*cc) is a conversion character; look for suppressed assignment - * ('*' occurring after '%' and before conversion character) - */ - s1 = strchr(s, (int)'*'); - if (s1 && (s1 < cc)) { - /* suppressed assignment; skip past conversion character */ - s = cc+1; - if (*cc == '[') { - /* skip character set ([..], []..], or [^]..]) */ - if (cc[1] == ']') { - s = &(cc[2]); - } else if ((cc[1] == '^') && (cc[2] == ']')) { - s = &(cc[3]); - } - s = strchr(s, (int)']'); - if (s == NULL) { - /* bad character-set syntax */ - return(NULL); - } - s++; /* skip past ']' */ - } - /* keep looking for conversion/assignment character */ - - continue; - } else { - /* (*cc) is a conversion/assignment character */ - break; - } - } - if (cc == NULL) return(NULL); - retval = cc; - /* - * (*cc) is a conversion/assignment indicator. Make sure there - * aren't any more in the format string. - */ - s = cc+1; - while (s && *s) { - if ((s1 = strstr(s, "%%")) != NULL) { - /* not a conversion/assignment indicator; skip over */ - s = s1+2; continue; - } - if ((s = strchr(s, (int)'%')) == NULL) return(retval); - if ((cc = strpbrk(s, "pwn$c[deEfgGiousxX")) == NULL) return(retval); - /* - * (*cc) is a conversion character; look for suppressed assignment - * ('*' occurring after '%' and before conversion character) - */ - s1 = strchr(s, (int)'*'); - if (s1 && (s1 < cc)) { - /* suppressed assignment; skip past conversion character */ - s = cc+1; - if (*cc == '[') { - /* skip character set ([..], []..], or [^]..]) */ - if (cc[1] == ']') { - s = &(cc[2]); - } else if ((cc[1] == '^') && (cc[2] == ']')) { - s = &(cc[3]); - } - s = strchr(s, (int)']'); - if (s == NULL) return(NULL); /* bad character-set syntax */ - s++; /* skip past ']' */ - } - continue; - } else { - /* (*cc) assignment is not suppressed */ - return(NULL); - } - } - return(retval); -} - -#if OVERRIDESTDCALC -/* Override standard EPICS expression evaluator (if we're loaded after it) */ -epicsShareFunc long epicsShareAPI - calcPerform(double *parg, double *presult, char *post) -{ - return(sCalcPerform(parg, 12, NULL, 0, presult, NULL, 0, post)); -} -#endif - -epicsShareFunc long epicsShareAPI - sCalcPerform(double *parg, int numArgs, char **psarg, int numSArgs, double *presult, char *psresult, int lenSresult, char *post) -{ - struct stackElement stack[STACKSIZE], *top; - register struct stackElement *ps, *ps1, *ps2; - char *s2, tmpstr[1000]; - register char *s, *s1; - register int i, j, k; - long l; - unsigned short ui; - unsigned long ul; - float f; - double d; - register double *topd, *pd; - short h, got_if; - -#if DEBUG - if (sCalcPerformDebug>=10) { - int more; - printf("sCalcPerform: postfix:"); - for (s=post, more=1; more;) { - printf("%2d ", *s); - switch (*s) { - case END_STACK: - more = 0; - break; - case LITERAL: - printf("(0x"); - for (i=0, s++; i<8; i++, s++) printf("%2x ", (unsigned int)(unsigned char)*s); - printf(") "); - break; - case SLITERAL: - s++; /* point past code */ - printf("'"); - while (*s) printf("%c", *s++); - printf("' "); - s++; - break; - case FETCH: - s++; /* point past code */ - printf("@%d ", *s++); - break; - case SFETCH: - s++; /* point past code */ - printf("$%d ", *s++); - break; - default: - if (*s == BAD_EXPRESSION) more=0; - s++; - break; - } - } - printf("\n"); - } -#endif - - /* Make sure postfix expression exists and is nontrivial */ - /* if ((*post == END_STACK) || (*post == BAD_EXPRESSION)) return(-1);*/ - if (*post == BAD_EXPRESSION) return(-1); - - - if (*post++ != USES_STRING) { - - topd = pd = (double *)&stack[10]; - pd--; - - /* No string expressions */ - while (*post != END_STACK) { - - switch (*post){ - - case FETCH: - ++pd; - ++post; - *pd = (*post < numArgs) ? parg[(int)*post] : 0; - break; - - case STORE: - /* not implemented */ - return(-1); - - case CONST_PI: - ++pd; - *pd = PI; - break; - - case CONST_D2R: - ++pd; - *pd = PI/180.; - break; - - case CONST_R2D: - ++pd; - *pd = 180./PI; - break; - - case CONST_S2R: - ++pd; - *pd = PI/(180.*3600); - break; - - case CONST_R2S: - ++pd; - *pd = (180.*3600)/PI; - break; - - case ADD: - --pd; - *pd = *pd + pd[1]; - break; - - case SUB: - --pd; - *pd = *pd - pd[1]; - break; - - case MULT: - --pd; - *pd = *pd * pd[1]; - break; - - case DIV: - --pd; - if (pd[1] == 0) /* can't divide by zero */ - return(-1); - *pd = *pd / pd[1]; - break; - - case COND_IF: - /* if false condition then skip true expression */ - if (*pd == 0.0) { - /* skip to matching COND_ELSE */ - for (got_if=1; got_if>0 && *(post+1) != END_STACK; ++post) { - switch(post[1]) { - case LITERAL: post+=8; break; - case COND_IF: got_if++; break; - case COND_ELSE: got_if--; break; - case FETCH: case SFETCH: post++; break; - } - } - } - /* remove condition from stack top */ - --pd; - break; - - case COND_ELSE: - /* result, true condition is on stack so skip false condition */ - /* skip to matching COND_END */ - for (got_if=1; got_if>0 && *(post+1) != END_STACK; ++post) { - switch(post[1]) { - case LITERAL: post+=8; break; - case COND_IF: got_if++; break; - case COND_END: got_if--; break; - case FETCH: post++; break; - } - } - break; - - case COND_END: - break; - - case ABS_VAL: - if (*pd < 0 ) *pd *= -1; - break; - - case UNARY_NEG: - *pd *= -1; - break; - - case SQU_RT: - /* check for neg number */ - if (*pd < 0) return(-1); - *pd = sqrt(*pd); - break; - - case EXP: - *pd = exp(*pd); - break; - - case LOG_10: - /* check for neg number */ - if (*pd < 0) return(-1); - *pd = log10(*pd); - break; - - case LOG_E: - /* check for neg number */ - if (*pd < 0) return(-1); - *pd = log(*pd); - break; - - case RANDOM: - ++pd; - *pd = local_random(); - break; - - case EXPON: - --pd; - if (*pd == 0) break; - if (*pd < 0) { - i = (int) pd[1]; - /* is exponent an integer? */ - if ((pd[1] - (double)i) != 0) return (-1); - *pd = exp(pd[1] * log(-(*pd))); - /* is value negative */ - if ((i % 2) > 0) *pd = -(*pd); - } else { - *pd = exp(pd[1] * log(*pd)); - } - break; - - case MODULO: - --pd; - if ((int)(pd[1]) == 0) - return(-1); - *pd = (double)((int)(*pd) % (int)(pd[1])); - break; - - case REL_OR: - --pd; - *pd = *pd || pd[1]; - break; - - case REL_AND: - --pd; - *pd = *pd && pd[1]; - break; - - case BIT_OR: - /* force double values into integers and or them */ - --pd; - *pd = (int)(pd[1]) | (int)(*pd); - break; - - case BIT_AND: - /* force double values into integers and and them */ - --pd; - *pd = (int)(pd[1]) & (int)(*pd); - break; - - case BIT_EXCL_OR: - /* force double values to integers to exclusive or them */ - --pd; - *pd = (int)(pd[1]) ^ (int)(*pd); - break; - - case GR_OR_EQ: - --pd; - *pd = *pd >= pd[1]; - break; - - case GR_THAN: - --pd; - *pd = *pd > pd[1]; - break; - - case LESS_OR_EQ: - --pd; - *pd = *pd <= pd[1]; - break; - - case LESS_THAN: - --pd; - *pd = *pd < pd[1]; - break; - - case NOT_EQ: - --pd; - *pd = *pd != pd[1]; - break; - - case EQUAL: - --pd; - *pd = *pd == pd[1]; - break; - - case RIGHT_SHIFT: - --pd; - *pd = (int)(*pd) >> (int)(pd[1]); - break; - - case LEFT_SHIFT: - --pd; - *pd = (int)(*pd) << (int)(pd[1]); - break; - - case MAX_VAL: - --pd; - if (*pd < pd[1]) *pd = pd[1]; - break; - - case MIN_VAL: - --pd; - if (*pd > pd[1]) *pd = pd[1]; - break; - - case ACOS: - *pd = acos(*pd); - break; - - case ASIN: - *pd = asin(*pd); - break; - - case ATAN: - *pd = atan(*pd); - break; - - case ATAN2: - --pd; - *pd = atan2(pd[1], *pd); - break; - - case COS: - *pd = cos(*pd); - break; - - case SIN: - *pd = sin(*pd); - break; - - case TAN: - *pd = tan(*pd); - break; - - case COSH: - *pd = cosh(*pd); - break; - - case SINH: - *pd = sinh(*pd); - break; - - case TANH: - *pd = tanh(*pd); - break; - - case CEIL: - *pd = ceil(*pd); - break; - - case FLOOR: - *pd = floor(*pd); - break; - - case NINT: - d = *pd; - *pd = (double)(long)(d >= 0 ? d+0.5 : d-0.5); - break; - - case REL_NOT: - *pd = (*pd ? 0 : 1); - break; - - case BIT_NOT: - *pd = ~(int)(*pd); - break; - - case LITERAL: - ++pd; - ++post; - if (post == NULL) { - ++post; - printf("%.7s bad constant in expression\n",post); - *pd = 0.; - break; - } - memcpy((void *)&(*pd),post,8); - post += 7; - break; - - default: - break; - } - - /* move ahead in postfix expression */ - ++post; - } - - /* if everything is peachy,the stack should end at its first position */ - if (pd != topd) return(-1); -#if DEBUG > 1 -/* check out floating rep of numbers like NaN, Inf */ -{ -union { unsigned char s[8]; double d; } u; -u.d = *pd; -printf("sCalcPerform: result: %g = (0x", *pd); -for (i=0; i<8; i++) printf("%2x ", u.s[i]); -printf(") \n"); -} -#endif - *presult = *pd; - if (psresult && (lenSresult > 15)) { - if (isnan(*pd)) { - strcpy(psresult,"nan"); - } else if (isinf(*pd)) { - strcpy(psresult,"inf"); - } else { - (void)cvtDoubleToString(*pd, psresult, 8); - } - } - } else { - - /*** expression requires string operations ***/ - - top = ps = &stack[10]; - ps--; /* Expression handler assumes ps is pointing to a filled element */ - - /* string expressions and values handled */ - while (*post != END_STACK) { - - switch (*post){ - - case FETCH: - INC(ps); - ++post; - ps->s = NULL; - ps->d = (*post < numArgs) ? parg[(int)*post] : 0; - break; - - case SFETCH: - INC(ps); - ++post; - if (*post < numSArgs) { - /* fetch from string variable */ - ps->s = calloc(strlen(psarg[(int)*post])+1, 1); - strcpy(ps->s, psarg[(int)*post]); - } else { - /* fetch from variable that caller did not supply */ - ps->s = calloc(1, 1); - *(ps->s) = 0; - } - break; - - case STORE: - /* not implemented */ - cleanup(top, ps); - return(-1); - - case CONST_PI: - INC(ps); - ps->s = NULL; - ps->d = PI; - break; - - case CONST_D2R: - INC(ps); - ps->s = NULL; - ps->d = PI/180.; - break; - - case CONST_R2D: - INC(ps); - ps->s = NULL; - ps->d = 180./PI; - break; - - case CONST_S2R: - INC(ps); - ps->s = NULL; - ps->d = PI/(180.*3600); - break; - - case CONST_R2S: - INC(ps); - ps->s = NULL; - ps->d = (180.*3600)/PI; - break; - - case ADD: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - ps->d = ps->d + ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - ps->d = ps->d + ps1->d; - } else { - /* concatenate two strings */ - s = ps->s; - ps->s = calloc(strlen(ps->s) + strlen(ps1->s) + 1, 1); - strcpy(ps->s, s); - strcat(ps->s, ps1->s); - free(s); - cleanStringElement(ps1); - } - break; - - case SUB: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - ps->d = ps->d - ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - ps->d = ps->d - ps1->d; - } else { - /* subtract ps1->s from ps->s */ - s = strstr(ps->s, ps1->s); - s1 = ps->s; - s2 = ps1->s; - if (s && (strlen(s2) <= (strlen(s1) - (s - s1)))) { - for (s1=s+strlen(s2); *s1; s++, s1++) *s = *s1; - *s = '\0'; - } - cleanStringElement(ps1); - } - break; - - case MULT: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = ps->d * ps1->d; - break; - - case DIV: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - if (ps1->d == 0) /* can't divide by zero */ - return(-1); - ps->d = ps->d / ps1->d; - break; - - case COND_IF: - /* if false condition then skip true expression */ - toDouble(ps); - if (ps->d == 0.0) { - /* skip to matching COND_ELSE */ - for (got_if=1; got_if>0 && *(post+1) != END_STACK; ++post) { - switch(post[1]) { - case LITERAL: post+=8; break; - case SLITERAL: post++; while (post[1]) post++; break; - case COND_IF: got_if++; break; - case COND_ELSE: got_if--; break; - case FETCH: case SFETCH: post++; break; - } - } - } - /* remove condition from stack top */ - DEC(ps); - break; - - case COND_ELSE: - /* result, true condition is on stack so skip false condition */ - /* skip to matching COND_END */ - for (got_if=1; got_if>0 && *(post+1) != END_STACK; ++post) { - switch(post[1]) { - case LITERAL: post+=8; break; - case SLITERAL: post++; while (post[1]) post++; break; - case COND_IF: got_if++; break; - case COND_END: got_if--; break; - case FETCH: case SFETCH: post++; break; - } - } - break; - - case COND_END: - break; - - case ABS_VAL: - toDouble(ps); - if (ps->d < 0 ) ps->d *= -1; - break; - - case UNARY_NEG: - toDouble(ps); - ps->d *= -1; - break; - - case SQU_RT: - toDouble(ps); - /* check for neg number */ - if (ps->d < 0) {cleanup(top, ps); return(-1);} - ps->d = sqrt(ps->d); - break; - - case EXP: - toDouble(ps); - ps->d = exp(ps->d); - break; - - case LOG_10: - toDouble(ps); - /* check for neg number */ - if (ps->d < 0) {cleanup(top, ps); return(-1);} - ps->d = log10(ps->d); - break; - - case LOG_E: - toDouble(ps); - /* check for neg number */ - if (ps->d < 0) {cleanup(top, ps); return(-1);} - ps->d = log(ps->d); - break; - - case RANDOM: - INC(ps); - ps->d = local_random(); - ps->s = NULL; - break; - - case EXPON: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - if (ps->d == 0) break; - if (ps->d < 0) { - i = (int) ps1->d; - /* is exponent an integer? */ - if ((ps1->d - (double)i) != 0) return (-1); - ps->d = exp(ps1->d * log(-(ps->d))); - /* is value negative */ - if ((i % 2) > 0) ps->d = -ps->d; - } else { - ps->d = exp(ps1->d * log(ps->d)); - } - break; - - case MODULO: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - if ((int)ps1->d == 0) - return(-1); - ps->d = (double)((int)ps->d % (int)ps1->d); - break; - - case REL_OR: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = ps->d || ps1->d; - break; - - case REL_AND: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = ps->d && ps1->d; - break; - - case BIT_OR: - /* force double values into integers and or them */ - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = (int)(ps1->d) | (int)(ps->d); - break; - - case BIT_AND: - /* force double values into integers and and them */ - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = (int)(ps1->d) & (int)(ps->d); - break; - - case BIT_EXCL_OR: - /* force double values to integers to exclusive or them */ - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = (int)(ps1->d) ^ (int)(ps->d); - break; - - case GR_OR_EQ: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - ps->d = ps->d >= ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - ps->d = ps->d >= ps1->d; - } else { - /* compare ps->s to ps1->s */ - ps->d = (double)(strcmp(ps->s, ps1->s) >= 0); - free(ps->s); - ps->s = NULL; - cleanStringElement(ps1); - } - break; - - case GR_THAN: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - ps->d = ps->d > ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - ps->d = ps->d > ps1->d; - } else { - /* compare ps->s to ps1->s */ - ps->d = (double)(strcmp(ps->s, ps1->s) > 0); - free(ps->s); - ps->s = NULL; - cleanStringElement(ps1); - } - break; - - case LESS_OR_EQ: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - ps->d = ps->d <= ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - ps->d = ps->d <= ps1->d; - } else { - /* compare ps->s to ps1->s */ - ps->d = (double)(strcmp(ps->s, ps1->s) <= 0); - free(ps->s); - ps->s = NULL; - cleanStringElement(ps1); - } - break; - - case LESS_THAN: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - ps->d = ps->d < ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - ps->d = ps->d < ps1->d; - } else { - /* compare ps->s to ps1->s */ - ps->d = (double)(strcmp(ps->s, ps1->s) < 0); - free(ps->s); - ps->s = NULL; - cleanStringElement(ps1); - } - break; - - case NOT_EQ: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - ps->d = ps->d != ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - ps->d = ps->d != ps1->d; - } else { - /* compare ps->s to ps1->s */ - ps->d = (double)(strcmp(ps->s, ps1->s) != 0); - free(ps->s); - ps->s = NULL; - cleanStringElement(ps1); - } - break; - - case EQUAL: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - ps->d = ps->d == ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - ps->d = ps->d == ps1->d; - } else if ((isString(ps)) && (isString(ps1))) { - /* compare ps->s to ps1->s */ - ps->d = (double)(strcmp(ps->s, ps1->s) == 0); - free(ps->s); - ps->s = NULL; - cleanStringElement(ps1); - } - break; - - case RIGHT_SHIFT: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = (int)(ps->d) >> (int)(ps1->d); - break; - - case LEFT_SHIFT: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = (int)(ps->d) << (int)(ps1->d); - break; - - case MAX_VAL: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - if (ps->d < ps1->d) ps->d = ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - if (ps->d < ps1->d) ps->d = ps1->d; - } else { - /* compare ps->s to ps1->s */ - if (strcmp(ps->s, ps1->s) < 0) { - s = ps->s; - ps->s = ps1->s; - ps1->s = s; - } - cleanStringElement(ps1); - } - break; - - case MIN_VAL: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) { - toDouble(ps1); - if (ps->d > ps1->d) ps->d = ps1->d; - } else if (isDouble(ps1)) { - to_double(ps); - if (ps->d > ps1->d) ps->d = ps1->d; - } else { - /* compare ps->s to ps1->s */ - if (strcmp(ps->s, ps1->s) > 0) { - s = ps->s; - ps->s = ps1->s; - ps1->s = s; - } - cleanStringElement(ps1); - } - break; - - case ACOS: - toDouble(ps); - ps->d = acos(ps->d); - break; - - case ASIN: - toDouble(ps); - ps->d = asin(ps->d); - break; - - case ATAN: - toDouble(ps); - ps->d = atan(ps->d); - break; - - case ATAN2: - ps1 = ps; - DEC(ps); - toDouble(ps1); - toDouble(ps); - ps->d = atan2(ps1->d, ps->d); - break; - - case COS: - toDouble(ps); - ps->d = cos(ps->d); - break; - - case SIN: - toDouble(ps); - ps->d = sin(ps->d); - break; - - case TAN: - toDouble(ps); - ps->d = tan(ps->d); - break; - - case COSH: - toDouble(ps); - ps->d = cosh(ps->d); - break; - - case SINH: - toDouble(ps); - ps->d = sinh(ps->d); - break; - - case TANH: - toDouble(ps); - ps->d = tanh(ps->d); - break; - - case CEIL: - toDouble(ps); - ps->d = ceil(ps->d); - break; - - case FLOOR: - toDouble(ps); - ps->d = floor(ps->d); - break; - - case NINT: - if (isDouble(ps)) { - d = ps->d; - ps->d = (double)(long)(d >= 0 ? d+0.5 : d-0.5); - } else { - /* hunt down integer and convert */ - s = strpbrk(ps->s,"0123456789"); - if ((s > ps->s) && (s[-1] == '.')) s--; - if ((s > ps->s) && (s[-1] == '-')) s--; - d = s ? atof(s) : 0.0; - free(ps->s); ps->s = NULL; - ps->d = (double)(long)(d >= 0 ? d+0.5 : d-0.5); - } - break; - - case REL_NOT: - toDouble(ps); - ps->d = (ps->d ? 0 : 1); - break; - - case BIT_NOT: - toDouble(ps); - ps->d = ~(int)(ps->d); - break; - - case LITERAL: - INC(ps); - ++post; - if (post == NULL) { - ++post; - printf("%.7s bad constant in expression\n",post); - ps->s = NULL; - ps->d = 0.; - break; - } - memcpy((void *)&(ps->d),post,8); - ps->s = NULL; - post += 7; - break; - - case SLITERAL: - INC(ps); - ++post; - if (post == NULL) { - ++post; - printf("%.7s bad constant in expression\n",post); - ps->s = NULL; - ps->d = 0.; - break; - } - ps->s = calloc(strlen(post)+1, 1); - strcpy(ps->s, post); - /* skip to end of string */ - while (*post) post++; - break; - - case TO_DOUBLE: - if (isString(ps)) { - /* hunt down number and convert */ - s = strpbrk(ps->s,"0123456789"); - if ((s > ps->s) && (s[-1] == '.')) s--; - if ((s > ps->s) && (s[-1] == '-')) s--; - ps->d = s ? atof(s) : 0.0; - free(ps->s); ps->s = NULL; - } - break; - - case TO_STRING: - toString(ps); - break; - - case PRINTF: - ps1 = ps; - DEC(ps); - if (isDouble(ps)) - {cleanup(top, ps1); return(-1);} - s = ps->s; - while ((s1 = strstr(s, "%%"))) {s = s1+2;} - if (((s = strpbrk(s, "%")) == NULL) || - ((s = strpbrk(s+1, "*cdeEfgGiousxX")) == NULL)) { - /* no printf arguments needed */ - sprintf(tmpstr, ps->s); - } else { - switch (*s) { - default: case '*': - cleanup(top, ps1); - return(-1); - case 'c': case 'd': case 'i': case 'o': - case 'u': case 'x': case 'X': - toDouble(ps1); - l = myNINT(ps1->d); - sprintf(tmpstr, ps->s, l); - break; - case 'e': case 'E': case 'f': case 'g': case 'G': - toDouble(ps1); - sprintf(tmpstr, ps->s, ps1->d); - break; - case 's': - toString(ps1); - sprintf(tmpstr, ps->s, ps1->s); - break; - } - } - if (strlen(ps->s) < strlen(tmpstr)) { - free(ps->s); - ps->s = calloc(strlen(tmpstr)+1, 1); - } - strcpy(ps->s, tmpstr); - cleanStackElement(ps1); - break; - - case SSCANF: - ps1 = ps; - DEC(ps); - if (isDouble(ps) || isDouble(ps1)) - {cleanup(top, ps1); return(-1);} - s = findConversionIndicator(ps1->s); - if (s == NULL) {cleanup(top, ps1); return(-1);} - switch (*s) { - default: case 'p': case 'w': case 'n': case '$': - cleanup(top, ps1); - return(-1); - case 'd': case 'i': - if (s[-1] == 'h') { - sscanf(ps->s, ps1->s, &h); - ps->d = (double)h; - } else { - sscanf(ps->s, ps1->s, &l); - ps->d = (double)l; - } - cleanStringElement(ps); - ps->s = NULL; - break; - case 'o': case 'u': case 'x': case 'X': - if (s[-1] == 'h') { - sscanf(ps->s, ps1->s, &ui); - ps->d = (double)ui; - } else { - sscanf(ps->s, ps1->s, &ul); - ps->d = (double)ul; - } - cleanStringElement(ps); - ps->s = NULL; - break; - case 'e': case 'E': case 'f': case 'g': case 'G': - if (s[-1] == 'l') { - sscanf(ps->s, ps1->s, &(ps->d)); - } else { - sscanf(ps->s, ps1->s, &f); - ps->d = (double)f; - } - cleanStringElement(ps); - ps->s = NULL; - break; - case 'c': case '[': case 's': - sscanf(ps->s, ps1->s, tmpstr); - if (strlen(ps->s) < strlen(tmpstr)) { - free(ps->s); - ps->s = calloc(strlen(tmpstr)+1, 1); - } - strcpy(ps->s, tmpstr); - break; - } - cleanStringElement(ps1); - break; - - case SUBRANGE: - ps2 = ps; - DEC(ps); - ps1 = ps; - DEC(ps); - toString(ps); - k = strlen(ps->s); - if (isDouble(ps1)) { - i = (int)ps1->d; - if (i < 0) i += k; - } else { - s = strstr(ps->s, ps1->s); - i = s ? (s - ps->s) + strlen(ps1->s) : 0; - } - if (isDouble(ps2)) { - j = (int)ps2->d; - if (j < 0) j += k; - } else { - if (*(ps2->s)) { - s = strstr(ps->s, ps2->s); - j = s ? (s - ps->s) - 1 : k; - } else { - j = k; - } - } - i = MAX(MIN(i,k),0); - j = MIN(j,k); - for (s=ps->s, s1=s+i, s2=s+j ; *s1 && s1 <= s2; ) - {*s++ = *s1++;} - *s = 0; - break; - - case REPLACE: - ps2 = ps; - DEC(ps); - ps1 = ps; - DEC(ps); - toString(ps); - toString(ps1); - toString(ps2); - i = strlen(ps->s); - j = strlen(ps1->s); - k = strlen(ps2->s); - s1 = strstr(ps->s, ps1->s); - s2 = ps2->s; - if (s1 >= ps->s) { - char *s_old, *s_dest; - s_old = s = ps->s; - if (k > j) ps->s = malloc(i - j + k + 1); - s_dest = ps->s; - while (s < s1) *s_dest++ = *s++; - s += j; - while (*s2) *s_dest++ = *s2++; - while (*s) *s_dest++ = *s++; - *s_dest = '\0'; - if (k > j) free(s_old); - } - cleanStringElement(ps1); - cleanStringElement(ps2); - break; - - default: - break; - } - - /* move ahead in postfix expression */ - ++post; - } - - /* if everything is peachy,the stack should end at its first position */ - if (ps != top) - return(-1); - - if (isDouble(ps)) { - if (presult) *presult = ps->d; - if (psresult) { - toString(ps); - for (i=0, s=ps->s, s1=psresult; *s && is, lenSresult); */ - psresult[lenSresult-1] = 0; - cleanStringElement(ps); - } - } else { - if (psresult) { - for (i=0, s=ps->s, s1=psresult; *s && id; - } else { - cleanStringElement(ps); - } - } - - } /* if (*post++ != USES_STRING) {} else */ - - return(((isnan(*presult)||isinf(*presult)) ? -1 : 0)); -} - - -/* - * RAND - * - * generates a random number between 0 and 1 using the - * seed = (multy * seed) + addy Random Number Generator by Knuth - * SemiNumerical Algorithms - * Chapter 1 - * randy = seed / 65535.0 To normalize the number between 0 - 1 - */ -static unsigned short seed = 0xa3bf; -static unsigned short multy = 191 * 8 + 5; /* 191 % 8 == 5 */ -static unsigned short addy = 0x3141; -static double local_random() -{ - double randy; - - /* random number */ - seed = (seed * multy) + addy; - randy = (float) seed / 65535.0; - - /* between 0 - 1 */ - return(randy); -} diff --git a/src/libCom/calc/sCalcPostfix.c b/src/libCom/calc/sCalcPostfix.c deleted file mode 100644 index 34525e238..000000000 --- a/src/libCom/calc/sCalcPostfix.c +++ /dev/null @@ -1,682 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* $Id$ - * Subroutines used to convert an infix expression to a postfix expression - * - * Author: Bob Dalesio - * Date: 12-12-86 - */ - -/* - * Subroutines - * - * Public - * - * sCalcPostfix convert an algebraic expression to symbolic postfix - * args - * pinfix the algebraic expression - * pp_postfix address of the symbolic postfix expression - * perror error information - * returns - * 0 successful - * -1 not successful - * Private routines for calcPostfix - * - * find_element finds a symbolic element in the expression element tbl - * args - * pbuffer pointer to the infix expression element - * pelement pointer to the expression element table entry - * pno_bytes pointer to the size of this element - * parg pointer to arg (used for fetch) - * returns - * TRUE element found - * FALSE element not found - * - * get_element finds the next expression element in the infix expr - * args - * pinfix pointer into the infix expression - * pelement pointer to the expression element table - * pno_bytes size of the element in the infix expression - * parg pointer to argument (used for fetch) - * returns - * FINE found an expression element - * VARIABLE found a database reference - * UNKNOWN_ELEMENT unknown element found in the infix expression - */ - -#include -#include -#include -#include - -#include "dbDefs.h" -#define epicsExportSharedSymbols -#include "sCalcPostfix.h" -#include "sCalcPostfixPvt.h" - - -#define OVERRIDESTDCALC 0 -#define DEBUG 0 -volatile int sCalcPostfixDebug=0; - -/* declarations for postfix */ -/* element types */ -#define OPERAND 0 -#define UNARY_OPERATOR 1 -#define BINARY_OPERATOR 2 -#define EXPR_TERM 3 -#define COND 4 -#define CLOSE_PAREN 5 -#define CONDITIONAL 6 -#define ELSE 7 -#define SEPARATOR 8 -#define TRASH 9 -#define FLOAT_PT_CONST 10 -#define MINUS_OPERATOR 11 -#define STRING_CONST 12 -#define CLOSE_BRACKET 13 -#define CLOSE_CURLY 14 - -#define UNARY_MINUS_I_S_P 7 -#define UNARY_MINUS_I_C_P 8 -#define UNARY_MINUS_CODE UNARY_NEG -#define BINARY_MINUS_I_S_P 4 -#define BINARY_MINUS_I_C_P 4 -#define BINARY_MINUS_CODE SUB - -/* parsing return values */ -#define FINE 0 -#define UNKNOWN_ELEMENT -1 -#define END -2 - -/* - * element table - * - * structure of an element - */ -struct expression_element{ - char element[10]; /* character representation of an element */ - char in_stack_pri; /* priority in translation stack */ - char in_coming_pri; /* priority when first checking */ - char type; /* element type */ - char code; /* postfix representation */ -}; - -/* - * NOTE: DO NOT CHANGE WITHOUT READING THIS NOTICE !!!!!!!!!!!!!!!!!!!! - * Because the routine that looks for a match in this table takes the first - * match it finds, elements whose designations are contained in other elements - * MUST come first in this list. (e.g. ABS will match A if A preceeds ABS and - * then try to find BS therefore ABS must be first in this list - */ -static struct expression_element elements[] = { -/* -element i_s_p i_c_p type_element internal_rep */ -{"ABS", 7, 8, UNARY_OPERATOR, ABS_VAL}, /* absolute value */ -{"NOT", 7, 8, UNARY_OPERATOR, UNARY_NEG}, /* unary negate */ -{"-", 7, 8, MINUS_OPERATOR, UNARY_NEG}, /* unary negate (or binary op) */ -{"SQRT", 7, 8, UNARY_OPERATOR, SQU_RT}, /* square root */ -{"SQR", 7, 8, UNARY_OPERATOR, SQU_RT}, /* square root */ -{"EXP", 7, 8, UNARY_OPERATOR, EXP}, /* exponential function */ -{"LOGE", 7, 8, UNARY_OPERATOR, LOG_E}, /* log E */ -{"LN", 7, 8, UNARY_OPERATOR, LOG_E}, /* log E */ -{"LOG", 7, 8, UNARY_OPERATOR, LOG_10}, /* log 10 */ -{"ACOS", 7, 8, UNARY_OPERATOR, ACOS}, /* arc cosine */ -{"ASIN", 7, 8, UNARY_OPERATOR, ASIN}, /* arc sine */ -{"ATAN2", 7, 8, UNARY_OPERATOR, ATAN2}, /* arc tangent */ -{"ATAN", 7, 8, UNARY_OPERATOR, ATAN}, /* arc tangent */ -{"MAX", 7, 8, UNARY_OPERATOR, MAX_VAL}, /* maximum of 2 args */ -{"MIN", 7, 8, UNARY_OPERATOR, MIN_VAL}, /* minimum of 2 args */ -{"CEIL", 7, 8, UNARY_OPERATOR, CEIL}, /* smallest integer >= */ -{"FLOOR", 7, 8, UNARY_OPERATOR, FLOOR}, /* largest integer <= */ -{"NINT", 7, 8, UNARY_OPERATOR, NINT}, /* nearest integer */ -{"INT", 7, 8, UNARY_OPERATOR, NINT}, /* nearest integer */ -{"COSH", 7, 8, UNARY_OPERATOR, COSH}, /* hyperbolic cosine */ -{"COS", 7, 8, UNARY_OPERATOR, COS}, /* cosine */ -{"SINH", 7, 8, UNARY_OPERATOR, SINH}, /* hyperbolic sine */ -{"SIN", 7, 8, UNARY_OPERATOR, SIN}, /* sine */ -{"TANH", 7, 8, UNARY_OPERATOR, TANH}, /* hyperbolic tangent*/ -{"TAN", 7, 8, UNARY_OPERATOR, TAN}, /* tangent */ -{"!=", 3, 3, BINARY_OPERATOR,NOT_EQ}, /* not equal */ -{"!", 7, 8, UNARY_OPERATOR, REL_NOT}, /* not */ -{"~", 7, 8, UNARY_OPERATOR, BIT_NOT}, /* bitwise not */ -{"DBL", 7, 8, UNARY_OPERATOR, TO_DOUBLE}, /* convert to double */ -{"STR", 7, 8, UNARY_OPERATOR, TO_STRING}, /* convert to string */ -{"$P", 7, 8, UNARY_OPERATOR, PRINTF}, /* formatted print to string */ -{"PRINTF", 7, 8, UNARY_OPERATOR, PRINTF}, /* formatted print to string */ -{"$S", 7, 8, UNARY_OPERATOR, SSCANF}, /* scan string argument */ -{"SSCANF", 7, 8, UNARY_OPERATOR, SSCANF}, /* scan string argument */ -{"RNDM", 0, 0, OPERAND, RANDOM}, /* Random Number */ -{"OR", 1, 1, BINARY_OPERATOR,BIT_OR}, /* or */ -{"AND", 2, 2, BINARY_OPERATOR,BIT_AND}, /* and */ -{"XOR", 1, 1, BINARY_OPERATOR,BIT_EXCL_OR}, /* exclusive or */ -{"PI", 0, 0, OPERAND, CONST_PI}, /* pi */ -{"D2R", 0, 0, OPERAND, CONST_D2R}, /* pi/180 */ -{"R2D", 0, 0, OPERAND, CONST_R2D}, /* 180/pi */ -{"S2R", 0, 0, OPERAND, CONST_S2R}, /* arc-sec to radians: pi/(180*3600) */ -{"R2S", 0, 0, OPERAND, CONST_R2S}, /* radians to arc-sec: (180*3600)/pi */ -{"0", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"1", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"2", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"3", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"4", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"5", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"6", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"7", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"8", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"9", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{".", 0, 0, FLOAT_PT_CONST, LITERAL}, /* flt pt constant */ -{"\"", 0, 0, STRING_CONST, SLITERAL}, /* string constant */ -{"'", 0, 0, STRING_CONST, SLITERAL}, /* string constant */ -{"?", 0, 0, CONDITIONAL, COND_IF}, /* conditional */ -{":", 0, 0, CONDITIONAL, COND_ELSE}, /* else */ -{"(", 0, 8, UNARY_OPERATOR, PAREN}, /* open paren */ -{"[", 0, 8, BINARY_OPERATOR,SUBRANGE}, /* string subrange */ -{"{", 0, 8, BINARY_OPERATOR,REPLACE}, /* string replace */ -{"^", 6, 6, BINARY_OPERATOR,EXPON}, /* exponentiation */ -{"**", 6, 6, BINARY_OPERATOR,EXPON}, /* exponentiation */ -{"+", 4, 4, BINARY_OPERATOR,ADD}, /* addition */ -#if 0 /* "-" operator is overloaded; may be unary or binary */ -{"-", 4, 4, BINARY_OPERATOR,SUB}, /* subtraction */ -#endif -{"*", 5, 5, BINARY_OPERATOR,MULT}, /* multiplication */ -{"/", 5, 5, BINARY_OPERATOR,DIV}, /* division */ -{"%", 5, 5, BINARY_OPERATOR,MODULO}, /* modulo */ -{",", 0, 0, SEPARATOR, COMMA}, /* comma */ -{")", 0, 0, CLOSE_PAREN, PAREN}, /* close paren */ -{"]", 0, 0, CLOSE_BRACKET, SUBRANGE}, /* close bracket */ -{"}", 0, 0, CLOSE_CURLY, REPLACE}, /* close curly bracket */ -{"||", 1, 1, BINARY_OPERATOR,REL_OR}, /* logical or */ -{"|", 1, 1, BINARY_OPERATOR,BIT_OR}, /* bitwise or */ -{"&&", 2, 2, BINARY_OPERATOR,REL_AND}, /* logical and */ -{"&", 2, 2, BINARY_OPERATOR,BIT_AND}, /* bitwise and */ -{">>", 2, 2, BINARY_OPERATOR,RIGHT_SHIFT}, /* right shift */ -{">=", 3, 3, BINARY_OPERATOR,GR_OR_EQ}, /* greater or equal*/ -{">", 3, 3, BINARY_OPERATOR,GR_THAN}, /* greater than */ -{"<<", 2, 2, BINARY_OPERATOR,LEFT_SHIFT}, /* left shift */ -{"<=", 3, 3, BINARY_OPERATOR,LESS_OR_EQ}, /* less or equal to*/ -{"<", 3, 3, BINARY_OPERATOR,LESS_THAN}, /* less than */ -{"#", 3, 3, BINARY_OPERATOR,NOT_EQ}, /* not equal */ -{"==", 3, 3, BINARY_OPERATOR,EQUAL}, /* equal */ -{"=", 3, 3, BINARY_OPERATOR,EQUAL}, /* equal */ -{""} -}; - -/* - * Element-table entry for "fetch" operation. This element is used for all - * named variables. Currently, letters A-Z (double) and AA-ZZ (string) are - * allowed. Lower and upper case letters mean the same thing. - */ -static struct expression_element fetch_element = { -"A", 0, 0, OPERAND, FETCH, /* fetch var */ -}; - -static struct expression_element fetch_string_element = { -"AA", 0, 0, OPERAND, SFETCH, /* fetch var */ -}; - -static int strncasecmpPrivate(char *s1, char *s2, size_t n) -{ - short i; - for (i=0; i<(short)n && (*s1 || *s2); i++, s1++, s2++) { - if (toupper((int)*s1) > toupper((int)*s2)) return(1); - if (toupper((int)*s1) < toupper((int)*s2)) return(-1); - } - return(0); -} -/* - * FIND_ELEMENT - * - * find the pointer to an entry in the element table - */ -static int find_element(pbuffer, pelement, pno_bytes, parg) - char *pbuffer; - struct expression_element **pelement; - short *pno_bytes, *parg; - { - *parg = 0; - - /* compare the string to each element in the element table */ - *pelement = &elements[0]; - while ((*pelement)->element[0] != NULL){ - if (strncasecmpPrivate(pbuffer,(*pelement)->element, strlen((*pelement)->element)) == 0){ - *pno_bytes += strlen((*pelement)->element); - return(TRUE); - } - *pelement += 1; - } - - /* look for a variable reference */ - /* double variables: ["a" - "z"], numbered 1-26 */ - if (isalpha((int)*pbuffer)) { - *pelement = &fetch_element; /* fetch means "variable reference" (fetch or store) */ - *parg = *pbuffer - (isupper((int)*pbuffer) ? 'A' : 'a'); - *pno_bytes += 1; - /* string variables: ["aa" - "zz"], numbered 1-26 */ - if (pbuffer[1] == pbuffer[0]) { - *pelement = &fetch_string_element; - *pno_bytes += 1; - } - return(TRUE); - } - if (sCalcPostfixDebug) printf("find_element: can't find '%s'\n", pbuffer); - return(FALSE); - } - -/* - * GET_ELEMENT - * - * get an expression element - */ -static int get_element(pinfix, pelement, pno_bytes, parg) -char *pinfix; -struct expression_element **pelement; -short *pno_bytes, *parg; -{ - - /* get the next expression element from the infix expression */ - if (*pinfix == NULL) return(END); - *pno_bytes = 0; - while (*pinfix == 0x20){ - *pno_bytes += 1; - pinfix++; - } - if (*pinfix == NULL) return(END); - if (!find_element(pinfix, pelement, pno_bytes, parg)) - return(UNKNOWN_ELEMENT); - if (sCalcPostfixDebug > 5) printf("get_element: found element '%s', arg=%d\n", (*pelement)->element, *parg); - - return(FINE); - - -} - -#if OVERRIDESTDCALC -/* Override standard EPICS expression evaluator (if we're loaded after it). */ -long epicsShareAPI postfix(const char *pinfix,char *ppostfix,short *perror) -{ - char *my_ppostfix = NULL, *s, *d; - long retval; - - retval = sCalcPostfix(pinfix, &my_ppostfix, perror); - if (*my_ppostfix == BAD_EXPRESSION) { - *ppostfix = BAD_EXPRESSION; - } else { - for (s = my_ppostfix, d = ppostfix; *s != END_STACK; ) { - *d++=*s++; - } - *d = *s; - } - free(my_ppostfix); - return(retval); -} -#endif - -/* - * sCalcPostFix - * - * convert an infix expression to a postfix expression - */ -#define MAX_POSTFIX_SIZE 100 -long epicsShareAPI sCalcPostfix(const char *pin, char **pp_postfix, short *perror) -{ - short no_bytes; - short operand_needed; - short new_expression; - struct expression_element stack[80]; - struct expression_element *pelement; - struct expression_element *pstacktop; - double constant; - char c, *pposthold; - char in_stack_pri, in_coming_pri, code; - char *ppostfix, *ppostfixStart; - short arg; - char infix[MAX_POSTFIX_SIZE]; - char *pinfix = &infix[0]; - int len; - - if (sCalcPostfixDebug) printf("sCalcPostfix: entry\n"); - len = strlen(pin); - if(len>=MAX_POSTFIX_SIZE) return(-1); - strcpy(infix,pin); - /* Allocate a buffer for the postfix expression. */ - if (*pp_postfix) free(*pp_postfix); /* Free old buffer. */ - ppostfix = calloc(5*strlen(pinfix)+7, 1); - *pp_postfix = ppostfix; - ppostfixStart = ppostfix++; - *ppostfixStart = BAD_EXPRESSION; - *ppostfix = END_STACK; - - /* place the expression elements into postfix */ - operand_needed = TRUE; - new_expression = TRUE; - *perror = 0; - if (*pinfix == 0) { - return(0); - } - pstacktop = &stack[0]; - while (get_element(pinfix, &pelement, &no_bytes, &arg) != END){ - pinfix += no_bytes; - code = pelement->code; - if ((*ppostfixStart != USES_STRING) && ((code == TO_STRING) || - (code == PRINTF) || (code == SSCANF) || (code == SLITERAL) || - (code == SUBRANGE) || (code == SFETCH))) { - *ppostfixStart = USES_STRING; - } - - switch (pelement->type){ - - case OPERAND: - if (!operand_needed){ - *perror = 5; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add operand to the expression */ - *ppostfix++ = pelement->code; - - /* if this is a variable reference, append variable number */ - if ((pelement->code == (char)FETCH) || (pelement->code == (char)SFETCH)) { - *ppostfix++ = arg; - } - - operand_needed = FALSE; - new_expression = FALSE; - break; - - case FLOAT_PT_CONST: - if (!operand_needed){ - *perror = 5; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add constant to postfix expression */ - *ppostfix++ = pelement->code; - pposthold = ppostfix; - - pinfix-=no_bytes; - while (*pinfix == ' ') *ppostfix++ = *pinfix++; - while (TRUE) { - if ( ( *pinfix >= '0' && *pinfix <= '9' ) || *pinfix == '.' ) { - *ppostfix++ = *pinfix; - pinfix++; - } else if ( *pinfix == 'E' || *pinfix == 'e' ) { - *ppostfix++ = *pinfix; - pinfix++; - if (*pinfix == '+' || *pinfix == '-' ) { - *ppostfix++ = *pinfix; - pinfix++; - } - } else break; - } - *ppostfix++ = '\0'; - - ppostfix = pposthold; - if ( sscanf(ppostfix,"%lg",&constant) != 1) { - *ppostfix = '\0'; - } else { - memcpy(ppostfix,(void *)&constant,8); - } - ppostfix+=8; - - operand_needed = FALSE; - new_expression = FALSE; - break; - - case STRING_CONST: - if (!operand_needed){ - *perror = 5; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add string literal to the postfix expression */ - *ppostfix++ = pelement->code; - c = pinfix[-1]; - while (*pinfix != c && *pinfix) *ppostfix++ = *pinfix++; - *ppostfix++ = '\0'; - if (*pinfix) pinfix++; - - operand_needed = FALSE; - new_expression = FALSE; - break; - - case BINARY_OPERATOR: - if (operand_needed){ - *perror = 4; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add operators of higher or equal priority to postfix expression */ - while ( (pstacktop >= &stack[1]) && - (pstacktop->in_stack_pri >= pelement->in_coming_pri)) { - *ppostfix++ = pstacktop->code; - pstacktop--; - } - - /* add new operator to stack */ - pstacktop++; - *pstacktop = *pelement; - - operand_needed = TRUE; - break; - - case UNARY_OPERATOR: - if (!operand_needed){ - *perror = 5; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add operators of higher or equal priority to postfix expression */ - while ( (pstacktop >= &stack[1]) && - (pstacktop->in_stack_pri >= pelement->in_coming_pri)) { - *ppostfix++ = pstacktop->code; - pstacktop--; - } - - /* add new operator to stack */ - pstacktop++; - *pstacktop = *pelement; - - new_expression = FALSE; - break; - - case MINUS_OPERATOR: - if (operand_needed) { - /* then assume minus was intended as a unary operator */ - in_coming_pri = UNARY_MINUS_I_C_P; - in_stack_pri = UNARY_MINUS_I_S_P; - code = UNARY_MINUS_CODE; - new_expression = FALSE; - } else { - /* then assume minus was intended as a binary operator */ - in_coming_pri = BINARY_MINUS_I_C_P; - in_stack_pri = BINARY_MINUS_I_S_P; - code = BINARY_MINUS_CODE; - operand_needed = TRUE; - } - - /* add operators of higher or equal priority to postfix expression */ - while ( (pstacktop >= &stack[1]) && - (pstacktop->in_stack_pri >= in_coming_pri)) { - *ppostfix++ = pstacktop->code; - pstacktop--; - } - - /* add new operator to stack */ - pstacktop++; - *pstacktop = *pelement; - pstacktop->in_stack_pri = in_stack_pri; - pstacktop->code = code; - - break; - - case SEPARATOR: - if (operand_needed){ - *perror = 4; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add operators to postfix until open paren */ - while ((pstacktop->element[0] != '(') && (pstacktop->element[0] != '[') - && (pstacktop->element[0] != '{')) { - if (pstacktop == &stack[1] || pstacktop == &stack[0]){ - *perror = 6; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - *ppostfix++ = pstacktop->code; - pstacktop--; - } - operand_needed = TRUE; - break; - - case CLOSE_PAREN: - if (operand_needed){ - *perror = 4; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add operators to postfix until matching paren */ - while (pstacktop->element[0] != '(') { - if (pstacktop == &stack[1] || pstacktop == &stack[0]) { - *perror = 6; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - *ppostfix++ = pstacktop->code; - pstacktop--; - } - pstacktop--; /* remove ( from stack */ - break; - - case CLOSE_BRACKET: - if (operand_needed){ - *perror = 4; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add operators to postfix until matching bracket */ - while (pstacktop->element[0] != '[') { - if (pstacktop == &stack[1] || pstacktop == &stack[0]) { - *perror = 6; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - *ppostfix++ = pstacktop->code; - pstacktop--; - } - /* add SUBRANGE operator to postfix */ - if (pstacktop == &stack[0]) { - *perror = 6; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - *ppostfix++ = pstacktop->code; - pstacktop--; - break; - - case CLOSE_CURLY: - if (operand_needed){ - *perror = 4; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add operators to postfix until matching bracket */ - while (pstacktop->element[0] != '{') { - if (pstacktop == &stack[1] || pstacktop == &stack[0]) { - *perror = 6; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - *ppostfix++ = pstacktop->code; - pstacktop--; - } - /* add REPLACE operator to postfix */ - if (pstacktop == &stack[0]) { - *perror = 6; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - *ppostfix++ = pstacktop->code; - pstacktop--; - break; - - case CONDITIONAL: - if (operand_needed){ - *perror = 4; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add operators of higher priority to postfix expression */ - while ( (pstacktop >= &stack[1]) && - (pstacktop->in_stack_pri > pelement->in_coming_pri)) { - *ppostfix++ = pstacktop->code; - pstacktop--; - } - - /* add new element to the postfix expression */ - *ppostfix++ = pelement->code; - - /* add : operator with COND_END code to stack */ - if (pelement->element[0] == ':'){ - pstacktop++; - *pstacktop = *pelement; - pstacktop->code = COND_END; - } - - operand_needed = TRUE; - break; - - case EXPR_TERM: - if (operand_needed && !new_expression){ - *perror = 4; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add all operators on stack to postfix */ - while (pstacktop >= &stack[1]){ - if (pstacktop->element[0] == '('){ - *perror = 6; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - *ppostfix++ = pstacktop->code; - pstacktop--; - } - - /* add new element to the postfix expression */ - *ppostfix++ = pelement->code; - - operand_needed = TRUE; - new_expression = TRUE; - break; - - default: - *perror = 8; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - } - if (operand_needed){ - *perror = 4; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - - /* add all operators on stack to postfix */ - while (pstacktop >= &stack[1]){ - if (pstacktop->element[0] == '('){ - *perror = 6; - *ppostfixStart = BAD_EXPRESSION; return(-1); - } - *ppostfix++ = pstacktop->code; - pstacktop--; - } - *ppostfix++ = END_STACK; - *ppostfix = '\0'; - - if (ppostfixStart[1] == END_STACK) - *ppostfixStart = BAD_EXPRESSION; - else if (*ppostfixStart != USES_STRING) - *ppostfixStart = NO_STRING; - - return(0); -} diff --git a/src/libCom/calc/sCalcPostfix.h b/src/libCom/calc/sCalcPostfix.h deleted file mode 100644 index 3a4a88c8e..000000000 --- a/src/libCom/calc/sCalcPostfix.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* sCalcPostfix.h - * Author: Bob Dalesio - * Date: 9-21-88 - */ - -#ifndef INCsCalcPostfixH -#define INCsCalcPostfixH - -#include "shareLib.h" - -#define BAD_EXPRESSION 0 -#define END_STACK 127 - -#ifdef __cplusplus -extern "C" { -#endif - -epicsShareFunc long epicsShareAPI sCalcPostfix (const char *pinfix, - char **pp_postfix, short *perror); - -epicsShareFunc long epicsShareAPI - sCalcPerform (double *parg, int numArgs, - char **psarg, int numSArgs, double *presult, - char *psresult, int lenSresult, char *post); - -#ifdef __cplusplus -} -#endif - -#endif /* INCsCalcPostfixH */ - diff --git a/src/libCom/calc/sCalcPostfixPvt.h b/src/libCom/calc/sCalcPostfixPvt.h deleted file mode 100644 index 9b2b9460e..000000000 --- a/src/libCom/calc/sCalcPostfixPvt.h +++ /dev/null @@ -1,98 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* sCalcPostfixPvt.h - * Author: Bob Dalesio - * Date: 9-21-88 - */ - -#ifndef INCpostfixh -#include -#endif -#ifndef INCpostfixPvth -#define INCpostfixPvth - -/* #define BAD_EXPRESSION 0 */ - -/* defines for element table */ -/* elements that define a value */ -#define FETCH 1 -#define SFETCH 2 -#define CONST_PI 3 -#define CONST_D2R 4 -#define CONST_R2D 5 -#define CONST_S2R 6 -#define CONST_R2S 7 -#define RANDOM 8 -#define LITERAL 9 -#define SLITERAL 10 -#define SSCANF 11 - -#define VALUE_ELEMENT 11 - -/* elements that operate on a value */ -#define ACOS 12 -#define ASIN 13 -#define ATAN 14 -#define COS 15 -#define COSH 16 -#define SIN 17 -#define RIGHT_SHIFT 18 -#define LEFT_SHIFT 19 -#define SINH 20 -#define TAN 21 -#define TANH 22 -#define LOG_2 23 -#define COND_ELSE 24 -#define ABS_VAL 25 -#define UNARY_NEG 26 -#define SQU_RT 27 -#define EXP 28 -#define CEIL 29 -#define FLOOR 30 -#define LOG_10 31 -#define LOG_E 32 -#define ADD 33 -#define SUB 34 -#define MULT 35 -#define DIV 36 -#define EXPON 37 -#define MODULO 38 -#define BIT_OR 39 -#define BIT_AND 40 -#define BIT_EXCL_OR 41 -#define GR_OR_EQ 42 -#define GR_THAN 43 -#define LESS_OR_EQ 44 -#define LESS_THAN 45 -#define NOT_EQ 46 -#define EQUAL 47 -#define REL_OR 48 -#define REL_AND 49 -#define REL_NOT 50 -#define BIT_NOT 51 -#define PAREN 52 -#define MAX_VAL 53 -#define MIN_VAL 54 -#define COMMA 55 -#define COND_IF 56 -#define COND_END 57 -#define NINT 58 -#define ATAN2 59 -#define STORE 60 -#define TO_DOUBLE 61 -#define PRINTF 62 -#define SUBRANGE 63 -#define TO_STRING 64 -#define REPLACE 65 -/* #define END_STACK 127 */ - -#define USES_STRING 126 -#define NO_STRING 125 -#endif /* INCpostfixPvth */