hare

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

commit 4c2d5ff1162be816f0498f79804333a802a75a70
parent 6507fa604db4cb304daaa6ba2f3ae86e3706557c
Author: Alexey Yerin <yyp@disroot.org>
Date:   Thu, 25 Nov 2021 20:50:27 +0300

unix::tty: add termios support on +freebsd

Signed-off-by: Alexey Yerin <yyp@disroot.org>

Diffstat:
Mrt/+freebsd/types.ha | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Aunix/tty/+freebsd/termios.ha | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/rt/+freebsd/types.ha b/rt/+freebsd/types.ha @@ -118,6 +118,110 @@ export type winsize = struct { ws_ypixel: u16, }; +export type termios = struct { + c_iflag: tcflag, + c_oflag: tcflag, + c_cflag: tcflag, + c_lflag: tcflag, + c_cc: [NCCS]cc, +}; + +export def NCCS: size = 20; + +export type tcflag = enum uint { + // c_iflag bits + IGNBRK = 0x00000001, + BRKINT = 0x00000002, + IGNPAR = 0x00000004, + PARMRK = 0x00000008, + INPCK = 0x00000010, + ISTRIP = 0x00000020, + INLCR = 0x00000040, + IGNCR = 0x00000080, + ICRNL = 0x00000100, + IXON = 0x00000200, + IXOFF = 0x00000400, + IXANY = 0x00000800, + IMAXBEL = 0x00002000, + + // c_oflag bits + OPOST = 0x00000001, + ONLCR = 0x00000002, + TABDLY = 0x00000004, + TAB0 = 0x00000000, + TAB3 = 0x00000004, + ONOEOT = 0x00000008, + OCRNL = 0x00000010, + ONOCR = 0x00000020, + ONLRET = 0x00000040, + + // c_cflag bits + CIGNORE = 0x00000001, + CSIZE = 0x00000300, + CS5 = 0x00000000, + CS6 = 0x00000100, + CS7 = 0x00000200, + CS8 = 0x00000300, + CSTOPB = 0x00000400, + CREAD = 0x00000800, + PARENB = 0x00001000, + PARODD = 0x00002000, + HUPCL = 0x00004000, + CLOCAL = 0x00008000, + CCTS_OFLOW = 0x00010000, + CRTS_IFLOW = 0x00020000, + CRTSCTS = (CCTS_OFLOW | CRTS_IFLOW), + CDTR_IFLOW = 0x00040000, + CDSR_OFLOW = 0x00080000, + CCAR_OFLOW = 0x00100000, + CNO_RTSDTR = 0x00200000, + + // c_lflag bits + ECHOKE = 0x00000001, + ECHOE = 0x00000002, + ECHOK = 0x00000004, + ECHO = 0x00000008, + ECHONL = 0x00000010, + ECHOPRT = 0x00000020, + ECHOCTL = 0x00000040, + ISIG = 0x00000080, + ICANON = 0x00000100, + ALTWERASE = 0x00000200, + IEXTEN = 0x00000400, + EXTPROC = 0x00000800, + TOSTOP = 0x00400000, + FLUSHO = 0x00800000, + NOKERNINFO = 0x02000000, + PENDIN = 0x20000000, + NOFLSH = 0x80000000, +}; + +export type cc = enum char { + VEOF = 0, + VEOL = 1, + VEOL2 = 2, + VERASE = 3, + VWERASE = 4, + VKILL = 5, + VREPRINT = 6, + VERASE2 = 7, + VINTR = 8, + VQUIT = 9, + VSUSP = 10, + VDSUSP = 11, + VSTART = 12, + VSTOP = 13, + VLNEXT = 14, + VDISCARD = 15, + VMIN = 16, + VTIME = 17, + VSTATUS = 18, +}; + +export def TIOCGWINSZ: u64 = 0x40087468; +export def TIOCGETA: u64 = 0x402c7413; +export def TIOCSETA: u64 = 0x802c7414; + export type rusage = struct { ru_utime: timeval, ru_stime: timeval, @@ -137,8 +241,6 @@ export type rusage = struct { ru_nivcsw: i64, }; -export def TIOCGWINSZ: u64 = 0x40087468; - export def DT_UNKNOWN: u8 = 0; export def DT_FIFO: u8 = 1; export def DT_CHR: u8 = 2; diff --git a/unix/tty/+freebsd/termios.ha b/unix/tty/+freebsd/termios.ha @@ -0,0 +1,60 @@ +use io; +use rt; +use errors; + +export type termios = struct { + file: io::file, + saved: rt::termios, + current: rt::termios, +}; + +// Retrieves serial port settings of the given terminal. +export fn termios_query(file: io::file) (termios | errors::error) = { + let settings = rt::termios { ... }; + + match (rt::ioctl(file, rt::TIOCGETA, &settings)) { + case int => void; + case err: rt::errno => + return errors::errno(err); + }; + + return termios { + file = file, + saved = settings, + current = settings, + }; +}; + +// Restores original serial port settings. +export fn termios_restore(termios: *const termios) void = { + rt::ioctl(termios.file, rt::TIOCSETA, &termios.saved): void; +}; + +// Sets serial port settings. +export fn termios_set(termios: *const termios) (void | errors::error) = { + match (rt::ioctl(termios.file, rt::TIOCSETA, &termios.current)) { + case int => void; + case err: rt::errno => + return errors::errno(err); + }; +}; + +// Enables "raw" mode for this terminal, disabling echoing, line +// editing, and signal handling. Users should call [[termios_query]] +// prior to this to save the previous terminal settings, and +// [[termios_restore]] to restore them before exiting. +export fn makeraw(termios: *termios) (void | errors::error) = { + // Disable break signal and CR<->LF processing + termios.current.c_iflag &= ~(rt::tcflag::IGNBRK | rt::tcflag::BRKINT + | rt::tcflag::INLCR | rt::tcflag::IGNCR + | rt::tcflag::ICRNL); + // Disable output post-processing + termios.current.c_oflag &= ~rt::tcflag::OPOST; + // Disable character echo, canonical mode, implementation defined + // extensions and INTR/QUIT/SUSP characters + termios.current.c_lflag &= ~(rt::tcflag::ECHO | rt::tcflag::ECHONL + | rt::tcflag::ICANON | rt::tcflag::IEXTEN + | rt::tcflag::ISIG); + + termios_set(termios)?; +};