From c64c478e3f1acc802eb86a7281b85285bc4eafa3 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Wed, 3 Jun 2026 00:01:26 +0900 Subject: [PATCH] w6l/obj: write diagnostics with str .len (fix truncated-newline off-by-one) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 5 literal os.write diagnostics in obj.ww ("cannot read object", "missing .text", "missing .symtab", and two "duplicate symbol") passed hand-counted byte lengths that were each short by one, dropping the trailing '\n' so every diagnostic printed without its newline. Replace each magic length with the string's own .len via the local-binding idiom (let m: str = "..."; os.write(2, m.ptr, m.len: u64);) — the established wcc/err.ww + w6c/w6l/main.ww pattern — which fixes the off-by-one and closes the hand-count class by construction. Uses str-variable .len (correct on both stages), not "literal".len (cstage miscompile, #14), so this is byte-identical cs==ww. Also fold two trivially-safe nested-if collapses in the same file: the archive-member skip guard (three sequential `if (first != ...)` with no else → one &&-chain) and the text/data exclusivity guard (`if (intext) { if (indt) ...`→ `if (intext && indt)`). Verified: w6l_ww on a missing object now writes the full "w6l: cannot read object\n"; w6c and w6c_ww emit byte-identical asm for the regenerated main.combined.ww. --- selfhost/cmd/w6l/main.combined.ww | 21 +++++++++++++-------- selfhost/cmd/w6l/obj.ww | 21 +++++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/selfhost/cmd/w6l/main.combined.ww b/selfhost/cmd/w6l/main.combined.ww index 57bde81a..7ba25de5 100644 --- a/selfhost/cmd/w6l/main.combined.ww +++ b/selfhost/cmd/w6l/main.combined.ww @@ -3284,7 +3284,7 @@ fn loadarchive(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { let first: u8 = buf[pos]; // Skip the symbol table ('/'), long-name table ('//'), and // any padding entries (NUL or space leading byte). - if (first != '/') { if (first != 0u8) { if (first != ' ') { + if (first != '/' && first != 0u8 && first != ' ') { let m: *armember = alloc(armember { size = hdrsize })!; let mbs: []u8 = alloc([], hdrsize)!; let mb: *u8 = mbs.ptr; @@ -3298,7 +3298,7 @@ fn loadarchive(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { if (head == nil) { head = m; } else { tail.mnext = m; }; tail = m; - }; }; }; + }; pos = hdrend + hdrsize; if ((hdrsize & 1u64) != 0u64) { pos = pos + 1u64; }; }; @@ -3329,7 +3329,8 @@ export fn load(l: *lnk, path: *u8) i32 = { let buflen: u64; bufp, buflen = slurp(path); if (bufp == nil) { - os.write(2, "w6l: cannot read object\n".ptr, 23u64); + let m: str = "w6l: cannot read object\n"; + os.write(2, m.ptr, m.len: u64); return -1; }; if (isarchive(bufp, buflen)) { @@ -3380,11 +3381,13 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { i += 1u32; }; if (idxtext < 0) { - os.write(2, "w6l: missing .text\n".ptr, 18u64); + let m: str = "w6l: missing .text\n"; + os.write(2, m.ptr, m.len: u64); return -1; }; if (idxsymtab < 0) { - os.write(2, "w6l: missing .symtab\n".ptr, 20u64); + let m: str = "w6l: missing .symtab\n"; + os.write(2, m.ptr, m.len: u64); return -1; }; @@ -3451,10 +3454,11 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { if (idxdata >= 0) { indt = (stshndx: i32) == idxdata; }; - if (intext) { if (indt) { indt = false; }; }; + if (intext && indt) { indt = false; }; if (intext) { if (gs.defined != 0) { - os.write(2, "w6l: duplicate symbol\n".ptr, 21u64); + let m: str = "w6l: duplicate symbol\n"; + os.write(2, m.ptr, m.len: u64); l.errs += 1; } else { gs.defined = 1; @@ -3465,7 +3469,8 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { }; if (indt) { if (gs.defined != 0) { - os.write(2, "w6l: duplicate symbol\n".ptr, 21u64); + let m: str = "w6l: duplicate symbol\n"; + os.write(2, m.ptr, m.len: u64); l.errs += 1; } else { gs.defined = 1; diff --git a/selfhost/cmd/w6l/obj.ww b/selfhost/cmd/w6l/obj.ww index eda2cc94..366b5e4f 100644 --- a/selfhost/cmd/w6l/obj.ww +++ b/selfhost/cmd/w6l/obj.ww @@ -341,7 +341,7 @@ fn loadarchive(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { let first: u8 = buf[pos]; // Skip the symbol table ('/'), long-name table ('//'), and // any padding entries (NUL or space leading byte). - if (first != '/') { if (first != 0u8) { if (first != ' ') { + if (first != '/' && first != 0u8 && first != ' ') { let m: *armember = alloc(armember { size = hdrsize })!; let mbs: []u8 = alloc([], hdrsize)!; let mb: *u8 = mbs.ptr; @@ -355,7 +355,7 @@ fn loadarchive(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { if (head == nil) { head = m; } else { tail.mnext = m; }; tail = m; - }; }; }; + }; pos = hdrend + hdrsize; if ((hdrsize & 1u64) != 0u64) { pos = pos + 1u64; }; }; @@ -386,7 +386,8 @@ export fn load(l: *lnk, path: *u8) i32 = { let buflen: u64; bufp, buflen = slurp(path); if (bufp == nil) { - os.write(2, "w6l: cannot read object\n".ptr, 23u64); + let m: str = "w6l: cannot read object\n"; + os.write(2, m.ptr, m.len: u64); return -1; }; if (isarchive(bufp, buflen)) { @@ -437,11 +438,13 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { i += 1u32; }; if (idxtext < 0) { - os.write(2, "w6l: missing .text\n".ptr, 18u64); + let m: str = "w6l: missing .text\n"; + os.write(2, m.ptr, m.len: u64); return -1; }; if (idxsymtab < 0) { - os.write(2, "w6l: missing .symtab\n".ptr, 20u64); + let m: str = "w6l: missing .symtab\n"; + os.write(2, m.ptr, m.len: u64); return -1; }; @@ -508,10 +511,11 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { if (idxdata >= 0) { indt = (stshndx: i32) == idxdata; }; - if (intext) { if (indt) { indt = false; }; }; + if (intext && indt) { indt = false; }; if (intext) { if (gs.defined != 0) { - os.write(2, "w6l: duplicate symbol\n".ptr, 21u64); + let m: str = "w6l: duplicate symbol\n"; + os.write(2, m.ptr, m.len: u64); l.errs += 1; } else { gs.defined = 1; @@ -522,7 +526,8 @@ fn loadimage(l: *lnk, path: *u8, buf: *u8, len: u64) i32 = { }; if (indt) { if (gs.defined != 0) { - os.write(2, "w6l: duplicate symbol\n".ptr, 21u64); + let m: str = "w6l: duplicate symbol\n"; + os.write(2, m.ptr, m.len: u64); l.errs += 1; } else { gs.defined = 1;