From: cuz Date: Thu, 6 Nov 2003 11:22:31 +0000 (+0000) Subject: Revised symbol scoping X-Git-Tag: V2.12.0~1185 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=8400fb848a63cbc03b8d4f44eb30767074e96dec;p=cc65 Revised symbol scoping git-svn-id: svn://svn.cc65.org/cc65/trunk@2614 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index 22ff2a8de..70e949852 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -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; diff --git a/src/ca65/expr.c b/src/ca65/expr.c index dd0513dd2..f72f12eee 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -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", - }; - - 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; - - } + /* Parse the symbol name and search for the symbol */ + SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING); - /* 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; - - if (Tok != TOK_IDENT) { - Error (ERR_IDENT_EXPECTED); - if (Tok != TOK_RPAREN) { - NextTok (); - } - } else { - Result = SymIsRef (SVal, SCOPE_ANY); - NextTok (); - } + /* Parse the symbol name and search for the symbol */ + SymEntry* Sym = ParseScopedSymName (SYM_FIND_EXISTING); - /* Done */ - return Result; + /* Check if the symbol is referenced */ + return (Sym != 0 && SymIsRef (Sym)); } @@ -553,34 +484,19 @@ static ExprNode* Factor (void) NextTok (); break; - case TOK_NAMESPACE: - NextTok (); - if (Tok != TOK_IDENT) { - Error (ERR_IDENT_EXPECTED); - N = GenLiteralExpr (0); /* Dummy */ - } 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 (); - } - break; - - case TOK_IDENT: - S = SymRef (SVal, SCOPE_LOCAL); - if (SymIsConst (S)) { - /* Use the literal value instead */ - N = GenLiteralExpr (GetSymVal (S)); + 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 { - /* Create symbol node */ - N = GenSymExpr (S); + /* Mark the symbol as referenced */ + SymRef (S); + /* Create symbol node */ + N = GenSymExpr (S); } - NextTok (); break; case TOK_ULABEL: @@ -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; } diff --git a/src/ca65/macpack.c b/src/ca65/macpack.c index e27569322..bb657b268 100644 --- a/src/ca65/macpack.c +++ b/src/ca65/macpack.c @@ -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" diff --git a/src/ca65/main.c b/src/ca65/main.c index d80f29853..fd93fac97 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -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; diff --git a/src/ca65/make/gcc.mak b/src/ca65/make/gcc.mak index ed8d812c3..b8440d573 100644 --- a/src/ca65/make/gcc.mak +++ b/src/ca65/make/gcc.mak @@ -39,6 +39,7 @@ OBJS = anonname.o \ segment.o \ spool.o \ symentry.o \ + symbol.o \ symtab.o \ toklist.o \ ulabel.o diff --git a/src/ca65/make/watcom.mak b/src/ca65/make/watcom.mak index dc0ff3861..195fe866d 100644 --- a/src/ca65/make/watcom.mak +++ b/src/ca65/make/watcom.mak @@ -87,6 +87,7 @@ OBJS = anonname.obj \ scanner.obj \ segment.obj \ spool.obj \ + symbol.obj \ symentry.obj \ symtab.obj \ toklist.obj \ diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 641f0417e..1a98e855d 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -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 { diff --git a/src/ca65/symbol.c b/src/ca65/symbol.c new file mode 100644 index 000000000..ab3e0ccf2 --- /dev/null +++ b/src/ca65/symbol.c @@ -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 + +/* 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); + + } + } +} + + + diff --git a/src/ca65/symbol.h b/src/ca65/symbol.h new file mode 100644 index 000000000..218806b05 --- /dev/null +++ b/src/ca65/symbol.h @@ -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 + + + diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index 0dd8130c1..660fdf0df 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -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; +} + + + + diff --git a/src/ca65/symentry.h b/src/ca65/symentry.h index 189d31854..5d5aadd0a 100644 --- a/src/ca65/symentry.h +++ b/src/ca65/symentry.h @@ -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 */ diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index 892cbc56a..70945c34f 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -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); } diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index b28e7159b..ae343a9c0 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -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 */