commit c97b946439ed6024d4a1381d70e4fd2cdd426db7
parent 904ef3090352080cee6f7a0898cbf32066d3f536
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 4 Sep 2021 11:03:07 +0200
all: return io::file from os::open
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
18 files changed, 80 insertions(+), 73 deletions(-)
diff --git a/cmd/harec/errors.ha b/cmd/harec/errors.ha
@@ -16,18 +16,18 @@ fn printerr(err: parse::error) void = {
fn printerr_syntax(err: lex::syntax) void = {
let location = err.0, details = err.1;
- let file = os::open(location.path) as *io::stream;
- defer io::close(file);
+ let file = os::open(location.path)!;
+ defer io::close(&file);
let line = 1u;
for (line < location.line) {
- let r = bufio::scanrune(file) as rune;
+ let r = bufio::scanrune(&file) as rune;
if (r == '\n') {
line += 1u;
};
};
- let line = bufio::scanline(file) as []u8;
+ let line = bufio::scanline(&file) as []u8;
defer free(line);
let line = strings::fromutf8(line);
fmt::errorfln("{}:{},{}: Syntax error: {}",
diff --git a/cmd/harec/main.ha b/cmd/harec/main.ha
@@ -51,13 +51,13 @@ export fn main() void = {
for (let i = 0z; i < len(cmd.args); i += 1) {
let input = match (os::open(cmd.args[i])) {
- f: *io::stream => f,
+ f: io::file => f,
err: io::error => fmt::fatal("Error opening {}: {}",
cmd.args[i], io::strerror(err)),
};
- defer io::close(input);
+ defer io::close(&input);
static let buf: [os::BUFSIZ]u8 = [0...];
- let bufin = bufio::buffered(input, buf, []);
+ let bufin = bufio::buffered(&input, buf, []);
defer io::close(bufin);
let lexer = lex::init(bufin, cmd.args[i]);
diff --git a/cmd/haredoc/hare.ha b/cmd/haredoc/hare.ha
@@ -14,9 +14,9 @@ fn emit_hare(ctx: *context) (void | error) = {
let first = true;
match (ctx.readme) {
- readme: *io::stream => {
+ readme: io::file => {
first = false;
- for (true) match (bufio::scanline(readme)?) {
+ for (true) match (bufio::scanline(&readme)?) {
b: []u8 => {
fmt::printfln("// {}", strings::fromutf8(b))?;
free(b);
@@ -24,7 +24,7 @@ fn emit_hare(ctx: *context) (void | error) = {
io::EOF => break,
};
},
- null => void,
+ void => void,
};
// XXX: Should we emit the dependencies, too?
diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha
@@ -71,10 +71,10 @@ fn emit_html(ctx: *context) (void | error) = {
fmt::println("</span></h2>")?;
match (ctx.readme) {
- null => void,
- f: *io::stream => {
+ void => void,
+ f: io::file => {
fmt::println("<div class='readme'>")?;
- markup_html(ctx, f)?;
+ markup_html(ctx, &f)?;
fmt::println("</div>")?;
},
};
diff --git a/cmd/haredoc/main.ha b/cmd/haredoc/main.ha
@@ -27,7 +27,7 @@ type context = struct {
format: format,
template: bool,
show_undocumented: bool,
- readme: nullable *io::stream,
+ readme: (io::file | void),
};
export fn main() void = {
@@ -110,15 +110,15 @@ export fn main() void = {
const rpath = path::join(version.basedir, "README");
defer free(rpath);
- const readme: nullable *io::stream = if (decl == "") {
+ const readme: (io::file | void) = if (decl == "") {
yield match (os::open(rpath)) {
- err: fs::error => null,
- f: *io::stream => f,
+ err: fs::error => void,
+ f: io::file => f,
};
- } else null;
+ } else void;
defer match (readme) {
- null => void,
- f: *io::stream => io::close(f),
+ void => void,
+ f: io::file => io::close(&f),
};
if (decl != "") {
@@ -176,12 +176,12 @@ fn has_decl(decl: ast::decl, name: str) bool = {
fn scan(path: str) (ast::subunit | error) = {
const input = match (os::open(path)) {
- s: *io::stream => s,
+ f: io::file => f,
err: fs::error => fmt::fatal("Error reading {}: {}",
path, fs::strerror(err)),
};
- defer io::close(input);
- const lexer = lex::init(input, path, lex::flags::COMMENTS);
+ defer io::close(&input);
+ const lexer = lex::init(&input, path, lex::flags::COMMENTS);
return parse::subunit(&lexer)?;
};
diff --git a/cmd/haredoc/tty.ha b/cmd/haredoc/tty.ha
@@ -16,8 +16,8 @@ fn emit_tty(ctx: *context) (void | error) = {
const summary = ctx.summary;
match (ctx.readme) {
- readme: *io::stream => {
- for (true) match (bufio::scanline(readme)?) {
+ readme: io::file => {
+ for (true) match (bufio::scanline(&readme)?) {
b: []u8 => {
firstline = false;
fmt::printfln(
@@ -28,7 +28,7 @@ fn emit_tty(ctx: *context) (void | error) = {
io::EOF => break,
};
},
- null => void,
+ void => void,
};
// XXX: Should we emit the dependencies, too?
diff --git a/fs/fs.ha b/fs/fs.ha
@@ -24,7 +24,7 @@ export fn open(fs: *fs, path: str, flags: flags...) (*io::stream | error) = {
// filesystem implementations (such cases will return [[io::unsupported]]).
//
// If no flags are provided, the default read/write mode is RDONLY.
-export fn open_file(fs: *fs, path: str, flags: flags...) (*io::file | error) = {
+export fn open_file(fs: *fs, path: str, flags: flags...) (io::file | error) = {
return match (fs.openfile) {
null => errors::unsupported,
f: *openfilefunc => f(fs, path, flags...),
@@ -56,7 +56,7 @@ export fn create_file(
path: str,
mode: mode,
flags: flags...
-) (*io::file | error) = {
+) (io::file | error) = {
return match (fs.createfile) {
null => errors::unsupported,
f: *createfilefunc => f(fs, path, mode, flags...),
diff --git a/fs/types.ha b/fs/types.ha
@@ -187,7 +187,7 @@ export type openfilefunc = fn(
fs: *fs,
path: str,
flags: flags...
-) (*io::file | error);
+) (io::file | error);
export type createfunc = fn(
fs: *fs,
@@ -201,7 +201,7 @@ export type createfilefunc = fn(
path: str,
mode: mode,
flags: flags...
-) (*io::file | error);
+) (io::file | error);
// An abstract implementation of a filesystem, which provides common filesystem
// operations such as file creation and deletion, but which may be backed by any
diff --git a/hare/module/manifest.ha b/hare/module/manifest.ha
@@ -233,18 +233,18 @@ export fn manifest_write(ctx: *context, manifest: *manifest) (void | error) = {
let mpath = path::join(cachedir, "manifest");
defer free(mpath);
- let fd = temp::named(ctx.fs, cachedir, io::mode::WRITE, 0o644)?;
+ let file = temp::named(ctx.fs, cachedir, io::mode::WRITE, 0o644)?;
defer {
- fs::remove(ctx.fs, fd.name): void;
- io::close(fd);
+ fs::remove(ctx.fs, file.name): void;
+ io::close(&file);
};
let ident = unparse::identstr(manifest.ident);
defer free(ident);
- fmt::fprintfln(fd, "# {}", ident)?;
- fmt::fprintln(fd, "# This file is an internal Hare implementation detail.")?;
- fmt::fprintln(fd, "# The format is not stable.")?;
- fmt::fprintfln(fd, "version {}", VERSION)?;
+ fmt::fprintfln(&file, "# {}", ident)?;
+ fmt::fprintln(&file, "# This file is an internal Hare implementation detail.")?;
+ fmt::fprintln(&file, "# The format is not stable.")?;
+ fmt::fprintfln(&file, "version {}", VERSION)?;
for (let i = 0z; i < len(manifest.inputs); i += 1) {
const input = manifest.inputs[i];
let hash = hex::encodestr(input.hash);
@@ -252,7 +252,7 @@ export fn manifest_write(ctx: *context, manifest: *manifest) (void | error) = {
const want = fs::stat_mask::INODE | fs::stat_mask::MTIME;
assert(input.stat.mask & want == want);
- fmt::fprintfln(fd, "input {} {} {} {}",
+ fmt::fprintfln(&file, "input {} {} {} {}",
hash, input.path, input.stat.inode,
time::unix(input.stat.mtime))?;
};
@@ -262,19 +262,19 @@ export fn manifest_write(ctx: *context, manifest: *manifest) (void | error) = {
let hash = hex::encodestr(ver.hash);
defer free(hash);
- fmt::fprintf(fd, "module {}", hash)?;
+ fmt::fprintf(&file, "module {}", hash)?;
for (let j = 0z; j < len(ver.inputs); j += 1) {
let hash = hex::encodestr(ver.inputs[i].hash);
defer free(hash);
- fmt::fprintf(fd, " {}", hash)?;
+ fmt::fprintf(&file, " {}", hash)?;
};
- fmt::fprintln(fd)?;
+ fmt::fprintln(&file)?;
};
- fs::move(ctx.fs, fd.name, mpath)?;
+ fs::move(ctx.fs, file.name, mpath)?;
};
fn input_finish(in: *input) void = {
diff --git a/io/+linux/file.ha b/io/+linux/file.ha
@@ -33,14 +33,19 @@ export fn fdopen(fd: int, name: str, mode: mode) file = {
return stream;
};
+// Duplicates a [[file]] onto the heap, as if it were opened with [[fdalloc]].
+export fn filedup(f: *file) *file = {
+ let new = alloc(*f);
+ new.closer = &fd_close;
+ return new;
+};
+
// Similar to [[fdopen]], but heap-allocates the file. Closing the stream will
// free the associated resources.
-export fn fdalloc(fd: int, name: str, mode: mode) *file = {
- let file = alloc(fdopen(fd, strings::dup(name), mode));
- file.closer = &fd_close;
- return file;
-};
+export fn fdalloc(fd: int, name: str, mode: mode) *file =
+ filedup(&fdopen(fd, strings::dup(name), mode));
+// Returns true if a [[stream]] is a file.
export fn is_file(s: *stream) bool = {
return s.reader == &fd_read
|| s.writer == &fd_write
diff --git a/os/+linux/dirfdfs.ha b/os/+linux/dirfdfs.ha
@@ -126,7 +126,7 @@ fn _fs_open(
path: str,
mode: io::mode,
oh: *rt::open_how,
-) (*io::file | fs::error) = {
+) (io::file | fs::error) = {
let fs = fs: *os_filesystem;
oh.resolve = 0u64;
@@ -148,14 +148,14 @@ fn _fs_open(
fd: int => fd,
};
- return io::fdalloc(fd, path, mode);
+ return io::fdopen(fd, path, mode);
};
fn fs_open_file(
fs: *fs::fs,
path: str,
flags: fs::flags...
-) (*io::file | fs::error) = {
+) (io::file | fs::error) = {
let oflags = 0;
let iomode = io::mode::NONE;
if (len(flags) == 0z) {
@@ -192,14 +192,14 @@ fn fs_open(
fs: *fs::fs,
path: str,
flags: fs::flags...
-) (*io::stream | fs::error) = fs_open_file(fs, path, flags...)?;
+) (*io::stream | fs::error) = io::filedup(&fs_open_file(fs, path, flags...)?);
fn fs_create_file(
fs: *fs::fs,
path: str,
mode: fs::mode,
flags: fs::flags...
-) (*io::file | fs::error) = {
+) (io::file | fs::error) = {
let oflags = 0;
let iomode = io::mode::NONE;
if (len(flags) == 0z) {
@@ -233,7 +233,9 @@ fn fs_create(
path: str,
mode: fs::mode,
flags: fs::flags...
-) (*io::stream | fs::error) = fs_create_file(fs, path, mode, flags...)?;
+) (*io::stream | fs::error) = {
+ return io::filedup(&fs_create_file(fs, path, mode, flags...)?);
+};
fn fs_remove(fs: *fs::fs, path: str) (void | fs::error) = {
let fs = fs: *os_filesystem;
diff --git a/os/fs.ha b/os/fs.ha
@@ -66,8 +66,8 @@ export fn resolve(path: str) str = fs::resolve(cwd, path);
// [[fs::flags::CLOEXEC]] are used when opening the file. If you pass your own
// flags, it is recommended that you add the latter two unless you know that you
// do not want them.
-export fn open(path: str, flags: fs::flags...) (*io::stream | fs::error) =
- fs::open(cwd, path, flags...);
+export fn open(path: str, flags: fs::flags...) (io::file | fs::error) =
+ fs::open_file(cwd, path, flags...);
// Creates a new file and opens it for writing.
//
@@ -82,4 +82,4 @@ export fn create(
path: str,
mode: fs::mode,
flags: fs::flags...
-) (*io::stream | fs::error) = fs::create(cwd, path, mode, flags...);
+) (io::file | fs::error) = fs::create_file(cwd, path, mode, flags...);
diff --git a/temp/+linux.ha b/temp/+linux.ha
@@ -22,7 +22,7 @@ fn get_tmpdir() str = os::tryenv("TMPDIR", "/tmp");
export fn file(
iomode: io::mode,
mode: fs::mode...
-) (*io::stream | fs::error) = {
+) (io::file | fs::error) = {
assert(iomode == io::mode::WRITE || iomode == io::mode::RDWR);
assert(len(mode) == 0 || len(mode) == 1);
let fmode = if (len(mode) != 0) mode[0] else 0o644: fs::mode;
@@ -36,7 +36,7 @@ export fn file(
// TODO: Add a custom "close" function which removes the named
// file
err: fs::error => named(os::cwd, get_tmpdir(), iomode, mode...),
- s: *io::stream => s,
+ f: io::file => f,
};
};
@@ -54,7 +54,7 @@ export fn named(
path: str,
iomode: io::mode,
mode: fs::mode...
-) (*io::stream | fs::error) = {
+) (io::file | fs::error) = {
assert(iomode == io::mode::WRITE || iomode == io::mode::RDWR);
assert(len(mode) == 0 || len(mode) == 1);
@@ -73,10 +73,10 @@ export fn named(
random::buffer(rand);
const id = *(&rand[0]: *u64);
const fpath = fmt::bsprintf(pathbuf, "{}/temp.{}", path, id);
- match (fs::create(fs, fpath, fmode, oflags)) {
+ match (fs::create_file(fs, fpath, fmode, oflags)) {
errors::exists => continue,
err: fs::error => return err,
- s: *io::stream => return s,
+ f: io::file => return f,
};
};
abort(); // Unreachable
diff --git a/unix/hosts/lookup.ha b/unix/hosts/lookup.ha
@@ -13,11 +13,11 @@ export fn lookup(name: str) []ip::addr = {
// XXX: Would be cool if we could do this without allocating anything
// XXX: Would be cool to have meaningful error handling(?)
const file = os::open(path)!;
- defer io::close(file);
+ defer io::close(&file);
let addrs: []ip::addr = [];
for (true) {
- const line = match (bufio::scanline(file)) {
+ const line = match (bufio::scanline(&file)) {
io::EOF => break,
line: []u8 => line,
};
diff --git a/unix/passwd/group.ha b/unix/passwd/group.ha
@@ -61,13 +61,13 @@ export fn grent_finish(ent: grent) void = {
// See [[nextgr]] for low-level parsing API.
export fn getgroup(name: str) (grent | void) = {
let file = match (os::open("/etc/group")) {
- s: *io::stream => s,
+ f: io::file => f,
* => abort("Unable to open /etc/group"),
};
- defer io::close(file);
+ defer io::close(&file);
for (true) {
- let ent = match (nextgr(file)) {
+ let ent = match (nextgr(&file)) {
e: grent => e,
io::EOF => break,
* => abort("Invalid entry in /etc/group"),
diff --git a/unix/passwd/passwd.ha b/unix/passwd/passwd.ha
@@ -78,13 +78,13 @@ export fn pwent_finish(ent: pwent) void = {
// See [[nextpw]] for low-level parsing API.
export fn getuser(username: str) (pwent | void) = {
let file = match (os::open("/etc/passwd")) {
- s: *io::stream => s,
+ f: io::file => f,
* => abort("Can't open /etc/passwd"),
};
- defer io::close(file);
+ defer io::close(&file);
for (true) {
- let ent = match (nextpw(file)) {
+ let ent = match (nextpw(&file)) {
e: pwent => e,
io::EOF => break,
* => abort("Invalid entry in /etc/passwd"),
diff --git a/unix/resolvconf/load.ha b/unix/resolvconf/load.ha
@@ -23,10 +23,10 @@ export fn load() []ip::addr = {
};
const file = os::open(path)!;
- defer io::close(file);
+ defer io::close(&file);
for (true) {
- const line = match (bufio::scanline(file)) {
+ const line = match (bufio::scanline(&file)) {
io::EOF => break,
line: []u8 => line,
};
diff --git a/unix/tty/+linux/open.ha b/unix/tty/+linux/open.ha
@@ -5,10 +5,10 @@ use os;
// Returns a stream connected to the TTY of the current process. The caller must
// close it using [[io::close]].
-export fn open() (*io::stream | error) = {
+export fn open() (io::file | error) = {
return match (os::open("/dev/tty", fs::flags::RDWR,
fs::flags::CLOEXEC)) {
- s: *io::stream => s,
+ f: io::file => f,
fs::error => errors::noentry,
};
};