hash.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. ** hash.c
  3. ** hash manager for lua
  4. ** Luiz Henrique de Figueiredo - 17 Aug 90
  5. */
  6. char *rcs_hash="$Id: hash.c,v 2.1 1994/04/20 22:07:57 celes Exp celes $";
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include "mm.h"
  10. #include "opcode.h"
  11. #include "hash.h"
  12. #include "inout.h"
  13. #include "table.h"
  14. #include "lua.h"
  15. #define streq(s1,s2) (strcmp(s1,s2)==0)
  16. #define strneq(s1,s2) (strcmp(s1,s2)!=0)
  17. #define new(s) ((s *)malloc(sizeof(s)))
  18. #define newvector(n,s) ((s *)calloc(n,sizeof(s)))
  19. #define nhash(t) ((t)->nhash)
  20. #define nodelist(t) ((t)->list)
  21. #define list(t,i) ((t)->list[i])
  22. #define markarray(t) ((t)->mark)
  23. #define ref_tag(n) (tag(&(n)->ref))
  24. #define ref_nvalue(n) (nvalue(&(n)->ref))
  25. #define ref_svalue(n) (svalue(&(n)->ref))
  26. typedef struct ArrayList
  27. {
  28. Hash *array;
  29. struct ArrayList *next;
  30. } ArrayList;
  31. static ArrayList *listhead = NULL;
  32. static int head (Hash *t, Object *ref) /* hash function */
  33. {
  34. if (tag(ref) == T_NUMBER) return (((int)nvalue(ref))%nhash(t));
  35. else if (tag(ref) == T_STRING)
  36. {
  37. int h;
  38. char *name = svalue(ref);
  39. for (h=0; *name!=0; name++) /* interpret name as binary number */
  40. {
  41. h <<= 8;
  42. h += (unsigned char) *name; /* avoid sign extension */
  43. h %= nhash(t); /* make it a valid index */
  44. }
  45. return h;
  46. }
  47. else
  48. {
  49. lua_reportbug ("unexpected type to index table");
  50. return -1;
  51. }
  52. }
  53. static Node *present(Hash *t, Object *ref, int h)
  54. {
  55. Node *n=NULL, *p;
  56. if (tag(ref) == T_NUMBER)
  57. {
  58. for (p=NULL,n=list(t,h); n!=NULL; p=n, n=n->next)
  59. if (ref_tag(n) == T_NUMBER && nvalue(ref) == ref_nvalue(n)) break;
  60. }
  61. else if (tag(ref) == T_STRING)
  62. {
  63. for (p=NULL,n=list(t,h); n!=NULL; p=n, n=n->next)
  64. if (ref_tag(n) == T_STRING && streq(svalue(ref),ref_svalue(n))) break;
  65. }
  66. if (n==NULL) /* name not present */
  67. return NULL;
  68. #if 0
  69. if (p!=NULL) /* name present but not first */
  70. {
  71. p->next=n->next; /* move-to-front self-organization */
  72. n->next=list(t,h);
  73. list(t,h)=n;
  74. }
  75. #endif
  76. return n;
  77. }
  78. static void freelist (Node *n)
  79. {
  80. while (n)
  81. {
  82. Node *next = n->next;
  83. free (n);
  84. n = next;
  85. }
  86. }
  87. /*
  88. ** Create a new hash. Return the hash pointer or NULL on error.
  89. */
  90. static Hash *hashcreate (unsigned int nhash)
  91. {
  92. Hash *t = new (Hash);
  93. if (t == NULL)
  94. {
  95. lua_error ("not enough memory");
  96. return NULL;
  97. }
  98. nhash(t) = nhash;
  99. markarray(t) = 0;
  100. nodelist(t) = newvector (nhash, Node*);
  101. if (nodelist(t) == NULL)
  102. {
  103. lua_error ("not enough memory");
  104. return NULL;
  105. }
  106. return t;
  107. }
  108. /*
  109. ** Delete a hash
  110. */
  111. static void hashdelete (Hash *h)
  112. {
  113. int i;
  114. for (i=0; i<nhash(h); i++)
  115. freelist (list(h,i));
  116. free (nodelist(h));
  117. free(h);
  118. }
  119. /*
  120. ** Mark a hash and check its elements
  121. */
  122. void lua_hashmark (Hash *h)
  123. {
  124. if (markarray(h) == 0)
  125. {
  126. int i;
  127. markarray(h) = 1;
  128. for (i=0; i<nhash(h); i++)
  129. {
  130. Node *n;
  131. for (n = list(h,i); n != NULL; n = n->next)
  132. {
  133. lua_markobject(&n->ref);
  134. lua_markobject(&n->val);
  135. }
  136. }
  137. }
  138. }
  139. /*
  140. ** Garbage collection to arrays
  141. ** Delete all unmarked arrays.
  142. */
  143. void lua_hashcollector (void)
  144. {
  145. ArrayList *curr = listhead, *prev = NULL;
  146. while (curr != NULL)
  147. {
  148. ArrayList *next = curr->next;
  149. if (markarray(curr->array) != 1)
  150. {
  151. if (prev == NULL) listhead = next;
  152. else prev->next = next;
  153. hashdelete(curr->array);
  154. free(curr);
  155. }
  156. else
  157. {
  158. markarray(curr->array) = 0;
  159. prev = curr;
  160. }
  161. curr = next;
  162. }
  163. }
  164. /*
  165. ** Create a new array
  166. ** This function insert the new array at array list. It also
  167. ** execute garbage collection if the number of array created
  168. ** exceed a pre-defined range.
  169. */
  170. Hash *lua_createarray (int nhash)
  171. {
  172. ArrayList *new = new(ArrayList);
  173. if (new == NULL)
  174. {
  175. lua_error ("not enough memory");
  176. return NULL;
  177. }
  178. new->array = hashcreate(nhash);
  179. if (new->array == NULL)
  180. {
  181. lua_error ("not enough memory");
  182. return NULL;
  183. }
  184. if (lua_nentity == lua_block)
  185. lua_pack();
  186. lua_nentity++;
  187. new->next = listhead;
  188. listhead = new;
  189. return new->array;
  190. }
  191. /*
  192. ** If the hash node is present, return its pointer, otherwise create a new
  193. ** node for the given reference and also return its pointer.
  194. ** On error, return NULL.
  195. */
  196. Object *lua_hashdefine (Hash *t, Object *ref)
  197. {
  198. int h;
  199. Node *n;
  200. h = head (t, ref);
  201. if (h < 0) return NULL;
  202. n = present(t, ref, h);
  203. if (n == NULL)
  204. {
  205. n = new(Node);
  206. if (n == NULL)
  207. {
  208. lua_error ("not enough memory");
  209. return NULL;
  210. }
  211. n->ref = *ref;
  212. tag(&n->val) = T_NIL;
  213. n->next = list(t,h); /* link node to head of list */
  214. list(t,h) = n;
  215. }
  216. return (&n->val);
  217. }
  218. /*
  219. ** Internal function to manipulate arrays.
  220. ** Given an array object and a reference value, return the next element
  221. ** in the hash.
  222. ** This function pushs the element value and its reference to the stack.
  223. */
  224. static void firstnode (Hash *a, int h)
  225. {
  226. if (h < nhash(a))
  227. {
  228. int i;
  229. for (i=h; i<nhash(a); i++)
  230. {
  231. if (list(a,i) != NULL)
  232. {
  233. if (tag(&list(a,i)->val) != T_NIL)
  234. {
  235. lua_pushobject (&list(a,i)->ref);
  236. lua_pushobject (&list(a,i)->val);
  237. return;
  238. }
  239. else
  240. {
  241. Node *next = list(a,i)->next;
  242. while (next != NULL && tag(&next->val) == T_NIL) next = next->next;
  243. if (next != NULL)
  244. {
  245. lua_pushobject (&next->ref);
  246. lua_pushobject (&next->val);
  247. return;
  248. }
  249. }
  250. }
  251. }
  252. }
  253. lua_pushnil();
  254. lua_pushnil();
  255. }
  256. void lua_next (void)
  257. {
  258. Hash *a;
  259. Object *o = lua_getparam (1);
  260. Object *r = lua_getparam (2);
  261. if (o == NULL || r == NULL)
  262. { lua_error ("too few arguments to function `next'"); return; }
  263. if (lua_getparam (3) != NULL)
  264. { lua_error ("too many arguments to function `next'"); return; }
  265. if (tag(o) != T_ARRAY)
  266. { lua_error ("first argument of function `next' is not a table"); return; }
  267. a = avalue(o);
  268. if (tag(r) == T_NIL)
  269. {
  270. firstnode (a, 0);
  271. return;
  272. }
  273. else
  274. {
  275. int h = head (a, r);
  276. if (h >= 0)
  277. {
  278. Node *n = list(a,h);
  279. while (n)
  280. {
  281. if (memcmp(&n->ref,r,sizeof(Object)) == 0)
  282. {
  283. if (n->next == NULL)
  284. {
  285. firstnode (a, h+1);
  286. return;
  287. }
  288. else if (tag(&n->next->val) != T_NIL)
  289. {
  290. lua_pushobject (&n->next->ref);
  291. lua_pushobject (&n->next->val);
  292. return;
  293. }
  294. else
  295. {
  296. Node *next = n->next->next;
  297. while (next != NULL && tag(&next->val) == T_NIL) next = next->next;
  298. if (next == NULL)
  299. {
  300. firstnode (a, h+1);
  301. return;
  302. }
  303. else
  304. {
  305. lua_pushobject (&next->ref);
  306. lua_pushobject (&next->val);
  307. }
  308. return;
  309. }
  310. }
  311. n = n->next;
  312. }
  313. if (n == NULL)
  314. lua_error ("error in function 'next': reference not found");
  315. }
  316. }
  317. }