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_ns.c < prev    next >
Encoding:
C/C++ Source or Header  |  2008-02-03  |  12.5 KB  |  547 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_ns.c
  22.  * @ingroup scc sld
  23.  * @brief ScummC namespace
  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_util.h"
  35. #include "scc_parse.h"
  36. #include "scc_ns.h"
  37.  
  38.  
  39. void scc_symbol_list_free(scc_symbol_t* s);
  40.  
  41. void scc_symbol_free(scc_symbol_t* s) {
  42.   if(s->sym) free(s->sym);
  43.   if(s->childs) scc_symbol_list_free(s->childs);
  44.   free(s);
  45. }
  46.  
  47. void scc_symbol_list_free(scc_symbol_t* s) {
  48.   scc_symbol_t* n;
  49.  
  50.   while(s) {
  51.     n = s->next;
  52.     scc_symbol_free(s);
  53.     s = n;
  54.   }
  55. }
  56.  
  57. int scc_sym_is_var(int type) {
  58.   if(type == SCC_RES_VAR ||
  59.      type == SCC_RES_BVAR ||
  60.      type == SCC_RES_LVAR)
  61.     return 1;
  62.   return 0;
  63. }
  64.  
  65. int scc_sym_is_global(int type) {
  66.   if(type == SCC_RES_VAR ||
  67.      type == SCC_RES_BVAR ||
  68.      type == SCC_RES_ROOM ||
  69.      type == SCC_RES_VERB ||
  70.      type == SCC_RES_ACTOR ||
  71.      type == SCC_RES_CLASS)
  72.     return 1;
  73.   return 0;
  74. }
  75.  
  76. int scc_sym_is_only_global(int type) {
  77.   if(type == SCC_RES_ROOM ||
  78.      type == SCC_RES_VERB ||
  79.      type == SCC_RES_ACTOR ||
  80.      type == SCC_RES_CLASS)
  81.     return 1;
  82.   return 0;
  83. }
  84.  
  85. scc_ns_t* scc_ns_new(scc_target_t* target) {
  86.   scc_ns_t* ns = calloc(1,sizeof(scc_ns_t));
  87.   ns->target = target;
  88.   return ns;
  89. }
  90.  
  91. void scc_ns_free(scc_ns_t* ns) {
  92.   scc_symbol_list_free(ns->glob_sym);
  93.   free(ns);
  94. }
  95.  
  96. scc_symbol_t* scc_ns_get_sym(scc_ns_t* ns, char* room, char* sym) {
  97.   scc_symbol_t* r;
  98.   scc_symbol_t* cur;
  99.  
  100.   if(room) {
  101.     for(r = ns->glob_sym ; r ; r = r->next) {
  102.       if(r->type != SCC_RES_ROOM) continue;
  103.       if(!strcmp(r->sym,room)) break;
  104.     }
  105.     if(!r) return NULL;
  106.     cur = r->childs;
  107.   } else if(ns->cur) {
  108.     if(ns->cur->childs)
  109.       cur = ns->cur->childs;
  110.     else if(ns->cur->parent)
  111.       cur = ns->cur->parent->childs;
  112.     else
  113.       cur = ns->glob_sym;
  114.   } else {
  115.     cur = ns->glob_sym;
  116.   }
  117.     
  118.  
  119.   while(cur) {
  120.     for(r = cur ; r ; r = r->next) {
  121.       if(strcmp(r->sym,sym)) continue;
  122.       return r;
  123.     }
  124.     // for full name we don't want to continue the search
  125.     if(room) break;
  126.     if(cur->parent) {
  127.       if(cur->parent->parent)
  128.     cur = cur->parent->parent->childs;
  129.       else
  130.     cur = ns->glob_sym;
  131.     } else
  132.       cur = NULL;
  133.   }
  134.  
  135.   return NULL;
  136. }
  137.  
  138. scc_symbol_t* scc_ns_get_sym_with_id(scc_ns_t* ns,int type, int id) {
  139.   scc_symbol_t* r,*r2;
  140.  
  141.   // room, verbs and variables are in the global ns
  142.   if(scc_sym_is_global(type)) {
  143.     for(r = ns->glob_sym ; r ; r = r->next) {
  144.       if(r->type == type && r->rid == id) return r;
  145.     }
  146.     if(scc_sym_is_only_global(type))
  147.       return NULL;
  148.   }
  149.  
  150.   // local vars are in the current sym
  151.   if(type == SCC_RES_LVAR) {
  152.     for(r = ns->cur ; r ; r = r->next) {
  153.       if(r->type == SCC_RES_LVAR && r->rid == id) return r;
  154.     }
  155.     return NULL;
  156.   }
  157.       
  158.  
  159.   // the rest is in some room ... somewhere :)
  160.   for(r = ns->glob_sym ; r ; r = r->next) {
  161.     if(r->type != SCC_RES_ROOM) continue;
  162.     for(r2 = r->childs ; r2 ; r2 = r2->next) {
  163.       if(r2->type == type && r2->rid == id) return r2;
  164.     }
  165.   }
  166.  
  167.   return NULL;
  168. }
  169.  
  170. // check if a redeclaration is compatible with the one we had before
  171. static int scc_ns_redecl_sym(scc_ns_t* ns, scc_symbol_t* i, 
  172.                  int type, int subtype,
  173.                  int addr) {
  174.   if(i->type != type || i->subtype != subtype) {
  175.     scc_log(LOG_ERR,"Symbol %s is already defined with another type.\n",
  176.             i->sym);
  177.     return 0;
  178.   }
  179.   if(i->addr >= 0 && addr >= 0 && i->addr != addr) {
  180.     scc_log(LOG_ERR,"Symbol %s is already defined with address %d.\n",
  181.             i->sym,i->addr);
  182.     return 0;
  183.   }
  184.  
  185.   if(i->addr < 0 && addr)
  186.     return scc_ns_set_sym_addr(ns,i,addr);
  187.  
  188.   return 1;
  189. }
  190.  
  191. scc_symbol_t*  scc_ns_add_sym(scc_ns_t* ns, char* sym,
  192.                   int type, int subtype,
  193.                   int addr,char status) {
  194.   scc_symbol_t* rr = scc_ns_get_sym(ns,NULL,sym);
  195.  
  196.   if(rr) {
  197.     // check for address eventual type/address clash
  198.     if(!scc_ns_redecl_sym(ns,rr,type,subtype,addr)) return 0;
  199.     // the new sym export
  200.     if(status == 'E') {
  201.       // alredy exported ??
  202.       if(rr->status == 'E') {
  203.     scc_log(LOG_ERR,"Symbol %s is exported more than once.\n",sym);
  204.     return 0;
  205.       }
  206.       rr->status = 'E';
  207.     }
  208.     return rr;
  209.   }
  210.  
  211.   scc_log(LOG_DBG,"Adding %s symbol %s (%d-%d @ %d)\n",
  212.           status == 'E' ? "exported" : "imported",
  213.           sym,type,subtype,addr);
  214.  
  215.   rr = calloc(1,sizeof(scc_symbol_t));
  216.   rr->type = type;
  217.   rr->subtype = subtype;
  218.   rr->sym = strdup(sym);
  219.   rr->addr = -1;
  220.   rr->status = status;
  221.  
  222.   if(addr >= 0) {
  223.     if(!scc_ns_set_sym_addr(ns,rr,addr)) {
  224.       scc_symbol_free(rr);
  225.       return NULL;
  226.     }
  227.   }
  228.  
  229.   if(ns->cur) {
  230.     rr->next = ns->cur->childs;
  231.     ns->cur->childs = rr;
  232.     rr->parent = ns->cur;
  233.   } else {
  234.     rr->next = ns->glob_sym;
  235.     ns->glob_sym = rr;
  236.   }
  237.  
  238.   return rr;
  239. }
  240.  
  241. static int scc_ns_make_addr(int type, int subtype, int addr, int loff) {
  242.  
  243.   if(addr < 0) return addr;
  244.  
  245.   if(type == SCC_RES_BVAR) addr |= 0x8000;
  246.   else if(type == SCC_RES_LVAR) addr |= 0x4000;
  247.   else if(type == SCC_RES_LSCR) addr += loff;
  248.  
  249.   return addr;
  250. }
  251.  
  252. scc_symbol_t* scc_ns_decl(scc_ns_t* ns, char* room, char* sym, 
  253.               int type, int subtype, int addr) {
  254.   scc_symbol_t* rr;
  255.   scc_symbol_t* new;
  256.  
  257.   addr = scc_ns_make_addr(type,subtype,addr,ns->target->max_global_scr);
  258.  
  259.   if(room) {
  260.       // go into a room ns
  261.       rr = scc_ns_get_sym(ns,NULL,room);
  262.       if(!rr || rr->type != SCC_RES_ROOM) {
  263.     scc_log(LOG_ERR,"%s is not a declared room.\n",room);
  264.     return NULL;
  265.       }
  266.       // return scc_ns_decl_in_room(ns,rr,sym,type,subtype,addr);
  267.   } else {
  268.     rr = scc_ns_get_sym(ns,NULL,sym);
  269.     if(rr) {
  270.       if(scc_ns_redecl_sym(ns,rr,type,subtype,addr)) return rr;
  271.       return NULL;
  272.     }
  273.   }
  274.   
  275.   new = calloc(1,sizeof(scc_symbol_t));
  276.   new->type = type;
  277.   new->subtype = subtype;
  278.   new->sym = strdup(sym);
  279.  
  280.   if(addr >= 0) {
  281.     if(!scc_ns_set_sym_addr(ns,new,addr)) {
  282.       scc_symbol_free(new);
  283.       return NULL;
  284.     }
  285.   } else
  286.       new->addr = addr;
  287.  
  288.   if(room) {
  289.     new->next = rr->childs;
  290.     rr->childs = new;
  291.     new->parent = rr;
  292.   } else if(ns->cur) {
  293.     new->next = ns->cur->childs;
  294.     ns->cur->childs = new;
  295.     new->parent = ns->cur;
  296.   } else {
  297.     new->next = ns->glob_sym;
  298.     ns->glob_sym = new;
  299.   }
  300.     
  301.   return new;
  302.   
  303. }
  304.  
  305. int scc_ns_push(scc_ns_t* ns, scc_symbol_t* s) {
  306.  
  307.   if(s->parent != ns->cur) {
  308.     scc_log(LOG_ERR,"Trying to push sym %s into the ns, but it doesn't belong to the current level %s\n",s->sym,ns->cur->sym);
  309.     return 0;
  310.   }
  311.   
  312.   ns->cur = s;
  313.   return 1;
  314. }
  315.  
  316. void scc_ns_clear(scc_ns_t* ns,int type) {
  317.   scc_symbol_t *s,*o = NULL;
  318.  
  319.   if(!ns->cur) {
  320.     scc_log(LOG_ERR,"Trying to clear ns, but there are no pushed syms!!!\n");
  321.     return;
  322.   }
  323.  
  324.   s = ns->cur->childs;
  325.   while(s) {
  326.     
  327.     if(s->type != type) {
  328.       o = s;
  329.       s = s->next;
  330.       continue;
  331.     }
  332.      
  333.     if(o) {
  334.       o->next = s->next;
  335.       scc_symbol_free(s);
  336.       s = o->next;
  337.     } else {
  338.       ns->cur->childs = s->next;
  339.       scc_symbol_free(s);
  340.       s = ns->cur->childs;
  341.     }
  342.   }
  343.   memset(&ns->as[type],0,0x10000/8);
  344. }
  345.  
  346. int scc_ns_pop(scc_ns_t* ns) {
  347.  
  348.  
  349.   if(!ns->cur) {
  350.     scc_log(LOG_ERR,"Trying to pop ns, but there is no pushed sym !!!\n");
  351.     return 0;
  352.   }
  353.  
  354.   ns->cur = ns->cur->parent;
  355.   return 1;
  356. }
  357.  
  358. // allocate a ressource id for this symbol
  359. int scc_ns_get_rid(scc_ns_t* ns, scc_symbol_t* s) {
  360.   scc_log(LOG_DBG,"Get rid for %s\n",s->sym);
  361.   // make sure the parent symbols all have rid allocated
  362.   if(s->parent && !s->parent->rid) scc_ns_get_rid(ns,s->parent);
  363.  
  364.   if(s->rid > 0) return s->rid;
  365.  
  366.   // bit variable have there own address space
  367.   ns->rids[s->type]++;
  368.   s->rid = ns->rids[s->type];
  369.  
  370.   return s->rid;
  371. }
  372.  
  373. int scc_ns_set_sym_addr(scc_ns_t* ns, scc_symbol_t* s,int addr) {
  374.   uint8_t* as = ns->as[s->type];
  375.  
  376.   if(addr == s->addr) return 1;
  377.  
  378.   if(addr > ns->target->addr_max[s->type]) {
  379.     scc_log(LOG_ERR,"Address 0x%X is invalid for its type.\n",addr);
  380.     return 0;
  381.   }
  382.  
  383.   if(as[addr/8] & (1 << (addr%8))) {
  384.     scc_log(LOG_ERR,"Address 0x%X is already in use.\n",addr);
  385.     return 0;
  386.   }
  387.   as[addr/8] |= (1 << (addr%8));
  388.  
  389.   s->addr = addr;
  390.   return 1;
  391. }
  392.  
  393. int scc_ns_alloc_sym_addr(scc_ns_t* ns,scc_symbol_t* s,int* cur) {
  394.   uint8_t* as = ns->as[s->type];
  395.   int i;
  396.  
  397.   if(s->addr >= 0) return 1;
  398.  
  399.   for(i = cur[0] ; i <= ns->target->addr_max[s->type] ; i++) {
  400.     if(as[i/8] & (1 << (i%8))) continue;
  401.     as[i/8] |= 1 << (i%8);
  402.     cur[0]++;
  403.     s->addr = i;
  404.     return 1;
  405.   }
  406.   return 0;
  407.  
  408. }
  409.  
  410. int scc_ns_alloc_addr(scc_ns_t* ns) {
  411.   scc_symbol_t* r,*s;
  412.   int cur[SCC_RES_LAST];
  413.  
  414.   memcpy(cur,ns->target->addr_min,SCC_RES_LAST*sizeof(int));
  415.  
  416.   scc_log(LOG_DBG,"Allocating address:\n");
  417.   for(r = ns->glob_sym ; r ; r = r->next) {
  418.     if(!scc_ns_alloc_sym_addr(ns,r,&cur[r->type])) {
  419.       scc_log(LOG_ERR,"Failed to allocate an address for %s.\n",r->sym);
  420.       return 0;
  421.     }
  422.     scc_log(LOG_DBG,"%s @ 0x%X\n",r->sym,r->addr);
  423.     if(r->type == SCC_RES_ROOM) {
  424.       for(s = r->childs ; s ; s = s->next) {
  425.     if(!scc_ns_alloc_sym_addr(ns,s,&cur[s->type])) {
  426.       scc_log(LOG_ERR,"Failed to allocate an address for %s::%s.\n",
  427.                   r->sym,s->sym);
  428.       return 0;
  429.     }
  430.     scc_log(LOG_DBG,"%s::%s @ 0x%X\n",r->sym,s->sym,s->addr);
  431.       }
  432.     }
  433.   }
  434.  
  435.   return 1;
  436. }
  437.  
  438. static int scc_symbol_get_addr_from(scc_symbol_t* s,scc_symbol_t* ref) {
  439.   if(ref->addr < 0) {
  440.     scc_log(LOG_ERR,"The symbol %s has no address in the src ns.\n",s->sym);
  441.     return 0;
  442.   }
  443.  
  444.   if(s->addr >= 0 && s->addr != ref->addr) {
  445.     scc_log(LOG_ERR,"Got address clash on symbol %s: 0x%X != 0x%X ????\n",s->sym,
  446.             s->addr,ref->addr);
  447.   }
  448.  
  449.   if(ref->type != s->type ||
  450.      ref->subtype != s->subtype) {
  451.     scc_log(LOG_ERR,"The symbol %s is not of the same type in src ns.\n",s->sym);
  452.     return 0;
  453.   }
  454.   s->addr = ref->addr;
  455.   return 1;
  456. }
  457.  
  458.  
  459. int scc_ns_get_addr_from(scc_ns_t* ns,scc_ns_t* from) {
  460.   scc_symbol_t* r,*s,*ref;
  461.  
  462.   for(r = ns->glob_sym ; r ; r = r->next) {
  463.     ref = scc_ns_get_sym(from,NULL,r->sym);
  464.     if(!ref) {
  465.       scc_log(LOG_ERR,"Failed to find symbol %s in the scr ns.\n",r->sym);
  466.       return 0;
  467.     }
  468.     if(!scc_symbol_get_addr_from(r,ref)) return 0;
  469.     if(r->type == SCC_RES_ROOM) {
  470.       for(s = r->childs ; s ; s = s->next) {
  471.     ref = scc_ns_get_sym(from,r->sym,s->sym);
  472.     if(!ref) {
  473.           scc_log(LOG_ERR,"Failed to find symbol %s::%s in the scr ns.\n",
  474.                   r->sym,s->sym);
  475.       return 0;
  476.     }
  477.     if(!scc_symbol_get_addr_from(s,ref)) return 0;
  478.       }
  479.     }
  480.   }
  481.   return 1;
  482. }
  483.  
  484.  
  485. int scc_ns_res_max(scc_ns_t* ns,int type) {
  486.   scc_symbol_t* r,*s;
  487.   int n = 0;
  488.  
  489.   if(scc_sym_is_global(type)) {
  490.     for(r = ns->glob_sym ; r ; r = r->next) {
  491.       if(r->type == type && r->addr > n) n = r->addr;
  492.     }
  493.     if(type == SCC_RES_BVAR)
  494.       n &= 0x7FFF;
  495.  
  496.     if(scc_sym_is_only_global(type))
  497.       return n;
  498.   }
  499.    
  500.   for(r = ns->glob_sym ; r ; r = r->next) {
  501.     if(r->type != SCC_RES_ROOM) continue;
  502.     for(s = r->childs ; s ; s = s->next) {
  503.       if(s->type == type && s->addr > n) n = s->addr;
  504.     }
  505.   }
  506.   return n;
  507.  
  508. }
  509.  
  510. int scc_ns_is_addr_alloc(scc_ns_t* ns,int type,int addr) {
  511.   if(addr < 0 || type < 0 || type >= SCC_RES_LAST) return 0;
  512.  
  513.   return (ns->as[type][addr/8] & (1<<(addr%8))) ? 1 : 0;
  514. }
  515.  
  516. scc_symbol_t* scc_ns_get_sym_at(scc_ns_t* ns,int type,int addr) {
  517.   scc_symbol_t* r,*r2;
  518.  
  519.   // room, verbs and variables are in the global ns
  520.   if(scc_sym_is_global(type)) {
  521.     for(r = ns->glob_sym ; r ; r = r->next) {
  522.       if(r->type == type && r->addr == addr) return r;
  523.     }
  524.     if(scc_sym_is_only_global(type))
  525.       return NULL;
  526.   }
  527.  
  528.   // local vars are in the current sym
  529.   if(type == SCC_RES_LVAR) {
  530.     for(r = ns->cur ; r ; r = r->next) {
  531.       if(r->type == SCC_RES_LVAR && r->addr == addr) return r;
  532.     }
  533.     return NULL;
  534.   }
  535.       
  536.  
  537.   // the rest is in some room ... somewhere :)
  538.   for(r = ns->glob_sym ; r ; r = r->next) {
  539.     if(r->type != SCC_RES_ROOM) continue;
  540.     for(r2 = r->childs ; r2 ; r2 = r2->next) {
  541.       if(r2->type == type && r2->addr == addr) return r2;
  542.     }
  543.   }
  544.   
  545.   return NULL;
  546. }
  547.