| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 | 
							- /*
 -  * Copyright © 2008 Intel Corporation
 -  *
 -  * Permission is hereby granted, free of charge, to any person obtaining a
 -  * copy of this software and associated documentation files (the "Software"),
 -  * to deal in the Software without restriction, including without limitation
 -  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 -  * and/or sell copies of the Software, and to permit persons to whom the
 -  * Software is furnished to do so, subject to the following conditions:
 -  *
 -  * The above copyright notice and this permission notice (including the next
 -  * paragraph) shall be included in all copies or substantial portions of the
 -  * Software.
 -  *
 -  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 -  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 -  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 -  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 -  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 -  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 -  * DEALINGS IN THE SOFTWARE.
 -  */
 - 
 - #include "main/imports.h"
 - #include "symbol_table.h"
 - #include "hash_table.h"
 - 
 - struct symbol {
 -     /**
 -      * Link to the next symbol in the table with the same name
 -      *
 -      * The linked list of symbols with the same name is ordered by scope
 -      * from inner-most to outer-most.
 -      */
 -     struct symbol *next_with_same_name;
 - 
 - 
 -     /**
 -      * Link to the next symbol in the table with the same scope
 -      *
 -      * The linked list of symbols with the same scope is unordered.  Symbols
 -      * in this list my have unique names.
 -      */
 -     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;
 - 
 -     
 -     /**
 -      * Arbitrary user supplied data.
 -      */
 -     void *data;
 - 
 -    /** 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. */
 -     const char *name;
 - 
 -     /** Linked list of symbols with the same name. */
 -     struct symbol *symbols;
 - };
 - 
 - 
 - /**
 -  * Element of the scope stack.
 -  */
 - struct scope_level {
 -     /** Link to next (inner) scope level. */
 -     struct scope_level *next;
 -     
 -     /** Linked list of symbols with the same scope. */
 -     struct symbol *symbols;
 - };
 - 
 - 
 - /**
 -  *
 -  */
 - struct _mesa_symbol_table {
 -     /** Hash table containing all symbols in the symbol table. */
 -     struct hash_table *ht;
 - 
 -     /** 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)
 - {
 -     struct scope_level *const scope = table->current_scope;
 -     struct symbol *sym = scope->symbols;
 - 
 -     table->current_scope = scope->next;
 -     table->depth--;
 - 
 -     free(scope);
 - 
 -     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;
 - 
 -         free(sym);
 - 
 -         sym = next;
 -     }
 - 
 -     check_symbol_table(table);
 - }
 - 
 - 
 - void
 - _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
 - {
 -     struct scope_level *const scope = calloc(1, sizeof(*scope));
 -     
 -     scope->next = table->current_scope;
 -     table->current_scope = scope;
 -     table->depth++;
 - }
 - 
 - 
 - static struct symbol_header *
 - 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;
 - }
 - 
 - 
 - /**
 -  * Determine the scope "distance" of a symbol from the current scope
 -  *
 -  * \return
 -  * A non-negative number for the number of scopes between the current scope
 -  * and the scope where a symbol was defined.  A value of zero means the current
 -  * scope.  A negative number if the symbol does not exist.
 -  */
 - int
 - _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
 - 				int name_space, 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;
 - 	  }
 -        }
 -     }
 - 
 -     return -1;
 - }
 - 
 - 
 - void *
 - _mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
 -                                int name_space, const char *name)
 - {
 -     struct symbol_header *const hdr = find_symbol(table, name);
 - 
 -     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;
 - }
 - 
 - 
 - int
 - _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
 -                               int name_space, const char *name,
 -                               void *declaration)
 - {
 -     struct symbol_header *hdr;
 -     struct symbol *sym;
 - 
 -     check_symbol_table(table);
 - 
 -     hdr = find_symbol(table, name);
 - 
 -     check_symbol_table(table);
 - 
 -     if (hdr == NULL) {
 -         hdr = calloc(1, sizeof(*hdr));
 -         hdr->name = name;
 - 
 -         hash_table_insert(table->ht, 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 == table->depth))
 -        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;
 - 
 -     assert(sym->hdr == hdr);
 - 
 -     hdr->symbols = sym;
 -     table->current_scope->symbols = sym;
 - 
 -     check_symbol_table(table);
 -     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);
 - 
 -        _mesa_symbol_table_push_scope(table);
 -     }
 - 
 -     return 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;
 -        _mesa_free(hdr);
 -    }
 - 
 -    hash_table_dtor(table->ht);
 -    free(table);
 - }
 
 
  |