math.c

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

C
1,549
字号
                    *thbr = NULL, *elbr = NULL;
                // check do branche for existance
                if (dobr && ifmode)
                {
                    // then...
                    thbr = *((ExpressionItem**)&(dobr->param1));
                    // ... and else branches
                    if (dobr->next) elbr = *((ExpressionItem**)&(dobr->next->param1));
                }
                while (true)
                {
                    RunAndGetConst((int) ifbr, result, ITC_INT);
                    if (ifmode)
                    {
                        // we need then or else branch?
                        if ((*((__int64*)&result->param1))) dobr = thbr;
                        else dobr = elbr;
                    } else
                    {
                        // while mode
                        if (!(*((__int64*)&result->param1))) break;
                    }
                    // ok, run the approtiate branch of if statement (if available)
                    if (dobr)
                    {
                        CleanupItems(result);
                        RunTree(dobr, result, options);
                    }
                    if (ifmode) break;
                    CleanupItems(result);
                }
            }
            break;
        case IT_FUNCTION:
            if (subtype == ITF_USER)
            {
                int i;
                UserFunc *f = &(UserFuncs[ioptions]);
                int flags = f->varflags;
                ExpressionItem *ip = *((ExpressionItem**)&(item->param1));
                ExpressionItem *si = AllocItem(), *var = AllocItem();
                ExpressionItem *vals[32];
                si->type = IT_VARIABLE | ITV_STACK;
                for (i = 0; i < f->varsnum; i++)
                {
                    // push every variable
                    ExpressionItem *val;
                    var->type = (IT_VARIABLE | ITV_USER) + f->vars[i];
                    RunTree(var, val, RTO_NEEDCONST | ITC_STRING | ITC_INT | ITC_FLOAT | ITC_ARRAY);
                    SaveResult(si, val);
                    CleanupItems(val);
                    // calculate argument value and for future
                    if (ip)
                    {
                        if (flags&1)
                        {
                            // var ptr required
                            RunTree(*((ExpressionItem**)&(ip->param1)), vals[i], 0);
                        } else
                        {
                            RunTree(*((ExpressionItem**)&(ip->param1)), vals[i], RTO_NEEDCONST | ITC_STRING | ITC_INT | ITC_FLOAT | ITC_ARRAY);
                        }
                        ip = ip->next;
                    } else vals[i] = AllocItem();

                    flags >>= 1;
                }

                // now when all values got we could save them to variables
                for (i = 0; i < f->varsnum; i++)
                {
                        var->type = (IT_VARIABLE | ITV_USER) + f->vars[i];
                        SaveResult(var, vals[i]);
                        CleanupItems(vals[i]);
                }


                // ok, call the func
                RunTree(f->root, result, RTO_NEEDCONST | ITC_STRING | ITC_INT | ITC_FLOAT | ITC_ARRAY);

                // pop original params
                for (i = f->varsnum-1; i >= 0; i--)
                {
                    // pop every variable
                    ExpressionItem *val;
                    var->type = (IT_VARIABLE | ITV_USER) + f->vars[i];
                    RunTree(si, val, RTO_NEEDCONST | ITC_STRING | ITC_INT | ITC_FLOAT | ITC_ARRAY);
                    SaveResult(var, val);
                    CleanupItems(val);
                }

                // free used items
                CleanupItems(si); CleanupItems(var);
            } else if (subtype == ITF_TYPE)
            {
                int newtype = (int) MathFunctions[ioptions].fptr;
                if (newtype < ITC_UNKNOWN)
                {
                    // get as possibly close to ready expression
                    RunAndGetConst((int)item->param1, result, newtype);
                    if (ioptions == ITFT_CARRAY_ID)
                        CopyArray(result);
                } else if (newtype == FTT_FLOATF)
                {
                    // float format function
                    ExpressionItem *arg1, *arg2;
                    RunAndGetConst((int)item->param1, arg1, ITC_FLOAT);
                    double value = *((double*)&(arg1->param1));
                    RunAndGetConst((int)item->param2, arg2, ITC_INT);
                    int format = (int) *((__int64*)&(arg2->param1));

                    result = AllocItem();
                    result->type = IT_CONST | ITC_STRING;
                    result->param1 = (EIPARAM)  AllocString();
                    FloatFormat((char*) result->param1, value, format);
                    CleanupItems(arg1); CleanupItems(arg2);
                } else if (newtype == FTT_LEN)
                {
                    // length function
                    RunTree(*((ExpressionItem **) &(item->param1)), result, RTO_NEEDCONST | ITC_STRING | ITC_ARRAY);
                    if ((result->type & (ITEMTYPE|ITEMSUBTYPE)) == (IT_CONST|ITC_ARRAY))
                    {
                        int len = ((ArrayDesc*)(result->param1))->count;
                        CleanupItems(result);
                        result = AllocItem();
                        *((__int64*)&(result->param1)) = (__int64) len;
                        break;
                    } else
                        if ((result->type & (ITEMTYPE|ITEMSUBTYPE)) != (IT_CONST|ITC_STRING))
                            ItemToType(result, ITC_STRING);

                    if ((result->type & (ITEMTYPE|ITEMSUBTYPE)) == (IT_CONST|ITC_STRING))
                    {
                        // ok, that's string
                        int len = lstrlen((char*)result->param1);
                        dbgGlobalFree((HGLOBAL) result->param1);
                        *((__int64*)&(result->param1)) = (__int64) len;
                        result->type = IT_CONST | ITC_INT;
                    } else CleanupItems(result);
                } else
                {
                    // only one left - c() - char/int/char conversion
                    RunTree(*((ExpressionItem **) &(item->param1)), result, RTO_NEEDCONST | ITC_STRING | ITC_INT);
                    if ((result->type & (ITEMTYPE|ITEMSUBTYPE)) == (IT_CONST|ITC_STRING))
                    {
                        // ok, that's string - convert first char to int
                        int chr = (*((char*)result->param1)) & 0xFF;
                        dbgGlobalFree((HGLOBAL) result->param1);
                        *((__int64*)&(result->param1)) = (__int64) chr;
                        result->type = IT_CONST | ITC_INT;
                        break;
                    }
                    if ((result->type & (ITEMTYPE|ITEMSUBTYPE)) == (IT_CONST|ITC_INT))
                    {
                        // ok, that's int - convert to new string (char+0)
                        int chr = (int) (*((__int64*)&(result->param1))) & 0xFF;
                        result->param1 = (EIPARAM)  AllocString();
                        *((char*)result->param1) = (char) chr;
                        *((char*)(result->param1+1)) = (char) 0;
                        result->type = IT_CONST | ITC_STRING;
                        break;
                    } else CleanupItems(result);
                }
            } else
            {
                // oops :-o function call :)
                RunAndGetConst((int)item->param1, result, ITC_FLOAT);
                double &value = *((double*)&(result->param1));
                if (subtype == ITF_MATH1)
                {
                    // Built-In math function with 1 arg
                    value = MathFunctions[ioptions].fptr(value);
                } else
                if (subtype == ITF_MATH2)
                {
                    // Built-In math function with 2 args
                    if (ioptions >= MATHFUNCNUM-2)
                    {
                        // specific function - we need second arg as out
                        ExpressionItem *arg2, *res2 = AllocItem();
                        RunTree(*((ExpressionItem**)&(item->param2)), arg2, 0);
                        if (ioptions == MATHFUNCNUM-1)
                        {
                            // fmodf function - second arg is ptr to double
                            res2->type = IT_CONST | ITC_FLOAT;
                            double &v = *((double*)&(res2->param1));
                            value = ((Math2dFuncPtr)(MathFunctions[ioptions].fptr))(value, &v);
                        } else
                        {
                            // frexp function - second arg is ptr to int
                            int v = 0;
                            value = ((Math2iFuncPtr)(MathFunctions[ioptions].fptr))(value, &v);
                            *((__int64 *)&(res2->param1)) = (__int64) v;
                        }
                        SaveResult(arg2, res2);
                        CleanupItems(arg2); CleanupItems(res2);
                    } else
                    {
                        // normal 2-arg math function
                        ExpressionItem *arg2;
                        RunAndGetConst((int)item->param2, arg2, ITC_FLOAT);
                        double value2 = *((double*)&(arg2->param1));
                        value = ((Math2FuncPtr)(MathFunctions[ioptions].fptr))(value, value2);
                        CleanupItems(arg2);
                    }
                }
            }
            break;
        case IT_ARRAY:
            {
                // currently only array access is used
                ExpressionItem *index, *aritem;
                RunTree(*((ExpressionItem **) &(item->param1)), aritem, RTO_NEEDCONST | ITC_STRING | ITC_ARRAY);

                if ((aritem->type & (ITEMTYPE|ITEMSUBTYPE)) == (IT_CONST | ITC_STRING))
                {
                    // argument is string
                    char *str = (char*)(aritem->param1);
                    int len = lstrlen(str);
                    // have we two indexes or one?
                    if ((*((ExpressionItem **) &(item->param2)))->type != IT_EXPRESSION)
                    {
                        // one index - user need a char
                        RunAndGetConst((int)item->param2, index, ITC_INT);

                        int pos = (int) *((__int64*)&(index->param1));
                        if (pos < 0) pos += len; // -index - means from end
                        if ((pos > len) || (pos < 0))
                            *str = 0; // index is accross string boundaries
                        else
                        {
                            // new string - just a single char
                            *str = *(str+pos);
                            *(str+1) = 0;
                        }
                    } else
                    {
                        // two indexes
                        ExpressionItem *index2;
                        // if first index is skipped -> 0 (from first char)
                        if ((*((ExpressionItem **) &(item->param2)))->param1 == 0)
                            index = AllocItem();
                        else
                            RunAndGetConst((int)(*((ExpressionItem **) &(item->param2)))->param1, index, ITC_INT);
                        if ((*((ExpressionItem **) &(item->param2)))->next->param1 == 0)
                        {
                            // if second index is skipped -> -1 (till last char)
                            index2 = AllocItem();
                            *((__int64*)&(index2->param1)) = -1;
                        }
                        else
                            RunAndGetConst((int)(*((ExpressionItem **) &(item->param2)))->next->param1, index2, ITC_INT);

                        // ok, we've got two indexes
                        int pos1 = (int) *((__int64*)&(index->param1));
                        int pos2 = (int) *((__int64*)&(index2->param1));
                        if (pos1 < 0) pos1 += len; // -index - means from end
                        if (pos2 < 0) pos2 += len; // -index - means from end
                        // limit start/stop positions
                        if (pos1 < 0) pos1 = 0;
                        if (pos2 < 0) pos2 = 0;
                        if (pos1 > len) pos1 = len;
                        if (pos2 >= len) pos2 = len-1;

                        // copy string part
                        char* lpos = str + (pos2-pos1);
                        while (str <= lpos)
                        {
                            *str = *(str + pos1);
                            str++;
                        }
                        // null-termiante
                        *str = 0;

                        CleanupItems(index2);
                    }

                } else
                {
                    // argument is array
                    RunAndGetConst((int)item->param2, index, ITC_INT);

                    // convert array pointer to array item pointer
                    aritem->type = IT_VARIABLE | ITV_ARRITEM;
                    aritem->param2 = (EIPARAM) *((__int64*)&(index->param1));

                    ArrayDesc *ad = (ArrayDesc*)aritem->param1;
                    if (((int)aritem->param2) >= ad->count)
                    {
                        ad->count = ((int)aritem->param2)+1;
                        while (ad->count > ad->size)
                        {
                            // resize array
                            ExpressionItem **oldei = ad->array;
                            ad->array = (ExpressionItem**) dbgGlobalAlloc(GPTR, 2*ad->size*sizeof(ExpressionItem*));
                            for (int i = 0; i < ad->size; i++)
                                ad->array[i] = oldei[i];
                            ad->size*=2;
                            dbgGlobalFree(oldei);
                        }
                    }
                }

                CleanupItems(index);

                // we need constant result?
                if (options & RTO_NEEDCONST)
                {
                    RunTree(aritem, result, options);
                    CleanupItems(aritem);
                } else result = aritem;
            }
            break;
        }
        item = item->next;
    }
}

extern "C"
void __declspec(dllexport) Script(HWND hwndParent, int string_size,
                                      char *variables, stack_t **stacktop)
{
  Math_INIT();
  char *buffer = AllocString(), *buf = buffer;
  ExpressionItem *root = NULL; // root of current tree

  // pop script string
  popstring(buffer);

  // parse it
  ParseString(buf, root);

#ifdef _DEBUG
  // dump
  PrintTree(root, buffer);
#endif

  ExpressionItem *result;
  RunTree(root, result, 0);
  CleanupItems(result);

  CleanupItems(root);
  dbgGlobalFree((HGLOBAL) buffer);
}

double _infinity;
extern "C" void _fpreset();

void CleanAll(int init)
{
  if (init)
  {
    unsigned char _infinity_base[8] = {0, 0, 0, 0, 0, 0, 0xf0, 0x7f};
    _fltused = 0;
    _infinity = *((double*)(_infinity_base));
    _fpreset();

    stack = NULL;
    UserVarsCount = 0;
    UserFuncsCount = 0;
  } else
  {
    int i;
    // cleanup stack
    CleanupItems(stack); stack = NULL;
    // cleanup user vars
    for (i = 0; i < UserVarsCount; i++)
        CleanupItems(UserVars[i].item);
    // cleanup user funcs
    for (i = 0; i < UserFuncsCount; i++)
        CleanupItems(UserFuncs[i].root);
    UserVarsCount = 0;
    UserFuncsCount = 0;

    dbgGlobalCheck();
  }
}

BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
    CleanAll(ul_reason_for_call == DLL_PROCESS_ATTACH);
    return TRUE;
}

⌨️ 快捷键说明

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