hash.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. ** hash.c
  3. ** hash manager for lua
  4. ** Luiz Henrique de Figueiredo - 17 Aug 90
  5. ** Modified by Waldemar Celes Filho
  6. ** 12 May 93
  7. */
  8. #include <string.h>
  9. #include <stdlib.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 ref_tag(n) (tag(&(n)->ref))
  23. #define ref_nvalue(n) (nvalue(&(n)->ref))
  24. #define ref_svalue(n) (svalue(&(n)->ref))
  25. static int head (Hash *t, Object *ref) /* hash function */
  26. {
  27. if (tag(ref) == T_NUMBER) return (((int)nvalue(ref))%nhash(t));
  28. else if (tag(ref) == T_STRING)
  29. {
  30. int h;
  31. char *name = svalue(ref);
  32. for (h=0; *name!=0; name++) /* interpret name as binary number */
  33. {
  34. h <<= 8;
  35. h += (unsigned char) *name; /* avoid sign extension */
  36. h %= nhash(t); /* make it a valid index */
  37. }
  38. return h;
  39. }
  40. else
  41. {
  42. lua_reportbug ("unexpected type to index table");
  43. return -1;
  44. }
  45. }
  46. static Node *present(Hash *t, Object *ref, int h)
  47. {
  48. Node *n=NULL, *p;
  49. if (tag(ref) == T_NUMBER)
  50. {
  51. for (p=NULL,n=list(t,h); n!=NULL; p=n, n=n->next)
  52. if (ref_tag(n) == T_NUMBER && nvalue(ref) == ref_nvalue(n)) break;
  53. }
  54. else if (tag(ref) == T_STRING)
  55. {
  56. for (p=NULL,n=list(t,h); n!=NULL; p=n, n=n->next)
  57. if (ref_tag(n) == T_STRING && streq(svalue(ref),ref_svalue(n))) break;
  58. }
  59. if (n==NULL) /* name not present */
  60. return NULL;
  61. #if 0
  62. if (p!=NULL) /* name present but not first */
  63. {
  64. p->next=n->next; /* move-to-front self-organization */
  65. n->next=list(t,h);
  66. list(t,h)=n;
  67. }
  68. #endif
  69. return n;
  70. }
  71. static void freelist (Node *n)
  72. {
  73. while (n)
  74. {
  75. Node *next = n->next;
  76. free (n);
  77. n = next;
  78. }
  79. }
  80. /*
  81. ** Create a new hash. Return the hash pointer or NULL on error.
  82. */
  83. Hash *lua_hashcreate (unsigned int nhash)
  84. {
  85. Hash *t = new (Hash);
  86. if (t == NULL)
  87. {
  88. lua_error ("not enough memory");
  89. return NULL;
  90. }
  91. nhash(t) = nhash;
  92. markarray(t) = 0;
  93. nodelist(t) = newvector (nhash, Node*);
  94. if (nodelist(t) == NULL)
  95. {
  96. lua_error ("not enough memory");
  97. return NULL;
  98. }
  99. return t;
  100. }
  101. /*
  102. ** Delete a hash
  103. */
  104. void lua_hashdelete (Hash *h)
  105. {
  106. int i;
  107. for (i=0; i<nhash(h); i++)
  108. freelist (list(h,i));
  109. free (nodelist(h));
  110. free(h);
  111. }
  112. /*
  113. ** If the hash node is present, return its pointer, otherwise create a new
  114. ** node for the given reference and also return its pointer.
  115. ** On error, return NULL.
  116. */
  117. Object *lua_hashdefine (Hash *t, Object *ref)
  118. {
  119. int h;
  120. Node *n;
  121. h = head (t, ref);
  122. if (h < 0) return NULL;
  123. n = present(t, ref, h);
  124. if (n == NULL)
  125. {
  126. n = new(Node);
  127. if (n == NULL)
  128. {
  129. lua_error ("not enough memory");
  130. return NULL;
  131. }
  132. n->ref = *ref;
  133. tag(&n->val) = T_NIL;
  134. n->next = list(t,h); /* link node to head of list */
  135. list(t,h) = n;
  136. }
  137. return (&n->val);
  138. }
  139. /*
  140. ** Mark a hash and check its elements
  141. */
  142. void lua_hashmark (Hash *h)
  143. {
  144. int i;
  145. markarray(h) = 1;
  146. for (i=0; i<nhash(h); i++)
  147. {
  148. Node *n;
  149. for (n = list(h,i); n != NULL; n = n->next)
  150. {
  151. lua_markobject (&n->ref);
  152. lua_markobject (&n->val);
  153. }
  154. }
  155. }
  156. /*
  157. ** Internal function to manipulate arrays.
  158. ** Given an array object and a reference value, return the next element
  159. ** in the hash.
  160. ** This function pushs the element value and its reference to the stack.
  161. */
  162. #include "lua.h"
  163. static void firstnode (Hash *a, int h)
  164. {
  165. if (h < nhash(a))
  166. {
  167. int i;
  168. for (i=h; i<nhash(a); i++)
  169. {
  170. if (list(a,i) != NULL && tag(&list(a,i)->val) != T_NIL)
  171. {
  172. lua_pushobject (&list(a,i)->ref);
  173. lua_pushobject (&list(a,i)->val);
  174. return;
  175. }
  176. }
  177. }
  178. lua_pushnil();
  179. lua_pushnil();
  180. }
  181. void lua_next (void)
  182. {
  183. Hash *a;
  184. Object *o = lua_getparam (1);
  185. Object *r = lua_getparam (2);
  186. if (o == NULL || r == NULL)
  187. { lua_error ("too few arguments to function `next'"); return; }
  188. if (lua_getparam (3) != NULL)
  189. { lua_error ("too many arguments to function `next'"); return; }
  190. if (tag(o) != T_ARRAY)
  191. { lua_error ("first argument of function `next' is not a table"); return; }
  192. a = avalue(o);
  193. if (tag(r) == T_NIL)
  194. {
  195. firstnode (a, 0);
  196. return;
  197. }
  198. else
  199. {
  200. int h = head (a, r);
  201. if (h >= 0)
  202. {
  203. Node *n = list(a,h);
  204. while (n)
  205. {
  206. if (memcmp(&n->ref,r,sizeof(Object)) == 0)
  207. {
  208. if (n->next == NULL)
  209. {
  210. firstnode (a, h+1);
  211. return;
  212. }
  213. else if (tag(&n->next->val) != T_NIL)
  214. {
  215. lua_pushobject (&n->next->ref);
  216. lua_pushobject (&n->next->val);
  217. return;
  218. }
  219. else
  220. {
  221. Node *next = n->next->next;
  222. while (next != NULL && tag(&next->val) == T_NIL) next = next->next;
  223. if (next == NULL)
  224. {
  225. firstnode (a, h+1);
  226. return;
  227. }
  228. else
  229. {
  230. lua_pushobject (&next->ref);
  231. lua_pushobject (&next->val);
  232. }
  233. return;
  234. }
  235. }
  236. n = n->next;
  237. }
  238. if (n == NULL)
  239. lua_error ("error in function 'next': reference not found");
  240. }
  241. }
  242. }