#include "expr.h"
#include "global.h"
#include "scanner.h"
+#include "segment.h"
#include "spool.h"
#include "symentry.h"
#include "symtab.h"
return ADDR_SIZE_ABS;
}
- /* Return the address size of the enclosing scope */
- return S->SymTab->AddrSize;
+ /* Return the address size of the segment */
+ return GetCurrentSegAddrSize ();
}
+int SymSearchTree (SymEntry* T, const char* 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,
+ * E will be set to the last entry, and the result of the function is <0 if
+ * the entry should be inserted on the left side, and >0 if it should get
+ * inserted on the right side.
+ */
+{
+ /* Is there a tree? */
+ if (T == 0) {
+ *E = 0;
+ return 1;
+ }
+
+ /* We have a table, search it */
+ while (1) {
+
+ /* Get the symbol name */
+ const char* SymName = GetString (T->Name);
+
+ /* Choose next entry */
+ int Cmp = strcmp (Name, SymName);
+ if (Cmp < 0 && T->Left) {
+ T = T->Left;
+ } else if (Cmp > 0&& T->Right) {
+ T = T->Right;
+ } else {
+ /* Found or end of search, return the result */
+ *E = T;
+ return Cmp;
+ }
+ }
+}
+
+
+
void SymRef (SymEntry* S)
/* Mark the given symbol as referenced */
{
-void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
+void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags)
/* Define a new symbol */
{
if (S->Flags & SF_IMPORT) {
/* Map a default address size to a real value */
if (AddrSize == ADDR_SIZE_DEFAULT) {
- AddrSize = SymAddrSize (S);
+ long Val;
+ if (IsConstExpr (Expr, &Val) && IsByteRange (Val)) {
+ AddrSize = ADDR_SIZE_ZP;
+ } else {
+ AddrSize = SymAddrSize (S);
+ }
}
/* Set the symbol value */
- S->V.Expr = Expr;
+ S->V.Expr = Expr;
/* If the symbol is marked as global, export it */
if (S->Flags & SF_GLOBAL) {
/* Use the real size of the symbol */
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
- Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S));
+ PWarning (GetSymPos (S), 1, "Symbol `%s' is %s but exported as %s",
+ GetSymName (S), AddrSizeToStr (S->AddrSize),
+ AddrSizeToStr (S->ExportSize));
}
}
-void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
+void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an imported symbol */
{
/* Don't accept local symbols */
/* If the symbol is marked as import or global, check the symbol flags,
* then do silently remove the global flag
*/
- if (S->Flags & (SF_IMPORT | SF_GLOBAL)) {
- if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) ||
- AddrSize != S->AddrSize) {
+ if (S->Flags & SF_IMPORT) {
+ if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
}
+ if (AddrSize != S->AddrSize) {
+ Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ }
+ }
+ if (S->Flags & SF_GLOBAL) {
+ if (S->AddrSize != ADDR_SIZE_DEFAULT && S->AddrSize != AddrSize) {
+ Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ }
S->Flags &= ~SF_GLOBAL;
}
-void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
+void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an exported symbol */
{
/* Don't accept local symbols */
return;
}
- /* If the symbol was already marked as an export or global, check if
- * this was done specifiying the same address size. In case of a global
- * declaration, silently remove the global flag.
+ /* If the symbol was marked as global before, make it an export */
+ if (S->Flags & SF_GLOBAL) {
+ S->ExportSize = S->AddrSize;
+ S->Flags &= ~SF_GLOBAL;
+ }
+
+ /* If the symbol was already marked as an export, check if this was done
+ * specifiying the same address size. If the old spec had no explicit
+ * address size, use the new one.
*/
- if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
- if (S->ExportSize != AddrSize) {
+ if (S->Flags & SF_EXPORT) {
+ if (S->ExportSize == ADDR_SIZE_DEFAULT) {
+ S->ExportSize = AddrSize;
+ } else if (AddrSize == ADDR_SIZE_DEFAULT) {
+ AddrSize = S->ExportSize;
+ }
+ if (S->ExportSize != ADDR_SIZE_DEFAULT && S->ExportSize != AddrSize) {
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
}
- S->Flags &= ~SF_GLOBAL;
}
S->ExportSize = AddrSize;
*/
if (S->Flags & SF_DEFINED) {
if (S->ExportSize == ADDR_SIZE_DEFAULT) {
- /* Use the real size of the symbol */
+ /* No export size given, use the real size of the symbol */
S->ExportSize = S->AddrSize;
} else if (S->AddrSize > S->ExportSize) {
- Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S));
+ Warning (1, "Symbol `%s' is %s but exported as %s",
+ GetSymName (S), AddrSizeToStr (S->AddrSize),
+ AddrSizeToStr (S->ExportSize));
}
}
-void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
+void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as a global symbol, that is, as a symbol that is
* either imported or exported.
*/
return;
}
- /* Map a default address size to a real value */
- if (AddrSize == ADDR_SIZE_DEFAULT) {
- AddrSize = SymAddrSize (S);
- }
-
/* If the symbol is already marked as import or export, check the
* size of the definition, then bail out.
*/
if (S->Flags & SF_IMPORT) {
- if (AddrSize != S->AddrSize) {
+ if (AddrSize != ADDR_SIZE_DEFAULT && AddrSize != S->AddrSize) {
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
}
return;
}
if (S->Flags & SF_EXPORT) {
+ /* If the old symbol had no explicit address size spec, use the
+ * new one.
+ */
+ if (S->ExportSize == ADDR_SIZE_DEFAULT) {
+ S->ExportSize = AddrSize;
+ }
if (AddrSize != S->ExportSize) {
Error ("Address size mismatch for symbol `%s'", GetSymName (S));
}
*/
if (S->Flags & SF_DEFINED) {
/* The symbol is defined, export it */
- if (S->ExportSize != AddrSize) {
- Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ S->ExportSize = AddrSize;
+ if (S->ExportSize == ADDR_SIZE_DEFAULT) {
+ /* No export size given, use the real size of the symbol */
+ S->ExportSize = S->AddrSize;
+ } else if (S->AddrSize > S->ExportSize) {
+ Warning (1, "Symbol `%s' is %s but exported as %s",
+ GetSymName (S), AddrSizeToStr (S->AddrSize),
+ AddrSizeToStr (S->ExportSize));
}
S->Flags |= (SF_EXPORT | Flags);
S->ExportSize = AddrSize;
+void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio)
+/* Mark the given symbol as a module constructor/destructor. This will also
+ * mark the symbol as an export. Initializers may never be zero page symbols.
+ */
+{
+ /* Check the parameters */
+#if (CD_TYPE_MIN != 0)
+ CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
+#else
+ CHECK (Type <= CD_TYPE_MAX);
+#endif
+ CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
+
+ /* Don't accept local symbols */
+ if (IsLocalNameId (S->Name)) {
+ Error ("Illegal use of a local symbol");
+ return;
+ }
+
+ /* 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));
+ return;
+ }
+
+ /* If the symbol was already marked as an export or global, check if
+ * this was done specifiying the same address size. In case of a global
+ * declaration, silently remove the global flag.
+ */
+ if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
+ if (S->ExportSize != AddrSize) {
+ Error ("Address size mismatch for symbol `%s'", GetSymName (S));
+ }
+ S->Flags &= ~SF_GLOBAL;
+ }
+ S->ExportSize = AddrSize;
+
+ /* If the symbol is already defined, check symbol size against the
+ * exported size.
+ */
+ if (S->Flags & SF_DEFINED) {
+ if (S->ExportSize == ADDR_SIZE_DEFAULT) {
+ /* 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));
+ }
+ }
+
+ /* If the symbol was already declared as a condes, check if the new
+ * priority value is the same as the old one.
+ */
+ if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
+ if (S->ConDesPrio[Type] != Prio) {
+ Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
+ }
+ }
+ S->ConDesPrio[Type] = Prio;
+
+ /* Set the symbol data */
+ S->Flags |= (SF_EXPORT | SF_REFERENCED);
+}
+
+
+
int SymIsDef (const SymEntry* S)
/* Return true if the given symbol is already defined */
{
-unsigned GetSymAddrSize (const SymEntry* S)
+unsigned char GetSymAddrSize (const SymEntry* S)
/* Return the address size of the symbol. Beware: This function will just
* return the AddrSize member, it will not look at the expression!
*/
+long GetSymVal (SymEntry* S)
+/* Return the value of a symbol assuming it's constant. FAIL will be called
+ * in case the symbol is undefined or not constant.
+ */
+{
+ long Val;
+ CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val));
+ return Val;
+}
+
+
+
unsigned GetSymIndex (const SymEntry* S)
/* Return the symbol index for the given symbol */
{