tree.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. ** tree.c
  3. ** TecCGraf - PUC-Rio
  4. */
  5. char *rcs_tree="$Id: tree.c,v 1.5 1994/11/16 16:03:48 roberto Exp roberto $";
  6. #include <string.h>
  7. #include "mem.h"
  8. #include "lua.h"
  9. #include "tree.h"
  10. #include "table.h"
  11. #define lua_strcmp(a,b) (a[0]<b[0]?(-1):(a[0]>b[0]?(1):strcmp(a,b)))
  12. static TreeNode *string_root = NULL;
  13. static TreeNode *constant_root = NULL;
  14. /*
  15. ** Insert a new string/constant/variable at the tree.
  16. */
  17. static TreeNode *tree_create (TreeNode **node, char *str, int *created)
  18. {
  19. if (*node == NULL)
  20. {
  21. *node = (TreeNode *) luaI_malloc(sizeof(TreeNode)+strlen(str));
  22. (*node)->left = (*node)->right = NULL;
  23. strcpy((*node)->str, str);
  24. (*node)->varindex = (*node)->constindex = UNMARKED_STRING;
  25. *created = 1;
  26. return *node;
  27. }
  28. else
  29. {
  30. int c = lua_strcmp(str, (*node)->str);
  31. if (c < 0)
  32. return tree_create(&(*node)->left, str, created);
  33. else if (c > 0)
  34. return tree_create(&(*node)->right, str, created);
  35. else
  36. return *node;
  37. }
  38. }
  39. char *lua_strcreate (char *str)
  40. {
  41. int created=0;
  42. TreeNode *t = tree_create(&string_root, str, &created);
  43. if (created)
  44. {
  45. if (lua_nentity == lua_block) lua_pack ();
  46. lua_nentity++;
  47. }
  48. return t->str;
  49. }
  50. TreeNode *lua_constcreate (char *str)
  51. {
  52. int created;
  53. return tree_create(&constant_root, str, &created);
  54. }
  55. /*
  56. ** Free a node of the tree
  57. */
  58. static TreeNode *lua_strfree (TreeNode *parent)
  59. {
  60. if (parent->left == NULL && parent->right == NULL) /* no child */
  61. {
  62. luaI_free(parent);
  63. return NULL;
  64. }
  65. else if (parent->left == NULL) /* only right child */
  66. {
  67. TreeNode *p = parent->right;
  68. luaI_free(parent);
  69. return p;
  70. }
  71. else if (parent->right == NULL) /* only left child */
  72. {
  73. TreeNode *p = parent->left;
  74. luaI_free(parent);
  75. return p;
  76. }
  77. else /* two children */
  78. {
  79. TreeNode *p = parent, *r = parent->right;
  80. while (r->left != NULL)
  81. {
  82. p = r;
  83. r = r->left;
  84. }
  85. if (p == parent)
  86. {
  87. r->left = parent->left;
  88. parent->left = NULL;
  89. parent->right = r->right;
  90. r->right = lua_strfree(parent);
  91. }
  92. else
  93. {
  94. TreeNode *t = r->right;
  95. r->left = parent->left;
  96. r->right = parent->right;
  97. parent->left = NULL;
  98. parent->right = t;
  99. p->left = lua_strfree(parent);
  100. }
  101. return r;
  102. }
  103. }
  104. /*
  105. ** Traverse tree for garbage collection
  106. */
  107. static TreeNode *lua_travcollector (TreeNode *r)
  108. {
  109. if (r == NULL) return NULL;
  110. r->right = lua_travcollector(r->right);
  111. r->left = lua_travcollector(r->left);
  112. if (r->constindex == UNMARKED_STRING)
  113. {
  114. ++lua_recovered;
  115. return lua_strfree(r);
  116. }
  117. else
  118. {
  119. r->constindex = UNMARKED_STRING;
  120. return r;
  121. }
  122. }
  123. /*
  124. ** Garbage collection function.
  125. ** This function traverse the tree freening unindexed strings
  126. */
  127. void lua_strcollector (void)
  128. {
  129. string_root = lua_travcollector(string_root);
  130. }
  131. /*
  132. ** Return next variable.
  133. */
  134. static TreeNode *tree_next (TreeNode *node, char *str)
  135. {
  136. if (node == NULL) return NULL;
  137. else if (str == NULL) return node;
  138. else
  139. {
  140. int c = lua_strcmp(str, node->str);
  141. if (c == 0)
  142. return node->left != NULL ? node->left : node->right;
  143. else if (c < 0)
  144. {
  145. TreeNode *result = tree_next(node->left, str);
  146. return result != NULL ? result : node->right;
  147. }
  148. else
  149. return tree_next(node->right, str);
  150. }
  151. }
  152. TreeNode *lua_varnext (char *n)
  153. {
  154. TreeNode *result;
  155. char *name = n;
  156. while (1)
  157. { /* repeat until a valid (non nil) variable */
  158. result = tree_next(constant_root, name);
  159. if (result == NULL) return NULL;
  160. if (result->varindex != UNMARKED_STRING &&
  161. s_tag(result->varindex) != LUA_T_NIL)
  162. return result;
  163. name = result->str;
  164. }
  165. }