--- /dev/null
+/*****************************************************************************/
+/* */
+/* anonname.c */
+/* */
+/* Create names for anonymous scopes/variables/types */
+/* */
+/* */
+/* */
+/* (C) 2000-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#include <stdio.h>
+#include <string.h>
+
+/* common */
+#include "xsprintf.h"
+
+/* ca65 */
+#include "anonname.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+static const char AnonTag[] = "$anon";
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+char* AnonName (char* Buf, unsigned Size, const char* Spec)
+/* Get a name for an anonymous scope, variable or type. Size is the size of
+ * the buffer passed to the function, Spec will be used as part of the
+ * identifier if given. A pointer to the buffer is returned.
+ */
+{
+ static unsigned ACount = 0;
+ xsprintf (Buf, Size, "%s-%s-%04X", AnonTag, Spec, ++ACount);
+ return Buf;
+}
+
+
+
+int IsAnonName (const char* Name)
+/* Check if the given symbol name is that of an anonymous symbol */
+{
+ return (strncmp (Name, AnonTag, sizeof (AnonTag) - 1) == 0);
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* anonname.h */
+/* */
+/* Create names for anonymous scopes/variables/types */
+/* */
+/* */
+/* */
+/* (C) 2000-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#ifndef ANONNAME_H
+#define ANONNAME_H
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+char* AnonName (char* Buf, unsigned Size, const char* Spec);
+/* Get a name for an anonymous scope, variable or type. Size is the size of
+ * the buffer passed to the function, Spec will be used as part of the
+ * identifier if given. A pointer to the buffer is returned.
+ */
+
+int IsAnonName (const char* Name);
+/* Check if the given symbol name is that of an anonymous symbol */
+
+
+
+/* End of anonname.h */
+#endif
+
+
+
-static ExprNode* NewExprNode (void)
+static ExprNode* NewExprNode (unsigned Op)
/* Create a new expression node */
{
ExprNode* N;
/* Allocate fresh memory */
N = xmalloc (sizeof (ExprNode));
}
- N->Op = EXPR_NULL;
+ N->Op = Op;
N->Left = N->Right = 0;
N->Obj = 0;
N = GenLiteralExpr (GetSymVal (S));
} else {
/* Create symbol node */
- N = NewExprNode ();
- N->Op = EXPR_SYMBOL;
- N->V.Sym = S;
+ N = GenSymExpr (S);
}
NextTok ();
}
N = GenLiteralExpr (GetSymVal (S));
} else {
/* Create symbol node */
- N = NewExprNode ();
- N->Op = EXPR_SYMBOL;
- N->V.Sym = S;
+ N = GenSymExpr (S);
}
NextTok ();
break;
case TOK_MINUS:
NextTok ();
- N = NewExprNode ();
+ N = NewExprNode (EXPR_UNARY_MINUS);
N->Left = Factor ();
- N->Op = EXPR_UNARY_MINUS;
break;
case TOK_NOT:
NextTok ();
- N = NewExprNode ();
+ N = NewExprNode (EXPR_NOT);
N->Left = Factor ();
- N->Op = EXPR_NOT;
break;
case TOK_STAR:
case TOK_LT:
NextTok ();
- N = NewExprNode ();
+ N = NewExprNode (EXPR_BYTE0);
N->Left = Factor ();
- N->Op = EXPR_BYTE0;
break;
case TOK_GT:
NextTok ();
- N = NewExprNode ();
+ N = NewExprNode (EXPR_BYTE1);
N->Left = Factor ();
- N->Op = EXPR_BYTE1;
break;
case TOK_LPAREN:
static ExprNode* Term (void)
{
- ExprNode* Root;
-
/* Read left hand side */
- Root = Factor ();
+ ExprNode* Root = Factor ();
/* Handle multiplicative operations */
while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
Tok == TOK_SHR) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_MUL: Root->Op = EXPR_MUL; break;
- case TOK_DIV: Root->Op = EXPR_DIV; break;
- case TOK_MOD: Root->Op = EXPR_MOD; break;
- case TOK_AND: Root->Op = EXPR_AND; break;
- case TOK_XOR: Root->Op = EXPR_XOR; break;
- case TOK_SHL: Root->Op = EXPR_SHL; break;
- case TOK_SHR: Root->Op = EXPR_SHR; break;
+ case TOK_MUL: Root = NewExprNode (EXPR_MUL); break;
+ case TOK_DIV: Root = NewExprNode (EXPR_DIV); break;
+ case TOK_MOD: Root = NewExprNode (EXPR_MOD); break;
+ case TOK_AND: Root = NewExprNode (EXPR_AND); break;
+ case TOK_XOR: Root = NewExprNode (EXPR_XOR); break;
+ case TOK_SHL: Root = NewExprNode (EXPR_SHL); break;
+ case TOK_SHR: Root = NewExprNode (EXPR_SHR); break;
default: Internal ("Invalid token");
}
+ Root->Left = Left;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
static ExprNode* SimpleExpr (void)
{
- ExprNode* Root;
-
/* Read left hand side */
- Root = Term ();
+ ExprNode* Root = Term ();
/* Handle additive operations */
while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_PLUS: Root->Op = EXPR_PLUS; break;
- case TOK_MINUS: Root->Op = EXPR_MINUS; break;
- case TOK_OR: Root->Op = EXPR_OR; break;
+ 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;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_EQ: Root->Op = EXPR_EQ; break;
- case TOK_NE: Root->Op = EXPR_NE; break;
- case TOK_LT: Root->Op = EXPR_LT; break;
- case TOK_GT: Root->Op = EXPR_GT; break;
- case TOK_LE: Root->Op = EXPR_LE; break;
- case TOK_GE: Root->Op = EXPR_GE; break;
+ 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;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
/* Handle booleans */
while (Tok == TOK_BAND || Tok == TOK_BXOR) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_BAND: Root->Op = EXPR_BAND; break;
- case TOK_BXOR: Root->Op = EXPR_BXOR; break;
+ case TOK_BAND: Root = NewExprNode (EXPR_BAND); break;
+ case TOK_BXOR: Root = NewExprNode (EXPR_BXOR); break;
default: Internal ("Invalid token");
}
+ Root->Left = Left;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
/* Handle booleans */
while (Tok == TOK_BOR) {
- /* Create a new node and insert the left expression */
+ /* Create the new node */
ExprNode* Left = Root;
- Root = NewExprNode ();
- Root->Left = Left;
-
- /* Determine the operator token */
switch (Tok) {
- case TOK_BOR: Root->Op = EXPR_BOR; break;
+ case TOK_BOR: Root = NewExprNode (EXPR_BOR); break;
default: Internal ("Invalid token");
}
+ Root->Left = Left;
+
+ /* Skip the operator token */
NextTok ();
/* Parse the right hand side */
/* Handle booleans */
if (Tok == TOK_BNOT) {
- /* Create a new node */
- Root = NewExprNode ();
+ /* Create the new node */
+ Root = NewExprNode (EXPR_BNOT);
- /* Determine the operator token */
- switch (Tok) {
- case TOK_BNOT: Root->Op = EXPR_BNOT; break;
- default: Internal ("Invalid token");
- }
+ /* Skip the operator token */
NextTok ();
/* Parse the left hand side, allow more BNOTs */
/* Try to simplify the given expression tree */
{
if (Root) {
- SimplifyExpr (Root->Left);
- SimplifyExpr (Root->Right);
+ Root->Left = SimplifyExpr (Root->Left);
+ Root->Right = SimplifyExpr (Root->Right);
if (IsConstExpr (Root)) {
/* The complete expression is constant */
Root->V.Val = GetExprVal (Root);
if (Root) {
FreeExpr (Root->Left);
FreeExpr (Root->Right);
+ if (Root->Op == EXPR_SYMBOL) {
+ /* Remove the symbol reference */
+ SymDelRef (Root->V.Sym, Root);
+ }
FreeExprNode (Root);
}
}
ExprNode* GenLiteralExpr (long Val)
/* Return an expression tree that encodes the given literal value */
{
- ExprNode* Expr = NewExprNode ();
- Expr->Op = EXPR_LITERAL;
+ ExprNode* Expr = NewExprNode (EXPR_LITERAL);
Expr->V.Val = Val;
return Expr;
}
+ExprNode* GenSymExpr (SymEntry* Sym)
+/* Return an expression node that encodes the given symbol */
+{
+ ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
+ Expr->V.Sym = Sym;
+ SymAddRef (Sym, Expr);
+ return Expr;
+}
+
+
+
+static ExprNode* GenSectionExpr (unsigned SegNum)
+/* Return an expression node for the given section */
+{
+ ExprNode* Expr = NewExprNode (EXPR_SECTION);
+ Expr->V.SegNum = SegNum;
+ return Expr;
+}
+
+
+
ExprNode* GenCurrentPC (void)
/* Return the current program counter as expression */
{
- ExprNode* Left;
ExprNode* Root;
if (RelocMode) {
/* Create SegmentBase + Offset */
- Left = NewExprNode ();
- Left->Op = EXPR_SECTION;
- Left->V.SegNum = GetSegNum ();
-
- Root = NewExprNode ();
- Root->Left = Left;
+ Root = NewExprNode (EXPR_PLUS);
+ Root->Left = GenSectionExpr (GetSegNum ());
Root->Right = GenLiteralExpr (GetPC ());
- Root->Op = EXPR_PLUS;
} else {
/* Absolute mode, just return PC value */
Root = GenLiteralExpr (GetPC ());
ExprNode* GenSwapExpr (ExprNode* Expr)
/* Return an extended expression with lo and hi bytes swapped */
{
- ExprNode* N = NewExprNode ();
- N->Op = EXPR_SWAP;
+ ExprNode* N = NewExprNode (EXPR_SWAP);
N->Left = Expr;
return N;
}
{
ExprNode* N;
ExprNode* Root;
- ExprNode* Left;
/* Create *+Offs */
if (RelocMode) {
- Left = NewExprNode ();
- Left->Op = EXPR_SECTION;
- Left->V.SegNum = GetSegNum ();
-
- N = NewExprNode ();
- N->Left = Left;
+ N = NewExprNode (EXPR_PLUS);
+ N->Left = GenSectionExpr (GetSegNum ());
N->Right = GenLiteralExpr (GetPC () + Offs);
- N->Op = EXPR_PLUS;
} else {
N = GenLiteralExpr (GetPC () + Offs);
}
/* Create the root node */
- Root = NewExprNode ();
+ Root = NewExprNode (EXPR_MINUS);
Root->Left = Expression ();
Root->Right = N;
- Root->Op = EXPR_MINUS;
/* Return the result */
return SimplifyExpr (Root);
ExprNode* GenULabelExpr (unsigned Num)
/* Return an expression for an unnamed label with the given index */
{
- /* Get an expression node */
- ExprNode* Node = NewExprNode ();
-
- /* Set the values */
- Node->Op = EXPR_ULABEL;
+ ExprNode* Node = NewExprNode (EXPR_ULABEL);
Node->V.Val = Num;
/* Return the new node */
/* Force the given expression into a byte and return the result */
{
/* Use the low byte operator to force the expression into byte size */
- ExprNode* Root = NewExprNode ();
+ ExprNode* Root = NewExprNode (EXPR_BYTE0);
Root->Left = Expr;
- Root->Op = EXPR_BYTE0;
/* Return the result */
return Root;
/* Force the given expression into a word and return the result. */
{
/* AND the expression by $FFFF to force it into word size */
- ExprNode* Root = NewExprNode ();
+ ExprNode* Root = NewExprNode (EXPR_AND);
Root->Left = Expr;
- Root->Op = EXPR_AND;
Root->Right = GenLiteralExpr (0xFFFF);
/* Return the result */
/* Generate an expression that compares Expr and Val for inequality */
{
/* Generate a compare node */
- ExprNode* Root = NewExprNode ();
+ ExprNode* Root = NewExprNode (EXPR_NE);
Root->Left = Expr;
- Root->Op = EXPR_NE;
Root->Right = GenLiteralExpr (Val);
/* Return the result */
} else {
return IsConstExpr (Root->Right);
}
- } else {
+ } else {
/* lhs not const --> tree not const */
return 0;
}
case EXPR_SYMBOL:
if (SymIsZP (N->V.Sym)) {
*IsByte = 1;
- } else if (SymHasExpr (N->V.Sym)) {
+ } else if (SymHasExpr (N->V.Sym)) {
/* Check if this expression is a byte expression */
*IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
}
case EXPR_SYMBOL:
if (SymHasExpr (Expr->V.Sym)) {
- /* The symbol has an expression tree */
- SymEntry* Sym = Expr->V.Sym;
- if (SymHasUserMark (Sym)) {
- /* Circular definition */
- if (Verbosity) {
- DumpExpr (Expr);
- }
- PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
- return GenLiteralExpr (0); /* Return a dummy value */
- }
- SymMarkUser (Sym);
- Expr = RemoveSyms (GetSymExpr (Sym), 1);
- SymUnmarkUser (Sym);
- return Expr;
+ /* The symbol has an expression tree */
+ SymEntry* Sym = Expr->V.Sym;
+ if (SymHasUserMark (Sym)) {
+ /* Circular definition */
+ if (Verbosity) {
+ DumpExpr (Expr);
+ }
+ PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
+ return GenLiteralExpr (0); /* Return a dummy value */
+ }
+ SymMarkUser (Sym);
+ Expr = RemoveSyms (GetSymExpr (Sym), 1);
+ SymUnmarkUser (Sym);
+ return Expr;
} else if (SymIsConst (Expr->V.Sym)) {
- /* The symbol is a constant */
- return GenLiteralExpr (GetSymVal (Expr->V.Sym));
+ /* The symbol is a constant */
+ return GenLiteralExpr (GetSymVal (Expr->V.Sym));
}
break;
case EXPR_ULABEL:
if (ULabCanResolve ()) {
- ExprNode* NewExpr = ULabResolve (Expr->V.Val);
- FreeExpr (Expr);
- Expr = NewExpr;
+ ExprNode* NewExpr = ULabResolve (Expr->V.Val);
+ FreeExpr (Expr);
+ Expr = NewExpr;
}
break;
/* Clone the current node if needed */
if (MustClone) {
- /* Create a new node */
- ExprNode* Clone = NewExprNode ();
+ ExprNode* Clone;
- /* Clone the operation */
- Clone->Op = Expr->Op;
-
- /* Clone the attribute if needed */
+ /* Clone the expression tree */
switch (Expr->Op) {
case EXPR_LITERAL:
+ Clone = GenLiteralExpr (Expr->V.Val);
+ break;
+
case EXPR_ULABEL:
- Clone->V.Val = Expr->V.Val;
- break;
+ Clone = GenULabelExpr (Expr->V.Val);
+ break;
case EXPR_SYMBOL:
- Clone->V.Sym = Expr->V.Sym;
- break;
+ Clone = GenSymExpr (Expr->V.Sym);
+ break;
case EXPR_SECTION:
- Clone->V.SegNum = Expr->V.SegNum;
- break;
+ Clone = GenSectionExpr (Expr->V.SegNum);
+ break;
- }
+ default:
+ Clone = NewExprNode (Expr->Op);
+ Clone->Left = RemoveSyms (Expr->Left, 1);
+ Clone->Right = RemoveSyms (Expr->Right, 1);
+ break;
- /* Clone the tree nodes */
- Clone->Left = RemoveSyms (Expr->Left, MustClone);
- Clone->Right = RemoveSyms (Expr->Right, MustClone);
+ }
/* Done */
return Clone;
} else {
/* Nothing to clone */
- Expr->Left = RemoveSyms (Expr->Left, MustClone);
- Expr->Right = RemoveSyms (Expr->Right, MustClone);
+ Expr->Left = RemoveSyms (Expr->Left, 0);
+ Expr->Right = RemoveSyms (Expr->Right, 0);
/* Done */
return Expr;
-
}
}
Expr = GenLiteralExpr (Val);
} else if (Val) {
/* Extracted a value */
- N = NewExprNode ();
- N->Op = EXPR_PLUS;
+ N = NewExprNode (EXPR_PLUS);
N->Left = Expr;
N->Right = GenLiteralExpr (Val);
Expr = N;
return 0;
}
- /* Get a new node */
- Clone = NewExprNode ();
-
- /* Clone the operation */
- Clone->Op = Expr->Op;
-
- /* Clone the attribute if needed */
+ /* Clone the node */
switch (Expr->Op) {
case EXPR_LITERAL:
+ Clone = GenLiteralExpr (Expr->V.Val);
+ break;
+
case EXPR_ULABEL:
- Clone->V.Val = Expr->V.Val;
+ Clone = GenULabelExpr (Expr->V.Val);
break;
case EXPR_SYMBOL:
- Clone->V.Sym = Expr->V.Sym;
+ Clone = GenSymExpr (Expr->V.Sym);
break;
case EXPR_SECTION:
- Clone->V.SegNum = Expr->V.SegNum;
+ Clone = GenSectionExpr (Expr->V.SegNum);
break;
+ default:
+ /* Generate a new node */
+ Clone = NewExprNode (Expr->Op);
+ /* Clone the tree nodes */
+ Clone->Left = CloneExpr (Expr->Left);
+ Clone->Right = CloneExpr (Expr->Right);
+ break;
}
- /* Clone the tree nodes */
- Clone->Left = CloneExpr (Expr->Left);
- Clone->Right = CloneExpr (Expr->Right);
-
/* Done */
return Clone;
}
+
ExprNode* GenLiteralExpr (long Val);
/* Return an expression tree that encodes the given literal value */
+ExprNode* GenSymExpr (struct SymEntry* Sym);
+/* Return an expression node that encodes the given symbol */
+
ExprNode* GenCurrentPC (void);
/* Return the current program counter as expression */
/* Enter the base lexical level. We must do that here, since we may
* define symbols using -D.
*/
- SymEnterLevel ();
+ SymEnterLevel (0);
/* Check the parameters */
I = 1;
EBIND = emxbind
LDFLAGS =
-OBJS = asserts.o \
+OBJS = anonname.o \
+ asserts.o \
condasm.o \
dbginfo.o \
ea.o \
# ------------------------------------------------------------------------------
# All library OBJ files
-OBJS = asserts.obj \
+OBJS = anonname.obj \
+ asserts.obj \
condasm.obj \
dbginfo.obj \
ea.obj \
#include "xmalloc.h"
/* ca65 */
+#include "anonname.h"
#include "asserts.h"
#include "condasm.h"
#include "dbginfo.h"
if (IsZPSeg ()) {
Flags |= SYM_ZP;
}
- SymDef (SVal, GenCurrentPC (), Flags);
- NextTok ();
+ SymDef (SVal, GenCurrentPC (), Flags);
+ SymEnterLevel (SVal);
+ NextTok ();
+ } else {
+ char Buf[sizeof (SVal)];
+ SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope"));
}
- SymEnterLevel ();
}
-SymEntry* NewSymEntry (const char* Name)
+SymEntry* NewSymEntry (unsigned Name)
/* Allocate a symbol table entry, initialize and return it */
{
- SymEntry* S;
- unsigned Len;
-
- /* Get the length of the name */
- Len = strlen (Name);
-
/* Allocate memory */
- S = xmalloc (sizeof (SymEntry) + Len);
+ SymEntry* S = xmalloc (sizeof (SymEntry));
/* Initialize the entry */
S->Left = 0;
S->Pos = CurPos;
S->Flags = 0;
S->V.Expr = 0;
+ S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
- memcpy (S->Name, Name, Len+1);
+ S->Name = Name;
/* Insert it into the list of all entries */
S->List = SymList;
}
-
+
/* common */
#include "cddefs.h"
+#include "coll.h"
#include "filepos.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_EXPORT 0x0004 /* Export this symbol */
-#define SF_IMPORT 0x0008 /* Import this symbol */
-#define SF_GLOBAL 0x0010 /* Global symbol */
-#define SF_ZP 0x0020 /* Declared as zeropage symbol */
+#define SF_USER 0x0001 /* User bit */
+#define SF_TRAMPOLINE 0x0002 /* Trampoline entry */
+#define SF_EXPORT 0x0004 /* Export this symbol */
+#define SF_IMPORT 0x0008 /* Import this symbol */
+#define SF_GLOBAL 0x0010 /* Global symbol */
+#define SF_ZP 0x0020 /* Declared as zeropage symbol */
#define SF_ABS 0x0040 /* Declared as absolute symbol */
#define SF_LABEL 0x0080 /* Used as a label */
#define SF_FORCED 0x0100 /* Forced import, SF_IMPORT also set */
long Val; /* Value (if CONST set) */
SymEntry* Sym; /* Symbol (if trampoline entry) */
} V;
+ Collection ExprRefs; /* Expressions using this symbol */
unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */
/* ...actually value+1 (used as flag) */
- char Name [1]; /* Dynamic allocation */
+ unsigned Name; /* Name index in global string pool */
};
/* List of all symbol table entries */
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
-SymEntry* NewSymEntry (const char* Name);
+SymEntry* NewSymEntry (unsigned Name);
/* Allocate a symbol table entry, initialize and return it */
+#if defined(HAVE_INLINE)
+INLINE void SymAddRef (SymEntry* Sym, struct ExprNode* Expr)
+/* Add a reference to this symbol */
+{
+ CollAppend (&Sym->ExprRefs, Expr);
+}
+#else
+#define SymAddRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr)
+#endif
+
+#if defined(HAVE_INLINE)
+INLINE void SymDelRef (SymEntry* Sym, struct ExprNode* Expr)
+/* Delete a reference to this symbol */
+{
+ CollDeleteItem (&Sym->ExprRefs, Expr);
+}
+#else
+#define SymDelRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
+#endif
+
/* End of symentry.h */
#define SUB_HASHTAB_SIZE 53
typedef struct SymTable SymTable;
struct SymTable {
+ SymTable* Left; /* Pointer to smaller entry */
+ SymTable* Right; /* Pointer to greater entry */
+ SymTable* Parent; /* Link to enclosing scope if any */
+ SymTable* Childs; /* Pointer to child scopes */
+ unsigned Level; /* Lexical level */
unsigned TableSlots; /* Number of hash table slots */
unsigned TableEntries; /* Number of entries in the table */
- SymTable* BackLink; /* Link to enclosing scope if any */
+ unsigned Name; /* Name of the scope */
SymEntry* Table [1]; /* Dynamic allocation */
};
-static int IsLocal (const char* Name)
+static int IsLocalName (const char* Name)
/* Return true if Name is the name of a local symbol */
{
return (*Name == LocalStart);
-static SymTable* NewSymTable (unsigned Size)
+static int IsLocalNameId (unsigned Name)
+/* Return true if Name is the name of a local symbol */
+{
+ return (*GetString (Name) == LocalStart);
+}
+
+
+
+static unsigned SymTableSize (unsigned Level)
+/* Get the size of a table for the given lexical level */
+{
+ switch (Level) {
+ case 0: return 213;
+ case 1: return 53;
+ default: return 29;
+ }
+}
+
+
+
+static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
/* Allocate a symbol table on the heap and return it */
{
- SymTable* S;
+ /* Determine the lexical level and the number of table slots */
+ unsigned Level = Parent? Parent->Level + 1 : 0;
+ unsigned Slots = SymTableSize (Level);
/* Allocate memory */
- S = xmalloc (sizeof (SymTable) + (Size-1) * sizeof (SymEntry*));
+ SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));
/* Set variables and clear hash table entries */
- S->TableSlots = Size;
+ S->Left = 0;
+ S->Right = 0;
+ S->Childs = 0;
+ S->Level = Level;
+ S->TableSlots = Slots;
S->TableEntries = 0;
- S->BackLink = 0;
- while (Size--) {
- S->Table [Size] = 0;
+ S->Parent = Parent;
+ S->Name = Name;
+ while (Slots--) {
+ S->Table[Slots] = 0;
+ }
+
+ /* Insert the symbol table into the child tree of the parent */
+ if (Parent) {
+ SymTable* T = Parent->Childs;
+ if (T == 0) {
+ /* First entry */
+ Parent->Childs = S;
+ } else {
+ while (1) {
+ /* Choose next entry */
+ if (S->Name < T->Name) {
+ if (T->Left) {
+ T = T->Left;
+ } else {
+ T->Left = S;
+ break;
+ }
+ } else if (S->Name > T->Name) {
+ if (T->Right) {
+ T = T->Right;
+ } else {
+ T->Right = S;
+ break;
+ }
+ } else {
+ /* Duplicate scope name */
+ Internal ("Duplicate scope name: `%s'", GetString (S->Name));
+ }
+ }
+ }
+ } else {
+ /* This is the root table */
+ RootTab = S;
}
/* Return the prepared struct */
-static int SearchSymTab (SymEntry* T, const char* Name, SymEntry** E)
-/* Search in the given table for a name (Hash is the hash value of Name and
- * is given as parameter so that it will not get calculated twice if we search
- * in more than one table). 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.
+static int SearchSymTree (SymEntry* T, unsigned 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.
*/
{
int Cmp;
/* Is there a tree? */
if (T == 0) {
- *E = 0;
- return 1;
+ *E = 0;
+ return 1;
}
/* We have a table, search it */
while (1) {
- /* Choose next entry */
- Cmp = strcmp (Name, T->Name);
- if (Cmp < 0 && T->Left) {
+ /* Choose next entry */
+ if (Name < T->Name) {
+ Cmp = -1;
+ } else if (Name > T->Name) {
+ Cmp = +1;
+ } else {
+ Cmp = 0;
+ }
+ if (Name < T->Name && T->Left) {
T = T->Left;
- } else if (Cmp > 0 && T->Right) {
+ } else if (Name > T->Name && T->Right) {
T = T->Right;
} else {
- /* Found or end of search */
- break;
+ /* Found or end of search, return the result */
+ *E = T;
+ return Cmp;
}
}
-
- /* Return the search result */
- *E = T;
- return Cmp;
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
-static SymEntry* SymFind (SymTable* Tab, const char* Name, int AllocNew)
+static SymEntry* SymFind (SymTable* Tab, unsigned 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.
int Cmp;
unsigned Hash;
- if (IsLocal (Name)) {
+ if (IsLocalNameId (Name)) {
/* Local symbol, get the table */
if (!SymLast) {
}
/* Search for the symbol if we have a table */
- Cmp = SearchSymTab (SymLast->Locals, Name, &S);
+ Cmp = SearchSymTree (SymLast->Locals, Name, &S);
/* If we found an entry, return it */
if (Cmp == 0) {
} else {
/* Global symbol: Get the hash value for the name */
- Hash = HashStr (Name) % Tab->TableSlots;
+ Hash = Name % Tab->TableSlots;
/* Search for the entry */
- Cmp = SearchSymTab (Tab->Table [Hash], Name, &S);
+ Cmp = SearchSymTree (Tab->Table[Hash], Name, &S);
/* If we found an entry, return it */
if (Cmp == 0) {
/* Check for a trampoline entry, in this case return the real
* symbol.
*/
- if (S->Flags & SF_TRAMPOLINE) {
- return S->V.Sym;
- } else {
- return S;
+ while (S->Flags & SF_TRAMPOLINE) {
+ S = S->V.Sym;
}
+ return S;
}
if (AllocNew) {
/* Otherwise create a new entry, insert and return it */
SymEntry* N = NewSymEntry (Name);
if (S == 0) {
- Tab->Table [Hash] = N;
+ Tab->Table[Hash] = N;
} else if (Cmp < 0) {
S->Left = N;
} else {
-static SymEntry* SymFindAny (SymTable* Tab, const char* Name)
+static SymEntry* SymFindAny (SymTable* Tab, unsigned Name)
/* Find a symbol in any table */
{
SymEntry* Sym;
/* Found, return it */
return Sym;
} else {
- /* Not found, search in the backlink, if we have one */
- Tab = Tab->BackLink;
+ /* Not found, search in the parent scope, if we have one */
+ Tab = Tab->Parent;
}
} while (Sym == 0 && Tab != 0);
-void SymEnterLevel (void)
+void SymEnterLevel (const char* ScopeName)
/* Enter a new lexical level */
{
- if (RootTab == 0) {
- /* Create the main symbol table */
- RootTab = SymTab = NewSymTable (MAIN_HASHTAB_SIZE);
- } else {
- /* Create a local symbol table */
- SymTable* LocalSyms = NewSymTable (SUB_HASHTAB_SIZE);
- LocalSyms->BackLink = SymTab;
- SymTab = LocalSyms;
+ /* Accept NULL pointers for the scope name */
+ if (ScopeName == 0) {
+ ScopeName = "";
}
+
+ /* Create the new table */
+ SymTab = NewSymTable (SymTab, GetStringId (ScopeName));
}
void SymLeaveLevel (void)
/* Leave the current lexical level */
{
- SymTab = SymTab->BackLink;
+ SymTab = SymTab->Parent;
}
/* Define a new symbol */
{
/* Do we have such a symbol? */
- SymEntry* S = SymFind (SymTab, Name, SF_ALLOC_NEW);
+ SymEntry* S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* Defined symbol is marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, Name);
}
/* If this is not a local symbol, remember it as the last global one */
- if (!IsLocal (Name)) {
+ if (!IsLocalName (Name)) {
SymLast = S;
}
}
/* Search for the symbol and return it */
{
SymEntry* S;
+ unsigned NameId = GetStringId (Name);
switch (Scope) {
- case SCOPE_GLOBAL: S = SymFind (RootTab, Name, SF_ALLOC_NEW); break;
- case SCOPE_LOCAL: S = SymFind (SymTab, Name, SF_ALLOC_NEW); break;
+ case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_ALLOC_NEW); break;
+ case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_ALLOC_NEW); break;
/* Others are not allowed */
case SCOPE_ANY:
SymEntry* S;
/* Don't accept local symbols */
- if (IsLocal (Name)) {
+ if (IsLocalName (Name)) {
Error (ERR_ILLEGAL_LOCAL_USE);
return;
}
/* Do we have such a symbol? */
- S = SymFind (SymTab, Name, SF_ALLOC_NEW);
+ S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
if (S->Flags & SF_DEFINED) {
Error (ERR_SYM_ALREADY_DEFINED, Name);
S->Flags |= SF_MULTDEF;
SymEntry* S;
/* Don't accept local symbols */
- if (IsLocal (Name)) {
+ if (IsLocalName (Name)) {
Error (ERR_ILLEGAL_LOCAL_USE);
return;
}
/* Do we have such a symbol? */
- S = SymFind (SymTab, Name, SF_ALLOC_NEW);
+ S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, Name);
SymEntry* S;
/* Don't accept local symbols */
- if (IsLocal (Name)) {
+ if (IsLocalName (Name)) {
Error (ERR_ILLEGAL_LOCAL_USE);
return;
}
/* Search for this symbol, create a new entry if needed */
- S = SymFind (SymTab, Name, SF_ALLOC_NEW);
+ S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
/* If the symbol is already marked as import or export, check the
* size of the definition, then bail out. */
CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
/* Don't accept local symbols */
- if (IsLocal (Name)) {
+ if (IsLocalName (Name)) {
Error (ERR_ILLEGAL_LOCAL_USE);
return;
}
/* Do we have such a symbol? */
- S = SymFind (SymTab, Name, SF_ALLOC_NEW);
+ S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, Name);
{
SymEntry* S = 0;
+ /* Get the string pool index for the name */
+ unsigned NameId = GetStringId (Name);
+
/* Search for the symbol */
switch (Scope) {
- case SCOPE_ANY: S = SymFindAny (SymTab, Name); break;
- case SCOPE_GLOBAL: S = SymFind (RootTab, Name, SF_FIND_EXISTING); break;
- case SCOPE_LOCAL: S = SymFind (SymTab, Name, SF_FIND_EXISTING); break;
+ case SCOPE_ANY: S = SymFindAny (SymTab, NameId); break;
+ case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_FIND_EXISTING); break;
+ case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_FIND_EXISTING); break;
default: Internal ("Invalid scope in SymIsDef: %d", Scope);
}
{
SymEntry* S = 0;
+ /* Get the string pool index for the name */
+ unsigned NameId = GetStringId (Name);
+
/* Search for the symbol */
switch (Scope) {
- case SCOPE_ANY: S = SymFindAny (SymTab, Name); break;
- case SCOPE_GLOBAL: S = SymFind (RootTab, Name, SF_FIND_EXISTING); break;
- case SCOPE_LOCAL: S = SymFind (SymTab, Name, SF_FIND_EXISTING); break;
+ case SCOPE_ANY: S = SymFindAny (SymTab, NameId); break;
+ case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_FIND_EXISTING); break;
+ case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_FIND_EXISTING); break;
default: Internal ("Invalid scope in SymIsRef: %d", Scope);
}
* enclosing scope for a symbol with the same name, and return the ZP
* attribute of this symbol if we find one.
*/
- if (!IsLocal (S->Name) &&
+ if (!IsLocalNameId (S->Name) &&
(S->Flags & (SF_ZP | SF_ABS | SF_DEFINED | SF_IMPORT)) == 0 &&
- S->SymTab->BackLink != 0) {
+ S->SymTab->Parent != 0) {
/* Try to find a symbol with the same name in the enclosing scope */
- SymEntry* E = SymFindAny (S->SymTab->BackLink, S->Name);
+ SymEntry* E = SymFindAny (S->SymTab->Parent, S->Name);
/* If we found one, use the ZP flag */
if (E && (E->Flags & SF_ZP) != 0) {
if (S->Flags & SF_TRAMPOLINE) {
S = S->V.Sym;
}
- return S->Name;
+ return GetString (S->Name);
}
SymEntry* Sym = 0;
if (S->SymTab) {
/* It's a global symbol, get the higher level table */
- SymTable* Tab = S->SymTab->BackLink;
+ SymTable* Tab = S->SymTab->Parent;
while (Tab) {
Sym = SymFindAny (Tab, S->Name);
if (Sym) {
break;
} else {
/* The symbol found is undefined itself. Look further */
- Tab = Sym->SymTab->BackLink;
+ Tab = Sym->SymTab->Parent;
}
} else {
/* No symbol found */
if (S->Flags & SF_EXPORT) {
if (Sym->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
- PError (&S->Pos, ERR_SYM_ALREADY_IMPORT, S->Name);
+ PError (&S->Pos, ERR_SYM_ALREADY_IMPORT, GetString (S->Name));
}
Sym->Flags |= S->Flags & (SF_EXPORT | SF_ZP);
}
/* The symbol is definitely undefined */
if (S->Flags & SF_EXPORT) {
/* We will not auto-import an export */
- PError (&S->Pos, ERR_EXPORT_UNDEFINED, S->Name);
+ PError (&S->Pos, ERR_EXPORT_UNDEFINED, GetString (S->Name));
} else {
if (AutoImport) {
/* Mark as import, will be indexed later */
S->Flags |= SF_IMPORT;
} else {
/* Error */
- PError (&S->Pos, ERR_SYM_UNDEFINED, S->Name);
+ PError (&S->Pos, ERR_SYM_UNDEFINED, GetString (S->Name));
}
}
}
SymEntry* S;
/* Check for open lexical levels */
- if (SymTab->BackLink != 0) {
+ if (SymTab->Parent != 0) {
Error (ERR_OPEN_PROC);
}
(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, WARN_SYM_NOT_REFERENCED, S->Name);
+ PWarning (&S->Pos, WARN_SYM_NOT_REFERENCED, 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, WARN_IMPORT_NOT_REFERENCED, S->Name);
+ PWarning (&S->Pos, WARN_IMPORT_NOT_REFERENCED, GetString (S->Name));
} else {
/* Give the import an index, count imports */
S->Index = ImportCount++;
if ((S->Flags & SF_TRAMPOLINE) != 0) {
fprintf (F,
"%-24s %s %s %s %s %s\n",
- S->Name,
+ GetString (S->Name),
(S->Flags & SF_DEFINED)? "DEF" : "---",
(S->Flags & SF_REFERENCED)? "REF" : "---",
(S->Flags & SF_IMPORT)? "IMP" : "---",
} else {
ObjWrite8 (IMP_ABS);
}
- ObjWriteVar (GetStringId (S->Name));
+ ObjWriteVar (S->Name);
ObjWritePos (&S->Pos);
}
S = S->List;
}
/* Write the name */
- ObjWriteVar (GetStringId (S->Name));
+ ObjWriteVar (S->Name);
/* Write the value */
if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
ObjWrite8 (ExprMask);
/* Write the name */
- ObjWriteVar (GetStringId (S->Name));
+ ObjWriteVar (S->Name);
/* Write the value */
if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
+
-void SymEnterLevel (void);
+void SymEnterLevel (const char* ScopeName);
/* Enter a new lexical level */
void SymLeaveLevel (void);