math.c

来自「NullSofts criptable install system2.28源代」· C语言 代码 · 共 1,549 行 · 第 1/4 页

C
1,549
字号
{
    char *buffer, *bp;
    if (item == NULL) return;
    int itemt = item->type & ITEMTYPE, oldtype = item->type & ITEMSUBTYPE;

    if (((itemt == IT_CONST) && (oldtype == type))
        || (itemt != IT_CONST)) return;

    switch (type)
    {
    case ITC_STRING:
        buffer = AllocString();
        ItemToString(buffer, item);
        item->param1 = (EIPARAM)  buffer;
        item->param2 = 0;
        break;
    case ITC_FLOAT:
        if (oldtype == ITC_INT)
            *((double *)&(item->param1)) = (double) *((__int64 *)&(item->param1));
        else
        {
            bp = buffer = (char*) item->param1;
            StringToItem(buffer, item, STI_FLOAT);
            dbgGlobalFree(bp);
        }
        break;
    case ITC_INT:
        if (oldtype == ITC_FLOAT)
            *((__int64 *)&(item->param1)) = (__int64) *((double *)&(item->param1));
        else
        {
            bp = buffer = (char*) item->param1;
            StringToItem(buffer, item, STI_INT);
            dbgGlobalFree(bp);
        }
        break;
    case ITC_ARRAY:
        if (oldtype == ITC_STRING)
        {
            char *buf = (char*) item->param1;
            int len = lstrlen(buf)+1;
            ExpressionItem *ni = AllocArray(lstrlen(buf)+1);
            ArrayDesc *ad = (ArrayDesc*) ni->param1;
            for (int i = 0; i < len; i++)
            {
                ad->array[i] = AllocItem();
                *((__int64 *) &(ad->array[i]->param1)) = (__int64) buf[i];
            }
            ad->count = len;
            CleanupItems(item);
            item = ni;
        }
        break;
    }
    item->type = IT_CONST | type;
}

void SaveResult(ExpressionItem *var, ExpressionItem *result)
{
    if ((var->type & ITEMTYPE) != IT_VARIABLE) return;

    // result should be stored at variable to
    int varindex = var->type & ITEMOPTIONS;
    switch (var->type & ITEMSUBTYPE)
    {
    case ITV_NSIS:
        {
            // store string result direct to NSIS variable
            char *ptr = g_variables + varindex*g_stringsize;
            ItemToString(ptr, result);
        }
        break;
    case ITV_USER:
        {
            CleanupItems(UserVars[varindex].item);
            UserVars[varindex].item = CopyItem(result);
        }
        break;
    case ITV_ARRITEM:
        {
            ExpressionItem *&ei = ((ArrayDesc*)(var->param1))->array[(int)var->param2];
            CleanupItems(ei);
            ei = CopyItem(result);
        }
        break;
    case ITV_STACK:
        {
            ExpressionItem *newitem = CopyItem(result);
            newitem->next = stack;
            stack = newitem;
        }
        break;
    case ITV_NSTACK:
        {
            char *buf = AllocString();
            ItemToString(buf, result);
            pushstring(buf);
            dbgGlobalFree(buf);
        }
        break;
    }
}

void RunAndGetConst(int from, ExpressionItem* &result, int type)
{
    RunTree(*((ExpressionItem**)&(from)), result, type | RTO_NEEDCONST);
    ItemToType(result, type);
}

void RunTree(ExpressionItem *from, ExpressionItem* &result, int options)
{
    ExpressionItem *item = from;
    result = NULL;
    while (item != NULL)
    {
        CleanupItems(result);
        int type = item->type & ITEMTYPE,
            subtype = item->type & ITEMSUBTYPE,
            ioptions = item->type & ITEMOPTIONS;
        switch (type)
        {
        case IT_EXPRESSION:
            RunTree(*((ExpressionItem**)&(item->param1)), result, options);
            break;
        case IT_CONST:
            result = CopyItem(item);
            break;
        case IT_VARIABLE:
            if (options & RTO_NEEDCONST)
            {
                // we need const result - :) is it nsis or common variable
                switch (subtype)
                {
                case ITV_NSIS:
                    {
                        // nsis
                        result = AllocItem();
                        char *variable = getuservariable(ioptions);
                        StringToItem(variable, result, options);
                    }
                    break;
                case ITV_USER:
                    {
                        // usual variable
                        if (UserVars[ioptions].item)
                            result = CopyItem(UserVars[ioptions].item);
                        else
                            result = AllocItem();
                    }
                    break;
                case ITV_ARRITEM:
                    {
                        // array item
                        ExpressionItem *ei = ((ArrayDesc*)(item->param1))->array[(int)item->param2];
                        if (ei)
                            result = CopyItem(ei);
                        else
                            result = AllocItem();
                    }
                    break;
                case ITV_STACK:
                    {
                        // pop from plugin stack
                        result = stack;
                        if (result == NULL) result = AllocItem();
                        stack = result->next;
                        result->next = NULL;
                    }
                    break;
                case ITV_NSTACK:
                    {
                        // NSIS stack
                        char buffer[1024], *buf = buffer;
                        result = AllocItem();
                        popstring(buffer);
                        StringToItem(buf, result, options);
                    }
                    break;
                }
            }
            else
                // if we don't need const - we will just pass variable record
                result = CopyItem(item);
            break;
        case IT_OPERATOR:
            {
                ExpressionItem *var = NULL, *item1 = NULL, *item2 = NULL;
                // prepare arguments in case of SET operator
                if (ioptions & PO_SET)
                {
                    if ((item->param1) && (ioptions & PO_PRENONCONST))
                    {
                        RunTree(*((ExpressionItem**)&(item->param1)), var, 0);
                        if (ioptions & PO_USESPRE)
                            RunTree(var, item1, RTO_NEEDCONST | STI_INT | STI_FLOAT | STI_STRING);
                    } else
                    if ((item->param2) && (ioptions & PO_POSTNONCONST))
                    {
                        RunTree(*((ExpressionItem**)&(item->param2)), var, 0);
                        if (ioptions & PO_USESPOST)
                            RunTree(var, item2, RTO_NEEDCONST | STI_INT | STI_FLOAT | STI_STRING);
                    }
                }

                // prepare arguments in case of any operator
                int needmore = 1;
                if ((!item1) && (item->param1) && (ioptions & PO_USESPRE))
                {
                    RunTree(*((ExpressionItem**)&(item->param1)), item1, RTO_NEEDCONST | STI_INT | STI_FLOAT | STI_STRING);
                    // logical expressions && and || can make decision on first arg basis
                    if ((subtype == ITO_LAND) || (subtype == ITO_LOR) )
                    {
                        ItemToType(item1, ITC_INT);
                        int res = (int) *((__int64*) &(item1->param1));
                        if (((res)&&(subtype==ITO_LOR)) || ((!res)&&(subtype==ITO_LAND)))
                            needmore = 0;
                    }
                }

                // get-reference operator
                if ((!item1) && (subtype == ITO_AND) && (!item2) && (item->param2))
                {
                    RunTree(*((ExpressionItem**)&(item->param2)), result, 0);
                    break;
                }

                if ((needmore) && (!item2) && (item->param2) && (ioptions & PO_USESPOST))
                    RunTree(*((ExpressionItem**)&(item->param2)), item2, RTO_NEEDCONST | STI_INT | STI_FLOAT | STI_STRING);

                // reference operator
                if ((!item1) && (subtype == ITO_MUL) && ((item2->type & ITEMTYPE) == (IT_VARIABLE)))
                {
                    // ok, that's the result we need
                    if (options & RTO_NEEDCONST)
                    {
                        RunTree(item2, result, options);
                        CleanupItems(item2);
                    } else
                        result = item2;
                    break;
                }

                __int64 i1=0, i2=0, i3=0, i4=0;
                if (((!item1)||((item1->type & ITEMTYPE)==IT_CONST)) &&
                    ((!item2)||((item2->type & ITEMTYPE)==IT_CONST)))
                {

                // find the best type match for operation
                int it1 = (item1 && (ioptions & PO_USESPRE))?(item1->type & ITEMSUBTYPE):(ITC_UNKNOWN),
                    it2 = (item2 && (ioptions & PO_USESPOST))?(item2->type & ITEMSUBTYPE):(ITC_UNKNOWN),
                    type = (it1 < it2)?(it1):(it2);

                // convert operands to desired type
                ItemToType(item1, type);
                ItemToType(item2, type);

                switch (type)
                {
                case ITC_INT:
                    {
                        i1 = (item1)?(*((__int64*)&item1->param1)):(0);
                        i2 = (item2)?(*((__int64*)&item2->param1)):(0);

                    switch (subtype)
                    {
                    case ITO_MINUS: i1 -= i2; break;    // unary minus auto handled with NULL
                    case ITO_PLUS:  i1 += i2; break;
                    case ITO_SHL:   i1 <<= i2; break;
                    case ITO_SHR:   i1 >>= i2; break;
                    case ITO_MUL:   i1 *= i2; break;
                    case ITO_MOD:
                    case ITO_DIV:
                                    if (i2 == 0) { i3 = 0; i4 = i1;  }
                                    else { i3 = i1 / i2; i4 = i1 % i2; }
                                    if (subtype == ITO_DIV) i1 = i3; else i1 = i4;
                                    break;
                    case ITO_SET:   i1 = i2; break;
                    case ITO_LE:    i1 = (i1 <= i2); break;
                    case ITO_GE:    i1 = (i1 >= i2); break;
                    case ITO_NE:    i1 = (i1 != i2); break;
                    case ITO_EQ:    i1 = (i1 == i2); break;
                    case ITO_LS:    i1 = (i1 < i2); break;
                    case ITO_GR:    i1 = (i1 > i2); break;
                    case ITO_AND:   i1 = (i1 & i2); break;
                    case ITO_OR:    i1 = (i1 | i2); break;
                    case ITO_XOR:   i1 = (i1 ^ i2); break;
                    case ITO_NOT:   i1 = ~i2; break;
                    case ITO_LNOT:  i1 = !i2; break;
                    case ITO_LAND:  i1 = i1 && i2; break;
                    case ITO_LOR:   i1 = i1 || i2; break;
                    case ITO_INC:
                            if (item1) i2 = i1++;
                            else i1 = ++i2;
                            break;
                    case ITO_DEC:
                            if (item1) i2 = i1--;
                            else i1 = --i2;
                            break;
                    }
                    result = AllocItem();
                    *((__int64*)&result->param1) = i1;
                    }
                    break;
                case ITC_FLOAT:
                    {
                        int ir = -666;
                        double i1 = (item1)?(*((double*)&item1->param1)):(0.0);
                        double i2 = (item2)?(*((double*)&item2->param1)):(0.0);

                    switch (subtype)
                    {
                    case ITO_MINUS: i1 -= i2; break;    // unary minus auto handled with NULL
                    case ITO_PLUS:  i1 += i2; break;
                    case ITO_MUL:   i1 *= i2; break;
                    case ITO_DIV:   i1 /= i2; break;
                    case ITO_SET:   i1 = i2; break;
                    case ITO_LE:    ir = (i1 <= i2); break;
                    case ITO_GE:    ir = (i1 >= i2); break;
                    case ITO_NE:    ir = (i1 != i2); break;
                    case ITO_EQ:    ir = (i1 == i2); break;
                    case ITO_LS:    ir = (i1 < i2); break;
                    case ITO_GR:    ir = (i1 > i2); break;
                    }
                    result = AllocItem();
                    if (ir == -666)
                    {
                        // if ir value left intact - result is double
                        result->type = IT_CONST | ITC_FLOAT;
                        *((double*)&result->param1) = i1;
                    } else
                        *((__int64*)&result->param1) = (__int64) ir;
                    }
                    break;
                case ITC_STRING:
                    {
                        int ir = -666;
                        char *i1 = (item1)?((char*)item1->param1):(NULL);
                        char *i2 = (item2)?((char*)item2->param1):(NULL);
                       	int sc = (i1 && i2)?(lstrcmp(i1, i2)):((i1)?(1):((i2)?(-1):(0)));

                    switch (subtype)
                    {
                    case ITO_PLUS:  lstrcat(i1, i2); break;
                    case ITO_SET:   i1 = i2; break;
                    case ITO_LE:    ir = (sc <= 0); break;
                    case ITO_GE:    ir = (sc >= 0); break;
                    case ITO_NE:    ir = (sc != 0); break;
                    case ITO_EQ:    ir = (sc == 0); break;
                    case ITO_LS:    ir = (sc < 0); break;
                    case ITO_GR:    ir = (sc > 0); break;
                    }
                    if (ir == -666)
                    {
                        result = CopyItem((item1)?(item1):(item2));
                    } else
                    {
                        result = AllocItem();
                        *((__int64*)&result->param1) = (__int64) ir;
                    }
                    }
                    break;
                case ITC_ARRAY:
                    result = CopyItem(item2);
                    break;
                }

                } // check for both items constant
                // the other case - usually UniaryPre operators working with non constants
                else result = CopyItem(item2);

                if (ioptions & PO_SET)
                {
                    // Save our result in output variable
                    SaveResult(var, result);
                }

                // Actual value to be returned as result is at i2 for ++ and -- ops
                if ((subtype == ITO_DEC) || (subtype == ITO_INC))
                    *((__int64*)&result->param1) = i2;

                CleanupItems(item1); CleanupItems(item2); CleanupItems(var);
            }
            break;
        case IT_LOGIC:
            {
                int ifmode = (subtype == ITL_IF);
                ExpressionItem *ifbr = *((ExpressionItem**)&(item->param1)),
                    *dobr = *((ExpressionItem**)&(item->param2)),

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?