commit 1c749a3059051c52c3bc24540e27b0ccbcfff273
parent cde6ab178200cc4bb79c287ecf40a7508953933a
Author: Waldemar Celes <celes@tecgraf.puc-rio.br>
Date: Tue, 19 Jul 1994 18:23:58 -0300
Arvore binaria de strings, variaveis e constantes.
Diffstat:
A | tree.c | | | 210 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | tree.h | | | 27 | +++++++++++++++++++++++++++ |
2 files changed, 237 insertions(+), 0 deletions(-)
diff --git a/tree.c b/tree.c
@@ -0,0 +1,210 @@
+/*
+** tree.c
+** TecCGraf - PUC-Rio
+*/
+
+char *rcs_tree="$Id: $";
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "lua.h"
+#include "tree.h"
+
+
+#define lua_strcmp(a,b) (a[0]<b[0]?(-1):(a[0]>b[0]?(1):strcmp(a,b)))
+
+
+typedef struct TreeNode
+{
+ struct TreeNode *right;
+ struct TreeNode *left;
+ Word index;
+ char str[1]; /* \0 byte already reserved */
+} TreeNode;
+
+static TreeNode *string_root = NULL;
+static TreeNode *constant_root = NULL;
+static TreeNode *variable_root = NULL;
+
+/*
+** Insert a new string/constant/variable at the tree.
+*/
+static char *tree_create (TreeNode **node, char *str)
+{
+ if (*node == NULL)
+ {
+ *node = (TreeNode *) malloc (sizeof(TreeNode)+strlen(str));
+ if (*node == NULL)
+ lua_error ("memoria insuficiente\n");
+ (*node)->left = (*node)->right = NULL;
+ strcpy((*node)->str, str);
+ (*node)->index = UNMARKED_STRING;
+ return (*node)->str;
+ }
+ else
+ {
+ int c = lua_strcmp(str, (*node)->str);
+ if (c < 0)
+ return tree_create(&(*node)->left, str);
+ else if (c > 0)
+ return tree_create(&(*node)->right, str);
+ else
+ return (*node)->str;
+ }
+}
+
+char *lua_strcreate (char *str)
+{
+ return tree_create(&string_root, str);
+}
+
+char *lua_constcreate (char *str)
+{
+ return tree_create(&constant_root, str);
+}
+
+char *lua_varcreate (char *str)
+{
+ return tree_create(&variable_root, str);
+}
+
+
+
+/*
+** Free a node of the tree
+*/
+static TreeNode *lua_strfree (TreeNode *parent)
+{
+ if (parent->left == NULL && parent->right == NULL) /* no child */
+ {
+ free (parent);
+ return NULL;
+ }
+ else if (parent->left == NULL) /* only right child */
+ {
+ TreeNode *p = parent->right;
+ free (parent);
+ return p;
+ }
+ else if (parent->right == NULL) /* only left child */
+ {
+ TreeNode *p = parent->left;
+ free (parent);
+ return p;
+ }
+ else /* two children */
+ {
+ TreeNode *p = parent, *r = parent->right;
+ while (r->left != NULL)
+ {
+ p = r;
+ r = r->left;
+ }
+ if (p == parent)
+ {
+ r->left = parent->left;
+ parent->left = NULL;
+ parent->right = r->right;
+ r->right = lua_strfree(parent);
+ }
+ else
+ {
+ TreeNode *t = r->right;
+ r->left = parent->left;
+ r->right = parent->right;
+ parent->left = NULL;
+ parent->right = t;
+ p->left = lua_strfree(parent);
+ }
+ return r;
+ }
+}
+
+/*
+** Traverse tree for garbage collection
+*/
+static TreeNode *lua_travcollector (TreeNode *r)
+{
+ if (r == NULL) return NULL;
+ r->right = lua_travcollector(r->right);
+ r->left = lua_travcollector(r->left);
+ if (r->index == UNMARKED_STRING)
+ return lua_strfree(r);
+ else
+ {
+ r->index = UNMARKED_STRING;
+ return r;
+ }
+}
+
+
+/*
+** Garbage collection function.
+** This function traverse the tree freening unindexed strings
+*/
+void lua_strcollector (void)
+{
+ string_root = lua_travcollector(string_root);
+}
+
+/*
+** Return next variable.
+*/
+static TreeNode *tree_next (TreeNode *node, char *str)
+{
+#if 0
+ if (node == NULL) return NULL;
+ if (str == NULL || lua_strcmp(str, node->str) < 0)
+ {
+ TreeNode *result = tree_next(node->left, str);
+ return result == NULL ? node : result;
+ }
+ else
+ {
+ return tree_next(node->right, str);
+ }
+#else
+ if (node == NULL) return NULL;
+ else if (str == NULL) return node;
+ else
+ {
+ int c = lua_strcmp(str, node->str);
+ if (c == 0)
+ return node->left != NULL ? node->left : node->right;
+ else if (c < 0)
+ {
+ TreeNode *result = tree_next(node->left, str);
+ return result != NULL ? result : node->right;
+ }
+ else
+ return tree_next(node->right, str);
+ }
+#endif
+}
+
+char *lua_varnext (char *n)
+{
+ TreeNode *result = tree_next(variable_root, n);
+ return result != NULL ? result->str : NULL;
+}
+
+
+/*
+** Given an id, find the string with exaustive search
+*/
+static char *tree_name (TreeNode *node, Word index)
+{
+ if (node == NULL) return NULL;
+ if (node->index == index) return node->str;
+ else
+ {
+ char *result = tree_name(node->left, index);
+ return result != NULL ? result : tree_name(node->right, index);
+ }
+}
+char *lua_varname (Word index)
+{
+ return tree_name(variable_root, index);
+}
diff --git a/tree.h b/tree.h
@@ -0,0 +1,27 @@
+/*
+** tree.h
+** TecCGraf - PUC-Rio
+** $Id: $
+*/
+
+#ifndef tree_h
+#define tree_h
+
+#include "opcode.h"
+
+
+#define UNMARKED_STRING 0xFFFF
+#define MARKED_STRING 0xFFFE
+#define MAX_WORD 0xFFFD
+
+#define indexstring(s) (*(((Word *)s)-1))
+
+
+char *lua_strcreate (char *str);
+char *lua_constcreate (char *str);
+char *lua_varcreate (char *str);
+void lua_strcollector (void);
+char *lua_varnext (char *n);
+char *lua_varname (Word index);
+
+#endif