SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name) /* Find a symbol in the given or any of its parent scopes. The function will ** never create a new symbol, since this can only be done in one specific ** scope. */ { /* Generate the name hash */ unsigned Hash = HashBuf (Name); /* Search for the symbol */ SymEntry* Sym; do { /* Search in the current table. Ignore entries flagged with SF_UNUSED, ** because for such symbols there is a real entry in one of the parent ** scopes. */ if (SymSearchTree (Scope->Table[Hash % Scope->TableSlots], Name, &Sym) == 0) { if (Sym->Flags & SF_UNUSED) { Sym = 0; } else { /* Found, return it */ break; } } else { Sym = 0; } /* Not found, search in the parent scope, if we have one */ Scope = Scope->Parent; } while (Sym == 0 && Scope != 0); /* Return the result */ return Sym; }
SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action) /* Find a new symbol table entry in the given table. If Action contains ** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the ** entry found, or the new entry created, or - in case Action is ** SYM_FIND_EXISTING - return 0. */ { SymEntry* S; /* Global symbol: Get the hash value for the name */ unsigned Hash = HashBuf (Name) % Scope->TableSlots; /* Search for the entry */ int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S); /* If we found an entry, return it */ if (Cmp == 0) { if ((Action & SYM_CHECK_ONLY) == 0 && SymTabIsClosed (Scope)) { S->Flags |= SF_FIXED; } return S; } if (Action & SYM_ALLOC_NEW) { /* Otherwise create a new entry, insert and return it. If the scope is ** already closed, mark the symbol as fixed so it won't be resolved ** by a symbol in the enclosing scopes later. */ SymEntry* N = NewSymEntry (Name, SF_NONE); if (SymTabIsClosed (Scope)) { N->Flags |= SF_FIXED; } N->Sym.Tab = Scope; if (S == 0) { Scope->Table[Hash] = N; } else if (Cmp < 0) { S->Left = N; } else { S->Right = N; } ++Scope->TableEntries; return N; } /* We did not find the entry and AllocNew is false. */ return 0; }
static unsigned HT_GenHash (const void* Key) /* Generate the hash over a key. */ { return HashBuf (Key); }