diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 5dcf5ca71..67b00436d 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -83,7 +83,6 @@ static ExprNode* FreeExprNodes = 0; static unsigned FreeNodeCount = 0; - /*****************************************************************************/ /* Helpers */ /*****************************************************************************/ @@ -1646,8 +1645,10 @@ long ConstExpression (void) { long Val; + ProcessingConst = 1; /* Read the expression */ ExprNode* Expr = Expression (); + ProcessingConst = 0; /* Study the expression */ ExprDesc D; diff --git a/src/ca65/global.c b/src/ca65/global.c index 050d19e09..d957b4324 100644 --- a/src/ca65/global.c +++ b/src/ca65/global.c @@ -58,6 +58,9 @@ StrBuf FullDepName = STATIC_STRBUF_INITIALIZER; /* Full dependency file */ const char ObjExt[] = ".o";/* Default object extension */ char LocalStart = '@'; /* This char starts local symbols */ +unsigned char ProcessingConst = 0; /* Currently processed expression + ** is supposed to be const + */ unsigned char IgnoreCase = 0; /* Ignore case on identifiers? */ unsigned char AutoImport = 0; /* Mark unresolveds as import */ diff --git a/src/ca65/global.h b/src/ca65/global.h index b3de99df5..02dd49ef1 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -60,6 +60,9 @@ extern StrBuf FullDepName; /* Name of full dependencies file */ extern const char ObjExt[]; /* Default object extension */ extern char LocalStart; /* This char starts local symbols */ +extern unsigned char ProcessingConst; /* Currently processed expression + ** is supposed to be const + */ extern unsigned char IgnoreCase; /* Ignore case on identifiers? */ extern unsigned char AutoImport; /* Mark unresolveds as import */ diff --git a/src/ca65/symbol.c b/src/ca65/symbol.c index f1c259082..f75728bd4 100644 --- a/src/ca65/symbol.c +++ b/src/ca65/symbol.c @@ -40,12 +40,11 @@ /* ca65 */ #include "error.h" +#include "global.h" #include "nexttok.h" #include "scanner.h" #include "symbol.h" - - /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -159,7 +158,7 @@ SymEntry* ParseScopedSymName (SymFindAction Action) StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; StrBuf Ident = STATIC_STRBUF_INITIALIZER; int NoScope; - SymEntry* Sym; + SymEntry* Sym = 0; /* Parse the scoped symbol name */ SymTable* Scope = ParseScopedIdent (&Ident, &ScopeName); @@ -179,8 +178,32 @@ SymEntry* ParseScopedSymName (SymFindAction Action) */ if (NoScope && (Action & SYM_ALLOC_NEW) == 0) { Sym = SymFindAny (Scope, &Ident); + + if (Sym == 0) { + Sym = SymFindInChildren (Scope, &Ident); + } } else { - Sym = SymFind (Scope, &Ident, Action); + /* If we are processing a symbol within an expression, which the + ** parser expects to be constant, that symbol had to be defined + ** already for the expression to resolve correctly. Search for it + ** in the current scope first, and if not found, retry in all + ** enclosing scopes. + */ + + if ((Action & SYM_ALLOC_NEW) && ProcessingConst) { + Sym = SymFind (Scope, &Ident, SYM_FIND_EXISTING); + + if (Sym == 0) { + Sym = SymFindAny (Scope, &Ident); + } + } + + /* If still not found, or if in non-const expression, it will just + ** get added to the current scope. + */ + if (Sym == 0) { + Sym = SymFind (Scope, &Ident, Action); + } } } else { /* No scope ==> no symbol. To avoid errors in the calling routine that diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index a01d14bd8..0924e66db 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -424,6 +424,22 @@ SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action) } +SymEntry* SymFindInChildren (SymTable* Parent, const StrBuf* Name) +{ + SymTable* Scope = Parent->Childs; + SymEntry* Sym = 0; + + if (Scope) { + do { + Sym = SymFind (Scope, Name, SYM_CHECK_ONLY); + Scope = Scope->Next; + } while (Sym == 0 && Scope != 0); + } + + return Sym; +} + + SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name) /* Find a symbol in the given or any of its parent scopes. The function will diff --git a/src/ca65/symtab.h b/src/ca65/symtab.h index 7e7a9009c..37069a815 100644 --- a/src/ca65/symtab.h +++ b/src/ca65/symtab.h @@ -122,6 +122,12 @@ SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Acti ** created, or - in case Action is SYM_FIND_EXISTING - return 0. */ +SymEntry* SymFindInChildren (SymTable* Scope, const StrBuf* Name); +/* Find a symbol in children scopes of given scope (if they exist). The +** function will never create a new symbol, since this can only be done in one +** specific scope. +*/ + SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action); /* Find a new symbol table entry in the given table. If Action contains ** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the