From 57fea9be9f1299c769582a948a0b8d8cf061d005 Mon Sep 17 00:00:00 2001 From: Lukas Krickl Date: Fri, 11 Jul 2025 06:53:24 +0200 Subject: [PATCH] BUG: Fixed macro expansion bug that consumed new lines in nested macros This was fixed by simply appending new lines to the start of the expansion list when a nested macro is used. This is not an ideal fix. The root cause of the macro going missing surely is in another place, however this is a decent enough solution for now. If the root cause of new lines being dropped in this case this commit should be reverted. --- BUGS.md | 17 ----------------- src/test.c | 2 +- src/ulas.c | 20 +++++++++++++++++++- tests/t0.bin | Bin 245 -> 247 bytes tests/t0.s | 10 ++++++++++ tests/t0_dasm.s | 4 +++- 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/BUGS.md b/BUGS.md index 23564d6..5eb8751 100644 --- a/BUGS.md +++ b/BUGS.md @@ -1,22 +1,5 @@ # Known Bugs -## Nested macros break if a macro expansion is used - -e.g. - -``` -#macro macro1 - nop - other_macro -#endmacro - -#macro other_macro - nop -#endmacro -``` - -This seems to be caused by the new line after the initial line (ld a, $1) being eaten. This likely happens during `pp_proc` that is applied to the already expanded macro. - ## .scc ' ' does not work `.scc ' ' = 100` results in an error. The expected result is for it to re-map the space character. diff --git a/src/test.c b/src/test.c index 6ee4b61..0fa1c23 100644 --- a/src/test.c +++ b/src/test.c @@ -126,7 +126,7 @@ void test_preproc(void) { "#macro mtest\ntest macro with no args\n#endmacro\nmtest"); assert_preproc("", -1, "#macro test\n not terminated\n"); assert_preproc( - "content macro t1\nt1\nafter\ncontent n1\n", 0, + "\ncontent macro t1\nt1\nafter\ncontent n1\n", 0, "#macro test\nmnested macro $1\n$1\n#macro " "mnested\ncontent $1\n#endmacro\nafter\nmnested n1\n#endmacro\ntest t1"); diff --git a/src/ulas.c b/src/ulas.c index 40e6aca..127456a 100644 --- a/src/ulas.c +++ b/src/ulas.c @@ -848,6 +848,8 @@ void ulas_trimend(char c, char *buf, unsigned long n) { } } +char *ulas_preprocexpand2(struct ulas_preproc *pp, const char *raw_line, + unsigned long *n, int recursive); void ulas_preprocexpand_rec(struct ulas_preproc *pp) { // expand macro result again to allow // defines to appear in the macro @@ -859,12 +861,17 @@ void ulas_preprocexpand_rec(struct ulas_preproc *pp) { ULASERR("Max macro recursion depth reached\n"); return; } - ulas_preprocexpand(pp, pp->line2.buf, &n); + ulas_preprocexpand2(pp, pp->line2.buf, &n, 1); pp->exp_depth--; } char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line, unsigned long *n) { + return ulas_preprocexpand2(pp, raw_line, n, 0); +} + +char *ulas_preprocexpand2(struct ulas_preproc *pp, const char *raw_line, + unsigned long *n, int recursive) { const char *praw_line = raw_line; memset(pp->line.buf, 0, pp->line.maxlen); @@ -968,6 +975,17 @@ char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line, const char *tocat = NULL; unsigned long tocatlen = 0; + // always start an expanded macro with a new line + // to ensure expansion are separated if we are in a recursive call + // this fixes new lines in recursive macros being consumed + if (recursive) { + int len = strnlen(pp->line.buf, pp->line.maxlen) + 1; + ulas_strensr(&pp->line, + len + 1); + strncat(pp->line.buf, "\n", len); + } + + // now tokenize the macro's value and look for $0-$9 // and replace those instances // eveyrthing else will just be copied as is diff --git a/tests/t0.bin b/tests/t0.bin index d41e18491e41b6202e206a0b53959dbd95b81574..782f7d1c6efd1a8aa99f737553384837c6a3a5cb 100644 GIT binary patch delta 9 Qcmey$_?>aWS0)Aq02Utub^rhX delta 6 Ncmey)_?2