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