1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
// SPDX-License-Identifier: MPL-2.0
// (c) Hare authors <https://harelang.org>
use errors;
use io;
use os;
use rt;
use strings;
use types::c;
export type strlist = []nullable *const c::char;
fn free_strlist(l: strlist) void = {
for (let i = 0z; i < len(l) - 1; i += 1) {
free(l[i]: *const c::char);
};
free(l);
};
export type platform_argv = strlist;
fn platform_newargv(name: str, args: str...) (platform_argv | nomem) = {
let ok = false;
let argv: platform_argv = alloc([null...], len(args) + 2z)?;
defer if (!ok) platform_free_argv(argv);
argv[0] = c::fromstr(name)?;
let i = 1z;
for (let arg .. args) {
argv[i] = c::fromstr(arg)?;
i += 1;
};
ok = true;
return argv;
};
fn platform_free_argv(argv: platform_argv) void = free_strlist(argv);
fn platform_setname(cmd: *command, name: str) (void | nomem) = {
cmd.argv[0] = c::fromstr(name)?;
};
export type platform_env = strlist;
fn platfrom_newenv() platform_env = [];
fn platform_dup_env(env: []str) (platform_env | nomem) = {
let ok = false;
let dup: platform_env = [];
defer if (!ok) platform_free_env(dup);
for (let e .. env) {
let centry = c::fromstr(e)?;
if (append(dup, centry) is nomem) {
free(centry);
return nomem;
};
};
append(dup, null)?;
ok = true;
return dup;
};
fn platform_free_env(env: platform_env) void = free_strlist(env);
fn platform_finish(cmd: *command) void = rt::close(cmd.platform)!;
fn platform_setenv(
cmd: *command,
key: str,
value: str
) (void | errors::invalid | nomem) = {
if (len(cmd.env) == 0) {
append(cmd.env, null)?;
};
let entry = strings::join("=", key, value)?;
defer free(entry);
let centry = c::fromstr(entry)?;
if (insert(cmd.env[len(cmd.env)-1], centry) is nomem) {
free(centry);
return nomem;
};
};
fn platform_unsetenv(cmd: *command, key: str) (void | errors::invalid) = {
// XXX: This can be a binary search
for (let i = 0z; cmd.env[i] != null; i += 1) {
let e = c::tostr(cmd.env[i]: *const c::char)!;
if (strings::cut(e, "=").0 == key) {
free(cmd.env[i]);
delete(cmd.env[i]);
break;
};
};
};
export type platform_cmd = io::file;
// Same as [[cmd]] except that executable file is determined by [[io::file]].
// This function is not portable.
export fn cmdfile(file: io::file, name: str, args: str...) (command | nomem) = {
let argv = platform_newargv(name, args...)?;
let env = match (platform_dup_env(os::getenvs())) {
case let env: platform_env =>
yield env;
case nomem =>
platform_free_argv(argv);
return nomem;
};
return command {
platform = file,
argv = argv,
env = env,
files = [],
dir = "",
};
};
|