/* */
/* symentry.c */
/* */
-/* Symbol table entry forward for the ca65 macroassembler */
+/* Symbol table entry for the ca65 macroassembler */
/* */
/* */
/* */
-/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstraße 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* common */
#include "addrsize.h"
+#include "symdefs.h"
#include "xmalloc.h"
/* ca65 */
-SymEntry* NewSymEntry (const char* Name, unsigned Flags)
+SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
/* Allocate a symbol table entry, initialize and return it */
{
+ unsigned I;
+
/* Allocate memory */
SymEntry* S = xmalloc (sizeof (SymEntry));
/* Initialize the entry */
- S->Left = 0;
- S->Right = 0;
- S->Locals = 0;
- S->SymTab = 0;
- S->Pos = CurPos;
- S->Flags = Flags;
+ S->Left = 0;
+ S->Right = 0;
+ S->Locals = 0;
+ S->Sym.Tab = 0;
+ S->LineInfos = EmptyCollection;
+ GetFullLineInfo (&S->LineInfos, 1);
+ for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
+ S->GuessedUse[I] = 0;
+ }
+ S->Flags = Flags;
+ S->DebugSymId = ~0U;
+ S->ImportId = ~0U;
S->Expr = 0;
S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
S->ExportSize = ADDR_SIZE_DEFAULT;
S->AddrSize = ADDR_SIZE_DEFAULT;
memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
- S->Name = GetStringId (Name);
+ S->Name = GetStrBufId (Name);
/* Insert it into the list of all entries */
S->List = SymList;
-int SymSearchTree (SymEntry* T, const char* Name, SymEntry** E)
+int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E)
/* Search in the given tree for a name. If we find the symbol, the function
* will return 0 and put the entry pointer into E. If we did not find the
* symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
while (1) {
/* Get the symbol name */
- const char* SymName = GetString (T->Name);
+ const StrBuf* SymName = GetStrBuf (T->Name);
/* Choose next entry */
- int Cmp = strcmp (Name, SymName);
+ int Cmp = SB_Compare (Name, SymName);
if (Cmp < 0 && T->Left) {
T = T->Left;
} else if (Cmp > 0&& T->Right) {
/* Safety */
CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S);
- /* We cannot touch the root node, since there are pointers to it.
+ /* We cannot touch the root node, since there are pointers to it.
* Replace it by a literal node.
*/
E->Op = EXPR_LITERAL;
- E->V.Val = Val;
+ E->V.IVal = Val;
}
/* Remove all symbol references from the symbol */
{
if (S->Flags & SF_IMPORT) {
/* Defined symbol is marked as imported external symbol */
- Error ("Symbol `%s' is already an import", GetSymName (S));
+ Error ("Symbol `%m%p' is already an import", GetSymName (S));
return;
}
if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
/* Variable symbols cannot be exports or globals */
- Error ("Var symbol `%s' cannot be an export or global symbol", GetSymName (S));
+ Error ("Var symbol `%m%p' cannot be an export or global symbol", GetSymName (S));
return;
}
if (S->Flags & SF_DEFINED) {
/* Multiple definition. In case of a variable, this is legal. */
if ((S->Flags & SF_VAR) == 0) {
- Error ("Symbol `%s' is already defined", GetSymName (S));
+ Error ("Symbol `%m%p' is already defined", GetSymName (S));
S->Flags |= SF_MULTDEF;
return;
} else {
/* Redefinition must also be a variable symbol */
if ((Flags & SF_VAR) == 0) {
- Error ("Symbol `%s' is already different kind", GetSymName (S));
+ Error ("Symbol `%m%p' is already different kind", GetSymName (S));
return;
}
/* Delete the current symbol expression, since it will get
/* Set the symbol value */
S->Expr = Expr;
- /* In case of a variable symbol, walk over all expressions containing
+ /* In case of a variable symbol, walk over all expressions containing
* this symbol and replace the (sub-)expression by the literal value of
* the tree. Be sure to replace the expression node in place, since there
* may be pointers to it.
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
- PWarning (GetSymPos (S), 1, "Symbol `%s' is %s but exported %s",
- GetSymName (S), AddrSizeToStr (S->AddrSize),
- AddrSizeToStr (S->ExportSize));
+ LIWarning (&S->LineInfos, 1, "Symbol `%m%p' is %s but exported %s",
+ GetSymName (S), AddrSizeToStr (S->AddrSize),
+ AddrSizeToStr (S->ExportSize));
}
}
/* Mark the given symbol as an imported symbol */
{
if (S->Flags & SF_DEFINED) {
- Error ("Symbol `%s' is already defined", GetSymName (S));
+ Error ("Symbol `%m%p' is already defined", GetSymName (S));
S->Flags |= SF_MULTDEF;
return;
}
if (S->Flags & SF_EXPORT) {
/* The symbol is already marked as exported symbol */
- Error ("Cannot import exported symbol `%s'", GetSymName (S));
+ Error ("Cannot import exported symbol `%m%p'", GetSymName (S));
return;
}
*/
if (S->Flags & SF_IMPORT) {
if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
- Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
+ Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
}
if (AddrSize != S->AddrSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
if (S->Flags & SF_GLOBAL) {
S->Flags &= ~SF_GLOBAL;
if (AddrSize != S->AddrSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
/* Check if it's ok to export the symbol */
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
- Error ("Symbol `%s' is already an import", GetSymName (S));
+ Error ("Symbol `%m%p' is already an import", GetSymName (S));
return;
}
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported */
- Error ("Var symbol `%s' cannot be exported", GetSymName (S));
+ Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
return;
}
*/
if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
S->Flags &= ~SF_GLOBAL;
}
*/
if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
if (S->ExportSize != AddrSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
S->ExportSize = AddrSize;
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
- Warning (1, "Symbol `%s' is %s but exported %s",
+ Warning (1, "Symbol `%m%p' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
{
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */
- Error ("Var symbol `%s' cannot be made global", GetSymName (S));
+ Error ("Var symbol `%m%p' cannot be made global", GetSymName (S));
return;
}
AddrSize = GetCurrentSegAddrSize ();
}
if (AddrSize != S->AddrSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
return;
}
if ((S->Flags & SF_DEFINED) == 0) {
/* Symbol is undefined */
if (AddrSize != S->ExportSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
} else if (AddrSize != ADDR_SIZE_DEFAULT) {
/* Symbol is defined and address size given */
if (AddrSize != S->ExportSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
return;
*/
if (S->Flags & SF_GLOBAL) {
if (AddrSize != S->ExportSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
return;
}
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
/* We're exporting a symbol smaller than it actually is */
- Warning (1, "Symbol `%s' is %s but exported %s",
+ Warning (1, "Symbol `%m%p' is %s but exported %s",
GetSymName (S), AddrSizeToStr (S->AddrSize),
AddrSizeToStr (S->ExportSize));
}
/* Check for errors */
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
- Error ("Symbol `%s' is already an import", GetSymName (S));
+ Error ("Symbol `%m%p' is already an import", GetSymName (S));
return;
}
if (S->Flags & SF_VAR) {
/* Variable symbols cannot be exported or imported */
- Error ("Var symbol `%s' cannot be exported", GetSymName (S));
+ Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
return;
}
*/
if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
if (S->ExportSize != AddrSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
S->Flags &= ~SF_GLOBAL;
}
/* Use the real size of the symbol */
S->ExportSize = S->AddrSize;
} else if (S->AddrSize != S->ExportSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
}
}
*/
if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
if (S->ConDesPrio[Type] != Prio) {
- Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
+ Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
}
}
S->ConDesPrio[Type] = Prio;
+void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize)
+/* Mark the address size of the given symbol as guessed. The address size
+ * passed as argument is the one NOT used, because the actual address size
+ * wasn't known. Example: Zero page addressing was not used because symbol
+ * is undefined, and absolute addressing was available.
+ */
+{
+ /* We must have a valid address size passed */
+ PRECONDITION (AddrSize != ADDR_SIZE_DEFAULT);
+
+ /* We do not support all address sizes currently */
+ if (AddrSize > sizeof (Sym->GuessedUse) / sizeof (Sym->GuessedUse[0])) {
+ return;
+ }
+
+ /* We can only remember one such occurance */
+ if (Sym->GuessedUse[AddrSize-1]) {
+ return;
+ }
+
+ /* Ok, remember the file position */
+ Sym->GuessedUse[AddrSize-1] = xdup (&CurTok.Pos, sizeof (CurTok.Pos));
+}
+
+
+
void SymExportFromGlobal (SymEntry* S)
/* Called at the end of assembly. Converts a global symbol that is defined
* into an export.
-int SymIsConst (SymEntry* S, long* Val)
+int SymIsConst (const SymEntry* S, long* Val)
/* Return true if the given symbol has a constant value. If Val is not NULL
* and the symbol has a constant value, store it's value there.
*/
* NULL if the symbol is a cheap local, or defined on global level.
*/
{
- return (S->SymTab && S->SymTab->Parent)? S->SymTab->Parent : 0;
+ if ((S->Flags & SF_LOCAL) != 0) {
+ /* This is a cheap local symbol */
+ return 0;
+ } else if (S->Sym.Tab == 0) {
+ /* Symbol not in a table. This may happen if there have been errors
+ * before. Return NULL in this case to avoid further errors.
+ */
+ return 0;
+ } else {
+ /* This is a global symbol */
+ return S->Sym.Tab->Parent;
+ }
}
-unsigned GetSymIndex (const SymEntry* S)
-/* Return the symbol index for the given symbol */
+unsigned GetSymImportId (const SymEntry* S)
+/* Return the import id for the given symbol */
+{
+ PRECONDITION (S != 0 && (S->Flags & SF_IMPORT) && S->ImportId != ~0U);
+ return S->ImportId;
+}
+
+
+
+unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
+/* Return a set of flags used when writing symbol information into a file.
+ * If the SYM_CONST bit is set, ConstVal will contain the constant value
+ * of the symbol. The result does not include the condes count.
+ * See common/symdefs.h for more information.
+ */
+{
+ /* Setup info flags */
+ unsigned Flags = 0;
+ Flags |= SymIsConst (S, ConstVal)? SYM_CONST : SYM_EXPR;
+ Flags |= (S->Flags & SF_LABEL)? SYM_LABEL : SYM_EQUATE;
+ Flags |= (S->Flags & SF_LOCAL)? SYM_CHEAP_LOCAL : SYM_STD;
+
+ /* Return the result */
+ return Flags;
+}
+
+
+
+const FilePos* GetSymPos (const SymEntry* S)
+/* Return the position of first occurence in the source for the given symbol */
{
- PRECONDITION (S != 0 && (S->Flags & SF_INDEXED) != 0);
- return S->Index;
+ /* The actual source entry is in slot zero */
+ return &((const LineInfo*) CollConstAt (&S->LineInfos, 0))->Pos;
}