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 + -
显示快捷键?