[plt-scheme] feedback wanted: termios library interface module
I recently put together a termios library interface module (see module
and sample usage code below). My initial, limited testing on Linux
shows that it's an order of magnitude faster than calling stty via a
subprocess (no surprise here). Since I've only written a couple of
mzscheme interface modules so far, I would appreciate feedback from
those who have more experience writing mzscheme interface modules to
external libraries. I'm particularily interested in knowing if there is
a better or more scheme friendly way to handle external library APIs
that use C structs. For example, I used scheme_malloc_atomic to
allocate termios structs, as it appears that the GC will automatically
collect the memory. I also followed the existing C API fairly closely
to take advantage of the existing manpages. Your feedback is appreciated.
Thank you,
Peter Santoro
;; SAMPLE USAGE:
(define (read-char-immediate)
(let ((tty-settings-old (make-termios)) (tty-settings-new (make-termios)))
(tcgetattr (stdin-fileno) tty-settings-old)
(tcgetattr (stdin-fileno) tty-settings-new)
(tcclr-local |ICANON| tty-settings-new)
(tcclr-local |ECHO| tty-settings-new)
(tcset-cc 1 tty-settings-new |VMIN|)
(tcset-cc 0 tty-settings-new |VTIME|)
(tcsetattr (stdin-fileno) |TCSAFLUSH| tty-settings-new)
(begin0 (read-char) (tcsetattr (stdin-fileno) |TCSANOW| tty-settings-old))))
;; MODULE FOLLOWS:
;; -*-mode: mzscheme-*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Module Stuff
;; mzc --auto-dir ++ldf -lncurses termios.ss
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module termios mzscheme
(require (lib "cffi.ss" "compiler"))
(provide (all-defined-except define-c-const))
(c-declare "#include <termios.h>")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Helper Macro (from Ed Cavazos's MzCurses)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-syntax define-c-const
(lambda (stx)
(syntax-case stx ()
((_ name)
(identifier? (syntax name))
(with-syntax ((c-code-string
(format "___result = ~a;"
(syntax-e (syntax name)))))
(syntax
(define name
((c-lambda ()
int
c-code-string)))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constants
;; manpage: stdio
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;(define stdin 0)
;(define stdout 1)
;(define stderr 2)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Attribute Control Functions
;; manpage: termios
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-c-const |TCSANOW|)
(define-c-const |TCSADRAIN|)
(define-c-const |TCSAFLUSH|)
(define tcgetattr (c-lambda (int (pointer "struct termios")) int "tcgetattr"))
(define tcsetattr (c-lambda (int int (pointer "struct termios")) int "tcsetattr"))
(define stdin-fileno (c-lambda () int
"___result = fileno(stdin);
"))
(define stdout-fileno (c-lambda () int
"___result = fileno(stdout);
"))
(define stderr-fileno (c-lambda () int
"___result = fileno(stderr);
"))
(define make-termios (c-lambda () scheme-object
"char *p = scheme_malloc_atomic(sizeof(struct termios));
___result = scheme_make_cptr( p, \"struct termios\");
"))
; set/clear input flags
(define-c-const |BRKINT|)
(define-c-const |IGNBRK|)
(define-c-const |ICRNL|)
(define-c-const |IGNCR|)
(define-c-const |INLCR|)
(define-c-const |IGNPAR|)
(define-c-const |INPCK|)
(define-c-const |PARMRK|)
(define-c-const |ISTRIP|)
(define-c-const |IXOFF|)
(define-c-const |IXON|)
(define tcset-input (c-lambda (int (pointer "struct termios")) void
"struct termios *p = ___arg2;
p->c_iflag |= ___arg1;
"))
(define tcclr-input (c-lambda (int (pointer "struct termios")) void
"struct termios *p = ___arg2;
p->c_iflag &= ~___arg1;
"))
; set/clear output flags
(define-c-const |OPOST|)
(define-c-const |ONLCR|)
(define-c-const |OCRNL|)
(define-c-const |ONOCR|)
(define-c-const |ONLRET|)
(define-c-const |OFILL|)
(define-c-const |OFDEL|)
(define-c-const |NLDLY|)
(define-c-const |CRDLY|)
(define-c-const |TABDLY|)
(define-c-const |BSDLY|)
(define-c-const |VTDLY|)
(define-c-const |FFDLY|)
(define tcset-output (c-lambda (int (pointer "struct termios")) void
"struct termios *p = ___arg2;
p->c_oflag |= ___arg1;
"))
(define tcclr-output (c-lambda (int (pointer "struct termios")) void
"struct termios *p = ___arg2;
p->c_oflag &= ~___arg1;
"))
; set/clear local flags
(define-c-const |ECHO|)
(define-c-const |ECHOE|)
(define-c-const |ECHOK|)
(define-c-const |ECHONL|)
(define-c-const |ICANON|)
(define-c-const |IEXTEN|)
(define-c-const |ISIG|)
(define-c-const |NOFLSH|)
(define-c-const |TOSTOP|)
(define tcset-local (c-lambda (int (pointer "struct termios")) void
"struct termios *p = ___arg2;
p->c_lflag |= ___arg1;
"))
(define tcclr-local (c-lambda (int (pointer "struct termios")) void
"struct termios *p = ___arg2;
p->c_lflag &= ~___arg1;
"))
; set/clear control flags
(define-c-const |CLOCAL|)
(define-c-const |CREAD|)
(define-c-const |CS5|)
(define-c-const |CS6|)
(define-c-const |CS7|)
(define-c-const |CS8|)
(define-c-const |CSTOPB|)
(define-c-const |HUPCL|)
(define-c-const |PARENB|)
(define-c-const |PARODD|)
(define tcset-control (c-lambda (int (pointer "struct termios")) void
"struct termios *p = ___arg2;
p->c_cflag |= ___arg1;
"))
(define tcclr-control (c-lambda (int (pointer "struct termios")) void
"struct termios *p = ___arg2;
p->c_cflag &= ~___arg1;
"))
; set control characters
(define-c-const |VEOF|)
(define-c-const |VEOL|)
(define-c-const |VERASE|)
(define-c-const |VINTR|)
(define-c-const |VKILL|)
(define-c-const |VQUIT|)
(define-c-const |VSUSP|)
(define-c-const |VSTART|)
(define-c-const |VSTOP|)
(define-c-const |VMIN|)
(define-c-const |VTIME|)
(define tcset-cc (c-lambda (int (pointer "struct termios") int) void
"struct termios *p = ___arg2;
p->c_cc[___arg3] = ___arg1;
"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Speed Control Functions
;; manpage: termios
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-c-const |B0|)
(define-c-const |B50|)
(define-c-const |B75|)
(define-c-const |B110|)
(define-c-const |B134|)
(define-c-const |B150|)
(define-c-const |B200|)
(define-c-const |B300|)
(define-c-const |B600|)
(define-c-const |B1800|)
(define-c-const |B2400|)
(define-c-const |B4800|)
(define-c-const |B9600|)
(define-c-const |B19200|)
(define-c-const |B38400|)
(define-c-const |B57600|)
(define-c-const |B115200|)
(define-c-const |B230400|)
(define cfgetispeed (c-lambda ((pointer "struct termios")) int "cfgetispeed"))
(define cfsetispeed (c-lambda ((pointer "struct termios") int) int "cfsetispeed"))
(define cfgetospeed (c-lambda ((pointer "struct termios")) int "cfgetospeed"))
(define cfsetospeed (c-lambda ((pointer "struct termios") int) int "cfsetospeed"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Line Control Functions
;; manpage: termios
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-c-const |TCOON|)
(define-c-const |TCOOFF|)
(define-c-const |TCION|)
(define-c-const |TCIOFF|)
(define tcdrain (c-lambda (int) int "tcdrain"))
(define tcflush (c-lambda (int int) int "tcflush"))
(define tcflow (c-lambda (int int) int "tcflow"))
;; Process Control Functions
;; manpage: termios
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define tcgetpgrp (c-lambda (int) int "tcgetpgrp"))
(define tcsetpgrp (c-lambda (int int) int "tcsetpgrp"))
)