Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2008 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. #include "main/imports.h"
  25. #include "symbol_table.h"
  26. #include "hash_table.h"
  27.  
  28. struct symbol {
  29.     /**
  30.      * Link to the next symbol in the table with the same name
  31.      *
  32.      * The linked list of symbols with the same name is ordered by scope
  33.      * from inner-most to outer-most.
  34.      */
  35.     struct symbol *next_with_same_name;
  36.  
  37.  
  38.     /**
  39.      * Link to the next symbol in the table with the same scope
  40.      *
  41.      * The linked list of symbols with the same scope is unordered.  Symbols
  42.      * in this list my have unique names.
  43.      */
  44.     struct symbol *next_with_same_scope;
  45.  
  46.  
  47.     /**
  48.      * Header information for the list of symbols with the same name.
  49.      */
  50.     struct symbol_header *hdr;
  51.  
  52.  
  53.     /**
  54.      * Name space of the symbol
  55.      *
  56.      * Name space are arbitrary user assigned integers.  No two symbols can
  57.      * exist in the same name space at the same scope level.
  58.      */
  59.     int name_space;
  60.  
  61.     /** Scope depth where this symbol was defined. */
  62.     unsigned depth;
  63.  
  64.     /**
  65.      * Arbitrary user supplied data.
  66.      */
  67.     void *data;
  68. };
  69.  
  70.  
  71. /**
  72.  */
  73. struct symbol_header {
  74.     /** Linkage in list of all headers in a given symbol table. */
  75.     struct symbol_header *next;
  76.  
  77.     /** Symbol name. */
  78.     char *name;
  79.  
  80.     /** Linked list of symbols with the same name. */
  81.     struct symbol *symbols;
  82. };
  83.  
  84.  
  85. /**
  86.  * Element of the scope stack.
  87.  */
  88. struct scope_level {
  89.     /** Link to next (inner) scope level. */
  90.     struct scope_level *next;
  91.    
  92.     /** Linked list of symbols with the same scope. */
  93.     struct symbol *symbols;
  94. };
  95.  
  96.  
  97. /**
  98.  *
  99.  */
  100. struct _mesa_symbol_table {
  101.     /** Hash table containing all symbols in the symbol table. */
  102.     struct hash_table *ht;
  103.  
  104.     /** Top of scope stack. */
  105.     struct scope_level *current_scope;
  106.  
  107.     /** List of all symbol headers in the table. */
  108.     struct symbol_header *hdr;
  109.  
  110.     /** Current scope depth. */
  111.     unsigned depth;
  112. };
  113.  
  114.  
  115. static void
  116. check_symbol_table(struct _mesa_symbol_table *table)
  117. {
  118. #if !defined(NDEBUG)
  119.     struct scope_level *scope;
  120.  
  121.     for (scope = table->current_scope; scope != NULL; scope = scope->next) {
  122.         struct symbol *sym;
  123.  
  124.         for (sym = scope->symbols
  125.              ; sym != NULL
  126.              ; sym = sym->next_with_same_name) {
  127.             const struct symbol_header *const hdr = sym->hdr;
  128.             struct symbol *sym2;
  129.  
  130.             for (sym2 = hdr->symbols
  131.                  ; sym2 != NULL
  132.                  ; sym2 = sym2->next_with_same_name) {
  133.                 assert(sym2->hdr == hdr);
  134.             }
  135.         }
  136.     }
  137. #else
  138.     (void) table;
  139. #endif /* !defined(NDEBUG) */
  140. }
  141.  
  142. void
  143. _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
  144. {
  145.     struct scope_level *const scope = table->current_scope;
  146.     struct symbol *sym = scope->symbols;
  147.  
  148.     table->current_scope = scope->next;
  149.     table->depth--;
  150.  
  151.     free(scope);
  152.  
  153.     while (sym != NULL) {
  154.         struct symbol *const next = sym->next_with_same_scope;
  155.         struct symbol_header *const hdr = sym->hdr;
  156.  
  157.         assert(hdr->symbols == sym);
  158.  
  159.         hdr->symbols = sym->next_with_same_name;
  160.  
  161.         free(sym);
  162.  
  163.         sym = next;
  164.     }
  165.  
  166.     check_symbol_table(table);
  167. }
  168.  
  169.  
  170. void
  171. _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
  172. {
  173.     struct scope_level *const scope = calloc(1, sizeof(*scope));
  174.    
  175.     if (scope == NULL) {
  176.        _mesa_error_no_memory(__func__);
  177.        return;
  178.     }
  179.  
  180.     scope->next = table->current_scope;
  181.     table->current_scope = scope;
  182.     table->depth++;
  183. }
  184.  
  185.  
  186. static struct symbol_header *
  187. find_symbol(struct _mesa_symbol_table *table, const char *name)
  188. {
  189.     return (struct symbol_header *) hash_table_find(table->ht, name);
  190. }
  191.  
  192.  
  193. /**
  194.  * Determine the scope "distance" of a symbol from the current scope
  195.  *
  196.  * \return
  197.  * A non-negative number for the number of scopes between the current scope
  198.  * and the scope where a symbol was defined.  A value of zero means the current
  199.  * scope.  A negative number if the symbol does not exist.
  200.  */
  201. int
  202. _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
  203.                                 int name_space, const char *name)
  204. {
  205.     struct symbol_header *const hdr = find_symbol(table, name);
  206.     struct symbol *sym;
  207.  
  208.     if (hdr != NULL) {
  209.        for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
  210.           assert(sym->hdr == hdr);
  211.  
  212.           if ((name_space == -1) || (sym->name_space == name_space)) {
  213.              assert(sym->depth <= table->depth);
  214.              return sym->depth - table->depth;
  215.           }
  216.        }
  217.     }
  218.  
  219.     return -1;
  220. }
  221.  
  222.  
  223. void *
  224. _mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
  225.                                int name_space, const char *name)
  226. {
  227.     struct symbol_header *const hdr = find_symbol(table, name);
  228.  
  229.     if (hdr != NULL) {
  230.         struct symbol *sym;
  231.  
  232.  
  233.         for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
  234.             assert(sym->hdr == hdr);
  235.  
  236.             if ((name_space == -1) || (sym->name_space == name_space)) {
  237.                 return sym->data;
  238.             }
  239.         }
  240.     }
  241.  
  242.     return NULL;
  243. }
  244.  
  245.  
  246. int
  247. _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
  248.                               int name_space, const char *name,
  249.                               void *declaration)
  250. {
  251.     struct symbol_header *hdr;
  252.     struct symbol *sym;
  253.  
  254.     check_symbol_table(table);
  255.  
  256.     hdr = find_symbol(table, name);
  257.  
  258.     check_symbol_table(table);
  259.  
  260.     if (hdr == NULL) {
  261.        hdr = calloc(1, sizeof(*hdr));
  262.        if (hdr == NULL) {
  263.           _mesa_error_no_memory(__func__);
  264.           return -1;
  265.        }
  266.  
  267.        hdr->name = strdup(name);
  268.        if (hdr->name == NULL) {
  269.           free(hdr);
  270.           _mesa_error_no_memory(__func__);
  271.           return -1;
  272.        }
  273.  
  274.        hash_table_insert(table->ht, hdr, hdr->name);
  275.        hdr->next = table->hdr;
  276.        table->hdr = hdr;
  277.     }
  278.  
  279.     check_symbol_table(table);
  280.  
  281.     /* If the symbol already exists in this namespace at this scope, it cannot
  282.      * be added to the table.
  283.      */
  284.     for (sym = hdr->symbols
  285.          ; (sym != NULL) && (sym->name_space != name_space)
  286.          ; sym = sym->next_with_same_name) {
  287.        /* empty */
  288.     }
  289.  
  290.     if (sym && (sym->depth == table->depth))
  291.        return -1;
  292.  
  293.     sym = calloc(1, sizeof(*sym));
  294.     if (sym == NULL) {
  295.        _mesa_error_no_memory(__func__);
  296.        return -1;
  297.     }
  298.  
  299.     sym->next_with_same_name = hdr->symbols;
  300.     sym->next_with_same_scope = table->current_scope->symbols;
  301.     sym->hdr = hdr;
  302.     sym->name_space = name_space;
  303.     sym->data = declaration;
  304.     sym->depth = table->depth;
  305.  
  306.     assert(sym->hdr == hdr);
  307.  
  308.     hdr->symbols = sym;
  309.     table->current_scope->symbols = sym;
  310.  
  311.     check_symbol_table(table);
  312.     return 0;
  313. }
  314.  
  315.  
  316. int
  317. _mesa_symbol_table_add_global_symbol(struct _mesa_symbol_table *table,
  318.                                      int name_space, const char *name,
  319.                                      void *declaration)
  320. {
  321.     struct symbol_header *hdr;
  322.     struct symbol *sym;
  323.     struct symbol *curr;
  324.     struct scope_level *top_scope;
  325.  
  326.     check_symbol_table(table);
  327.  
  328.     hdr = find_symbol(table, name);
  329.  
  330.     check_symbol_table(table);
  331.  
  332.     if (hdr == NULL) {
  333.         hdr = calloc(1, sizeof(*hdr));
  334.         if (hdr == NULL) {
  335.            _mesa_error_no_memory(__func__);
  336.            return -1;
  337.         }
  338.  
  339.         hdr->name = strdup(name);
  340.  
  341.         hash_table_insert(table->ht, hdr, hdr->name);
  342.         hdr->next = table->hdr;
  343.         table->hdr = hdr;
  344.     }
  345.  
  346.     check_symbol_table(table);
  347.  
  348.     /* If the symbol already exists in this namespace at this scope, it cannot
  349.      * be added to the table.
  350.      */
  351.     for (sym = hdr->symbols
  352.          ; (sym != NULL) && (sym->name_space != name_space)
  353.          ; sym = sym->next_with_same_name) {
  354.        /* empty */
  355.     }
  356.  
  357.     if (sym && sym->depth == 0)
  358.        return -1;
  359.  
  360.     /* Find the top-level scope */
  361.     for (top_scope = table->current_scope
  362.          ; top_scope->next != NULL
  363.          ; top_scope = top_scope->next) {
  364.        /* empty */
  365.     }
  366.  
  367.     sym = calloc(1, sizeof(*sym));
  368.     if (sym == NULL) {
  369.        _mesa_error_no_memory(__func__);
  370.        return -1;
  371.     }
  372.  
  373.     sym->next_with_same_scope = top_scope->symbols;
  374.     sym->hdr = hdr;
  375.     sym->name_space = name_space;
  376.     sym->data = declaration;
  377.  
  378.     assert(sym->hdr == hdr);
  379.  
  380.     /* Since next_with_same_name is ordered by scope, we need to append the
  381.      * new symbol to the _end_ of the list.
  382.      */
  383.     if (hdr->symbols == NULL) {
  384.        hdr->symbols = sym;
  385.     } else {
  386.        for (curr = hdr->symbols
  387.             ; curr->next_with_same_name != NULL
  388.             ; curr = curr->next_with_same_name) {
  389.           /* empty */
  390.        }
  391.        curr->next_with_same_name = sym;
  392.     }
  393.     top_scope->symbols = sym;
  394.  
  395.     check_symbol_table(table);
  396.     return 0;
  397. }
  398.  
  399.  
  400.  
  401. struct _mesa_symbol_table *
  402. _mesa_symbol_table_ctor(void)
  403. {
  404.     struct _mesa_symbol_table *table = calloc(1, sizeof(*table));
  405.  
  406.     if (table != NULL) {
  407.        table->ht = hash_table_ctor(32, hash_table_string_hash,
  408.                                    hash_table_string_compare);
  409.  
  410.        _mesa_symbol_table_push_scope(table);
  411.     }
  412.  
  413.     return table;
  414. }
  415.  
  416.  
  417. void
  418. _mesa_symbol_table_dtor(struct _mesa_symbol_table *table)
  419. {
  420.    struct symbol_header *hdr;
  421.    struct symbol_header *next;
  422.  
  423.    while (table->current_scope != NULL) {
  424.       _mesa_symbol_table_pop_scope(table);
  425.    }
  426.  
  427.    for (hdr = table->hdr; hdr != NULL; hdr = next) {
  428.        next = hdr->next;
  429.        free(hdr->name);
  430.        free(hdr);
  431.    }
  432.  
  433.    hash_table_dtor(table->ht);
  434.    free(table);
  435. }
  436.