hare

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

commit 904ef3090352080cee6f7a0898cbf32066d3f536
parent 098879d7cd61043130abc1125ec63a1b564e9e31
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat,  4 Sep 2021 10:51:50 +0200

io: introduce io::unwrapfd

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mio/+linux/file.ha | 22+++++++++++++---------
Munix/tty/+linux/isatty.ha | 5++++-
Munix/tty/+linux/winsize.ha | 5++++-
3 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/io/+linux/file.ha b/io/+linux/file.ha @@ -48,16 +48,20 @@ export fn is_file(s: *stream) bool = { || s.copier == &fd_copy; }; -// Returns the file descriptor for a given [[file]] or [[stream]]. In the latter -// case, a non-file input will cause the program to abort. This function is not +// Returns the file descriptor for a given [[file]]. This function is not // portable. -export fn fd(f: (*file | *stream)) int = match (f) { - f: *file => f.fd, - f: *stream => { - assert(is_file(f)); - let f = f: *file; - yield f.fd; - }, +export fn fd(f: *file) int = f.fd; + +// Returns the file descriptor for a given [[stream]], returning void if the +// stream is not backed by a file. This function is not portable. +export fn unwrapfd(s: *stream) (int | void) = { + for (!is_file(s)) { + s = match (io::source(s)) { + errors::unsupported => return, + s: *io::stream => s, + }; + }; + return fd(s: *file); }; fn fd_read(s: *stream, buf: []u8) (size | EOF | error) = { diff --git a/unix/tty/+linux/isatty.ha b/unix/tty/+linux/isatty.ha @@ -4,7 +4,10 @@ use os; // Returns whether the given stream is connected to a terminal. export fn isatty(stream: *io::stream) bool = { - let fd = io::fd(stream); + let fd = match (io::unwrapfd(stream)) { + void => return false, + fd: int => fd, + }; let wsz = rt::winsize { ... }; return match (rt::ioctl(fd, rt::TIOCGWINSZ, &wsz: *void)) { e: rt::errno => false, diff --git a/unix/tty/+linux/winsize.ha b/unix/tty/+linux/winsize.ha @@ -5,7 +5,10 @@ use rt; // Returns the dimensions of underlying terminal of the stream. export fn winsize(tty: *io::stream) (ttysize | error) = { - let fd = io::fd(tty); + let fd = match (io::unwrapfd(tty)) { + void => return errors::unsupported, + fd: int => fd, + }; let wsz = rt::winsize { ... }; return match (rt::ioctl(fd, rt::TIOCGWINSZ, &wsz: *void)) { e: rt::errno => switch (e: int) {