w6l/obj: write diagnostics with str .len (fix truncated-newline off-by-one)

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.
This commit is contained in:
2026-06-03 00:01:26 +09:00
parent 6f9a964a79
commit c64c478e3f
2 changed files with 26 additions and 16 deletions

View File

@@ -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;

View File

@@ -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;