symbol_table: Add support for adding a symbol at top-level/global scope.
authorKenneth Graunke <kenneth@whitecape.org>
Mon, 6 Dec 2010 18:42:27 +0000 (10:42 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 6 Dec 2010 21:43:22 +0000 (13:43 -0800)
src/mesa/program/symbol_table.c
src/mesa/program/symbol_table.h

index 09e7cb4..004f1f8 100644 (file)
@@ -336,12 +336,12 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
     check_symbol_table(table);
 
     if (hdr == NULL) {
-        hdr = calloc(1, sizeof(*hdr));
-        hdr->name = strdup(name);
+       hdr = calloc(1, sizeof(*hdr));
+       hdr->name = strdup(name);
 
-        hash_table_insert(table->ht, hdr, hdr->name);
-       hdr->next = table->hdr;
-       table->hdr = hdr;
+       hash_table_insert(table->ht, hdr, hdr->name);
+       hdr->next = table->hdr;
+       table->hdr = hdr;
     }
 
     check_symbol_table(table);
@@ -376,6 +376,81 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
 }
 
 
+int
+_mesa_symbol_table_add_global_symbol(struct _mesa_symbol_table *table,
+                                    int name_space, const char *name,
+                                    void *declaration)
+{
+    struct symbol_header *hdr;
+    struct symbol *sym;
+    struct symbol *curr;
+    struct scope_level *top_scope;
+
+    check_symbol_table(table);
+
+    hdr = find_symbol(table, name);
+
+    check_symbol_table(table);
+
+    if (hdr == NULL) {
+        hdr = calloc(1, sizeof(*hdr));
+        hdr->name = strdup(name);
+
+        hash_table_insert(table->ht, hdr, hdr->name);
+        hdr->next = table->hdr;
+        table->hdr = hdr;
+    }
+
+    check_symbol_table(table);
+
+    /* 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 */
+    }
+
+    if (sym && sym->depth == 0)
+       return -1;
+
+    /* 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));
+    sym->next_with_same_scope = top_scope->symbols;
+    sym->hdr = hdr;
+    sym->name_space = name_space;
+    sym->data = declaration;
+
+    assert(sym->hdr == hdr);
+
+    /* Since next_with_same_name is ordered by scope, we need to append the
+     * new symbol to the _end_ of the list.
+     */
+    if (hdr->symbols == NULL) {
+       hdr->symbols = sym;
+    } else {
+       for (curr = hdr->symbols
+           ; curr->next_with_same_name != NULL
+           ; curr = curr->next_with_same_name) {
+         /* empty */
+       }
+       curr->next_with_same_name = sym;
+    }
+    top_scope->symbols = sym;
+
+    check_symbol_table(table);
+    return 0;
+}
+
+
+
 struct _mesa_symbol_table *
 _mesa_symbol_table_ctor(void)
 {
index 1d570fc..f9d9164 100644 (file)
@@ -33,6 +33,10 @@ extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table);
 extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab,
     int name_space, const char *name, void *declaration);
 
+extern int _mesa_symbol_table_add_global_symbol(
+    struct _mesa_symbol_table *symtab, int name_space, const char *name,
+    void *declaration);
+
 extern int _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
     int name_space, const char *name);