From 477adc23fbd807f77f7765d0cda2ac051cd64d90 Mon Sep 17 00:00:00 2001 From: laubzega Date: Tue, 30 Jun 2020 20:36:13 -0700 Subject: [PATCH] Fix #1056. --- src/ca65/condasm.c | 61 +++++++++++++++++++++++++++++++++++++++++++++- src/ca65/pseudo.c | 2 ++ src/ca65/scanner.c | 2 ++ src/ca65/token.h | 2 ++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index b8bda4c7d..914096cae 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -32,6 +32,8 @@ /*****************************************************************************/ +#include "addrsize.h" +#include "scopedefs.h" /* ca65 */ #include "error.h" @@ -42,6 +44,7 @@ #include "symbol.h" #include "symtab.h" #include "condasm.h" +#include "pseudo.h" @@ -193,7 +196,7 @@ static void FreeIf (void) int Done; do { IfDesc* ID = GetCurrentIf(); - if (ID == 0) { + if (ID == 0 || strcmp(ID->Name, ".WEAKPROC") == 0) { Error (" Unexpected .ENDIF"); Done = 1; } else { @@ -205,6 +208,23 @@ static void FreeIf (void) } while (!Done); } +static void CheckNoWeak (void) +{ + int Done = 0; + + do { + IfDesc* ID = GetCurrentIf(); + if (ID == 0) { + Done = 1; + } else { + if (strcmp(ID->Name, ".WEAKPROC") == 0) { + Error (".WEAKPROC nesting not allowed"); + Done = 1; + } + } + } while (!Done); +} + /*****************************************************************************/ @@ -282,6 +302,27 @@ void DoConditionals (void) CalcOverallIfCond (); break; + case TOK_ENDWEAK: + D = GetCurrentIf(); + if (D == 0 || strcmp(D->Name, ".WEAKPROC") != 0) { + Error ("Unexpected .ENDWEAK"); + } else { + ReleaseFullLineInfo (&D->LineInfos); + DoneCollection (&D->LineInfos); + --IfCount; + } + if (CurrentScope->Type != SCOPE_SCOPE || CurrentScope->Label == 0) { + } else { + SymLeaveLevel (); + } + + NextTok (); + ExpectSep (); + + /* Get the new overall condition */ + CalcOverallIfCond (); + break; + case TOK_IF: D = AllocIf (".IF", 1); NextTok (); @@ -437,6 +478,23 @@ void DoConditionals (void) CalcOverallIfCond (); break; + case TOK_WEAKPROC: + CheckNoWeak(); + D = AllocIf (".WEAKPROC", 1); + NextTok (); + if (IfCond) { + SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); + SetIfCond (D, Sym != 0 && SymIsRef (Sym)); + + if (Sym != 0) { + SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); + SymEnterLevel (&CurTok.SVal, SCOPE_SCOPE, ADDR_SIZE_DEFAULT, Sym); + } + ExpectSep (); + } + CalcOverallIfCond (); + break; + default: /* Skip tokens */ NextTok (); @@ -458,6 +516,7 @@ int CheckConditionals (void) case TOK_ELSE: case TOK_ELSEIF: case TOK_ENDIF: + case TOK_ENDWEAK: case TOK_IF: case TOK_IFBLANK: case TOK_IFCONST: diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 5b2ef0573..cf6be94e7 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -2027,6 +2027,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoEndScope }, { ccNone, DoUnexpected }, /* .ENDSTRUCT */ { ccNone, DoUnexpected }, /* .ENDUNION */ + { ccKeepToken, DoConditionals }, /* .ENDWEAK */ { ccNone, DoEnum }, { ccNone, DoError }, { ccNone, DoExitMacro }, @@ -2121,6 +2122,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoUnion }, { ccNone, DoUnexpected }, /* .VERSION */ { ccNone, DoWarning }, + { ccKeepToken, DoConditionals }, /* .WEAKPROC */ { ccNone, DoWord }, { ccNone, DoUnexpected }, /* .XMATCH */ { ccNone, DoZeropage }, diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 361a817c1..0dd7e0f10 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -186,6 +186,7 @@ struct DotKeyword { { ".ENDSCOPE", TOK_ENDSCOPE }, { ".ENDSTRUCT", TOK_ENDSTRUCT }, { ".ENDUNION", TOK_ENDUNION }, + { ".ENDWEAK", TOK_ENDWEAK }, { ".ENUM", TOK_ENUM }, { ".ERROR", TOK_ERROR }, { ".EXITMAC", TOK_EXITMACRO }, @@ -292,6 +293,7 @@ struct DotKeyword { { ".UNION", TOK_UNION }, { ".VERSION", TOK_VERSION }, { ".WARNING", TOK_WARNING }, + { ".WEAKPROC", TOK_WEAKPROC }, { ".WORD", TOK_WORD }, { ".XMATCH", TOK_XMATCH }, { ".XOR", TOK_BOOLXOR }, diff --git a/src/ca65/token.h b/src/ca65/token.h index 8998cc162..f71ddf799 100644 --- a/src/ca65/token.h +++ b/src/ca65/token.h @@ -165,6 +165,7 @@ typedef enum token_t { TOK_ENDSCOPE, TOK_ENDSTRUCT, TOK_ENDUNION, + TOK_ENDWEAK, TOK_ENUM, TOK_ERROR, TOK_EXITMACRO, @@ -259,6 +260,7 @@ typedef enum token_t { TOK_UNION, TOK_VERSION, TOK_WARNING, + TOK_WEAKPROC, TOK_WORD, TOK_XMATCH, TOK_ZEROPAGE,