aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-11-10 22:36:25 +0100
committerXavier Del Campo Romero <xavi92@disroot.org>2025-11-12 00:45:34 +0100
commita83684db1c1f24b9d744e7b6078e819bf44d169d (patch)
tree4e4b5f0001d87abeabdba1c5cdc394e8d214cb89
parent0086ccf0272fa195dca36845fde9c54149c72f0e (diff)
downloadnwc-a83684db1c1f24b9d744e7b6078e819bf44d169d.tar.gz
Support if/else
-rw-r--r--read_instr.c119
-rw-r--r--types.h1
2 files changed, 117 insertions, 3 deletions
diff --git a/read_instr.c b/read_instr.c
index 805326c..7f7d2a6 100644
--- a/read_instr.c
+++ b/read_instr.c
@@ -358,6 +358,21 @@ static bool branch(const uint8_t op)
return false;
}
+static bool cbranch(const uint8_t op)
+{
+ switch (op)
+ {
+ case OP_IF:
+ case OP_ELSE:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
struct block
{
uint8_t op;
@@ -470,7 +485,7 @@ static int add_branch(const uint8_t op, struct lo *const lo, const struct blocks
struct lo_entry *const e = &ve[lo->n++];
- *e = (const struct lo_entry){.b = tgt, .pc = offset};
+ *e = (const struct lo_entry){.op = op, .b = tgt, .pc = offset};
if (tgt->op == OP_LOOP)
e->dst = tgt->pc;
@@ -479,6 +494,50 @@ static int add_branch(const uint8_t op, struct lo *const lo, const struct blocks
return 0;
}
+static int add_cbranch(const uint8_t op, struct lo *const lo,
+ const struct blocks *const b, const unsigned level, FILE *const f)
+{
+ const long offset = ftell(f);
+
+ if (offset < 0)
+ {
+ fprintf(stderr, "%s: ftell(3): %s\n", __func__,
+ strerror(errno));
+ return -1;
+ }
+
+ const struct block *tgt = NULL;
+
+ for (const struct block *bl = b->tail; bl; bl = bl->prev)
+ if (bl->op == OP_IF && bl->level == level)
+ {
+ tgt = bl;
+ break;
+ }
+
+ if (!tgt)
+ {
+ fprintf(stderr, "%s: could not find matching block, pc=%ld\n",
+ __func__, offset);
+ return -1;
+ }
+
+ const size_t n = lo->n + 1;
+ struct lo_entry *const ve = realloc(lo->entries, n * sizeof *lo->entries);
+
+ if (!ve)
+ {
+ fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+
+ struct lo_entry *const e = &ve[lo->n++];
+
+ *e = (const struct lo_entry){.op = op, .b = tgt, .pc = offset};
+ lo->entries = ve;
+ return 0;
+}
+
static int set_end(struct lo *const lo, const struct blocks *const b,
const unsigned level, FILE *const f)
{
@@ -512,7 +571,51 @@ static int set_end(struct lo *const lo, const struct blocks *const b,
{
struct lo_entry *const e = &lo->entries[i];
- if (e->b == tgt && tgt->op == OP_BLOCK)
+ if (e->b == tgt)
+ {
+ if (tgt->op == OP_BLOCK)
+ e->dst = offset;
+ else if (tgt->op == OP_IF &&
+ (e->op == OP_ELSE || (e->op == OP_IF && !e->dst)))
+ e->dst = offset;
+ }
+ }
+
+ return 0;
+}
+
+static int set_else(struct lo *const lo, const struct blocks *const b,
+ const unsigned level, FILE *const f)
+{
+ long offset = ftell(f);
+
+ if (offset < 0)
+ {
+ fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+
+ const struct block *tgt = NULL;
+
+ for (const struct block *bl = b->tail; bl; bl = bl->prev)
+ if (bl->level == level && bl->op == OP_IF)
+ {
+ tgt = bl;
+ break;
+ }
+
+ if (!tgt)
+ {
+ fprintf(stderr, "%s: could not find matching block for end, pc=%ld\n",
+ __func__, offset);
+ return -1;
+ }
+
+ for (size_t i = 0; i < lo->n; i++)
+ {
+ struct lo_entry *const e = &lo->entries[i];
+
+ if (e->b == tgt && e->op == OP_IF)
e->dst = offset;
}
@@ -567,7 +670,17 @@ int read_instr(FILE *const f, struct parse *const p)
}
else if (branch(op) && add_branch(op, &lo, &b, relative_depth, level, f))
{
- fprintf(stderr, "%s: add_entry failed\n", __func__);
+ fprintf(stderr, "%s: add_branch failed\n", __func__);
+ goto failure;
+ }
+ else if (cbranch(op) && add_cbranch(op, &lo, &b, level, f))
+ {
+ fprintf(stderr, "%s: add_cbranch failed\n", __func__);
+ goto failure;
+ }
+ else if (op == OP_ELSE && set_else(&lo, &b, level, f))
+ {
+ fprintf(stderr, "%s: set_else failed\n", __func__);
goto failure;
}
else if (op == OP_END)
diff --git a/types.h b/types.h
index 323e17e..1702f44 100644
--- a/types.h
+++ b/types.h
@@ -64,6 +64,7 @@ struct parse
{
struct lo_entry
{
+ uint8_t op;
const struct block *b;
uint32_t pc, dst;
} *entries;