From e87325033d04955ea871e367f015b7ec508ae481 Mon Sep 17 00:00:00 2001 From: mvax Date: Sat, 25 Feb 2023 12:39:36 -0500 Subject: [PATCH 01/12] Fix .endmacro in a .define in a macro body --- src/ca65/macro.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 4812b12c4..16d916c88 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -391,6 +391,7 @@ void MacDef (unsigned Style) Macro* M; TokNode* N; int HaveParams; + int DefineActive = 0; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { @@ -491,8 +492,8 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed */ - if (CurTok.Tok == TOK_ENDMACRO) { + /* In classic macros, only .endmacro is allowed, but ignore it if it is in a .define */ + if (CurTok.Tok == TOK_ENDMACRO && !DefineActive) { /* Done */ break; } @@ -573,6 +574,13 @@ void MacDef (unsigned Style) } ++M->TokCount; + /* Mark if .define has been read until end of line has been reached */ + if (CurTok.Tok == TOK_DEFINE) { + DefineActive = 1; + } else if (TokIsSep(CurTok.Tok)) { + DefineActive = 0; + } + /* Read the next token */ NextTok (); } @@ -582,7 +590,7 @@ void MacDef (unsigned Style) NextTok (); } - /* Reset the Incomplete flag now that parsing is done */ +/* Reset the Incomplete flag now that parsing is done */ M->Incomplete = 0; Done: From 429e90dffdc326bbb23a332ea3b7b11dc67f8c67 Mon Sep 17 00:00:00 2001 From: mvax Date: Sat, 25 Feb 2023 12:42:26 -0500 Subject: [PATCH 02/12] Fix .endmacro in a .define in a macro body --- src/ca65/macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 16d916c88..24cdcad38 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -590,7 +590,7 @@ void MacDef (unsigned Style) NextTok (); } -/* Reset the Incomplete flag now that parsing is done */ + /* Reset the Incomplete flag now that parsing is done */ M->Incomplete = 0; Done: From 0a05f78d47c8a6ea20b97fd570d0f5db054aa387 Mon Sep 17 00:00:00 2001 From: mvax Date: Sat, 25 Feb 2023 13:38:02 -0500 Subject: [PATCH 03/12] Fix .endmacro not at the start of the line. --- src/ca65/macro.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 24cdcad38..c09b2412f 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -391,7 +391,7 @@ void MacDef (unsigned Style) Macro* M; TokNode* N; int HaveParams; - int DefineActive = 0; + int LastTokWasSep = 0; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { @@ -493,7 +493,7 @@ void MacDef (unsigned Style) /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { /* In classic macros, only .endmacro is allowed, but ignore it if it is in a .define */ - if (CurTok.Tok == TOK_ENDMACRO && !DefineActive) { + if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; } @@ -574,12 +574,8 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Mark if .define has been read until end of line has been reached */ - if (CurTok.Tok == TOK_DEFINE) { - DefineActive = 1; - } else if (TokIsSep(CurTok.Tok)) { - DefineActive = 0; - } + /* Save if last token was a separator to know if .endmacro is valid */ + LastTokWasSep = TokIsSep(CurTok.Tok); /* Read the next token */ NextTok (); From 4b29615f2bad008cc5a7b015616883a4e837972b Mon Sep 17 00:00:00 2001 From: mvax Date: Sat, 25 Feb 2023 13:49:19 -0500 Subject: [PATCH 04/12] Fix .endmacro not at the start of the line. Allow empty macro --- src/ca65/macro.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index c09b2412f..fa90009b5 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -480,6 +480,7 @@ void MacDef (unsigned Style) */ if (Style == MAC_STYLE_CLASSIC) { ConsumeSep (); + LastTokWasSep = 1; } else if (HaveParams) { ConsumeRParen (); } From 7d894fbe04f64aa0917404412cc5b14a1c970818 Mon Sep 17 00:00:00 2001 From: mvax Date: Sat, 25 Feb 2023 13:52:13 -0500 Subject: [PATCH 05/12] Fix .endmacro not at the start of the line. Fix comment --- src/ca65/macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index fa90009b5..92a0f6e9a 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -493,7 +493,7 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed, but ignore it if it is in a .define */ + /* In classic macros, only .endmacro is allowed, but ignore it if it is not at the start of the line */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; From 993054c9d300a222e3a7abbf9d7217fa4e47e4b3 Mon Sep 17 00:00:00 2001 From: mvax Date: Wed, 1 Mar 2023 11:58:42 -0500 Subject: [PATCH 06/12] Fix .endmacro not at the start of the line. .ENDMACRO error with line number of macro definition start --- src/ca65/macro.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 92a0f6e9a..84f0e8bcd 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -364,7 +364,7 @@ static void FreeMacExp (MacExp* E) -static void MacSkipDef (unsigned Style) +static void MacSkipDef (unsigned Style, FilePos Pos) /* Skip a macro definition */ { if (Style == MAC_STYLE_CLASSIC) { @@ -375,7 +375,7 @@ static void MacSkipDef (unsigned Style) if (CurTok.Tok != TOK_EOF) { SkipUntilSep (); } else { - Error ("'.ENDMACRO' expected"); + PError (&Pos, "'.ENDMACRO' expected"); } } else { /* Skip until end of line */ @@ -391,19 +391,26 @@ void MacDef (unsigned Style) Macro* M; TokNode* N; int HaveParams; - int LastTokWasSep = 0; + + /* Remember if we are at the beginning of the line. If the macro name + ** and parameters pass then this will be set, so set it now */ + int LastTokWasSep = 1; + + /* Save the position of the start of the macro definition to allow + ** using Perror to display the error if .ENDMACRO isn't found */ + FilePos Pos = CurTok.Pos; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected"); - MacSkipDef (Style); + MacSkipDef (Style, Pos); return; } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) { /* The identifier is a name of a 6502 instruction, which is not ** allowed if not explicitly enabled. */ Error ("Cannot use an instruction as macro name"); - MacSkipDef (Style); + MacSkipDef (Style, Pos); return; } @@ -412,7 +419,7 @@ void MacDef (unsigned Style) /* Macro is already defined */ Error ("A macro named '%m%p' is already defined", &CurTok.SVal); /* Skip tokens until we reach the final .endmacro */ - MacSkipDef (Style); + MacSkipDef (Style, Pos); return; } @@ -480,7 +487,6 @@ void MacDef (unsigned Style) */ if (Style == MAC_STYLE_CLASSIC) { ConsumeSep (); - LastTokWasSep = 1; } else if (HaveParams) { ConsumeRParen (); } @@ -493,14 +499,14 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed, but ignore it if it is not at the start of the line */ + /* In classic macros, only .endmacro is allowed, but do no exit the macro definition if not at the start of a line */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; } /* May not have end of file in a macro definition */ if (CurTok.Tok == TOK_EOF) { - Error ("'.ENDMACRO' expected"); + PError (&Pos, "'.ENDMACRO' expected"); goto Done; } } else { From 1c60bc50098ac981f05131eb4e85556f0cd0a5be Mon Sep 17 00:00:00 2001 From: mvax Date: Wed, 1 Mar 2023 21:47:50 -0500 Subject: [PATCH 07/12] Fix .endmacro not at the start of the line. Fix style, add doc., add tests --- doc/ca65.sgml | 14 +++++++++++++- src/ca65/macro.c | 35 ++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index b65d337bb..b19a66a2d 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2522,7 +2522,19 @@ See: ,

- Marks the end of a macro definition. + Marks the end of a macro definition. Note, .ENDMACRO should be on + its own line to successfully end the macro definition. It is possible to use + to create a symbol that references + .ENDMACRO without ending the macro definition. + + Example: + + + .macro new_mac + .define startmac .macro + .define endmac .endmacro + .endmacro + See: , , diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 84f0e8bcd..72436fdec 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -364,7 +364,7 @@ static void FreeMacExp (MacExp* E) -static void MacSkipDef (unsigned Style, FilePos Pos) +static void MacSkipDef (unsigned Style) /* Skip a macro definition */ { if (Style == MAC_STYLE_CLASSIC) { @@ -375,7 +375,7 @@ static void MacSkipDef (unsigned Style, FilePos Pos) if (CurTok.Tok != TOK_EOF) { SkipUntilSep (); } else { - PError (&Pos, "'.ENDMACRO' expected"); + Error ("'.ENDMACRO' expected"); } } else { /* Skip until end of line */ @@ -390,27 +390,32 @@ void MacDef (unsigned Style) { Macro* M; TokNode* N; + FilePos Pos; int HaveParams; + int LastTokWasSep; - /* Remember if we are at the beginning of the line. If the macro name - ** and parameters pass then this will be set, so set it now */ - int LastTokWasSep = 1; + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now + */ + LastTokWasSep = 1; /* Save the position of the start of the macro definition to allow - ** using Perror to display the error if .ENDMACRO isn't found */ - FilePos Pos = CurTok.Pos; + ** using Perror to display the error if .ENDMACRO isn't found + */ + Pos = CurTok.Pos; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected"); - MacSkipDef (Style, Pos); + MacSkipDef (Style); return; } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) { /* The identifier is a name of a 6502 instruction, which is not ** allowed if not explicitly enabled. */ Error ("Cannot use an instruction as macro name"); - MacSkipDef (Style, Pos); + MacSkipDef (Style); return; } @@ -419,7 +424,7 @@ void MacDef (unsigned Style) /* Macro is already defined */ Error ("A macro named '%m%p' is already defined", &CurTok.SVal); /* Skip tokens until we reach the final .endmacro */ - MacSkipDef (Style, Pos); + MacSkipDef (Style); return; } @@ -499,14 +504,16 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed, but do no exit the macro definition if not at the start of a line */ + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. + */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; } /* May not have end of file in a macro definition */ if (CurTok.Tok == TOK_EOF) { - PError (&Pos, "'.ENDMACRO' expected"); + PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name); goto Done; } } else { @@ -581,7 +588,9 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Save if last token was a separator to know if .endmacro is valid */ + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line + */ LastTokWasSep = TokIsSep(CurTok.Tok); /* Read the next token */ From 0b71d1cfff0bf3fd7d329701e231fb9b0bbb818a Mon Sep 17 00:00:00 2001 From: mvax Date: Wed, 1 Mar 2023 21:55:14 -0500 Subject: [PATCH 08/12] Fix .endmacro not at the start of the line. Fix last commit --- doc/ca65.sgml | 2 +- src/ca65/macro.c | 18 +++++++++--------- test/asm/err/bug2013.s | 6 ++++++ test/asm/val/bug2013.s | 30 ++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 test/asm/err/bug2013.s create mode 100644 test/asm/val/bug2013.s diff --git a/doc/ca65.sgml b/doc/ca65.sgml index b19a66a2d..b68acb639 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2522,7 +2522,7 @@ See: ,

- Marks the end of a macro definition. Note, .ENDMACRO should be on + Marks the end of a macro definition. Note, .ENDMACRO should be on its own line to successfully end the macro definition. It is possible to use to create a symbol that references .ENDMACRO without ending the macro definition. diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 72436fdec..6e059f421 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -394,14 +394,14 @@ void MacDef (unsigned Style) int HaveParams; int LastTokWasSep; - /* For classic macros, remember if we are at the beginning of the line. - ** If the macro name and parameters pass our checks then we will be on a - ** new line, so set it now + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now */ LastTokWasSep = 1; - /* Save the position of the start of the macro definition to allow - ** using Perror to display the error if .ENDMACRO isn't found + /* Save the position of the start of the macro definition to allow + ** using Perror to display the error if .ENDMACRO isn't found */ Pos = CurTok.Pos; @@ -504,8 +504,8 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, if .endmacro is not at the start of the line - ** it will be added to the macro definition instead of closing it. + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ @@ -588,8 +588,8 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Save if last token was a separator to know if .endmacro is at - ** the start of a line + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line */ LastTokWasSep = TokIsSep(CurTok.Tok); diff --git a/test/asm/err/bug2013.s b/test/asm/err/bug2013.s new file mode 100644 index 000000000..8907675fb --- /dev/null +++ b/test/asm/err/bug2013.s @@ -0,0 +1,6 @@ +; for PR #2013 +; should produce error output: +; ... Error: '.ENDMACRO' expected for macro 'test' + +.macro test + nop .endmacro diff --git a/test/asm/val/bug2013.s b/test/asm/val/bug2013.s new file mode 100644 index 000000000..b6e9e37e6 --- /dev/null +++ b/test/asm/val/bug2013.s @@ -0,0 +1,30 @@ +; for PR #2013 + .import _exit + .export _main + + ; this macro is invalid, but should not cause an error (if it is never expanded) + .macro invalid + nop .endmacro + .endmacro + + .define temp_endmac .endmacro + .macro new_mac + .define startmac .macro + .define endmac .endmacro + temp_endmac + + .undefine temp_endmac + + new_mac + + startmac dex2 + dex + dex + endmac + +_main: + ldx #$02 + dex2 + ; x should be zero + txa + jmp _exit \ No newline at end of file From 98d2d9ee4e3d86c1d44d9a1d696d631031cdeffe Mon Sep 17 00:00:00 2001 From: mvax Date: Wed, 1 Mar 2023 21:59:00 -0500 Subject: [PATCH 09/12] Fix .endmacro not at the start of the line. Fix style --- test/asm/val/bug2013.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/asm/val/bug2013.s b/test/asm/val/bug2013.s index b6e9e37e6..cfb8efefb 100644 --- a/test/asm/val/bug2013.s +++ b/test/asm/val/bug2013.s @@ -27,4 +27,4 @@ _main: dex2 ; x should be zero txa - jmp _exit \ No newline at end of file + jmp _exit From 3f2129894be43d2840c28c5a33cd39c306984c1e Mon Sep 17 00:00:00 2001 From: mvax Date: Thu, 2 Mar 2023 15:12:30 -0500 Subject: [PATCH 10/12] Fix .endmacro not at the start of the line. Rename test files. --- test/asm/err/{bug2013.s => endmacro.s} | 0 test/asm/val/{bug2013.s => endmacro.s} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/asm/err/{bug2013.s => endmacro.s} (100%) rename test/asm/val/{bug2013.s => endmacro.s} (100%) diff --git a/test/asm/err/bug2013.s b/test/asm/err/endmacro.s similarity index 100% rename from test/asm/err/bug2013.s rename to test/asm/err/endmacro.s diff --git a/test/asm/val/bug2013.s b/test/asm/val/endmacro.s similarity index 100% rename from test/asm/val/bug2013.s rename to test/asm/val/endmacro.s From 90d5f41b377dfe810758c3cfdd0dd42d735a3bc7 Mon Sep 17 00:00:00 2001 From: mvax Date: Thu, 2 Mar 2023 17:26:05 -0500 Subject: [PATCH 11/12] Consistent case for .endmacro in comments --- src/ca65/macro.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 6e059f421..d776411be 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -394,14 +394,14 @@ void MacDef (unsigned Style) int HaveParams; int LastTokWasSep; - /* For classic macros, remember if we are at the beginning of the line. - ** If the macro name and parameters pass our checks then we will be on a - ** new line, so set it now + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now */ LastTokWasSep = 1; - /* Save the position of the start of the macro definition to allow - ** using Perror to display the error if .ENDMACRO isn't found + /* Save the position of the start of the macro definition to allow + ** using Perror to display the error if .endmacro isn't found */ Pos = CurTok.Pos; @@ -504,8 +504,8 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, if .endmacro is not at the start of the line - ** it will be added to the macro definition instead of closing it. + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ @@ -588,8 +588,8 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Save if last token was a separator to know if .endmacro is at - ** the start of a line + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line */ LastTokWasSep = TokIsSep(CurTok.Tok); From c092f57b73a92b6db55d43a4b4f649059d77bf2e Mon Sep 17 00:00:00 2001 From: mvax Date: Thu, 2 Mar 2023 17:31:55 -0500 Subject: [PATCH 12/12] Consistent case for .endmacro in comments, remove trailing spaces --- src/ca65/macro.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index d776411be..904c80756 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -394,13 +394,13 @@ void MacDef (unsigned Style) int HaveParams; int LastTokWasSep; - /* For classic macros, remember if we are at the beginning of the line. - ** If the macro name and parameters pass our checks then we will be on a - ** new line, so set it now + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now */ LastTokWasSep = 1; - /* Save the position of the start of the macro definition to allow + /* Save the position of the start of the macro definition to allow ** using Perror to display the error if .endmacro isn't found */ Pos = CurTok.Pos; @@ -504,8 +504,8 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, if .endmacro is not at the start of the line - ** it will be added to the macro definition instead of closing it. + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. */ if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ @@ -588,8 +588,8 @@ void MacDef (unsigned Style) } ++M->TokCount; - /* Save if last token was a separator to know if .endmacro is at - ** the start of a line + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line */ LastTokWasSep = TokIsSep(CurTok.Tok);