diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-11-10 22:36:25 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-11-12 00:45:34 +0100 |
| commit | a83684db1c1f24b9d744e7b6078e819bf44d169d (patch) | |
| tree | 4e4b5f0001d87abeabdba1c5cdc394e8d214cb89 | |
| parent | 0086ccf0272fa195dca36845fde9c54149c72f0e (diff) | |
| download | nwc-a83684db1c1f24b9d744e7b6078e819bf44d169d.tar.gz | |
Support if/else
| -rw-r--r-- | read_instr.c | 119 | ||||
| -rw-r--r-- | types.h | 1 |
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) @@ -64,6 +64,7 @@ struct parse { struct lo_entry { + uint8_t op; const struct block *b; uint32_t pc, dst; } *entries; |
