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:
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))