Main Page | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

dynamic_symbol.c

Go to the documentation of this file.
00001 /*****************************************************************************\
00002  *      File:   dynamic_symbol.c
00003  *      Author: John C. Gyllenhaal
00004  *      Creation Date:  1995
00005  *      Copyright (c) 1995 John C. Gyllenhaal, Wen-mei Hwu and
00006  *                         The Board of Trustees of the University of Illinois.
00007  *                         All rights reserved.
00008  *      The University of Illinois software License Agreement
00009  *      specifies the terms and conditions for redistribution.
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 /* Create and initialize STRING_Symbol_Table.
00034  * Creates a hash table of initial size 2 * expected_size rounded up
00035  * to the closest power of two.  (Min hash size 32)
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     /* If expected size negative, force to be 0 */
00045     if (expected_size < 0)
00046         expected_size = 0;
00047 
00048     /* To prevent infinite loop by sizing algorithm (and running out of
00049      * memory :) ), expected_size must be <= a billion.
00050      */
00051     if (expected_size > 1000000000)
00052         L_punt ("STRING_Symbol_Table: unreasonable expected_size (%u)",
00053                  expected_size);
00054 
00055     /* Want a minumum size of at least twice the expected size */
00056     min_size = expected_size * 2;
00057 
00058     /* Start with a minumum hash size of 32.  
00059      * (Smaller sizes don't work as well with the hashing algorithm)
00060      */
00061     hash_size = 32;
00062 
00063     /* Double hash_size until min_size is reached or exceeded */
00064     while (hash_size < min_size)
00065         hash_size = hash_size << 1;
00066 
00067     
00068     /* Create new symbol table pool (and symbol pool if necessary) */
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     /* Allocate symbol table */
00079     table = (STRING_Symbol_Table *) L_alloc (STRING_Symbol_Table_pool);
00080 
00081     /* Allocate array for hash */
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     /* Initialize hash table */
00090     for (i=0; i < hash_size; i++)
00091         hash[i] = NULL;
00092 
00093     /* Initialize fields */
00094     table->name = strdup (name);
00095     table->hash = hash;
00096     table->hash_size = hash_size;
00097     table->hash_mask = hash_size -1; /* AND mask, works only for power of 2 */
00098     /* Resize when count at 75% of hash_size */
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 /* Frees the symbol table, and optionally frees the data pointed to */
00108 void STRING_delete_symbol_table (STRING_Symbol_Table *table, 
00109                              void (*free_routine)(void *))
00110 {
00111     STRING_Symbol *symbol, *next_symbol;
00112 
00113     /* For all the symbols in the table, free each one */
00114     for (symbol = table->head_symbol; symbol != NULL;
00115          symbol = next_symbol)
00116     {
00117         /* Get the next symbol before deleting this one */
00118         next_symbol = symbol->next_symbol;
00119 
00120         /* If free routine specified, free data */
00121         if (free_routine != NULL)
00122             free_routine (symbol->data);
00123 
00124         /* Free symbol structure and name*/
00125         free (symbol->name);
00126         L_free (STRING_Symbol_pool, symbol);
00127     }
00128 
00129     /* Free the hash array and table name*/
00130     free (table->hash);
00131     free (table->name);
00132 
00133     /* Free the table structure */
00134     L_free (STRING_Symbol_Table_pool, table);
00135 }
00136 
00137 /* Doubles the symbol table hash array size */
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     /* Double the size of the hash array */
00146     new_hash_size = table->hash_size * 2;
00147 
00148     /* Allocate new hash array */
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     /* Initialize new hash table */
00157     for (i=0; i < new_hash_size; i++)
00158         new_hash[i] = NULL;
00159 
00160     /* Get the hash mask for the new hash table */
00161     new_hash_mask = new_hash_size -1; /* AND mask, works only for power of 2 */
00162     
00163     /* Go though all the symbol and add to new hash table.
00164      * Can totally disreguard old hash links.
00165      */
00166     for (symbol = table->head_symbol; symbol != NULL; 
00167          symbol = symbol->next_symbol)
00168     {
00169         /* Get index into hash table to use for this name */
00170         new_hash_index = symbol->hash_val & new_hash_mask;
00171         
00172         /* Add symbol to head of linked list */
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     /* Free old hash table */
00182     free (table->hash);
00183    
00184     /* Initialize table fields for new hash table */
00185     table->hash = new_hash;
00186     table->hash_size = new_hash_size;
00187     table->hash_mask = new_hash_mask;
00188     /* Resize when count at 75% of new_hash_size */
00189     table->resize_size = new_hash_size - (new_hash_size >> 2); 
00190 }
00191 
00192 /* Hashes a string, returning an unsigned 32 bit number. */
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     /* Scan through all the characters, adding the characters to the
00202      * hash value.  Multiply the hash value by 17 (using shifts) before
00203      * adding each character in.
00204      *
00205      * This very quick hash algorithm was tuned to work well with
00206      * strings ending with numbers.
00207      */
00208     ptr = (unsigned char *) string;
00209     while ((ch = *ptr) != 0)
00210     {
00211         /* Multiply hash_val by 17 by adding 16*hash_val to it.
00212          * (Use a shift, integer multiply is usually very expensive)
00213          */
00214         hash_val += (hash_val << 4);
00215 
00216         /* Add in character value */
00217         hash_val += ch;
00218 
00219         /* Goto next character */
00220         ptr ++;
00221     }
00222 
00223     /* Return the hash value */
00224     return (hash_val);
00225 }
00226 
00227 
00228 /* Adds structure to symbol table, data is not copied (name is)!!! 
00229  * Dynamically increases symbol table's hash array.
00230  * Returns pointer to added symbol.
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     /* Increase symbol table size if necessary before adding new symbol.  
00240      * This will change the hash_mask if the table is resized!
00241      */
00242     symbol_count = table->symbol_count;
00243     if (symbol_count >= table->resize_size)
00244     {
00245         STRING_resize_symbol_table (table);
00246     }
00247 
00248     /* Allocate a symbol (pool initialized in create table routine)*/
00249     symbol = (STRING_Symbol *) L_alloc (STRING_Symbol_pool);
00250     
00251     /* Initialize fields */
00252     symbol->name = strdup(name);
00253     symbol->data = data;
00254     symbol->table = table;
00255 
00256     /* Get tail symbol for ease of use */
00257     tail_symbol = table->tail_symbol;
00258 
00259     /* Add to linked list of symbols */
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     /* Get hash value of name and put in symbol structure for quick compare
00271      * and table resize.
00272      */
00273     hash_val = STRING_hash_string (name);
00274     symbol->hash_val = hash_val;
00275 
00276     /* Get index into hash table */
00277     hash_index = hash_val & table->hash_mask;
00278     
00279     /* Get head symbol in current linked list for ease of use */
00280     hash_head = table->hash[hash_index];
00281 
00282     
00283     /* Sanity check (may want to ifdef out later).
00284      *
00285      * Check that this symbol's name is not already in the symbol table.
00286      * Punt if it is, since can cause a major debugging nightmare.
00287      */
00288     for (check_symbol = hash_head; check_symbol != NULL;
00289          check_symbol = check_symbol->next_hash)
00290     {
00291         /* Check hash value before doing strcmp to avoid function
00292          * call when possible.
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     /* Add symbol to head of linked list */
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     /* Update table's symbol count */
00311     table->symbol_count = symbol_count + 1;
00312 
00313     /* Return symbol added */
00314     return (symbol);
00315 }
00316 
00317 /* Returns a STRING_Symbol structure with the desired name, or NULL
00318  * if the name is not in the symbol table.
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     /* Get the hash value for the name */
00326     hash_val = STRING_hash_string (name);
00327 
00328     /* Get the index into the hash table */
00329     hash_index = hash_val & table->hash_mask;
00330 
00331     /* Search the linked list for matching name */
00332     for (symbol = table->hash[hash_index]; symbol != NULL; 
00333          symbol = symbol->next_hash)
00334     {
00335         /* Compare hash_vals first before using string compare */
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  * Returns the data for desired name, or NULL
00348  * if the name is not in the symbol table.
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     /* Get the hash value for the name */
00356     hash_val = STRING_hash_string (name);
00357 
00358     /* Get the index into the hash table */
00359     hash_index = hash_val & table->hash_mask;
00360 
00361     /* Search the linked list for matching name */
00362     for (symbol = table->hash[hash_index]; symbol != NULL; 
00363          symbol = symbol->next_hash)
00364     {
00365         /* Compare hash_vals first before using string compare */
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 /* Deletes symbol and optionally deletes the data using the free routine */
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     /* Get the table the symbol is from */
00384     table = symbol->table;
00385 
00386     /* Get the hash index from the symbol's hash_val */
00387     hash_index = symbol->hash_val & table->hash_mask;
00388 
00389     /* Remove symbol from hash table */
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     /* Remove symbol from symbol list */
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     /* If free routine specified, free symbol data */
00415     if (free_routine != NULL)
00416         free_routine (symbol->data);
00417 
00418 
00419     /* Free symbol structure and name*/
00420     free (symbol->name);
00421     L_free (STRING_Symbol_pool, symbol);
00422 
00423     /* Decrement table symbol count */
00424     table->symbol_count --;
00425 }
00426 
00427 
00428 /* Prints out the symbol table's hash table (debug routine) */
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     /* Count lines used in table */
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     /* For each hash_index in hash table */
00445     for (hash_index = 0; hash_index < table->hash_size; hash_index++)
00446     {
00447         /* Skip empty lines */
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  *** INT routines
00465  ***
00466  ***/
00467 
00468 /* Create and initialize INT_Symbol_Table.
00469  * Creates a hash table of initial size 2 * expected_size rounded up
00470  * to the closest power of two.  (Min hash size 32)
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     /* If expected size negative, force to be 0 */
00480     if (expected_size < 0)
00481         expected_size = 0;
00482 
00483     /* To prevent infinite loop by sizing algorithm (and running out of
00484      * memory :) ), expected_size must be <= a billion.
00485      */
00486     if (expected_size > 1000000000)
00487         L_punt ("INT_Symbol_Table: unreasonable expected_size (%u)",
00488                  expected_size);
00489 
00490     /* Want a minumum size of at least twice the expected size */
00491     min_size = expected_size * 2;
00492 
00493     /* Start with a minumum hash size of 32.  
00494      * (Smaller sizes don't work as well with the hashing algorithm)
00495      */
00496     hash_size = 32;
00497 
00498     /* Double hash_size until min_size is reached or exceeded */
00499     while (hash_size < min_size)
00500         hash_size = hash_size << 1;
00501 
00502     
00503     /* Create new symbol table pool (and symbol pool if necessary) */
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     /* Allocate symbol table */
00514     table = (INT_Symbol_Table *) L_alloc (INT_Symbol_Table_pool);
00515 
00516     /* Allocate array for hash */
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     /* Initialize hash table */
00525     for (i=0; i < hash_size; i++)
00526         hash[i] = NULL;
00527 
00528     /* Initialize fields */
00529     table->name = strdup (name);
00530     table->hash = hash;
00531     table->hash_size = hash_size;
00532     table->hash_mask = hash_size -1; /* AND mask, works only for power of 2 */
00533     /* Resize when count at 75% of hash_size */
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 /* Frees the symbol table, and optionally frees the data pointed to */
00543 void INT_delete_symbol_table (INT_Symbol_Table *table, 
00544                              void (*free_routine)(void *))
00545 {
00546     INT_Symbol *symbol, *next_symbol;
00547 
00548     /* For all the symbols in the table, free each one */
00549     for (symbol = table->head_symbol; symbol != NULL;
00550          symbol = next_symbol)
00551     {
00552         /* Get the next symbol before deleting this one */
00553         next_symbol = symbol->next_symbol;
00554 
00555         /* If free routine specified, free data */
00556         if (free_routine != NULL)
00557             free_routine (symbol->data);
00558 
00559         /* Free symbol structure */
00560         L_free (INT_Symbol_pool, symbol);
00561     }
00562 
00563     /* Free the hash array and table name*/
00564     free (table->hash);
00565     free (table->name);
00566 
00567     /* Free the table structure */
00568     L_free (INT_Symbol_Table_pool, table);
00569 }
00570 
00571 /* Doubles the symbol table hash array size */
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     /* Double the size of the hash array */
00580     new_hash_size = table->hash_size * 2;
00581 
00582     /* Allocate new hash array */
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     /* Initialize new hash table */
00591     for (i=0; i < new_hash_size; i++)
00592         new_hash[i] = NULL;
00593 
00594     /* Get the hash mask for the new hash table */
00595     new_hash_mask = new_hash_size -1; /* AND mask, works only for power of 2 */
00596     
00597     /* Go though all the symbol and add to new hash table.
00598      * Can totally disreguard old hash links.
00599      */
00600     for (symbol = table->head_symbol; symbol != NULL; 
00601          symbol = symbol->next_symbol)
00602     {
00603         /* Get index into hash table to use for this name */
00604         new_hash_index = symbol->value & new_hash_mask;
00605         
00606         /* Add symbol to head of linked list */
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     /* Free old hash table */
00616     free (table->hash);
00617    
00618     /* Initialize table fields for new hash table */
00619     table->hash = new_hash;
00620     table->hash_size = new_hash_size;
00621     table->hash_mask = new_hash_mask;
00622     /* Resize when count at 75% of new_hash_size */
00623     table->resize_size = new_hash_size - (new_hash_size >> 2); 
00624 }
00625 
00626 
00627 /* Adds structure to symbol table, data is not copied!!! 
00628  * Dynamically increases symbol table's hash array.
00629  * Returns pointer to added symbol.
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     /* Increase symbol table size if necessary before adding new symbol.  
00638      * This will change the hash_mask if the table is resized!
00639      */
00640     symbol_count = table->symbol_count;
00641     if (symbol_count >= table->resize_size)
00642     {
00643         INT_resize_symbol_table (table);
00644     }
00645 
00646     /* Allocate a symbol (pool initialized in create table routine)*/
00647     symbol = (INT_Symbol *) L_alloc (INT_Symbol_pool);
00648     
00649     /* Initialize fields */
00650     symbol->value = value;
00651     symbol->data = data;
00652     symbol->table = table;
00653 
00654     /* Get tail symbol for ease of use */
00655     tail_symbol = table->tail_symbol;
00656 
00657     /* Add to linked list of symbols */
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     /* Get index into hash table to use for this value */
00668     hash_index = value & table->hash_mask;
00669     
00670     /* Get head symbol in current linked list for ease of use */
00671     hash_head = table->hash[hash_index];
00672 
00673     
00674     /* Sanity check (may want to ifdef out later).
00675      *
00676      * Check that this symbol's name is not already in the symbol table.
00677      * Punt if it is, since can cause a major debugging nightmare.
00678      */
00679     for (check_symbol = hash_head; check_symbol != NULL;
00680          check_symbol = check_symbol->next_hash)
00681     {
00682         /* If value the same, punt */
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     /* Add symbol to head of linked list */
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     /* Update table's symbol count */
00699     table->symbol_count = symbol_count + 1;
00700 
00701     /* Return symbol added */
00702     return (symbol);
00703 }
00704 
00705 /* Returns a INT_Symbol structure with the desired valuee, or NULL
00706  * if the value is not in the symbol table.
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     /* Get the index into the hash table */
00714     hash_index = value & table->hash_mask;
00715 
00716     /* Search the linked list for matching name */
00717     for (symbol = table->hash[hash_index]; symbol != NULL; 
00718          symbol = symbol->next_hash)
00719     {
00720         /* Compare values to find match */
00721         if (symbol->value == value)
00722         {
00723             return (symbol);
00724         }
00725     }
00726     return (NULL);
00727 }
00728 
00729 /* 
00730  * Returns the data for desired value, or NULL
00731  * if the name is not in the symbol table.
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     /* Get the index into the hash table */
00739     hash_index = value & table->hash_mask;
00740 
00741     /* Search the linked list for matching name */
00742     for (symbol = table->hash[hash_index]; symbol != NULL; 
00743          symbol = symbol->next_hash)
00744     {
00745         /* Compare values to find match */
00746         if (symbol->value == value)
00747         {
00748             return (symbol->data);
00749         }
00750     }
00751     return (NULL);
00752 }
00753 
00754 /* Deletes symbol and optionally deletes the data using the free routine */
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     /* Get the table the symbol is from */
00762     table = symbol->table;
00763 
00764     /* Get the hash index from the symbol's value */
00765     hash_index = symbol->value & table->hash_mask;
00766 
00767     /* Remove symbol from hash table */
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     /* Remove symbol from symbol list */
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     /* If free routine specified, free symbol data */
00793     if (free_routine != NULL)
00794         free_routine (symbol->data);
00795 
00796     /* Free symbol structure */
00797     L_free (INT_Symbol_pool, symbol);
00798 
00799     /* Decrement table symbol count */
00800     table->symbol_count --;
00801 }
00802 
00803 
00804 /* Prints out the symbol table's hash table (debug routine) */
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     /* Count lines used in table */
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     /* For each hash_index in hash table */
00821     for (hash_index = 0; hash_index < table->hash_size; hash_index++)
00822     {
00823         /* Skip empty lines */
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 

Generated on Mon Jul 21 20:24:10 2003 for TINKER LEGO DOC by doxygen 1.3.2