SymEntry* AddLabelSym (const char* Name, unsigned Flags) /* Add a goto label to the label table */ { /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name)); if (Entry) { if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) { /* Trying to define the label more than once */ Error ("Label `%s' is defined more than once", Name); } Entry->Flags |= Flags; } else { /* Create a new entry */ Entry = NewSymEntry (Name, SC_LABEL | Flags); /* Set a new label number */ Entry->V.Label = GetLocalLabel (); /* Generate the assembler name of the label */ Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label)); /* Add the entry to the label table */ AddSymEntry (LabelTab, Entry); } /* Return the entry */ return Entry; }
SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val) /* Add an constant symbol to the symbol table and return it */ { /* Enums must be inserted in the global symbol table */ SymTable* Tab = ((Flags & SC_ENUM) == SC_ENUM)? SymTab0 : SymTab; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); if (Entry) { if ((Entry->Flags & SC_CONST) != SC_CONST) { Error ("Symbol `%s' is already different kind", Name); } else { Error ("Multiple definition for `%s'", Name); } return Entry; } /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Enum values are ints */ Entry->Type = TypeDup (T); /* Set the enum data */ Entry->V.ConstVal = Val; /* Add the entry to the symbol table */ AddSymEntry (Tab, Entry); /* Return the entry */ return Entry; }
SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width) /* Add a bit field to the local symbol table and return the symbol entry */ { /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); if (Entry) { /* We have a symbol with this name already */ Error ("Multiple definition for `%s'", Name); } else { /* Create a new entry */ Entry = NewSymEntry (Name, SC_BITFIELD); /* Set the symbol attributes. Bit-fields are always of type unsigned */ Entry->Type = type_uint; Entry->V.B.Offs = Offs; Entry->V.B.BitOffs = BitOffs; Entry->V.B.BitWidth = Width; /* Add the entry to the symbol table */ AddSymEntry (SymTab, Entry); } /* Return the entry */ return Entry; }
SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action) /* Find a cheap local symbol. 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; int Cmp; /* Local symbol, get the table */ if (!Parent) { /* No last global, so there's no local table */ Error ("No preceeding global symbol"); if (Action & SYM_ALLOC_NEW) { return NewSymEntry (Name, SF_LOCAL); } else { return 0; } } /* Search for the symbol if we have a table */ Cmp = SymSearchTree (Parent->Locals, Name, &S); /* If we found an entry, return it */ if (Cmp == 0) { return S; } if (Action & SYM_ALLOC_NEW) { /* Otherwise create a new entry, insert and return it */ SymEntry* N = NewSymEntry (Name, SF_LOCAL); N->Sym.Entry = Parent; if (S == 0) { Parent->Locals = N; } else if (Cmp < 0) { S->Left = N; } else { S->Right = N; } return N; } /* We did not find the entry and AllocNew is false. */ return 0; }
SymEntry* ParseScopedSymName (SymFindAction Action) /* Parse a (possibly scoped) symbol name, search for it in the symbol table * and return the symbol table entry. */ { StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; StrBuf Ident = STATIC_STRBUF_INITIALIZER; int NoScope; SymEntry* Sym; /* Parse the scoped symbol name */ SymTable* Scope = ParseScopedIdent (&Ident, &ScopeName); /* If ScopeName is empty, no scope was specified */ NoScope = SB_IsEmpty (&ScopeName); /* We don't need ScopeName any longer */ SB_Done (&ScopeName); /* Check if the scope is valid. Errors have already been diagnosed by * the routine, so just exit. */ if (Scope) { /* Search for the symbol and return it. If no scope was specified, * search also in the upper levels. */ if (NoScope && (Action & SYM_ALLOC_NEW) == 0) { Sym = SymFindAny (Scope, &Ident); } else { Sym = SymFind (Scope, &Ident, Action); } } else { /* No scope ==> no symbol. To avoid errors in the calling routine that * may not expect NULL to be returned if Action contains SYM_ALLOC_NEW, * create a new symbol. */ if (Action & SYM_ALLOC_NEW) { Sym = NewSymEntry (&Ident, SF_NONE); } else { Sym = 0; } } /* Deallocate memory for ident */ SB_Done (&Ident); /* Return the symbol found */ 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; }
SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs) /* Add a local symbol and return the symbol entry */ { /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); if (Entry) { /* We have a symbol with this name already */ Error ("Multiple definition for `%s'", Name); } else { /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Set the symbol attributes */ Entry->Type = TypeDup (T); if ((Flags & SC_AUTO) == SC_AUTO) { Entry->V.Offs = Offs; } else if ((Flags & SC_REGISTER) == SC_REGISTER) { Entry->V.R.RegOffs = Offs; Entry->V.R.SaveOffs = StackPtr; } else if ((Flags & SC_EXTERN) == SC_EXTERN) { Entry->V.Label = Offs; SymSetAsmName (Entry); } else if ((Flags & SC_STATIC) == SC_STATIC) { /* Generate the assembler name from the label number */ Entry->V.Label = Offs; Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label)); } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) { Entry->V.Offs = Offs; } else { Internal ("Invalid flags in AddLocalSym: %04X", Flags); } /* Add the entry to the symbol table */ AddSymEntry (SymTab, Entry); } /* Return the entry */ return Entry; }
SymEntry* AddStructSym (const char* Name, unsigned Type, unsigned Size, SymTable* Tab) /* Add a struct/union entry and return it */ { SymEntry* Entry; /* Type must be struct or union */ PRECONDITION (Type == SC_STRUCT || Type == SC_UNION); /* Do we have an entry with this name already? */ Entry = FindSymInTable (TagTab, Name, HashStr (Name)); if (Entry) { /* We do have an entry. This may be a forward, so check it. */ if ((Entry->Flags & SC_TYPEMASK) != Type) { /* Existing symbol is not a struct */ Error ("Symbol `%s' is already different kind", Name); } else if (Size > 0 && Entry->V.S.Size > 0) { /* Both structs are definitions. */ Error ("Multiple definition for `%s'", Name); } else { /* Define the struct size if it is given */ if (Size > 0) { Entry->V.S.SymTab = Tab; Entry->V.S.Size = Size; } } } else { /* Create a new entry */ Entry = NewSymEntry (Name, Type); /* Set the struct data */ Entry->V.S.SymTab = Tab; Entry->V.S.Size = Size; /* Add it to the current table */ AddSymEntry (TagTab, Entry); } /* Return the entry */ return Entry; }
SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* Add an external or global symbol to the symbol table and return the entry */ { /* There is some special handling for functions, so check if it is one */ int IsFunc = IsTypeFunc (T); /* Functions must be inserted in the global symbol table */ SymTable* Tab = IsFunc? SymTab0 : SymTab; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); if (Entry) { Type* EType; /* We have a symbol with this name already */ if (Entry->Flags & SC_TYPE) { Error ("Multiple definition for `%s'", Name); return Entry; } /* Get the type string of the existing symbol */ EType = Entry->Type; /* If we are handling arrays, the old entry or the new entry may be an ** incomplete declaration. Accept this, and if the exsting entry is ** incomplete, complete it. */ if (IsTypeArray (T) && IsTypeArray (EType)) { /* Get the array sizes */ long Size = GetElementCount (T); long ESize = GetElementCount (EType); if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) || TypeCmp (T + 1, EType + 1) < TC_EQUAL) { /* Types not identical: Conflicting types */ Error ("Conflicting types for `%s'", Name); return Entry; } else { /* Check if we have a size in the existing definition */ if (ESize == UNSPECIFIED) { /* Existing, size not given, use size from new def */ SetElementCount (EType, Size); } } } else { /* New type must be identical */ if (TypeCmp (EType, T) < TC_EQUAL) { Error ("Conflicting types for `%s'", Name); return Entry; } /* In case of a function, use the new type descriptor, since it ** contains pointers to the new symbol tables that are needed if ** an actual function definition follows. Be sure not to use the ** new descriptor if it contains a function declaration with an ** empty parameter list. */ if (IsFunc) { /* Get the function descriptor from the new type */ FuncDesc* F = GetFuncDesc (T); /* Use this new function descriptor if it doesn't contain ** an empty parameter list. */ if ((F->Flags & FD_EMPTY) == 0) { Entry->V.F.Func = F; SetFuncDesc (EType, F); } } } /* Add the new flags */ Entry->Flags |= Flags; } else { /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Set the symbol attributes */ Entry->Type = TypeDup (T); /* If this is a function, set the function descriptor and clear ** additional fields. */ if (IsFunc) { Entry->V.F.Func = GetFuncDesc (Entry->Type); Entry->V.F.Seg = 0; } /* Add the assembler name of the symbol */ SymSetAsmName (Entry); /* Add the entry to the symbol table */ AddSymEntry (Tab, Entry); } /* Return the entry */ return Entry; }