1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-28 03:29:39 +00:00

Work on named scopes

git-svn-id: svn://svn.cc65.org/cc65/trunk@2592 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-10-31 20:21:48 +00:00
parent 8abe61a32f
commit fbdbf4d07c
12 changed files with 503 additions and 278 deletions

83
src/ca65/anonname.c Normal file
View File

@ -0,0 +1,83 @@
/*****************************************************************************/
/* */
/* anonname.c */
/* */
/* Create names for anonymous scopes/variables/types */
/* */
/* */
/* */
/* (C) 2000-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <string.h>
/* common */
#include "xsprintf.h"
/* ca65 */
#include "anonname.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
static const char AnonTag[] = "$anon";
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* AnonName (char* Buf, unsigned Size, const char* Spec)
/* Get a name for an anonymous scope, variable or type. Size is the size of
* the buffer passed to the function, Spec will be used as part of the
* identifier if given. A pointer to the buffer is returned.
*/
{
static unsigned ACount = 0;
xsprintf (Buf, Size, "%s-%s-%04X", AnonTag, Spec, ++ACount);
return Buf;
}
int IsAnonName (const char* Name)
/* Check if the given symbol name is that of an anonymous symbol */
{
return (strncmp (Name, AnonTag, sizeof (AnonTag) - 1) == 0);
}

62
src/ca65/anonname.h Normal file
View File

@ -0,0 +1,62 @@
/*****************************************************************************/
/* */
/* anonname.h */
/* */
/* Create names for anonymous scopes/variables/types */
/* */
/* */
/* */
/* (C) 2000-2003 Ullrich von Bassewitz */
/* Römerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef ANONNAME_H
#define ANONNAME_H
/*****************************************************************************/
/* Code */
/*****************************************************************************/
char* AnonName (char* Buf, unsigned Size, const char* Spec);
/* Get a name for an anonymous scope, variable or type. Size is the size of
* the buffer passed to the function, Spec will be used as part of the
* identifier if given. A pointer to the buffer is returned.
*/
int IsAnonName (const char* Name);
/* Check if the given symbol name is that of an anonymous symbol */
/* End of anonname.h */
#endif

View File

@ -84,7 +84,7 @@ static unsigned FreeNodeCount = 0;
static ExprNode* NewExprNode (void)
static ExprNode* NewExprNode (unsigned Op)
/* Create a new expression node */
{
ExprNode* N;
@ -98,7 +98,7 @@ static ExprNode* NewExprNode (void)
/* Allocate fresh memory */
N = xmalloc (sizeof (ExprNode));
}
N->Op = EXPR_NULL;
N->Op = Op;
N->Left = N->Right = 0;
N->Obj = 0;
@ -560,9 +560,7 @@ static ExprNode* Factor (void)
N = GenLiteralExpr (GetSymVal (S));
} else {
/* Create symbol node */
N = NewExprNode ();
N->Op = EXPR_SYMBOL;
N->V.Sym = S;
N = GenSymExpr (S);
}
NextTok ();
}
@ -575,9 +573,7 @@ static ExprNode* Factor (void)
N = GenLiteralExpr (GetSymVal (S));
} else {
/* Create symbol node */
N = NewExprNode ();
N->Op = EXPR_SYMBOL;
N->V.Sym = S;
N = GenSymExpr (S);
}
NextTok ();
break;
@ -589,16 +585,14 @@ static ExprNode* Factor (void)
case TOK_MINUS:
NextTok ();
N = NewExprNode ();
N = NewExprNode (EXPR_UNARY_MINUS);
N->Left = Factor ();
N->Op = EXPR_UNARY_MINUS;
break;
case TOK_NOT:
NextTok ();
N = NewExprNode ();
N = NewExprNode (EXPR_NOT);
N->Left = Factor ();
N->Op = EXPR_NOT;
break;
case TOK_STAR:
@ -609,16 +603,14 @@ static ExprNode* Factor (void)
case TOK_LT:
NextTok ();
N = NewExprNode ();
N = NewExprNode (EXPR_BYTE0);
N->Left = Factor ();
N->Op = EXPR_BYTE0;
break;
case TOK_GT:
NextTok ();
N = NewExprNode ();
N = NewExprNode (EXPR_BYTE1);
N->Left = Factor ();
N->Op = EXPR_BYTE1;
break;
case TOK_LPAREN:
@ -697,32 +689,29 @@ static ExprNode* Factor (void)
static ExprNode* Term (void)
{
ExprNode* Root;
/* Read left hand side */
Root = Factor ();
ExprNode* Root = Factor ();
/* Handle multiplicative operations */
while (Tok == TOK_MUL || Tok == TOK_DIV || Tok == TOK_MOD ||
Tok == TOK_AND || Tok == TOK_XOR || Tok == TOK_SHL ||
Tok == TOK_SHR) {
/* Create a new node and insert the left expression */
/* Create the new node */
ExprNode* Left = Root;
Root = NewExprNode ();
Root->Left = Left;
/* Determine the operator token */
switch (Tok) {
case TOK_MUL: Root->Op = EXPR_MUL; break;
case TOK_DIV: Root->Op = EXPR_DIV; break;
case TOK_MOD: Root->Op = EXPR_MOD; break;
case TOK_AND: Root->Op = EXPR_AND; break;
case TOK_XOR: Root->Op = EXPR_XOR; break;
case TOK_SHL: Root->Op = EXPR_SHL; break;
case TOK_SHR: Root->Op = EXPR_SHR; break;
case TOK_MUL: Root = NewExprNode (EXPR_MUL); break;
case TOK_DIV: Root = NewExprNode (EXPR_DIV); break;
case TOK_MOD: Root = NewExprNode (EXPR_MOD); break;
case TOK_AND: Root = NewExprNode (EXPR_AND); break;
case TOK_XOR: Root = NewExprNode (EXPR_XOR); break;
case TOK_SHL: Root = NewExprNode (EXPR_SHL); break;
case TOK_SHR: Root = NewExprNode (EXPR_SHR); break;
default: Internal ("Invalid token");
}
Root->Left = Left;
/* Skip the operator token */
NextTok ();
/* Parse the right hand side */
@ -738,26 +727,23 @@ static ExprNode* Term (void)
static ExprNode* SimpleExpr (void)
{
ExprNode* Root;
/* Read left hand side */
Root = Term ();
ExprNode* Root = Term ();
/* Handle additive operations */
while (Tok == TOK_PLUS || Tok == TOK_MINUS || Tok == TOK_OR) {
/* Create a new node and insert the left expression */
/* Create the new node */
ExprNode* Left = Root;
Root = NewExprNode ();
Root->Left = Left;
/* Determine the operator token */
switch (Tok) {
case TOK_PLUS: Root->Op = EXPR_PLUS; break;
case TOK_MINUS: Root->Op = EXPR_MINUS; break;
case TOK_OR: Root->Op = EXPR_OR; break;
case TOK_PLUS: Root = NewExprNode (EXPR_PLUS); break;
case TOK_MINUS: Root = NewExprNode (EXPR_MINUS); break;
case TOK_OR: Root = NewExprNode (EXPR_OR); break;
default: Internal ("Invalid token");
}
Root->Left = Left;
/* Skip the operator token */
NextTok ();
/* Parse the right hand side */
@ -781,21 +767,20 @@ static ExprNode* BoolExpr (void)
while (Tok == TOK_EQ || Tok == TOK_NE || Tok == TOK_LT ||
Tok == TOK_GT || Tok == TOK_LE || Tok == TOK_GE) {
/* Create a new node and insert the left expression */
/* Create the new node */
ExprNode* Left = Root;
Root = NewExprNode ();
Root->Left = Left;
/* Determine the operator token */
switch (Tok) {
case TOK_EQ: Root->Op = EXPR_EQ; break;
case TOK_NE: Root->Op = EXPR_NE; break;
case TOK_LT: Root->Op = EXPR_LT; break;
case TOK_GT: Root->Op = EXPR_GT; break;
case TOK_LE: Root->Op = EXPR_LE; break;
case TOK_GE: Root->Op = EXPR_GE; break;
case TOK_EQ: Root = NewExprNode (EXPR_EQ); break;
case TOK_NE: Root = NewExprNode (EXPR_NE); break;
case TOK_LT: Root = NewExprNode (EXPR_LT); break;
case TOK_GT: Root = NewExprNode (EXPR_GT); break;
case TOK_LE: Root = NewExprNode (EXPR_LE); break;
case TOK_GE: Root = NewExprNode (EXPR_GE); break;
default: Internal ("Invalid token");
}
Root->Left = Left;
/* Skip the operator token */
NextTok ();
/* Parse the right hand side */
@ -818,17 +803,16 @@ static ExprNode* Expr2 (void)
/* Handle booleans */
while (Tok == TOK_BAND || Tok == TOK_BXOR) {
/* Create a new node and insert the left expression */
/* Create the new node */
ExprNode* Left = Root;
Root = NewExprNode ();
Root->Left = Left;
/* Determine the operator token */
switch (Tok) {
case TOK_BAND: Root->Op = EXPR_BAND; break;
case TOK_BXOR: Root->Op = EXPR_BXOR; break;
case TOK_BAND: Root = NewExprNode (EXPR_BAND); break;
case TOK_BXOR: Root = NewExprNode (EXPR_BXOR); break;
default: Internal ("Invalid token");
}
Root->Left = Left;
/* Skip the operator token */
NextTok ();
/* Parse the right hand side */
@ -851,16 +835,15 @@ static ExprNode* Expr1 (void)
/* Handle booleans */
while (Tok == TOK_BOR) {
/* Create a new node and insert the left expression */
/* Create the new node */
ExprNode* Left = Root;
Root = NewExprNode ();
Root->Left = Left;
/* Determine the operator token */
switch (Tok) {
case TOK_BOR: Root->Op = EXPR_BOR; break;
case TOK_BOR: Root = NewExprNode (EXPR_BOR); break;
default: Internal ("Invalid token");
}
Root->Left = Left;
/* Skip the operator token */
NextTok ();
/* Parse the right hand side */
@ -882,14 +865,10 @@ static ExprNode* Expr0 (void)
/* Handle booleans */
if (Tok == TOK_BNOT) {
/* Create a new node */
Root = NewExprNode ();
/* Create the new node */
Root = NewExprNode (EXPR_BNOT);
/* Determine the operator token */
switch (Tok) {
case TOK_BNOT: Root->Op = EXPR_BNOT; break;
default: Internal ("Invalid token");
}
/* Skip the operator token */
NextTok ();
/* Parse the left hand side, allow more BNOTs */
@ -912,8 +891,8 @@ static ExprNode* SimplifyExpr (ExprNode* Root)
/* Try to simplify the given expression tree */
{
if (Root) {
SimplifyExpr (Root->Left);
SimplifyExpr (Root->Right);
Root->Left = SimplifyExpr (Root->Left);
Root->Right = SimplifyExpr (Root->Right);
if (IsConstExpr (Root)) {
/* The complete expression is constant */
Root->V.Val = GetExprVal (Root);
@ -966,6 +945,10 @@ void FreeExpr (ExprNode* Root)
if (Root) {
FreeExpr (Root->Left);
FreeExpr (Root->Right);
if (Root->Op == EXPR_SYMBOL) {
/* Remove the symbol reference */
SymDelRef (Root->V.Sym, Root);
}
FreeExprNode (Root);
}
}
@ -975,30 +958,44 @@ void FreeExpr (ExprNode* Root)
ExprNode* GenLiteralExpr (long Val)
/* Return an expression tree that encodes the given literal value */
{
ExprNode* Expr = NewExprNode ();
Expr->Op = EXPR_LITERAL;
ExprNode* Expr = NewExprNode (EXPR_LITERAL);
Expr->V.Val = Val;
return Expr;
}
ExprNode* GenSymExpr (SymEntry* Sym)
/* Return an expression node that encodes the given symbol */
{
ExprNode* Expr = NewExprNode (EXPR_SYMBOL);
Expr->V.Sym = Sym;
SymAddRef (Sym, Expr);
return Expr;
}
static ExprNode* GenSectionExpr (unsigned SegNum)
/* Return an expression node for the given section */
{
ExprNode* Expr = NewExprNode (EXPR_SECTION);
Expr->V.SegNum = SegNum;
return Expr;
}
ExprNode* GenCurrentPC (void)
/* Return the current program counter as expression */
{
ExprNode* Left;
ExprNode* Root;
if (RelocMode) {
/* Create SegmentBase + Offset */
Left = NewExprNode ();
Left->Op = EXPR_SECTION;
Left->V.SegNum = GetSegNum ();
Root = NewExprNode ();
Root->Left = Left;
Root = NewExprNode (EXPR_PLUS);
Root->Left = GenSectionExpr (GetSegNum ());
Root->Right = GenLiteralExpr (GetPC ());
Root->Op = EXPR_PLUS;
} else {
/* Absolute mode, just return PC value */
Root = GenLiteralExpr (GetPC ());
@ -1012,8 +1009,7 @@ ExprNode* GenCurrentPC (void)
ExprNode* GenSwapExpr (ExprNode* Expr)
/* Return an extended expression with lo and hi bytes swapped */
{
ExprNode* N = NewExprNode ();
N->Op = EXPR_SWAP;
ExprNode* N = NewExprNode (EXPR_SWAP);
N->Left = Expr;
return N;
}
@ -1027,27 +1023,20 @@ ExprNode* GenBranchExpr (unsigned Offs)
{
ExprNode* N;
ExprNode* Root;
ExprNode* Left;
/* Create *+Offs */
if (RelocMode) {
Left = NewExprNode ();
Left->Op = EXPR_SECTION;
Left->V.SegNum = GetSegNum ();
N = NewExprNode ();
N->Left = Left;
N = NewExprNode (EXPR_PLUS);
N->Left = GenSectionExpr (GetSegNum ());
N->Right = GenLiteralExpr (GetPC () + Offs);
N->Op = EXPR_PLUS;
} else {
N = GenLiteralExpr (GetPC () + Offs);
}
/* Create the root node */
Root = NewExprNode ();
Root = NewExprNode (EXPR_MINUS);
Root->Left = Expression ();
Root->Right = N;
Root->Op = EXPR_MINUS;
/* Return the result */
return SimplifyExpr (Root);
@ -1058,11 +1047,7 @@ ExprNode* GenBranchExpr (unsigned Offs)
ExprNode* GenULabelExpr (unsigned Num)
/* Return an expression for an unnamed label with the given index */
{
/* Get an expression node */
ExprNode* Node = NewExprNode ();
/* Set the values */
Node->Op = EXPR_ULABEL;
ExprNode* Node = NewExprNode (EXPR_ULABEL);
Node->V.Val = Num;
/* Return the new node */
@ -1075,9 +1060,8 @@ ExprNode* GenByteExpr (ExprNode* Expr)
/* Force the given expression into a byte and return the result */
{
/* Use the low byte operator to force the expression into byte size */
ExprNode* Root = NewExprNode ();
ExprNode* Root = NewExprNode (EXPR_BYTE0);
Root->Left = Expr;
Root->Op = EXPR_BYTE0;
/* Return the result */
return Root;
@ -1089,9 +1073,8 @@ ExprNode* GenWordExpr (ExprNode* Expr)
/* Force the given expression into a word and return the result. */
{
/* AND the expression by $FFFF to force it into word size */
ExprNode* Root = NewExprNode ();
ExprNode* Root = NewExprNode (EXPR_AND);
Root->Left = Expr;
Root->Op = EXPR_AND;
Root->Right = GenLiteralExpr (0xFFFF);
/* Return the result */
@ -1104,9 +1087,8 @@ ExprNode* GenNE (ExprNode* Expr, long Val)
/* Generate an expression that compares Expr and Val for inequality */
{
/* Generate a compare node */
ExprNode* Root = NewExprNode ();
ExprNode* Root = NewExprNode (EXPR_NE);
Root->Left = Expr;
Root->Op = EXPR_NE;
Root->Right = GenLiteralExpr (Val);
/* Return the result */
@ -1165,7 +1147,7 @@ int IsConstExpr (ExprNode* Root)
} else {
return IsConstExpr (Root->Right);
}
} else {
} else {
/* lhs not const --> tree not const */
return 0;
}
@ -1208,7 +1190,7 @@ static void CheckByteExpr (const ExprNode* N, int* IsByte)
case EXPR_SYMBOL:
if (SymIsZP (N->V.Sym)) {
*IsByte = 1;
} else if (SymHasExpr (N->V.Sym)) {
} else if (SymHasExpr (N->V.Sym)) {
/* Check if this expression is a byte expression */
*IsByte = IsByteExpr (GetSymExpr (N->V.Sym));
}
@ -1403,31 +1385,31 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
case EXPR_SYMBOL:
if (SymHasExpr (Expr->V.Sym)) {
/* The symbol has an expression tree */
SymEntry* Sym = Expr->V.Sym;
if (SymHasUserMark (Sym)) {
/* Circular definition */
if (Verbosity) {
DumpExpr (Expr);
}
PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
return GenLiteralExpr (0); /* Return a dummy value */
}
SymMarkUser (Sym);
Expr = RemoveSyms (GetSymExpr (Sym), 1);
SymUnmarkUser (Sym);
return Expr;
/* The symbol has an expression tree */
SymEntry* Sym = Expr->V.Sym;
if (SymHasUserMark (Sym)) {
/* Circular definition */
if (Verbosity) {
DumpExpr (Expr);
}
PError (GetSymPos (Sym), ERR_CIRCULAR_REFERENCE);
return GenLiteralExpr (0); /* Return a dummy value */
}
SymMarkUser (Sym);
Expr = RemoveSyms (GetSymExpr (Sym), 1);
SymUnmarkUser (Sym);
return Expr;
} else if (SymIsConst (Expr->V.Sym)) {
/* The symbol is a constant */
return GenLiteralExpr (GetSymVal (Expr->V.Sym));
/* The symbol is a constant */
return GenLiteralExpr (GetSymVal (Expr->V.Sym));
}
break;
case EXPR_ULABEL:
if (ULabCanResolve ()) {
ExprNode* NewExpr = ULabResolve (Expr->V.Val);
FreeExpr (Expr);
Expr = NewExpr;
ExprNode* NewExpr = ULabResolve (Expr->V.Val);
FreeExpr (Expr);
Expr = NewExpr;
}
break;
@ -1436,46 +1418,46 @@ static ExprNode* RemoveSyms (ExprNode* Expr, int MustClone)
/* Clone the current node if needed */
if (MustClone) {
/* Create a new node */
ExprNode* Clone = NewExprNode ();
ExprNode* Clone;
/* Clone the operation */
Clone->Op = Expr->Op;
/* Clone the attribute if needed */
/* Clone the expression tree */
switch (Expr->Op) {
case EXPR_LITERAL:
Clone = GenLiteralExpr (Expr->V.Val);
break;
case EXPR_ULABEL:
Clone->V.Val = Expr->V.Val;
break;
Clone = GenULabelExpr (Expr->V.Val);
break;
case EXPR_SYMBOL:
Clone->V.Sym = Expr->V.Sym;
break;
Clone = GenSymExpr (Expr->V.Sym);
break;
case EXPR_SECTION:
Clone->V.SegNum = Expr->V.SegNum;
break;
Clone = GenSectionExpr (Expr->V.SegNum);
break;
default:
Clone = NewExprNode (Expr->Op);
Clone->Left = RemoveSyms (Expr->Left, 1);
Clone->Right = RemoveSyms (Expr->Right, 1);
break;
}
/* Clone the tree nodes */
Clone->Left = RemoveSyms (Expr->Left, MustClone);
Clone->Right = RemoveSyms (Expr->Right, MustClone);
/* Done */
return Clone;
} else {
/* Nothing to clone */
Expr->Left = RemoveSyms (Expr->Left, MustClone);
Expr->Right = RemoveSyms (Expr->Right, MustClone);
Expr->Left = RemoveSyms (Expr->Left, 0);
Expr->Right = RemoveSyms (Expr->Right, 0);
/* Done */
return Expr;
}
}
@ -1560,8 +1542,7 @@ ExprNode* FinalizeExpr (ExprNode* Expr)
Expr = GenLiteralExpr (Val);
} else if (Val) {
/* Extracted a value */
N = NewExprNode ();
N->Op = EXPR_PLUS;
N = NewExprNode (EXPR_PLUS);
N->Left = Expr;
N->Right = GenLiteralExpr (Val);
Expr = N;
@ -1583,34 +1564,34 @@ ExprNode* CloneExpr (ExprNode* Expr)
return 0;
}
/* Get a new node */
Clone = NewExprNode ();
/* Clone the operation */
Clone->Op = Expr->Op;
/* Clone the attribute if needed */
/* Clone the node */
switch (Expr->Op) {
case EXPR_LITERAL:
Clone = GenLiteralExpr (Expr->V.Val);
break;
case EXPR_ULABEL:
Clone->V.Val = Expr->V.Val;
Clone = GenULabelExpr (Expr->V.Val);
break;
case EXPR_SYMBOL:
Clone->V.Sym = Expr->V.Sym;
Clone = GenSymExpr (Expr->V.Sym);
break;
case EXPR_SECTION:
Clone->V.SegNum = Expr->V.SegNum;
Clone = GenSectionExpr (Expr->V.SegNum);
break;
default:
/* Generate a new node */
Clone = NewExprNode (Expr->Op);
/* Clone the tree nodes */
Clone->Left = CloneExpr (Expr->Left);
Clone->Right = CloneExpr (Expr->Right);
break;
}
/* Clone the tree nodes */
Clone->Left = CloneExpr (Expr->Left);
Clone->Right = CloneExpr (Expr->Right);
/* Done */
return Clone;
}
@ -1663,3 +1644,4 @@ void WriteExpr (ExprNode* Expr)

View File

@ -66,6 +66,9 @@ void FreeExpr (ExprNode* Root);
ExprNode* GenLiteralExpr (long Val);
/* Return an expression tree that encodes the given literal value */
ExprNode* GenSymExpr (struct SymEntry* Sym);
/* Return an expression node that encodes the given symbol */
ExprNode* GenCurrentPC (void);
/* Return the current program counter as expression */

View File

@ -519,7 +519,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 ();
SymEnterLevel (0);
/* Check the parameters */
I = 1;

View File

@ -10,7 +10,8 @@ CC = gcc
EBIND = emxbind
LDFLAGS =
OBJS = asserts.o \
OBJS = anonname.o \
asserts.o \
condasm.o \
dbginfo.o \
ea.o \

View File

@ -43,7 +43,8 @@ CFLAGS += -i=..\common
# ------------------------------------------------------------------------------
# All library OBJ files
OBJS = asserts.obj \
OBJS = anonname.obj \
asserts.obj \
condasm.obj \
dbginfo.obj \
ea.obj \

View File

@ -49,6 +49,7 @@
#include "xmalloc.h"
/* ca65 */
#include "anonname.h"
#include "asserts.h"
#include "condasm.h"
#include "dbginfo.h"
@ -1248,10 +1249,13 @@ static void DoProc (void)
if (IsZPSeg ()) {
Flags |= SYM_ZP;
}
SymDef (SVal, GenCurrentPC (), Flags);
NextTok ();
SymDef (SVal, GenCurrentPC (), Flags);
SymEnterLevel (SVal);
NextTok ();
} else {
char Buf[sizeof (SVal)];
SymEnterLevel (AnonName (Buf, sizeof (Buf), "Scope"));
}
SymEnterLevel ();
}

View File

@ -60,17 +60,11 @@ SymEntry* SymList = 0; /* List of all symbol table entries */
SymEntry* NewSymEntry (const char* Name)
SymEntry* NewSymEntry (unsigned Name)
/* Allocate a symbol table entry, initialize and return it */
{
SymEntry* S;
unsigned Len;
/* Get the length of the name */
Len = strlen (Name);
/* Allocate memory */
S = xmalloc (sizeof (SymEntry) + Len);
SymEntry* S = xmalloc (sizeof (SymEntry));
/* Initialize the entry */
S->Left = 0;
@ -80,8 +74,9 @@ SymEntry* NewSymEntry (const char* Name)
S->Pos = CurPos;
S->Flags = 0;
S->V.Expr = 0;
S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
memcpy (S->Name, Name, Len+1);
S->Name = Name;
/* Insert it into the list of all entries */
S->List = SymList;
@ -92,4 +87,4 @@ SymEntry* NewSymEntry (const char* Name)
}

View File

@ -40,6 +40,7 @@
/* common */
#include "cddefs.h"
#include "coll.h"
#include "filepos.h"
@ -52,12 +53,12 @@
/* Bits for the Flags value in SymEntry */
#define SF_NONE 0x0000 /* Empty flag set */
#define SF_USER 0x0001 /* User bit */
#define SF_TRAMPOLINE 0x0002 /* Trampoline entry */
#define SF_EXPORT 0x0004 /* Export this symbol */
#define SF_IMPORT 0x0008 /* Import this symbol */
#define SF_GLOBAL 0x0010 /* Global symbol */
#define SF_ZP 0x0020 /* Declared as zeropage symbol */
#define SF_USER 0x0001 /* User bit */
#define SF_TRAMPOLINE 0x0002 /* Trampoline entry */
#define SF_EXPORT 0x0004 /* Export this symbol */
#define SF_IMPORT 0x0008 /* Import this symbol */
#define SF_GLOBAL 0x0010 /* Global symbol */
#define SF_ZP 0x0020 /* Declared as zeropage symbol */
#define SF_ABS 0x0040 /* Declared as absolute symbol */
#define SF_LABEL 0x0080 /* Used as a label */
#define SF_FORCED 0x0100 /* Forced import, SF_IMPORT also set */
@ -84,9 +85,10 @@ struct SymEntry {
long Val; /* Value (if CONST set) */
SymEntry* Sym; /* Symbol (if trampoline entry) */
} V;
Collection ExprRefs; /* Expressions using this symbol */
unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */
/* ...actually value+1 (used as flag) */
char Name [1]; /* Dynamic allocation */
unsigned Name; /* Name index in global string pool */
};
/* List of all symbol table entries */
@ -95,14 +97,34 @@ extern SymEntry* SymList;
/*****************************************************************************/
/* Code */
/* Code */
/*****************************************************************************/
SymEntry* NewSymEntry (const char* Name);
SymEntry* NewSymEntry (unsigned Name);
/* Allocate a symbol table entry, initialize and return it */
#if defined(HAVE_INLINE)
INLINE void SymAddRef (SymEntry* Sym, struct ExprNode* Expr)
/* Add a reference to this symbol */
{
CollAppend (&Sym->ExprRefs, Expr);
}
#else
#define SymAddRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr)
#endif
#if defined(HAVE_INLINE)
INLINE void SymDelRef (SymEntry* Sym, struct ExprNode* Expr)
/* Delete a reference to this symbol */
{
CollDeleteItem (&Sym->ExprRefs, Expr);
}
#else
#define SymDelRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr)
#endif
/* End of symentry.h */

View File

@ -71,9 +71,14 @@
#define SUB_HASHTAB_SIZE 53
typedef struct SymTable SymTable;
struct SymTable {
SymTable* Left; /* Pointer to smaller entry */
SymTable* Right; /* Pointer to greater entry */
SymTable* Parent; /* Link to enclosing scope if any */
SymTable* Childs; /* Pointer to child scopes */
unsigned Level; /* Lexical level */
unsigned TableSlots; /* Number of hash table slots */
unsigned TableEntries; /* Number of entries in the table */
SymTable* BackLink; /* Link to enclosing scope if any */
unsigned Name; /* Name of the scope */
SymEntry* Table [1]; /* Dynamic allocation */
};
@ -96,7 +101,7 @@ static unsigned ExportCount = 0;/* Counter for export symbols */
static int IsLocal (const char* Name)
static int IsLocalName (const char* Name)
/* Return true if Name is the name of a local symbol */
{
return (*Name == LocalStart);
@ -104,20 +109,81 @@ static int IsLocal (const char* Name)
static SymTable* NewSymTable (unsigned Size)
static int IsLocalNameId (unsigned Name)
/* Return true if Name is the name of a local symbol */
{
return (*GetString (Name) == LocalStart);
}
static unsigned SymTableSize (unsigned Level)
/* Get the size of a table for the given lexical level */
{
switch (Level) {
case 0: return 213;
case 1: return 53;
default: return 29;
}
}
static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
/* Allocate a symbol table on the heap and return it */
{
SymTable* S;
/* Determine the lexical level and the number of table slots */
unsigned Level = Parent? Parent->Level + 1 : 0;
unsigned Slots = SymTableSize (Level);
/* Allocate memory */
S = xmalloc (sizeof (SymTable) + (Size-1) * sizeof (SymEntry*));
SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));
/* Set variables and clear hash table entries */
S->TableSlots = Size;
S->Left = 0;
S->Right = 0;
S->Childs = 0;
S->Level = Level;
S->TableSlots = Slots;
S->TableEntries = 0;
S->BackLink = 0;
while (Size--) {
S->Table [Size] = 0;
S->Parent = Parent;
S->Name = Name;
while (Slots--) {
S->Table[Slots] = 0;
}
/* Insert the symbol table into the child tree of the parent */
if (Parent) {
SymTable* T = Parent->Childs;
if (T == 0) {
/* First entry */
Parent->Childs = S;
} else {
while (1) {
/* Choose next entry */
if (S->Name < T->Name) {
if (T->Left) {
T = T->Left;
} else {
T->Left = S;
break;
}
} else if (S->Name > T->Name) {
if (T->Right) {
T = T->Right;
} else {
T->Right = S;
break;
}
} else {
/* Duplicate scope name */
Internal ("Duplicate scope name: `%s'", GetString (S->Name));
}
}
}
} else {
/* This is the root table */
RootTab = S;
}
/* Return the prepared struct */
@ -126,53 +192,54 @@ static SymTable* NewSymTable (unsigned Size)
static int SearchSymTab (SymEntry* T, const char* Name, SymEntry** E)
/* Search in the given table for a name (Hash is the hash value of Name and
* is given as parameter so that it will not get calculated twice if we search
* in more than one table). If we find the symbol, the function will return 0
* and put the entry pointer into E. If we did not find the symbol, and the
* tree is empty, E is set to NULL. If the tree is not empty, E will be set to
* the last entry, and the result of the function is <0 if the entry should
* be inserted on the left side, and >0 if it should get inserted on the right
* side.
static int SearchSymTree (SymEntry* T, unsigned Name, SymEntry** E)
/* Search in the given tree for a name. If we find the symbol, the function
* will return 0 and put the entry pointer into E. If we did not find the
* symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
* E will be set to the last entry, and the result of the function is <0 if
* the entry should be inserted on the left side, and >0 if it should get
* inserted on the right side.
*/
{
int Cmp;
/* Is there a tree? */
if (T == 0) {
*E = 0;
return 1;
*E = 0;
return 1;
}
/* We have a table, search it */
while (1) {
/* Choose next entry */
Cmp = strcmp (Name, T->Name);
if (Cmp < 0 && T->Left) {
/* Choose next entry */
if (Name < T->Name) {
Cmp = -1;
} else if (Name > T->Name) {
Cmp = +1;
} else {
Cmp = 0;
}
if (Name < T->Name && T->Left) {
T = T->Left;
} else if (Cmp > 0 && T->Right) {
} else if (Name > T->Name && T->Right) {
T = T->Right;
} else {
/* Found or end of search */
break;
/* Found or end of search, return the result */
*E = T;
return Cmp;
}
}
/* Return the search result */
*E = T;
return Cmp;
}
/*****************************************************************************/
/* Code */
/* Code */
/*****************************************************************************/
static SymEntry* SymFind (SymTable* Tab, const char* Name, int AllocNew)
static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
/* Find a new symbol table entry in the given table. If AllocNew is given and
* the entry is not found, create a new one. Return the entry found, or the
* new entry created, or - in case AllocNew is zero - return 0.
@ -182,7 +249,7 @@ static SymEntry* SymFind (SymTable* Tab, const char* Name, int AllocNew)
int Cmp;
unsigned Hash;
if (IsLocal (Name)) {
if (IsLocalNameId (Name)) {
/* Local symbol, get the table */
if (!SymLast) {
@ -196,7 +263,7 @@ static SymEntry* SymFind (SymTable* Tab, const char* Name, int AllocNew)
}
/* Search for the symbol if we have a table */
Cmp = SearchSymTab (SymLast->Locals, Name, &S);
Cmp = SearchSymTree (SymLast->Locals, Name, &S);
/* If we found an entry, return it */
if (Cmp == 0) {
@ -220,21 +287,20 @@ static SymEntry* SymFind (SymTable* Tab, const char* Name, int AllocNew)
} else {
/* Global symbol: Get the hash value for the name */
Hash = HashStr (Name) % Tab->TableSlots;
Hash = Name % Tab->TableSlots;
/* Search for the entry */
Cmp = SearchSymTab (Tab->Table [Hash], Name, &S);
Cmp = SearchSymTree (Tab->Table[Hash], Name, &S);
/* If we found an entry, return it */
if (Cmp == 0) {
/* Check for a trampoline entry, in this case return the real
* symbol.
*/
if (S->Flags & SF_TRAMPOLINE) {
return S->V.Sym;
} else {
return S;
while (S->Flags & SF_TRAMPOLINE) {
S = S->V.Sym;
}
return S;
}
if (AllocNew) {
@ -242,7 +308,7 @@ static SymEntry* SymFind (SymTable* Tab, const char* Name, int AllocNew)
/* Otherwise create a new entry, insert and return it */
SymEntry* N = NewSymEntry (Name);
if (S == 0) {
Tab->Table [Hash] = N;
Tab->Table[Hash] = N;
} else if (Cmp < 0) {
S->Left = N;
} else {
@ -261,7 +327,7 @@ static SymEntry* SymFind (SymTable* Tab, const char* Name, int AllocNew)
static SymEntry* SymFindAny (SymTable* Tab, const char* Name)
static SymEntry* SymFindAny (SymTable* Tab, unsigned Name)
/* Find a symbol in any table */
{
SymEntry* Sym;
@ -272,8 +338,8 @@ static SymEntry* SymFindAny (SymTable* Tab, const char* Name)
/* Found, return it */
return Sym;
} else {
/* Not found, search in the backlink, if we have one */
Tab = Tab->BackLink;
/* Not found, search in the parent scope, if we have one */
Tab = Tab->Parent;
}
} while (Sym == 0 && Tab != 0);
@ -283,18 +349,16 @@ static SymEntry* SymFindAny (SymTable* Tab, const char* Name)
void SymEnterLevel (void)
void SymEnterLevel (const char* ScopeName)
/* Enter a new lexical level */
{
if (RootTab == 0) {
/* Create the main symbol table */
RootTab = SymTab = NewSymTable (MAIN_HASHTAB_SIZE);
} else {
/* Create a local symbol table */
SymTable* LocalSyms = NewSymTable (SUB_HASHTAB_SIZE);
LocalSyms->BackLink = SymTab;
SymTab = LocalSyms;
/* Accept NULL pointers for the scope name */
if (ScopeName == 0) {
ScopeName = "";
}
/* Create the new table */
SymTab = NewSymTable (SymTab, GetStringId (ScopeName));
}
@ -302,7 +366,7 @@ void SymEnterLevel (void)
void SymLeaveLevel (void)
/* Leave the current lexical level */
{
SymTab = SymTab->BackLink;
SymTab = SymTab->Parent;
}
@ -319,7 +383,7 @@ void SymDef (const char* Name, ExprNode* Expr, unsigned Flags)
/* Define a new symbol */
{
/* Do we have such a symbol? */
SymEntry* S = SymFind (SymTab, Name, SF_ALLOC_NEW);
SymEntry* S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* Defined symbol is marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, Name);
@ -359,7 +423,7 @@ void SymDef (const char* Name, ExprNode* Expr, unsigned Flags)
}
/* If this is not a local symbol, remember it as the last global one */
if (!IsLocal (Name)) {
if (!IsLocalName (Name)) {
SymLast = S;
}
}
@ -370,10 +434,11 @@ 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, Name, SF_ALLOC_NEW); break;
case SCOPE_LOCAL: S = SymFind (SymTab, Name, SF_ALLOC_NEW); break;
case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_ALLOC_NEW); break;
case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_ALLOC_NEW); break;
/* Others are not allowed */
case SCOPE_ANY:
@ -398,13 +463,13 @@ static void SymImportInternal (const char* Name, unsigned Flags)
SymEntry* S;
/* Don't accept local symbols */
if (IsLocal (Name)) {
if (IsLocalName (Name)) {
Error (ERR_ILLEGAL_LOCAL_USE);
return;
}
/* Do we have such a symbol? */
S = SymFind (SymTab, Name, SF_ALLOC_NEW);
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
if (S->Flags & SF_DEFINED) {
Error (ERR_SYM_ALREADY_DEFINED, Name);
S->Flags |= SF_MULTDEF;
@ -462,13 +527,13 @@ static void SymExportInternal (const char* Name, unsigned Flags)
SymEntry* S;
/* Don't accept local symbols */
if (IsLocal (Name)) {
if (IsLocalName (Name)) {
Error (ERR_ILLEGAL_LOCAL_USE);
return;
}
/* Do we have such a symbol? */
S = SymFind (SymTab, Name, SF_ALLOC_NEW);
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, Name);
@ -515,13 +580,13 @@ static void SymGlobalInternal (const char* Name, unsigned Flags)
SymEntry* S;
/* Don't accept local symbols */
if (IsLocal (Name)) {
if (IsLocalName (Name)) {
Error (ERR_ILLEGAL_LOCAL_USE);
return;
}
/* Search for this symbol, create a new entry if needed */
S = SymFind (SymTab, Name, SF_ALLOC_NEW);
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
/* If the symbol is already marked as import or export, check the
* size of the definition, then bail out. */
@ -574,13 +639,13 @@ void SymConDes (const char* Name, unsigned Type, unsigned Prio)
CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
/* Don't accept local symbols */
if (IsLocal (Name)) {
if (IsLocalName (Name)) {
Error (ERR_ILLEGAL_LOCAL_USE);
return;
}
/* Do we have such a symbol? */
S = SymFind (SymTab, Name, SF_ALLOC_NEW);
S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
if (S->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
Error (ERR_SYM_ALREADY_IMPORT, Name);
@ -618,11 +683,14 @@ int SymIsDef (const char* Name, int Scope)
{
SymEntry* S = 0;
/* Get the string pool index for the name */
unsigned NameId = GetStringId (Name);
/* Search for the symbol */
switch (Scope) {
case SCOPE_ANY: S = SymFindAny (SymTab, Name); break;
case SCOPE_GLOBAL: S = SymFind (RootTab, Name, SF_FIND_EXISTING); break;
case SCOPE_LOCAL: S = SymFind (SymTab, Name, SF_FIND_EXISTING); break;
case SCOPE_ANY: S = SymFindAny (SymTab, NameId); break;
case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_FIND_EXISTING); break;
case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_FIND_EXISTING); break;
default: Internal ("Invalid scope in SymIsDef: %d", Scope);
}
@ -637,11 +705,14 @@ int SymIsRef (const char* Name, int Scope)
{
SymEntry* S = 0;
/* Get the string pool index for the name */
unsigned NameId = GetStringId (Name);
/* Search for the symbol */
switch (Scope) {
case SCOPE_ANY: S = SymFindAny (SymTab, Name); break;
case SCOPE_GLOBAL: S = SymFind (RootTab, Name, SF_FIND_EXISTING); break;
case SCOPE_LOCAL: S = SymFind (SymTab, Name, SF_FIND_EXISTING); break;
case SCOPE_ANY: S = SymFindAny (SymTab, NameId); break;
case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_FIND_EXISTING); break;
case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_FIND_EXISTING); break;
default: Internal ("Invalid scope in SymIsRef: %d", Scope);
}
@ -687,12 +758,12 @@ int SymIsZP (SymEntry* S)
* enclosing scope for a symbol with the same name, and return the ZP
* attribute of this symbol if we find one.
*/
if (!IsLocal (S->Name) &&
if (!IsLocalNameId (S->Name) &&
(S->Flags & (SF_ZP | SF_ABS | SF_DEFINED | SF_IMPORT)) == 0 &&
S->SymTab->BackLink != 0) {
S->SymTab->Parent != 0) {
/* Try to find a symbol with the same name in the enclosing scope */
SymEntry* E = SymFindAny (S->SymTab->BackLink, S->Name);
SymEntry* E = SymFindAny (S->SymTab->Parent, S->Name);
/* If we found one, use the ZP flag */
if (E && (E->Flags & SF_ZP) != 0) {
@ -830,7 +901,7 @@ const char* GetSymName (SymEntry* S)
if (S->Flags & SF_TRAMPOLINE) {
S = S->V.Sym;
}
return S->Name;
return GetString (S->Name);
}
@ -877,7 +948,7 @@ static void SymCheckUndefined (SymEntry* S)
SymEntry* Sym = 0;
if (S->SymTab) {
/* It's a global symbol, get the higher level table */
SymTable* Tab = S->SymTab->BackLink;
SymTable* Tab = S->SymTab->Parent;
while (Tab) {
Sym = SymFindAny (Tab, S->Name);
if (Sym) {
@ -888,7 +959,7 @@ static void SymCheckUndefined (SymEntry* S)
break;
} else {
/* The symbol found is undefined itself. Look further */
Tab = Sym->SymTab->BackLink;
Tab = Sym->SymTab->Parent;
}
} else {
/* No symbol found */
@ -910,7 +981,7 @@ static void SymCheckUndefined (SymEntry* S)
if (S->Flags & SF_EXPORT) {
if (Sym->Flags & SF_IMPORT) {
/* The symbol is already marked as imported external symbol */
PError (&S->Pos, ERR_SYM_ALREADY_IMPORT, S->Name);
PError (&S->Pos, ERR_SYM_ALREADY_IMPORT, GetString (S->Name));
}
Sym->Flags |= S->Flags & (SF_EXPORT | SF_ZP);
}
@ -922,14 +993,14 @@ static void SymCheckUndefined (SymEntry* S)
/* The symbol is definitely undefined */
if (S->Flags & SF_EXPORT) {
/* We will not auto-import an export */
PError (&S->Pos, ERR_EXPORT_UNDEFINED, S->Name);
PError (&S->Pos, ERR_EXPORT_UNDEFINED, GetString (S->Name));
} else {
if (AutoImport) {
/* Mark as import, will be indexed later */
S->Flags |= SF_IMPORT;
} else {
/* Error */
PError (&S->Pos, ERR_SYM_UNDEFINED, S->Name);
PError (&S->Pos, ERR_SYM_UNDEFINED, GetString (S->Name));
}
}
}
@ -943,7 +1014,7 @@ void SymCheck (void)
SymEntry* S;
/* Check for open lexical levels */
if (SymTab->BackLink != 0) {
if (SymTab->Parent != 0) {
Error (ERR_OPEN_PROC);
}
@ -984,12 +1055,12 @@ void SymCheck (void)
(S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
/* Symbol was defined but never referenced */
PWarning (&S->Pos, WARN_SYM_NOT_REFERENCED, S->Name);
PWarning (&S->Pos, WARN_SYM_NOT_REFERENCED, GetString (S->Name));
}
if (S->Flags & SF_IMPORT) {
if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
/* Imported symbol is not referenced */
PWarning (&S->Pos, WARN_IMPORT_NOT_REFERENCED, S->Name);
PWarning (&S->Pos, WARN_IMPORT_NOT_REFERENCED, GetString (S->Name));
} else {
/* Give the import an index, count imports */
S->Index = ImportCount++;
@ -1020,7 +1091,7 @@ void SymDump (FILE* F)
if ((S->Flags & SF_TRAMPOLINE) != 0) {
fprintf (F,
"%-24s %s %s %s %s %s\n",
S->Name,
GetString (S->Name),
(S->Flags & SF_DEFINED)? "DEF" : "---",
(S->Flags & SF_REFERENCED)? "REF" : "---",
(S->Flags & SF_IMPORT)? "IMP" : "---",
@ -1060,7 +1131,7 @@ void WriteImports (void)
} else {
ObjWrite8 (IMP_ABS);
}
ObjWriteVar (GetStringId (S->Name));
ObjWriteVar (S->Name);
ObjWritePos (&S->Pos);
}
S = S->List;
@ -1137,7 +1208,7 @@ void WriteExports (void)
}
/* Write the name */
ObjWriteVar (GetStringId (S->Name));
ObjWriteVar (S->Name);
/* Write the value */
if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
@ -1201,7 +1272,7 @@ void WriteDbgSyms (void)
ObjWrite8 (ExprMask);
/* Write the name */
ObjWriteVar (GetStringId (S->Name));
ObjWriteVar (S->Name);
/* Write the value */
if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
@ -1231,3 +1302,4 @@ void WriteDbgSyms (void)

View File

@ -72,7 +72,7 @@
void SymEnterLevel (void);
void SymEnterLevel (const char* ScopeName);
/* Enter a new lexical level */
void SymLeaveLevel (void);