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

symtable.C

Go to the documentation of this file.
00001 
00002 #include <assert.h>
00003 #include <string.h>
00004 #include <stdio.h>
00005 #include "stdtypes.h"
00006 #include "blockpool.h"
00007 #include "pools.h"
00008 #include "str.h"
00009 #include "list.h"
00010 #include "fifo_list.h"
00011 #include "hash_serv.h"
00012 #include "sparse.h"
00013 #include "strtable.h"
00014 #include "sym.h"
00015 #include "type.h"
00016 #include "const.h"
00017 #include "symtable.h"
00018 #include "typetable.h"
00019 #include "dsym.h"
00020 
00021 
00033 sym *symtable::chain_elem::search_list( STRING item )
00034 {
00035     LIST<sym *>::handle h;
00036     sym *list_sym, *sym;
00037     
00038     sym = NULL;
00039     for (h = list.first(); h != NULL; h = list.next(h)) {
00040         list_sym = list.get_item( h );
00041         if ( list_sym->get_name().GetText() == item.GetText() ) {
00042             sym = list_sym;
00043             break;
00044         }  // if
00045     } // for
00046     
00047     return sym;
00048 } // search_list
00049 
00050 
00051 
00059 sym *symtable::new_sym( STRING str, uint kind )
00060 {
00061     sym *pNewSym;
00062 
00063     assert( alloc_pool != NULL );
00064 
00065     switch ( kind ) {
00066     // IDENT: has scope
00067     case sy_ident:
00068         pNewSym = new( alloc_pool ) sym_ident( str );
00069         pNewSym->set_scope( get_owner() );
00070         break;
00071     // TYPE : no scope
00072     case sy_type:
00073         pNewSym = new( alloc_pool ) sym_type( str );
00074         break;
00075     // CONST: no scope
00076     case sy_const:
00077         pNewSym = new( alloc_pool ) sym_const( str );
00078         break;
00079 
00080     // SUBPROG: local symbol table
00081     case sy_subprog:
00082         pNewSym = new( alloc_pool ) sym_subprog( str );
00083 
00084         // the subprogram is in the scope of the owner of this symbol table
00085         pNewSym->set_scope( get_owner() );
00086         // A function or procedure will allocate memory from
00087         // from the same pool as its parent scope (which will be
00088         // either a component or the global scope, in the case of
00089         // a function in a package).
00090         //
00091         pNewSym->get_symtab()->set_pool( alloc_pool );
00092         // Set the allocation pool for the type table
00093         pNewSym->get_typtab()->set_pool( alloc_pool );  
00094         // The symbol table is owned by the subprogram
00095         pNewSym->get_symtab()->set_owner( pNewSym );
00096         break;
00097 
00098     // COMPONENT: local memory pool and local symbol table
00099     case sy_component:
00100         pNewSym = new( alloc_pool ) sym_component( str );
00101 
00102         // symbols in the component scope are owned by the component
00103         pNewSym->get_symtab()->set_owner( pNewSym  );
00104         break;
00105 
00106     // PROCESS: local symbol table
00107     case sy_process:
00108         pNewSym = new( alloc_pool ) sym_process( str );
00109 
00110         // the process is in the scope of its component
00111         pNewSym->set_scope( get_owner() );
00112         // set the memory pool to the pool of the parent
00113         pNewSym->get_symtab()->set_pool( alloc_pool );
00114         // Set the allocation pool for the type table
00115         pNewSym->get_typtab()->set_pool( alloc_pool );  
00116         // The symbol table is owned by the process
00117         pNewSym->get_symtab()->set_owner( pNewSym );
00118         break;
00119     case sy_package:   // its not currently clear what to do about packages
00120     case sy_block_label:
00121     case bad_symbol:
00122     default:
00123         // bad symbol kind
00124         assert( FALSE );
00125         break;
00126     } // switch
00127 
00128     assert( pNewSym != NULL );
00129 
00130     return pNewSym;
00131 } // new_sym
00132 
00133 
00139 sym *symtable::find_sym( STRING name )
00140 {
00141     STRING str;
00142     sym *retsym;
00143     
00144     retsym = NULL;
00145     if (name.GetText() != NULL) {
00146         // If the name is not entered into the string table then
00147         // its not in the symbol table.  Of course the name could
00148         // be in the string table and not in the symbol table, since
00149         // the string table is global and symbol could be out of scope.
00150         str = strtab.find_string( name, FALSE );
00151         if (str.GetText() != NULL) {
00152             unsigned int ix, val;
00153 
00154             val = hash_value( str.GetText() );
00155             // table size should always be a power of 2, so
00156             // table_size - 1 is likely to be a prime.
00157             ix = val % (table_size - 1);
00158             if (hash->probe( ix )) { 
00159                 retsym =  (*hash)[ ix ].search_list( str );
00160             }   
00161         }
00162     }
00163 
00164     return retsym;
00165 } // find_sym
00166 
00167 
00168 
00174 sym *symtable::enter_sym( STRING name, uint kind )
00175 {
00176     unsigned int ix, val;
00177     sym *retsym;
00178     STRING str;
00179 
00180     retsym = NULL;
00181 
00182     if (kind == sy_process) {
00183         // Processes are special cases.  They are allocated by the
00184         // symbol table class, since they are derived from the
00185         // symbol type.  But they are not entered into the symbol
00186         // table, since in VHDL a process name can't be referenced.
00187         // Allocation of processes by the symbol table allows uniform
00188         // allocation of all symbol derived objects.
00189         retsym = new_sym( name, kind);
00190     }
00191     else {
00192 
00193         assert( name.GetText() != NULL );
00194 
00195         val = hash_value( name.GetText() );
00196         str = strtab.find_string( name, TRUE );  // insert into table if its not there.
00197         // table size should always be a power of 2, so
00198         // table_size - 1 is likely to be a prime.
00199         ix = val % (table_size - 1);
00200         if (! hash->probe( ix ) ) {
00201 
00202             hash->insert( chain_elem(), ix );
00203             
00204             retsym = new_sym( str, kind );
00205             (*hash)[ix].list.add( retsym );
00206         }
00207         else {
00208             retsym = (*hash)[ix].search_list( str );
00209             if ( retsym == NULL) {
00210                 retsym = new_sym( str, kind );
00211                 (*hash)[ix].list.add( retsym );
00212             }
00213         }
00214     }
00215 
00216     return retsym;
00217 } // enter_sym
00218 
00219 
00227 void symtable::dealloc_sub_tables(void)
00228 {
00229     uint i;
00230 
00231     for (i = 0; i < table_size; i++) {
00232         if (hash->probe( i )) {
00233             LIST<sym *>::handle h;
00234             sym * pListSym;
00235             
00236             for (h = (*hash)[i].list.first(); h != NULL; h = (*hash)[i].list.next(h)) {
00237                 pListSym = (*hash)[i].list.get_item( h );
00238                 if (pListSym->has_scope()) {
00239                     pListSym->get_symtab()->dealloc_sub_tables();
00240                     pListSym->dealloc();
00241                 }
00242             } // for
00243         } // if
00244     } // for
00245 } // dealloc_sub_tables
00246 
00250 void symtable::pr(FILE *fp)
00251 {
00252     uint i;
00253 
00254     for (i = 0; i < table_size; i++) {
00255         if (hash->probe( i )) {
00256             LIST<sym *>::handle h;
00257             sym * pListSym;
00258             
00259             for (h = (*hash)[i].list.first(); h != NULL; h = (*hash)[i].list.next(h)) {
00260                 // fprintf(fp, "hash_label::pr: i = %d, ", i );
00261                 pListSym = (*hash)[i].list.get_item( h );
00262                 pListSym->get_name().pr(fp);
00263                 fprintf(fp, "\n");
00264             } // for
00265         } // if
00266     } // for
00267 } // pr
00268 
00269 
00270 
00275 sym *symtable::get_sym(void)
00276 {
00277     sym * pHashSym;
00278 
00279     pHashSym = NULL;
00280 
00281     while (list_handle == NULL && hash_slot < table_size) {
00282         if (hash->probe( hash_slot )) {
00283             list_handle = (*hash)[hash_slot].list.first();
00284         }
00285         if (list_handle == NULL) {
00286             hash_slot++;
00287         }
00288     } // while
00289 
00290     if (list_handle != NULL && hash_slot < table_size) {
00291 
00292         pHashSym = (*hash)[hash_slot].list.get_item( list_handle );
00293 
00294         list_handle = (*hash)[hash_slot].list.next(list_handle);
00295 
00296         // if we've hit the end of the list, increment the
00297         // slot so we're not stuck in the same place
00298         if (list_handle == NULL)
00299             hash_slot++;        
00300     }
00301 
00302     return pHashSym;
00303 } // get_str
00304 

Generated on Wed Mar 31 21:15:55 2004 for Data Structures for a VHDL Compiler by doxygen 1.3.3