configure.ac: Add checks for Flex/Yacc/Bison and other furry animals, for the new...
[platform/upstream/gst-plugins-good.git] / gst / goom / goomsl.c
1 #include <math.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include "goomsl.h"
6 #include "goomsl_private.h"
7 #include "goomsl_yacc.h"
8
9 /*#define TRACE_SCRIPT*/
10
11  /* {{{ definition of the instructions number */
12 #define INSTR_SETI_VAR_INTEGER     1
13 #define INSTR_SETI_VAR_VAR         2
14 #define INSTR_SETF_VAR_FLOAT       3
15 #define INSTR_SETF_VAR_VAR         4
16 #define INSTR_NOP                  5
17 /* #define INSTR_JUMP              6 */
18 #define INSTR_SETP_VAR_PTR         7
19 #define INSTR_SETP_VAR_VAR         8
20 #define INSTR_SUBI_VAR_INTEGER     9
21 #define INSTR_SUBI_VAR_VAR         10
22 #define INSTR_SUBF_VAR_FLOAT       11
23 #define INSTR_SUBF_VAR_VAR         12
24 #define INSTR_ISLOWERF_VAR_VAR     13
25 #define INSTR_ISLOWERF_VAR_FLOAT   14
26 #define INSTR_ISLOWERI_VAR_VAR     15
27 #define INSTR_ISLOWERI_VAR_INTEGER 16
28 #define INSTR_ADDI_VAR_INTEGER     17
29 #define INSTR_ADDI_VAR_VAR         18
30 #define INSTR_ADDF_VAR_FLOAT       19
31 #define INSTR_ADDF_VAR_VAR         20
32 #define INSTR_MULI_VAR_INTEGER     21
33 #define INSTR_MULI_VAR_VAR         22
34 #define INSTR_MULF_VAR_FLOAT       23
35 #define INSTR_MULF_VAR_VAR         24
36 #define INSTR_DIVI_VAR_INTEGER     25
37 #define INSTR_DIVI_VAR_VAR         26
38 #define INSTR_DIVF_VAR_FLOAT       27
39 #define INSTR_DIVF_VAR_VAR         28
40 /* #define INSTR_JZERO             29 */
41 #define INSTR_ISEQUALP_VAR_VAR     30
42 #define INSTR_ISEQUALP_VAR_PTR     31
43 #define INSTR_ISEQUALI_VAR_VAR     32
44 #define INSTR_ISEQUALI_VAR_INTEGER 33
45 #define INSTR_ISEQUALF_VAR_VAR     34
46 #define INSTR_ISEQUALF_VAR_FLOAT   35
47 /* #define INSTR_CALL              36 */
48 /* #define INSTR_RET               37 */
49 /* #define INSTR_EXT_CALL          38 */
50 #define INSTR_NOT_VAR              39
51 /* #define INSTR_JNZERO            40 */
52 #define  INSTR_SETS_VAR_VAR        41
53 #define  INSTR_ISEQUALS_VAR_VAR    42
54 #define  INSTR_ADDS_VAR_VAR        43
55 #define  INSTR_SUBS_VAR_VAR        44
56 #define  INSTR_MULS_VAR_VAR        45
57 #define  INSTR_DIVS_VAR_VAR        46
58
59  /* }}} */
60 /* {{{ definition of the validation error types */
61 static const char *VALIDATE_OK = "ok";
62
63 #define VALIDATE_ERROR "error while validating "
64 #define VALIDATE_TODO "todo"
65 #define VALIDATE_SYNTHAX_ERROR "synthax error"
66 #define VALIDATE_NO_SUCH_INT "no such integer variable"
67 #define VALIDATE_NO_SUCH_VAR "no such variable"
68 #define VALIDATE_NO_SUCH_DEST_VAR "no such destination variable"
69 #define VALIDATE_NO_SUCH_SRC_VAR "no such src variable"
70 /* }}} */
71
72   /***********************************/
73  /* PROTOTYPE OF INTERNAL FUNCTIONS */
74 /***********************************/
75
76 /* {{{ */
77 static void gsl_instr_free (Instruction * _this);
78 static const char *gsl_instr_validate (Instruction * _this);
79 static void gsl_instr_display (Instruction * _this);
80
81 static InstructionFlow *iflow_new (void);
82 static void iflow_add_instr (InstructionFlow * _this, Instruction * instr);
83 static void iflow_clean (InstructionFlow * _this);
84 static void iflow_free (InstructionFlow * _this);
85 static void iflow_execute (FastInstructionFlow * _this, GoomSL * gsl);
86
87 /* }}} */
88
89   /************************************/
90  /* DEFINITION OF INTERNAL FUNCTIONS */
91 /************************************/
92
93 void
94 iflow_free (InstructionFlow * _this)
95 {                               /* {{{ */
96   goom_hash_free (_this->labels);
97   free (_this);                 /*TODO: finir cette fonction */
98 }                               /* }}} */
99
100 void
101 iflow_clean (InstructionFlow * _this)
102 {                               /* {{{ */
103   /* TODO: clean chaque instruction du flot */
104   _this->number = 0;
105   goom_hash_free (_this->labels);
106   _this->labels = goom_hash_new ();
107 }                               /* }}} */
108
109 InstructionFlow *
110 iflow_new (void)
111 {                               /* {{{ */
112   InstructionFlow *_this =
113       (InstructionFlow *) malloc (sizeof (InstructionFlow));
114   _this->number = 0;
115   _this->tabsize = 6;
116   _this->instr =
117       (Instruction **) malloc (_this->tabsize * sizeof (Instruction *));
118   _this->labels = goom_hash_new ();
119
120   return _this;
121 }                               /* }}} */
122
123 void
124 iflow_add_instr (InstructionFlow * _this, Instruction * instr)
125 {                               /* {{{ */
126   if (_this->number == _this->tabsize) {
127     _this->tabsize *= 2;
128     _this->instr =
129         (Instruction **) realloc (_this->instr,
130         _this->tabsize * sizeof (Instruction *));
131   }
132   _this->instr[_this->number] = instr;
133   instr->address = _this->number;
134   _this->number++;
135 }                               /* }}} */
136
137 void
138 gsl_instr_set_namespace (Instruction * _this, GoomHash * ns)
139 {                               /* {{{ */
140   if (_this->cur_param <= 0) {
141     fprintf (stderr, "ERROR: Line %d, No more params to instructions\n",
142         _this->line_number);
143     exit (1);
144   }
145   _this->vnamespace[_this->cur_param - 1] = ns;
146 }                               /* }}} */
147
148 void
149 gsl_instr_add_param (Instruction * instr, char *param, int type)
150 {                               /* {{{ */
151   int len;
152
153   if (instr == NULL)
154     return;
155   if (instr->cur_param == 0)
156     return;
157   --instr->cur_param;
158   len = strlen (param);
159   instr->params[instr->cur_param] = (char *) malloc (len + 1);
160   strcpy (instr->params[instr->cur_param], param);
161   instr->types[instr->cur_param] = type;
162   if (instr->cur_param == 0) {
163
164     const char *result = gsl_instr_validate (instr);
165
166     if (result != VALIDATE_OK) {
167       printf ("ERROR: Line %d: ", instr->parent->num_lines + 1);
168       gsl_instr_display (instr);
169       printf ("... %s\n", result);
170       instr->parent->compilationOK = 0;
171       exit (1);
172     }
173 #if USE_JITC_X86
174     iflow_add_instr (instr->parent->iflow, instr);
175 #else
176     if (instr->id != INSTR_NOP)
177       iflow_add_instr (instr->parent->iflow, instr);
178     else
179       gsl_instr_free (instr);
180 #endif
181   }
182 }                               /* }}} */
183
184 Instruction *
185 gsl_instr_init (GoomSL * parent, const char *name, int id, int nb_param,
186     int line_number)
187 {                               /* {{{ */
188   Instruction *instr = (Instruction *) malloc (sizeof (Instruction));
189   instr->params = (char **) malloc (nb_param * sizeof (char *));
190   instr->vnamespace = (GoomHash **) malloc (nb_param * sizeof (GoomHash *));
191   instr->types = (int *) malloc (nb_param * sizeof (int));
192   instr->cur_param = instr->nb_param = nb_param;
193   instr->parent = parent;
194   instr->id = id;
195   instr->name = name;
196   instr->jump_label = NULL;
197   instr->line_number = line_number;
198   return instr;
199 }                               /* }}} */
200
201 void
202 gsl_instr_free (Instruction * _this)
203 {                               /* {{{ */
204   int i;
205
206   free (_this->types);
207   for (i = _this->cur_param; i < _this->nb_param; ++i)
208     free (_this->params[i]);
209   free (_this->params);
210   free (_this);
211 }                               /* }}} */
212
213 void
214 gsl_instr_display (Instruction * _this)
215 {                               /* {{{ */
216   int i = _this->nb_param - 1;
217
218   printf ("%s", _this->name);
219   while (i >= _this->cur_param) {
220     printf (" %s", _this->params[i]);
221     --i;
222   }
223 }                               /* }}} */
224
225   /****************************************/
226  /* VALIDATION OF INSTRUCTION PARAMETERS */
227 /****************************************/
228
229 static const char *
230 validate_v_v (Instruction * _this)
231 {                               /* {{{ */
232   HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
233   HashValue *src = goom_hash_get (_this->vnamespace[0], _this->params[0]);
234
235   if (dest == NULL) {
236     return VALIDATE_NO_SUCH_DEST_VAR;
237   }
238   if (src == NULL) {
239     return VALIDATE_NO_SUCH_SRC_VAR;
240   }
241   _this->data.udest.var = dest->ptr;
242   _this->data.usrc.var = src->ptr;
243   return VALIDATE_OK;
244 }                               /* }}} */
245
246 static const char *
247 validate_v_i (Instruction * _this)
248 {                               /* {{{ */
249   HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
250
251   _this->data.usrc.value_int = strtol (_this->params[0], NULL, 0);
252
253   if (dest == NULL) {
254     return VALIDATE_NO_SUCH_INT;
255   }
256   _this->data.udest.var = dest->ptr;
257   return VALIDATE_OK;
258 }                               /* }}} */
259
260 static const char *
261 validate_v_p (Instruction * _this)
262 {                               /* {{{ */
263   HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
264
265   _this->data.usrc.value_ptr = strtol (_this->params[0], NULL, 0);
266
267   if (dest == NULL) {
268     return VALIDATE_NO_SUCH_INT;
269   }
270   _this->data.udest.var = dest->ptr;
271   return VALIDATE_OK;
272 }                               /* }}} */
273
274 static const char *
275 validate_v_f (Instruction * _this)
276 {                               /* {{{ */
277   HashValue *dest = goom_hash_get (_this->vnamespace[1], _this->params[1]);
278
279   _this->data.usrc.value_float = atof (_this->params[0]);
280
281   if (dest == NULL) {
282     return VALIDATE_NO_SUCH_VAR;
283   }
284   _this->data.udest.var = dest->ptr;
285   return VALIDATE_OK;
286 }                               /* }}} */
287
288 static const char *
289 validate (Instruction * _this,
290     int vf_f_id, int vf_v_id,
291     int vi_i_id, int vi_v_id, int vp_p_id, int vp_v_id, int vs_v_id)
292 {                               /* {{{ */
293   if ((_this->types[1] == TYPE_FVAR) && (_this->types[0] == TYPE_FLOAT)) {
294     _this->id = vf_f_id;
295     return validate_v_f (_this);
296   } else if ((_this->types[1] == TYPE_FVAR) && (_this->types[0] == TYPE_FVAR)) {
297     _this->id = vf_v_id;
298     return validate_v_v (_this);
299   } else if ((_this->types[1] == TYPE_IVAR)
300       && (_this->types[0] == TYPE_INTEGER)) {
301     _this->id = vi_i_id;
302     return validate_v_i (_this);
303   } else if ((_this->types[1] == TYPE_IVAR) && (_this->types[0] == TYPE_IVAR)) {
304     _this->id = vi_v_id;
305     return validate_v_v (_this);
306   } else if ((_this->types[1] == TYPE_PVAR) && (_this->types[0] == TYPE_PTR)) {
307     if (vp_p_id == INSTR_NOP)
308       return VALIDATE_ERROR;
309     _this->id = vp_p_id;
310     return validate_v_p (_this);
311   } else if ((_this->types[1] == TYPE_PVAR) && (_this->types[0] == TYPE_PVAR)) {
312     _this->id = vp_v_id;
313     if (vp_v_id == INSTR_NOP)
314       return VALIDATE_ERROR;
315     return validate_v_v (_this);
316   } else if ((_this->types[1] < FIRST_RESERVED) && (_this->types[1] >= 0)
317       && (_this->types[0] == _this->types[1])) {
318     _this->id = vs_v_id;
319     if (vs_v_id == INSTR_NOP)
320       return "Impossible operation to perform between two structs";
321     return validate_v_v (_this);
322   }
323   return VALIDATE_ERROR;
324 }                               /* }}} */
325
326 const char *
327 gsl_instr_validate (Instruction * _this)
328 {                               /* {{{ */
329   if (_this->id != INSTR_EXT_CALL) {
330     int i = _this->nb_param;
331
332     while (i > 0) {
333       i--;
334       if (_this->types[i] == TYPE_VAR) {
335         int type = gsl_type_of_var (_this->vnamespace[i], _this->params[i]);
336
337         if (type == INSTR_INT)
338           _this->types[i] = TYPE_IVAR;
339         else if (type == INSTR_FLOAT)
340           _this->types[i] = TYPE_FVAR;
341         else if (type == INSTR_PTR)
342           _this->types[i] = TYPE_PVAR;
343         else if ((type >= 0) && (type < FIRST_RESERVED))
344           _this->types[i] = type;
345         else
346           fprintf (stderr, "WARNING: Line %d, %s has no namespace\n",
347               _this->line_number, _this->params[i]);
348       }
349     }
350   }
351
352   switch (_this->id) {
353
354       /* set */
355     case INSTR_SET:
356       return validate (_this,
357           INSTR_SETF_VAR_FLOAT, INSTR_SETF_VAR_VAR,
358           INSTR_SETI_VAR_INTEGER, INSTR_SETI_VAR_VAR,
359           INSTR_SETP_VAR_PTR, INSTR_SETP_VAR_VAR, INSTR_SETS_VAR_VAR);
360
361       /* extcall */
362     case INSTR_EXT_CALL:
363       if (_this->types[0] == TYPE_VAR) {
364         HashValue *fval =
365             goom_hash_get (_this->parent->functions, _this->params[0]);
366         if (fval) {
367           _this->data.udest.external_function =
368               (struct _ExternalFunctionStruct *) fval->ptr;
369           return VALIDATE_OK;
370         }
371       }
372       return VALIDATE_ERROR;
373
374       /* call */
375     case INSTR_CALL:
376       if (_this->types[0] == TYPE_LABEL) {
377         _this->jump_label = _this->params[0];
378         return VALIDATE_OK;
379       }
380       return VALIDATE_ERROR;
381
382       /* ret */
383     case INSTR_RET:
384       return VALIDATE_OK;
385
386       /* jump */
387     case INSTR_JUMP:
388
389       if (_this->types[0] == TYPE_LABEL) {
390         _this->jump_label = _this->params[0];
391         return VALIDATE_OK;
392       }
393       return VALIDATE_ERROR;
394
395       /* jzero / jnzero */
396     case INSTR_JZERO:
397     case INSTR_JNZERO:
398
399       if (_this->types[0] == TYPE_LABEL) {
400         _this->jump_label = _this->params[0];
401         return VALIDATE_OK;
402       }
403       return VALIDATE_ERROR;
404
405       /* label */
406     case INSTR_LABEL:
407
408       if (_this->types[0] == TYPE_LABEL) {
409         _this->id = INSTR_NOP;
410         _this->nop_label = _this->params[0];
411         goom_hash_put_int (_this->parent->iflow->labels, _this->params[0],
412             _this->parent->iflow->number);
413         return VALIDATE_OK;
414       }
415       return VALIDATE_ERROR;
416
417       /* isequal */
418     case INSTR_ISEQUAL:
419       return validate (_this,
420           INSTR_ISEQUALF_VAR_FLOAT, INSTR_ISEQUALF_VAR_VAR,
421           INSTR_ISEQUALI_VAR_INTEGER, INSTR_ISEQUALI_VAR_VAR,
422           INSTR_ISEQUALP_VAR_PTR, INSTR_ISEQUALP_VAR_VAR,
423           INSTR_ISEQUALS_VAR_VAR);
424
425       /* not */
426     case INSTR_NOT:
427       _this->id = INSTR_NOT_VAR;
428       return VALIDATE_OK;
429
430       /* islower */
431     case INSTR_ISLOWER:
432       return validate (_this,
433           INSTR_ISLOWERF_VAR_FLOAT, INSTR_ISLOWERF_VAR_VAR,
434           INSTR_ISLOWERI_VAR_INTEGER, INSTR_ISLOWERI_VAR_VAR,
435           INSTR_NOP, INSTR_NOP, INSTR_NOP);
436
437       /* add */
438     case INSTR_ADD:
439       return validate (_this,
440           INSTR_ADDF_VAR_FLOAT, INSTR_ADDF_VAR_VAR,
441           INSTR_ADDI_VAR_INTEGER, INSTR_ADDI_VAR_VAR,
442           INSTR_NOP, INSTR_NOP, INSTR_ADDS_VAR_VAR);
443
444       /* mul */
445     case INSTR_MUL:
446       return validate (_this,
447           INSTR_MULF_VAR_FLOAT, INSTR_MULF_VAR_VAR,
448           INSTR_MULI_VAR_INTEGER, INSTR_MULI_VAR_VAR,
449           INSTR_NOP, INSTR_NOP, INSTR_MULS_VAR_VAR);
450
451       /* sub */
452     case INSTR_SUB:
453       return validate (_this,
454           INSTR_SUBF_VAR_FLOAT, INSTR_SUBF_VAR_VAR,
455           INSTR_SUBI_VAR_INTEGER, INSTR_SUBI_VAR_VAR,
456           INSTR_NOP, INSTR_NOP, INSTR_SUBS_VAR_VAR);
457
458       /* div */
459     case INSTR_DIV:
460       return validate (_this,
461           INSTR_DIVF_VAR_FLOAT, INSTR_DIVF_VAR_VAR,
462           INSTR_DIVI_VAR_INTEGER, INSTR_DIVI_VAR_VAR,
463           INSTR_NOP, INSTR_NOP, INSTR_DIVS_VAR_VAR);
464
465     default:
466       return VALIDATE_TODO;
467   }
468   return VALIDATE_ERROR;
469 }                               /* }}} */
470
471   /*************/
472  /* EXECUTION */
473 /*************/
474 void
475 iflow_execute (FastInstructionFlow * _this, GoomSL * gsl)
476 {                               /* {{{ */
477   int flag = 0;
478   int ip = 0;
479   FastInstruction *instr = _this->instr;
480   int stack[0x10000];
481   int stack_pointer = 0;
482
483   stack[stack_pointer++] = -1;
484
485   /* Quelques Macro pour rendre le code plus lisible */
486 #define pSRC_VAR        instr[ip].data.usrc.var
487 #define SRC_VAR_INT    *instr[ip].data.usrc.var_int
488 #define SRC_VAR_FLOAT  *instr[ip].data.usrc.var_float
489 #define SRC_VAR_PTR    *instr[ip].data.usrc.var_ptr
490
491 #define pDEST_VAR       instr[ip].data.udest.var
492 #define DEST_VAR_INT   *instr[ip].data.udest.var_int
493 #define DEST_VAR_FLOAT *instr[ip].data.udest.var_float
494 #define DEST_VAR_PTR   *instr[ip].data.udest.var_ptr
495
496 #define VALUE_INT       instr[ip].data.usrc.value_int
497 #define VALUE_FLOAT     instr[ip].data.usrc.value_float
498 #define VALUE_PTR       instr[ip].data.usrc.value_ptr
499
500 #define JUMP_OFFSET     instr[ip].data.udest.jump_offset
501
502 #define SRC_STRUCT_ID  instr[ip].data.usrc.var_int[-1]
503 #define DEST_STRUCT_ID instr[ip].data.udest.var_int[-1]
504 #define SRC_STRUCT_IBLOCK(i)  gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i]
505 #define SRC_STRUCT_FBLOCK(i)  gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i]
506 #define DEST_STRUCT_IBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i]
507 #define DEST_STRUCT_FBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i]
508 #define DEST_STRUCT_IBLOCK_VAR(i,j) \
509   ((int*)((char*)pDEST_VAR   + gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i].data))[j]
510 #define DEST_STRUCT_FBLOCK_VAR(i,j) \
511   ((float*)((char*)pDEST_VAR + gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i].data))[j]
512 #define SRC_STRUCT_IBLOCK_VAR(i,j) \
513   ((int*)((char*)pSRC_VAR    + gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i].data))[j]
514 #define SRC_STRUCT_FBLOCK_VAR(i,j) \
515   ((float*)((char*)pSRC_VAR  + gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i].data))[j]
516 #define DEST_STRUCT_SIZE      gsl->gsl_struct[DEST_STRUCT_ID]->size
517
518   while (1) {
519     int i;
520
521 #ifdef TRACE_SCRIPT
522     printf ("execute ");
523     gsl_instr_display (instr[ip].proto);
524     printf ("\n");
525 #endif
526     switch (instr[ip].id) {
527
528         /* SET.I */
529       case INSTR_SETI_VAR_INTEGER:
530         DEST_VAR_INT = VALUE_INT;
531         ++ip;
532         break;
533
534       case INSTR_SETI_VAR_VAR:
535         DEST_VAR_INT = SRC_VAR_INT;
536         ++ip;
537         break;
538
539         /* SET.F */
540       case INSTR_SETF_VAR_FLOAT:
541         DEST_VAR_FLOAT = VALUE_FLOAT;
542         ++ip;
543         break;
544
545       case INSTR_SETF_VAR_VAR:
546         DEST_VAR_FLOAT = SRC_VAR_FLOAT;
547         ++ip;
548         break;
549
550         /* SET.P */
551       case INSTR_SETP_VAR_VAR:
552         DEST_VAR_PTR = SRC_VAR_PTR;
553         ++ip;
554         break;
555
556       case INSTR_SETP_VAR_PTR:
557         DEST_VAR_PTR = VALUE_PTR;
558         ++ip;
559         break;
560
561         /* JUMP */
562       case INSTR_JUMP:
563         ip += JUMP_OFFSET;
564         break;
565
566         /* JZERO */
567       case INSTR_JZERO:
568         ip += (flag ? 1 : JUMP_OFFSET);
569         break;
570
571       case INSTR_NOP:
572         ++ip;
573         break;
574
575         /* ISEQUAL.P */
576       case INSTR_ISEQUALP_VAR_VAR:
577         flag = (DEST_VAR_PTR == SRC_VAR_PTR);
578         ++ip;
579         break;
580
581       case INSTR_ISEQUALP_VAR_PTR:
582         flag = (DEST_VAR_PTR == VALUE_PTR);
583         ++ip;
584         break;
585
586         /* ISEQUAL.I */
587       case INSTR_ISEQUALI_VAR_VAR:
588         flag = (DEST_VAR_INT == SRC_VAR_INT);
589         ++ip;
590         break;
591
592       case INSTR_ISEQUALI_VAR_INTEGER:
593         flag = (DEST_VAR_INT == VALUE_INT);
594         ++ip;
595         break;
596
597         /* ISEQUAL.F */
598       case INSTR_ISEQUALF_VAR_VAR:
599         flag = (DEST_VAR_FLOAT == SRC_VAR_FLOAT);
600         ++ip;
601         break;
602
603       case INSTR_ISEQUALF_VAR_FLOAT:
604         flag = (DEST_VAR_FLOAT == VALUE_FLOAT);
605         ++ip;
606         break;
607
608         /* ISLOWER.I */
609       case INSTR_ISLOWERI_VAR_VAR:
610         flag = (DEST_VAR_INT < SRC_VAR_INT);
611         ++ip;
612         break;
613
614       case INSTR_ISLOWERI_VAR_INTEGER:
615         flag = (DEST_VAR_INT < VALUE_INT);
616         ++ip;
617         break;
618
619         /* ISLOWER.F */
620       case INSTR_ISLOWERF_VAR_VAR:
621         flag = (DEST_VAR_FLOAT < SRC_VAR_FLOAT);
622         ++ip;
623         break;
624
625       case INSTR_ISLOWERF_VAR_FLOAT:
626         flag = (DEST_VAR_FLOAT < VALUE_FLOAT);
627         ++ip;
628         break;
629
630         /* ADD.I */
631       case INSTR_ADDI_VAR_VAR:
632         DEST_VAR_INT += SRC_VAR_INT;
633         ++ip;
634         break;
635
636       case INSTR_ADDI_VAR_INTEGER:
637         DEST_VAR_INT += VALUE_INT;
638         ++ip;
639         break;
640
641         /* ADD.F */
642       case INSTR_ADDF_VAR_VAR:
643         DEST_VAR_FLOAT += SRC_VAR_FLOAT;
644         ++ip;
645         break;
646
647       case INSTR_ADDF_VAR_FLOAT:
648         DEST_VAR_FLOAT += VALUE_FLOAT;
649         ++ip;
650         break;
651
652         /* MUL.I */
653       case INSTR_MULI_VAR_VAR:
654         DEST_VAR_INT *= SRC_VAR_INT;
655         ++ip;
656         break;
657
658       case INSTR_MULI_VAR_INTEGER:
659         DEST_VAR_INT *= VALUE_INT;
660         ++ip;
661         break;
662
663         /* MUL.F */
664       case INSTR_MULF_VAR_FLOAT:
665         DEST_VAR_FLOAT *= VALUE_FLOAT;
666         ++ip;
667         break;
668
669       case INSTR_MULF_VAR_VAR:
670         DEST_VAR_FLOAT *= SRC_VAR_FLOAT;
671         ++ip;
672         break;
673
674         /* DIV.I */
675       case INSTR_DIVI_VAR_VAR:
676         DEST_VAR_INT /= SRC_VAR_INT;
677         ++ip;
678         break;
679
680       case INSTR_DIVI_VAR_INTEGER:
681         DEST_VAR_INT /= VALUE_INT;
682         ++ip;
683         break;
684
685         /* DIV.F */
686       case INSTR_DIVF_VAR_FLOAT:
687         DEST_VAR_FLOAT /= VALUE_FLOAT;
688         ++ip;
689         break;
690
691       case INSTR_DIVF_VAR_VAR:
692         DEST_VAR_FLOAT /= SRC_VAR_FLOAT;
693         ++ip;
694         break;
695
696         /* SUB.I */
697       case INSTR_SUBI_VAR_VAR:
698         DEST_VAR_INT -= SRC_VAR_INT;
699         ++ip;
700         break;
701
702       case INSTR_SUBI_VAR_INTEGER:
703         DEST_VAR_INT -= VALUE_INT;
704         ++ip;
705         break;
706
707         /* SUB.F */
708       case INSTR_SUBF_VAR_FLOAT:
709         DEST_VAR_FLOAT -= VALUE_FLOAT;
710         ++ip;
711         break;
712
713       case INSTR_SUBF_VAR_VAR:
714         DEST_VAR_FLOAT -= SRC_VAR_FLOAT;
715         ++ip;
716         break;
717
718         /* CALL */
719       case INSTR_CALL:
720         stack[stack_pointer++] = ip + 1;
721         ip += JUMP_OFFSET;
722         break;
723
724         /* RET */
725       case INSTR_RET:
726         ip = stack[--stack_pointer];
727         if (ip < 0)
728           return;
729         break;
730
731         /* EXT_CALL */
732       case INSTR_EXT_CALL:
733         instr[ip].data.udest.external_function->function (gsl, gsl->vars,
734             instr[ip].data.udest.external_function->vars);
735         ++ip;
736         break;
737
738         /* NOT */
739       case INSTR_NOT_VAR:
740         flag = !flag;
741         ++ip;
742         break;
743
744         /* JNZERO */
745       case INSTR_JNZERO:
746         ip += (flag ? JUMP_OFFSET : 1);
747         break;
748
749       case INSTR_SETS_VAR_VAR:
750         memcpy (pDEST_VAR, pSRC_VAR, DEST_STRUCT_SIZE);
751         ++ip;
752         break;
753
754       case INSTR_ISEQUALS_VAR_VAR:
755         break;
756
757       case INSTR_ADDS_VAR_VAR:
758         /* process integers */
759         i = 0;
760         while (DEST_STRUCT_IBLOCK (i).size > 0) {
761           int j = DEST_STRUCT_IBLOCK (i).size;
762
763           while (j--) {
764             DEST_STRUCT_IBLOCK_VAR (i, j) += SRC_STRUCT_IBLOCK_VAR (i, j);
765           }
766           ++i;
767         }
768         /* process floats */
769         i = 0;
770         while (DEST_STRUCT_FBLOCK (i).size > 0) {
771           int j = DEST_STRUCT_FBLOCK (i).size;
772
773           while (j--) {
774             DEST_STRUCT_FBLOCK_VAR (i, j) += SRC_STRUCT_FBLOCK_VAR (i, j);
775           }
776           ++i;
777         }
778         ++ip;
779         break;
780
781       case INSTR_SUBS_VAR_VAR:
782         /* process integers */
783         i = 0;
784         while (DEST_STRUCT_IBLOCK (i).size > 0) {
785           int j = DEST_STRUCT_IBLOCK (i).size;
786
787           while (j--) {
788             DEST_STRUCT_IBLOCK_VAR (i, j) -= SRC_STRUCT_IBLOCK_VAR (i, j);
789           }
790           ++i;
791         }
792         /* process floats */
793         i = 0;
794         while (DEST_STRUCT_FBLOCK (i).size > 0) {
795           int j = DEST_STRUCT_FBLOCK (i).size;
796
797           while (j--) {
798             DEST_STRUCT_FBLOCK_VAR (i, j) -= SRC_STRUCT_FBLOCK_VAR (i, j);
799           }
800           ++i;
801         }
802         ++ip;
803         break;
804
805       case INSTR_MULS_VAR_VAR:
806         /* process integers */
807         i = 0;
808         while (DEST_STRUCT_IBLOCK (i).size > 0) {
809           int j = DEST_STRUCT_IBLOCK (i).size;
810
811           while (j--) {
812             DEST_STRUCT_IBLOCK_VAR (i, j) *= SRC_STRUCT_IBLOCK_VAR (i, j);
813           }
814           ++i;
815         }
816         /* process floats */
817         i = 0;
818         while (DEST_STRUCT_FBLOCK (i).size > 0) {
819           int j = DEST_STRUCT_FBLOCK (i).size;
820
821           while (j--) {
822             DEST_STRUCT_FBLOCK_VAR (i, j) *= SRC_STRUCT_FBLOCK_VAR (i, j);
823           }
824           ++i;
825         }
826         ++ip;
827         break;
828
829       case INSTR_DIVS_VAR_VAR:
830         /* process integers */
831         i = 0;
832         while (DEST_STRUCT_IBLOCK (i).size > 0) {
833           int j = DEST_STRUCT_IBLOCK (i).size;
834
835           while (j--) {
836             DEST_STRUCT_IBLOCK_VAR (i, j) /= SRC_STRUCT_IBLOCK_VAR (i, j);
837           }
838           ++i;
839         }
840         /* process floats */
841         i = 0;
842         while (DEST_STRUCT_FBLOCK (i).size > 0) {
843           int j = DEST_STRUCT_FBLOCK (i).size;
844
845           while (j--) {
846             DEST_STRUCT_FBLOCK_VAR (i, j) /= SRC_STRUCT_FBLOCK_VAR (i, j);
847           }
848           ++i;
849         }
850         ++ip;
851         break;
852
853       default:
854         printf ("NOT IMPLEMENTED : %d\n", instr[ip].id);
855         ++ip;
856         exit (1);
857     }
858   }
859 }                               /* }}} */
860
861 int
862 gsl_malloc (GoomSL * _this, int size)
863 {                               /* {{{ */
864   if (_this->nbPtr >= _this->ptrArraySize) {
865     _this->ptrArraySize *= 2;
866     _this->ptrArray =
867         (void **) realloc (_this->ptrArray,
868         sizeof (void *) * _this->ptrArraySize);
869   }
870   _this->ptrArray[_this->nbPtr] = malloc (size);
871   return _this->nbPtr++;
872 }                               /* }}} */
873
874 void *
875 gsl_get_ptr (GoomSL * _this, int id)
876 {                               /* {{{ */
877   if ((id >= 0) && (id < _this->nbPtr))
878     return _this->ptrArray[id];
879   fprintf (stderr, "INVALID GET PTR 0x%08x\n", id);
880   return NULL;
881 }                               /* }}} */
882
883 void
884 gsl_free_ptr (GoomSL * _this, int id)
885 {                               /* {{{ */
886   if ((id >= 0) && (id < _this->nbPtr)) {
887     free (_this->ptrArray[id]);
888     _this->ptrArray[id] = 0;
889   }
890 }                               /* }}} */
891
892 void
893 gsl_enternamespace (const char *name)
894 {                               /* {{{ */
895   HashValue *val = goom_hash_get (currentGoomSL->functions, name);
896
897   if (val) {
898     ExternalFunctionStruct *function = (ExternalFunctionStruct *) val->ptr;
899
900     currentGoomSL->currentNS++;
901     currentGoomSL->namespaces[currentGoomSL->currentNS] = function->vars;
902   } else {
903     fprintf (stderr, "ERROR: Line %d, Could not find namespace: %s\n",
904         currentGoomSL->num_lines, name);
905     exit (1);
906   }
907 }                               /* }}} */
908
909 void
910 gsl_reenternamespace (GoomHash * nsinfo)
911 {
912   currentGoomSL->currentNS++;
913   currentGoomSL->namespaces[currentGoomSL->currentNS] = nsinfo;
914 }
915
916 GoomHash *
917 gsl_leavenamespace (void)
918 {                               /* {{{ */
919   currentGoomSL->currentNS--;
920   return currentGoomSL->namespaces[currentGoomSL->currentNS + 1];
921 }                               /* }}} */
922
923 GoomHash *
924 gsl_find_namespace (const char *name)
925 {                               /* {{{ */
926   int i;
927
928   for (i = currentGoomSL->currentNS; i >= 0; --i) {
929     if (goom_hash_get (currentGoomSL->namespaces[i], name))
930       return currentGoomSL->namespaces[i];
931   }
932   return NULL;
933 }                               /* }}} */
934
935 void
936 gsl_declare_task (const char *name)
937 {                               /* {{{ */
938   if (goom_hash_get (currentGoomSL->functions, name)) {
939     return;
940   } else {
941     ExternalFunctionStruct *gef =
942         (ExternalFunctionStruct *) malloc (sizeof (ExternalFunctionStruct));
943     gef->function = 0;
944     gef->vars = goom_hash_new ();
945     gef->is_extern = 0;
946     goom_hash_put_ptr (currentGoomSL->functions, name, (void *) gef);
947   }
948 }                               /* }}} */
949
950 void
951 gsl_declare_external_task (const char *name)
952 {                               /* {{{ */
953   if (goom_hash_get (currentGoomSL->functions, name)) {
954     fprintf (stderr, "ERROR: Line %d, Duplicate declaration of %s\n",
955         currentGoomSL->num_lines, name);
956     return;
957   } else {
958     ExternalFunctionStruct *gef =
959         (ExternalFunctionStruct *) malloc (sizeof (ExternalFunctionStruct));
960     gef->function = 0;
961     gef->vars = goom_hash_new ();
962     gef->is_extern = 1;
963     goom_hash_put_ptr (currentGoomSL->functions, name, (void *) gef);
964   }
965 }                               /* }}} */
966
967 static void
968 reset_scanner (GoomSL * gss)
969 {                               /* {{{ */
970   gss->num_lines = 0;
971   gss->instr = NULL;
972   iflow_clean (gss->iflow);
973
974   /* reset variables */
975   goom_hash_free (gss->vars);
976   gss->vars = goom_hash_new ();
977   gss->currentNS = 0;
978   gss->namespaces[0] = gss->vars;
979
980   goom_hash_free (gss->structIDS);
981   gss->structIDS = goom_hash_new ();
982
983   while (gss->nbStructID > 0) {
984     int i;
985
986     gss->nbStructID--;
987     for (i = 0; i < gss->gsl_struct[gss->nbStructID]->nbFields; ++i)
988       free (gss->gsl_struct[gss->nbStructID]->fields[i]);
989     free (gss->gsl_struct[gss->nbStructID]);
990   }
991
992   gss->compilationOK = 1;
993
994   goom_heap_delete (gss->data_heap);
995   gss->data_heap = goom_heap_new ();
996 }                               /* }}} */
997
998 static void
999 calculate_labels (InstructionFlow * iflow)
1000 {                               /* {{{ */
1001   int i = 0;
1002
1003   while (i < iflow->number) {
1004     Instruction *instr = iflow->instr[i];
1005
1006     if (instr->jump_label) {
1007       HashValue *label = goom_hash_get (iflow->labels, instr->jump_label);
1008
1009       if (label) {
1010         instr->data.udest.jump_offset = -instr->address + label->i;
1011       } else {
1012         fprintf (stderr, "ERROR: Line %d, Could not find label %s\n",
1013             instr->line_number, instr->jump_label);
1014         instr->id = INSTR_NOP;
1015         instr->nop_label = 0;
1016         exit (1);
1017       }
1018     }
1019     ++i;
1020   }
1021 }                               /* }}} */
1022
1023 static int
1024 powerOfTwo (int i)
1025 {
1026   int b;
1027
1028   for (b = 0; b < 31; b++)
1029     if (i == (1 << b))
1030       return b;
1031   return 0;
1032 }
1033
1034 /* Cree un flow d'instruction optimise */
1035 static void
1036 gsl_create_fast_iflow (void)
1037 {                               /* {{{ */
1038   int number = currentGoomSL->iflow->number;
1039   int i;
1040
1041 #ifdef USE_JITC_X86
1042
1043   /* pour compatibilite avec les MACROS servant a execution */
1044   int ip = 0;
1045   GoomSL *gsl = currentGoomSL;
1046
1047   JitcX86Env *jitc;
1048
1049   if (currentGoomSL->jitc != NULL)
1050     jitc_x86_delete (currentGoomSL->jitc);
1051   jitc = currentGoomSL->jitc = jitc_x86_env_new (0xffff);
1052   currentGoomSL->jitc_func = jitc_prepare_func (jitc);
1053
1054 #if 0
1055 #define SRC_STRUCT_ID  instr[ip].data.usrc.var_int[-1]
1056 #define DEST_STRUCT_ID instr[ip].data.udest.var_int[-1]
1057 #define SRC_STRUCT_IBLOCK(i)  gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i]
1058 #define SRC_STRUCT_FBLOCK(i)  gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i]
1059 #define DEST_STRUCT_IBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i]
1060 #define DEST_STRUCT_FBLOCK(i) gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i]
1061 #define DEST_STRUCT_IBLOCK_VAR(i,j) \
1062   ((int*)((char*)pDEST_VAR   + gsl->gsl_struct[DEST_STRUCT_ID]->iBlock[i].data))[j]
1063 #define DEST_STRUCT_FBLOCK_VAR(i,j) \
1064   ((float*)((char*)pDEST_VAR + gsl->gsl_struct[DEST_STRUCT_ID]->fBlock[i].data))[j]
1065 #define SRC_STRUCT_IBLOCK_VAR(i,j) \
1066   ((int*)((char*)pSRC_VAR    + gsl->gsl_struct[SRC_STRUCT_ID]->iBlock[i].data))[j]
1067 #define SRC_STRUCT_FBLOCK_VAR(i,j) \
1068   ((float*)((char*)pSRC_VAR  + gsl->gsl_struct[SRC_STRUCT_ID]->fBlock[i].data))[j]
1069 #define DEST_STRUCT_SIZE      gsl->gsl_struct[DEST_STRUCT_ID]->size
1070 #endif
1071
1072   JITC_JUMP_LABEL (jitc, "__very_end__");
1073   JITC_ADD_LABEL (jitc, "__very_start__");
1074
1075   for (i = 0; i < number; ++i) {
1076     Instruction *instr = currentGoomSL->iflow->instr[i];
1077
1078     switch (instr->id) {
1079       case INSTR_SETI_VAR_INTEGER:
1080         jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_int,
1081             instr->data.usrc.value_int);
1082         break;
1083       case INSTR_SETI_VAR_VAR:
1084         jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_int);
1085         jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
1086         break;
1087         /* SET.F */
1088       case INSTR_SETF_VAR_FLOAT:
1089         jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_float,
1090             *(int *) (&instr->data.usrc.value_float));
1091         break;
1092       case INSTR_SETF_VAR_VAR:
1093         jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_float);
1094         jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_float);
1095         break;
1096       case INSTR_NOP:
1097         if (instr->nop_label != 0)
1098           JITC_ADD_LABEL (jitc, instr->nop_label);
1099         break;
1100       case INSTR_JUMP:
1101         JITC_JUMP_LABEL (jitc, instr->jump_label);
1102         break;
1103       case INSTR_SETP_VAR_PTR:
1104         jitc_add (jitc, "mov [$d], $d", instr->data.udest.var_ptr,
1105             instr->data.usrc.value_ptr);
1106         break;
1107       case INSTR_SETP_VAR_VAR:
1108         jitc_add (jitc, "mov eax, [$d]", instr->data.usrc.var_ptr);
1109         jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_ptr);
1110         break;
1111       case INSTR_SUBI_VAR_INTEGER:
1112         jitc_add (jitc, "add [$d],  $d", instr->data.udest.var_int,
1113             -instr->data.usrc.value_int);
1114         break;
1115       case INSTR_SUBI_VAR_VAR:
1116         jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
1117         jitc_add (jitc, "sub eax, [$d]", instr->data.usrc.var_int);
1118         jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
1119         break;
1120       case INSTR_SUBF_VAR_FLOAT:
1121         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1122         break;
1123       case INSTR_SUBF_VAR_VAR:
1124         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1125         break;
1126       case INSTR_ISLOWERF_VAR_VAR:
1127         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1128         break;
1129       case INSTR_ISLOWERF_VAR_FLOAT:
1130         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1131         break;
1132       case INSTR_ISLOWERI_VAR_VAR:
1133         jitc_add (jitc, "mov edx, [$d]", instr->data.udest.var_int);
1134         jitc_add (jitc, "sub edx, [$d]", instr->data.usrc.var_int);
1135         jitc_add (jitc, "shr edx, $d", 31);
1136         break;
1137       case INSTR_ISLOWERI_VAR_INTEGER:
1138         jitc_add (jitc, "mov edx, [$d]", instr->data.udest.var_int);
1139         jitc_add (jitc, "sub edx, $d", instr->data.usrc.value_int);
1140         jitc_add (jitc, "shr edx, $d", 31);
1141         break;
1142       case INSTR_ADDI_VAR_INTEGER:
1143         jitc_add (jitc, "add [$d],  $d", instr->data.udest.var_int,
1144             instr->data.usrc.value_int);
1145         break;
1146       case INSTR_ADDI_VAR_VAR:
1147         jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
1148         jitc_add (jitc, "add eax, [$d]", instr->data.usrc.var_int);
1149         jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
1150         break;
1151       case INSTR_ADDF_VAR_FLOAT:
1152         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1153         break;
1154       case INSTR_ADDF_VAR_VAR:
1155         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1156         break;
1157       case INSTR_MULI_VAR_INTEGER:
1158         if (instr->data.usrc.value_int != 1) {
1159           int po2 = powerOfTwo (instr->data.usrc.value_int);
1160
1161           if (po2) {
1162             /* performs (V / 2^n) by doing V >> n */
1163             jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
1164             jitc_add (jitc, "sal  eax, $d", po2);
1165             jitc_add (jitc, "mov  [$d], eax", instr->data.udest.var_int);
1166           } else {
1167             jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
1168             jitc_add (jitc, "imul eax, $d", instr->data.usrc.value_int);
1169             jitc_add (jitc, "mov  [$d], eax", instr->data.udest.var_int);
1170           }
1171         }
1172         break;
1173       case INSTR_MULI_VAR_VAR:
1174         jitc_add (jitc, "mov  eax,  [$d]", instr->data.udest.var_int);
1175         jitc_add (jitc, "imul eax,  [$d]", instr->data.usrc.var_int);
1176         jitc_add (jitc, "mov  [$d], eax", instr->data.udest.var_int);
1177         break;
1178       case INSTR_MULF_VAR_FLOAT:
1179         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1180         break;
1181       case INSTR_MULF_VAR_VAR:
1182         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1183         break;
1184       case INSTR_DIVI_VAR_INTEGER:
1185         if ((instr->data.usrc.value_int != 1)
1186             && (instr->data.usrc.value_int != 0)) {
1187           int po2 = powerOfTwo (instr->data.usrc.value_int);
1188
1189           if (po2) {
1190             /* performs (V / 2^n) by doing V >> n */
1191             jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
1192             jitc_add (jitc, "sar  eax, $d", po2);
1193             jitc_add (jitc, "mov  [$d], eax", instr->data.udest.var_int);
1194           } else {
1195             /* performs (V/n) by doing (V*(32^2/n)) */
1196             long coef;
1197             double dcoef =
1198                 (double) 4294967296.0 / (double) instr->data.usrc.value_int;
1199             if (dcoef < 0.0)
1200               dcoef = -dcoef;
1201             coef = (long) floor (dcoef);
1202             dcoef -= floor (dcoef);
1203             if (dcoef < 0.5)
1204               coef += 1;
1205
1206             jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
1207             jitc_add (jitc, "mov  edx, $d", coef);
1208             jitc_add (jitc, "imul edx");
1209             if (instr->data.usrc.value_int < 0)
1210               jitc_add (jitc, "neg edx");
1211             jitc_add (jitc, "mov [$d], edx", instr->data.udest.var_int);
1212           }
1213         }
1214         break;
1215       case INSTR_DIVI_VAR_VAR:
1216         jitc_add (jitc, "mov  eax, [$d]", instr->data.udest.var_int);
1217         jitc_add (jitc, "cdq"); /* sign extend eax into edx */
1218         jitc_add (jitc, "idiv [$d]", instr->data.usrc.var_int);
1219         jitc_add (jitc, "mov [$d], eax", instr->data.udest.var_int);
1220         break;
1221       case INSTR_DIVF_VAR_FLOAT:
1222         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1223         break;
1224       case INSTR_DIVF_VAR_VAR:
1225         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1226         break;
1227       case INSTR_JZERO:
1228         jitc_add (jitc, "cmp edx, $d", 0);
1229         jitc_add (jitc, "je $s", instr->jump_label);
1230         break;
1231       case INSTR_ISEQUALP_VAR_VAR:
1232         jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_ptr);
1233         jitc_add (jitc, "mov edx, $d", 0);
1234         jitc_add (jitc, "cmp eax, [$d]", instr->data.usrc.var_ptr);
1235         jitc_add (jitc, "jne $d", 1);
1236         jitc_add (jitc, "inc edx");
1237         break;
1238       case INSTR_ISEQUALP_VAR_PTR:
1239         jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_ptr);
1240         jitc_add (jitc, "mov edx, $d", 0);
1241         jitc_add (jitc, "cmp eax, $d", instr->data.usrc.value_ptr);
1242         jitc_add (jitc, "jne $d", 1);
1243         jitc_add (jitc, "inc edx");
1244         break;
1245       case INSTR_ISEQUALI_VAR_VAR:
1246         jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
1247         jitc_add (jitc, "mov edx, $d", 0);
1248         jitc_add (jitc, "cmp eax, [$d]", instr->data.usrc.var_int);
1249         jitc_add (jitc, "jne $d", 1);
1250         jitc_add (jitc, "inc edx");
1251         break;
1252       case INSTR_ISEQUALI_VAR_INTEGER:
1253         jitc_add (jitc, "mov eax, [$d]", instr->data.udest.var_int);
1254         jitc_add (jitc, "mov edx, $d", 0);
1255         jitc_add (jitc, "cmp eax, $d", instr->data.usrc.value_int);
1256         jitc_add (jitc, "jne $d", 1);
1257         jitc_add (jitc, "inc edx");
1258         break;
1259       case INSTR_ISEQUALF_VAR_VAR:
1260         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1261         break;
1262       case INSTR_ISEQUALF_VAR_FLOAT:
1263         printf ("NOT IMPLEMENTED : %d\n", instr->id);
1264         break;
1265       case INSTR_CALL:
1266         jitc_add (jitc, "call $s", instr->jump_label);
1267         break;
1268       case INSTR_RET:
1269         jitc_add (jitc, "ret");
1270         break;
1271       case INSTR_EXT_CALL:
1272         jitc_add (jitc, "mov eax, [$d]",
1273             &(instr->data.udest.external_function->vars));
1274         jitc_add (jitc, "push eax");
1275         jitc_add (jitc, "mov edx, [$d]", &(currentGoomSL->vars));
1276         jitc_add (jitc, "push edx");
1277         jitc_add (jitc, "mov eax, [$d]", &(currentGoomSL));
1278         jitc_add (jitc, "push eax");
1279
1280         jitc_add (jitc, "mov eax, [$d]",
1281             &(instr->data.udest.external_function));
1282         jitc_add (jitc, "mov eax, [eax]");
1283         jitc_add (jitc, "call [eax]");
1284         jitc_add (jitc, "add esp, $d", 12);
1285         break;
1286       case INSTR_NOT_VAR:
1287         jitc_add (jitc, "mov eax, edx");
1288         jitc_add (jitc, "mov edx, $d", 1);
1289         jitc_add (jitc, "sub edx, eax");
1290         break;
1291       case INSTR_JNZERO:
1292         jitc_add (jitc, "cmp edx, $d", 0);
1293         jitc_add (jitc, "jne $s", instr->jump_label);
1294         break;
1295       case INSTR_SETS_VAR_VAR:
1296       {
1297         int loop = DEST_STRUCT_SIZE / sizeof (int);
1298         int dst = (int) pDEST_VAR;
1299         int src = (int) pSRC_VAR;
1300
1301         while (loop--) {
1302           jitc_add (jitc, "mov eax, [$d]", src);
1303           jitc_add (jitc, "mov [$d], eax", dst);
1304           src += 4;
1305           dst += 4;
1306         }
1307       }
1308         break;
1309       case INSTR_ISEQUALS_VAR_VAR:
1310         break;
1311       case INSTR_ADDS_VAR_VAR:
1312       {
1313         /* process integers */
1314         int i = 0;
1315
1316         while (DEST_STRUCT_IBLOCK (i).size > 0) {
1317           int j = DEST_STRUCT_IBLOCK (i).size;
1318
1319           while (j--) {         /* TODO interlace 2 */
1320             jitc_add (jitc, "mov eax, [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
1321             jitc_add (jitc, "add eax, [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
1322             jitc_add (jitc, "mov [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
1323           }
1324           ++i;
1325         }
1326         /* process floats */
1327         i = 0;
1328         while (DEST_STRUCT_FBLOCK (i).size > 0) {
1329           int j = DEST_STRUCT_FBLOCK (i).size;
1330
1331           while (j--) {
1332             /* DEST_STRUCT_FBLOCK_VAR(i,j) += SRC_STRUCT_FBLOCK_VAR(i,j); */
1333             /* TODO */
1334           }
1335           ++i;
1336         }
1337         break;
1338       }
1339       case INSTR_SUBS_VAR_VAR:
1340       {
1341         /* process integers */
1342         int i = 0;
1343
1344         while (DEST_STRUCT_IBLOCK (i).size > 0) {
1345           int j = DEST_STRUCT_IBLOCK (i).size;
1346
1347           while (j--) {
1348             jitc_add (jitc, "mov eax, [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
1349             jitc_add (jitc, "sub eax, [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
1350             jitc_add (jitc, "mov [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
1351           }
1352           ++i;
1353         }
1354         break;
1355       }
1356       case INSTR_MULS_VAR_VAR:
1357       {
1358         /* process integers */
1359         int i = 0;
1360
1361         while (DEST_STRUCT_IBLOCK (i).size > 0) {
1362           int j = DEST_STRUCT_IBLOCK (i).size;
1363
1364           while (j--) {
1365             jitc_add (jitc, "mov  eax,  [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
1366             jitc_add (jitc, "imul eax,  [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
1367             jitc_add (jitc, "mov  [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
1368           }
1369           ++i;
1370         }
1371         break;
1372       }
1373       case INSTR_DIVS_VAR_VAR:
1374       {
1375         /* process integers */
1376         int i = 0;
1377
1378         while (DEST_STRUCT_IBLOCK (i).size > 0) {
1379           int j = DEST_STRUCT_IBLOCK (i).size;
1380
1381           while (j--) {
1382             jitc_add (jitc, "mov  eax,  [$d]", &DEST_STRUCT_IBLOCK_VAR (i, j));
1383             jitc_add (jitc, "cdq");
1384             jitc_add (jitc, "idiv [$d]", &SRC_STRUCT_IBLOCK_VAR (i, j));
1385             jitc_add (jitc, "mov  [$d], eax", &DEST_STRUCT_IBLOCK_VAR (i, j));
1386           }
1387           ++i;
1388         }
1389         break;
1390       }
1391     }
1392   }
1393
1394   JITC_ADD_LABEL (jitc, "__very_end__");
1395   jitc_add (jitc, "call $s", "__very_start__");
1396   jitc_add (jitc, "mov eax, $d", 0);
1397   jitc_validate_func (jitc);
1398 #else
1399   InstructionFlow *iflow = currentGoomSL->iflow;
1400   FastInstructionFlow *fastiflow =
1401       (FastInstructionFlow *) malloc (sizeof (FastInstructionFlow));
1402   fastiflow->mallocedInstr = calloc (number * 16, sizeof (FastInstruction));
1403   /* fastiflow->instr = (FastInstruction*)(((int)fastiflow->mallocedInstr) + 16 - (((int)fastiflow->mallocedInstr)%16)); */
1404   fastiflow->instr = (FastInstruction *) fastiflow->mallocedInstr;
1405   fastiflow->number = number;
1406   for (i = 0; i < number; ++i) {
1407     fastiflow->instr[i].id = iflow->instr[i]->id;
1408     fastiflow->instr[i].data = iflow->instr[i]->data;
1409     fastiflow->instr[i].proto = iflow->instr[i];
1410   }
1411   currentGoomSL->fastiflow = fastiflow;
1412 #endif
1413 }                               /* }}} */
1414
1415 void yy_scan_string (const char *str);
1416 void yyparse (void);
1417
1418 GoomHash *
1419 gsl_globals (GoomSL * _this)
1420 {
1421   return _this->vars;
1422 }
1423
1424
1425 /**
1426  * Some native external functions
1427  */
1428 static void
1429 ext_charAt (GoomSL * gsl, GoomHash * global, GoomHash * local)
1430 {
1431   char *string = GSL_LOCAL_PTR (gsl, local, "value");
1432   int index = GSL_LOCAL_INT (gsl, local, "index");
1433
1434   GSL_GLOBAL_INT (gsl, "charAt") = 0;
1435   if (string == NULL) {
1436     return;
1437   }
1438   if (index < strlen (string))
1439     GSL_GLOBAL_INT (gsl, "charAt") = string[index];
1440 }
1441
1442 static void
1443 ext_i2f (GoomSL * gsl, GoomHash * global, GoomHash * local)
1444 {
1445   int i = GSL_LOCAL_INT (gsl, local, "value");
1446
1447   GSL_GLOBAL_FLOAT (gsl, "i2f") = i;
1448 }
1449
1450 static void
1451 ext_f2i (GoomSL * gsl, GoomHash * global, GoomHash * local)
1452 {
1453   float f = GSL_LOCAL_FLOAT (gsl, local, "value");
1454
1455   GSL_GLOBAL_INT (gsl, "f2i") = f;
1456 }
1457
1458 /**
1459  *
1460  */
1461 void
1462 gsl_compile (GoomSL * _currentGoomSL, const char *script)
1463 {                               /* {{{ */
1464   char *script_and_externals;
1465   static const char *sBinds =
1466       "external <charAt: string value, int index> : int\n"
1467       "external <f2i: float value> : int\n"
1468       "external <i2f: int value> : float\n";
1469
1470 #ifdef VERBOSE
1471   printf ("\n=== Starting Compilation ===\n");
1472 #endif
1473
1474   script_and_externals = malloc (strlen (script) + strlen (sBinds) + 2);
1475   strcpy (script_and_externals, sBinds);
1476   strcat (script_and_externals, script);
1477
1478   /* 0- reset */
1479   currentGoomSL = _currentGoomSL;
1480   reset_scanner (currentGoomSL);
1481
1482   /* 1- create the syntaxic tree */
1483   yy_scan_string (script_and_externals);
1484   yyparse ();
1485
1486   /* 2- generate code */
1487   gsl_commit_compilation ();
1488
1489   /* 3- resolve symbols */
1490   calculate_labels (currentGoomSL->iflow);
1491
1492   /* 4- optimize code */
1493   gsl_create_fast_iflow ();
1494
1495   /* 5- bind a few internal functions */
1496   gsl_bind_function (currentGoomSL, "charAt", ext_charAt);
1497   gsl_bind_function (currentGoomSL, "f2i", ext_f2i);
1498   gsl_bind_function (currentGoomSL, "i2f", ext_i2f);
1499   free (script_and_externals);
1500
1501 #ifdef VERBOSE
1502   printf ("=== Compilation done. # of lines: %d. # of instr: %d ===\n",
1503       currentGoomSL->num_lines, currentGoomSL->iflow->number);
1504 #endif
1505 }                               /* }}} */
1506
1507 void
1508 gsl_execute (GoomSL * scanner)
1509 {                               /* {{{ */
1510   if (scanner->compilationOK) {
1511 #if USE_JITC_X86
1512     scanner->jitc_func ();
1513 #else
1514     iflow_execute (scanner->fastiflow, scanner);
1515 #endif
1516   }
1517 }                               /* }}} */
1518
1519 GoomSL *
1520 gsl_new (void)
1521 {                               /* {{{ */
1522   GoomSL *gss = (GoomSL *) malloc (sizeof (GoomSL));
1523
1524   gss->iflow = iflow_new ();
1525   gss->vars = goom_hash_new ();
1526   gss->functions = goom_hash_new ();
1527   gss->nbStructID = 0;
1528   gss->structIDS = goom_hash_new ();
1529   gss->gsl_struct_size = 32;
1530   gss->gsl_struct =
1531       (GSL_Struct **) malloc (gss->gsl_struct_size * sizeof (GSL_Struct *));
1532   gss->currentNS = 0;
1533   gss->namespaces[0] = gss->vars;
1534   gss->data_heap = goom_heap_new ();
1535
1536   reset_scanner (gss);
1537
1538   gss->compilationOK = 0;
1539   gss->nbPtr = 0;
1540   gss->ptrArraySize = 256;
1541   gss->ptrArray = (void **) malloc (gss->ptrArraySize * sizeof (void *));
1542 #ifdef USE_JITC_X86
1543   gss->jitc = NULL;
1544 #endif
1545   return gss;
1546 }                               /* }}} */
1547
1548 void
1549 gsl_bind_function (GoomSL * gss, const char *fname,
1550     GoomSL_ExternalFunction func)
1551 {                               /* {{{ */
1552   HashValue *val = goom_hash_get (gss->functions, fname);
1553
1554   if (val) {
1555     ExternalFunctionStruct *gef = (ExternalFunctionStruct *) val->ptr;
1556
1557     gef->function = func;
1558   } else
1559     fprintf (stderr, "Unable to bind function %s\n", fname);
1560 }                               /* }}} */
1561
1562 int
1563 gsl_is_compiled (GoomSL * gss)
1564 {                               /* {{{ */
1565   return gss->compilationOK;
1566 }                               /* }}} */
1567
1568 void
1569 gsl_free (GoomSL * gss)
1570 {                               /* {{{ */
1571   iflow_free (gss->iflow);
1572   free (gss->vars);
1573   free (gss->functions);
1574   free (gss);
1575 }                               /* }}} */
1576
1577
1578 static int gsl_nb_import;
1579 static char gsl_already_imported[256][256];
1580
1581 char *
1582 gsl_init_buffer (const char *fname)
1583 {
1584   char *fbuffer;
1585
1586   fbuffer = (char *) malloc (512);
1587   fbuffer[0] = 0;
1588   gsl_nb_import = 0;
1589   if (fname)
1590     gsl_append_file_to_buffer (fname, &fbuffer);
1591   return fbuffer;
1592 }
1593
1594 static char *
1595 gsl_read_file (const char *fname)
1596 {
1597   FILE *f;
1598   char *buffer;
1599   int fsize;
1600
1601   f = fopen (fname, "rt");
1602   if (!f) {
1603     fprintf (stderr, "ERROR: Could not load file %s\n", fname);
1604     exit (1);
1605   }
1606   fseek (f, 0, SEEK_END);
1607   fsize = ftell (f);
1608   rewind (f);
1609   buffer = (char *) malloc (fsize + 512);
1610   fread (buffer, 1, fsize, f);
1611   fclose (f);
1612   buffer[fsize] = 0;
1613   return buffer;
1614 }
1615
1616 void
1617 gsl_append_file_to_buffer (const char *fname, char **buffer)
1618 {
1619   char *fbuffer;
1620   int size, fsize, i = 0;
1621   char reset_msg[256];
1622
1623   /* look if the file have not been already imported */
1624   for (i = 0; i < gsl_nb_import; ++i) {
1625     if (strcmp (gsl_already_imported[i], fname) == 0)
1626       return;
1627   }
1628
1629   /* add fname to the already imported files. */
1630   strcpy (gsl_already_imported[gsl_nb_import++], fname);
1631
1632   /* load the file */
1633   fbuffer = gsl_read_file (fname);
1634   fsize = strlen (fbuffer);
1635
1636   /* look for #import */
1637   while (fbuffer[i]) {
1638     if ((fbuffer[i] == '#') && (fbuffer[i + 1] == 'i')) {
1639       char impName[256];
1640       int j;
1641
1642       while (fbuffer[i] && (fbuffer[i] != ' '))
1643         i++;
1644       i++;
1645       j = 0;
1646       while (fbuffer[i] && (fbuffer[i] != '\n'))
1647         impName[j++] = fbuffer[i++];
1648       impName[j++] = 0;
1649       gsl_append_file_to_buffer (impName, buffer);
1650     }
1651     i++;
1652   }
1653
1654   sprintf (reset_msg, "\n#FILE %s#\n#RST_LINE#\n", fname);
1655   strcat (*buffer, reset_msg);
1656   size = strlen (*buffer);
1657   *buffer = (char *) realloc (*buffer, size + fsize + 256);
1658   strcat ((*buffer) + size, fbuffer);
1659   free (fbuffer);
1660 }