123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791 |
- /*
- Expression Evaluator Library (NS-EEL) v2
- Copyright (C) 2004-2008 Cockos Incorporated
- Copyright (C) 1999-2003 Nullsoft, Inc.
-
- nseel-compiler.c
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- // for VirtualProtect
- #include "ns-eel-int.h"
- #include <string.h>
- #include <math.h>
- #include <stdio.h>
- #include <ctype.h>
- #ifndef _WIN64
- #ifndef __ppc__
- #include <float.h>
- #endif
- #endif
- #ifdef __APPLE__
- #ifdef __LP64__
- #define EEL_USE_MPROTECT
- #endif
- #endif
- #ifdef EEL_USE_MPROTECT
- #include <sys/mman.h>
- #include <stdint.h>
- #include <unistd.h>
- #endif
- #ifdef NSEEL_EEL1_COMPAT_MODE
- #ifndef EEL_NO_CHANGE_FPFLAGS
- #define EEL_NO_CHANGE_FPFLAGS
- #endif
- #endif
- #ifndef _WIN64
- #if !defined(_RC_CHOP) && !defined(EEL_NO_CHANGE_FPFLAGS)
- #include <fpu_control.h>
- #define _RC_CHOP _FPU_RC_ZERO
- #define _MCW_RC _FPU_RC_ZERO
- static unsigned int _controlfp(unsigned int val, unsigned int mask)
- {
- unsigned int ret;
- _FPU_GETCW(ret);
- if (mask)
- {
- ret&=~mask;
- ret|=val;
- _FPU_SETCW(ret);
- }
- return ret;
- }
- #endif
- #endif
- #ifdef __ppc__
- #define GLUE_MOV_EAX_DIRECTVALUE_SIZE 8
- static void GLUE_MOV_EAX_DIRECTVALUE_GEN(void *b, INT_PTR v)
- {
- unsigned int uv=(unsigned int)v;
- unsigned short *p=(unsigned short *)b;
- *p++ = 0x3C60; // addis r3, r0, hw
- *p++ = (uv>>16)&0xffff;
- *p++ = 0x6063; // ori r3, r3, lw
- *p++ = uv&0xffff;
- }
- // mflr r5
- // stwu r5, -4(r1)
- const static unsigned int GLUE_FUNC_ENTER[2] = { 0x7CA802A6, 0x94A1FFFC };
- // lwz r5, 0(r1)
- // addi r1, r1, 4
- // mtlr r5
- const static unsigned int GLUE_FUNC_LEAVE[3] = { 0x80A10000, 0x38210004, 0x7CA803A6 };
- #define GLUE_FUNC_ENTER_SIZE sizeof(GLUE_FUNC_ENTER)
- #define GLUE_FUNC_LEAVE_SIZE sizeof(GLUE_FUNC_LEAVE)
- const static unsigned int GLUE_RET[]={0x4E800020}; // blr
- const static unsigned int GLUE_MOV_ESI_EDI=0x7E308B78; // mr r16, r17
- static int GLUE_RESET_ESI(char *out, void *ptr)
- {
- if (out) memcpy(out,&GLUE_MOV_ESI_EDI,sizeof(GLUE_MOV_ESI_EDI));
- return sizeof(GLUE_MOV_ESI_EDI);
- }
- // stwu r3, -4(r1)
- const static unsigned int GLUE_PUSH_EAX[1]={ 0x9461FFFC};
- // lwz r14, 0(r1)
- // addi r1, r1, 4
- const static unsigned int GLUE_POP_EBX[2]={ 0x81C10000, 0x38210004, };
- // lwz r15, 0(r1)
- // addi r1, r1, 4
- const static unsigned int GLUE_POP_ECX[2]={ 0x81E10000, 0x38210004 };
- static void GLUE_CALL_CODE(INT_PTR bp, INT_PTR cp)
- {
- __asm__(
- "stmw r14, -80(r1)\n"
- "mtctr %0\n"
- "mr r17, %1\n"
- "subi r17, r17, 8\n"
- "mflr r5\n"
- "stw r5, -84(r1)\n"
- "subi r1, r1, 88\n"
- "bctrl\n"
- "addi r1, r1, 88\n"
- "lwz r5, -84(r1)\n"
- "lmw r14, -80(r1)\n"
- "mtlr r5\n"
- ::"r" (cp), "r" (bp));
- };
- INT_PTR *EEL_GLUE_set_immediate(void *_p, void *newv)
- {
- // todo 64 bit ppc will take some work
- unsigned int *p=(unsigned int *)_p;
- while ((p[0]&0x0000FFFF) != 0x0000dead &&
- (p[1]&0x0000FFFF) != 0x0000beef) p++;
- p[0] = (p[0]&0xFFFF0000) | (((unsigned int)newv)>>16);
- p[1] = (p[1]&0xFFFF0000) | (((unsigned int)newv)&0xFFFF);
- return (INT_PTR*)++p;
- }
- #else
- //x86 specific code
- #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];
- #if defined(_WIN64) || defined(__LP64__)
- #define GLUE_MOV_EAX_DIRECTVALUE_SIZE 10
- static void GLUE_MOV_EAX_DIRECTVALUE_GEN(void *b, INT_PTR v) {
- unsigned short *bb = (unsigned short *)b;
- *bb++ =0xB848;
- *(INT_PTR *)bb = v;
- }
- const static unsigned char GLUE_PUSH_EAX[2]={ 0x50,0x50}; // push rax ; push rax (push twice to preserve alignment)
- const static unsigned char GLUE_POP_EBX[2]={0x5F, 0x5f}; //pop rdi ; twice
- const static unsigned char GLUE_POP_ECX[2]={0x59, 0x59 }; // pop rcx ; twice
- #else
- #define GLUE_MOV_EAX_DIRECTVALUE_SIZE 5
- static void GLUE_MOV_EAX_DIRECTVALUE_GEN(void *b, int v)
- {
- *((unsigned char *)b) =0xB8;
- b= ((unsigned char *)b)+1;
- *(int *)b = v;
- }
- const static unsigned char GLUE_PUSH_EAX[4]={0x83, 0xEC, 12, 0x50}; // sub esp, 12, push eax
- const static unsigned char GLUE_POP_EBX[4]={0x5F, 0x83, 0xC4, 12}; //pop ebx, add esp, 12 // DI=5F, BX=0x5B;
- const static unsigned char GLUE_POP_ECX[4]={0x59, 0x83, 0xC4, 12}; // pop ecx, add esp, 12
- #endif
- //const static unsigned short GLUE_MOV_ESI_EDI=0xF78B;
- const static unsigned char GLUE_RET=0xC3;
- static int GLUE_RESET_ESI(unsigned char *out, void *ptr)
- {
- #if defined(_WIN64) || defined(__LP64__)
- if (out)
- {
- *out++ = 0x48;
- *out++ = 0xBE; // mov rsi, constant64
- *(void **)out = ptr;
- out+=sizeof(void *);
- }
- return 2+sizeof(void *);
- #else
- if (out)
- {
- *out++ = 0xBE; // mov esi, constant
- memcpy(out,&ptr,sizeof(void *));
- out+=sizeof(void *);
- }
- return 1+sizeof(void *);
- #endif
- }
- static void GLUE_CALL_CODE(INT_PTR bp, INT_PTR cp)
- {
- #if defined(_WIN64) || defined(__LP64__)
- extern void win64_callcode(INT_PTR code);
- win64_callcode(cp);
- #else // non-64 bit
- #ifdef _MSC_VER
- #ifndef EEL_NO_CHANGE_FPFLAGS
- unsigned int old_v=_controlfp(0,0);
- _controlfp(_RC_CHOP,_MCW_RC);
- #endif
- __asm
- {
- mov eax, cp
- pushad
- call eax
- popad
- };
- #ifndef EEL_NO_CHANGE_FPFLAGS
- _controlfp(old_v,_MCW_RC);
- #endif
- #else // gcc x86
- #ifndef EEL_NO_CHANGE_FPFLAGS
- unsigned int old_v=_controlfp(0,0);
- _controlfp(_RC_CHOP,_MCW_RC);
- #endif
- __asm__("call *%%eax"::"a" (cp): "%ecx","%edx","%esi","%edi");
- #ifndef EEL_NO_CHANGE_FPFLAGS
- _controlfp(old_v,_MCW_RC);
- #endif
- #endif //gcc x86
- #endif // 32bit
- }
- INT_PTR *EEL_GLUE_set_immediate(void *_p, void *newv)
- {
- char *p=(char*)_p;
- while (*(INT_PTR *)p != ~(INT_PTR)0) p++;
- *(INT_PTR *)p = (INT_PTR)newv;
- return ((INT_PTR*)p)+1;
- }
- #endif
- static void *GLUE_realAddress(void *fn, void *fn_e, int *size)
- {
- #if defined(_MSC_VER) || defined(__LP64__)
- unsigned char *p;
- #if defined(_DEBUG) && !defined(__LP64__)
- if (*(unsigned char *)fn == 0xE9) // this means jump to the following address
- {
- fn = ((unsigned char *)fn) + *(int *)((char *)fn+1) + 5;
- }
- #endif
- // this may not work in debug mode
- p=(unsigned char *)fn;
- for (;;)
- {
- int a;
- for (a=0;a<12;a++)
- {
- if (p[a] != (a?0x90:0x89)) break;
- }
- if (a>=12)
- {
- *size = (char *)p - (char *)fn;
- // if (*size<0) MessageBox(NULL,"expect poof","a",0);
- return fn;
- }
- p++;
- }
- #else
- char *p=(char *)fn_e - sizeof(GLUE_RET);
- if (p <= (char *)fn) *size=0;
- else
- {
- while (p > (char *)fn && memcmp(p,&GLUE_RET,sizeof(GLUE_RET))) p-=sizeof(GLUE_RET);
- *size = p - (char *)fn;
- }
- return fn;
- #endif
- }
- static int nseel_evallib_stats[5]; // source bytes, static code bytes, call code bytes, data bytes, segments
- int *NSEEL_getstats()
- {
- return nseel_evallib_stats;
- }
- EEL_F *NSEEL_getglobalregs()
- {
- return nseel_globalregs;
- }
- // this stuff almost works
- static int findByteOffsetInSource(compileContext *ctx, int byteoffs,int *destoffs)
- {
- int x;
- if (!ctx->compileLineRecs || !ctx->compileLineRecs_size) return *destoffs=0;
- if (byteoffs < ctx->compileLineRecs[0].destByteCount)
- {
- *destoffs=0;
- return 1;
- }
- for (x = 0; x < ctx->compileLineRecs_size-1; x ++)
- {
- if (byteoffs >= ctx->compileLineRecs[x].destByteCount &&
- byteoffs < ctx->compileLineRecs[x+1].destByteCount) break;
- }
- *destoffs=ctx->compileLineRecs[(x&&x==ctx->compileLineRecs_size-1)?x-1:x].srcByteCount;
- return x+2;
- }
- static void onCompileNewLine(compileContext *ctx, int srcBytes, int destBytes)
- {
- if (!ctx->compileLineRecs || ctx->compileLineRecs_size >= ctx->compileLineRecs_alloc)
- {
- ctx->compileLineRecs_alloc = ctx->compileLineRecs_size+1024;
- ctx->compileLineRecs = (lineRecItem *)realloc(ctx->compileLineRecs,sizeof(lineRecItem)*ctx->compileLineRecs_alloc);
- }
- if (ctx->compileLineRecs)
- {
- ctx->compileLineRecs[ctx->compileLineRecs_size].srcByteCount=srcBytes;
- ctx->compileLineRecs[ctx->compileLineRecs_size++].destByteCount=destBytes;
- }
- }
- #define LLB_DSIZE (65536-64)
- typedef struct _llBlock {
- struct _llBlock *next;
- int sizeused;
- char block[LLB_DSIZE];
- } llBlock;
- typedef struct _startPtr {
- struct _startPtr *next;
- void *startptr;
- } startPtr;
- typedef struct {
- void *workTable;
- llBlock *blocks;
- void *code;
- int code_stats[4];
- } codeHandleType;
- #ifndef NSEEL_MAX_TEMPSPACE_ENTRIES
- #define NSEEL_MAX_TEMPSPACE_ENTRIES 2048
- #endif
- static void *__newBlock(llBlock **start,int size);
- #define newTmpBlock(x) __newTmpBlock((llBlock **)&ctx->tmpblocks_head,x)
- #define newBlock(x,a) __newBlock_align(ctx,x,a)
- static void *__newTmpBlock(llBlock **start, int size)
- {
- void *p=__newBlock(start,size+4);
- if (p && size>=0) *((int *)p) = size;
- return p;
- }
- static void *__newBlock_align(compileContext *ctx, int size, int align) // makes sure block is aligned to 32 byte boundary, for code
- {
- int a1=align-1;
- char *p=(char*)__newBlock((llBlock **)&ctx->blocks_head,size+a1);
- return p+((align-(((INT_PTR)p)&a1))&a1);
- }
- static void freeBlocks(llBlock **start);
- #define DECL_ASMFUNC(x) \
- void nseel_asm_##x(void); \
- void nseel_asm_##x##_end(void); \
- DECL_ASMFUNC(sin)
- DECL_ASMFUNC(cos)
- DECL_ASMFUNC(tan)
- DECL_ASMFUNC(1pdd)
- DECL_ASMFUNC(2pdd)
- DECL_ASMFUNC(2pdds)
- DECL_ASMFUNC(1pp)
- DECL_ASMFUNC(2pp)
- DECL_ASMFUNC(sqr)
- DECL_ASMFUNC(sqrt)
- DECL_ASMFUNC(log)
- DECL_ASMFUNC(log10)
- DECL_ASMFUNC(abs)
- DECL_ASMFUNC(min)
- DECL_ASMFUNC(max)
- DECL_ASMFUNC(sig)
- DECL_ASMFUNC(sign)
- DECL_ASMFUNC(band)
- DECL_ASMFUNC(bor)
- DECL_ASMFUNC(bnot)
- DECL_ASMFUNC(if)
- DECL_ASMFUNC(repeat)
- DECL_ASMFUNC(repeatwhile)
- DECL_ASMFUNC(equal)
- DECL_ASMFUNC(notequal)
- DECL_ASMFUNC(below)
- DECL_ASMFUNC(above)
- DECL_ASMFUNC(beloweq)
- DECL_ASMFUNC(aboveeq)
- DECL_ASMFUNC(assign)
- DECL_ASMFUNC(add)
- DECL_ASMFUNC(sub)
- DECL_ASMFUNC(add_op)
- DECL_ASMFUNC(sub_op)
- DECL_ASMFUNC(mul)
- DECL_ASMFUNC(div)
- DECL_ASMFUNC(mul_op)
- DECL_ASMFUNC(div_op)
- DECL_ASMFUNC(mod)
- DECL_ASMFUNC(mod_op)
- DECL_ASMFUNC(or)
- DECL_ASMFUNC(and)
- DECL_ASMFUNC(or_op)
- DECL_ASMFUNC(and_op)
- DECL_ASMFUNC(uplus)
- DECL_ASMFUNC(uminus)
- DECL_ASMFUNC(invsqrt)
- DECL_ASMFUNC(exec2)
- static void NSEEL_PProc_GRAM(void *data, int data_size, compileContext *ctx)
- {
- if (data_size>0) EEL_GLUE_set_immediate(data, ctx->gram_blocks);
- }
- static EEL_F g_signs[2]={1.0,-1.0};
- static EEL_F negativezeropointfive=-0.5f;
- static EEL_F onepointfive=1.5f;
- static EEL_F g_closefact = NSEEL_CLOSEFACTOR;
- static const EEL_F eel_zero=0.0, eel_one=1.0;
- //#if defined(_MSC_VER) && _MSC_VER >= 1400
- //static double __floor(double a) { return floor(a); }
- //#endif
- static double eel1band(double a, double b)
- {
- return (fabs(a)>g_closefact && fabs(b) > g_closefact) ? 1.0 : 0.0;
- }
- static double eel1bor(double a, double b)
- {
- return (fabs(a)>g_closefact || fabs(b) > g_closefact) ? 1.0 : 0.0;
- }
- static double eel1sigmoid(double x, double constraint)
- {
- double t = (1+exp(-x * (constraint)));
- return fabs(t)>g_closefact ? 1.0/t : 0;
- }
- EEL_F NSEEL_CGEN_CALL nseel_int_rand(EEL_F *f);
- static functionType fnTable1[] = {
- { "_if", nseel_asm_if,nseel_asm_if_end, 3, {&g_closefact} },
- { "_and", nseel_asm_band,nseel_asm_band_end, 2 } ,
- { "_or", nseel_asm_bor,nseel_asm_bor_end, 2 } ,
- { "loop", nseel_asm_repeat,nseel_asm_repeat_end, 2 },
- { "while", nseel_asm_repeatwhile,nseel_asm_repeatwhile_end, 1 },
- #ifdef __ppc__
- { "_not", nseel_asm_bnot,nseel_asm_bnot_end, 1, {&g_closefact,&eel_zero,&eel_one} } ,
- { "_equal", nseel_asm_equal,nseel_asm_equal_end, 2, {&g_closefact,&eel_zero, &eel_one} },
- { "_noteq", nseel_asm_notequal,nseel_asm_notequal_end, 2, {&g_closefact,&eel_one,&eel_zero} },
- { "_below", nseel_asm_below,nseel_asm_below_end, 2, {&eel_zero, &eel_one} },
- { "_above", nseel_asm_above,nseel_asm_above_end, 2, {&eel_zero, &eel_one} },
- { "_beleq", nseel_asm_beloweq,nseel_asm_beloweq_end, 2, {&eel_zero, &eel_one} },
- { "_aboeq", nseel_asm_aboveeq,nseel_asm_aboveeq_end, 2, {&eel_zero, &eel_one} },
- #else
- { "_not", nseel_asm_bnot,nseel_asm_bnot_end, 1, {&g_closefact} } ,
- { "_equal", nseel_asm_equal,nseel_asm_equal_end, 2, {&g_closefact} },
- { "_noteq", nseel_asm_notequal,nseel_asm_notequal_end, 2, {&g_closefact} },
- { "_below", nseel_asm_below,nseel_asm_below_end, 2 },
- { "_above", nseel_asm_above,nseel_asm_above_end, 2 },
- { "_beleq", nseel_asm_beloweq,nseel_asm_beloweq_end, 2 },
- { "_aboeq", nseel_asm_aboveeq,nseel_asm_aboveeq_end, 2 },
- #endif
- { "_set",nseel_asm_assign,nseel_asm_assign_end,2},
- { "_mod",nseel_asm_mod,nseel_asm_mod_end,2},
- { "_mulop",nseel_asm_mul_op,nseel_asm_mul_op_end,2},
- { "_divop",nseel_asm_div_op,nseel_asm_div_op_end,2},
- { "_orop",nseel_asm_or_op,nseel_asm_or_op_end,2},
- { "_andop",nseel_asm_and_op,nseel_asm_and_op_end,2},
- { "_addop",nseel_asm_add_op,nseel_asm_add_op_end,2},
- { "_subop",nseel_asm_sub_op,nseel_asm_sub_op_end,2},
- { "_modop",nseel_asm_mod_op,nseel_asm_mod_op_end,2},
- #ifdef __ppc__
- { "sin", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&sin} },
- { "cos", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&cos} },
- { "tan", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&tan} },
- #else
- { "sin", nseel_asm_sin,nseel_asm_sin_end, 1 },
- { "cos", nseel_asm_cos,nseel_asm_cos_end, 1 },
- { "tan", nseel_asm_tan,nseel_asm_tan_end, 1 },
- #endif
- { "asin", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&asin}, },
- { "acos", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&acos}, },
- { "atan", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&atan}, },
- { "atan2", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&atan2}, },
- { "sqr", nseel_asm_sqr,nseel_asm_sqr_end, 1 },
- #ifdef __ppc__
- { "sqrt", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&sqrt}, },
- #else
- { "sqrt", nseel_asm_sqrt,nseel_asm_sqrt_end, 1 },
- #endif
- { "pow", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&pow}, },
- { "_powop", nseel_asm_2pdds,nseel_asm_2pdds_end, 2, {&pow}, },
- { "exp", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&exp}, },
- #ifdef __ppc__
- { "log", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&log} },
- { "log10", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&log10} },
- #else
- { "log", nseel_asm_log,nseel_asm_log_end, 1, },
- { "log10", nseel_asm_log10,nseel_asm_log10_end, 1, },
- #endif
- { "abs", nseel_asm_abs,nseel_asm_abs_end, 1 },
- { "min", nseel_asm_min,nseel_asm_min_end, 2 },
- { "max", nseel_asm_max,nseel_asm_max_end, 2 },
- #ifdef __ppc__
- { "sign", nseel_asm_sign,nseel_asm_sign_end, 1, {&eel_zero}} ,
- #else
- { "sign", nseel_asm_sign,nseel_asm_sign_end, 1, {&g_signs}} ,
- #endif
- { "rand", nseel_asm_1pp,nseel_asm_1pp_end, 1, {&nseel_int_rand}, } ,
- //#if defined(_MSC_VER) && _MSC_VER >= 1400
- // { "floor", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&__floor} },
- //#else
- // { "floor", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&floor} },
- //#endif
- { "ceil", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&ceil} },
- #ifdef __ppc__
- { "invsqrt", nseel_asm_invsqrt,nseel_asm_invsqrt_end, 1, },
- #else
- { "invsqrt", nseel_asm_invsqrt,nseel_asm_invsqrt_end, 1, {&negativezeropointfive, &onepointfive} },
- #endif
- { "sigmoid", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&eel1sigmoid}, },
- // these differ from _and/_or, they always evaluate both...
- { "band", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&eel1band}, },
- { "bor", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&eel1bor}, },
- {"exec2",nseel_asm_exec2,nseel_asm_exec2_end,2},
- {"exec3",nseel_asm_exec2,nseel_asm_exec2_end,3},
- {"_mem",_asm_megabuf,_asm_megabuf_end,1,{&g_closefact,&__NSEEL_RAMAlloc},NSEEL_PProc_RAM},
- {"_gmem",_asm_megabuf,_asm_megabuf_end,1,{&g_closefact,&__NSEEL_RAMAllocGMEM},NSEEL_PProc_GRAM},
- {"freembuf",_asm_generic1parm,_asm_generic1parm_end,1,{&__NSEEL_RAM_MemFree},NSEEL_PProc_RAM},
- {"memcpy",_asm_generic3parm,_asm_generic3parm_end,3,{&__NSEEL_RAM_MemCpy},NSEEL_PProc_RAM},
- {"memset",_asm_generic3parm,_asm_generic3parm_end,3,{&__NSEEL_RAM_MemSet},NSEEL_PProc_RAM},
- };
- static functionType *fnTableUser;
- static int fnTableUser_size;
- functionType *nseel_getFunctionFromTable(int idx)
- {
- if (idx<0) return 0;
- if (idx>=sizeof(fnTable1)/sizeof(fnTable1[0]))
- {
- idx -= sizeof(fnTable1)/sizeof(fnTable1[0]);
- if (!fnTableUser || idx >= fnTableUser_size) return 0;
- return fnTableUser+idx;
- }
- return fnTable1+idx;
- }
- int NSEEL_init() // returns 0 on success
- {
- NSEEL_quit();
- return 0;
- }
- void NSEEL_addfunctionex2(const char *name, int nparms, char *code_startaddr, int code_len, void *pproc, void *fptr, void *fptr2)
- {
- if (!fnTableUser || !(fnTableUser_size&7))
- {
- fnTableUser=(functionType *)realloc(fnTableUser,(fnTableUser_size+8)*sizeof(functionType));
- }
- if (fnTableUser)
- {
- memset(&fnTableUser[fnTableUser_size],0,sizeof(functionType));
- fnTableUser[fnTableUser_size].nParams = nparms;
- fnTableUser[fnTableUser_size].name = name;
- fnTableUser[fnTableUser_size].afunc = code_startaddr;
- fnTableUser[fnTableUser_size].func_e = code_startaddr + code_len;
- fnTableUser[fnTableUser_size].pProc = (NSEEL_PPPROC) pproc;
- fnTableUser[fnTableUser_size].replptrs[0]=fptr;
- fnTableUser[fnTableUser_size].replptrs[1]=fptr2;
- fnTableUser_size++;
- }
- }
- void NSEEL_quit()
- {
- free(fnTableUser);
- fnTableUser_size=0;
- fnTableUser=0;
- }
- //---------------------------------------------------------------------------------------------------------------
- static void freeBlocks(llBlock **start)
- {
- llBlock *s=*start;
- *start=0;
- while (s)
- {
- llBlock *llB = s->next;
- #ifdef _WIN32
- VirtualFree(s, 0 /*LLB_DSIZE*/, MEM_RELEASE);
- #else
- free(s);
- #endif
- s=llB;
- }
- }
- //---------------------------------------------------------------------------------------------------------------
- static void *__newBlock(llBlock **start, int size)
- {
- llBlock *llb;
- int alloc_size;
- if (*start && (LLB_DSIZE - (*start)->sizeused) >= size)
- {
- void *t=(*start)->block+(*start)->sizeused;
- (*start)->sizeused+=(size+7)&~7;
- return t;
- }
- alloc_size=sizeof(llBlock);
- if ((int)size > LLB_DSIZE) alloc_size += size - LLB_DSIZE;
-
- #ifdef _WIN32
- llb = (llBlock *)VirtualAlloc(NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- #else
- llb = (llBlock *)malloc(alloc_size); // grab bigger block if absolutely necessary (heh)
- #endif
- #if defined(EEL_USE_MPROTECT)
- {
- static int pagesize = 0;
- if (!pagesize)
- {
- pagesize=sysconf(_SC_PAGESIZE);
- if (!pagesize) pagesize=4096;
- }
- uintptr_t offs,eoffs;
- offs=((uintptr_t)llb)&~(pagesize-1);
- eoffs=((uintptr_t)llb + alloc_size + pagesize-1)&~(pagesize-1);
- mprotect((void*)offs,eoffs-offs,PROT_WRITE|PROT_READ|PROT_EXEC);
- }
- #endif
- llb->sizeused=(size+7)&~7;
- llb->next = *start;
- *start = llb;
- return llb->block;
- }
- //---------------------------------------------------------------------------------------------------------------
- INT_PTR nseel_createCompiledValue(compileContext *ctx, EEL_F value, EEL_F *addrValue)
- {
- unsigned char *block;
- block=(unsigned char *)newTmpBlock(GLUE_MOV_EAX_DIRECTVALUE_SIZE);
- if (addrValue == NULL)
- {
- *(addrValue = (EEL_F *)newBlock(sizeof(EEL_F),sizeof(EEL_F))) = value;
- ctx->l_stats[3]+=sizeof(EEL_F);
- }
- GLUE_MOV_EAX_DIRECTVALUE_GEN(block+4,(INT_PTR)addrValue);
- return ((INT_PTR)(block));
- }
- //---------------------------------------------------------------------------------------------------------------
- static void *nseel_getFunctionAddress(int fntype, int fn, int *size, NSEEL_PPPROC *pProc, void ***replList)
- {
- *replList=0;
- switch (fntype)
- {
- case MATH_SIMPLE:
- switch (fn)
- {
- case FN_ASSIGN:
- return GLUE_realAddress(nseel_asm_assign,nseel_asm_assign_end,size);
- case FN_ADD:
- return GLUE_realAddress(nseel_asm_add,nseel_asm_add_end,size);
- case FN_SUB:
- return GLUE_realAddress(nseel_asm_sub,nseel_asm_sub_end,size);
- case FN_MULTIPLY:
- return GLUE_realAddress(nseel_asm_mul,nseel_asm_mul_end,size);
- case FN_DIVIDE:
- return GLUE_realAddress(nseel_asm_div,nseel_asm_div_end,size);
- case FN_MODULO:
- return GLUE_realAddress(nseel_asm_exec2,nseel_asm_exec2_end,size);
- case FN_AND:
- return GLUE_realAddress(nseel_asm_and,nseel_asm_and_end,size);
- case FN_OR:
- return GLUE_realAddress(nseel_asm_or,nseel_asm_or_end,size);
- case FN_UPLUS:
- return GLUE_realAddress(nseel_asm_uplus,nseel_asm_uplus_end,size);
- case FN_UMINUS:
- return GLUE_realAddress(nseel_asm_uminus,nseel_asm_uminus_end,size);
- }
- case MATH_FN:
- {
- functionType *p=nseel_getFunctionFromTable(fn);
- if (p)
- {
- *replList=p->replptrs;
- *pProc=p->pProc;
- return GLUE_realAddress(p->afunc,p->func_e,size);
- }
- }
- }
- *size=0;
- return 0;
- }
- //---------------------------------------------------------------------------------------------------------------
- INT_PTR nseel_createCompiledFunction3(compileContext *ctx, int fntype, INT_PTR fn, INT_PTR code1, INT_PTR code2, INT_PTR code3)
- {
- int sizes1=((int *)code1)[0];
- int sizes2=((int *)code2)[0];
- int sizes3=((int *)code3)[0];
- if (fntype == MATH_FN && fn == 0) // special case: IF
- {
- void *func3;
- int size;
- INT_PTR *ptr;
- char *block;
- unsigned char *newblock2,*newblock3;
- unsigned char *p;
- p=newblock2=newBlock(sizes2+sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE,32);
- memcpy(p,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); p+=GLUE_FUNC_ENTER_SIZE;
- memcpy(p,(char*)code2+4,sizes2); p+=sizes2;
- memcpy(p,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); p+=GLUE_FUNC_LEAVE_SIZE;
- memcpy(p,&GLUE_RET,sizeof(GLUE_RET)); p+=sizeof(GLUE_RET);
- p=newblock3=newBlock(sizes3+sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE,32);
- memcpy(p,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); p+=GLUE_FUNC_ENTER_SIZE;
- memcpy(p,(char*)code3+4,sizes3); p+=sizes3;
- memcpy(p,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); p+=GLUE_FUNC_LEAVE_SIZE;
- memcpy(p,&GLUE_RET,sizeof(GLUE_RET)); p+=sizeof(GLUE_RET);
- ctx->l_stats[2]+=sizes2+sizes3+sizeof(GLUE_RET)*2;
-
- func3 = GLUE_realAddress(nseel_asm_if,nseel_asm_if_end,&size);
- block=(char *)newTmpBlock(sizes1+size);
- memcpy(block+4,(char*)code1+4,sizes1);
- ptr=(INT_PTR *)(block+4+sizes1);
- memcpy(ptr,func3,size);
- ptr=EEL_GLUE_set_immediate(ptr,&g_closefact);
- ptr=EEL_GLUE_set_immediate(ptr,newblock2);
- EEL_GLUE_set_immediate(ptr,newblock3);
- ctx->computTableTop++;
- return (INT_PTR)block;
- }
- else
- {
- int size2;
- unsigned char *block;
- unsigned char *outp;
- void *myfunc;
- NSEEL_PPPROC preProc=0;
- void **repl;
-
- myfunc = nseel_getFunctionAddress(fntype, fn, &size2, &preProc,&repl);
- block=(unsigned char *)newTmpBlock(size2+sizes1+sizes2+sizes3+
- sizeof(GLUE_PUSH_EAX) +
- sizeof(GLUE_PUSH_EAX) +
- sizeof(GLUE_POP_EBX) +
- sizeof(GLUE_POP_ECX));
- outp=block+4;
- memcpy(outp,(char*)code1+4,sizes1);
- outp+=sizes1;
- memcpy(outp,&GLUE_PUSH_EAX,sizeof(GLUE_PUSH_EAX)); outp+=sizeof(GLUE_PUSH_EAX);
- memcpy(outp,(char*)code2+4,sizes2);
- outp+=sizes2;
- memcpy(outp,&GLUE_PUSH_EAX,sizeof(GLUE_PUSH_EAX)); outp+=sizeof(GLUE_PUSH_EAX);
- memcpy(outp,(char*)code3+4,sizes3);
- outp+=sizes3;
- memcpy(outp,&GLUE_POP_EBX,sizeof(GLUE_POP_EBX)); outp+=sizeof(GLUE_POP_EBX);
- memcpy(outp,&GLUE_POP_ECX,sizeof(GLUE_POP_ECX)); outp+=sizeof(GLUE_POP_ECX);
- memcpy(outp,myfunc,size2);
- if (preProc) preProc(outp,size2,ctx);
- if (repl)
- {
- if (repl[0]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[0]);
- if (repl[1]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[1]);
- if (repl[2]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[2]);
- if (repl[3]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[3]);
- }
- ctx->computTableTop++;
- return ((INT_PTR)(block));
- }
- }
- //---------------------------------------------------------------------------------------------------------------
- INT_PTR nseel_createCompiledFunction2(compileContext *ctx, int fntype, INT_PTR fn, INT_PTR code1, INT_PTR code2)
- {
- int size2;
- unsigned char *outp;
- void *myfunc;
- int sizes1=((int *)code1)[0];
- int sizes2=((int *)code2)[0];
- if (fntype == MATH_FN && (fn == 1 || fn == 2 || fn == 3)) // special case: LOOP/BOR/BAND
- {
- void *func3;
- int size;
- INT_PTR *ptr;
- char *block;
- unsigned char *newblock2, *p;
- p=newblock2=newBlock(sizes2+sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE,32);
- memcpy(p,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); p+=GLUE_FUNC_ENTER_SIZE;
- memcpy(p,(char*)code2+4,sizes2); p+=sizes2;
- memcpy(p,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); p+=GLUE_FUNC_LEAVE_SIZE;
- memcpy(p,&GLUE_RET,sizeof(GLUE_RET)); p+=sizeof(GLUE_RET);
- ctx->l_stats[2]+=sizes2+2;
-
- if (fn == 1) func3 = GLUE_realAddress(nseel_asm_band,nseel_asm_band_end,&size);
- else if (fn == 3) func3 = GLUE_realAddress(nseel_asm_repeat,nseel_asm_repeat_end,&size);
- else func3 = GLUE_realAddress(nseel_asm_bor,nseel_asm_bor_end,&size);
- block=(char *)newTmpBlock(sizes1+size);
- memcpy(block+4,(char*)code1+4,sizes1);
- ptr=(INT_PTR *)(block+4+sizes1);
- memcpy(ptr,func3,size);
- if (fn!=3) ptr=EEL_GLUE_set_immediate(ptr,&g_closefact); // for or/and
- ptr=EEL_GLUE_set_immediate(ptr,newblock2);
- if (fn!=3) ptr=EEL_GLUE_set_immediate(ptr,&g_closefact); // for or/and
- #ifdef __ppc__
- if (fn!=3) // for or/and on ppc we need a one
- {
- ptr=EEL_GLUE_set_immediate(ptr,&eel_one);
- }
- #endif
- ctx->computTableTop++;
- return (INT_PTR)block;
- }
- {
- NSEEL_PPPROC preProc=0;
- unsigned char *block;
- void **repl;
- myfunc = nseel_getFunctionAddress(fntype, fn, &size2,&preProc,&repl);
- block=(unsigned char *)newTmpBlock(size2+sizes1+sizes2+sizeof(GLUE_PUSH_EAX)+sizeof(GLUE_POP_EBX));
- outp=block+4;
- memcpy(outp,(char*)code1+4,sizes1);
- outp+=sizes1;
- memcpy(outp,&GLUE_PUSH_EAX,sizeof(GLUE_PUSH_EAX)); outp+=sizeof(GLUE_PUSH_EAX);
- memcpy(outp,(char*)code2+4,sizes2);
- outp+=sizes2;
- memcpy(outp,&GLUE_POP_EBX,sizeof(GLUE_POP_EBX)); outp+=sizeof(GLUE_POP_EBX);
- memcpy(outp,myfunc,size2);
- if (preProc) preProc(outp,size2,ctx);
- if (repl)
- {
- if (repl[0]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[0]);
- if (repl[1]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[1]);
- if (repl[2]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[2]);
- if (repl[3]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[3]);
- }
- ctx->computTableTop++;
- return ((INT_PTR)(block));
- }
- }
- //---------------------------------------------------------------------------------------------------------------
- INT_PTR nseel_createCompiledFunction1(compileContext *ctx, int fntype, INT_PTR fn, INT_PTR code)
- {
- NSEEL_PPPROC preProc=0;
- int size,size2;
- char *block;
- void *myfunc;
- void *func1;
-
- size =((int *)code)[0];
- func1 = (void *)(code+4);
-
- if (fntype == MATH_FN && fn == 4) // special case: while
- {
- void *func3;
- INT_PTR *ptr;
- unsigned char *newblock2, *p;
- p=newblock2=newBlock(size+sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE,32);
- memcpy(p,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); p+=GLUE_FUNC_ENTER_SIZE;
- memcpy(p,func1,size); p+=size;
- memcpy(p,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); p+=GLUE_FUNC_LEAVE_SIZE;
- memcpy(p,&GLUE_RET,sizeof(GLUE_RET)); p+=sizeof(GLUE_RET);
- ctx->l_stats[2]+=size+2;
-
- func3 = GLUE_realAddress(nseel_asm_repeatwhile,nseel_asm_repeatwhile_end,&size);
- block=(char *)newTmpBlock(size);
- ptr = (INT_PTR *)(block+4);
- memcpy(ptr,func3,size);
- ptr=EEL_GLUE_set_immediate(ptr,newblock2);
- EEL_GLUE_set_immediate(ptr,&g_closefact);
- ctx->computTableTop++;
- return (INT_PTR)block;
- }
- {
- void **repl;
- myfunc = nseel_getFunctionAddress(fntype, fn, &size2,&preProc,&repl);
- block=(char *)newTmpBlock(size+size2);
- memcpy(block+4, func1, size);
- memcpy(block+size+4,myfunc,size2);
- if (preProc) preProc(block+size+4,size2,ctx);
- if (repl)
- {
- unsigned char *outp=(unsigned char *)block+size+4;
- if (repl[0]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[0]);
- if (repl[1]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[1]);
- if (repl[2]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[2]);
- if (repl[3]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[3]);
- }
- ctx->computTableTop++;
- return ((INT_PTR)(block));
- }
- }
- static char *preprocessCode(compileContext *ctx, char *expression)
- {
- char *expression_start=expression;
- int len=0;
- int alloc_len=strlen(expression)+1+64;
- char *buf=(char *)malloc(alloc_len);
- int semicnt=0;
- // we need to call onCompileNewLine for each new line we get
-
- //onCompileNewLine(ctx,
- while (*expression)
- {
- if (len > alloc_len-64)
- {
- alloc_len = len+128;
- buf=(char*)realloc(buf,alloc_len);
- }
- if (expression[0] == '/')
- {
- if (expression[1] == '/')
- {
- expression+=2;
- while (expression[0] && expression[0] != '\n') expression++;
- continue;
- }
- else if (expression[1] == '*')
- {
- expression+=2;
- while (expression[0] && (expression[0] != '*' || expression[1] != '/'))
- {
- if (expression[0] == '\n') onCompileNewLine(ctx,expression+1-expression_start,len);
- expression++;
- }
- if (expression[0]) expression+=2; // at this point we KNOW expression[0]=* and expression[1]=/
- continue;
- }
- }
-
- if (expression[0] == '$')
- {
- if (toupper(expression[1]) == 'X')
- {
- char *p=expression+2;
- unsigned int v=strtoul(expression+2,&p,16);
- char tmp[64];
- expression=p;
- sprintf(tmp,"%u",v);
- memcpy(buf+len,tmp,strlen(tmp));
- len+=strlen(tmp);
- ctx->l_stats[0]+=strlen(tmp);
- continue;
- }
- if (expression[1]=='\'' && expression[2] && expression[3]=='\'')
- {
- char tmp[64];
- sprintf(tmp,"%u",((unsigned char *)expression)[2]);
- expression+=4;
- memcpy(buf+len,tmp,strlen(tmp));
- len+=strlen(tmp);
- ctx->l_stats[0]+=strlen(tmp);
- continue;
- }
- if (toupper(expression[1]) == 'P' && toupper(expression[2]) == 'I')
- {
- static char *str="3.141592653589793";
- expression+=3;
- memcpy(buf+len,str,17);
- len+=17; //strlen(str);
- ctx->l_stats[0]+=17;
- continue;
- }
- if (toupper(expression[1]) == 'E')
- {
- static char *str="2.71828183";
- expression+=2;
- memcpy(buf+len,str,10);
- len+=10; //strlen(str);
- ctx->l_stats[0]+=10;
- continue;
- }
- if (toupper(expression[1]) == 'P' && toupper(expression[2]) == 'H' && toupper(expression[3]) == 'I')
- {
- static char *str="1.61803399";
- expression+=4;
- memcpy(buf+len,str,10);
- len+=10; //strlen(str);
- ctx->l_stats[0]+=10;
- continue;
- }
-
- }
- {
- char c=*expression++;
- if (c == '\n') onCompileNewLine(ctx,expression-expression_start,len);
- if (isspace(c)) c=' ';
- if (c == '(') semicnt++;
- else if (c == ')') { semicnt--; if (semicnt < 0) semicnt=0; }
- else if (c == ';' && semicnt > 0)
- {
- // convert ; to % if next nonwhitespace char is alnum, otherwise convert to space
- int p=0;
- int nc;
- int commentstate=0;
- while ((nc=expression[p]))
- {
- if (!commentstate && nc == '/')
- {
- if (expression[p+1] == '/') commentstate=1;
- else if (expression[p+1] == '*') commentstate=2;
- }
- if (commentstate == 1 && nc == '\n') commentstate=0;
- else if (commentstate == 2 && nc == '*' && expression[p+1]=='/')
- {
- p++; // skip *
- commentstate=0;
- }
- else if (!commentstate && !isspace(nc)) break;
- p++;
- }
- // fucko, we should look for even more chars, me thinks
- if (nc && (isalnum(nc)
- #if 1
- || nc == '(' || nc == '_' || nc == '!' || nc == '$'
- #endif
- )) c='%';
- else c = ' '; // stray ;
- }
- #if 0
- else if (semicnt > 0 && c == ',')
- {
- int p=0;
- int nc;
- while ((nc=expression[p]) && isspace(nc)) p++;
- if (nc == ',' || nc == ')')
- {
- expression += p+1;
- buf[len++]=',';
- buf[len++]='0';
- c=nc; // append this char
- }
- }
- #endif
- // list of operators
- else if (!isspace(c) && !isalnum(c)) // check to see if this operator is ours
- {
- static char *symbollists[]=
- {
- "", // or any control char that is not parenthed
- ":(,;?%",
- ",):?;", // or || or &&
- ",);", // jf> removed :? from this, for =
- ",);",
- "", // only scans for a negative ] level
- };
- static struct
- {
- char op[2];
- char lscan,rscan;
- char *func;
- } preprocSymbols[] =
- {
- {{'+','='}, 0, 3, "_addop" },
- {{'-','='}, 0, 3, "_subop" },
- {{'%','='}, 0, 3, "_modop" },
- {{'|','='}, 0, 3, "_orop" },
- {{'&','='}, 0, 3, "_andop"},
- {{'/','='}, 0, 3, "_divop"},
- {{'*','='}, 0, 3, "_mulop"},
- {{'^','='}, 0, 3, "_powop"},
- {{'=','='}, 1, 2, "_equal" },
- {{'<','='}, 1, 2, "_beleq" },
- {{'>','='}, 1, 2, "_aboeq" },
- {{'<',0 }, 1, 2, "_below" },
- {{'>',0 }, 1, 2, "_above" },
- {{'!','='}, 1, 2, "_noteq" },
- {{'|','|'}, 1, 2, "_or" },
- {{'&','&'}, 1, 2, "_and" },
- {{'=',0 }, 0, 3, "_set" },
- {{'%',0}, 0, 0, "_mod" },
- {{'^',0}, 0, 0, "pow" },
- {{'[',0 }, 0, 5, },
- {{'!',0 },-1, 0, }, // this should also ignore any leading +-
- {{'?',0 }, 1, 4, },
- };
- int n;
- int ns=sizeof(preprocSymbols)/sizeof(preprocSymbols[0]);
- for (n = 0; n < ns; n++)
- {
- if (c == preprocSymbols[n].op[0] && (!preprocSymbols[n].op[1] || expression[0] == preprocSymbols[n].op[1]))
- {
- break;
- }
- }
- if (n < ns)
- {
- int lscan=preprocSymbols[n].lscan;
- int rscan=preprocSymbols[n].rscan;
- // parse left side of =, scanning back for an unparenthed nonwhitespace nonalphanumeric nonparenth?
- // so megabuf(x+y)= would be fine, x=, but +x= would do +set(x,)
- char *l_ptr=0;
- char *r_ptr=0;
- if (lscan >= 0)
- {
- char *scan=symbollists[lscan];
- int l_semicnt=0;
- l_ptr=buf + len - 1;
- while (l_ptr >= buf)
- {
- if (*l_ptr == ')') l_semicnt++;
- else if (*l_ptr == '(')
- {
- l_semicnt--;
- if (l_semicnt < 0) break;
- }
- else if (!l_semicnt)
- {
- if (!*scan)
- {
- if (!isspace(*l_ptr) && !isalnum(*l_ptr) && *l_ptr != '_' && *l_ptr != '.') break;
- }
- else
- {
- char *sc=scan;
- if (lscan == 2 && ( // not currently used, even
- (l_ptr[0]=='|' && l_ptr[1] == '|')||
- (l_ptr[0]=='&' && l_ptr[1] == '&')
- )
- ) break;
- while (*sc && *l_ptr != *sc) sc++;
- if (*sc) break;
- }
- }
- l_ptr--;
- }
- buf[len]=0;
- l_ptr++;
- len = l_ptr - buf;
- l_ptr = strdup(l_ptr); // doesn't need to be preprocessed since it just was
- }
- if (preprocSymbols[n].op[1]) expression++;
- r_ptr=expression;
- {
- // scan forward to an uncommented, unparenthed semicolon, comma, or )
- int r_semicnt=0;
- int r_qcnt=0;
- char *scan=symbollists[rscan];
- int commentstate=0;
- int hashadch=0;
- int bracketcnt=0;
- while (*r_ptr)
- {
- if (!commentstate && *r_ptr == '/')
- {
- if (r_ptr[1] == '/') commentstate=1;
- else if (r_ptr[1] == '*') commentstate=2;
- }
- if (commentstate == 1 && *r_ptr == '\n') commentstate=0;
- else if (commentstate == 2 && *r_ptr == '*' && r_ptr[1]=='/')
- {
- r_ptr++; // skip *
- commentstate=0;
- }
- else if (!commentstate)
- {
- if (*r_ptr == '(') {hashadch=1; r_semicnt++; }
- else if (*r_ptr == ')')
- {
- r_semicnt--;
- if (r_semicnt < 0) break;
- }
- else if (!r_semicnt)
- {
- char *sc=scan;
- if (*r_ptr == ';' || *r_ptr == ',') break;
-
- if (!rscan)
- {
- if (*r_ptr == ':') break;
- if (!isspace(*r_ptr) && !isalnum(*r_ptr) && *r_ptr != '_' && *r_ptr != '.' && hashadch) break;
- if (isalnum(*r_ptr) || *r_ptr == '_')hashadch=1;
- }
- else if (rscan == 2 &&
- ((r_ptr[0]=='|' && r_ptr[1] == '|')||
- (r_ptr[0]=='&' && r_ptr[1] == '&')
- )
- ) break;
- else if (rscan == 3 || rscan == 4)
- {
- if (*r_ptr == ':') r_qcnt--;
- else if (*r_ptr == '?') r_qcnt++;
- if (r_qcnt < 3-rscan) break;
- }
- else if (rscan == 5)
- {
- if (*r_ptr == '[') bracketcnt++;
- else if (*r_ptr == ']') bracketcnt--;
- if (bracketcnt < 0) break;
- }
- while (*sc && *r_ptr != *sc) sc++;
- if (*sc) break;
- }
- }
- r_ptr++;
- }
- // expression -> r_ptr is our string (not including r_ptr)
- {
- char *orp=r_ptr;
- char rps=*orp;
- *orp=0; // temporarily terminate
- r_ptr=preprocessCode(ctx,expression);
- expression=orp;
- *orp = rps; // fix termination(restore string)
- }
- }
- if (r_ptr)
- {
- int thisl = strlen(l_ptr?l_ptr:"") + strlen(r_ptr) + 32;
- if (len+thisl > alloc_len-64)
- {
- alloc_len = len+thisl+128;
- buf=(char*)realloc(buf,alloc_len);
- }
- if (n == ns-3)
- {
- char *lp = l_ptr;
- char *rp = r_ptr;
- while (lp && *lp && isspace(*lp)) lp++;
- while (rp && *rp && isspace(*rp)) rp++;
- if (lp && !strncasecmp(lp,"gmem",4) && (!lp[4] || isspace(lp[4])))
- {
- len+=sprintf(buf+len,"_gmem(%s",r_ptr && *r_ptr ? r_ptr : "0");
- ctx->l_stats[0]+=strlen(l_ptr)+4;
- }
- else if (rp && *rp && strcmp(rp,"0"))
- {
- len+=sprintf(buf+len,"_mem((%s)+(%s)",lp,rp);
- ctx->l_stats[0]+=strlen(lp)+strlen(rp)+8;
- }
- else
- {
- len+=sprintf(buf+len,"_mem(%s",lp);
- ctx->l_stats[0]+=strlen(lp)+4;
- }
- // skip the ]
- if (*expression == ']') expression++;
- }
- else if (n == ns-2)
- {
- len+=sprintf(buf+len,"_not(%s",
- r_ptr);
- ctx->l_stats[0]+=4;
- }
- else if (n == ns-1)// if (l_ptr,r_ptr1,r_ptr2)
- {
- char *rptr2=r_ptr;
- char *tmp=r_ptr;
- int parcnt=0;
- int qcnt=1;
- while (*rptr2)
- {
- if (*rptr2 == '?') qcnt++;
- else if (*rptr2 == ':') qcnt--;
- else if (*rptr2 == '(') parcnt++;
- else if (*rptr2 == ')') parcnt--;
- if (parcnt < 0) break;
- if (!parcnt && !qcnt && *rptr2 == ':') break;
- rptr2++;
- }
- if (*rptr2) *rptr2++=0;
- while (isspace(*rptr2)) rptr2++;
- while (isspace(*tmp)) tmp++;
- len+=sprintf(buf+len,"_if(%s,%s,%s",l_ptr,*tmp?tmp:"0",*rptr2?rptr2:"0");
- ctx->l_stats[0]+=6;
- }
- else
- {
- len+=sprintf(buf+len,"%s(%s,%s",preprocSymbols[n].func,l_ptr?l_ptr:"",r_ptr);
- ctx->l_stats[0]+=strlen(preprocSymbols[n].func)+2;
- }
- }
- free(r_ptr);
- free(l_ptr);
- c = ')'; // close parenth below
- }
- }
- // if (c != ' ' || (len && buf[len-1] != ' ')) // don't bother adding multiple spaces
- {
- buf[len++]=c;
- if (c != ' ') ctx->l_stats[0]++;
- }
- }
- }
- buf[len]=0;
- return buf;
- }
- #ifdef PPROC_TEST
- int main(int argc, char* argv[])
- {
- compileContext ctx={0};
- char *p=preprocessCode(&ctx,argv[1]);
- if (p)printf("%s\n",p);
- free(p);
- return 0;
- }
- #endif
- #if 0
- static void movestringover(char *str, int amount)
- {
- char tmp[1024+8];
- int l=(int)strlen(str);
- l=min(1024-amount-1,l);
- memcpy(tmp,str,l+1);
- while (l >= 0 && tmp[l]!='\n') l--;
- l++;
- tmp[l]=0;//ensure we null terminate
- memcpy(str+amount,tmp,l+1);
- }
- #endif
- //------------------------------------------------------------------------------
- NSEEL_CODEHANDLE NSEEL_code_compile(NSEEL_VMCTX _ctx, char *_expression, int lineoffs)
- {
- compileContext *ctx = (compileContext *)_ctx;
- char *expression,*expression_start;
- int computable_size=0;
- codeHandleType *handle;
- startPtr *scode=NULL;
- startPtr *startpts=NULL;
- if (!ctx) return 0;
- ctx->last_error_string[0]=0;
- if (!_expression || !*_expression) return 0;
- freeBlocks((llBlock **)&ctx->tmpblocks_head); // free blocks
- freeBlocks((llBlock **)&ctx->blocks_head); // free blocks
- memset(ctx->l_stats,0,sizeof(ctx->l_stats));
- free(ctx->compileLineRecs); ctx->compileLineRecs=0; ctx->compileLineRecs_size=0; ctx->compileLineRecs_alloc=0;
- handle = (codeHandleType*)newBlock(sizeof(codeHandleType),8);
- if (!handle)
- {
- return 0;
- }
-
- memset(handle,0,sizeof(codeHandleType));
- expression_start=expression=preprocessCode(ctx,_expression);
- while (*expression)
- {
- void *startptr;
- char *expr;
- ctx->colCount=0;
- ctx->computTableTop=0;
- // single out segment
- while (*expression == ';' || isspace(*expression)) expression++;
- if (!*expression) break;
- expr=expression;
- while (*expression && *expression != ';') expression++;
- if (*expression) *expression++ = 0;
- // parse
-
- startptr=nseel_compileExpression(ctx,expr);
- if (ctx->computTableTop > NSEEL_MAX_TEMPSPACE_ENTRIES- /* safety */ 16 - /* alignment */4 ||
- !startptr)
- {
- int byteoffs = expr - expression_start;
- int destoffs,linenumber;
- char buf[21], *p;
- int x,le;
- #ifdef NSEEL_EEL1_COMPAT_MODE
- if (!startptr) continue;
- #endif
- if (ctx->errVar > 0) byteoffs += ctx->errVar;
- linenumber=findByteOffsetInSource(ctx,byteoffs,&destoffs);
- if (destoffs < 0) destoffs=0;
- le=strlen(_expression);
- if (destoffs >= le) destoffs=le;
- p= _expression + destoffs;
- for (x = 0;x < 20; x ++)
- {
- if (!*p || *p == '\r' || *p == '\n') break;
- buf[x]=*p++;
- }
- buf[x]=0;
- sprintf(ctx->last_error_string,"Around line %d '%s'",linenumber+lineoffs,buf);
- ctx->last_error_string[sizeof(ctx->last_error_string)-1]=0;
- scode=NULL;
- break;
- }
- if (computable_size < ctx->computTableTop)
- {
- computable_size=ctx->computTableTop;
- }
- {
- startPtr *tmp=(startPtr*) __newBlock((llBlock **)&ctx->tmpblocks_head,sizeof(startPtr));
- if (!tmp) break;
- tmp->startptr = startptr;
- tmp->next=NULL;
- if (!scode) scode=startpts=tmp;
- else
- {
- scode->next=tmp;
- scode=tmp;
- }
- }
- }
- free(ctx->compileLineRecs); ctx->compileLineRecs=0; ctx->compileLineRecs_size=0; ctx->compileLineRecs_alloc=0;
- // check to see if failed on the first startingCode
- if (!scode)
- {
- handle=NULL; // return NULL (after resetting blocks_head)
- }
- else
- {
- char *tabptr = (char *)(handle->workTable=calloc(computable_size+64, sizeof(EEL_F)));
- unsigned char *writeptr;
- startPtr *p=startpts;
- int size=sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE; // for ret at end :)
- if (((INT_PTR)tabptr)&31)
- tabptr += 32-(((INT_PTR)tabptr)&31);
- // now we build one big code segment out of our list of them, inserting a mov esi, computable before each item
- while (p)
- {
- size += GLUE_RESET_ESI(NULL,0);
- size+=*(int *)p->startptr;
- p=p->next;
- }
- handle->code = newBlock(size,32);
- if (handle->code)
- {
- writeptr=(unsigned char *)handle->code;
- memcpy(writeptr,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); writeptr += GLUE_FUNC_ENTER_SIZE;
- p=startpts;
- while (p)
- {
- int thissize=*(int *)p->startptr;
- writeptr+=GLUE_RESET_ESI(writeptr,tabptr);
- //memcpy(writeptr,&GLUE_MOV_ESI_EDI,sizeof(GLUE_MOV_ESI_EDI));
- //writeptr+=sizeof(GLUE_MOV_ESI_EDI);
- memcpy(writeptr,(char*)p->startptr + 4,thissize);
- writeptr += thissize;
-
- p=p->next;
- }
- memcpy(writeptr,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); writeptr += GLUE_FUNC_LEAVE_SIZE;
- memcpy(writeptr,&GLUE_RET,sizeof(GLUE_RET)); writeptr += sizeof(GLUE_RET);
- ctx->l_stats[1]=size;
- }
- handle->blocks = ctx->blocks_head;
- ctx->blocks_head=0;
- }
- freeBlocks((llBlock **)&ctx->tmpblocks_head); // free blocks
- freeBlocks((llBlock **)&ctx->blocks_head); // free blocks
- if (handle)
- {
- memcpy(handle->code_stats,ctx->l_stats,sizeof(ctx->l_stats));
- nseel_evallib_stats[0]+=ctx->l_stats[0];
- nseel_evallib_stats[1]+=ctx->l_stats[1];
- nseel_evallib_stats[2]+=ctx->l_stats[2];
- nseel_evallib_stats[3]+=ctx->l_stats[3];
- nseel_evallib_stats[4]++;
- }
- memset(ctx->l_stats,0,sizeof(ctx->l_stats));
- free(expression_start);
- return (NSEEL_CODEHANDLE)handle;
- }
- //------------------------------------------------------------------------------
- void NSEEL_code_execute(NSEEL_CODEHANDLE code)
- {
- INT_PTR tabptr;
- INT_PTR codeptr;
- codeHandleType *h = (codeHandleType *)code;
- if (!h || !h->code) return;
- codeptr = (INT_PTR) h->code;
- #if 0
- {
- unsigned int *p=(unsigned int *)codeptr;
- while (*p != GLUE_RET[0])
- {
- printf("instr:%04X:%04X\n",*p>>16,*p&0xffff);
- p++;
- }
- }
- #endif
- tabptr=(INT_PTR)h->workTable;
- if (tabptr&31)
- tabptr += 32-((tabptr)&31);
- //printf("calling code!\n");
- GLUE_CALL_CODE(tabptr,codeptr);
- }
- char *NSEEL_code_getcodeerror(NSEEL_VMCTX ctx)
- {
- compileContext *c=(compileContext *)ctx;
- if (ctx && c->last_error_string[0]) return c->last_error_string;
- return 0;
- }
- //------------------------------------------------------------------------------
- void NSEEL_code_free(NSEEL_CODEHANDLE code)
- {
- codeHandleType *h = (codeHandleType *)code;
- if (h != NULL)
- {
- free(h->workTable);
- nseel_evallib_stats[0]-=h->code_stats[0];
- nseel_evallib_stats[1]-=h->code_stats[1];
- nseel_evallib_stats[2]-=h->code_stats[2];
- nseel_evallib_stats[3]-=h->code_stats[3];
- nseel_evallib_stats[4]--;
- freeBlocks(&h->blocks);
- }
- }
- //------------------------------------------------------------------------------
- void NSEEL_VM_resetvars(NSEEL_VMCTX _ctx)
- {
- if (_ctx)
- {
- compileContext *ctx=(compileContext *)_ctx;
- int x;
- if (ctx->varTable_Names || ctx->varTable_Values) for (x = 0; x < ctx->varTable_numBlocks; x ++)
- {
- if (ctx->varTable_Names) free(ctx->varTable_Names[x]);
- if (ctx->varTable_Values) free(ctx->varTable_Values[x]);
- }
- free(ctx->varTable_Values);
- free(ctx->varTable_Names);
- ctx->varTable_Values=0;
- ctx->varTable_Names=0;
- ctx->varTable_numBlocks=0;
- }
- }
- NSEEL_VMCTX NSEEL_VM_alloc() // return a handle
- {
- compileContext *ctx=calloc(1,sizeof(compileContext));
- return ctx;
- }
- void NSEEL_VM_free(NSEEL_VMCTX _ctx) // free when done with a VM and ALL of its code have been freed, as well
- {
- if (_ctx)
- {
- compileContext *ctx=(compileContext *)_ctx;
- NSEEL_VM_resetvars(_ctx);
- NSEEL_VM_freeRAM(_ctx);
- freeBlocks((llBlock **)&ctx->tmpblocks_head); // free blocks
- freeBlocks((llBlock **)&ctx->blocks_head); // free blocks
- free(ctx->compileLineRecs);
- free(ctx);
- }
- }
- int *NSEEL_code_getstats(NSEEL_CODEHANDLE code)
- {
- codeHandleType *h = (codeHandleType *)code;
- if (h)
- {
- return h->code_stats;
- }
- return 0;
- }
- void NSEEL_VM_SetCustomFuncThis(NSEEL_VMCTX ctx, void *thisptr)
- {
- if (ctx)
- {
- compileContext *c=(compileContext*)ctx;
- c->caller_this=thisptr;
- }
- }
- void NSEEL_PProc_RAM(void *data, int data_size, compileContext *ctx)
- {
- if (data_size>0) EEL_GLUE_set_immediate(data, &ctx->ram_blocks);
- }
- void NSEEL_PProc_THIS(void *data, int data_size, compileContext *ctx)
- {
- if (data_size>0) EEL_GLUE_set_immediate(data, ctx->caller_this);
- }
|