BUG: Fixed macro expansion bug that consumed new lines in nested macros
authorLukas Krickl <lukas@krickl.dev>
Fri, 11 Jul 2025 04:53:24 +0000 (06:53 +0200)
committerLukas Krickl <lukas@krickl.dev>
Fri, 11 Jul 2025 04:53:24 +0000 (06:53 +0200)
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
src/test.c
src/ulas.c
tests/t0.bin
tests/t0.s
tests/t0_dasm.s

diff --git a/BUGS.md b/BUGS.md
index 23564d6e077e48c040cc9fba8d40fd89f2461fbf..5eb8751bba8663b2b1d1ef5d43d3efc352652eea 100644 (file)
--- 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.
index 6ee4b6115c6e4b49cdd622057654b31f37c4082d..0fa1c239e6482f77d71720de779e95ce3d045191 100644 (file)
@@ -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");
 
index 40e6acade94f5c33089c28e26ff6e2c5469dba7d..127456a6dce507ee715b7465dec0ded0cc349260 100644 (file)
@@ -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
index d41e18491e41b6202e206a0b53959dbd95b81574..782f7d1c6efd1a8aa99f737553384837c6a3a5cb 100644 (file)
Binary files a/tests/t0.bin and b/tests/t0.bin differ
index 04c14b83d65d283f21dc539add280f8a21273f64..fe556b69bbb2a534fde23e1fd5d880b674368b88 100644 (file)
@@ -212,3 +212,13 @@ test_scoped:
 
 defarg2 DEFARG * arg_p, arg_p
 
+#macro nopnest1
+  nop
+  nopnest2
+#endmacro
+
+#macro nopnest2
+  nop
+#endmacro
+
+nopnest1
index 4191bb5be84c47de1ca912b702b043217bd28e1f..47f15d20c818052e172693eee93acd0720fd024d 100644 (file)
   nop 
   inc bc
   ld [bc], a
-.db 0x2
+  ld [bc], a
+  nop 
+.db 0x0