lib/fmt: render i64::MIN via math.absi64, not in-i64 negate (#67)
i64dec computed the magnitude with `n = -n` inside i64, which wraps at i64::MIN (-MIN == MIN stays negative), so the `for (n > 0)` loop never ran and println(i64::MIN) emitted only the bare '-'. The whole print/ println/fprint family was affected at the single boundary value (and int MIN, since int is 8B). ref/hare/fmt/print.ha:124-129 takes the magnitude through math::absi64 into a u64; do the same (math.absi64 exists, lib/math/math.ww:12). ww's own printf path was already correct ((-v): u64), so print and printf now agree. fmttest gains fprinti64min + fprintintmin pinning the boundary.
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
package fmt;
|
||||
|
||||
import io;
|
||||
import math;
|
||||
import memio;
|
||||
import os;
|
||||
import strings;
|
||||
@@ -38,16 +39,18 @@ let i64dec_buf: [21]u8;
|
||||
// of strconv.i64tos for the pre-printf-family print path; the
|
||||
// printf-family path below dispatches through strconv directly.
|
||||
fn i64dec(v: i64) str = {
|
||||
let neg: bool = false;
|
||||
let n: i64 = v;
|
||||
if (n < 0) { neg = true; n = -n; };
|
||||
// ref/hare/fmt/print.ha:124-129: magnitude via math::absi64 into u64,
|
||||
// sign tested separately. `n = -n` on an i64 wraps at i64::MIN
|
||||
// (-MIN == MIN), so the old loop never ran and only the '-' printed.
|
||||
let neg: bool = v < 0;
|
||||
let n: u64 = math.absi64(v);
|
||||
let tmp: [20]u8;
|
||||
let i: i32 = 0;
|
||||
if (n == 0) { tmp[0] = '0'; i = 1; };
|
||||
for (n > 0) {
|
||||
let d: i64 = n % 10i64;
|
||||
tmp[i] = (d + 48i64): u8;
|
||||
n = n / 10i64;
|
||||
if (n == 0u64) { tmp[0] = '0'; i = 1; };
|
||||
for (n > 0u64) {
|
||||
let d: u64 = n % 10u64;
|
||||
tmp[i] = (d + 48u64): u8;
|
||||
n = n / 10u64;
|
||||
i += 1;
|
||||
};
|
||||
let out: i32 = 0;
|
||||
|
||||
@@ -76,6 +76,44 @@ fn errsource() io.stream = {
|
||||
match (c) { case void => {}; case let eioe: io.error => abort(); };
|
||||
};
|
||||
|
||||
// ---- fprint: i64::MIN / int MIN whole-magnitude (#67) ------------------
|
||||
// i64dec used `n = -n` within i64, which wraps at i64::MIN (-MIN == MIN),
|
||||
// so the digit loop never ran and only the bare '-' was emitted. The fix
|
||||
// takes the magnitude through math.absi64 into u64. These rows pin the
|
||||
// boundary value plus a normal negative, zero, and int MIN.
|
||||
|
||||
@test fn fprinti64min() void = {
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let m: i64 = -9223372036854775807i64 - 1i64;
|
||||
let r: (size | io.error) = fmt.fprint(s, m);
|
||||
match (r) {
|
||||
case let n: size => { assert(!(n: i32 != 20)); };
|
||||
case let eioe: io.error => abort();
|
||||
};
|
||||
assert(!(!streq(memio.string(&mem), "-9223372036854775808")));
|
||||
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => abort(); };
|
||||
};
|
||||
|
||||
@test fn fprintintmin() void = {
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let m: int = -9223372036854775807 - 1;
|
||||
let r: (size | io.error) = fmt.fprint(s, m, -7i64, 0i64);
|
||||
match (r) {
|
||||
case let n: size => { assert(!(n: i32 != 25)); }; // "-9223372036854775808 -7 0"
|
||||
case let eioe: io.error => abort();
|
||||
};
|
||||
assert(!(!streq(memio.string(&mem), "-9223372036854775808 -7 0")));
|
||||
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => abort(); };
|
||||
};
|
||||
|
||||
// ---- fprint: bool + rune renders as "true A" --------------------------
|
||||
|
||||
@test fn fprintboolrune() void = {
|
||||
|
||||
Reference in New Issue
Block a user