]> git.sur5r.net Git - cc65/blobdiff - src/ca65/symbol.c
Finished implemenation of commands to delete macros. Added the new commands to
[cc65] / src / ca65 / symbol.c
index 685c0e45e416f8be2b39b46cc25d4f5a8d463645..5f5abe560d0786194020de7819519bbfd9645a07 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -35,6 +35,9 @@
 
 #include <string.h>
 
+/* common */
+#include "strbuf.h"
+
 /* ca65 */
 #include "error.h"
 #include "nexttok.h"
 
 
 /*****************************************************************************/
-/*                                          Data                                    */
-/*****************************************************************************/
-
-
-
-/*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
 
-SymEntry* ParseScopedSymName (int AllocNew)
-/* Parse a (possibly scoped) symbol name, search for it in the symbol table
- * and return the symbol table entry.
+SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
+/* Parse a (possibly scoped) identifer. The scope of the name must exist and
+ * is returned as function result, while the last part (the identifier) which
+ * may be either a symbol or a scope depending on the context is returned in
+ * Name. FullName is a string buffer that is used to store the full name of
+ * the identifier including the scope. It is used internally and may be used
+ * by the caller for error messages or similar.
  */
 {
-    /* Get the starting table */
     SymTable* Scope;
-    if (Tok == TOK_NAMESPACE) {
+
+    /* Clear both passed string buffers */
+    SB_Clear (Name);
+    SB_Clear (FullName);
+
+    /* Get the starting table */
+    if (CurTok.Tok == TOK_NAMESPACE) {
+
+        /* Start from the root scope */
         Scope = RootScope;
+
+    } else if (CurTok.Tok == TOK_IDENT) {
+
+        /* Remember the name and skip it */
+        SB_Copy (Name, &CurTok.SVal);
         NextTok ();
+
+        /* If no namespace symbol follows, we're already done */
+        if (CurTok.Tok != TOK_NAMESPACE) {
+            SB_Terminate (FullName);
+            return CurrentScope;
+        }
+
+        /* Pass the scope back to the caller */
+        SB_Append (FullName, Name);
+                               
+        /* The scope must exist, so search for it starting with the current
+         * scope.
+         */
+        Scope = SymFindAnyScope (CurrentScope, Name);
+        if (Scope == 0) {
+            /* Scope not found */
+            SB_Terminate (FullName);
+            Error ("No such scope: `%m%p'", FullName);
+            return 0;
+        }
+
     } else {
-        Scope = CurrentScope;
-        /* ### Need to walk up the tree */
+
+        /* Invalid token */
+        Error ("Identifier expected");
+        return 0;
+
     }
 
-    /* Resolve scopes */
+    /* Skip the namespace token that follows */
+    SB_AppendStr (FullName, "::");
+    NextTok ();
+
+    /* Resolve scopes. */
     while (1) {
 
-        /* An identifier must follow. Remember and skip it. */
-        char Name[sizeof (SVal)];
-        if (Tok != TOK_IDENT) {
+        /* Next token must be an identifier. */
+        if (CurTok.Tok != TOK_IDENT) {
             Error ("Identifier expected");
             return 0;
         }
-        strcpy (Name, SVal);
+
+        /* Remember and skip the identifier */
+        SB_Copy (Name, &CurTok.SVal);
         NextTok ();
 
-        /* If the next token is a namespace token, handle the name as the
-         * name of a scope, otherwise it's the name of a symbol in that
-         * scope.
+        /* If a namespace token follows, we search for another scope, otherwise
+         * the name is a symbol and we're done.
          */
+        if (CurTok.Tok != TOK_NAMESPACE) {
+            /* Symbol */
+            return Scope;
+        }
 
-        if (Tok == TOK_NAMESPACE) {
-
-            /* Search for the child scope */
-            Scope = SymFindScope (Scope, Name, AllocNew);
+        /* Pass the scope back to the caller */
+        SB_Append (FullName, Name);
 
-           /* Skip the namespace token */
-           NextTok ();
+        /* Search for the child scope */
+        Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
+        if (Scope == 0) {
+            /* Scope not found */
+            Error ("No such scope: `%m%p'", FullName);
+            return 0;
+        }
 
-            /* If we didn't find the scope, bail out */
-            if (Scope == 0) {
-                return 0;
-            }
+        /* Skip the namespace token that follows */
+        SB_AppendStr (FullName, "::");
+        NextTok ();
+    }
+}
 
-        } else {
 
-            /* Search for the symbol and return it */
-            return SymFind (Scope, Name, AllocNew);
 
+SymEntry* ParseScopedSymName (int AllocNew)
+/* Parse a (possibly scoped) symbol name, search for it in the symbol table
+ * and return the symbol table entry.
+ */
+{
+    StrBuf    ScopeName = STATIC_STRBUF_INITIALIZER;
+    StrBuf    Ident = STATIC_STRBUF_INITIALIZER;
+    int       NoScope;
+    SymEntry* Sym;
+
+    /* Parse the scoped symbol name */
+    SymTable* Scope = ParseScopedIdent (&Ident, &ScopeName);
+
+    /* If ScopeName is empty, no scope was specified */
+    NoScope = SB_IsEmpty (&ScopeName);
+
+    /* We don't need ScopeName any longer */
+    SB_Done (&ScopeName);
+
+    /* Check if the scope is valid. Errors have already been diagnosed by
+     * the routine, so just exit.
+     */
+    if (Scope) {
+        /* Search for the symbol and return it. If no scope was specified,
+         * search also in the upper levels.
+         */
+        if (NoScope && !AllocNew) {
+            Sym = SymFindAny (Scope, &Ident);
+        } else {
+            Sym = SymFind (Scope, &Ident, AllocNew);
+        }
+    } else {
+        /* No scope ==> no symbol. To avoid errors in the calling routine that
+         * may not expect NULL to be returned if AllocNew is true, create a new
+         * symbol.
+         */
+        if (AllocNew) {
+            Sym = NewSymEntry (&Ident, SF_NONE);
+        } else {
+            Sym = 0;
         }
     }
+
+    /* Deallocate memory for ident */
+    SB_Done (&Ident);
+
+    /* Return the symbol found */
+    return Sym;
 }
 
 
 
-SymTable* ParseScopedSymTable (int AllocNew)
+SymTable* ParseScopedSymTable (void)
 /* 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;
-        }
+    StrBuf    ScopeName = STATIC_STRBUF_INITIALIZER;
+    StrBuf    Name = STATIC_STRBUF_INITIALIZER;
+    int       NoScope;
 
-        /* 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) {
+    /* Parse the scoped symbol name */
+    SymTable* Scope = ParseScopedIdent (&Name, &ScopeName);
 
-        /* Search for the child scope if we have a valid parent */
-        if (Scope) {
-            Scope = SymFindScope (Scope, SVal, AllocNew);
-        }
+    /* If ScopeName is empty, no scope was specified */
+    NoScope = SB_IsEmpty (&ScopeName);
 
-        /* Skip the name token */
-        NextTok ();
+    /* We don't need FullName any longer */
+    SB_Done (&ScopeName);
 
-        /* If a namespace token follows, read on, otherwise bail out */
-        if (Tok == TOK_NAMESPACE) {
-            NextTok ();
-            if (Tok != TOK_IDENT) {
-                Error ("Identifier expected");
-            }
+    /* If we got no error, search for the child scope withint the enclosing one.
+     * Beware: If no explicit parent scope was specified, search in all upper
+     * levels.
+     */
+    if (Scope) {
+        /* Search for the last scope */
+        if (NoScope) {
+            Scope = SymFindAnyScope (Scope, &Name);
         } else {
-            break;
+            Scope = SymFindScope (Scope, &Name, SYM_FIND_EXISTING);
         }
     }
 
-    /* Return the scope we found or created */
+    /* Free memory for name */
+    SB_Done (&Name);
+
+    /* Return the scope found */
     return Scope;
 }
 
 
 
+SymEntry* ParseAnySymName (int AllocNew)
+/* Parse a cheap local symbol or a a (possibly scoped) symbol name, search
+ * for it in the symbol table and return the symbol table entry.
+ */
+{
+    SymEntry* Sym;
+
+    /* Distinguish cheap locals and other symbols */
+    if (CurTok.Tok == TOK_LOCAL_IDENT) {
+        Sym = SymFindLocal (SymLast, &CurTok.SVal, AllocNew);
+        NextTok ();
+    } else {
+        Sym = ParseScopedSymName (AllocNew);
+    }
+
+    /* Return the symbol found */
+    return Sym;
+}
+
+
+