Fixed macro expansion not allowing #defines to expand
authorLukas Krickl <lukas@krickl.dev>
Mon, 4 Nov 2024 20:48:46 +0000 (21:48 +0100)
committerLukas Krickl <lukas@krickl.dev>
Mon, 4 Nov 2024 20:48:46 +0000 (21:48 +0100)
src/test.c
src/ulas.c
src/ulas.h
tests/t0.bin
tests/t0.s
tests/t0_dasm.s

index 8b912b2787721d68adba6edeb503f62c2bebca24..c54a422628b071c67aeae2329b14205c98baa6b4 100644 (file)
@@ -90,7 +90,7 @@ void test_strbuf(void) {
     FILE *dst = fmemopen(dstbuf, ULAS_LINEMAX, "we");                          \
     assert(ulas_preproc(dst, src) == (expect_ret));                            \
     fclose(src);                                                               \
-    fclose(dst);                                                               \
+    fclose(dst);         printf("%s\n", dstbuf);                                                      \
     assert(strcmp(dstbuf, (expect_dst)) == 0);                                 \
   }
 
@@ -123,12 +123,12 @@ void test_preproc(void) {
       "#macro test\n  line $1 1 label$$$$,$$ $$\n  line $2 2\n  line $3 3 "
       "$0\n#endmacro\ntest p1, p2, p3");
   assert_preproc("test macro with no args\n", 0,
-                 "#macro test\ntest macro with no args\n#endmacro\ntest");
+                 "#macro mtest\ntest macro with no args\n#endmacro\nmtest");
   assert_preproc("", -1, "#macro test\n not terminated\n");
   assert_preproc(
-      "nested macro t1\nafter\ncontent n1\n", 0,
-      "#macro test\nnested macro $1\n#macro "
-      "nested\ncontent $1\n#endmacro\nafter\nnested n1\n#endmacro\ntest t1");
+      "content 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");
 
   // this macro caused a heap buffer overflow in production code
   assert_preproc("ld a, verylongmacroinput & 0xFF\nld [hl+], a\nld a, "
index 4cca8619631ea23ee58de4b5f00c511b1bfbc7ef..a7767aa9b88c4a9c04c6552b9a62d783f69a2d7f 100644 (file)
@@ -959,6 +959,18 @@ char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line,
             strncat(pp->line.buf, tocat, tocatlen);
           }
         }
+        // expand macro result again to allow
+        // defines to appear in the macro
+        ulas_strensr(&pp->line2, strlen(pp->line.buf) + 1);
+        sprintf(pp->line2.buf, "%s", pp->line.buf);
+        unsigned long n = strlen(pp->line.buf);
+        pp->exp_depth++;
+        if (pp->exp_depth > ULAS_PREPROC_MAX_MACRO_DEPTH) {
+          ULASERR("Max macro recursion depth reached\n");
+          goto end;
+        }
+        ulas_preprocexpand(pp, pp->line2.buf, &n);
+        pp->exp_depth--;
         goto end;
       }
       }
@@ -1215,7 +1227,7 @@ int ulas_preprocnext(struct ulas_preproc *pp, FILE *dst, FILE *src, char *buf,
 }
 
 struct ulas_preproc ulas_preprocinit(void) {
-  struct ulas_preproc pp = {NULL, 0, ulas_str(1), ulas_str(1)};
+  struct ulas_preproc pp = {NULL, 0, ulas_str(1), ulas_str(1), ulas_str(1)};
   for (unsigned long i = 0; i < ULAS_MACROPARAMMAX; i++) {
     pp.macroparam[i] = ulas_str(8);
   }
@@ -1224,7 +1236,8 @@ struct ulas_preproc ulas_preprocinit(void) {
   // set up initial defs
   for (int i = 0; i < ulascfg.defslen; i++) {
 
-    struct ulas_ppdef def = {ULAS_PPDEF, strdup(ulascfg.defs[i]), strdup(""), 0};
+    struct ulas_ppdef def = {ULAS_PPDEF, strdup(ulascfg.defs[i]), strdup(""),
+                             0};
     ulas_preprocdef(&pp, def);
   }
 
@@ -1246,6 +1259,7 @@ void ulas_preprocclear(struct ulas_preproc *pp) {
 
 void ulas_preprocfree(struct ulas_preproc *pp) {
   ulas_strfree(&pp->line);
+  ulas_strfree(&pp->line2);
   ulas_strfree(&pp->tok);
 
   ulas_preprocclear(pp);
index f85c5bf9d6e87eb04ca35a80a1efdbe19c9e58b7..4d09d37eb4d89ca10e6cf871d5673b05ec3cb795 100644 (file)
@@ -263,12 +263,17 @@ struct ulas_symbuf {
  * Assembly context
  */
 
+#define ULAS_PREPROC_MAX_MACRO_DEPTH 255
+
 struct ulas_preproc {
   struct ulas_ppdef *defs;
   unsigned long defslen;
 
   struct ulas_str tok;
   struct ulas_str line;
+  struct ulas_str line2;
+
+  int exp_depth;
 
   // macro parameter buffers
   struct ulas_str macroparam[ULAS_MACROPARAMMAX];
index bd436c2f0552e558120389cc70d36fd5b7186cb6..aa1249716fb9bb1cc0ec9caa78676685e161935d 100644 (file)
Binary files a/tests/t0.bin and b/tests/t0.bin differ
index 684ffa3544f6f22e6237b8e261b0cdb00805b72b..10a7beeff0e1a3b4c177d41a5fade6827b42059a 100644 (file)
@@ -167,3 +167,12 @@ toplevel 5, 6
 #ifndef ULAS_PREDEF
   xor a, a
 #endif
+
+#define DEFARG 1
+
+#macro defarg 
+  .db $1 + 1, $2
+  .db $1
+#endmacro 
+
+defarg DEFARG, 2
index c682cadbf71155a019a1131b6c3f348f2b62e19c..bddc3eff18f0812f28aed49612590ddcbc8f6c1d 100644 (file)
   dec b
   inc b
   ld b, 0x76
-.db 0x76
+  halt 
+  ld [bc], a
+  ld [bc], a
+.db 0x1