fixed: milkdrop would crash and burn in debug compiles
[vuplus_xbmc] / xbmc / visualizations / Milkdrop / vis_milkdrop / evallib / Compiler.c
1 /*\r
2   LICENSE\r
3   -------\r
4 Copyright 2005 Nullsoft, Inc.\r
5 All rights reserved.\r
6 \r
7 Redistribution and use in source and binary forms, with or without modification, \r
8 are permitted provided that the following conditions are met:\r
9 \r
10   * Redistributions of source code must retain the above copyright notice,\r
11     this list of conditions and the following disclaimer. \r
12 \r
13   * Redistributions in binary form must reproduce the above copyright notice,\r
14     this list of conditions and the following disclaimer in the documentation\r
15     and/or other materials provided with the distribution. \r
16 \r
17   * Neither the name of Nullsoft nor the names of its contributors may be used to \r
18     endorse or promote products derived from this software without specific prior written permission. \r
19  \r
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR \r
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \r
22 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \r
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\r
26 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT \r
27 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 \r
29 */\r
30 #include <windows.h>\r
31 //#include <xtl.h>\r
32 #include <stdio.h>\r
33 #include <math.h>\r
34 #include "Compiler.h"\r
35 #include "eval.h"\r
36 \r
37 #define LLB_DSIZE (65536-64)\r
38 typedef struct _llBlock {\r
39         struct _llBlock *next;\r
40   int sizeused;\r
41         char block[LLB_DSIZE];\r
42 } llBlock;\r
43 \r
44 typedef struct _startPtr {\r
45   struct _startPtr *next;\r
46   void *startptr;\r
47 } startPtr;\r
48 \r
49 typedef struct {\r
50         llBlock *blocks;\r
51   startPtr *startpts;\r
52         } codeHandleType;\r
53 \r
54 static llBlock *blocks_head = NULL;\r
55 \r
56 double computTable[16384];\r
57 double *nextBlock=computTable;\r
58 \r
59 extern CRITICAL_SECTION g_eval_cs;\r
60 \r
61 static void *newBlock(int size);\r
62 static void freeBlocks(llBlock *start);\r
63 \r
64 \r
65 void _asm_sin(void);\r
66 void _asm_cos(void);\r
67 void _asm_tan(void);\r
68 void _asm_int(void);\r
69 void _asm_asin(void);\r
70 void _asm_acos(void);\r
71 void _asm_atan(void);\r
72 void _asm_atan2(void);\r
73 void _asm_sqr(void);\r
74 void _asm_sqrt(void);\r
75 void _asm_pow(void);\r
76 void _asm_exp(void);\r
77 void _asm_log(void);\r
78 void _asm_log10(void);\r
79 void _asm_abs(void);\r
80 void _asm_min(void);\r
81 void _asm_max(void);\r
82 void _asm_sig(void);\r
83 void _asm_sign(void);\r
84 void _asm_rand(void);\r
85 void _asm_band(void);\r
86 void _asm_bor(void);\r
87 void _asm_bnot(void);\r
88 void _asm_if(void);\r
89 void _asm_equal(void);\r
90 void _asm_below(void);\r
91 void _asm_above(void);\r
92 void _asm_assign(void);\r
93 void _asm_add(void);\r
94 void _asm_sub(void);\r
95 void _asm_mul(void);\r
96 void _asm_div(void);\r
97 void _asm_mod(void);\r
98 void _asm_or(void);\r
99 void _asm_and(void);\r
100 void _asm_uplus(void);\r
101 void _asm_uminus(void);\r
102 void _asm_function3(void);\r
103 void _asm_function3_end(void);\r
104 void _asm_function2(void);\r
105 void _asm_function2_end(void);\r
106 void _asm_function1(void);\r
107 void _asm_function1_end(void);\r
108 void _asm_simpleValue(void);\r
109 void _asm_simpleValue_end(void);\r
110 \r
111 functionType fnTable[27] = {{ "sin",   _asm_sin,   1 },\r
112                            { "cos",    _asm_cos,   1 },\r
113                            { "tan",    _asm_tan,   1 },\r
114                            { "int",    _asm_int,   1 },\r
115                            { "asin",   _asm_asin,  1 },\r
116                            { "acos",   _asm_acos,  1 },\r
117                            { "atan",   _asm_atan,  1 },\r
118                            { "atan2",  _asm_atan2, 2 },\r
119                            { "sqr",    _asm_sqr,   1 },\r
120                            { "sqrt",   _asm_sqrt,  1 },\r
121                            { "pow",    _asm_pow,   2 },\r
122                            { "exp",    _asm_exp,   1 },\r
123                            { "log",    _asm_log,   1 },\r
124                            { "log10",  _asm_log10, 1 },\r
125                            { "abs",    _asm_abs,   1 },\r
126                            { "min",    _asm_min,   2 },\r
127                            { "max",    _asm_max,   2 },\r
128                                                                                                          { "sigmoid",_asm_sig,   2 } ,\r
129                                                                                                          { "sign",   _asm_sign,  1 } ,\r
130                                                                                                          { "rand",   _asm_rand,  1 } ,\r
131                                                                                                          { "band",   _asm_band,  2 } ,\r
132                                                                                                          { "bor",    _asm_bor,   2 } ,\r
133                                                                                                          { "bnot",   _asm_bnot,  1 } ,\r
134                                                                                                          { "if",     _asm_if,    3 },\r
135                                                                                                          { "equal",  _asm_equal, 2 },\r
136                                                                                                          { "below",  _asm_below, 2 },\r
137                                                                                                          { "above",  _asm_above, 2 },\r
138                            };\r
139 \r
140 \r
141 //---------------------------------------------------------------------------------------------------------------\r
142 void *realAddress(void *fn)\r
143 {\r
144 #if defined(_DEBUG) && 0\r
145   // if this ever is needed, it should check that, the the data\r
146   // is of the expected jump format before assuming it is so\r
147         // Debug Mode\r
148         char *ptr = (char *)fn;\r
149         ptr += (*(int *)((ptr+1))+5);\r
150         return ptr;\r
151 #else\r
152   // Release Mode\r
153         return fn;\r
154 #endif\r
155 }\r
156 \r
157 //#define realAddress(a) a\r
158 \r
159 //---------------------------------------------------------------------------------------------------------------\r
160 static void freeBlocks(llBlock *start)\r
161 {\r
162   while (start)\r
163         {\r
164     llBlock *llB = start->next;\r
165     GlobalFree(start);\r
166           start=llB;\r
167         }\r
168 }\r
169 \r
170 //---------------------------------------------------------------------------------------------------------------\r
171 static void *newBlock(int size)\r
172 {\r
173   llBlock *llb;\r
174   int alloc_size;\r
175   if (blocks_head && (LLB_DSIZE - blocks_head->sizeused) >= size)\r
176   {\r
177     void *t=blocks_head->block+blocks_head->sizeused;\r
178     blocks_head->sizeused+=size;\r
179     return t;\r
180   }\r
181   alloc_size=sizeof(llBlock);\r
182   if ((int)size > LLB_DSIZE) alloc_size += size - LLB_DSIZE;\r
183   llb = (llBlock *)GlobalAlloc(GMEM_FIXED,alloc_size); // grab bigger block if absolutely necessary (heh)\r
184   llb->sizeused=size;\r
185   llb->next = blocks_head;  \r
186   blocks_head = llb;\r
187   return llb->block;\r
188 }\r
189 \r
190 //---------------------------------------------------------------------------------------------------------------\r
191 static int *findFBlock(char *p)\r
192 {\r
193   while (*(int *)p != 0xFFFFFFFF) p++;\r
194   return (int*)p;\r
195 }\r
196 \r
197 \r
198 //---------------------------------------------------------------------------------------------------------------\r
199 int createCompiledValue(double value, double *addrValue)\r
200 {\r
201   int size;\r
202   char *block;\r
203   double *dupValue;\r
204   int i =0;\r
205   char *p;\r
206   char txt[512];\r
207 \r
208   //size=(int)_asm_simpleValue_end-(int)_asm_simpleValue;\r
209   size = 0x10;\r
210   block=(char *)newBlock(size);\r
211 \r
212   if (addrValue == NULL)\r
213           *(dupValue = (double *)newBlock(sizeof(double))) = value;\r
214   else\r
215           dupValue = addrValue;\r
216 \r
217   memcpy(block, realAddress(_asm_simpleValue), size);\r
218 \r
219   p = block;\r
220   while (*(int *)p != 0xFFFFFFFF)\r
221   {\r
222           txt[i++] = *p;\r
223           p++;\r
224   };\r
225   txt[i] = 0;\r
226 \r
227   *findFBlock(block)=(int)dupValue;\r
228 \r
229   return ((int)(block));\r
230 \r
231 }\r
232 \r
233 //---------------------------------------------------------------------------------------------------------------\r
234 int getFunctionAddress(int fntype, int fn)\r
235 {\r
236   switch (fntype)\r
237         {\r
238         case MATH_SIMPLE:\r
239                 switch (fn)\r
240                         {\r
241                           case FN_ASSIGN:\r
242                                   return (int)realAddress(_asm_assign);\r
243                           case FN_ADD:\r
244                                   return (int)realAddress(_asm_add);\r
245                           case FN_SUB:\r
246                                   return (int)realAddress(_asm_sub);\r
247                           case FN_MULTIPLY:\r
248                                   return (int)realAddress(_asm_mul);\r
249                           case FN_DIVIDE:\r
250                                   return (int)realAddress(_asm_div);\r
251                           case FN_MODULO:\r
252                                   return (int)realAddress(_asm_mod);\r
253                           case FN_AND:\r
254                                   return (int)realAddress(_asm_and);\r
255                           case FN_OR:\r
256                                   return (int)realAddress(_asm_or);\r
257                           case FN_UPLUS:\r
258                                   return (int)realAddress(_asm_uplus);\r
259                           case FN_UMINUS:\r
260                                   return (int)realAddress(_asm_uminus);\r
261                         }\r
262           case MATH_FN:\r
263                   return (int)realAddress(fnTable[fn].afunc);\r
264         }               \r
265   return 0;\r
266 }\r
267 \r
268 \r
269 //---------------------------------------------------------------------------------------------------------------\r
270 int createCompiledFunction3(int fntype, int fn, int code1, int code2, int code3)\r
271 {\r
272   int *p;\r
273   int size;\r
274   char *block;\r
275 \r
276 //  size=(int)_asm_function3_end-(int)_asm_function3;\r
277   size = 0x30;\r
278   block=(char *)newBlock(size);\r
279 \r
280   memcpy(block, realAddress(_asm_function3), size);\r
281 \r
282   p=findFBlock(block); *p++=code1;\r
283   p=findFBlock((char*)p); *p++=code2;\r
284   p=findFBlock((char*)p); *p++=code3;\r
285   p=findFBlock((char*)p); *p++=getFunctionAddress(fntype, fn);\r
286 \r
287   return ((int)(block));\r
288 }\r
289 \r
290 //---------------------------------------------------------------------------------------------------------------\r
291 int createCompiledFunction2(int fntype, int fn, int code1, int code2)\r
292 {\r
293   int *p;\r
294   int size;\r
295   char *block;\r
296 \r
297 //  size=(int)_asm_function2_end-(int)_asm_function2;\r
298         size = 0x20;\r
299   block=(char *)newBlock(size);\r
300 \r
301   memcpy(block, realAddress(_asm_function2), size);\r
302 \r
303   p=findFBlock(block); *p++=code1;\r
304   p=findFBlock((char*)p); *p++=code2;\r
305   p=findFBlock((char*)p); *p++=getFunctionAddress(fntype, fn);\r
306 \r
307   return ((int)(block));\r
308 }\r
309 \r
310 \r
311 //---------------------------------------------------------------------------------------------------------------\r
312 int createCompiledFunction1(int fntype, int fn, int code)\r
313 {\r
314   int size;\r
315   int *p;\r
316   char *block;\r
317 \r
318 //  size=(int)_asm_function1_end-(int)_asm_function1;\r
319   size = 0x20;\r
320   block=(char *)newBlock(size);\r
321 \r
322   memcpy(block, realAddress(_asm_function1), size);\r
323 \r
324   p=findFBlock(block); *p++=code;\r
325   p=findFBlock((char*)p); *p++=getFunctionAddress(fntype, fn);\r
326 \r
327   return ((int)(block));\r
328 }\r
329 \r
330 //------------------------------------------------------------------------------\r
331 int compileCode(char *expression)\r
332 {\r
333   char expr[4096];\r
334   codeHandleType *handle;\r
335   startPtr *scode=NULL;\r
336   blocks_head=0;\r
337 \r
338   if (!expression || !*expression) return 0;\r
339   if (!varTable) return 0;\r
340 \r
341   handle = (codeHandleType*)newBlock(sizeof(codeHandleType));\r
342 \r
343   if (!handle) return 0;\r
344   \r
345   memset(handle,0,sizeof(codeHandleType));\r
346 \r
347   while (*expression)\r
348         {\r
349     startPtr *tmp;\r
350     char *expr_ptr;\r
351     int l=4095;\r
352     colCount=0;\r
353 \r
354     // single out segment\r
355     while (*expression == ';' || *expression == ' ' || *expression == '\n' || \r
356            *expression == '\r' || *expression == '\t') expression++;\r
357     if (!*expression) break;\r
358     expr_ptr = expr;\r
359           while (l-->0) \r
360     {\r
361       int a=*expression;\r
362       if (a) expression++;\r
363       if (!a || a == ';') break;\r
364       if (a == '\n' || a=='\r' || a=='\t') a=' ';\r
365       *expr_ptr++ = a;\r
366     }\r
367           *expr_ptr = 0;\r
368 \r
369     // parse\r
370     tmp=(startPtr*) newBlock(sizeof(startPtr));\r
371     if (!tmp) break;\r
372     tmp->startptr=compileExpression(expr);\r
373     if (!tmp->startptr) { scode=NULL; break; }\r
374     tmp->next=NULL;\r
375     if (!scode) scode=handle->startpts=tmp;\r
376     else\r
377     {\r
378       scode->next=tmp;\r
379       scode=tmp;\r
380     }\r
381   }\r
382 \r
383   // check to see if failed on the first startingCode\r
384   if (!scode)\r
385   {\r
386     freeBlocks(blocks_head);  // free blocks\r
387     handle=NULL;              // return NULL (after resetting blocks_head)\r
388   }\r
389   else handle->blocks = blocks_head;\r
390 \r
391   blocks_head=0;\r
392 \r
393   return (int)handle;\r
394 }\r
395 \r
396 //------------------------------------------------------------------------------\r
397 void executeCode(int handle)\r
398 {\r
399   codeHandleType *h = (codeHandleType *)handle;\r
400   startPtr *p;\r
401   if (!h) return;\r
402 //  EnterCriticalSection(&g_eval_cs);\r
403   p=h->startpts;\r
404   while (p)\r
405   {\r
406     void *startPoint=p->startptr;\r
407     if (!startPoint) break;\r
408     p=p->next;\r
409           nextBlock=computTable;\r
410     __asm pusha // Lets cover our ass\r
411     __asm call startPoint\r
412     __asm popa\r
413   }\r
414 //  LeaveCriticalSection(&g_eval_cs);\r
415 }\r
416 \r
417 //------------------------------------------------------------------------------\r
418 void freeCode(int handle)\r
419 {\r
420   codeHandleType *h = (codeHandleType *)handle;\r
421   if (h != NULL)\r
422   {\r
423     freeBlocks(h->blocks);\r
424   }\r
425 }\r
426 \r