diff --git a/doc/ca65.sgml b/doc/ca65.sgml index b65d337bb..b68acb639 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 4812b12c4..904c80756 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -390,7 +390,20 @@ void MacDef (unsigned Style) { Macro* M; TokNode* N; + FilePos Pos; 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 + */ + 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 + */ + Pos = CurTok.Pos; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { @@ -491,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 */ - if (CurTok.Tok == TOK_ENDMACRO) { + /* 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) { - Error ("'.ENDMACRO' expected"); + PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name); goto Done; } } else { @@ -573,6 +588,11 @@ void MacDef (unsigned Style) } ++M->TokCount; + /* 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 */ NextTok (); } diff --git a/test/asm/err/endmacro.s b/test/asm/err/endmacro.s new file mode 100644 index 000000000..8907675fb --- /dev/null +++ b/test/asm/err/endmacro.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/endmacro.s b/test/asm/val/endmacro.s new file mode 100644 index 000000000..cfb8efefb --- /dev/null +++ b/test/asm/val/endmacro.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