mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-17 17:25:47 -04:00
Initial community commit
This commit is contained in:
80
Src/ns-eel/megabuf.c
Normal file
80
Src/ns-eel/megabuf.c
Normal file
@ -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) {}
|
21
Src/ns-eel/megabuf.h
Normal file
21
Src/ns-eel/megabuf.h
Normal file
@ -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
|
90
Src/ns-eel/ns-eel-addfuncs.h
Normal file
90
Src/ns-eel/ns-eel-addfuncs.h
Normal file
@ -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__
|
156
Src/ns-eel/ns-eel-int.h
Normal file
156
Src/ns-eel/ns-eel-int.h
Normal file
@ -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__
|
80
Src/ns-eel/ns-eel.h
Normal file
80
Src/ns-eel/ns-eel.h
Normal file
@ -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__
|
553
Src/ns-eel/nseel-caltab.c
Normal file
553
Src/ns-eel/nseel-caltab.c
Normal file
@ -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;
|
||||
}
|
776
Src/ns-eel/nseel-cfunc.c
Normal file
776
Src/ns-eel/nseel-cfunc.c
Normal file
@ -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 )
|
946
Src/ns-eel/nseel-compiler.c
Normal file
946
Src/ns-eel/nseel-compiler.c
Normal file
@ -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;
|
||||
}
|
282
Src/ns-eel/nseel-eval.c
Normal file
282
Src/ns-eel/nseel-eval.c
Normal file
@ -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;
|
||||
}
|
265
Src/ns-eel/nseel-lextab.c
Normal file
265
Src/ns-eel/nseel-lextab.c
Normal file
@ -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,
|
||||
};
|
||||
|
||||
|
162
Src/ns-eel/nseel-yylex.c
Normal file
162
Src/ns-eel/nseel-yylex.c
Normal file
@ -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);
|
||||
}
|
Reference in New Issue
Block a user