home *** CD-ROM | disk | FTP | other *** search
/ hobbes.nmsu.edu 2008 / 2008-06-02_hobbes.nmsu.edu.zip / new / scummc-0.2.0-os2.zip / ScummC / src / scc_code.c < prev    next >
Encoding:
C/C++ Source or Header  |  2008-01-29  |  32.8 KB  |  1,364 lines

  1. /* ScummC
  2.  * Copyright (C) 2004-2006  Alban Bedel
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17.  *
  18.  */
  19.  
  20. /**
  21.  * @file scc_code.c
  22.  * @ingroup scc
  23.  * @brief SCUMM code generator
  24.  */
  25.  
  26. #include "config.h"
  27.  
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <inttypes.h>
  32. #include <errno.h>
  33.  
  34. #include "scc_parse.h"
  35. #include "scc_ns.h"
  36. #include "scc_util.h"
  37. #include "scc_code.h"
  38.  
  39. #define YYSTYPE int
  40. #include "scc_parse.tab.h"
  41.  
  42. scc_operator_t scc_bin_op[] = {
  43.   { '+', SCC_OP_ADD, AADD },
  44.   { '-', SCC_OP_SUB, ASUB },
  45.   { '*', SCC_OP_MUL, AMUL },
  46.   { '/', SCC_OP_DIV, ADIV },
  47.   { '&', SCC_OP_BAND, AAND },
  48.   { '|', SCC_OP_BOR,  AOR },
  49.   { LAND, SCC_OP_LAND, 0 },
  50.   { LOR, SCC_OP_LOR ,0 },
  51.   { '<', SCC_OP_L ,0 },
  52.   { LE, SCC_OP_LE ,0 },
  53.   { '>', SCC_OP_G ,0 },
  54.   { GE, SCC_OP_GE ,0 },
  55.   { EQ, SCC_OP_EQ ,0 },
  56.   { NEQ, SCC_OP_NEQ ,0 },
  57.   { 0, 0, 0 }
  58. };
  59.  
  60. struct scc_loop_st {
  61.   scc_loop_t* next;
  62.   
  63.   int type; 
  64.   int id;   
  65.   char* sym;
  66. };
  67.  
  68. static scc_loop_t *loop_stack = NULL;
  69.  
  70. scc_loop_t* scc_loop_get(int type,char* sym) {
  71.   scc_loop_t* l;
  72.  
  73.   // look for the first match
  74.   if(!sym) {
  75.     if(type == SCC_BRANCH_CONTINUE) {
  76.       // continue don't work in switch, so find the first
  77.       // non switch loop
  78.       for(l = loop_stack ; l && l->type == SCC_INST_SWITCH ; l = l->next);
  79.       return l;
  80.     }
  81.     return loop_stack;
  82.   }
  83.   
  84.   for(l = loop_stack ; l ; l = l->next) {
  85.     if(!l->sym) continue;
  86.     if(!strcmp(l->sym,sym)) {
  87.       if(type != SCC_BRANCH_CONTINUE || l->type != SCC_INST_SWITCH)
  88.         return l;
  89.     }
  90.   }
  91.   return NULL;
  92. }
  93.  
  94. void scc_loop_push(int type, char* sym) {
  95.   scc_loop_t* l;
  96.  
  97.   if(sym && scc_loop_get(SCC_BRANCH_BREAK,sym)) {
  98.     scc_log(LOG_ERR,"Warning: there is already a loop named %s in the loop stack.\n",
  99.             sym);
  100.   }
  101.  
  102.   l = calloc(1,sizeof(scc_loop_t));
  103.  
  104.   l->id = (loop_stack ? loop_stack->id : 0) + 1;
  105.   l->type = type;
  106.   l->sym = sym;
  107.  
  108.   l->next = loop_stack;
  109.   loop_stack = l;
  110. }
  111.  
  112. scc_loop_t* scc_loop_pop(void) {
  113.   scc_loop_t* l;
  114.  
  115.   if(!loop_stack) {
  116.     scc_log(LOG_ERR,"Can't pop empty loop stack.\n");
  117.     return NULL;
  118.   }
  119.  
  120.   l = loop_stack;
  121.   loop_stack = l->next;
  122.   l->next = NULL;
  123.  
  124.   return l;
  125. }
  126.  
  127. static void scc_loop_fix_code(scc_code_t* c,int br, int cont) {
  128.   scc_loop_t* l = scc_loop_pop();
  129.   int pos = 0;
  130.  
  131.   for( ; c ; c = c->next) {
  132.     pos += c->len;
  133.     if(c->fix != SCC_FIX_BRANCH) continue;
  134.     if(c->data[1] != l->id) continue;
  135.     
  136.     if(c->data[2] == SCC_BRANCH_BREAK) {
  137.       SCC_SET_S16LE(c->data,1,br - pos);
  138.     } else if(cont >= 0 && c->data[2] == SCC_BRANCH_CONTINUE) {
  139.       SCC_SET_S16LE(c->data,1,cont - pos);
  140.     } else {
  141.       SCC_SET_S16LE(c->data,1,pos);
  142.     }
  143.     c->fix = SCC_FIX_NONE;
  144.  
  145.     scc_log(LOG_DBG,"Branch fixed to 0x%hx\n",SCC_GET_16LE(c->data,1));
  146.   }
  147.  
  148.   free(l);
  149. }
  150.  
  151. static scc_operator_t* scc_get_bin_op(int op) {
  152.   int i;
  153.  
  154.   for(i = 0 ; scc_bin_op[i].scc_op ; i++){
  155.     if(scc_bin_op[i].scc_op == op)
  156.       return &scc_bin_op[i];
  157.   }
  158.  
  159.   return NULL;
  160. }
  161.  
  162. static scc_operator_t* scc_get_assign_op(int op) {
  163.   int i;
  164.  
  165.   for(i = 0 ; scc_bin_op[i].scc_op ; i++){
  166.     if(scc_bin_op[i].assign_op == op)
  167.       return &scc_bin_op[i];
  168.   }
  169.  
  170.   return NULL;
  171. }
  172.  
  173. static scc_code_t* scc_statement_gen_code(scc_statement_t* st, int ret_val);
  174.  
  175. scc_code_t* scc_code_new(int len) {
  176.   scc_code_t* c = calloc(1,sizeof(scc_code_t));
  177.  
  178.   if(len > 0) {
  179.     c->data = malloc(len);
  180.     c->len = len;
  181.   }
  182.   return c;
  183. }
  184.  
  185. void scc_code_free(scc_code_t* c) {
  186.   if(!c) return;
  187.   if(c->data) free(c->data);
  188.   free(c);
  189. }
  190.  
  191. void scc_code_free_all(scc_code_t* c) {
  192.  
  193.   while(c) {
  194.     scc_code_t* n = c->next;
  195.     scc_code_free(c);
  196.     c = n;
  197.   }    
  198.  
  199. }
  200.  
  201. static scc_code_t* scc_code_push_val(uint8_t op,uint16_t v) {
  202.   scc_code_t* code;
  203.  
  204.   if(v <= 0xFF) {
  205.     code = scc_code_new(2);
  206.     code->data[0] = op-1;
  207.     code->data[1] = v;
  208.   } else {
  209.     code = scc_code_new(3);
  210.     code->data[0] = op;
  211.     SCC_SET_16LE(code->data,1,v);
  212.   }
  213.  
  214.   return code;
  215. }
  216.  
  217. static scc_code_t* scc_code_push_res(uint8_t op,scc_symbol_t* res) {
  218.   scc_code_t* c,*d;
  219.  
  220.   // Address is alredy assigned
  221.   if(res->addr >= 0) return scc_code_push_val(op,res->addr);
  222.  
  223.   if(!res->rid) {
  224.     scc_log(LOG_ERR,"Resource %s has no assigned rid!!!!\n",res->sym);
  225.     return NULL;
  226.   }
  227.  
  228.   // no addr, so code the op and addr separatly
  229.   c = scc_code_new(1);
  230.   c->data[0] = op;
  231.   d = scc_code_new(2);
  232.   SCC_SET_16LE(d->data,0,res->rid);
  233.   d->fix = SCC_FIX_RES + res->type;
  234.   c->next = d;
  235.  
  236.   return c;
  237. }
  238.  
  239. static scc_code_t* scc_code_res_addr(int op, scc_symbol_t* res) {
  240.   scc_code_t *c,*o;
  241.  
  242.   c = scc_code_new(2);
  243.   if(res->addr >= 0) {
  244.     SCC_SET_16LE(c->data,0,res->addr);
  245.   } else {
  246.     SCC_SET_16LE(c->data,0,res->rid);
  247.     c->fix = SCC_FIX_RES + res->type;
  248.   }
  249.  
  250.   if(op < 0) return c;
  251.  
  252.   if(op > 0xFF) {
  253.     o = scc_code_new(2);
  254.     o->data[0] = op >> 8;
  255.     o->data[1] = op & 0xFF;
  256.   } else {
  257.     o = scc_code_new(1);
  258.     o->data[0] = op;
  259.   }
  260.   o->next = c;
  261.   return o;
  262. }
  263.  
  264. int scc_code_size(scc_code_t* c) {
  265.   int size = 0;
  266.   while(c) {
  267.     size += c->len;
  268.     c = c->next;
  269.   }
  270.   return size;
  271. }
  272.  
  273. static scc_code_t* scc_str_gen_code(scc_str_t* s) {
  274.   scc_code_t *code = NULL,*last = NULL,*c;
  275.  
  276.   while(s) {
  277.     switch(s->type) {
  278.     case SCC_STR_CHAR:
  279.       c = calloc(1,sizeof(scc_code_t));
  280.       c->data = strdup(s->str);
  281.       c->len = strlen(s->str);
  282.       break;
  283.     case SCC_STR_INT:
  284.     case SCC_STR_VERB:
  285.     case SCC_STR_NAME:
  286.     case SCC_STR_STR:
  287.       c = scc_code_res_addr(0xFF00 | (s->type & 0xFF),s->sym);
  288.       break;
  289.     case SCC_STR_COLOR:
  290.       c = scc_code_new(4);
  291.       c->data[0] = 0xFF;
  292.       c->data[1] = SCC_STR_COLOR;
  293.       c->data[2] = s->str[0];
  294.       c->data[3] = s->str[1];
  295.       break;
  296.     case SCC_STR_VOICE:
  297.       c = scc_code_new(2);
  298.       c->data[0] = 0xFF;
  299.       c->data[1] = SCC_STR_VOICE;
  300.       SCC_LIST_ADD(code,last,c);
  301.       c = scc_code_new(14);
  302.       SCC_SET_16LE(c->data,0,s->sym->rid);
  303.       c->fix |= SCC_FIX_RES + s->sym->type;
  304.       break;
  305.     default:
  306.       scc_log(LOG_ERR,"Got an unknown string type.\n");
  307.       break;
  308.     }
  309.     SCC_LIST_ADD(code,last,c);
  310.     s = s->next;
  311.   }
  312.  
  313.   // Append the terminal 0
  314.   c = scc_code_new(1);
  315.   c->data[0] = '\0';
  316.   SCC_LIST_ADD(code,last,c);
  317.  
  318.   return code;
  319. }
  320.  
  321. static scc_code_t* scc_statement_gen_ref_code(scc_statement_t* st) {
  322.   scc_code_t* code = NULL;
  323.  
  324.   switch(st->type) {
  325.   case SCC_ST_VAR:
  326.     code = scc_code_res_addr(-1,st->val.v.r);
  327.     break;
  328.   case SCC_ST_RES:
  329.     code = scc_code_res_addr(-1,st->val.r);
  330.     break;
  331.   case SCC_ST_VAL:
  332.     code = scc_code_new(2);
  333.     SCC_SET_16LE(code->data,0,(uint16_t)st->val.i);
  334.     break;
  335.   case SCC_ST_STR:
  336.     code = scc_str_gen_code(st->val.s);
  337.     break;
  338.   }
  339.   return code;
  340. }
  341.  
  342.  
  343. static scc_code_t* scc_call_gen_code(scc_call_t* call, int ret_val) {
  344.   scc_code_t *code = NULL,*last = NULL,*c;
  345.   scc_statement_t* a = NULL;
  346.   int n = 0;
  347.   
  348.   // Check if we need to prepend an op code
  349.   // In that case it mean the function take
  350.   // a list as argument and we must also close it
  351.   // with the number of arguments (including this one)
  352.   if(call->func->hidden_args > 0 &&
  353.      (call->func->argt[call->func->argc] & 0xFFFF) == SCC_FA_OP) {
  354.       c = scc_code_push_val(SCC_OP_PUSH,
  355.                             call->func->argt[call->func->argc]>>16);
  356.       SCC_LIST_ADD(code,last,c);
  357.   }
  358.   
  359.   // Generate arg code
  360.   for(n = 0, a = call->argv ; a ; n++, a = a->next) {
  361.     if(call->func->argt[n] & SCC_FA_REF) continue;
  362.     c = scc_statement_gen_code(a,1);
  363.     SCC_LIST_ADD(code,last,c);
  364.   }
  365.  
  366.   // Add the arguments using the default value
  367.   for( ; n < call->func->argc ; n++) {
  368.     if(call->func->argt[n] & SCC_FA_REF) continue;
  369.     if((call->func->argt[n] & 0xFFFF) != SCC_FA_VAL) continue;
  370.     c = scc_code_push_val(SCC_OP_PUSH,call->func->dfault[n]);
  371.     SCC_LIST_ADD(code,last,c);
  372.   }
  373.   
  374.   // If we had an extra op code close the list
  375.   if(call->func->hidden_args > 0 &&
  376.      (call->func->argt[call->func->argc] & 0xFFFF) == SCC_FA_OP) {
  377.     c = scc_code_push_val(SCC_OP_PUSH,n+1);
  378.     SCC_LIST_ADD(code,last,c);
  379.   }
  380.   
  381.   
  382.   if(call->func->opcode <= 0xFF) {
  383.     c = scc_code_new(1);
  384.     c->data[0] = call->func->opcode;
  385.   } else {
  386.     c = scc_code_new(2);
  387.     c->data[0] = (call->func->opcode & 0xFF00)>>8;
  388.     c->data[1] = call->func->opcode & 0xFF;
  389.   }
  390.   SCC_LIST_ADD(code,last,c);
  391.  
  392.   // add ref arguments
  393.   for(n = 0, a = call->argv ; a ; n++, a = a->next) {
  394.     if(!(call->func->argt[n] & SCC_FA_REF)) continue;
  395.     c = scc_statement_gen_ref_code(a);
  396.     SCC_LIST_ADD(code,last,c);
  397.   }
  398.  
  399.   for( ; n < call->func->argc+ call->func->hidden_args ; n++) {
  400.     // only hidden arg type atm
  401.     if(call->func->argt[n] != SCC_FA_SELF_OFF) continue;
  402.     c = scc_code_new(2);
  403.     SCC_SET_S16LE(c->data,0,-scc_code_size(code)-2);
  404.     SCC_LIST_ADD(code,last,c);
  405.   }
  406.  
  407.   if(call->user_script) {
  408.     if(ret_val) {
  409.       // Pass VAR_RETURN back
  410.       c = scc_code_push_val(SCC_OP_VAR_READ,SCC_VAR_RETURN);
  411.       SCC_LIST_ADD(code,last,c);
  412.     }
  413.   } else {
  414.     // kick the return val if it's not needed
  415.     if(call->func->ret && (!ret_val)) {
  416.       c = scc_code_new(1);
  417.       c->data[0] = SCC_OP_POP;
  418.       SCC_LIST_ADD(code,last,c);
  419.     }
  420.     if(!call->func->ret && ret_val) {
  421.       scc_log(LOG_WARN,"Warning: the function %s doesn't return anything.\n",
  422.               call->func->sym);
  423.       c = scc_code_push_val(SCC_OP_PUSH,0);
  424.       SCC_LIST_ADD(code,last,c);
  425.     }
  426.   }
  427.  
  428.   return code;
  429. }
  430.  
  431. static scc_code_t* scc_assign_gen_code(scc_op_t* op, int ret_val) {
  432.   scc_code_t *code = NULL,*last = NULL,*c;
  433.   scc_statement_t *a = op->argv, *b = op->argv->next;
  434.   scc_operator_t* oper;
  435.  
  436.   if(!a->val.v.y &&
  437.      b->type != SCC_ST_LIST &&
  438.      b->type != SCC_ST_STR) { // simple variable
  439.  
  440.     if(op->op != '=') {
  441.       c = scc_statement_gen_code(a,1);
  442.       SCC_LIST_ADD(code,last,c);
  443.     }
  444.      
  445.     c = scc_statement_gen_code(b,1);
  446.     SCC_LIST_ADD(code,last,c);
  447.  
  448.     if(op->op != '=') {
  449.       oper = scc_get_assign_op(op->op);
  450.  
  451.       c = scc_code_new(1);
  452.       c->data[0] = oper->op;
  453.       SCC_LIST_ADD(code,last,c);
  454.     }
  455.  
  456.     // dup the value to use it as return val
  457.     if(ret_val) {
  458.       c = scc_code_new(1);
  459.       c->data[0] = SCC_OP_DUP;
  460.       SCC_LIST_ADD(code,last,c);
  461.     }
  462.  
  463.     c = scc_code_push_res(SCC_OP_VAR_WRITE,a->val.v.r);
  464.     SCC_LIST_ADD(code,last,c);
  465.  
  466.     return code;
  467.   }
  468.  
  469.   // assignement to an array
  470.   switch(b->type) {
  471.   case SCC_ST_LIST:
  472.       
  473.     if(a->val.v.x) {
  474.       c = scc_statement_gen_code(a->val.v.x,1);
  475.       SCC_LIST_ADD(code,last,c);
  476.     }
  477.  
  478.     c = scc_statement_gen_code(b,1);
  479.     SCC_LIST_ADD(code,last,c);
  480.  
  481.     if(a->val.v.y)
  482.         c = scc_statement_gen_code(a->val.v.y,1);
  483.     else
  484.         c = scc_code_push_val(SCC_OP_PUSH,0);
  485.     SCC_LIST_ADD(code,last,c);
  486.       
  487.     c = scc_code_res_addr(a->val.v.x ? SCC_OP_ARRAY2_WRITE_LIST : SCC_OP_ARRAY_WRITE_LIST,
  488.                           a->val.v.r);
  489.     SCC_LIST_ADD(code,last,c);
  490.  
  491.     // put a dummy return val
  492.     if(ret_val) {
  493.       c = scc_code_push_val(SCC_OP_PUSH,1);
  494.       SCC_LIST_ADD(code,last,c);
  495.     }
  496.     break;
  497.  
  498.   case SCC_ST_STR:
  499.  
  500.     // should not happend, alredy checked in the parser
  501.     // or we should simply multiply both index ??
  502.     if(a->val.v.x)
  503.       scc_log(LOG_WARN,"Warning: strings can't be assigned to 2-dim arrays, ignoring second index.\n");
  504.  
  505.     if(a->val.v.y)
  506.         c = scc_statement_gen_code(a->val.v.y,1);
  507.     else
  508.         c = scc_code_push_val(SCC_OP_PUSH,0);
  509.     SCC_LIST_ADD(code,last,c);
  510.  
  511.     c = scc_code_res_addr(SCC_OP_ARRAY_WRITE_STR,a->val.v.r);
  512.     SCC_LIST_ADD(code,last,c);
  513.  
  514.     c = scc_str_gen_code(b->val.s);
  515.     SCC_LIST_ADD(code,last,c);
  516.  
  517.     // push a dummy return value.
  518.     if(ret_val) {
  519.       c = scc_code_push_val(SCC_OP_PUSH,1);
  520.       SCC_LIST_ADD(code,last,c);
  521.     }
  522.     break;
  523.  
  524.   default:
  525.  
  526.     // push the x index
  527.     if(a->val.v.x) {
  528.       c = scc_statement_gen_code(a->val.v.x,1);
  529.       SCC_LIST_ADD(code,last,c);
  530.     }
  531.  
  532.     // the y
  533.     c = scc_statement_gen_code(a->val.v.y,1);
  534.     SCC_LIST_ADD(code,last,c);
  535.  
  536.     // If we have an op push a
  537.     if(op->op != '=') {
  538.       c = scc_statement_gen_code(a,1);
  539.       SCC_LIST_ADD(code,last,c);
  540.     }
  541.  
  542.     // push b
  543.     c = scc_statement_gen_code(b,1);
  544.     SCC_LIST_ADD(code,last,c);
  545.  
  546.     // put the op
  547.     if(op->op != '=') {
  548.       oper = scc_get_assign_op(op->op);
  549.       
  550.       c = scc_code_new(1);
  551.       c->data[0] = oper->op;
  552.       SCC_LIST_ADD(code,last,c);
  553.     }
  554.       
  555.     if(a->val.v.x)
  556.       c = scc_code_push_res(SCC_OP_ARRAY2_WRITE,a->val.v.r);
  557.     else
  558.       c = scc_code_push_res(SCC_OP_ARRAY_WRITE,a->val.v.r);
  559.     SCC_LIST_ADD(code,last,c);
  560.  
  561.     // put a dummy return val
  562.     if(ret_val) {
  563.       c = scc_code_push_val(SCC_OP_PUSH,1);
  564.       SCC_LIST_ADD(code,last,c);
  565.     }
  566.     break;
  567.   }
  568.  
  569.   return code;
  570. }
  571.  
  572. static scc_code_t* scc_bop_gen_code(scc_op_t* op, int ret_val) {
  573.   scc_code_t *code = NULL,*last = NULL,*c;
  574.   scc_statement_t *a = op->argv, *b = op->argv->next;
  575.   scc_operator_t* oper = scc_get_bin_op(op->op);
  576.   
  577.   if(!oper) {
  578.     scc_log(LOG_ERR,"Got unhandled binary operator.\n");
  579.     return NULL;
  580.   }
  581.  
  582.   c = scc_statement_gen_code(a,1);
  583.   SCC_LIST_ADD(code,last,c);
  584.   c = scc_statement_gen_code(b,1);
  585.   SCC_LIST_ADD(code,last,c);
  586.   
  587.   c = scc_code_new(1);
  588.   c->data[0] = oper->op;
  589.   SCC_LIST_ADD(code,last,c);  
  590.  
  591.   if(!ret_val) {
  592.     c = scc_code_new(1);
  593.     c->data[0] = SCC_OP_POP;
  594.     SCC_LIST_ADD(code,last,c);
  595.   }
  596.  
  597.   return code;
  598. }
  599.  
  600. static scc_code_t* scc_uop_gen_code(scc_op_t* op, int ret_val) {
  601.   scc_code_t *code = NULL,*last = NULL,*c;
  602.   int o;
  603.  
  604.   switch(op->op) {
  605.   case '-':
  606.     c = scc_statement_gen_code(op->argv,ret_val);
  607.     SCC_LIST_ADD(code,last,c);
  608.     if(!ret_val) break;
  609.  
  610.     c = scc_code_push_val(SCC_OP_PUSH,-1);
  611.     SCC_LIST_ADD(code,last,c);
  612.  
  613.     c = scc_code_new(1);
  614.     c->data[0] = SCC_OP_MUL;
  615.     SCC_LIST_ADD(code,last,c);
  616.     break;
  617.   case '!':
  618.     c = scc_statement_gen_code(op->argv,ret_val);
  619.     SCC_LIST_ADD(code,last,c);
  620.     if(!ret_val) break;
  621.  
  622.     c = scc_code_new(1);
  623.     c->data[0] = SCC_OP_NOT;
  624.     SCC_LIST_ADD(code,last,c);
  625.     break;
  626.   case PREINC:
  627.   case PREDEC:
  628.     if(op->argv->val.v.y) {
  629.       if(op->argv->val.v.x) {
  630.         // push the index for the final write
  631.         c = scc_statement_gen_code(op->argv->val.v.x,1);
  632.         SCC_LIST_ADD(code,last,c);
  633.         c = scc_statement_gen_code(op->argv->val.v.y,1);
  634.         SCC_LIST_ADD(code,last,c);
  635.  
  636.         // for 2dim array we have to expand to a full addition
  637.         // push the x index and choose the op we need
  638.         c = scc_statement_gen_code(op->argv->val.v.x,1);
  639.         SCC_LIST_ADD(code,last,c);
  640.         o = (op->op == PREINC ? SCC_OP_ADD : SCC_OP_SUB);
  641.       } else
  642.         o = (op->op == PREINC ? SCC_OP_INC_ARRAY : SCC_OP_DEC_ARRAY);
  643.  
  644.       // push the index
  645.       c = scc_statement_gen_code(op->argv->val.v.y,1);
  646.       SCC_LIST_ADD(code,last,c);
  647.  
  648.     } else
  649.       o = (op->op == PREINC ? SCC_OP_INC_VAR : SCC_OP_DEC_VAR);
  650.  
  651.     if(op->argv->val.v.x) {
  652.       // push the array entry on the stack
  653.       c = scc_code_push_res(SCC_OP_ARRAY2_READ,op->argv->val.v.r);
  654.       SCC_LIST_ADD(code,last,c);
  655.       // push a 1
  656.       c = scc_code_push_val(SCC_OP_PUSH,1);
  657.       SCC_LIST_ADD(code,last,c);
  658.  
  659.       // push the op
  660.       c = scc_code_new(1);
  661.       c->data[0] = o;
  662.       SCC_LIST_ADD(code,last,c);
  663.       // put the result back into the variable
  664.       c = scc_code_push_res(SCC_OP_ARRAY2_WRITE,op->argv->val.v.r);
  665.     } else  // put the opcode
  666.       c = scc_code_push_res(o,op->argv->val.v.r);
  667.     SCC_LIST_ADD(code,last,c);
  668.     if(!ret_val) break;
  669.     c = scc_statement_gen_code(op->argv,1);
  670.     SCC_LIST_ADD(code,last,c);
  671.     break;
  672.   case POSTINC:
  673.   case POSTDEC:
  674.     if(ret_val) {
  675.       c = scc_statement_gen_code(op->argv,1);
  676.       SCC_LIST_ADD(code,last,c);
  677.     }
  678.     if(op->argv->val.v.y) {
  679.       if(op->argv->val.v.x) {
  680.         // push the index for the final write
  681.         c = scc_statement_gen_code(op->argv->val.v.x,1);
  682.         SCC_LIST_ADD(code,last,c);
  683.         c = scc_statement_gen_code(op->argv->val.v.y,1);
  684.         SCC_LIST_ADD(code,last,c);
  685.  
  686.         // for 2dim array we have to expand to a full addition
  687.         // push the x index and choose the op we need
  688.         c = scc_statement_gen_code(op->argv->val.v.x,1);
  689.         SCC_LIST_ADD(code,last,c);
  690.         o = (op->op == POSTINC ? SCC_OP_ADD : SCC_OP_SUB);
  691.       } else
  692.         o = (op->op == POSTINC ? SCC_OP_INC_ARRAY : SCC_OP_DEC_ARRAY);
  693.  
  694.       // push the index
  695.       c = scc_statement_gen_code(op->argv->val.v.y,1);
  696.       SCC_LIST_ADD(code,last,c);
  697.     } else
  698.       o = (op->op == POSTINC ? SCC_OP_INC_VAR : SCC_OP_DEC_VAR);
  699.  
  700.     if(op->argv->val.v.x) {
  701.       // push the array entry on the stack
  702.       c = scc_code_push_res(SCC_OP_ARRAY2_READ,op->argv->val.v.r);
  703.       SCC_LIST_ADD(code,last,c);
  704.       // push a 1
  705.       c = scc_code_push_val(SCC_OP_PUSH,1);
  706.       SCC_LIST_ADD(code,last,c);
  707.  
  708.       // push the op
  709.       c = scc_code_new(1);
  710.       c->data[0] = o;
  711.       SCC_LIST_ADD(code,last,c);
  712.       // put the result back into the variable
  713.       c = scc_code_push_res(SCC_OP_ARRAY2_WRITE,op->argv->val.v.r);
  714.     } else
  715.       c = scc_code_push_res(o,op->argv->val.v.r);
  716.     SCC_LIST_ADD(code,last,c);
  717.     break;
  718.   default:
  719.     scc_log(LOG_ERR,"Got unhandled unary operator: %c\n",op->op);
  720.     return NULL;
  721.   }
  722.  
  723.   return code;
  724. }
  725.  
  726. static scc_code_t* scc_top_gen_code(scc_op_t* op, int ret_val) {
  727.   scc_code_t *code = NULL,*last = NULL,*c;
  728.   scc_code_t *cb,*cc;
  729.   scc_statement_t *a,*x,*y;
  730.   int lb,lc;
  731.  
  732.   a = op->argv; x = a->next; y = x->next;
  733.  
  734.   cb = scc_statement_gen_code(x,ret_val);
  735.   lb = scc_code_size(cb);
  736.   cc = scc_statement_gen_code(y,ret_val);
  737.   lc = scc_code_size(cc);
  738.  
  739.   if(lb + lc == 0) {
  740.     if(ret_val)
  741.       scc_log(LOG_ERR,"Something went badly wrong.\n");
  742.     return NULL;
  743.   }
  744.  
  745.   // gen the condition value code
  746.   c = scc_statement_gen_code(a,1);
  747.   SCC_LIST_ADD(code,last,c);
  748.  
  749.   // if
  750.   c = scc_code_new(3);
  751.   c->data[0] = SCC_OP_JZ;
  752.   SCC_SET_S16LE(c->data,1,scc_code_size(cb) + 3);
  753.   SCC_LIST_ADD(code,last,c);
  754.  
  755.   SCC_LIST_ADD(code,last,cb);
  756.  
  757.   c = scc_code_new(3);
  758.   c->data[0] = SCC_OP_JMP;
  759.   SCC_SET_S16LE(c->data,1,scc_code_size(cc));
  760.   SCC_LIST_ADD(code,last,c);
  761.   
  762.   SCC_LIST_ADD(code,last,cc);
  763.  
  764.   return code;
  765. }
  766.  
  767. static scc_code_t* scc_op_gen_code(scc_op_t* op, int ret_val) {
  768.   scc_code_t *code = NULL; //,*last = NULL,*c;
  769.  
  770.   switch(op->type) {
  771.   case SCC_OT_ASSIGN:
  772.     code = scc_assign_gen_code(op,ret_val);
  773.     break;
  774.   case SCC_OT_BINARY:
  775.     code = scc_bop_gen_code(op,ret_val);
  776.     break;
  777.   case SCC_OT_UNARY:
  778.     code = scc_uop_gen_code(op,ret_val);
  779.     break;
  780.   case SCC_OT_TERNARY:
  781.     code = scc_top_gen_code(op,ret_val);
  782.     break;
  783.   default:
  784.     scc_log(LOG_ERR,"Got unhandled op %c (%d)\n",op->op,op->op);
  785.   }
  786.  
  787.   return code;
  788. }
  789.  
  790. static scc_code_t* scc_statement_gen_code(scc_statement_t* st, int ret_val) {
  791.   scc_code_t *code = NULL,*last = NULL,*c;
  792.   scc_statement_t* a = NULL;
  793.   int n = 0;
  794.  
  795.   switch(st->type) {
  796.   case SCC_ST_VAL:
  797.     if(ret_val) {
  798.       c = scc_code_push_val(SCC_OP_PUSH,st->val.i);
  799.       SCC_LIST_ADD(code,last,c);
  800.     }
  801.     break;
  802.   case SCC_ST_RES:
  803.     if(ret_val) {
  804.       c = scc_code_push_res(SCC_OP_PUSH,st->val.r);
  805.       SCC_LIST_ADD(code,last,c);
  806.     }
  807.     break;
  808.   case SCC_ST_CALL:
  809.     c = scc_call_gen_code(&st->val.c,ret_val);
  810.     SCC_LIST_ADD(code,last,c);
  811.     break;
  812.   case SCC_ST_LIST:
  813.     if(!ret_val) break;
  814.     // count the elements
  815.     //for(a = st->val.l ; a ; a = a->next) n++;
  816.     
  817.     // gen their code and count the elements
  818.     for(a = st->val.l ; a ; a = a->next) {
  819.       c = scc_statement_gen_code(a,1);
  820.       SCC_LIST_ADD(code,last,c);
  821.       n++;
  822.     }
  823.     // push the number of element
  824.     c = scc_code_push_val(SCC_OP_PUSH,n);
  825.     SCC_LIST_ADD(code,last,c);
  826.     break;
  827.   case SCC_ST_VAR:
  828.     if(!ret_val) break;
  829.  
  830.     if(st->val.v.y) {
  831.       // push x value
  832.       if(st->val.v.x) {
  833.         c = scc_statement_gen_code(st->val.v.x,1);
  834.         SCC_LIST_ADD(code,last,c);
  835.       }
  836.       // push y value
  837.       c = scc_statement_gen_code(st->val.v.y,1);
  838.       SCC_LIST_ADD(code,last,c);
  839.       // op code
  840.       c = scc_code_push_res(st->val.v.x ? SCC_OP_ARRAY2_READ  : SCC_OP_ARRAY_READ,
  841.                             st->val.v.r);
  842.       SCC_LIST_ADD(code,last,c);
  843.     } else {
  844.       c = scc_code_push_res(SCC_OP_VAR_READ,st->val.v.r);
  845.       SCC_LIST_ADD(code,last,c);
  846.     }
  847.     break;
  848.   case SCC_ST_OP:
  849.     c = scc_op_gen_code(&st->val.o,ret_val);
  850.     SCC_LIST_ADD(code,last,c);
  851.     break;
  852.   case SCC_ST_CHAIN:
  853.     // gen the code for each element
  854.     // only the last one one should potentialy return a value
  855.     for(a = st->val.l ; a ; a = a->next) {
  856.       c = scc_statement_gen_code(a,a->next ? 0 : ret_val);
  857.       SCC_LIST_ADD(code,last,c);
  858.     }
  859.     break;
  860.   default:
  861.     scc_log(LOG_ERR,"Got unhandled statement type: %d\n",st->type);
  862.   }
  863.  
  864.   return code;
  865.  
  866. }
  867.  
  868. static scc_code_t* scc_instruct_gen_code(scc_instruct_t* inst);
  869. static scc_code_t* scc_branch_gen_code(scc_instruct_t* inst);
  870.  
  871. static scc_code_t* scc_if_gen_code(scc_instruct_t* inst) {
  872.   scc_code_t *code=NULL,*last=NULL,*c;
  873.   scc_code_t *a = NULL;
  874.   int len = 0;
  875.  
  876.   // gen the condition value code
  877.   c = scc_statement_gen_code(inst->cond,1);
  878.   SCC_LIST_ADD(code,last,c);
  879.  
  880.   // Optimize out the branch instructions, they all generate a jump
  881.   if(inst->body->type == SCC_INST_BRANCH &&
  882.      inst->body->subtype != SCC_BRANCH_RETURN) {
  883.     // get the code
  884.     c = scc_branch_gen_code(inst->body);
  885.     // set our condition instead of the unconditional jmp
  886.     c->data[0] = inst->subtype ? SCC_OP_JZ : SCC_OP_JNZ;
  887.     SCC_LIST_ADD(code,last,c);
  888.   } else {  
  889.     // gen the if body code so we can know how big it is
  890.     a = scc_instruct_gen_code(inst->body);
  891.     len = scc_code_size(a);
  892.     // if we have an else block we need to add a jump at the
  893.     // end of the first body
  894.     if(inst->body2) len += 3;
  895.  
  896.     // if
  897.     c = scc_code_new(3);
  898.     c->data[0] = inst->subtype ? SCC_OP_JNZ : SCC_OP_JZ;
  899.  
  900.     SCC_SET_S16LE(c->data,1,len);
  901.     SCC_LIST_ADD(code,last,c);
  902.     // body 1
  903.     SCC_LIST_ADD(code,last,a);
  904.   }
  905.  
  906.   // else
  907.   if(inst->body2) {
  908.  
  909.  
  910.     // we need the size of the else block to jump above it
  911.     // at the end of the if block
  912.     a = scc_instruct_gen_code(inst->body2);
  913.  
  914.     // If we optimized a branch inst we don't have a first body
  915.     // so we don't need a jump after it
  916.     if(len) {
  917.       // endif :)
  918.       c = scc_code_new(3);
  919.       c->data[0] = SCC_OP_JMP;
  920.       SCC_SET_S16LE(c->data,1,scc_code_size(a));
  921.       SCC_LIST_ADD(code,last,c);
  922.     }
  923.  
  924.     // body 2
  925.     SCC_LIST_ADD(code,last,a);
  926.   }
  927.   return code;
  928. }
  929.  
  930. static scc_code_t* scc_for_gen_code(scc_instruct_t* inst) {
  931.   scc_code_t *code=NULL,*last=NULL,*c;
  932.   scc_code_t *loop,*body,*post = NULL;
  933.   int cont;
  934.  
  935.   // push the loop context
  936.   scc_loop_push(inst->type,inst->sym);
  937.  
  938.   body = scc_instruct_gen_code(inst->body);
  939.   if(inst->post)
  940.       post = scc_statement_gen_code(inst->post,0);
  941.  
  942.   // pre
  943.   if(inst->pre) {
  944.       c = scc_statement_gen_code(inst->pre,0);
  945.       SCC_LIST_ADD(code,last,c);
  946.   }
  947.  
  948.   // cond  
  949.   loop = c = scc_statement_gen_code(inst->cond,1);
  950.   SCC_LIST_ADD(code,last,c);
  951.  
  952.   c = scc_code_new(3);
  953.   c->data[0] = SCC_OP_JZ;
  954.   SCC_SET_S16LE(c->data,1,scc_code_size(body) + scc_code_size(post) + 3);
  955.   SCC_LIST_ADD(code,last,c);
  956.  
  957.   // body
  958.   SCC_LIST_ADD(code,last,body);
  959.   // post
  960.   cont = scc_code_size(code);
  961.   SCC_LIST_ADD(code,last,post);
  962.  
  963.   c = scc_code_new(3);
  964.   c->data[0] = SCC_OP_JMP;
  965.   SCC_LIST_ADD(code,last,c);
  966.  
  967.   SCC_SET_S16LE(c->data,1, - scc_code_size(loop));
  968.  
  969.   //  br = scc_code_size(code);
  970.  
  971.   scc_loop_fix_code(code,scc_code_size(code),cont);
  972.  
  973.   return code;
  974. }
  975.  
  976. static scc_code_t* scc_while_gen_code(scc_instruct_t* inst) {
  977.   scc_code_t *code=NULL,*last=NULL,*c;
  978.   scc_code_t *body;
  979.  
  980.   // push the loop context
  981.   scc_loop_push(inst->type,inst->sym);
  982.  
  983.   body = scc_instruct_gen_code(inst->body);
  984.  
  985.   // cond
  986.   c = scc_statement_gen_code(inst->cond,1);
  987.   SCC_LIST_ADD(code,last,c);
  988.  
  989.   c = scc_code_new(3);
  990.   c->data[0] = inst->subtype ? SCC_OP_JNZ : SCC_OP_JZ;
  991.   SCC_SET_S16LE(c->data,1, scc_code_size(body) + 3);
  992.   SCC_LIST_ADD(code,last,c);
  993.  
  994.   // body
  995.   SCC_LIST_ADD(code,last,body);
  996.  
  997.   c = scc_code_new(3);
  998.   c->data[0] = SCC_OP_JMP;
  999.   SCC_LIST_ADD(code,last,c);
  1000.  
  1001.   SCC_SET_S16LE(c->data,1, - scc_code_size(code));
  1002.  
  1003.   scc_loop_fix_code(code,scc_code_size(code),0);
  1004.  
  1005.   return code;
  1006. }
  1007.  
  1008.  
  1009. static scc_code_t* scc_do_gen_code(scc_instruct_t* inst) {
  1010.   scc_code_t *code=NULL,*last=NULL,*c;
  1011.   int cont;
  1012.   // push the loop context
  1013.   scc_loop_push(inst->type,inst->sym);
  1014.  
  1015.   // body
  1016.   c = scc_instruct_gen_code(inst->body);
  1017.   SCC_LIST_ADD(code,last,c);
  1018.   cont = scc_code_size(c);
  1019.  
  1020.   // cond
  1021.   c = scc_statement_gen_code(inst->cond,1);
  1022.   SCC_LIST_ADD(code,last,c);
  1023.  
  1024.   c = scc_code_new(3);
  1025.   c->data[0] = inst->subtype ? SCC_OP_JZ : SCC_OP_JNZ;
  1026.   SCC_LIST_ADD(code,last,c);
  1027.  
  1028.   SCC_SET_S16LE(c->data,1, -scc_code_size(code));
  1029.  
  1030.   scc_loop_fix_code(code,scc_code_size(code),cont);
  1031.  
  1032.   return code;
  1033. }
  1034.  
  1035. static scc_code_t* scc_branch_gen_code(scc_instruct_t* inst) {
  1036.   scc_code_t *code=NULL,*last=NULL,*c;
  1037.   scc_loop_t* l;
  1038.  
  1039.   if(inst->subtype == SCC_BRANCH_RETURN) {
  1040.     if(inst->pre) {
  1041.       c = scc_statement_gen_code(inst->pre,1);
  1042.       SCC_LIST_ADD(code,last,c);
  1043.       c = scc_code_push_val(SCC_OP_VAR_WRITE,SCC_VAR_RETURN);
  1044.       SCC_LIST_ADD(code,last,c);
  1045.     }
  1046.     c = scc_code_new(1);
  1047.     c->data[0] = SCC_OP_SCR_RET;
  1048.     c->fix = SCC_FIX_RETURN;
  1049.     SCC_LIST_ADD(code,last,c);
  1050.     return code;
  1051.   }
  1052.  
  1053.   if(!loop_stack) {
  1054.     scc_log(LOG_ERR,"Branching instructions can't be used outside of loops.\n");
  1055.     return NULL;
  1056.   }
  1057.  
  1058.   l = scc_loop_get(inst->subtype,inst->sym);
  1059.   if(!l) {
  1060.     scc_log(LOG_ERR,"No loop named %s was found in the loop stack.\n",
  1061.        inst->sym);
  1062.     return NULL;
  1063.   }
  1064.  
  1065.   if(l->type == SCC_INST_SWITCH && inst->subtype == SCC_BRANCH_CONTINUE) {
  1066.     scc_log(LOG_ERR,"Continue is not allowed in switch blocks.\n");
  1067.     return NULL;
  1068.   }
  1069.  
  1070.   c = scc_code_new(3);
  1071.   c->fix = SCC_FIX_BRANCH;
  1072.   c->data[0] = SCC_OP_JMP;
  1073.   c->data[1] = l->id;
  1074.   c->data[2] = inst->subtype;
  1075.   
  1076.   
  1077.   return c;
  1078. }
  1079.  
  1080. static scc_code_t* scc_switch_gen_code(scc_instruct_t* inst) {
  1081.   scc_code_t *code=NULL,*last=NULL,*c;
  1082.   scc_code_t *cond_code,*body_code;
  1083.   scc_instruct_t *i = inst->body, *i0 = NULL;
  1084.   scc_statement_t* cond = i->cond;
  1085.   int add_jmp = 0;
  1086.  
  1087.   // gen the switched value code, if we have some conditions
  1088.   if(cond) {
  1089.     c = scc_statement_gen_code(inst->cond,1);
  1090.     SCC_LIST_ADD(code,last,c);
  1091.   }
  1092.  
  1093.   // push the loop context
  1094.   scc_loop_push(inst->type,inst->sym);
  1095.  
  1096.   // generate the first condition code
  1097.   if(cond)
  1098.     cond_code = scc_statement_gen_code(cond,1);
  1099.  
  1100.   while(cond) {
  1101.  
  1102.     // dup the switched value
  1103.     c = scc_code_new(1);
  1104.     c->data[0] = SCC_OP_DUP;
  1105.     SCC_LIST_ADD(code,last,c);
  1106.     // put the condition
  1107.     SCC_LIST_ADD(code,last,cond_code);
  1108.     // if
  1109.     c = scc_code_new(4);
  1110.     c->data[0] = SCC_OP_NEQ;
  1111.     c->data[1] = SCC_OP_JNZ;
  1112.  
  1113.     // there's a next condition, so we'll add a jump
  1114.     // instead of a real body
  1115.     if(cond->next) {
  1116.       add_jmp = 1;
  1117.       SCC_SET_S16LE(c->data,2,1 /*kill*/ + 3 /*jmp*/);
  1118.  
  1119.     } else { // that's the last condition so put the body
  1120. #if 1
  1121.       // look if the last instruction is a break, if so spare the
  1122.       // useless jump.
  1123.       // here and under we could probably stop at the first break found
  1124.       for(i0 = i->body ; i0 && i0->next ; i0 = i0->next);
  1125.       if(i0 && i0->type == SCC_INST_BRANCH && 
  1126.      i0->subtype == SCC_BRANCH_BREAK)
  1127.     add_jmp = 0;
  1128.       else
  1129. #endif
  1130.     add_jmp = 1;
  1131.       
  1132.       body_code = scc_instruct_gen_code(i->body);
  1133.       
  1134.       SCC_SET_S16LE(c->data,2,scc_code_size(body_code) + 1 + (add_jmp ? 3 : 0));
  1135.     }
  1136.     SCC_LIST_ADD(code,last,c);
  1137.  
  1138.     // kill the switched value before entering the body
  1139.     c = scc_code_new(1);
  1140.     c->data[0] = SCC_OP_POP;
  1141.     SCC_LIST_ADD(code,last,c);
  1142.  
  1143.     if(!cond->next) {
  1144.       // no next condition, add the body
  1145.       SCC_LIST_ADD(code,last,body_code);
  1146.  
  1147.       // find the next condition
  1148.       i = i->next;
  1149.       if(i)
  1150.     cond = i->cond;
  1151.       else
  1152.     cond = NULL;
  1153.     } else
  1154.       cond = cond->next;
  1155.  
  1156.     // generate the code for the next condition so we can get its size
  1157.     if(cond) cond_code = scc_statement_gen_code(cond,1);
  1158.  
  1159.     // if needed add the jump to the next block
  1160.     if(add_jmp) {
  1161.       c = scc_code_new(3);
  1162.       c->data[0] = SCC_OP_JMP;
  1163.       SCC_SET_S16LE(c->data,1,1 + (cond ? scc_code_size(cond_code) + 4 + 1 : 0));
  1164.       SCC_LIST_ADD(code,last,c);
  1165.     }
  1166.     if(!cond && i) break;
  1167.   }
  1168.  
  1169.   // the "final" kill is not needed if we had no condition at all
  1170.   if(inst->body->cond) {
  1171.     c = scc_code_new(1);
  1172.     c->data[0] = SCC_OP_POP;
  1173.     SCC_LIST_ADD(code,last,c);
  1174.   }
  1175.  
  1176.   // default
  1177.   if(i) {
  1178.     scc_instruct_t* i1 = NULL;
  1179.     for(i0 = i->body ; i0 && i0->next ; i1 = i0, i0 = i0->next);
  1180.     if(i0 && i0->type == SCC_INST_BRANCH &&
  1181.        i0->subtype == SCC_BRANCH_BREAK) {
  1182.       if(i1)
  1183.     i1->next = NULL;
  1184.       else
  1185.     i->body = NULL;
  1186.       free(i0); // check me
  1187.     }
  1188.     
  1189.     if(i->body) {
  1190.       c = scc_instruct_gen_code(i->body);
  1191.       SCC_LIST_ADD(code,last,c);
  1192.     }
  1193.   }
  1194.   
  1195.   scc_loop_fix_code(code,scc_code_size(code),-1);
  1196.  
  1197.  
  1198.   return code;
  1199. }
  1200.  
  1201. static scc_code_t* scc_cutscene_gen_code(scc_instruct_t* inst) {
  1202.     scc_code_t *code=NULL,*last=NULL,*c;
  1203.     scc_statement_t* st;
  1204.     int n;
  1205.  
  1206.     // generate the argument list
  1207.     for(st = inst->cond, n=0 ; st ; st = st->next) {
  1208.         c = scc_statement_gen_code(st,1);
  1209.         SCC_LIST_ADD(code,last,c);
  1210.         n++;
  1211.     }
  1212.     // push the number of element
  1213.     c = scc_code_push_val(SCC_OP_PUSH,n);
  1214.     SCC_LIST_ADD(code,last,c);
  1215.     // put the cutscene begin op code
  1216.     c = scc_code_new(1);
  1217.     c->data[0] = SCC_OP_CUTSCENE_BEGIN;
  1218.     SCC_LIST_ADD(code,last,c);
  1219.     // add the body code
  1220.     c = scc_instruct_gen_code(inst->body);
  1221.     SCC_LIST_ADD(code,last,c);
  1222.     // put the cutscene end op code
  1223.     c = scc_code_new(1);
  1224.     c->data[0] = SCC_OP_CUTSCENE_END;
  1225.     SCC_LIST_ADD(code,last,c);
  1226.  
  1227.     return code;
  1228. }
  1229.  
  1230. static scc_code_t* scc_override_gen_code(scc_instruct_t* inst) {
  1231.   scc_code_t *code=NULL,*last=NULL,*c;
  1232.   scc_code_t *try;
  1233.   int try_size;
  1234.  
  1235.   // generate the code in the try block
  1236.   try = scc_instruct_gen_code(inst->body);
  1237.   try_size = scc_code_size(try);
  1238.  
  1239.   // make the override op
  1240.   c = scc_code_new(4);
  1241.   c->data[0] = SCC_OP_OVERRIDE_BEGIN;
  1242.   c->data[1] = SCC_OP_JMP;
  1243.   SCC_SET_S16LE(c->data,2,try_size);
  1244.   SCC_LIST_ADD(code,last,c);
  1245.  
  1246.   // append the try code
  1247.   SCC_LIST_ADD(code,last,try);
  1248.  
  1249.   // then the override block
  1250.   c = scc_instruct_gen_code(inst->body2);
  1251.   SCC_LIST_ADD(code,last,c);
  1252.  
  1253.   // end the block
  1254.   c = scc_code_new(1);
  1255.   c->data[0] = SCC_OP_OVERRIDE_END;
  1256.   SCC_LIST_ADD(code,last,c);
  1257.  
  1258.   return code;
  1259. }
  1260.  
  1261. static scc_code_t* scc_instruct_gen_code(scc_instruct_t* inst) {
  1262.   scc_code_t *code=NULL,*last=NULL,*c;
  1263.  
  1264.   for( ; inst ; inst = inst->next ) {
  1265.     switch(inst->type) {
  1266.     case SCC_INST_ST:
  1267.       c = scc_statement_gen_code(inst->pre,0);
  1268.       break;
  1269.     case SCC_INST_IF:
  1270.       c = scc_if_gen_code(inst);
  1271.       break;
  1272.     case SCC_INST_FOR:
  1273.       c = scc_for_gen_code(inst);
  1274.       break;
  1275.     case SCC_INST_WHILE:
  1276.       c = scc_while_gen_code(inst);
  1277.       break;
  1278.     case SCC_INST_DO:
  1279.       c = scc_do_gen_code(inst);
  1280.       break;
  1281.     case SCC_INST_BRANCH:
  1282.       c = scc_branch_gen_code(inst);
  1283.       break;
  1284.     case SCC_INST_SWITCH:
  1285.       c = scc_switch_gen_code(inst);
  1286.       break;
  1287.     case SCC_INST_CUTSCENE:
  1288.       c = scc_cutscene_gen_code(inst);
  1289.       break;
  1290.     case SCC_INST_OVERRIDE:
  1291.       c = scc_override_gen_code(inst);
  1292.       break;
  1293.     default:
  1294.       scc_log(LOG_ERR,"Unsupported instruction type: %d\n",inst->type);
  1295.       c = NULL;
  1296.     }
  1297.     SCC_LIST_ADD(code,last,c);
  1298.   }
  1299.  
  1300.   return code;
  1301. }
  1302.  
  1303. scc_script_t* scc_script_new(scc_ns_t* ns, scc_instruct_t* inst,
  1304.                              uint8_t return_op,char close_scr) {
  1305.   scc_code_t* code = scc_instruct_gen_code(inst);
  1306.   scc_sym_fix_t* rf = NULL, *rf_last = NULL, *r;
  1307.   scc_symbol_t* sym;
  1308.   int p,l;
  1309.   uint8_t* data;
  1310.   scc_script_t* scr;
  1311.   
  1312.   if(!code) return NULL;
  1313.  
  1314.   l = scc_code_size(code) + (close_scr ? 1 : 0);
  1315.   data = malloc(l);
  1316.  
  1317.   for(p = 0 ; code ; p+= code->len, code = code->next) {
  1318.     memcpy(&data[p],code->data,code->len);
  1319.     if(code->fix == SCC_FIX_RETURN) {
  1320.       data[p] = return_op;
  1321.       continue;
  1322.     }
  1323.     if(code->fix >= SCC_FIX_RES) {
  1324.       uint16_t rid = SCC_GET_16LE(data,p);
  1325.       sym = scc_ns_get_sym_with_id(ns,code->fix - SCC_FIX_RES,rid);
  1326.       if(!sym) {
  1327.     scc_log(LOG_ERR,"Unable to find resource %d of type %d\n",
  1328.                 rid,code->fix - SCC_FIX_RES);
  1329.     continue;
  1330.       }
  1331.       r = calloc(1,sizeof(scc_sym_fix_t));
  1332.       r->off = p;
  1333.       r->sym = sym;
  1334.       SCC_LIST_ADD(rf,rf_last,r);
  1335.     }
  1336.   }
  1337.  
  1338.   if(close_scr) data[l-1] = return_op;
  1339.  
  1340.   scr = calloc(1,sizeof(scc_script_t));
  1341.   scr->code = data;
  1342.   scr->code_len = l;
  1343.   scr->sym_fix = rf;
  1344.  
  1345.   return scr;
  1346. }
  1347.  
  1348. void scc_script_free(scc_script_t* scr) {
  1349.  
  1350.   if(scr->code) free(scr->code);
  1351.   free(scr);
  1352. }
  1353.  
  1354. void scc_script_list_free(scc_script_t* scr) {
  1355.   scc_script_t* n;
  1356.  
  1357.   while(scr) {
  1358.     n = scr->next;
  1359.     scc_script_free(scr);
  1360.     scr = n;
  1361.   }
  1362.  
  1363. }
  1364.