Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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. struct _mesa_symbol_table_iterator {
  116.     /**
  117.      * Name space of symbols returned by this iterator.
  118.      */
  119.     int name_space;
  120.  
  121.  
  122.     /**
  123.      * Currently iterated symbol
  124.      *
  125.      * The next call to \c _mesa_symbol_table_iterator_get will return this
  126.      * value.  It will also update this value to the value that should be
  127.      * returned by the next call.
  128.      */
  129.     struct symbol *curr;
  130. };
  131.  
  132.  
  133. static void
  134. check_symbol_table(struct _mesa_symbol_table *table)
  135. {
  136. #if 1
  137.     struct scope_level *scope;
  138.  
  139.     for (scope = table->current_scope; scope != NULL; scope = scope->next) {
  140.         struct symbol *sym;
  141.  
  142.         for (sym = scope->symbols
  143.              ; sym != NULL
  144.              ; sym = sym->next_with_same_name) {
  145.             const struct symbol_header *const hdr = sym->hdr;
  146.             struct symbol *sym2;
  147.  
  148.             for (sym2 = hdr->symbols
  149.                  ; sym2 != NULL
  150.                  ; sym2 = sym2->next_with_same_name) {
  151.                 assert(sym2->hdr == hdr);
  152.             }
  153.         }
  154.     }
  155. #endif
  156. }
  157.  
  158. void
  159. _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table)
  160. {
  161.     struct scope_level *const scope = table->current_scope;
  162.     struct symbol *sym = scope->symbols;
  163.  
  164.     table->current_scope = scope->next;
  165.     table->depth--;
  166.  
  167.     free(scope);
  168.  
  169.     while (sym != NULL) {
  170.         struct symbol *const next = sym->next_with_same_scope;
  171.         struct symbol_header *const hdr = sym->hdr;
  172.  
  173.         assert(hdr->symbols == sym);
  174.  
  175.         hdr->symbols = sym->next_with_same_name;
  176.  
  177.         free(sym);
  178.  
  179.         sym = next;
  180.     }
  181.  
  182.     check_symbol_table(table);
  183. }
  184.  
  185.  
  186. void
  187. _mesa_symbol_table_push_scope(struct _mesa_symbol_table *table)
  188. {
  189.     struct scope_level *const scope = calloc(1, sizeof(*scope));
  190.    
  191.     scope->next = table->current_scope;
  192.     table->current_scope = scope;
  193.     table->depth++;
  194. }
  195.  
  196.  
  197. static struct symbol_header *
  198. find_symbol(struct _mesa_symbol_table *table, const char *name)
  199. {
  200.     return (struct symbol_header *) hash_table_find(table->ht, name);
  201. }
  202.  
  203.  
  204. struct _mesa_symbol_table_iterator *
  205. _mesa_symbol_table_iterator_ctor(struct _mesa_symbol_table *table,
  206.                                  int name_space, const char *name)
  207. {
  208.     struct _mesa_symbol_table_iterator *iter = calloc(1, sizeof(*iter));
  209.     struct symbol_header *const hdr = find_symbol(table, name);
  210.    
  211.     iter->name_space = name_space;
  212.  
  213.     if (hdr != NULL) {
  214.         struct symbol *sym;
  215.  
  216.         for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
  217.             assert(sym->hdr == hdr);
  218.  
  219.             if ((name_space == -1) || (sym->name_space == name_space)) {
  220.                 iter->curr = sym;
  221.                 break;
  222.             }
  223.         }
  224.     }
  225.  
  226.     return iter;
  227. }
  228.  
  229.  
  230. void
  231. _mesa_symbol_table_iterator_dtor(struct _mesa_symbol_table_iterator *iter)
  232. {
  233.     free(iter);
  234. }
  235.  
  236.  
  237. void *
  238. _mesa_symbol_table_iterator_get(struct _mesa_symbol_table_iterator *iter)
  239. {
  240.     return (iter->curr == NULL) ? NULL : iter->curr->data;
  241. }
  242.  
  243.  
  244. int
  245. _mesa_symbol_table_iterator_next(struct _mesa_symbol_table_iterator *iter)
  246. {
  247.     struct symbol_header *hdr;
  248.  
  249.     if (iter->curr == NULL) {
  250.         return 0;
  251.     }
  252.  
  253.     hdr = iter->curr->hdr;
  254.     iter->curr = iter->curr->next_with_same_name;
  255.  
  256.     while (iter->curr != NULL) {
  257.         assert(iter->curr->hdr == hdr);
  258.         (void)hdr;
  259.  
  260.         if ((iter->name_space == -1)
  261.             || (iter->curr->name_space == iter->name_space)) {
  262.             return 1;
  263.         }
  264.  
  265.         iter->curr = iter->curr->next_with_same_name;
  266.     }
  267.  
  268.     return 0;
  269. }
  270.  
  271.  
  272. /**
  273.  * Determine the scope "distance" of a symbol from the current scope
  274.  *
  275.  * \return
  276.  * A non-negative number for the number of scopes between the current scope
  277.  * and the scope where a symbol was defined.  A value of zero means the current
  278.  * scope.  A negative number if the symbol does not exist.
  279.  */
  280. int
  281. _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
  282.                                 int name_space, const char *name)
  283. {
  284.     struct symbol_header *const hdr = find_symbol(table, name);
  285.     struct symbol *sym;
  286.  
  287.     if (hdr != NULL) {
  288.        for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
  289.           assert(sym->hdr == hdr);
  290.  
  291.           if ((name_space == -1) || (sym->name_space == name_space)) {
  292.              assert(sym->depth <= table->depth);
  293.              return sym->depth - table->depth;
  294.           }
  295.        }
  296.     }
  297.  
  298.     return -1;
  299. }
  300.  
  301.  
  302. void *
  303. _mesa_symbol_table_find_symbol(struct _mesa_symbol_table *table,
  304.                                int name_space, const char *name)
  305. {
  306.     struct symbol_header *const hdr = find_symbol(table, name);
  307.  
  308.     if (hdr != NULL) {
  309.         struct symbol *sym;
  310.  
  311.  
  312.         for (sym = hdr->symbols; sym != NULL; sym = sym->next_with_same_name) {
  313.             assert(sym->hdr == hdr);
  314.  
  315.             if ((name_space == -1) || (sym->name_space == name_space)) {
  316.                 return sym->data;
  317.             }
  318.         }
  319.     }
  320.  
  321.     return NULL;
  322. }
  323.  
  324.  
  325. int
  326. _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
  327.                               int name_space, const char *name,
  328.                               void *declaration)
  329. {
  330.     struct symbol_header *hdr;
  331.     struct symbol *sym;
  332.  
  333.     check_symbol_table(table);
  334.  
  335.     hdr = find_symbol(table, name);
  336.  
  337.     check_symbol_table(table);
  338.  
  339.     if (hdr == NULL) {
  340.        hdr = calloc(1, sizeof(*hdr));
  341.        hdr->name = strdup(name);
  342.  
  343.        hash_table_insert(table->ht, hdr, hdr->name);
  344.        hdr->next = table->hdr;
  345.        table->hdr = hdr;
  346.     }
  347.  
  348.     check_symbol_table(table);
  349.  
  350.     /* If the symbol already exists in this namespace at this scope, it cannot
  351.      * be added to the table.
  352.      */
  353.     for (sym = hdr->symbols
  354.          ; (sym != NULL) && (sym->name_space != name_space)
  355.          ; sym = sym->next_with_same_name) {
  356.        /* empty */
  357.     }
  358.  
  359.     if (sym && (sym->depth == table->depth))
  360.        return -1;
  361.  
  362.     sym = calloc(1, sizeof(*sym));
  363.     sym->next_with_same_name = hdr->symbols;
  364.     sym->next_with_same_scope = table->current_scope->symbols;
  365.     sym->hdr = hdr;
  366.     sym->name_space = name_space;
  367.     sym->data = declaration;
  368.     sym->depth = table->depth;
  369.  
  370.     assert(sym->hdr == hdr);
  371.  
  372.     hdr->symbols = sym;
  373.     table->current_scope->symbols = sym;
  374.  
  375.     check_symbol_table(table);
  376.     return 0;
  377. }
  378.  
  379.  
  380. int
  381. _mesa_symbol_table_add_global_symbol(struct _mesa_symbol_table *table,
  382.                                      int name_space, const char *name,
  383.                                      void *declaration)
  384. {
  385.     struct symbol_header *hdr;
  386.     struct symbol *sym;
  387.     struct symbol *curr;
  388.     struct scope_level *top_scope;
  389.  
  390.     check_symbol_table(table);
  391.  
  392.     hdr = find_symbol(table, name);
  393.  
  394.     check_symbol_table(table);
  395.  
  396.     if (hdr == NULL) {
  397.         hdr = calloc(1, sizeof(*hdr));
  398.         hdr->name = strdup(name);
  399.  
  400.         hash_table_insert(table->ht, hdr, hdr->name);
  401.         hdr->next = table->hdr;
  402.         table->hdr = hdr;
  403.     }
  404.  
  405.     check_symbol_table(table);
  406.  
  407.     /* If the symbol already exists in this namespace at this scope, it cannot
  408.      * be added to the table.
  409.      */
  410.     for (sym = hdr->symbols
  411.          ; (sym != NULL) && (sym->name_space != name_space)
  412.          ; sym = sym->next_with_same_name) {
  413.        /* empty */
  414.     }
  415.  
  416.     if (sym && sym->depth == 0)
  417.        return -1;
  418.  
  419.     /* Find the top-level scope */
  420.     for (top_scope = table->current_scope
  421.          ; top_scope->next != NULL
  422.          ; top_scope = top_scope->next) {
  423.        /* empty */
  424.     }
  425.  
  426.     sym = calloc(1, sizeof(*sym));
  427.     sym->next_with_same_scope = top_scope->symbols;
  428.     sym->hdr = hdr;
  429.     sym->name_space = name_space;
  430.     sym->data = declaration;
  431.  
  432.     assert(sym->hdr == hdr);
  433.  
  434.     /* Since next_with_same_name is ordered by scope, we need to append the
  435.      * new symbol to the _end_ of the list.
  436.      */
  437.     if (hdr->symbols == NULL) {
  438.        hdr->symbols = sym;
  439.     } else {
  440.        for (curr = hdr->symbols
  441.             ; curr->next_with_same_name != NULL
  442.             ; curr = curr->next_with_same_name) {
  443.           /* empty */
  444.        }
  445.        curr->next_with_same_name = sym;
  446.     }
  447.     top_scope->symbols = sym;
  448.  
  449.     check_symbol_table(table);
  450.     return 0;
  451. }
  452.  
  453.  
  454.  
  455. struct _mesa_symbol_table *
  456. _mesa_symbol_table_ctor(void)
  457. {
  458.     struct _mesa_symbol_table *table = calloc(1, sizeof(*table));
  459.  
  460.     if (table != NULL) {
  461.        table->ht = hash_table_ctor(32, hash_table_string_hash,
  462.                                    hash_table_string_compare);
  463.  
  464.        _mesa_symbol_table_push_scope(table);
  465.     }
  466.  
  467.     return table;
  468. }
  469.  
  470.  
  471. void
  472. _mesa_symbol_table_dtor(struct _mesa_symbol_table *table)
  473. {
  474.    struct symbol_header *hdr;
  475.    struct symbol_header *next;
  476.  
  477.    while (table->current_scope != NULL) {
  478.       _mesa_symbol_table_pop_scope(table);
  479.    }
  480.  
  481.    for (hdr = table->hdr; hdr != NULL; hdr = next) {
  482.        next = hdr->next;
  483.        free(hdr->name);
  484.        free(hdr);
  485.    }
  486.  
  487.    hash_table_dtor(table->ht);
  488.    free(table);
  489. }
  490.