void EnterGlobalLevel (void) /* Enter the program global lexical level */ { /* Safety */ PRECONDITION (++LexicalLevel == LEX_LEVEL_GLOBAL); /* Create and assign the symbol table */ SymTab0 = SymTab = NewSymTable (SYMTAB_SIZE_GLOBAL); /* Create and assign the tag table */ TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL); }
void EnterBlockLevel (void) /* Enter a nested block in a function */ { SymTable* S; /* New lexical level */ ++LexicalLevel; /* Get a new symbol table and make it current */ S = NewSymTable (SYMTAB_SIZE_BLOCK); S->PrevTab = SymTab; SymTab = S; /* Get a new tag table and make it current */ S = NewSymTable (SYMTAB_SIZE_BLOCK); S->PrevTab = TagTab; TagTab = S; }
void EnterFunctionLevel (void) /* Enter function lexical level */ { SymTable* S; /* New lexical level */ ++LexicalLevel; /* Get a new symbol table and make it current */ S = NewSymTable (SYMTAB_SIZE_FUNCTION); S->PrevTab = SymTab; SymTab = S; /* Get a new tag table and make it current */ S = NewSymTable (SYMTAB_SIZE_FUNCTION); S->PrevTab = TagTab; TagTab = S; /* Create and assign a new label table */ LabelTab = NewSymTable (SYMTAB_SIZE_LABEL); }
void EnterStructLevel (void) /* Enter a nested block for a struct definition */ { SymTable* S; /* Get a new symbol table and make it current. Note: Structs and enums ** nested in struct scope are NOT local to the struct but visible in the ** outside scope. So we will NOT create a new struct or enum table. */ S = NewSymTable (SYMTAB_SIZE_BLOCK); S->PrevTab = SymTab; SymTab = S; }
void ReenterFunctionLevel (struct FuncDesc* F) /* Reenter the function lexical level using the existing tables from F */ { /* New lexical level */ ++LexicalLevel; /* Make the tables current again */ F->SymTab->PrevTab = SymTab; SymTab = F->SymTab; F->TagTab->PrevTab = TagTab; TagTab = F->TagTab; /* Create and assign a new label table */ LabelTab = NewSymTable (SYMTAB_SIZE_LABEL); }
void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, unsigned char AddrSize, SymEntry* ScopeLabel) /* Enter a new lexical level */ { /* Map a default address size to something real */ if (AddrSize == ADDR_SIZE_DEFAULT) { /* Use the segment address size */ AddrSize = GetCurrentSegAddrSize (); } /* If we have a current scope, search for the given name and create a ** new one if it doesn't exist. If this is the root scope, just create it. */ if (CurrentScope) { /* Search for the scope, create a new one */ CurrentScope = SymFindScope (CurrentScope, ScopeName, SYM_ALLOC_NEW); /* Check if the scope has been defined before */ if (CurrentScope->Flags & ST_DEFINED) { Error ("Duplicate scope `%m%p'", ScopeName); } } else { CurrentScope = RootScope = NewSymTable (0, ScopeName); } /* Mark the scope as defined and set type, address size and owner symbol */ CurrentScope->Flags |= ST_DEFINED; CurrentScope->AddrSize = AddrSize; CurrentScope->Type = Type; CurrentScope->Label = ScopeLabel; /* If this is a scope that allows to emit data into segments, add spans ** for all currently existing segments. Doing this for just a few scope ** types is not really necessary but an optimization, because it does not ** allocate memory for useless data (unhandled types here don't occupy ** space in any segment). */ if (CurrentScope->Type <= SCOPE_HAS_DATA) { OpenSpanList (&CurrentScope->Spans); } }
SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Action) /* Find a scope in the given enclosing scope */ { SymTable** T = &Parent->Childs; while (*T) { int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name)); if (Cmp < 0) { T = &(*T)->Left; } else if (Cmp > 0) { T = &(*T)->Right; } else { /* Found the scope */ return *T; } } /* Create a new scope if requested and we didn't find one */ if (*T == 0 && (Action & SYM_ALLOC_NEW) != 0) { *T = NewSymTable (Parent, Name); } /* Return the scope */ return *T; }