/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* Warning levels */
-extern unsigned WarnLevel;
+extern unsigned WarnLevel;
/* Statistics */
extern unsigned ErrorCount;
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print an error message */
-
+
void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print an error message giving an explicit file and position. */
+/*****************************************************************************/
+/* Forwards */
+/*****************************************************************************/
+
+
+
+static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
+/* Study an expression tree and place the contents into D */
+
+
+
/*****************************************************************************/
/* Helpers */
/*****************************************************************************/
} else {
/* Mark the symbol as referenced */
SymRef (S);
- /* Create symbol node */
- N = GenSymExpr (S);
+ /* Remove the symbol if possible */
+ if (SymHasExpr (S)) {
+ N = CloneExpr (GetSymExpr (S));
+ } else {
+ /* Create symbol node */
+ N = GenSymExpr (S);
+ }
}
break;
/* Generate an expression tree */
unsigned char Op;
- switch (T) {
+ switch (T) {
case TOK_MUL: Op = EXPR_MUL; break;
case TOK_DIV: Op = EXPR_DIV; break;
case TOK_MOD: Op = EXPR_MOD; break;
/* Handle additive operations */
while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
- /* Create the new node */
- ExprNode* Left = Root;
- switch (Tok) {
- case TOK_PLUS: Root = NewExprNode (EXPR_PLUS); break;
- case TOK_MINUS: Root = NewExprNode (EXPR_MINUS); break;
- case TOK_OR: Root = NewExprNode (EXPR_OR); break;
- default: Internal ("Invalid token");
- }
- Root->Left = Left;
+ long LVal, RVal, Val;
+ ExprNode* Left;
+ ExprNode* Right;
- /* Skip the operator token */
- NextTok ();
+ /* Remember the token and skip it */
+ enum Token T = Tok;
+ NextTok ();
- /* Parse the right hand side */
- Root->Right = Term ();
+ /* Move root to left side and read the right side */
+ Left = Root;
+ Right = Term ();
+
+ /* If both expressions are constant, we can evaluate the term */
+ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
+ switch (T) {
+ case TOK_PLUS: Val = LVal + RVal; break;
+ case TOK_MINUS: Val = LVal - RVal; break;
+ case TOK_OR: Val = LVal | RVal; break;
+ default: Internal ("Invalid token");
+ }
+
+ /* Generate a literal expression and delete the old left and
+ * right sides.
+ */
+ FreeExpr (Left);
+ FreeExpr (Right);
+ Root = GenLiteralExpr (Val);
+
+ } else {
+
+ /* Generate an expression tree */
+ unsigned char Op;
+ switch (T) {
+ case TOK_PLUS: Op = EXPR_PLUS; break;
+ case TOK_MINUS: Op = EXPR_MINUS; break;
+ case TOK_OR: Op = EXPR_OR; break;
+ default: Internal ("Invalid token");
+ }
+ Root = NewExprNode (Op);
+ Root->Left = Left;
+ Root->Right = Right;
+
+ }
}
/* Return the expression tree we've created */
while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
- /* Create the new node */
- ExprNode* Left = Root;
- switch (Tok) {
- case TOK_EQ: Root = NewExprNode (EXPR_EQ); break;
- case TOK_NE: Root = NewExprNode (EXPR_NE); break;
- case TOK_LT: Root = NewExprNode (EXPR_LT); break;
- case TOK_GT: Root = NewExprNode (EXPR_GT); break;
- case TOK_LE: Root = NewExprNode (EXPR_LE); break;
- case TOK_GE: Root = NewExprNode (EXPR_GE); break;
- default: Internal ("Invalid token");
- }
- Root->Left = Left;
+ long LVal, RVal, Val;
+ ExprNode* Left;
+ ExprNode* Right;
- /* Skip the operator token */
- NextTok ();
+ /* Remember the token and skip it */
+ enum Token T = Tok;
+ NextTok ();
+
+ /* Move root to left side and read the right side */
+ Left = Root;
+ Right = SimpleExpr ();
+
+ /* If both expressions are constant, we can evaluate the term */
+ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
- /* Parse the right hand side */
- Root->Right = SimpleExpr ();
+ switch (T) {
+ case TOK_EQ: Val = (LVal == RVal); break;
+ case TOK_NE: Val = (LVal != RVal); break;
+ case TOK_LT: Val = (LVal < RVal); break;
+ case TOK_GT: Val = (LVal > RVal); break;
+ case TOK_LE: Val = (LVal <= RVal); break;
+ case TOK_GE: Val = (LVal >= RVal); break;
+ default: Internal ("Invalid token");
+ }
+
+ /* Generate a literal expression and delete the old left and
+ * right sides.
+ */
+ FreeExpr (Left);
+ FreeExpr (Right);
+ Root = GenLiteralExpr (Val);
+
+ } else {
+ /* Generate an expression tree */
+ unsigned char Op;
+ switch (T) {
+ case TOK_EQ: Op = EXPR_EQ; break;
+ case TOK_NE: Op = EXPR_NE; break;
+ case TOK_LT: Op = EXPR_LT; break;
+ case TOK_GT: Op = EXPR_GT; break;
+ case TOK_LE: Op = EXPR_LE; break;
+ case TOK_GE: Op = EXPR_GE; break;
+ default: Internal ("Invalid token");
+ }
+ Root = NewExprNode (Op);
+ Root->Left = Left;
+ Root->Right = Right;
+
+ }
}
/* Return the expression tree we've created */
/* Handle booleans */
while (Tok == TOK_BOOLAND || Tok == TOK_BOOLXOR) {
- /* Create the new node */
- ExprNode* Left = Root;
- switch (Tok) {
- case TOK_BOOLAND: Root = NewExprNode (EXPR_BOOLAND); break;
- case TOK_BOOLXOR: Root = NewExprNode (EXPR_BOOLXOR); break;
- default: Internal ("Invalid token");
- }
- Root->Left = Left;
+ long LVal, RVal, Val;
+ ExprNode* Left;
+ ExprNode* Right;
- /* Skip the operator token */
- NextTok ();
+ /* Remember the token and skip it */
+ enum Token T = Tok;
+ NextTok ();
+
+ /* Move root to left side and read the right side */
+ Left = Root;
+ Right = BoolExpr ();
+
+ /* If both expressions are constant, we can evaluate the term */
+ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
+
+ switch (T) {
+ case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break;
+ case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break;
+ default: Internal ("Invalid token");
+ }
+
+ /* Generate a literal expression and delete the old left and
+ * right sides.
+ */
+ FreeExpr (Left);
+ FreeExpr (Right);
+ Root = GenLiteralExpr (Val);
- /* Parse the right hand side */
- Root->Right = BoolExpr ();
+ } else {
+ /* Generate an expression tree */
+ unsigned char Op;
+ switch (T) {
+ case TOK_BOOLAND: Op = EXPR_BOOLAND; break;
+ case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break;
+ default: Internal ("Invalid token");
+ }
+ Root = NewExprNode (Op);
+ Root->Left = Left;
+ Root->Right = Right;
+
+ }
}
/* Return the expression tree we've created */
/* Handle booleans */
while (Tok == TOK_BOOLOR) {
- /* Create the new node */
- ExprNode* Left = Root;
- switch (Tok) {
- case TOK_BOOLOR: Root = NewExprNode (EXPR_BOOLOR); break;
- default: Internal ("Invalid token");
- }
- Root->Left = Left;
+ long LVal, RVal, Val;
+ ExprNode* Left;
+ ExprNode* Right;
- /* Skip the operator token */
- NextTok ();
+ /* Remember the token and skip it */
+ enum Token T = Tok;
+ NextTok ();
+
+ /* Move root to left side and read the right side */
+ Left = Root;
+ Right = Expr2 ();
+
+ /* If both expressions are constant, we can evaluate the term */
+ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) {
+
+ switch (T) {
+ case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break;
+ default: Internal ("Invalid token");
+ }
- /* Parse the right hand side */
- Root->Right = Expr2 ();
+ /* Generate a literal expression and delete the old left and
+ * right sides.
+ */
+ FreeExpr (Left);
+ FreeExpr (Right);
+ Root = GenLiteralExpr (Val);
+
+ } else {
+
+ /* Generate an expression tree */
+ unsigned char Op;
+ switch (T) {
+ case TOK_BOOLOR: Op = EXPR_BOOLOR; break;
+ default: Internal ("Invalid token");
+ }
+ Root = NewExprNode (Op);
+ Root->Left = Left;
+ Root->Right = Right;
+ }
}
/* Return the expression tree we've created */
/* Handle booleans */
if (Tok == TOK_BOOLNOT) {
- /* Create the new node */
- Root = NewExprNode (EXPR_BOOLNOT);
+ long Val;
+ ExprNode* Left;
/* Skip the operator token */
NextTok ();
- /* Parse the left hand side, allow more BNOTs */
- Root->Left = Expr0 ();
+ /* Read the argument */
+ Left = Expr0 ();
+
+ /* If the argument is const, evaluate it directly */
+ if (IsEasyConst (Left, &Val)) {
+ FreeExpr (Left);
+ Root = GenLiteralExpr (!Val);
+ } else {
+ Root = NewExprNode (EXPR_BOOLNOT);
+ Root->Left = Left;
+ }
} else {
-static void StudyExpr (ExprNode* Expr, ExprDesc* D, int Sign);
static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D)
-/* Study a binary expression subtree */
+/* Study a binary expression subtree. Helper function for StudyExpr. */
{
StudyExpr (Expr->Left, D, 1);
if (ExprDescIsConst (D)) {
{
ExprNode* N;
ExprNode* Root;
+ long Val;
+
+ /* Read Expression() */
+ N = Expression ();
+
+ /* If the expression is a cheap constant, generate a simpler tree */
+ if (IsEasyConst (N, &Val)) {
+
+ /* Free the constant expression tree */
+ FreeExpr (N);
+
+ /* Generate the final expression:
+ * Val - (* + Offs)
+ * Val - ((Seg + PC) + Offs)
+ * Val - Seg - PC - Offs
+ * (Val - PC - Offs) - Seg
+ */
+ Root = GenLiteralExpr (Val - GetPC () - Offs);
+ if (RelocMode) {
+ N = Root;
+ Root = NewExprNode (EXPR_MINUS);
+ Root->Left = N;
+ Root->Right = GenSectionExpr (GetCurrentSegNum ());
+ }
- /* Create *+Offs */
- if (RelocMode) {
- N = NewExprNode (EXPR_PLUS);
- N->Left = GenSectionExpr (GetCurrentSegNum ());
- N->Right = GenLiteralExpr (GetPC () + Offs);
} else {
- N = GenLiteralExpr (GetPC () + Offs);
- }
- /* Create the root node */
- Root = NewExprNode (EXPR_MINUS);
- Root->Left = Expression ();
- Root->Right = N;
+ /* Generate the expression:
+ * N - (* + Offs)
+ * N - ((Seg + PC) + Offs)
+ * N - Seg - PC - Offs
+ * N - (PC + Offs) - Seg
+ */
+ Root = NewExprNode (EXPR_MINUS);
+ Root->Left = N;
+ Root->Right = GenLiteralExpr (GetPC () + Offs);
+ if (RelocMode) {
+ N = Root;
+ Root = NewExprNode (EXPR_MINUS);
+ Root->Left = N;
+ Root->Right = GenSectionExpr (GetCurrentSegNum ());
+ }
+ }
/* Return the result */
- return SimplifyExpr (Root);
+ return Root;
}
/* Enter the base lexical level. We must do that here, since we may
* define symbols using -D.
*/
- SymEnterLevel ("", ADDR_SIZE_DEFAULT);
+ SymEnterLevel ("", ST_GLOBAL, ADDR_SIZE_DEFAULT);
/* Check the parameters */
I = 1;
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
-static unsigned OptionalAddrSize (void)
+static unsigned char OptionalAddrSize (void)
/* If a colon follows, parse an optional address size spec and return it.
* Otherwise return ADDR_SIZE_DEFAULT.
*/
-static void ExportImport (void (*Func) (SymEntry*, unsigned, unsigned),
- unsigned DefAddrSize, unsigned Flags)
+static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned),
+ unsigned char DefAddrSize, unsigned Flags)
/* Export or import symbols */
{
SymEntry* Sym;
- unsigned AddrSize;
+ unsigned char AddrSize;
while (1) {
{
long Prio;
+
+ /* Find the symbol table entry, allocate a new one if necessary */
+ SymEntry* Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
+
/* Optional constructor priority */
if (Tok == TOK_COMMA) {
/* Priority value follows */
}
/* Define the symbol */
- SymConDes (Name, Type, (unsigned) Prio);
+ SymConDes (Sym, ADDR_SIZE_DEFAULT, Type, (unsigned) Prio);
}
static void DoEndProc (void)
/* Leave a lexical level */
{
- if (CurrentScope != RootScope) {
- SymLeaveLevel ();
- } else {
+ if (CurrentScope == RootScope || GetCurrentSymTabType () != ST_PROC) {
/* No local scope */
- ErrorSkip ("No open lexical level");
+ ErrorSkip ("No open .PROC");
+ } else {
+ SymLeaveLevel ();
}
}
static void DoEndScope (void)
/* Leave a lexical level */
{
- if (CurrentScope != RootScope) {
- SymLeaveLevel ();
- } else {
+ if (CurrentScope == RootScope || GetCurrentSymTabType () != ST_SCOPE) {
/* No local scope */
- ErrorSkip ("No open lexical level");
+ ErrorSkip ("No open .SCOPE");
+ } else {
+ SymLeaveLevel ();
}
}
static void DoProc (void)
/* Start a new lexical scope */
{
- if (Tok == TOK_IDENT) {
+ char Name[sizeof(SVal)];
+ unsigned char AddrSize;
- unsigned AddrSize;
+ if (Tok == TOK_IDENT) {
/* The new scope has a name. Remember it. */
- char Name[sizeof(SVal)];
strcpy (Name, SVal);
/* Search for the symbol, generate a new one if needed */
/* Mark the symbol as defined */
SymDef (Sym, GenCurrentPC (), AddrSize, SF_LABEL);
- /* Enter a new scope with the given name */
- SymEnterLevel (Name, AddrSize);
-
} else {
/* A .PROC statement without a name */
- char Buf[sizeof (SVal)];
- SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope"), ADDR_SIZE_DEFAULT);
Warning (1, "Unnamed .PROCs are deprecated, please use .SCOPE");
+ AnonName (Name, sizeof (Name), "PROC");
+ AddrSize = ADDR_SIZE_DEFAULT;
}
+
+ /* Enter a new scope */
+ SymEnterLevel (Name, ST_PROC, AddrSize);
}
/* Start a local scope */
{
char Name[sizeof (SVal)];
+ unsigned char AddrSize;
- if (Tok == TOK_IDENT) {
- unsigned AddrSize;
+ if (Tok == TOK_IDENT) {
- /* The new scope has a name. Remember and skip it. */
+ /* The new scope has a name. Remember and skip it. */
strcpy (Name, SVal);
NextTok ();
- /* Read an optional address size specifier */
- AddrSize = OptionalAddrSize ();
-
- /* Enter a new scope with the given name */
- SymEnterLevel (Name, AddrSize);
-
} else {
/* An unnamed scope */
- SymEnterLevel (AnonName (Name, sizeof (Name), "Scope"), ADDR_SIZE_DEFAULT);
+ AnonName (Name, sizeof (Name), "SCOPE");
}
+
+ /* Read an optional address size specifier */
+ AddrSize = OptionalAddrSize ();
+
+ /* Enter the new scope */
+ SymEnterLevel (Name, ST_SCOPE, AddrSize);
+
}
{ ccNone, DoRepeat },
{ ccNone, DoRes },
{ ccNone, DoInvalid }, /* .RIGHT */
- { ccNone, DoROData },
+ { ccNone, DoROData },
{ ccNone, DoScope },
{ ccNone, DoSegment },
{ ccNone, DoSetCPU },
-unsigned ParseAddrSize (void)
+unsigned char ParseAddrSize (void)
/* Check if the next token is a keyword that denotes an address size specifier.
* If so, return the corresponding address size constant, otherwise output an
* error message and return ADDR_SIZE_DEFAULT.
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
+/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
* or -1 if the keyword was not found.
*/
-unsigned ParseAddrSize (void);
+unsigned char ParseAddrSize (void);
/* Check if the next token is a keyword that denotes an address size specifier.
* If so, return the corresponding address size constant, otherwise output an
* error message and return ADDR_SIZE_DEFAULT.
#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 ();
}
-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) {
}
/* 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 */
{
#define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#endif
-void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned AddrSize, unsigned Flags);
+void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned char AddrSize, unsigned Flags);
/* Mark a symbol as defined */
void SymRef (SymEntry* Sym);
/* Mark the given symbol as referenced */
-void SymImport (SymEntry* Sym, unsigned AddrSize, unsigned Flags);
+void SymImport (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
/* Mark the given symbol as an imported symbol */
-void SymExport (SymEntry* Sym, unsigned AddrSize, unsigned Flags);
+void SymExport (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
/* Mark the given symbol as an exported symbol */
-void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags);
+void SymGlobal (SymEntry* Sym, unsigned char AddrSize, unsigned Flags);
/* Mark the given symbol as a global symbol, that is, as a symbol that is
* either imported or exported.
*/
+void SymConDes (SymEntry* Sym, 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.
+ */
+
int SymIsDef (const SymEntry* Sym);
/* Return true if the given symbol is already defined */
S->Childs = 0;
S->Flags = ST_NONE;
S->AddrSize = ADDR_SIZE_DEFAULT;
- S->Type = 0;
+ S->Type = ST_UNDEF;
S->Level = Level;
S->TableSlots = Slots;
S->TableEntries = 0;
-void SymEnterLevel (const char* ScopeName, unsigned AddrSize)
+void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char AddrSize)
/* Enter a new lexical level */
{
/* Map a default address size to something real */
* 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 `%s'", ScopeName);
}
+
} else {
CurrentScope = RootScope = NewSymTable (0, ScopeName);
}
- /* Mark the scope as defined */
- CurrentScope->Flags |= ST_DEFINED;
+ /* Mark the scope as defined and set type and address size */
+ CurrentScope->Flags |= ST_DEFINED;
+ CurrentScope->AddrSize = AddrSize;
+ CurrentScope->Type = Type;
}
do {
/* Search in the current table */
Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
- if (Sym) {
+ if (Sym) {
/* Found, return it */
return Sym;
} else {
-void SymConDes (const char* Name, 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.
- */
-{
- SymEntry* S;
-
- /* 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 (IsLocalName (Name)) {
- Error ("Illegal use of a local symbol");
- return;
- }
-
- /* Do we have such a symbol? */
- S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
- if (S->Flags & SF_IMPORT) {
- /* The symbol is already marked as imported external symbol */
- Error ("Symbol `%s' is already an import", Name);
- return;
- }
-
- /* If the symbol is marked as global, silently remove the global flag */
- if (S->Flags & SF_GLOBAL) {
- S->Flags &= ~SF_GLOBAL;
- }
-
- /* Check if the symbol was not already defined as ZP symbol */
- if (S->AddrSize == ADDR_SIZE_ZP) {
- Error ("Redeclaration mismatch for symbol `%s'", Name);
- }
-
- /* 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'", Name);
- }
- }
- S->ConDesPrio[Type] = Prio;
-
- /* Set the symbol data */
- S->Flags |= SF_EXPORT | SF_REFERENCED;
-}
-
-
-
int SymIsZP (SymEntry* S)
/* Return true if the symbol is explicitly marked as zeropage symbol */
{
+unsigned char GetCurrentSymTabType ()
+/* Return the type of the current symbol table */
+{
+ CHECK (CurrentScope != 0);
+ return CurrentScope->Type;
+}
+
+
+
static void SymCheckUndefined (SymEntry* S)
/* Handle an undefined symbol */
{
-
+
#define ST_NONE 0x00 /* No flags */
#define ST_DEFINED 0x01 /* Scope has been defined */
+/* Symbol table types */
+#define ST_GLOBAL 0x00 /* Root level */
+#define ST_PROC 0x01 /* .PROC */
+#define ST_SCOPE 0x02 /* .SCOPE */
+#define ST_STUCT 0x03 /* .STRUCT */
+#define ST_UNDEF 0xFF
+
/* A symbol table */
typedef struct SymTable SymTable;
struct SymTable {
-void SymEnterLevel (const char* ScopeName, unsigned AddrSize);
+void SymEnterLevel (const char* ScopeName, unsigned char Type, unsigned char AddrSize);
/* Enter a new lexical level */
void SymLeaveLevel (void);
* new entry created, or - in case AllocNew is zero - return 0.
*/
-void SymConDes (const char* Name, 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.
- */
-
int SymIsZP (SymEntry* Sym);
/* Return true if the symbol is explicitly marked as zeropage symbol */
+unsigned char GetCurrentSymTabType ();
+/* Return the type of the current symbol table */
+
void SymCheck (void);
/* Run through all symbols and check for anomalies and errors */