libCom/calc: Support 0x literals as epicsUInt32
Also use epicsInt32 for all integer calculations.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "osiUnistd.h"
|
||||
#include "dbDefs.h"
|
||||
#include "epicsMath.h"
|
||||
#include "epicsTypes.h"
|
||||
#include "errlog.h"
|
||||
#include "postfix.h"
|
||||
#include "postfixPvt.h"
|
||||
@@ -43,7 +44,7 @@ epicsShareFunc long
|
||||
double stack[CALCPERFORM_STACK+1]; /* zero'th entry not used */
|
||||
double *ptop; /* stack pointer */
|
||||
double top; /* value from top of stack */
|
||||
int itop; /* integer from top of stack */
|
||||
epicsInt32 itop; /* integer from top of stack */
|
||||
int op;
|
||||
int nargs;
|
||||
|
||||
@@ -55,14 +56,14 @@ epicsShareFunc long
|
||||
switch (op){
|
||||
|
||||
case LITERAL_DOUBLE:
|
||||
memcpy((void *)++ptop, pinst, sizeof(double));
|
||||
memcpy(++ptop, pinst, sizeof(double));
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
|
||||
case LITERAL_INT:
|
||||
memcpy(&itop, pinst, sizeof(int));
|
||||
memcpy(&itop, pinst, sizeof(epicsInt32));
|
||||
*++ptop = itop;
|
||||
pinst += sizeof(int);
|
||||
pinst += sizeof(epicsInt32);
|
||||
break;
|
||||
|
||||
case FETCH_VAL:
|
||||
@@ -136,11 +137,11 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case MODULO:
|
||||
itop = (long) *ptop--;
|
||||
itop = (epicsInt32) *ptop--;
|
||||
if (itop)
|
||||
*ptop = (long) *ptop % itop;
|
||||
*ptop = (epicsInt32) *ptop % itop;
|
||||
else
|
||||
*ptop = epicsNAN; /* NaN */
|
||||
*ptop = epicsNAN;
|
||||
break;
|
||||
|
||||
case POWER:
|
||||
@@ -261,7 +262,7 @@ epicsShareFunc long
|
||||
|
||||
case NINT:
|
||||
top = *ptop;
|
||||
*ptop = (double)(long)(top >= 0 ? top + 0.5 : top - 0.5);
|
||||
*ptop = (double)(epicsInt32)(top >= 0 ? top + 0.5 : top - 0.5);
|
||||
break;
|
||||
|
||||
case RANDOM:
|
||||
@@ -283,33 +284,33 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case BIT_OR:
|
||||
itop = (long) *ptop--;
|
||||
*ptop = (long) *ptop | itop;
|
||||
itop = (epicsInt32) *ptop--;
|
||||
*ptop = (epicsInt32) *ptop | itop;
|
||||
break;
|
||||
|
||||
case BIT_AND:
|
||||
itop = (long) *ptop--;
|
||||
*ptop = (long) *ptop & itop;
|
||||
itop = (epicsInt32) *ptop--;
|
||||
*ptop = (epicsInt32) *ptop & itop;
|
||||
break;
|
||||
|
||||
case BIT_EXCL_OR:
|
||||
itop = (long) *ptop--;
|
||||
*ptop = (long) *ptop ^ itop;
|
||||
itop = (epicsInt32) *ptop--;
|
||||
*ptop = (epicsInt32) *ptop ^ itop;
|
||||
break;
|
||||
|
||||
case BIT_NOT:
|
||||
itop = (long) *ptop;
|
||||
itop = (epicsInt32) *ptop;
|
||||
*ptop = ~itop;
|
||||
break;
|
||||
|
||||
case RIGHT_SHIFT:
|
||||
itop = (long) *ptop--;
|
||||
*ptop = (long) *ptop >> itop;
|
||||
itop = (epicsInt32) *ptop--;
|
||||
*ptop = (epicsInt32) *ptop >> itop;
|
||||
break;
|
||||
|
||||
case LEFT_SHIFT:
|
||||
itop = (long) *ptop--;
|
||||
*ptop = (long) *ptop << itop;
|
||||
itop = (epicsInt32) *ptop--;
|
||||
*ptop = (epicsInt32) *ptop << itop;
|
||||
break;
|
||||
|
||||
case NOT_EQ:
|
||||
@@ -381,7 +382,7 @@ calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
case LITERAL_INT:
|
||||
pinst += sizeof(int);
|
||||
pinst += sizeof(epicsInt32);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
@@ -468,7 +469,7 @@ static int cond_search(const char **ppinst, int match)
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
case LITERAL_INT:
|
||||
pinst += sizeof(int);
|
||||
pinst += sizeof(epicsInt32);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
|
||||
+45
-28
@@ -20,8 +20,10 @@
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbDefs.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsStdlib.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsTypes.h"
|
||||
#include "postfix.h"
|
||||
#include "postfixPvt.h"
|
||||
#include "shareLib.h"
|
||||
@@ -71,6 +73,7 @@ static const ELEMENT operands[] = {
|
||||
{"-", 7, 8, 0, UNARY_OPERATOR, UNARY_NEG},
|
||||
{".", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"0", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"0X", 0, 0, 1, LITERAL_OPERAND,LITERAL_INT},
|
||||
{"1", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"2", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"3", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
@@ -214,8 +217,6 @@ epicsShareFunc long
|
||||
int cond_count = 0;
|
||||
char *pout = ppostfix;
|
||||
char *pnext;
|
||||
double lit_d;
|
||||
int lit_i;
|
||||
|
||||
if (psrc == NULL || *psrc == '\0' ||
|
||||
pout == NULL || perror == NULL) {
|
||||
@@ -237,29 +238,45 @@ epicsShareFunc long
|
||||
operand_needed = FALSE;
|
||||
break;
|
||||
|
||||
case LITERAL_OPERAND:
|
||||
runtime_depth += pel->runtime_effect;
|
||||
case LITERAL_OPERAND:
|
||||
runtime_depth += pel->runtime_effect;
|
||||
psrc -= strlen(pel->name);
|
||||
if (pel->code == LITERAL_DOUBLE) {
|
||||
double lit_d;
|
||||
epicsInt32 lit_i;
|
||||
|
||||
psrc -= strlen(pel->name);
|
||||
lit_d = epicsStrtod(psrc, &pnext);
|
||||
if (pnext == psrc) {
|
||||
*perror = CALC_ERR_BAD_LITERAL;
|
||||
goto bad;
|
||||
}
|
||||
psrc = pnext;
|
||||
lit_i = lit_d;
|
||||
if (lit_d != (double) lit_i) {
|
||||
*pout++ = pel->code;
|
||||
memcpy(pout, (void *)&lit_d, sizeof(double));
|
||||
pout += sizeof(double);
|
||||
} else {
|
||||
*pout++ = LITERAL_INT;
|
||||
memcpy(pout, (void *)&lit_i, sizeof(int));
|
||||
pout += sizeof(int);
|
||||
}
|
||||
if (epicsParseDouble(psrc, &lit_d, &pnext)) {
|
||||
*perror = CALC_ERR_BAD_LITERAL;
|
||||
goto bad;
|
||||
}
|
||||
psrc = pnext;
|
||||
lit_i = lit_d;
|
||||
if (lit_d != (double) lit_i) {
|
||||
*pout++ = pel->code;
|
||||
memcpy(pout, &lit_d, sizeof(double));
|
||||
pout += sizeof(double);
|
||||
} else {
|
||||
*pout++ = LITERAL_INT;
|
||||
memcpy(pout, &lit_i, sizeof(epicsInt32));
|
||||
pout += sizeof(epicsInt32);
|
||||
}
|
||||
}
|
||||
else {
|
||||
epicsUInt32 lit_ui;
|
||||
|
||||
operand_needed = FALSE;
|
||||
break;
|
||||
assert(pel->code == LITERAL_INT);
|
||||
if (epicsParseUInt32(psrc, &lit_ui, 0, &pnext)) {
|
||||
*perror = CALC_ERR_BAD_LITERAL;
|
||||
goto bad;
|
||||
}
|
||||
psrc = pnext;
|
||||
*pout++ = LITERAL_INT;
|
||||
memcpy(pout, &lit_ui, sizeof(epicsInt32));
|
||||
pout += sizeof(epicsInt32);
|
||||
}
|
||||
|
||||
operand_needed = FALSE;
|
||||
break;
|
||||
|
||||
case STORE_OPERATOR:
|
||||
if (pout == ppostfix || pstacktop > stack ||
|
||||
@@ -580,19 +597,19 @@ epicsShareFunc void
|
||||
};
|
||||
char op;
|
||||
double lit_d;
|
||||
int lit_i;
|
||||
epicsInt32 lit_i;
|
||||
|
||||
while ((op = *pinst) != END_EXPRESSION) {
|
||||
switch (op) {
|
||||
case LITERAL_DOUBLE:
|
||||
memcpy((void *)&lit_d, ++pinst, sizeof(double));
|
||||
memcpy(&lit_d, ++pinst, sizeof(double));
|
||||
printf("\tDouble %g\n", lit_d);
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
case LITERAL_INT:
|
||||
memcpy((void *)&lit_i, ++pinst, sizeof(int));
|
||||
printf("\tInteger %d\n", lit_i);
|
||||
pinst += sizeof(int);
|
||||
memcpy(&lit_i, ++pinst, sizeof(epicsInt32));
|
||||
printf("\tInteger %d (0x%x)\n", lit_i, lit_i);
|
||||
pinst += sizeof(epicsInt32);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
|
||||
@@ -238,7 +238,7 @@ MAIN(epicsCalcTest)
|
||||
const double a=1.0, b=2.0, c=3.0, d=4.0, e=5.0, f=6.0,
|
||||
g=7.0, h=8.0, i=9.0, j=10.0, k=11.0, l=12.0;
|
||||
|
||||
testPlan(570);
|
||||
testPlan(577);
|
||||
|
||||
/* LITERAL_OPERAND elements */
|
||||
testExpr(0);
|
||||
@@ -253,6 +253,11 @@ MAIN(epicsCalcTest)
|
||||
testExpr(9);
|
||||
testExpr(.1);
|
||||
testExpr(0.1);
|
||||
testExpr(0X0);
|
||||
testExpr(0x10);
|
||||
testExpr(0x7fffffff);
|
||||
testCalc("0x80000000", -2147483648.0);
|
||||
testCalc("0xffffffff", -1);
|
||||
testExpr(Inf);
|
||||
testCalc("Infinity", Inf);
|
||||
testExpr(NaN);
|
||||
@@ -287,6 +292,7 @@ MAIN(epicsCalcTest)
|
||||
testExpr(-1);
|
||||
testExpr(-Inf);
|
||||
testExpr(- -1);
|
||||
testCalc("-0x80000000", 2147483648.0);
|
||||
|
||||
/* UNARY_OPERATOR elements */
|
||||
testExpr((1));
|
||||
@@ -855,6 +861,7 @@ MAIN(epicsCalcTest)
|
||||
testArgs("13.1;B:=A;A:=B;C:=D;D:=C", A_A|A_D, A_A|A_B|A_C|A_D);
|
||||
|
||||
// Malformed expressions
|
||||
testBadExpr("0x0.1", CALC_ERR_SYNTAX);
|
||||
testBadExpr("1*", CALC_ERR_INCOMPLETE);
|
||||
testBadExpr("*1", CALC_ERR_SYNTAX);
|
||||
testBadExpr("MIN", CALC_ERR_INCOMPLETE);
|
||||
|
||||
Reference in New Issue
Block a user