mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-17 10:35:46 -04:00
Initial community commit
This commit is contained in:
1511
Src/ns-eel2/asm-nseel-ppc-gcc.c
Normal file
1511
Src/ns-eel2/asm-nseel-ppc-gcc.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Src/ns-eel2/asm-nseel-x64-macho.o
Normal file
BIN
Src/ns-eel2/asm-nseel-x64-macho.o
Normal file
Binary file not shown.
2153
Src/ns-eel2/asm-nseel-x86-gcc.c
Normal file
2153
Src/ns-eel2/asm-nseel-x86-gcc.c
Normal file
File diff suppressed because it is too large
Load Diff
4101
Src/ns-eel2/asm-nseel-x86-msvc.c
Normal file
4101
Src/ns-eel2/asm-nseel-x86-msvc.c
Normal file
File diff suppressed because it is too large
Load Diff
260
Src/ns-eel2/denormal.h
Normal file
260
Src/ns-eel2/denormal.h
Normal file
@ -0,0 +1,260 @@
|
||||
#ifndef _WDL_DENORMAL_H_
|
||||
#define _WDL_DENORMAL_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#ifdef __ppc__ // todo: other big endian platforms...
|
||||
unsigned int hw;
|
||||
unsigned int lw;
|
||||
#else
|
||||
unsigned int lw;
|
||||
unsigned int hw;
|
||||
#endif
|
||||
} WDL_DenormalTwoInts;
|
||||
|
||||
typedef union { double fl; WDL_DenormalTwoInts w; } WDL_DenormalDoubleAccess;
|
||||
typedef union { float fl; unsigned int w; } WDL_DenormalFloatAccess;
|
||||
|
||||
|
||||
// note: the _aggressive versions filter out anything less than around 1.0e-16 or so (approximately) to 0.0, including -0.0 (becomes 0.0)
|
||||
// note: new! the _aggressive versions also filter inf and NaN to 0.0
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define WDL_DENORMAL_INLINE inline
|
||||
#elif defined(_MSC_VER)
|
||||
#define WDL_DENORMAL_INLINE __inline
|
||||
#else
|
||||
#define WDL_DENORMAL_INLINE
|
||||
#endif
|
||||
|
||||
#define WDL_DENORMAL_DOUBLE_HW(a) (((const WDL_DenormalDoubleAccess*)(a))->w.hw)
|
||||
#define WDL_DENORMAL_DOUBLE_LW(a) (((const WDL_DenormalDoubleAccess*)(a))->w.lw)
|
||||
#define WDL_DENORMAL_FLOAT_W(a) (((const WDL_DenormalFloatAccess*)(a))->w)
|
||||
|
||||
#define WDL_DENORMAL_DOUBLE_HW_NC(a) (((WDL_DenormalDoubleAccess*)(a))->w.hw)
|
||||
#define WDL_DENORMAL_DOUBLE_LW_NC(a) (((WDL_DenormalDoubleAccess*)(a))->w.lw)
|
||||
#define WDL_DENORMAL_FLOAT_W_NC(a) (((WDL_DenormalFloatAccess*)(a))->w)
|
||||
|
||||
#define WDL_DENORMAL_DOUBLE_AGGRESSIVE_CUTOFF 0x3cA00000 // 0x3B8000000 maybe instead? that's 10^-5 smaller or so
|
||||
#define WDL_DENORMAL_FLOAT_AGGRESSIVE_CUTOFF 0x25000000
|
||||
|
||||
|
||||
// define WDL_DENORMAL_WANTS_SCOPED_FTZ, and then use a WDL_denormal_ftz_scope in addition to denormal_*(), then
|
||||
// if FTZ is available it will be used instead...
|
||||
//
|
||||
#ifdef WDL_DENORMAL_WANTS_SCOPED_FTZ
|
||||
|
||||
#if defined(__SSE2__) || _M_IX86_FP >= 2 || defined(_WIN64)
|
||||
#define WDL_DENORMAL_FTZMODE
|
||||
#define WDL_DENORMAL_FTZSTATE_TYPE unsigned int
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#else
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#define wdl_denorm_mm_getcsr() _mm_getcsr()
|
||||
#define wdl_denorm_mm_setcsr(x) _mm_setcsr(x)
|
||||
#if defined(__SSE3__)
|
||||
#define wdl_denorm_mm_csr_mask ((1<<15)|(1<<11) | (1<<8) | (1<<6)) // FTZ, underflow, denormal mask, DAZ
|
||||
#else
|
||||
#define wdl_denorm_mm_csr_mask ((1<<15)|(1<<11)) // FTZ and underflow only (target SSE2)
|
||||
#endif
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
#define WDL_DENORMAL_FTZMODE
|
||||
#define WDL_DENORMAL_FTZSTATE_TYPE unsigned long
|
||||
static unsigned long __attribute__((unused)) wdl_denorm_mm_getcsr()
|
||||
{
|
||||
unsigned long rv;
|
||||
#ifdef __aarch64__
|
||||
asm volatile ( "mrs %0, fpcr" : "=r" (rv));
|
||||
#else
|
||||
asm volatile ( "fmrx %0, fpscr" : "=r" (rv));
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
static void __attribute__((unused)) wdl_denorm_mm_setcsr(unsigned long v)
|
||||
{
|
||||
#ifdef __aarch64__
|
||||
asm volatile ( "msr fpcr, %0" :: "r"(v));
|
||||
#else
|
||||
asm volatile ( "fmxr fpscr, %0" :: "r"(v));
|
||||
#endif
|
||||
}
|
||||
#define wdl_denorm_mm_csr_mask (1<<24)
|
||||
#endif
|
||||
|
||||
class WDL_denormal_ftz_scope
|
||||
{
|
||||
public:
|
||||
WDL_denormal_ftz_scope()
|
||||
{
|
||||
#ifdef WDL_DENORMAL_FTZMODE
|
||||
const WDL_DENORMAL_FTZSTATE_TYPE b = wdl_denorm_mm_csr_mask;
|
||||
old_state = wdl_denorm_mm_getcsr();
|
||||
if ((need_restore = (old_state & b) != b))
|
||||
wdl_denorm_mm_setcsr(old_state|b);
|
||||
#endif
|
||||
}
|
||||
~WDL_denormal_ftz_scope()
|
||||
{
|
||||
#ifdef WDL_DENORMAL_FTZMODE
|
||||
if (need_restore) wdl_denorm_mm_setcsr(old_state);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WDL_DENORMAL_FTZMODE
|
||||
WDL_DENORMAL_FTZSTATE_TYPE old_state;
|
||||
bool need_restore;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(WDL_DENORMAL_FTZMODE) && !defined(WDL_DENORMAL_DO_NOT_FILTER)
|
||||
|
||||
static double WDL_DENORMAL_INLINE denormal_filter_double(double a)
|
||||
{
|
||||
return (WDL_DENORMAL_DOUBLE_HW(&a)&0x7ff00000) ? a : 0.0;
|
||||
}
|
||||
|
||||
static double WDL_DENORMAL_INLINE denormal_filter_double2(double a)
|
||||
{
|
||||
return ((WDL_DENORMAL_DOUBLE_HW(&a)+0x100000)&0x7ff00000) > 0x100000 ? a : 0.0;
|
||||
}
|
||||
|
||||
static double WDL_DENORMAL_INLINE denormal_filter_double_aggressive(double a)
|
||||
{
|
||||
return ((WDL_DENORMAL_DOUBLE_HW(&a)+0x100000)&0x7ff00000) >= WDL_DENORMAL_DOUBLE_AGGRESSIVE_CUTOFF ? a : 0.0;
|
||||
}
|
||||
|
||||
static float WDL_DENORMAL_INLINE denormal_filter_float(float a)
|
||||
{
|
||||
return (WDL_DENORMAL_FLOAT_W(&a)&0x7f800000) ? a : 0.0f;
|
||||
}
|
||||
|
||||
static float WDL_DENORMAL_INLINE denormal_filter_float2(float a)
|
||||
{
|
||||
return ((WDL_DENORMAL_FLOAT_W(&a)+0x800000)&0x7f800000) > 0x800000 ? a : 0.0f;
|
||||
}
|
||||
|
||||
|
||||
static float WDL_DENORMAL_INLINE denormal_filter_float_aggressive(float a)
|
||||
{
|
||||
return ((WDL_DENORMAL_FLOAT_W(&a)+0x800000)&0x7f800000) >= WDL_DENORMAL_FLOAT_AGGRESSIVE_CUTOFF ? a : 0.0f;
|
||||
}
|
||||
static void WDL_DENORMAL_INLINE denormal_fix_double(double *a)
|
||||
{
|
||||
if (!(WDL_DENORMAL_DOUBLE_HW(a)&0x7ff00000)) *a=0.0;
|
||||
}
|
||||
|
||||
static void WDL_DENORMAL_INLINE denormal_fix_double_aggressive(double *a)
|
||||
{
|
||||
if (((WDL_DENORMAL_DOUBLE_HW(a)+0x100000)&0x7ff00000) < WDL_DENORMAL_DOUBLE_AGGRESSIVE_CUTOFF) *a=0.0;
|
||||
}
|
||||
|
||||
static void WDL_DENORMAL_INLINE denormal_fix_float(float *a)
|
||||
{
|
||||
if (!(WDL_DENORMAL_FLOAT_W(a)&0x7f800000)) *a=0.0f;
|
||||
}
|
||||
static void WDL_DENORMAL_INLINE denormal_fix_float_aggressive(float *a)
|
||||
{
|
||||
if (((WDL_DENORMAL_FLOAT_W(a)+0x800000)&0x7f800000) < WDL_DENORMAL_FLOAT_AGGRESSIVE_CUTOFF) *a=0.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus // automatic typed versions (though one should probably use the explicit versions...
|
||||
|
||||
|
||||
static double WDL_DENORMAL_INLINE denormal_filter(double a)
|
||||
{
|
||||
return (WDL_DENORMAL_DOUBLE_HW(&a)&0x7ff00000) ? a : 0.0;
|
||||
}
|
||||
static double WDL_DENORMAL_INLINE denormal_filter_aggressive(double a)
|
||||
{
|
||||
return ((WDL_DENORMAL_DOUBLE_HW(&a)+0x100000)&0x7ff00000) >= WDL_DENORMAL_DOUBLE_AGGRESSIVE_CUTOFF ? a : 0.0;
|
||||
}
|
||||
|
||||
static float WDL_DENORMAL_INLINE denormal_filter(float a)
|
||||
{
|
||||
return (WDL_DENORMAL_FLOAT_W(&a)&0x7f800000) ? a : 0.0f;
|
||||
}
|
||||
|
||||
static float WDL_DENORMAL_INLINE denormal_filter_aggressive(float a)
|
||||
{
|
||||
return ((WDL_DENORMAL_FLOAT_W(&a)+0x800000)&0x7f800000) >= WDL_DENORMAL_FLOAT_AGGRESSIVE_CUTOFF ? a : 0.0f;
|
||||
}
|
||||
|
||||
static void WDL_DENORMAL_INLINE denormal_fix(double *a)
|
||||
{
|
||||
if (!(WDL_DENORMAL_DOUBLE_HW(a)&0x7ff00000)) *a=0.0;
|
||||
}
|
||||
static void WDL_DENORMAL_INLINE denormal_fix_aggressive(double *a)
|
||||
{
|
||||
if (((WDL_DENORMAL_DOUBLE_HW(a)+0x100000)&0x7ff00000) < WDL_DENORMAL_DOUBLE_AGGRESSIVE_CUTOFF) *a=0.0;
|
||||
}
|
||||
static void WDL_DENORMAL_INLINE denormal_fix(float *a)
|
||||
{
|
||||
if (!(WDL_DENORMAL_FLOAT_W(a)&0x7f800000)) *a=0.0f;
|
||||
}
|
||||
static void WDL_DENORMAL_INLINE denormal_fix_aggressive(float *a)
|
||||
{
|
||||
if (((WDL_DENORMAL_FLOAT_W(a)+0x800000)&0x7f800000) < WDL_DENORMAL_FLOAT_AGGRESSIVE_CUTOFF) *a=0.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // cplusplus versions
|
||||
|
||||
#else // end of !WDL_DENORMAL_DO_NOT_FILTER (and other platform-specific checks)
|
||||
|
||||
#define denormal_filter(x) (x)
|
||||
#define denormal_filter2(x) (x)
|
||||
#define denormal_filter_double(x) (x)
|
||||
#define denormal_filter_double2(x) (x)
|
||||
#define denormal_filter_double_aggressive(x) (x)
|
||||
#define denormal_filter_float(x) (x)
|
||||
#define denormal_filter_float2(x) (x)
|
||||
#define denormal_filter_float_aggressive(x) (x)
|
||||
#define denormal_filter_aggressive(x) (x)
|
||||
#define denormal_fix(x) do { } while(0)
|
||||
#define denormal_fix_aggressive(x) do { } while(0)
|
||||
#define denormal_fix_double(x) do { } while(0)
|
||||
#define denormal_fix_double_aggressive(x) do { } while(0)
|
||||
#define denormal_fix_float(x) do { } while(0)
|
||||
#define denormal_fix_float_aggressive(x) do { } while(0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////
|
||||
// this isnt a denormal function but it is similar, so we'll put it here as a bonus
|
||||
|
||||
static void WDL_DENORMAL_INLINE GetDoubleMaxAbsValue(double *out, const double *in) // note: the value pointed to by "out" must be >=0.0, __NOT__ <= -0.0
|
||||
{
|
||||
unsigned int hw = WDL_DENORMAL_DOUBLE_HW(in)&0x7fffffff;
|
||||
if (hw >= WDL_DENORMAL_DOUBLE_HW(out) && (hw>WDL_DENORMAL_DOUBLE_HW(out) || WDL_DENORMAL_DOUBLE_LW(in) > WDL_DENORMAL_DOUBLE_LW(out)))
|
||||
{
|
||||
WDL_DENORMAL_DOUBLE_LW_NC(out) = WDL_DENORMAL_DOUBLE_LW(in);
|
||||
WDL_DENORMAL_DOUBLE_HW_NC(out) = hw;
|
||||
}
|
||||
}
|
||||
|
||||
static void WDL_DENORMAL_INLINE GetFloatMaxAbsValue(float *out, const float *in) // note: the value pointed to by "out" must be >=0.0, __NOT__ <= -0.0
|
||||
{
|
||||
unsigned int hw = WDL_DENORMAL_FLOAT_W(in)&0x7fffffff;
|
||||
if (hw > WDL_DENORMAL_FLOAT_W(out)) WDL_DENORMAL_FLOAT_W_NC(out)=hw;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
static void WDL_DENORMAL_INLINE GetFloatMaxAbsValue(double *out, const double *in) // note: the value pointed to by "out" must be >=0.0, __NOT__ <= -0.0
|
||||
{
|
||||
GetDoubleMaxAbsValue(out,in);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
524
Src/ns-eel2/glue_x86.h
Normal file
524
Src/ns-eel2/glue_x86.h
Normal file
@ -0,0 +1,524 @@
|
||||
#ifndef _NSEEL_GLUE_X86_H_
|
||||
#define _NSEEL_GLUE_X86_H_
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#define GLUE_MAX_FPSTACK_SIZE 8
|
||||
|
||||
// endOfInstruction is end of jump with relative offset, offset is offset from end of instruction to jump to
|
||||
#define GLUE_JMP_SET_OFFSET(endOfInstruction,offset) (((int *)(endOfInstruction))[-1] = (offset))
|
||||
|
||||
static const unsigned char GLUE_JMP_NC[] = { 0xE9, 0,0,0,0, }; // jmp<offset>
|
||||
static const unsigned char GLUE_JMP_IF_P1_Z[] = {0x85, 0xC0, 0x0F, 0x84, 0,0,0,0 }; // test eax, eax, jz
|
||||
static const unsigned char GLUE_JMP_IF_P1_NZ[] = {0x85, 0xC0, 0x0F, 0x85, 0,0,0,0 }; // test eax, eax, jnz
|
||||
|
||||
#define GLUE_FUNC_ENTER_SIZE 0
|
||||
#define GLUE_FUNC_LEAVE_SIZE 0
|
||||
const static unsigned int GLUE_FUNC_ENTER[1];
|
||||
const static unsigned int GLUE_FUNC_LEAVE[1];
|
||||
|
||||
// x86
|
||||
// stack is 16 byte aligned
|
||||
// when pushing values to stack, alignment pushed first, then value (value is at the lower address)
|
||||
// when pushing pointers to stack, alignment pushed first, then pointer (pointer is at the lower address)
|
||||
|
||||
static const unsigned char GLUE_PUSH_P1PTR_AS_VALUE[] =
|
||||
{
|
||||
0x83, 0xEC, 8, /* sub esp, 8 */
|
||||
0xff, 0x70, 0x4, /* push dword [eax+4] */
|
||||
0xff, 0x30, /* push dword [eax] */
|
||||
};
|
||||
|
||||
static int GLUE_POP_VALUE_TO_ADDR(unsigned char *buf, void *destptr)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
*buf++ = 0xB8; *(void **) buf = destptr; buf+=4; // mov eax, directvalue
|
||||
|
||||
*buf++ = 0x8f; *buf++ = 0x00; // pop dword [eax]
|
||||
*buf++ = 0x8f; *buf++ = 0x40; *buf++ = 4; // pop dword [eax+4]
|
||||
|
||||
*buf++ = 0x59; // pop ecx (alignment)
|
||||
*buf++ = 0x59; // pop ecx (alignment)
|
||||
}
|
||||
|
||||
return 12;
|
||||
}
|
||||
|
||||
static int GLUE_COPY_VALUE_AT_P1_TO_PTR(unsigned char *buf, void *destptr)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
*buf++ = 0x8B; *buf++ = 0x38; // mov edi, [eax]
|
||||
*buf++ = 0x8B; *buf++ = 0x48; *buf++ = 0x04; // mov ecx, [eax+4]
|
||||
|
||||
|
||||
*buf++ = 0xB8; *(void **) buf = destptr; buf+=4; // mov eax, directvalue
|
||||
*buf++ = 0x89; *buf++ = 0x38; // mov [eax], edi
|
||||
*buf++ = 0x89; *buf++ = 0x48; *buf++ = 0x04; // mov [eax+4], ecx
|
||||
}
|
||||
|
||||
return 2 + 3 + 5 + 2 + 3;
|
||||
}
|
||||
|
||||
static int GLUE_POP_FPSTACK_TO_PTR(unsigned char *buf, void *destptr)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
*buf++ = 0xB8; *(void **) buf = destptr; buf+=4; // mov eax, directvalue
|
||||
*buf++ = 0xDD; *buf++ = 0x18; // fstp qword [eax]
|
||||
}
|
||||
return 1+4+2;
|
||||
}
|
||||
|
||||
|
||||
#define GLUE_MOV_PX_DIRECTVALUE_SIZE 5
|
||||
#define GLUE_MOV_PX_DIRECTVALUE_TOSTACK_SIZE 6 // length when wv == -1
|
||||
|
||||
static void GLUE_MOV_PX_DIRECTVALUE_GEN(void *b, INT_PTR v, int wv)
|
||||
{
|
||||
if (wv==-1)
|
||||
{
|
||||
const static unsigned char t[2] = {0xDD, 0x05};
|
||||
memcpy(b,t,2);
|
||||
b= ((unsigned char *)b)+2;
|
||||
}
|
||||
else
|
||||
{
|
||||
const static unsigned char tab[3] = {
|
||||
0xB8 /* mov eax, dv*/,
|
||||
0xBF /* mov edi, dv */ ,
|
||||
0xB9 /* mov ecx, dv */
|
||||
};
|
||||
*((unsigned char *)b) = tab[wv]; // mov eax, dv
|
||||
b= ((unsigned char *)b)+1;
|
||||
}
|
||||
*(INT_PTR *)b = v;
|
||||
}
|
||||
const static unsigned char GLUE_PUSH_P1[4]={0x83, 0xEC, 12, 0x50}; // sub esp, 12, push eax
|
||||
|
||||
#define GLUE_STORE_P1_TO_STACK_AT_OFFS_SIZE(x) 7
|
||||
static void GLUE_STORE_P1_TO_STACK_AT_OFFS(void *b, int offs)
|
||||
{
|
||||
((unsigned char *)b)[0] = 0x89; // mov [esp+offs], eax
|
||||
((unsigned char *)b)[1] = 0x84;
|
||||
((unsigned char *)b)[2] = 0x24;
|
||||
*(int *)((unsigned char *)b+3) = offs;
|
||||
}
|
||||
|
||||
#define GLUE_MOVE_PX_STACKPTR_SIZE 2
|
||||
static void GLUE_MOVE_PX_STACKPTR_GEN(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_MOVE_PX_STACKPTR_SIZE]=
|
||||
{
|
||||
{ 0x89, 0xe0 }, // mov eax, esp
|
||||
{ 0x89, 0xe7 }, // mov edi, esp
|
||||
{ 0x89, 0xe1 }, // mov ecx, esp
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_MOVE_PX_STACKPTR_SIZE);
|
||||
}
|
||||
|
||||
#define GLUE_MOVE_STACK_SIZE 6
|
||||
static void GLUE_MOVE_STACK(void *b, int amt)
|
||||
{
|
||||
((unsigned char *)b)[0] = 0x81;
|
||||
if (amt <0)
|
||||
{
|
||||
((unsigned char *)b)[1] = 0xEC;
|
||||
*(int *)((char*)b+2) = -amt; // sub esp, -amt
|
||||
}
|
||||
else
|
||||
{
|
||||
((unsigned char *)b)[1] = 0xc4;
|
||||
*(int *)((char*)b+2) = amt; // add esp, amt
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define GLUE_POP_PX_SIZE 4
|
||||
static void GLUE_POP_PX(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_POP_PX_SIZE]=
|
||||
{
|
||||
{0x58,/*pop eax*/ 0x83, 0xC4, 12 /* add esp, 12*/},
|
||||
{0x5F,/*pop edi*/ 0x83, 0xC4, 12},
|
||||
{0x59,/*pop ecx*/ 0x83, 0xC4, 12},
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_POP_PX_SIZE);
|
||||
}
|
||||
|
||||
#define GLUE_SET_PX_FROM_P1_SIZE 2
|
||||
static void GLUE_SET_PX_FROM_P1(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_SET_PX_FROM_P1_SIZE]={
|
||||
{0x90,0x90}, // should never be used! (nopnop)
|
||||
{0x89,0xC7}, // mov edi, eax
|
||||
{0x89,0xC1}, // mov ecx, eax
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_SET_PX_FROM_P1_SIZE);
|
||||
}
|
||||
|
||||
#define GLUE_POP_FPSTACK_SIZE 2
|
||||
static const unsigned char GLUE_POP_FPSTACK[2] = { 0xDD, 0xD8 }; // fstp st0
|
||||
|
||||
static const unsigned char GLUE_POP_FPSTACK_TOSTACK[] = {
|
||||
0x83, 0xEC, 16, // sub esp, 16
|
||||
0xDD, 0x1C, 0x24 // fstp qword (%esp)
|
||||
};
|
||||
|
||||
static const unsigned char GLUE_POP_STACK_TO_FPSTACK[] = {
|
||||
0xDD, 0x04, 0x24, // fld qword (%esp)
|
||||
0x83, 0xC4, 16 // add esp, 16
|
||||
};
|
||||
|
||||
static const unsigned char GLUE_POP_FPSTACK_TO_WTP[] = {
|
||||
0xDD, 0x1E, /* fstp qword [esi] */
|
||||
0x83, 0xC6, 8, /* add esi, 8 */
|
||||
};
|
||||
|
||||
#define GLUE_SET_PX_FROM_WTP_SIZE 2
|
||||
static void GLUE_SET_PX_FROM_WTP(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_SET_PX_FROM_WTP_SIZE]={
|
||||
{0x89,0xF0}, // mov eax, esi
|
||||
{0x89,0xF7}, // mov edi, esi
|
||||
{0x89,0xF1}, // mov ecx, esi
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_SET_PX_FROM_WTP_SIZE);
|
||||
}
|
||||
|
||||
#define GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE 2
|
||||
static void GLUE_PUSH_VAL_AT_PX_TO_FPSTACK(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE]={
|
||||
{0xDD,0x00}, // fld qword [eax]
|
||||
{0xDD,0x07}, // fld qword [edi]
|
||||
{0xDD,0x01}, // fld qword [ecx]
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE);
|
||||
}
|
||||
|
||||
#define GLUE_POP_FPSTACK_TO_WTP_TO_PX_SIZE (GLUE_SET_PX_FROM_WTP_SIZE + sizeof(GLUE_POP_FPSTACK_TO_WTP))
|
||||
static void GLUE_POP_FPSTACK_TO_WTP_TO_PX(unsigned char *buf, int wv)
|
||||
{
|
||||
GLUE_SET_PX_FROM_WTP(buf,wv);
|
||||
memcpy(buf + GLUE_SET_PX_FROM_WTP_SIZE,GLUE_POP_FPSTACK_TO_WTP,sizeof(GLUE_POP_FPSTACK_TO_WTP));
|
||||
};
|
||||
|
||||
|
||||
const static unsigned char GLUE_RET=0xC3;
|
||||
|
||||
static int GLUE_RESET_WTP(unsigned char *out, void *ptr)
|
||||
{
|
||||
if (out)
|
||||
{
|
||||
*out++ = 0xBE; // mov esi, constant
|
||||
memcpy(out,&ptr,sizeof(void *));
|
||||
out+=sizeof(void *);
|
||||
}
|
||||
return 1+sizeof(void *);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4731)
|
||||
#endif
|
||||
|
||||
#define GLUE_TABPTR_IGNORED
|
||||
#define GLUE_CALL_CODE(bp, cp, rt) do { \
|
||||
if (h->compile_flags&NSEEL_CODE_COMPILE_FLAG_NOFPSTATE) eel_callcode32_fast(cp, rt); \
|
||||
else eel_callcode32(cp, rt);\
|
||||
} while(0)
|
||||
|
||||
static void eel_callcode32(INT_PTR cp, INT_PTR ramptr)
|
||||
{
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
short oldsw, newsw;
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
|
||||
__asm
|
||||
{
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
fnstcw [oldsw]
|
||||
mov ax, [oldsw]
|
||||
or ax, 0xE3F // 53 or 64 bit precision (depending on whether 0x100 is set), trunc, and masking all exceptions
|
||||
mov [newsw], ax
|
||||
fldcw [newsw]
|
||||
#endif
|
||||
|
||||
mov eax, cp
|
||||
mov ebx, ramptr
|
||||
|
||||
pushad
|
||||
mov ebp, esp
|
||||
and esp, -16
|
||||
|
||||
// on win32, which _MSC_VER implies, we keep things aligned to 16 bytes, and if we call a win32 function,
|
||||
// the stack is 16 byte aligned before the call, meaning that if calling a function with no frame pointer,
|
||||
// the stack would be aligned to a 16 byte boundary +4, which isn't good for performance. Having said that,
|
||||
// normally we compile with frame pointers (which brings that to 16 byte + 8, which is fine), or ICC, which
|
||||
// for nontrivial functions will align the stack itself (for very short functions, it appears to weigh the
|
||||
// cost of aligning the stack vs that of the slower misaligned double accesses).
|
||||
|
||||
// it may be worthwhile (at some point) to put some logic in the code that calls out to functions
|
||||
// (generic1parm etc) to detect which alignment would be most optimal.
|
||||
sub esp, 12
|
||||
call eax
|
||||
mov esp, ebp
|
||||
popad
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
fldcw [oldsw]
|
||||
#endif
|
||||
};
|
||||
|
||||
#else // gcc x86
|
||||
__asm__(
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
"fnstcw %2\n"
|
||||
"movw %2, %%ax\n"
|
||||
"orw $0xE3F, %%ax\n" // 53 or 64 bit precision (depending on whether 0x100 is set), trunc, and masking all exceptions
|
||||
"movw %%ax, %3\n"
|
||||
"fldcw %3\n"
|
||||
#endif
|
||||
"pushl %%ebx\n"
|
||||
"movl %%ecx, %%ebx\n"
|
||||
"pushl %%ebp\n"
|
||||
"movl %%esp, %%ebp\n"
|
||||
"andl $-16, %%esp\n" // align stack to 16 bytes
|
||||
"subl $12, %%esp\n" // call will push 4 bytes on stack, align for that
|
||||
"call *%%edx\n"
|
||||
"leave\n"
|
||||
"popl %%ebx\n"
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
"fldcw %2\n"
|
||||
#endif
|
||||
::
|
||||
"d" (cp), "c" (ramptr)
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
, "m" (oldsw), "m" (newsw)
|
||||
#endif
|
||||
: "%eax","%esi","%edi");
|
||||
#endif //gcc x86
|
||||
}
|
||||
|
||||
void eel_enterfp(int s[2])
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm
|
||||
{
|
||||
mov ecx, s
|
||||
fnstcw [ecx]
|
||||
mov ax, [ecx]
|
||||
or ax, 0xE3F // 53 or 64 bit precision (depending on whether 0x100 is set), trunc, and masking all exceptions
|
||||
mov [ecx+4], ax
|
||||
fldcw [ecx+4]
|
||||
};
|
||||
#else
|
||||
__asm__(
|
||||
"fnstcw (%%ecx)\n"
|
||||
"movw (%%ecx), %%ax\n"
|
||||
"orw $0xE3F, %%ax\n" // 53 or 64 bit precision (depending on whether 0x100 is set), trunc, and masking all exceptions
|
||||
"movw %%ax, 4(%%ecx)\n"
|
||||
"fldcw 4(%%ecx)\n"
|
||||
:: "c" (s) : "%eax");
|
||||
#endif
|
||||
}
|
||||
void eel_leavefp(int s[2])
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm
|
||||
{
|
||||
mov ecx, s
|
||||
fldcw [ecx]
|
||||
};
|
||||
#else
|
||||
__asm__(
|
||||
"fldcw (%%ecx)\n"
|
||||
:: "c" (s) : "%eax");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void eel_callcode32_fast(INT_PTR cp, INT_PTR ramptr)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, cp
|
||||
mov ebx, ramptr
|
||||
|
||||
pushad
|
||||
mov ebp, esp
|
||||
and esp, -16
|
||||
|
||||
// on win32, which _MSC_VER implies, we keep things aligned to 16 bytes, and if we call a win32 function,
|
||||
// the stack is 16 byte aligned before the call, meaning that if calling a function with no frame pointer,
|
||||
// the stack would be aligned to a 16 byte boundary +4, which isn't good for performance. Having said that,
|
||||
// normally we compile with frame pointers (which brings that to 16 byte + 8, which is fine), or ICC, which
|
||||
// for nontrivial functions will align the stack itself (for very short functions, it appears to weigh the
|
||||
// cost of aligning the stack vs that of the slower misaligned double accesses).
|
||||
|
||||
// it may be worthwhile (at some point) to put some logic in the code that calls out to functions
|
||||
// (generic1parm etc) to detect which alignment would be most optimal.
|
||||
sub esp, 12
|
||||
call eax
|
||||
mov esp, ebp
|
||||
popad
|
||||
};
|
||||
|
||||
#else // gcc x86
|
||||
__asm__(
|
||||
"pushl %%ebx\n"
|
||||
"movl %%ecx, %%ebx\n"
|
||||
"pushl %%ebp\n"
|
||||
"movl %%esp, %%ebp\n"
|
||||
"andl $-16, %%esp\n" // align stack to 16 bytes
|
||||
"subl $12, %%esp\n" // call will push 4 bytes on stack, align for that
|
||||
"call *%%edx\n"
|
||||
"leave\n"
|
||||
"popl %%ebx\n"
|
||||
::
|
||||
"d" (cp), "c" (ramptr)
|
||||
: "%eax","%esi","%edi");
|
||||
#endif //gcc x86
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned char *EEL_GLUE_set_immediate(void *_p, INT_PTR newv)
|
||||
{
|
||||
char *p=(char*)_p;
|
||||
INT_PTR scan = 0xFEFEFEFE;
|
||||
while (*(INT_PTR *)p != scan) p++;
|
||||
*(INT_PTR *)p = newv;
|
||||
return (unsigned char *) (((INT_PTR*)p)+1);
|
||||
}
|
||||
|
||||
#define INT_TO_LECHARS(x) ((x)&0xff),(((x)>>8)&0xff), (((x)>>16)&0xff), (((x)>>24)&0xff)
|
||||
|
||||
|
||||
#define GLUE_INLINE_LOOPS
|
||||
|
||||
static const unsigned char GLUE_LOOP_LOADCNT[]={
|
||||
0xDB, 0x1E, //fistp dword [esi]
|
||||
0x8B, 0x0E, // mov ecx, [esi]
|
||||
0x81, 0xf9, 1,0,0,0, // cmp ecx, 1
|
||||
0x0F, 0x8C, 0,0,0,0, // JL <skipptr>
|
||||
};
|
||||
|
||||
#if NSEEL_LOOPFUNC_SUPPORT_MAXLEN > 0
|
||||
#define GLUE_LOOP_CLAMPCNT_SIZE sizeof(GLUE_LOOP_CLAMPCNT)
|
||||
static const unsigned char GLUE_LOOP_CLAMPCNT[]={
|
||||
0x81, 0xf9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), // cmp ecx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
0x0F, 0x8C, 5,0,0,0, // JL over-the-mov
|
||||
0xB9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), // mov ecx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
};
|
||||
#else
|
||||
|
||||
#define GLUE_LOOP_CLAMPCNT_SIZE 0
|
||||
#define GLUE_LOOP_CLAMPCNT ""
|
||||
|
||||
#endif
|
||||
|
||||
#define GLUE_LOOP_BEGIN_SIZE sizeof(GLUE_LOOP_BEGIN)
|
||||
static const unsigned char GLUE_LOOP_BEGIN[]={
|
||||
0x56, //push esi
|
||||
0x51, // push ecx
|
||||
0x81, 0xEC, 0x08, 0,0,0, // sub esp, 8
|
||||
};
|
||||
static const unsigned char GLUE_LOOP_END[]={
|
||||
0x81, 0xC4, 0x08, 0,0,0, // add esp, 8
|
||||
0x59, //pop ecx
|
||||
0x5E, // pop esi
|
||||
0x49, // dec ecx
|
||||
0x0f, 0x85, 0,0,0,0, // jnz ...
|
||||
};
|
||||
|
||||
|
||||
#if NSEEL_LOOPFUNC_SUPPORT_MAXLEN > 0
|
||||
#define GLUE_WHILE_SETUP_SIZE sizeof(GLUE_WHILE_SETUP)
|
||||
static const unsigned char GLUE_WHILE_SETUP[]={
|
||||
0xB9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), // mov ecx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
};
|
||||
static const unsigned char GLUE_WHILE_BEGIN[]={
|
||||
0x56, //push esi
|
||||
0x51, // push ecx
|
||||
0x81, 0xEC, 0x08, 0,0,0, // sub esp, 8
|
||||
};
|
||||
static const unsigned char GLUE_WHILE_END[]={
|
||||
0x81, 0xC4, 0x08, 0,0,0, // add esp, 8
|
||||
0x59, //pop ecx
|
||||
0x5E, // pop esi
|
||||
|
||||
|
||||
0x49, // dec ecx
|
||||
0x0f, 0x84, 0,0,0,0, // jz endpt
|
||||
};
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define GLUE_WHILE_SETUP_SIZE 0
|
||||
#define GLUE_WHILE_SETUP ""
|
||||
#define GLUE_WHILE_END_NOJUMP
|
||||
static const unsigned char GLUE_WHILE_BEGIN[]={
|
||||
0x56, //push esi
|
||||
0x81, 0xEC, 12, 0,0,0, // sub esp, 12
|
||||
};
|
||||
static const unsigned char GLUE_WHILE_END[]={
|
||||
0x81, 0xC4, 12, 0,0,0, // add esp, 12
|
||||
0x5E, // pop esi
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static const unsigned char GLUE_WHILE_CHECK_RV[] = {
|
||||
0x85, 0xC0, // test eax, eax
|
||||
0x0F, 0x85, 0,0,0,0 // jnz looppt
|
||||
};
|
||||
|
||||
static const unsigned char GLUE_SET_P1_Z[] = { 0x29, 0xC0 }; // sub eax, eax
|
||||
static const unsigned char GLUE_SET_P1_NZ[] = { 0xb0, 0x01 }; // mov al, 1
|
||||
|
||||
#define GLUE_HAS_FXCH
|
||||
static const unsigned char GLUE_FXCH[] = {0xd9, 0xc9};
|
||||
|
||||
#define GLUE_HAS_FLDZ
|
||||
static const unsigned char GLUE_FLDZ[] = {0xd9, 0xee};
|
||||
#define GLUE_HAS_FLD1
|
||||
static const unsigned char GLUE_FLD1[] = {0xd9, 0xe8};
|
||||
|
||||
static EEL_F negativezeropointfive=-0.5f;
|
||||
static EEL_F onepointfive=1.5f;
|
||||
#define GLUE_INVSQRT_NEEDREPL &negativezeropointfive, &onepointfive,
|
||||
|
||||
|
||||
#define GLUE_HAS_NATIVE_TRIGSQRTLOG
|
||||
|
||||
static void *GLUE_realAddress(void *fn, void *fn_e, int *size)
|
||||
{
|
||||
static const unsigned char sig[12] = { 0x89, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
|
||||
unsigned char *p = (unsigned char *)fn;
|
||||
|
||||
#if defined(_DEBUG) && defined(_MSC_VER)
|
||||
if (*p == 0xE9) // this means jump to the following address (debug stub)
|
||||
{
|
||||
p += 5 + *(int *)(p+1);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (memcmp(p,sig,sizeof(sig))) p++;
|
||||
p+=sizeof(sig);
|
||||
fn = p;
|
||||
|
||||
while (memcmp(p,sig,sizeof(sig))) p++;
|
||||
*size = p - (unsigned char *)fn;
|
||||
return fn;
|
||||
}
|
||||
|
||||
#endif
|
261
Src/ns-eel2/glue_x86_64.h
Normal file
261
Src/ns-eel2/glue_x86_64.h
Normal file
@ -0,0 +1,261 @@
|
||||
#ifndef _NSEEL_GLUE_X86_64_H_
|
||||
#define _NSEEL_GLUE_X86_64_H_
|
||||
|
||||
#define GLUE_MAX_FPSTACK_SIZE 8
|
||||
#define GLUE_JMP_SET_OFFSET(endOfInstruction,offset) (((int *)(endOfInstruction))[-1] = (offset))
|
||||
|
||||
#define GLUE_PREFER_NONFP_DV_ASSIGNS
|
||||
|
||||
static const unsigned char GLUE_JMP_NC[] = { 0xE9, 0,0,0,0, }; // jmp<offset>
|
||||
static const unsigned char GLUE_JMP_IF_P1_Z[] = {0x85, 0xC0, 0x0F, 0x84, 0,0,0,0 }; // test eax, eax, jz
|
||||
static const unsigned char GLUE_JMP_IF_P1_NZ[] = {0x85, 0xC0, 0x0F, 0x85, 0,0,0,0 }; // test eax, eax, jnz
|
||||
|
||||
|
||||
#define GLUE_FUNC_ENTER_SIZE 0
|
||||
#define GLUE_FUNC_LEAVE_SIZE 0
|
||||
const static unsigned int GLUE_FUNC_ENTER[1];
|
||||
const static unsigned int GLUE_FUNC_LEAVE[1];
|
||||
|
||||
// on x86-64:
|
||||
// stack is always 16 byte aligned
|
||||
// pushing values to the stack (for eel functions) has alignment pushed first, then value (value is at the lower address)
|
||||
// pushing pointers to the stack has the pointer pushed first, then the alignment (pointer is at the higher address)
|
||||
#define GLUE_MOV_PX_DIRECTVALUE_SIZE 10
|
||||
static void GLUE_MOV_PX_DIRECTVALUE_GEN(void *b, INT_PTR v, int wr) {
|
||||
const static unsigned short tab[3] =
|
||||
{
|
||||
0xB848 /* mov rax, dv*/,
|
||||
0xBF48 /* mov rdi, dv */ ,
|
||||
0xB948 /* mov rcx, dv */
|
||||
};
|
||||
unsigned short *bb = (unsigned short *)b;
|
||||
*bb++ = tab[wr]; // mov rax, directvalue
|
||||
*(INT_PTR *)bb = v;
|
||||
}
|
||||
|
||||
const static unsigned char GLUE_PUSH_P1[2]={ 0x50,0x50}; // push rax (pointer); push rax (alignment)
|
||||
|
||||
#define GLUE_POP_PX_SIZE 2
|
||||
static void GLUE_POP_PX(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_POP_PX_SIZE]=
|
||||
{
|
||||
{0x58,/*pop eax*/ 0x58}, // pop alignment, then pop pointer
|
||||
{0x5F,/*pop edi*/ 0x5F},
|
||||
{0x59,/*pop ecx*/ 0x59},
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_POP_PX_SIZE);
|
||||
}
|
||||
|
||||
static const unsigned char GLUE_PUSH_P1PTR_AS_VALUE[] =
|
||||
{
|
||||
0x50, /*push rax - for alignment */
|
||||
0xff, 0x30, /* push qword [rax] */
|
||||
};
|
||||
|
||||
static int GLUE_POP_VALUE_TO_ADDR(unsigned char *buf, void *destptr) // trashes P2 (rdi) and P3 (rcx)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
*buf++ = 0x48; *buf++ = 0xB9; *(void **) buf = destptr; buf+=8; // mov rcx, directvalue
|
||||
*buf++ = 0x8f; *buf++ = 0x01; // pop qword [rcx]
|
||||
*buf++ = 0x5F ; // pop rdi (alignment, safe to trash rdi though)
|
||||
}
|
||||
return 1+10+2;
|
||||
}
|
||||
|
||||
static int GLUE_COPY_VALUE_AT_P1_TO_PTR(unsigned char *buf, void *destptr) // trashes P2/P3
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
*buf++ = 0x48; *buf++ = 0xB9; *(void **) buf = destptr; buf+=8; // mov rcx, directvalue
|
||||
*buf++ = 0x48; *buf++ = 0x8B; *buf++ = 0x38; // mov rdi, [rax]
|
||||
*buf++ = 0x48; *buf++ = 0x89; *buf++ = 0x39; // mov [rcx], rdi
|
||||
}
|
||||
|
||||
return 3 + 10 + 3;
|
||||
}
|
||||
|
||||
static int GLUE_POP_FPSTACK_TO_PTR(unsigned char *buf, void *destptr)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
*buf++ = 0x48;
|
||||
*buf++ = 0xB8;
|
||||
*(void **) buf = destptr; buf+=8; // mov rax, directvalue
|
||||
*buf++ = 0xDD; *buf++ = 0x18; // fstp qword [rax]
|
||||
}
|
||||
return 2+8+2;
|
||||
}
|
||||
|
||||
|
||||
#define GLUE_SET_PX_FROM_P1_SIZE 3
|
||||
static void GLUE_SET_PX_FROM_P1(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_SET_PX_FROM_P1_SIZE]={
|
||||
{0x90,0x90,0x90}, // should never be used! (nopnop)
|
||||
{0x48,0x89,0xC7}, // mov rdi, rax
|
||||
{0x48,0x89,0xC1}, // mov rcx, rax
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_SET_PX_FROM_P1_SIZE);
|
||||
}
|
||||
|
||||
|
||||
#define GLUE_POP_FPSTACK_SIZE 2
|
||||
static const unsigned char GLUE_POP_FPSTACK[2] = { 0xDD, 0xD8 }; // fstp st0
|
||||
|
||||
static const unsigned char GLUE_POP_FPSTACK_TOSTACK[] = {
|
||||
0x48, 0x81, 0xEC, 16, 0,0,0, // sub rsp, 16
|
||||
0xDD, 0x1C, 0x24 // fstp qword (%rsp)
|
||||
};
|
||||
|
||||
static const unsigned char GLUE_POP_FPSTACK_TO_WTP[] = {
|
||||
0xDD, 0x1E, /* fstp qword [rsi] */
|
||||
0x48, 0x81, 0xC6, 8, 0,0,0,/* add rsi, 8 */
|
||||
};
|
||||
|
||||
#define GLUE_SET_PX_FROM_WTP_SIZE 3
|
||||
static void GLUE_SET_PX_FROM_WTP(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_SET_PX_FROM_WTP_SIZE]={
|
||||
{0x48, 0x89,0xF0}, // mov rax, rsi
|
||||
{0x48, 0x89,0xF7}, // mov rdi, rsi
|
||||
{0x48, 0x89,0xF1}, // mov rcx, rsi
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_SET_PX_FROM_WTP_SIZE);
|
||||
}
|
||||
|
||||
#define GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE 2
|
||||
static void GLUE_PUSH_VAL_AT_PX_TO_FPSTACK(void *b, int wv)
|
||||
{
|
||||
static const unsigned char tab[3][GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE]={
|
||||
{0xDD,0x00}, // fld qword [rax]
|
||||
{0xDD,0x07}, // fld qword [rdi]
|
||||
{0xDD,0x01}, // fld qword [rcx]
|
||||
};
|
||||
memcpy(b,tab[wv],GLUE_PUSH_VAL_AT_PX_TO_FPSTACK_SIZE);
|
||||
}
|
||||
static unsigned char GLUE_POP_STACK_TO_FPSTACK[] = {
|
||||
0xDD, 0x04, 0x24, // fld qword (%rsp)
|
||||
0x48, 0x81, 0xC4, 16, 0,0,0, // add rsp, 16
|
||||
};
|
||||
|
||||
|
||||
#define GLUE_POP_FPSTACK_TO_WTP_TO_PX_SIZE (GLUE_SET_PX_FROM_WTP_SIZE + sizeof(GLUE_POP_FPSTACK_TO_WTP))
|
||||
static void GLUE_POP_FPSTACK_TO_WTP_TO_PX(unsigned char *buf, int wv)
|
||||
{
|
||||
GLUE_SET_PX_FROM_WTP(buf,wv);
|
||||
memcpy(buf + GLUE_SET_PX_FROM_WTP_SIZE,GLUE_POP_FPSTACK_TO_WTP,sizeof(GLUE_POP_FPSTACK_TO_WTP));
|
||||
};
|
||||
|
||||
|
||||
const static unsigned char GLUE_RET=0xC3;
|
||||
|
||||
static int GLUE_RESET_WTP(unsigned char *out, void *ptr)
|
||||
{
|
||||
if (out)
|
||||
{
|
||||
*out++ = 0x48;
|
||||
*out++ = 0xBE; // mov rsi, constant64
|
||||
*(void **)out = ptr;
|
||||
out+=sizeof(void *);
|
||||
}
|
||||
return 2+sizeof(void *);
|
||||
}
|
||||
|
||||
extern void win64_callcode(INT_PTR code, INT_PTR ram_tab);
|
||||
#define GLUE_CALL_CODE(bp, cp, rt) win64_callcode(cp, rt)
|
||||
|
||||
static unsigned char *EEL_GLUE_set_immediate(void *_p, INT_PTR newv)
|
||||
{
|
||||
char *p=(char*)_p;
|
||||
INT_PTR scan = 0xFEFEFEFEFEFEFEFE;
|
||||
while (*(INT_PTR *)p != scan) p++;
|
||||
*(INT_PTR *)p = newv;
|
||||
return (unsigned char *) (((INT_PTR*)p)+1);
|
||||
}
|
||||
|
||||
#define INT_TO_LECHARS(x) ((x)&0xff),(((x)>>8)&0xff), (((x)>>16)&0xff), (((x)>>24)&0xff)
|
||||
|
||||
#define GLUE_INLINE_LOOPS
|
||||
|
||||
static const unsigned char GLUE_LOOP_LOADCNT[]={
|
||||
0xDD, 0x0E, //fistTp qword [rsi]
|
||||
0x48, 0x8B, 0x0E, // mov rcx, [rsi]
|
||||
0x48, 0x81, 0xf9, 1,0,0,0, // cmp rcx, 1
|
||||
0x0F, 0x8C, 0,0,0,0, // JL <skipptr>
|
||||
};
|
||||
static const unsigned char GLUE_LOOP_CLAMPCNT[]={
|
||||
0x48, 0x81, 0xf9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), // cmp rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
0x0F, 0x8C, 10,0,0,0, // JL over-the-mov
|
||||
0x48, 0xB9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), 0,0,0,0, // mov rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
};
|
||||
static const unsigned char GLUE_LOOP_BEGIN[]={
|
||||
0x56, //push rsi
|
||||
0x51, // push rcx
|
||||
};
|
||||
static const unsigned char GLUE_LOOP_END[]={
|
||||
0x59, //pop rcx
|
||||
0x5E, // pop rsi
|
||||
0xff, 0xc9, // dec rcx
|
||||
0x0f, 0x85, 0,0,0,0, // jnz ...
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const unsigned char GLUE_WHILE_SETUP[]={
|
||||
0x48, 0xB9, INT_TO_LECHARS(NSEEL_LOOPFUNC_SUPPORT_MAXLEN), 0,0,0,0, // mov rcx, NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
};
|
||||
static const unsigned char GLUE_WHILE_BEGIN[]={
|
||||
0x56, //push rsi
|
||||
0x51, // push rcx
|
||||
};
|
||||
static const unsigned char GLUE_WHILE_END[]={
|
||||
0x59, //pop rcx
|
||||
0x5E, // pop rsi
|
||||
|
||||
0xff, 0xc9, // dec rcx
|
||||
0x0f, 0x84, 0,0,0,0, // jz endpt
|
||||
};
|
||||
static const unsigned char GLUE_WHILE_CHECK_RV[] = {
|
||||
0x85, 0xC0, // test eax, eax
|
||||
0x0F, 0x85, 0,0,0,0 // jnz looppt
|
||||
};
|
||||
|
||||
static const unsigned char GLUE_SET_P1_Z[] = { 0x48, 0x29, 0xC0 }; // sub rax, rax
|
||||
static const unsigned char GLUE_SET_P1_NZ[] = { 0xb0, 0x01 }; // mov al, 1
|
||||
|
||||
|
||||
#define GLUE_HAS_FXCH
|
||||
static const unsigned char GLUE_FXCH[] = {0xd9, 0xc9};
|
||||
|
||||
#define GLUE_HAS_FLDZ
|
||||
static const unsigned char GLUE_FLDZ[] = {0xd9, 0xee};
|
||||
#define GLUE_HAS_FLD1
|
||||
static const unsigned char GLUE_FLD1[] = {0xd9, 0xe8};
|
||||
|
||||
|
||||
static EEL_F negativezeropointfive=-0.5f;
|
||||
static EEL_F onepointfive=1.5f;
|
||||
#define GLUE_INVSQRT_NEEDREPL &negativezeropointfive, &onepointfive,
|
||||
|
||||
#define GLUE_HAS_NATIVE_TRIGSQRTLOG
|
||||
|
||||
|
||||
static void *GLUE_realAddress(void *fn, void *fn_e, int *size)
|
||||
{
|
||||
static const unsigned char sig[12] = { 0x89, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
|
||||
unsigned char *p = (unsigned char *)fn;
|
||||
|
||||
while (memcmp(p,sig,sizeof(sig))) p++;
|
||||
p+=sizeof(sig);
|
||||
fn = p;
|
||||
|
||||
while (memcmp(p,sig,sizeof(sig))) p++;
|
||||
*size = p - (unsigned char *)fn;
|
||||
return fn;
|
||||
}
|
||||
|
||||
// end of x86-64
|
||||
|
||||
#endif
|
81
Src/ns-eel2/ns-eel-addfuncs.h
Normal file
81
Src/ns-eel2/ns-eel-addfuncs.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
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__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct _compileContext;
|
||||
|
||||
void *NSEEL_PProc_RAM(void *data, int data_size, struct _compileContext *ctx);
|
||||
void *NSEEL_PProc_THIS(void *data, int data_size, struct _compileContext *ctx);
|
||||
|
||||
|
||||
#ifdef EEL_TARGET_PORTABLE
|
||||
|
||||
extern EEL_BC_TYPE _asm_generic3parm[]; // 3 double * parms, returning double *
|
||||
extern EEL_BC_TYPE _asm_generic3parm_retd[]; // 3 double * parms, returning double
|
||||
extern EEL_BC_TYPE _asm_generic2parm[]; // 2 double * parms, returning double *
|
||||
extern EEL_BC_TYPE _asm_generic2parm_retd[]; // 2 double * parms, returning double
|
||||
extern EEL_BC_TYPE _asm_generic1parm[]; // 1 double * parms, returning double *
|
||||
extern EEL_BC_TYPE _asm_generic1parm_retd[]; // 1 double * parms, returning double
|
||||
|
||||
extern const void *const _asm_generic1parm_retd_end;
|
||||
extern const void *const _asm_generic1parm_end;
|
||||
extern const void *const _asm_generic2parm_retd_end;
|
||||
extern const void *const _asm_generic2parm_end;
|
||||
extern const void *const _asm_generic3parm_retd_end;
|
||||
extern const void *const _asm_generic3parm_end;
|
||||
#else
|
||||
|
||||
void _asm_generic3parm(void); // 3 double * parms, returning double *
|
||||
void _asm_generic3parm_end(void);
|
||||
void _asm_generic3parm_retd(void); // 3 double * parms, returning double
|
||||
void _asm_generic3parm_retd_end(void);
|
||||
void _asm_generic2parm(void); // 2 double * parms, returning double *
|
||||
void _asm_generic2parm_end(void);
|
||||
void _asm_generic2parm_retd(void); // 2 double * parms, returning double
|
||||
void _asm_generic2parm_retd_end(void);
|
||||
void _asm_generic1parm(void); // 1 double * parms, returning double *
|
||||
void _asm_generic1parm_end(void);
|
||||
void _asm_generic1parm_retd(void); // 1 double * parms, returning double
|
||||
void _asm_generic1parm_retd_end(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if EEL_F_SIZE == 4
|
||||
#define EEL_F_SSTR "4"
|
||||
#define EEL_F_SUFFIX "s"
|
||||
#else
|
||||
#define EEL_F_SSTR "8"
|
||||
#define EEL_F_SUFFIX "l"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif//__NS_EEL_ADDFUNCS_H__
|
62
Src/ns-eel2/ns-eel-func-ref.h
Normal file
62
Src/ns-eel2/ns-eel-func-ref.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef _NSEEL_FUNC_REF_H_
|
||||
#define _NSEEL_FUNC_REF_H_
|
||||
|
||||
#include "ns-eel.h"
|
||||
#define TMP_MKSTR2(x) #x
|
||||
#define TMP_MKSTR(x) TMP_MKSTR2(x)
|
||||
|
||||
const char *nseel_builtin_function_reference=
|
||||
"while\texpression\tExecutes expression until expression evaluates to zero"
|
||||
#if NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
", or until " TMP_MKSTR(NSEEL_LOOPFUNC_SUPPORT_MAXLEN) "iterations occur"
|
||||
#endif
|
||||
". An alternate and more useful syntax is while (expression) ( statements ), which evaluates statements after "
|
||||
"every non-zero evaluation of expression.\0"
|
||||
"loop\tcount,expression\tEvaluates count once, and then executes expression count"
|
||||
#if NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
", but not more than " TMP_MKSTR(NSEEL_LOOPFUNC_SUPPORT_MAXLEN) ","
|
||||
#endif
|
||||
" times.\0"
|
||||
"sin\tangle\tReturns the sine of the angle specified (specified in radians -- to convert from degrees to radians, multiply by $pi/180, or 0.017453).\0"
|
||||
"cos\tangle\tReturns the cosine of the angle specified (specified in radians).\0"
|
||||
"tan\tangle\tReturns the tangent of the angle specified (specified in radians).\0"
|
||||
"sqrt\tvalue\tReturns the square root of the parameter. If the parameter is negative, the return value is undefined.\0"
|
||||
"log\tvalue\tReturns the natural logarithm (base e) of the parameter. If the value is not greater than 0, the return value is undefined.\0"
|
||||
"log10\tvalue\tReturns the base-10 logarithm of the parameter. If the value is not greater than 0, the return value is undefined.\0"
|
||||
"asin\tvalue\tReturns the arc sine of the value specified (return value is in radians). If the parameter is not between -1.0 and 1.0 inclusive, the return value is undefined.\0"
|
||||
"acos\tvalue\tReturns the arc cosine of the value specified (return value is in radians). If the parameter is not between -1.0 and 1.0 inclusive, the return value is undefined.\0"
|
||||
"atan\tvalue\tReturns the arc tangent of the value specified (return value is in radians). If the parameter is not between -1.0 and 1.0 inclusive, the return value is undefined.\0"
|
||||
"atan2\tnumerator,denominator\tReturns the arc tangent of the numerator divided by the denominator, allowing the denominator to be 0, and using their signs to produce a more meaningful result.\0"
|
||||
"exp\texponent\tReturns the number e ($e, approximately 2.718) raised to the parameter-th power. This function is significantly faster than pow() or the ^ operator.\0"
|
||||
"abs\tvalue\tReturns the absolute value of the parameter.\0"
|
||||
"sqr\tvalue\tReturns the square of the parameter (similar to value*value, but only evaluating value once).\0"
|
||||
"min\t&value,&value\tReturns (by reference) the minimum value of the two parameters. Since min() returns by reference, expressions such as min(x,y) = 5 are possible.\0"
|
||||
"max\t&value,&value\tReturns (by reference) the maximum value of the two parameters. Since max() returns by reference, expressions such as max(x,y) = 5 are possible.\0"
|
||||
"sign\tvalue\tReturns 1.0 if the parameter is greater than 0, -1.0 if the parameter is less than 0, or 0 if the parameter is 0.\0"
|
||||
"floor\tvalue\tReturns the value rounded to the next lowest integer (floor(3.9)==3, floor(-3.1)==-4).\0"
|
||||
"ceil\tvalue\tReturns the value rounded to the next highest integer (ceil(3.1)==4, ceil(-3.9)==-3).\0"
|
||||
"invsqrt\tvalue\tReturns a fast inverse square root (1/sqrt(x)) approximation of the parameter.\0"
|
||||
"freembuf\taddress\tHints the runtime that memory above the address specified may no longer be used. The runtime may, at its leisure, choose to lose the contents of memory above the address specified.\0"
|
||||
"memcpy\tdest,src,length\tCopies length items of memory from src to dest. Regions are permitted to overlap.\0"
|
||||
"memset\toffset,value,length\tSets length items of memory at offset to value.\0"
|
||||
"mem_get_values\toffset, ...\tReads values from memory starting at offset into variables specified. Slower than regular memory reads for less than a few variables, faster for more than a few. Undefined behavior if used with more than 32767 variables.\0"
|
||||
"mem_set_values\toffset, ...\tWrites values to memory starting at offset from variables specified. Slower than regular memory writes for less than a few variables, faster for more than a few. Undefined behavior if used with more than 32767 variables.\0"
|
||||
"stack_push\t&value\tPushes value onto the user stack, returns a reference to the parameter.\0"
|
||||
"stack_pop\t&value\tPops a value from the user stack into value, or into a temporary buffer if value is not specified, and returns a reference to where the stack was popped. Note that no checking is done to determine if the stack is empty, and as such stack_pop() will never fail.\0"
|
||||
"stack_peek\tindex\tReturns a reference to the item on the top of the stack (if index is 0), or to the Nth item on the stack if index is greater than 0. \0"
|
||||
"stack_exch\t&value\tExchanges a value with the top of the stack, and returns a reference to the parameter (with the new value).\0"
|
||||
#ifdef NSEEL_EEL1_COMPAT_MODE
|
||||
"rand\tmax\tReturns a psuedorandom non-negative integer number less than the parameter.\0"
|
||||
"sigmoid\tvalue,constraint\tReturns 1.0/(1+exp(-x * (constraint))), or 0 if a divide by 0 would occur.\0"
|
||||
"band\tx,y\tReturns 1 if both x and y evaluate to nonzero, 0 if otherwise. Both parameters are always evaluated.\0"
|
||||
"bor\tx,y\tReturns 1 if either x or y evaluate to nonzero, 0 if otherwise. Both parameters are always evaluated.\0"
|
||||
"exec2\tx,y\tEvaluates x, then evaluates and returns y.\0"
|
||||
"exec3\tx,y,z\tEvaluates x, evaluates y, then evaluates and returns z.\0"
|
||||
#else
|
||||
"rand\t[max]\tReturns a psuedorandom real number between 0 and the parameter, inclusive. If the parameter is omitted or less than 1.0, 1.0 is used as a maximum instead.\0"
|
||||
|
||||
#endif
|
||||
;
|
||||
#undef TMP_MKSTR
|
||||
|
||||
#endif
|
331
Src/ns-eel2/ns-eel-int.h
Normal file
331
Src/ns-eel2/ns-eel-int.h
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
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__
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include "../wdltypes.h"
|
||||
#endif
|
||||
|
||||
#include "ns-eel.h"
|
||||
#include "ns-eel-addfuncs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
enum {
|
||||
|
||||
// these ignore fn in opcodes, just use fntype to determine function
|
||||
FN_MULTIPLY=0,
|
||||
FN_DIVIDE,
|
||||
FN_JOIN_STATEMENTS,
|
||||
FN_DENORMAL_LIKELY,
|
||||
FN_DENORMAL_UNLIKELY,
|
||||
FN_ADD,
|
||||
FN_SUB,
|
||||
FN_AND,
|
||||
FN_OR,
|
||||
FN_UMINUS,
|
||||
FN_NOT,
|
||||
FN_NOTNOT,
|
||||
FN_XOR,
|
||||
FN_SHL,
|
||||
FN_SHR,
|
||||
FN_MOD,
|
||||
FN_POW,
|
||||
FN_LT,
|
||||
FN_GT,
|
||||
FN_LTE,
|
||||
FN_GTE,
|
||||
FN_EQ,
|
||||
FN_EQ_EXACT,
|
||||
FN_NE,
|
||||
FN_NE_EXACT,
|
||||
FN_LOGICAL_AND,
|
||||
FN_LOGICAL_OR,
|
||||
FN_IF_ELSE,
|
||||
FN_MEMORY,
|
||||
FN_GMEMORY,
|
||||
FN_NONCONST_BEGIN,
|
||||
FN_ASSIGN=FN_NONCONST_BEGIN,
|
||||
|
||||
FN_ADD_OP,
|
||||
FN_SUB_OP,
|
||||
FN_MOD_OP,
|
||||
FN_OR_OP,
|
||||
FN_AND_OP,
|
||||
FN_XOR_OP,
|
||||
FN_DIV_OP,
|
||||
FN_MUL_OP,
|
||||
FN_POW_OP,
|
||||
|
||||
FN_WHILE,
|
||||
FN_LOOP,
|
||||
|
||||
FUNCTYPE_SIMPLEMAX,
|
||||
|
||||
|
||||
FUNCTYPE_FUNCTIONTYPEREC=1000, // fn is a functionType *
|
||||
FUNCTYPE_EELFUNC, // fn is a _codeHandleFunctionRec *
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define YYSTYPE opcodeRec *
|
||||
|
||||
#define NSEEL_CLOSEFACTOR 0.00001
|
||||
|
||||
|
||||
typedef struct opcodeRec opcodeRec;
|
||||
|
||||
typedef struct _codeHandleFunctionRec
|
||||
{
|
||||
struct _codeHandleFunctionRec *next; // main linked list (only used for high level functions)
|
||||
struct _codeHandleFunctionRec *derivedCopies; // separate linked list, _head being the main function, other copies being derived versions
|
||||
|
||||
void *startptr; // compiled code (may be cleared + recompiled when shared)
|
||||
opcodeRec *opcodes;
|
||||
|
||||
int startptr_size; // 0=no code. -1 = needs calculation. >0 = size.
|
||||
int tmpspace_req;
|
||||
|
||||
int num_params;
|
||||
|
||||
int rvMode; // RETURNVALUE_*
|
||||
int fpStackUsage; // 0-8, usually
|
||||
int canHaveDenormalOutput;
|
||||
|
||||
// local storage's first items are the parameters, then locals. Note that the opcodes will reference localstorage[] via VARPTRPTR, but
|
||||
// the values localstorage[x] points are reallocated from context-to-context, if it is a common function.
|
||||
|
||||
// separately allocated list of pointers, the contents of the list should be zeroed on context changes if a common function
|
||||
// note that when making variations on a function (context), it is shared, but since it is zeroed on context changes, it is context-local
|
||||
int localstorage_size;
|
||||
EEL_F **localstorage;
|
||||
|
||||
int isCommonFunction;
|
||||
int usesNamespaces;
|
||||
unsigned int parameterAsNamespaceMask;
|
||||
|
||||
char fname[NSEEL_MAX_FUNCSIG_NAME+1];
|
||||
} _codeHandleFunctionRec;
|
||||
|
||||
#define LLB_DSIZE (65536-64)
|
||||
typedef struct _llBlock {
|
||||
struct _llBlock *next;
|
||||
int sizeused;
|
||||
char block[LLB_DSIZE];
|
||||
} llBlock;
|
||||
|
||||
typedef struct {
|
||||
llBlock *blocks,
|
||||
*blocks_data;
|
||||
void *workTable; // references a chunk in blocks_data
|
||||
|
||||
void *code;
|
||||
int code_size; // in case the caller wants to write it out
|
||||
int code_stats[4];
|
||||
|
||||
int want_stack;
|
||||
void *stack; // references a chunk in blocks_data, somewhere within the complete NSEEL_STACK_SIZE aligned at NSEEL_STACK_SIZE
|
||||
|
||||
void *ramPtr;
|
||||
|
||||
int workTable_size; // size (minus padding/extra space) of workTable -- only used if EEL_VALIDATE_WORKTABLE_USE set, but might be handy to have around too
|
||||
int compile_flags;
|
||||
} codeHandleType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EEL_F *value;
|
||||
int refcnt;
|
||||
char isreg;
|
||||
char str[1];
|
||||
} varNameRec;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *ptr;
|
||||
int size, alloc;
|
||||
} eel_growbuf;
|
||||
#define EEL_GROWBUF(type) union { eel_growbuf _growbuf; type *_tval; }
|
||||
#define EEL_GROWBUF_RESIZE(gb, newsz) __growbuf_resize(&(gb)->_growbuf, (newsz)*(int)sizeof((gb)->_tval[0])) // <0 to free, does not realloc down otherwise
|
||||
#define EEL_GROWBUF_GET(gb) ((gb)->_tval)
|
||||
#define EEL_GROWBUF_GET_SIZE(gb) ((gb)->_growbuf.size/(int)sizeof((gb)->_tval[0]))
|
||||
|
||||
typedef struct _compileContext
|
||||
{
|
||||
eel_function_table *registered_func_tab;
|
||||
const char *(*func_check)(const char *fn_name, void *user); // return error message if not permitted
|
||||
void *func_check_user;
|
||||
|
||||
EEL_GROWBUF(varNameRec *) varNameList;
|
||||
EEL_F *varValueStore;
|
||||
int varValueStore_left;
|
||||
|
||||
int errVar,gotEndOfInput;
|
||||
opcodeRec *result;
|
||||
char last_error_string[256];
|
||||
|
||||
void *scanner;
|
||||
const char *rdbuf_start, *rdbuf, *rdbuf_end;
|
||||
|
||||
llBlock *tmpblocks_head, // used while compiling, and freed after compiling
|
||||
|
||||
*blocks_head, // used while compiling, transferred to code context (these are pages marked as executable)
|
||||
*blocks_head_data, // used while compiling, transferred to code context
|
||||
|
||||
*pblocks; // persistent blocks, stores data used by varTable_Names, varTable_Values, etc.
|
||||
|
||||
int l_stats[4]; // source bytes, static code bytes, call code bytes, data bytes
|
||||
int has_used_global_vars;
|
||||
|
||||
_codeHandleFunctionRec *functions_local, *functions_common;
|
||||
|
||||
// state used while generating functions
|
||||
int optimizeDisableFlags;
|
||||
int current_compile_flags;
|
||||
struct opcodeRec *directValueCache; // linked list using fn as next
|
||||
|
||||
int isSharedFunctions;
|
||||
int isGeneratingCommonFunction;
|
||||
int function_usesNamespaces;
|
||||
int function_globalFlag; // set if restrict globals to function_localTable_Names[2]
|
||||
// [0] is parameter+local symbols (combined space)
|
||||
// [1] is symbols which get implied "this." if used
|
||||
// [2] is globals permitted
|
||||
int function_localTable_Size[3]; // for parameters only
|
||||
char **function_localTable_Names[3]; // lists of pointers
|
||||
EEL_F **function_localTable_ValuePtrs;
|
||||
const char *function_curName; // name of current function
|
||||
|
||||
EEL_F (*onString)(void *caller_this, struct eelStringSegmentRec *list);
|
||||
EEL_F (*onNamedString)(void *caller_this, const char *name);
|
||||
|
||||
EEL_F *(*getVariable)(void *userctx, const char *name);
|
||||
void *getVariable_userctx;
|
||||
|
||||
codeHandleType *tmpCodeHandle;
|
||||
|
||||
struct
|
||||
{
|
||||
int needfree;
|
||||
int maxblocks;
|
||||
double closefact;
|
||||
EEL_F *blocks[NSEEL_RAM_BLOCKS];
|
||||
} ram_state
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((aligned (8)))
|
||||
#endif
|
||||
;
|
||||
|
||||
void *gram_blocks;
|
||||
|
||||
void *caller_this;
|
||||
}
|
||||
compileContext;
|
||||
|
||||
#define NSEEL_NPARAMS_FLAG_CONST 0x80000
|
||||
typedef struct functionType {
|
||||
const char *name;
|
||||
void *afunc;
|
||||
void *func_e;
|
||||
int nParams;
|
||||
void *replptrs[4];
|
||||
NSEEL_PPPROC pProc;
|
||||
} functionType;
|
||||
|
||||
functionType *nseel_getFunctionByName(compileContext *ctx, const char *name, int *mchk); // sets mchk (if non-NULL) to how far allowed to scan forward for duplicate names
|
||||
|
||||
opcodeRec *nseel_createCompiledValue(compileContext *ctx, EEL_F value);
|
||||
opcodeRec *nseel_createCompiledValuePtr(compileContext *ctx, EEL_F *addrValue, const char *namestr);
|
||||
|
||||
opcodeRec *nseel_createMoreParametersOpcode(compileContext *ctx, opcodeRec *code1, opcodeRec *code2);
|
||||
opcodeRec *nseel_createSimpleCompiledFunction(compileContext *ctx, int fn, int np, opcodeRec *code1, opcodeRec *code2);
|
||||
opcodeRec *nseel_createMemoryAccess(compileContext *ctx, opcodeRec *code1, opcodeRec *code2);
|
||||
opcodeRec *nseel_createIfElse(compileContext *ctx, opcodeRec *code1, opcodeRec *code2, opcodeRec *code3);
|
||||
opcodeRec *nseel_createFunctionByName(compileContext *ctx, const char *name, int np, opcodeRec *code1, opcodeRec *code2, opcodeRec *code3);
|
||||
|
||||
// converts a generic identifier (VARPTR) opcode into either an actual variable reference (parmcnt = -1),
|
||||
// or if parmcnt >= 0, to a function call (see nseel_setCompiledFunctionCallParameters())
|
||||
opcodeRec *nseel_resolve_named_symbol(compileContext *ctx, opcodeRec *rec, int parmcnt, int *errOut);
|
||||
|
||||
// sets parameters and calculates parameter count for opcode, and calls nseel_resolve_named_symbol() with the right
|
||||
// parameter count
|
||||
opcodeRec *nseel_setCompiledFunctionCallParameters(compileContext *ctx, opcodeRec *fn, opcodeRec *code1, opcodeRec *code2, opcodeRec *code3, opcodeRec *postCode, int *errOut);
|
||||
// errOut will be set if return NULL:
|
||||
// -1 if postCode set when not wanted (i.e. not while())
|
||||
// 0 if func not found,
|
||||
// 1 if function requires 2+ parameters but was given more
|
||||
// 2 if function needs more parameters
|
||||
// 4 if function requires 1 parameter but was given more
|
||||
|
||||
|
||||
|
||||
struct eelStringSegmentRec *nseel_createStringSegmentRec(compileContext *ctx, const char *str, int len);
|
||||
opcodeRec *nseel_eelMakeOpcodeFromStringSegments(compileContext *ctx, struct eelStringSegmentRec *rec);
|
||||
|
||||
EEL_F *nseel_int_register_var(compileContext *ctx, const char *name, int isReg, const char **namePtrOut);
|
||||
_codeHandleFunctionRec *eel_createFunctionNamespacedInstance(compileContext *ctx, _codeHandleFunctionRec *fr, const char *nameptr);
|
||||
|
||||
typedef struct nseel_globalVarItem
|
||||
{
|
||||
EEL_F data;
|
||||
struct nseel_globalVarItem *_next;
|
||||
char name[1]; // varlen, does not include _global. prefix
|
||||
} nseel_globalVarItem;
|
||||
|
||||
extern nseel_globalVarItem *nseel_globalreg_list; // if NSEEL_EEL1_COMPAT_MODE, must use NSEEL_getglobalregs() for regxx values
|
||||
|
||||
#include "y.tab.h"
|
||||
|
||||
// nseel_simple_tokenizer will return comments as tokens if state is non-NULL
|
||||
const char *nseel_simple_tokenizer(const char **ptr, const char *endptr, int *lenOut, int *state);
|
||||
int nseel_filter_escaped_string(char *outbuf, int outbuf_sz, const char *rdptr, size_t rdptr_size, char delim_char); // returns length used, minus NUL char
|
||||
|
||||
opcodeRec *nseel_translate(compileContext *ctx, const char *tmp, size_t tmplen); // tmplen=0 for nul-term
|
||||
int nseel_lookup(compileContext *ctx, opcodeRec **opOut, const char *sname);
|
||||
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAMAlloc(EEL_F **blocks, unsigned int w);
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAMAllocGMEM(EEL_F ***blocks, unsigned int w);
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAM_MemSet(EEL_F **blocks,EEL_F *dest, EEL_F *v, EEL_F *lenptr);
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAM_MemFree(void *blocks, EEL_F *which);
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAM_MemTop(void *blocks, EEL_F *which);
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAM_MemCpy(EEL_F **blocks,EEL_F *dest, EEL_F *src, EEL_F *lenptr);
|
||||
EEL_F NSEEL_CGEN_CALL __NSEEL_RAM_Mem_SetValues(EEL_F **blocks, INT_PTR np, EEL_F **parms);
|
||||
EEL_F NSEEL_CGEN_CALL __NSEEL_RAM_Mem_GetValues(EEL_F **blocks, INT_PTR np, EEL_F **parms);
|
||||
|
||||
extern EEL_F nseel_ramalloc_onfail; // address returned by __NSEEL_RAMAlloc et al on failure
|
||||
extern EEL_F * volatile nseel_gmembuf_default; // can free/zero this on DLL unload if needed
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif//__NS_EELINT_H__
|
275
Src/ns-eel2/ns-eel.h
Normal file
275
Src/ns-eel2/ns-eel.h
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
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__
|
||||
|
||||
// put standard includes here
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef EEL_F_SIZE
|
||||
#define EEL_F_SIZE 8
|
||||
#endif
|
||||
|
||||
#define NSEEL_EEL1_COMPAT_MODE
|
||||
|
||||
#include "wdltypes.h"
|
||||
|
||||
#if EEL_F_SIZE == 4
|
||||
typedef float EEL_F;
|
||||
typedef float *EEL_F_PTR;
|
||||
#else
|
||||
typedef double EEL_F WDL_FIXALIGN;
|
||||
typedef double *EEL_F_PTR;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define NSEEL_CGEN_CALL __cdecl
|
||||
#else
|
||||
#define NSEEL_CGEN_CALL
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// host should implement these (can be empty stub functions if no VM will execute code in multiple threads at once)
|
||||
|
||||
// implement if you will be running the code in same VM from multiple threads,
|
||||
// or VMs that have the same GRAM pointer from different threads, or multiple
|
||||
// VMs that have a NULL GRAM pointer from multiple threads.
|
||||
// if you give each VM it's own unique GRAM and only run each VM in one thread, then you can leave it blank.
|
||||
|
||||
// or if you're daring....
|
||||
|
||||
void NSEEL_HOSTSTUB_EnterMutex();
|
||||
void NSEEL_HOSTSTUB_LeaveMutex();
|
||||
|
||||
|
||||
int NSEEL_init(); // returns nonzero on failure (only if EEL_VALIDATE_FSTUBS defined), otherwise the same as NSEEL_quit(), and completely optional
|
||||
void NSEEL_quit(); // clears any added functions
|
||||
|
||||
|
||||
// adds a function that returns a value (EEL_F)
|
||||
#define NSEEL_addfunc_retval(name,np,pproc,fptr) \
|
||||
NSEEL_addfunc_ret_type(name,np,1,pproc,(void *)(fptr),NSEEL_ADDFUNC_DESTINATION)
|
||||
|
||||
// adds a function that returns a pointer (EEL_F*)
|
||||
#define NSEEL_addfunc_retptr(name,np,pproc,fptr) \
|
||||
NSEEL_addfunc_ret_type(name,np,0,pproc,(void *)(fptr),NSEEL_ADDFUNC_DESTINATION)
|
||||
|
||||
// adds a void or bool function
|
||||
#define NSEEL_addfunc_retbool(name,np,pproc,fptr) \
|
||||
NSEEL_addfunc_ret_type(name,np,-1,pproc,(void *)(fptr),NSEEL_ADDFUNC_DESTINATION)
|
||||
|
||||
// adds a function that takes min_np or more parameters (func sig needs to be EEL_F func(void *ctx, INT_PTR np, EEL_F **parms)
|
||||
#define NSEEL_addfunc_varparm(name, min_np, pproc, fptr) \
|
||||
NSEEL_addfunc_varparm_ex(name,min_np,0,pproc,fptr,NSEEL_ADDFUNC_DESTINATION)
|
||||
|
||||
// adds a function that takes np parameters via func: sig needs to be EEL_F func(void *ctx, INT_PTR np, EEL_F **parms)
|
||||
#define NSEEL_addfunc_exparms(name, np, pproc, fptr) \
|
||||
NSEEL_addfunc_varparm_ex(name,np,1,pproc,fptr,NSEEL_ADDFUNC_DESTINATION)
|
||||
|
||||
|
||||
// deprecated
|
||||
#define NSEEL_addfunction(name,nparms,code,len) NSEEL_addfunctionex((name),(nparms),(code),(len),0,0)
|
||||
#define NSEEL_addfunctionex(name,nparms,code,len,pproc,fptr) NSEEL_addfunctionex2((name),(nparms),(code),(len),(pproc),(fptr),0, NSEEL_ADDFUNC_DESTINATION)
|
||||
|
||||
#ifndef NSEEL_ADDFUNC_DESTINATION
|
||||
#define NSEEL_ADDFUNC_DESTINATION (NULL)
|
||||
#endif
|
||||
|
||||
struct functionType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct functionType *list;
|
||||
int list_size;
|
||||
} eel_function_table;
|
||||
|
||||
struct _compileContext;
|
||||
typedef void *(*NSEEL_PPPROC)(void *data, int data_size, struct _compileContext *userfunc_data);
|
||||
void NSEEL_addfunctionex2(const char *name, int nparms, char *code_startaddr, int code_len, NSEEL_PPPROC pproc, void *fptr, void *fptr2, eel_function_table *destination);
|
||||
|
||||
void NSEEL_addfunc_ret_type(const char *name, int np, int ret_type, NSEEL_PPPROC pproc, void *fptr, eel_function_table *destination); // ret_type=-1 for bool, 1 for value, 0 for ptr
|
||||
void NSEEL_addfunc_varparm_ex(const char *name, int min_np, int want_exact, NSEEL_PPPROC pproc, EEL_F (NSEEL_CGEN_CALL *fptr)(void *, INT_PTR, EEL_F **), eel_function_table *destination);
|
||||
|
||||
int *NSEEL_getstats(); // returns a pointer to 5 ints... source bytes, static code bytes, call code bytes, data bytes, number of code handles
|
||||
|
||||
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_SetFunctionTable(NSEEL_VMCTX, eel_function_table *tab); // use NULL to use default (global) table
|
||||
|
||||
// validateFunc can return error message if not permitted
|
||||
void NSEEL_VM_SetFunctionValidator(NSEEL_VMCTX, const char * (*validateFunc)(const char *fn_name, void *user), void *user);
|
||||
|
||||
void NSEEL_VM_remove_unused_vars(NSEEL_VMCTX _ctx);
|
||||
void NSEEL_VM_clear_var_refcnts(NSEEL_VMCTX _ctx);
|
||||
void NSEEL_VM_remove_all_nonreg_vars(NSEEL_VMCTX _ctx);
|
||||
void NSEEL_VM_enumallvars(NSEEL_VMCTX ctx, int (*func)(const char *name, EEL_F *val, void *ctx), void *userctx); // return false from func to stop
|
||||
|
||||
EEL_F *NSEEL_VM_regvar(NSEEL_VMCTX ctx, const char *name); // register a variable (before compilation)
|
||||
EEL_F *NSEEL_VM_getvar(NSEEL_VMCTX ctx, const char *name); // get a variable (if registered or created by code)
|
||||
int NSEEL_VM_get_var_refcnt(NSEEL_VMCTX _ctx, const char *name); // returns -1 if not registered, or >=0
|
||||
void NSEEL_VM_set_var_resolver(NSEEL_VMCTX ctx, EEL_F *(*res)(void *userctx, const char *name), void *userctx);
|
||||
|
||||
void NSEEL_VM_freeRAM(NSEEL_VMCTX ctx); // clears and frees all (VM) RAM used
|
||||
void NSEEL_VM_freeRAMIfCodeRequested(NSEEL_VMCTX); // call after code to free the script-requested memory
|
||||
int NSEEL_VM_wantfreeRAM(NSEEL_VMCTX ctx); // want NSEEL_VM_freeRAMIfCodeRequested?
|
||||
|
||||
// if you set this, it uses a local GMEM context.
|
||||
// Must be set before compilation.
|
||||
// void *p=NULL;
|
||||
// NSEEL_VM_SetGRAM(ctx,&p);
|
||||
// .. do stuff
|
||||
// NSEEL_VM_FreeGRAM(&p);
|
||||
void NSEEL_VM_SetGRAM(NSEEL_VMCTX ctx, void **gram);
|
||||
void NSEEL_VM_FreeGRAM(void **ufd); // frees a gmem context.
|
||||
void NSEEL_VM_SetCustomFuncThis(NSEEL_VMCTX ctx, void *thisptr);
|
||||
|
||||
EEL_F *NSEEL_VM_getramptr(NSEEL_VMCTX ctx, unsigned int offs, int *validCount);
|
||||
EEL_F *NSEEL_VM_getramptr_noalloc(NSEEL_VMCTX ctx, unsigned int offs, int *validCount);
|
||||
|
||||
|
||||
// set 0 to query. returns actual value used (limits, granularity apply -- see NSEEL_RAM_BLOCKS)
|
||||
int NSEEL_VM_setramsize(NSEEL_VMCTX ctx, int maxent);
|
||||
|
||||
|
||||
struct eelStringSegmentRec {
|
||||
struct eelStringSegmentRec *_next;
|
||||
const char *str_start; // escaped characters, including opening/trailing characters
|
||||
int str_len;
|
||||
};
|
||||
void NSEEL_VM_SetStringFunc(NSEEL_VMCTX ctx,
|
||||
EEL_F (*onString)(void *caller_this, struct eelStringSegmentRec *list),
|
||||
EEL_F (*onNamedString)(void *caller_this, const char *name));
|
||||
|
||||
// call with NULL to calculate size, or non-null to generate to buffer (returning size used -- will not null terminate, caller responsibility)
|
||||
int nseel_stringsegments_tobuf(char *bufOut, int bufout_sz, struct eelStringSegmentRec *list);
|
||||
|
||||
|
||||
NSEEL_CODEHANDLE NSEEL_code_compile(NSEEL_VMCTX ctx, const char *code, int lineoffs);
|
||||
#define NSEEL_CODE_COMPILE_FLAG_COMMONFUNCS 1 // allows that code's functions to be used in other code (note you shouldn't destroy that codehandle without destroying others first if used)
|
||||
#define NSEEL_CODE_COMPILE_FLAG_COMMONFUNCS_RESET 2 // resets common code functions
|
||||
#define NSEEL_CODE_COMPILE_FLAG_NOFPSTATE 4 // hint that the FPU/SSE state should be good-to-go
|
||||
#define NSEEL_CODE_COMPILE_FLAG_ONLY_BUILTIN_FUNCTIONS 8 // very restrictive mode (only math functions really)
|
||||
|
||||
NSEEL_CODEHANDLE NSEEL_code_compile_ex(NSEEL_VMCTX ctx, const char *code, int lineoffs, int flags);
|
||||
|
||||
char *NSEEL_code_getcodeerror(NSEEL_VMCTX ctx);
|
||||
int NSEEL_code_geterror_flag(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
|
||||
|
||||
|
||||
// global memory control/view
|
||||
extern unsigned int NSEEL_RAM_limitmem; // if nonzero, memory limit for user data, in bytes
|
||||
extern unsigned int NSEEL_RAM_memused;
|
||||
extern int NSEEL_RAM_memused_errors;
|
||||
|
||||
|
||||
|
||||
// configuration:
|
||||
|
||||
// use the handwritten lexer -- the flex (eel2.l generated) lexer mostly works, but doesn't support string parsing at the moment
|
||||
// this mode is faster and uses less ram than eel2.l anyway, so leave it on
|
||||
#define NSEEL_SUPER_MINIMAL_LEXER
|
||||
|
||||
// #define NSEEL_EEL1_COMPAT_MODE // supports old behaviors (continue after failed compile), old functions _bnot etc. disables string support (strings were used as comments in eel1 etc)
|
||||
|
||||
#define NSEEL_MAX_VARIABLE_NAMELEN 128 // define this to override the max variable length
|
||||
#define NSEEL_MAX_EELFUNC_PARAMETERS 40
|
||||
#define NSEEL_MAX_FUNCSIG_NAME 2048 // longer than variable maxlen, due to multiple namespaces
|
||||
|
||||
// maximum loop length (0 for unlimited)
|
||||
#ifndef NSEEL_LOOPFUNC_SUPPORT_MAXLEN
|
||||
#define NSEEL_LOOPFUNC_SUPPORT_MAXLEN 1048576
|
||||
#endif
|
||||
|
||||
#define NSEEL_MAX_FUNCTION_SIZE_FOR_INLINE 2048
|
||||
|
||||
// when a VM ctx doesn't have a GRAM context set, make the global one this big
|
||||
#define NSEEL_SHARED_GRAM_SIZE (1<<20)
|
||||
|
||||
//#define EEL_DUMP_OPS // used for testing frontend parser/logic changes
|
||||
|
||||
// note: if you wish to change NSEEL_RAM_*, and your target is x86-64, you will need to regenerate things.
|
||||
|
||||
// on osx:
|
||||
// php a2x64.php win64x
|
||||
// php a2x64.php macho64
|
||||
|
||||
// or on win32:
|
||||
// php a2x64.php
|
||||
// php a2x64.php macho64x
|
||||
// this will regenerate the .asm files and object files
|
||||
|
||||
// 512 * 65536 = 32 million entries maximum (256MB RAM)
|
||||
// default is limited to 128 * 65536 = 8 million entries (64MB RAM)
|
||||
|
||||
// default to 8 million entries, use NSEEL_VM_setramsize() to change at runtime
|
||||
#define NSEEL_RAM_BLOCKS_DEFAULTMAX 128
|
||||
|
||||
// 512 entry block table maximum (2k/4k per VM)
|
||||
#define NSEEL_RAM_BLOCKS_LOG2 9
|
||||
|
||||
// 65536 items per block (512KB)
|
||||
#define NSEEL_RAM_ITEMSPERBLOCK_LOG2 16
|
||||
|
||||
#define NSEEL_RAM_BLOCKS (1 << NSEEL_RAM_BLOCKS_LOG2)
|
||||
#define NSEEL_RAM_ITEMSPERBLOCK (1<<NSEEL_RAM_ITEMSPERBLOCK_LOG2)
|
||||
|
||||
#define NSEEL_STACK_SIZE 4096 // about 64k overhead if the stack functions are used in a given code handle
|
||||
|
||||
// arch neutral mode, runs about 1/8th speed or so
|
||||
//#define EEL_TARGET_PORTABLE
|
||||
|
||||
#ifdef EEL_TARGET_PORTABLE
|
||||
#define EEL_BC_TYPE int
|
||||
#endif
|
||||
|
||||
#ifdef NSEEL_EEL1_COMPAT_MODE
|
||||
double *NSEEL_getglobalregs();
|
||||
#endif
|
||||
|
||||
void eel_setfp_round(); // use to set fp to rounding mode (normal) -- only really use this when being called from EEL
|
||||
void eel_setfp_trunc(); // use to restore fp to trunc mode -- only really use this when being called from EEL
|
||||
|
||||
void eel_enterfp(int s[2]);
|
||||
void eel_leavefp(int s[2]);
|
||||
|
||||
extern void *(*nseel_gmem_calloc)(size_t,size_t); // set this to the calloc() implementation used by the context that will call NSEEL_VM_FreeGRAM()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//__NS_EEL_H__
|
1
Src/ns-eel2/nseel-caltab.c
Normal file
1
Src/ns-eel2/nseel-caltab.c
Normal file
@ -0,0 +1 @@
|
||||
// no longer used
|
188
Src/ns-eel2/nseel-cfunc.c
Normal file
188
Src/ns-eel2/nseel-cfunc.c
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
Expression Evaluator Library (NS-EEL) v2
|
||||
Copyright (C) 2004-2013 Cockos Incorporated
|
||||
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 "ns-eel-int.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
// these are used by our assembly code
|
||||
|
||||
|
||||
#define N 624
|
||||
#define M 397
|
||||
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
|
||||
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
|
||||
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
|
||||
|
||||
static unsigned int genrand_int32(void)
|
||||
{
|
||||
|
||||
unsigned int y;
|
||||
static unsigned int mag01[2]={0x0UL, MATRIX_A};
|
||||
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||
|
||||
static unsigned int mt[N]; /* the array for the state vector */
|
||||
static int mti; /* mti==N+1 means mt[N] is not initialized */
|
||||
|
||||
|
||||
if (!mti)
|
||||
{
|
||||
unsigned int s=0x4141f00d;
|
||||
mt[0]= s & 0xffffffffUL;
|
||||
for (mti=1; mti<N; mti++)
|
||||
{
|
||||
mt[mti] =
|
||||
(1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
|
||||
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
|
||||
/* In the previous versions, MSBs of the seed affect */
|
||||
/* only MSBs of the array mt[]. */
|
||||
/* 2002/01/09 modified by Makoto Matsumoto */
|
||||
mt[mti] &= 0xffffffffUL;
|
||||
/* for >32 bit machines */
|
||||
}
|
||||
}
|
||||
|
||||
if (mti >= N) { /* generate N words at one time */
|
||||
int kk;
|
||||
|
||||
for (kk=0;kk<N-M;kk++) {
|
||||
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
|
||||
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
|
||||
}
|
||||
for (;kk<N-1;kk++) {
|
||||
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
|
||||
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
|
||||
}
|
||||
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
y = mt[mti++];
|
||||
|
||||
/* Tempering */
|
||||
y ^= (y >> 11);
|
||||
y ^= (y << 7) & 0x9d2c5680UL;
|
||||
y ^= (y << 15) & 0xefc60000UL;
|
||||
y ^= (y >> 18);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
EEL_F NSEEL_CGEN_CALL nseel_int_rand(EEL_F f)
|
||||
{
|
||||
EEL_F x=floor(f);
|
||||
if (x < 1.0) x=1.0;
|
||||
|
||||
#ifdef NSEEL_EEL1_COMPAT_MODE
|
||||
return (EEL_F)(genrand_int32()%(int)x);
|
||||
#else
|
||||
return (EEL_F) (genrand_int32()*(1.0/(double)0xFFFFFFFF)*x);
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef EEL_TARGET_PORTABLE
|
||||
|
||||
#ifdef __ppc__
|
||||
#include "asm-nseel-ppc-gcc.c"
|
||||
#elif defined(__aarch64__)
|
||||
#include "asm-nseel-aarch64-gcc.c"
|
||||
#elif defined(__arm__)
|
||||
#include "asm-nseel-arm-gcc.c"
|
||||
#elif defined (_M_ARM) && _M_ARM == 7
|
||||
// vc on ARM, tbd
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN64
|
||||
//nasm
|
||||
#else
|
||||
#include "asm-nseel-x86-msvc.c"
|
||||
|
||||
void eel_setfp_round()
|
||||
{
|
||||
short oldsw;
|
||||
__asm
|
||||
{
|
||||
fnstcw [oldsw]
|
||||
mov ax, [oldsw]
|
||||
and ax, 0xF3FF // round to nearest
|
||||
mov [oldsw], ax
|
||||
fldcw [oldsw]
|
||||
}
|
||||
}
|
||||
void eel_setfp_trunc()
|
||||
{
|
||||
short oldsw;
|
||||
__asm
|
||||
{
|
||||
fnstcw [oldsw]
|
||||
mov ax, [oldsw]
|
||||
or ax, 0xC00 // truncate
|
||||
mov [oldsw], ax
|
||||
fldcw [oldsw]
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#elif !defined(__LP64__)
|
||||
#define FUNCTION_MARKER "\n.byte 0x89,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90\n"
|
||||
#include "asm-nseel-x86-gcc.c"
|
||||
void eel_setfp_round()
|
||||
{
|
||||
__asm__(
|
||||
"subl $16, %esp\n"
|
||||
"fnstcw (%esp)\n"
|
||||
"mov (%esp), %ax\n"
|
||||
"and $0xF3FF, %ax\n" // set round to nearest
|
||||
"mov %ax, 4(%esp)\n"
|
||||
"fldcw 4(%esp)\n"
|
||||
"addl $16, %esp\n"
|
||||
);
|
||||
}
|
||||
void eel_setfp_trunc()
|
||||
{
|
||||
__asm__(
|
||||
"subl $16, %esp\n"
|
||||
"fnstcw (%esp)\n"
|
||||
"mov (%esp), %ax\n"
|
||||
"or $0xC00, %ax\n" // set to truncate
|
||||
"mov %ax, 4(%esp)\n"
|
||||
"fldcw 4(%esp)\n"
|
||||
"addl $16, %esp\n"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
5700
Src/ns-eel2/nseel-compiler.c
Normal file
5700
Src/ns-eel2/nseel-compiler.c
Normal file
File diff suppressed because it is too large
Load Diff
447
Src/ns-eel2/nseel-eval.c
Normal file
447
Src/ns-eel2/nseel-eval.c
Normal file
@ -0,0 +1,447 @@
|
||||
/*
|
||||
Expression Evaluator Library (NS-EEL) v2
|
||||
Copyright (C) 2004-2013 Cockos Incorporated
|
||||
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 <string.h>
|
||||
#include <ctype.h>
|
||||
#include "ns-eel-int.h"
|
||||
#include "wdlcstring.h"
|
||||
|
||||
|
||||
static const char *nseel_skip_space_and_comments(const char *p, const char *endptr)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
while (p < endptr && isspace(p[0])) p++;
|
||||
if (p >= endptr-1 || *p != '/') return p;
|
||||
|
||||
if (p[1]=='/')
|
||||
{
|
||||
while (p < endptr && *p != '\r' && *p != '\n') p++;
|
||||
}
|
||||
else if (p[1] == '*')
|
||||
{
|
||||
p+=2;
|
||||
while (p < endptr-1 && (p[0] != '*' || p[1] != '/')) p++;
|
||||
p+=2;
|
||||
if (p>=endptr) return endptr;
|
||||
}
|
||||
else return p;
|
||||
}
|
||||
}
|
||||
|
||||
// removes any escaped characters, also will convert pairs delim_char into single delim_chars
|
||||
int nseel_filter_escaped_string(char *outbuf, int outbuf_sz, const char *rdptr, size_t rdptr_size, char delim_char)
|
||||
{
|
||||
int outpos = 0;
|
||||
const char *rdptr_end = rdptr + rdptr_size;
|
||||
while (rdptr < rdptr_end && outpos < outbuf_sz-1)
|
||||
{
|
||||
char thisc=*rdptr;
|
||||
if (thisc == '\\' && rdptr < rdptr_end-1)
|
||||
{
|
||||
const char nc = rdptr[1];
|
||||
if (nc == 'r' || nc == 'R') { thisc = '\r'; }
|
||||
else if (nc == 'n' || nc == 'N') { thisc = '\n'; }
|
||||
else if (nc == 't' || nc == 'T') { thisc = '\t'; }
|
||||
else if (nc == 'b' || nc == 'B') { thisc = '\b'; }
|
||||
else if ((nc >= '0' && nc <= '9') || nc == 'x' || nc == 'X')
|
||||
{
|
||||
unsigned char c=0;
|
||||
char base_shift = 3;
|
||||
char num_top = '7';
|
||||
|
||||
rdptr++; // skip backslash
|
||||
if (nc > '9') // implies xX
|
||||
{
|
||||
base_shift = 4;
|
||||
num_top = '9';
|
||||
rdptr ++; // skip x
|
||||
}
|
||||
|
||||
while (rdptr < rdptr_end)
|
||||
{
|
||||
char tc=*rdptr;
|
||||
if (tc >= '0' && tc <= num_top)
|
||||
{
|
||||
c = (c<<base_shift) + tc - '0';
|
||||
}
|
||||
else if (base_shift==4)
|
||||
{
|
||||
if (tc >= 'a' && tc <= 'f')
|
||||
{
|
||||
c = (c<<base_shift) + (tc - 'a' + 10);
|
||||
}
|
||||
else if (tc >= 'A' && tc <= 'F')
|
||||
{
|
||||
c = (c<<base_shift) + (tc - 'A' + 10);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else break;
|
||||
|
||||
rdptr++;
|
||||
}
|
||||
outbuf[outpos++] = (char)c;
|
||||
continue;
|
||||
}
|
||||
else // \c where c is an unknown character drops the backslash -- works for \, ', ", etc
|
||||
{
|
||||
thisc = nc;
|
||||
}
|
||||
rdptr+=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thisc == delim_char) break;
|
||||
rdptr++;
|
||||
}
|
||||
outbuf[outpos++] = thisc;
|
||||
}
|
||||
outbuf[outpos]=0;
|
||||
return outpos;
|
||||
}
|
||||
|
||||
int nseel_stringsegments_tobuf(char *bufOut, int bufout_sz, struct eelStringSegmentRec *list) // call with NULL to calculate size, or non-null to generate to buffer (returning size used)
|
||||
{
|
||||
int pos=0;
|
||||
while (list)
|
||||
{
|
||||
if (!bufOut)
|
||||
{
|
||||
pos += list->str_len;
|
||||
}
|
||||
else if (list->str_len > 1)
|
||||
{
|
||||
if (pos >= bufout_sz) break;
|
||||
pos += nseel_filter_escaped_string(bufOut + pos, bufout_sz-pos, list->str_start+1, list->str_len-1, list->str_start[0]);
|
||||
}
|
||||
list = list->_next;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// state can be NULL, it will be set if finished with unterminated thing: 1 for multiline comment, ' or " for string
|
||||
const char *nseel_simple_tokenizer(const char **ptr, const char *endptr, int *lenOut, int *state)
|
||||
{
|
||||
const char *p = *ptr;
|
||||
const char *rv = p;
|
||||
|
||||
if (state) // if state set, returns comments as tokens
|
||||
{
|
||||
if (*state == 1) goto in_comment;
|
||||
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
if (*state == '\'' || *state == '\"')
|
||||
{
|
||||
delim = (char)*state;
|
||||
goto in_string;
|
||||
}
|
||||
#endif
|
||||
|
||||
// skip any whitespace
|
||||
while (p < endptr && isspace(p[0])) p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// state not passed, skip comments (do not return them as tokens)
|
||||
p = nseel_skip_space_and_comments(p,endptr);
|
||||
}
|
||||
|
||||
if (p >= endptr)
|
||||
{
|
||||
*ptr = endptr;
|
||||
*lenOut = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv=p;
|
||||
|
||||
if (*p == '$' && p+3 < endptr && p[1] == '\'' && p[3] == '\'')
|
||||
{
|
||||
p+=4;
|
||||
}
|
||||
else if (state && *p == '/' && p < endptr-1 && (p[1] == '/' || p[1] == '*'))
|
||||
{
|
||||
if (p[1] == '/')
|
||||
{
|
||||
while (p < endptr && *p != '\r' && *p != '\n') p++; // advance to end of line
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state) *state=1;
|
||||
p+=2;
|
||||
in_comment:
|
||||
while (p < endptr)
|
||||
{
|
||||
const char c = *p++;
|
||||
if (c == '*' && p < endptr && *p == '/')
|
||||
{
|
||||
p++;
|
||||
if (state) *state=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (isalnum(*p) || *p == '_' || *p == '#' || *p == '$')
|
||||
{
|
||||
if (*p == '$' && p < endptr-1 && p[1] == '~') p++;
|
||||
p++;
|
||||
while (p < endptr && (isalnum(*p) || *p == '_' || *p == '.')) p++;
|
||||
}
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
else if (*p == '\'' || *p == '\"')
|
||||
{
|
||||
delim = *p++;
|
||||
if (state) *state=delim;
|
||||
in_string:
|
||||
|
||||
while (p < endptr)
|
||||
{
|
||||
const char c = *p++;
|
||||
if (p < endptr && c == '\\') p++; // skip escaped characters
|
||||
else if (c == delim)
|
||||
{
|
||||
if (state) *state=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
p++;
|
||||
}
|
||||
*ptr = p;
|
||||
*lenOut = (int) (p - rv);
|
||||
return p>rv ? rv : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef NSEEL_SUPER_MINIMAL_LEXER
|
||||
|
||||
int nseellex(opcodeRec **output, YYLTYPE * yylloc_param, compileContext *scctx)
|
||||
{
|
||||
int rv=0,toklen=0;
|
||||
const char *rdptr = scctx->rdbuf;
|
||||
const char *endptr = scctx->rdbuf_end;
|
||||
const char *tok = nseel_simple_tokenizer(&rdptr,endptr,&toklen,NULL);
|
||||
*output = 0;
|
||||
if (tok)
|
||||
{
|
||||
rv = tok[0];
|
||||
if (rv == '$')
|
||||
{
|
||||
if (rdptr != tok+1)
|
||||
{
|
||||
*output = nseel_translate(scctx,tok,rdptr-tok);
|
||||
if (*output) rv=VALUE;
|
||||
}
|
||||
}
|
||||
#ifndef NSEEL_EEL1_COMPAT_MODE
|
||||
else if (rv == '#' && scctx->onNamedString)
|
||||
{
|
||||
*output = nseel_translate(scctx,tok,rdptr-tok);
|
||||
if (*output) rv=STRING_IDENTIFIER;
|
||||
}
|
||||
else if (rv == '\'')
|
||||
{
|
||||
if (toklen > 1 && tok[toklen-1] == '\'')
|
||||
{
|
||||
*output = nseel_translate(scctx, tok, toklen);
|
||||
if (*output) rv = VALUE;
|
||||
}
|
||||
else scctx->gotEndOfInput|=8;
|
||||
}
|
||||
else if (rv == '\"' && scctx->onString)
|
||||
{
|
||||
if (toklen > 1 && tok[toklen-1] == '\"')
|
||||
{
|
||||
*output = (opcodeRec *)nseel_createStringSegmentRec(scctx,tok,toklen);
|
||||
if (*output) rv = STRING_LITERAL;
|
||||
}
|
||||
else scctx->gotEndOfInput|=16;
|
||||
}
|
||||
#endif
|
||||
else if (isalpha(rv) || rv == '_')
|
||||
{
|
||||
// toklen already valid
|
||||
char buf[NSEEL_MAX_VARIABLE_NAMELEN*2];
|
||||
if (toklen > sizeof(buf) - 1) toklen=sizeof(buf) - 1;
|
||||
memcpy(buf,tok,toklen);
|
||||
buf[toklen]=0;
|
||||
*output = nseel_createCompiledValuePtr(scctx, NULL, buf);
|
||||
if (*output) rv = IDENTIFIER;
|
||||
}
|
||||
else if ((rv >= '0' && rv <= '9') || (rv == '.' && (rdptr < endptr && rdptr[0] >= '0' && rdptr[0] <= '9')))
|
||||
{
|
||||
if (rv == '0' && rdptr < endptr && (rdptr[0] == 'x' || rdptr[0] == 'X'))
|
||||
{
|
||||
rdptr++;
|
||||
while (rdptr < endptr && (rv=rdptr[0]) && ((rv>='0' && rv<='9') || (rv>='a' && rv<='f') || (rv>='A' && rv<='F'))) rdptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int pcnt=rv == '.';
|
||||
while (rdptr < endptr && (rv=rdptr[0]) && ((rv>='0' && rv<='9') || (rv == '.' && !pcnt++))) rdptr++;
|
||||
}
|
||||
*output = nseel_translate(scctx,tok,rdptr-tok);
|
||||
if (*output) rv=VALUE;
|
||||
}
|
||||
else if (rv == '<')
|
||||
{
|
||||
const char nc=*rdptr;
|
||||
if (nc == '<')
|
||||
{
|
||||
rdptr++;
|
||||
rv=TOKEN_SHL;
|
||||
}
|
||||
else if (nc == '=')
|
||||
{
|
||||
rdptr++;
|
||||
rv=TOKEN_LTE;
|
||||
}
|
||||
}
|
||||
else if (rv == '>')
|
||||
{
|
||||
const char nc=*rdptr;
|
||||
if (nc == '>')
|
||||
{
|
||||
rdptr++;
|
||||
rv=TOKEN_SHR;
|
||||
}
|
||||
else if (nc == '=')
|
||||
{
|
||||
rdptr++;
|
||||
rv=TOKEN_GTE;
|
||||
}
|
||||
}
|
||||
else if (rv == '&' && *rdptr == '&')
|
||||
{
|
||||
rdptr++;
|
||||
rv = TOKEN_LOGICAL_AND;
|
||||
}
|
||||
else if (rv == '|' && *rdptr == '|')
|
||||
{
|
||||
rdptr++;
|
||||
rv = TOKEN_LOGICAL_OR;
|
||||
}
|
||||
else if (*rdptr == '=')
|
||||
{
|
||||
switch (rv)
|
||||
{
|
||||
case '+': rv=TOKEN_ADD_OP; rdptr++; break;
|
||||
case '-': rv=TOKEN_SUB_OP; rdptr++; break;
|
||||
case '%': rv=TOKEN_MOD_OP; rdptr++; break;
|
||||
case '|': rv=TOKEN_OR_OP; rdptr++; break;
|
||||
case '&': rv=TOKEN_AND_OP; rdptr++; break;
|
||||
case '~': rv=TOKEN_XOR_OP; rdptr++; break;
|
||||
case '/': rv=TOKEN_DIV_OP; rdptr++; break;
|
||||
case '*': rv=TOKEN_MUL_OP; rdptr++; break;
|
||||
case '^': rv=TOKEN_POW_OP; rdptr++; break;
|
||||
case '!':
|
||||
rdptr++;
|
||||
if (rdptr < endptr && *rdptr == '=')
|
||||
{
|
||||
rdptr++;
|
||||
rv=TOKEN_NE_EXACT;
|
||||
}
|
||||
else
|
||||
rv=TOKEN_NE;
|
||||
break;
|
||||
case '=':
|
||||
rdptr++;
|
||||
if (rdptr < endptr && *rdptr == '=')
|
||||
{
|
||||
rdptr++;
|
||||
rv=TOKEN_EQ_EXACT;
|
||||
}
|
||||
else
|
||||
rv=TOKEN_EQ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scctx->rdbuf = rdptr;
|
||||
yylloc_param->first_column = (int)(tok - scctx->rdbuf_start);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
void nseelerror(YYLTYPE *pos,compileContext *ctx, const char *str)
|
||||
{
|
||||
ctx->errVar=pos->first_column>0?pos->first_column:(int)(ctx->rdbuf_end - ctx->rdbuf_start);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
int nseel_gets(compileContext *ctx, char *buf, size_t sz)
|
||||
{
|
||||
int n=0;
|
||||
const char *endptr = ctx->rdbuf_end;
|
||||
const char *rdptr = ctx->rdbuf;
|
||||
if (!rdptr) return 0;
|
||||
|
||||
while (n < sz && rdptr < endptr) buf[n++] = *rdptr++;
|
||||
ctx->rdbuf=rdptr;
|
||||
return n;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//#define EEL_TRACE_LEX
|
||||
|
||||
#ifdef EEL_TRACE_LEX
|
||||
#define nseellex nseellex2
|
||||
|
||||
#endif
|
||||
#include "lex.nseel.c"
|
||||
|
||||
#ifdef EEL_TRACE_LEX
|
||||
|
||||
#undef nseellex
|
||||
|
||||
int nseellex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
|
||||
{
|
||||
int a=nseellex2(yylval_param,yylloc_param,yyscanner);
|
||||
|
||||
char buf[512];
|
||||
sprintf(buf,"tok: %c (%d)\n",a,a);
|
||||
OutputDebugString(buf);
|
||||
return a;
|
||||
}
|
||||
#endif//EEL_TRACE_LEX
|
||||
|
||||
|
||||
void nseelerror(YYLTYPE *pos,compileContext *ctx, const char *str)
|
||||
{
|
||||
ctx->errVar=pos->first_column>0?pos->first_column:(int)(ctx->rdbuf_end - ctx->rdbuf_start);
|
||||
}
|
||||
#endif // !NSEEL_SUPER_MINIMAL_LEXER
|
1
Src/ns-eel2/nseel-lextab.c
Normal file
1
Src/ns-eel2/nseel-lextab.c
Normal file
@ -0,0 +1 @@
|
||||
// no longer used
|
463
Src/ns-eel2/nseel-ram.c
Normal file
463
Src/ns-eel2/nseel-ram.c
Normal file
@ -0,0 +1,463 @@
|
||||
/*
|
||||
Expression Evaluator Library (NS-EEL) v2
|
||||
Copyright (C) 2004-2013 Cockos Incorporated
|
||||
Copyright (C) 1999-2003 Nullsoft, Inc.
|
||||
|
||||
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.h"
|
||||
#include "ns-eel-int.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <malloc.h>
|
||||
#ifdef _MSC_VER
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
unsigned int NSEEL_RAM_limitmem=0;
|
||||
unsigned int NSEEL_RAM_memused=0;
|
||||
int NSEEL_RAM_memused_errors=0;
|
||||
|
||||
|
||||
|
||||
int NSEEL_VM_wantfreeRAM(NSEEL_VMCTX ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
compileContext *c=(compileContext*)ctx;
|
||||
if (c->ram_state.needfree)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NSEEL_VM_freeRAMIfCodeRequested(NSEEL_VMCTX ctx) // check to see if our free flag was set
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
compileContext *c=(compileContext*)ctx;
|
||||
if (c->ram_state.needfree)
|
||||
{
|
||||
NSEEL_HOSTSTUB_EnterMutex();
|
||||
{
|
||||
INT_PTR startpos=((INT_PTR)c->ram_state.needfree)-1;
|
||||
EEL_F **blocks = c->ram_state.blocks;
|
||||
INT_PTR pos=0;
|
||||
int x;
|
||||
for (x = 0; x < NSEEL_RAM_BLOCKS; x ++)
|
||||
{
|
||||
if (pos >= startpos)
|
||||
{
|
||||
if (blocks[x])
|
||||
{
|
||||
if (NSEEL_RAM_memused >= sizeof(EEL_F) * NSEEL_RAM_ITEMSPERBLOCK)
|
||||
NSEEL_RAM_memused -= sizeof(EEL_F) * NSEEL_RAM_ITEMSPERBLOCK;
|
||||
else NSEEL_RAM_memused_errors++;
|
||||
free(blocks[x]);
|
||||
blocks[x]=0;
|
||||
}
|
||||
}
|
||||
pos+=NSEEL_RAM_ITEMSPERBLOCK;
|
||||
}
|
||||
c->ram_state.needfree=0;
|
||||
}
|
||||
NSEEL_HOSTSTUB_LeaveMutex();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
EEL_F nseel_ramalloc_onfail;
|
||||
EEL_F * volatile nseel_gmembuf_default;
|
||||
|
||||
|
||||
void *(*nseel_gmem_calloc)(size_t a, size_t b);
|
||||
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAMAllocGMEM(EEL_F ***blocks, unsigned int w)
|
||||
{
|
||||
if (blocks)
|
||||
{
|
||||
EEL_F **pblocks=*blocks;
|
||||
|
||||
if (w < NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK)
|
||||
{
|
||||
const unsigned int whichblock = w/NSEEL_RAM_ITEMSPERBLOCK;
|
||||
EEL_F *p=NULL;
|
||||
if (!pblocks || !(p=pblocks[whichblock]))
|
||||
{
|
||||
NSEEL_HOSTSTUB_EnterMutex();
|
||||
if (!nseel_gmem_calloc) nseel_gmem_calloc=calloc;
|
||||
|
||||
if (!(pblocks=*blocks)) pblocks = *blocks = (EEL_F **)nseel_gmem_calloc(sizeof(EEL_F *),NSEEL_RAM_BLOCKS);
|
||||
else p = pblocks[whichblock];
|
||||
|
||||
if (!p && pblocks)
|
||||
{
|
||||
p=pblocks[whichblock]=(EEL_F *)nseel_gmem_calloc(sizeof(EEL_F),NSEEL_RAM_ITEMSPERBLOCK);
|
||||
}
|
||||
NSEEL_HOSTSTUB_LeaveMutex();
|
||||
}
|
||||
if (p) return p + (w&(NSEEL_RAM_ITEMSPERBLOCK-1));
|
||||
}
|
||||
return &nseel_ramalloc_onfail;
|
||||
}
|
||||
|
||||
if (!nseel_gmembuf_default)
|
||||
{
|
||||
NSEEL_HOSTSTUB_EnterMutex();
|
||||
if (!nseel_gmembuf_default) nseel_gmembuf_default=(EEL_F*)calloc(sizeof(EEL_F),NSEEL_SHARED_GRAM_SIZE);
|
||||
NSEEL_HOSTSTUB_LeaveMutex();
|
||||
if (!nseel_gmembuf_default) return &nseel_ramalloc_onfail;
|
||||
}
|
||||
|
||||
return nseel_gmembuf_default+(((unsigned int)w)&((NSEEL_SHARED_GRAM_SIZE)-1));
|
||||
}
|
||||
|
||||
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAMAlloc(EEL_F **pblocks, unsigned int w)
|
||||
{
|
||||
// fprintf(stderr,"got request at %d, %d\n",w/NSEEL_RAM_ITEMSPERBLOCK, w&(NSEEL_RAM_ITEMSPERBLOCK-1));
|
||||
if (w < NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK)
|
||||
{
|
||||
unsigned int whichblock = w/NSEEL_RAM_ITEMSPERBLOCK;
|
||||
EEL_F *p=pblocks[whichblock];
|
||||
if (!p && whichblock < ((unsigned int *)pblocks)[-3]) // pblocks -1/-2 are closefact, -3 is maxblocks
|
||||
{
|
||||
NSEEL_HOSTSTUB_EnterMutex();
|
||||
|
||||
if (!(p=pblocks[whichblock]))
|
||||
{
|
||||
|
||||
const int msize=sizeof(EEL_F) * NSEEL_RAM_ITEMSPERBLOCK;
|
||||
if (!NSEEL_RAM_limitmem || NSEEL_RAM_memused+msize < NSEEL_RAM_limitmem)
|
||||
{
|
||||
p=pblocks[whichblock]=(EEL_F *)calloc(sizeof(EEL_F),NSEEL_RAM_ITEMSPERBLOCK);
|
||||
if (p) NSEEL_RAM_memused+=msize;
|
||||
}
|
||||
}
|
||||
NSEEL_HOSTSTUB_LeaveMutex();
|
||||
}
|
||||
if (p) return p + (w&(NSEEL_RAM_ITEMSPERBLOCK-1));
|
||||
}
|
||||
// fprintf(stderr,"ret 0\n");
|
||||
return &nseel_ramalloc_onfail;
|
||||
}
|
||||
|
||||
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAM_MemFree(void *blocks, EEL_F *which)
|
||||
{
|
||||
// blocks points to ram_state.blocks, so back it up past closefact and maxblocks to needfree
|
||||
int *flag = (int *)((char *)blocks - sizeof(double) - 2*sizeof(int));
|
||||
int d=(int)(*which);
|
||||
if (d < 0) d=0;
|
||||
if (d < flag[1]*NSEEL_RAM_ITEMSPERBLOCK) flag[0]=1+d;
|
||||
return which;
|
||||
}
|
||||
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAM_MemTop(void *blocks, EEL_F *which)
|
||||
{
|
||||
// blocks points to ram_state.blocks, so back it up past closefact to maxblocks
|
||||
const int *flag = (int *)((char *)blocks - sizeof(double) - sizeof(int));
|
||||
*which = flag[0]*NSEEL_RAM_ITEMSPERBLOCK;
|
||||
return which;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAM_MemCpy(EEL_F **blocks,EEL_F *dest, EEL_F *src, EEL_F *lenptr)
|
||||
{
|
||||
const int mem_size=NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK;
|
||||
int dest_offs = (int)(*dest + 0.0001);
|
||||
int src_offs = (int)(*src + 0.0001);
|
||||
int len = (int)(*lenptr + 0.0001);
|
||||
int want_mmove=0;
|
||||
|
||||
// trim to front
|
||||
if (src_offs<0)
|
||||
{
|
||||
len += src_offs;
|
||||
dest_offs -= src_offs;
|
||||
src_offs=0;
|
||||
}
|
||||
if (dest_offs<0)
|
||||
{
|
||||
len += dest_offs;
|
||||
src_offs -= dest_offs;
|
||||
dest_offs=0;
|
||||
}
|
||||
if (src_offs + len > mem_size) len = mem_size-src_offs;
|
||||
if (dest_offs + len > mem_size) len = mem_size-dest_offs;
|
||||
|
||||
if (src_offs == dest_offs || len < 1) return dest;
|
||||
|
||||
if (src_offs < dest_offs && src_offs+len > dest_offs)
|
||||
{
|
||||
// if src_offs < dest_offs and overlapping, must copy right to left
|
||||
if ((dest_offs - src_offs) < NSEEL_RAM_ITEMSPERBLOCK) want_mmove = 1;
|
||||
src_offs += len;
|
||||
dest_offs += len;
|
||||
while (len > 0)
|
||||
{
|
||||
const int maxdlen=((dest_offs-1)&(NSEEL_RAM_ITEMSPERBLOCK-1)) + 1;
|
||||
const int maxslen=((src_offs-1)&(NSEEL_RAM_ITEMSPERBLOCK-1)) + 1;
|
||||
int copy_len = len;
|
||||
EEL_F *srcptr,*destptr;
|
||||
|
||||
if (copy_len > maxdlen) copy_len=maxdlen;
|
||||
if (copy_len > maxslen) copy_len=maxslen;
|
||||
|
||||
srcptr = __NSEEL_RAMAlloc(blocks,src_offs - copy_len);
|
||||
destptr = __NSEEL_RAMAlloc(blocks,dest_offs - copy_len);
|
||||
if (srcptr==&nseel_ramalloc_onfail || destptr==&nseel_ramalloc_onfail) break;
|
||||
|
||||
if (want_mmove) memmove(destptr,srcptr,sizeof(EEL_F)*copy_len);
|
||||
else memcpy(destptr,srcptr,sizeof(EEL_F)*copy_len);
|
||||
src_offs-=copy_len;
|
||||
dest_offs-=copy_len;
|
||||
len-=copy_len;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
if (dest_offs < src_offs && dest_offs+len > src_offs)
|
||||
{
|
||||
// if dest_offs < src_offs and overlapping, and less than NSEEL_RAM_ITEMSPERBLOCK apart, use memmove()
|
||||
if ((src_offs-dest_offs) < NSEEL_RAM_ITEMSPERBLOCK) want_mmove = 1;
|
||||
}
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
const int maxdlen=NSEEL_RAM_ITEMSPERBLOCK - (dest_offs&(NSEEL_RAM_ITEMSPERBLOCK-1));
|
||||
const int maxslen=NSEEL_RAM_ITEMSPERBLOCK - (src_offs&(NSEEL_RAM_ITEMSPERBLOCK-1));
|
||||
int copy_len = len;
|
||||
EEL_F *srcptr,*destptr;
|
||||
|
||||
if (copy_len > maxdlen) copy_len=maxdlen;
|
||||
if (copy_len > maxslen) copy_len=maxslen;
|
||||
|
||||
srcptr = __NSEEL_RAMAlloc(blocks,src_offs);
|
||||
destptr = __NSEEL_RAMAlloc(blocks,dest_offs);
|
||||
if (srcptr==&nseel_ramalloc_onfail || destptr==&nseel_ramalloc_onfail) break;
|
||||
|
||||
if (want_mmove) memmove(destptr,srcptr,sizeof(EEL_F)*copy_len);
|
||||
else memcpy(destptr,srcptr,sizeof(EEL_F)*copy_len);
|
||||
src_offs+=copy_len;
|
||||
dest_offs+=copy_len;
|
||||
len-=copy_len;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
EEL_F * NSEEL_CGEN_CALL __NSEEL_RAM_MemSet(EEL_F **blocks,EEL_F *dest, EEL_F *v, EEL_F *lenptr)
|
||||
{
|
||||
int offs = (int)(*dest + 0.0001);
|
||||
int len = (int)(*lenptr + 0.0001);
|
||||
EEL_F t;
|
||||
if (offs<0)
|
||||
{
|
||||
len += offs;
|
||||
offs=0;
|
||||
}
|
||||
if (offs >= NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK) return dest;
|
||||
|
||||
if (offs+len > NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK) len = NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK - offs;
|
||||
|
||||
if (len < 1) return dest;
|
||||
|
||||
|
||||
t=*v; // set value
|
||||
|
||||
// int lastBlock=-1;
|
||||
while (len > 0)
|
||||
{
|
||||
int lcnt;
|
||||
EEL_F *ptr=__NSEEL_RAMAlloc(blocks,offs);
|
||||
if (ptr==&nseel_ramalloc_onfail) break;
|
||||
|
||||
lcnt=NSEEL_RAM_ITEMSPERBLOCK-(offs&(NSEEL_RAM_ITEMSPERBLOCK-1));
|
||||
if (lcnt > len) lcnt=len;
|
||||
|
||||
len -= lcnt;
|
||||
offs += lcnt;
|
||||
|
||||
while (lcnt--)
|
||||
{
|
||||
*ptr++=t;
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
static inline int __getset_values(EEL_F **blocks, int isset, int len, EEL_F **parms)
|
||||
{
|
||||
int offs, lout=0;
|
||||
unsigned int pageidx, sub_offs;
|
||||
if (--len < 1) return 0;
|
||||
offs = (int)(parms++[0][0] + 0.0001);
|
||||
|
||||
if (offs<=0)
|
||||
{
|
||||
len += offs;
|
||||
parms -= offs;
|
||||
offs=0;
|
||||
pageidx=sub_offs=0;
|
||||
if (len<1) return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sub_offs = ((unsigned int)offs) & (NSEEL_RAM_ITEMSPERBLOCK-1);
|
||||
pageidx = ((unsigned int)offs)>>NSEEL_RAM_ITEMSPERBLOCK_LOG2;
|
||||
if (pageidx>=NSEEL_RAM_BLOCKS) return 0;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int lcnt=NSEEL_RAM_ITEMSPERBLOCK-sub_offs;
|
||||
EEL_F *ptr=blocks[pageidx];
|
||||
if (!ptr)
|
||||
{
|
||||
ptr = __NSEEL_RAMAlloc(blocks,offs + lout);
|
||||
if (ptr==&nseel_ramalloc_onfail) return lout;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr += sub_offs;
|
||||
}
|
||||
|
||||
if (lcnt >= len)
|
||||
{
|
||||
// this page satisfies the request (normal behavior)
|
||||
lout += len;
|
||||
if (isset) while (len--) *ptr++=parms++[0][0];
|
||||
else while (len--) parms++[0][0] = *ptr++;
|
||||
return lout;
|
||||
}
|
||||
|
||||
// crossing a page boundary
|
||||
len -= lcnt;
|
||||
lout += lcnt;
|
||||
if (isset) while (lcnt--) *ptr++=parms++[0][0];
|
||||
else while (lcnt--) parms++[0][0] = *ptr++;
|
||||
|
||||
if (len <= 0 || ++pageidx >= NSEEL_RAM_BLOCKS) return lout;
|
||||
sub_offs=0;
|
||||
}
|
||||
}
|
||||
|
||||
EEL_F NSEEL_CGEN_CALL __NSEEL_RAM_Mem_SetValues(EEL_F **blocks, INT_PTR np, EEL_F **parms)
|
||||
{
|
||||
return __getset_values(blocks,1,(int)np,parms);
|
||||
}
|
||||
|
||||
EEL_F NSEEL_CGEN_CALL __NSEEL_RAM_Mem_GetValues(EEL_F **blocks, INT_PTR np, EEL_F **parms)
|
||||
{
|
||||
return __getset_values(blocks,0,(int)np,parms);
|
||||
}
|
||||
|
||||
void NSEEL_VM_SetGRAM(NSEEL_VMCTX ctx, void **gram)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
compileContext *c=(compileContext*)ctx;
|
||||
c->gram_blocks = gram;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NSEEL_VM_freeRAM(NSEEL_VMCTX ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
int x;
|
||||
compileContext *c=(compileContext*)ctx;
|
||||
EEL_F **blocks = c->ram_state.blocks;
|
||||
for (x = 0; x < NSEEL_RAM_BLOCKS; x ++)
|
||||
{
|
||||
if (blocks[x])
|
||||
{
|
||||
if (NSEEL_RAM_memused >= sizeof(EEL_F) * NSEEL_RAM_ITEMSPERBLOCK)
|
||||
NSEEL_RAM_memused -= sizeof(EEL_F) * NSEEL_RAM_ITEMSPERBLOCK;
|
||||
else NSEEL_RAM_memused_errors++;
|
||||
free(blocks[x]);
|
||||
blocks[x]=0;
|
||||
}
|
||||
}
|
||||
c->ram_state.needfree=0; // no need to free anymore
|
||||
}
|
||||
}
|
||||
|
||||
void NSEEL_VM_FreeGRAM(void **ufd)
|
||||
{
|
||||
if (ufd[0])
|
||||
{
|
||||
EEL_F **blocks = (EEL_F **)ufd[0];
|
||||
int x;
|
||||
for (x = 0; x < NSEEL_RAM_BLOCKS; x ++)
|
||||
{
|
||||
if (blocks[x])
|
||||
{
|
||||
if (NSEEL_RAM_memused >= sizeof(EEL_F) * NSEEL_RAM_ITEMSPERBLOCK)
|
||||
NSEEL_RAM_memused -= sizeof(EEL_F) * NSEEL_RAM_ITEMSPERBLOCK;
|
||||
else NSEEL_RAM_memused_errors++;
|
||||
}
|
||||
free(blocks[x]);
|
||||
blocks[x]=0;
|
||||
}
|
||||
free(blocks);
|
||||
ufd[0]=0;
|
||||
}
|
||||
}
|
||||
|
||||
EEL_F *NSEEL_VM_getramptr(NSEEL_VMCTX ctx, unsigned int offs, int *validCount)
|
||||
{
|
||||
EEL_F *d=__NSEEL_RAMAlloc(ctx ? ((compileContext*)ctx)->ram_state.blocks : 0,offs);
|
||||
if (!d || d == &nseel_ramalloc_onfail) return NULL;
|
||||
if (validCount) *validCount = NSEEL_RAM_ITEMSPERBLOCK - (offs%NSEEL_RAM_ITEMSPERBLOCK);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
EEL_F *NSEEL_VM_getramptr_noalloc(NSEEL_VMCTX ctx, unsigned int offs, int *validCount)
|
||||
{
|
||||
EEL_F *d;
|
||||
compileContext *cc = (compileContext *)ctx;
|
||||
|
||||
if (!cc ||
|
||||
offs >= NSEEL_RAM_ITEMSPERBLOCK*NSEEL_RAM_BLOCKS ||
|
||||
NULL == (d = cc->ram_state.blocks[offs/NSEEL_RAM_ITEMSPERBLOCK])
|
||||
)
|
||||
{
|
||||
if (validCount) *validCount = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offs %= NSEEL_RAM_ITEMSPERBLOCK;
|
||||
if (validCount) *validCount = NSEEL_RAM_ITEMSPERBLOCK - offs;
|
||||
return d + offs;
|
||||
}
|
40
Src/ns-eel2/nseel-yylex.c
Normal file
40
Src/ns-eel2/nseel-yylex.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Expression Evaluator Library (NS-EEL)
|
||||
Copyright (C) 2004-2013 Cockos Incorporated
|
||||
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 YYMALLOC malloc
|
||||
# define YYFREE free
|
||||
|
||||
int nseellex(void * yylval_param,void * yylloc_param ,void *yyscanner);
|
||||
void nseelerror(void *pos,compileContext *ctx, const char *str);
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "y.tab.c"
|
||||
|
316
Src/ns-eel2/wdlcstring.h
Normal file
316
Src/ns-eel2/wdlcstring.h
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
WDL - wdlcstring.h
|
||||
Copyright (C) 2005 and later, Cockos Incorporated
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
C string manipulation utilities -- [v]snprintf for Win32, also snprintf_append, lstrcatn, etc
|
||||
*/
|
||||
#ifndef _WDL_CSTRING_H_
|
||||
#define _WDL_CSTRING_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "wdltypes.h"
|
||||
|
||||
#ifdef _WDL_CSTRING_IMPL_ONLY_
|
||||
#ifdef _WDL_CSTRING_IF_ONLY_
|
||||
#undef _WDL_CSTRING_IF_ONLY_
|
||||
#endif
|
||||
#define _WDL_CSTRING_PREFIX
|
||||
#else
|
||||
#define _WDL_CSTRING_PREFIX static WDL_STATICFUNC_UNUSED
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
// provide snprintf()/vsnprintf() for win32 -- note that these have no way of knowing
|
||||
// what the amount written was, code should(must) be written to not depend on this.
|
||||
#ifdef snprintf
|
||||
#undef snprintf
|
||||
#endif
|
||||
#define snprintf WDL_snprintf
|
||||
|
||||
#ifdef vsnprintf
|
||||
#undef vsnprintf
|
||||
#endif
|
||||
#define vsnprintf WDL_vsnprintf
|
||||
|
||||
#endif // win32 snprintf/vsnprintf
|
||||
|
||||
// use wdlcstring.h's lstrcpyn_safe rather than the real lstrcpyn.
|
||||
#ifdef _WIN32
|
||||
#ifdef lstrcpyn
|
||||
#undef lstrcpyn
|
||||
#endif
|
||||
#define lstrcpyn lstrcpyn_safe
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WDL_CSTRING_IF_ONLY_
|
||||
|
||||
void lstrcpyn_safe(char *o, const char *in, INT_PTR count);
|
||||
void lstrcatn(char *o, const char *in, INT_PTR count);
|
||||
void WDL_VARARG_WARN(printf,3,4) snprintf_append(char *o, INT_PTR count, const char *format, ...);
|
||||
void vsnprintf_append(char *o, INT_PTR count, const char *format, va_list va);
|
||||
|
||||
const char *WDL_get_filepart(const char *str); // returns whole string if no dir chars
|
||||
const char *WDL_get_fileext(const char *str); // returns ".ext" or end of string "" if no extension
|
||||
char *WDL_remove_fileext(char *str); // returns pointer to "ext" if ".ext" was removed (zero-d dot), or NULL
|
||||
char WDL_remove_filepart(char *str); // returns dir character that was zeroed, or 0 if new string is empty
|
||||
int WDL_remove_trailing_dirchars(char *str); // returns trailing dirchar count removed, will not convert "/" into ""
|
||||
size_t WDL_remove_trailing_crlf(char *str); // returns new length
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
void WDL_vsnprintf(char *o, size_t count, const char *format, va_list args);
|
||||
void WDL_VARARG_WARN(printf,3,4) WDL_snprintf(char *o, size_t count, const char *format, ...);
|
||||
#endif
|
||||
|
||||
int WDL_strcmp_logical(const char *s1, const char *s2, int case_sensitive);
|
||||
#else
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
|
||||
_WDL_CSTRING_PREFIX void WDL_vsnprintf(char *o, size_t count, const char *format, va_list args)
|
||||
{
|
||||
if (count>0)
|
||||
{
|
||||
int rv;
|
||||
o[0]=0;
|
||||
rv=_vsnprintf(o,count,format,args); // returns -1 if over, and does not null terminate, ugh
|
||||
if (rv < 0 || rv>=(int)count-1) o[count-1]=0;
|
||||
}
|
||||
}
|
||||
_WDL_CSTRING_PREFIX void WDL_VARARG_WARN(printf,3,4) WDL_snprintf(char *o, size_t count, const char *format, ...)
|
||||
{
|
||||
if (count>0)
|
||||
{
|
||||
int rv;
|
||||
va_list va;
|
||||
va_start(va,format);
|
||||
o[0]=0;
|
||||
rv=_vsnprintf(o,count,format,va); // returns -1 if over, and does not null terminate, ugh
|
||||
va_end(va);
|
||||
|
||||
if (rv < 0 || rv>=(int)count-1) o[count-1]=0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_WDL_CSTRING_PREFIX void lstrcpyn_safe(char *o, const char *in, INT_PTR count)
|
||||
{
|
||||
if (count>0)
|
||||
{
|
||||
while (--count>0 && *in) *o++ = *in++;
|
||||
*o=0;
|
||||
}
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX void lstrcatn(char *o, const char *in, INT_PTR count)
|
||||
{
|
||||
if (count>0)
|
||||
{
|
||||
while (*o) { if (--count < 1) return; o++; }
|
||||
while (--count>0 && *in) *o++ = *in++;
|
||||
*o=0;
|
||||
}
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX const char *WDL_get_filepart(const char *str) // returns whole string if no dir chars
|
||||
{
|
||||
const char *p = str;
|
||||
while (*p) p++;
|
||||
while (p >= str && !WDL_IS_DIRCHAR(*p)) --p;
|
||||
return p + 1;
|
||||
}
|
||||
_WDL_CSTRING_PREFIX const char *WDL_get_fileext(const char *str) // returns ".ext" or end of string "" if no extension
|
||||
{
|
||||
const char *p=str, *ep;
|
||||
while (*p) p++;
|
||||
ep = p;
|
||||
while (p >= str && !WDL_IS_DIRCHAR(*p))
|
||||
{
|
||||
if (*p == '.') return p;
|
||||
--p;
|
||||
}
|
||||
return ep;
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX char *WDL_remove_fileext(char *str) // returns pointer to "ext" if ".ext" was removed (zero-d dot), or NULL
|
||||
{
|
||||
char *p=str;
|
||||
while (*p) p++;
|
||||
while (p >= str && !WDL_IS_DIRCHAR(*p))
|
||||
{
|
||||
if (*p == '.')
|
||||
{
|
||||
*p = 0;
|
||||
return p+1;
|
||||
}
|
||||
--p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX char WDL_remove_filepart(char *str) // returns dir character that was zeroed, or 0 if new string is empty
|
||||
{
|
||||
char *p=str;
|
||||
while (*p) p++;
|
||||
while (p >= str)
|
||||
{
|
||||
char c = *p;
|
||||
if (WDL_IS_DIRCHAR(c))
|
||||
{
|
||||
*p = 0;
|
||||
return c;
|
||||
}
|
||||
--p;
|
||||
}
|
||||
str[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX int WDL_remove_trailing_dirchars(char *str) // returns trailing dirchar count removed
|
||||
{
|
||||
int cnt = 0;
|
||||
char *p=str;
|
||||
while (*p) p++;
|
||||
while (p > str+1 && WDL_IS_DIRCHAR(p[-1]))
|
||||
{
|
||||
cnt++;
|
||||
p--;
|
||||
}
|
||||
*p = 0;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX size_t WDL_remove_trailing_crlf(char *str) // returns new length
|
||||
{
|
||||
char *p=str;
|
||||
while (*p) p++;
|
||||
while (p > str && (p[-1] == '\r' || p[-1] == '\n')) p--;
|
||||
*p = 0;
|
||||
return p-str;
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX void WDL_VARARG_WARN(printf,3,4) snprintf_append(char *o, INT_PTR count, const char *format, ...)
|
||||
{
|
||||
if (count>0)
|
||||
{
|
||||
va_list va;
|
||||
while (*o) { if (--count < 1) return; o++; }
|
||||
va_start(va,format);
|
||||
vsnprintf(o,count,format,va);
|
||||
va_end(va);
|
||||
}
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX void vsnprintf_append(char *o, INT_PTR count, const char *format, va_list va)
|
||||
{
|
||||
if (count>0)
|
||||
{
|
||||
while (*o) { if (--count < 1) return; o++; }
|
||||
vsnprintf(o,count,format,va);
|
||||
}
|
||||
}
|
||||
|
||||
_WDL_CSTRING_PREFIX int WDL_strcmp_logical(const char *s1, const char *s2, int case_sensitive)
|
||||
{
|
||||
// also exists as WDL_LogicalSortStringKeyedArray::_cmpstr()
|
||||
|
||||
char lastNonZeroChar=0;
|
||||
// last matching character, updated if not 0. this allows us to track whether
|
||||
// we are inside of a number with the same leading digits
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char c1=*s1++, c2=*s2++;
|
||||
if (!c1) return c1-c2;
|
||||
|
||||
if (c1!=c2)
|
||||
{
|
||||
if (c1 >= '0' && c1 <= '9' && c2 >= '0' && c2 <= '9')
|
||||
{
|
||||
int lzdiff=0, cnt=0;
|
||||
if (lastNonZeroChar < '1' || lastNonZeroChar > '9')
|
||||
{
|
||||
while (c1 == '0') { c1=*s1++; lzdiff--; }
|
||||
while (c2 == '0') { c2=*s2++; lzdiff++; } // lzdiff = lz2-lz1, more leading 0s = earlier in list
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (c1 >= '0' && c1 <= '9')
|
||||
{
|
||||
if (c2 < '0' || c2 > '9') return 1;
|
||||
|
||||
c1=s1[cnt];
|
||||
c2=s2[cnt++];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c2 >= '0' && c2 <= '9') return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s1--;
|
||||
s2--;
|
||||
|
||||
while (cnt--)
|
||||
{
|
||||
const int d = *s1++ - *s2++;
|
||||
if (d) return d;
|
||||
}
|
||||
|
||||
if (lzdiff) return lzdiff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!case_sensitive)
|
||||
{
|
||||
if (c1>='a' && c1<='z') c1+='A'-'a';
|
||||
if (c2>='a' && c2<='z') c2+='A'-'a';
|
||||
}
|
||||
if (c1 != c2) return c1-c2;
|
||||
}
|
||||
}
|
||||
else if (c1 != '0') lastNonZeroChar=c1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#undef _WDL_CSTRING_PREFIX
|
||||
|
||||
#endif
|
160
Src/ns-eel2/wdltypes.h
Normal file
160
Src/ns-eel2/wdltypes.h
Normal file
@ -0,0 +1,160 @@
|
||||
#ifndef _WDLTYPES_
|
||||
#define _WDLTYPES_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
typedef __int64 WDL_INT64;
|
||||
typedef unsigned __int64 WDL_UINT64;
|
||||
|
||||
#else
|
||||
|
||||
typedef long long WDL_INT64;
|
||||
typedef unsigned long long WDL_UINT64;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define WDL_UINT64_CONST(x) (x##ui64)
|
||||
#define WDL_INT64_CONST(x) (x##i64)
|
||||
#else
|
||||
#define WDL_UINT64_CONST(x) (x##ULL)
|
||||
#define WDL_INT64_CONST(x) (x##LL)
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(_MSC_VER) || _MSC_VER > 1200
|
||||
#define WDL_DLGRET INT_PTR CALLBACK
|
||||
#else
|
||||
#define WDL_DLGRET BOOL CALLBACK
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
typedef intptr_t INT_PTR;
|
||||
typedef uintptr_t UINT_PTR;
|
||||
#endif
|
||||
|
||||
#if defined(__ppc__) || !defined(__cplusplus)
|
||||
typedef char WDL_bool;
|
||||
#else
|
||||
typedef bool WDL_bool;
|
||||
#endif
|
||||
|
||||
#ifndef GWLP_USERDATA
|
||||
#define GWLP_USERDATA GWL_USERDATA
|
||||
#define GWLP_WNDPROC GWL_WNDPROC
|
||||
#define GWLP_HINSTANCE GWL_HINSTANCE
|
||||
#define GWLP_HWNDPARENT GWL_HWNDPARENT
|
||||
#define DWLP_USER DWL_USER
|
||||
#define DWLP_DLGPROC DWL_DLGPROC
|
||||
#define DWLP_MSGRESULT DWL_MSGRESULT
|
||||
#define SetWindowLongPtr(a,b,c) SetWindowLong(a,b,c)
|
||||
#define GetWindowLongPtr(a,b) GetWindowLong(a,b)
|
||||
#define SetWindowLongPtrW(a,b,c) SetWindowLongW(a,b,c)
|
||||
#define GetWindowLongPtrW(a,b) GetWindowLongW(a,b)
|
||||
#define SetWindowLongPtrA(a,b,c) SetWindowLongA(a,b,c)
|
||||
#define GetWindowLongPtrA(a,b) GetWindowLongA(a,b)
|
||||
|
||||
#define GCLP_WNDPROC GCL_WNDPROC
|
||||
#define GCLP_HICON GCL_HICON
|
||||
#define GCLP_HICONSM GCL_HICONSM
|
||||
#define SetClassLongPtr(a,b,c) SetClassLong(a,b,c)
|
||||
#define GetClassLongPtr(a,b) GetClassLong(a,b)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
// for structures that contain doubles, or doubles in structures that are after stuff of questionable alignment (for OSX/linux)
|
||||
#define WDL_FIXALIGN __attribute__ ((aligned (8)))
|
||||
// usage: void func(int a, const char *fmt, ...) WDL_VARARG_WARN(printf,2,3); // note: if member function, this pointer is counted as well, so as member function that would be 3,4
|
||||
#define WDL_VARARG_WARN(x,n,s) __attribute__ ((format (x,n,s)))
|
||||
#define WDL_STATICFUNC_UNUSED __attribute__((unused))
|
||||
|
||||
#else
|
||||
#define WDL_FIXALIGN
|
||||
#define WDL_VARARG_WARN(x,n,s)
|
||||
#define WDL_STATICFUNC_UNUSED
|
||||
#endif
|
||||
|
||||
#ifndef WDL_WANT_NEW_EXCEPTIONS
|
||||
#if defined(__cplusplus)
|
||||
#include <new>
|
||||
#define WDL_NEW (std::nothrow)
|
||||
#endif
|
||||
#else
|
||||
#define WDL_NEW
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(max) && defined(WDL_DEFINE_MINMAX)
|
||||
#define max(x,y) ((x)<(y)?(y):(x))
|
||||
#define min(x,y) ((x)<(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
#ifndef wdl_max
|
||||
#define wdl_max(x,y) ((x)<(y)?(y):(x))
|
||||
#define wdl_min(x,y) ((x)<(y)?(x):(y))
|
||||
#define wdl_abs(x) ((x)<0 ? -(x) : (x))
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef strnicmp
|
||||
#define strnicmp(x,y,z) strncasecmp(x,y,z)
|
||||
#endif
|
||||
#ifndef stricmp
|
||||
#define stricmp(x,y) strcasecmp(x,y)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WDL_BACKSLASHES_ARE_ORDINARY
|
||||
#define WDL_IS_DIRCHAR(x) ((x) == '/')
|
||||
#else
|
||||
// for multi-platform applications it seems better to treat backslashes as directory separators even if it
|
||||
// isn't supported by the underying system (for resolving filenames, etc)
|
||||
#ifdef _WIN32
|
||||
#define WDL_IS_DIRCHAR(x) ((x) == '\\' || (x) == '/')
|
||||
#else
|
||||
#define WDL_IS_DIRCHAR(x) ((x) == '/' || (x) == '\\')
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(WDL_BACKSLASHES_ARE_ORDINARY)
|
||||
#define WDL_DIRCHAR '\\'
|
||||
#define WDL_DIRCHAR_STR "\\"
|
||||
#else
|
||||
#define WDL_DIRCHAR '/'
|
||||
#define WDL_DIRCHAR_STR "/"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
// on __APPLE__ we should ideally check the filesystem for case-sensitivity, assuming a case-insensitive-only match
|
||||
#define wdl_filename_cmp(x,y) stricmp(x,y)
|
||||
#define wdl_filename_cmpn(x,y,n) strnicmp(x,y,n)
|
||||
#else
|
||||
#define wdl_filename_cmp(x,y) strcmp(x,y)
|
||||
#define wdl_filename_cmpn(x,y,n) strncmp(x,y,n)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
#define WDL_likely(x) (__builtin_expect(!!(x),1))
|
||||
#define WDL_unlikely(x) (__builtin_expect(!!(x),0))
|
||||
#else
|
||||
#define WDL_likely(x) (!!(x))
|
||||
#define WDL_unlikely(x) (!!(x))
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
#include <assert.h>
|
||||
#define WDL_ASSERT(x) assert(x)
|
||||
#define WDL_NORMALLY(x) (assert(x),1)
|
||||
#define WDL_NOT_NORMALLY(x) (assert(!(x)),0)
|
||||
#else
|
||||
#define WDL_ASSERT(x)
|
||||
#define WDL_NORMALLY(x) WDL_likely(x)
|
||||
#define WDL_NOT_NORMALLY(x) WDL_unlikely(x)
|
||||
#endif
|
||||
|
||||
#endif
|
2191
Src/ns-eel2/y.tab.c
Normal file
2191
Src/ns-eel2/y.tab.c
Normal file
File diff suppressed because it is too large
Load Diff
117
Src/ns-eel2/y.tab.h
Normal file
117
Src/ns-eel2/y.tab.h
Normal file
@ -0,0 +1,117 @@
|
||||
/* A Bison parser, made by GNU Bison 2.3. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
VALUE = 258,
|
||||
IDENTIFIER = 259,
|
||||
TOKEN_SHL = 260,
|
||||
TOKEN_SHR = 261,
|
||||
TOKEN_LTE = 262,
|
||||
TOKEN_GTE = 263,
|
||||
TOKEN_EQ = 264,
|
||||
TOKEN_EQ_EXACT = 265,
|
||||
TOKEN_NE = 266,
|
||||
TOKEN_NE_EXACT = 267,
|
||||
TOKEN_LOGICAL_AND = 268,
|
||||
TOKEN_LOGICAL_OR = 269,
|
||||
TOKEN_ADD_OP = 270,
|
||||
TOKEN_SUB_OP = 271,
|
||||
TOKEN_MOD_OP = 272,
|
||||
TOKEN_OR_OP = 273,
|
||||
TOKEN_AND_OP = 274,
|
||||
TOKEN_XOR_OP = 275,
|
||||
TOKEN_DIV_OP = 276,
|
||||
TOKEN_MUL_OP = 277,
|
||||
TOKEN_POW_OP = 278,
|
||||
STRING_LITERAL = 279,
|
||||
STRING_IDENTIFIER = 280
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define VALUE 258
|
||||
#define IDENTIFIER 259
|
||||
#define TOKEN_SHL 260
|
||||
#define TOKEN_SHR 261
|
||||
#define TOKEN_LTE 262
|
||||
#define TOKEN_GTE 263
|
||||
#define TOKEN_EQ 264
|
||||
#define TOKEN_EQ_EXACT 265
|
||||
#define TOKEN_NE 266
|
||||
#define TOKEN_NE_EXACT 267
|
||||
#define TOKEN_LOGICAL_AND 268
|
||||
#define TOKEN_LOGICAL_OR 269
|
||||
#define TOKEN_ADD_OP 270
|
||||
#define TOKEN_SUB_OP 271
|
||||
#define TOKEN_MOD_OP 272
|
||||
#define TOKEN_OR_OP 273
|
||||
#define TOKEN_AND_OP 274
|
||||
#define TOKEN_XOR_OP 275
|
||||
#define TOKEN_DIV_OP 276
|
||||
#define TOKEN_MUL_OP 277
|
||||
#define TOKEN_POW_OP 278
|
||||
#define STRING_LITERAL 279
|
||||
#define STRING_IDENTIFIER 280
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef int YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
|
||||
typedef struct YYLTYPE
|
||||
{
|
||||
int first_line;
|
||||
int first_column;
|
||||
int last_line;
|
||||
int last_column;
|
||||
} YYLTYPE;
|
||||
# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYLTYPE_IS_DECLARED 1
|
||||
# define YYLTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user