Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 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
}