Revised symbol scoping
git-svn-id: svn://svn.cc65.org/cc65/trunk@2614 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
4a667ead00
commit
8400fb848a
13 changed files with 682 additions and 596 deletions
|
@ -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;
|
||||
|
|
128
src/ca65/expr.c
128
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",
|
||||
};
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -39,6 +39,7 @@ OBJS = anonname.o \
|
|||
segment.o \
|
||||
spool.o \
|
||||
symentry.o \
|
||||
symbol.o \
|
||||
symtab.o \
|
||||
toklist.o \
|
||||
ulabel.o
|
||||
|
|
|
@ -87,6 +87,7 @@ OBJS = anonname.obj \
|
|||
scanner.obj \
|
||||
segment.obj \
|
||||
spool.obj \
|
||||
symbol.obj \
|
||||
symentry.obj \
|
||||
symtab.obj \
|
||||
toklist.obj \
|
||||
|
|
|
@ -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
113
src/ca65/symbol.c
Normal 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
65
src/ca65/symbol.h
Normal 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
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue