141 lines
3.9 KiB
Plaintext
141 lines
3.9 KiB
Plaintext
const std = #import("std");
|
|
const Allocator = std.Allocator;
|
|
const current = #import("builtin").os;
|
|
const system = switch (current) {
|
|
.linux => linux,
|
|
.macos => macos,
|
|
.windows => windows,
|
|
};
|
|
|
|
|
|
const exit = fn(exit_code: s32) noreturn {
|
|
switch (current) {
|
|
.linux => _ = #syscall(231, exit_code),
|
|
.macos => macos.exit(exit_code),
|
|
.windows => windows.ExitProcess(exit_code),
|
|
}
|
|
|
|
unreachable;
|
|
}
|
|
|
|
const ProtectionFlags = struct(u32){
|
|
read: bool,
|
|
write: bool,
|
|
execute: bool,
|
|
};
|
|
|
|
const MapFlags = struct(u32){
|
|
reserve: bool,
|
|
commit: bool,
|
|
};
|
|
|
|
const allocate_virtual_memory = fn(address: ?[&]u8, length: usize, general_protection_flags: ProtectionFlags, general_map_flags: MapFlags) ?[&]u8 {
|
|
const protection_flags = system.get_protection_flags(flags = general_protection_flags);
|
|
const map_flags = system.get_map_flags(flags = general_map_flags);
|
|
|
|
switch (current) {
|
|
.linux => {
|
|
if (linux.unwrapSyscall(syscall_result = linux.mmap(address, length, protection_flags, map_flags, fd = -1, offset = 0))) |result_address| {
|
|
const pointer: [&]u8 = #cast(result_address);
|
|
return pointer;
|
|
} else {
|
|
return null;
|
|
}
|
|
},
|
|
else => #error("OS not supported"),
|
|
}
|
|
|
|
}
|
|
|
|
const free_virtual_memory = fn(bytes_ptr: [&]const u8, bytes_len: usize) bool {
|
|
switch (current) {
|
|
.linux => {
|
|
if (linux.unwrapSyscall(syscall_result = linux.munmap(bytes_ptr, bytes_len))) |result| {
|
|
return result == 0;
|
|
} else {
|
|
return false;
|
|
}
|
|
},
|
|
else => #error("OS not supported"),
|
|
}
|
|
}
|
|
|
|
const readlink = fn(file_path: [&:0]const u8, buffer: []u8) ?[]u8 {
|
|
switch (current) {
|
|
.linux => {
|
|
const raw_result = linux.readlink(file_path, bytes_ptr = buffer.ptr, bytes_len = buffer.len);
|
|
|
|
if (linux.unwrapSyscall(syscall_result = raw_result)) |byte_count| {
|
|
const bytes = buffer[0..byte_count];
|
|
return bytes;
|
|
} else {
|
|
return null;
|
|
}
|
|
},
|
|
else => #error("OS not supported"),
|
|
}
|
|
}
|
|
|
|
const max_path_byte_count = switch (current) {
|
|
.linux => 0x1000,
|
|
else => #error("OS not supported"),
|
|
};
|
|
|
|
const current_executable_path = fn(allocator: &Allocator) ?[]u8 {
|
|
switch (current) {
|
|
.linux => {
|
|
var buffer: [max_path_byte_count]u8 = undefined;
|
|
if (readlink(file_path = "/proc/self/exe", buffer = buffer.&)) |bytes| {
|
|
if (allocator.duplicate_bytes(bytes)) |result| {
|
|
return result;
|
|
} else {
|
|
return null;
|
|
}
|
|
} else {
|
|
return null;
|
|
}
|
|
},
|
|
else => #error("OS not supported"),
|
|
}
|
|
}
|
|
|
|
const FileDescriptor = struct{
|
|
handle: system.FileDescriptor,
|
|
|
|
const write = fn (file_descriptor: FileDescriptor, bytes: []const u8) ?usize {
|
|
switch (current) {
|
|
.linux => {
|
|
const raw_result = #syscall(1, file_descriptor.handle, #cast(bytes.ptr), bytes.len);
|
|
if (linux.unwrapSyscall(syscall_result = raw_result)) |byte_count| {
|
|
return byte_count;
|
|
} else {
|
|
return null;
|
|
}
|
|
},
|
|
else => #error("OS not supported"),
|
|
}
|
|
}
|
|
};
|
|
|
|
const StdFileDescriptor = enum {
|
|
stdin = 0,
|
|
stdout = 1,
|
|
stderr = 2,
|
|
|
|
const get = fn(descriptor: StdFileDescriptor) FileDescriptor{
|
|
switch (current) {
|
|
.linux, .macos => {
|
|
return FileDescriptor{
|
|
.handle = #cast(descriptor),
|
|
};
|
|
},
|
|
else => #error("OS not supported"),
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
const linux = #import("os/linux.nat");
|
|
const macos = #import("os/macos.nat");
|
|
const windows = #import("os/windows.nat");
|