hare

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

platform_environ.ha (3069B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use errors;
      5 use rt;
      6 use strings;
      7 use types::c;
      8 
      9 // The command line arguments provided to the program. By convention, the first
     10 // member is usually the name of the program.
     11 export let args: []str = [];
     12 
     13 // Statically allocate arg strings if there are few enough arguments, saves a
     14 // syscall if we don't need it.
     15 let args_static: [32]str = [""...];
     16 
     17 @init fn args() void = {
     18 	if (rt::argc < len(args_static)) {
     19 		args = args_static[..rt::argc];
     20 		for (let i = 0z; i < rt::argc; i += 1) {
     21 			args[i] = c::tostr(rt::argv[i]: *const c::char)!;
     22 		};
     23 	} else {
     24 		args = alloc([], rt::argc)!;
     25 		for (let i = 0z; i < rt::argc; i += 1) {
     26 			append(args, c::tostr(rt::argv[i]: *const c::char)!)!;
     27 		};
     28 	};
     29 };
     30 
     31 @fini fn args() void = {
     32 	if (rt::argc >= len(args_static)) {
     33 		free(args);
     34 	};
     35 };
     36 
     37 // Returns a slice of the environment strings in form KEY=VALUE.
     38 export fn getenvs() []str = {
     39 	if (len(envp) > 0) {
     40 		return envp;
     41 	};
     42 	for (let i = 0z; rt::envp[i] != null; i += 1) {
     43 		let s = c::tostr(rt::envp[i]: *const c::char)!;
     44 		append(envp, strings::dup(s))!;
     45 	};
     46 	return envp;
     47 };
     48 
     49 // Returns the host kernel name
     50 export fn sysname() const str = {
     51 	let name: [2]int = [rt::CTL_KERN, rt::KERN_OSTYPE];
     52 
     53 	static let buf: [32]u8 = [0...];
     54 	let buf_sz = len(buf);
     55 
     56 	rt::sysctl(name, len(name): uint, &buf, &buf_sz, null, 0)!;
     57 	return strings::fromutf8(buf[..(buf_sz -1)])!;
     58 };
     59 
     60 // Returns the host system hostname
     61 export fn hostname() const str = {
     62 	let name: [2]int = [rt::CTL_KERN, rt::KERN_HOSTNAME];
     63 
     64 	static let buf: [rt::MAXHOSTNAMELEN]u8 = [0...];
     65 	let buf_sz = len(buf);
     66 
     67 	rt::sysctl(name, len(name): uint, &buf, &buf_sz, null, 0)!;
     68 	return strings::fromutf8(buf[..(buf_sz -1)])!;
     69 };
     70 
     71 // Returns the host operating system version
     72 export fn version() const str = {
     73 	let name: [2]int = [rt::CTL_KERN, rt::KERN_OSRELEASE];
     74 
     75 	static let buf: [32]u8 = [0...];
     76 	let buf_sz = len(buf);
     77 
     78 	rt::sysctl(name, len(name): uint, &buf, &buf_sz, null, 0)!;
     79 	return strings::fromutf8(buf[..(buf_sz -1)])!;
     80 };
     81 
     82 // Returns the host CPU architecture, in a platform-specific format. See
     83 // [[architecture]] for a more portable wrapper.
     84 export fn machine() const str = {
     85 	let name: [2]int = [rt::CTL_HW, rt::HW_MACHINE];
     86 
     87 	static let buf: [32]u8 = [0...];
     88 	let buf_sz = len(buf);
     89 
     90 	rt::sysctl(name, len(name): uint, &buf, &buf_sz, null, 0)!;
     91 
     92 	return strings::fromutf8(buf[..(buf_sz - 1)])!;
     93 };
     94 
     95 // Returns the host CPU architecture.
     96 export fn architecture() arch = {
     97 	switch (machine()) {
     98 	case "arm64" =>
     99 		return arch::AARCH64;
    100 	case "riscv64" =>
    101 		return arch::RISCV64;
    102 	case "amd64" =>
    103 		return arch::X86_64;
    104 	case => abort(); // unreachable
    105 	};
    106 };
    107 
    108 // Returns the number of usable CPUs.
    109 export fn cpucount() (size | errors::error) = {
    110 	let name: [2]int = [rt::CTL_HW, rt::HW_NCPUONLINE];
    111 
    112 	let ncpu: int = 0;
    113 	let ncpu_sz = size(int);
    114 
    115 	match (rt::sysctl(name, len(name): uint, &ncpu, &ncpu_sz, null, 0)) {
    116 	case void =>
    117 		return ncpu: size;
    118 	case let err: rt::errno =>
    119 		return errors::errno(err);
    120 	};
    121 };