From: Brendan Hansen Date: Wed, 28 Jun 2023 22:33:22 +0000 (-0500) Subject: added: TTY support to platform layer and `core.os` X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=576e22429b9e3a64a7ad79b693228707d49f591d;p=onyx.git added: TTY support to platform layer and `core.os` --- diff --git a/core/os/tty.onyx b/core/os/tty.onyx new file mode 100644 index 00000000..4609ae45 --- /dev/null +++ b/core/os/tty.onyx @@ -0,0 +1,55 @@ +package core.os + +use runtime + +TTY_State :: struct { + rows: i32; + cols: i32; + stdin_is_tty: bool; + stdout_is_tty: bool; + stderr_is_tty: bool; + echo: bool; + input_buffered: bool; + input_linefeeds: bool; +} + +tty_sane :: () { + state := tty_get(); + state.echo = true; + state.input_buffered = true; + tty_set(&state); +} + +tty_raw :: () { + state := tty_get(); + state.echo = false; + state.input_buffered = false; + tty_set(&state); +} + +#if runtime.platform.Supports_TTY { + +tty_get :: () -> TTY_State { + state: TTY_State; + runtime.platform.__tty_get(&state); + return state; +} + +tty_set :: (state: &TTY_State) -> bool { + return runtime.platform.__tty_set(state); +} + +} else { + +tty_get :: () -> TTY_State { + assert(false, "core.os.tty_get not supported on this platform."); +} + +tty_set :: (state: &TTY_State) -> bool { + assert(false, "core.os.tty_get not supported on this platform."); + return false; +} + +} + + diff --git a/core/runtime/platform/js/platform.onyx b/core/runtime/platform/js/platform.onyx index e60d205b..5b17a96b 100644 --- a/core/runtime/platform/js/platform.onyx +++ b/core/runtime/platform/js/platform.onyx @@ -20,6 +20,7 @@ Supports_Type_Info :: true Supports_Threads :: true Supports_Env_Vars :: false Supports_Futexes :: true +Supports_TTY :: false __output_string :: (s: str) -> u32 #foreign "host" "print_str" --- __output_error :: (s: str) -> u32 #foreign "host" "print_str" --- diff --git a/core/runtime/platform/onyx/platform.onyx b/core/runtime/platform/onyx/platform.onyx index 70592a9f..578ea682 100644 --- a/core/runtime/platform/onyx/platform.onyx +++ b/core/runtime/platform/onyx/platform.onyx @@ -28,6 +28,7 @@ Supports_Type_Info :: true Supports_Threads :: true Supports_Env_Vars :: true Supports_Futexes :: true +Supports_TTY :: true #library "onyx_runtime" @@ -69,6 +70,10 @@ ProcessData :: #distinct u64 __futex_wait :: (addr: rawptr, expected: i32, timeout: i32) -> i32 --- __futex_wake :: (addr: rawptr, maximum: i32) -> i32 --- + // TTY + __tty_get :: (state: &os.TTY_State) -> void --- + __tty_set :: (state: &os.TTY_State) -> bool --- + // Time and sleep __time :: () -> u64 --- diff --git a/core/runtime/platform/wasi/platform.onyx b/core/runtime/platform/wasi/platform.onyx index f6fe6716..8722ad90 100644 --- a/core/runtime/platform/wasi/platform.onyx +++ b/core/runtime/platform/wasi/platform.onyx @@ -37,6 +37,7 @@ Supports_Type_Info :: true Supports_Threads :: true Supports_Env_Vars :: true Supports_Futexes :: false +Supports_TTY :: false __output_string :: (s: str) -> u32 { diff --git a/core/std.onyx b/core/std.onyx index ad9a0a49..74076f74 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -106,6 +106,10 @@ use runtime #load "./os/env" } +#if runtime.platform.Supports_TTY { + #load "./os/tty" +} + #if runtime.Multi_Threading_Enabled { #load "./intrinsics/atomics" diff --git a/runtime/onyx_runtime.c b/runtime/onyx_runtime.c index 9be0bf3d..24dc0d1d 100644 --- a/runtime/onyx_runtime.c +++ b/runtime/onyx_runtime.c @@ -21,6 +21,9 @@ #include #include #include + #include + #include + #include #endif #include "types.h" // For POINTER_SIZE @@ -32,6 +35,7 @@ #include "src/ort_os.h" #include "src/ort_cptr.h" #include "src/ort_net.h" +#include "src/ort_tty.h" ONYX_LIBRARY { @@ -75,6 +79,8 @@ ONYX_LIBRARY { ONYX_FUNC(__random_get) ONYX_FUNC(__futex_wait) ONYX_FUNC(__futex_wake) + ONYX_FUNC(__tty_get) + ONYX_FUNC(__tty_set) ONYX_FUNC(__register_cleanup) ONYX_FUNC(__net_create_socket) diff --git a/runtime/src/ort_tty.h b/runtime/src/ort_tty.h new file mode 100644 index 00000000..fa5b8fc6 --- /dev/null +++ b/runtime/src/ort_tty.h @@ -0,0 +1,72 @@ + +struct Onyx_TTY_State { + int rows, columns; + unsigned char stdin_is_tty, stdout_is_tty, stderr_is_tty; + unsigned char echo, input_buffered, input_linefeeds; +}; + +ONYX_DEF(__tty_get, (WASM_I32), ()) { + struct Onyx_TTY_State *state = ONYX_PTR(params->data[0].of.i32); + +#ifdef _BH_LINUX + struct winsize sz; + ioctl(0, TIOCGWINSZ, &sz); + state->rows = sz.ws_row; + state->columns = sz.ws_col; + + struct termios term; + state->stdout_is_tty = tcgetattr(1, &term) == 0; + state->stderr_is_tty = tcgetattr(2, &term) == 0; + state->stdin_is_tty = tcgetattr(0, &term) == 0; // Do stdin last because we use it next. + + state->echo = (term.c_lflag & ECHO) != 0; + state->input_buffered = (term.c_lflag & ICANON) != 0; + state->input_linefeeds = (term.c_lflag & ONLCR) != 0; +#endif + +#ifdef _BH_WINDOWS + memset(state, 0, sizeof(*state)); + + state->rows = 80; + state->columns = 25; + state->echo = 1; + state->input_buffered = 1; + state->linefeeds_ignored = 0; +#endif + + return NULL; +} + +ONYX_DEF(__tty_set, (WASM_I32), (WASM_I32)) { + struct Onyx_TTY_State *state = ONYX_PTR(params->data[0].of.i32); + +#ifdef _BH_LINUX + int success = 1; + + struct termios term; + if (!tcgetattr(0, &term)) { + if (state->echo) term.c_lflag |= (ECHO | ECHOE | ECHOK | ECHOCTL | IEXTEN); + else term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHOCTL | IEXTEN); + + if (state->input_buffered) term.c_lflag |= ICANON; + else term.c_lflag &= ~ICANON; + + if (state->input_linefeeds) term.c_lflag |= ONLCR; + else term.c_lflag &= ~ONLCR; + + success = tcsetattr(0, TCSANOW, &term) == 0; + + } else { + success = 0; + } + + results->data[0] = WASM_I32_VAL(success); +#endif + +#ifdef _BH_WINDOWS + results->data[0] = WASM_I32_VAL(0); +#endif + return NULL; +} + +