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