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