Skip to content

Commit

Permalink
Make adjustments to be able to run tests on macos
Browse files Browse the repository at this point in the history
  • Loading branch information
Victorious3 committed Jun 1, 2024
1 parent d288928 commit 01188bb
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 22 deletions.
5 changes: 4 additions & 1 deletion src/testrunner.pr
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ if runner {
#if defined WIN32 {
const dll_ext = ".dll"
const dev_null = "nul"
} else if defined MACOS {
const dll_ext = ".dylib"
const dev_null = "/dev/null"
} else {
const dll_ext = ".so"
const dev_null = "/dev/null"
Expand Down Expand Up @@ -278,7 +281,7 @@ def enumerate_dir(file_or_dir: String, pattern: String, recursive: bool, res: &V
res.push(file_or_dir)
return
} else if sres.st_mode & 0o170000 == 0o040000 {
var dir: *linux::s___dirstream
var dir: Dir

if not (dir = linux::opendir(file_or_dir.to_array().value)) { return }

Expand Down
7 changes: 6 additions & 1 deletion std/io.pr
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ export const NO_BLOCKING = 1

export const _IONBF = 2
const F_SETFL = 4
const O_NONBLOCK = 2048

#if defined MACOS {
const O_NONBLOCK = 4
} else {
const O_NONBLOCK = 2048
}

export def pipe(mode: int = 0) -> File, File {
var res: [2; int]
Expand Down
90 changes: 72 additions & 18 deletions std/process.pr
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,14 @@ import std
linux::execvp(exe.to_array().value, pargs.value)
exit(1)
}

let fd = linux::syscall(SYS_pidfd_open, pid, 2048 /* PIDFD_NONBLOCK */)

#if defined MACOS {
// MacOS has no facility to open a process as a file discriptor,
// so we have to use something other than poll
let fd = 0
} else {
let fd = linux::syscall(SYS_pidfd_open, pid, 2048 /* PIDFD_NONBLOCK */)
}

return [
pid = pid, fd = fd,
Expand All @@ -151,29 +157,77 @@ import std
return (status & 0xFF00) >> 8
}

export def wait(process: *Process, timeout: ulong = -1) {
var pfd = [fd = process.fd !int, events = POLLIN, revents = 0] !linux::s_pollfd;
if linux::poll(*pfd, 1, timeout !int) == 0 {
return
#if defined MACOS {
var gtimeout = false
def on_timeout(sig: int) {
gtimeout = true
}
}

var stat_val: int
if linux::waitpid(process.pid, *stat_val, 0) == -1 {
abort("Waitpid error\n")
}
if WIFSIGNALED(stat_val) {
process.exit_code = 128 + WTERMSIG(stat_val)
} else if WIFEXITED(stat_val) {
process.exit_code = WEXITSTATUS(stat_val)
export def wait(process: *Process, timeout: ulong = -1) {
#if defined MACOS {
// We need to do something stupid with signals here to mimick a timeout
gtimeout = false
let old_handler = cstd::signal(cstd::SIGALRM, *on_timeout)
if timeout < -1 {
linux::ualarm((timeout * 1000) !int, 0)
}

while not gtimeout {
var stat_val: int

let status = linux::waitpid(process.pid, *stat_val, 1 /* WNOHANG */)
if status == -1 {
abort("Waitpid error\n")
} else if status == 0 {
linux::pause()
continue
}

if WIFSIGNALED(stat_val) {
process.exit_code = 128 + WTERMSIG(stat_val)
} else if WIFEXITED(stat_val) {
process.exit_code = WEXITSTATUS(stat_val)
} else {
abort("Invalid signal\n")
}

process.running = false

linux::alarm(0)
cstd::signal(cstd::SIGALRM, old_handler)
return
}

cstd::signal(cstd::SIGALRM, old_handler)
} else {
abort("Invalid signal\n")
}
var pfd = [fd = process.fd !int, events = POLLIN, revents = 0] !linux::s_pollfd;
if linux::poll(*pfd, 1, timeout !int) == 0 {
return
}

process.running = false
var stat_val: int
if linux::waitpid(process.pid, *stat_val, 1 /* WNOHANG */) == -1 {
abort("Waitpid error\n")
}
if WIFSIGNALED(stat_val) {
process.exit_code = 128 + WTERMSIG(stat_val)
} else if WIFEXITED(stat_val) {
process.exit_code = WEXITSTATUS(stat_val)
} else {
abort("Invalid signal\n")
}

process.running = false
}
}

export def terminate(process: *Process) {
linux::kill(process.pid, SIGTERM)
#if defined MACOS {
cstd::kill(process.pid, SIGTERM)
} else {
linux::kill(process.pid, SIGTERM)
}
}

export def dispose(process: *Process) {
Expand Down
81 changes: 80 additions & 1 deletion std/shared.pr
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,85 @@ export def find_symbol(library: *Library, name: String) -> Optional(Symbol) {
}
windows::FreeLibrary(library.handle !*windows::s_HINSTANCE__)
}
} else if defined MACOS {
import linux
import io
import process

const RTLD_NOW = 2

export def load(path: String, init: bool = true) -> Library {

let handle = linux::dlopen(path.to_array().value, RTLD_NOW)
if not handle { abort("Couldn't open shared library " + path + "\n") }

// We're going to call nm here because it seems to be the most straight forward way of enumerating symbols
// If you know a better way of doing this please tell me.

let r, w = io::pipe(io::NO_BLOCKING)
let args = allocate_ref(String, 2)
args(0) = "-gU"
args(1) = path

let proc = *process::spawn("/usr/bin/nm", args, stdout = w)
var data: Str
while proc.running {
proc.wait(100)
data = data + r.read_remaining()
}
proc.dispose()
let nm_symbols = data.split('\n')

let symbols = vector::make(Symbol)

for var sym in @nm_symbols {
let name = sym.substring(20)
let nm_kind = sym(17)

if nm_kind == 'D' or nm_kind == 'S' or nm_kind == 'T' {
var err = dlerror()
symbols.push([
kind = SymbolKind::FUNCTION if nm_kind == 'T' else SymbolKind::OBJECT,
name = name,
value = dlsym(handle, name.to_array().value)
] !Symbol)
err = dlerror()
if err {
print("Couldn't load symbol ", name, ": ", err, "\n")
}
}
}

let library = [
path = path,
handle = handle,
symbols = symbols.to_array()
] !Library

if init {
let main_sym = find_symbol(*library, "main::__main__::([[char]])")
if main_sym.exists {
let main = main_sym.get().value !(def ([[char]]) -> [])
// FIXME Pass in actual command line arguments
let args = zero_allocate(type [char], 0)
main(args)
delete(args)
}
}

return library
}

export def close(library: *Library, finalize: bool = true) {
if finalize {
let finalizer_sym = find_symbol(library, "main::__finalizer__::()")
if finalizer_sym.exists {
let finalizer = finalizer_sym.get().value !(def -> [])
finalizer()
}
}
linux::dlclose(library.handle)
}

} else {
import linux
Expand Down Expand Up @@ -164,7 +243,7 @@ export def find_symbol(library: *Library, name: String) -> Optional(Symbol) {
export def load(path: String, init: bool = true) -> Library {
let fh = open(path, "rb")
if not fh {
abort("Couldn't open library " + path + " (" + make_string(cstd::strerror(@linux::__errno_location())) + ")\n")
abort("Couldn't open library " + path + " (" + std::c_error_str() + ")\n")
}
defer close(fh)

Expand Down
14 changes: 13 additions & 1 deletion std/std.pr
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ from strings export *
import linux
import macos
export type File = *cstd::s___sFILE
export type Dir = *linux::s_DIR

export def stdin -> File { return cstd::__stdinp }
export def stdout -> File { return cstd::__stdoutp }
Expand All @@ -199,7 +200,8 @@ from strings export *
export const PATH_MAX = 4096
} else {
import linux
export type File = *cstd::s__IO_FILE
export type File = *cstd::s__IO_FIL
export type Dir = *linux::s___dirstream

export def stdin -> File { return cstd::stdin }
export def stdout -> File { return cstd::stdout }
Expand Down Expand Up @@ -227,6 +229,16 @@ export const SEEK_SET: int = 0
export const SEEK_CUR: int = 1
export const SEEK_END: int = 2

export def c_error_str -> Str {
#if defined MACOS {
return make_string(cstd::strerror(@linux::__error()))
} else if defined LINUX {
return make_string(cstd::strerror(@liunx::__errno_location()))
} else {
// TODO Implement for Windows
}
}

// TODO This is causing an ambigious reference error, it really shouldn't
/*export def combine_hashes(a: uint64, b: uint64) -> uint64 {
var hash: uint64 = 17
Expand Down
19 changes: 19 additions & 0 deletions std/strings.pr
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import cstd
import std
import runtime
import optional
import vector

export def length(s: [char]) -> size_t {
return s.size - 1
Expand Down Expand Up @@ -739,6 +740,24 @@ export def match(pattern: String, candidate: String) -> bool {
return match(pattern, candidate, 0, 0)
}

export def split(input: String, separator: char) -> &[Str] {
let res = vector::make(Str)

var last = 0
for var i in 0..input.length {
if input(i) == separator {
res.push(input.substring(last, i))
i += 1
last = i
}
}
if last < input.length {
res.push(input.substring(last, input.length))
}

return res.to_array()
}

export def utf8_encode(code_point: uint64) -> Str {
var res: StringBuffer = ""
if code_point <= 0x007F {
Expand Down

0 comments on commit 01188bb

Please sign in to comment.