hash.c 5.2 KB

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