Major update, code reorganization and enhancement.

This commit is contained in:
Andrew Johnson
2006-03-30 20:07:06 +00:00
parent e9e4e34fdf
commit 97a5aa16a0
4 changed files with 1022 additions and 999 deletions
+393 -432
View File
@@ -12,450 +12,391 @@
* 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. CalcPerform
* calculates the postfix expression.
*
* Subroutines
*
* Public
*
* calcPerform perform the calculation
* args
* double *pargs address of arguments (12)
* double *presult address of result
* char *rpcl address of reverse polish buffer
* returns
* 0 fetched successfully
* -1 fetch failed
*
* Private routine for calcPerform
* local_random random number generator
* returns
* double value between 0.00 and 1.00
*/
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#define epicsExportSharedSymbols
#include "osiUnistd.h"
#include "dbDefs.h"
#include "epicsMath.h"
#define epicsExportSharedSymbols
#include "postfix.h"
#include "postfixPvt.h"
#include "osiUnistd.h"
static double local_random(void);
#define NOT_SET 0
#define TRUE_COND 1
#define FALSE_COND 2
static double calcRandom(void);
static int cond_search(const char **ppinst, int match);
#ifndef PI
#define PI 3.141592654
#define PI 3.14159265358979323
#endif
epicsShareFunc long epicsShareAPI
calcPerform(double *parg, double *presult, char *post)
/* calcPerform
*
* Evalutate the postfix expression
*/
epicsShareFunc long
calcPerform(double *parg, double *presult, const char *pinst)
{
double *pstacktop; /* stack of values */
double stack[80];
short temp1;
double *top;
int itop; /* integer top value */
int inexttop; /* ineteger next to top value */
short cond_flag; /* conditional else flag */
short got_if;
/* initialize flag */
cond_flag = NOT_SET;
pstacktop = &stack[0];
/* DEBUG print statements
for (short i=0;i<184;i++){
printf ("%d_",post[i]);
if ( post[i] == END_STACK ) break;
if ( post[i] == 71 ) i=i+8;
}
printf ("*FINISHED*\n");
*/
if(*post == BAD_EXPRESSION) return(-1);
/* set post to postfix expression in calc structure */
top = pstacktop;
/* polish calculator loop */
while (*post != END_STACK){
switch (*post){
case FETCH_A:
++pstacktop;
*pstacktop = parg[0];
break;
case FETCH_B:
++pstacktop;
*pstacktop = parg[1];
break;
case FETCH_C:
++pstacktop;
*pstacktop = parg[2];
break;
case FETCH_D:
++pstacktop;
*pstacktop = parg[3];
break;
case FETCH_E:
++pstacktop;
*pstacktop = parg[4];
break;
case FETCH_F:
++pstacktop;
*pstacktop = parg[5];
break;
case FETCH_G:
++pstacktop;
*pstacktop = parg[6];
break;
case FETCH_H:
++pstacktop;
*pstacktop = parg[7];
break;
case FETCH_I:
++pstacktop;
*pstacktop = parg[8];
break;
case FETCH_J:
++pstacktop;
*pstacktop = parg[9];
break;
case FETCH_K:
++pstacktop;
*pstacktop = parg[10];
break;
case FETCH_L:
++pstacktop;
*pstacktop = parg[11];
break;
case CONST_PI:
++pstacktop;
*pstacktop = PI;
break;
case CONST_D2R:
++pstacktop;
*pstacktop = PI/180.;
break;
case CONST_R2D:
++pstacktop;
*pstacktop = 180./PI;
break;
case ADD:
--pstacktop;
*pstacktop = *pstacktop + *(pstacktop+1);
break;
case SUB:
--pstacktop;
*pstacktop = *pstacktop - *(pstacktop+1);
break;
case MULT:
--pstacktop;
*pstacktop = *pstacktop * *(pstacktop+1);
break;
case DIV:
--pstacktop;
if (*(pstacktop+1) == 0) /* can't divide by zero */
return(-1);
*pstacktop = *pstacktop / *(pstacktop+1);
break;
case COND_IF:
/* if false condition then skip true expression */
if (*pstacktop == 0.0) {
/* skip to matching COND_ELSE */
for (got_if=1; got_if>0 && *(post+1) != END_STACK; ++post) {
if (*(post+1) == CONSTANT ) post+=8;
else if (*(post+1) == COND_IF ) got_if++;
else if (*(post+1) == COND_ELSE) got_if--;
}
}
/* remove condition from stack top */
--pstacktop;
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) {
if (*(post+1) == CONSTANT ) post+=8;
else if (*(post+1) == COND_IF ) got_if++;
else if (*(post+1) == COND_END) got_if--;
}
break;
case COND_END:
break;
case ABS_VAL:
if (*pstacktop < 0) *pstacktop = -*pstacktop;
break;
case UNARY_NEG:
*pstacktop = -1* (*pstacktop);
break;
case SQU_RT:
if (*pstacktop < 0) return(-1); /* undefined */
*pstacktop = sqrt(*pstacktop);
break;
case EXP:
*pstacktop = exp(*pstacktop);
break;
case LOG_10:
*pstacktop = log10(*pstacktop);
break;
case LOG_E:
*pstacktop = log(*pstacktop);
break;
case RANDOM:
++pstacktop;
*pstacktop = local_random();
break;
case EXPON:
--pstacktop;
if (*pstacktop == 0) break;
if (*pstacktop < 0){
temp1 = (int) *(pstacktop+1);
/* is exponent an integer */
if ((*(pstacktop+1) - (double)temp1) != 0) return (-1);
*pstacktop = exp(*(pstacktop+1) * log(-*pstacktop));
/* is value negative */
if ((temp1 % 2) > 0) *pstacktop = -*pstacktop;
}else{
*pstacktop = exp(*(pstacktop+1) * log(*pstacktop));
}
break;
case MODULO:
--pstacktop;
itop = (int)*pstacktop;
inexttop = (int)*(pstacktop+1);
if (inexttop == 0)
return(-1);
*pstacktop = itop % inexttop;
break;
case REL_OR:
--pstacktop;
*pstacktop = (*pstacktop || *(pstacktop+1));
break;
case REL_AND:
--pstacktop;
*pstacktop = (*pstacktop && *(pstacktop+1));
break;
case BIT_OR:
/* force double values into integers and or them */
itop = (int)*pstacktop;
inexttop = (int)*(pstacktop-1);
--pstacktop;
*pstacktop = (inexttop | itop);
break;
case BIT_AND:
/* force double values into integers and and them */
itop = (int)*pstacktop;
inexttop = (int)*(pstacktop-1);
--pstacktop;
*pstacktop = (inexttop & itop);
break;
case BIT_EXCL_OR:
/*force double values to integers to exclusive or them*/
itop = (int)*pstacktop;
inexttop = (int)*(pstacktop-1);
--pstacktop;
*pstacktop = (inexttop ^ itop);
break;
case GR_OR_EQ:
--pstacktop;
*pstacktop = *pstacktop >= *(pstacktop+1);
break;
case GR_THAN:
--pstacktop;
*pstacktop = *pstacktop > *(pstacktop+1);
break;
case LESS_OR_EQ:
--pstacktop;
*pstacktop = *pstacktop <= *(pstacktop+1);
break;
case LESS_THAN:
--pstacktop;
*pstacktop = *pstacktop < *(pstacktop+1);
break;
case NOT_EQ:
--pstacktop;
*pstacktop = *pstacktop != *(pstacktop+1);
break;
case EQUAL:
--pstacktop;
*pstacktop = (*pstacktop == *(pstacktop+1));
break;
case RIGHT_SHIFT:
itop = (int)*pstacktop;
inexttop = (int)*(pstacktop-1);
--pstacktop;
*pstacktop = (inexttop >> itop);
break;
case LEFT_SHIFT:
itop = (int)*pstacktop;
inexttop = (int)*(pstacktop-1);
--pstacktop;
*pstacktop = (inexttop << itop);
break;
case MAX:
--pstacktop;
if (*pstacktop < *(pstacktop+1))
*pstacktop = *(pstacktop+1);
break;
case MIN:
--pstacktop;
if (*pstacktop > *(pstacktop+1))
*pstacktop = *(pstacktop+1);
break;
case ACOS:
*pstacktop = acos(*pstacktop);
break;
case ASIN:
*pstacktop = asin(*pstacktop);
break;
case ATAN:
*pstacktop = atan(*pstacktop);
break;
case ATAN2:
--pstacktop;
*pstacktop = atan2(*(pstacktop+1), *pstacktop);
break;
case COS:
*pstacktop = cos(*pstacktop);
break;
case SIN:
*pstacktop = sin(*pstacktop);
break;
case TAN:
*pstacktop = tan(*pstacktop);
break;
case COSH:
*pstacktop = cosh(*pstacktop);
break;
case SINH:
*pstacktop = sinh(*pstacktop);
break;
case TANH:
*pstacktop = tanh(*pstacktop);
break;
case CEIL:
*pstacktop = ceil(*pstacktop);
break;
case FLOOR:
*pstacktop = floor(*pstacktop);
break;
case NINT:
*pstacktop = (double)(long)((*pstacktop) >= 0 ? (*pstacktop)+0.5 : (*pstacktop)-0.5);
break;
case REL_NOT:
*pstacktop = ((*pstacktop)?0:1);
break;
case BIT_NOT:
itop = (int)*pstacktop;
*pstacktop = ~itop;
break;
case CONSTANT:
++pstacktop;
++post;
if ( post == NULL ) {
++post;
printf("%.7s bad constant in expression\n",post);
break;
}
memcpy((void *)pstacktop,post,8);
post+=7;
break;
default:
printf("%d bad expression element\n",*post);
break;
}
/* move ahead in postfix expression */
++post;
double stack[CALCPERFORM_STACK]; /* zero'th entry not used */
double *ptop; /* stack pointer */
double top; /* value from top of stack */
int itop; /* integer from top of stack */
/* initialize */
ptop = stack;
if(*pinst == END_EXPRESSION) return -1;
/* RPN evaluation loop */
while (*pinst != END_EXPRESSION){
switch (*pinst){
case LITERAL:
++ptop;
++pinst;
memcpy((void *)ptop, pinst, sizeof(double));
pinst += sizeof(double) - 1;
break;
case FETCH_A:
case FETCH_B:
case FETCH_C:
case FETCH_D:
case FETCH_E:
case FETCH_F:
case FETCH_G:
case FETCH_H:
case FETCH_I:
case FETCH_J:
case FETCH_K:
case FETCH_L:
*++ptop = parg[*pinst - FETCH_A];
break;
case STORE_A:
case STORE_B:
case STORE_C:
case STORE_D:
case STORE_E:
case STORE_F:
case STORE_G:
case STORE_H:
case STORE_I:
case STORE_J:
case STORE_K:
case STORE_L:
parg[*pinst - STORE_A] = *ptop--;
break;
case CONST_PI:
*++ptop = PI;
break;
case CONST_D2R:
*++ptop = PI/180.;
break;
case CONST_R2D:
*++ptop = 180./PI;
break;
case UNARY_NEG:
*ptop = - *ptop;
break;
case ADD:
top = *ptop--;
*ptop += top;
break;
case SUB:
top = *ptop--;
*ptop -= top;
break;
case MULT:
top = *ptop--;
*ptop *= top;
break;
case DIV:
top = *ptop--;
*ptop /= top;
break;
case MODULO:
top = *ptop--;
*ptop = fmod(*ptop, top);
break;
case POWER:
top = *ptop--;
*ptop = pow(*ptop, top);
break;
case ABS_VAL:
if (*ptop < 0.0) *ptop = - *ptop;
break;
case EXP:
*ptop = exp(*ptop);
break;
case LOG_10:
*ptop = log10(*ptop);
break;
case LOG_E:
*ptop = log(*ptop);
break;
case MAX:
top = *ptop--;
if (*ptop < top || isnan(top))
*ptop = top;
break;
case MIN:
top = *ptop--;
if (*ptop > top || isnan(top))
*ptop = top;
break;
case SQU_RT:
*ptop = sqrt(*ptop);
break;
case ACOS:
*ptop = acos(*ptop);
break;
case ASIN:
*ptop = asin(*ptop);
break;
case ATAN:
*ptop = atan(*ptop);
break;
case ATAN2:
top = *ptop--;
*ptop = atan2(top, *ptop); /* Ouch!: Args backwards! */
break;
case COS:
*ptop = cos(*ptop);
break;
case SIN:
*ptop = sin(*ptop);
break;
case TAN:
*ptop = tan(*ptop);
break;
case COSH:
*ptop = cosh(*ptop);
break;
case SINH:
*ptop = sinh(*ptop);
break;
case TANH:
*ptop = tanh(*ptop);
break;
case CEIL:
*ptop = ceil(*ptop);
break;
case FLOOR:
*ptop = floor(*ptop);
break;
case FINITE:
*ptop = finite(*ptop);
break;
case ISINF:
*ptop = isinf(*ptop);
break;
case ISNAN:
*ptop = isnan(*ptop);
break;
case NINT:
top = *ptop;
*ptop = (double)(long)(top >= 0 ? top + 0.5 : top - 0.5);
break;
case RANDOM:
*++ptop = calcRandom();
break;
case REL_OR:
top = *ptop--;
*ptop = *ptop || top;
break;
case REL_AND:
top = *ptop--;
*ptop = *ptop && top;
break;
case REL_NOT:
*ptop = ! *ptop;
break;
case BIT_OR:
itop = (int) *ptop--;
*ptop = (int) *ptop | itop;
break;
case BIT_AND:
itop = (int) *ptop--;
*ptop = (int) *ptop & itop;
break;
case BIT_EXCL_OR:
itop = (int) *ptop--;
*ptop = (int) *ptop ^ itop;
break;
case BIT_NOT:
itop = (int) *ptop;
*ptop = ~itop;
break;
case RIGHT_SHIFT:
itop = (int) *ptop--;
*ptop = (int) *ptop >> itop;
break;
case LEFT_SHIFT:
itop = (int) *ptop--;
*ptop = (int) *ptop << itop;
break;
case NOT_EQ:
top = *ptop--;
*ptop = *ptop != top;
break;
case LESS_THAN:
top = *ptop--;
*ptop = *ptop < top;
break;
case LESS_OR_EQ:
top = *ptop--;
*ptop = *ptop <= top;
break;
case EQUAL:
top = *ptop--;
*ptop = *ptop == top;
break;
case GR_OR_EQ:
top = *ptop--;
*ptop = *ptop >= top;
break;
case GR_THAN:
top = *ptop--;
*ptop = *ptop > top;
break;
case COND_IF:
if (*ptop-- == 0.0 &&
cond_search(&pinst, COND_ELSE)) return -1;
break;
case COND_ELSE:
if (cond_search(&pinst, COND_END)) return -1;
break;
case COND_END:
break;
default:
errlogPrintf("calcPerform: Bad Opcode %d at %p\n",*pinst, pinst);
return -1;
}
/* if everything is peachy,the stack should end at its first position */
if (++top == pstacktop)
*presult = *pstacktop;
else
return(-1);
return(((isnan(*presult)||isinf(*presult)) ? -1 : 0));
/* Advance to next opcode */
++pinst;
}
/* The stack should now have one item on it, the expression value */
if (ptop != stack + 1)
return -1;
*presult = *ptop;
return (isnan(*presult) || isinf(*presult)) ? -1 : 0; /* FIXME */
}
/*
* RAND
*
* generates a random number between 0 and 1 using the
epicsShareFunc long
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) {
switch (op) {
case LITERAL:
pinst += sizeof(double);
break;
case FETCH_A:
case FETCH_B:
case FETCH_C:
case FETCH_D:
case FETCH_E:
case FETCH_F:
case FETCH_G:
case FETCH_H:
case FETCH_I:
case FETCH_J:
case FETCH_K:
case FETCH_L:
/* Don't claim to use an arg we already stored to */
inputs |= (1 << (op - FETCH_A)) & ~stores;
break;
case STORE_A:
case STORE_B:
case STORE_C:
case STORE_D:
case STORE_E:
case STORE_F:
case STORE_G:
case STORE_H:
case STORE_I:
case STORE_J:
case STORE_K:
case STORE_L:
stores |= (1 << (op - STORE_A));
break;
default:
break;
}
pinst++;
}
if (pinputs) *pinputs = inputs;
if (pstores) *pstores = stores;
return 0;
}
/* Generate a random number between 0 and 1 using the algorithm
* seed = (multy * seed) + addy Random Number Generator by Knuth
* SemiNumerical Algorithms
* Chapter 1
@@ -464,14 +405,34 @@ printf ("*FINISHED*\n");
static unsigned short seed = 0xa3bf;
static unsigned short multy = 191 * 8 + 5; /* 191 % 8 == 5 */
static unsigned short addy = 0x3141;
static double local_random()
static double calcRandom()
{
double randy;
seed = (seed * multy) + addy;
/* random number */
seed = (seed * multy) + addy;
randy = (float) seed / 65535.0;
/* between 0 - 1 */
return(randy);
/* between 0 - 1 */
return (double) seed / 65535.0;
}
/* Search the instruction stream for a matching operator, skipping any
* other conditional instructions found
*/
static int cond_search(const char **ppinst, int match)
{
const char *pinst = *ppinst + 1;
int count = 1;
int op;
while ((op = *pinst) != END_EXPRESSION) {
if (op == match && --count == 0) {
*ppinst = pinst;
return 0;
} else if (op == COND_IF)
count++;
else if (op == LITERAL)
pinst += sizeof(double);
pinst++;
}
return 1;
}
+497 -482
View File
File diff suppressed because it is too large Load Diff
+50 -4
View File
@@ -16,15 +16,61 @@
#define INCpostfixh
#include "shareLib.h"
#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 MAX_INFIX_SIZE 100
#define MAX_POSTFIX_SIZE INFIX_TO_POSTFIX_SIZE(MAX_INFIX_SIZE)
/* Error numbers from postfix */
#define CALC_ERR_NONE 0 /* No error */
#define CALC_ERR_TOOMANY 1 /* Too many results returned */
#define CALC_ERR_BAD_LITERAL 2 /* Bad numeric literal */
#define CALC_ERR_BAD_ASSIGNMENT 3 /* Bad assignment target */
#define CALC_ERR_BAD_SEPERATOR 4 /* Comma without parentheses */
#define CALC_ERR_PAREN_NOT_OPEN 5 /* Close parenthesis without open */
#define CALC_ERR_PAREN_OPEN 6 /* Open parenthesis at end of expression */
#define CALC_ERR_CONDITIONAL 7 /* Unbalanced conditional ?: operators */
#define CALC_ERR_INCOMPLETE 8 /* Incomplete expression, operand missing */
#define CALC_ERR_UNDERFLOW 9 /* Runtime stack would underflow */
#define CALC_ERR_OVERFLOW 10 /* Runtime stack would overflow */
#define CALC_ERR_SYNTAX 11 /* Syntax error */
#define CALC_ERR_NULL_ARG 12 /* NULL or empty input argument */
#define CALC_ERR_INTERNAL 13 /* Internal error, bad element type */
/* Changes in the above errors must also be made in calcErrorStr() */
#ifdef __cplusplus
extern "C" {
#endif
epicsShareFunc long epicsShareAPI
postfix (const char *pinfix, char *ppostfix, short *perror);
epicsShareFunc long
postfix(const char *pinfix, char *ppostfix, short *perror);
epicsShareFunc long epicsShareAPI
calcPerform(double *parg, double *presult, char *post);
epicsShareFunc long
calcPerform(double *parg, double *presult, const char *ppostfix);
epicsShareFunc long
calcArgUsage(const char *ppostfix, unsigned long *pinputs, unsigned long *pstores);
epicsShareFunc const char *
calcErrorStr(short error);
epicsShareFunc void
calcExprDump(const char *pinst);
#ifdef __cplusplus
}
+82 -81
View File
@@ -12,90 +12,91 @@
* 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.
*/
#ifndef INCpostfixPvth
#define INCpostfixPvth
#include "shareLib.h"
/* defines for element table */
#define BAD_EXPRESSION 0
#define FETCH_A 1
#define FETCH_B 2
#define FETCH_C 3
#define FETCH_D 4
#define FETCH_E 5
#define FETCH_F 6
#define FETCH_G 7
#define FETCH_H 8
#define FETCH_I 9
#define FETCH_J 10
#define FETCH_K 11
#define FETCH_L 12
#define ACOS 13
#define ASIN 14
#define ATAN 15
#define COS 16
#define COSH 17
#define SIN 18
#define STORE_A 19
#define STORE_B 20
#define STORE_C 21
#define STORE_D 22
#define STORE_E 23
#define STORE_F 24
#define STORE_G 25
#define STORE_H 26
#define STORE_I 27
#define STORE_J 28
#define STORE_K 29
#define STORE_L 30
#define RIGHT_SHIFT 31
#define LEFT_SHIFT 32
#define SINH 33
#define TAN 34
#define TANH 35
#define LOG_2 36
#define COND_ELSE 37
#define ABS_VAL 38
#define UNARY_NEG 39
#define SQU_RT 40
#define EXP 41
#define CEIL 42
#define FLOOR 43
#define LOG_10 44
#define LOG_E 45
#define RANDOM 46
#define ADD 47
#define SUB 48
#define MULT 49
#define DIV 50
#define EXPON 51
#define MODULO 52
#define BIT_OR 53
#define BIT_AND 54
#define BIT_EXCL_OR 55
#define GR_OR_EQ 56
#define GR_THAN 57
#define LESS_OR_EQ 58
#define LESS_THAN 59
#define NOT_EQ 60
#define EQUAL 61
#define REL_OR 62
#define REL_AND 63
#define REL_NOT 64
#define BIT_NOT 65
#define PAREN 66
#define MAX 67
#define MIN 68
#define COMMA 69
#define COND_IF 70
#define COND_END 71
#define CONSTANT 72
#define CONST_PI 73
#define CONST_D2R 74
#define CONST_R2D 75
#define NINT 76
#define ATAN2 77
#define END_STACK 127
/* RPN opcodes */
typedef enum {
END_EXPRESSION = 0,
/* Operands */
LITERAL,
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 */
STORE_A, STORE_B, STORE_C, STORE_D, STORE_E, STORE_F,
STORE_G, STORE_H, STORE_I, STORE_J, STORE_K, STORE_L,
/* Trigonometry Constants */
CONST_PI,
CONST_D2R,
CONST_R2D,
/* Arithmetic */
UNARY_NEG,
ADD,
SUB,
MULT,
DIV,
MODULO,
POWER,
/* Algebraic */
ABS_VAL,
EXP,
LOG_10,
LOG_E,
MAX,
MIN,
SQU_RT,
/* Trigonometric */
ACOS,
ASIN,
ATAN,
ATAN2,
COS,
COSH,
SIN,
SINH,
TAN,
TANH,
/* Numeric */
CEIL,
FLOOR,
FINITE,
ISINF,
ISNAN,
NINT,
RANDOM,
/* Boolean */
REL_OR,
REL_AND,
REL_NOT,
/* Bitwise */
BIT_OR,
BIT_AND,
BIT_EXCL_OR,
BIT_NOT,
RIGHT_SHIFT,
LEFT_SHIFT,
/* Relationals */
NOT_EQ,
LESS_THAN,
LESS_OR_EQ,
EQUAL,
GR_OR_EQ,
GR_THAN,
/* Conditional */
COND_IF,
COND_ELSE,
COND_END,
/* Misc */
NOT_GENERATED
} rpn_opcode;
#endif /* INCpostfixPvth */