nseel-compiler.c 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791
  1. /*
  2. Expression Evaluator Library (NS-EEL) v2
  3. Copyright (C) 2004-2008 Cockos Incorporated
  4. Copyright (C) 1999-2003 Nullsoft, Inc.
  5. nseel-compiler.c
  6. This software is provided 'as-is', without any express or implied
  7. warranty. In no event will the authors be held liable for any damages
  8. arising from the use of this software.
  9. Permission is granted to anyone to use this software for any purpose,
  10. including commercial applications, and to alter it and redistribute it
  11. freely, subject to the following restrictions:
  12. 1. The origin of this software must not be misrepresented; you must not
  13. claim that you wrote the original software. If you use this software
  14. in a product, an acknowledgment in the product documentation would be
  15. appreciated but is not required.
  16. 2. Altered source versions must be plainly marked as such, and must not be
  17. misrepresented as being the original software.
  18. 3. This notice may not be removed or altered from any source distribution.
  19. */
  20. // for VirtualProtect
  21. #include "ns-eel-int.h"
  22. #include <string.h>
  23. #include <math.h>
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #ifndef _WIN64
  27. #ifndef __ppc__
  28. #include <float.h>
  29. #endif
  30. #endif
  31. #ifdef __APPLE__
  32. #ifdef __LP64__
  33. #define EEL_USE_MPROTECT
  34. #endif
  35. #endif
  36. #ifdef EEL_USE_MPROTECT
  37. #include <sys/mman.h>
  38. #include <stdint.h>
  39. #include <unistd.h>
  40. #endif
  41. #ifdef NSEEL_EEL1_COMPAT_MODE
  42. #ifndef EEL_NO_CHANGE_FPFLAGS
  43. #define EEL_NO_CHANGE_FPFLAGS
  44. #endif
  45. #endif
  46. #ifndef _WIN64
  47. #if !defined(_RC_CHOP) && !defined(EEL_NO_CHANGE_FPFLAGS)
  48. #include <fpu_control.h>
  49. #define _RC_CHOP _FPU_RC_ZERO
  50. #define _MCW_RC _FPU_RC_ZERO
  51. static unsigned int _controlfp(unsigned int val, unsigned int mask)
  52. {
  53. unsigned int ret;
  54. _FPU_GETCW(ret);
  55. if (mask)
  56. {
  57. ret&=~mask;
  58. ret|=val;
  59. _FPU_SETCW(ret);
  60. }
  61. return ret;
  62. }
  63. #endif
  64. #endif
  65. #ifdef __ppc__
  66. #define GLUE_MOV_EAX_DIRECTVALUE_SIZE 8
  67. static void GLUE_MOV_EAX_DIRECTVALUE_GEN(void *b, INT_PTR v)
  68. {
  69. unsigned int uv=(unsigned int)v;
  70. unsigned short *p=(unsigned short *)b;
  71. *p++ = 0x3C60; // addis r3, r0, hw
  72. *p++ = (uv>>16)&0xffff;
  73. *p++ = 0x6063; // ori r3, r3, lw
  74. *p++ = uv&0xffff;
  75. }
  76. // mflr r5
  77. // stwu r5, -4(r1)
  78. const static unsigned int GLUE_FUNC_ENTER[2] = { 0x7CA802A6, 0x94A1FFFC };
  79. // lwz r5, 0(r1)
  80. // addi r1, r1, 4
  81. // mtlr r5
  82. const static unsigned int GLUE_FUNC_LEAVE[3] = { 0x80A10000, 0x38210004, 0x7CA803A6 };
  83. #define GLUE_FUNC_ENTER_SIZE sizeof(GLUE_FUNC_ENTER)
  84. #define GLUE_FUNC_LEAVE_SIZE sizeof(GLUE_FUNC_LEAVE)
  85. const static unsigned int GLUE_RET[]={0x4E800020}; // blr
  86. const static unsigned int GLUE_MOV_ESI_EDI=0x7E308B78; // mr r16, r17
  87. static int GLUE_RESET_ESI(char *out, void *ptr)
  88. {
  89. if (out) memcpy(out,&GLUE_MOV_ESI_EDI,sizeof(GLUE_MOV_ESI_EDI));
  90. return sizeof(GLUE_MOV_ESI_EDI);
  91. }
  92. // stwu r3, -4(r1)
  93. const static unsigned int GLUE_PUSH_EAX[1]={ 0x9461FFFC};
  94. // lwz r14, 0(r1)
  95. // addi r1, r1, 4
  96. const static unsigned int GLUE_POP_EBX[2]={ 0x81C10000, 0x38210004, };
  97. // lwz r15, 0(r1)
  98. // addi r1, r1, 4
  99. const static unsigned int GLUE_POP_ECX[2]={ 0x81E10000, 0x38210004 };
  100. static void GLUE_CALL_CODE(INT_PTR bp, INT_PTR cp)
  101. {
  102. __asm__(
  103. "stmw r14, -80(r1)\n"
  104. "mtctr %0\n"
  105. "mr r17, %1\n"
  106. "subi r17, r17, 8\n"
  107. "mflr r5\n"
  108. "stw r5, -84(r1)\n"
  109. "subi r1, r1, 88\n"
  110. "bctrl\n"
  111. "addi r1, r1, 88\n"
  112. "lwz r5, -84(r1)\n"
  113. "lmw r14, -80(r1)\n"
  114. "mtlr r5\n"
  115. ::"r" (cp), "r" (bp));
  116. };
  117. INT_PTR *EEL_GLUE_set_immediate(void *_p, void *newv)
  118. {
  119. // todo 64 bit ppc will take some work
  120. unsigned int *p=(unsigned int *)_p;
  121. while ((p[0]&0x0000FFFF) != 0x0000dead &&
  122. (p[1]&0x0000FFFF) != 0x0000beef) p++;
  123. p[0] = (p[0]&0xFFFF0000) | (((unsigned int)newv)>>16);
  124. p[1] = (p[1]&0xFFFF0000) | (((unsigned int)newv)&0xFFFF);
  125. return (INT_PTR*)++p;
  126. }
  127. #else
  128. //x86 specific code
  129. #define GLUE_FUNC_ENTER_SIZE 0
  130. #define GLUE_FUNC_LEAVE_SIZE 0
  131. const static unsigned int GLUE_FUNC_ENTER[1];
  132. const static unsigned int GLUE_FUNC_LEAVE[1];
  133. #if defined(_WIN64) || defined(__LP64__)
  134. #define GLUE_MOV_EAX_DIRECTVALUE_SIZE 10
  135. static void GLUE_MOV_EAX_DIRECTVALUE_GEN(void *b, INT_PTR v) {
  136. unsigned short *bb = (unsigned short *)b;
  137. *bb++ =0xB848;
  138. *(INT_PTR *)bb = v;
  139. }
  140. const static unsigned char GLUE_PUSH_EAX[2]={ 0x50,0x50}; // push rax ; push rax (push twice to preserve alignment)
  141. const static unsigned char GLUE_POP_EBX[2]={0x5F, 0x5f}; //pop rdi ; twice
  142. const static unsigned char GLUE_POP_ECX[2]={0x59, 0x59 }; // pop rcx ; twice
  143. #else
  144. #define GLUE_MOV_EAX_DIRECTVALUE_SIZE 5
  145. static void GLUE_MOV_EAX_DIRECTVALUE_GEN(void *b, int v)
  146. {
  147. *((unsigned char *)b) =0xB8;
  148. b= ((unsigned char *)b)+1;
  149. *(int *)b = v;
  150. }
  151. const static unsigned char GLUE_PUSH_EAX[4]={0x83, 0xEC, 12, 0x50}; // sub esp, 12, push eax
  152. const static unsigned char GLUE_POP_EBX[4]={0x5F, 0x83, 0xC4, 12}; //pop ebx, add esp, 12 // DI=5F, BX=0x5B;
  153. const static unsigned char GLUE_POP_ECX[4]={0x59, 0x83, 0xC4, 12}; // pop ecx, add esp, 12
  154. #endif
  155. //const static unsigned short GLUE_MOV_ESI_EDI=0xF78B;
  156. const static unsigned char GLUE_RET=0xC3;
  157. static int GLUE_RESET_ESI(unsigned char *out, void *ptr)
  158. {
  159. #if defined(_WIN64) || defined(__LP64__)
  160. if (out)
  161. {
  162. *out++ = 0x48;
  163. *out++ = 0xBE; // mov rsi, constant64
  164. *(void **)out = ptr;
  165. out+=sizeof(void *);
  166. }
  167. return 2+sizeof(void *);
  168. #else
  169. if (out)
  170. {
  171. *out++ = 0xBE; // mov esi, constant
  172. memcpy(out,&ptr,sizeof(void *));
  173. out+=sizeof(void *);
  174. }
  175. return 1+sizeof(void *);
  176. #endif
  177. }
  178. static void GLUE_CALL_CODE(INT_PTR bp, INT_PTR cp)
  179. {
  180. #if defined(_WIN64) || defined(__LP64__)
  181. extern void win64_callcode(INT_PTR code);
  182. win64_callcode(cp);
  183. #else // non-64 bit
  184. #ifdef _MSC_VER
  185. #ifndef EEL_NO_CHANGE_FPFLAGS
  186. unsigned int old_v=_controlfp(0,0);
  187. _controlfp(_RC_CHOP,_MCW_RC);
  188. #endif
  189. __asm
  190. {
  191. mov eax, cp
  192. pushad
  193. call eax
  194. popad
  195. };
  196. #ifndef EEL_NO_CHANGE_FPFLAGS
  197. _controlfp(old_v,_MCW_RC);
  198. #endif
  199. #else // gcc x86
  200. #ifndef EEL_NO_CHANGE_FPFLAGS
  201. unsigned int old_v=_controlfp(0,0);
  202. _controlfp(_RC_CHOP,_MCW_RC);
  203. #endif
  204. __asm__("call *%%eax"::"a" (cp): "%ecx","%edx","%esi","%edi");
  205. #ifndef EEL_NO_CHANGE_FPFLAGS
  206. _controlfp(old_v,_MCW_RC);
  207. #endif
  208. #endif //gcc x86
  209. #endif // 32bit
  210. }
  211. INT_PTR *EEL_GLUE_set_immediate(void *_p, void *newv)
  212. {
  213. char *p=(char*)_p;
  214. while (*(INT_PTR *)p != ~(INT_PTR)0) p++;
  215. *(INT_PTR *)p = (INT_PTR)newv;
  216. return ((INT_PTR*)p)+1;
  217. }
  218. #endif
  219. static void *GLUE_realAddress(void *fn, void *fn_e, int *size)
  220. {
  221. #if defined(_MSC_VER) || defined(__LP64__)
  222. unsigned char *p;
  223. #if defined(_DEBUG) && !defined(__LP64__)
  224. if (*(unsigned char *)fn == 0xE9) // this means jump to the following address
  225. {
  226. fn = ((unsigned char *)fn) + *(int *)((char *)fn+1) + 5;
  227. }
  228. #endif
  229. // this may not work in debug mode
  230. p=(unsigned char *)fn;
  231. for (;;)
  232. {
  233. int a;
  234. for (a=0;a<12;a++)
  235. {
  236. if (p[a] != (a?0x90:0x89)) break;
  237. }
  238. if (a>=12)
  239. {
  240. *size = (char *)p - (char *)fn;
  241. // if (*size<0) MessageBox(NULL,"expect poof","a",0);
  242. return fn;
  243. }
  244. p++;
  245. }
  246. #else
  247. char *p=(char *)fn_e - sizeof(GLUE_RET);
  248. if (p <= (char *)fn) *size=0;
  249. else
  250. {
  251. while (p > (char *)fn && memcmp(p,&GLUE_RET,sizeof(GLUE_RET))) p-=sizeof(GLUE_RET);
  252. *size = p - (char *)fn;
  253. }
  254. return fn;
  255. #endif
  256. }
  257. static int nseel_evallib_stats[5]; // source bytes, static code bytes, call code bytes, data bytes, segments
  258. int *NSEEL_getstats()
  259. {
  260. return nseel_evallib_stats;
  261. }
  262. EEL_F *NSEEL_getglobalregs()
  263. {
  264. return nseel_globalregs;
  265. }
  266. // this stuff almost works
  267. static int findByteOffsetInSource(compileContext *ctx, int byteoffs,int *destoffs)
  268. {
  269. int x;
  270. if (!ctx->compileLineRecs || !ctx->compileLineRecs_size) return *destoffs=0;
  271. if (byteoffs < ctx->compileLineRecs[0].destByteCount)
  272. {
  273. *destoffs=0;
  274. return 1;
  275. }
  276. for (x = 0; x < ctx->compileLineRecs_size-1; x ++)
  277. {
  278. if (byteoffs >= ctx->compileLineRecs[x].destByteCount &&
  279. byteoffs < ctx->compileLineRecs[x+1].destByteCount) break;
  280. }
  281. *destoffs=ctx->compileLineRecs[(x&&x==ctx->compileLineRecs_size-1)?x-1:x].srcByteCount;
  282. return x+2;
  283. }
  284. static void onCompileNewLine(compileContext *ctx, int srcBytes, int destBytes)
  285. {
  286. if (!ctx->compileLineRecs || ctx->compileLineRecs_size >= ctx->compileLineRecs_alloc)
  287. {
  288. ctx->compileLineRecs_alloc = ctx->compileLineRecs_size+1024;
  289. ctx->compileLineRecs = (lineRecItem *)realloc(ctx->compileLineRecs,sizeof(lineRecItem)*ctx->compileLineRecs_alloc);
  290. }
  291. if (ctx->compileLineRecs)
  292. {
  293. ctx->compileLineRecs[ctx->compileLineRecs_size].srcByteCount=srcBytes;
  294. ctx->compileLineRecs[ctx->compileLineRecs_size++].destByteCount=destBytes;
  295. }
  296. }
  297. #define LLB_DSIZE (65536-64)
  298. typedef struct _llBlock {
  299. struct _llBlock *next;
  300. int sizeused;
  301. char block[LLB_DSIZE];
  302. } llBlock;
  303. typedef struct _startPtr {
  304. struct _startPtr *next;
  305. void *startptr;
  306. } startPtr;
  307. typedef struct {
  308. void *workTable;
  309. llBlock *blocks;
  310. void *code;
  311. int code_stats[4];
  312. } codeHandleType;
  313. #ifndef NSEEL_MAX_TEMPSPACE_ENTRIES
  314. #define NSEEL_MAX_TEMPSPACE_ENTRIES 2048
  315. #endif
  316. static void *__newBlock(llBlock **start,int size);
  317. #define newTmpBlock(x) __newTmpBlock((llBlock **)&ctx->tmpblocks_head,x)
  318. #define newBlock(x,a) __newBlock_align(ctx,x,a)
  319. static void *__newTmpBlock(llBlock **start, int size)
  320. {
  321. void *p=__newBlock(start,size+4);
  322. if (p && size>=0) *((int *)p) = size;
  323. return p;
  324. }
  325. static void *__newBlock_align(compileContext *ctx, int size, int align) // makes sure block is aligned to 32 byte boundary, for code
  326. {
  327. int a1=align-1;
  328. char *p=(char*)__newBlock((llBlock **)&ctx->blocks_head,size+a1);
  329. return p+((align-(((INT_PTR)p)&a1))&a1);
  330. }
  331. static void freeBlocks(llBlock **start);
  332. #define DECL_ASMFUNC(x) \
  333. void nseel_asm_##x(void); \
  334. void nseel_asm_##x##_end(void); \
  335. DECL_ASMFUNC(sin)
  336. DECL_ASMFUNC(cos)
  337. DECL_ASMFUNC(tan)
  338. DECL_ASMFUNC(1pdd)
  339. DECL_ASMFUNC(2pdd)
  340. DECL_ASMFUNC(2pdds)
  341. DECL_ASMFUNC(1pp)
  342. DECL_ASMFUNC(2pp)
  343. DECL_ASMFUNC(sqr)
  344. DECL_ASMFUNC(sqrt)
  345. DECL_ASMFUNC(log)
  346. DECL_ASMFUNC(log10)
  347. DECL_ASMFUNC(abs)
  348. DECL_ASMFUNC(min)
  349. DECL_ASMFUNC(max)
  350. DECL_ASMFUNC(sig)
  351. DECL_ASMFUNC(sign)
  352. DECL_ASMFUNC(band)
  353. DECL_ASMFUNC(bor)
  354. DECL_ASMFUNC(bnot)
  355. DECL_ASMFUNC(if)
  356. DECL_ASMFUNC(repeat)
  357. DECL_ASMFUNC(repeatwhile)
  358. DECL_ASMFUNC(equal)
  359. DECL_ASMFUNC(notequal)
  360. DECL_ASMFUNC(below)
  361. DECL_ASMFUNC(above)
  362. DECL_ASMFUNC(beloweq)
  363. DECL_ASMFUNC(aboveeq)
  364. DECL_ASMFUNC(assign)
  365. DECL_ASMFUNC(add)
  366. DECL_ASMFUNC(sub)
  367. DECL_ASMFUNC(add_op)
  368. DECL_ASMFUNC(sub_op)
  369. DECL_ASMFUNC(mul)
  370. DECL_ASMFUNC(div)
  371. DECL_ASMFUNC(mul_op)
  372. DECL_ASMFUNC(div_op)
  373. DECL_ASMFUNC(mod)
  374. DECL_ASMFUNC(mod_op)
  375. DECL_ASMFUNC(or)
  376. DECL_ASMFUNC(and)
  377. DECL_ASMFUNC(or_op)
  378. DECL_ASMFUNC(and_op)
  379. DECL_ASMFUNC(uplus)
  380. DECL_ASMFUNC(uminus)
  381. DECL_ASMFUNC(invsqrt)
  382. DECL_ASMFUNC(exec2)
  383. static void NSEEL_PProc_GRAM(void *data, int data_size, compileContext *ctx)
  384. {
  385. if (data_size>0) EEL_GLUE_set_immediate(data, ctx->gram_blocks);
  386. }
  387. static EEL_F g_signs[2]={1.0,-1.0};
  388. static EEL_F negativezeropointfive=-0.5f;
  389. static EEL_F onepointfive=1.5f;
  390. static EEL_F g_closefact = NSEEL_CLOSEFACTOR;
  391. static const EEL_F eel_zero=0.0, eel_one=1.0;
  392. //#if defined(_MSC_VER) && _MSC_VER >= 1400
  393. //static double __floor(double a) { return floor(a); }
  394. //#endif
  395. static double eel1band(double a, double b)
  396. {
  397. return (fabs(a)>g_closefact && fabs(b) > g_closefact) ? 1.0 : 0.0;
  398. }
  399. static double eel1bor(double a, double b)
  400. {
  401. return (fabs(a)>g_closefact || fabs(b) > g_closefact) ? 1.0 : 0.0;
  402. }
  403. static double eel1sigmoid(double x, double constraint)
  404. {
  405. double t = (1+exp(-x * (constraint)));
  406. return fabs(t)>g_closefact ? 1.0/t : 0;
  407. }
  408. EEL_F NSEEL_CGEN_CALL nseel_int_rand(EEL_F *f);
  409. static functionType fnTable1[] = {
  410. { "_if", nseel_asm_if,nseel_asm_if_end, 3, {&g_closefact} },
  411. { "_and", nseel_asm_band,nseel_asm_band_end, 2 } ,
  412. { "_or", nseel_asm_bor,nseel_asm_bor_end, 2 } ,
  413. { "loop", nseel_asm_repeat,nseel_asm_repeat_end, 2 },
  414. { "while", nseel_asm_repeatwhile,nseel_asm_repeatwhile_end, 1 },
  415. #ifdef __ppc__
  416. { "_not", nseel_asm_bnot,nseel_asm_bnot_end, 1, {&g_closefact,&eel_zero,&eel_one} } ,
  417. { "_equal", nseel_asm_equal,nseel_asm_equal_end, 2, {&g_closefact,&eel_zero, &eel_one} },
  418. { "_noteq", nseel_asm_notequal,nseel_asm_notequal_end, 2, {&g_closefact,&eel_one,&eel_zero} },
  419. { "_below", nseel_asm_below,nseel_asm_below_end, 2, {&eel_zero, &eel_one} },
  420. { "_above", nseel_asm_above,nseel_asm_above_end, 2, {&eel_zero, &eel_one} },
  421. { "_beleq", nseel_asm_beloweq,nseel_asm_beloweq_end, 2, {&eel_zero, &eel_one} },
  422. { "_aboeq", nseel_asm_aboveeq,nseel_asm_aboveeq_end, 2, {&eel_zero, &eel_one} },
  423. #else
  424. { "_not", nseel_asm_bnot,nseel_asm_bnot_end, 1, {&g_closefact} } ,
  425. { "_equal", nseel_asm_equal,nseel_asm_equal_end, 2, {&g_closefact} },
  426. { "_noteq", nseel_asm_notequal,nseel_asm_notequal_end, 2, {&g_closefact} },
  427. { "_below", nseel_asm_below,nseel_asm_below_end, 2 },
  428. { "_above", nseel_asm_above,nseel_asm_above_end, 2 },
  429. { "_beleq", nseel_asm_beloweq,nseel_asm_beloweq_end, 2 },
  430. { "_aboeq", nseel_asm_aboveeq,nseel_asm_aboveeq_end, 2 },
  431. #endif
  432. { "_set",nseel_asm_assign,nseel_asm_assign_end,2},
  433. { "_mod",nseel_asm_mod,nseel_asm_mod_end,2},
  434. { "_mulop",nseel_asm_mul_op,nseel_asm_mul_op_end,2},
  435. { "_divop",nseel_asm_div_op,nseel_asm_div_op_end,2},
  436. { "_orop",nseel_asm_or_op,nseel_asm_or_op_end,2},
  437. { "_andop",nseel_asm_and_op,nseel_asm_and_op_end,2},
  438. { "_addop",nseel_asm_add_op,nseel_asm_add_op_end,2},
  439. { "_subop",nseel_asm_sub_op,nseel_asm_sub_op_end,2},
  440. { "_modop",nseel_asm_mod_op,nseel_asm_mod_op_end,2},
  441. #ifdef __ppc__
  442. { "sin", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&sin} },
  443. { "cos", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&cos} },
  444. { "tan", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&tan} },
  445. #else
  446. { "sin", nseel_asm_sin,nseel_asm_sin_end, 1 },
  447. { "cos", nseel_asm_cos,nseel_asm_cos_end, 1 },
  448. { "tan", nseel_asm_tan,nseel_asm_tan_end, 1 },
  449. #endif
  450. { "asin", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&asin}, },
  451. { "acos", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&acos}, },
  452. { "atan", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&atan}, },
  453. { "atan2", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&atan2}, },
  454. { "sqr", nseel_asm_sqr,nseel_asm_sqr_end, 1 },
  455. #ifdef __ppc__
  456. { "sqrt", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&sqrt}, },
  457. #else
  458. { "sqrt", nseel_asm_sqrt,nseel_asm_sqrt_end, 1 },
  459. #endif
  460. { "pow", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&pow}, },
  461. { "_powop", nseel_asm_2pdds,nseel_asm_2pdds_end, 2, {&pow}, },
  462. { "exp", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&exp}, },
  463. #ifdef __ppc__
  464. { "log", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&log} },
  465. { "log10", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&log10} },
  466. #else
  467. { "log", nseel_asm_log,nseel_asm_log_end, 1, },
  468. { "log10", nseel_asm_log10,nseel_asm_log10_end, 1, },
  469. #endif
  470. { "abs", nseel_asm_abs,nseel_asm_abs_end, 1 },
  471. { "min", nseel_asm_min,nseel_asm_min_end, 2 },
  472. { "max", nseel_asm_max,nseel_asm_max_end, 2 },
  473. #ifdef __ppc__
  474. { "sign", nseel_asm_sign,nseel_asm_sign_end, 1, {&eel_zero}} ,
  475. #else
  476. { "sign", nseel_asm_sign,nseel_asm_sign_end, 1, {&g_signs}} ,
  477. #endif
  478. { "rand", nseel_asm_1pp,nseel_asm_1pp_end, 1, {&nseel_int_rand}, } ,
  479. //#if defined(_MSC_VER) && _MSC_VER >= 1400
  480. // { "floor", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&__floor} },
  481. //#else
  482. // { "floor", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&floor} },
  483. //#endif
  484. { "ceil", nseel_asm_1pdd,nseel_asm_1pdd_end, 1, {&ceil} },
  485. #ifdef __ppc__
  486. { "invsqrt", nseel_asm_invsqrt,nseel_asm_invsqrt_end, 1, },
  487. #else
  488. { "invsqrt", nseel_asm_invsqrt,nseel_asm_invsqrt_end, 1, {&negativezeropointfive, &onepointfive} },
  489. #endif
  490. { "sigmoid", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&eel1sigmoid}, },
  491. // these differ from _and/_or, they always evaluate both...
  492. { "band", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&eel1band}, },
  493. { "bor", nseel_asm_2pdd,nseel_asm_2pdd_end, 2, {&eel1bor}, },
  494. {"exec2",nseel_asm_exec2,nseel_asm_exec2_end,2},
  495. {"exec3",nseel_asm_exec2,nseel_asm_exec2_end,3},
  496. {"_mem",_asm_megabuf,_asm_megabuf_end,1,{&g_closefact,&__NSEEL_RAMAlloc},NSEEL_PProc_RAM},
  497. {"_gmem",_asm_megabuf,_asm_megabuf_end,1,{&g_closefact,&__NSEEL_RAMAllocGMEM},NSEEL_PProc_GRAM},
  498. {"freembuf",_asm_generic1parm,_asm_generic1parm_end,1,{&__NSEEL_RAM_MemFree},NSEEL_PProc_RAM},
  499. {"memcpy",_asm_generic3parm,_asm_generic3parm_end,3,{&__NSEEL_RAM_MemCpy},NSEEL_PProc_RAM},
  500. {"memset",_asm_generic3parm,_asm_generic3parm_end,3,{&__NSEEL_RAM_MemSet},NSEEL_PProc_RAM},
  501. };
  502. static functionType *fnTableUser;
  503. static int fnTableUser_size;
  504. functionType *nseel_getFunctionFromTable(int idx)
  505. {
  506. if (idx<0) return 0;
  507. if (idx>=sizeof(fnTable1)/sizeof(fnTable1[0]))
  508. {
  509. idx -= sizeof(fnTable1)/sizeof(fnTable1[0]);
  510. if (!fnTableUser || idx >= fnTableUser_size) return 0;
  511. return fnTableUser+idx;
  512. }
  513. return fnTable1+idx;
  514. }
  515. int NSEEL_init() // returns 0 on success
  516. {
  517. NSEEL_quit();
  518. return 0;
  519. }
  520. void NSEEL_addfunctionex2(const char *name, int nparms, char *code_startaddr, int code_len, void *pproc, void *fptr, void *fptr2)
  521. {
  522. if (!fnTableUser || !(fnTableUser_size&7))
  523. {
  524. fnTableUser=(functionType *)realloc(fnTableUser,(fnTableUser_size+8)*sizeof(functionType));
  525. }
  526. if (fnTableUser)
  527. {
  528. memset(&fnTableUser[fnTableUser_size],0,sizeof(functionType));
  529. fnTableUser[fnTableUser_size].nParams = nparms;
  530. fnTableUser[fnTableUser_size].name = name;
  531. fnTableUser[fnTableUser_size].afunc = code_startaddr;
  532. fnTableUser[fnTableUser_size].func_e = code_startaddr + code_len;
  533. fnTableUser[fnTableUser_size].pProc = (NSEEL_PPPROC) pproc;
  534. fnTableUser[fnTableUser_size].replptrs[0]=fptr;
  535. fnTableUser[fnTableUser_size].replptrs[1]=fptr2;
  536. fnTableUser_size++;
  537. }
  538. }
  539. void NSEEL_quit()
  540. {
  541. free(fnTableUser);
  542. fnTableUser_size=0;
  543. fnTableUser=0;
  544. }
  545. //---------------------------------------------------------------------------------------------------------------
  546. static void freeBlocks(llBlock **start)
  547. {
  548. llBlock *s=*start;
  549. *start=0;
  550. while (s)
  551. {
  552. llBlock *llB = s->next;
  553. #ifdef _WIN32
  554. VirtualFree(s, 0 /*LLB_DSIZE*/, MEM_RELEASE);
  555. #else
  556. free(s);
  557. #endif
  558. s=llB;
  559. }
  560. }
  561. //---------------------------------------------------------------------------------------------------------------
  562. static void *__newBlock(llBlock **start, int size)
  563. {
  564. llBlock *llb;
  565. int alloc_size;
  566. if (*start && (LLB_DSIZE - (*start)->sizeused) >= size)
  567. {
  568. void *t=(*start)->block+(*start)->sizeused;
  569. (*start)->sizeused+=(size+7)&~7;
  570. return t;
  571. }
  572. alloc_size=sizeof(llBlock);
  573. if ((int)size > LLB_DSIZE) alloc_size += size - LLB_DSIZE;
  574. #ifdef _WIN32
  575. llb = (llBlock *)VirtualAlloc(NULL, alloc_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  576. #else
  577. llb = (llBlock *)malloc(alloc_size); // grab bigger block if absolutely necessary (heh)
  578. #endif
  579. #if defined(EEL_USE_MPROTECT)
  580. {
  581. static int pagesize = 0;
  582. if (!pagesize)
  583. {
  584. pagesize=sysconf(_SC_PAGESIZE);
  585. if (!pagesize) pagesize=4096;
  586. }
  587. uintptr_t offs,eoffs;
  588. offs=((uintptr_t)llb)&~(pagesize-1);
  589. eoffs=((uintptr_t)llb + alloc_size + pagesize-1)&~(pagesize-1);
  590. mprotect((void*)offs,eoffs-offs,PROT_WRITE|PROT_READ|PROT_EXEC);
  591. }
  592. #endif
  593. llb->sizeused=(size+7)&~7;
  594. llb->next = *start;
  595. *start = llb;
  596. return llb->block;
  597. }
  598. //---------------------------------------------------------------------------------------------------------------
  599. INT_PTR nseel_createCompiledValue(compileContext *ctx, EEL_F value, EEL_F *addrValue)
  600. {
  601. unsigned char *block;
  602. block=(unsigned char *)newTmpBlock(GLUE_MOV_EAX_DIRECTVALUE_SIZE);
  603. if (addrValue == NULL)
  604. {
  605. *(addrValue = (EEL_F *)newBlock(sizeof(EEL_F),sizeof(EEL_F))) = value;
  606. ctx->l_stats[3]+=sizeof(EEL_F);
  607. }
  608. GLUE_MOV_EAX_DIRECTVALUE_GEN(block+4,(INT_PTR)addrValue);
  609. return ((INT_PTR)(block));
  610. }
  611. //---------------------------------------------------------------------------------------------------------------
  612. static void *nseel_getFunctionAddress(int fntype, int fn, int *size, NSEEL_PPPROC *pProc, void ***replList)
  613. {
  614. *replList=0;
  615. switch (fntype)
  616. {
  617. case MATH_SIMPLE:
  618. switch (fn)
  619. {
  620. case FN_ASSIGN:
  621. return GLUE_realAddress(nseel_asm_assign,nseel_asm_assign_end,size);
  622. case FN_ADD:
  623. return GLUE_realAddress(nseel_asm_add,nseel_asm_add_end,size);
  624. case FN_SUB:
  625. return GLUE_realAddress(nseel_asm_sub,nseel_asm_sub_end,size);
  626. case FN_MULTIPLY:
  627. return GLUE_realAddress(nseel_asm_mul,nseel_asm_mul_end,size);
  628. case FN_DIVIDE:
  629. return GLUE_realAddress(nseel_asm_div,nseel_asm_div_end,size);
  630. case FN_MODULO:
  631. return GLUE_realAddress(nseel_asm_exec2,nseel_asm_exec2_end,size);
  632. case FN_AND:
  633. return GLUE_realAddress(nseel_asm_and,nseel_asm_and_end,size);
  634. case FN_OR:
  635. return GLUE_realAddress(nseel_asm_or,nseel_asm_or_end,size);
  636. case FN_UPLUS:
  637. return GLUE_realAddress(nseel_asm_uplus,nseel_asm_uplus_end,size);
  638. case FN_UMINUS:
  639. return GLUE_realAddress(nseel_asm_uminus,nseel_asm_uminus_end,size);
  640. }
  641. case MATH_FN:
  642. {
  643. functionType *p=nseel_getFunctionFromTable(fn);
  644. if (p)
  645. {
  646. *replList=p->replptrs;
  647. *pProc=p->pProc;
  648. return GLUE_realAddress(p->afunc,p->func_e,size);
  649. }
  650. }
  651. }
  652. *size=0;
  653. return 0;
  654. }
  655. //---------------------------------------------------------------------------------------------------------------
  656. INT_PTR nseel_createCompiledFunction3(compileContext *ctx, int fntype, INT_PTR fn, INT_PTR code1, INT_PTR code2, INT_PTR code3)
  657. {
  658. int sizes1=((int *)code1)[0];
  659. int sizes2=((int *)code2)[0];
  660. int sizes3=((int *)code3)[0];
  661. if (fntype == MATH_FN && fn == 0) // special case: IF
  662. {
  663. void *func3;
  664. int size;
  665. INT_PTR *ptr;
  666. char *block;
  667. unsigned char *newblock2,*newblock3;
  668. unsigned char *p;
  669. p=newblock2=newBlock(sizes2+sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE,32);
  670. memcpy(p,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); p+=GLUE_FUNC_ENTER_SIZE;
  671. memcpy(p,(char*)code2+4,sizes2); p+=sizes2;
  672. memcpy(p,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); p+=GLUE_FUNC_LEAVE_SIZE;
  673. memcpy(p,&GLUE_RET,sizeof(GLUE_RET)); p+=sizeof(GLUE_RET);
  674. p=newblock3=newBlock(sizes3+sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE,32);
  675. memcpy(p,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); p+=GLUE_FUNC_ENTER_SIZE;
  676. memcpy(p,(char*)code3+4,sizes3); p+=sizes3;
  677. memcpy(p,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); p+=GLUE_FUNC_LEAVE_SIZE;
  678. memcpy(p,&GLUE_RET,sizeof(GLUE_RET)); p+=sizeof(GLUE_RET);
  679. ctx->l_stats[2]+=sizes2+sizes3+sizeof(GLUE_RET)*2;
  680. func3 = GLUE_realAddress(nseel_asm_if,nseel_asm_if_end,&size);
  681. block=(char *)newTmpBlock(sizes1+size);
  682. memcpy(block+4,(char*)code1+4,sizes1);
  683. ptr=(INT_PTR *)(block+4+sizes1);
  684. memcpy(ptr,func3,size);
  685. ptr=EEL_GLUE_set_immediate(ptr,&g_closefact);
  686. ptr=EEL_GLUE_set_immediate(ptr,newblock2);
  687. EEL_GLUE_set_immediate(ptr,newblock3);
  688. ctx->computTableTop++;
  689. return (INT_PTR)block;
  690. }
  691. else
  692. {
  693. int size2;
  694. unsigned char *block;
  695. unsigned char *outp;
  696. void *myfunc;
  697. NSEEL_PPPROC preProc=0;
  698. void **repl;
  699. myfunc = nseel_getFunctionAddress(fntype, fn, &size2, &preProc,&repl);
  700. block=(unsigned char *)newTmpBlock(size2+sizes1+sizes2+sizes3+
  701. sizeof(GLUE_PUSH_EAX) +
  702. sizeof(GLUE_PUSH_EAX) +
  703. sizeof(GLUE_POP_EBX) +
  704. sizeof(GLUE_POP_ECX));
  705. outp=block+4;
  706. memcpy(outp,(char*)code1+4,sizes1);
  707. outp+=sizes1;
  708. memcpy(outp,&GLUE_PUSH_EAX,sizeof(GLUE_PUSH_EAX)); outp+=sizeof(GLUE_PUSH_EAX);
  709. memcpy(outp,(char*)code2+4,sizes2);
  710. outp+=sizes2;
  711. memcpy(outp,&GLUE_PUSH_EAX,sizeof(GLUE_PUSH_EAX)); outp+=sizeof(GLUE_PUSH_EAX);
  712. memcpy(outp,(char*)code3+4,sizes3);
  713. outp+=sizes3;
  714. memcpy(outp,&GLUE_POP_EBX,sizeof(GLUE_POP_EBX)); outp+=sizeof(GLUE_POP_EBX);
  715. memcpy(outp,&GLUE_POP_ECX,sizeof(GLUE_POP_ECX)); outp+=sizeof(GLUE_POP_ECX);
  716. memcpy(outp,myfunc,size2);
  717. if (preProc) preProc(outp,size2,ctx);
  718. if (repl)
  719. {
  720. if (repl[0]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[0]);
  721. if (repl[1]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[1]);
  722. if (repl[2]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[2]);
  723. if (repl[3]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[3]);
  724. }
  725. ctx->computTableTop++;
  726. return ((INT_PTR)(block));
  727. }
  728. }
  729. //---------------------------------------------------------------------------------------------------------------
  730. INT_PTR nseel_createCompiledFunction2(compileContext *ctx, int fntype, INT_PTR fn, INT_PTR code1, INT_PTR code2)
  731. {
  732. int size2;
  733. unsigned char *outp;
  734. void *myfunc;
  735. int sizes1=((int *)code1)[0];
  736. int sizes2=((int *)code2)[0];
  737. if (fntype == MATH_FN && (fn == 1 || fn == 2 || fn == 3)) // special case: LOOP/BOR/BAND
  738. {
  739. void *func3;
  740. int size;
  741. INT_PTR *ptr;
  742. char *block;
  743. unsigned char *newblock2, *p;
  744. p=newblock2=newBlock(sizes2+sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE,32);
  745. memcpy(p,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); p+=GLUE_FUNC_ENTER_SIZE;
  746. memcpy(p,(char*)code2+4,sizes2); p+=sizes2;
  747. memcpy(p,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); p+=GLUE_FUNC_LEAVE_SIZE;
  748. memcpy(p,&GLUE_RET,sizeof(GLUE_RET)); p+=sizeof(GLUE_RET);
  749. ctx->l_stats[2]+=sizes2+2;
  750. if (fn == 1) func3 = GLUE_realAddress(nseel_asm_band,nseel_asm_band_end,&size);
  751. else if (fn == 3) func3 = GLUE_realAddress(nseel_asm_repeat,nseel_asm_repeat_end,&size);
  752. else func3 = GLUE_realAddress(nseel_asm_bor,nseel_asm_bor_end,&size);
  753. block=(char *)newTmpBlock(sizes1+size);
  754. memcpy(block+4,(char*)code1+4,sizes1);
  755. ptr=(INT_PTR *)(block+4+sizes1);
  756. memcpy(ptr,func3,size);
  757. if (fn!=3) ptr=EEL_GLUE_set_immediate(ptr,&g_closefact); // for or/and
  758. ptr=EEL_GLUE_set_immediate(ptr,newblock2);
  759. if (fn!=3) ptr=EEL_GLUE_set_immediate(ptr,&g_closefact); // for or/and
  760. #ifdef __ppc__
  761. if (fn!=3) // for or/and on ppc we need a one
  762. {
  763. ptr=EEL_GLUE_set_immediate(ptr,&eel_one);
  764. }
  765. #endif
  766. ctx->computTableTop++;
  767. return (INT_PTR)block;
  768. }
  769. {
  770. NSEEL_PPPROC preProc=0;
  771. unsigned char *block;
  772. void **repl;
  773. myfunc = nseel_getFunctionAddress(fntype, fn, &size2,&preProc,&repl);
  774. block=(unsigned char *)newTmpBlock(size2+sizes1+sizes2+sizeof(GLUE_PUSH_EAX)+sizeof(GLUE_POP_EBX));
  775. outp=block+4;
  776. memcpy(outp,(char*)code1+4,sizes1);
  777. outp+=sizes1;
  778. memcpy(outp,&GLUE_PUSH_EAX,sizeof(GLUE_PUSH_EAX)); outp+=sizeof(GLUE_PUSH_EAX);
  779. memcpy(outp,(char*)code2+4,sizes2);
  780. outp+=sizes2;
  781. memcpy(outp,&GLUE_POP_EBX,sizeof(GLUE_POP_EBX)); outp+=sizeof(GLUE_POP_EBX);
  782. memcpy(outp,myfunc,size2);
  783. if (preProc) preProc(outp,size2,ctx);
  784. if (repl)
  785. {
  786. if (repl[0]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[0]);
  787. if (repl[1]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[1]);
  788. if (repl[2]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[2]);
  789. if (repl[3]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[3]);
  790. }
  791. ctx->computTableTop++;
  792. return ((INT_PTR)(block));
  793. }
  794. }
  795. //---------------------------------------------------------------------------------------------------------------
  796. INT_PTR nseel_createCompiledFunction1(compileContext *ctx, int fntype, INT_PTR fn, INT_PTR code)
  797. {
  798. NSEEL_PPPROC preProc=0;
  799. int size,size2;
  800. char *block;
  801. void *myfunc;
  802. void *func1;
  803. size =((int *)code)[0];
  804. func1 = (void *)(code+4);
  805. if (fntype == MATH_FN && fn == 4) // special case: while
  806. {
  807. void *func3;
  808. INT_PTR *ptr;
  809. unsigned char *newblock2, *p;
  810. p=newblock2=newBlock(size+sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE,32);
  811. memcpy(p,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); p+=GLUE_FUNC_ENTER_SIZE;
  812. memcpy(p,func1,size); p+=size;
  813. memcpy(p,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); p+=GLUE_FUNC_LEAVE_SIZE;
  814. memcpy(p,&GLUE_RET,sizeof(GLUE_RET)); p+=sizeof(GLUE_RET);
  815. ctx->l_stats[2]+=size+2;
  816. func3 = GLUE_realAddress(nseel_asm_repeatwhile,nseel_asm_repeatwhile_end,&size);
  817. block=(char *)newTmpBlock(size);
  818. ptr = (INT_PTR *)(block+4);
  819. memcpy(ptr,func3,size);
  820. ptr=EEL_GLUE_set_immediate(ptr,newblock2);
  821. EEL_GLUE_set_immediate(ptr,&g_closefact);
  822. ctx->computTableTop++;
  823. return (INT_PTR)block;
  824. }
  825. {
  826. void **repl;
  827. myfunc = nseel_getFunctionAddress(fntype, fn, &size2,&preProc,&repl);
  828. block=(char *)newTmpBlock(size+size2);
  829. memcpy(block+4, func1, size);
  830. memcpy(block+size+4,myfunc,size2);
  831. if (preProc) preProc(block+size+4,size2,ctx);
  832. if (repl)
  833. {
  834. unsigned char *outp=(unsigned char *)block+size+4;
  835. if (repl[0]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[0]);
  836. if (repl[1]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[1]);
  837. if (repl[2]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[2]);
  838. if (repl[3]) outp=(unsigned char *)EEL_GLUE_set_immediate(outp,repl[3]);
  839. }
  840. ctx->computTableTop++;
  841. return ((INT_PTR)(block));
  842. }
  843. }
  844. static char *preprocessCode(compileContext *ctx, char *expression)
  845. {
  846. char *expression_start=expression;
  847. int len=0;
  848. int alloc_len=strlen(expression)+1+64;
  849. char *buf=(char *)malloc(alloc_len);
  850. int semicnt=0;
  851. // we need to call onCompileNewLine for each new line we get
  852. //onCompileNewLine(ctx,
  853. while (*expression)
  854. {
  855. if (len > alloc_len-64)
  856. {
  857. alloc_len = len+128;
  858. buf=(char*)realloc(buf,alloc_len);
  859. }
  860. if (expression[0] == '/')
  861. {
  862. if (expression[1] == '/')
  863. {
  864. expression+=2;
  865. while (expression[0] && expression[0] != '\n') expression++;
  866. continue;
  867. }
  868. else if (expression[1] == '*')
  869. {
  870. expression+=2;
  871. while (expression[0] && (expression[0] != '*' || expression[1] != '/'))
  872. {
  873. if (expression[0] == '\n') onCompileNewLine(ctx,expression+1-expression_start,len);
  874. expression++;
  875. }
  876. if (expression[0]) expression+=2; // at this point we KNOW expression[0]=* and expression[1]=/
  877. continue;
  878. }
  879. }
  880. if (expression[0] == '$')
  881. {
  882. if (toupper(expression[1]) == 'X')
  883. {
  884. char *p=expression+2;
  885. unsigned int v=strtoul(expression+2,&p,16);
  886. char tmp[64];
  887. expression=p;
  888. sprintf(tmp,"%u",v);
  889. memcpy(buf+len,tmp,strlen(tmp));
  890. len+=strlen(tmp);
  891. ctx->l_stats[0]+=strlen(tmp);
  892. continue;
  893. }
  894. if (expression[1]=='\'' && expression[2] && expression[3]=='\'')
  895. {
  896. char tmp[64];
  897. sprintf(tmp,"%u",((unsigned char *)expression)[2]);
  898. expression+=4;
  899. memcpy(buf+len,tmp,strlen(tmp));
  900. len+=strlen(tmp);
  901. ctx->l_stats[0]+=strlen(tmp);
  902. continue;
  903. }
  904. if (toupper(expression[1]) == 'P' && toupper(expression[2]) == 'I')
  905. {
  906. static char *str="3.141592653589793";
  907. expression+=3;
  908. memcpy(buf+len,str,17);
  909. len+=17; //strlen(str);
  910. ctx->l_stats[0]+=17;
  911. continue;
  912. }
  913. if (toupper(expression[1]) == 'E')
  914. {
  915. static char *str="2.71828183";
  916. expression+=2;
  917. memcpy(buf+len,str,10);
  918. len+=10; //strlen(str);
  919. ctx->l_stats[0]+=10;
  920. continue;
  921. }
  922. if (toupper(expression[1]) == 'P' && toupper(expression[2]) == 'H' && toupper(expression[3]) == 'I')
  923. {
  924. static char *str="1.61803399";
  925. expression+=4;
  926. memcpy(buf+len,str,10);
  927. len+=10; //strlen(str);
  928. ctx->l_stats[0]+=10;
  929. continue;
  930. }
  931. }
  932. {
  933. char c=*expression++;
  934. if (c == '\n') onCompileNewLine(ctx,expression-expression_start,len);
  935. if (isspace(c)) c=' ';
  936. if (c == '(') semicnt++;
  937. else if (c == ')') { semicnt--; if (semicnt < 0) semicnt=0; }
  938. else if (c == ';' && semicnt > 0)
  939. {
  940. // convert ; to % if next nonwhitespace char is alnum, otherwise convert to space
  941. int p=0;
  942. int nc;
  943. int commentstate=0;
  944. while ((nc=expression[p]))
  945. {
  946. if (!commentstate && nc == '/')
  947. {
  948. if (expression[p+1] == '/') commentstate=1;
  949. else if (expression[p+1] == '*') commentstate=2;
  950. }
  951. if (commentstate == 1 && nc == '\n') commentstate=0;
  952. else if (commentstate == 2 && nc == '*' && expression[p+1]=='/')
  953. {
  954. p++; // skip *
  955. commentstate=0;
  956. }
  957. else if (!commentstate && !isspace(nc)) break;
  958. p++;
  959. }
  960. // fucko, we should look for even more chars, me thinks
  961. if (nc && (isalnum(nc)
  962. #if 1
  963. || nc == '(' || nc == '_' || nc == '!' || nc == '$'
  964. #endif
  965. )) c='%';
  966. else c = ' '; // stray ;
  967. }
  968. #if 0
  969. else if (semicnt > 0 && c == ',')
  970. {
  971. int p=0;
  972. int nc;
  973. while ((nc=expression[p]) && isspace(nc)) p++;
  974. if (nc == ',' || nc == ')')
  975. {
  976. expression += p+1;
  977. buf[len++]=',';
  978. buf[len++]='0';
  979. c=nc; // append this char
  980. }
  981. }
  982. #endif
  983. // list of operators
  984. else if (!isspace(c) && !isalnum(c)) // check to see if this operator is ours
  985. {
  986. static char *symbollists[]=
  987. {
  988. "", // or any control char that is not parenthed
  989. ":(,;?%",
  990. ",):?;", // or || or &&
  991. ",);", // jf> removed :? from this, for =
  992. ",);",
  993. "", // only scans for a negative ] level
  994. };
  995. static struct
  996. {
  997. char op[2];
  998. char lscan,rscan;
  999. char *func;
  1000. } preprocSymbols[] =
  1001. {
  1002. {{'+','='}, 0, 3, "_addop" },
  1003. {{'-','='}, 0, 3, "_subop" },
  1004. {{'%','='}, 0, 3, "_modop" },
  1005. {{'|','='}, 0, 3, "_orop" },
  1006. {{'&','='}, 0, 3, "_andop"},
  1007. {{'/','='}, 0, 3, "_divop"},
  1008. {{'*','='}, 0, 3, "_mulop"},
  1009. {{'^','='}, 0, 3, "_powop"},
  1010. {{'=','='}, 1, 2, "_equal" },
  1011. {{'<','='}, 1, 2, "_beleq" },
  1012. {{'>','='}, 1, 2, "_aboeq" },
  1013. {{'<',0 }, 1, 2, "_below" },
  1014. {{'>',0 }, 1, 2, "_above" },
  1015. {{'!','='}, 1, 2, "_noteq" },
  1016. {{'|','|'}, 1, 2, "_or" },
  1017. {{'&','&'}, 1, 2, "_and" },
  1018. {{'=',0 }, 0, 3, "_set" },
  1019. {{'%',0}, 0, 0, "_mod" },
  1020. {{'^',0}, 0, 0, "pow" },
  1021. {{'[',0 }, 0, 5, },
  1022. {{'!',0 },-1, 0, }, // this should also ignore any leading +-
  1023. {{'?',0 }, 1, 4, },
  1024. };
  1025. int n;
  1026. int ns=sizeof(preprocSymbols)/sizeof(preprocSymbols[0]);
  1027. for (n = 0; n < ns; n++)
  1028. {
  1029. if (c == preprocSymbols[n].op[0] && (!preprocSymbols[n].op[1] || expression[0] == preprocSymbols[n].op[1]))
  1030. {
  1031. break;
  1032. }
  1033. }
  1034. if (n < ns)
  1035. {
  1036. int lscan=preprocSymbols[n].lscan;
  1037. int rscan=preprocSymbols[n].rscan;
  1038. // parse left side of =, scanning back for an unparenthed nonwhitespace nonalphanumeric nonparenth?
  1039. // so megabuf(x+y)= would be fine, x=, but +x= would do +set(x,)
  1040. char *l_ptr=0;
  1041. char *r_ptr=0;
  1042. if (lscan >= 0)
  1043. {
  1044. char *scan=symbollists[lscan];
  1045. int l_semicnt=0;
  1046. l_ptr=buf + len - 1;
  1047. while (l_ptr >= buf)
  1048. {
  1049. if (*l_ptr == ')') l_semicnt++;
  1050. else if (*l_ptr == '(')
  1051. {
  1052. l_semicnt--;
  1053. if (l_semicnt < 0) break;
  1054. }
  1055. else if (!l_semicnt)
  1056. {
  1057. if (!*scan)
  1058. {
  1059. if (!isspace(*l_ptr) && !isalnum(*l_ptr) && *l_ptr != '_' && *l_ptr != '.') break;
  1060. }
  1061. else
  1062. {
  1063. char *sc=scan;
  1064. if (lscan == 2 && ( // not currently used, even
  1065. (l_ptr[0]=='|' && l_ptr[1] == '|')||
  1066. (l_ptr[0]=='&' && l_ptr[1] == '&')
  1067. )
  1068. ) break;
  1069. while (*sc && *l_ptr != *sc) sc++;
  1070. if (*sc) break;
  1071. }
  1072. }
  1073. l_ptr--;
  1074. }
  1075. buf[len]=0;
  1076. l_ptr++;
  1077. len = l_ptr - buf;
  1078. l_ptr = strdup(l_ptr); // doesn't need to be preprocessed since it just was
  1079. }
  1080. if (preprocSymbols[n].op[1]) expression++;
  1081. r_ptr=expression;
  1082. {
  1083. // scan forward to an uncommented, unparenthed semicolon, comma, or )
  1084. int r_semicnt=0;
  1085. int r_qcnt=0;
  1086. char *scan=symbollists[rscan];
  1087. int commentstate=0;
  1088. int hashadch=0;
  1089. int bracketcnt=0;
  1090. while (*r_ptr)
  1091. {
  1092. if (!commentstate && *r_ptr == '/')
  1093. {
  1094. if (r_ptr[1] == '/') commentstate=1;
  1095. else if (r_ptr[1] == '*') commentstate=2;
  1096. }
  1097. if (commentstate == 1 && *r_ptr == '\n') commentstate=0;
  1098. else if (commentstate == 2 && *r_ptr == '*' && r_ptr[1]=='/')
  1099. {
  1100. r_ptr++; // skip *
  1101. commentstate=0;
  1102. }
  1103. else if (!commentstate)
  1104. {
  1105. if (*r_ptr == '(') {hashadch=1; r_semicnt++; }
  1106. else if (*r_ptr == ')')
  1107. {
  1108. r_semicnt--;
  1109. if (r_semicnt < 0) break;
  1110. }
  1111. else if (!r_semicnt)
  1112. {
  1113. char *sc=scan;
  1114. if (*r_ptr == ';' || *r_ptr == ',') break;
  1115. if (!rscan)
  1116. {
  1117. if (*r_ptr == ':') break;
  1118. if (!isspace(*r_ptr) && !isalnum(*r_ptr) && *r_ptr != '_' && *r_ptr != '.' && hashadch) break;
  1119. if (isalnum(*r_ptr) || *r_ptr == '_')hashadch=1;
  1120. }
  1121. else if (rscan == 2 &&
  1122. ((r_ptr[0]=='|' && r_ptr[1] == '|')||
  1123. (r_ptr[0]=='&' && r_ptr[1] == '&')
  1124. )
  1125. ) break;
  1126. else if (rscan == 3 || rscan == 4)
  1127. {
  1128. if (*r_ptr == ':') r_qcnt--;
  1129. else if (*r_ptr == '?') r_qcnt++;
  1130. if (r_qcnt < 3-rscan) break;
  1131. }
  1132. else if (rscan == 5)
  1133. {
  1134. if (*r_ptr == '[') bracketcnt++;
  1135. else if (*r_ptr == ']') bracketcnt--;
  1136. if (bracketcnt < 0) break;
  1137. }
  1138. while (*sc && *r_ptr != *sc) sc++;
  1139. if (*sc) break;
  1140. }
  1141. }
  1142. r_ptr++;
  1143. }
  1144. // expression -> r_ptr is our string (not including r_ptr)
  1145. {
  1146. char *orp=r_ptr;
  1147. char rps=*orp;
  1148. *orp=0; // temporarily terminate
  1149. r_ptr=preprocessCode(ctx,expression);
  1150. expression=orp;
  1151. *orp = rps; // fix termination(restore string)
  1152. }
  1153. }
  1154. if (r_ptr)
  1155. {
  1156. int thisl = strlen(l_ptr?l_ptr:"") + strlen(r_ptr) + 32;
  1157. if (len+thisl > alloc_len-64)
  1158. {
  1159. alloc_len = len+thisl+128;
  1160. buf=(char*)realloc(buf,alloc_len);
  1161. }
  1162. if (n == ns-3)
  1163. {
  1164. char *lp = l_ptr;
  1165. char *rp = r_ptr;
  1166. while (lp && *lp && isspace(*lp)) lp++;
  1167. while (rp && *rp && isspace(*rp)) rp++;
  1168. if (lp && !strncasecmp(lp,"gmem",4) && (!lp[4] || isspace(lp[4])))
  1169. {
  1170. len+=sprintf(buf+len,"_gmem(%s",r_ptr && *r_ptr ? r_ptr : "0");
  1171. ctx->l_stats[0]+=strlen(l_ptr)+4;
  1172. }
  1173. else if (rp && *rp && strcmp(rp,"0"))
  1174. {
  1175. len+=sprintf(buf+len,"_mem((%s)+(%s)",lp,rp);
  1176. ctx->l_stats[0]+=strlen(lp)+strlen(rp)+8;
  1177. }
  1178. else
  1179. {
  1180. len+=sprintf(buf+len,"_mem(%s",lp);
  1181. ctx->l_stats[0]+=strlen(lp)+4;
  1182. }
  1183. // skip the ]
  1184. if (*expression == ']') expression++;
  1185. }
  1186. else if (n == ns-2)
  1187. {
  1188. len+=sprintf(buf+len,"_not(%s",
  1189. r_ptr);
  1190. ctx->l_stats[0]+=4;
  1191. }
  1192. else if (n == ns-1)// if (l_ptr,r_ptr1,r_ptr2)
  1193. {
  1194. char *rptr2=r_ptr;
  1195. char *tmp=r_ptr;
  1196. int parcnt=0;
  1197. int qcnt=1;
  1198. while (*rptr2)
  1199. {
  1200. if (*rptr2 == '?') qcnt++;
  1201. else if (*rptr2 == ':') qcnt--;
  1202. else if (*rptr2 == '(') parcnt++;
  1203. else if (*rptr2 == ')') parcnt--;
  1204. if (parcnt < 0) break;
  1205. if (!parcnt && !qcnt && *rptr2 == ':') break;
  1206. rptr2++;
  1207. }
  1208. if (*rptr2) *rptr2++=0;
  1209. while (isspace(*rptr2)) rptr2++;
  1210. while (isspace(*tmp)) tmp++;
  1211. len+=sprintf(buf+len,"_if(%s,%s,%s",l_ptr,*tmp?tmp:"0",*rptr2?rptr2:"0");
  1212. ctx->l_stats[0]+=6;
  1213. }
  1214. else
  1215. {
  1216. len+=sprintf(buf+len,"%s(%s,%s",preprocSymbols[n].func,l_ptr?l_ptr:"",r_ptr);
  1217. ctx->l_stats[0]+=strlen(preprocSymbols[n].func)+2;
  1218. }
  1219. }
  1220. free(r_ptr);
  1221. free(l_ptr);
  1222. c = ')'; // close parenth below
  1223. }
  1224. }
  1225. // if (c != ' ' || (len && buf[len-1] != ' ')) // don't bother adding multiple spaces
  1226. {
  1227. buf[len++]=c;
  1228. if (c != ' ') ctx->l_stats[0]++;
  1229. }
  1230. }
  1231. }
  1232. buf[len]=0;
  1233. return buf;
  1234. }
  1235. #ifdef PPROC_TEST
  1236. int main(int argc, char* argv[])
  1237. {
  1238. compileContext ctx={0};
  1239. char *p=preprocessCode(&ctx,argv[1]);
  1240. if (p)printf("%s\n",p);
  1241. free(p);
  1242. return 0;
  1243. }
  1244. #endif
  1245. #if 0
  1246. static void movestringover(char *str, int amount)
  1247. {
  1248. char tmp[1024+8];
  1249. int l=(int)strlen(str);
  1250. l=min(1024-amount-1,l);
  1251. memcpy(tmp,str,l+1);
  1252. while (l >= 0 && tmp[l]!='\n') l--;
  1253. l++;
  1254. tmp[l]=0;//ensure we null terminate
  1255. memcpy(str+amount,tmp,l+1);
  1256. }
  1257. #endif
  1258. //------------------------------------------------------------------------------
  1259. NSEEL_CODEHANDLE NSEEL_code_compile(NSEEL_VMCTX _ctx, char *_expression, int lineoffs)
  1260. {
  1261. compileContext *ctx = (compileContext *)_ctx;
  1262. char *expression,*expression_start;
  1263. int computable_size=0;
  1264. codeHandleType *handle;
  1265. startPtr *scode=NULL;
  1266. startPtr *startpts=NULL;
  1267. if (!ctx) return 0;
  1268. ctx->last_error_string[0]=0;
  1269. if (!_expression || !*_expression) return 0;
  1270. freeBlocks((llBlock **)&ctx->tmpblocks_head); // free blocks
  1271. freeBlocks((llBlock **)&ctx->blocks_head); // free blocks
  1272. memset(ctx->l_stats,0,sizeof(ctx->l_stats));
  1273. free(ctx->compileLineRecs); ctx->compileLineRecs=0; ctx->compileLineRecs_size=0; ctx->compileLineRecs_alloc=0;
  1274. handle = (codeHandleType*)newBlock(sizeof(codeHandleType),8);
  1275. if (!handle)
  1276. {
  1277. return 0;
  1278. }
  1279. memset(handle,0,sizeof(codeHandleType));
  1280. expression_start=expression=preprocessCode(ctx,_expression);
  1281. while (*expression)
  1282. {
  1283. void *startptr;
  1284. char *expr;
  1285. ctx->colCount=0;
  1286. ctx->computTableTop=0;
  1287. // single out segment
  1288. while (*expression == ';' || isspace(*expression)) expression++;
  1289. if (!*expression) break;
  1290. expr=expression;
  1291. while (*expression && *expression != ';') expression++;
  1292. if (*expression) *expression++ = 0;
  1293. // parse
  1294. startptr=nseel_compileExpression(ctx,expr);
  1295. if (ctx->computTableTop > NSEEL_MAX_TEMPSPACE_ENTRIES- /* safety */ 16 - /* alignment */4 ||
  1296. !startptr)
  1297. {
  1298. int byteoffs = expr - expression_start;
  1299. int destoffs,linenumber;
  1300. char buf[21], *p;
  1301. int x,le;
  1302. #ifdef NSEEL_EEL1_COMPAT_MODE
  1303. if (!startptr) continue;
  1304. #endif
  1305. if (ctx->errVar > 0) byteoffs += ctx->errVar;
  1306. linenumber=findByteOffsetInSource(ctx,byteoffs,&destoffs);
  1307. if (destoffs < 0) destoffs=0;
  1308. le=strlen(_expression);
  1309. if (destoffs >= le) destoffs=le;
  1310. p= _expression + destoffs;
  1311. for (x = 0;x < 20; x ++)
  1312. {
  1313. if (!*p || *p == '\r' || *p == '\n') break;
  1314. buf[x]=*p++;
  1315. }
  1316. buf[x]=0;
  1317. sprintf(ctx->last_error_string,"Around line %d '%s'",linenumber+lineoffs,buf);
  1318. ctx->last_error_string[sizeof(ctx->last_error_string)-1]=0;
  1319. scode=NULL;
  1320. break;
  1321. }
  1322. if (computable_size < ctx->computTableTop)
  1323. {
  1324. computable_size=ctx->computTableTop;
  1325. }
  1326. {
  1327. startPtr *tmp=(startPtr*) __newBlock((llBlock **)&ctx->tmpblocks_head,sizeof(startPtr));
  1328. if (!tmp) break;
  1329. tmp->startptr = startptr;
  1330. tmp->next=NULL;
  1331. if (!scode) scode=startpts=tmp;
  1332. else
  1333. {
  1334. scode->next=tmp;
  1335. scode=tmp;
  1336. }
  1337. }
  1338. }
  1339. free(ctx->compileLineRecs); ctx->compileLineRecs=0; ctx->compileLineRecs_size=0; ctx->compileLineRecs_alloc=0;
  1340. // check to see if failed on the first startingCode
  1341. if (!scode)
  1342. {
  1343. handle=NULL; // return NULL (after resetting blocks_head)
  1344. }
  1345. else
  1346. {
  1347. char *tabptr = (char *)(handle->workTable=calloc(computable_size+64, sizeof(EEL_F)));
  1348. unsigned char *writeptr;
  1349. startPtr *p=startpts;
  1350. int size=sizeof(GLUE_RET)+GLUE_FUNC_ENTER_SIZE+GLUE_FUNC_LEAVE_SIZE; // for ret at end :)
  1351. if (((INT_PTR)tabptr)&31)
  1352. tabptr += 32-(((INT_PTR)tabptr)&31);
  1353. // now we build one big code segment out of our list of them, inserting a mov esi, computable before each item
  1354. while (p)
  1355. {
  1356. size += GLUE_RESET_ESI(NULL,0);
  1357. size+=*(int *)p->startptr;
  1358. p=p->next;
  1359. }
  1360. handle->code = newBlock(size,32);
  1361. if (handle->code)
  1362. {
  1363. writeptr=(unsigned char *)handle->code;
  1364. memcpy(writeptr,&GLUE_FUNC_ENTER,GLUE_FUNC_ENTER_SIZE); writeptr += GLUE_FUNC_ENTER_SIZE;
  1365. p=startpts;
  1366. while (p)
  1367. {
  1368. int thissize=*(int *)p->startptr;
  1369. writeptr+=GLUE_RESET_ESI(writeptr,tabptr);
  1370. //memcpy(writeptr,&GLUE_MOV_ESI_EDI,sizeof(GLUE_MOV_ESI_EDI));
  1371. //writeptr+=sizeof(GLUE_MOV_ESI_EDI);
  1372. memcpy(writeptr,(char*)p->startptr + 4,thissize);
  1373. writeptr += thissize;
  1374. p=p->next;
  1375. }
  1376. memcpy(writeptr,&GLUE_FUNC_LEAVE,GLUE_FUNC_LEAVE_SIZE); writeptr += GLUE_FUNC_LEAVE_SIZE;
  1377. memcpy(writeptr,&GLUE_RET,sizeof(GLUE_RET)); writeptr += sizeof(GLUE_RET);
  1378. ctx->l_stats[1]=size;
  1379. }
  1380. handle->blocks = ctx->blocks_head;
  1381. ctx->blocks_head=0;
  1382. }
  1383. freeBlocks((llBlock **)&ctx->tmpblocks_head); // free blocks
  1384. freeBlocks((llBlock **)&ctx->blocks_head); // free blocks
  1385. if (handle)
  1386. {
  1387. memcpy(handle->code_stats,ctx->l_stats,sizeof(ctx->l_stats));
  1388. nseel_evallib_stats[0]+=ctx->l_stats[0];
  1389. nseel_evallib_stats[1]+=ctx->l_stats[1];
  1390. nseel_evallib_stats[2]+=ctx->l_stats[2];
  1391. nseel_evallib_stats[3]+=ctx->l_stats[3];
  1392. nseel_evallib_stats[4]++;
  1393. }
  1394. memset(ctx->l_stats,0,sizeof(ctx->l_stats));
  1395. free(expression_start);
  1396. return (NSEEL_CODEHANDLE)handle;
  1397. }
  1398. //------------------------------------------------------------------------------
  1399. void NSEEL_code_execute(NSEEL_CODEHANDLE code)
  1400. {
  1401. INT_PTR tabptr;
  1402. INT_PTR codeptr;
  1403. codeHandleType *h = (codeHandleType *)code;
  1404. if (!h || !h->code) return;
  1405. codeptr = (INT_PTR) h->code;
  1406. #if 0
  1407. {
  1408. unsigned int *p=(unsigned int *)codeptr;
  1409. while (*p != GLUE_RET[0])
  1410. {
  1411. printf("instr:%04X:%04X\n",*p>>16,*p&0xffff);
  1412. p++;
  1413. }
  1414. }
  1415. #endif
  1416. tabptr=(INT_PTR)h->workTable;
  1417. if (tabptr&31)
  1418. tabptr += 32-((tabptr)&31);
  1419. //printf("calling code!\n");
  1420. GLUE_CALL_CODE(tabptr,codeptr);
  1421. }
  1422. char *NSEEL_code_getcodeerror(NSEEL_VMCTX ctx)
  1423. {
  1424. compileContext *c=(compileContext *)ctx;
  1425. if (ctx && c->last_error_string[0]) return c->last_error_string;
  1426. return 0;
  1427. }
  1428. //------------------------------------------------------------------------------
  1429. void NSEEL_code_free(NSEEL_CODEHANDLE code)
  1430. {
  1431. codeHandleType *h = (codeHandleType *)code;
  1432. if (h != NULL)
  1433. {
  1434. free(h->workTable);
  1435. nseel_evallib_stats[0]-=h->code_stats[0];
  1436. nseel_evallib_stats[1]-=h->code_stats[1];
  1437. nseel_evallib_stats[2]-=h->code_stats[2];
  1438. nseel_evallib_stats[3]-=h->code_stats[3];
  1439. nseel_evallib_stats[4]--;
  1440. freeBlocks(&h->blocks);
  1441. }
  1442. }
  1443. //------------------------------------------------------------------------------
  1444. void NSEEL_VM_resetvars(NSEEL_VMCTX _ctx)
  1445. {
  1446. if (_ctx)
  1447. {
  1448. compileContext *ctx=(compileContext *)_ctx;
  1449. int x;
  1450. if (ctx->varTable_Names || ctx->varTable_Values) for (x = 0; x < ctx->varTable_numBlocks; x ++)
  1451. {
  1452. if (ctx->varTable_Names) free(ctx->varTable_Names[x]);
  1453. if (ctx->varTable_Values) free(ctx->varTable_Values[x]);
  1454. }
  1455. free(ctx->varTable_Values);
  1456. free(ctx->varTable_Names);
  1457. ctx->varTable_Values=0;
  1458. ctx->varTable_Names=0;
  1459. ctx->varTable_numBlocks=0;
  1460. }
  1461. }
  1462. NSEEL_VMCTX NSEEL_VM_alloc() // return a handle
  1463. {
  1464. compileContext *ctx=calloc(1,sizeof(compileContext));
  1465. return ctx;
  1466. }
  1467. void NSEEL_VM_free(NSEEL_VMCTX _ctx) // free when done with a VM and ALL of its code have been freed, as well
  1468. {
  1469. if (_ctx)
  1470. {
  1471. compileContext *ctx=(compileContext *)_ctx;
  1472. NSEEL_VM_resetvars(_ctx);
  1473. NSEEL_VM_freeRAM(_ctx);
  1474. freeBlocks((llBlock **)&ctx->tmpblocks_head); // free blocks
  1475. freeBlocks((llBlock **)&ctx->blocks_head); // free blocks
  1476. free(ctx->compileLineRecs);
  1477. free(ctx);
  1478. }
  1479. }
  1480. int *NSEEL_code_getstats(NSEEL_CODEHANDLE code)
  1481. {
  1482. codeHandleType *h = (codeHandleType *)code;
  1483. if (h)
  1484. {
  1485. return h->code_stats;
  1486. }
  1487. return 0;
  1488. }
  1489. void NSEEL_VM_SetCustomFuncThis(NSEEL_VMCTX ctx, void *thisptr)
  1490. {
  1491. if (ctx)
  1492. {
  1493. compileContext *c=(compileContext*)ctx;
  1494. c->caller_this=thisptr;
  1495. }
  1496. }
  1497. void NSEEL_PProc_RAM(void *data, int data_size, compileContext *ctx)
  1498. {
  1499. if (data_size>0) EEL_GLUE_set_immediate(data, &ctx->ram_blocks);
  1500. }
  1501. void NSEEL_PProc_THIS(void *data, int data_size, compileContext *ctx)
  1502. {
  1503. if (data_size>0) EEL_GLUE_set_immediate(data, ctx->caller_this);
  1504. }