hare

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

commit 91bcdbeb4858cf39875b95b4b3c2be029e16dcfc
parent 4df0fba8b05fcf175805f7bb41aa7fd6333e2ad9
Author: Autumn! <autumnull@posteo.net>
Date:   Sat, 13 May 2023 15:32:31 +0000

io: move fd-related functions into one file

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

Diffstat:
Dio/+freebsd/file.ha | 65-----------------------------------------------------------------
Aio/+freebsd/platform_file.ha | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dio/+freebsd/platform_lock.ha | 15---------------
Dio/+freebsd/platform_trunc.ha | 10----------
Dio/+linux/file.ha | 81-------------------------------------------------------------------------------
Aio/+linux/platform_file.ha | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dio/+linux/platform_lock.ha | 15---------------
Dio/+linux/platform_trunc.ha | 10----------
Aio/file.ha | 23+++++++++++++++++++++++
Dio/lock.ha | 20--------------------
Dio/trunc.ha | 4----
Mscripts/gen-stdlib | 14++++----------
Mstdlib.mk | 28++++++++--------------------
13 files changed, 219 insertions(+), 250 deletions(-)

diff --git a/io/+freebsd/file.ha b/io/+freebsd/file.ha @@ -1,65 +0,0 @@ -// License: MPL-2.0 -// (c) 2021-2022 Drew DeVault <sir@cmpwn.com> -// (c) 2021 Ember Sawady <ecs@d2evs.net> -use errors; -use rt; -use strings; - -// This is an opaque type which encloses an OS-level file handle resource. It -// can be used as a [[handle]] in most situations, but there are some APIs which -// require a [[file]] with some OS-level handle backing it - this type is used -// for such APIs. -// -// On FreeBSD, [[io::file]] is a file descriptor. -export type file = int; - -// Opens a Unix file descriptor as a file. This is a low-level interface, to -// open files most programs will use something like [[os::open]]. This function -// is not portable. -export fn fdopen(fd: int) file = fd; - -fn fd_read(fd: file, buf: []u8) (size | EOF | error) = { - match (rt::read(fd, buf: *[*]u8, len(buf))) { - case let err: rt::errno => - return errors::errno(err); - case let n: size => - switch (n) { - case 0 => - return EOF; - case => - return n; - }; - }; -}; - -fn fd_write(fd: file, buf: const []u8) (size | error) = { - match (rt::write(fd, buf: *const [*]u8, len(buf))) { - case let err: rt::errno => - return errors::errno(err); - case let n: size => - return n; - }; -}; - -fn fd_close(fd: file) (void | error) = { - match (rt::close(fd)) { - case void => void; - case let err: rt::errno => - return errors::errno(err); - }; -}; - -fn fd_seek( - fd: file, - offs: off, - whence: whence, -) (off | error) = { - match (rt::lseek(fd, offs: i64, whence: int)) { - case let err: rt::errno => - return errors::errno(err); - case let n: i64 => - return n: off; - }; -}; - -fn fd_copy(to: file, from: file) (size | error) = errors::unsupported; diff --git a/io/+freebsd/platform_file.ha b/io/+freebsd/platform_file.ha @@ -0,0 +1,84 @@ +// License: MPL-2.0 +// (c) 2021-2022 Drew DeVault <sir@cmpwn.com> +// (c) 2021 Ember Sawady <ecs@d2evs.net> +use errors; +use rt; +use strings; + +// This is an opaque type which encloses an OS-level file handle resource. It +// can be used as a [[handle]] in most situations, but there are some APIs which +// require a [[file]] with some OS-level handle backing it - this type is used +// for such APIs. +// +// On FreeBSD, [[io::file]] is a file descriptor. +export type file = int; + +// Opens a Unix file descriptor as a file. This is a low-level interface, to +// open files most programs will use something like [[os::open]]. This function +// is not portable. +export fn fdopen(fd: int) file = fd; + +fn fd_read(fd: file, buf: []u8) (size | EOF | error) = { + match (rt::read(fd, buf: *[*]u8, len(buf))) { + case let err: rt::errno => + return errors::errno(err); + case let n: size => + switch (n) { + case 0 => + return EOF; + case => + return n; + }; + }; +}; + +fn fd_write(fd: file, buf: const []u8) (size | error) = { + match (rt::write(fd, buf: *const [*]u8, len(buf))) { + case let err: rt::errno => + return errors::errno(err); + case let n: size => + return n; + }; +}; + +fn fd_close(fd: file) (void | error) = { + match (rt::close(fd)) { + case void => void; + case let err: rt::errno => + return errors::errno(err); + }; +}; + +fn fd_seek( + fd: file, + offs: off, + whence: whence, +) (off | error) = { + match (rt::lseek(fd, offs: i64, whence: int)) { + case let err: rt::errno => + return errors::errno(err); + case let n: i64 => + return n: off; + }; +}; + +fn fd_copy(to: file, from: file) (size | error) = errors::unsupported; + +fn fd_lock(fd: file, flags: int) (bool | error) = { + match (rt::flock(fd: int, flags)) { + case void => return true; + case let e: rt::errno => + if (e == rt::EWOULDBLOCK: rt::errno) { + return false; + } else { + return errors::errno(e); + }; + }; +}; + +fn fd_trunc(fd: file, ln: size) (void | error) = { + match (rt::ftruncate(fd: int, ln: rt::off_t)) { + case void => void; + case let e: rt::errno => return errors::errno(e); + }; +}; diff --git a/io/+freebsd/platform_lock.ha b/io/+freebsd/platform_lock.ha @@ -1,15 +0,0 @@ -// License: MPL-2.0 -use errors; -use rt; - -fn platform_lock(fd: file, flags: int) (bool | error) = { - match (rt::flock(fd: int, flags)) { - case void => return true; - case let e: rt::errno => - if (e == rt::EWOULDBLOCK: rt::errno) { - return false; - } else { - return errors::errno(e); - }; - }; -}; diff --git a/io/+freebsd/platform_trunc.ha b/io/+freebsd/platform_trunc.ha @@ -1,10 +0,0 @@ -// License: MPL-2.0 -use errors; -use rt; - - fn platform_trunc(fd: file, ln: size) (void | error) = { - match (rt::ftruncate(fd: int, ln: rt::off_t)) { - case void => void; - case let e: rt::errno => return errors::errno(e); - }; - }; diff --git a/io/+linux/file.ha b/io/+linux/file.ha @@ -1,81 +0,0 @@ -// License: MPL-2.0 -// (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net> -// (c) 2021-2022 Drew DeVault <sir@cmpwn.com> -// (c) 2021 Ember Sawady <ecs@d2evs.net> -use errors; -use rt; -use strings; - -// This is an opaque type which encloses an OS-level file handle resource. It -// can be used as a [[handle]] in most situations, but there are some APIs which -// require a [[file]] with some OS-level handle backing it - this type is used -// for such APIs. -// -// On Linux, [[file]] is a file descriptor. -export type file = int; - -// Opens a Unix file descriptor as a file. This is a low-level interface, to -// open files most programs will use something like [[os::open]]. This function -// is not portable. -export fn fdopen(fd: int) file = fd; - -fn fd_read(fd: file, buf: []u8) (size | EOF | error) = { - match (rt::read(fd, buf: *[*]u8, len(buf))) { - case let err: rt::errno => - return errors::errno(err); - case let n: size => - switch (n) { - case 0 => - return EOF; - case => - return n; - }; - }; -}; - -fn fd_write(fd: file, buf: const []u8) (size | error) = { - match (rt::write(fd, buf: *const [*]u8, len(buf))) { - case let err: rt::errno => - return errors::errno(err); - case let n: size => - return n; - }; -}; - -fn fd_close(fd: file) (void | error) = { - match (rt::close(fd)) { - case void => void; - case let err: rt::errno => - return errors::errno(err); - }; -}; - -fn fd_seek( - fd: file, - offs: off, - whence: whence, -) (off | error) = { - match (rt::lseek(fd, offs: i64, whence: int)) { - case let err: rt::errno => - return errors::errno(err); - case let n: i64 => - return n: off; - }; -}; - -def SENDFILE_MAX: size = 2147479552z; - -fn fd_copy(to: file, from: file) (size | error) = { - let sum = 0z; - for (true) match (rt::sendfile(to, from, null, SENDFILE_MAX)) { - case let err: rt::errno => - if (err == rt::EINVAL && sum == 0) { - return errors::unsupported; - }; - return errors::errno(err); - case let n: size => - if (n == 0) break; - sum += n; - }; - return sum; -}; diff --git a/io/+linux/platform_file.ha b/io/+linux/platform_file.ha @@ -0,0 +1,100 @@ +// License: MPL-2.0 +// (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net> +// (c) 2021-2022 Drew DeVault <sir@cmpwn.com> +// (c) 2021 Ember Sawady <ecs@d2evs.net> +use errors; +use rt; +use strings; + +// This is an opaque type which encloses an OS-level file handle resource. It +// can be used as a [[handle]] in most situations, but there are some APIs which +// require a [[file]] with some OS-level handle backing it - this type is used +// for such APIs. +// +// On Linux, [[file]] is a file descriptor. +export type file = int; + +// Opens a Unix file descriptor as a file. This is a low-level interface, to +// open files most programs will use something like [[os::open]]. This function +// is not portable. +export fn fdopen(fd: int) file = fd; + +fn fd_read(fd: file, buf: []u8) (size | EOF | error) = { + match (rt::read(fd, buf: *[*]u8, len(buf))) { + case let err: rt::errno => + return errors::errno(err); + case let n: size => + switch (n) { + case 0 => + return EOF; + case => + return n; + }; + }; +}; + +fn fd_write(fd: file, buf: const []u8) (size | error) = { + match (rt::write(fd, buf: *const [*]u8, len(buf))) { + case let err: rt::errno => + return errors::errno(err); + case let n: size => + return n; + }; +}; + +fn fd_close(fd: file) (void | error) = { + match (rt::close(fd)) { + case void => void; + case let err: rt::errno => + return errors::errno(err); + }; +}; + +fn fd_seek( + fd: file, + offs: off, + whence: whence, +) (off | error) = { + match (rt::lseek(fd, offs: i64, whence: int)) { + case let err: rt::errno => + return errors::errno(err); + case let n: i64 => + return n: off; + }; +}; + +def SENDFILE_MAX: size = 2147479552z; + +fn fd_copy(to: file, from: file) (size | error) = { + let sum = 0z; + for (true) match (rt::sendfile(to, from, null, SENDFILE_MAX)) { + case let err: rt::errno => + if (err == rt::EINVAL && sum == 0) { + return errors::unsupported; + }; + return errors::errno(err); + case let n: size => + if (n == 0) break; + sum += n; + }; + return sum; +}; + +fn fd_lock(fd: file, flags: int) (bool | error) = { + match (rt::flock(fd: int, flags)) { + case void => return true; + case let e: rt::errno => + if (e == rt::EWOULDBLOCK: rt::errno) { + return false; + } else { + return errors::errno(e); + }; + }; +}; + +fn fd_trunc(fd: file, ln: size) (void | error) = { + match (rt::ftruncate(fd: int, ln: rt::off_t)) { + case void => void; + case let e: rt::errno => return errors::errno(e); + }; +}; diff --git a/io/+linux/platform_lock.ha b/io/+linux/platform_lock.ha @@ -1,15 +0,0 @@ -// License: MPL-2.0 -use errors; -use rt; - -fn platform_lock(fd: file, flags: int) (bool | error) = { - match (rt::flock(fd: int, flags)) { - case void => return true; - case let e: rt::errno => - if (e == rt::EWOULDBLOCK: rt::errno) { - return false; - } else { - return errors::errno(e); - }; - }; -}; diff --git a/io/+linux/platform_trunc.ha b/io/+linux/platform_trunc.ha @@ -1,10 +0,0 @@ -// License: MPL-2.0 -use errors; -use rt; - - fn platform_trunc(fd: file, ln: size) (void | error) = { - match (rt::ftruncate(fd: int, ln: rt::off_t)) { - case void => void; - case let e: rt::errno => return errors::errno(e); - }; - }; diff --git a/io/file.ha b/io/file.ha @@ -0,0 +1,23 @@ +// License: MPL-2.0 +use rt; + +// Lock operation to use with [[lock]]. +export type lockop = enum int { + // shared file lock + SHARED = rt::LOCK_SH, + // exclusive file lock + EXCLUSIVE = rt::LOCK_EX, + // unlock file + UNLOCK = rt::LOCK_UN, +}; + +// Apply or remove an advisory lock on an open file. If block is true, the request will block while waiting +// for the lock. +export fn lock(fd: file, block: bool, op: lockop) (bool | error) = { + let flags = op: int; + if (!block) flags |= rt::LOCK_NB; + return fd_lock(fd, flags); +}; + +// Truncate a file to a specified length. The file must be open for writing. +export fn trunc(fd: file, ln: size) (void | error) = fd_trunc(fd, ln); diff --git a/io/lock.ha b/io/lock.ha @@ -1,20 +0,0 @@ -// License: MPL-2.0 -use rt; - -// Lock operation to use with [[lock]]. -export type lockop = enum int { - // shared file lock - SHARED = rt::LOCK_SH, - // exclusive file lock - EXCLUSIVE = rt::LOCK_EX, - // unlock file - UNLOCK = rt::LOCK_UN, -}; - -// Apply or remove an advisory lock on an open file. If block is true, the request will block while waiting -// for the lock. -export fn lock(fd: file, block: bool, op: lockop) (bool | error) = { - let flags = op: int; - if (!block) flags |= rt::LOCK_NB; - return platform_lock(fd, flags); -}; diff --git a/io/trunc.ha b/io/trunc.ha @@ -1,4 +0,0 @@ -// License: MPL-2.0 - -// Truncate a file to a specified length. The file must be open for writing. -export fn trunc(fd: file, ln: size) (void | error) = platform_trunc(fd, ln); diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -867,40 +867,34 @@ hash_siphash() { gensrcs_io() { gen_srcs -plinux io \ 'arch+$(ARCH).ha' \ - +linux/file.ha \ +linux/mmap.ha \ - +linux/platform_lock.ha \ - +linux/platform_trunc.ha \ + +linux/platform_file.ha \ +linux/vector.ha \ copy.ha \ drain.ha \ empty.ha \ + file.ha \ handle.ha \ limit.ha \ - lock.ha \ stream.ha \ tee.ha \ - trunc.ha \ types.ha \ util.ha \ zero.ha \ $* gen_srcs -pfreebsd io \ 'arch+$(ARCH).ha' \ - +freebsd/file.ha \ +freebsd/mmap.ha \ - +freebsd/platform_lock.ha \ - +freebsd/platform_trunc.ha \ + +freebsd/platform_file.ha \ +freebsd/vector.ha \ copy.ha \ drain.ha \ empty.ha \ + file.ha \ handle.ha \ limit.ha \ - lock.ha \ stream.ha \ tee.ha \ - trunc.ha \ types.ha \ util.ha \ zero.ha \ diff --git a/stdlib.mk b/stdlib.mk @@ -1556,20 +1556,17 @@ $(HARECACHE)/hash/siphash/hash_siphash-any.ssa: $(stdlib_hash_siphash_any_srcs) # io (+linux) stdlib_io_linux_srcs = \ $(STDLIB)/io/arch+$(ARCH).ha \ - $(STDLIB)/io/+linux/file.ha \ $(STDLIB)/io/+linux/mmap.ha \ - $(STDLIB)/io/+linux/platform_lock.ha \ - $(STDLIB)/io/+linux/platform_trunc.ha \ + $(STDLIB)/io/+linux/platform_file.ha \ $(STDLIB)/io/+linux/vector.ha \ $(STDLIB)/io/copy.ha \ $(STDLIB)/io/drain.ha \ $(STDLIB)/io/empty.ha \ + $(STDLIB)/io/file.ha \ $(STDLIB)/io/handle.ha \ $(STDLIB)/io/limit.ha \ - $(STDLIB)/io/lock.ha \ $(STDLIB)/io/stream.ha \ $(STDLIB)/io/tee.ha \ - $(STDLIB)/io/trunc.ha \ $(STDLIB)/io/types.ha \ $(STDLIB)/io/util.ha \ $(STDLIB)/io/zero.ha @@ -1577,20 +1574,17 @@ stdlib_io_linux_srcs = \ # io (+freebsd) stdlib_io_freebsd_srcs = \ $(STDLIB)/io/arch+$(ARCH).ha \ - $(STDLIB)/io/+freebsd/file.ha \ $(STDLIB)/io/+freebsd/mmap.ha \ - $(STDLIB)/io/+freebsd/platform_lock.ha \ - $(STDLIB)/io/+freebsd/platform_trunc.ha \ + $(STDLIB)/io/+freebsd/platform_file.ha \ $(STDLIB)/io/+freebsd/vector.ha \ $(STDLIB)/io/copy.ha \ $(STDLIB)/io/drain.ha \ $(STDLIB)/io/empty.ha \ + $(STDLIB)/io/file.ha \ $(STDLIB)/io/handle.ha \ $(STDLIB)/io/limit.ha \ - $(STDLIB)/io/lock.ha \ $(STDLIB)/io/stream.ha \ $(STDLIB)/io/tee.ha \ - $(STDLIB)/io/trunc.ha \ $(STDLIB)/io/types.ha \ $(STDLIB)/io/util.ha \ $(STDLIB)/io/zero.ha @@ -3997,20 +3991,17 @@ $(TESTCACHE)/hash/siphash/hash_siphash-any.ssa: $(testlib_hash_siphash_any_srcs) # io (+linux) testlib_io_linux_srcs = \ $(STDLIB)/io/arch+$(ARCH).ha \ - $(STDLIB)/io/+linux/file.ha \ $(STDLIB)/io/+linux/mmap.ha \ - $(STDLIB)/io/+linux/platform_lock.ha \ - $(STDLIB)/io/+linux/platform_trunc.ha \ + $(STDLIB)/io/+linux/platform_file.ha \ $(STDLIB)/io/+linux/vector.ha \ $(STDLIB)/io/copy.ha \ $(STDLIB)/io/drain.ha \ $(STDLIB)/io/empty.ha \ + $(STDLIB)/io/file.ha \ $(STDLIB)/io/handle.ha \ $(STDLIB)/io/limit.ha \ - $(STDLIB)/io/lock.ha \ $(STDLIB)/io/stream.ha \ $(STDLIB)/io/tee.ha \ - $(STDLIB)/io/trunc.ha \ $(STDLIB)/io/types.ha \ $(STDLIB)/io/util.ha \ $(STDLIB)/io/zero.ha \ @@ -4020,20 +4011,17 @@ testlib_io_linux_srcs = \ # io (+freebsd) testlib_io_freebsd_srcs = \ $(STDLIB)/io/arch+$(ARCH).ha \ - $(STDLIB)/io/+freebsd/file.ha \ $(STDLIB)/io/+freebsd/mmap.ha \ - $(STDLIB)/io/+freebsd/platform_lock.ha \ - $(STDLIB)/io/+freebsd/platform_trunc.ha \ + $(STDLIB)/io/+freebsd/platform_file.ha \ $(STDLIB)/io/+freebsd/vector.ha \ $(STDLIB)/io/copy.ha \ $(STDLIB)/io/drain.ha \ $(STDLIB)/io/empty.ha \ + $(STDLIB)/io/file.ha \ $(STDLIB)/io/handle.ha \ $(STDLIB)/io/limit.ha \ - $(STDLIB)/io/lock.ha \ $(STDLIB)/io/stream.ha \ $(STDLIB)/io/tee.ha \ - $(STDLIB)/io/trunc.ha \ $(STDLIB)/io/types.ha \ $(STDLIB)/io/util.ha \ $(STDLIB)/io/zero.ha \