diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index 6198f4017..a874aa1c6 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 (); @@ -447,6 +488,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 (); @@ -468,6 +526,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 2ce1ae087..3a6d5db51 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -2103,6 +2103,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoEndScope }, { ccNone, DoUnexpected }, /* .ENDSTRUCT */ { ccNone, DoUnexpected }, /* .ENDUNION */ + { ccKeepToken, DoConditionals }, /* .ENDWEAK */ { ccNone, DoEnum }, { ccNone, DoError }, { ccNone, DoExitMacro }, @@ -2203,6 +2204,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 185100025..2ef33ed0f 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -187,6 +187,7 @@ struct DotKeyword { { ".ENDSCOPE", TOK_ENDSCOPE }, { ".ENDSTRUCT", TOK_ENDSTRUCT }, { ".ENDUNION", TOK_ENDUNION }, + { ".ENDWEAK", TOK_ENDWEAK }, { ".ENUM", TOK_ENUM }, { ".ERROR", TOK_ERROR }, { ".EXITMAC", TOK_EXITMACRO }, @@ -300,6 +301,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 b8bbb6d6e..1583b3033 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, @@ -265,6 +266,7 @@ typedef enum token_t { TOK_UNION, TOK_VERSION, TOK_WARNING, + TOK_WEAKPROC, TOK_WORD, TOK_XMATCH, TOK_ZEROPAGE,