From b2aceaea241d39cc7f821790579e77e70c71fd4a Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Sun, 1 Sep 2024 19:58:07 +0200 Subject: [PATCH 1/2] Fix behavior of .INCLUDE within a macro or .REPEAT. In the original code .INCLUDE was executed after expansion of the macro or .REPEAT - which was wrong and caused all sorts of unexpected behavior. Related issues/PRs are #231, #1473, #2159 and maybe others. Note: After this change error messages for nested macro/.include statements may be wrong. This is an unrelated bug that was always there and got exposed by this fix. The bug needs to be addressed in a separate PR. --- src/ca65/istack.c | 26 ++++++++++++++++++++++++++ src/ca65/istack.h | 20 ++++++++++++++++++++ src/ca65/scanner.c | 11 +++++++++-- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/ca65/istack.c b/src/ca65/istack.c index 7a95e7e8c..979c09740 100644 --- a/src/ca65/istack.c +++ b/src/ca65/istack.c @@ -156,3 +156,29 @@ void CheckInputStack (void) Error ("Open %s", IStack->Desc); } } + + + +InputStack RetrieveInputStack (void) +/* Retrieve the current input stack. This will also clear it. Used when +** including a file. The current input stack is stored together with the old +** input file and restored when the file is closed. + */ +{ + /* We do not touch the counter so input sources are counted across + ** includes. + */ + InputStack S = IStack; + IStack = 0; + return S; +} + + + +void RestoreInputStack (InputStack S) +/* Restore an old input stack that was retrieved by RetrieveInputStack(). */ +{ + CHECK (IStack == 0); + IStack = S; +} + diff --git a/src/ca65/istack.h b/src/ca65/istack.h index aa37bab14..28c413d39 100644 --- a/src/ca65/istack.h +++ b/src/ca65/istack.h @@ -38,6 +38,17 @@ +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Opaque pointer to an input stack */ +typedef void* InputStack; + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -63,6 +74,15 @@ void CheckInputStack (void); ** stuff on the input stack. */ +InputStack RetrieveInputStack (void); +/* Retrieve the current input stack. This will also clear it. Used when +** including a file. The current input stack is stored together with the old +** input file and restored when the file is closed. + */ + +void RestoreInputStack (InputStack S); +/* Restore an old input stack that was retrieved by RetrieveInputStack(). */ + /* End of istack.h */ diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 146c74958..89ff851fc 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -113,6 +113,7 @@ struct CharSource { token_t Tok; /* Last token */ int C; /* Last character */ int SkipN; /* For '\r\n' line endings, skip '\n\ if next */ + InputStack IStack; /* Saved input stack */ const CharSourceFunctions* Func; /* Pointer to function table */ union { InputFile File; /* File data */ @@ -321,6 +322,9 @@ static void UseCharSource (CharSource* S) S->Tok = CurTok.Tok; S->C = C; + /* Remember the current input stack */ + S->IStack = RetrieveInputStack (); + /* Use the new input source */ S->Next = Source; Source = S; @@ -347,7 +351,10 @@ static void DoneCharSource (void) /* Restore the old token */ CurTok.Tok = Source->Tok; - C = Source->C; + C = Source->C; + + /* Restore the old input source */ + RestoreInputStack (Source->IStack); /* Remember the last stacked input source */ S = Source->Next; @@ -1521,7 +1528,7 @@ CharAgain: /* In case of the main file, do not close it, but return EOF. */ if (Source && Source->Next) { DoneCharSource (); - goto Again; + goto Restart; } else { CurTok.Tok = TOK_EOF; } From cc0db26e20d4508f63db539ea619c57863e47d27 Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:22:29 +0200 Subject: [PATCH 2/2] Added some tests. --- test/asm/listing/070-include-macro.inc | 1 + test/asm/listing/070-include-macro.s | 13 +++++++++++++ test/asm/listing/070-include-repeat.inc | 1 + test/asm/listing/070-include-repeat.s | 4 ++++ test/asm/listing/ref/070-include-macro.err-ref | 1 + test/asm/listing/ref/070-include-repeat.err-ref | 6 ++++++ 6 files changed, 26 insertions(+) create mode 100644 test/asm/listing/070-include-macro.inc create mode 100644 test/asm/listing/070-include-macro.s create mode 100644 test/asm/listing/070-include-repeat.inc create mode 100644 test/asm/listing/070-include-repeat.s create mode 100644 test/asm/listing/ref/070-include-macro.err-ref create mode 100644 test/asm/listing/ref/070-include-repeat.err-ref diff --git a/test/asm/listing/070-include-macro.inc b/test/asm/listing/070-include-macro.inc new file mode 100644 index 000000000..0152a7965 --- /dev/null +++ b/test/asm/listing/070-include-macro.inc @@ -0,0 +1 @@ +foo: diff --git a/test/asm/listing/070-include-macro.s b/test/asm/listing/070-include-macro.s new file mode 100644 index 000000000..aad55cb52 --- /dev/null +++ b/test/asm/listing/070-include-macro.s @@ -0,0 +1,13 @@ +.macro IncludeFile FilePath + .proc bar + .include FilePath + .endproc +.endmacro + +IncludeFile "070-include-macro.inc" + +.ifdef bar::foo + .out "bar::foo is defined" +.else + .out "bar::foo is undefined" +.endif diff --git a/test/asm/listing/070-include-repeat.inc b/test/asm/listing/070-include-repeat.inc new file mode 100644 index 000000000..0eb22a710 --- /dev/null +++ b/test/asm/listing/070-include-repeat.inc @@ -0,0 +1 @@ +.out "include file" diff --git a/test/asm/listing/070-include-repeat.s b/test/asm/listing/070-include-repeat.s new file mode 100644 index 000000000..20170255f --- /dev/null +++ b/test/asm/listing/070-include-repeat.s @@ -0,0 +1,4 @@ +.repeat 3 + .include "070-include-repeat.inc" + .out "main file" +.endrepeat diff --git a/test/asm/listing/ref/070-include-macro.err-ref b/test/asm/listing/ref/070-include-macro.err-ref new file mode 100644 index 000000000..5faf98c4b --- /dev/null +++ b/test/asm/listing/ref/070-include-macro.err-ref @@ -0,0 +1 @@ +bar::foo is defined diff --git a/test/asm/listing/ref/070-include-repeat.err-ref b/test/asm/listing/ref/070-include-repeat.err-ref new file mode 100644 index 000000000..d42e70ee7 --- /dev/null +++ b/test/asm/listing/ref/070-include-repeat.err-ref @@ -0,0 +1,6 @@ +include file +main file +include file +main file +include file +main file