#ifdef __cplusplus
extern "C"
{
#endif


#include <windows.h>
#include <stdio.h>
#include "postfix.h"

// function declarations
void ProcessExpression(void);
void ProcessOR(void);
void ProcessAND(void);
void ProcessBITWISEOR(void);
void ProcessBITWISEXOR(void);
void ProcessBITWISEAND(void);
void ProcessEQUALITY(void);
void ProcessRELATIONAL(void);
void ProcessADDITION(void);
void ProcessMULTIPLICATION(void);
void ProcessFactor(void);
void GetToken(char *String);
BOOL StringToValue(char *, int *);
void Trim(char *);
void OutputPostfix(int);

// global variables
char  TokenString[MAXTOKENLEN + 1];
int   PostfixOutputBuffer[1024];
int TypeOfToken;
int TokenPos;
int PostfixPtr;
int MaxParamID;
int ErrorType;
int PostfixStack[sizeof(PostfixOutputBuffer) / 2];
int *StackPtr;

extern DWORD CmdArg[4];


struct  TOKENS
{
    char *TokenString;
    int TypeOfToken;
}Tokens[MAXTOKENTYPES] =

// tokens are arranged from longest token string to shortest token string
{
    {"<>", NOTEQUAL},
    {"!=", NOTEQUAL},
    {"<=", LESSEQUAL},
    {">=", GREATEREQUAL},
    {"==", EQUAL},
    {"&&", AND},
    {"AND",AND},
    {"||", OR},
    {"OR", OR},
    {"&",  BITWISEAND},
    {"|",  BITWISEOR},
    {"^",  BITWISEXOR},
    {"*",  MULT},
    {"/",  DIV},
    {"%",  MOD},
    {"+",  ADD},
    {"-",  SUB},
    {"=",  EQUAL},
    {"<",  LESS},
    {">",  GREATER},
    {"!",  NOT},
    {"~",  COMPL},
    {"(",  LPAREN},
    {")",  RPAREN}
};



/********************************************************************
    Convert expression string from Infix notation to Postfix notation.

    Order of precedence:
    High     Parenthesis
                    ()

                Unary operators
                    !           Logical NOT
                    -           Negation
                    ~           Complement
 *
                Arithmetic Operators
                    *, /, % Multiplication, Division, Modulus
                    +, -        Addition, Subtraction

                Relational operators (All relational operators have equal precedence unless otherwise noted)
                    <           Less than
                    <=          Less than or equal
                    >           Greater than
                    >=          Greater than or equal
                The following relational operators have a lower precedence than those listed above.
                    =, ==       Equal
                    !=, <>  Not equal

                Bitwise Operators
                    &           And
                    |           Or
                    ^           Xor

                Logic operators
                    &&          And
    Low         ||          Or

    Note: Spaces separating compound operators (!<space>=) will generate errors.

********************************************************************/

/***********************************************************
    On entry ExpString points to the string to be converted
    to postfix notation and MaxParamID max value to be used
    as a zero based index when looking up parameters.
    On exit Error will be set to the error value if an error
    occured while parsing the expression.
    The return value is -1 if successful, if an error occured
    the return value is the index into ExpString where the
    error occured.
    The Postfix expression is saved in the global variable
    PostfixOutputBuffer.
***********************************************************/
int InfixToPostfix(char *ExpString, int MaxParamID, int *Error)
{
    // clear ouput buffer
    memset(PostfixOutputBuffer, 0, sizeof(PostfixOutputBuffer));

    // initialize global variables
    PostfixPtr = 0;
    MaxParamID = MaxParamID;
    ErrorType = 0;
    TypeOfToken = STARTTOKEN;

    // initialize token scanner
    GetToken(ExpString);
    if (TypeOfToken == ENDTOKEN)
    {
        // no trigger expression specified
        return -1;
    }
    if (TypeOfToken != ERRORTOKEN)
    {
        // convert infix expression to postix notation
        ProcessExpression();
    }
    if (TypeOfToken != ERRORTOKEN && TypeOfToken != ENDTOKEN)
    {
        // entire expression was not processed, probably due to ambiguous operators
        ErrorType = AMBIGOPER;
    }
    if (ErrorType)
    {
        if (Error)
            *Error = ErrorType;
        return TokenPos;
    }
    // expression processed successfully
    return -1;
}

// Process operators in reverse order of precedence
void ProcessExpression(void)
{
    ProcessOR();
}

/***********************************************************
    Process terms seperated by the logical OR operator
***********************************************************/
void ProcessOR(void)
{
    int OpType = 0;

    // process term
    ProcessAND();

    while (TypeOfToken == OR)
    {
        OpType = TypeOfToken;
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            break;
        ProcessAND();
        OutputPostfix(OpType);
    }
}

/***********************************************************
    Process terms seperated by the logical AND operator
***********************************************************/
void ProcessAND(void)
{
    int OpType;

    ProcessBITWISEXOR();

    while (TypeOfToken == AND)
    {
        OpType = TypeOfToken;
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            break;
        ProcessBITWISEXOR();
        OutputPostfix(OpType);
    }
}

/***********************************************************
    Process terms seperated by the Bitwise XOR operator
***********************************************************/
void ProcessBITWISEXOR(void)
{
    int OpType;

    ProcessBITWISEOR();

    while (TypeOfToken == BITWISEAND)
    {
        OpType = TypeOfToken;
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            break;
        ProcessBITWISEOR();
        OutputPostfix(OpType);
    }
}

/***********************************************************
    Process terms seperated by the Bitwise OR operator
***********************************************************/
void ProcessBITWISEOR(void)
{
    int OpType;

    ProcessBITWISEAND();

    while (TypeOfToken == BITWISEXOR)
    {
        OpType = TypeOfToken;
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            break;
        ProcessBITWISEAND();
        OutputPostfix(OpType);
    }
}

/***********************************************************
    Process terms seperated by the Bitwise AND operator
***********************************************************/
void ProcessBITWISEAND(void)
{
    int OpType;

    ProcessEQUALITY();

    while (TypeOfToken == BITWISEOR)
    {
        OpType = TypeOfToken;
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            break;
        ProcessEQUALITY();
        OutputPostfix(OpType);
    }
}

/***********************************************************
    Process terms seperated by the EQUAL or NOT EQUAL operators
***********************************************************/
void ProcessEQUALITY(void)
{
    int OpType;

    ProcessRELATIONAL();

    // check for equality operator
    while (TypeOfToken == EQUAL || TypeOfToken == NOTEQUAL)
    {
        // remember relational operator
        OpType = TypeOfToken;

        // get next token and process any sub-expression
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            return;
        ProcessRELATIONAL();

        // output relational operator
        OutputPostfix(OpType);
    }
}

/***********************************************************
    Process terms seperated by the RELATIONAL operators
***********************************************************/
void ProcessRELATIONAL(void)
{
    int OpType;

    ProcessADDITION();

    // check for relational operator
    while (TypeOfToken >= LESS && TypeOfToken <= GREATEREQUAL)
    {
        // remember relational operator
        OpType = TypeOfToken;

        // get next token and process any sub-expression
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            return;
        ProcessADDITION();

        // output relational operator
        OutputPostfix(OpType);
    }
}

/***********************************************************
    Process terms seperated by the addition or subtraction operators
***********************************************************/
void ProcessADDITION(void)
{
    int OpType;

    ProcessMULTIPLICATION();

    while (TypeOfToken == ADD || TypeOfToken == SUB)
    {
        OpType = TypeOfToken;
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            break;
        ProcessMULTIPLICATION();
        OutputPostfix(OpType);
    }
}

/***********************************************************
    Process terms seperated by the multiplication or division operators
***********************************************************/
void ProcessMULTIPLICATION(void)
{
    int OpType;

    ProcessFactor();

    while (TypeOfToken == MULT || TypeOfToken == DIV || TypeOfToken == MOD)
    {
        OpType = TypeOfToken;
        GetToken(NULL);
        if (TypeOfToken == ERRORTOKEN)
            break;
        ProcessFactor();
        OutputPostfix(OpType);
    }
}

/***********************************************************
    A factor is an indentifier, number, unary   operator, or
    parenthesized sub expression.
***********************************************************/
void ProcessFactor(void)
{
    switch (TypeOfToken)
    {
        case STS_IDENTIFIER:
        case LEN_IDENTIFIER:
        case SD_IDENTIFIER:
        case NODE_IDENTIFIER:
        case FC_IDENTIFIER:
        case DSAP_IDENTIFIER:
        case SSAP_IDENTIFIER:
        case GAP_IDENTIFIER:
        case DATA_BYTE_IDENTIFIER:
        case DATA_WORD_IDENTIFIER:
        case CMD_ARG_IDENTIFIER:
        case NUMBER:
            OutputPostfix(TypeOfToken);
            GetToken(NULL);
            break;
        case NOT:
            GetToken(NULL);
            if (TypeOfToken != ERRORTOKEN)
            {
                ProcessFactor();
                OutputPostfix(NOT);
            }
            break;
        case NEG:
            GetToken(NULL);
            if (TypeOfToken != ERRORTOKEN)
            {
                ProcessFactor();
                OutputPostfix(NEG);
            }
            break;
        case COMPL:
            GetToken(NULL);
            if (TypeOfToken != ERRORTOKEN)
            {
                ProcessFactor();
                OutputPostfix(COMPL);
            }
            break;
        case LPAREN:
            GetToken(NULL);
            if (TypeOfToken == ERRORTOKEN)
                break;
            ProcessExpression();
            if (TypeOfToken == ERRORTOKEN)
                break;
            if (TypeOfToken != RPAREN)
            {
                // error - missing right parenthesis
                ErrorType = MISSINGPARENTH;
                TypeOfToken = ERRORTOKEN;
            }
            else
                GetToken(NULL);
            break;
        default:
            // unrecognized token type
            ErrorType = MISSINGPARAM;
            TypeOfToken = ERRORTOKEN;
            break;
    }
}

/***********************************************************
    Parse expression string into tokens.

    On return global variable TypeOfToken contains the type of
    token being returned. If token type is IDENTIFIER the
    global variable TokenString will contain the single
    character identifier. If token type is NUMBER the global
    variable TokenString will contain the ascii string for
    the number including the (-) sign if present.
***********************************************************/
void GetToken(char *String)
{
    int  Len;
    int  Type;
    int  Dummy;
    char *Ptr;
    char IdType;

    static char *StartOfString;
    static char *NextToken;

    if (String)
    {
        Ptr = String;
        StartOfString = String;
    }
    else
        Ptr = NextToken;

    // skip spaces
    while (*Ptr == ' ')
        Ptr++;
    if (*Ptr == 0)
    {
        // end of expression
        TypeOfToken = ENDTOKEN;
        return;
    }
    // check for an operator
    for (Type = 0; Type < MAXTOKENTYPES; Type++)
    {
        if (_strnicmp(Ptr, Tokens[Type].TokenString, strlen(Tokens[Type].TokenString)) == 0)
        {
            TokenPos = (int)(Ptr - StartOfString);
            if (Tokens[Type].TypeOfToken == SUB && isdigit(*(Ptr + 1)) &&
                ((TypeOfToken >= FIRSTOPERTOKEN && TypeOfToken <= LASTOPERTOKEN) ||
                TypeOfToken == STARTTOKEN))
            {
                // minus sign is preceeded by an operator and followed by a digit
                // assume it is the unary negate operator
                //which will be processed when checking for numeric values
                break;
            }
            if (Tokens[Type].TypeOfToken == SUB &&
                ((TypeOfToken >= FIRSTOPERTOKEN && TypeOfToken <= LASTOPERTOKEN) ||
                TypeOfToken == STARTTOKEN))
            {
                // minus sign is preceeded by an operator and not followed by a digit
                // assume the unary negation operator
                TypeOfToken = NEG;
                NextToken = Ptr + strlen(Tokens[Type].TokenString);
                return;
            }
            switch(Tokens[Type].TypeOfToken)
            {
                case LPAREN:
                    if (!(TypeOfToken >= FIRSTOPERTOKEN && TypeOfToken <= LASTOPERTOKEN) &&
                         TypeOfToken != STARTTOKEN && TypeOfToken != LPAREN)
                    {
                        ErrorType = MISSINGOPER;
                        TypeOfToken = ERRORTOKEN;
                        TokenPos--;
                        return;
                    }
                    break;
                case NOT:
                    if (TypeOfToken == RPAREN)
                    {
                        ErrorType = MISSINGOPER;
                        TypeOfToken = ERRORTOKEN;
                        TokenPos--;
                        return;
                    }
                    break;
                case COMPL:
                    if (TypeOfToken == RPAREN)
                    {
                        ErrorType = MISSINGOPER;
                        TypeOfToken = ERRORTOKEN;
                        TokenPos--;
                        return;
                    }
                    break;
                default:
                    if ((TypeOfToken >= FIRSTOPERTOKEN && TypeOfToken <= LASTOPERTOKEN) ||
                         TypeOfToken == LPAREN || TypeOfToken == STARTTOKEN)
                    {
                        ErrorType = MISSINGPARAM;
                        TypeOfToken = ERRORTOKEN;
                        TokenPos--;
                        return;
                    }
                    break;
            }
            TypeOfToken = Tokens[Type].TypeOfToken;
            NextToken = Ptr + strlen(Tokens[Type].TokenString);
            return;
        }
    }
    memset(TokenString, 0, sizeof(TokenString));

    if  (
            (*Ptr == STS_CHAR)          ||
            (*Ptr == LEN_CHAR)          ||
            (*Ptr == SD_CHAR)           ||
            (*Ptr == NODE_CHAR)         ||
            (*Ptr == FC_CHAR)           ||
            (*Ptr == DSAP_CHAR)         ||
            (*Ptr == SSAP_CHAR)         ||
            (*Ptr == GAP_CHAR)          ||
            (*Ptr == DATA_BYTE_CHAR)    ||
            (*Ptr == DATA_WORD_CHAR)    ||
            (*Ptr == CMD_ARG_CHAR)
        )
    {
        IdType = *Ptr++;

        Len = 1;
        if (*Ptr == '0' && ((*(Ptr + 1)) | 0x20) == 'x')
        {
            // value is hex
            // get length of hex string
            while (isalnum(*(Ptr + Len)))
                Len++;
            if (Len > 6 || sscanf((Ptr + 2), "%x", &Dummy) != 1)
            {
                // error occurred converting hex value
                ErrorType = INVALIDVALUE;
                TypeOfToken = ERRORTOKEN;
                TokenPos += Len - 1;
                return;
            }
            sprintf(TokenString,"%d", Dummy);
        }
        else
        {
            // value is decimal
            while (isdigit(*(Ptr + Len)))
                Len++;
            strncpy(TokenString, Ptr, Len);
            TokenPos = (int)(Ptr - StartOfString);
            if (!StringToValue(TokenString, &Dummy))
            {
                // invalid value
                ErrorType = INVALIDVALUE;
                TypeOfToken = ERRORTOKEN;
                TokenPos += Len - 1;
                return;
            }
        }

        if (TypeOfToken == NUMBER               ||
            TypeOfToken == STS_IDENTIFIER       ||
            TypeOfToken == LEN_IDENTIFIER       ||
            TypeOfToken == SD_IDENTIFIER        ||
            TypeOfToken == NODE_IDENTIFIER      ||
            TypeOfToken == FC_IDENTIFIER        ||
            TypeOfToken == DSAP_IDENTIFIER      ||
            TypeOfToken == SSAP_IDENTIFIER      ||
            TypeOfToken == GAP_IDENTIFIER       ||
            TypeOfToken == DATA_BYTE_IDENTIFIER ||
            TypeOfToken == DATA_WORD_IDENTIFIER ||
            TypeOfToken == CMD_ARG_IDENTIFIER   ||
            TypeOfToken == RPAREN)
        {
            // missing operator
            ErrorType = MISSINGOPER;
            TypeOfToken = ERRORTOKEN;
            TokenPos--;
            return;
        }
        switch ( IdType )
        {
        case STS_CHAR :
            TypeOfToken = STS_IDENTIFIER;
            break;

        case LEN_CHAR :
            TypeOfToken = LEN_IDENTIFIER;
            break;

        case SD_CHAR :
            TypeOfToken = SD_IDENTIFIER;
            break;

        case NODE_CHAR :
            TypeOfToken = NODE_IDENTIFIER;
            break;

        case FC_CHAR :
            TypeOfToken = FC_IDENTIFIER;
            break;

        case DSAP_CHAR :
            TypeOfToken = DSAP_IDENTIFIER;
            break;

        case SSAP_CHAR :
            TypeOfToken = SSAP_IDENTIFIER;
            break;

        case GAP_CHAR :
            TypeOfToken = GAP_IDENTIFIER;
            break;

        case DATA_BYTE_CHAR :
            TypeOfToken = DATA_BYTE_IDENTIFIER;
            break;

        case DATA_WORD_CHAR :
            TypeOfToken = DATA_WORD_IDENTIFIER;
            break;

        case CMD_ARG_CHAR :
            TypeOfToken = CMD_ARG_IDENTIFIER;
            break;
        }

        NextToken = Ptr + Len;
        return;
    }

    // check for numeric value
    else if (isdigit(*Ptr) || *Ptr == '-')
    {
        Len = 1;
        if (*Ptr == '0' && ((*(Ptr + 1)) | 0x20) == 'x')
        {
            // value is hex
            // get length of hex string
            while (isalnum(*(Ptr + Len)))
                Len++;
            if (Len > 6 || sscanf((Ptr + 2), "%x", &Dummy) != 1)
            {
                // error occurred converting hex value
                ErrorType = INVALIDVALUE;
                TypeOfToken = ERRORTOKEN;
                TokenPos += Len - 1;
                return;
            }
            sprintf(TokenString,"%d", Dummy);
        }
        else
        {
            // value is decimal
            while (isdigit(*(Ptr + Len)))
                Len++;
            strncpy(TokenString, Ptr, Len);
            TokenPos = (int)(Ptr - StartOfString);
            if (!StringToValue(TokenString, &Dummy))
            {
                // invalid value
                ErrorType = INVALIDVALUE;
                TypeOfToken = ERRORTOKEN;
                TokenPos += Len - 1;
                return;
            }
        }
        if  (
                TypeOfToken == NUMBER               ||
                TypeOfToken == STS_IDENTIFIER       ||
                TypeOfToken == LEN_IDENTIFIER       ||
                TypeOfToken == SD_IDENTIFIER        ||
                TypeOfToken == NODE_IDENTIFIER      ||
                TypeOfToken == FC_IDENTIFIER        ||
                TypeOfToken == DSAP_IDENTIFIER      ||
                TypeOfToken == SSAP_IDENTIFIER      ||
                TypeOfToken == GAP_IDENTIFIER       ||
                TypeOfToken == DATA_BYTE_IDENTIFIER ||
                TypeOfToken == DATA_WORD_IDENTIFIER ||
                TypeOfToken == CMD_ARG_IDENTIFIER   ||
                TypeOfToken == RPAREN
            )
        {
            // missing operator
            ErrorType = MISSINGOPER;
            TypeOfToken = ERRORTOKEN;
            TokenPos--;
            return;
        }
        // token is a number
        TypeOfToken = NUMBER;
        NextToken = Ptr + Len;
        return;
    }
    // unrecognized token
    ErrorType = INVALIDOPER;
    TypeOfToken = ERRORTOKEN;
    TokenPos = (int)(Ptr - StartOfString);
}

BOOL StringToValue(char *String, int * NewValue)
{
    Trim(String);
    if (strspn(String, "0123456789+-") == strlen(String) && strlen(String) > 0)
    {
        *NewValue = atoi(String);
        return TRUE;
    }
    // invalid entry
    return FALSE;
}

void Trim(char *String)
{
    int Index;

    Index = strspn(String, " ");
    _strrev(String);
    String[strlen(String) - Index] = 0;
    Index = strspn(String, " ");
    _strrev(String);
    String[strlen(String) - Index] = 0;
}

/***********************************************************
    Convert and output tokens to postfix buffer.

    If Type is IDENTIFIER the single character identifier
    contained in global variable TokenString is placed in the
    postfix buffer. If Type is NUMBER the value of Type
    (NUMBER) is placed in the postfix buffer followed by the
    integer value of the number string contained in global
    variable    TokenString low byte first. If Type is neither
    IDENTIFIER nor  NUMBER the value of Type is placed in the
    postfix buffer. This value represents the operator.
    See postfix.h for   operator definitions.
***********************************************************/
void OutputPostfix(int Type)
{
    switch (Type)
    {
        case NODE_IDENTIFIER:
        case DATA_BYTE_IDENTIFIER:
        case DATA_WORD_IDENTIFIER:
        case CMD_ARG_IDENTIFIER:
        case NUMBER:
            PostfixOutputBuffer[PostfixPtr++] = Type;
            PostfixOutputBuffer[PostfixPtr++] = atoi(TokenString);
            break;
        default:
            PostfixOutputBuffer[PostfixPtr++] = Type;
            break;
    }
}

// definition of Postfix stack macros
#define Push(i) (*(StackPtr++) = i)
#define Pop(i)  i = (*(--StackPtr))

/***********************************************************
    Solve the Postfix expression contained in the global
    variable    PostfixOutputBuffer and return the result.
***********************************************************/
int EvaluatePostfixExpression(BYTE Sts, BYTE Len, BYTE Sd, BYTE * pNode, BYTE * pFc, BYTE * pDSap, BYTE * pSSap, DWORD Gap, BYTE * pData)
{
    int   * Ptr;
    int     Operand1;
    int     Operand2;
    int     Ofs;
    int     Val;

    // reset stack pointer
    StackPtr = PostfixStack;
    Ptr      = PostfixOutputBuffer;
    if (*Ptr == 0)
    {
        // expression buffer is empty
        return TRUE;
    }
    while (*Ptr)
    {
        if (*Ptr == NUMBER)
        {
            Ptr++;
            Push(*Ptr++);
            continue;
        }
        else if (*Ptr == STS_IDENTIFIER )
        {
            Ptr++;
            Push(Sts);
            continue;
        }
        else if (*Ptr == LEN_IDENTIFIER )
        {
            Ptr++;
            Push(Len);
            continue;
        }
        else if (*Ptr == SD_IDENTIFIER )
        {
            Ptr++;
            Push(Sd);
            continue;
        }
        else if (*Ptr == GAP_IDENTIFIER )
        {
            Ptr++;
            Push(Gap);
            continue;
        }
        else if (*Ptr == NODE_IDENTIFIER )
        {
            Ptr++;
            if ( pNode!=NULL )
            {
                Push((pNode[*Ptr++])&0x7f);
            }
            else
            {
                Push(0x10000);
                Ptr++;
            }
            continue;
        }
        else if (*Ptr == FC_IDENTIFIER )
        {
            Ptr++;
            if ( pFc!=NULL )
            {
                Push(*pFc);
            }
            else
            {
                Push(0x10000);
            }

            continue;
        }
        else if (*Ptr == DSAP_IDENTIFIER )
        {
            Ptr++;
            if ( pDSap!=NULL )
            {
                Push(*pDSap);
            }
            else
            {
                Push(0x10000);
            }
            continue;
        }
        else if (*Ptr == SSAP_IDENTIFIER )
        {
            Ptr++;
            if ( pSSap!=NULL )
            {
                Push(*pSSap);
            }
            else
            {
                Push(0x10000);
            }
            continue;
        }
        else if (*Ptr == DATA_BYTE_IDENTIFIER)
        {
            Ptr++;
            Ofs = *Ptr++;

            if ( (Len>Ofs) && (pData!=NULL) )
            {
                Push(pData[Ofs]);
            }
            else
            {
                Push(0x10000);
            }


        }
        else if (*Ptr == DATA_WORD_IDENTIFIER)
        {
            Ptr++;
            Ofs = *Ptr++;

            if ( (Len>(Ofs+1)) && (pData!=NULL) )
            {
                Val  = pData[Ofs  ]<<8;
                Val |= pData[Ofs+1];
                Push(Val);
            }
            else
            {
                Push(0x10000);
                Ptr++;
            }
            continue;
        }
        else if (*Ptr == CMD_ARG_IDENTIFIER)
        {
            Ptr++;
            Push(CmdArg[*Ptr++]);
            continue;
        }
        else
        {
            // pop the required operands of the postfix stack and perform the indicated
            // operation and push the result back onto the stack
            switch (*Ptr)
            {
                case NOT:
                    Pop(Operand1);
                    Operand1 = !Operand1;
                    break;
                case NEG:
                    Pop(Operand1);
                    Operand1 = -Operand1;
                    break;
                case COMPL:
                    Pop(Operand1);
                    Operand1 = ~Operand1;
                    break;
                case AND:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 = Operand1 && Operand2;
                    break;
                case OR:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 = Operand1 || Operand2;
                    break;
                case BITWISEAND:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 &= Operand2;
                    break;
                case BITWISEOR:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 |= Operand2;
                    break;
                case BITWISEXOR:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 ^= Operand2;
                    break;
                case MULT:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 *= Operand2;
                    break;
                case DIV:
                    Pop(Operand2);
                    Pop(Operand1);

                    if ( Operand2!=0 )
                    {
                        Operand1 /= Operand2;
                    }
                    else
                    {
                        Operand1 = 0;
                    }
                    break;
                case MOD:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 %= Operand2;
                    break;
                case ADD:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 += Operand2;
                    break;
                case SUB:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 -= Operand2;
                    break;
                case EQUAL:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 = (Operand1 == Operand2);
                    break;
                case LESS:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 = (Operand1 < Operand2);
                    break;
                case GREATER:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 = (Operand1 > Operand2);
                    break;
                case LESSEQUAL:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 = (Operand1 <= Operand2);
                    break;
                case GREATEREQUAL:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 = (Operand1 >= Operand2);
                    break;
                case NOTEQUAL:
                    Pop(Operand2);
                    Pop(Operand1);
                    Operand1 = (Operand1 != Operand2);
                    break;
            }
            Push(Operand1);
            Ptr++;
        }
    }
    Pop(Operand1);
    return Operand1;
}

#ifdef __cplusplus
}
#endif