tree.c 2.7 KB

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