2 * Copyright © 2008 Intel Corporation
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:
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
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.
24 #include "main/imports.h"
25 #include "symbol_table.h"
26 #include "../../util/hash_table.h"
30 * Link to the next symbol in the table with the same name
32 * The linked list of symbols with the same name is ordered by scope
33 * from inner-most to outer-most.
35 struct symbol
*next_with_same_name
;
39 * Link to the next symbol in the table with the same scope
41 * The linked list of symbols with the same scope is unordered. Symbols
42 * in this list my have unique names.
44 struct symbol
*next_with_same_scope
;
48 * Header information for the list of symbols with the same name.
50 struct symbol_header
*hdr
;
54 * Name space of the symbol
56 * Name space are arbitrary user assigned integers. No two symbols can
57 * exist in the same name space at the same scope level.
61 /** Scope depth where this symbol was defined. */
65 * Arbitrary user supplied data.
73 struct symbol_header
{
74 /** Linkage in list of all headers in a given symbol table. */
75 struct symbol_header
*next
;
80 /** Linked list of symbols with the same name. */
81 struct symbol
*symbols
;
86 * Element of the scope stack.
89 /** Link to next (inner) scope level. */
90 struct scope_level
*next
;
92 /** Linked list of symbols with the same scope. */
93 struct symbol
*symbols
;
100 struct _mesa_symbol_table
{
101 /** Hash table containing all symbols in the symbol table. */
102 struct hash_table
*ht
;
104 /** Top of scope stack. */
105 struct scope_level
*current_scope
;
107 /** List of all symbol headers in the table. */
108 struct symbol_header
*hdr
;
110 /** Current scope depth. */
116 check_symbol_table(struct _mesa_symbol_table
*table
)
119 struct scope_level
*scope
;
121 for (scope
= table
->current_scope
; scope
!= NULL
; scope
= scope
->next
) {
124 for (sym
= scope
->symbols
126 ; sym
= sym
->next_with_same_name
) {
127 const struct symbol_header
*const hdr
= sym
->hdr
;
130 for (sym2
= hdr
->symbols
132 ; sym2
= sym2
->next_with_same_name
) {
133 assert(sym2
->hdr
== hdr
);
139 #endif /* !defined(NDEBUG) */
143 _mesa_symbol_table_pop_scope(struct _mesa_symbol_table
*table
)
145 struct scope_level
*const scope
= table
->current_scope
;
146 struct symbol
*sym
= scope
->symbols
;
148 table
->current_scope
= scope
->next
;
153 while (sym
!= NULL
) {
154 struct symbol
*const next
= sym
->next_with_same_scope
;
155 struct symbol_header
*const hdr
= sym
->hdr
;
157 assert(hdr
->symbols
== sym
);
159 hdr
->symbols
= sym
->next_with_same_name
;
166 check_symbol_table(table
);
171 _mesa_symbol_table_push_scope(struct _mesa_symbol_table
*table
)
173 struct scope_level
*const scope
= calloc(1, sizeof(*scope
));
176 _mesa_error_no_memory(__func__
);
180 scope
->next
= table
->current_scope
;
181 table
->current_scope
= scope
;
186 static struct symbol_header
*
187 find_symbol(struct _mesa_symbol_table
*table
, const char *name
)
189 struct hash_entry
*entry
= _mesa_hash_table_search(table
->ht
, name
);
190 return entry
? (struct symbol_header
*) entry
->data
: NULL
;
195 * Determine the scope "distance" of a symbol from the current scope
198 * A non-negative number for the number of scopes between the current scope
199 * and the scope where a symbol was defined. A value of zero means the current
200 * scope. A negative number if the symbol does not exist.
203 _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table
*table
,
204 int name_space
, const char *name
)
206 struct symbol_header
*const hdr
= find_symbol(table
, name
);
210 for (sym
= hdr
->symbols
; sym
!= NULL
; sym
= sym
->next_with_same_name
) {
211 assert(sym
->hdr
== hdr
);
213 if ((name_space
== -1) || (sym
->name_space
== name_space
)) {
214 assert(sym
->depth
<= table
->depth
);
215 return sym
->depth
- table
->depth
;
225 _mesa_symbol_table_find_symbol(struct _mesa_symbol_table
*table
,
226 int name_space
, const char *name
)
228 struct symbol_header
*const hdr
= find_symbol(table
, name
);
234 for (sym
= hdr
->symbols
; sym
!= NULL
; sym
= sym
->next_with_same_name
) {
235 assert(sym
->hdr
== hdr
);
237 if ((name_space
== -1) || (sym
->name_space
== name_space
)) {
248 _mesa_symbol_table_add_symbol(struct _mesa_symbol_table
*table
,
249 int name_space
, const char *name
,
252 struct symbol_header
*hdr
;
255 check_symbol_table(table
);
257 hdr
= find_symbol(table
, name
);
259 check_symbol_table(table
);
262 hdr
= calloc(1, sizeof(*hdr
));
264 _mesa_error_no_memory(__func__
);
268 hdr
->name
= strdup(name
);
269 if (hdr
->name
== NULL
) {
271 _mesa_error_no_memory(__func__
);
275 _mesa_hash_table_insert(table
->ht
, hdr
->name
, hdr
);
276 hdr
->next
= table
->hdr
;
280 check_symbol_table(table
);
282 /* If the symbol already exists in this namespace at this scope, it cannot
283 * be added to the table.
285 for (sym
= hdr
->symbols
286 ; (sym
!= NULL
) && (sym
->name_space
!= name_space
)
287 ; sym
= sym
->next_with_same_name
) {
291 if (sym
&& (sym
->depth
== table
->depth
))
294 sym
= calloc(1, sizeof(*sym
));
296 _mesa_error_no_memory(__func__
);
300 sym
->next_with_same_name
= hdr
->symbols
;
301 sym
->next_with_same_scope
= table
->current_scope
->symbols
;
303 sym
->name_space
= name_space
;
304 sym
->data
= declaration
;
305 sym
->depth
= table
->depth
;
307 assert(sym
->hdr
== hdr
);
310 table
->current_scope
->symbols
= sym
;
312 check_symbol_table(table
);
318 _mesa_symbol_table_add_global_symbol(struct _mesa_symbol_table
*table
,
319 int name_space
, const char *name
,
322 struct symbol_header
*hdr
;
325 struct scope_level
*top_scope
;
327 check_symbol_table(table
);
329 hdr
= find_symbol(table
, name
);
331 check_symbol_table(table
);
334 hdr
= calloc(1, sizeof(*hdr
));
336 _mesa_error_no_memory(__func__
);
340 hdr
->name
= strdup(name
);
342 _mesa_hash_table_insert(table
->ht
, hdr
->name
, hdr
);
343 hdr
->next
= table
->hdr
;
347 check_symbol_table(table
);
349 /* If the symbol already exists in this namespace at this scope, it cannot
350 * be added to the table.
352 for (sym
= hdr
->symbols
353 ; (sym
!= NULL
) && (sym
->name_space
!= name_space
)
354 ; sym
= sym
->next_with_same_name
) {
358 if (sym
&& sym
->depth
== 0)
361 /* Find the top-level scope */
362 for (top_scope
= table
->current_scope
363 ; top_scope
->next
!= NULL
364 ; top_scope
= top_scope
->next
) {
368 sym
= calloc(1, sizeof(*sym
));
370 _mesa_error_no_memory(__func__
);
374 sym
->next_with_same_scope
= top_scope
->symbols
;
376 sym
->name_space
= name_space
;
377 sym
->data
= declaration
;
379 assert(sym
->hdr
== hdr
);
381 /* Since next_with_same_name is ordered by scope, we need to append the
382 * new symbol to the _end_ of the list.
384 if (hdr
->symbols
== NULL
) {
387 for (curr
= hdr
->symbols
388 ; curr
->next_with_same_name
!= NULL
389 ; curr
= curr
->next_with_same_name
) {
392 curr
->next_with_same_name
= sym
;
394 top_scope
->symbols
= sym
;
396 check_symbol_table(table
);
402 struct _mesa_symbol_table
*
403 _mesa_symbol_table_ctor(void)
405 struct _mesa_symbol_table
*table
= calloc(1, sizeof(*table
));
408 table
->ht
= _mesa_hash_table_create(NULL
, _mesa_key_hash_string
,
409 _mesa_key_string_equal
);
411 _mesa_symbol_table_push_scope(table
);
419 _mesa_symbol_table_dtor(struct _mesa_symbol_table
*table
)
421 struct symbol_header
*hdr
;
422 struct symbol_header
*next
;
424 while (table
->current_scope
!= NULL
) {
425 _mesa_symbol_table_pop_scope(table
);
428 for (hdr
= table
->hdr
; hdr
!= NULL
; hdr
= next
) {
434 _mesa_hash_table_destroy(table
->ht
, NULL
);