From 2520b79fdf6c344c358e21518b1a5fbcccb21095 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Mon, 19 Feb 2024 22:43:36 +0100 Subject: Make error messages great again --- src/c8asm/assembler.c | 8 ++-- src/c8asm/common.h | 3 ++ src/c8asm/lexer.c | 27 ++++++------- src/c8asm/parser.c | 107 +++++++++++++++++++++++--------------------------- src/common/cerr.c | 6 +-- 5 files changed, 70 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/c8asm/assembler.c b/src/c8asm/assembler.c index 8ccf9b0..ffa9025 100644 --- a/src/c8asm/assembler.c +++ b/src/c8asm/assembler.c @@ -54,16 +54,14 @@ getaddr(struct raw_addr a) labels that aren’t integer-literals by that. */ if (lbl = getlabel(a.sv)) return lbl->addr + 0x200; - die_at_pos_with_code(filename, filebuf, a.sv, a.sv.p - baseptr, E_LNEXISTS); + DIE_AT_POS_WITH_CODE(a.sv, a.sv.p, E_LNEXISTS); } void pushlabel(struct labels *dst, struct label lbl) { - if (getlabel(lbl.sv)) { - die_at_pos_with_code(filename, filebuf, lbl.sv, lbl.sv.p - baseptr, - E_LEXISTS); - } + if (getlabel(lbl.sv)) + DIE_AT_POS_WITH_CODE(lbl.sv, lbl.sv.p, E_LEXISTS); dapush(dst, lbl); } diff --git a/src/c8asm/common.h b/src/c8asm/common.h index 49af0f7..aa32b2b 100644 --- a/src/c8asm/common.h +++ b/src/c8asm/common.h @@ -3,6 +3,9 @@ #include +#define DIE_AT_POS_WITH_CODE(HL, P, ...) \ + die_at_pos_with_code(filename, filebuf, (HL), (P)-baseptr, __VA_ARGS__); + extern size_t filesize; extern const char *filename; extern const char8_t *baseptr; diff --git a/src/c8asm/lexer.c b/src/c8asm/lexer.c index 3d2a3bf..87835a9 100644 --- a/src/c8asm/lexer.c +++ b/src/c8asm/lexer.c @@ -10,9 +10,6 @@ #define ISDIGIT(n) ((n) >= '0' && (n) <= '9') #define U8MOV(sv, n) ((sv)->p += (n), (sv)->len -= (n)) -#define die_at_pos_with_code(HL, OFF, ...) \ - die_at_pos_with_code(filename, filebuf, (HL), (OFF), __VA_ARGS__) - #define E_BASE "integer with invalid base specifier" #define E_EXTRA "unknown extraneous character" #define E_IDENTCCHAR "illegal character in identifier" @@ -68,12 +65,12 @@ lexfile(void) return toks; } +#define DIE_AT_POS_WITH_CODE2(HL, ...) \ + DIE_AT_POS_WITH_CODE((HL), sv->p - w, __VA_ARGS__) + void lexline(struct tokens *toks, struct u8view *sv) { -#define _die_at_pos_with_code(HL, ...) \ - die_at_pos_with_code((HL), sv->p - baseptr - w, __VA_ARGS__) - struct token tok; for (;;) { @@ -117,7 +114,7 @@ lexline(struct tokens *toks, struct u8view *sv) break; default: if (!ISDIGIT(ch)) - _die_at_pos_with_code(tok.sv, E_BASE); + DIE_AT_POS_WITH_CODE2(tok.sv, E_BASE); } } @@ -130,10 +127,10 @@ out: if (ch == '.') { tok.sv.len += w = u8next(&ch, &sv->p, &sv->len); if (!w || rprop_is_pat_ws(ch)) - _die_at_pos_with_code(tok.sv, E_IDENTLOST); + DIE_AT_POS_WITH_CODE2(tok.sv, E_IDENTLOST); if (ch != '_' && !rprop_is_xids(ch)) { U8MOV(&tok.sv, 1); - _die_at_pos_with_code(tok.sv, E_IDENTSCHAR); + DIE_AT_POS_WITH_CODE2(tok.sv, E_IDENTSCHAR); } } @@ -147,7 +144,7 @@ out: .p = sv->p - w, .len = w, }; - _die_at_pos_with_code(hl, E_IDENTCCHAR); + DIE_AT_POS_WITH_CODE2(hl, E_IDENTCCHAR); } tok.sv.len += w; @@ -159,7 +156,7 @@ out: if (ch == '"') goto found; } - _die_at_pos_with_code(tok.sv, E_UNTERMINATED); + DIE_AT_POS_WITH_CODE2(tok.sv, E_UNTERMINATED); found: } else if (ch == ':') { tok.kind = T_COLON; @@ -167,7 +164,7 @@ found: goto end; } else { struct u8view hl = {.p = sv->p - w, .len = w}; - _die_at_pos_with_code(hl, E_EXTRA); + DIE_AT_POS_WITH_CODE2(hl, E_EXTRA); } /* The colon is the only token that isn’t whitespace separated */ @@ -175,7 +172,7 @@ found: w = u8next(&ch, &sv->p, &sv->len); if (!w || !rprop_is_pat_ws(ch)) { struct u8view hl = {.p = sv->p - w, .len = w}; - _die_at_pos_with_code(hl, E_EXTRA); + DIE_AT_POS_WITH_CODE2(hl, E_EXTRA); } } @@ -189,10 +186,10 @@ end:; .sv.len = 0, }; dapush(toks, tok); - -#undef _die_at_pos_with_code } +#undef DIE_AT_POS_WITH_CODE2 + bool skipws(struct u8view *sv) { diff --git a/src/c8asm/parser.c b/src/c8asm/parser.c index 5a68fad..208511d 100644 --- a/src/c8asm/parser.c +++ b/src/c8asm/parser.c @@ -11,14 +11,11 @@ #include "macros.h" #include "parser.h" -#define E_BADLABEL "identifier ‘%.*s’ cannot be used as a label" -#define E_EARLY "expected %s but input ended prematurely" -#define E_EXPECTED2 "expected %s but got %s" -#define E_EXPECTED "expected %s but got %s ‘%.*s’" -#define E_INSTR "got unknown instruction ‘%.*s’" -#define E_TOOLARGE "expected %s but got out-of-range integer ‘%.*s’" - -#define die_with_off(P, ...) die_with_off(filename, (P)-baseptr, __VA_ARGS__) +#define E_BADLABEL "identifier cannot be used as a label" +#define E_EARLY "expected %s but input ended prematurely" +#define E_EXPECTED "expected %s but got %s" +#define E_INSTR "got unknown instruction" +#define E_TOOLARGE "expected %s but got out-of-range integer" enum numsize { NS_NIBBLE = 0xF, @@ -94,7 +91,7 @@ parselabel(void) .name = tokens->buf[i].sv, }; if (regtype(lbl.name) != RT_NONE) - die_with_off(lbl.name.p, E_BADLABEL, U8_PRI_ARGS(lbl.name)); + DIE_AT_POS_WITH_CODE(lbl.name, lbl.name.p, E_BADLABEL); dapush(&ast, lbl); i += 2; return true; @@ -115,7 +112,7 @@ parseop(void) } if (!(op = oplookup(tok.sv.p, tok.sv.len))) - die_with_off(tok.sv.p, E_INSTR, U8_PRI_ARGS(tok.sv)); + DIE_AT_POS_WITH_CODE(tok.sv, tok.sv.p, E_INSTR); op->pfn(); } @@ -126,7 +123,7 @@ parseaddr(struct token tok) return (struct raw_addr){.val = parsenum(tok, NS_ADDR)}; if (tok.kind == T_IDENT) { if (regtype(tok.sv) != RT_NONE) - die_with_off(tok.sv.p, E_BADLABEL, U8_PRI_ARGS(tok.sv)); + DIE_AT_POS_WITH_CODE(tok.sv, tok.sv.p, E_BADLABEL); return (struct raw_addr){.label = true, .sv = tok.sv}; } unreachable(); @@ -192,7 +189,7 @@ parsenum(struct token tok, enum numsize size) : size == NS_BYTE ? "byte" : size == NS_ADDR ? "address" : (unreachable(), nullptr); - die_with_off(tok.sv.p, E_TOOLARGE, s, U8_PRI_ARGS(tok.sv)); + DIE_AT_POS_WITH_CODE(tok.sv, tok.sv.p, E_TOOLARGE, s); } acc *= tok.base; @@ -207,19 +204,15 @@ reqnext(const char *want, tokkind msk) { struct token t; - if (i >= tokens->len) - die_with_off(baseptr + filesize - 1, E_EARLY, want); + if (i >= tokens->len) { + DIE_AT_POS_WITH_CODE((struct u8view){}, baseptr + filesize - 1, E_EARLY, + want); + } if ((t = tokens->buf[i++]).kind & msk) return t; - if (t.kind == T_EOL) { - die_at_pos_with_code(filename, filebuf, (struct u8view){}, - t.sv.p - baseptr, E_EXPECTED2, want, - tokrepr(t.kind)); - } - - die_at_pos_with_code(filename, filebuf, t.sv, t.sv.p - baseptr, E_EXPECTED, - want, tokrepr(t.kind), U8_PRI_ARGS(t.sv)); + DIE_AT_POS_WITH_CODE(t.kind == T_EOL ? (struct u8view){} : t.sv, t.sv.p, + E_EXPECTED, want, tokrepr(t.kind)); } #define I(...) ((struct dir){.kind = D_INSTR, .instr = (__VA_ARGS__)}) @@ -230,8 +223,8 @@ reqnext(const char *want, tokkind msk) struct instr ins = {.kind = (T)}; \ struct token tok = reqnext("v-register", T_IDENT); \ if (regtype(tok.sv) & ~RT_VX) { \ - die_with_off(tok.sv.p, E_EXPECTED, "v-register", \ - tokrepr(tok.kind), U8_PRI_ARGS(tok.sv)); \ + DIE_AT_POS_WITH_CODE(tok.sv, tok.sv.p, E_EXPECTED, "v-register", \ + tokrepr(tok.kind)); \ } \ ins.args[ins.len++].val = hexval(tok.sv.p[1]); \ dapush(&ast, I(ins)); \ @@ -242,12 +235,12 @@ reqnext(const char *want, tokkind msk) struct token lhs = reqnext("v-register", T_IDENT); \ struct token rhs = reqnext("v-register", T_IDENT); \ if (regtype(lhs.sv) & ~RT_VX) { \ - die_with_off(lhs.sv.p, E_EXPECTED, "v-register", \ - tokrepr(lhs.kind), U8_PRI_ARGS(lhs.sv)); \ + DIE_AT_POS_WITH_CODE(lhs.sv, lhs.sv.p, E_EXPECTED, "v-register", \ + tokrepr(lhs.kind)); \ } \ if (regtype(rhs.sv) & ~RT_VX) { \ - die_with_off(rhs.sv.p, E_EXPECTED, "v-register", \ - tokrepr(rhs.kind), U8_PRI_ARGS(rhs.sv)); \ + DIE_AT_POS_WITH_CODE(rhs.sv, rhs.sv.p, E_EXPECTED, "v-register", \ + tokrepr(rhs.kind)); \ } \ ins.args[ins.len++].val = hexval(lhs.sv.p[1]); \ ins.args[ins.len++].val = hexval(rhs.sv.p[1]); \ @@ -270,8 +263,8 @@ parseop_add(void) ins.kind = I_ADD_VX_B; ins.args[ins.len++].val = parsenum(tok, NS_BYTE); } else if (regtype(tok.sv) != RT_VX) { - die_with_off(tok.sv.p, E_EXPECTED, "v-register", tokrepr(tok.kind), - U8_PRI_ARGS(tok.sv)); + DIE_AT_POS_WITH_CODE(tok.sv, tok.sv.p, E_EXPECTED, "v-register", + tokrepr(tok.kind)); } else { ins.kind = I_ADD_VX_VY; ins.args[ins.len++].val = hexval(tok.sv.p[1]); @@ -281,14 +274,14 @@ parseop_add(void) ins.kind = I_ADD_I_VX; tok = reqnext("v-register", T_IDENT); if (regtype(tok.sv) != RT_VX) { - die_with_off(tok.sv.p, E_EXPECTED, "v-register", tokrepr(tok.kind), - U8_PRI_ARGS(tok.sv)); + DIE_AT_POS_WITH_CODE(tok.sv, tok.sv.p, E_EXPECTED, "v-register", + tokrepr(tok.kind)); } ins.args[ins.len++].val = hexval(tok.sv.p[1]); break; default: - die_with_off(tok.sv.p, E_EXPECTED, "v- or i-register", - tokrepr(tok.kind), U8_PRI_ARGS(tok.sv)); + DIE_AT_POS_WITH_CODE(tok.sv, tok.sv.p, E_EXPECTED, "v- or i-register", + tokrepr(tok.kind)); } dapush(&ast, I(ins)); @@ -354,12 +347,12 @@ parseop_drw(void) op3 = reqnext("nibble", T_NUMBER); if (regtype(op1.sv) != RT_VX) { - die_with_off(op1.sv.p, E_EXPECTED, "v-register", tokrepr(op1.kind), - U8_PRI_ARGS(op1.sv)); + DIE_AT_POS_WITH_CODE(op1.sv, op1.sv.p, E_EXPECTED, "v-register", + tokrepr(op1.kind)); } if (regtype(op2.sv) != RT_VX) { - die_with_off(op2.sv.p, E_EXPECTED, "v-register", tokrepr(op2.kind), - U8_PRI_ARGS(op2.sv)); + DIE_AT_POS_WITH_CODE(op2.sv, op2.sv.p, E_EXPECTED, "v-register", + tokrepr(op2.kind)); } ins.args[ins.len++].val = hexval(op1.sv.p[1]); @@ -389,8 +382,8 @@ parseop_jp(void) } else if (op.kind == T_IDENT) { ins.kind = I_JP_V0_A; if (op.sv.len != 2 || !memeq(op.sv.p, "v0", 2)) { - die_with_off(op.sv.p, E_EXPECTED, "v0-register or address", - tokrepr(op.kind), U8_PRI_ARGS(op.sv)); + DIE_AT_POS_WITH_CODE(op.sv, op.sv.p, E_EXPECTED, + "v0-register or address", tokrepr(op.kind)); } ins.args[ins.len++] = parseaddr(reqnext("address", T_NUMBER | T_IDENT)); } else @@ -412,8 +405,8 @@ parseop_ld(void) ins.kind = rt == RT_DT ? I_LD_DT : I_LD_ST; op = reqnext("v-register", T_IDENT); if (regtype(op.sv) != RT_VX) { - die_with_off(op.sv.p, E_EXPECTED, "v-register", tokrepr(op.kind), - U8_PRI_ARGS(op.sv)); + DIE_AT_POS_WITH_CODE(op.sv, op.sv.p, E_EXPECTED, "v-register", + tokrepr(op.kind)); } ins.args[ins.len++].val = hexval(op.sv.p[1]); break; @@ -441,9 +434,9 @@ parseop_ld(void) ins.args[ins.len++].val = hexval(op.sv.p[1]); break; default: - die_with_off(op.sv.p, E_EXPECTED, - "v-, k-, or dt-register, or byte", - tokrepr(op.kind), U8_PRI_ARGS(op.sv)); + DIE_AT_POS_WITH_CODE(op.sv, op.sv.p, E_EXPECTED, + "v-, k-, or dt-register, or byte", + tokrepr(op.kind)); } break; @@ -457,8 +450,8 @@ parseop_ld(void) break; default: - die_with_off(op.sv.p, E_EXPECTED, "v-, i-, dt-, or st-register", - tokrepr(op.kind), U8_PRI_ARGS(op.sv)); + DIE_AT_POS_WITH_CODE(op.sv, op.sv.p, E_EXPECTED, + "v-, i-, dt-, or st-register", tokrepr(op.kind)); } dapush(&ast, I(ins)); @@ -486,8 +479,8 @@ parseop_rnd(void) op2 = reqnext("byte", T_NUMBER); if (regtype(op1.sv) != RT_VX) { - die_with_off(op1.sv.p, E_EXPECTED, "v-register", tokrepr(op1.kind), - U8_PRI_ARGS(op1.sv)); + DIE_AT_POS_WITH_CODE(op1.sv, op1.sv.p, E_EXPECTED, "v-register", + tokrepr(op1.kind)); } ins.args[ins.len++].val = hexval(op1.sv.p[1]); @@ -511,16 +504,16 @@ parseop_se(void) op2 = reqnext("byte or v-register", T_IDENT | T_NUMBER); if (regtype(op1.sv) != RT_VX) { - die_with_off(op1.sv.p, E_EXPECTED, "v-register", tokrepr(op1.kind), - U8_PRI_ARGS(op1.sv)); + DIE_AT_POS_WITH_CODE(op1.sv, op1.sv.p, E_EXPECTED, "v-register", + tokrepr(op1.kind)); } ins.args[ins.len++].val = hexval(op1.sv.p[1]); switch (op2.kind) { case T_IDENT: if (regtype(op2.sv) != RT_VX) { - die_with_off(op2.sv.p, E_EXPECTED, "v-register", tokrepr(op2.kind), - U8_PRI_ARGS(op2.sv)); + DIE_AT_POS_WITH_CODE(op2.sv, op2.sv.p, E_EXPECTED, "v-register", + tokrepr(op2.kind)); } ins.kind = I_SE_VX_VY; ins.args[ins.len++].val = hexval(op2.sv.p[1]); @@ -570,16 +563,16 @@ parseop_sne(void) op2 = reqnext("byte or v-register", T_IDENT | T_NUMBER); if (regtype(op1.sv) != RT_VX) { - die_with_off(op1.sv.p, E_EXPECTED, "v-register", tokrepr(op1.kind), - U8_PRI_ARGS(op1.sv)); + DIE_AT_POS_WITH_CODE(op1.sv, op1.sv.p, E_EXPECTED, "v-register", + tokrepr(op1.kind)); } ins.args[ins.len++].val = hexval(op1.sv.p[1]); switch (op2.kind) { case T_IDENT: if (regtype(op2.sv) != RT_VX) { - die_with_off(op2.sv.p, E_EXPECTED, "v-register", tokrepr(op2.kind), - U8_PRI_ARGS(op2.sv)); + DIE_AT_POS_WITH_CODE(op2.sv, op2.sv.p, E_EXPECTED, "v-register", + tokrepr(op2.kind)); } ins.kind = I_SNE_VX_VY; ins.args[ins.len++].val = hexval(op2.sv.p[1]); diff --git a/src/common/cerr.c b/src/common/cerr.c index 819df4a..98bca0f 100644 --- a/src/common/cerr.c +++ b/src/common/cerr.c @@ -19,7 +19,6 @@ #define SGR_BOLD "\33[1m" #define SGR_DONE "\33[0m" -#define SGR_WARN "\33[1;35m" #define SGR_ERR "\33[1;31m" int sizelen(size_t); @@ -27,7 +26,7 @@ int sizelen(size_t); static bool color; static const char *progname; -static const char *_bold, *_done, *_warn, *_err; +static const char *_bold, *_done, *_err; void cerrinit(const char *s) @@ -43,10 +42,9 @@ cerrinit(const char *s) if (color) { _bold = SGR_BOLD; _done = SGR_DONE; - _warn = SGR_WARN; _err = SGR_ERR; } else - _bold = _done = _warn = _err = ""; + _bold = _done = _err = ""; } void -- cgit v1.2.3