diff --git a/src/ca65/make/gcc.mak b/src/ca65/make/gcc.mak index b8440d573..8fbfdbbba 100644 --- a/src/ca65/make/gcc.mak +++ b/src/ca65/make/gcc.mak @@ -38,6 +38,7 @@ OBJS = anonname.o \ scanner.o \ segment.o \ spool.o \ + struct.o \ symentry.o \ symbol.o \ symtab.o \ diff --git a/src/ca65/make/watcom.mak b/src/ca65/make/watcom.mak index 195fe866d..bcc4ab774 100644 --- a/src/ca65/make/watcom.mak +++ b/src/ca65/make/watcom.mak @@ -87,6 +87,7 @@ OBJS = anonname.obj \ scanner.obj \ segment.obj \ spool.obj \ + struct.obj \ symbol.obj \ symentry.obj \ symtab.obj \ diff --git a/src/ca65/nexttok.c b/src/ca65/nexttok.c index 9d58787f3..5be1dfc8a 100644 --- a/src/ca65/nexttok.c +++ b/src/ca65/nexttok.c @@ -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 (); diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 4d6d945cb..c3752168a 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -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 (); } diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 594584da5..e75b73e02 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -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 }, diff --git a/src/ca65/scanner.h b/src/ca65/scanner.h index ed5d2614d..373fdb57b 100644 --- a/src/ca65/scanner.h +++ b/src/ca65/scanner.h @@ -151,6 +151,7 @@ enum Token { TOK_ENDREP, TOK_ENDSCOPE, TOK_ENDSTRUCT, + TOK_ENDUNION, TOK_ERROR, TOK_EXITMACRO, TOK_EXPORT, diff --git a/src/ca65/struct.c b/src/ca65/struct.c new file mode 100644 index 000000000..69b8864e3 --- /dev/null +++ b/src/ca65/struct.c @@ -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); +} + + + diff --git a/src/ca65/struct.h b/src/ca65/struct.h new file mode 100644 index 000000000..0444f8e92 --- /dev/null +++ b/src/ca65/struct.h @@ -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 + + + diff --git a/src/ca65/symbol.c b/src/ca65/symbol.c index 12b93f77c..685c0e45e 100644 --- a/src/ca65/symbol.c +++ b/src/ca65/symbol.c @@ -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; +} + + + diff --git a/src/ca65/symbol.h b/src/ca65/symbol.h index 218806b05..e8e1fa950 100644 --- a/src/ca65/symbol.h +++ b/src/ca65/symbol.h @@ -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. */ diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index dc56b7ba5..a47fde9a6 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -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 */ { diff --git a/src/ca65/symentry.h b/src/ca65/symentry.h index 46dba46fa..a7b3bf330 100644 --- a/src/ca65/symentry.h +++ b/src/ca65/symentry.h @@ -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 */ diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index d21d0e1eb..ca3966867 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -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) { diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index 86d0aa4ca..587384267 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -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 */