📄 math.c
字号:
#include <windows.h>#include "MyMath.h"#include "Math.h"extern "C" int _fltused;#ifdef __MINGW32__int _fltused = 1;#endifExpressionItem *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 26typedef 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 29const 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 operanvoid 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 35const 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -