hare

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

commit 9346336ffe19f9216b9148763daf22e739ecec91
parent 6a5dbe35b0ea90dbb6edeba87ac852267b0edb1e
Author: Autumn! <autumnull@posteo.net>
Date:   Sun,  7 May 2023 01:43:28 +0000

path: use custom error types and strerror

Signed-off-by: Autumn! <autumnull@posteo.net>

Diffstat:
Mpath/README | 4+++-
Mpath/buffer.ha | 5++---
Apath/error.ha | 12++++++++++++
Mpath/stack.ha | 13++++++-------
Mscripts/gen-stdlib | 1+
Mstdlib.mk | 2++
6 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/path/README b/path/README @@ -17,7 +17,9 @@ Assuming that [[PATHSEP]] is '/', "/usr//bin/../bin/./hare/" becomes The buffer object includes an array of length [[PATH_MAX]], which can be somewhat large; on Linux it's 4096 bytes. You can allocate this on the stack in -most cases, but you may prefer to allocate it elsewhere depending on your needs. +most cases, but you may prefer to allocate it elsewhere depending on your +needs. Functions in this module return [[too_long]] if the buffer's capacity +would be exceeded. // Stack allocated let buf = path::init()!; diff --git a/path/buffer.ha b/path/buffer.ha @@ -2,7 +2,6 @@ // (c) 2022 Drew DeVault <sir@cmpwn.com> // (c) 2022 Humm <hummsmith42@gmail.com> use bytes; -use errors; use strings; export type buffer = struct { @@ -11,7 +10,7 @@ export type buffer = struct { }; // Initializes a new path buffer. -export fn init(items: str...) (buffer | errors::overflow) = { +export fn init(items: str...) (buffer | error) = { let buf = buffer { ... }; push(&buf, items...)?; return buf; @@ -19,7 +18,7 @@ export fn init(items: str...) (buffer | errors::overflow) = { // Sets the value of a path buffer to a list of components, overwriting any // previous value. Returns the new string value of the path. -export fn set(buf: *buffer, items: str...) (str | errors::overflow) = { +export fn set(buf: *buffer, items: str...) (str | error) = { buf.end = 0; return push(buf, items...); }; diff --git a/path/error.ha b/path/error.ha @@ -0,0 +1,12 @@ +// Returned when adding an extension if the path is root, or the final path +// segment consists entirely of dots. +export type cant_extend = !void; +// Returned when a path buffer would have overflowed. +export type too_long = !void; +export type error = !(cant_extend | too_long); + +// Convert an [[error]] into a descriptive string. +export fn strerror(e: error) str = match (e) { +case cant_extend => return "Can't add extension (filename is root or all dots)"; +case too_long => return "Path buffer overflow"; +}; diff --git a/path/stack.ha b/path/stack.ha @@ -1,12 +1,11 @@ // License: MPL-2.0 // (c) 2021-2022 Drew DeVault <sir@cmpwn.com> use bytes; -use errors; use strings; // Appends path elements onto the end of a path buffer. // Returns the new string value of the path. -export fn push(buf: *buffer, items: str...) (str | errors::overflow) = { +export fn push(buf: *buffer, items: str...) (str | error) = { for (let i = 0z; i < len(items); i += 1) { let elem = strings::toutf8(items[i]); for (true) match (bytes::index(elem, PATHSEP)) { @@ -39,7 +38,7 @@ const dotdot: []u8 = ['.', '.']; // x/.. + .. => x/../.. // x/y + .. => x // x + y => x/y -fn appendnorm(buf: *buffer, seg: []u8) (size | errors::overflow) = { +fn appendnorm(buf: *buffer, seg: []u8) (size | error) = { if (len(seg) == 0 || bytes::equal(dot, seg)) return buf.end; if (bytes::equal(dotdot, seg)) { if (isroot(buf)) return buf.end; @@ -59,12 +58,12 @@ fn appendnorm(buf: *buffer, seg: []u8) (size | errors::overflow) = { // append a segment to a buffer, *without* preserving normalization. // returns the new end of the buffer -fn appendlit(buf: *buffer, bs: []u8) (size | errors::overflow) = { +fn appendlit(buf: *buffer, bs: []u8) (size | error) = { let newend = buf.end; if (buf.end == 0 || isroot(buf)) { - if (PATH_MAX < buf.end + len(bs)) return errors::overflow; + if (PATH_MAX < buf.end + len(bs)) return too_long; } else { - if (PATH_MAX < buf.end + len(bs) + 1) return errors::overflow; + if (PATH_MAX < buf.end + len(bs) + 1) return too_long; buf.buf[buf.end] = PATHSEP; newend += 1; }; @@ -187,7 +186,7 @@ export fn join(items: str...) str = { // If the path is the root directory, the root directory is returned. The value // is either borrowed from the input or statically allocated; use // [[strings::dup]] to extend its lifetime or modify it. -export fn parent(buf: *const buffer) (str | errors::overflow) = { +export fn parent(buf: *const buffer) (str | error) = { const newend = appendnorm(buf, dotdot)?; if (newend == 0) return "."; return strings::fromutf8_unsafe(buf.buf[..newend]); diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -1203,6 +1203,7 @@ path() { gen_srcs path \ '+$(PLATFORM).ha' \ buffer.ha \ + error.ha \ util.ha \ stack.ha \ names.ha \ diff --git a/stdlib.mk b/stdlib.mk @@ -1836,6 +1836,7 @@ $(HARECACHE)/os/exec/os_exec-freebsd.ssa: $(stdlib_os_exec_freebsd_srcs) $(stdli stdlib_path_any_srcs = \ $(STDLIB)/path/+$(PLATFORM).ha \ $(STDLIB)/path/buffer.ha \ + $(STDLIB)/path/error.ha \ $(STDLIB)/path/util.ha \ $(STDLIB)/path/stack.ha \ $(STDLIB)/path/names.ha \ @@ -4110,6 +4111,7 @@ $(TESTCACHE)/os/exec/os_exec-freebsd.ssa: $(testlib_os_exec_freebsd_srcs) $(test testlib_path_any_srcs = \ $(STDLIB)/path/+$(PLATFORM).ha \ $(STDLIB)/path/buffer.ha \ + $(STDLIB)/path/error.ha \ $(STDLIB)/path/util.ha \ $(STDLIB)/path/stack.ha \ $(STDLIB)/path/names.ha \