tree.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. ** tree.c
  3. ** TecCGraf - PUC-Rio
  4. */
  5. char *rcs_tree="$Id: tree.c,v 1.12 1994/12/20 21:20:36 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. typedef struct StringNode {
  13. struct StringNode *next;
  14. TaggedString ts;
  15. } StringNode;
  16. static StringNode *string_root = NULL;
  17. static TreeNode *constant_root = NULL;
  18. /*
  19. ** Insert a new constant/variable at the tree.
  20. */
  21. static TreeNode *tree_create (TreeNode **node, char *str)
  22. {
  23. if (*node == NULL)
  24. {
  25. *node = (TreeNode *) luaI_malloc(sizeof(TreeNode)+strlen(str));
  26. (*node)->left = (*node)->right = NULL;
  27. strcpy((*node)->ts.str, str);
  28. (*node)->ts.marked = 0;
  29. (*node)->ts.hash = 0;
  30. (*node)->varindex = (*node)->constindex = NOT_USED;
  31. return *node;
  32. }
  33. else
  34. {
  35. int c = lua_strcmp(str, (*node)->ts.str);
  36. if (c < 0)
  37. return tree_create(&(*node)->left, str);
  38. else if (c > 0)
  39. return tree_create(&(*node)->right, str);
  40. else
  41. return *node;
  42. }
  43. }
  44. TaggedString *lua_createstring (char *str)
  45. {
  46. StringNode *newString;
  47. if (str == NULL) return NULL;
  48. lua_pack();
  49. newString = (StringNode *)luaI_malloc(sizeof(StringNode)+strlen(str));
  50. newString->ts.marked = 0;
  51. newString->ts.hash = 0;
  52. strcpy(newString->ts.str, str);
  53. newString->next = string_root;
  54. string_root = newString;
  55. return &(newString->ts);
  56. }
  57. TreeNode *lua_constcreate (char *str)
  58. {
  59. return tree_create(&constant_root, str);
  60. }
  61. /*
  62. ** Garbage collection function.
  63. ** This function traverse the string list freeing unindexed strings
  64. */
  65. Long lua_strcollector (void)
  66. {
  67. StringNode *curr = string_root, *prev = NULL;
  68. Long counter = 0;
  69. while (curr)
  70. {
  71. StringNode *next = curr->next;
  72. if (!curr->ts.marked)
  73. {
  74. if (prev == NULL) string_root = next;
  75. else prev->next = next;
  76. luaI_free(curr);
  77. ++counter;
  78. }
  79. else
  80. {
  81. curr->ts.marked = 0;
  82. prev = curr;
  83. }
  84. curr = next;
  85. }
  86. return counter;
  87. }
  88. /*
  89. ** Return next variable.
  90. */
  91. static TreeNode *tree_next (TreeNode *node, char *str)
  92. {
  93. if (node == NULL) return NULL;
  94. else if (str == NULL) return node;
  95. else
  96. {
  97. int c = lua_strcmp(str, node->ts.str);
  98. if (c == 0)
  99. return node->left != NULL ? node->left : node->right;
  100. else if (c < 0)
  101. {
  102. TreeNode *result = tree_next(node->left, str);
  103. return result != NULL ? result : node->right;
  104. }
  105. else
  106. return tree_next(node->right, str);
  107. }
  108. }
  109. TreeNode *lua_varnext (char *n)
  110. {
  111. TreeNode *result;
  112. char *name = n;
  113. while (1)
  114. { /* repeat until a valid (non nil) variable */
  115. result = tree_next(constant_root, name);
  116. if (result == NULL) return NULL;
  117. if (result->varindex != NOT_USED &&
  118. s_tag(result->varindex) != LUA_T_NIL)
  119. return result;
  120. name = result->ts.str;
  121. }
  122. }