Revised symbol scoping

git-svn-id: svn://svn.cc65.org/cc65/trunk@2614 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-11-06 11:22:31 +00:00
parent 4a667ead00
commit 8400fb848a
13 changed files with 682 additions and 596 deletions

View file

@ -38,6 +38,7 @@
#include "expr.h" #include "expr.h"
#include "instr.h" #include "instr.h"
#include "nexttok.h" #include "nexttok.h"
#include "symbol.h"
#include "symtab.h" #include "symtab.h"
#include "condasm.h" #include "condasm.h"
@ -304,12 +305,8 @@ void DoConditionals (void)
D = AllocIf (".IFDEF", 1); D = AllocIf (".IFDEF", 1);
NextTok (); NextTok ();
if (IfCond) { if (IfCond) {
if (Tok != TOK_IDENT) { SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
ErrorSkip (ERR_IDENT_EXPECTED); SetIfCond (D, Sym != 0 && SymIsDef (Sym));
} else {
SetIfCond (D, SymIsDef (SVal, SCOPE_ANY));
NextTok ();
}
} }
IfCond = GetCurrentIfCond (); IfCond = GetCurrentIfCond ();
break; break;
@ -343,12 +340,8 @@ void DoConditionals (void)
D = AllocIf (".IFNDEF", 1); D = AllocIf (".IFNDEF", 1);
NextTok (); NextTok ();
if (IfCond) { if (IfCond) {
if (Tok != TOK_IDENT) { SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
ErrorSkip (ERR_IDENT_EXPECTED); SetIfCond (D, Sym == 0 || !SymIsDef (Sym));
} else {
SetIfCond (D, !SymIsDef (SVal, SCOPE_ANY));
NextTok ();
}
} }
IfCond = GetCurrentIfCond (); IfCond = GetCurrentIfCond ();
break; break;
@ -357,12 +350,8 @@ void DoConditionals (void)
D = AllocIf (".IFNREF", 1); D = AllocIf (".IFNREF", 1);
NextTok (); NextTok ();
if (IfCond) { if (IfCond) {
if (Tok != TOK_IDENT) { SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
ErrorSkip (ERR_IDENT_EXPECTED); SetIfCond (D, Sym == 0 || !SymIsRef (Sym));
} else {
SetIfCond (D, !SymIsRef (SVal, SCOPE_ANY));
NextTok ();
}
} }
IfCond = GetCurrentIfCond (); IfCond = GetCurrentIfCond ();
break; break;
@ -407,12 +396,8 @@ void DoConditionals (void)
D = AllocIf (".IFREF", 1); D = AllocIf (".IFREF", 1);
NextTok (); NextTok ();
if (IfCond) { if (IfCond) {
if (Tok != TOK_IDENT) { SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
ErrorSkip (ERR_IDENT_EXPECTED); SetIfCond (D, Sym != 0 && SymIsRef (Sym));
} else {
SetIfCond (D, SymIsRef (SVal, SCOPE_ANY));
NextTok ();
}
} }
IfCond = GetCurrentIfCond (); IfCond = GetCurrentIfCond ();
break; break;

View file

@ -51,9 +51,9 @@
#include "global.h" #include "global.h"
#include "instr.h" #include "instr.h"
#include "nexttok.h" #include "nexttok.h"
/* #include "objcode.h" */
#include "objfile.h" #include "objfile.h"
#include "segment.h" #include "segment.h"
#include "symbol.h"
#include "symtab.h" #include "symtab.h"
#include "toklist.h" #include "toklist.h"
#include "ulabel.h" #include "ulabel.h"
@ -113,7 +113,7 @@ static void FreeExprNode (ExprNode* E)
if (E) { if (E) {
if (E->Op == EXPR_SYMBOL) { if (E->Op == EXPR_SYMBOL) {
/* Remove the symbol reference */ /* Remove the symbol reference */
SymDelRef (E->V.Sym, E); SymDelExprRef (E->V.Sym, E);
} }
/* Place the symbol into the free nodes list if possible */ /* Place the symbol into the free nodes list if possible */
if (FreeNodeCount < MAX_FREE_NODES) { if (FreeNodeCount < MAX_FREE_NODES) {
@ -208,71 +208,11 @@ static int FuncConst (void)
static int FuncDefined (void) static int FuncDefined (void)
/* Handle the .DEFINED builtin function */ /* Handle the .DEFINED builtin function */
{ {
static const char* Keys[] = { /* Parse the symbol name and search for the symbol */
"ANY", SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
"GLOBAL",
"LOCAL",
};
char Name [sizeof (SVal)]; /* Check if the symbol is defined */
int Result = 0; return (Sym != 0 && SymIsDef (Sym));
int Scope;
/* First argument is a symbol name */
if (Tok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
if (Tok != TOK_RPAREN) {
NextTok ();
}
return 0;
}
/* Remember the name, then skip it */
strcpy (Name, SVal);
NextTok ();
/* Comma and scope spec may follow */
if (Tok == TOK_COMMA) {
/* Skip the comma */
NextTok ();
/* An identifier must follow */
if (Tok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
return 0;
}
/* Get the scope, then skip it */
Scope = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
NextTok ();
/* Check if we got a valid keyword */
if (Scope < 0) {
Error (ERR_ILLEGAL_SCOPE);
return 0;
}
/* Map the scope */
switch (Scope) {
case 0: Scope = SCOPE_ANY; break;
case 1: Scope = SCOPE_GLOBAL; break;
case 2: Scope = SCOPE_LOCAL; break;
default: Internal ("Invalid scope: %d", Scope);
}
} else {
/* Any scope */
Scope = SCOPE_ANY;
}
/* Search for the symbol */
Result = SymIsDef (SVal, Scope);
/* Done */
return Result;
} }
@ -377,20 +317,11 @@ static int FuncMatch (void)
static int FuncReferenced (void) static int FuncReferenced (void)
/* Handle the .REFERENCED builtin function */ /* Handle the .REFERENCED builtin function */
{ {
int Result = 0; /* Parse the symbol name and search for the symbol */
SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
if (Tok != TOK_IDENT) { /* Check if the symbol is referenced */
Error (ERR_IDENT_EXPECTED); return (Sym != 0 && SymIsRef (Sym));
if (Tok != TOK_RPAREN) {
NextTok ();
}
} else {
Result = SymIsRef (SVal, SCOPE_ANY);
NextTok ();
}
/* Done */
return Result;
} }
@ -553,36 +484,21 @@ static ExprNode* Factor (void)
NextTok (); NextTok ();
break; break;
case TOK_NAMESPACE: case TOK_NAMESPACE:
NextTok (); case TOK_IDENT:
if (Tok != TOK_IDENT) { /* Search for the symbol */
Error (ERR_IDENT_EXPECTED); S = ParseScopedSymName (SYM_ALLOC_NEW);
N = GenLiteralExpr (0); /* Dummy */ if (S == 0) {
/* Some weird error happened before */
N = GenLiteralExpr (0);
} else { } else {
S = SymRef (SVal, SCOPE_GLOBAL); /* Mark the symbol as referenced */
if (SymIsConst (S)) { SymRef (S);
/* Use the literal value instead */ /* Create symbol node */
N = GenLiteralExpr (GetSymVal (S)); N = GenSymExpr (S);
} else {
/* Create symbol node */
N = GenSymExpr (S);
}
NextTok ();
} }
break; break;
case TOK_IDENT:
S = SymRef (SVal, SCOPE_LOCAL);
if (SymIsConst (S)) {
/* Use the literal value instead */
N = GenLiteralExpr (GetSymVal (S));
} else {
/* Create symbol node */
N = GenSymExpr (S);
}
NextTok ();
break;
case TOK_ULABEL: case TOK_ULABEL:
N = ULabRef (IVal); N = ULabRef (IVal);
NextTok (); NextTok ();
@ -977,7 +893,7 @@ ExprNode* GenSymExpr (SymEntry* Sym)
{ {
ExprNode* Expr = NewExprNode (EXPR_SYMBOL); ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
Expr->V.Sym = Sym; Expr->V.Sym = Sym;
SymAddRef (Sym, Expr); SymAddExprRef (Sym, Expr);
return Expr; return Expr;
} }

View file

@ -76,7 +76,7 @@ static char MacLongBranch[] =
" .if .match(Target, 0)\n" " .if .match(Target, 0)\n"
" bne *+5\n" " bne *+5\n"
" jmp Target\n" " jmp Target\n"
" .elseif .def(Target,local) .and ((*+2)-(Target) <= 127)\n" " .elseif .def(Target) .and ((*+2)-(Target) <= 127)\n"
" beq Target\n" " beq Target\n"
" .else\n" " .else\n"
" bne *+5\n" " bne *+5\n"
@ -87,7 +87,7 @@ static char MacLongBranch[] =
" .if .match(Target, 0)\n" " .if .match(Target, 0)\n"
" beq *+5\n" " beq *+5\n"
" jmp Target\n" " jmp Target\n"
" .elseif .def(Target,local) .and ((*+2)-(Target) <= 127)\n" " .elseif .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bne Target\n" " bne Target\n"
" .else\n" " .else\n"
" beq *+5\n" " beq *+5\n"
@ -98,7 +98,7 @@ static char MacLongBranch[] =
" .if .match(Target, 0)\n" " .if .match(Target, 0)\n"
" bpl *+5\n" " bpl *+5\n"
" jmp Target\n" " jmp Target\n"
" .elseif .def(Target,local) .and ((*+2)-(Target) <= 127)\n" " .elseif .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bmi Target\n" " bmi Target\n"
" .else\n" " .else\n"
" bpl *+5\n" " bpl *+5\n"
@ -109,7 +109,7 @@ static char MacLongBranch[] =
" .if .match(Target, 0)\n" " .if .match(Target, 0)\n"
" bmi *+5\n" " bmi *+5\n"
" jmp Target\n" " jmp Target\n"
" .elseif .def(Target,local) .and ((*+2)-(Target) <= 127)\n" " .elseif .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bpl Target\n" " bpl Target\n"
" .else\n" " .else\n"
" bmi *+5\n" " bmi *+5\n"
@ -120,7 +120,7 @@ static char MacLongBranch[] =
" .if .match(Target, 0)\n" " .if .match(Target, 0)\n"
" bcc *+5\n" " bcc *+5\n"
" jmp Target\n" " jmp Target\n"
" .elseif .def(Target,local) .and ((*+2)-(Target) <= 127)\n" " .elseif .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bcs Target\n" " bcs Target\n"
" .else\n" " .else\n"
" bcc *+5\n" " bcc *+5\n"
@ -131,7 +131,7 @@ static char MacLongBranch[] =
" .if .match(Target, 0)\n" " .if .match(Target, 0)\n"
" bcs *+5\n" " bcs *+5\n"
" jmp Target\n" " jmp Target\n"
" .elseif .def(Target,local) .and ((*+2)-(Target) <= 127)\n" " .elseif .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bcc Target\n" " bcc Target\n"
" .else\n" " .else\n"
" bcs *+5\n" " bcs *+5\n"
@ -142,7 +142,7 @@ static char MacLongBranch[] =
" .if .match(Target, 0)\n" " .if .match(Target, 0)\n"
" bvc *+5\n" " bvc *+5\n"
" jmp Target\n" " jmp Target\n"
" .elseif .def(Target,local) .and ((*+2)-(Target) <= 127)\n" " .elseif .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bvs Target\n" " bvs Target\n"
" .else\n" " .else\n"
" bvc *+5\n" " bvc *+5\n"
@ -153,7 +153,7 @@ static char MacLongBranch[] =
" .if .match(Target, 0)\n" " .if .match(Target, 0)\n"
" bvs *+5\n" " bvs *+5\n"
" jmp Target\n" " jmp Target\n"
" .elseif .def(Target,local) .and ((*+2)-(Target) <= 127)\n" " .elseif .def(Target) .and ((*+2)-(Target) <= 127)\n"
" bvc Target\n" " bvc Target\n"
" .else\n" " .else\n"
" bvs *+5\n" " bvs *+5\n"

View file

@ -139,6 +139,8 @@ static void DefineSymbol (const char* Def)
unsigned I; unsigned I;
long Val; long Val;
char SymName [MAX_STR_LEN+1]; char SymName [MAX_STR_LEN+1];
SymEntry* Sym;
/* The symbol must start with a character or underline */ /* The symbol must start with a character or underline */
if (Def [0] != '_' && !IsAlpha (Def [0])) { if (Def [0] != '_' && !IsAlpha (Def [0])) {
@ -177,13 +179,16 @@ static void DefineSymbol (const char* Def)
} }
} }
/* Search for the symbol, allocate a new one if it doesn't exist */
Sym = SymFind (CurrentScope, SymName, SYM_ALLOC_NEW);
/* Check if have already a symbol with this name */ /* Check if have already a symbol with this name */
if (SymIsDef (SymName, SCOPE_ANY)) { if (SymIsDef (Sym)) {
AbEnd ("`%s' is already defined", SymName); AbEnd ("`%s' is already defined", SymName);
} }
/* Define the symbol */ /* Mark the symbol as defined */
SymDef (SymName, GenLiteralExpr (Val), SYM_DEFAULT); SymDef (Sym, GenLiteralExpr (Val), SYM_DEFAULT);
} }
@ -337,7 +342,6 @@ static void DoPCAssign (void)
static void OneLine (void) static void OneLine (void)
/* Assemble one line */ /* Assemble one line */
{ {
char Ident [MAX_STR_LEN+1];
int Done = 0; int Done = 0;
/* Initialize the new listing line if we are actually reading from file /* Initialize the new listing line if we are actually reading from file
@ -366,8 +370,10 @@ static void OneLine (void)
} else { } else {
/* No, label. Remember the identifier, then skip it */ /* No, label. Remember the identifier, then skip it */
int HadWS = WS; /* Did we have whitespace before the ident? */ int HadWS = WS; /* Did we have whitespace before the ident? */
strcpy (Ident, SVal);
/* Generate the symbol table entry, then skip the name */
SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
NextTok (); NextTok ();
/* If a colon follows, this is a label definition. If there /* If a colon follows, this is a label definition. If there
@ -379,14 +385,14 @@ static void OneLine (void)
/* Skip the '=' */ /* Skip the '=' */
NextTok (); NextTok ();
/* Define the symbol with the expression following the '=' */ /* Define the symbol with the expression following the '=' */
SymDef (Ident, Expression(), Flags); SymDef (Sym, Expression(), Flags);
/* Don't allow anything after a symbol definition */ /* Don't allow anything after a symbol definition */
Done = 1; Done = 1;
} else { } else {
/* Define the symbol flags */ /* Define the symbol flags */
unsigned Flags = IsZPSeg ()? SYM_ZP | SYM_LABEL : SYM_LABEL; unsigned Flags = IsZPSeg ()? SYM_ZP | SYM_LABEL : SYM_LABEL;
/* Define a label */ /* Define a label */
SymDef (Ident, GenCurrentPC (), Flags); SymDef (Sym, GenCurrentPC (), Flags);
/* Skip the colon. If NoColonLabels is enabled, allow labels /* Skip the colon. If NoColonLabels is enabled, allow labels
* without a colon if there is no whitespace before the * without a colon if there is no whitespace before the
* identifier. * identifier.
@ -519,7 +525,7 @@ int main (int argc, char* argv [])
/* Enter the base lexical level. We must do that here, since we may /* Enter the base lexical level. We must do that here, since we may
* define symbols using -D. * define symbols using -D.
*/ */
SymEnterLevel (0); SymEnterLevel ("");
/* Check the parameters */ /* Check the parameters */
I = 1; I = 1;

View file

@ -39,6 +39,7 @@ OBJS = anonname.o \
segment.o \ segment.o \
spool.o \ spool.o \
symentry.o \ symentry.o \
symbol.o \
symtab.o \ symtab.o \
toklist.o \ toklist.o \
ulabel.o ulabel.o

View file

@ -87,6 +87,7 @@ OBJS = anonname.obj \
scanner.obj \ scanner.obj \
segment.obj \ segment.obj \
spool.obj \ spool.obj \
symbol.obj \
symentry.obj \ symentry.obj \
symtab.obj \ symtab.obj \
toklist.obj \ toklist.obj \

View file

@ -663,11 +663,11 @@ static void DoEnd (void)
static void DoEndProc (void) static void DoEndProc (void)
/* Leave a lexical level */ /* Leave a lexical level */
{ {
if (!SymIsLocalLevel ()) { if (CurrentScope != RootScope) {
SymLeaveLevel ();
} else {
/* No local scope */ /* No local scope */
ErrorSkip (ERR_NO_OPEN_PROC); ErrorSkip (ERR_NO_OPEN_PROC);
} else {
SymLeaveLevel ();
} }
} }
@ -1245,11 +1245,12 @@ static void DoProc (void)
{ {
if (Tok == TOK_IDENT) { if (Tok == TOK_IDENT) {
/* The new scope has a name */ /* The new scope has a name */
SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
unsigned Flags = SYM_LABEL; unsigned Flags = SYM_LABEL;
if (IsZPSeg ()) { if (IsZPSeg ()) {
Flags |= SYM_ZP; Flags |= SYM_ZP;
} }
SymDef (SVal, GenCurrentPC (), Flags); SymDef (Sym, GenCurrentPC (), Flags);
SymEnterLevel (SVal); SymEnterLevel (SVal);
NextTok (); NextTok ();
} else { } else {

113
src/ca65/symbol.c Normal file
View file

@ -0,0 +1,113 @@
/*****************************************************************************/
/* */
/* symbol.c */
/* */
/* Parse a symbol name and search for it */
/* */
/* */
/* */
/* (C) 1998-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 <string.h>
/* ca65 */
#include "error.h"
#include "nexttok.h"
#include "scanner.h"
#include "symbol.h"
#include "symtab.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/*****************************************************************************/
/* Code */
/*****************************************************************************/
SymEntry* ParseScopedSymName (int AllocNew)
/* Parse a (possibly scoped) symbol name, search for it in the symbol table
* and return the symbol table entry.
*/
{
/* Get the starting table */
SymTable* Scope;
if (Tok == TOK_NAMESPACE) {
Scope = RootScope;
NextTok ();
} else {
Scope = CurrentScope;
}
/* Resolve scopes */
while (1) {
/* An identifier must follow. Remember and skip it. */
char Name[sizeof (SVal)];
if (Tok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
return 0;
}
strcpy (Name, SVal);
NextTok ();
/* If the next token is a namespace token, handle the name as the
* name of a scope, otherwise it's the name of a symbol in that
* scope.
*/
if (Tok == TOK_NAMESPACE) {
/* Search for the child scope */
Scope = SymFindScope (Scope, Name, AllocNew);
/* Skip the namespace token */
NextTok ();
/* If we didn't find the scope, bail out */
if (Scope == 0) {
return 0;
}
} else {
/* Search for the symbol and return it */
return SymFind (Scope, Name, AllocNew);
}
}
}

65
src/ca65/symbol.h Normal file
View file

@ -0,0 +1,65 @@
/*****************************************************************************/
/* */
/* symbol.h */
/* */
/* Parse a symbol name and search for it */
/* */
/* */
/* */
/* (C) 1998-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 SYMBOL_H
#define SYMBOL_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/*****************************************************************************/
/* Code */
/*****************************************************************************/
struct SymEntry* ParseScopedSymName (int AllowNew);
/* Parse a (possibly scoped) symbol name, search for it in the symbol table
* and return the symbol table entry.
*/
/* End of symbol.h */
#endif

View file

@ -39,7 +39,11 @@
#include "xmalloc.h" #include "xmalloc.h"
/* ca65 */ /* ca65 */
#include "error.h"
#include "expr.h"
#include "global.h"
#include "scanner.h" #include "scanner.h"
#include "spool.h"
#include "symentry.h" #include "symentry.h"
@ -50,7 +54,11 @@
SymEntry* SymList = 0; /* List of all symbol table entries */ /* List of all symbol table entries */
SymEntry* SymList = 0;
/* Pointer to last defined symbol */
SymEntry* SymLast = 0;
@ -60,7 +68,23 @@ SymEntry* SymList = 0; /* List of all symbol table entries */
SymEntry* NewSymEntry (unsigned Name) int IsLocalName (const char* Name)
/* Return true if Name is the name of a local symbol */
{
return (*Name == LocalStart);
}
int IsLocalNameId (unsigned Name)
/* Return true if Name is the name of a local symbol */
{
return (*GetString (Name) == LocalStart);
}
SymEntry* NewSymEntry (const char* Name)
/* Allocate a symbol table entry, initialize and return it */ /* Allocate a symbol table entry, initialize and return it */
{ {
/* Allocate memory */ /* Allocate memory */
@ -76,7 +100,7 @@ SymEntry* NewSymEntry (unsigned Name)
S->V.Expr = 0; S->V.Expr = 0;
S->ExprRefs = AUTO_COLLECTION_INITIALIZER; S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio)); memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
S->Name = Name; S->Name = GetStringId (Name);
/* Insert it into the list of all entries */ /* Insert it into the list of all entries */
S->List = SymList; S->List = SymList;
@ -87,4 +111,234 @@ SymEntry* NewSymEntry (unsigned Name)
} }
void SymRef (SymEntry* S)
/* Mark the given symbol as referenced */
{
/* Mark the symbol as referenced */
S->Flags |= SF_REFERENCED;
}
void SymDef (SymEntry* S, ExprNode* Expr, unsigned Flags)
/* Define a new symbol */
{
if (S->Flags & SF_IMPORT) {
/* Defined symbol is marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, GetSymName (S));
return;
}
if (S->Flags & SF_DEFINED) {
/* Multiple definition */
Error (ERR_SYM_ALREADY_DEFINED, GetSymName (S));
S->Flags |= SF_MULTDEF;
return;
}
/* Set the symbol data */
if (IsConstExpr (Expr)) {
/* Expression is const, store the value */
S->Flags |= SF_CONST;
S->V.Val = GetExprVal (Expr);
FreeExpr (Expr);
} else {
/* Not const, store the expression */
S->V.Expr = Expr;
}
S->Flags |= SF_DEFINED;
if (Flags & SYM_ZP) {
S->Flags |= SF_ZP;
}
if (Flags & SYM_LABEL) {
S->Flags |= SF_LABEL;
}
/* If the symbol is a ZP symbol, check if the value is in correct range */
if (S->Flags & SF_ZP) {
/* Already marked as ZP symbol by some means */
if (!IsByteExpr (Expr)) {
Error (ERR_RANGE);
}
}
/* If this is not a local symbol, remember it as the last global one */
if (!IsLocalNameId (S->Name)) {
SymLast = S;
}
}
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 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) != 0 &&
(S->Flags & SF_IMPORT) == 0 &&
(S->Flags & SF_CONST) == 0);
}
void SymFinalize (SymEntry* S)
/* Finalize a symbol expression if there is one */
{
/* Resolve trampoline entries */
if (S->Flags & SF_TRAMPOLINE) {
S = S->V.Sym;
}
/* Check if we have an expression */
if ((S->Flags & SF_FINALIZED) == 0 && SymHasExpr (S)) {
S->V.Expr = FinalizeExpr (S->V.Expr);
S->Flags |= SF_FINALIZED;
}
}
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;
}
long GetSymVal (SymEntry* S)
/* Return the symbol value */
{
/* Resolve trampoline entries */
if (S->Flags & SF_TRAMPOLINE) {
S = S->V.Sym;
}
PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0);
return S->V.Val;
}
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 && (S->Flags & SF_CONST) == 0);
return S->V.Expr;
}
const char* GetSymName (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 GetSymIndex (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));
return S->Index;
}
const FilePos* GetSymPos (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;
}

View file

@ -69,6 +69,15 @@
#define SF_DEFINED 0x4000 /* Defined */ #define SF_DEFINED 0x4000 /* Defined */
#define SF_REFERENCED 0x8000 /* Referenced */ #define SF_REFERENCED 0x8000 /* Referenced */
/* Flags used in SymDef */
#define SYM_DEFAULT 0x00
#define SYM_ZP 0x01
#define SYM_LABEL 0x02
/* Arguments for SymFind... */
#define SYM_FIND_EXISTING 0
#define SYM_ALLOC_NEW 1
/* Structure of a symbol table entry */ /* Structure of a symbol table entry */
typedef struct SymEntry SymEntry; typedef struct SymEntry SymEntry;
struct SymEntry { struct SymEntry {
@ -94,37 +103,92 @@ struct SymEntry {
/* List of all symbol table entries */ /* List of all symbol table entries */
extern SymEntry* SymList; extern SymEntry* SymList;
/* Pointer to last defined symbol */
extern SymEntry* SymLast;
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
SymEntry* NewSymEntry (unsigned Name); int IsLocalName (const char* Name);
/* Return true if Name is the name of a local symbol */
int IsLocalNameId (unsigned Name);
/* Return true if Name is the name of a local symbol */
SymEntry* NewSymEntry (const char* Name);
/* Allocate a symbol table entry, initialize and return it */ /* Allocate a symbol table entry, initialize and return it */
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE void SymAddRef (SymEntry* Sym, struct ExprNode* Expr) INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Add a reference to this symbol */ /* Add an expression reference to this symbol */
{ {
CollAppend (&Sym->ExprRefs, Expr); CollAppend (&Sym->ExprRefs, Expr);
} }
#else #else
#define SymAddRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr) #define SymAddExprRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr)
#endif #endif
#if defined(HAVE_INLINE) #if defined(HAVE_INLINE)
INLINE void SymDelRef (SymEntry* Sym, struct ExprNode* Expr) INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Delete a reference to this symbol */ /* Delete an expression reference to this symbol */
{ {
CollDeleteItem (&Sym->ExprRefs, Expr); CollDeleteItem (&Sym->ExprRefs, Expr);
} }
#else #else
#define SymDelRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr) #define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#endif #endif
void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned Flags);
/* Mark a symbol as defined */
void SymRef (SymEntry* Sym);
/* Mark the given symbol as referenced */
int SymIsDef (const SymEntry* Sym);
/* Return true if the given symbol is already defined */
int SymIsRef (const SymEntry* Sym);
/* Return true if the given symbol has been referenced */
int SymIsImport (const SymEntry* Sym);
/* Return true if the given symbol is marked as import */
int SymHasExpr (const SymEntry* Sym);
/* Return true if the given symbol has an associated expression */
void SymFinalize (SymEntry* S);
/* Finalize a symbol expression if there is one */
void SymMarkUser (SymEntry* Sym);
/* Set a user mark on the specified symbol */
void SymUnmarkUser (SymEntry* Sym);
/* Remove a user mark from the specified symbol */
int SymHasUserMark (SymEntry* Sym);
/* Return the state of the user mark for the specified symbol */
long GetSymVal (SymEntry* Sym);
/* Return the symbol value */
struct ExprNode* GetSymExpr (SymEntry* Sym);
/* Get the expression for a non-const symbol */
const char* GetSymName (SymEntry* Sym);
/* Return the name of the symbol */
unsigned GetSymIndex (SymEntry* Sym);
/* Return the symbol index for the given symbol */
const FilePos* GetSymPos (SymEntry* Sym);
/* Return the position of first occurence in the source for the given symbol */
/* End of symentry.h */ /* End of symentry.h */

View file

@ -66,30 +66,11 @@
#define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT) #define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT)
#define SF_DBGINFOVAL (SF_DEFINED) #define SF_DBGINFOVAL (SF_DEFINED)
/* Definitions for the hash table */ /* Symbol tables */
#define MAIN_HASHTAB_SIZE 213 SymTable* CurrentScope = 0; /* Pointer to current symbol table */
#define SUB_HASHTAB_SIZE 53 SymTable* RootScope = 0; /* Root symbol table */
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 */
unsigned Name; /* Name of the scope */
SymEntry* Table [1]; /* Dynamic allocation */
};
/* Arguments for SymFind */
#define SF_FIND_EXISTING 0
#define SF_ALLOC_NEW 1
/* Symbol table variables */ /* Symbol table variables */
static SymEntry* SymLast = 0; /* Pointer to last defined symbol */
static SymTable* SymTab = 0; /* Pointer to current symbol table */
static SymTable* RootTab = 0; /* Root symbol table */
static unsigned ImportCount = 0;/* Counter for import symbols */ static unsigned ImportCount = 0;/* Counter for import symbols */
static unsigned ExportCount = 0;/* Counter for export symbols */ static unsigned ExportCount = 0;/* Counter for export symbols */
@ -101,22 +82,6 @@ static unsigned ExportCount = 0;/* Counter for export symbols */
static int IsLocalName (const char* Name)
/* Return true if Name is the name of a local symbol */
{
return (*Name == LocalStart);
}
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) static unsigned SymTableSize (unsigned Level)
/* Get the size of a table for the given lexical level */ /* Get the size of a table for the given lexical level */
{ {
@ -129,7 +94,7 @@ static unsigned SymTableSize (unsigned Level)
static SymTable* NewSymTable (SymTable* Parent, unsigned Name) static SymTable* NewSymTable (SymTable* Parent, const char* Name)
/* Allocate a symbol table on the heap and return it */ /* Allocate a symbol table on the heap and return it */
{ {
/* Determine the lexical level and the number of table slots */ /* Determine the lexical level and the number of table slots */
@ -147,7 +112,7 @@ static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
S->TableSlots = Slots; S->TableSlots = Slots;
S->TableEntries = 0; S->TableEntries = 0;
S->Parent = Parent; S->Parent = Parent;
S->Name = Name; S->Name = GetStringId (Name);
while (Slots--) { while (Slots--) {
S->Table[Slots] = 0; S->Table[Slots] = 0;
} }
@ -161,14 +126,15 @@ static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
} else { } else {
while (1) { while (1) {
/* Choose next entry */ /* Choose next entry */
if (S->Name < T->Name) { int Cmp = strcmp (Name, GetString (T->Name));
if (Cmp < 0) {
if (T->Left) { if (T->Left) {
T = T->Left; T = T->Left;
} else { } else {
T->Left = S; T->Left = S;
break; break;
} }
} else if (S->Name > T->Name) { } else if (Cmp > 0) {
if (T->Right) { if (T->Right) {
T = T->Right; T = T->Right;
} else { } else {
@ -177,13 +143,13 @@ static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
} }
} else { } else {
/* Duplicate scope name */ /* Duplicate scope name */
Internal ("Duplicate scope name: `%s'", GetString (S->Name)); Internal ("Duplicate scope name: `%s'", Name);
} }
} }
} }
} else { } else {
/* This is the root table */ /* This is the root table */
RootTab = S; RootScope = S;
} }
/* Return the prepared struct */ /* Return the prepared struct */
@ -192,7 +158,7 @@ static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
static int SearchSymTree (SymEntry* T, unsigned Name, SymEntry** E) static int SearchSymTree (SymEntry* T, const char* Name, SymEntry** E)
/* Search in the given tree for a name. If we find the symbol, the function /* 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 * 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, * symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
@ -201,8 +167,6 @@ static int SearchSymTree (SymEntry* T, unsigned Name, SymEntry** E)
* inserted on the right side. * inserted on the right side.
*/ */
{ {
int Cmp;
/* Is there a tree? */ /* Is there a tree? */
if (T == 0) { if (T == 0) {
*E = 0; *E = 0;
@ -211,17 +175,15 @@ static int SearchSymTree (SymEntry* T, unsigned Name, SymEntry** E)
/* We have a table, search it */ /* We have a table, search it */
while (1) { while (1) {
/* Get the symbol name */
const char* SymName = GetString (T->Name);
/* Choose next entry */ /* Choose next entry */
if (Name < T->Name) { int Cmp = strcmp (Name, SymName);
Cmp = -1; if (Cmp < 0 && T->Left) {
} else if (Name > T->Name) {
Cmp = +1;
} else {
Cmp = 0;
}
if (Name < T->Name && T->Left) {
T = T->Left; T = T->Left;
} else if (Name > T->Name && T->Right) { } else if (Cmp > 0&& T->Right) {
T = T->Right; T = T->Right;
} else { } else {
/* Found or end of search, return the result */ /* Found or end of search, return the result */
@ -234,12 +196,58 @@ static int SearchSymTree (SymEntry* T, unsigned Name, SymEntry** E)
/*****************************************************************************/ /*****************************************************************************/
/* Code */ /* Code */
/*****************************************************************************/ /*****************************************************************************/
static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew) void SymEnterLevel (const char* ScopeName)
/* Enter a new lexical level */
{
/* ### Check existing scope */
/* Create the new table */
CurrentScope = NewSymTable (CurrentScope, ScopeName);
}
void SymLeaveLevel (void)
/* Leave the current lexical level */
{
CurrentScope = CurrentScope->Parent;
}
SymTable* SymFindScope (SymTable* Parent, const char* Name, unsigned Flags)
/* Find a scope in the given enclosing scope */
{
SymTable** T = &Parent->Childs;
while (*T) {
int Cmp = strcmp (Name, GetString ((*T)->Name));
if (Cmp < 0) {
T = &(*T)->Left;
} else if (Cmp > 0) {
T = &(*T)->Right;
} else {
/* Found the scope */
return *T;
}
}
/* Create a new scope if requested and we didn't find one */
if (*T == 0 && Flags == SYM_ALLOC_NEW) {
*T = NewSymTable (Parent, Name);
}
/* Return the scope */
return *T;
}
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
/* Find a new symbol table entry in the given table. If AllocNew is given and /* 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 * 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. * new entry created, or - in case AllocNew is zero - return 0.
@ -247,18 +255,17 @@ static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
{ {
SymEntry* S; SymEntry* S;
int Cmp; int Cmp;
unsigned Hash;
if (IsLocalNameId (Name)) { if (IsLocalName (Name)) {
/* Local symbol, get the table */ /* Local symbol, get the table */
if (!SymLast) { if (!SymLast) {
/* No last global, so there's no local table */ /* No last global, so there's no local table */
Error (ERR_ILLEGAL_LOCAL_USE); Error (ERR_ILLEGAL_LOCAL_USE);
if (AllocNew) { if (AllocNew) {
return NewSymEntry (Name); return NewSymEntry (Name);
} else { } else {
return 0; return 0;
} }
} }
@ -287,10 +294,10 @@ static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
} else { } else {
/* Global symbol: Get the hash value for the name */ /* Global symbol: Get the hash value for the name */
Hash = Name % Tab->TableSlots; unsigned Hash = HashStr (Name) % Scope->TableSlots;
/* Search for the entry */ /* Search for the entry */
Cmp = SearchSymTree (Tab->Table[Hash], Name, &S); Cmp = SearchSymTree (Scope->Table[Hash], Name, &S);
/* If we found an entry, return it */ /* If we found an entry, return it */
if (Cmp == 0) { if (Cmp == 0) {
@ -308,14 +315,14 @@ static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
/* Otherwise create a new entry, insert and return it */ /* Otherwise create a new entry, insert and return it */
SymEntry* N = NewSymEntry (Name); SymEntry* N = NewSymEntry (Name);
if (S == 0) { if (S == 0) {
Tab->Table[Hash] = N; Scope->Table[Hash] = N;
} else if (Cmp < 0) { } else if (Cmp < 0) {
S->Left = N; S->Left = N;
} else { } else {
S->Right = N; S->Right = N;
} }
N->SymTab = Tab; N->SymTab = Scope;
++Tab->TableEntries; ++Scope->TableEntries;
return N; return N;
} }
@ -327,21 +334,24 @@ static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
static SymEntry* SymFindAny (SymTable* Tab, unsigned Name) static SymEntry* SymFindAny (SymTable* Scope, const char* Name)
/* Find a symbol in any table */ /* Find a symbol in the given or any of its parent scopes. The function will
* never create a new symbol, since this can only be done in one specific
* scope.
*/
{ {
SymEntry* Sym; SymEntry* Sym;
do { do {
/* Search in the current table */ /* Search in the current table */
Sym = SymFind (Tab, Name, SF_FIND_EXISTING); Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
if (Sym) { if (Sym) {
/* Found, return it */ /* Found, return it */
return Sym; return Sym;
} else { } else {
/* Not found, search in the parent scope, if we have one */ /* Not found, search in the parent scope, if we have one */
Tab = Tab->Parent; Scope = Scope->Parent;
} }
} while (Sym == 0 && Tab != 0); } while (Sym == 0 && Scope != 0);
/* Not found */ /* Not found */
return 0; return 0;
@ -349,114 +359,6 @@ static SymEntry* SymFindAny (SymTable* Tab, unsigned Name)
void SymEnterLevel (const char* ScopeName)
/* Enter a new lexical level */
{
/* 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->Parent;
}
int SymIsLocalLevel (void)
/* Return true if we are on a local symbol table level. */
{
return (SymTab != RootTab);
}
void SymDef (const char* Name, ExprNode* Expr, unsigned Flags)
/* Define a new symbol */
{
/* Do we have such a symbol? */
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);
return;
}
if (S->Flags & SF_DEFINED) {
/* Multiple definition */
Error (ERR_SYM_ALREADY_DEFINED, Name);
S->Flags |= SF_MULTDEF;
return;
}
/* Set the symbol data */
if (IsConstExpr (Expr)) {
/* Expression is const, store the value */
S->Flags |= SF_CONST;
S->V.Val = GetExprVal (Expr);
FreeExpr (Expr);
} else {
/* Not const, store the expression */
S->V.Expr = Expr;
}
S->Flags |= SF_DEFINED;
if (Flags & SYM_ZP) {
S->Flags |= SF_ZP;
}
if (Flags & SYM_LABEL) {
S->Flags |= SF_LABEL;
}
/* If the symbol is a ZP symbol, check if the value is in correct range */
if (S->Flags & SF_ZP) {
/* Already marked as ZP symbol by some means */
if (!IsByteExpr (Expr)) {
Error (ERR_RANGE);
}
}
/* If this is not a local symbol, remember it as the last global one */
if (!IsLocalName (Name)) {
SymLast = S;
}
}
SymEntry* SymRef (const char* Name, int Scope)
/* Search for the symbol and return it */
{
SymEntry* S;
unsigned NameId = GetStringId (Name);
switch (Scope) {
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:
default:
Internal ("Invalid scope in SymRef: %d", Scope);
/* NOTREACHED */
S = 0;
}
/* Mark the symbol as referenced */
S->Flags |= SF_REFERENCED;
/* Return it */
return S;
}
static void SymImportInternal (const char* Name, unsigned Flags) static void SymImportInternal (const char* Name, unsigned Flags)
/* Mark the given symbol as an imported symbol */ /* Mark the given symbol as an imported symbol */
{ {
@ -469,7 +371,7 @@ static void SymImportInternal (const char* Name, unsigned Flags)
} }
/* Do we have such a symbol? */ /* Do we have such a symbol? */
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW); S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
if (S->Flags & SF_DEFINED) { if (S->Flags & SF_DEFINED) {
Error (ERR_SYM_ALREADY_DEFINED, Name); Error (ERR_SYM_ALREADY_DEFINED, Name);
S->Flags |= SF_MULTDEF; S->Flags |= SF_MULTDEF;
@ -533,7 +435,7 @@ static void SymExportInternal (const char* Name, unsigned Flags)
} }
/* Do we have such a symbol? */ /* Do we have such a symbol? */
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW); S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
if (S->Flags & SF_IMPORT) { if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */ /* The symbol is already marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, Name); Error (ERR_SYM_ALREADY_IMPORT, Name);
@ -586,7 +488,7 @@ static void SymGlobalInternal (const char* Name, unsigned Flags)
} }
/* Search for this symbol, create a new entry if needed */ /* Search for this symbol, create a new entry if needed */
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW); S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
/* If the symbol is already marked as import or export, check the /* If the symbol is already marked as import or export, check the
* size of the definition, then bail out. */ * size of the definition, then bail out. */
@ -645,7 +547,7 @@ void SymConDes (const char* Name, unsigned Type, unsigned Prio)
} }
/* Do we have such a symbol? */ /* Do we have such a symbol? */
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW); S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
if (S->Flags & SF_IMPORT) { if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */ /* The symbol is already marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, Name); Error (ERR_SYM_ALREADY_IMPORT, Name);
@ -678,50 +580,6 @@ void SymConDes (const char* Name, unsigned Type, unsigned Prio)
int SymIsDef (const char* Name, int Scope)
/* Return true if the given symbol is already defined */
{
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, 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);
}
/* Check if it's defined */
return S != 0 && (S->Flags & SF_DEFINED) != 0;
}
int SymIsRef (const char* Name, int Scope)
/* Return true if the given symbol has been referenced */
{
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, 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);
}
/* Check if it's defined */
return S != 0 && (S->Flags & SF_REFERENCED) != 0;
}
int SymIsConst (SymEntry* S) int SymIsConst (SymEntry* S)
/* Return true if the given symbol has a constant value */ /* Return true if the given symbol has a constant value */
{ {
@ -763,7 +621,7 @@ int SymIsZP (SymEntry* S)
S->SymTab->Parent != 0) { S->SymTab->Parent != 0) {
/* Try to find a symbol with the same name in the enclosing scope */ /* Try to find a symbol with the same name in the enclosing scope */
SymEntry* E = SymFindAny (S->SymTab->Parent, S->Name); SymEntry* E = SymFindAny (S->SymTab->Parent, GetString (S->Name));
/* If we found one, use the ZP flag */ /* If we found one, use the ZP flag */
if (E && (E->Flags & SF_ZP) != 0) { if (E && (E->Flags & SF_ZP) != 0) {
@ -777,161 +635,6 @@ int SymIsZP (SymEntry* S)
int SymIsImport (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 SymHasExpr (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) != 0 &&
(S->Flags & SF_IMPORT) == 0 &&
(S->Flags & SF_CONST) == 0);
}
void SymFinalize (SymEntry* S)
/* Finalize a symbol expression if there is one */
{
/* Resolve trampoline entries */
if (S->Flags & SF_TRAMPOLINE) {
S = S->V.Sym;
}
/* Check if we have an expression */
if ((S->Flags & SF_FINALIZED) == 0 && SymHasExpr (S)) {
S->V.Expr = FinalizeExpr (S->V.Expr);
S->Flags |= SF_FINALIZED;
}
}
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;
}
long GetSymVal (SymEntry* S)
/* Return the symbol value */
{
/* Resolve trampoline entries */
if (S->Flags & SF_TRAMPOLINE) {
S = S->V.Sym;
}
PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0);
return S->V.Val;
}
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 && (S->Flags & SF_CONST) == 0);
return S->V.Expr;
}
const char* GetSymName (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 GetSymIndex (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));
return S->Index;
}
const FilePos* GetSymPos (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;
}
static void SymCheckUndefined (SymEntry* S) static void SymCheckUndefined (SymEntry* S)
/* Handle an undefined symbol */ /* Handle an undefined symbol */
{ {
@ -950,7 +653,7 @@ static void SymCheckUndefined (SymEntry* S)
/* It's a global symbol, get the higher level table */ /* It's a global symbol, get the higher level table */
SymTable* Tab = S->SymTab->Parent; SymTable* Tab = S->SymTab->Parent;
while (Tab) { while (Tab) {
Sym = SymFindAny (Tab, S->Name); Sym = SymFindAny (Tab, GetString (S->Name));
if (Sym) { if (Sym) {
if (Sym->Flags & (SF_DEFINED | SF_IMPORT)) { if (Sym->Flags & (SF_DEFINED | SF_IMPORT)) {
/* We've found a symbol in a higher level that is /* We've found a symbol in a higher level that is
@ -1014,7 +717,7 @@ void SymCheck (void)
SymEntry* S; SymEntry* S;
/* Check for open lexical levels */ /* Check for open lexical levels */
if (SymTab->Parent != 0) { if (CurrentScope->Parent != 0) {
Error (ERR_OPEN_PROC); Error (ERR_OPEN_PROC);
} }

View file

@ -59,10 +59,23 @@
#define SCOPE_GLOBAL 1 #define SCOPE_GLOBAL 1
#define SCOPE_LOCAL 2 #define SCOPE_LOCAL 2
/* Flags used in SymDef */ /* A symbol table */
#define SYM_DEFAULT 0x00 typedef struct SymTable SymTable;
#define SYM_ZP 0x01 struct SymTable {
#define SYM_LABEL 0x02 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 */
unsigned Name; /* Name of the scope */
SymEntry* Table[1]; /* Dynamic allocation */
};
/* Symbol tables */
SymTable* CurrentScope; /* Pointer to current symbol table */
SymTable* RootScope; /* Root symbol table */
@ -78,20 +91,14 @@ void SymEnterLevel (const char* ScopeName);
void SymLeaveLevel (void); void SymLeaveLevel (void);
/* Leave the current lexical level */ /* Leave the current lexical level */
int SymIsLocalLevel (void); SymTable* SymFindScope (SymTable* Parent, const char* Name, unsigned Flags);
/* Return true if we are on a local symbol table level. */ /* Find a scope in the given enclosing scope */
void SymDef (const char* Name, ExprNode* Expr, unsigned Flags); SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew);
/* Define a new symbol */ /* 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
SymEntry* SymRef (const char* Name, int Scope); * new entry created, or - in case AllocNew is zero - return 0.
/* Search for the symbol and return it */ */
int SymIsDef (const char* Name, int Scope);
/* Return true if the given symbol is already defined */
int SymIsRef (const char* Name, int Scope);
/* Return true if the given symbol has been referenced */
void SymImport (const char* Name); void SymImport (const char* Name);
/* Mark the given symbol as an imported symbol */ /* Mark the given symbol as an imported symbol */
@ -129,36 +136,6 @@ int SymIsConst (SymEntry* Sym);
int SymIsZP (SymEntry* Sym); int SymIsZP (SymEntry* Sym);
/* Return true if the symbol is explicitly marked as zeropage symbol */ /* Return true if the symbol is explicitly marked as zeropage symbol */
int SymIsImport (SymEntry* Sym);
/* Return true if the given symbol is marked as import */
int SymHasExpr (SymEntry* Sym);
/* Return true if the given symbol has an associated expression */
void SymMarkUser (SymEntry* Sym);
/* Set a user mark on the specified symbol */
void SymUnmarkUser (SymEntry* Sym);
/* Remove a user mark from the specified symbol */
int SymHasUserMark (SymEntry* Sym);
/* Return the state of the user mark for the specified symbol */
long GetSymVal (SymEntry* Sym);
/* Return the symbol value */
ExprNode* GetSymExpr (SymEntry* Sym);
/* Get the expression for a non-const symbol */
const char* GetSymName (SymEntry* Sym);
/* Return the name of the symbol */
unsigned GetSymIndex (SymEntry* Sym);
/* Return the symbol index for the given symbol */
const FilePos* GetSymPos (SymEntry* Sym);
/* Return the position of first occurence in the source for the given symbol */
void SymCheck (void); void SymCheck (void);
/* Run through all symbols and check for anomalies and errors */ /* Run through all symbols and check for anomalies and errors */