hare

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

commit e0ed8fa32b0c4d66fd1ec1c2bd4d684cba14e471
parent 478ca35964a855842d5dfebe3063e8e69d100204
Author: Ember Sawady <ecs@d2evs.net>
Date:   Wed,  7 Jun 2023 08:06:41 +0000

os: add setenv and unsetenv

Signed-off-by: Ember Sawady <ecs@d2evs.net>

Diffstat:
Mos/+freebsd/dirfdfs.ha | 1-
Dos/+freebsd/environ.ha | 138-------------------------------------------------------------------------------
Aos/+freebsd/platform_environ.ha | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mos/+linux/dirfdfs.ha | 1-
Dos/+linux/environ.ha | 144-------------------------------------------------------------------------------
Aos/+linux/platform_environ.ha | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aos/environ.ha | 45+++++++++++++++++++++++++++++++++++++++++++++
Mscripts/gen-stdlib | 10++++++----
Mstdlib.mk | 20++++++++++++--------
9 files changed, 283 insertions(+), 296 deletions(-)

diff --git a/os/+freebsd/dirfdfs.ha b/os/+freebsd/dirfdfs.ha @@ -2,7 +2,6 @@ // (c) 2021-2022 Drew DeVault <sir@cmpwn.com> // (c) 2021 Ember Sawady <ecs@d2evs.net> // (c) 2022 Jon Eskin <eskinjp@gmail.com> -use bytes; use errors; use encoding::utf8; use fs; diff --git a/os/+freebsd/environ.ha b/os/+freebsd/environ.ha @@ -1,138 +0,0 @@ -// License: MPL-2.0 -// (c) 2021 Drew DeVault <sir@cmpwn.com> -// (c) 2021 Ember Sawady <ecs@d2evs.net> -use bytes; -use errors; -use rt; -use strings; -use types::c; - -// The command line arguments provided to the program. By convention, the first -// member is usually the name of the program. -export let args: []str = []; - -// Statically allocate arg strings if there are few enough arguments, saves a -// syscall if we don't need it. -let args_static: [32]str = [""...]; - -@init fn init_environ() void = { - if (rt::argc < len(args_static)) { - args = args_static[..rt::argc]; - for (let i = 0z; i < rt::argc; i += 1) { - args[i] = c::tostr(rt::argv[i]: *const c::char)!; - }; - } else { - args = alloc([], rt::argc); - for (let i = 0z; i < rt::argc; i += 1) { - append(args, c::tostr(rt::argv[i]: *const c::char)!); - }; - }; - -}; - -@fini fn fini_environ() void = { - if (rt::argc >= len(args_static)) { - free(args); - }; - free(envp); -}; - -// Looks up an environment variable and returns its value, or void if unset. -export fn getenv(name: const str) (str | void) = { - const name_b = strings::toutf8(name); - for (let i = 0z; rt::envp[i] != null; i += 1) { - const item = rt::envp[i]: *[*]u8; - const ln = c::strlen(item: *c::char); - const eq: size = match (bytes::index(item[..ln], '=')) { - case void => - abort("Environment violates System-V invariants"); - case let i: size => - yield i; - }; - if (bytes::equal(name_b, item[..eq])) { - const ln = c::strlen(item: *const c::char); - return strings::fromutf8(item[eq+1..ln])!; - }; - }; -}; - -// Looks up an environment variable and returns its value, or a default value if -// unset. -export fn tryenv(name: const str, default: str) str = match (getenv(name)) { -case let s: str => - yield s; -case void => - yield default; -}; - -let envp: []str = []; - -// Returns a slice of the environment strings in the form KEY=VALUE. -export fn getenvs() []str = { - if (len(envp) != 0) { - return envp; - }; - for (let i = 0z; rt::envp[i] != null; i += 1) { - append(envp, c::tostr(rt::envp[i]: *const c::char)!); - }; - return envp; -}; - -// Returns the host kernel name -export fn sysname() const str = { - static let buf: [512]u8 = [0...]; - let sz: size = len(buf); - rt::sysctlbyname("kern.ostype", &buf, &sz, null, 0)!; - return strings::fromutf8(buf[..(sz - 1)])!; -}; - -// Returns the host system hostname -export fn hostname() const str = { - static let buf: [512]u8 = [0...]; - let sz: size = len(buf); - rt::sysctlbyname("kern.hostname", &buf, &sz, null, 0)!; - return strings::fromutf8(buf[..(sz - 1)])!; -}; - -// Returns the host kernel version -export fn release() const str = { - static let buf: [512]u8 = [0...]; - let sz: size = len(buf); - rt::sysctlbyname("kern.osrelease", &buf, &sz, null, 0)!; - return strings::fromutf8(buf[..(sz - 1)])!; -}; - -// Returns the host operating system version -export fn version() const str = { - static let buf: [512]u8 = [0...]; - let sz: size = len(buf); - rt::sysctlbyname("kern.version", &buf, &sz, null, 0)!; - return strings::fromutf8(buf[..(sz - 1)])!; -}; - -// Returns the host CPU architecture -export fn machine() const str = { - static let buf: [512]u8 = [0...]; - let sz: size = len(buf); - rt::sysctlbyname("hw.machine", &buf, &sz, null, 0)!; - const mach = strings::fromutf8(buf[..(sz - 1)])!; - // Translate to Hare names - switch (mach) { - case "amd64" => - return "x86_64"; - case => - return mach; - }; -}; - -// Returns the number of usable CPUs. -export fn cpucount() (int | errors::error) = { - let count = 0; - let length = size(int); - match (rt::sysctlbyname("hw.ncpu", &count, &length, null, 0)) { - case void => void; - case let err: rt::errno => - return errors::errno(err); - }; - return count; -}; diff --git a/os/+freebsd/platform_environ.ha b/os/+freebsd/platform_environ.ha @@ -0,0 +1,107 @@ +// License: MPL-2.0 +// (c) 2021 Drew DeVault <sir@cmpwn.com> +// (c) 2021 Ember Sawady <ecs@d2evs.net> +use errors; +use rt; +use strings; +use types::c; + +// The command line arguments provided to the program. By convention, the first +// member is usually the name of the program. +export let args: []str = []; + +// Statically allocate arg strings if there are few enough arguments, saves a +// syscall if we don't need it. +let args_static: [32]str = [""...]; + +@init fn args() void = { + if (rt::argc < len(args_static)) { + args = args_static[..rt::argc]; + for (let i = 0z; i < rt::argc; i += 1) { + args[i] = c::tostr(rt::argv[i]: *const c::char)!; + }; + } else { + args = alloc([], rt::argc); + for (let i = 0z; i < rt::argc; i += 1) { + append(args, c::tostr(rt::argv[i]: *const c::char)!); + }; + }; + +}; + +@fini fn args() void = { + if (rt::argc >= len(args_static)) { + free(args); + }; +}; + +// Returns a slice of the environment strings in the form KEY=VALUE. +export fn getenvs() []str = { + if (len(envp) != 0) { + return envp; + }; + for (let i = 0z; rt::envp[i] != null; i += 1) { + let s = c::tostr(rt::envp[i]: *const c::char)!; + append(envp, strings::dup(s)); + }; + return envp; +}; + +// Returns the host kernel name +export fn sysname() const str = { + static let buf: [512]u8 = [0...]; + let sz: size = len(buf); + rt::sysctlbyname("kern.ostype", &buf, &sz, null, 0)!; + return strings::fromutf8(buf[..(sz - 1)])!; +}; + +// Returns the host system hostname +export fn hostname() const str = { + static let buf: [512]u8 = [0...]; + let sz: size = len(buf); + rt::sysctlbyname("kern.hostname", &buf, &sz, null, 0)!; + return strings::fromutf8(buf[..(sz - 1)])!; +}; + +// Returns the host kernel version +export fn release() const str = { + static let buf: [512]u8 = [0...]; + let sz: size = len(buf); + rt::sysctlbyname("kern.osrelease", &buf, &sz, null, 0)!; + return strings::fromutf8(buf[..(sz - 1)])!; +}; + +// Returns the host operating system version +export fn version() const str = { + static let buf: [512]u8 = [0...]; + let sz: size = len(buf); + rt::sysctlbyname("kern.version", &buf, &sz, null, 0)!; + return strings::fromutf8(buf[..(sz - 1)])!; +}; + +// Returns the host CPU architecture +export fn machine() const str = { + static let buf: [512]u8 = [0...]; + let sz: size = len(buf); + rt::sysctlbyname("hw.machine", &buf, &sz, null, 0)!; + const mach = strings::fromutf8(buf[..(sz - 1)])!; + // Translate to Hare names + switch (mach) { + case "amd64" => + return "x86_64"; + case => + return mach; + }; +}; + +// Returns the number of usable CPUs. +export fn cpucount() (int | errors::error) = { + let count = 0; + let length = size(int); + match (rt::sysctlbyname("hw.ncpu", &count, &length, null, 0)) { + case void => void; + case let err: rt::errno => + return errors::errno(err); + }; + return count; +}; diff --git a/os/+linux/dirfdfs.ha b/os/+linux/dirfdfs.ha @@ -4,7 +4,6 @@ // (c) 2021-2022 Drew DeVault <sir@cmpwn.com> // (c) 2021 Ember Sawady <ecs@d2evs.net> // (c) 2022 Jon Eskin <eskinjp@gmail.com> -use bytes; use errors; use encoding::utf8; use fs; diff --git a/os/+linux/environ.ha b/os/+linux/environ.ha @@ -1,144 +0,0 @@ -// License: MPL-2.0 -// (c) 2021 Drew DeVault <sir@cmpwn.com> -// (c) 2021 Ember Sawady <ecs@d2evs.net> -use bytes; -use errors; -use math; -use rt; -use strings; -use types::c; - -// The command line arguments provided to the program. By convention, the first -// member is usually the name of the program. -export let args: []str = []; - -// Statically allocate arg strings if there are few enough arguments, saves a -// syscall if we don't need it. -let args_static: [32]str = [""...]; - -@init fn init_environ() void = { - if (rt::argc < len(args_static)) { - args = args_static[..rt::argc]; - for (let i = 0z; i < rt::argc; i += 1) { - args[i] = c::tostr(rt::argv[i]: *const c::char)!; - }; - } else { - args = alloc([], rt::argc); - for (let i = 0z; i < rt::argc; i += 1) { - append(args, c::tostr(rt::argv[i]: *const c::char)!); - }; - }; - -}; - -@fini fn fini_environ() void = { - if (rt::argc >= len(args_static)) { - free(args); - }; - free(envp); -}; - -// Looks up an environment variable and returns its value, or void if unset. -export fn getenv(name: const str) (str | void) = { - const name_b = strings::toutf8(name); - for (let i = 0z; rt::envp[i] != null; i += 1) { - const item = rt::envp[i]: *[*]u8; - const ln = c::strlen(item: *c::char); - const eq: size = match (bytes::index(item[..ln], '=')) { - case void => - abort("Environment violates System-V invariants"); - case let i: size => - yield i; - }; - if (bytes::equal(name_b, item[..eq])) { - const ln = c::strlen(item: *const c::char); - return strings::fromutf8(item[eq+1..ln])!; - }; - }; -}; - -// Looks up an environment variable and returns its value, or a default value if -// unset. -export fn tryenv(name: const str, default: str) str = match (getenv(name)) { -case let s: str => - yield s; -case void => - yield default; -}; - -let envp: []str = []; - -// Returns a slice of the environment strings in the form KEY=VALUE. -export fn getenvs() []str = { - if (len(envp) != 0) { - return envp; - }; - for (let i = 0z; rt::envp[i] != null; i += 1) { - append(envp, c::tostr(rt::envp[i]: *const c::char)!); - }; - return envp; -}; - -let uts: rt::utsname = rt::utsname { ... }; -let uts_valid: bool = false; - -// Returns the host kernel name -export fn sysname() const str = { - if (!uts_valid) { - rt::uname(&uts) as void; - uts_valid = true; - }; - return c::tostr(&uts.sysname: *const c::char)!; -}; - -// Returns the host system hostname -export fn hostname() const str = { - if (!uts_valid) { - rt::uname(&uts) as void; - uts_valid = true; - }; - return c::tostr(&uts.nodename: *const c::char)!; -}; - -// Returns the host kernel version -export fn release() const str = { - if (!uts_valid) { - rt::uname(&uts) as void; - uts_valid = true; - }; - return c::tostr(&uts.release: *const c::char)!; -}; - -// Returns the host operating system version -export fn version() const str = { - if (!uts_valid) { - rt::uname(&uts) as void; - uts_valid = true; - }; - return c::tostr(&uts.version: *const c::char)!; -}; - -// Returns the host CPU architecture -export fn machine() const str = { - if (!uts_valid) { - rt::uname(&uts) as void; - uts_valid = true; - }; - return c::tostr(&uts.machine: *const c::char)!; -}; - -// Returns the number of usable CPUs. -export fn cpucount() (int | errors::error) = { - let set = rt::cpu_set { ... }; - match (rt::sched_getaffinity(rt::getpid(), size(rt::cpu_set), &set)) { - case void => void; - case let err: rt::errno => - return errors::errno(err); - }; - - let ret = 0; - for (let i = 0z; i < len(set.__bits); i += 1) { - ret += math::pop_count_u64(set.__bits[i]): int; - }; - return ret; -}; diff --git a/os/+linux/platform_environ.ha b/os/+linux/platform_environ.ha @@ -0,0 +1,113 @@ +// License: MPL-2.0 +// (c) 2021 Drew DeVault <sir@cmpwn.com> +// (c) 2021 Ember Sawady <ecs@d2evs.net> +use errors; +use math; +use rt; +use strings; +use types::c; + +// The command line arguments provided to the program. By convention, the first +// member is usually the name of the program. +export let args: []str = []; + +// Statically allocate arg strings if there are few enough arguments, saves a +// syscall if we don't need it. +let args_static: [32]str = [""...]; + +@init fn args() void = { + if (rt::argc < len(args_static)) { + args = args_static[..rt::argc]; + for (let i = 0z; i < rt::argc; i += 1) { + args[i] = c::tostr(rt::argv[i]: *const c::char)!; + }; + } else { + args = alloc([], rt::argc); + for (let i = 0z; i < rt::argc; i += 1) { + append(args, c::tostr(rt::argv[i]: *const c::char)!); + }; + }; + +}; + +@fini fn args() void = { + if (rt::argc >= len(args_static)) { + free(args); + }; +}; + +// Returns a slice of the environment strings in the form KEY=VALUE. +export fn getenvs() []str = { + if (len(envp) != 0) { + return envp; + }; + for (let i = 0z; rt::envp[i] != null; i += 1) { + let s = c::tostr(rt::envp[i]: *const c::char)!; + append(envp, strings::dup(s)); + }; + return envp; +}; + +let uts: rt::utsname = rt::utsname { ... }; +let uts_valid: bool = false; + +// Returns the host kernel name +export fn sysname() const str = { + if (!uts_valid) { + rt::uname(&uts) as void; + uts_valid = true; + }; + return c::tostr(&uts.sysname: *const c::char)!; +}; + +// Returns the host system hostname +export fn hostname() const str = { + if (!uts_valid) { + rt::uname(&uts) as void; + uts_valid = true; + }; + return c::tostr(&uts.nodename: *const c::char)!; +}; + +// Returns the host kernel version +export fn release() const str = { + if (!uts_valid) { + rt::uname(&uts) as void; + uts_valid = true; + }; + return c::tostr(&uts.release: *const c::char)!; +}; + +// Returns the host operating system version +export fn version() const str = { + if (!uts_valid) { + rt::uname(&uts) as void; + uts_valid = true; + }; + return c::tostr(&uts.version: *const c::char)!; +}; + +// Returns the host CPU architecture +export fn machine() const str = { + if (!uts_valid) { + rt::uname(&uts) as void; + uts_valid = true; + }; + return c::tostr(&uts.machine: *const c::char)!; +}; + +// Returns the number of usable CPUs. +export fn cpucount() (int | errors::error) = { + let set = rt::cpu_set { ... }; + match (rt::sched_getaffinity(rt::getpid(), size(rt::cpu_set), &set)) { + case void => void; + case let err: rt::errno => + return errors::errno(err); + }; + + let ret = 0; + for (let i = 0z; i < len(set.__bits); i += 1) { + ret += math::pop_count_u64(set.__bits[i]): int; + }; + return ret; +}; diff --git a/os/environ.ha b/os/environ.ha @@ -0,0 +1,45 @@ +use errors; +use strings; + +let envp: []str = []; + +@fini fn envp() void = strings::freeall(envp); + +// Looks up an environment variable and returns its value, or void if unset. +export fn getenv(name: const str) (str | void) = { + getenvs(); // populate envp + for (let i = 0z; i < len(envp); i += 1) { + let (key, value) = strings::cut(envp[i], "="); + if (key == name) return value; + }; +}; + +// Looks up an environment variable and returns its value, or a default value if +// unset. +export fn tryenv(name: const str, default: str) str = match (getenv(name)) { +case let s: str => return s; +case void => return default; +}; + +// Sets an environment variable, overwriting it if it's already set. The name +// may not contain '=' or '\0', and the value may not contain '\0'. +export fn setenv(name: const str, value: const str) (void | errors::invalid) = { + if (strings::contains(value, '\0')) return errors::invalid; + unsetenv(name)?; + append(envp, strings::join("=", name, value)); +}; + +// Unsets an environment variable. Does nothing if the variable isn't set. The +// name may not contain '=' or '\0'. +export fn unsetenv(name: const str) (void | errors::invalid) = { + if (strings::contains(name, '=', '\0')) return errors::invalid; + getenvs(); // populate envp + for (let i = 0z; i < len(envp); i += 1) { + if (strings::cut(envp[i], "=").0 == name) { + free(envp[i]); + delete(envp[i]); + break; + }; + }; +}; + diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -1164,25 +1164,27 @@ os() { gen_srcs -plinux os \ +linux/dirfdfs.ha \ - +linux/environ.ha \ + +linux/platform_environ.ha \ +linux/$exit \ +linux/fs.ha \ +linux/memory.ha \ +linux/status.ha \ +linux/stdfd.ha \ + environ.ha \ os.ha - gen_ssa -plinux os io strings fs encoding::utf8 bytes bufio \ + gen_ssa -plinux os io strings fs encoding::utf8 bufio \ errors math types::c gen_srcs -pfreebsd os \ - +freebsd/environ.ha \ + +freebsd/platform_environ.ha \ +freebsd/$exit \ +freebsd/dirfdfs.ha \ +freebsd/status.ha \ +freebsd/stdfd.ha \ +freebsd/fs.ha \ + environ.ha \ os.ha - gen_ssa -pfreebsd os io strings fs encoding::utf8 bytes bufio \ + gen_ssa -pfreebsd os io strings fs encoding::utf8 bufio \ errors types::c } diff --git a/stdlib.mk b/stdlib.mk @@ -1881,15 +1881,16 @@ $(HARECACHE)/net/uri/net_uri-any.ssa: $(stdlib_net_uri_any_srcs) $(stdlib_rt) $( # os (+linux) stdlib_os_linux_srcs = \ $(STDLIB)/os/+linux/dirfdfs.ha \ - $(STDLIB)/os/+linux/environ.ha \ + $(STDLIB)/os/+linux/platform_environ.ha \ $(STDLIB)/os/+linux/exit.ha \ $(STDLIB)/os/+linux/fs.ha \ $(STDLIB)/os/+linux/memory.ha \ $(STDLIB)/os/+linux/status.ha \ $(STDLIB)/os/+linux/stdfd.ha \ + $(STDLIB)/os/environ.ha \ $(STDLIB)/os/os.ha -$(HARECACHE)/os/os-linux.ssa: $(stdlib_os_linux_srcs) $(stdlib_rt) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_math_$(PLATFORM)) $(stdlib_types_c_$(PLATFORM)) +$(HARECACHE)/os/os-linux.ssa: $(stdlib_os_linux_srcs) $(stdlib_rt) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_math_$(PLATFORM)) $(stdlib_types_c_$(PLATFORM)) @printf 'HAREC \t$@\n' @mkdir -p $(HARECACHE)/os @$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nos \ @@ -1897,15 +1898,16 @@ $(HARECACHE)/os/os-linux.ssa: $(stdlib_os_linux_srcs) $(stdlib_rt) $(stdlib_io_$ # os (+freebsd) stdlib_os_freebsd_srcs = \ - $(STDLIB)/os/+freebsd/environ.ha \ + $(STDLIB)/os/+freebsd/platform_environ.ha \ $(STDLIB)/os/+freebsd/exit.ha \ $(STDLIB)/os/+freebsd/dirfdfs.ha \ $(STDLIB)/os/+freebsd/status.ha \ $(STDLIB)/os/+freebsd/stdfd.ha \ $(STDLIB)/os/+freebsd/fs.ha \ + $(STDLIB)/os/environ.ha \ $(STDLIB)/os/os.ha -$(HARECACHE)/os/os-freebsd.ssa: $(stdlib_os_freebsd_srcs) $(stdlib_rt) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_types_c_$(PLATFORM)) +$(HARECACHE)/os/os-freebsd.ssa: $(stdlib_os_freebsd_srcs) $(stdlib_rt) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_types_c_$(PLATFORM)) @printf 'HAREC \t$@\n' @mkdir -p $(HARECACHE)/os @$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nos \ @@ -4332,15 +4334,16 @@ $(TESTCACHE)/net/uri/net_uri-any.ssa: $(testlib_net_uri_any_srcs) $(testlib_rt) # os (+linux) testlib_os_linux_srcs = \ $(STDLIB)/os/+linux/dirfdfs.ha \ - $(STDLIB)/os/+linux/environ.ha \ + $(STDLIB)/os/+linux/platform_environ.ha \ $(STDLIB)/os/+linux/exit+test.ha \ $(STDLIB)/os/+linux/fs.ha \ $(STDLIB)/os/+linux/memory.ha \ $(STDLIB)/os/+linux/status.ha \ $(STDLIB)/os/+linux/stdfd.ha \ + $(STDLIB)/os/environ.ha \ $(STDLIB)/os/os.ha -$(TESTCACHE)/os/os-linux.ssa: $(testlib_os_linux_srcs) $(testlib_rt) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_math_$(PLATFORM)) $(testlib_types_c_$(PLATFORM)) +$(TESTCACHE)/os/os-linux.ssa: $(testlib_os_linux_srcs) $(testlib_rt) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_math_$(PLATFORM)) $(testlib_types_c_$(PLATFORM)) @printf 'HAREC \t$@\n' @mkdir -p $(TESTCACHE)/os @$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nos \ @@ -4348,15 +4351,16 @@ $(TESTCACHE)/os/os-linux.ssa: $(testlib_os_linux_srcs) $(testlib_rt) $(testlib_i # os (+freebsd) testlib_os_freebsd_srcs = \ - $(STDLIB)/os/+freebsd/environ.ha \ + $(STDLIB)/os/+freebsd/platform_environ.ha \ $(STDLIB)/os/+freebsd/exit+test.ha \ $(STDLIB)/os/+freebsd/dirfdfs.ha \ $(STDLIB)/os/+freebsd/status.ha \ $(STDLIB)/os/+freebsd/stdfd.ha \ $(STDLIB)/os/+freebsd/fs.ha \ + $(STDLIB)/os/environ.ha \ $(STDLIB)/os/os.ha -$(TESTCACHE)/os/os-freebsd.ssa: $(testlib_os_freebsd_srcs) $(testlib_rt) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_types_c_$(PLATFORM)) +$(TESTCACHE)/os/os-freebsd.ssa: $(testlib_os_freebsd_srcs) $(testlib_rt) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_types_c_$(PLATFORM)) @printf 'HAREC \t$@\n' @mkdir -p $(TESTCACHE)/os @$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nos \