#include "main/imports.h"
#include "symbol_table.h"
-#include "hash_table.h"
+#include "../../util/hash_table.h"
+#include "util/u_string.h"
struct symbol {
+ /** Symbol name. */
+ char *name;
+
/**
* Link to the next symbol in the table with the same name
*
*/
struct symbol *next_with_same_name;
-
/**
* Link to the next symbol in the table with the same scope
*
*/
struct symbol *next_with_same_scope;
-
- /**
- * Header information for the list of symbols with the same name.
- */
- struct symbol_header *hdr;
-
-
- /**
- * Name space of the symbol
- *
- * Name space are arbitrary user assigned integers. No two symbols can
- * exist in the same name space at the same scope level.
- */
- int name_space;
-
/** Scope depth where this symbol was defined. */
unsigned depth;
};
-/**
- */
-struct symbol_header {
- /** Linkage in list of all headers in a given symbol table. */
- struct symbol_header *next;
-
- /** Symbol name. */
- char *name;
-
- /** Linked list of symbols with the same name. */
- struct symbol *symbols;
-};
-
-
/**
* Element of the scope stack.
*/
/** Top of scope stack. */
struct scope_level *current_scope;
- /** List of all symbol headers in the table. */
- struct symbol_header *hdr;
-
/** Current scope depth. */
unsigned depth;
};
-
-struct _mesa_symbol_table_iterator {
- /**
- * Name space of symbols returned by this iterator.
- */
- int name_space;
-
-
- /**
- * Currently iterated symbol
- *
- * The next call to \c _mesa_symbol_table_iterator_get will return this
- * value. It will also update this value to the value that should be
- * returned by the next call.
- */
- struct symbol *curr;
-};
-
-
-static void
-check_symbol_table(struct _mesa_symbol_table *table)
-{
-#if 1
- struct scope_level *scope;
-
- for (scope = table->current_scope; scope != NULL; scope = scope->next) {
- struct symbol *sym;
-
- for (sym = scope->symbols
- ; sym != NULL
- ; sym = sym->next_with_same_name) {
- const struct symbol_header *const hdr = sym->hdr;
- struct symbol *sym2;
-
- for (sym2 = hdr->symbols
- ; sym2 != NULL
- ; sym2 = sym2->next_with_same_name) {
- assert(sym2->hdr == hdr);
- }
- }
- }
-#endif
-}
-
void
_mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
{
while (sym != NULL) {
struct symbol *const next = sym->next_with_same_scope;
- struct symbol_header *const hdr = sym->hdr;
-
- assert(hdr->symbols == sym);
-
- hdr->symbols = sym->next_with_same_name;
+ struct hash_entry *hte = _mesa_hash_table_search(table->ht,
+ sym->name);
+ if (sym->next_with_same_name) {
+ /* If there is a symbol with this name in an outer scope update
+ * the hash table to point to it.
+ */
+ hte->key = sym->next_with_same_name->name;
+ hte->data = sym->next_with_same_name;
+ } else {
+ _mesa_hash_table_remove(table->ht, hte);
+ free(sym->name);
+ }
free(sym);
-
sym = next;
}
-
- check_symbol_table(table);
}
_mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
{
struct scope_level *const scope = calloc(1, sizeof(*scope));
-
+ if (scope == NULL) {
+ _mesa_error_no_memory(__func__);
+ return;
+ }
+
scope->next = table->current_scope;
table->current_scope = scope;
table->depth++;
}
-static struct symbol_header *
+static struct symbol *
find_symbol(struct _mesa_symbol_table *table, const char *name)
{
- return (struct symbol_header *) hash_table_find(table->ht, name);
-}
-
-
-struct _mesa_symbol_table_iterator *
-_mesa_symbol_table_iterator_ctor(struct _mesa_symbol_table *table,
- int name_space, const char *name)
-{
- struct _mesa_symbol_table_iterator *iter = calloc(1, sizeof(*iter));
- struct symbol_header *const hdr = find_symbol(table, name);
-
- iter->name_space = name_space;
-
- if (hdr != NULL) {
- struct symbol *sym;
-
- for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
- assert(sym->hdr == hdr);
-
- if ((name_space == -1) || (sym->name_space == name_space)) {
- iter->curr = sym;
- break;
- }
- }
- }
-
- return iter;
-}
-
-
-void
-_mesa_symbol_table_iterator_dtor(struct _mesa_symbol_table_iterator *iter)
-{
- free(iter);
-}
-
-
-void *
-_mesa_symbol_table_iterator_get(struct _mesa_symbol_table_iterator *iter)
-{
- return (iter->curr == NULL) ? NULL : iter->curr->data;
-}
-
-
-int
-_mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter)
-{
- struct symbol_header *hdr;
-
- if (iter->curr == NULL) {
- return 0;
- }
-
- hdr = iter->curr->hdr;
- iter->curr = iter->curr->next_with_same_name;
-
- while (iter->curr != NULL) {
- assert(iter->curr->hdr == hdr);
-
- if ((iter->name_space == -1)
- || (iter->curr->name_space == iter->name_space)) {
- return 1;
- }
-
- iter->curr = iter->curr->next_with_same_name;
- }
-
- return 0;
+ struct hash_entry *entry = _mesa_hash_table_search(table->ht, name);
+ return entry ? (struct symbol *) entry->data : NULL;
}
*/
int
_mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
- int name_space, const char *name)
+ const char *name)
{
- struct symbol_header *const hdr = find_symbol(table, name);
- struct symbol *sym;
-
- if (hdr != NULL) {
- for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
- assert(sym->hdr == hdr);
-
- if ((name_space == -1) || (sym->name_space == name_space)) {
- assert(sym->depth <= table->depth);
- return sym->depth - table->depth;
- }
- }
- }
+ struct symbol *const sym = find_symbol(table, name);
+
+ if (sym) {
+ assert(sym->depth <= table->depth);
+ return sym->depth - table->depth;
+ }
- return -1;
+ return -1;
}
void *
_mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
- int name_space, const char *name)
+ const char *name)
{
- struct symbol_header *const hdr = find_symbol(table, name);
+ struct symbol *const sym = find_symbol(table, name);
+ if (sym)
+ return sym->data;
- if (hdr != NULL) {
- struct symbol *sym;
-
-
- for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
- assert(sym->hdr == hdr);
-
- if ((name_space == -1) || (sym->name_space == name_space)) {
- return sym->data;
- }
- }
- }
-
- return NULL;
+ return NULL;
}
int
_mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
- int name_space, const char *name,
- void *declaration)
+ const char *name, void *declaration)
{
- struct symbol_header *hdr;
- struct symbol *sym;
+ struct symbol *new_sym;
+ struct symbol *sym = find_symbol(table, name);
- check_symbol_table(table);
+ if (sym && sym->depth == table->depth)
+ return -1;
- hdr = find_symbol(table, name);
+ new_sym = calloc(1, sizeof(*sym));
+ if (new_sym == NULL) {
+ _mesa_error_no_memory(__func__);
+ return -1;
+ }
- check_symbol_table(table);
+ if (sym) {
+ /* Store link to symbol in outer scope with the same name */
+ new_sym->next_with_same_name = sym;
+ new_sym->name = sym->name;
+ } else {
+ new_sym->name = util_strdup(name);
+ if (new_sym->name == NULL) {
+ free(new_sym);
+ _mesa_error_no_memory(__func__);
+ return -1;
+ }
+ }
- if (hdr == NULL) {
- hdr = calloc(1, sizeof(*hdr));
- hdr->name = strdup(name);
+ new_sym->next_with_same_scope = table->current_scope->symbols;
+ new_sym->data = declaration;
+ new_sym->depth = table->depth;
- hash_table_insert(table->ht, hdr, hdr->name);
- hdr->next = table->hdr;
- table->hdr = hdr;
- }
+ table->current_scope->symbols = new_sym;
- check_symbol_table(table);
+ _mesa_hash_table_insert(table->ht, new_sym->name, new_sym);
- /* If the symbol already exists in this namespace at this scope, it cannot
- * be added to the table.
- */
- for (sym = hdr->symbols
- ; (sym != NULL) && (sym->name_space != name_space)
- ; sym = sym->next_with_same_name) {
- /* empty */
- }
+ return 0;
+}
+
+int
+_mesa_symbol_table_replace_symbol(struct _mesa_symbol_table *table,
+ const char *name,
+ void *declaration)
+{
+ struct symbol *sym = find_symbol(table, name);
- if (sym && (sym->depth == table->depth))
+ /* If the symbol doesn't exist, it cannot be replaced. */
+ if (sym == NULL)
return -1;
- sym = calloc(1, sizeof(*sym));
- sym->next_with_same_name = hdr->symbols;
- sym->next_with_same_scope = table->current_scope->symbols;
- sym->hdr = hdr;
- sym->name_space = name_space;
sym->data = declaration;
- sym->depth = table->depth;
+ return 0;
+}
- assert(sym->hdr == hdr);
+int
+_mesa_symbol_table_add_global_symbol(struct _mesa_symbol_table *table,
+ const char *name, void *declaration)
+{
+ struct scope_level *top_scope;
+ struct symbol *inner_sym = NULL;
+ struct symbol *sym = find_symbol(table, name);
- hdr->symbols = sym;
- table->current_scope->symbols = sym;
+ while (sym) {
+ if (sym->depth == 0)
+ return -1;
- check_symbol_table(table);
- return 0;
+ inner_sym = sym;
+
+ /* Get symbol from the outer scope with the same name */
+ sym = sym->next_with_same_name;
+ }
+
+ /* Find the top-level scope */
+ for (top_scope = table->current_scope; top_scope->next != NULL;
+ top_scope = top_scope->next) {
+ /* empty */
+ }
+
+ sym = calloc(1, sizeof(*sym));
+ if (sym == NULL) {
+ _mesa_error_no_memory(__func__);
+ return -1;
+ }
+
+ if (inner_sym) {
+ /* In case we add the global out of order store a link to the global
+ * symbol in global.
+ */
+ inner_sym->next_with_same_name = sym;
+
+ sym->name = inner_sym->name;
+ } else {
+ sym->name = util_strdup(name);
+ if (sym->name == NULL) {
+ free(sym);
+ _mesa_error_no_memory(__func__);
+ return -1;
+ }
+ }
+
+ sym->next_with_same_scope = top_scope->symbols;
+ sym->data = declaration;
+
+ top_scope->symbols = sym;
+
+ _mesa_hash_table_insert(table->ht, sym->name, sym);
+
+ return 0;
}
+
struct _mesa_symbol_table *
_mesa_symbol_table_ctor(void)
{
struct _mesa_symbol_table *table = calloc(1, sizeof(*table));
if (table != NULL) {
- table->ht = hash_table_ctor(32, hash_table_string_hash,
- hash_table_string_compare);
+ table->ht = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+ _mesa_key_string_equal);
_mesa_symbol_table_push_scope(table);
}
void
_mesa_symbol_table_dtor(struct _mesa_symbol_table *table)
{
- struct symbol_header *hdr;
- struct symbol_header *next;
-
while (table->current_scope != NULL) {
_mesa_symbol_table_pop_scope(table);
}
- for (hdr = table->hdr; hdr != NULL; hdr = next) {
- next = hdr->next;
- free(hdr->name);
- free(hdr);
- }
-
- hash_table_dtor(table->ht);
+ _mesa_hash_table_destroy(table->ht, NULL);
free(table);
}