// Copyright (C) 1999-2003 Core Technologies. // // This file is part of tpasm. // // tpasm is free software; you can redistribute it and/or modify // it under the terms of the tpasm LICENSE AGREEMENT. // // tpasm is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // tpasm LICENSE AGREEMENT for more details. // // You should have received a copy of the tpasm LICENSE AGREEMENT // along with tpasm; see the file "LICENSE.TXT". // Low level symbol table handling #include "include.h" static unsigned int STHash(const char *name) // Return the hash value for the given name and table size. { unsigned int hash; unsigned int count; hash=0; for(count=0;name[count];count++) { hash^=1<<(name[count]&0x0F); hash^=((name[count]>>4)&0x0F)<<(count&0x07); } return(hash%STHASHTABLESIZE); } static inline bool STCompNames(const char *name1,const char *name2) // Compares the given names and returns true if they are the same. { return(strcmp(name1,name2)==0); } SYMTABLENODE *STFindNode(SYMTABLE *table,const char *name) // Find the node with the given name. // return NULL if none could be located { int hash; SYMTABLENODE *theNode; hash=STHash(name); theNode=table->hashList[hash]; while(theNode&&!STCompNames(name,theNode->name)) { theNode=theNode->hashNext; } return(theNode); } void STRemoveEntry(SYMTABLE *table,SYMTABLENODE *theNode) // Removes any entry with the given name from the table. { if(theNode->hashNext) // first unlink it from the hash table { theNode->hashNext->hashPrev=theNode->hashPrev; } if(theNode->hashPrev) { theNode->hashPrev->hashNext=theNode->hashNext; } else { table->hashList[theNode->hashValue]=theNode->hashNext; } if(theNode->prev==NULL) // then unlink it from the ordered list { table->first=theNode->next; if(theNode->next==NULL) { table->last=NULL; } else { theNode->next->prev=NULL; } } else { theNode->prev->next=theNode->next; if(theNode->next==NULL) { table->last=theNode->prev; } else { theNode->next->prev=theNode->prev; } } DisposePtr(theNode); // and then destroy it } static SYMTABLENODE *STCreateNode(const char *name,void *data) // Returns a new node containing the given name and data. // NOTE: the hash value is calculated at this time, and placed into // the node as well { SYMTABLENODE *newNode; if((newNode=(SYMTABLENODE*)NewPtr(sizeof(SYMTABLENODE)+strlen(name)+1))) { newNode->data=data; newNode->hashValue=STHash(name); strcpy(newNode->name,name); return(newNode); } return(NULL); } SYMTABLENODE *STAddEntryAtStart(SYMTABLE *table,const char *name,void *data) // Adds the given name and data to table as the first entry. // It is allowed for two names in the table to have the same value, but // it is not guaranteed which will be returned when searching { SYMTABLENODE *newNode; if((newNode=STCreateNode(name,data))) { if(table->hashList[newNode->hashValue]) { table->hashList[newNode->hashValue]->hashPrev=newNode; } newNode->hashNext=table->hashList[newNode->hashValue]; // link into hash list newNode->hashPrev=NULL; table->hashList[newNode->hashValue]=newNode; if(table->first) // then link into ordered list { table->first->prev=newNode; } else { table->last=newNode; // first entry in the table } newNode->next=table->first; newNode->prev=NULL; table->first=newNode; } return(newNode); } SYMTABLENODE *STAddEntryAtEnd(SYMTABLE *table,const char *name,void *data) // Adds the given name and data to table as the last entry. // It is allowed for two names in the table to have the same value, but // it is not guaranteed which will be returned when searching { SYMTABLENODE *newNode; if((newNode=STCreateNode(name,data))) { if(table->hashList[newNode->hashValue]) { table->hashList[newNode->hashValue]->hashPrev=newNode; } newNode->hashNext=table->hashList[newNode->hashValue]; // link into hash list newNode->hashPrev=NULL; table->hashList[newNode->hashValue]=newNode; if(table->last) // then link into ordered list { table->last->next=newNode; } else { table->first=newNode; // first entry in the table } newNode->prev=table->last; newNode->next=NULL; table->last=newNode; } return(newNode); } void *STFindDataForName(SYMTABLE *table,const char *name) // Finds the data for name in the table. // Returns pointer to the node's data on success, NULL otherwise. { SYMTABLENODE *curNode; if((curNode=STFindNode(table,name))) { return(curNode->data); } return(NULL); } SYMTABLENODE *STFindFirstEntry(SYMTABLE *table) // Return the first node linked to table { return(table->first); } SYMTABLENODE *STFindLastEntry(SYMTABLE *table) // Return the last node linked to table { return(table->last); } SYMTABLENODE *STFindNextEntry(SYMTABLE *table,SYMTABLENODE *previousEntry) // return the entry just after previousEntry in table { return(previousEntry->next); } SYMTABLENODE *STFindPrevEntry(SYMTABLE *table,SYMTABLENODE *nextEntry) // return the entry just before nextEntry in table { return(nextEntry->prev); } unsigned int STNumEntries(SYMTABLE *table) // Returns the number of entries in the table. { SYMTABLENODE *curEnt; unsigned int numEnts; numEnts=0; curEnt=table->first; while(curEnt!=NULL) { numEnts++; curEnt=curEnt->next; } return(numEnts); } SYMTABLE *STNewSymbolTable() // Create and initialize a new symbol table. { SYMTABLE *theTable; unsigned int count; if((theTable=(SYMTABLE*)NewPtr(sizeof(SYMTABLE)))) { theTable->first=theTable->last=NULL; for(count=0;counthashList[count]=NULL; } return(theTable); } return(NULL); } void STDisposeSymbolTable(SYMTABLE *table) // Dispose of all memory allocated for the given symbol table. Note that // the links are not maintained during the process. { SYMTABLENODE *curEnt, *tmpEnt; curEnt=table->first; while(curEnt) { tmpEnt=curEnt->next; DisposePtr(curEnt); curEnt=tmpEnt; } DisposePtr(table); }