Work on named scopes
git-svn-id: svn://svn.cc65.org/cc65/trunk@2592 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
8abe61a32f
commit
fbdbf4d07c
12 changed files with 503 additions and 278 deletions
83
src/ca65/anonname.c
Normal file
83
src/ca65/anonname.c
Normal 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
62
src/ca65/anonname.h
Normal 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
|
||||
|
||||
|
||||
|
310
src/ca65/expr.c
310
src/ca65/expr.c
|
@ -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)
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -10,7 +10,8 @@ CC = gcc
|
|||
EBIND = emxbind
|
||||
LDFLAGS =
|
||||
|
||||
OBJS = asserts.o \
|
||||
OBJS = anonname.o \
|
||||
asserts.o \
|
||||
condasm.o \
|
||||
dbginfo.o \
|
||||
ea.o \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
|
||||
|
||||
|
||||
void SymEnterLevel (void);
|
||||
void SymEnterLevel (const char* ScopeName);
|
||||
/* Enter a new lexical level */
|
||||
|
||||
void SymLeaveLevel (void);
|
||||
|
|
Loading…
Add table
Reference in a new issue