From: cuz Date: Wed, 3 Dec 2003 10:13:41 +0000 (+0000) Subject: Fixes for scoping and better .sizeof support X-Git-Tag: V2.12.0~1096 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=92a001d3af29c92621a3b7263acc19543b31cfc0;p=cc65 Fixes for scoping and better .sizeof support git-svn-id: svn://svn.cc65.org/cc65/trunk@2706 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 171ab44c7..ca6f24916 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -386,21 +386,26 @@ static ExprNode* FuncReferenced (void) static ExprNode* FuncSizeOf (void) /* Handle the .SIZEOF function */ { - StrBuf FullName = AUTO_STRBUF_INITIALIZER; + StrBuf ScopeName = AUTO_STRBUF_INITIALIZER; char Name[sizeof (SVal)]; SymTable* Scope; SymEntry* Sym; SymEntry* SizeSym; long Size; + int NoScope; + /* Assume an error */ + SizeSym = 0; + + /* Check for a cheap local which needs special handling */ if (Tok == TOK_LOCAL_IDENT) { - /* Cheap local symbol, special handling */ + /* Cheap local symbol */ Sym = SymFindLocal (SymLast, SVal, SYM_FIND_EXISTING); if (Sym == 0) { - Error ("Unknown symbol or scope: `%s'", SB_GetConstBuf (&FullName)); - return GenLiteralExpr (0); + Error ("Unknown symbol or scope: `%s%s'", + SB_GetConstBuf (&ScopeName), Name); } else { SizeSym = GetSizeOfSymbol (Sym); } @@ -408,33 +413,59 @@ static ExprNode* FuncSizeOf (void) } else { /* Parse the scope and the name */ - SymTable* ParentScope = ParseScopedIdent (Name, &FullName); - + SymTable* ParentScope = ParseScopedIdent (Name, &ScopeName); + /* Check if the parent scope is valid */ if (ParentScope == 0) { /* No such scope */ - DoneStrBuf (&FullName); + DoneStrBuf (&ScopeName); return GenLiteralExpr (0); } - - /* The scope is valid, search first for a child scope, then for a symbol */ - if ((Scope = SymFindScope (ParentScope, Name, SYM_FIND_EXISTING)) != 0) { + + /* If ScopeName is empty, no explicit scope was specified. We have to + * search upper scope levels in this case. + */ + NoScope = SB_IsEmpty (&ScopeName); + + /* First search for a scope with the given name */ + if (NoScope) { + Scope = SymFindAnyScope (ParentScope, Name); + } else { + Scope = SymFindScope (ParentScope, Name, SYM_FIND_EXISTING); + } + + /* If we did find a scope with the name, read the symbol defining the + * size, otherwise search for a symbol entry with the name and scope. + */ + if (Scope) { /* Yep, it's a scope */ SizeSym = GetSizeOfScope (Scope); - } else if ((Sym = SymFind (ParentScope, Name, SYM_FIND_EXISTING)) != 0) { - SizeSym = GetSizeOfSymbol (Sym); } else { - Error ("Unknown symbol or scope: `%s'", SB_GetConstBuf (&FullName)); - return GenLiteralExpr (0); + if (NoScope) { + Sym = SymFindAny (ParentScope, Name); + } else { + Sym = SymFind (ParentScope, Name, SYM_FIND_EXISTING); + } + + /* If we found the symbol retrieve the size, otherwise complain */ + if (Sym) { + SizeSym = GetSizeOfSymbol (Sym); + } else { + Error ("Unknown symbol or scope: `%s%s'", + SB_GetConstBuf (&ScopeName), Name); + } } } /* Check if we have a size */ if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) { - Error ("Size of `%s' is unknown", SB_GetConstBuf (&FullName)); - return GenLiteralExpr (0); + Error ("Size of `%s%s' is unknown", SB_GetConstBuf (&ScopeName), Name); + Size = 0; } + /* Free the scope name */ + DoneStrBuf (&ScopeName); + /* Return the size */ return GenLiteralExpr (Size); } diff --git a/src/ca65/symbol.c b/src/ca65/symbol.c index e4c46136d..a209f2209 100644 --- a/src/ca65/symbol.c +++ b/src/ca65/symbol.c @@ -53,14 +53,15 @@ -SymTable* ParseScopedIdent (char* Name, StrBuf* FullName) +SymTable* ParseScopedIdent (char* Name, StrBuf* ScopeName) /* Parse a (possibly scoped) identifer. Name must point to a buffer big enough * to hold such an identifier. 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. + * a symbol or a scope depending on the context is returned in Name. ScopeName + * is a string buffer that is used to store the name of the scope, the + * identifier lives in. It does contain anything but the identifier itself, so + * if ScopeName is empty on return, no explicit scope was specified. The full + * name of the identifier (including the scope) is ScopeName+Name. */ { /* Get the starting table */ @@ -73,23 +74,26 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* FullName) } else if (Tok == TOK_IDENT) { /* Remember the name and skip it */ - SB_AppendStr (FullName, strcpy (Name, SVal)); + strcpy (Name, SVal); NextTok (); /* If no namespace symbol follows, we're already done */ if (Tok != TOK_NAMESPACE) { - SB_Terminate (FullName); + SB_Terminate (ScopeName); return CurrentScope; } + /* Pass the scope back to the caller */ + SB_AppendStr (ScopeName, 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: `%s'", SB_GetConstBuf (FullName)); + SB_Terminate (ScopeName); + Error ("No such scope: `%s'", SB_GetConstBuf (ScopeName)); return 0; } @@ -97,14 +101,14 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* FullName) /* Invalid token */ Error ("Identifier expected"); - SB_Terminate (FullName); + SB_Terminate (ScopeName); Name[0] = '\0'; return 0; } /* Skip the namespace token that follows */ - SB_AppendStr (FullName, "::"); + SB_AppendStr (ScopeName, "::"); NextTok (); /* Resolve scopes. */ @@ -113,13 +117,13 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* FullName) /* Next token must be an identifier. */ if (Tok != TOK_IDENT) { Error ("Identifier expected"); - SB_Terminate (FullName); + SB_Terminate (ScopeName); Name[0] = '\0'; return 0; } /* Remember and skip the identifier */ - SB_AppendStr (FullName, strcpy (Name, SVal)); + strcpy (Name, SVal); NextTok (); /* If a namespace token follows, we search for another scope, otherwise @@ -127,25 +131,28 @@ SymTable* ParseScopedIdent (char* Name, StrBuf* FullName) */ if (Tok != TOK_NAMESPACE) { /* Symbol */ - SB_Terminate (FullName); + SB_Terminate (ScopeName); return Scope; } + /* Pass the scope back to the caller */ + SB_AppendStr (ScopeName, Name); + /* Search for the child scope */ Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING); if (Scope == 0) { /* Scope not found */ - SB_Terminate (FullName); - Error ("No such scope: `%s'", SB_GetConstBuf (FullName)); + SB_Terminate (ScopeName); + Error ("No such scope: `%s'", SB_GetConstBuf (ScopeName)); return 0; } /* Skip the namespace token that follows */ - SB_AppendStr (FullName, "::"); + SB_AppendStr (ScopeName, "::"); NextTok (); } } - + SymEntry* ParseScopedSymName (int AllocNew) @@ -153,32 +160,49 @@ SymEntry* ParseScopedSymName (int AllocNew) * and return the symbol table entry. */ { - StrBuf FullName = AUTO_STRBUF_INITIALIZER; + StrBuf ScopeName = AUTO_STRBUF_INITIALIZER; char Ident[sizeof (SVal)]; + int NoScope; + SymEntry* Sym; /* Parse the scoped symbol name */ - SymTable* Scope = ParseScopedIdent (Ident, &FullName); + SymTable* Scope = ParseScopedIdent (Ident, &ScopeName); - /* We don't need FullName any longer */ - DoneStrBuf (&FullName); + /* If ScopeName is empty, no scope was specified */ + NoScope = SB_IsEmpty (&ScopeName); + + /* We don't need ScopeName any longer */ + DoneStrBuf (&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 */ - return SymFind (Scope, Ident, AllocNew); + /* Search for the symbol and return it. If no scope was specified, + * search also in the upper levels. + */ + if (NoScope) { + Sym = SymFindAny (Scope, Ident); + if (Sym == 0 && AllocNew) { + Sym = SymFind (Scope, Ident, AllocNew); + } + } 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) { - return NewSymEntry (Ident, SF_NONE); + Sym = NewSymEntry (Ident, SF_NONE); } else { - return 0; + Sym = 0; } } + + /* Return the symbol found */ + return Sym; } @@ -188,21 +212,31 @@ SymTable* ParseScopedSymTable (void) * symbol space and return the symbol table struct. */ { - StrBuf FullName = AUTO_STRBUF_INITIALIZER; - char Ident[sizeof (SVal)]; + StrBuf ScopeName = AUTO_STRBUF_INITIALIZER; + char Name[sizeof (SVal)]; + int NoScope; + /* Parse the scoped symbol name */ - SymTable* Scope = ParseScopedIdent (Ident, &FullName); + SymTable* Scope = ParseScopedIdent (Name, &ScopeName); + + /* If ScopeName is empty, no scope was specified */ + NoScope = SB_IsEmpty (&ScopeName); /* We don't need FullName any longer */ - DoneStrBuf (&FullName); + DoneStrBuf (&ScopeName); - /* Check if the scope is valid. Errors have already been diagnosed by - * the routine, so just exit. + /* 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 */ - Scope = SymFindScope (Scope, Ident, SYM_FIND_EXISTING); + if (NoScope) { + Scope = SymFindAnyScope (Scope, Name); + } else { + Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING); + } } return Scope; } diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index 4fab0d7bc..68e2237c2 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -345,7 +345,7 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew) -static SymEntry* SymFindAny (SymTable* Scope, const char* Name) +SymEntry* SymFindAny (SymTable* Scope, const char* Name) /* Find a symbol 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. diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index 48b348474..22c0e778b 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -123,6 +123,12 @@ SymEntry* SymFind (SymTable* Scope, const char* Name, int AllocNew); * new entry created, or - in case AllocNew is zero - return 0. */ +SymEntry* SymFindAny (SymTable* Scope, const char* Name); +/* Find a symbol 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. + */ + int SymIsZP (SymEntry* Sym); /* Return true if the symbol is explicitly marked as zeropage symbol */