27 #include "libComAPI.h" 67 static const ELEMENT operands[] = {
132 static const ELEMENT operators[] = {
143 {
",", 0, 0, 0,
SEPERATOR, NOT_GENERATED},
173 get_element(
int opnd,
const char **ppsrc,
const ELEMENT **ppel)
179 while (isspace((
int) (
unsigned char) **ppsrc)) ++*ppsrc;
180 if (**ppsrc ==
'\0')
return FALSE;
190 while (pel >= ptable) {
191 size_t len = strlen(pel->
name);
209 postfix(
const char *psrc,
char *pout,
short *perror)
214 int operand_needed =
TRUE;
215 int runtime_depth = 0;
217 char *
const pdest = pout;
220 if (psrc ==
NULL || *psrc ==
'\0' ||
231 while (get_element(operand_needed, &psrc, &pel)) {
237 operand_needed =
FALSE;
243 psrc -= strlen(pel->
name);
254 if (lit_d != (
double) lit_i) {
256 memcpy(pout, &lit_d,
sizeof(
double));
257 pout +=
sizeof(double);
278 operand_needed =
FALSE;
282 if (pout == pdest || pstacktop > stack ||
283 *--pout < FETCH_A || *pout >
FETCH_L) {
291 operand_needed =
TRUE;
297 while ((pstacktop > stack) &&
299 *pout++ = pstacktop->
code;
314 while ((pstacktop > stack) &&
316 *pout++ = pstacktop->
code;
328 operand_needed =
TRUE;
333 while (pstacktop->
name[0] !=
'(') {
334 if (pstacktop <= stack+1) {
338 *pout++ = pstacktop->
code;
345 operand_needed =
TRUE;
351 while (pstacktop->
name[0] !=
'(') {
352 if (pstacktop <= stack+1) {
356 *pout++ = pstacktop->
code;
366 if ((pstacktop > stack) &&
379 while ((pstacktop > stack) &&
381 *pout++ = pstacktop->
code;
394 if (pel->
name[0] ==
':') {
395 if (--cond_count < 0) {
407 operand_needed =
TRUE;
412 while (pstacktop > stack) {
413 if (pstacktop->
name[0] ==
'(') {
417 *pout++ = pstacktop->
code;
425 if (cond_count != 0) {
429 if (runtime_depth > 1) {
434 operand_needed =
TRUE;
442 if (runtime_depth < 0) {
458 while (pstacktop > stack) {
459 if (pstacktop->
name[0] ==
'(') {
463 *pout++ = pstacktop->
code;
472 if (cond_count != 0) {
476 if (operand_needed || runtime_depth != 1) {
492 LIBCOM_API
const char *
495 static const char *errStrs[] = {
497 "Too many results returned",
498 "Badly formed numeric literal",
499 "Bad assignment target",
500 "Comma without enclosing parentheses",
501 "Close parenthesis found without open",
502 "Parenthesis still open at end of expression",
503 "Unbalanced conditional ?: operators",
504 "Incomplete expression, operand missing",
505 "Not enough operands provided",
506 "Runtime stack overflow",
507 "Syntax error, unknown operator/operand",
508 "NULL or empty input argument to postfix()",
509 "Internal error, unknown element type",
514 return errStrs[error];
525 static const char *opcodes[] = {
528 "LITERAL_DOUBLE",
"LITERAL_INT",
"VAL",
529 "FETCH_A",
"FETCH_B",
"FETCH_C",
"FETCH_D",
"FETCH_E",
"FETCH_F",
530 "FETCH_G",
"FETCH_H",
"FETCH_I",
"FETCH_J",
"FETCH_K",
"FETCH_L",
532 "STORE_A",
"STORE_B",
"STORE_C",
"STORE_D",
"STORE_E",
"STORE_F",
533 "STORE_G",
"STORE_H",
"STORE_I",
"STORE_J",
"STORE_K",
"STORE_L",
606 memcpy(&lit_d, ++pinst,
sizeof(
double));
607 printf(
"\tDouble %g\n", lit_d);
608 pinst +=
sizeof(double);
612 printf(
"\tInteger %d (0x%x)\n", lit_i, lit_i);
619 printf(
"\t%s, %d arg(s)\n", opcodes[(
int) op], *++pinst);
623 printf(
"\t%s\n", opcodes[(
int) op]);
#define CALC_ERR_NULL_ARG
NULL or empty input argument.
LIBCOM_API const char * calcErrorStr(short error)
Convert an error code to a string.
#define assert(exp)
Declare that a condition should be true.
#define CALC_ERR_BAD_LITERAL
Bad numeric literal.
An EPICS-specific replacement for ANSI C's assert.
The API for the EPICS Calculation Engine.
Miscellaneous macro definitions.
#define CALC_ERR_OVERFLOW
Runtime stack would overflow.
#define CALC_ERR_TOOMANY
Too many results returned.
#define CALC_ERR_INTERNAL
Internal error, bad element type.
#define CALC_ERR_UNDERFLOW
Runtime stack would underflow.
#define CALC_ERR_INCOMPLETE
Incomplete expression, operand missing.
#define CALC_ERR_PAREN_NOT_OPEN
Close parenthesis without open.
#define CALC_ERR_BAD_SEPERATOR
Comma without parentheses.
#define CALC_ERR_BAD_ASSIGNMENT
Bad assignment target.
LIBCOM_API int epicsParseDouble(const char *str, double *to, char **units)
LIBCOM_API void calcExprDump(const char *pinst)
Disassemble a postfix expression.
signed char runtime_effect
int epicsStrnCaseCmp(const char *s1, const char *s2, size_t len)
#define CALCPERFORM_STACK
Size of the internal partial result stack.
LIBCOM_API int epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
#define CALC_ERR_CONDITIONAL
Unbalanced conditional ?: operators.
ChannelPut::shared_pointer op
LIBCOM_API long postfix(const char *psrc, char *pout, short *perror)
Compile an infix expression into postfix byte-code.
struct expression_element ELEMENT
#define CALC_ERR_SYNTAX
Syntax error.
#define CALC_ERR_NONE
No error.
#define CALC_ERR_PAREN_OPEN
Open parenthesis at end of expression.