hare

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

commit 140cdef5dff9565b0a9828b8a0d6688bb19996db
parent ee84a84873a304f7848b78b9d4aebfa75f80643f
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon,  1 Feb 2021 10:08:50 -0500

os: add os::open

Diffstat:
Mos/+linux/fdstream.ha | 40++++++++++++++++++++--------------------
Aos/+linux/open.ha | 29+++++++++++++++++++++++++++++
Mrt/+linux/abort.ha | 2+-
Mrt/+linux/syscalls.ha | 7+++++--
4 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/os/+linux/fdstream.ha b/os/+linux/fdstream.ha @@ -24,6 +24,26 @@ export fn fdopen(fd: int, name: str) *io::stream = { return &stream.stream; }; +// Returns the file descriptor for a given [io::stream]. If there is no fd +// associated with this stream, void is returned. +export fn streamfd(s: *io::stream) (int | void) = { + if (s.reader != &fd_read) { + return void; + }; + let stream = s: *fd_stream; + return stream.fd; +}; + +fn static_fdopen(fd: int, name: str, stream: *fd_stream) void = { + stream.stream = io::stream { + name = name, + reader = &fd_read, + writer = &fd_write, + closer = &fd_close, + }; + stream.fd = fd; +}; + fn fd_read(s: *io::stream, buf: []u8) (size | io::error) = { let stream = s: *fd_stream; let r = rt::read(stream.fd, (&buf: *types::slice).data: *[*]u8, len(buf)); @@ -53,23 +73,3 @@ fn fd_close(s: *io::stream) void = { rt::close(stream.fd); free(stream); }; - -fn static_fdopen(fd: int, name: str, stream: *fd_stream) void = { - stream.stream = io::stream { - name = name, - reader = &fd_read, - writer = &fd_write, - closer = &fd_close, - }; - stream.fd = fd; -}; - -// Returns the file descriptor for a given [io::stream]. If there is no fd -// associated with this stream, void is returned. -export fn streamfd(s: *io::stream) (int | void) = { - if (s.reader != &fd_read) { - return void; - }; - let stream = s: *fd_stream; - return stream.fd; -}; diff --git a/os/+linux/open.ha b/os/+linux/open.ha @@ -0,0 +1,29 @@ +use io; +use rt; +use strings; + +export fn open(path: (str | []u8), mode: io::mode) (*io::stream | io::error) = { + // Verify that these line up with the Linux ABI: + static assert(io::mode::RDONLY: uint == 0u); + static assert(io::mode::WRONLY: uint == 1u); + static assert(io::mode::RDWR: uint == 2u); + + const p: []u8 = match (path) { + s: str => strings::to_utf8(s), + b: []u8 => b, + }; + const name: str = match (path) { + s: str => s, + b: []u8 => "<open([]u8)>", // TODO: try to decode it? + }; + + // TODO: Cast slice to array + let r = rt::open((&p: *types::slice).data: *const char, mode: int, 0u); + let fd: int = match (rt::wrap_return(r)) { + err: rt::errno => return errno_to_io(err), + n: size => n: int, + }; + + // TODO: Pass mode flags along to fd_stream + return fdopen(fd, name); +}; diff --git a/rt/+linux/abort.ha b/rt/+linux/abort.ha @@ -7,7 +7,7 @@ export @noreturn @symbol("rt.abort") fn _abort(msg: str) void = { }; // See harec:include/gen.h -const reasons: [3]str = [ +const reasons: [_]str = [ "slice or array access out of bounds", // 0 "type assertion failed", // 1 "out of memory", // 2 diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha @@ -6,14 +6,17 @@ fn syscall4(u64, u64, u64, u64, u64) u64; fn syscall5(u64, u64, u64, u64, u64, u64) u64; fn syscall6(u64, u64, u64, u64, u64, u64, u64) u64; -export fn close(fd: int) int = syscall1(SYS_close, fd: u64): int; - export fn read(fd: int, buf: *void, count: size) size = syscall3(SYS_read, fd: u64, buf: uintptr: u64, count: u64): size; export fn write(fd: int, buf: *const void, count: size) size = syscall3(SYS_write, fd: u64, buf: uintptr: u64, count: u64): size; +export fn open(path: *const char, flags: int, mode: uint) size = + syscall3(SYS_open, path: uintptr: u64, flags: u64, mode: u64): size; + +export fn close(fd: int) int = syscall1(SYS_close, fd: u64): int; + export fn getpid() int = syscall0(SYS_getpid): int; export @noreturn fn exit(status: int) void = syscall1(SYS_exit, status: u64);