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