extern int WQL_Eval()

in Unix/wql/wql.c [498:775]


extern int WQL_Eval(
    const WQL* wql, 
    WQL_Lookup lookup,
    void* data)
{
    size_t i;
    WQL_Symbol symbols[WQL_MAX_SYMBOLS];
    size_t nsymbols = 0;

    if (!wql || !wql->className || !lookup)
        return -1;

    /* Return success if there is no WHERE clause */
    if (wql->nsymbols == 0)
        return 0;

    /* Perform postfix evaluation */
    for (i = 0; i < wql->nsymbols; i++)
    {
        const WQL_Symbol* sym = &wql->symbols[i];
        WQL_Type type = sym->type;

        if (nsymbols >= WQL_MAX_SYMBOLS)
            return -1;

        switch (type)
        {
            case WQL_TYPE_AND:
            case WQL_TYPE_OR:
            {
                if (nsymbols < 2)
                    return -1;

                {
#if defined(hpux)
#pragma diag_suppress 2549
#endif
                    WQL_Symbol s2 = symbols[--nsymbols];
                    WQL_Symbol s1 = symbols[--nsymbols];
#if defined(hpux)
#pragma diag_default 2549
#endif
                    WQL_Symbol s;
                    int f;

                    memset(&s, '\0', sizeof(s));

                    if (s1.type != WQL_TYPE_BOOLEAN)
                        return -1;
                    if (s2.type != WQL_TYPE_BOOLEAN)
                        return -1;

                    s.type = WQL_TYPE_BOOLEAN;

                    if (type == WQL_TYPE_OR)
                        f = (s1.value.boolean || s2.value.boolean);
                    else
                        f = (s1.value.boolean && s2.value.boolean);

                    s.value.boolean = f ? 1 : 0;
                    symbols[nsymbols++] = s;
                }

                break;
            }
            case WQL_TYPE_NOT:
            {
                if (nsymbols < 1)
                    return -1;
                {
                    WQL_Symbol s1 = symbols[--nsymbols];
                    WQL_Symbol s;

                    memset(&s, '\0', sizeof(s));

                    if (s1.type != WQL_TYPE_BOOLEAN)
                        return -1;

                    s.type = WQL_TYPE_BOOLEAN;
                    s.value.boolean = (!s1.value.boolean) ? 1 : 0;
                    symbols[nsymbols++] = s;
                }

                break;
            }
            case WQL_TYPE_EQ:
            case WQL_TYPE_NE:
            case WQL_TYPE_LT:
            case WQL_TYPE_LE:
            case WQL_TYPE_GT:
            case WQL_TYPE_GE:
            case WQL_TYPE_LIKE:
            {
                if (nsymbols < 2)
                    return -1;
                {
                    WQL_Symbol s2 = symbols[--nsymbols];
                    WQL_Symbol s1 = symbols[--nsymbols];
                    WQL_Symbol s;
                    int r;
                    int f;

                    memset(&s, '\0', sizeof(s));

                    /* This type only returned by _ValidateLookup() */
                    if (s2.type == WQL_TYPE_ANY || s1.type == WQL_TYPE_ANY)
                    {
                        return 0;
                    }

                    /* If either operand is null */
                    if (s1.type == WQL_TYPE_NULL || s2.type == WQL_TYPE_NULL)
                    {
                        /* Set flag non-zero if both operands are null */
                        int bothNull =
                            (s1.type==WQL_TYPE_NULL && s2.type==WQL_TYPE_NULL);

                        if (type == WQL_TYPE_EQ || type == WQL_TYPE_LIKE)
                        {
                            s.type = WQL_TYPE_BOOLEAN;
                            s.value.boolean = bothNull ? 1 : 0;
                            symbols[nsymbols++] = s;
                            break;
                        }
                        else if (type == WQL_TYPE_NE)
                        {
                            s.type = WQL_TYPE_BOOLEAN;
                            s.value.boolean = bothNull ? 0 : 1;
                            symbols[nsymbols++] = s;
                            break;
                        }
                        else
                            return -1;
                    }
                    else
                    {

                        if (type == WQL_TYPE_LIKE)
                            r = _CompareLike(&s1, &s2);
                        else
                        {
                            WQL_Symbol lhs = s1;
                            WQL_Symbol rhs = s2;

                            if (lhs.type != rhs.type)
                            {
                                if (_FixupType(&lhs, &rhs) != 0)
                                    return -1;
                            }

                            r = _Compare(&lhs, &rhs);
                        }

                        switch (type)
                        {
                            case WQL_TYPE_EQ:
                            case WQL_TYPE_LIKE:
                                f = (r == 0);
                                break;
                            case WQL_TYPE_NE:
                                f = (r != 0);
                                break;
                            case WQL_TYPE_LT:
                                f = (r < 0);
                                break;
                            case WQL_TYPE_LE:
                                f = (r <= 0);
                                break;
                            case WQL_TYPE_GT:
                                f = (r > 0);
                                break;
                            case WQL_TYPE_GE:
                                f = (r >= 0);
                                break;
                            default:
                                f = 0;
                                break;
                        }

                        s.type = WQL_TYPE_BOOLEAN;
                        s.value.boolean = f ? 1 : 0;
                        symbols[nsymbols++] = s;
                    }
                }
                break;
            }
            case WQL_TYPE_IDENTIFIER:
            {
                WQL_Symbol tmp;

                memset(&tmp, 0, sizeof(WQL_Symbol));

                if ((*lookup)(
                    sym->value.string, 
                    sym->value.embeddedClassName, 
                    sym->value.embeddedPropertyName, 
                    &tmp, 
                    wql->batch, 
                    data) != 0)
                {
                    return -1;
                }

                if (tmp.type != WQL_TYPE_BOOLEAN &&
                    tmp.type != WQL_TYPE_INTEGER &&
                    tmp.type != WQL_TYPE_REAL &&
                    tmp.type != WQL_TYPE_STRING &&
                    tmp.type != WQL_TYPE_NULL &&
                    tmp.type != WQL_TYPE_ANY)
                {
                    return -1;
                }
                symbols[nsymbols++] = tmp;
                break;
            }
            case WQL_TYPE_BOOLEAN:
            case WQL_TYPE_INTEGER:
            case WQL_TYPE_REAL:
            case WQL_TYPE_STRING:
            case WQL_TYPE_NULL:
            case WQL_TYPE_ANY:
                symbols[nsymbols++] = *sym;
                break;

            case WQL_TYPE_ISA:
            {
                WQL_Symbol s2;
                WQL_Symbol s1;

                if (nsymbols < 2)
                    return -1;

                s2 = symbols[--nsymbols];
                s1 = symbols[--nsymbols];

                if (s1.type != WQL_TYPE_STRING)
                    return -1;

                if (s2.type != WQL_TYPE_STRING)
                    return -1;

                /* Ask lookup() to perform ISA operation */
                {
                    WQL_Symbol tmp = s2;

                    if ((*lookup)(
                        s1.value.string, /* Embedded property name */
                        s2.value.string, /* Embedded class name */
                        NULL,
                        &tmp, 
                        wql->batch, 
                        data) != 0)
                    {
                        return -1;
                    }

                    symbols[nsymbols++] = tmp;
                }
                break;
            }
        }
    }

    /* There should be exactly 1 symbol left on stack */
    if (nsymbols != 1)
        return -1;

    /* There should be exactly 1 symbol left on stack */
    /* Final token on stack should be boolean */
    if (symbols[0].type != WQL_TYPE_BOOLEAN)
        return -1;

    /* Return '0' for equal, '1' for not-equal */
    if (symbols[0].value.boolean)
        return 0;
    else
        return 1;
}