Added basic .rep directive
authorLukas Krickl <lukas@krickl.dev>
Sun, 24 Dec 2023 15:44:45 +0000 (16:44 +0100)
committerLukas Krickl <lukas@krickl.dev>
Sun, 24 Dec 2023 15:44:45 +0000 (16:44 +0100)
include/ulas.h
src/ulas.c
tests/t0.bin
tests/t0.s

index c05bfbf426587acb2a1805cf42de92248f0553a5..b06e5fbb029bdc68c07fa0ebe1213c961632c789 100644 (file)
@@ -411,7 +411,7 @@ enum ulas_asmdir {
   // it requires up to 8 integer expressions between 0 and 3
   ULAS_ASMDIR_CHR,
   // .rep <n>, <step>, <line>
-  // repeats a line n times 
+  // repeats a line n times
   ULAS_ASMDIR_REP,
 };
 
@@ -629,6 +629,7 @@ int ulas_asminstr(char *dst, unsigned long max, const char **line,
 //         -1 on error
 int ulas_asmnext(FILE *dst, FILE *src, char *buf, int n);
 int ulas_asm(FILE *dst, FILE *src);
+int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n);
 
 // parses and executes a 32 bit signed int math expressions
 int ulas_intexpr(const char **line, unsigned long n, int *rc);
index 67c43854eec604f4b6507e7293e6c690c9a637fc..0a11ad16c982834325b93bb12dac65586d5ca477 100644 (file)
@@ -2584,6 +2584,41 @@ int ulas_asmdirchr(FILE *dst, const char **line, unsigned long n, int *rc) {
   return written;
 }
 
+int ulas_asmdirrep(FILE *dst, FILE *src, const char **line, unsigned long n) {
+  int repval = 0;
+  int rc = 0;
+
+  ULAS_EVALEXPRS(repval = ulas_intexpr(line, n, &rc));
+  ulas_tok(&ulas.tok, line, n);
+  struct ulas_tok t =
+      ulas_totok(ulas.tok.buf, strnlen(ulas.tok.buf, ulas.tok.maxlen), &rc);
+  if (rc == -1 || t.type != ',') {
+    ULASERR("Expected ,\n");
+    return 0;
+  }
+
+  int step = 0;
+  ULAS_EVALEXPRS(step = ulas_intexpr(line, n, &rc));
+  ulas_tok(&ulas.tok, line, n);
+  t = ulas_totok(ulas.tok.buf, strnlen(ulas.tok.buf, ulas.tok.maxlen), &rc);
+  if (rc == -1 || t.type != ',') {
+    ULASERR("Expected ,\n");
+    return 0;
+  }
+
+  unsigned long argline_len = strlen(*line);
+
+  for (int i = 0; i < repval; i += step) {
+    rc = ulas_asmline(dst, src, *line, argline_len);
+    if (rc == -1) {
+      break;
+    }
+  }
+
+  *line += argline_len;
+  return rc;
+}
+
 int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
   // this buffer is written both to dst and to verbose output
   char outbuf[ULAS_OUTBUFMAX];
@@ -2618,22 +2653,14 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
   }
 
   if (ulas.tok.buf[0] == ULAS_TOK_ASMDIR_BEGIN) {
-    const char *dirstrs[] = {ULAS_ASMSTR_ORG,
-                             ULAS_ASMSTR_SET,
-                             ULAS_ASMSTR_BYTE,
-                             ULAS_ASMSTR_STR,
-                             ULAS_ASMSTR_FILL,
-                             ULAS_ASMSTR_PAD,
-                             ULAS_ASMSTR_INCBIN,
-                             ULAS_ASMSTR_DEF,
-                             ULAS_ASMSTR_CHKSM,
-                             ULAS_ASMSTR_ADV,
-                             ULAS_ASMSTR_SET_ENUM_DEF,
-                             ULAS_ASMSTR_DEFINE_ENUM,
-                             ULAS_ASMSTR_SETCHRCODE,
-                             ULAS_ASMSTR_CHR,
-                             ULAS_ASMSTR_REP,
-                             NULL};
+    const char *dirstrs[] = {ULAS_ASMSTR_ORG,          ULAS_ASMSTR_SET,
+                             ULAS_ASMSTR_BYTE,         ULAS_ASMSTR_STR,
+                             ULAS_ASMSTR_FILL,         ULAS_ASMSTR_PAD,
+                             ULAS_ASMSTR_INCBIN,       ULAS_ASMSTR_DEF,
+                             ULAS_ASMSTR_CHKSM,        ULAS_ASMSTR_ADV,
+                             ULAS_ASMSTR_SET_ENUM_DEF, ULAS_ASMSTR_DEFINE_ENUM,
+                             ULAS_ASMSTR_SETCHRCODE,   ULAS_ASMSTR_CHR,
+                             ULAS_ASMSTR_REP,          NULL};
     enum ulas_asmdir dirs[] = {
         ULAS_ASMDIR_ORG,          ULAS_ASMDIR_SET,
         ULAS_ASMDIR_BYTE,         ULAS_ASMDIR_STR,
@@ -2641,7 +2668,8 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
         ULAS_ASMDIR_INCBIN,       ULAS_ASMDIR_DEF,
         ULAS_ASMDIR_CHKSM,        ULAS_ASMDIR_ADV,
         ULAS_ASMDIR_SET_ENUM_DEF, ULAS_ASMDIR_DEFINE_ENUM,
-        ULAS_ASMDIR_SETCHRCODE,   ULAS_ASMDIR_CHR, ULAS_ASMDIR_REP};
+        ULAS_ASMDIR_SETCHRCODE,   ULAS_ASMDIR_CHR,
+        ULAS_ASMDIR_REP};
 
     enum ulas_asmdir dir = ULAS_ASMDIR_NONE;
 
@@ -2703,6 +2731,7 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
       other_writes += ulas_asmdirchr(dst, &line, n, &rc);
       break;
     case ULAS_ASMDIR_REP:
+      rc = ulas_asmdirrep(dst, src, &line, n);
       break;
     case ULAS_ASMDIR_PAD:
       // TODO: pad is the same as .fill n, $ - n
index 612d93adb5f4783ef8949eff6d2bbfa8334aaae0..d480d73b283696097da413d86de46765d34ebc83 100644 (file)
Binary files a/tests/t0.bin and b/tests/t0.bin differ
index 93ad7b80f889faeb5a76656da4893a4f7f199565..296c6fd1d3c0f94b4861930440eb53984fb58e31 100644 (file)
@@ -130,3 +130,5 @@ l3: .db 1
 .str "abc"
 .db 1, 2, 3
 .chr 01233213
+
+.rep 6, 2, halt