tree.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. ** tree.c
  3. ** TecCGraf - PUC-Rio
  4. */
  5. char *rcs_tree="$Id: tree.c,v 1.27 1997/06/09 17:28:14 roberto Exp roberto $";
  6. #include <string.h>
  7. #include "luamem.h"
  8. #include "lua.h"
  9. #include "tree.h"
  10. #include "lex.h"
  11. #include "hash.h"
  12. #include "table.h"
  13. #include "fallback.h"
  14. #define NUM_HASHS 64
  15. typedef struct {
  16. int size;
  17. int nuse; /* number of elements (including EMPTYs) */
  18. TaggedString **hash;
  19. } stringtable;
  20. static int initialized = 0;
  21. static stringtable string_root[NUM_HASHS];
  22. static TaggedString EMPTY = {LUA_T_STRING, NULL, {{NOT_USED, NOT_USED}},
  23. 0, 2, {0}};
  24. static unsigned long hash (char *s, int tag)
  25. {
  26. unsigned long h;
  27. if (tag != LUA_T_STRING)
  28. h = (unsigned long)s;
  29. else {
  30. h = 0;
  31. while (*s)
  32. h = ((h<<5)-h)^(unsigned char)*(s++);
  33. }
  34. return h;
  35. }
  36. static void luaI_inittree (void)
  37. {
  38. int i;
  39. for (i=0; i<NUM_HASHS; i++) {
  40. string_root[i].size = 0;
  41. string_root[i].nuse = 0;
  42. string_root[i].hash = NULL;
  43. }
  44. }
  45. static void initialize (void)
  46. {
  47. initialized = 1;
  48. luaI_inittree();
  49. luaI_addReserved();
  50. luaI_initsymbol();
  51. luaI_initconstant();
  52. luaI_initfallbacks();
  53. }
  54. static void grow (stringtable *tb)
  55. {
  56. int newsize = luaI_redimension(tb->size);
  57. TaggedString **newhash = newvector(newsize, TaggedString *);
  58. int i;
  59. for (i=0; i<newsize; i++)
  60. newhash[i] = NULL;
  61. /* rehash */
  62. tb->nuse = 0;
  63. for (i=0; i<tb->size; i++)
  64. if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) {
  65. int h = tb->hash[i]->hash%newsize;
  66. while (newhash[h])
  67. h = (h+1)%newsize;
  68. newhash[h] = tb->hash[i];
  69. tb->nuse++;
  70. }
  71. luaI_free(tb->hash);
  72. tb->size = newsize;
  73. tb->hash = newhash;
  74. }
  75. static TaggedString *newone(char *buff, int tag, unsigned long h)
  76. {
  77. TaggedString *ts;
  78. if (tag == LUA_T_STRING) {
  79. ts = (TaggedString *)luaI_malloc(sizeof(TaggedString)+strlen(buff));
  80. strcpy(ts->str, buff);
  81. ts->u.s.varindex = ts->u.s.constindex = NOT_USED;
  82. ts->tag = LUA_T_STRING;
  83. }
  84. else {
  85. ts = (TaggedString *)luaI_malloc(sizeof(TaggedString));
  86. ts->u.v = buff;
  87. ts->tag = tag == LUA_ANYTAG ? 0 : tag;
  88. }
  89. ts->marked = 0;
  90. ts->hash = h;
  91. return ts;
  92. }
  93. static TaggedString *insert (char *buff, int tag, stringtable *tb)
  94. {
  95. TaggedString *ts;
  96. unsigned long h = hash(buff, tag);
  97. int i;
  98. int j = -1;
  99. if ((Long)tb->nuse*3 >= (Long)tb->size*2)
  100. {
  101. if (!initialized)
  102. initialize();
  103. grow(tb);
  104. }
  105. i = h%tb->size;
  106. while ((ts = tb->hash[i]) != NULL)
  107. {
  108. if (ts == &EMPTY)
  109. j = i;
  110. else if ((ts->tag == LUA_T_STRING) ?
  111. (tag == LUA_T_STRING && (strcmp(buff, ts->str) == 0)) :
  112. ((tag == ts->tag || tag == LUA_ANYTAG) && buff == ts->u.v))
  113. return ts;
  114. i = (i+1)%tb->size;
  115. }
  116. /* not found */
  117. lua_pack();
  118. if (j != -1) /* is there an EMPTY space? */
  119. i = j;
  120. else
  121. tb->nuse++;
  122. ts = tb->hash[i] = newone(buff, tag, h);
  123. return ts;
  124. }
  125. TaggedString *luaI_createudata (void *udata, int tag)
  126. {
  127. return insert(udata, tag, &string_root[(unsigned)udata%NUM_HASHS]);
  128. }
  129. TaggedString *lua_createstring (char *str)
  130. {
  131. return insert(str, LUA_T_STRING, &string_root[(unsigned)str[0]%NUM_HASHS]);
  132. }
  133. void luaI_strcallIM (TaggedString *l)
  134. {
  135. TObject o;
  136. ttype(&o) = LUA_T_USERDATA;
  137. for (; l; l=l->next) {
  138. tsvalue(&o) = l;
  139. luaI_gcIM(&o);
  140. }
  141. }
  142. void luaI_strfree (TaggedString *l)
  143. {
  144. while (l) {
  145. TaggedString *next = l->next;
  146. luaI_free(l);
  147. l = next;
  148. }
  149. }
  150. /*
  151. ** Garbage collection function.
  152. */
  153. TaggedString *luaI_strcollector (long *acum)
  154. {
  155. Long counter = 0;
  156. TaggedString *frees = NULL;
  157. int i;
  158. for (i=0; i<NUM_HASHS; i++)
  159. {
  160. stringtable *tb = &string_root[i];
  161. int j;
  162. for (j=0; j<tb->size; j++)
  163. {
  164. TaggedString *t = tb->hash[j];
  165. if (t != NULL && t->marked <= 1)
  166. {
  167. if (t->marked)
  168. t->marked = 0;
  169. else
  170. {
  171. t->next = frees;
  172. frees = t;
  173. tb->hash[j] = &EMPTY;
  174. counter++;
  175. }
  176. }
  177. }
  178. }
  179. *acum += counter;
  180. return frees;
  181. }