[plt-scheme] feedback wanted: termios library interface module

From: Peter Santoro (psantoro at att.net)
Date: Thu Oct 16 16:44:21 EDT 2003

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"))

)






Posted on the users mailing list.