From 633e0a2d64ca2e4d7e8d90e7acbc293b1154d32d Mon Sep 17 00:00:00 2001 From: laubzega Date: Fri, 3 Jul 2020 19:18:11 -0700 Subject: [PATCH 1/3] Fix #796 (References inside of a scope aren't known outside of that scope.) --- src/ca65/expr.c | 3 ++- src/ca65/global.c | 3 +++ src/ca65/global.h | 3 +++ src/ca65/symbol.c | 26 ++++++++++++++++++++++---- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/ca65/expr.c b/src/ca65/expr.c index 8703b2a55..c3edca73a 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -83,7 +83,6 @@ static ExprNode* FreeExprNodes = 0; static unsigned FreeNodeCount = 0; - /*****************************************************************************/ /* Helpers */ /*****************************************************************************/ @@ -1629,8 +1628,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 a216fc406..82b08032b 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 77d90beca..2806656de 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 3b06fd1a2..e29e6ef51 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); @@ -180,7 +179,26 @@ SymEntry* ParseScopedSymName (SymFindAction Action) if (NoScope && (Action & SYM_ALLOC_NEW) == 0) { Sym = SymFindAny (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 ) { + Sym = SymFind (Scope, &Ident, Action); + } } } else { /* No scope ==> no symbol. To avoid errors in the calling routine that From 779461f4077c607cb2063d91bd45590d997948c4 Mon Sep 17 00:00:00 2001 From: laubzega Date: Sat, 4 Jul 2020 00:02:00 -0700 Subject: [PATCH 2/3] Second part of the experimental fix for #796. --- src/ca65/symbol.c | 6 +++++- src/ca65/symtab.c | 16 ++++++++++++++++ src/ca65/symtab.h | 6 ++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/ca65/symbol.c b/src/ca65/symbol.c index e29e6ef51..b48760b98 100644 --- a/src/ca65/symbol.c +++ b/src/ca65/symbol.c @@ -178,6 +178,9 @@ SymEntry* ParseScopedSymName (SymFindAction Action) */ if (NoScope && (Action & SYM_ALLOC_NEW) == 0) { Sym = SymFindAny (Scope, &Ident); + if (!Sym) { + Sym = SymFindInChildren(Scope, &Ident); + } } else { /* If we are processing a symbol within an expression, which the ** parser expects to be constant, that symbol had to be defined @@ -193,10 +196,11 @@ SymEntry* ParseScopedSymName (SymFindAction Action) 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 ) { + if (!Sym) { Sym = SymFind (Scope, &Ident, Action); } } diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index afe7b3ad6..d0a65c56c 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 (Scope && !Sym); + } + + 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 From 50df5845dc9c576d6a6f0668361dbe76c6337ed8 Mon Sep 17 00:00:00 2001 From: laubzega Date: Sat, 4 Jul 2020 00:17:04 -0700 Subject: [PATCH 3/3] Cleanup for #796 fix. --- src/ca65/symbol.c | 7 ++++--- src/ca65/symtab.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ca65/symbol.c b/src/ca65/symbol.c index b48760b98..760247e5c 100644 --- a/src/ca65/symbol.c +++ b/src/ca65/symbol.c @@ -178,8 +178,9 @@ SymEntry* ParseScopedSymName (SymFindAction Action) */ if (NoScope && (Action & SYM_ALLOC_NEW) == 0) { Sym = SymFindAny (Scope, &Ident); - if (!Sym) { - Sym = SymFindInChildren(Scope, &Ident); + + if (Sym == 0) { + Sym = SymFindInChildren (Scope, &Ident); } } else { /* If we are processing a symbol within an expression, which the @@ -200,7 +201,7 @@ SymEntry* ParseScopedSymName (SymFindAction Action) /* If still not found, or if in non-const expression, it will just ** get added to the current scope. */ - if (!Sym) { + if (Sym == 0) { Sym = SymFind (Scope, &Ident, Action); } } diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index d0a65c56c..f593b713d 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -431,9 +431,9 @@ SymEntry* SymFindInChildren (SymTable* Parent, const StrBuf* Name) if (Scope) { do { - Sym = SymFind(Scope, Name, SYM_CHECK_ONLY); + Sym = SymFind (Scope, Name, SYM_CHECK_ONLY); Scope = Scope->Next; - } while (Scope && !Sym); + } while (Sym == 0 && Scope != 0); } return Sym;