+static ExprNode* Symbol (SymEntry* S)
+/* Reference a symbol and return an expression for it */
+{
+ if (S == 0) {
+ /* Some weird error happened before */
+ return GenLiteralExpr (0);
+ } else {
+ /* Mark the symbol as referenced */
+ SymRef (S);
+ /* Remove the symbol if possible */
+ if (SymHasExpr (S)) {
+ return CloneExpr (GetSymExpr (S));
+ } else {
+ /* Create symbol node */
+ return GenSymExpr (S);
+ }
+ }
+}
+
+
+
static ExprNode* Factor (void)
{
ExprNode* L;
ExprNode* N;
- SymEntry* S;
long Val;
switch (Tok) {
case TOK_NAMESPACE:
case TOK_IDENT:
- /* Search for the symbol */
- S = ParseScopedSymName (SYM_ALLOC_NEW);
- if (S == 0) {
- /* Some weird error happened before */
- N = GenLiteralExpr (0);
- } else {
- /* Mark the symbol as referenced */
- SymRef (S);
- /* Remove the symbol if possible */
- if (SymHasExpr (S)) {
- N = CloneExpr (GetSymExpr (S));
- } else {
- /* Create symbol node */
- N = GenSymExpr (S);
- }
- }
+ N = Symbol (ParseScopedSymName (SYM_ALLOC_NEW));
break;
+ case TOK_LOCAL_IDENT:
+ N = Symbol (SymFindLocal (SVal, SYM_ALLOC_NEW));
+ NextTok ();
+ break;
+
case TOK_ULABEL:
N = ULabRef (IVal);
NextTok ();
#include <ctype.h>
/* common */
+#include "addrsize.h"
#include "assertdefs.h"
+#include "attrib.h"
#include "bitops.h"
#include "check.h"
static void PutBitBranch (const InsDesc* Ins);
static void PutREP (const InsDesc* Ins);
static void PutSEP (const InsDesc* Ins);
-static void PutJmp (const InsDesc* Ins);
+static void PutJMP (const InsDesc* Ins);
+static void PutRTS (const InsDesc* Ins);
static void PutAll (const InsDesc* Ins);
{ "INC", 0x000006c, 0x00, 4, PutAll },
{ "INX", 0x0000001, 0xe8, 0, PutAll },
{ "INY", 0x0000001, 0xc8, 0, PutAll },
- { "JMP", 0x0000808, 0x4c, 6, PutJmp },
+ { "JMP", 0x0000808, 0x4c, 6, PutJMP },
{ "JSR", 0x0000008, 0x20, 7, PutAll },
{ "LDA", 0x080A26C, 0xa0, 0, PutAll },
{ "LDX", 0x080030C, 0xa2, 1, PutAll },
{ "ROR", 0x000006F, 0x62, 1, PutAll },
{ "RTI", 0x0000001, 0x40, 0, PutAll },
{ "RTL", 0x0000001, 0x6b, 0, PutAll },
- { "RTS", 0x0000001, 0x60, 0, PutAll },
+ { "RTS", 0x0000001, 0x60, 0, PutRTS },
{ "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
{ "SEC", 0x0000001, 0x38, 0, PutAll },
{ "SED", 0x0000001, 0xf8, 0, PutAll },
-static void PutJmp (const InsDesc* Ins)
+static void PutJMP (const InsDesc* Ins)
/* Handle the jump instruction for the 6502. Problem is that these chips have
* a bug: If the address crosses a page, the upper byte gets not corrected and
* the instruction will fail. The PutJmp function will add a linker assertion
+static void PutRTS (const InsDesc* Ins attribute ((unused)))
+/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
+ * the enclosing scope is FAR.
+ */
+{
+ if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
+ Emit0 (0x6B); /* RTL */
+ } else {
+ Emit0 (0x60); /* RTS */
+ }
+}
+
+
+
static void PutAll (const InsDesc* Ins)
/* Handle all other instructions */
{
}
/* Assemble the line */
- if (Tok == TOK_IDENT) {
+ if (Tok == TOK_LOCAL_IDENT || (Tok == TOK_IDENT && !IsMacro (SVal))) {
- /* Is it a macro? */
- if (IsMacro (SVal)) {
+ /* Did we have whitespace before the ident? */
+ int HadWS = WS;
- /* Yes, start a macro expansion */
- MacExpandStart ();
- Done = 1;
-
- } else {
-
- /* No, label. Remember the identifier, then skip it */
- int HadWS = WS; /* Did we have whitespace before the ident? */
-
- /* Generate the symbol table entry, then skip the name */
- SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
- NextTok ();
-
- /* If a colon follows, this is a label definition. If there
- * is no colon, it's an assignment.
- */
- if (Tok == TOK_EQ || Tok == TOK_ASSIGN) {
- /* If it's an assign token, we have a label */
- unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE;
- /* Skip the '=' */
- NextTok ();
- /* Define the symbol with the expression following the '=' */
- SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
- /* Don't allow anything after a symbol definition */
- Done = 1;
- } else {
- /* Define a label */
- SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
- /* Skip the colon. If NoColonLabels is enabled, allow labels
- * without a colon if there is no whitespace before the
- * identifier.
- */
- if (Tok != TOK_COLON) {
- if (HadWS || !NoColonLabels) {
- Error ("`:' expected");
- }
- if (Tok == TOK_NAMESPACE) {
- /* Smart :: handling */
- NextTok ();
- }
- } else {
- /* Skip the colon */
- NextTok ();
- }
- }
- }
+ /* Generate the symbol table entry, then skip the name */
+ SymEntry* Sym;
+ if (Tok == TOK_IDENT) {
+ Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
+ } else {
+ Sym = SymFindLocal (SVal, SYM_ALLOC_NEW);
+ }
+ NextTok ();
+
+ /* If a colon follows, this is a label definition. If there
+ * is no colon, it's an assignment.
+ */
+ if (Tok == TOK_EQ || Tok == TOK_ASSIGN) {
+ /* If it's an assign token, we have a label */
+ unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE;
+ /* Skip the '=' */
+ NextTok ();
+ /* Define the symbol with the expression following the '=' */
+ SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags);
+ /* Don't allow anything after a symbol definition */
+ Done = 1;
+ } else {
+ /* Define a label */
+ SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL);
+ /* Skip the colon. If NoColonLabels is enabled, allow labels
+ * without a colon if there is no whitespace before the
+ * identifier.
+ */
+ if (Tok != TOK_COLON) {
+ if (HadWS || !NoColonLabels) {
+ Error ("`:' expected");
+ /* Try some smart error recovery */
+ if (Tok == TOK_NAMESPACE) {
+ NextTok ();
+ }
+ }
+ } else {
+ /* Skip the colon */
+ NextTok ();
+ }
+ }
}
if (!Done) {
- if (TokIsPseudo (Tok)) {
- /* A control command, IVal is index into table */
+ if (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO) {
+ /* A control command */
HandlePseudo ();
} else if (Tok == TOK_MNEMO) {
/* A mnemonic - assemble one instruction */
/* If no memory model was given, use the default */
if (MemoryModel == MMODEL_UNKNOWN) {
- MemoryModel = MMODEL_NEAR;
+ SetMemoryModel (MMODEL_NEAR);
}
/* Intialize the target translation tables */
ConsumeLParen ();
/* Accept identifiers or numeric expressions */
- if (Tok == TOK_IDENT) {
+ if (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT) {
/* Save the identifier, then skip it */
strcpy (Buf, SVal);
NextTok ();
-int TokIsPseudo (unsigned Tok)
-/* Return true if the given token is a pseudo instruction token */
-{
- return (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO);
-}
-
-
-
void HandlePseudo (void)
/* Handle a pseudo instruction */
{
/* */
/* */
/* */
-/* (C) 1998-2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
-int TokIsPseudo (unsigned Tok);
-/* Return true if the given token is a pseudo instruction token */
-
void HandlePseudo (void);
/* Handle a pseudo instruction */
goto Again;
}
- /* An identifier */
- Tok = TOK_IDENT;
+ /* A local identifier */
+ Tok = TOK_LOCAL_IDENT;
return;
}
int TokHasSVal (enum Token Tok)
/* Return true if the given token has an attached SVal */
{
- return (Tok == TOK_IDENT || Tok == TOK_STRCON);
+ return (Tok == TOK_IDENT || TOK_LOCAL_IDENT || Tok == TOK_STRCON);
}
if (!IgnoreCase) {
UpcaseSVal ();
}
-
+
/* Do a linear search (a binary search is not worth the effort) */
for (I = 0; I < Count; ++I) {
if (strcmp (SVal, Keys [I]) == 0) {
TOK_EOF, /* End of input file */
TOK_SEP, /* Separator (usually newline) */
TOK_IDENT, /* An identifier */
+ TOK_LOCAL_IDENT, /* A cheap local identifier */
TOK_MNEMO, /* A mnemonic */
TOK_INTCON, /* Integer constant */
TOK_RODATA,
TOK_SCOPE,
TOK_SEGMENT,
- TOK_SETCPU,
+ TOK_SETCPU,
TOK_SIZEOF,
TOK_SMART,
TOK_STRAT,
+void SymTransferExprRefs (SymEntry* From, SymEntry* To)
+/* Transfer all expression references from one symbol to another. */
+{
+ unsigned I;
+
+ for (I = 0; I < CollCount (&From->ExprRefs); ++I) {
+
+ /* Get the expression node */
+ ExprNode* E = CollAtUnchecked (&From->ExprRefs, I);
+
+ /* Safety */
+ CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == From);
+
+ /* Replace the symbol reference */
+ E->V.Sym = To;
+
+ /* Add the expression reference */
+ SymAddExprRef (To, E);
+ }
+
+ /* Remove all symbol references from the old symbol */
+ CollDeleteAll (&From->ExprRefs);
+}
+
+
+
void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags)
/* Define a new symbol */
{
void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an imported symbol */
{
- /* Don't accept local symbols */
- if (IsLocalNameId (S->Name)) {
- Error ("Illegal use of a local symbol");
- return;
- }
-
if (S->Flags & SF_DEFINED) {
Error ("Symbol `%s' is already defined", GetSymName (S));
S->Flags |= SF_MULTDEF;
void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an exported symbol */
{
- /* Don't accept local symbols */
- if (IsLocalNameId (S->Name)) {
- Error ("Illegal use of a local symbol");
- return;
- }
-
/* Check if it's ok to export the symbol */
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
* either imported or exported.
*/
{
- /* Don't accept local symbols */
- if (IsLocalNameId (S->Name)) {
- Error ("Illegal use of a local symbol");
- return;
- }
-
/* If the symbol is already marked as import, the address size must match.
* Apart from that, ignore the global declaration.
*/
#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 */
-int SymIsDef (const SymEntry* S)
-/* Return true if the given symbol is already defined */
-{
- return (S->Flags & SF_DEFINED) != 0;
-}
-
-
-
-int SymIsRef (const SymEntry* S)
-/* Return true if the given symbol has been referenced */
-{
- return (S->Flags & SF_REFERENCED) != 0;
-}
-
-
-
-int SymIsImport (const SymEntry* S)
-/* Return true if the given symbol is marked as import */
-{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
- /* Check the import flag */
- return (S->Flags & SF_IMPORT) != 0;
-}
-
-
-
int SymIsConst (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.
*/
{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
/* Check for constness */
return (SymHasExpr (S) && IsConstExpr (S->V.Expr, Val));
}
-int SymHasExpr (const SymEntry* S)
-/* Return true if the given symbol has an associated expression */
-{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
- /* Check the expression */
- return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED);
-}
-
-
-
-void SymMarkUser (SymEntry* S)
-/* Set a user mark on the specified symbol */
-{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
- /* Set the bit */
- S->Flags |= SF_USER;
-}
-
-
-
-void SymUnmarkUser (SymEntry* S)
-/* Remove a user mark from the specified symbol */
-{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
- /* Reset the bit */
- S->Flags &= ~SF_USER;
-}
-
-
-
-int SymHasUserMark (SymEntry* S)
-/* Return the state of the user mark for the specified symbol */
-{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
- /* Check the bit */
- return (S->Flags & SF_USER) != 0;
-}
-
-
-
struct ExprNode* GetSymExpr (SymEntry* S)
/* Get the expression for a non-const symbol */
{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
PRECONDITION (S != 0 && SymHasExpr (S));
return S->V.Expr;
}
* NULL. Do not call in other contexts!
*/
{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
return SymHasExpr (S)? S->V.Expr : 0;
}
-const char* GetSymName (const SymEntry* S)
-/* Return the name of the symbol */
-{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
- return GetString (S->Name);
-}
-
-
-
-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!
- */
-{
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
- return S->AddrSize;
-}
-
-
-
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.
unsigned GetSymIndex (const SymEntry* S)
/* Return the symbol index for the given symbol */
{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
PRECONDITION (S != 0 && (S->Flags & SF_INDEXED) != 0);
return S->Index;
}
-const FilePos* GetSymPos (const SymEntry* S)
-/* Return the position of first occurence in the source for the given symbol */
-{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
- PRECONDITION (S != 0);
- return &S->Pos;
-}
-
-
-
-
#include "cddefs.h"
#include "coll.h"
#include "filepos.h"
+#include "inline.h"
+
+/* ca65 */
+#include "spool.h"
/* Bits for the Flags value in SymEntry */
#define SF_NONE 0x0000 /* Empty flag set */
#define SF_USER 0x0001 /* User bit */
-#define SF_TRAMPOLINE 0x0002 /* Trampoline entry */
+#define SF_UNUSED 0x0002 /* Unused entry */
#define SF_EXPORT 0x0004 /* Export this symbol */
#define SF_IMPORT 0x0008 /* Import this symbol */
#define SF_GLOBAL 0x0010 /* Global symbol */
#define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#endif
+void SymTransferExprRefs (SymEntry* From, SymEntry* To);
+/* Transfer all expression references from one symbol to another. */
+
void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned char AddrSize, unsigned Flags);
/* Mark a symbol as defined */
* mark the symbol as an export. Initializers may never be zero page symbols.
*/
-int SymIsDef (const SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE int SymIsDef (const SymEntry* S)
/* Return true if the given symbol is already defined */
+{
+ return (S->Flags & SF_DEFINED) != 0;
+}
+#else
+# define SymIsDef(S) (((S)->Flags & SF_DEFINED) != 0)
+#endif
-int SymIsRef (const SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE int SymIsRef (const SymEntry* S)
/* Return true if the given symbol has been referenced */
+{
+ return (S->Flags & SF_REFERENCED) != 0;
+}
+#else
+# define SymIsRef(S) (((S)->Flags & SF_REFERENCED) != 0)
+#endif
-int SymIsImport (const SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE int SymIsImport (const SymEntry* S)
/* Return true if the given symbol is marked as import */
+{
+ /* Check the import flag */
+ return (S->Flags & SF_IMPORT) != 0;
+}
+#else
+# define SymIsImport(S) (((S)->Flags & SF_IMPORT) != 0)
+#endif
int SymIsConst (SymEntry* Sym, 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.
*/
-int SymHasExpr (const SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE int SymHasExpr (const SymEntry* S)
/* Return true if the given symbol has an associated expression */
+{
+ /* Check the expression */
+ return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED);
+}
+#else
+# define SymHasExpr(S) (((S)->Flags & (SF_DEFINED|SF_IMPORT)) != SF_DEFINED)
+#endif
-void SymMarkUser (SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE void SymMarkUser (SymEntry* S)
/* Set a user mark on the specified symbol */
+{
+ /* Set the bit */
+ S->Flags |= SF_USER;
+}
+#else
+# define SymMarkUser(S) ((S)->Flags |= SF_USER)
+#endif
-void SymUnmarkUser (SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE void SymUnmarkUser (SymEntry* S)
/* Remove a user mark from the specified symbol */
+{
+ /* Reset the bit */
+ S->Flags &= ~SF_USER;
+}
+#else
+# define SymUnmarkUser(S) ((S)->Flags &= ~SF_USER)
+#endif
-int SymHasUserMark (SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE int SymHasUserMark (SymEntry* S)
/* Return the state of the user mark for the specified symbol */
+{
+ /* Check the bit */
+ return (S->Flags & SF_USER) != 0;
+}
+#else
+# define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0)
+#endif
struct ExprNode* GetSymExpr (SymEntry* Sym);
/* Get the expression for a non-const symbol */
* NULL. Do not call in other contexts!
*/
-const char* GetSymName (const SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE const char* GetSymName (const SymEntry* S)
/* Return the name of the symbol */
+{
+ return GetString (S->Name);
+}
+#else
+# define GetSymName(S) GetString ((S)->Name)
+#endif
-unsigned char GetSymAddrSize (const SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE 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!
*/
+{
+ return S->AddrSize;
+}
+#else
+# define GetSymAddrSize(S) ((S)->AddrSize)
+#endif
long GetSymVal (SymEntry* Sym);
/* Return the value of a symbol assuming it's constant. FAIL will be called
unsigned GetSymIndex (const SymEntry* Sym);
/* Return the symbol index for the given symbol */
-const FilePos* GetSymPos (const SymEntry* Sym);
+#if defined(HAVE_INLINE)
+INLINE const FilePos* GetSymPos (const SymEntry* S)
/* Return the position of first occurence in the source for the given symbol */
-
+{
+ return &S->Pos;
+}
+#else
+# define GetSymPos(S) (&(S)->Pos)
+#endif
/* Combined symbol entry flags used within this module */
#define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
#define SF_UNDEFVAL (SF_REFERENCED)
-#define SF_EXPMASK (SF_TRAMPOLINE | SF_EXPORT)
-#define SF_EXPVAL (SF_EXPORT)
-#define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT)
+#define SF_DBGINFOMASK (SF_UNUSED | SF_DEFINED | SF_EXPORT | SF_IMPORT)
#define SF_DBGINFOVAL (SF_DEFINED)
/* Symbol tables */
SymTable* RootScope = 0; /* Root symbol table */
/* Symbol table variables */
-static unsigned ImportCount = 0;/* Counter for import symbols */
-static unsigned ExportCount = 0;/* Counter for export symbols */
+static unsigned ImportCount = 0; /* Counter for import symbols */
+static unsigned ExportCount = 0; /* Counter for export symbols */
-SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
-/* Find a new symbol table entry in the given table. If AllocNew is given and
- * the entry is not found, create a new one. Return the entry found, or the
- * new entry created, or - in case AllocNew is zero - return 0.
+SymEntry* SymFindLocal (const char* Name, int AllocNew)
+/* Find a cheap local symbol. If AllocNew is given and the entry is not
+ * found, create a new one. Return the entry found, or the new entry created,
+ * or - in case AllocNew is zero - return 0.
*/
{
SymEntry* S;
int Cmp;
- if (IsLocalName (Name)) {
+ /* Local symbol, get the table */
+ if (!SymLast) {
+ /* No last global, so there's no local table */
+ Error ("No preceeding global symbol");
+ if (AllocNew) {
+ return NewSymEntry (Name);
+ } else {
+ return 0;
+ }
+ }
- /* Local symbol, get the table */
- if (!SymLast) {
- /* No last global, so there's no local table */
- Error ("No preceeding global symbol");
- if (AllocNew) {
- return NewSymEntry (Name);
- } else {
- return 0;
- }
- }
+ /* Search for the symbol if we have a table */
+ Cmp = SymSearchTree (SymLast->Locals, Name, &S);
- /* Search for the symbol if we have a table */
- Cmp = SymSearchTree (SymLast->Locals, Name, &S);
+ /* If we found an entry, return it */
+ if (Cmp == 0) {
+ return S;
+ }
- /* If we found an entry, return it */
- if (Cmp == 0) {
- return S;
- }
+ if (AllocNew) {
- if (AllocNew) {
+ /* Otherwise create a new entry, insert and return it */
+ SymEntry* N = NewSymEntry (Name);
+ if (S == 0) {
+ SymLast->Locals = N;
+ } else if (Cmp < 0) {
+ S->Left = N;
+ } else {
+ S->Right = N;
+ }
+ return N;
+ }
- /* Otherwise create a new entry, insert and return it */
- SymEntry* N = NewSymEntry (Name);
- if (S == 0) {
- SymLast->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;
+}
- } else {
- /* Global symbol: Get the hash value for the name */
- unsigned Hash = HashStr (Name) % Scope->TableSlots;
- /* Search for the entry */
- Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
+SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
+/* Find a new symbol table entry in the given table. If AllocNew is given and
+ * the entry is not found, create a new one. Return the entry found, or the
+ * new entry created, or - in case AllocNew is zero - return 0.
+ */
+{
+ SymEntry* S;
- /* If we found an entry, return it */
- if (Cmp == 0) {
- /* Check for a trampoline entry, in this case return the real
- * symbol.
- */
- while (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
- return S;
- }
+ /* Global symbol: Get the hash value for the name */
+ unsigned Hash = HashStr (Name) % Scope->TableSlots;
- if (AllocNew) {
+ /* Search for the entry */
+ int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
- /* Otherwise create a new entry, insert and return it */
- SymEntry* N = NewSymEntry (Name);
- if (S == 0) {
- Scope->Table[Hash] = N;
- } else if (Cmp < 0) {
- S->Left = N;
- } else {
- S->Right = N;
- }
- N->SymTab = Scope;
- ++Scope->TableEntries;
- return N;
+ /* If we found an entry, return it */
+ if (Cmp == 0) {
+ return S;
+ }
+
+ if (AllocNew) {
+
+ /* Otherwise create a new entry, insert and return it */
+ SymEntry* N = NewSymEntry (Name);
+ if (S == 0) {
+ Scope->Table[Hash] = N;
+ } else if (Cmp < 0) {
+ S->Left = N;
+ } else {
+ S->Right = N;
+ }
+ N->SymTab = Scope;
+ ++Scope->TableEntries;
+ return N;
- }
}
/* We did not find the entry and AllocNew is false. */
int SymIsZP (SymEntry* S)
/* Return true if the symbol is explicitly marked as zeropage symbol */
{
- /* Resolve trampoline entries */
- if (S->Flags & SF_TRAMPOLINE) {
- S = S->V.Sym;
- }
-
/* If the symbol is not a global symbol, was not defined before, check the
* enclosing scope for a symbol with the same name, and return the ZP
* attribute of this symbol if we find one.
}
}
}
+
if (Sym) {
- /* We found the symbol in a higher level. Make S a trampoline
- * symbol. Beware: We have to transfer the symbol attributes to
- * the real symbol and check for any conflicts.
- */
- S->Flags |= SF_TRAMPOLINE;
- S->V.Sym = Sym;
- /* Transfer the flags. Note: S may not be imported, since in that
- * case it wouldn't be undefined.
- */
- if (S->Flags & SF_EXPORT) {
+ /* We found the symbol in a higher level. Transfer the flags and
+ * address size from the local symbol to that in the higher level
+ * and check for problems.
+ */
+ if (S->Flags & SF_EXPORT) {
if (Sym->Flags & SF_IMPORT) {
- /* The symbol is already marked as imported external symbol */
- PError (&S->Pos, "Symbol `%s' is already an import", GetString (S->Name));
+ /* The symbol is already marked as import */
+ PError (&S->Pos, "Symbol `%s' is already an import",
+ GetString (Sym->Name));
}
- Sym->Flags |= (S->Flags & SF_EXPORT);
- Sym->ExportSize = S->ExportSize;
- }
+ if (Sym->Flags & SF_EXPORT) {
+ /* The symbol is already marked as an export. */
+ if (Sym->AddrSize > S->ExportSize) {
+ /* We're exporting a symbol smaller than it actually is */
+ PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s",
+ GetSymName (Sym), AddrSizeToStr (Sym->AddrSize),
+ AddrSizeToStr (S->ExportSize));
+ }
+ } else {
+ /* Mark the symbol as an export */
+ Sym->Flags |= SF_EXPORT;
+ Sym->ExportSize = S->ExportSize;
+ if (Sym->ExportSize == ADDR_SIZE_DEFAULT) {
+ /* Use the actual size of the symbol */
+ Sym->ExportSize = Sym->AddrSize;
+ }
+ if (Sym->AddrSize > Sym->ExportSize) {
+ /* We're exporting a symbol smaller than it actually is */
+ PWarning (&S->Pos, 1, "Symbol `%s' is %s but exported %s",
+ GetSymName (Sym), AddrSizeToStr (Sym->AddrSize),
+ AddrSizeToStr (Sym->ExportSize));
+ }
+ }
+ }
+ Sym->Flags |= (S->Flags & SF_REFERENCED);
+
+ /* Transfer all expression references */
+ SymTransferExprRefs (S, Sym);
- /* Transfer the referenced flag */
- Sym->Flags |= (S->Flags & SF_REFERENCED);
+ /* Mark the symbol as unused removing all other flags */
+ S->Flags = SF_UNUSED;
} else {
/* The symbol is definitely undefined */
GetString (S->Name));
} else {
if (AutoImport) {
- /* Mark as import, will be indexed later */
- S->Flags |= SF_IMPORT;
+ /* Mark as import, will be indexed later */
+ S->Flags |= SF_IMPORT;
/* Use the address size for code */
S->AddrSize = CodeAddrSize;
} else {
- /* Error */
+ /* Error */
PError (&S->Pos, "Symbol `%s' is undefined", GetString (S->Name));
}
}
if (S->Flags & SF_GLOBAL) {
S->Flags &= ~SF_GLOBAL;
if (S->Flags & SF_DEFINED) {
- S->Flags |= SF_EXPORT;
+ S->Flags |= SF_EXPORT;
} else {
- S->Flags |= SF_IMPORT;
+ S->Flags |= SF_IMPORT;
}
}
}
/* Second pass: Walk again through the symbols. Ignore undefined's, since
- * we handled them in the last pass, and ignore trampoline symbols, since
+ * we handled them in the last pass, and ignore unused symbols, since
* we handled them in the last pass, too.
*/
S = SymList;
while (S) {
- if ((S->Flags & SF_TRAMPOLINE) == 0 &&
+ if ((S->Flags & SF_UNUSED) == 0 &&
(S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
- /* Symbol was defined but never referenced */
- PWarning (&S->Pos, 2,
+ /* Symbol was defined but never referenced */
+ PWarning (&S->Pos, 2,
"Symbol `%s' is defined but never used",
GetString (S->Name));
}
if (S->Flags & SF_IMPORT) {
- if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
- /* Imported symbol is not referenced */
- PWarning (&S->Pos, 2,
+ if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
+ /* Imported symbol is not referenced */
+ PWarning (&S->Pos, 2,
"Symbol `%s' is imported but never used",
GetString (S->Name));
- } else {
- /* Give the import an index, count imports */
- S->Index = ImportCount++;
- S->Flags |= SF_INDEXED;
- }
+ } else {
+ /* Give the import an index, count imports */
+ S->Index = ImportCount++;
+ S->Flags |= SF_INDEXED;
+ }
}
if (S->Flags & SF_EXPORT) {
- /* Give the export an index, count exports */
- S->Index = ExportCount++;
- S->Flags |= SF_INDEXED;
+ /* Give the export an index, count exports */
+ S->Index = ExportCount++;
+ S->Flags |= SF_INDEXED;
}
}
SymEntry* S = SymList;
while (S) {
- /* Ignore trampoline symbols */
- if ((S->Flags & SF_TRAMPOLINE) != 0) {
+ /* Ignore unused symbols */
+ if ((S->Flags & SF_UNUSED) != 0) {
fprintf (F,
"%-24s %s %s %s %s %s\n",
GetString (S->Name),
*/
S = SymList;
while (S) {
- if ((S->Flags & (SF_TRAMPOLINE | SF_IMPORT)) == SF_IMPORT &&
+ if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT &&
(S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
ObjWrite8 (S->AddrSize);
/* Walk throught list and write all exports to the file */
S = SymList;
while (S) {
- if ((S->Flags & SF_EXPMASK) == SF_EXPVAL) {
+ if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
long ConstVal;
* scope.
*/
+SymEntry* SymFindLocal (const char* Name, int AllocNew);
+/* Find a cheap local symbol. If AllocNew is given and the entry is not
+ * found, create a new one. Return the entry found, or the new entry created,
+ * or - in case AllocNew is zero - return 0.
+ */
+
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew);
/* Find a new symbol table entry in the given table. If AllocNew is given and
* the entry is not found, create a new one. Return the entry found, or the