Merged the expand-calc-size branch.
This allows calc and calcout record expressions to be up to 79 characters long, and shortens the postfix buffer needed by introducing integer literals. Also removes the length limit for access security CALC expressions.
This commit is contained in:
@@ -1323,17 +1323,10 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
|
||||
unsigned long stores;
|
||||
|
||||
if (!pasgrule) return 0;
|
||||
insize = strlen(calc);
|
||||
if (insize > MAX_INFIX_SIZE) {
|
||||
pasgrule->calc = NULL;
|
||||
pasgrule->rpcl = NULL;
|
||||
status = S_asLib_badCalc;
|
||||
errlogPrintf("CALC expression too long: '%s'\n", calc);
|
||||
return status;
|
||||
}
|
||||
pasgrule->calc = asCalloc(1, insize+1);
|
||||
insize = strlen(calc) + 1;
|
||||
pasgrule->calc = asCalloc(1, insize);
|
||||
strcpy(pasgrule->calc, calc);
|
||||
pasgrule->rpcl = asCalloc(1, MAX_POSTFIX_SIZE);
|
||||
pasgrule->rpcl = asCalloc(1, INFIX_TO_POSTFIX_SIZE(insize));
|
||||
status = postfix(pasgrule->calc, pasgrule->rpcl, &err);
|
||||
if(status) {
|
||||
free((void *)pasgrule->calc);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
@@ -43,21 +43,26 @@ epicsShareFunc long
|
||||
double stack[CALCPERFORM_STACK+1]; /* zero'th entry not used */
|
||||
double *ptop; /* stack pointer */
|
||||
double top; /* value from top of stack */
|
||||
long itop; /* integer from top of stack */
|
||||
int itop; /* integer from top of stack */
|
||||
int op;
|
||||
int nargs;
|
||||
|
||||
/* initialize */
|
||||
ptop = stack;
|
||||
|
||||
/* RPN evaluation loop */
|
||||
while (*pinst != END_EXPRESSION){
|
||||
switch (*pinst){
|
||||
while ((op = *pinst++) != END_EXPRESSION){
|
||||
switch (op){
|
||||
|
||||
case LITERAL:
|
||||
++ptop;
|
||||
++pinst;
|
||||
memcpy((void *)ptop, pinst, sizeof(double));
|
||||
pinst += sizeof(double) - 1;
|
||||
case LITERAL_DOUBLE:
|
||||
memcpy((void *)++ptop, pinst, sizeof(double));
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
|
||||
case LITERAL_INT:
|
||||
memcpy(&itop, pinst, sizeof(int));
|
||||
*++ptop = itop;
|
||||
pinst += sizeof(int);
|
||||
break;
|
||||
|
||||
case FETCH_VAL:
|
||||
@@ -76,7 +81,7 @@ epicsShareFunc long
|
||||
case FETCH_J:
|
||||
case FETCH_K:
|
||||
case FETCH_L:
|
||||
*++ptop = parg[*pinst - FETCH_A];
|
||||
*++ptop = parg[op - FETCH_A];
|
||||
break;
|
||||
|
||||
case STORE_A:
|
||||
@@ -91,7 +96,7 @@ epicsShareFunc long
|
||||
case STORE_J:
|
||||
case STORE_K:
|
||||
case STORE_L:
|
||||
parg[*pinst - STORE_A] = *ptop--;
|
||||
parg[op - STORE_A] = *ptop--;
|
||||
break;
|
||||
|
||||
case CONST_PI:
|
||||
@@ -160,7 +165,7 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case MAX:
|
||||
nargs = *++pinst;
|
||||
nargs = *pinst++;
|
||||
while (--nargs) {
|
||||
top = *ptop--;
|
||||
if (*ptop < top || isnan(top))
|
||||
@@ -169,7 +174,7 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case MIN:
|
||||
nargs = *++pinst;
|
||||
nargs = *pinst++;
|
||||
while (--nargs) {
|
||||
top = *ptop--;
|
||||
if (*ptop > top || isnan(top))
|
||||
@@ -231,7 +236,7 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case FINITE:
|
||||
nargs = *++pinst;
|
||||
nargs = *pinst++;
|
||||
top = finite(*ptop);
|
||||
while (--nargs) {
|
||||
--ptop;
|
||||
@@ -245,7 +250,7 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case ISNAN:
|
||||
nargs = *++pinst;
|
||||
nargs = *pinst++;
|
||||
top = isnan(*ptop);
|
||||
while (--nargs) {
|
||||
--ptop;
|
||||
@@ -350,12 +355,9 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
default:
|
||||
errlogPrintf("calcPerform: Bad Opcode %d at %p\n",*pinst, pinst);
|
||||
errlogPrintf("calcPerform: Bad Opcode %d at %p\n", op, pinst-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Advance to next opcode */
|
||||
++pinst;
|
||||
}
|
||||
|
||||
/* The stack should now have one item on it, the expression value */
|
||||
@@ -372,12 +374,21 @@ calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
unsigned long inputs = 0;
|
||||
unsigned long stores = 0;
|
||||
char op;
|
||||
while ((op = *pinst) != END_EXPRESSION) {
|
||||
while ((op = *pinst++) != END_EXPRESSION) {
|
||||
switch (op) {
|
||||
|
||||
case LITERAL:
|
||||
case LITERAL_DOUBLE:
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
case LITERAL_INT:
|
||||
pinst += sizeof(int);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
case FINITE:
|
||||
case ISNAN:
|
||||
pinst++;
|
||||
break;
|
||||
|
||||
case FETCH_A:
|
||||
case FETCH_B:
|
||||
@@ -413,7 +424,6 @@ calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pinst++;
|
||||
}
|
||||
if (pinputs) *pinputs = inputs;
|
||||
if (pstores) *pstores = stores;
|
||||
@@ -439,24 +449,37 @@ static double calcRandom(void)
|
||||
}
|
||||
|
||||
/* Search the instruction stream for a matching operator, skipping any
|
||||
* other conditional instructions found
|
||||
* other conditional instructions found, and leave *ppinst pointing to
|
||||
* the next instruction to be executed.
|
||||
*/
|
||||
static int cond_search(const char **ppinst, int match)
|
||||
{
|
||||
const char *pinst = *ppinst + 1;
|
||||
const char *pinst = *ppinst;
|
||||
int count = 1;
|
||||
int op;
|
||||
|
||||
while ((op = *pinst) != END_EXPRESSION) {
|
||||
while ((op = *pinst++) != END_EXPRESSION) {
|
||||
if (op == match && --count == 0) {
|
||||
*ppinst = pinst;
|
||||
return 0;
|
||||
} else if (op == COND_IF)
|
||||
count++;
|
||||
else if (op == LITERAL)
|
||||
}
|
||||
switch (op) {
|
||||
case LITERAL_DOUBLE:
|
||||
pinst += sizeof(double);
|
||||
pinst++;
|
||||
break;
|
||||
case LITERAL_INT:
|
||||
pinst += sizeof(int);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
case FINITE:
|
||||
case ISNAN:
|
||||
pinst++;
|
||||
break;
|
||||
case COND_IF:
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
* Subroutines used to convert an infix expression to a postfix expression
|
||||
*
|
||||
* Author: Bob Dalesio
|
||||
* Original Author: Bob Dalesio
|
||||
* Date: 12-12-86
|
||||
*/
|
||||
|
||||
@@ -69,17 +69,17 @@ static const ELEMENT operands[] = {
|
||||
{"!", 7, 8, 0, UNARY_OPERATOR, REL_NOT},
|
||||
{"(", 0, 8, 0, UNARY_OPERATOR, NOT_GENERATED},
|
||||
{"-", 7, 8, 0, UNARY_OPERATOR, UNARY_NEG},
|
||||
{".", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"0", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"1", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"2", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"3", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"4", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"5", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"6", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"7", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"8", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"9", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{".", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"0", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"1", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"2", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"3", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"4", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"5", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"6", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"7", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"8", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"9", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"A", 0, 0, 1, OPERAND, FETCH_A},
|
||||
{"ABS", 7, 8, 0, UNARY_OPERATOR, ABS_VAL},
|
||||
{"ACOS", 7, 8, 0, UNARY_OPERATOR, ACOS},
|
||||
@@ -101,7 +101,7 @@ static const ELEMENT operands[] = {
|
||||
{"G", 0, 0, 1, OPERAND, FETCH_G},
|
||||
{"H", 0, 0, 1, OPERAND, FETCH_H},
|
||||
{"I", 0, 0, 1, OPERAND, FETCH_I},
|
||||
{"INF", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"INF", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"ISINF", 7, 8, 0, UNARY_OPERATOR, ISINF},
|
||||
{"ISNAN", 7, 8, 0, VARARG_OPERATOR,ISNAN},
|
||||
{"J", 0, 0, 1, OPERAND, FETCH_J},
|
||||
@@ -113,7 +113,7 @@ static const ELEMENT operands[] = {
|
||||
{"MAX", 7, 8, 0, VARARG_OPERATOR,MAX},
|
||||
{"MIN", 7, 8, 0, VARARG_OPERATOR,MIN},
|
||||
{"NINT", 7, 8, 0, UNARY_OPERATOR, NINT},
|
||||
{"NAN", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"NAN", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"NOT", 7, 8, 0, UNARY_OPERATOR, BIT_NOT},
|
||||
{"PI", 0, 0, 1, OPERAND, CONST_PI},
|
||||
{"R2D", 0, 0, 1, OPERAND, CONST_R2D},
|
||||
@@ -214,7 +214,8 @@ epicsShareFunc long
|
||||
int cond_count = 0;
|
||||
char *pout = ppostfix;
|
||||
char *pnext;
|
||||
double constant;
|
||||
double lit_d;
|
||||
int lit_i;
|
||||
|
||||
if (psrc == NULL || *psrc == '\0' ||
|
||||
pout == NULL || perror == NULL) {
|
||||
@@ -237,18 +238,25 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case LITERAL_OPERAND:
|
||||
*pout++ = pel->code;
|
||||
runtime_depth += pel->runtime_effect;
|
||||
|
||||
psrc -= strlen(pel->name);
|
||||
constant = epicsStrtod(psrc, &pnext);
|
||||
lit_d = epicsStrtod(psrc, &pnext);
|
||||
if (pnext == psrc) {
|
||||
*perror = CALC_ERR_BAD_LITERAL;
|
||||
goto bad;
|
||||
}
|
||||
psrc = pnext;
|
||||
memcpy(pout, (void *)&constant, sizeof(double));
|
||||
pout += sizeof(double);
|
||||
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);
|
||||
}
|
||||
|
||||
operand_needed = FALSE;
|
||||
break;
|
||||
@@ -500,7 +508,7 @@ epicsShareFunc void
|
||||
static const char *opcodes[] = {
|
||||
"End Expression",
|
||||
/* Operands */
|
||||
"LITERAL", "VAL",
|
||||
"LITERAL_DOUBLE", "LITERAL_INT", "VAL",
|
||||
"FETCH_A", "FETCH_B", "FETCH_C", "FETCH_D", "FETCH_E", "FETCH_F",
|
||||
"FETCH_G", "FETCH_H", "FETCH_I", "FETCH_J", "FETCH_K", "FETCH_L",
|
||||
/* Assignment */
|
||||
@@ -571,15 +579,21 @@ epicsShareFunc void
|
||||
"NOT_GENERATED"
|
||||
};
|
||||
char op;
|
||||
double lit;
|
||||
double lit_d;
|
||||
int lit_i;
|
||||
|
||||
while ((op = *pinst) != END_EXPRESSION) {
|
||||
switch (op) {
|
||||
case LITERAL:
|
||||
memcpy((void *)&lit, ++pinst, sizeof(double));
|
||||
printf("\tLiteral: %g\n", lit);
|
||||
case LITERAL_DOUBLE:
|
||||
memcpy((void *)&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);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
case FINITE:
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, 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
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* postfix.h
|
||||
* Author: Bob Dalesio
|
||||
* Original Author: Bob Dalesio
|
||||
* Date: 9-21-88
|
||||
*/
|
||||
|
||||
@@ -20,14 +19,23 @@
|
||||
#define CALCPERFORM_NARGS 12
|
||||
#define CALCPERFORM_STACK 80
|
||||
|
||||
#define INFIX_TO_POSTFIX_SIZE(n) (((n-2)>>2)*21 + ((n-2)&2)*5 + 10)
|
||||
/* The above is calculated from the following expression fragments:
|
||||
* 1?1: 4 chars expand to 21 chars
|
||||
* 1+ 2 chars expand to 10 chars
|
||||
* 1 1 char expands to 9 chars
|
||||
* All other infix operators convert by a factor of 1:1 or less.
|
||||
* Allow 1 char each for the infix and postfix terminators,
|
||||
* and the infix must be a complete expression
|
||||
#define INFIX_TO_POSTFIX_SIZE(n) (n*21/6)
|
||||
/* The above expression is an estimate of the maximum postfix buffer
|
||||
* size needed for a given infix expression buffer. The actual size
|
||||
* needed is never larger than this value, although it is actually a
|
||||
* few bytes smaller for some sizes.
|
||||
*
|
||||
* The maximum expansion from infix to postfix is for the sub-expression
|
||||
* .1?.1:
|
||||
* which is 6 characters long and results in 21 bytes of postfix:
|
||||
* .1 => LITERAL_DOUBLE + 8 byte value
|
||||
* ? => COND_IF
|
||||
* .1 => LITERAL_DOUBLE + 8 byte value
|
||||
* : => COND_ELSE
|
||||
* ...
|
||||
* => COND_END
|
||||
* For other short expressions the factor 21/6 always gives a big enough
|
||||
* postfix buffer (proven by hand, look at '1+' and '.1+' as well).
|
||||
*/
|
||||
|
||||
/* These are not hard limits, just default sizes for the database */
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, 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
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* postfixPvt.h
|
||||
* Author: Bob Dalesio
|
||||
* Original Author: Bob Dalesio
|
||||
* Date: 9-21-88
|
||||
*/
|
||||
|
||||
/* Notes:
|
||||
* 1. The FETCH_A through FETCH_L and STORE_A through STORE_L opcodes must
|
||||
* be contiguous.
|
||||
* 2. The LITERAL opcode is followed by its double value.
|
||||
* 3. You can't quite use strlen() on an RPN buffer, since the literal
|
||||
* double value can contain nil bytes.
|
||||
* 2. The LITERAL opcodes are followed by a binary representation of their
|
||||
* values, but these are not aligned properly.
|
||||
* 3. The var-arg functions MIN, MAX, FINITE and ISNAN are followed by
|
||||
* a byte giving the number of arguments to process.
|
||||
* 4. You can't use strlen() on an RPN buffer since the literal values
|
||||
* can contain zero bytes.
|
||||
*/
|
||||
|
||||
#ifndef INCpostfixPvth
|
||||
@@ -28,7 +30,7 @@
|
||||
typedef enum {
|
||||
END_EXPRESSION = 0,
|
||||
/* Operands */
|
||||
LITERAL, FETCH_VAL,
|
||||
LITERAL_DOUBLE, LITERAL_INT, FETCH_VAL,
|
||||
FETCH_A, FETCH_B, FETCH_C, FETCH_D, FETCH_E, FETCH_F,
|
||||
FETCH_G, FETCH_H, FETCH_I, FETCH_J, FETCH_K, FETCH_L,
|
||||
/* Assignment */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
@@ -66,13 +66,31 @@ void testCalc(const char *expr, double expected) {
|
||||
return;
|
||||
}
|
||||
|
||||
void testArgs(const char *expr, unsigned long einp, unsigned long eout) {
|
||||
char rpn[MAX_POSTFIX_SIZE];
|
||||
short err = 0;
|
||||
unsigned long vinp, vout;
|
||||
|
||||
if (postfix(expr, rpn, &err)) {
|
||||
testFail("postfix: %s in expression '%s'", calcErrorStr(err), expr);
|
||||
return;
|
||||
}
|
||||
if (calcArgUsage(rpn, &vinp, &vout)) {
|
||||
testFail("calcArgUsage returned error for '%s'", expr);
|
||||
return;
|
||||
}
|
||||
if (!testOk(vinp == einp && vout == eout, "Args for '%s'", expr)) {
|
||||
testDiag("Expected (%lx, %lx) got (%lx, %lx)", einp, eout, vinp, vout);
|
||||
}
|
||||
}
|
||||
|
||||
void testBadExpr(const char *expr, short expected_err) {
|
||||
/* Parse an invalid expression, test against expected error code */
|
||||
char rpn[MAX_POSTFIX_SIZE];
|
||||
short err = 0;
|
||||
|
||||
postfix(expr, rpn, &err);
|
||||
if (!testOk(err == expected_err, "%s (bad expression)", expr)) {
|
||||
if (!testOk(err == expected_err, "Bad expression '%s'", expr)) {
|
||||
testDiag("Expected '%s', actually got '%s'",
|
||||
calcErrorStr(expected_err), calcErrorStr(err));
|
||||
calcExprDump(rpn);
|
||||
@@ -83,8 +101,22 @@ void testBadExpr(const char *expr, short expected_err) {
|
||||
/* Test an expression that is also valid C code */
|
||||
#define testExpr(expr) testCalc(#expr, expr);
|
||||
|
||||
/* These are the argument bits for testArgs */
|
||||
#define A_A 0x001
|
||||
#define A_B 0x002
|
||||
#define A_C 0x004
|
||||
#define A_D 0x008
|
||||
#define A_E 0x010
|
||||
#define A_F 0x020
|
||||
#define A_G 0x040
|
||||
#define A_H 0x080
|
||||
#define A_I 0x100
|
||||
#define A_J 0x200
|
||||
#define A_K 0x400
|
||||
#define A_L 0x800
|
||||
|
||||
/* Macros to make some expressions into valid C code */
|
||||
|
||||
/* Macros and functions to make some expressions into valid C code */
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979
|
||||
@@ -198,7 +230,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(533);
|
||||
testPlan(566);
|
||||
|
||||
/* LITERAL_OPERAND elements */
|
||||
testExpr(0);
|
||||
@@ -780,7 +812,39 @@ MAIN(epicsCalcTest)
|
||||
testCalc("1+(1|2)**3", 1+pow((double) (1 | 2), 3.));// 8 6
|
||||
testExpr(1+(1?(1<2):(1>2))*2);
|
||||
|
||||
testArgs("a", A_A, 0);
|
||||
testArgs("A", A_A, 0);
|
||||
testArgs("B", A_B, 0);
|
||||
testArgs("C", A_C, 0);
|
||||
testArgs("D", A_D, 0);
|
||||
testArgs("E", A_E, 0);
|
||||
testArgs("F", A_F, 0);
|
||||
testArgs("G", A_G, 0);
|
||||
testArgs("H", A_H, 0);
|
||||
testArgs("I", A_I, 0);
|
||||
testArgs("J", A_J, 0);
|
||||
testArgs("K", A_K, 0);
|
||||
testArgs("L", A_L, 0);
|
||||
testArgs("A+B+C+D+E+F+G+H+I+J+K+L",
|
||||
A_A|A_B|A_C|A_D|A_E|A_F|A_G|A_H|A_I|A_J|A_K|A_L, 0);
|
||||
testArgs("0.1;A:=0", 0, A_A);
|
||||
testArgs("1.1;B:=0", 0, A_B);
|
||||
testArgs("2.1;C:=0", 0, A_C);
|
||||
testArgs("3.1;D:=0", 0, A_D);
|
||||
testArgs("4.1;E:=0", 0, A_E);
|
||||
testArgs("5.1;F:=0", 0, A_F);
|
||||
testArgs("6.1;G:=0", 0, A_G);
|
||||
testArgs("7.1;H:=0", 0, A_H);
|
||||
testArgs("8.1;I:=0", 0, A_I);
|
||||
testArgs("9.1;J:=0", 0, A_J);
|
||||
testArgs("10.1;K:=0", 0, A_K);
|
||||
testArgs("11.1;L:=0", 0, A_L);
|
||||
testArgs("12.1;A:=0;B:=A;C:=B;D:=C", 0, A_A|A_B|A_C|A_D);
|
||||
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("1*", CALC_ERR_INCOMPLETE);
|
||||
testBadExpr("*1", CALC_ERR_SYNTAX);
|
||||
testBadExpr("MIN", CALC_ERR_INCOMPLETE);
|
||||
testBadExpr("MIN()", CALC_ERR_SYNTAX);
|
||||
testBadExpr("MIN(A,)", CALC_ERR_SYNTAX);
|
||||
@@ -789,6 +853,9 @@ MAIN(epicsCalcTest)
|
||||
testBadExpr("MAX()", CALC_ERR_SYNTAX);
|
||||
testBadExpr("MAX(A,)", CALC_ERR_SYNTAX);
|
||||
testBadExpr("MAX(A,B,)", CALC_ERR_SYNTAX);
|
||||
testBadExpr("1?", CALC_ERR_CONDITIONAL);
|
||||
testBadExpr("1?1", CALC_ERR_CONDITIONAL);
|
||||
testBadExpr(":1", CALC_ERR_SYNTAX);
|
||||
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ recordtype(calc) {
|
||||
promptgroup(GUI_CALC)
|
||||
special(SPC_CALC)
|
||||
pp(TRUE)
|
||||
size(40)
|
||||
size(80)
|
||||
initial("0")
|
||||
}
|
||||
field(INPA,DBF_INLINK) {
|
||||
@@ -296,6 +296,6 @@ recordtype(calc) {
|
||||
prompt("Reverse Polish Calc")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(40)]")
|
||||
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ recordtype(calcout) {
|
||||
promptgroup(GUI_CALC)
|
||||
special(SPC_CALC)
|
||||
pp(TRUE)
|
||||
size(40)
|
||||
size(80)
|
||||
initial("0")
|
||||
}
|
||||
field(CLCV,DBF_LONG) {
|
||||
@@ -248,7 +248,7 @@ recordtype(calcout) {
|
||||
promptgroup(GUI_CALC)
|
||||
special(SPC_CALC)
|
||||
pp(TRUE)
|
||||
size(40)
|
||||
size(80)
|
||||
initial("0")
|
||||
}
|
||||
field(OCLV,DBF_LONG) {
|
||||
@@ -495,12 +495,12 @@ recordtype(calcout) {
|
||||
prompt("Reverse Polish Calc")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(40)]")
|
||||
extra("char rpcl[INFIX_TO_POSTFIX_SIZE(80)]")
|
||||
}
|
||||
field(ORPC,DBF_NOACCESS) {
|
||||
prompt("Reverse Polish OCalc")
|
||||
special(SPC_NOMOD)
|
||||
interest(4)
|
||||
extra("char orpc[INFIX_TO_POSTFIX_SIZE(40)]")
|
||||
extra("char orpc[INFIX_TO_POSTFIX_SIZE(80)]")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user