math.c
来自「NullSofts criptable install system2.28源代」· C语言 代码 · 共 1,549 行 · 第 1/4 页
C
1,549 行
#include <windows.h>
#include "MyMath.h"
#include "Math.h"
extern "C" int _fltused;
#ifdef __MINGW32__
int _fltused = 1;
#endif
ExpressionItem *stack;
int UserVarsCount, UserFuncsCount;
UserVar UserVars[MAX_USER_VARS];
UserFunc UserFuncs[MAX_USER_FUNCS];
void PrintTree(ExpressionItem *root, char *str);
void ParseString(char *&sp, ExpressionItem* &itemplace);
void CleanupItems(ExpressionItem* &itemplace);
void PlaceVariable(char *&vb, ParseInfo *pi);
void PlaceNewItem(char *&vb, ParseInfo *pi, int precedence)
{
ExpressionItem *newroot;
PlaceVariable(vb, pi);
if (pi->item == NULL) return;
while ((pi->OpsStack) && ((((int) pi->OpsStack->param2) < precedence)
|| ((((int)pi->OpsStack->param2) == precedence)
&& (precedence != OPERATOR_SET_PRECEDENCE))))
{
// second operand for our operator
newroot = pi->OpsStack;
*((ExpressionItem **)&(newroot->param2)) = pi->item;
pi->OpsStack = newroot->next;
newroot->next = NULL;
pi->item = newroot;
}
// finally we have got new root
newroot = pi->item;
if (pi->SetupNewRoot)
{
(*pi->root)->next = newroot;
pi->root = &((*pi->root)->next);
pi->SetupNewRoot = 0;
}
if (*pi->place == *pi->root) *pi->place = *pi->root = newroot;
else *pi->root = newroot;
// no item at our pockets
pi->item = NULL;
}
#define NSIS_VARS_COUNT 27
#define NSIS_VARS_STACK 25
#define NSIS_VARS_NSTACK 26
typedef char smallstr[2];
const smallstr NSISVariablesNames[NSIS_VARS_COUNT] = {{'r','0'}, {'r','1'}, {'r','2'}, {'r','3'}, {'r','4'}, {'r','5'}, {'r','6'}, {'r','7'}, {'r','8'}, {'r','9'},
{'R','0'}, {'R','1'}, {'R','2'}, {'R','3'}, {'R','4'}, {'R','5'}, {'R','6'}, {'R','7'}, {'R','8'}, {'R','9'},
{'C','L'}, {'I','D'}, {'O','D'}, {'E','D'}, {'L','G'}, {'S',0}, {'N','S'}};
ExpressionItem *FindVariable(char *varname)
{
int i;
ExpressionItem *item = AllocItem();
// check NSIS variables
for (i = 0; i < NSIS_VARS_COUNT; i++)
{
if (lstrcmpn(varname, NSISVariablesNames[i],2) == 0)
{
if (i == NSIS_VARS_STACK) item->type = IT_VARIABLE | ITV_STACK;
else if (i == NSIS_VARS_NSTACK) item->type = IT_VARIABLE | ITV_NSTACK;
else
item->type = (IT_VARIABLE | ITV_NSIS) + i;
return item;
}
}
// no.. that's user variable
for (i = 0; i < UserVarsCount; i++)
{
if (lstrcmp(varname, UserVars[i].name) == 0)
{
// ok. we found user var expression needed
break;
}
}
if (i == UserVarsCount)
{
// new variable
UserVarsCount++;
lstrcpy(UserVars[i].name, varname);
UserVars[i].item = NULL;
}
item->type = (IT_VARIABLE | ITV_USER) + i;
return item;
}
void PlaceVariable(char *&vb, ParseInfo *pi)
{
if (vb <= pi->valbuf) return;
*vb = 0;
pi->item = FindVariable(pi->valbuf);
vb = pi->valbuf;
}
typedef double (*math_d2)(double, double);
typedef double (*math_ddp)(double, double*);
typedef double (*math_di)(double, int*);
#define MATHFUNCNUM 29
const MathFunction MathFunctions[MATHFUNCNUM] = {
{{'s','i','n'}, ITF_MATH1 >> 8, sin},
{{'s','n','h'}, ITF_MATH1 >> 8, sinh},
{{'a','s','n'}, ITF_MATH1 >> 8, asin},
{{'c','o','s'}, ITF_MATH1 >> 8, cos},
{{'c','s','h'}, ITF_MATH1 >> 8, cosh},
{{'a','c','s'}, ITF_MATH1 >> 8, acos},
{{'t','a','n'}, ITF_MATH1 >> 8, tan},
{{'t','n','h'}, ITF_MATH1 >> 8, tanh},
{{'a','t','n'}, ITF_MATH1 >> 8, atan},
{{'a','b','s'}, ITF_MATH1 >> 8, fabs},
{{'l','n',0}, ITF_MATH1 >> 8, log},
{{'l','o','g'}, ITF_MATH1 >> 8, log10},
{{'e','x','p'}, ITF_MATH1 >> 8, exp},
{{'s','q','t'}, ITF_MATH1 >> 8, sqrt},
{{'c','e','l'}, ITF_MATH1 >> 8, ceil},
{{'f','l','r'}, ITF_MATH1 >> 8, floor},
{{'a','t','2'}, ITF_MATH2 >> 8, (Math1FuncPtr)(math_d2)atan2},
{{'p','o','w'}, ITF_MATH2 >> 8, (Math1FuncPtr)(math_d2)pow},
{{'f','m','d'}, ITF_MATH2 >> 8, (Math1FuncPtr)(math_d2)fmod},
// type conversions
{{'i',0,0}, ITF_TYPE >> 8, (Math1FuncPtr)ITC_INT},
{{'s',0,0}, ITF_TYPE >> 8, (Math1FuncPtr)ITC_STRING},
{{'f',0,0}, ITF_TYPE >> 8, (Math1FuncPtr)ITC_FLOAT},
{{'a',0,0}, ITF_TYPE >> 8, (Math1FuncPtr)ITC_ARRAY},
#define ITFT_CARRAY_ID 23
{{'c','a',0}, ITF_TYPE >> 8, (Math1FuncPtr)ITC_ARRAY},
{{'f','f',0}, ITF_TYPE >> 8, (Math1FuncPtr)FTT_FLOATF},
{{'l',0,0}, ITF_TYPE >> 8, (Math1FuncPtr)FTT_LEN},
{{'c',0,0}, ITF_TYPE >> 8, (Math1FuncPtr)FTT_CHAR},
{{'f','e','x'}, ITF_MATH2 >> 8, (Math1FuncPtr)(math_di)frexp},
{{'m','d','f'}, ITF_MATH2 >> 8, (Math1FuncPtr)(math_ddp)modf},
};
void PlaceFunction(char *&vb, char *&sp, ParseInfo *pi, int redefine)
{
int i;
ExpressionItem *item = pi->item = AllocItem();
*vb = 0;
// check BUILTIN functions
for (i = 0; i < MATHFUNCNUM; i++)
{
if (lstrcmpn(pi->valbuf, MathFunctions[i].name, 3) == 0)
{
item->type = IT_FUNCTION | (MathFunctions[i].type << 8) | i;
// get first argument
sp++;
ParseString(sp, *((ExpressionItem **)(&item->param1)));
if (*sp == ',')
{
// get second argument
sp++;
ParseString(sp, *((ExpressionItem **)(&item->param2)));
}
sp++; vb = pi->valbuf;
return;
}
}
// heh, may be it user function
for (i = 0; i < UserFuncsCount; i++)
{
if (lstrcmp(pi->valbuf, UserFuncs[i].name) == 0)
{
// Function found? Redefine option specified?
if (redefine) break;
item->type = IT_FUNCTION | ITF_USER | i;
// get arguments list
ExpressionItem **newplace = ((ExpressionItem **)(&pi->item->param1));
while (*sp != ')')
{
*newplace = AllocItem();
(*newplace)->type = IT_EXPRESSION;
sp++;
ParseString(sp, *((ExpressionItem **)(&(*newplace)->param1)));
newplace = &((*newplace)->next);
}
sp++; vb = pi->valbuf;
return;
}
}
// oops, we need no item for function defenition
CleanupItems(item); pi->item = NULL;
// it's user function define
int flags = 0;
char buffer[128], *buf = buffer;
// workaround for redefine flag - if the function already present,
// it will be cleared and redefined
UserFunc *f = &UserFuncs[i];
if (i == UserFuncsCount) UserFuncsCount++;
else CleanupItems(f->root);
lstrcpy(f->name, pi->valbuf);
f->varflags = 0;
f->varsnum = 0;
do
{
sp++;
switch (*sp)
{
case ' ':
break;
case ',':
case ')':
if (buf > buffer)
{
*buf = 0;
// it should be user variable
ExpressionItem *it = FindVariable(buffer);
f->vars[f->varsnum++] = (it->type) & ITEMOPTIONS;
CleanupItems(it);
buf = buffer;
flags <<= 1;
}
break;
case '&':
flags |= 1;
break;
default:
*(buf++) = *sp;
break;
}
}
while (*sp != ')');
// prepare flag for fast analisys
for (i = 0; i < f->varsnum; i++)
{
f->varflags <<= 1;
flags >>= 1;
f->varflags |= flags&1;
}
// find nearest round bracket - function body
while (*sp != '(' && *sp) sp++;
if (!*sp)
return;
sp++;
// now we are ready to parse function body
ParseString(sp, f->root);
sp++; // closing bracket
vb = pi->valbuf;
#ifdef _DEBUG
// dump function (in debug mode)
char place[1024];
wsprintf(place, "function %s(", f->name);
flags = f->varflags;
for (i = 0; i < f->varsnum; i++)
{
if (flags&1) lstrcat(place, "&");
lstrcat(place, UserVars[f->vars[i]].name);
if (i < f->varsnum-1) lstrcat(place, ", ");
flags >>= 1;
}
lstrcat(place, ")");
PrintTree(f->root, place);
#endif
}
// operator options
#define PO_UNARYPRE 0x1 // this operator can be uniary pre (--a) for ex
#define PO_UNARYPOST 0x2 // this op can be uniary post (a++) (couldn't be binary)
#define PO_PRENONCONST 0x4 // pre argument (a = b) -> a is non const
#define PO_POSTNONCONST 0x8 // post argument (b--) is non const
#define PO_LASTOP 0x10 // op should be the last item at expression (=, -=, etc)
#define PO_SET 0x20 // op will set new value to one of args
#define PO_USESPRE 0x40 // operator will use pre operand
#define PO_USESPOST 0x80 // operator will use post operan
void PlaceOp(char *&vb, int type, int precedence, ParseInfo *pi)
{
PlaceVariable(vb, pi);
if ((type & PO_UNARYPRE) && (!pi->item))
{
// uniary pre op
ExpressionItem *item = AllocItem();
item->type = type;
item->param2 = (EIPARAM) precedence;
item->next = pi->OpsStack;
pi->OpsStack = item;
}
else
{
// get previous tree as items and operators of lower precedence
PlaceNewItem(vb, pi, precedence);
// post operators
ExpressionItem *item = AllocItem();
item->type = type;
item->param1 = (EIPARAM) (*pi->root);
if (*pi->place == *pi->root) *pi->place = *pi->root = NULL;
else *pi->root = NULL;
if (type & PO_UNARYPOST)
{
// uniary post op
pi->item = item;
} else
{
// binary operator
item->param2 = (EIPARAM) precedence;
item->next = pi->OpsStack;
pi->OpsStack = item;
}
}
}
#define OPSNUM 35
const OpStruct Operators[OPSNUM] =
{
// three byte ops
{{'>','>','='}, 14, ITO_SHR | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{{'<','<','='}, 14, ITO_SHL | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
// two byte ops
// !!! don't forget to change Set Operator Precedence !!!
{"-=", 14, ITO_MINUS | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{"+=", 14, ITO_PLUS | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{"/=", 14, ITO_DIV | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{"*=", 14, ITO_MUL | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{"|=", 14, ITO_OR | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{"&=", 14, ITO_AND | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{"^=", 14, ITO_XOR | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{"%=", 14, ITO_MOD | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPRE | PO_USESPOST},
{"--", 2, ITO_DEC | PO_POSTNONCONST | PO_PRENONCONST | PO_UNARYPRE | PO_UNARYPOST | PO_SET | PO_USESPRE | PO_USESPOST},
{"++", 2, ITO_INC | PO_POSTNONCONST | PO_PRENONCONST | PO_UNARYPRE | PO_UNARYPOST | PO_SET | PO_USESPRE | PO_USESPOST},
{">>", 6, ITO_SHR | PO_USESPRE | PO_USESPOST},
{"<<", 6, ITO_SHL | PO_USESPRE | PO_USESPOST},
// logical
{"&&", 12, ITO_LAND | PO_USESPRE | PO_USESPOST},
{"||", 13, ITO_LOR | PO_USESPRE | PO_USESPOST},
// comparisons
{"<=", 7, ITO_LE | PO_USESPRE | PO_USESPOST},
{"=<", 7, ITO_LE | PO_USESPRE | PO_USESPOST},
{">=", 7, ITO_GE | PO_USESPRE | PO_USESPOST},
{"=>", 7, ITO_GE | PO_USESPRE | PO_USESPOST},
{"!=", 8, ITO_NE | PO_USESPRE | PO_USESPOST},
{"==", 8, ITO_EQ | PO_USESPRE | PO_USESPOST},
// single byte ops
// !!! don't forget to change Set Operator Precedence !!!
{"=", 14, ITO_SET | PO_PRENONCONST | PO_LASTOP | PO_SET | PO_USESPOST},
{"+", 5, ITO_PLUS | PO_USESPRE | PO_USESPOST},
{"-", 5, ITO_MINUS | PO_USESPRE | PO_USESPOST | PO_UNARYPRE},
{"*", 4, ITO_MUL | PO_USESPRE | PO_USESPOST | PO_UNARYPRE},
{"/", 4, ITO_DIV | PO_USESPRE | PO_USESPOST},
{"%", 4, ITO_MOD | PO_USESPRE | PO_USESPOST},
{"<", 7, ITO_LS | PO_USESPRE | PO_USESPOST},
{">", 7, ITO_GR | PO_USESPRE | PO_USESPOST},
{"&", 9, ITO_AND | PO_USESPRE | PO_USESPOST | PO_UNARYPRE},
{"|", 11, ITO_OR | PO_USESPRE | PO_USESPOST},
{"^", 10, ITO_XOR | PO_USESPRE | PO_USESPOST},
{"~", 3, ITO_NOT | PO_USESPOST | PO_UNARYPRE},
{"!", 3, ITO_LNOT |PO_USESPOST | PO_UNARYPRE}
};
void CheckForOperator(char *&sp, char *&vb, ParseInfo *pi)
{
for (int op = 0; op < OPSNUM; op++)
{
int c = lstrlen(Operators[op].name);
if (c > 3) c = 3; // real operator length
if (lstrcmpn(sp, Operators[op].name, c))
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?