📄 math.c
字号:
*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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -