Added .de and .se for simple enum-like definitions
authorLukas Krickl <lukas@krickl.dev>
Fri, 15 Dec 2023 08:14:18 +0000 (09:14 +0100)
committerLukas Krickl <lukas@krickl.dev>
Fri, 15 Dec 2023 08:14:18 +0000 (09:14 +0100)
include/ulas.h
src/main.c
src/ulas.c
tests/t0.bin
tests/t0.s

index 1b9ec115c8b8997feae9382aa0b1cde83e039efd..8ea8f146ebb977c11698432f79609f8c6a2840d0 100644 (file)
@@ -46,6 +46,8 @@
 #define ULAS_ASMSTR_DEF ".def"
 #define ULAS_ASMSTR_CHKSM ".chksm"
 #define ULAS_ASMSTR_ADV ".adv"
+#define ULAS_ASMSTR_SET_ENUM_DEF ".se"
+#define ULAS_ASMSTR_DEFINE_ENUM ".de"
 
 // configurable tokens
 #define ULAS_TOK_COMMENT ';'
@@ -245,6 +247,7 @@ struct ulas {
   struct ulas_symbuf syms;
 
   unsigned int address;
+  int enumv;
 
   // current scope index
   // each global-label increments the scope
@@ -374,6 +377,13 @@ enum ulas_asmdir {
   // .adv <int>
   // advance .org by n bytes without writing to rom
   ULAS_ASMDIR_ADV,
+  // .setenum <int>
+  // sets the internal _ENUM counter
+  ULAS_ASMDIR_SET_ENUM_DEF,
+  // .de <size>
+  // acts like .def but sets the value to the current _ENUM counter
+  // and increments it by size
+  ULAS_ASMDIR_DEFINE_ENUM,
 };
 
 // amount of registers
index c5a24c0b108defacc06f4b51d89fc437244ed65b..94d7b8b9f079a9f50a4d4c6711e8a0eb2bb3ac74 100644 (file)
@@ -12,7 +12,8 @@
  * TODO: Write documentation
  * TODO: process defined variables inside defines correctly
  * TODO: Implement struct, union and enum syntax
- * TODO: Add warning levels such as: warning when literal is too large for register with -w syntax 
+ * TODO: Add warning levels such as: warning when literal is too large for
+ * register with -w syntax
  */
 
 #define ULAS_NAME "ulas"
index b622d4d59d9b95f2f69f64140abcd802fa00d3c7..d8ed1f2208f27852972f4945e853603a659cbc1b 100644 (file)
@@ -294,9 +294,10 @@ int ulas_symbolset(const char *cname, int scope, struct ulas_tok tok,
 
   if (!existing) {
     // def new symbol
-    struct ulas_sym new_sym = {strndup(name, len), tok, scope, ulas.pass, constant};
+    struct ulas_sym new_sym = {strndup(name, len), tok, scope, ulas.pass,
+                               constant};
     ulas_symbufpush(&ulas.syms, new_sym);
-    
+
     rc = ulas_symbolout(ulassymout, &new_sym);
   } else if (existing->lastdefin != ulas.pass || !existing->constant) {
     // redefine if not defined this pass
@@ -2344,6 +2345,40 @@ int ulas_asmdirdef(const char **line, unsigned long n) {
   return ulas_asmdirset(line, n, t);
 }
 
+int ulas_asmdirdefenum(const char **line, unsigned long n) {
+  char name[ULAS_SYMNAMEMAX];
+  ulas_tok(&ulas.tok, line, n);
+  if (!ulas_isname(ulas.tok.buf, ulas.tok.maxlen)) {
+    ULASERR("Unexpected token '%s'\n", ulas.tok.buf);
+    return -1;
+  }
+  strncpy(name, ulas.tok.buf, ULAS_SYMNAMEMAX);
+
+  // consume ,
+  ulas_tok(&ulas.tok, line, n);
+  if (strncmp(ulas.tok.buf, ",", ulas.tok.maxlen) != 0) {
+    ULASERR("Unexpected token '%s'. Expected ','\n", ulas.tok.buf);
+    return -1;
+  }
+
+  union ulas_val val = {0};
+  val.intv = ulas.enumv; 
+  
+  int rc = 0;
+  ulas.enumv += ulas_intexpr(line, n, &rc);
+  if (rc == -1) {
+    goto fail;
+  }
+  struct ulas_tok tok = {ULAS_INT, val};
+
+  if (ulas.pass == ULAS_PASS_FINAL) {
+    // only really define in final pass
+    ulas_symbolset(name, -1, tok, 1);
+  }
+fail:
+  return rc;
+}
+
 int ulas_asmdirfill(FILE *dst, const char **line, unsigned long n, int *rc) {
   // fill <what>, <how many>
   int written = 0;
@@ -2432,6 +2467,11 @@ int ulas_asmdiradv(FILE *dst, const char **line, unsigned long n, int *rc) {
   return 0;
 }
 
+int ulas_asmdirsetenum(FILE *dst, const char **line, unsigned long n, int *rc) {
+  ULAS_EVALEXPRS(ulas.enumv = ulas_intexpr(line, strnlen(*line, n), rc));
+  return 0;
+}
+
 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];
@@ -2476,11 +2516,14 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
                              ULAS_ASMSTR_DEF,
                              ULAS_ASMSTR_CHKSM,
                              ULAS_ASMSTR_ADV,
+                             ULAS_ASMSTR_SET_ENUM_DEF,
+                             ULAS_ASMSTR_DEFINE_ENUM,
                              NULL};
     enum ulas_asmdir dirs[] = {
-        ULAS_ASMDIR_ORG,   ULAS_ASMDIR_SET, ULAS_ASMDIR_BYTE,   ULAS_ASMDIR_STR,
-        ULAS_ASMDIR_FILL,  ULAS_ASMDIR_PAD, ULAS_ASMDIR_INCBIN, ULAS_ASMDIR_DEF,
-        ULAS_ASMDIR_CHKSM, ULAS_ASMDIR_ADV};
+        ULAS_ASMDIR_ORG,    ULAS_ASMDIR_SET,          ULAS_ASMDIR_BYTE,
+        ULAS_ASMDIR_STR,    ULAS_ASMDIR_FILL,         ULAS_ASMDIR_PAD,
+        ULAS_ASMDIR_INCBIN, ULAS_ASMDIR_DEF,          ULAS_ASMDIR_CHKSM,
+        ULAS_ASMDIR_ADV,    ULAS_ASMDIR_SET_ENUM_DEF, ULAS_ASMDIR_DEFINE_ENUM};
 
     enum ulas_asmdir dir = ULAS_ASMDIR_NONE;
 
@@ -2529,6 +2572,12 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
     case ULAS_ASMDIR_ADV:
       ulas_asmdiradv(dst, &line, n, &rc);
       break;
+    case ULAS_ASMDIR_SET_ENUM_DEF:
+      ulas_asmdirsetenum(dst, &line, n, &rc);
+      break;
+    case ULAS_ASMDIR_DEFINE_ENUM:
+      rc = ulas_asmdirdefenum(&line, n);
+      break;
     case ULAS_ASMDIR_PAD:
       // TODO: pad is the same as .fill n, $ - n
     case ULAS_ASMDIR_NONE:
index c6b2e04dd11c6d338b71fd4aa2bc396154860dee..86f977a0e689ae4e568fe83cd0d813bc2639d3d9 100644 (file)
Binary files a/tests/t0.bin and b/tests/t0.bin differ
index c68724f4eae0ed712c56c668ed830a59ecad1412..8e4ec050c80ef2029be38e402ebf3adc7d91167d 100644 (file)
@@ -114,3 +114,9 @@ l3: .db 1
 .def int dbtest = 0x213
 .db (dbtest & 0xFF)
 .db (dbtest >> 8) & 0xFF
+
+.se 0x21
+.de de1, 2
+.de de2, 1
+  ld a, de1
+  ld a, de2