00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef lint
00013 #define lint
00014 static char copyright[] =
00015 "Copyright (c) 1995 John C. Gyllenhaal, Wen-mei Hwu and The Board of \n\
00016 Trustees of the University of Illinois. All rights reserved.\n";
00017 #endif
00018
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include "dynamic_symbol.h"
00023 #include "l_alloc_new.h"
00024 #include "l_punt.h"
00025
00026 L_Alloc_Pool *STRING_Symbol_Table_pool = NULL;
00027 L_Alloc_Pool *STRING_Symbol_pool = NULL;
00028
00029 L_Alloc_Pool *INT_Symbol_Table_pool = NULL;
00030 L_Alloc_Pool *INT_Symbol_pool = NULL;
00031
00032
00033
00034
00035
00036
00037 STRING_Symbol_Table *STRING_new_symbol_table (char *name, int expected_size)
00038 {
00039 STRING_Symbol_Table *table;
00040 STRING_Symbol **hash;
00041 unsigned int min_size, hash_size;
00042 int i;
00043
00044
00045 if (expected_size < 0)
00046 expected_size = 0;
00047
00048
00049
00050
00051 if (expected_size > 1000000000)
00052 L_punt ("STRING_Symbol_Table: unreasonable expected_size (%u)",
00053 expected_size);
00054
00055
00056 min_size = expected_size * 2;
00057
00058
00059
00060
00061 hash_size = 32;
00062
00063
00064 while (hash_size < min_size)
00065 hash_size = hash_size << 1;
00066
00067
00068
00069 if (STRING_Symbol_Table_pool == NULL)
00070 {
00071 STRING_Symbol_Table_pool = L_create_alloc_pool ("STRING_Symbol_Table",
00072 sizeof (STRING_Symbol_Table),
00073 16);
00074 STRING_Symbol_pool = L_create_alloc_pool ("STRING_Symbol",
00075 sizeof (STRING_Symbol), 64);
00076 }
00077
00078
00079 table = (STRING_Symbol_Table *) L_alloc (STRING_Symbol_Table_pool);
00080
00081
00082 hash = (STRING_Symbol **) malloc (hash_size * sizeof(STRING_Symbol *));
00083 if (hash == NULL)
00084 {
00085 L_punt ( "STRING_new_symbol_table: Out of memory, hash array size %i.",
00086 hash_size);
00087 }
00088
00089
00090 for (i=0; i < hash_size; i++)
00091 hash[i] = NULL;
00092
00093
00094 table->name = strdup (name);
00095 table->hash = hash;
00096 table->hash_size = hash_size;
00097 table->hash_mask = hash_size -1;
00098
00099 table->resize_size = hash_size - (hash_size >> 2);
00100 table->head_symbol = NULL;
00101 table->tail_symbol = NULL;
00102 table->symbol_count = 0;
00103
00104 return (table);
00105 }
00106
00107
00108 void STRING_delete_symbol_table (STRING_Symbol_Table *table,
00109 void (*free_routine)(void *))
00110 {
00111 STRING_Symbol *symbol, *next_symbol;
00112
00113
00114 for (symbol = table->head_symbol; symbol != NULL;
00115 symbol = next_symbol)
00116 {
00117
00118 next_symbol = symbol->next_symbol;
00119
00120
00121 if (free_routine != NULL)
00122 free_routine (symbol->data);
00123
00124
00125 free (symbol->name);
00126 L_free (STRING_Symbol_pool, symbol);
00127 }
00128
00129
00130 free (table->hash);
00131 free (table->name);
00132
00133
00134 L_free (STRING_Symbol_Table_pool, table);
00135 }
00136
00137
00138 void STRING_resize_symbol_table (STRING_Symbol_Table *table)
00139 {
00140 STRING_Symbol **new_hash, *symbol, *hash_head;
00141 int new_hash_size;
00142 unsigned int new_hash_mask, new_hash_index;
00143 int i;
00144
00145
00146 new_hash_size = table->hash_size * 2;
00147
00148
00149 new_hash = (STRING_Symbol **) malloc (new_hash_size * sizeof (STRING_Symbol *));
00150 if (new_hash == NULL)
00151 {
00152 L_punt ("STRING_resize_symbol_table: Out of memory, new size %i.",
00153 new_hash_size);
00154 }
00155
00156
00157 for (i=0; i < new_hash_size; i++)
00158 new_hash[i] = NULL;
00159
00160
00161 new_hash_mask = new_hash_size -1;
00162
00163
00164
00165
00166 for (symbol = table->head_symbol; symbol != NULL;
00167 symbol = symbol->next_symbol)
00168 {
00169
00170 new_hash_index = symbol->hash_val & new_hash_mask;
00171
00172
00173 hash_head = new_hash[new_hash_index];
00174 symbol->next_hash = hash_head;
00175 symbol->prev_hash = NULL;
00176 if (hash_head != NULL)
00177 hash_head->prev_hash = symbol;
00178 new_hash[new_hash_index] = symbol;
00179 }
00180
00181
00182 free (table->hash);
00183
00184
00185 table->hash = new_hash;
00186 table->hash_size = new_hash_size;
00187 table->hash_mask = new_hash_mask;
00188
00189 table->resize_size = new_hash_size - (new_hash_size >> 2);
00190 }
00191
00192
00193 static unsigned int STRING_hash_string (char *string)
00194 {
00195 unsigned int hash_val;
00196 unsigned char *ptr;
00197 unsigned int ch;
00198
00199 hash_val = 0;
00200
00201
00202
00203
00204
00205
00206
00207
00208 ptr = (unsigned char *) string;
00209 while ((ch = *ptr) != 0)
00210 {
00211
00212
00213
00214 hash_val += (hash_val << 4);
00215
00216
00217 hash_val += ch;
00218
00219
00220 ptr ++;
00221 }
00222
00223
00224 return (hash_val);
00225 }
00226
00227
00228
00229
00230
00231
00232 STRING_Symbol *STRING_add_symbol (STRING_Symbol_Table *table, char *name,
00233 void *data)
00234 {
00235 STRING_Symbol *symbol, *hash_head, *check_symbol, *tail_symbol;
00236 unsigned int hash_val, hash_index;
00237 int symbol_count;
00238
00239
00240
00241
00242 symbol_count = table->symbol_count;
00243 if (symbol_count >= table->resize_size)
00244 {
00245 STRING_resize_symbol_table (table);
00246 }
00247
00248
00249 symbol = (STRING_Symbol *) L_alloc (STRING_Symbol_pool);
00250
00251
00252 symbol->name = strdup(name);
00253 symbol->data = data;
00254 symbol->table = table;
00255
00256
00257 tail_symbol = table->tail_symbol;
00258
00259
00260 symbol->next_symbol = NULL;
00261 symbol->prev_symbol = tail_symbol;
00262
00263 if (tail_symbol == NULL)
00264 table->head_symbol = symbol;
00265 else
00266 tail_symbol->next_symbol = symbol;
00267 table->tail_symbol = symbol;
00268
00269
00270
00271
00272
00273 hash_val = STRING_hash_string (name);
00274 symbol->hash_val = hash_val;
00275
00276
00277 hash_index = hash_val & table->hash_mask;
00278
00279
00280 hash_head = table->hash[hash_index];
00281
00282
00283
00284
00285
00286
00287
00288 for (check_symbol = hash_head; check_symbol != NULL;
00289 check_symbol = check_symbol->next_hash)
00290 {
00291
00292
00293
00294 if ((check_symbol->hash_val == hash_val) &&
00295 (strcmp(check_symbol->name, name) == 0))
00296 {
00297 L_punt ("%s: cannot add '%s', already in table!",
00298 table->name, name);
00299 }
00300 }
00301
00302
00303
00304 symbol->next_hash = hash_head;
00305 symbol->prev_hash = NULL;
00306 if (hash_head != NULL)
00307 hash_head->prev_hash = symbol;
00308 table->hash[hash_index] = symbol;
00309
00310
00311 table->symbol_count = symbol_count + 1;
00312
00313
00314 return (symbol);
00315 }
00316
00317
00318
00319
00320 STRING_Symbol *STRING_find_symbol (STRING_Symbol_Table *table, char *name)
00321 {
00322 STRING_Symbol *symbol;
00323 unsigned int hash_val, hash_index;
00324
00325
00326 hash_val = STRING_hash_string (name);
00327
00328
00329 hash_index = hash_val & table->hash_mask;
00330
00331
00332 for (symbol = table->hash[hash_index]; symbol != NULL;
00333 symbol = symbol->next_hash)
00334 {
00335
00336 if ((symbol->hash_val == hash_val) &&
00337 (strcmp(symbol->name, name) == 0))
00338 {
00339 return (symbol);
00340 }
00341 }
00342
00343 return (NULL);
00344 }
00345
00346
00347
00348
00349
00350 void *STRING_find_symbol_data (STRING_Symbol_Table *table, char *name)
00351 {
00352 STRING_Symbol *symbol;
00353 unsigned int hash_val, hash_index;
00354
00355
00356 hash_val = STRING_hash_string (name);
00357
00358
00359 hash_index = hash_val & table->hash_mask;
00360
00361
00362 for (symbol = table->hash[hash_index]; symbol != NULL;
00363 symbol = symbol->next_hash)
00364 {
00365
00366 if ((symbol->hash_val == hash_val) &&
00367 (strcmp(symbol->name, name) == 0))
00368 {
00369 return (symbol->data);
00370 }
00371 }
00372
00373 return (NULL);
00374 }
00375
00376
00377 void STRING_delete_symbol (STRING_Symbol *symbol, void (*free_routine)(void *))
00378 {
00379 STRING_Symbol_Table *table;
00380 STRING_Symbol *next_hash, *prev_hash, *next_symbol, *prev_symbol;
00381 unsigned int hash_index;
00382
00383
00384 table = symbol->table;
00385
00386
00387 hash_index = symbol->hash_val & table->hash_mask;
00388
00389
00390 prev_hash = symbol->prev_hash;
00391 next_hash = symbol->next_hash;
00392 if (prev_hash == NULL)
00393 table->hash[hash_index] = next_hash;
00394 else
00395 prev_hash->next_hash = next_hash;
00396
00397 if (next_hash != NULL)
00398 next_hash->prev_hash = prev_hash;
00399
00400
00401 prev_symbol = symbol->prev_symbol;
00402 next_symbol = symbol->next_symbol;
00403 if (prev_symbol == NULL)
00404 table->head_symbol = next_symbol;
00405 else
00406 prev_symbol->next_symbol = next_symbol;
00407
00408 if (next_symbol == NULL)
00409 table->tail_symbol = prev_symbol;
00410 else
00411 next_symbol->prev_symbol = prev_symbol;
00412
00413
00414
00415 if (free_routine != NULL)
00416 free_routine (symbol->data);
00417
00418
00419
00420 free (symbol->name);
00421 L_free (STRING_Symbol_pool, symbol);
00422
00423
00424 table->symbol_count --;
00425 }
00426
00427
00428
00429 void STRING_print_symbol_table_hash (FILE *out, STRING_Symbol_Table *table)
00430 {
00431 STRING_Symbol *symbol;
00432 int hash_index, lines;
00433
00434
00435 lines = 0;
00436 for (hash_index = 0; hash_index < table->hash_size; hash_index++)
00437 {
00438 if (table->hash[hash_index] != NULL)
00439 lines++;
00440 }
00441 fprintf (out, "%s has %i entries (hash size %i, used %i):\n",
00442 table->name, table->symbol_count, table->hash_size, lines);
00443
00444
00445 for (hash_index = 0; hash_index < table->hash_size; hash_index++)
00446 {
00447
00448 if (table->hash[hash_index] == NULL)
00449 continue;
00450
00451 fprintf (out, "%4i:", hash_index);
00452 for (symbol = table->hash[hash_index]; symbol != NULL;
00453 symbol = symbol->next_hash)
00454 {
00455 fprintf (out, " %s", symbol->name);
00456 }
00457 fprintf (out, "\n");
00458 }
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 INT_Symbol_Table *INT_new_symbol_table (char *name, int expected_size)
00473 {
00474 INT_Symbol_Table *table;
00475 INT_Symbol **hash;
00476 unsigned int min_size, hash_size;
00477 int i;
00478
00479
00480 if (expected_size < 0)
00481 expected_size = 0;
00482
00483
00484
00485
00486 if (expected_size > 1000000000)
00487 L_punt ("INT_Symbol_Table: unreasonable expected_size (%u)",
00488 expected_size);
00489
00490
00491 min_size = expected_size * 2;
00492
00493
00494
00495
00496 hash_size = 32;
00497
00498
00499 while (hash_size < min_size)
00500 hash_size = hash_size << 1;
00501
00502
00503
00504 if (INT_Symbol_Table_pool == NULL)
00505 {
00506 INT_Symbol_Table_pool = L_create_alloc_pool ("INT_Symbol_Table",
00507 sizeof (INT_Symbol_Table),
00508 16);
00509 INT_Symbol_pool = L_create_alloc_pool ("INT_Symbol",
00510 sizeof (INT_Symbol), 64);
00511 }
00512
00513
00514 table = (INT_Symbol_Table *) L_alloc (INT_Symbol_Table_pool);
00515
00516
00517 hash = (INT_Symbol **) malloc (hash_size * sizeof(INT_Symbol *));
00518 if (hash == NULL)
00519 {
00520 L_punt ( "INT_new_symbol_table: Out of memory, hash array size %i.",
00521 hash_size);
00522 }
00523
00524
00525 for (i=0; i < hash_size; i++)
00526 hash[i] = NULL;
00527
00528
00529 table->name = strdup (name);
00530 table->hash = hash;
00531 table->hash_size = hash_size;
00532 table->hash_mask = hash_size -1;
00533
00534 table->resize_size = hash_size - (hash_size >> 2);
00535 table->head_symbol = NULL;
00536 table->tail_symbol = NULL;
00537 table->symbol_count = 0;
00538
00539 return (table);
00540 }
00541
00542
00543 void INT_delete_symbol_table (INT_Symbol_Table *table,
00544 void (*free_routine)(void *))
00545 {
00546 INT_Symbol *symbol, *next_symbol;
00547
00548
00549 for (symbol = table->head_symbol; symbol != NULL;
00550 symbol = next_symbol)
00551 {
00552
00553 next_symbol = symbol->next_symbol;
00554
00555
00556 if (free_routine != NULL)
00557 free_routine (symbol->data);
00558
00559
00560 L_free (INT_Symbol_pool, symbol);
00561 }
00562
00563
00564 free (table->hash);
00565 free (table->name);
00566
00567
00568 L_free (INT_Symbol_Table_pool, table);
00569 }
00570
00571
00572 void INT_resize_symbol_table (INT_Symbol_Table *table)
00573 {
00574 INT_Symbol **new_hash, *symbol, *hash_head;
00575 int new_hash_size;
00576 unsigned int new_hash_mask, new_hash_index;
00577 int i;
00578
00579
00580 new_hash_size = table->hash_size * 2;
00581
00582
00583 new_hash = (INT_Symbol **) malloc (new_hash_size * sizeof (INT_Symbol *));
00584 if (new_hash == NULL)
00585 {
00586 L_punt ("INT_resize_symbol_table: Out of memory, new size %i.",
00587 new_hash_size);
00588 }
00589
00590
00591 for (i=0; i < new_hash_size; i++)
00592 new_hash[i] = NULL;
00593
00594
00595 new_hash_mask = new_hash_size -1;
00596
00597
00598
00599
00600 for (symbol = table->head_symbol; symbol != NULL;
00601 symbol = symbol->next_symbol)
00602 {
00603
00604 new_hash_index = symbol->value & new_hash_mask;
00605
00606
00607 hash_head = new_hash[new_hash_index];
00608 symbol->next_hash = hash_head;
00609 symbol->prev_hash = NULL;
00610 if (hash_head != NULL)
00611 hash_head->prev_hash = symbol;
00612 new_hash[new_hash_index] = symbol;
00613 }
00614
00615
00616 free (table->hash);
00617
00618
00619 table->hash = new_hash;
00620 table->hash_size = new_hash_size;
00621 table->hash_mask = new_hash_mask;
00622
00623 table->resize_size = new_hash_size - (new_hash_size >> 2);
00624 }
00625
00626
00627
00628
00629
00630
00631 INT_Symbol *INT_add_symbol (INT_Symbol_Table *table, int value, void *data)
00632 {
00633 INT_Symbol *symbol, *hash_head, *check_symbol, *tail_symbol;
00634 unsigned int hash_index;
00635 int symbol_count;
00636
00637
00638
00639
00640 symbol_count = table->symbol_count;
00641 if (symbol_count >= table->resize_size)
00642 {
00643 INT_resize_symbol_table (table);
00644 }
00645
00646
00647 symbol = (INT_Symbol *) L_alloc (INT_Symbol_pool);
00648
00649
00650 symbol->value = value;
00651 symbol->data = data;
00652 symbol->table = table;
00653
00654
00655 tail_symbol = table->tail_symbol;
00656
00657
00658 symbol->next_symbol = NULL;
00659 symbol->prev_symbol = tail_symbol;
00660
00661 if (tail_symbol == NULL)
00662 table->head_symbol = symbol;
00663 else
00664 tail_symbol->next_symbol = symbol;
00665 table->tail_symbol = symbol;
00666
00667
00668 hash_index = value & table->hash_mask;
00669
00670
00671 hash_head = table->hash[hash_index];
00672
00673
00674
00675
00676
00677
00678
00679 for (check_symbol = hash_head; check_symbol != NULL;
00680 check_symbol = check_symbol->next_hash)
00681 {
00682
00683 if (check_symbol->value == value)
00684 {
00685 L_punt ("%s: cannot add '%i', already in table!",
00686 table->name, value);
00687 }
00688 }
00689
00690
00691
00692 symbol->next_hash = hash_head;
00693 symbol->prev_hash = NULL;
00694 if (hash_head != NULL)
00695 hash_head->prev_hash = symbol;
00696 table->hash[hash_index] = symbol;
00697
00698
00699 table->symbol_count = symbol_count + 1;
00700
00701
00702 return (symbol);
00703 }
00704
00705
00706
00707
00708 INT_Symbol *INT_find_symbol (INT_Symbol_Table *table, int value)
00709 {
00710 INT_Symbol *symbol;
00711 unsigned int hash_index;
00712
00713
00714 hash_index = value & table->hash_mask;
00715
00716
00717 for (symbol = table->hash[hash_index]; symbol != NULL;
00718 symbol = symbol->next_hash)
00719 {
00720
00721 if (symbol->value == value)
00722 {
00723 return (symbol);
00724 }
00725 }
00726 return (NULL);
00727 }
00728
00729
00730
00731
00732
00733 void *INT_find_symbol_data (INT_Symbol_Table *table, int value)
00734 {
00735 INT_Symbol *symbol;
00736 unsigned int hash_index;
00737
00738
00739 hash_index = value & table->hash_mask;
00740
00741
00742 for (symbol = table->hash[hash_index]; symbol != NULL;
00743 symbol = symbol->next_hash)
00744 {
00745
00746 if (symbol->value == value)
00747 {
00748 return (symbol->data);
00749 }
00750 }
00751 return (NULL);
00752 }
00753
00754
00755 void INT_delete_symbol (INT_Symbol *symbol, void (*free_routine)(void *))
00756 {
00757 INT_Symbol_Table *table;
00758 INT_Symbol *next_hash, *prev_hash, *next_symbol, *prev_symbol;
00759 unsigned int hash_index;
00760
00761
00762 table = symbol->table;
00763
00764
00765 hash_index = symbol->value & table->hash_mask;
00766
00767
00768 prev_hash = symbol->prev_hash;
00769 next_hash = symbol->next_hash;
00770 if (prev_hash == NULL)
00771 table->hash[hash_index] = next_hash;
00772 else
00773 prev_hash->next_hash = next_hash;
00774
00775 if (next_hash != NULL)
00776 next_hash->prev_hash = prev_hash;
00777
00778
00779 prev_symbol = symbol->prev_symbol;
00780 next_symbol = symbol->next_symbol;
00781 if (prev_symbol == NULL)
00782 table->head_symbol = next_symbol;
00783 else
00784 prev_symbol->next_symbol = next_symbol;
00785
00786 if (next_symbol == NULL)
00787 table->tail_symbol = prev_symbol;
00788 else
00789 next_symbol->prev_symbol = prev_symbol;
00790
00791
00792
00793 if (free_routine != NULL)
00794 free_routine (symbol->data);
00795
00796
00797 L_free (INT_Symbol_pool, symbol);
00798
00799
00800 table->symbol_count --;
00801 }
00802
00803
00804
00805 void INT_print_symbol_table_hash (FILE *out, INT_Symbol_Table *table)
00806 {
00807 INT_Symbol *symbol;
00808 int hash_index, lines;
00809
00810
00811 lines = 0;
00812 for (hash_index = 0; hash_index < table->hash_size; hash_index++)
00813 {
00814 if (table->hash[hash_index] != NULL)
00815 lines++;
00816 }
00817 fprintf (out, "%s has %i entries (hash size %i, used %i):\n",
00818 table->name, table->symbol_count, table->hash_size, lines);
00819
00820
00821 for (hash_index = 0; hash_index < table->hash_size; hash_index++)
00822 {
00823
00824 if (table->hash[hash_index] == NULL)
00825 continue;
00826
00827 fprintf (out, "%4i:", hash_index);
00828 for (symbol = table->hash[hash_index]; symbol != NULL;
00829 symbol = symbol->next_hash)
00830 {
00831 fprintf (out, " %i", symbol->value);
00832 }
00833 fprintf (out, "\n");
00834 }
00835 }
00836
00837