hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 8b1ca348725ccecce1b95cf12170f54e8e54ea56
parent 5893c49443b70fb649836b1da6a0caf4fe274249
Author: Sebastian <sebastian@sebsite.pw>
Date:   Tue,  5 Sep 2023 22:07:05 -0400

rt: print unknown errno number in strerror/errname

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mrt/+freebsd/errno.ha | 9+++++----
Mrt/+linux/errno.ha | 9+++++----
Art/unknown_errno.ha | 26++++++++++++++++++++++++++
Art/ztos.ha | 37+++++++++++++++++++++++++++++++++++++
Mscripts/gen-stdlib | 4++++
Mstdlib.mk | 8++++++++
6 files changed, 85 insertions(+), 8 deletions(-)

diff --git a/rt/+freebsd/errno.ha b/rt/+freebsd/errno.ha @@ -17,7 +17,7 @@ fn wrap_return(r: u64) (errno | u64) = { }; // Obtains a human-friendly reading of an [[errno]] (e.g. "Operation not -// permitted"). +// permitted"). The return value may be statically allocated. export fn strerror(err: errno) str = { switch (err: int) { case EPERM => @@ -213,11 +213,12 @@ export fn strerror(err: errno) str = { case ERPCMISMATCH => return "RPC version wrong"; case => - return "[unknown errno]"; // TODO: snprintf to add errno? + return unknown_errno(err); }; }; -// Gets the programmer-friendly name for an [[errno]] (e.g. EPERM). +// Gets the programmer-friendly name for an [[errno]] (e.g. EPERM). The return +// value may be statically allocated. export fn errname(err: errno) str = { switch (err: int) { case EPERM => @@ -413,7 +414,7 @@ export fn errname(err: errno) str = { case ERPCMISMATCH => return "ERPCMISMATCH"; case => - return "[unknown errno]"; // TODO: snprintf to add errno? + return unknown_errno(err); }; }; diff --git a/rt/+linux/errno.ha b/rt/+linux/errno.ha @@ -18,7 +18,7 @@ fn wrap_return(r: u64) (errno | u64) = { }; // Obtains a human-friendly reading of an [[errno]] (e.g. "Operation not -// permitted"). +// permitted"). The return value may be statically allocated. export fn strerror(err: errno) str = { switch (err: int) { case EPERM => @@ -284,11 +284,12 @@ export fn strerror(err: errno) str = { case EHWPOISON => return "Memory page has hardware error"; case => - return "[unknown errno]"; // TODO: snprintf to add errno? + return unknown_errno(err); }; }; -// Gets the programmer-friendly name for an [[errno]] (e.g. EPERM). +// Gets the programmer-friendly name for an [[errno]] (e.g. EPERM). The return +// value may be statically allocated. export fn errname(err: errno) str = { switch (err: int) { case EPERM => @@ -554,7 +555,7 @@ export fn errname(err: errno) str = { case EHWPOISON => return "EHWPOISON"; case => - return "[unknown errno]"; // TODO: snprintf to add errno? + return unknown_errno(err); }; }; diff --git a/rt/unknown_errno.ha b/rt/unknown_errno.ha @@ -0,0 +1,26 @@ +fn unknown_errno(err: errno) str = { + static let buf: [27]u8 = [0...]; + const s = *(&"[unknown errno ": *[]u8); + buf[..len(s)] = s; + if (err < 0) { + buf[len(s)] = '-'; + const s2 = &ztos(-err: size): *string; + buf[len(s) + 1..s2.length + len(s) + 1] = s2.data[..s2.length]; + buf[s2.length + len(s) + 1] = ']'; + return *(&buf[..s2.length + len(s) + 2]: *str); + } else { + const s2 = &ztos(err: size): *string; + buf[len(s)..s2.length + len(s)] = s2.data[..s2.length]; + buf[s2.length + len(s)] = ']'; + return *(&buf[..s2.length + len(s) + 1]: *str); + }; +}; + +@test fn unknown_errno() void = { + let err: errno = -1; + assert(strerror(err) == "[unknown errno -1]"); + err = 0; + assert(strerror(err) == "[unknown errno 0]"); + err = 2147483647; + assert(strerror(err) == "[unknown errno 2147483647]"); +}; diff --git a/rt/ztos.ha b/rt/ztos.ha @@ -0,0 +1,37 @@ +fn bytes_reverse(b: []u8) void = { + if (len(b) == 0) { + return; + }; + for (let s = 0z, e = len(b) - 1; s < e) { + let x = b[s]; + b[s] = b[e]; + b[e] = x; + s += 1; + e -= 1; + }; +}; + +fn ztos(u: size) const str = { + static let buf: [20]u8 = [0...]; + buf = [0...]; + + let s = struct { + b: *[*]u8 = &buf, + l: size = 0, + c: size = 0, + }; + + if (u == 0) { + s.b[s.l] = '0'; + s.l += 1; + }; + + for (u > 0) { + s.b[s.l] = '0' + (u % 10): u8; + s.l += 1; + u /= 10; + }; + + bytes_reverse(s.b[..s.l]); + return *(&s: *str); +}; diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -43,6 +43,8 @@ gensrcs_rt() { memmove.ha \ memset.ha \ strcmp.ha \ + unknown_errno.ha \ + ztos.ha \ $* gen_srcs -pfreebsd rt \ +freebsd/platform_abort.ha \ @@ -67,6 +69,8 @@ gensrcs_rt() { memmove.ha \ memset.ha \ strcmp.ha \ + unknown_errno.ha \ + ztos.ha \ $* } diff --git a/stdlib.mk b/stdlib.mk @@ -27,6 +27,8 @@ stdlib_rt_linux_srcs = \ $(STDLIB)/rt/memmove.ha \ $(STDLIB)/rt/memset.ha \ $(STDLIB)/rt/strcmp.ha \ + $(STDLIB)/rt/unknown_errno.ha \ + $(STDLIB)/rt/ztos.ha \ $(STDLIB)/rt/abort.ha \ $(STDLIB)/rt/start.ha @@ -54,6 +56,8 @@ stdlib_rt_freebsd_srcs = \ $(STDLIB)/rt/memmove.ha \ $(STDLIB)/rt/memset.ha \ $(STDLIB)/rt/strcmp.ha \ + $(STDLIB)/rt/unknown_errno.ha \ + $(STDLIB)/rt/ztos.ha \ $(STDLIB)/rt/abort.ha \ $(STDLIB)/rt/start.ha @@ -2427,6 +2431,8 @@ testlib_rt_linux_srcs = \ $(STDLIB)/rt/memmove.ha \ $(STDLIB)/rt/memset.ha \ $(STDLIB)/rt/strcmp.ha \ + $(STDLIB)/rt/unknown_errno.ha \ + $(STDLIB)/rt/ztos.ha \ $(STDLIB)/rt/abort+test.ha \ $(STDLIB)/rt/start+test.ha \ $(STDLIB)/rt/+test/signal_test.ha @@ -2455,6 +2461,8 @@ testlib_rt_freebsd_srcs = \ $(STDLIB)/rt/memmove.ha \ $(STDLIB)/rt/memset.ha \ $(STDLIB)/rt/strcmp.ha \ + $(STDLIB)/rt/unknown_errno.ha \ + $(STDLIB)/rt/ztos.ha \ $(STDLIB)/rt/abort+test.ha \ $(STDLIB)/rt/start+test.ha \ $(STDLIB)/rt/+test/signal_test.ha