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

View file

@ -51,9 +51,9 @@
#include "global.h"
#include "instr.h"
#include "nexttok.h"
/* #include "objcode.h" */
#include "objfile.h"
#include "segment.h"
#include "symbol.h"
#include "symtab.h"
#include "toklist.h"
#include "ulabel.h"
@ -113,7 +113,7 @@ static void FreeExprNode (ExprNode* E)
if (E) {
if (E->Op == EXPR_SYMBOL) {
/* Remove the symbol reference */
SymDelRef (E->V.Sym, E);
SymDelExprRef (E->V.Sym, E);
}
/* Place the symbol into the free nodes list if possible */
if (FreeNodeCount < MAX_FREE_NODES) {
@ -208,71 +208,11 @@ static int FuncConst (void)
static int FuncDefined (void)
/* Handle the .DEFINED builtin function */
{
static const char* Keys[] = {
"ANY",
"GLOBAL",
"LOCAL",
};
/* Parse the symbol name and search for the symbol */
SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING);
char Name [sizeof (SVal)];
int Result = 0;
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;
/* Check if the symbol is defined */
return (Sym != 0 && SymIsDef (Sym));
}
@ -377,20 +317,11 @@ static int FuncMatch (void)
static int FuncReferenced (void)
/* 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) {
Error (ERR_IDENT_EXPECTED);
if (Tok != TOK_RPAREN) {
NextTok ();
}
} else {
Result = SymIsRef (SVal, SCOPE_ANY);
NextTok ();
}
/* Done */
return Result;
/* Check if the symbol is referenced */
return (Sym != 0 && SymIsRef (Sym));
}
@ -553,36 +484,21 @@ static ExprNode* Factor (void)
NextTok ();
break;
case TOK_NAMESPACE:
NextTok ();
if (Tok != TOK_IDENT) {
Error (ERR_IDENT_EXPECTED);
N = GenLiteralExpr (0); /* Dummy */
case TOK_NAMESPACE:
case TOK_IDENT:
/* Search for the symbol */
S = ParseScopedSymName (SYM_ALLOC_NEW);
if (S == 0) {
/* Some weird error happened before */
N = GenLiteralExpr (0);
} else {
S = SymRef (SVal, SCOPE_GLOBAL);
if (SymIsConst (S)) {
/* Use the literal value instead */
N = GenLiteralExpr (GetSymVal (S));
} else {
/* Create symbol node */
N = GenSymExpr (S);
}
NextTok ();
/* Mark the symbol as referenced */
SymRef (S);
/* Create symbol node */
N = GenSymExpr (S);
}
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:
N = ULabRef (IVal);
NextTok ();
@ -977,7 +893,7 @@ ExprNode* GenSymExpr (SymEntry* Sym)
{
ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
Expr->V.Sym = Sym;
SymAddRef (Sym, Expr);
SymAddExprRef (Sym, Expr);
return Expr;
}

View file

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

View file

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

View file

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

View file

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

View file

@ -663,11 +663,11 @@ static void DoEnd (void)
static void DoEndProc (void)
/* Leave a lexical level */
{
if (!SymIsLocalLevel ()) {
if (CurrentScope != RootScope) {
SymLeaveLevel ();
} else {
/* No local scope */
ErrorSkip (ERR_NO_OPEN_PROC);
} else {
SymLeaveLevel ();
}
}
@ -1245,11 +1245,12 @@ static void DoProc (void)
{
if (Tok == TOK_IDENT) {
/* The new scope has a name */
SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
unsigned Flags = SYM_LABEL;
if (IsZPSeg ()) {
Flags |= SYM_ZP;
}
SymDef (SVal, GenCurrentPC (), Flags);
SymDef (Sym, GenCurrentPC (), Flags);
SymEnterLevel (SVal);
NextTok ();
} 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"
/* ca65 */
#include "error.h"
#include "expr.h"
#include "global.h"
#include "scanner.h"
#include "spool.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 memory */
@ -76,7 +100,7 @@ SymEntry* NewSymEntry (unsigned Name)
S->V.Expr = 0;
S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
S->Name = Name;
S->Name = GetStringId (Name);
/* Insert it into the list of all entries */
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_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 */
typedef struct SymEntry SymEntry;
struct SymEntry {
@ -94,37 +103,92 @@ struct SymEntry {
/* List of all symbol table entries */
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 */
#if defined(HAVE_INLINE)
INLINE void SymAddRef (SymEntry* Sym, struct ExprNode* Expr)
/* Add a reference to this symbol */
INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Add an expression reference to this symbol */
{
CollAppend (&Sym->ExprRefs, Expr);
}
#else
#define SymAddRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr)
#define SymAddExprRef(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 */
INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr)
/* Delete an expression reference to this symbol */
{
CollDeleteItem (&Sym->ExprRefs, Expr);
}
#else
#define SymDelRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#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 */

View file

@ -66,30 +66,11 @@
#define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT)
#define SF_DBGINFOVAL (SF_DEFINED)
/* Definitions for the hash table */
#define MAIN_HASHTAB_SIZE 213
#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 */
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 tables */
SymTable* CurrentScope = 0; /* Pointer to current symbol table */
SymTable* RootScope = 0; /* Root symbol table */
/* 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 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)
/* 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 */
{
/* 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->TableEntries = 0;
S->Parent = Parent;
S->Name = Name;
S->Name = GetStringId (Name);
while (Slots--) {
S->Table[Slots] = 0;
}
@ -161,14 +126,15 @@ static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
} else {
while (1) {
/* Choose next entry */
if (S->Name < T->Name) {
int Cmp = strcmp (Name, GetString (T->Name));
if (Cmp < 0) {
if (T->Left) {
T = T->Left;
} else {
T->Left = S;
break;
}
} else if (S->Name > T->Name) {
} else if (Cmp > 0) {
if (T->Right) {
T = T->Right;
} else {
@ -177,13 +143,13 @@ static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
}
} else {
/* Duplicate scope name */
Internal ("Duplicate scope name: `%s'", GetString (S->Name));
Internal ("Duplicate scope name: `%s'", Name);
}
}
}
} else {
/* This is the root table */
RootTab = S;
RootScope = S;
}
/* 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
* 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,
@ -201,8 +167,6 @@ static int SearchSymTree (SymEntry* T, unsigned Name, SymEntry** E)
* inserted on the right side.
*/
{
int Cmp;
/* Is there a tree? */
if (T == 0) {
*E = 0;
@ -211,17 +175,15 @@ static int SearchSymTree (SymEntry* T, unsigned Name, SymEntry** E)
/* We have a table, search it */
while (1) {
/* Get the symbol name */
const char* SymName = GetString (T->Name);
/* 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) {
int Cmp = strcmp (Name, SymName);
if (Cmp < 0 && T->Left) {
T = T->Left;
} else if (Name > T->Name && T->Right) {
} else if (Cmp > 0&& T->Right) {
T = T->Right;
} else {
/* 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
* 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.
@ -247,18 +255,17 @@ static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
{
SymEntry* S;
int Cmp;
unsigned Hash;
if (IsLocalNameId (Name)) {
if (IsLocalName (Name)) {
/* Local symbol, get the table */
if (!SymLast) {
/* No last global, so there's no local table */
Error (ERR_ILLEGAL_LOCAL_USE);
if (AllocNew) {
return NewSymEntry (Name);
return NewSymEntry (Name);
} else {
return 0;
return 0;
}
}
@ -287,10 +294,10 @@ static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
} else {
/* Global symbol: Get the hash value for the name */
Hash = Name % Tab->TableSlots;
unsigned Hash = HashStr (Name) % Scope->TableSlots;
/* 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 (Cmp == 0) {
@ -308,14 +315,14 @@ static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
/* Otherwise create a new entry, insert and return it */
SymEntry* N = NewSymEntry (Name);
if (S == 0) {
Tab->Table[Hash] = N;
Scope->Table[Hash] = N;
} else if (Cmp < 0) {
S->Left = N;
} else {
S->Right = N;
}
N->SymTab = Tab;
++Tab->TableEntries;
N->SymTab = Scope;
++Scope->TableEntries;
return N;
}
@ -327,21 +334,24 @@ static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
static SymEntry* SymFindAny (SymTable* Tab, unsigned Name)
/* Find a symbol in any table */
static SymEntry* SymFindAny (SymTable* Scope, const char* Name)
/* 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;
do {
/* Search in the current table */
Sym = SymFind (Tab, Name, SF_FIND_EXISTING);
Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
if (Sym) {
/* Found, return it */
return Sym;
} else {
/* 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 */
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)
/* 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? */
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
if (S->Flags & SF_DEFINED) {
Error (ERR_SYM_ALREADY_DEFINED, Name);
S->Flags |= SF_MULTDEF;
@ -533,7 +435,7 @@ static void SymExportInternal (const char* Name, unsigned Flags)
}
/* 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) {
/* The symbol is already marked as imported external symbol */
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 */
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
* 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? */
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
S = SymFind (CurrentScope, Name, SYM_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
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)
/* Return true if the given symbol has a constant value */
{
@ -763,7 +621,7 @@ int SymIsZP (SymEntry* S)
S->SymTab->Parent != 0) {
/* 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 (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)
/* Handle an undefined symbol */
{
@ -950,7 +653,7 @@ static void SymCheckUndefined (SymEntry* S)
/* It's a global symbol, get the higher level table */
SymTable* Tab = S->SymTab->Parent;
while (Tab) {
Sym = SymFindAny (Tab, S->Name);
Sym = SymFindAny (Tab, GetString (S->Name));
if (Sym) {
if (Sym->Flags & (SF_DEFINED | SF_IMPORT)) {
/* We've found a symbol in a higher level that is
@ -1014,7 +717,7 @@ void SymCheck (void)
SymEntry* S;
/* Check for open lexical levels */
if (SymTab->Parent != 0) {
if (CurrentScope->Parent != 0) {
Error (ERR_OPEN_PROC);
}

View file

@ -59,10 +59,23 @@
#define SCOPE_GLOBAL 1
#define SCOPE_LOCAL 2
/* Flags used in SymDef */
#define SYM_DEFAULT 0x00
#define SYM_ZP 0x01
#define SYM_LABEL 0x02
/* A 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 */
};
/* 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);
/* Leave the current lexical level */
int SymIsLocalLevel (void);
/* Return true if we are on a local symbol table level. */
SymTable* SymFindScope (SymTable* Parent, const char* Name, unsigned Flags);
/* Find a scope in the given enclosing scope */
void SymDef (const char* Name, ExprNode* Expr, unsigned Flags);
/* Define a new symbol */
SymEntry* SymRef (const char* Name, int Scope);
/* 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 */
SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew);
/* Find a new symbol table entry in the given table. If AllocNew is given and
* the entry is not found, create a new one. Return the entry found, or the
* new entry created, or - in case AllocNew is zero - return 0.
*/
void SymImport (const char* Name);
/* Mark the given symbol as an imported symbol */
@ -129,36 +136,6 @@ int SymIsConst (SymEntry* Sym);
int SymIsZP (SymEntry* Sym);
/* 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);
/* Run through all symbols and check for anomalies and errors */