]> git.sur5r.net Git - cc65/commitdiff
Added structs and unions, more work on scopes and expressions
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 13 Nov 2003 22:03:24 +0000 (22:03 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 13 Nov 2003 22:03:24 +0000 (22:03 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2662 b7a2c559-68d2-44c3-8de9-860c34a00d81

14 files changed:
src/ca65/make/gcc.mak
src/ca65/make/watcom.mak
src/ca65/nexttok.c
src/ca65/pseudo.c
src/ca65/scanner.c
src/ca65/scanner.h
src/ca65/struct.c [new file with mode: 0644]
src/ca65/struct.h [new file with mode: 0644]
src/ca65/symbol.c
src/ca65/symbol.h
src/ca65/symentry.c
src/ca65/symentry.h
src/ca65/symtab.c
src/ca65/symtab.h

index b8440d573d7d86289a31810e2d6d1e08676b8ad3..8fbfdbbba509bea196ad7b5181faac21894837ff 100644 (file)
@@ -38,6 +38,7 @@ OBJS =  anonname.o      \
         scanner.o      \
         segment.o       \
         spool.o         \
+        struct.o        \
         symentry.o      \
         symbol.o        \
         symtab.o       \
index 195fe866db4e085d51838d0b85af6d07b1e43d74..bcc4ab7743624441a0dba86dc3b9f74154a08bbd 100644 (file)
@@ -87,6 +87,7 @@ OBJS =        anonname.obj    \
        scanner.obj     \
         segment.obj     \
         spool.obj       \
+        struct.obj      \
        symbol.obj      \
         symentry.obj    \
        symtab.obj      \
index 9d58787f32f04c28144c91de7541254d1d368a48..5be1dfc8a19473ee8c30443ac746686e4ec62a44 100644 (file)
@@ -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 ();
index 4d6d945cb7be0868d0e1d7b5609252b1891a0f49..c3752168a1c2e0496b7d9ab986626abd1f966c46 100644 (file)
@@ -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 ();
     }
 
index 594584da593505473833f737d44352856c508aff..e75b73e02225af681e6d19ceb27dd1e5c3e30eb8 100644 (file)
@@ -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   },
index ed5d2614de08b9ecfebb7da3dd7744ad836de807..373fdb57b1112ab7f97bcde37c51ee9ef778ad0c 100644 (file)
@@ -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 (file)
index 0000000..69b8864
--- /dev/null
@@ -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 (file)
index 0000000..0444f8e
--- /dev/null
@@ -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
+
+
+
index 12b93f77c3cfe1bafd37ad219b70bee94a59ead2..685c0e45e416f8be2b39b46cc25d4f5a8d463645 100644 (file)
 
 
 /*****************************************************************************/
-/*                                          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;
+}
+
+
+
index 218806b05af86605dc438d3bdb367f5f0edc30a7..e8e1fa950c09cb4c1dc51d8a71d8804f84d3dc37 100644 (file)
@@ -7,7 +7,7 @@
 /*                                                                           */
 /*                                                                           */
 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 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.
  */
 
 
index dc56b7ba50d254a8f8cc10bb1cf32c06484316fe..a47fde9a64237f25ff6c35cc7ce616894a496368 100644 (file)
@@ -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 */
 {
index 46dba46faef884453b323a8b0f69249f6e26932c..a7b3bf3306cc5d55f442d1ad1f4ff0fe237a40ff 100644 (file)
@@ -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 */
 
index d21d0e1eb73f5833d326b7b677a72a98a3ca77ea..ca3966867c01fa75351c1cd79fc2464a592423eb 100644 (file)
@@ -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) {
index 86d0aa4caa8c40fe5405983968c16df48d9cd959..5873842678d749235923b29fb6e1d090b451fa79 100644 (file)
@@ -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 */