mirror of
https://github.com/cc65/cc65.git
synced 2025-02-05 20:31:53 +00:00
Added structs and unions, more work on scopes and expressions
git-svn-id: svn://svn.cc65.org/cc65/trunk@2662 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
274bafe6a5
commit
20608c81ce
@ -38,6 +38,7 @@ OBJS = anonname.o \
|
||||
scanner.o \
|
||||
segment.o \
|
||||
spool.o \
|
||||
struct.o \
|
||||
symentry.o \
|
||||
symbol.o \
|
||||
symtab.o \
|
||||
|
@ -87,6 +87,7 @@ OBJS = anonname.obj \
|
||||
scanner.obj \
|
||||
segment.obj \
|
||||
spool.obj \
|
||||
struct.obj \
|
||||
symbol.obj \
|
||||
symentry.obj \
|
||||
symtab.obj \
|
||||
|
@ -422,7 +422,7 @@ void ConsumeSep (void)
|
||||
/* Accept an EOF as separator */
|
||||
if (Tok != TOK_EOF) {
|
||||
if (Tok != TOK_SEP) {
|
||||
Error ("Too many characters");
|
||||
Error ("Unexpected trailing garbage characters");
|
||||
SkipUntilSep ();
|
||||
} else {
|
||||
NextTok ();
|
||||
|
@ -69,6 +69,8 @@
|
||||
#include "repeat.h"
|
||||
#include "segment.h"
|
||||
#include "spool.h"
|
||||
#include "struct.h"
|
||||
#include "symbol.h"
|
||||
#include "symtab.h"
|
||||
|
||||
|
||||
@ -80,7 +82,7 @@
|
||||
|
||||
|
||||
/* Keyword we're about to handle */
|
||||
static char Keyword [sizeof (SVal)+1] = ".";
|
||||
static char Keyword [sizeof (SVal)+1];
|
||||
|
||||
/* Segment stack */
|
||||
#define MAX_PUSHED_SEGMENTS 16
|
||||
@ -1494,14 +1496,6 @@ static void DoSmart (void)
|
||||
|
||||
|
||||
|
||||
static void DoStruct (void)
|
||||
/* Struct definition */
|
||||
{
|
||||
Error ("Not implemented");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoSunPlus (void)
|
||||
/* Switch to the SUNPLUS CPU */
|
||||
{
|
||||
@ -1510,10 +1504,42 @@ static void DoSunPlus (void)
|
||||
|
||||
|
||||
|
||||
static void DoUnion (void)
|
||||
/* Union definition */
|
||||
static void DoTag (void)
|
||||
/* Allocate space for a struct */
|
||||
{
|
||||
Error ("Not implemented");
|
||||
long Size;
|
||||
|
||||
/* Read the struct name */
|
||||
SymTable* Struct = ParseScopedSymTable (SYM_FIND_EXISTING);
|
||||
|
||||
/* Check the supposed struct */
|
||||
if (Struct == 0) {
|
||||
ErrorSkip ("Unknown struct");
|
||||
return;
|
||||
}
|
||||
if (GetSymTabType (Struct) != ST_STRUCT) {
|
||||
ErrorSkip ("Not a struct");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the size of the struct */
|
||||
Size = GetSymVal (SymFind (Struct, ".size", SYM_FIND_EXISTING));
|
||||
|
||||
/* Optional multiplicator may follow */
|
||||
if (Tok == TOK_COMMA) {
|
||||
long Multiplicator;
|
||||
NextTok ();
|
||||
Multiplicator = ConstExpression ();
|
||||
/* Multiplicator must make sense */
|
||||
if (Multiplicator <= 0) {
|
||||
ErrorSkip ("Range error");
|
||||
return;
|
||||
}
|
||||
Size *= Multiplicator;
|
||||
}
|
||||
|
||||
/* Emit fill fragments */
|
||||
EmitFill (Size);
|
||||
}
|
||||
|
||||
|
||||
@ -1619,6 +1645,7 @@ static CtrlDesc CtrlCmdTab [] = {
|
||||
{ ccNone, DoUnexpected }, /* .ENDREPEAT */
|
||||
{ ccNone, DoEndScope },
|
||||
{ ccNone, DoUnexpected }, /* .ENDSTRUCT */
|
||||
{ ccNone, DoUnexpected }, /* .ENDUNION */
|
||||
{ ccNone, DoError },
|
||||
{ ccNone, DoExitMacro },
|
||||
{ ccNone, DoExport },
|
||||
@ -1686,7 +1713,7 @@ static CtrlDesc CtrlCmdTab [] = {
|
||||
{ ccNone, DoUnexpected }, /* .STRLEN */
|
||||
{ ccNone, DoStruct },
|
||||
{ ccNone, DoSunPlus },
|
||||
{ ccNone, DoUnexpected }, /* .TAG */
|
||||
{ ccNone, DoTag },
|
||||
{ ccNone, DoUnexpected }, /* .TCOUNT */
|
||||
{ ccNone, DoUnexpected }, /* .TIME */
|
||||
{ ccNone, DoUnion },
|
||||
@ -1733,7 +1760,7 @@ void HandlePseudo (void)
|
||||
|
||||
/* Remember the instruction, then skip it if needed */
|
||||
if ((D->Flags & ccKeepToken) == 0) {
|
||||
strcpy (Keyword+1, SVal);
|
||||
strcpy (Keyword, SVal);
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
|
@ -162,6 +162,7 @@ struct DotKeyword {
|
||||
{ ".ENDREPEAT", TOK_ENDREP },
|
||||
{ ".ENDSCOPE", TOK_ENDSCOPE },
|
||||
{ ".ENDSTRUCT", TOK_ENDSTRUCT },
|
||||
{ ".ENDUNION", TOK_ENDUNION },
|
||||
{ ".ERROR", TOK_ERROR },
|
||||
{ ".EXITMAC", TOK_EXITMACRO },
|
||||
{ ".EXITMACRO", TOK_EXITMACRO },
|
||||
|
@ -151,6 +151,7 @@ enum Token {
|
||||
TOK_ENDREP,
|
||||
TOK_ENDSCOPE,
|
||||
TOK_ENDSTRUCT,
|
||||
TOK_ENDUNION,
|
||||
TOK_ERROR,
|
||||
TOK_EXITMACRO,
|
||||
TOK_EXPORT,
|
||||
|
267
src/ca65/struct.c
Normal file
267
src/ca65/struct.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* struct.c */
|
||||
/* */
|
||||
/* .STRUCT command */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 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. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "addrsize.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "error.h"
|
||||
#include "expr.h"
|
||||
#include "nexttok.h"
|
||||
#include "scanner.h"
|
||||
#include "symbol.h"
|
||||
#include "symtab.h"
|
||||
#include "struct.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
enum {
|
||||
STRUCT,
|
||||
UNION
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static long Member (long AllocSize)
|
||||
/* Read one struct member and return its size */
|
||||
{
|
||||
long Multiplicator;
|
||||
|
||||
/* A comma and a multiplicator may follow */
|
||||
if (Tok == TOK_COMMA) {
|
||||
NextTok ();
|
||||
Multiplicator = ConstExpression ();
|
||||
if (Multiplicator <= 0) {
|
||||
Error ("Range error");
|
||||
Multiplicator = 1;
|
||||
}
|
||||
AllocSize *= Multiplicator;
|
||||
}
|
||||
|
||||
/* Return the size */
|
||||
return AllocSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long DoStructInternal (long Offs, unsigned Type)
|
||||
/* Handle the .STRUCT command */
|
||||
{
|
||||
long Size = 0;
|
||||
|
||||
/* Outside of other structs, we need a name. Inside another struct or
|
||||
* union, the struct may be anonymous, in which case no new lexical level
|
||||
* is started.
|
||||
*/
|
||||
int Anon = (Tok != TOK_IDENT);
|
||||
if (Anon) {
|
||||
unsigned char T = GetCurrentSymTabType ();
|
||||
if (T != ST_STRUCT) {
|
||||
ErrorSkip ("Struct/union needs a name");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Enter a new scope, then skip the name */
|
||||
SymEnterLevel (SVal, ST_STRUCT, ADDR_SIZE_ABS);
|
||||
NextTok ();
|
||||
/* Start at zero offset in the new scope */
|
||||
Offs = 0;
|
||||
}
|
||||
|
||||
/* Test for end of line */
|
||||
ConsumeSep ();
|
||||
|
||||
/* Read until end of struct */
|
||||
while (Tok != TOK_ENDSTRUCT && Tok != TOK_ENDUNION && Tok != TOK_EOF) {
|
||||
|
||||
long MemberSize;
|
||||
SymEntry* Sym;
|
||||
SymTable* Struct;
|
||||
|
||||
/* The format is "[identifier] storage-allocator [, multiplicator]" */
|
||||
if (Tok == TOK_IDENT) {
|
||||
/* We have an identifier, generate a symbol */
|
||||
Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW);
|
||||
|
||||
/* Assign the symbol the offset of the current member */
|
||||
SymDef (Sym, GenLiteralExpr (Offs), ADDR_SIZE_DEFAULT, SF_NONE);
|
||||
|
||||
/* Skip the member name */
|
||||
NextTok ();
|
||||
}
|
||||
|
||||
/* Read storage allocators */
|
||||
MemberSize = 0; /* In case of errors, use zero */
|
||||
switch (Tok) {
|
||||
|
||||
case TOK_BYTE:
|
||||
NextTok ();
|
||||
MemberSize = Member (1);
|
||||
break;
|
||||
|
||||
case TOK_DBYT:
|
||||
case TOK_WORD:
|
||||
case TOK_ADDR:
|
||||
NextTok ();
|
||||
MemberSize = Member (2);
|
||||
break;
|
||||
|
||||
case TOK_FARADDR:
|
||||
NextTok ();
|
||||
MemberSize = Member (3);
|
||||
break;
|
||||
|
||||
case TOK_DWORD:
|
||||
NextTok ();
|
||||
MemberSize = Member (4);
|
||||
break;
|
||||
|
||||
case TOK_RES:
|
||||
Error ("Not implemented");
|
||||
break;
|
||||
|
||||
case TOK_TAG:
|
||||
NextTok ();
|
||||
Struct = ParseScopedSymTable (SYM_FIND_EXISTING);
|
||||
if (Struct == 0) {
|
||||
Error ("Unknown struct/union");
|
||||
} else if (GetSymTabType (Struct) != ST_STRUCT) {
|
||||
Error ("Not a struct/union");
|
||||
} else {
|
||||
MemberSize = Member (GetStructSize (Struct));
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK_STRUCT:
|
||||
NextTok ();
|
||||
MemberSize = DoStructInternal (Offs, STRUCT);
|
||||
break;
|
||||
|
||||
case TOK_UNION:
|
||||
NextTok ();
|
||||
MemberSize = DoStructInternal (Offs, UNION);
|
||||
break;
|
||||
|
||||
default:
|
||||
Error ("Invalid storage allocator in struct/union");
|
||||
SkipUntilSep ();
|
||||
}
|
||||
|
||||
/* Next member */
|
||||
if (Type == STRUCT) {
|
||||
/* Struct */
|
||||
Offs += MemberSize;
|
||||
Size += MemberSize;
|
||||
} else {
|
||||
/* Union */
|
||||
if (MemberSize > Size) {
|
||||
Size = MemberSize;
|
||||
}
|
||||
}
|
||||
|
||||
/* Expect end of line */
|
||||
ConsumeSep ();
|
||||
}
|
||||
|
||||
/* If this is not a anon struct, enter a special symbol named ".size"
|
||||
* into the symbol table of the struct that holds the size of the
|
||||
* struct. Since the symbol starts with a dot, it cannot be accessed
|
||||
* by user code.
|
||||
* Leave the struct scope level.
|
||||
*/
|
||||
if (!Anon) {
|
||||
/* Add a symbol */
|
||||
SymEntry* SizeSym = SymFind (CurrentScope, ".size", SYM_ALLOC_NEW);
|
||||
SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE);
|
||||
|
||||
/* Close the struct scope */
|
||||
SymLeaveLevel ();
|
||||
}
|
||||
|
||||
/* End of struct/union definition */
|
||||
if (Type == STRUCT) {
|
||||
Consume (TOK_ENDSTRUCT, "`.ENDSTRUCT' expected");
|
||||
} else {
|
||||
Consume (TOK_ENDUNION, "`.ENDUNION' expected");
|
||||
}
|
||||
|
||||
/* Return the size of the struct */
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long GetStructSize (SymTable* Struct)
|
||||
/* Get the size of a struct or union */
|
||||
{
|
||||
SymEntry* Sym = SymFind (Struct, ".size", SYM_FIND_EXISTING);
|
||||
if (Sym == 0) {
|
||||
Error ("Size of struct/union is unknown");
|
||||
return 0;
|
||||
} else {
|
||||
return GetSymVal (Sym);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DoStruct (void)
|
||||
/* Handle the .STRUCT command */
|
||||
{
|
||||
DoStructInternal (0, STRUCT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DoUnion (void)
|
||||
/* Handle the .UNION command */
|
||||
{
|
||||
DoStructInternal (0, UNION);
|
||||
}
|
||||
|
||||
|
||||
|
73
src/ca65/struct.h
Normal file
73
src/ca65/struct.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* struct.h */
|
||||
/* */
|
||||
/* .STRUCT command */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2003 Ullrich von Bassewitz */
|
||||
/* Römerstraße 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 STRUCT_H
|
||||
#define STRUCT_H
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
struct SymTable;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
long GetStructSize (SymTable* Struct);
|
||||
/* Get the size of a struct */
|
||||
|
||||
void DoStruct (void);
|
||||
/* Handle the .STRUCT command */
|
||||
|
||||
void DoUnion (void);
|
||||
/* Handle the .UNION command */
|
||||
|
||||
|
||||
|
||||
/* End of struct.h */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -45,13 +45,13 @@
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -68,6 +68,7 @@ SymEntry* ParseScopedSymName (int AllocNew)
|
||||
NextTok ();
|
||||
} else {
|
||||
Scope = CurrentScope;
|
||||
/* ### Need to walk up the tree */
|
||||
}
|
||||
|
||||
/* Resolve scopes */
|
||||
@ -111,3 +112,61 @@ SymEntry* ParseScopedSymName (int AllocNew)
|
||||
|
||||
|
||||
|
||||
SymTable* ParseScopedSymTable (int AllocNew)
|
||||
/* Parse a (possibly scoped) symbol table (scope) name, search for it in the
|
||||
* symbol space and return the symbol table struct.
|
||||
*/
|
||||
{
|
||||
/* Get the starting table */
|
||||
SymTable* Scope;
|
||||
if (Tok == TOK_NAMESPACE) {
|
||||
Scope = RootScope;
|
||||
NextTok ();
|
||||
} else {
|
||||
Scope = CurrentScope;
|
||||
if (Tok != TOK_IDENT) {
|
||||
Error ("Identifier expected");
|
||||
return Scope;
|
||||
}
|
||||
|
||||
/* If no new scope should be allocated, the scope may specify any
|
||||
* scope in any of the parent scopes, so search for it.
|
||||
*/
|
||||
if (!AllocNew) {
|
||||
Scope = SymFindAnyScope (Scope, SVal);
|
||||
NextTok ();
|
||||
if (Tok != TOK_NAMESPACE) {
|
||||
return Scope;
|
||||
}
|
||||
NextTok ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Resolve scopes. */
|
||||
while (Tok == TOK_IDENT) {
|
||||
|
||||
/* Search for the child scope if we have a valid parent */
|
||||
if (Scope) {
|
||||
Scope = SymFindScope (Scope, SVal, AllocNew);
|
||||
}
|
||||
|
||||
/* Skip the name token */
|
||||
NextTok ();
|
||||
|
||||
/* If a namespace token follows, read on, otherwise bail out */
|
||||
if (Tok == TOK_NAMESPACE) {
|
||||
NextTok ();
|
||||
if (Tok != TOK_IDENT) {
|
||||
Error ("Identifier expected");
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the scope we found or created */
|
||||
return Scope;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
||||
/* Römerstrasse 52 */
|
||||
/* Römerstraße 52 */
|
||||
/* D-70794 Filderstadt */
|
||||
/* EMail: uz@cc65.org */
|
||||
/* */
|
||||
@ -53,6 +53,11 @@
|
||||
struct SymEntry* ParseScopedSymName (int AllowNew);
|
||||
/* Parse a (possibly scoped) symbol name, search for it in the symbol table
|
||||
* and return the symbol table entry.
|
||||
*/
|
||||
|
||||
struct SymTable* ParseScopedSymTable (int AllocNew);
|
||||
/* Parse a (possibly scoped) symbol table (scope) name, search for it in the
|
||||
* symbol space and return the symbol table struct.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -131,6 +131,43 @@ SymEntry* NewSymEntry (const char* Name)
|
||||
|
||||
|
||||
|
||||
int SymSearchTree (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,
|
||||
* 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.
|
||||
*/
|
||||
{
|
||||
/* Is there a tree? */
|
||||
if (T == 0) {
|
||||
*E = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We have a table, search it */
|
||||
while (1) {
|
||||
|
||||
/* Get the symbol name */
|
||||
const char* SymName = GetString (T->Name);
|
||||
|
||||
/* Choose next entry */
|
||||
int Cmp = strcmp (Name, SymName);
|
||||
if (Cmp < 0 && T->Left) {
|
||||
T = T->Left;
|
||||
} else if (Cmp > 0&& T->Right) {
|
||||
T = T->Right;
|
||||
} else {
|
||||
/* Found or end of search, return the result */
|
||||
*E = T;
|
||||
return Cmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SymRef (SymEntry* S)
|
||||
/* Mark the given symbol as referenced */
|
||||
{
|
||||
@ -580,7 +617,7 @@ const char* GetSymName (const SymEntry* S)
|
||||
|
||||
|
||||
|
||||
unsigned GetSymAddrSize (const SymEntry* S)
|
||||
unsigned char GetSymAddrSize (const SymEntry* S)
|
||||
/* Return the address size of the symbol. Beware: This function will just
|
||||
* return the AddrSize member, it will not look at the expression!
|
||||
*/
|
||||
@ -593,6 +630,18 @@ unsigned GetSymAddrSize (const SymEntry* S)
|
||||
|
||||
|
||||
|
||||
long GetSymVal (SymEntry* S)
|
||||
/* Return the value of a symbol assuming it's constant. FAIL will be called
|
||||
* in case the symbol is undefined or not constant.
|
||||
*/
|
||||
{
|
||||
long Val;
|
||||
CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val));
|
||||
return Val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned GetSymIndex (const SymEntry* S)
|
||||
/* Return the symbol index for the given symbol */
|
||||
{
|
||||
|
@ -116,6 +116,15 @@ int IsLocalNameId (unsigned Name);
|
||||
SymEntry* NewSymEntry (const char* Name);
|
||||
/* Allocate a symbol table entry, initialize and return it */
|
||||
|
||||
int SymSearchTree (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,
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr)
|
||||
/* Add an expression reference to this symbol */
|
||||
@ -195,11 +204,16 @@ const struct ExprNode* SymResolve (const SymEntry* Sym);
|
||||
const char* GetSymName (const SymEntry* Sym);
|
||||
/* Return the name of the symbol */
|
||||
|
||||
unsigned GetSymAddrSize (const SymEntry* Sym);
|
||||
unsigned char GetSymAddrSize (const SymEntry* Sym);
|
||||
/* Return the address size of the symbol. Beware: This function will just
|
||||
* return the AddrSize member, it will not look at the expression!
|
||||
*/
|
||||
|
||||
long GetSymVal (SymEntry* Sym);
|
||||
/* Return the value of a symbol assuming it's constant. FAIL will be called
|
||||
* in case the symbol is undefined or not constant.
|
||||
*/
|
||||
|
||||
unsigned GetSymIndex (const SymEntry* Sym);
|
||||
/* Return the symbol index for the given symbol */
|
||||
|
||||
|
@ -160,43 +160,6 @@ static SymTable* NewSymTable (SymTable* Parent, const char* Name)
|
||||
|
||||
|
||||
|
||||
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,
|
||||
* 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.
|
||||
*/
|
||||
{
|
||||
/* Is there a tree? */
|
||||
if (T == 0) {
|
||||
*E = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We have a table, search it */
|
||||
while (1) {
|
||||
|
||||
/* Get the symbol name */
|
||||
const char* SymName = GetString (T->Name);
|
||||
|
||||
/* Choose next entry */
|
||||
int Cmp = strcmp (Name, SymName);
|
||||
if (Cmp < 0 && T->Left) {
|
||||
T = T->Left;
|
||||
} else if (Cmp > 0&& T->Right) {
|
||||
T = T->Right;
|
||||
} else {
|
||||
/* Found or end of search, return the result */
|
||||
*E = T;
|
||||
return Cmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@ -272,6 +235,27 @@ SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew)
|
||||
|
||||
|
||||
|
||||
SymTable* SymFindAnyScope (SymTable* Parent, const char* Name)
|
||||
/* Find a scope 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.
|
||||
*/
|
||||
{
|
||||
SymTable* Scope;
|
||||
do {
|
||||
/* Search in the current table */
|
||||
Scope = SymFindScope (Parent, Name, SYM_FIND_EXISTING);
|
||||
if (Scope == 0) {
|
||||
/* Not found, search in the parent scope, if we have one */
|
||||
Parent = Parent->Parent;
|
||||
}
|
||||
} while (Scope == 0 && Parent != 0);
|
||||
|
||||
return Scope;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
@ -295,7 +279,7 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
|
||||
}
|
||||
|
||||
/* Search for the symbol if we have a table */
|
||||
Cmp = SearchSymTree (SymLast->Locals, Name, &S);
|
||||
Cmp = SymSearchTree (SymLast->Locals, Name, &S);
|
||||
|
||||
/* If we found an entry, return it */
|
||||
if (Cmp == 0) {
|
||||
@ -322,7 +306,7 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew)
|
||||
unsigned Hash = HashStr (Name) % Scope->TableSlots;
|
||||
|
||||
/* Search for the entry */
|
||||
Cmp = SearchSymTree (Scope->Table[Hash], Name, &S);
|
||||
Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
|
||||
|
||||
/* If we found an entry, return it */
|
||||
if (Cmp == 0) {
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
/* common */
|
||||
#include "exprdefs.h"
|
||||
#include "inline.h"
|
||||
|
||||
/* ca65 */
|
||||
#include "symentry.h"
|
||||
@ -62,7 +63,8 @@
|
||||
#define ST_GLOBAL 0x00 /* Root level */
|
||||
#define ST_PROC 0x01 /* .PROC */
|
||||
#define ST_SCOPE 0x02 /* .SCOPE */
|
||||
#define ST_STUCT 0x03 /* .STRUCT */
|
||||
#define ST_STRUCT 0x03 /* .STRUCT */
|
||||
#define ST_UNION 0x04 /* .UNION */
|
||||
#define ST_UNDEF 0xFF
|
||||
|
||||
/* A symbol table */
|
||||
@ -103,6 +105,12 @@ void SymLeaveLevel (void);
|
||||
SymTable* SymFindScope (SymTable* Parent, const char* Name, int AllocNew);
|
||||
/* Find a scope in the given enclosing scope */
|
||||
|
||||
SymTable* SymFindAnyScope (SymTable* Parent, const char* Name);
|
||||
/* Find a scope 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* 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
|
||||
@ -112,6 +120,16 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew);
|
||||
int SymIsZP (SymEntry* Sym);
|
||||
/* Return true if the symbol is explicitly marked as zeropage symbol */
|
||||
|
||||
#if defined(HAVE_INLINE)
|
||||
INLINE unsigned char GetSymTabType (const SymTable* S)
|
||||
/* Return the type of the given symbol table */
|
||||
{
|
||||
return S->Type;
|
||||
}
|
||||
#else
|
||||
# define GetSymTabType(S) ((S)->Type)
|
||||
#endif
|
||||
|
||||
unsigned char GetCurrentSymTabType ();
|
||||
/* Return the type of the current symbol table */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user