diff options
Diffstat (limited to 'Src/ns-eel')
-rw-r--r-- | Src/ns-eel/megabuf.c | 80 | ||||
-rw-r--r-- | Src/ns-eel/megabuf.h | 21 | ||||
-rw-r--r-- | Src/ns-eel/ns-eel-addfuncs.h | 90 | ||||
-rw-r--r-- | Src/ns-eel/ns-eel-int.h | 156 | ||||
-rw-r--r-- | Src/ns-eel/ns-eel.h | 80 | ||||
-rw-r--r-- | Src/ns-eel/nseel-caltab.c | 553 | ||||
-rw-r--r-- | Src/ns-eel/nseel-cfunc.c | 776 | ||||
-rw-r--r-- | Src/ns-eel/nseel-compiler.c | 946 | ||||
-rw-r--r-- | Src/ns-eel/nseel-eval.c | 282 | ||||
-rw-r--r-- | Src/ns-eel/nseel-lextab.c | 265 | ||||
-rw-r--r-- | Src/ns-eel/nseel-yylex.c | 162 |
11 files changed, 3411 insertions, 0 deletions
diff --git a/Src/ns-eel/megabuf.c b/Src/ns-eel/megabuf.c new file mode 100644 index 00000000..bfee8f7b --- /dev/null +++ b/Src/ns-eel/megabuf.c @@ -0,0 +1,80 @@ +#include <windows.h> +#include "../ns-eel/ns-eel.h" +#include "../ns-eel/ns-eel-int.h" +#include "megabuf.h" + +void megabuf_ppproc(void *data, int data_size, void **userfunc_data) +{ + if (data_size > 5 && *(int*)((char *)data+1) == 0xFFFFFFFF) + { + *(int*)((char *)data+1) = (int) (userfunc_data+0); + } +} + +void megabuf_cleanup(NSEEL_VMCTX ctx) +{ + if (ctx) + { + compileContext *c=(compileContext*)ctx; + if (c->userfunc_data[0]) + { + double **blocks = (double **)c->userfunc_data[0]; + int x; + for (x = 0; x < MEGABUF_BLOCKS; x ++) + { + if (blocks[x]) VirtualFree(blocks[x], 0/*sizeof(double)*MEGABUF_ITEMSPERBLOCK*/, MEM_RELEASE); + //GlobalFree(blocks[x]); + blocks[x]=0; + } + VirtualFree(blocks, 0/*sizeof(double *)*MEGABUF_BLOCKS*/, MEM_RELEASE); + //GlobalFree((HGLOBAL)blocks); + c->userfunc_data[0]=0; + } + } +} + +static double * NSEEL_CGEN_CALL megabuf_(double ***blocks, double *which) +{ + static double error; + int w=(int)(*which + 0.0001); + int whichblock = w/MEGABUF_ITEMSPERBLOCK; + + if (!*blocks) + { + *blocks = (double **)VirtualAlloc(NULL, sizeof(double *)*MEGABUF_BLOCKS, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + //GlobalAlloc(GPTR,sizeof(double *)*MEGABUF_BLOCKS); + } + if (!*blocks) return &error; + + if (w >= 0 && whichblock >= 0 && whichblock < MEGABUF_BLOCKS) + { + int whichentry = w%MEGABUF_ITEMSPERBLOCK; + if (!(*blocks)[whichblock]) + { + (*blocks)[whichblock]=(double *)VirtualAlloc(NULL, sizeof(double)*MEGABUF_ITEMSPERBLOCK, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + //GlobalAlloc(GPTR,sizeof(double)*MEGABUF_ITEMSPERBLOCK); + } + if ((*blocks)[whichblock]) + return &(*blocks)[whichblock][whichentry]; + } + + return &error; +} + +static double * (NSEEL_CGEN_CALL *__megabuf)(double ***,double *) = &megabuf_; +__declspec ( naked ) void _asm_megabuf(void) +{ + double ***my_ctx; + double *parm_a, *__nextBlock; + __asm { mov edx, 0xFFFFFFFF } + __asm { mov ebp, esp } + __asm { sub esp, __LOCAL_SIZE } + __asm { mov dword ptr my_ctx, edx } + __asm { mov dword ptr parm_a, eax } + + __nextBlock = __megabuf(my_ctx,parm_a); + + __asm { mov eax, __nextBlock } // this is custom, returning pointer + __asm { mov esp, ebp } +} +__declspec ( naked ) void _asm_megabuf_end(void) {} diff --git a/Src/ns-eel/megabuf.h b/Src/ns-eel/megabuf.h new file mode 100644 index 00000000..41fa7aba --- /dev/null +++ b/Src/ns-eel/megabuf.h @@ -0,0 +1,21 @@ +#ifndef _MEGABUF_H_ +#define _MEGABUF_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MEGABUF_BLOCKS 64 +#define MEGABUF_ITEMSPERBLOCK 16384 + +void _asm_megabuf(void); +void _asm_megabuf_end(void); +void megabuf_ppproc(void *data, int data_size, void **userfunc_data); +void megabuf_cleanup(NSEEL_VMCTX); + +#ifdef __cplusplus +} +#endif + + +#endif
\ No newline at end of file diff --git a/Src/ns-eel/ns-eel-addfuncs.h b/Src/ns-eel/ns-eel-addfuncs.h new file mode 100644 index 00000000..fb15fcf2 --- /dev/null +++ b/Src/ns-eel/ns-eel-addfuncs.h @@ -0,0 +1,90 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + ns-eel-addfuncs.h: defines macros useful for adding functions to the compiler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __NS_EEL_ADDFUNCS_H__ +#define __NS_EEL_ADDFUNCS_H__ + + + +typedef void (*NSEEL_PPPROC)(void *data, int data_size, void **userfunc_data); + + + +// these are used for making your own naked functions in C. +/* +For example: +static double (*__acos)(double) = &acos; +__declspec ( naked ) void _asm_acos(void) +{ + FUNC1_ENTER + + *__nextBlock = __acos(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void _asm_acos_end(void) {} + + + +If you want to do straight asm, then , well, you can use your imagination +(eax, ebx, ecx are input, eax is output, all points to "double") +if you need 8 bytes of temp space for your output, use esi and increment esi by 8 +be sure to preserve edi, too. + +*/ + + + +#define FUNC1_ENTER \ + double *parm_a, *__nextBlock; \ + __asm { mov ebp, esp } \ + __asm { sub esp, __LOCAL_SIZE } \ + __asm { mov dword ptr parm_a, eax } \ + __asm { mov __nextBlock, esi } + +#define FUNC2_ENTER \ + double *parm_a,*parm_b,*__nextBlock; \ + __asm { mov ebp, esp } \ + __asm { sub esp, __LOCAL_SIZE } \ + __asm { mov dword ptr parm_a, eax } \ + __asm { mov dword ptr parm_b, ebx } \ + __asm { mov __nextBlock, esi } + +#define FUNC3_ENTER \ + double *parm_a,*parm_b,*parm_c,*__nextBlock; \ + __asm { mov ebp, esp } \ + __asm { sub esp, __LOCAL_SIZE } \ + __asm { mov dword ptr parm_a, eax } \ + __asm { mov dword ptr parm_b, ebx } \ + __asm { mov dword ptr parm_c, ecx } \ + __asm { mov __nextBlock, esi } + +#define FUNC_LEAVE \ + __asm { mov eax, esi } \ + __asm { add esi, 8 } \ + __asm { mov esp, ebp } + +#define NSEEL_CGEN_CALL __fastcall + + +#endif//__NS_EEL_ADDFUNCS_H__
\ No newline at end of file diff --git a/Src/ns-eel/ns-eel-int.h b/Src/ns-eel/ns-eel-int.h new file mode 100644 index 00000000..b7865315 --- /dev/null +++ b/Src/ns-eel/ns-eel-int.h @@ -0,0 +1,156 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + ns-eel-int.h: internal code definition header. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __NS_EELINT_H__ +#define __NS_EELINT_H__ + +#include "ns-eel.h" +#include "ns-eel-addfuncs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FN_ASSIGN 0 +#define FN_MULTIPLY 1 +#define FN_DIVIDE 2 +#define FN_MODULO 3 +#define FN_ADD 4 +#define FN_SUB 5 +#define FN_AND 6 +#define FN_OR 7 +#define FN_UMINUS 8 +#define FN_UPLUS 9 + +#define MATH_SIMPLE 0 +#define MATH_FN 1 + +#define YYSTYPE int + + +typedef struct +{ + double **varTable_Values; + char **varTable_Names; + int varTable_numBlocks; + + int errVar; + int colCount; + int result; + char last_error_string[256]; + YYSTYPE yylval; + int yychar; /* the lookahead symbol */ + int yynerrs; /* number of parse errors so far */ + char yytext[256]; + char lastVar[256]; + + char *llsave[16]; /* Look ahead buffer */ + char llbuf[100]; /* work buffer */ + char *llp1;// = &llbuf[0]; /* pointer to next avail. in token */ + char *llp2;// = &llbuf[0]; /* pointer to end of lookahead */ + char *llend;// = &llbuf[0]; /* pointer to end of token */ + char *llebuf;// = &llbuf[sizeof llbuf]; + int lleof; + int yyline;// = 0; + + void *tmpblocks_head,*blocks_head; + int computTableTop; // make it abort on potential overflow =) + int l_stats[4]; // source bytes, static code bytes, call code bytes, data bytes + + void *userfunc_data[64]; +} +compileContext; + +typedef struct { + char *name; + void *afunc; + void *func_e; + int nParams; + NSEEL_PPPROC pProc; +} functionType; + + +extern functionType *nseel_getFunctionFromTable(int idx); + +int nseel_createCompiledValue(compileContext *ctx, double value, double *addrValue); +int nseel_createCompiledFunction1(compileContext *ctx, int fntype, int fn, int code); +int nseel_createCompiledFunction2(compileContext *ctx, int fntype, int fn, int code1, int code2); +int nseel_createCompiledFunction3(compileContext *ctx, int fntype, int fn, int code1, int code2, int code3); + +extern double nseel_globalregs[100]; + +void nseel_resetVars(compileContext *ctx); +double *nseel_getVarPtr(compileContext *ctx, char *varName); +double *nseel_registerVar(compileContext *ctx, char *varName); + + +// other shat + + + +int nseel_setVar(compileContext *ctx, int varNum); +int nseel_getVar(compileContext *ctx, int varNum); +void *nseel_compileExpression(compileContext *ctx, char *txt); + +#define VALUE 258 +#define IDENTIFIER 259 +#define FUNCTION1 260 +#define FUNCTION2 261 +#define FUNCTION3 262 +#define UMINUS 263 +#define UPLUS 264 + +int nseel_translate(compileContext *ctx, int type); +void nseel_count(compileContext *ctx); +void nseel_setLastVar(compileContext *ctx); +int nseel_lookup(compileContext *ctx, int *typeOfObject); +int nseel_yyerror(compileContext *ctx); +int nseel_yylex(compileContext *ctx, char **exp); +int nseel_yyparse(compileContext *ctx, char *exp); +void nseel_llinit(compileContext *ctx); +int nseel_gettoken(compileContext *ctx, char *lltb, int lltbsiz); + +struct lextab { + int llendst; /* Last state number */ + char *lldefault; /* Default state table */ + char *llnext; /* Next state table */ + char *llcheck; /* Check table */ + int *llbase; /* Base table */ + int llnxtmax; /* Last in next table */ + int (*llmove)(); /* Move between states */ + char *llfinal; /* Final state descriptions */ + int (*llactr)(); /* Action routine */ + int *lllook; /* Look ahead vector if != NULL */ + char *llign; /* Ignore char vec if != NULL */ + char *llbrk; /* Break char vec if != NULL */ + char *llill; /* Illegal char vec if != NULL */ +}; +extern struct lextab nseel_lextab; + + + +#ifdef __cplusplus +} +#endif + +#endif//__NS_EELINT_H__
\ No newline at end of file diff --git a/Src/ns-eel/ns-eel.h b/Src/ns-eel/ns-eel.h new file mode 100644 index 00000000..99ca617d --- /dev/null +++ b/Src/ns-eel/ns-eel.h @@ -0,0 +1,80 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + ns-eel.h: main application interface header + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef __NS_EEL_H__ +#define __NS_EEL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int NSEEL_init(); // returns 0 on success +#define NSEEL_addfunction(name,nparms,code,len) NSEEL_addfunctionex((name),(nparms),(code),(len),0) +void NSEEL_addfunctionex(char *name, int nparms, int code_startaddr, int code_len, void *pproc); +void NSEEL_quit(); +int *NSEEL_getstats(); // returns a pointer to 5 ints... source bytes, static code bytes, call code bytes, data bytes, number of code handles +double *NSEEL_getglobalregs(); + +typedef void *NSEEL_VMCTX; +typedef void *NSEEL_CODEHANDLE; + +NSEEL_VMCTX NSEEL_VM_alloc(); // return a handle +void NSEEL_VM_free(NSEEL_VMCTX ctx); // free when done with a VM and ALL of its code have been freed, as well + +void NSEEL_VM_resetvars(NSEEL_VMCTX ctx); +double *NSEEL_VM_regvar(NSEEL_VMCTX ctx, char *name); + +NSEEL_CODEHANDLE NSEEL_code_compile(NSEEL_VMCTX ctx, char *code); +char *NSEEL_code_getcodeerror(NSEEL_VMCTX ctx); +void NSEEL_code_execute(NSEEL_CODEHANDLE code); +void NSEEL_code_free(NSEEL_CODEHANDLE code); +int *NSEEL_code_getstats(NSEEL_CODEHANDLE code); // 4 ints...source bytes, static code bytes, call code bytes, data bytes + + + +// configuration: + + +//#define NSEEL_REENTRANT_EXECUTION +// defining this allows code to run in different threads at the same time +// this can be slower at times. + +//#define NSEEL_MAX_VARIABLE_NAMELEN 8 +// define this to override the max variable length (default is 8 bytes) + +//#define NSEEL_MAX_TEMPSPACE_ENTRIES 2048 +// define this to override the maximum working space in 8 byte units. +// 2048 is the default, and is way more than enough for most applications + + +//#define NSEEL_LOOPFUNC_SUPPORT +//#define NSEEL_LOOPFUNC_SUPPORT_MAXLEN (4096) +// define this for loop() support +// and define maxlen if you wish to override the maximum loop length (default is 4096 times) + +#ifdef __cplusplus +} +#endif + +#endif//__NS_EEL_H__
\ No newline at end of file diff --git a/Src/ns-eel/nseel-caltab.c b/Src/ns-eel/nseel-caltab.c new file mode 100644 index 00000000..b80cad2c --- /dev/null +++ b/Src/ns-eel/nseel-caltab.c @@ -0,0 +1,553 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + nseel-caltab.c + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "ns-eel-int.h" + +#define VALUE 258 +#define IDENTIFIER 259 +#define FUNCTION1 260 +#define FUNCTION2 261 +#define FUNCTION3 262 +#define UMINUS 263 +#define UPLUS 264 +#define YYSTYPE int + +#define YYERROR(x) nseel_yyerror(ctx) + +#define YYFINAL 51 +#define YYFLAG -32768 +#define YYNTBASE 21 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 264 ? yytranslate[x] : 26) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 14, 9, 2, 18, + 19, 12, 10, 20, 11, 2, 13, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 17, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 8, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 15, 16 +}; + + +static const short yyr1[] = { 0, + 21, 21, 22, 23, 23, 23, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 25, 25, 25 +}; + +static const short yyr2[] = { 0, + 1, 3, 1, 1, 1, 3, 1, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 1, 4, 6, 8 +}; + +static const short yydefact[] = { 0, + 3, 4, 0, 0, 0, 0, 0, 0, 5, 7, + 1, 17, 0, 0, 0, 0, 4, 16, 15, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, + 0, 6, 14, 13, 11, 12, 8, 9, 10, 18, + 0, 0, 0, 0, 19, 0, 0, 20, 0, 0, + 0 +}; + +static const short yydefgoto[] = { 49, + 9, 10, 11, 12 +}; + +static const short yypact[] = { 19, +-32768, -11, -7, -5, -4, 38, 38, 38,-32768,-32768, + 136,-32768, 38, 38, 38, 38,-32768,-32768,-32768, 88, + 38, 38, 38, 38, 38, 38, 38, 136, 100, 49, + 62,-32768, 41, 54, -9, -9,-32768,-32768,-32768,-32768, + 38, 38, 112, 75,-32768, 38, 124,-32768, 12, 27, +-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768, -6,-32768 +}; + + +#define YYLAST 150 + + +static const short yytable[] = { 18, + 19, 20, 25, 26, 27, 13, 28, 29, 30, 31, + 14, 50, 15, 16, 33, 34, 35, 36, 37, 38, + 39, 1, 2, 3, 4, 5, 51, 0, 6, 7, + 0, 0, 0, 0, 43, 44, 8, 0, 0, 47, + 1, 17, 3, 4, 5, 0, 0, 6, 7, 22, + 23, 24, 25, 26, 27, 8, 21, 22, 23, 24, + 25, 26, 27, 23, 24, 25, 26, 27, 41, 21, + 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, + 0, 42, 21, 22, 23, 24, 25, 26, 27, 0, + 0, 0, 0, 0, 46, 21, 22, 23, 24, 25, + 26, 27, 0, 0, 0, 0, 32, 21, 22, 23, + 24, 25, 26, 27, 0, 0, 0, 0, 40, 21, + 22, 23, 24, 25, 26, 27, 0, 0, 0, 0, + 45, 21, 22, 23, 24, 25, 26, 27, 0, 0, + 0, 0, 48, 21, 22, 23, 24, 25, 26, 27 +}; + +static const short yycheck[] = { 6, + 7, 8, 12, 13, 14, 17, 13, 14, 15, 16, + 18, 0, 18, 18, 21, 22, 23, 24, 25, 26, + 27, 3, 4, 5, 6, 7, 0, -1, 10, 11, + -1, -1, -1, -1, 41, 42, 18, -1, -1, 46, + 3, 4, 5, 6, 7, -1, -1, 10, 11, 9, + 10, 11, 12, 13, 14, 18, 8, 9, 10, 11, + 12, 13, 14, 10, 11, 12, 13, 14, 20, 8, + 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, + -1, 20, 8, 9, 10, 11, 12, 13, 14, -1, + -1, -1, -1, -1, 20, 8, 9, 10, 11, 12, + 13, 14, -1, -1, -1, -1, 19, 8, 9, 10, + 11, 12, 13, 14, -1, -1, -1, -1, 19, 8, + 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, + 19, 8, 9, 10, 11, 12, 13, 14, -1, -1, + -1, -1, 19, 8, 9, 10, 11, 12, 13, 14 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (ctx->yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#define YYLEX nseel_yylex(ctx,&exp) + +/* If nonreentrant, generate the variables here */ + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#define YYINITDEPTH 5000 +#define YYMAXDEPTH 5000 + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +#define __yy_bcopy(from,to,count) memcpy(to,from,(count)>0?(count):0) + +//#ln 131 "bison.simple" +int nseel_yyparse(compileContext *ctx, char *exp) +{ + int yystate; + int yyn; + short *yyssp; + YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + + int yystacksize = YYINITDEPTH; + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + + ctx->yylval = 0; + yystate = 0; + yyerrstatus = 0; + ctx->yynerrs = 0; + ctx->yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. */ + + yyssp = yyss - 1; + yyvsp = yyvs; + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + + if (yystacksize >= YYMAXDEPTH) + { + YYERROR("internal error: parser stack overflow"); + return 2; + } + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; + + + if (yyssp >= yyss + yystacksize - 1) YYABORT; + } + + +// yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (ctx->yychar == YYEMPTY) + { +// yyStackSize = yyssp - (yyss - 1); + ctx->yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (ctx->yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + ctx->yychar = YYEOF; /* Don't call YYLEX any more */ + + } + else + { + yychar1 = YYTRANSLATE(ctx->yychar); + + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + + + /* Discard the token being shifted unless it is eof. */ + if (ctx->yychar != YYEOF) + ctx->yychar = YYEMPTY; + + *++yyvsp = ctx->yylval; + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + + + switch (yyn) { + +case 1: +//#ln 32 "cal.y" +{ yyval = yyvsp[0]; ctx->result = yyvsp[0]; ; + break;} +case 2: +//#ln 34 "cal.y" +{ { + int i = (int)nseel_setVar(ctx,(int)yyvsp[-2]); + int v=nseel_getVar(ctx,i); + + yyval = nseel_createCompiledFunction2(ctx,MATH_SIMPLE, FN_ASSIGN, v, (int)yyvsp[0]); + ctx->result = yyval; + } + ; + break;} +case 3: +//#ln 50 "cal.y" +{ yyval = yyvsp[0] ; + break;} +case 4: +//#ln 55 "cal.y" +{ yyval = nseel_getVar(ctx,(int)yyvsp[0]);; + break;} +case 5: +//#ln 57 "cal.y" +{ yyval = yyvsp[0];; + break;} +case 6: +//#ln 59 "cal.y" +{ yyval = yyvsp[-1];; + break;} +case 7: +//#ln 64 "cal.y" +{ yyval = yyvsp[0]; ; + break;} +case 8: +//#ln 66 "cal.y" +{ yyval = nseel_createCompiledFunction2(ctx,MATH_SIMPLE, FN_MULTIPLY, yyvsp[-2], yyvsp[0]); + break;} +case 9: +//#ln 72 "cal.y" +{ yyval = nseel_createCompiledFunction2(ctx,MATH_SIMPLE, FN_DIVIDE, yyvsp[-2], yyvsp[0]); + break;} +case 10: +//#ln 78 "cal.y" +{ yyval = nseel_createCompiledFunction2(ctx,MATH_SIMPLE, FN_MODULO, yyvsp[-2], yyvsp[0]); + break;} +case 11: +//#ln 84 "cal.y" +{ yyval = nseel_createCompiledFunction2(ctx,MATH_SIMPLE, FN_ADD, yyvsp[-2], yyvsp[0]); + break;} +case 12: +//#ln 90 "cal.y" +{ yyval = nseel_createCompiledFunction2(ctx,MATH_SIMPLE, FN_SUB, yyvsp[-2], yyvsp[0]); + break;} +case 13: +//#ln 96 "cal.y" +{ yyval = nseel_createCompiledFunction2(ctx,MATH_SIMPLE, FN_AND, yyvsp[-2], yyvsp[0]); + break;} +case 14: +//#ln 102 "cal.y" +{ yyval = nseel_createCompiledFunction2(ctx,MATH_SIMPLE, FN_OR, yyvsp[-2], yyvsp[0]); + break;} +case 15: +//#ln 108 "cal.y" +{ yyval = nseel_createCompiledFunction1(ctx,MATH_SIMPLE, FN_UMINUS, yyvsp[0]); + break;} +case 16: +//#ln 114 "cal.y" +{ yyval = nseel_createCompiledFunction1(ctx,MATH_SIMPLE, FN_UPLUS, yyvsp[0]); + break;} +case 17: +//#ln 120 "cal.y" +{ yyval = yyvsp[0]; + break;} +case 18: +//#ln 125 "cal.y" +{ yyval = nseel_createCompiledFunction1(ctx,MATH_FN, (int)yyvsp[-3], yyvsp[-1]); + break;} +case 19: +//#ln 131 "cal.y" +{ yyval = nseel_createCompiledFunction2(ctx,MATH_FN, (int)yyvsp[-5], yyvsp[-3], yyvsp[-1]); + break;} +case 20: +//#ln 137 "cal.y" +{ yyval = nseel_createCompiledFunction3(ctx,MATH_FN, (int)yyvsp[-7], yyvsp[-5], yyvsp[-3], yyvsp[-1]); + break;} +} + /* the action file gets copied in in place of this dollarsign */ +//#ln 362 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; + + *++yyvsp = yyval; + + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++ctx->yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; +#error this should not compile + msg = (char *) xmalloc(size + 15); + strcpy(msg, "syntax error"); + + if (count < 5) + { + count = 0; + for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + YYERROR(msg); + free(msg); + } + else +#endif /* YYERROR_VERBOSE */ + YYERROR("syntax error"); + } + +//yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (ctx->yychar == YYEOF) YYABORT; + + ctx->yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; + + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = ctx->yylval; + + yystate = yyn; + goto yynewstate; +} diff --git a/Src/ns-eel/nseel-cfunc.c b/Src/ns-eel/nseel-cfunc.c new file mode 100644 index 00000000..919f9407 --- /dev/null +++ b/Src/ns-eel/nseel-cfunc.c @@ -0,0 +1,776 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + nseel-cfunc.c: assembly/C implementation of operator/function templates + This file should be ideally compiled with optimizations towards "minimize size" + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +#include <windows.h> +#include <math.h> +#include "ns-eel-int.h" + + +// these are used by our assembly code +static float g_cmpaddtab[2]={0.0,1.0}; +static float g_signs[2]={1.0,-1.0}; +static double g_closefact = 0.00001; +static float g_half=0.5; +static float negativezeropointfive=-0.5f; +static float onepointfive=1.5f; + + + +/// functions called by built code + +#define isnonzero(x) (fabs(x) > g_closefact) +#pragma optimize( "", off ) +//--------------------------------------------------------------------------------------------------------------- +static double NSEEL_CGEN_CALL _rand(double *x) +{ + if (*x < 1.0) *x=1.0; + return (double)(rand()%(int)max(*x,1.0)); +} + +//--------------------------------------------------------------------------------------------------------------- +static double NSEEL_CGEN_CALL _band(double *var, double *var2) +{ + return isnonzero(*var) && isnonzero(*var2) ? 1 : 0; +} + +//--------------------------------------------------------------------------------------------------------------- +static double NSEEL_CGEN_CALL _bor(double *var, double *var2) +{ + return isnonzero(*var) || isnonzero(*var2) ? 1 : 0; +} + +//--------------------------------------------------------------------------------------------------------------- +static double NSEEL_CGEN_CALL _sig(double *x, double *constraint) +{ + double t = (1+exp(-*x * (*constraint))); + return isnonzero(t) ? 1.0/t : 0; +} + + +// end functions called by inline code + +// these make room on the stack for local variables, but do not need to +// worry about trashing ebp, since none of our code uses ebp and there's +// a pushad+popad surrounding the call + + +static double (*__asin)(double) = &asin; +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_asin(void) +{ + FUNC1_ENTER + + *__nextBlock = __asin(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_asin_end(void) {} + +static double (*__acos)(double) = &acos; +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_acos(void) +{ + FUNC1_ENTER + + *__nextBlock = __acos(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_acos_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (*__atan)(double) = &atan; +__declspec ( naked ) void nseel_asm_atan(void) +{ + FUNC1_ENTER + + *__nextBlock = __atan(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_atan_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (*__atan2)(double,double) = &atan2; +__declspec ( naked ) void nseel_asm_atan2(void) +{ + FUNC2_ENTER + + *__nextBlock = __atan2(*parm_b, *parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_atan2_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +static double (NSEEL_CGEN_CALL * __sig)(double *,double *) = &_sig; +__declspec ( naked ) void nseel_asm_sig(void) +{ + FUNC2_ENTER + + *__nextBlock = __sig(parm_b, parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_sig_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (NSEEL_CGEN_CALL *__rand)(double *) = &_rand; +__declspec ( naked ) void nseel_asm_rand(void) +{ + FUNC1_ENTER + + *__nextBlock = __rand(parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_rand_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (NSEEL_CGEN_CALL *__band)(double *,double *) = &_band; +__declspec ( naked ) void nseel_asm_band(void) +{ + FUNC2_ENTER + + *__nextBlock = __band(parm_b, parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_band_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double ( NSEEL_CGEN_CALL *__bor)(double *,double *) = &_bor; +__declspec ( naked ) void nseel_asm_bor(void) +{ + FUNC2_ENTER + + *__nextBlock = __bor(parm_b, parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_bor_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (* __pow)(double,double) = &pow; +__declspec ( naked ) void nseel_asm_pow(void) +{ + FUNC2_ENTER + + *__nextBlock = __pow(*parm_b, *parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_pow_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +static double (*__exp)(double) = &exp; +__declspec ( naked ) void nseel_asm_exp(void) +{ + FUNC1_ENTER + + *__nextBlock = __exp(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_exp_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +//static double (*__floor)(double) = &floor; +__declspec ( naked ) void nseel_asm_floor(void) +{ + FUNC1_ENTER + + *__nextBlock = __floor(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_floor_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +//static double (*__ceil)(double) = &ceil; +__declspec ( naked ) void nseel_asm_ceil(void) +{ + FUNC1_ENTER + + *__nextBlock = __ceil(*parm_a); + + FUNC_LEAVE +} +__declspec ( naked ) void nseel_asm_ceil_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- + + + + +// do nothing, eh +__declspec ( naked ) void nseel_asm_exec2(void) +{ +} +__declspec ( naked ) void nseel_asm_exec2_end(void) { } + + + +__declspec ( naked ) void nseel_asm_invsqrt(void) +{ + __asm + { + fld qword ptr [eax] + + mov edx, 0x5f3759df + fst dword ptr [esi] + // floating point stack has input, as does [eax] + fmul dword ptr [negativezeropointfive] + mov ecx, [esi] + sar ecx, 1 + sub edx, ecx + mov [esi], edx + + // st(0) = input, [eax] has x + fmul dword ptr [esi] + + fmul dword ptr [esi] + + fadd dword ptr [onepointfive] + + fmul dword ptr [esi] + mov eax, esi + + fstp qword ptr [esi] + + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_invsqrt_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sin(void) +{ + __asm + { + fld qword ptr [eax] + fsin + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_sin_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_cos(void) +{ + __asm + { + fld qword ptr [eax] + fcos + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_cos_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_tan(void) +{ + __asm + { + fld qword ptr [eax] + fsincos + fdiv + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_tan_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sqr(void) +{ + __asm + { + fld qword ptr [eax] + fmul st(0), st(0) + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_sqr_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sqrt(void) +{ + __asm + { + fld qword ptr [eax] + fabs + fsqrt + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_sqrt_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_log(void) +{ + __asm + { + fld1 + fldl2e + fdiv + fld qword ptr [eax] + mov eax, esi + fyl2x + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_log_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_log10(void) +{ + __asm + { + fld1 + fldl2t + fdiv + fld qword ptr [eax] + mov eax, esi + fyl2x + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_log10_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_abs(void) +{ + __asm + { + fld qword ptr [eax] + fabs + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_abs_end(void) {} + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_assign(void) +{ + __asm + { + fld qword ptr [eax] + fstp qword ptr [ebx] + } +} +__declspec ( naked ) void nseel_asm_assign_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_add(void) +{ + __asm + { + fld qword ptr [eax] + fadd qword ptr [ebx] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_add_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sub(void) +{ + __asm + { + fld qword ptr [ebx] + fsub qword ptr [eax] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_sub_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_mul(void) +{ + __asm + { + fld qword ptr [ebx] + fmul qword ptr [eax] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_mul_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_div(void) +{ + __asm + { + fld qword ptr [ebx] + fdiv qword ptr [eax] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_div_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_mod(void) +{ + __asm + { + fld qword ptr [ebx] + + fld qword ptr [eax] + fsub dword ptr [g_cmpaddtab+4] + fabs + fadd qword ptr [eax] + fadd dword ptr [g_cmpaddtab+4] + + fmul dword ptr [g_half] + + fistp dword ptr [esi] + fistp dword ptr [esi+4] + mov eax, [esi+4] + xor edx, edx + div dword ptr [esi] + mov [esi], edx + fild dword ptr [esi] + mov eax, esi + fstp qword ptr [esi] + add esi, 8 + + } +} +__declspec ( naked ) void nseel_asm_mod_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_or(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + fistp qword ptr [esi] + fistp qword ptr [esi+8] + mov ebx, [esi+8] + or [esi], ebx + mov ebx, [esi+12] + or [esi+4], ebx + fild qword ptr [esi] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_or_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_and(void) +{ + __asm + { + fld qword ptr [ebx] + fld qword ptr [eax] + + fistp qword ptr [esi] + fistp qword ptr [esi+8] + mov ebx, [esi+8] + and [esi], ebx + mov ebx, [esi+12] + and [esi+4], ebx + fild qword ptr [esi] + fstp qword ptr [esi] + + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_and_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_uplus(void) // this is the same as doing nothing, it seems +{ +#if 0 + __asm + { + mov ebx, nextBlock + mov ecx, [eax] + mov [ebx], ecx + mov ecx, [eax+4] + mov [ebx+4], ecx + mov eax, ebx + add ebx, 8 + mov nextBlock, ebx + } +#endif +} +__declspec ( naked ) void nseel_asm_uplus_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_uminus(void) +{ + __asm + { + mov ecx, [eax] + mov ebx, [eax+4] + xor ebx, 0x80000000 + mov [esi], ecx + mov [esi+4], ebx + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_uminus_end(void) {} + + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_sign(void) +{ + __asm + { + mov ecx, [eax+4] + mov edx, [eax] + test edx, 0FFFFFFFFh + jnz nonzero + + // high dword (minus sign bit) is zero + test ecx, 07FFFFFFFh + jz zero // zero zero, return the value passed directly + +nonzero: + shr ecx, 31 + + fld dword ptr [g_signs+ecx*4] + + fstp qword ptr [esi] + + mov eax, esi + add esi, 8 +zero: + } +} +__declspec ( naked ) void nseel_asm_sign_end(void) {} + + + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_bnot(void) +{ + __asm + { + fld qword ptr [eax] + fabs + fcomp qword ptr [g_closefact] + fstsw ax + shr eax, 6 + and eax, (1<<2) + fld dword ptr [g_cmpaddtab+eax] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_bnot_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_if(void) +{ + __asm + { + fld qword ptr [eax] + fabs + fcomp qword ptr [g_closefact] + fstsw ax + + shr eax, 6 + + mov dword ptr [esi], 0FFFFFFFFh + mov dword ptr [esi+4], 0FFFFFFFFh + + and eax, (1<<2) + + mov eax, [esi+eax] + + call eax // call the proper function + + // at this point, the return value will be in eax, as desired + } +} +__declspec ( naked ) void nseel_asm_if_end(void) {} + +#ifdef NSEEL_LOOPFUNC_SUPPORT +#ifndef NSEEL_LOOPFUNC_SUPPORT_MAXLEN +#define NSEEL_LOOPFUNC_SUPPORT_MAXLEN (4096) +#endif +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_repeat(void) +{ + __asm + { + fld qword ptr [eax] + fistp dword ptr [esi] + mov ecx, [esi] + cmp ecx, 1 + jl skip + cmp ecx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN + jl again + mov ecx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN +again: + push ecx + push esi // revert back to last temp workspace + mov ecx, 0FFFFFFFFh + call ecx + pop esi + pop ecx + dec ecx + jnz again +skip: + } +} +__declspec ( naked ) void nseel_asm_repeat_end(void) {} +#endif + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_equal(void) +{ + __asm + { + fld qword ptr [eax] + fsub qword ptr [ebx] + fabs + fcomp qword ptr [g_closefact] + fstsw ax + shr eax, 6 + and eax, (1<<2) + fld dword ptr [g_cmpaddtab+eax] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_equal_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_below(void) +{ + __asm + { + fld qword ptr [ebx] + fcomp qword ptr [eax] + fstsw ax + shr eax, 6 + and eax, (1<<2) + fld dword ptr [g_cmpaddtab+eax] + + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_below_end(void) {} + +//--------------------------------------------------------------------------------------------------------------- +__declspec ( naked ) void nseel_asm_above(void) +{ + __asm + { + fld qword ptr [eax] + fcomp qword ptr [ebx] + fstsw ax + shr eax, 6 + and eax, (1<<2) + fld dword ptr [g_cmpaddtab+eax] + + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_above_end(void) {} + + +__declspec ( naked ) void nseel_asm_min(void) +{ + __asm + { + fld qword ptr [eax] + fld qword ptr [ebx] + fld st(1) + fsub st(0), st(1) + fabs // stack contains fabs(1-2),1,2 + fchs + fadd + fadd + fmul dword ptr [g_half] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_min_end(void) {} + +__declspec ( naked ) void nseel_asm_max(void) +{ + __asm + { + fld qword ptr [eax] + fld qword ptr [ebx] + fld st(1) + fsub st(0), st(1) + fabs // stack contains fabs(1-2),1,2 + fadd + fadd + fmul dword ptr [g_half] + fstp qword ptr [esi] + mov eax, esi + add esi, 8 + } +} +__declspec ( naked ) void nseel_asm_max_end(void) {} + +#pragma optimize( "", on )
\ No newline at end of file diff --git a/Src/ns-eel/nseel-compiler.c b/Src/ns-eel/nseel-compiler.c new file mode 100644 index 00000000..eb25ec5c --- /dev/null +++ b/Src/ns-eel/nseel-compiler.c @@ -0,0 +1,946 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + nseel-compiler.c + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +#include <windows.h> +#include "ns-eel-int.h" + +#ifdef NSEEL_REENTRANT_EXECUTION +#include <malloc.h> +#endif + +#define ltoupper(x) ((char)CharUpper((LPSTR)x)) +static int nseel_evallib_stats[5]; // source bytes, static code bytes, call code bytes, data bytes, segments +int *NSEEL_getstats() +{ + return nseel_evallib_stats; +} +double *NSEEL_getglobalregs() +{ + return nseel_globalregs; +} + +static size_t LLB_DSIZE=0; +//#define LLB_DSIZE (65536-64) +typedef struct _llBlockHeader +{ + struct _llBlock *next; + size_t sizeused; +} llBlockHeader; + +typedef struct _llBlock { + llBlockHeader header; + char block[1]; +} llBlock; + +typedef struct _startPtr { + struct _startPtr *next; + void *startptr; +} startPtr; + + + +typedef struct { + int workTablePtr_size; + + llBlock *blocks; + void *code; + int code_stats[4]; +} codeHandleType; + +#ifndef NSEEL_MAX_TEMPSPACE_ENTRIES +#define NSEEL_MAX_TEMPSPACE_ENTRIES 2048 +#endif + +static void *__newBlock(llBlock **start,size_t size); + +#define newTmpBlock(x) __newBlock((llBlock **)&ctx->tmpblocks_head,x) +#define newBlock(x) __newBlock((llBlock **)&ctx->blocks_head,x) + +static void freeBlocks(llBlock *start); + +void nseel_asm_sin(void); +void nseel_asm_sin_end(void); +void nseel_asm_cos(void); +void nseel_asm_cos_end(void); +void nseel_asm_tan(void); +void nseel_asm_tan_end(void); +void nseel_asm_asin(void); +void nseel_asm_asin_end(void); +void nseel_asm_acos(void); +void nseel_asm_acos_end(void); +void nseel_asm_atan(void); +void nseel_asm_atan_end(void); +void nseel_asm_atan2(void); +void nseel_asm_atan2_end(void); +void nseel_asm_sqr(void); +void nseel_asm_sqr_end(void); + +void nseel_asm_sqrt(void); +void nseel_asm_sqrt_end(void); +void nseel_asm_pow(void); +void nseel_asm_pow_end(void); +void nseel_asm_exp(void); +void nseel_asm_exp_end(void); +void nseel_asm_log(void); +void nseel_asm_log_end(void); +void nseel_asm_log10(void); +void nseel_asm_log10_end(void); +void nseel_asm_abs(void); +void nseel_asm_abs_end(void); +void nseel_asm_min(void); +void nseel_asm_min_end(void); +void nseel_asm_max(void); +void nseel_asm_max_end(void); +void nseel_asm_sig(void); +void nseel_asm_sig_end(void); +void nseel_asm_sign(void); +void nseel_asm_sign_end(void); +void nseel_asm_rand(void); +void nseel_asm_rand_end(void); +void nseel_asm_band(void); +void nseel_asm_band_end(void); +void nseel_asm_bor(void); +void nseel_asm_bor_end(void); +void nseel_asm_bnot(void); +void nseel_asm_bnot_end(void); +void nseel_asm_if(void); +void nseel_asm_if_end(void); +void nseel_asm_repeat(void); +void nseel_asm_repeat_end(void); +void nseel_asm_equal(void); +void nseel_asm_equal_end(void); +void nseel_asm_below(void); +void nseel_asm_below_end(void); +void nseel_asm_above(void); +void nseel_asm_above_end(void); +void nseel_asm_assign(void); +void nseel_asm_assign_end(void); +void nseel_asm_add(void); +void nseel_asm_add_end(void); +void nseel_asm_sub(void); +void nseel_asm_sub_end(void); +void nseel_asm_mul(void); +void nseel_asm_mul_end(void); +void nseel_asm_div(void); +void nseel_asm_div_end(void); +void nseel_asm_mod(void); +void nseel_asm_mod_end(void); +void nseel_asm_or(void); +void nseel_asm_or_end(void); +void nseel_asm_and(void); +void nseel_asm_and_end(void); +void nseel_asm_uplus(void); +void nseel_asm_uplus_end(void); +void nseel_asm_uminus(void); +void nseel_asm_uminus_end(void); +void nseel_asm_floor(void); +void nseel_asm_floor_end(void); +void nseel_asm_ceil(void); +void nseel_asm_ceil_end(void); +void nseel_asm_invsqrt(void); +void nseel_asm_invsqrt_end(void); +void nseel_asm_exec2(void); +void nseel_asm_exec2_end(void); + +/* +#define DECL_ASMFUNC(x) \ + void nseel_asm_##x##(void); \ + void nseel_asm_##x##_end(void); \ + + DECL_ASMFUNC(sin) + DECL_ASMFUNC(cos) + DECL_ASMFUNC(tan) + DECL_ASMFUNC(asin) + DECL_ASMFUNC(acos) + DECL_ASMFUNC(atan) + DECL_ASMFUNC(atan2) + DECL_ASMFUNC(sqr) + DECL_ASMFUNC(sqrt) + DECL_ASMFUNC(pow) + DECL_ASMFUNC(exp) + DECL_ASMFUNC(log) + DECL_ASMFUNC(log10) + DECL_ASMFUNC(abs) + DECL_ASMFUNC(min) + DECL_ASMFUNC(min) + DECL_ASMFUNC(max) + DECL_ASMFUNC(sig) + DECL_ASMFUNC(sign) + DECL_ASMFUNC(rand) + DECL_ASMFUNC(band) + DECL_ASMFUNC(bor) + DECL_ASMFUNC(bnot) + DECL_ASMFUNC(if) + DECL_ASMFUNC(repeat) + DECL_ASMFUNC(equal) + DECL_ASMFUNC(below) + DECL_ASMFUNC(above) + DECL_ASMFUNC(assign) + DECL_ASMFUNC(add) + DECL_ASMFUNC(sub) + DECL_ASMFUNC(mul) + DECL_ASMFUNC(div) + DECL_ASMFUNC(mod) + DECL_ASMFUNC(or) + DECL_ASMFUNC(and) + DECL_ASMFUNC(uplus) + DECL_ASMFUNC(uminus) + DECL_ASMFUNC(floor) + DECL_ASMFUNC(ceil) + DECL_ASMFUNC(invsqrt) + DECL_ASMFUNC(exec2) +*/ + +static functionType fnTable1[] = { + { "if", nseel_asm_if,nseel_asm_if_end, 3 }, +#ifdef NSEEL_LOOPFUNC_SUPPORT + { "loop", nseel_asm_repeat,nseel_asm_repeat_end, 2 }, +#endif + { "sin", nseel_asm_sin,nseel_asm_sin_end, 1 }, + { "cos", nseel_asm_cos,nseel_asm_cos_end, 1 }, + { "tan", nseel_asm_tan,nseel_asm_tan_end, 1 }, + { "asin", nseel_asm_asin,nseel_asm_asin_end, 1 }, + { "acos", nseel_asm_acos,nseel_asm_acos_end, 1 }, + { "atan", nseel_asm_atan,nseel_asm_atan_end, 1 }, + { "atan2", nseel_asm_atan2,nseel_asm_atan2_end, 2 }, + { "sqr", nseel_asm_sqr,nseel_asm_sqr_end, 1 }, + { "sqrt", nseel_asm_sqrt,nseel_asm_sqrt_end, 1 }, + { "pow", nseel_asm_pow,nseel_asm_pow_end, 2 }, + { "exp", nseel_asm_exp,nseel_asm_exp_end, 1 }, + { "log", nseel_asm_log,nseel_asm_log_end, 1 }, + { "log10", nseel_asm_log10,nseel_asm_log10_end, 1 }, + { "abs", nseel_asm_abs,nseel_asm_abs_end, 1 }, + { "min", nseel_asm_min,nseel_asm_min_end, 2 }, + { "max", nseel_asm_max,nseel_asm_max_end, 2 }, + { "sigmoid",nseel_asm_sig,nseel_asm_sig_end, 2 } , + { "sign", nseel_asm_sign,nseel_asm_sign_end, 1 } , + { "rand", nseel_asm_rand,nseel_asm_rand_end, 1 } , + { "band", nseel_asm_band,nseel_asm_band_end, 2 } , + { "bor", nseel_asm_bor,nseel_asm_bor_end, 2 } , + { "bnot", nseel_asm_bnot,nseel_asm_bnot_end, 1 } , + { "equal", nseel_asm_equal,nseel_asm_equal_end, 2 }, + { "below", nseel_asm_below,nseel_asm_below_end, 2 }, + { "above", nseel_asm_above,nseel_asm_above_end, 2 }, + { "floor", nseel_asm_floor,nseel_asm_floor_end, 1 }, + { "ceil", nseel_asm_ceil,nseel_asm_ceil_end, 1 }, + { "invsqrt", nseel_asm_invsqrt,nseel_asm_invsqrt_end, 1 }, + { "assign",nseel_asm_assign,nseel_asm_assign_end,2}, + { "exec2",nseel_asm_exec2,nseel_asm_exec2_end,2}, + { "exec3",nseel_asm_exec2,nseel_asm_exec2_end,3}, + }; + +static functionType *fnTableUser; +static int fnTableUser_size; + +functionType *nseel_getFunctionFromTable(int idx) +{ + if (idx<0) return 0; + if (idx>=sizeof(fnTable1)/sizeof(fnTable1[0])) + { + idx -= sizeof(fnTable1)/sizeof(fnTable1[0]); + if (!fnTableUser || idx >= fnTableUser_size) return 0; + return fnTableUser+idx; + } + return fnTable1+idx; +} + +int NSEEL_init() // returns 0 on success +{ + NSEEL_quit(); + return 0; +} + +void NSEEL_addfunctionex(char *name, int nparms, int code_startaddr, int code_len, void *pproc) +{ + if (!fnTableUser || !(fnTableUser_size&7)) + { + fnTableUser=(functionType *)realloc(fnTableUser,(fnTableUser_size+8)*sizeof(functionType)); + } + if (fnTableUser) + { + fnTableUser[fnTableUser_size].nParams = nparms; + fnTableUser[fnTableUser_size].name = name; + fnTableUser[fnTableUser_size].afunc = (void *)code_startaddr; + fnTableUser[fnTableUser_size].func_e = (void *)(code_startaddr + code_len); + fnTableUser[fnTableUser_size].pProc = (NSEEL_PPPROC) pproc; + fnTableUser_size++; + } +} + +void NSEEL_quit() +{ + free(fnTableUser); + fnTableUser_size=0; + fnTableUser=0; +} + +//--------------------------------------------------------------------------------------------------------------- +static void *realAddress(void *fn, void *fn_e, int *size) +{ +#ifdef DISABLED_DEBUG + char *ptr = (char *)fn; + int beg=(*(int *)(ptr+1))+5; + + int extrasize=(int)nseel_asm_exec2_end - (int)nseel_asm_exec2; + int extrabeg=(*(int *)(((char *)nseel_asm_exec2)+1))+5; + + *size=((int)fn_e - (int)fn) - (extrasize-extrabeg) - beg; + return ptr + beg; +#else + // Release Mode + *size = (int)fn_e - (int) fn; + return fn; +#endif +} + +//--------------------------------------------------------------------------------------------------------------- +static void freeBlocks(llBlock *start) +{ + while (start) + { + llBlock *llB = start->header.next; + VirtualFree(start, 0 /*LLB_DSIZE*/, MEM_RELEASE); + start=llB; + } +} + +//--------------------------------------------------------------------------------------------------------------- +static void *__newBlock(llBlock **start, size_t size) +{ + llBlock *llb = NULL; + size_t alloc_size = 0; + if (!LLB_DSIZE) + { + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + LLB_DSIZE = systemInfo.dwAllocationGranularity; + } + + if (*start && (LLB_DSIZE - (*start)->header.sizeused) >= size) + { + void *t=(*start)->block+(*start)->header.sizeused; + (*start)->header.sizeused+=size; + return t; + } + + alloc_size=LLB_DSIZE; + size+=sizeof(llBlockHeader); // make sure we have enough room for the block header; + while (size > alloc_size) alloc_size += LLB_DSIZE; + llb = (llBlock *)VirtualAlloc(NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + llb->header.sizeused=size; + llb->header.next = *start; + *start = llb; + return llb->block; +} + + +#define X86_MOV_EAX_DIRECTVALUE 0xB8 +#define X86_MOV_ESI_DIRECTVALUE 0xBE +#define X86_MOV_ESI_DIRECTMEMVALUE 0x358B +#define X86_PUSH_EAX 0x50 +#define X86_POP_EBX 0x5B +#define X86_POP_ECX 0x59 +#define X86_MOV_ESI_EDI 0xF78B + +#define X86_PUSH_ESI 0x56 +#define X86_POP_ESI 0x5E + +#define X86_RET 0xC3 + + +//--------------------------------------------------------------------------------------------------------------- +static int *findFBlock(char *p) +{ + while (*(int *)p != 0xFFFFFFFF) p++; + return (int*)p; +} + + +//--------------------------------------------------------------------------------------------------------------- +int nseel_createCompiledValue(compileContext *ctx, double value, double *addrValue) +{ + unsigned char *block = NULL; + double *dupValue = NULL; + + block=(unsigned char *)newTmpBlock(4+5); + + if (addrValue == NULL) + { + ctx->l_stats[3]+=sizeof(double); + *(dupValue = (double *)newBlock(sizeof(double))) = value; + } + else + dupValue = addrValue; + + ((int*)block)[0]=5; + block[4]=X86_MOV_EAX_DIRECTVALUE; // mov eax, <value> + *(int *)(block+5) = (int)dupValue; + + return ((int)(block)); + +} + +//--------------------------------------------------------------------------------------------------------------- +static int nseel_getFunctionAddress(int fntype, int fn, int *size, NSEEL_PPPROC *pProc) +{ + *pProc = NULL; + switch (fntype) + { + case MATH_SIMPLE: + switch (fn) + { + case FN_ASSIGN: + return (int)realAddress(nseel_asm_assign,nseel_asm_assign_end,size); + case FN_ADD: + return (int)realAddress(nseel_asm_add,nseel_asm_add_end,size); + case FN_SUB: + return (int)realAddress(nseel_asm_sub,nseel_asm_sub_end,size); + case FN_MULTIPLY: + return (int)realAddress(nseel_asm_mul,nseel_asm_mul_end,size); + case FN_DIVIDE: + return (int)realAddress(nseel_asm_div,nseel_asm_div_end,size); + case FN_MODULO: + return (int)realAddress(nseel_asm_mod,nseel_asm_mod_end,size); + case FN_AND: + return (int)realAddress(nseel_asm_and,nseel_asm_and_end,size); + case FN_OR: + return (int)realAddress(nseel_asm_or,nseel_asm_or_end,size); + case FN_UPLUS: + return (int)realAddress(nseel_asm_uplus,nseel_asm_uplus_end,size); + case FN_UMINUS: + return (int)realAddress(nseel_asm_uminus,nseel_asm_uminus_end,size); + } + case MATH_FN: + { + functionType *p=nseel_getFunctionFromTable(fn); + if (!p) + { + if (size) *size=0; + return 0; + } + if (p->pProc) *pProc=p->pProc; + return (int)realAddress(p->afunc,p->func_e,size); + } + } + return 0; +} + +//--------------------------------------------------------------------------------------------------------------- +int nseel_createCompiledFunction3(compileContext *ctx, int fntype, int fn, int code1, int code2, int code3) +{ + int sizes1=((int *)code1)[0]; + int sizes2=((int *)code2)[0]; + int sizes3=((int *)code3)[0]; + + if (fntype == MATH_FN && fn == 0) // special case: IF + { + void *func3 = NULL; + int size = 0; + int *ptr = NULL; + char *block = NULL; + + unsigned char *newblock2,*newblock3 = NULL; + + newblock2=newBlock(sizes2+1); + memcpy(newblock2,(char*)code2+4,sizes2); + newblock2[sizes2]=X86_RET; + + newblock3=newBlock(sizes3+1); + memcpy(newblock3,(char*)code3+4,sizes3); + newblock3[sizes3]=X86_RET; + + ctx->l_stats[2]+=sizes2+sizes3+2; + + func3 = realAddress(nseel_asm_if,nseel_asm_if_end,&size); + + block=(char *)newTmpBlock(4+sizes1+size); + ((int*)block)[0]=sizes1+size; + memcpy(block+4,(char*)code1+4,sizes1); + ptr=(int *)(block+4+sizes1); + memcpy(ptr,func3,size); + + ptr=findFBlock((char*)ptr); *ptr++=(int)newblock2; + ptr=findFBlock((char*)ptr); *ptr=(int)newblock3; + ctx->computTableTop++; + + return (int)block; + + } + else + { + int size2 = 0; + unsigned char *block = NULL; + unsigned char *outp = NULL; + + int myfunc = 0; + NSEEL_PPPROC preProc; + + myfunc = nseel_getFunctionAddress(fntype, fn, &size2, &preProc); + + block=(unsigned char *)newTmpBlock(4+size2+sizes1+sizes2+sizes3+4); + + ((int*)block)[0]=4+size2+sizes1+sizes2+sizes3; + outp=block+4; + memcpy(outp,(char*)code1+4,sizes1); + outp+=sizes1; + *outp++ = X86_PUSH_EAX; + memcpy(outp,(char*)code2+4,sizes2); + outp+=sizes2; + *outp++ = X86_PUSH_EAX; + memcpy(outp,(char*)code3+4,sizes3); + outp+=sizes3; + *outp++ = X86_POP_EBX; + *outp++ = X86_POP_ECX; + + memcpy(outp,(void*)myfunc,size2); + if (preProc) preProc(outp,size2,ctx->userfunc_data); + + ctx->computTableTop++; + + return ((int)(block)); + } +} + +//--------------------------------------------------------------------------------------------------------------- +int nseel_createCompiledFunction2(compileContext *ctx, int fntype, int fn, int code1, int code2) +{ + int size2 = 0; + unsigned char *block = NULL; + unsigned char *outp = NULL; + int myfunc = 0; + int sizes1=((int *)code1)[0]; + int sizes2=((int *)code2)[0]; + +#ifdef NSEEL_LOOPFUNC_SUPPORT + if (fntype == MATH_FN && fn == 1) // special case: REPEAT + { + void *func3 = NULL; + int size = 0; + int *ptr = NULL; + char *block = NULL; + + unsigned char *newblock2 = NULL; + + newblock2=newBlock(sizes2+1); + memcpy(newblock2,(char*)code2+4,sizes2); + newblock2[sizes2]=X86_RET; + + ctx->l_stats[2]+=sizes2+2; + + func3 = realAddress(nseel_asm_repeat,nseel_asm_repeat_end,&size); + + block=(char *)newTmpBlock(4+sizes1+size); + ((int*)block)[0]=sizes1+size; + memcpy(block+4,(char*)code1+4,sizes1); + ptr=(int *)(block+4+sizes1); + memcpy(ptr,func3,size); + + ptr=findFBlock((char*)ptr); *ptr++=(int)newblock2; + + ctx->computTableTop++; + return (int)block; + } + else +#endif + { + NSEEL_PPPROC preProc; + myfunc = nseel_getFunctionAddress(fntype, fn, &size2,&preProc); + + block=(unsigned char *)newTmpBlock(2+size2+sizes1+sizes2+4); + + ((int*)block)[0]=2+size2+sizes1+sizes2; + outp=block+4; + memcpy(outp,(char*)code1+4,sizes1); + outp+=sizes1; + *outp++ = X86_PUSH_EAX; + memcpy(outp,(char*)code2+4,sizes2); + outp+=sizes2; + *outp++ = X86_POP_EBX; + + memcpy(outp,(void*)myfunc,size2); + if (preProc) preProc(outp,size2,ctx->userfunc_data); + + ctx->computTableTop++; + + return ((int)(block)); + } +} + + +//--------------------------------------------------------------------------------------------------------------- +int nseel_createCompiledFunction1(compileContext *ctx, int fntype, int fn, int code) +{ + NSEEL_PPPROC preProc; + int size,size2 = 0; + char *block = NULL; + int myfunc = 0; + void *func1 = NULL; + + size =((int *)code)[0]; + func1 = (void *)(code+4); + + myfunc = nseel_getFunctionAddress(fntype, fn, &size2,&preProc); + + block=(char *)newTmpBlock(4+size+size2); + ((int*)block)[0]=size+size2; + + memcpy(block+4, func1, size); + memcpy(block+size+4,(void*)myfunc,size2); + if (preProc) preProc(block+size+4,size2,ctx->userfunc_data); + + ctx->computTableTop++; + + return ((int)(block)); +} + +static char *preprocessCode(compileContext *ctx, char *expression) +{ + int len=0; + int alloc_len=strlen(expression)+1+64; + char *buf=(char *)malloc(alloc_len); + + while (*expression) + { + if (len > alloc_len-32) + { + alloc_len = len+128; + buf=(char*)realloc(buf,alloc_len); + } + + if (expression[0] == '/') + { + if (expression[1] == '/') + { + expression+=2; + while (expression[0] && expression[0] != '\r' && expression[0] != '\n') expression++; + } + else if (expression[1] == '*') + { + expression+=2; + while (expression[0] && (expression[0] != '*' || expression[1] != '/')) expression++; + if (expression[0]) expression+=2; // at this point we KNOW expression[0]=* and expression[1]=/ + } + else + { + char c=buf[len++]=*expression++; + if (c != ' ' && c != '\t' && c != '\r' && c != '\n') ctx->l_stats[0]++; + } + } + else if (expression[0] == '$') + { + if (ltoupper(expression[1]) == 'P' && ltoupper(expression[2]) == 'I') + { + static char *str="3.141592653589793"; + expression+=3; + memcpy(buf+len,str,17); + len+=17; //strlen(str); + ctx->l_stats[0]+=17; + } + else if (ltoupper(expression[1]) == 'E') + { + static char *str="2.71828183"; + expression+=2; + memcpy(buf+len,str,10); + len+=10; //strlen(str); + ctx->l_stats[0]+=10; + } + if (ltoupper(expression[1]) == 'P' && ltoupper(expression[2]) == 'H' && ltoupper(expression[3]) == 'I') + { + static char *str="1.61803399"; + expression+=4; + memcpy(buf+len,str,10); + len+=10; //strlen(str); + ctx->l_stats[0]+=10; + } + else + { + char c = buf[len++]=*expression++; + if (c != ' ' && c != '\t' && c != '\r' && c != '\n') ctx->l_stats[0]++; + } + } + else + { + char c=*expression++; + if (c == '\r' || c == '\n' || c == '\t') c=' '; + buf[len++]=c; + if (c != ' ') ctx->l_stats[0]++; + } + } + buf[len]=0; + + return buf; +} + +static void movestringover(char *str, int amount) +{ + char tmp[1024+8]; + + int l=(int)strlen(str); + l=min(1024-amount-1,l); + + memcpy(tmp,str,l+1); + + while (l >= 0 && tmp[l]!='\n') l--; + l++; + + tmp[l]=0;//ensure we null terminate + + memcpy(str+amount,tmp,l+1); +} + +//------------------------------------------------------------------------------ +NSEEL_CODEHANDLE NSEEL_code_compile(NSEEL_VMCTX _ctx, char *_expression) +{ + compileContext *ctx = (compileContext *)_ctx; + char *expression,*expression_start; + int computable_size=0; + codeHandleType *handle; + startPtr *scode=NULL; + startPtr *startpts=NULL; + + if (!ctx || !_expression || !*_expression) return 0; + + ctx->last_error_string[0]=0; + ctx->blocks_head=0; + ctx->tmpblocks_head=0; + memset(ctx->l_stats,0, sizeof(ctx->l_stats) / sizeof(ctx->l_stats[0])); + + handle = (codeHandleType*)newBlock(sizeof(codeHandleType)); + + if (!handle) + { + return 0; + } + + memset(handle,0,sizeof(codeHandleType)); + + expression_start=expression=preprocessCode(ctx,_expression); + + while (*expression) + { + startPtr *tmp; + char *expr; + ctx->colCount=0; + + // single out segment + while (*expression == ';' || *expression == ' ') expression++; + if (!*expression) break; + expr=expression; + while (*expression && *expression != ';') expression++; + if (*expression) *expression++ = 0; + + // parse + tmp=(startPtr*) newTmpBlock(sizeof(startPtr)); + if (!tmp) break; + ctx->computTableTop=0; + tmp->startptr=nseel_compileExpression(ctx,expr); + + if (ctx->computTableTop > NSEEL_MAX_TEMPSPACE_ENTRIES- /* safety */ 16 - /* alignment */4 || + !tmp->startptr) + { + lstrcpyn(ctx->last_error_string,expr,sizeof(ctx->last_error_string)/sizeof(ctx->last_error_string[0])); + scode=NULL; + break; + } + if (computable_size < ctx->computTableTop) + { + computable_size=ctx->computTableTop; + } + + tmp->next=NULL; + if (!scode) scode=startpts=tmp; + else + { + scode->next=tmp; + scode=tmp; + } + } + + // check to see if failed on the first startingCode + if (!scode) + { + freeBlocks((llBlock *)ctx->blocks_head); // free blocks + handle=NULL; // return NULL (after resetting blocks_head) + } + else + { + // now we build one big code segment out of our list of them, inserting a mov esi, computable before each item + unsigned char *writeptr; + int size=1; // for ret at end :) + startPtr *p; + p=startpts; + while (p) + { + size+=2; // mov esi, edi + size+=*(int *)p->startptr; + p=p->next; + } + handle->code = newBlock(size); + if (handle->code) + { + writeptr=(unsigned char *)handle->code; + p=startpts; + while (p) + { + int thissize=*(int *)p->startptr; + *(unsigned short *)writeptr= X86_MOV_ESI_EDI; + writeptr+=2; + memcpy(writeptr,(char*)p->startptr + 4,thissize); + writeptr += thissize; + + p=p->next; + } + *writeptr=X86_RET; // ret + ctx->l_stats[1]=size; + } + handle->blocks = ctx->blocks_head; + handle->workTablePtr_size=(computable_size) * sizeof(double); + } + freeBlocks((llBlock *)ctx->tmpblocks_head); // free blocks + ctx->tmpblocks_head=0; + + ctx->blocks_head=0; + + if (handle) + { + memcpy(handle->code_stats,ctx->l_stats,sizeof(ctx->l_stats)); + nseel_evallib_stats[0]+=ctx->l_stats[0]; + nseel_evallib_stats[1]+=ctx->l_stats[1]; + nseel_evallib_stats[2]+=ctx->l_stats[2]; + nseel_evallib_stats[3]+=ctx->l_stats[3]; + nseel_evallib_stats[4]++; + } + memset(ctx->l_stats,0,sizeof(ctx->l_stats)); + + free(expression_start); + + return (NSEEL_CODEHANDLE)handle; +} + +//------------------------------------------------------------------------------ +void NSEEL_code_execute(NSEEL_CODEHANDLE code) +{ +#ifdef NSEEL_REENTRANT_EXECUTION + int baseptr; +#else + static double _tab[NSEEL_MAX_TEMPSPACE_ENTRIES]; + int baseptr = (int) _tab; +#endif + codeHandleType *h = (codeHandleType *)code; + + if (!h || !h->code) + return; + +#ifdef NSEEL_REENTRANT_EXECUTION + baseptr = (int) alloca(h->workTablePtr_size + 16*sizeof(double) /*safety*/ + 32 /*alignment*/); + + if (!baseptr) + return; +#endif + + { + int startPoint=(int)h->code; + __asm + { + mov ebx, baseptr + mov eax, startPoint + pushad // Lets cover our ass + add ebx, 31 + and ebx, ~31 + mov edi, ebx + call eax + popad + } + } +} + +char *NSEEL_code_getcodeerror(NSEEL_VMCTX ctx) +{ + compileContext *c=(compileContext *)ctx; + if (ctx && c->last_error_string[0]) return c->last_error_string; + return 0; +} + +//------------------------------------------------------------------------------ +void NSEEL_code_free(NSEEL_CODEHANDLE code) +{ + codeHandleType *h = (codeHandleType *)code; + if (h != NULL) + { + nseel_evallib_stats[0]-=h->code_stats[0]; + nseel_evallib_stats[1]-=h->code_stats[1]; + nseel_evallib_stats[2]-=h->code_stats[2]; + nseel_evallib_stats[3]-=h->code_stats[3]; + nseel_evallib_stats[4]--; + freeBlocks(h->blocks); + } +} + + +//------------------------------------------------------------------------------ +void NSEEL_VM_resetvars(NSEEL_VMCTX _ctx) +{ + if (_ctx) + { + compileContext *ctx=(compileContext *)_ctx; + int x; + if (ctx->varTable_Names || ctx->varTable_Values) for (x = 0; x < ctx->varTable_numBlocks; x ++) + { + if (ctx->varTable_Names) + free(ctx->varTable_Names[x]); + + if (ctx->varTable_Values) + free(ctx->varTable_Values[x]); + } + + free(ctx->varTable_Values); + free(ctx->varTable_Names); + ctx->varTable_Values=0; + ctx->varTable_Names=0; + + ctx->varTable_numBlocks=0; + } +} + + +NSEEL_VMCTX NSEEL_VM_alloc() // return a handle +{ + compileContext *ctx=calloc(1,sizeof(compileContext)); + return ctx; +} + +void NSEEL_VM_free(NSEEL_VMCTX ctx) // free when done with a VM and ALL of its code have been freed, as well +{ + free(ctx); +} + +int *NSEEL_code_getstats(NSEEL_CODEHANDLE code) +{ + codeHandleType *h = (codeHandleType *)code; + if (h) + { + return h->code_stats; + } + return 0; +}
\ No newline at end of file diff --git a/Src/ns-eel/nseel-eval.c b/Src/ns-eel/nseel-eval.c new file mode 100644 index 00000000..2259fca4 --- /dev/null +++ b/Src/ns-eel/nseel-eval.c @@ -0,0 +1,282 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + nseel-eval.c + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include <windows.h> +#include "ns-eel-int.h" + +#define NSEEL_VARS_PER_BLOCK 64 +#define NSEEL_VARS_MALLOC_CHUNKSIZE 8 +#define NSEEL_GLOBALVAR_BASE (1<<24) + +#ifndef NSEEL_MAX_VARIABLE_NAMELEN +#define NSEEL_MAX_VARIABLE_NAMELEN 8 +#endif + + +#define INTCONST 1 +#define DBLCONST 2 +#define HEXCONST 3 +#define VARIABLE 4 +#define OTHER 5 + +double nseel_globalregs[100]; + +//------------------------------------------------------------------------------ +void *nseel_compileExpression(compileContext *ctx, char *exp) +{ + ctx->errVar=0; + nseel_llinit(ctx); + if (!nseel_yyparse(ctx,exp) && !ctx->errVar) + { + return (void*)ctx->result; + } + return 0; +} + +//------------------------------------------------------------------------------ +void nseel_setLastVar(compileContext *ctx) +{ + nseel_gettoken(ctx,ctx->lastVar, sizeof(ctx->lastVar)); +} + +static int register_var(compileContext *ctx, char *name, double **ptr) +{ + int wb; + int ti=0; + int i=0; + char *nameptr; + for (wb = 0; wb < ctx->varTable_numBlocks; wb ++) + { + int namepos=0; + for (ti = 0; ti < NSEEL_VARS_PER_BLOCK; ti ++) + { + if (!ctx->varTable_Names[wb][namepos] || !_strnicmp(ctx->varTable_Names[wb]+namepos,name,NSEEL_MAX_VARIABLE_NAMELEN)) + { + break; + } + namepos += NSEEL_MAX_VARIABLE_NAMELEN; + i++; + } + if (ti < NSEEL_VARS_PER_BLOCK) + break; + } + if (wb == ctx->varTable_numBlocks) + { + ti=0; + // add new block + if (!(ctx->varTable_numBlocks&(NSEEL_VARS_MALLOC_CHUNKSIZE-1)) || !ctx->varTable_Values || !ctx->varTable_Names ) + { + ctx->varTable_Values = (double **)realloc(ctx->varTable_Values,(ctx->varTable_numBlocks+NSEEL_VARS_MALLOC_CHUNKSIZE) * sizeof(double *)); + ctx->varTable_Names = (char **)realloc(ctx->varTable_Names,(ctx->varTable_numBlocks+NSEEL_VARS_MALLOC_CHUNKSIZE) * sizeof(char *)); + } + ctx->varTable_numBlocks++; + + ctx->varTable_Values[wb] = (double *)calloc(sizeof(double),NSEEL_VARS_PER_BLOCK); + ctx->varTable_Names[wb] = (char *)calloc(NSEEL_MAX_VARIABLE_NAMELEN,NSEEL_VARS_PER_BLOCK); + } + + nameptr=ctx->varTable_Names[wb]+ti*NSEEL_MAX_VARIABLE_NAMELEN; + if (!nameptr[0]) + { + strncpy(nameptr,name,NSEEL_MAX_VARIABLE_NAMELEN); + } + if (ptr) *ptr = ctx->varTable_Values[wb] + ti; + return i; +} + +//------------------------------------------------------------------------------ +int nseel_setVar(compileContext *ctx, int varNum) +{ + if (varNum < 0) // adding new var + { + char *var=ctx->lastVar; + if (!_strnicmp(var,"reg",3) && strlen(var) == 5 && isdigit(var[3]) && isdigit(var[4])) + { + int i,x=atoi(var+3); + if (x < 0 || x > 99) x=0; + i=NSEEL_GLOBALVAR_BASE+x; + return i; + } + + return register_var(ctx,ctx->lastVar,NULL); + + } + + // setting/getting oldvar + + if (varNum >= NSEEL_GLOBALVAR_BASE && varNum < NSEEL_GLOBALVAR_BASE+100) + { + return varNum; + } + + { + int wb,ti; + char *nameptr; + if (varNum < 0 || varNum >= ctx->varTable_numBlocks*NSEEL_VARS_PER_BLOCK) return -1; + + wb=varNum/NSEEL_VARS_PER_BLOCK; + ti=(varNum%NSEEL_VARS_PER_BLOCK); + nameptr=ctx->varTable_Names[wb]+ti*NSEEL_MAX_VARIABLE_NAMELEN; + if (!nameptr[0]) + { + strncpy(nameptr,ctx->lastVar,NSEEL_MAX_VARIABLE_NAMELEN); + } + return varNum; + } + +} + +//------------------------------------------------------------------------------ +int nseel_getVar(compileContext *ctx, int i) +{ + if (i >= 0 && i < (NSEEL_VARS_PER_BLOCK*ctx->varTable_numBlocks)) + return nseel_createCompiledValue(ctx,0, ctx->varTable_Values[i/NSEEL_VARS_PER_BLOCK] + i%NSEEL_VARS_PER_BLOCK); + if (i >= NSEEL_GLOBALVAR_BASE && i < NSEEL_GLOBALVAR_BASE+100) + return nseel_createCompiledValue(ctx,0, nseel_globalregs+i-NSEEL_GLOBALVAR_BASE); + + return nseel_createCompiledValue(ctx,0, NULL); +} + + + +//------------------------------------------------------------------------------ +double *NSEEL_VM_regvar(NSEEL_VMCTX _ctx, char *var) +{ + compileContext *ctx = (compileContext *)_ctx; + double *r; + if (!ctx) return 0; + + if (!_strnicmp(var,"reg",3) && strlen(var) == 5 && isdigit(var[3]) && isdigit(var[4])) + { + int x=atoi(var+3); + if (x < 0 || x > 99) x=0; + return nseel_globalregs + x; + } + + register_var(ctx,var,&r); + + return r; +} + +//------------------------------------------------------------------------------ +int nseel_translate(compileContext *ctx, int type) +{ + int v; + int n; + *ctx->yytext = 0; + nseel_gettoken(ctx,ctx->yytext, sizeof(ctx->yytext)); + + switch (type) + { + case INTCONST: return nseel_createCompiledValue(ctx,(double)atoi(ctx->yytext), NULL); + case DBLCONST: return nseel_createCompiledValue(ctx,(double)atof(ctx->yytext), NULL); + case HEXCONST: + v=0; + n=0; + while (1) + { + int a=ctx->yytext[n++]; + if (a >= '0' && a <= '9') v+=a-'0'; + else if (a >= 'A' && a <= 'F') v+=10+a-'A'; + else if (a >= 'a' && a <= 'f') v+=10+a-'a'; + else break; + v<<=4; + } + return nseel_createCompiledValue(ctx,(double)v, NULL); + } + return 0; +} + +//------------------------------------------------------------------------------ +int nseel_lookup(compileContext *ctx, int *typeOfObject) +{ + int i; + nseel_gettoken(ctx,ctx->yytext, sizeof(ctx->yytext)); + + if (!_strnicmp(ctx->yytext,"reg",3) && strlen(ctx->yytext) == 5 && isdigit(ctx->yytext[3]) && isdigit(ctx->yytext[4]) && (i=atoi(ctx->yytext+3))>=0 && i<100) + { + *typeOfObject=IDENTIFIER; + return i+NSEEL_GLOBALVAR_BASE; + } + + + { + int wb; + int ti=0; + i=0; + for (wb = 0; wb < ctx->varTable_numBlocks; wb ++) + { + int namepos=0; + for (ti = 0; ti < NSEEL_VARS_PER_BLOCK; ti ++) + { + if (!ctx->varTable_Names[wb][namepos]) break; + + if (!_strnicmp(ctx->varTable_Names[wb]+namepos,ctx->yytext,NSEEL_MAX_VARIABLE_NAMELEN)) + { + *typeOfObject = IDENTIFIER; + return i; + } + + namepos += NSEEL_MAX_VARIABLE_NAMELEN; + i++; + } + if (ti < NSEEL_VARS_PER_BLOCK) break; + } + } + + + for (i=0;nseel_getFunctionFromTable(i);i++) + { + functionType *f=nseel_getFunctionFromTable(i); + if (!strcmpi(f->name, ctx->yytext)) + { + switch (f->nParams) + { + case 1: *typeOfObject = FUNCTION1; break; + case 2: *typeOfObject = FUNCTION2; break; + case 3: *typeOfObject = FUNCTION3; break; + default: *typeOfObject = IDENTIFIER; break; + } + return i; + } + } + *typeOfObject = IDENTIFIER; + nseel_setLastVar(ctx); + return nseel_setVar(ctx,-1); +} + + + +//--------------------------------------------------------------------------- +void nseel_count(compileContext *ctx) +{ + nseel_gettoken(ctx,ctx->yytext, sizeof(ctx->yytext)); + ctx->colCount+=strlen(ctx->yytext); +} + +//--------------------------------------------------------------------------- +int nseel_yyerror(compileContext *ctx) +{ + ctx->errVar = ctx->colCount; + return 0; +}
\ No newline at end of file diff --git a/Src/ns-eel/nseel-lextab.c b/Src/ns-eel/nseel-lextab.c new file mode 100644 index 00000000..cc71be8a --- /dev/null +++ b/Src/ns-eel/nseel-lextab.c @@ -0,0 +1,265 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + nseel-lextab.c + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "ns-eel-int.h" + + +#define LEXSKIP (-1) + +static int _lmovb(struct lextab *lp, int c, int st) +{ + int base; + + while ((base = lp->llbase[st]+c) > lp->llnxtmax || + (lp->llcheck[base] & 0377) != st) { + + if (st != lp->llendst) { + base = lp->lldefault[st] & 0377; + st = base; + } + else + return(-1); + } + return(lp->llnext[base]&0377); +} + +#define INTCONST 1 +#define DBLCONST 2 +#define HEXCONST 3 +#define VARIABLE 4 +#define OTHER 5 + +static int _Alextab(compileContext *ctx, int __na__) +{ + if (__na__ >= 0 && __na__ <= 19) nseel_count(ctx); + switch (__na__) + { + case 0: ctx->yylval = nseel_translate(ctx,HEXCONST); return VALUE; + case 1: ctx->yylval = nseel_translate(ctx,INTCONST); return VALUE; + case 2: ctx->yylval = nseel_translate(ctx,INTCONST); return VALUE; + case 3: ctx->yylval = nseel_translate(ctx,DBLCONST); return VALUE; + case 4: + case 5: nseel_setLastVar(ctx); ctx->yylval = nseel_lookup(ctx,&__na__); return __na__; + case 6: return '+'; + case 7: return '-'; + case 8: return '*'; + case 9: return '/'; + case 10: return '%'; + case 11: return '&'; + case 12: return '|'; + case 13: return '('; + case 14: return ')'; + case 15: return '='; + case 16: return ','; + case 17: return ';'; + } + return (LEXSKIP); +} + + +static char _Flextab[] = + { + 1, 18, 17, 16, 15, 14, 13, 12, + 11, 10, 9, 8, 7, 6, 4, 5, + 5, 4, 4, 3, 3, 3, 3, 4, + 0, 4, 5, 0, 5, 4, 1, 3, + 0, 2, -1, 1, -1, + }; + + +static char _Nlextab[] = + { + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 1, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 1, 36, 36, 36, 36, 9, 8, 36, + 6, 5, 11, 13, 3, 12, 19, 10, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 36, 2, 36, 4, 36, 36, + 36, 29, 29, 29, 29, 29, 29, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 36, 36, 36, 36, 18, + 36, 29, 29, 29, 29, 29, 23, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 14, 18, + 18, 18, 18, 36, 7, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 36, + 36, 36, 36, 36, 36, 36, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 36, 36, 36, 36, 17, 36, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 36, 36, 36, 36, 36, 36, + 36, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 36, 36, 36, 36, 16, + 36, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 36, + 20, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 36, 36, 36, 36, 36, + 36, 36, 25, 25, 25, 25, 25, 25, + 36, 24, 36, 36, 36, 36, 36, 36, + 20, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 25, 25, 25, 25, 25, 25, + 36, 24, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 36, 36, 36, 36, + 36, 36, 36, 28, 28, 28, 28, 28, + 28, 36, 27, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 28, 28, 28, 28, 28, + 28, 31, 27, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 36, 36, 36, + 36, 36, 36, 36, 34, 34, 34, 33, + 34, 34, 36, 32, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 34, 34, 34, 33, + 34, 34, 36, 32, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 36, 36, + 36, 36, 36, 36, 36, 34, 34, 34, + 34, 34, 34, 36, 32, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 34, 34, 34, + 34, 34, 34, 36, 32, + }; + +static char _Clextab[] = + { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, 0, 0, -1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -1, 0, -1, 0, -1, -1, + -1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -1, -1, -1, -1, 0, + -1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -1, 0, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, -1, + -1, -1, -1, -1, -1, -1, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + -1, -1, -1, -1, 14, -1, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, -1, -1, -1, -1, -1, -1, + -1, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, -1, -1, -1, -1, 15, + -1, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, -1, + 19, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, -1, -1, -1, -1, -1, + -1, -1, 23, 23, 23, 23, 23, 23, + -1, 23, -1, -1, -1, -1, -1, -1, + 19, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 23, 23, 23, 23, 23, 23, + -1, 23, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, -1, -1, -1, -1, + -1, -1, -1, 26, 26, 26, 26, 26, + 26, -1, 26, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 26, 26, 26, 26, 26, + 26, 30, 26, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, -1, -1, -1, + -1, -1, -1, -1, 30, 30, 30, 30, + 30, 30, -1, 30, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 30, 30, 30, 30, + 30, 30, -1, 30, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, -1, -1, + -1, -1, -1, -1, -1, 33, 33, 33, + 33, 33, 33, -1, 33, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 33, 33, 33, + 33, 33, 33, -1, 33, + }; + +static char _Dlextab[] = + { + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 15, 14, 14, 36, 36, 20, 19, 14, + 14, 23, 15, 15, 26, 23, 36, 19, + 36, 36, 33, 30, + }; + +static int _Blextab[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 77, 152, + 0, 0, 0, 227, 237, 0, 0, 249, + 0, 0, 306, 0, 0, 0, 363, 0, + 0, 420, 0, 0, 0, + }; + +struct lextab nseel_lextab = { + 36, + _Dlextab, + _Nlextab, + _Clextab, + _Blextab, + 524, + _lmovb, + _Flextab, + _Alextab, + + 0, + 0, + 0, + 0, + }; + + diff --git a/Src/ns-eel/nseel-yylex.c b/Src/ns-eel/nseel-yylex.c new file mode 100644 index 00000000..073f449d --- /dev/null +++ b/Src/ns-eel/nseel-yylex.c @@ -0,0 +1,162 @@ +/* + Nullsoft Expression Evaluator Library (NS-EEL) + Copyright (C) 1999-2003 Nullsoft, Inc. + + nseel-yylex.c + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "ns-eel-int.h" + + +#define NBPW 16 +#define EOF (-1) + + +#define ERROR 256 /* yacc's value */ + +static int llset(compileContext *ctx); +static int llinp(compileContext *ctx, char **exp); +static int lexgetc(char **exp) +{ + char c= **exp; + if (c) (*exp)++; + return( c != 0 ? c : -1); +} +static int tst__b(register int c, char tab[]) +{ + return (tab[(c >> 3) & 037] & (1 << (c & 07)) ); +} + +int nseel_gettoken(compileContext *ctx, char *lltb, int lltbsiz) +{ + register char *lp, *tp, *ep; + + tp = lltb; + ep = tp+lltbsiz-1; + for (lp = ctx->llbuf; lp < ctx->llend && tp < ep;) + *tp++ = *lp++; + *tp = 0; + return(tp-lltb); +} + + +int nseel_yylex(compileContext *ctx, char **exp) +{ + register int c, st; + int final, l, llk, i; + register struct lextab *lp; + char *cp; + + while (1) + { + llk = 0; + if (llset(ctx)) return(0); + st = 0; + final = -1; + lp = &nseel_lextab; + + do { + if (lp->lllook && (l = lp->lllook[st])) { + for (c=0; c<NBPW; c++) + if (l&(1<<c)) + ctx->llsave[c] = ctx->llp1; + llk++; + } + if ((i = lp->llfinal[st]) != -1) { + final = i; + ctx->llend = ctx->llp1; + } + if ((c = llinp(ctx,exp)) < 0) + break; + if ((cp = lp->llbrk) && llk==0 && tst__b(c, cp)) { + ctx->llp1--; + break; + } + } while ((st = (*lp->llmove)(lp, c, st)) != -1); + + + if (ctx->llp2 < ctx->llp1) + ctx->llp2 = ctx->llp1; + if (final == -1) { + ctx->llend = ctx->llp1; + if (st == 0 && c < 0) + return(0); + if ((cp = lp->llill) && tst__b(c, cp)) { + continue; + } + return(ERROR); + } + if (c = (final >> 11) & 037) + ctx->llend = ctx->llsave[c-1]; + if ((c = (*lp->llactr)(ctx,final&03777)) >= 0) + return(c); + } +} + +void nseel_llinit(compileContext *ctx) +{ + ctx->llp1 = ctx->llp2 = ctx->llend = ctx->llbuf; + ctx->llebuf = ctx->llbuf + sizeof(ctx->llbuf); + ctx->lleof = ctx->yyline = 0; +} + + +static int llinp(compileContext *ctx, char **exp) +{ + register c; + register struct lextab *lp; + register char *cp; + + lp = &nseel_lextab; + cp = lp->llign; /* Ignore class */ + for (;;) { + /* + * Get the next character from the save buffer (if possible) + * If the save buffer's empty, then return EOF or the next + * input character. Ignore the character if it's in the + * ignore class. + */ + c = (ctx->llp1 < ctx->llp2) ? *ctx->llp1 & 0377 : (ctx->lleof) ? EOF : lexgetc(exp); + if (c >= 0) { /* Got a character? */ + if (cp && tst__b(c, cp)) + continue; /* Ignore it */ + if (ctx->llp1 >= ctx->llebuf) { /* No, is there room? */ + return -1; + } + *ctx->llp1++ = c; /* Store in token buff */ + } else + ctx->lleof = 1; /* Set EOF signal */ + return(c); + } +} + +static int llset(compileContext *ctx) +/* + * Return TRUE if EOF and nothing was moved in the look-ahead buffer + */ +{ + register char *lp1, *lp2; + + for (lp1 = ctx->llbuf, lp2 = ctx->llend; lp2 < ctx->llp2;) + *lp1++ = *lp2++; + ctx->llend = ctx->llp1 = ctx->llbuf; + ctx->llp2 = lp1; + return(ctx->lleof && lp1 == ctx->llbuf); +} |