hare

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

commit edb9ae65c0526a3c8a809d5cbead44857deef5f1
parent c26cce3953435c6f580c9d4b9e3f3179f5a3ab97
Author: Autumn! <autumnull@posteo.net>
Date:   Sun,  7 May 2023 01:43:32 +0000

path: remove join(), add prepend()

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

Diffstat:
Mcmd/hare/plan.ha | 3++-
Mcmd/hare/schedule.ha | 4++--
Mcmd/haredoc/html.ha | 5++---
Mcmd/haredoc/main.ha | 5++---
Mhare/module/manifest.ha | 16++++++++--------
Mhare/module/scan.ha | 16++++++++--------
Mhare/module/walk.ha | 21+++++++++------------
Apath/prefix.ha | 20++++++++++++++++++++
Mpath/stack.ha | 8--------
Mscripts/gen-stdlib | 1+
Mstdlib.mk | 2++
11 files changed, 56 insertions(+), 45 deletions(-)

diff --git a/cmd/hare/plan.ha b/cmd/hare/plan.ha @@ -313,5 +313,6 @@ fn mkfile(plan: *plan, input: str, ext: str) str = { const name = fmt::bsprintf(namebuf, "temp.{}.{}.{}", input, plan.counter, ext); plan.counter += 1; - return path::join(plan.workdir, name); + const buf = path::init(plan.workdir, name)!; + return strings::dup(path::string(&buf)); }; diff --git a/cmd/hare/schedule.ha b/cmd/hare/schedule.ha @@ -317,8 +317,8 @@ fn sched_hare_object( fmt::fatalf("Error: mkdirs {}: {}", path, fs::strerror(err)); }; - append(harec.cmd, ["-t", path::join(path, td)]...); - yield path::join(path, name); + append(harec.cmd, ["-t", strings::dup(path::push(&buf, td)!)]...); + yield strings::dup(path::push(&buf, "..", name)!); } else { // XXX: This is probably kind of dumb // It would be better to apply any defines which affect this diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha @@ -134,11 +134,10 @@ fn emit_html(ctx: *context) (void | error) = { fmt::fprintln(ctx.out, "<ul class='submodules'>")?; for (let i = 0z; i < len(submodules); i += 1) { let submodule = submodules[i]; - let path = path::join("/", identpath, submodule); - defer free(path); + let path = path::init("/", identpath, submodule)!; fmt::fprintf(ctx.out, "<li><a href='")?; - html_escape(ctx.out, path)?; + html_escape(ctx.out, path::string(&path))?; fmt::fprintf(ctx.out, "'>")?; html_escape(ctx.out, submodule)?; fmt::fprintfln(ctx.out, "</a></li>")?; diff --git a/cmd/haredoc/main.ha b/cmd/haredoc/main.ha @@ -161,10 +161,9 @@ export fn main() void = { }; }; - const rpath = path::join(version.basedir, "README"); - defer free(rpath); + const rpath = path::init(version.basedir, "README")!; const readme: (io::file | void) = if (decl == "") { - yield match (os::open(rpath)) { + yield match (os::open(path::string(&rpath))) { case let err: fs::error => yield void; case let f: io::file => diff --git a/hare/module/manifest.ha b/hare/module/manifest.ha @@ -53,11 +53,11 @@ export fn manifest_load(ctx: *context, ident: ast::ident) (manifest | error) = { }; let ipath = identpath(manifest.ident); defer free(ipath); - let cachedir = path::join(ctx.cache, ipath); - defer free(cachedir); + let cachedir = path::init(ctx.cache, ipath)!; + let cachedir = path::string(&cachedir); - let mpath = path::join(cachedir, "manifest"); - defer free(mpath); + let mpath = path::init(cachedir, "manifest")!; + let mpath = path::string(&mpath); let truefile = match (fs::open(ctx.fs, mpath, fs::flags::RDONLY)) { case errors::noentry => @@ -316,11 +316,11 @@ export fn current(man: *manifest, ver: *version) bool = { export fn manifest_write(ctx: *context, man: *manifest) (void | error) = { let ipath = identpath(man.ident); defer free(ipath); - let cachedir = path::join(ctx.cache, ipath); - defer free(cachedir); + let cachedir = path::init(ctx.cache, ipath)!; + let cachedir = path::string(&cachedir); - let mpath = path::join(cachedir, "manifest"); - defer free(mpath); + let mpath = path::init(cachedir, "manifest")!; + let mpath = path::string(&mpath); let (truefile, name) = temp::named(ctx.fs, cachedir, io::mode::WRITE, 0o644)?; let wbuf: [os::BUFSIZ]u8 = [0...]; diff --git a/hare/module/scan.ha b/hare/module/scan.ha @@ -83,9 +83,8 @@ export fn scan(ctx: *context, path: str) (version | error) = { }; scan_directory(ctx, &ver, &sha, path, iter)?; - let readme = path::join(path, "README"); - defer free(readme); - if (len(ver.inputs) == 0 && !fs::exists(ctx.fs, readme)) { + let buf = path::init(path, "README")!; + if (len(ver.inputs) == 0 && !fs::exists(ctx.fs, path::string(&buf))) { // TODO: HACK: README is a workaround for haredoc issues return notfound; }; @@ -222,7 +221,8 @@ fn scan_directory( continue; }; - let path = path::join(path, name); + const buf = path::init(path, name)!; + let path = strings::dup(path::string(&buf)); let tuple = (true, strings::dup(base), tags, path); let superceded = false; for (let j = 0z; j < len(inputs); j += 1) { @@ -268,7 +268,8 @@ fn scan_directory( continue; }; - let path = path::join(path, name); + const buf = path::init(path, name)!; + let path = strings::dup(path::string(&buf)); let tuple = (false, strings::dup(base), tags, path); let superceded = false; for (let j = 0z; j < len(inputs); j += 1) { @@ -328,9 +329,8 @@ export fn lookup(ctx: *context, name: ast::ident) (version | error) = { let ipath = identpath(name); defer free(ipath); for (let i = len(ctx.paths); i > 0; i -= 1) { - let cand = path::join(ctx.paths[i - 1], ipath); - defer free(cand); - match (scan(ctx, cand)) { + let cand = path::init(ctx.paths[i - 1], ipath)!; + match (scan(ctx, path::string(&cand))) { case let v: version => return v; case error => void; diff --git a/hare/module/walk.ha b/hare/module/walk.ha @@ -57,26 +57,23 @@ fn _walk( switch (ent.ftype) { case fs::mode::DIR => // TODO: Test that this is a valid name (grammar) - let subpath = path::join(path, ent.name); - defer free(subpath); + let subpath = path::init(path, ent.name)!; let newns = ast::ident_dup(ns); append(newns, strings::dup(ent.name)); - _walk(ctx, subpath, items, newns)?; + _walk(ctx, path::string(&subpath), items, newns)?; case fs::mode::LINK => - let linkpath = path::join(path, ent.name); - defer free(linkpath); - let linkpath = fs::readlink(ctx.fs, linkpath)?; - if (!path::abs(linkpath)) { - linkpath = path::join(path, linkpath); + let linkbuf = path::init(path, ent.name)!; + path::set(&linkbuf, fs::readlink(ctx.fs, path::string(&linkbuf))?)!; + if (!path::abs(&linkbuf)) { + path::prepend(&linkbuf, path)!; }; - const st = fs::stat(ctx.fs, linkpath)?; + const st = fs::stat(ctx.fs, path::string(&linkbuf))?; if (fs::isdir(st.mode)) { - let subpath = path::join(path, ent.name); - defer free(subpath); + let subpath = path::init(path, ent.name)!; let newns = ast::ident_dup(ns); append(newns, strings::dup(ent.name)); - _walk(ctx, subpath, items, newns)?; + _walk(ctx, path::string(&subpath), items, newns)?; }; case fs::mode::REG => void; // no-op diff --git a/path/prefix.ha b/path/prefix.ha @@ -0,0 +1,20 @@ +use strings; + +// Add a prefix to a buffer. The buffer will be modified, and it will +// remain normalized, so any ".." components in the original buffer may be +// collapsed. +export fn prepend(buf: *buffer, prefix: str...) (str | error) = { + static let tmp = buffer { ... }; + tmp = *buf; + set(buf, prefix...)?; + return push(buf, string(&tmp)); +}; + +@test fn prepend() void = { + const buf = init("a")!; + assert(prepend(&buf, "b")! == strings::fromutf8(['b', PATHSEP, 'a'])!); + + set(&buf, pathsepstr, "a")!; + assert(prepend(&buf, "b")! == strings::fromutf8(['b', PATHSEP, 'a'])!); +}; + diff --git a/path/stack.ha b/path/stack.ha @@ -174,14 +174,6 @@ fn split(buf: *buffer) (size, (str | void)) = { assert(string(&buf) == pathsepstr); }; -// Joins a list of path components together, normalizes it, and returns the -// resulting string. The caller must free the return value. If the resulting -// path would exceed [[PATH_MAX]], the program aborts. -export fn join(items: str...) str = { - static let buf = buffer { ... }; - return strings::dup(set(&buf, items...)!); -}; - // Returns the parent directory for a given path, without modifying the buffer. // If the path is the root directory, the root directory is returned. The value // is either borrowed from the input or statically allocated; use diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -1207,6 +1207,7 @@ path() { stack.ha \ ext_stack.ha \ posix.ha \ + prefix.ha \ iter.ha gen_ssa path strings bytes errors } diff --git a/stdlib.mk b/stdlib.mk @@ -1840,6 +1840,7 @@ stdlib_path_any_srcs = \ $(STDLIB)/path/stack.ha \ $(STDLIB)/path/ext_stack.ha \ $(STDLIB)/path/posix.ha \ + $(STDLIB)/path/prefix.ha \ $(STDLIB)/path/iter.ha $(HARECACHE)/path/path-any.ssa: $(stdlib_path_any_srcs) $(stdlib_rt) $(stdlib_strings_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) @@ -4115,6 +4116,7 @@ testlib_path_any_srcs = \ $(STDLIB)/path/stack.ha \ $(STDLIB)/path/ext_stack.ha \ $(STDLIB)/path/posix.ha \ + $(STDLIB)/path/prefix.ha \ $(STDLIB)/path/iter.ha $(TESTCACHE)/path/path-any.ssa: $(testlib_path_any_srcs) $(testlib_rt) $(testlib_strings_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_errors_$(PLATFORM))