1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

termios: new termios module (#17792)

* termio: new termio module

move the tcgetattr and tcsetattr functions in a new termio module.
The code needed refactoring as different OS have different fields
size, position and number for the C.termios structure, which
could not be correctly expressed consitently otherwise.

It has the positive side effect to reduce the number of unsafe calls.
New testing code was also added for the readline module as it is
relying of the feature.

* apply 2023 copyright to the new files too
This commit is contained in:
Thomas Mangin
2023-03-30 06:58:52 +01:00
committed by GitHub
parent 0826102e0a
commit 580d9cedc7
25 changed files with 921 additions and 723 deletions

View File

@ -0,0 +1,88 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// Serves as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
#include <termios.h>
#include <sys/ioctl.h>
// https://github.com/lattera/glibc/blob/master/sysdeps/unix/sysv/linux/bits/termios.h
const cclen = 32
type TcFlag = int
type Speed = int
type Cc = u8
// Termios stores the terminal options on Linux.
struct C.termios {
mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_line Cc
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
fn C.tcgetattr(fd int, termios_p &C.termios) int
fn C.tcsetattr(fd int, optional_actions int, const_termios_p &C.termios) int
fn C.ioctl(fd int, request u64, arg voidptr) int
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
[inline]
pub fn flag(value int) TcFlag {
return int(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
[inline]
pub fn invert(value TcFlag) TcFlag {
return ~int(value)
}
pub struct Termios {
pub mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_line Cc
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcgetattr(fd int, mut termios_p Termios) int {
unsafe {
return C.tcgetattr(fd, &C.termios(termios_p))
}
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
unsafe {
return C.tcsetattr(fd, optional_actions, &C.termios(termios_p))
}
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
unsafe {
return C.ioctl(fd, request, arg)
}
}

View File

@ -0,0 +1,86 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// Serves as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
#include <termios.h>
#include <sys/ioctl.h>
// https://github.com/apple/darwin-xnu/blob/main/bsd/sys/termios.h
const cclen = 20
type TcFlag = usize
type Speed = usize
type Cc = u8
// Termios stores the terminal options
struct C.termios {
mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
fn C.tcgetattr(fd int, termios_p &C.termios) int
fn C.tcsetattr(fd int, optional_actions int, const_termios_p &C.termios) int
fn C.ioctl(fd int, request u64, arg voidptr) int
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
[inline]
pub fn flag(value int) TcFlag {
return usize(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
[inline]
pub fn invert(value TcFlag) TcFlag {
return ~usize(value)
}
pub struct Termios {
pub mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcgetattr(fd int, mut termios_p Termios) int {
unsafe {
return C.tcgetattr(fd, &C.termios(termios_p))
}
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
unsafe {
return C.tcsetattr(fd, optional_actions, &C.termios(termios_p))
}
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
unsafe {
return C.ioctl(fd, request, arg)
}
}

View File

@ -0,0 +1,58 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// TODO Mac version needs to be implemented
// Will serve as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
// not used but needed for function declarations
type TcFlag = int
type Speed = int
type Cc = u8
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
// It is only implemented for Unix like OSes
pub fn flag(value int) TcFlag {
$compile_error('feature not available')
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
// It is only implemented for Unix like OSes
pub fn invert(value TcFlag) TcFlag {
$compile_error('feature not available')
}
// termios definitions
// Linux https://github.com/lattera/glibc/blob/master/sysdeps/unix/sysv/linux/bits/termios.h
// OpenBSD https://github.com/openbsd/src/blob/master/sys/sys/termios.h
// FreeBSD https://web.mit.edu/freebsd/head/sys/sys/_termios.h
// Solaris https://github.com/omniti-labs/illumos-omnios/blob/master/usr/src/uts/common/sys/termios.h
// DragonFly https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/sys/_termios.h
// QNX https://github.com/vocho/openqnx/blob/master/trunk/lib/c/public/termios.h
pub struct Termios {
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
// It is only implemented for Unix like OSes
pub fn tcgetattr(fd int, mut termios_p Termios) int {
$compile_error('feature not available')
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
// It is only implemented for Unix like OSes
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
$compile_error('feature not available')
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
$compile_error('feature not available')
}

View File

@ -0,0 +1,86 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// Serves as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
#include <termios.h>
#include <sys/ioctl.h>
// https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/sys/_termios.h
const cclen = 20
type TcFlag = int
type Speed = int
type Cc = u8
// Termios stores the terminal options
struct C.termios {
mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
fn C.tcgetattr(fd int, termios_p &C.termios) int
fn C.tcsetattr(fd int, optional_actions int, const_termios_p &C.termios) int
fn C.ioctl(fd int, request u64, arg voidptr) int
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
[inline]
pub fn flag(value int) TcFlag {
return int(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
[inline]
pub fn invert(value TcFlag) TcFlag {
return ~int(value)
}
pub struct Termios {
pub mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcgetattr(fd int, mut termios_p Termios) int {
unsafe {
return C.tcgetattr(fd, &C.termios(termios_p))
}
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
unsafe {
return C.tcsetattr(fd, optional_actions, &C.termios(termios_p))
}
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
unsafe {
return C.ioctl(fd, request, arg)
}
}

View File

@ -0,0 +1,86 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// Serves as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
#include <termios.h>
#include <sys/ioctl.h>
// https://web.mit.edu/freebsd/head/sys/sys/_termios.h
const cclen = 20
type TcFlag = int
type Speed = int
type Cc = u8
// Termios stores the terminal options
struct C.termios {
mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
fn C.tcgetattr(fd int, termios_p &C.termios) int
fn C.tcsetattr(fd int, optional_actions int, const_termios_p &C.termios) int
fn C.ioctl(fd int, request u64, arg voidptr) int
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
[inline]
pub fn flag(value int) TcFlag {
return int(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
[inline]
pub fn invert(value TcFlag) TcFlag {
return ~int(value)
}
pub struct Termios {
pub mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcgetattr(fd int, mut termios_p Termios) int {
unsafe {
return C.tcgetattr(fd, &C.termios(termios_p))
}
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
unsafe {
return C.tcsetattr(fd, optional_actions, &C.termios(termios_p))
}
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
unsafe {
return C.ioctl(fd, request, arg)
}
}

View File

@ -0,0 +1,88 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// Serves as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
#include <termios.h>
#include <sys/ioctl.h>
// https://github.com/lattera/glibc/blob/master/sysdeps/unix/sysv/linux/bits/termios.h
const cclen = 32
type TcFlag = int
type Speed = int
type Cc = u8
// Termios stores the terminal options on Linux.
struct C.termios {
mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_line Cc
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
fn C.tcgetattr(fd int, termios_p &C.termios) int
fn C.tcsetattr(fd int, optional_actions int, const_termios_p &C.termios) int
fn C.ioctl(fd int, request u64, arg voidptr) int
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
[inline]
pub fn flag(value int) TcFlag {
return int(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
[inline]
pub fn invert(value TcFlag) TcFlag {
return ~int(value)
}
pub struct Termios {
pub mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_line Cc
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcgetattr(fd int, mut termios_p Termios) int {
unsafe {
return C.tcgetattr(fd, &C.termios(termios_p))
}
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
unsafe {
return C.tcsetattr(fd, optional_actions, &C.termios(termios_p))
}
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
unsafe {
return C.ioctl(fd, request, arg)
}
}

View File

@ -0,0 +1,86 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// Serves as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
#include <termios.h>
#include <sys/ioctl.h>
// https://github.com/openbsd/src/blob/master/sys/sys/termios.h
const cclen = 20
type TcFlag = int
type Speed = int
type Cc = u8
// Termios stores the terminal options
struct C.termios {
mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
fn C.tcgetattr(fd int, termios_p &C.termios) int
fn C.tcsetattr(fd int, optional_actions int, const_termios_p &C.termios) int
fn C.ioctl(fd int, request u64, arg voidptr) int
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
[inline]
pub fn flag(value int) TcFlag {
return int(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
[inline]
pub fn invert(value TcFlag) TcFlag {
return ~int(value)
}
pub struct Termios {
pub mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
c_ispeed Speed
c_ospeed Speed
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcgetattr(fd int, mut termios_p Termios) int {
unsafe {
return C.tcgetattr(fd, &C.termios(termios_p))
}
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
unsafe {
return C.tcsetattr(fd, optional_actions, &C.termios(termios_p))
}
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
unsafe {
return C.ioctl(fd, request, arg)
}
}

View File

@ -0,0 +1,88 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// Serves as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
#include <termios.h>
#include <sys/ioctl.h>
// https://github.com/vocho/openqnx/blob/master/trunk/lib/c/public/termios.h
const cclen = 20
type TcFlag = int
type Speed = int
type Cc = u8
// Termios stores the terminal options
struct C.termios {
mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
reserved [3]u32
c_ispeed Speed
c_ospeed Speed
}
fn C.tcgetattr(fd int, termios_p &C.termios) int
fn C.tcsetattr(fd int, optional_actions int, const_termios_p &C.termios) int
fn C.ioctl(fd int, request u64, arg voidptr) int
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
[inline]
pub fn flag(value int) TcFlag {
return int(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
[inline]
pub fn invert(value TcFlag) TcFlag {
return ~int(value)
}
pub struct Termios {
pub mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
reserved [3]u32
c_ispeed Speed
c_ospeed Speed
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcgetattr(fd int, mut termios_p Termios) int {
unsafe {
return C.tcgetattr(fd, &C.termios(termios_p))
}
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
unsafe {
return C.tcsetattr(fd, optional_actions, &C.termios(termios_p))
}
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
unsafe {
return C.ioctl(fd, request, arg)
}
}

View File

@ -0,0 +1,82 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// Serves as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
#include <termios.h>
#include <sys/ioctl.h>
// https://web.mit.edu/freebsd/head/sys/sys/_termios.h
const cclen = 20
type TcFlag = int
type Speed = int
type Cc = u8
// Termios stores the terminal options
struct C.termios {
mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
}
fn C.tcgetattr(fd int, termios_p &C.termios) int
fn C.tcsetattr(fd int, optional_actions int, const_termios_p &C.termios) int
fn C.ioctl(fd int, request u64, arg voidptr) int
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
[inline]
pub fn flag(value int) TcFlag {
return int(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
[inline]
pub fn invert(value TcFlag) TcFlag {
return ~int(value)
}
pub struct Termios {
pub mut:
c_iflag TcFlag
c_oflag TcFlag
c_cflag TcFlag
c_lflag TcFlag
c_cc [cclen]Cc
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcgetattr(fd int, mut termios_p Termios) int {
unsafe {
return C.tcgetattr(fd, &C.termios(termios_p))
}
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
[inline]
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
unsafe {
return C.tcsetattr(fd, optional_actions, &C.termios(termios_p))
}
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
unsafe {
return C.ioctl(fd, request, arg)
}
}

View File

@ -0,0 +1,20 @@
module termios
fn test_termios() {
mut original_term := Termios{}
tcgetattr(0, mut original_term)
println(original_term)
mut silent_term := original_term
silent_term.c_lflag &= invert(C.ECHO)
tcsetattr(0, C.TCSANOW, mut silent_term)
mut check_term := Termios{}
tcgetattr(0, mut check_term)
assert check_term.c_lflag == silent_term.c_lflag
tcsetattr(0, C.TCSANOW, mut orginal_term)
tcgetattr(0, mut check_term)
assert check_term.c_lflag == orginal_term.c_lflag
}

View File

@ -0,0 +1,49 @@
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// TODO Windows version needs to be implemented.
// Will serve as more advanced input method
// based on the work of https://github.com/AmokHuginnsson/replxx
//
module termios
type TcFlag = int
type Speed = int
type Cc = u8
// flag provides a termios flag of the correct size
// for the underlying C.termios structure
// It is only implemented for Unix like OSes
pub fn flag(value int) TcFlag {
return int(value)
}
// invert is a platform dependant way to bitwise NOT (~) TcFlag
// as its length varies across platforms
// It is only implemented for Unix like OSes
pub fn invert(value TcFlag) TcFlag {
return ~int(value)
}
pub struct Termios {
}
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
// It is only implemented for Unix like OSes
pub fn tcgetattr(fd int, mut termios_p Termios) int {
return -1
}
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
// It is only implemented for Unix like OSes
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
return -1
}
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
// It is only implemented for Unix like OSes
[inline]
pub fn ioctl(fd int, request u64, arg voidptr) int {
return -1
}