using constantenum for termios options constants (icanon etc.); keywords stty syntax

Nikolay V. Razbegaev [2009-11-30 17:49]
using constantenum for termios options constants (icanon etc.); keywords stty syntax
Filename
README
conditions.lisp
ffi-termios-constants.lisp
ffi-termios-functions-unix.lisp
pkgdcl.lisp
streams.lisp
wrapers.lisp
diff --git a/README b/README
index 6d33ae8..06ba739 100644
--- a/README
+++ b/README
@@ -29,30 +29,29 @@ values before reading/writing.
 Usage of `with-serial-stream' macro is recommended. Syntax is like
 `with-open-file':
  (with-raw-serial (stream path &key
- 		   (speed 115200)
+ 		   (speed :b115200)
 		   (parity n)
 		   (byte-size 8)
 		   hardware-flow-control
 		   software-flow-control
-		   (flag (logior o-rdwr o-nonblock))
+		   (flag (logior o-rdwr o-nonblock o-noctty))
                    (mode *default-open-mode*)
                    (external-format :default)
 		   timeout read-timeout write-timeout)
     &body body)

-I.e. only serial device pathname is necessary parameter.
-You can specify require baud rate (note, that this macro
-will look for a corresponding baud rate constant and signal en error,
-if you try to use nonstandard baud rate), byte/character size and
-parity checking mode. Also you can turn on hardware/software flow control
-and specify additional stream parameters.
+I.e. only serial device pathname is necessary parameter.  You can
+specify require baud rate (in keyword form: `:b9600` and so),
+byte/character size and parity checking mode. Also you can turn on
+hardware/software flow control and specify additional stream
+parameters. Note, that this macro will allways set `raw` mode, so if
+you prefer `canonical` mode you should use `with-open-stream` and
+`stty` (see below) instead.
+
+`stty` function is like `stty' shell utility:
+  (stty fd :b115200 :raw t :hupcl nil)
+

-`stty' function is like `stty' shell utility, except for you should
-type "'icanon" instead of "-icanon" to disable feature, "'(icanon t)"
-instead of "icanon" to enable feature, "'(vtime 1)" instead of "vtime 1"
-to specify some value. And switching to raw mode is just
-"'raw", not "'(raw t)". Also, baud rate can be specified in integer
-(i.e. 115200) and symbol-constant (i.e. 'b115200) form.

 SUPPORTED PLATFORMS:

@@ -66,14 +65,11 @@ TODO:

 0 Checking right `#+' and `#-' for non posix features.

-1 Define termios constants via constantenum and change stty syntax
-  (keywords parameters).
-
-2 Testing on other OS and lisp implementation.
+1 Testing on other OS and lisp implementation.

-3 Testing units.
+2 Testing units.

-4 Restarts on i/o methods.
+3 Restarts on i/o methods.

-5 Streams class and methods for 9-bit mode (using parity checking bits
-for data too).
+4 Streams class and methods for 9-bit mode (using parity checking bits
+  for data too).
diff --git a/conditions.lisp b/conditions.lisp
index 9476ba9..08ccc8d 100644
--- a/conditions.lisp
+++ b/conditions.lisp
@@ -11,16 +11,28 @@
   ((request :initarg :request :reader request))
   (:report
    (lambda (c s)
-     (declare (ignorable c))
      (format s "Failled apply ~a request on serial device" (request c))))
   (:documentation
    "Signalled when `stty' failled to apply one of the requested settings"))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(define-condition termios-speed-failled (termios-set-failled)
+(define-condition termios-set-baud-rate-failled (termios-set-failled)
   ()
   (:report
    (lambda (c s)
-     (declare (ignorable c))
-     (format s "Failled to setup ~a baud speed on serial device" (request c))))
-  (:documentation "Signalled by `stty' when requested speed is unsupported"))
+     (format s "Failled to setup ~a termios baud rate" (request c))))
+  (:documentation "Signalled when requested baud rate is unsupported"))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(define-condition termios-set-flag-failled (termios-set-failled)
+  ()
+  (:report
+   (lambda (c s)
+     (format s "Failled to setup ~a termios flag" (request c))))
+  (:documentation "Signalled when requested flag is unsupported"))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(define-condition termios-set-control-character-failled (termios-set-failled)
+  ()
+  (:report
+   (lambda (c s)
+     (format s "Failled to setup ~a termios control character" (request c))))
+  (:documentation "Signalled when requested control character is unsupported"))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/ffi-termios-constants.lisp b/ffi-termios-constants.lisp
index 1fd864b..5934395 100644
--- a/ffi-termios-constants.lisp
+++ b/ffi-termios-constants.lisp
@@ -13,488 +13,462 @@
 (define "_BSD_SOURCE")
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; < clfags >
-#+(or linux bsd)
-(constant (cbaud "CBAUD")
-          :documentation
-          " Baud speed mask (4+1 bits).")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (cbaudex "CBAUDEX")
-          :documentation
-          "Extra baud speed mask (1 bit),included in CBAUD. ")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (csize "CSIZE")
-          :documentation
-          "Character size mask.  Values are CS5, CS6, CS7, or CS8.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; < valid character sizes >
-(constant (cs5 "CS5"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (cs6 "CS6"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (cs7 "CS7"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (cs8 "CS8"))
-;; </ valid character sizes >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (cstopb "CSTOPB")
-          :documentation
-          "Set two stop bits, rather than one.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (cread "CREAD")
-          :documentation "Enable receiver. This flag is really necessary.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (parenb "PARENB")
-          :documentation
-          "Enable parity generation on output and parity checking for input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (parodd "PARODD")
-          :documentation
-          "If  set,  then parity  for  input  and  output is  odd;
+(constantenum (cflag :define-constants t)
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:cbaud "CBAUD")
+   :documentation "Baud speed mask (4+1 bits).")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:cbaudex "CBAUDEX")
+   :documentation "Extra baud speed mask (1 bit),included in CBAUD. ")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:csize "CSIZE")
+   :documentation "Character size mask.  Values are CS5, CS6, CS7, or CS8.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ;; < valid character sizes >
+  ((:cs5 "CS5"))
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:cs6 "CS6"))
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:cs7 "CS7"))
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:cs8 "CS8"))
+  ;; </ valid character sizes >
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:cstopb "CSTOPB")
+   :documentation "Set two stop bits, rather than one.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:cread "CREAD")
+   :documentation "Enable receiver. This flag is really necessary.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:parenb "PARENB")
+   :documentation
+   "Enable parity generation on output and parity checking for input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:parodd "PARODD")
+   :documentation
+   "If  set,  then parity  for  input  and  output is  odd;
 	   otherwise even parity is used.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (hupcl "HUPCL")
-          :documentation
-          "Lower modem control lines after last process closes the
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:hupcl "HUPCL")
+   :documentation
+   "Lower modem control lines after last process closes the
 	   device (hang up).")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (clocal "CLOCAL") :documentation "Ignore modem control lines.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (loblk "LOBLK")
-          :documentation
-          "Block  output from a  non-current shell layer.
-           For use by shl (shell layers).")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or bsd linux)
-(constant (cibaud "CIBAUD")
-          :documentation
-          "Mask for input speeds. The values for the CIBAUD bits are the same
-           as the values for the CBAUD bits,shifted left IBSHIFT bits. ")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or bsd linux)
-(constant (cmspar "CMSPAR")
-          :documentation
-          "Use `stick' (mark/space) parity
-           (supported on certain serial devices):
-           if  PARODD is set, the parity bit is  always 1;
-           if PARODD is not set,then the parity bit is always 0).")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or bsd linux)
-(constant (crtscts "CRTSCTS")
-          :documentation "Enable RTS/CTS (hardware) flow control. ")
-;; </ cflags >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; < lflags >
-(constant (isig "ISIG")
-          :documentation
-          "When any of the characters INTR, QUIT, SUSP, or DSUSP
-           are received, generate the corresponding signal.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (icanon "ICANON") :documentation "Enable canonical mode.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (xcase "XCASE")
-          :documentation
-          "If ICANON is also  set, terminal is uppercase only.
-           Input is converted to lowercase, except for characters preceded
-           by \.  On output,  uppercase characters are preceded by
-	   \ and lowercase  characters are converted to uppercase.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (echo "ECHO") :documentation "Echo input characters.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (echoe "ECHOE")
-          :documentation
-          "If ICANON is also set, the ERASE character erases the
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:clocal "CLOCAL") :documentation "Ignore modem control lines.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:loblk "LOBLK")
+   :documentation
+   "Block  output from a  non-current shell layer.
+    For use by shl (shell layers).")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or bsd linux)
+  ((:cibaud "CIBAUD")
+   :documentation
+   "Mask for input speeds. The values for the CIBAUD bits are the same
+    as the values for the CBAUD bits,shifted left IBSHIFT bits. ")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or bsd linux)
+  ((:cmspar "CMSPAR")
+   :documentation
+   "Use `stick' (mark/space) parity
+    (supported on certain serial devices):
+    if  PARODD is set, the parity bit is  always 1;
+    if PARODD is not set,then the parity bit is always 0).")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or bsd linux)
+  ((:crtscts "CRTSCTS")
+   :documentation "Enable RTS/CTS (hardware) flow control.")) ; </cflags>
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; <lflags>
+(constantenum (lflag :define-constants t)
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:isig "ISIG")
+   :documentation
+   "When any of the characters INTR, QUIT, SUSP, or DSUSP
+    are received, generate the corresponding signal.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:icanon "ICANON") :documentation "Enable canonical mode.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:xcase "XCASE")
+   :documentation
+   "If ICANON is also  set, terminal is uppercase only.
+    Input is converted to lowercase, except for characters preceded
+    by \.  On output,  uppercase characters are preceded by
+    \\ and lowercase  characters are converted to uppercase.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:echo "ECHO") :documentation "Echo input characters.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:echoe "ECHOE")
+   :documentation
+   "If ICANON is also set, the ERASE character erases the
 	   preceding input character, and WERASE erases the
 	   preceding word.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (echok "ECHOK")
-          :documentation
-          "If ICANON is also set, the KILL character erases the current line.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (echonl "ECHONL")
-          :documentation
-          "If ICANON is also set, echo the NL character
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:echok "ECHOK")
+   :documentation
+   "If ICANON is also set, the KILL character erases the current line.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:echonl "ECHONL")
+   :documentation
+   "If ICANON is also set, echo the NL character
            even if ECHO is not set.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (echoctl "ECHOCTL")
-          :documentation
-          "If ECHO is  also  set, ASCII control signals other than TAB,
-           NL, START, and STOP are echoed as ^X, where X is the character
-           with ASCII code 0x40 greater than the control signal.
-           For  example, character  0x08  (BS) is echoed as  ^H.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (echoprt "ECHOPRT")
-          :documentation
-          "If ICANON and IECHO are also set, characters are printed
-           as they are being erased.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (echoke "ECHOKE")
-          :documentation
-          "If ICANON is also set, KILL is echoed by erasing each character
-           on the line, as  specified by ECHOE and ECHOPRT.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (defecho "DEFECHO")
-          :documentation " Echo only when a process is reading.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+bsd
-(constant (flusho "FLUSHO")
-          :documentation
-          "Output is being flushed.
-           This flag is toggled by typing the DISCARD character.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (noflsh "NOFLSH")
-          :documentation
-          "Disable  flushing  the  input  and output  queues  when
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:echoctl "ECHOCTL")
+   :documentation
+   "If ECHO is  also  set, ASCII control signals other than TAB,
+    NL, START, and STOP are echoed as ^X, where X is the character
+    with ASCII code 0x40 greater than the control signal.
+    For  example, character  0x08  (BS) is echoed as  ^H.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:echoprt "ECHOPRT")
+   :documentation
+   "If ICANON and IECHO are also set, characters are printed
+    as they are being erased.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:echoke "ECHOKE")
+   :documentation
+   "If ICANON is also set, KILL is echoed by erasing each character
+    on the line, as  specified by ECHOE and ECHOPRT.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:defecho "DEFECHO")
+   :documentation " Echo only when a process is reading.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+bsd
+  ((:flusho "FLUSHO")
+   :documentation
+   "Output is being flushed.
+    This flag is toggled by typing the DISCARD character.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:noflsh "NOFLSH")
+   :documentation
+   "Disable  flushing  the  input  and output  queues  when
            generating the SIGINT, SIGQUIT, and SIGSUSP signals.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (tostop "TOSTOP")
-          :documentation
-          "Send  the SIGTTOU signal to the process group of
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:tostop "TOSTOP")
+   :documentation
+   "Send  the SIGTTOU signal to the process group of
            a background process which tries to write to
            its controlling terminal.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+bsd
-(constant (pendin "PENDIN")
-          :documentation
-          "All characters in the input queue are reprinted when the
-           next character is read. (bash(1) handles typeahead this way.)")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (iexten "IEXTEN")
-          :documentation
-          "Enable implementation-defined input processing.
-           This flag, as well as ICANON must be enabled for the special
-           characters EOL2, LNEXT, REPRINT, WERASE to be interpreted,
-           and for the IUCLC flag to be effective.")
-;; </ lflags >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; < iflags >
-(constant (ignbrk "IGNBRK") :documentation "Ignore BREAK condition on input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (brkint "BRKINT")
-          :documentation
-          "If IGNBRK is set, a BREAK is ignored.  If it is not set
-           but BRKINT  is set, then  a BREAK causes the  input and
-	   output queues to be flushed, and if the terminal is the
-	   controlling terminal of  a foreground process group, it
-	   will  cause a  SIGINT  to be  sent  to this  foreground
-	   process group.  When neither IGNBRK nor BRKINT are set,
-	   a BREAK reads as a null byte ('0'), except when PARMRK
-	   is set, in which case  it reads as the sequence \377 \0 \0.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (ignpar "IGNPAR")
-          :documentation "Ignore framing errors and parity errors.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (parmrk "PARMRK")
-          :documentation
-          "If IGNPAR is not set, prefix a character with a parity
-           error or framing error with 377 0. If neither IGNPAR
-	   nor PARMRK is set, read a character with a parity error
-	   or framing error as 0.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (inpck "INPCK") :documentation "Enable input parity checking.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (istrip "ISTRIP") :documentation "Strip off eighth bit.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (inlcr "INLCR") :documentation "Translate NL to CR on input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (igncr "IGNCR") :documentation "Ignore carriage return on input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (icrnl "ICRNL")
-          :documentation
-          "Translate carriage return to newline on input
-           (unless IGNCR is set).")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+linux
-(constant (iuclc "IUCLC")
-          :documentation "Map uppercase characters to lowercase on input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (ixon "IXON")
-          :documentation "Enable XON/XOFF flow control on output.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; XSI features are #+xfi marked in sb-posix grovel file,
-;; but (find :xsi *features*) return NIL
-;; so i'm leaving xsi features unmarked
-(constant (ixany "IXANY")
-          :documentation
-          "Typing any character will restart stopped output.
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+bsd
+  ((:pendin "PENDIN")
+   :documentation
+   "All characters in the input queue are reprinted when the
+    next character is read. (bash(1) handles typeahead this way.)")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:iexten "IEXTEN")
+   :documentation
+   "Enable implementation-defined input processing.
+    This flag, as well as ICANON must be enabled for the special
+    characters EOL2, LNEXT, REPRINT, WERASE to be interpreted,
+    and for the IUCLC flag to be effective.")) ; </lflags>
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; <iflags>
+(constantenum (iflag :define-constants t)
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:ignbrk "IGNBRK") :documentation "Ignore BREAK condition on input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:brkint "BRKINT")
+   :documentation
+   "If IGNBRK is set, a BREAK is ignored.  If it is not set
+    but BRKINT  is set, then  a BREAK causes the  input and
+    output queues to be flushed, and if the terminal is the
+    controlling terminal of  a foreground process group, it
+    will  cause a  SIGINT  to be  sent  to this  foreground
+    process group.  When neither IGNBRK nor BRKINT are set,
+    a BREAK reads as a null byte ('0'), except when PARMRK
+    is set, in which case  it reads as the sequence \377 \0 \0.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:ignpar "IGNPAR")
+   :documentation "Ignore framing errors and parity errors.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:parmrk "PARMRK")
+   :documentation
+   "If IGNPAR is not set, prefix a character with a parity
+    error or framing error with 377 0. If neither IGNPAR
+    nor PARMRK is set, read a character with a parity error
+    or framing error as 0.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:inpck "INPCK") :documentation "Enable input parity checking.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:istrip "ISTRIP") :documentation "Strip off eighth bit.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:inlcr "INLCR") :documentation "Translate NL to CR on input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:igncr "IGNCR") :documentation "Ignore carriage return on input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:icrnl "ICRNL")
+   :documentation
+   "Translate carriage return to newline on input
+    (unless IGNCR is set).")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+linux
+  ((:iuclc "IUCLC")
+   :documentation "Map uppercase characters to lowercase on input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:ixon "IXON")
+   :documentation "Enable XON/XOFF flow control on output.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ;; XSI features are #+xfi marked in sb-posix grovel file,
+  ;; but (find :xsi *features*) return NIL
+  ;; so i'm leaving xsi features unmarked
+  ((:ixany "IXANY")
+   :documentation
+   "Typing any character will restart stopped output.
            (The default is to allow just the START character
            to restart output.)")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (ixoff "IXOFF")
-          :documentation "Enable XON/XOFF flow control on input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (imaxbel "IMAXBEL")
-          :documentation "Ring bell when input queue is full.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+linux
-(constant (iutf8 "IUTF8")
-          :documentation
-          "Input is UTF8; this allows character-erase to be correctly performed
-           in cooked mode.")
-;; </ iflags >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; < oflags >
-(constant (opost "OPOST")
-          :documentation "Enable implementation-defined output processing.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+linux
-(constant (olcuc "OLCUC")
-          :documentation "Map lowercase characters to uppercase on output.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (onlcr "ONLCR") :documentation "Map NL to CR-NL on output.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (ocrnl "OCRNL") :documentation "Map CR to NL on output.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (onocr "ONOCR") :documentation "Don't output CR at column 0.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (onlret "ONLRET") :documentation "Don't output CR.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (ofill "OFILL")
-          :documentation
-          "Send fill characters for a delay, rather than using a timed delay.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (ofdel "OFDEL")
-          :documentation
-          "Fill character is ASCII DEL (0177). If unset, fill character
-           is ASCII NUL ('0').")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (nldly "NLDLY")
-          :documentation
-          "Newline delay mask. Values are NL0 and NL1.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (crdly "CRDLY")
-          :documentation
-          "Carriage return delay mask. Values are CR0, CR1, CR2,or  CR3.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (tabdly "TABDLY")
-          :documentation
-          "Horizontal tab delay mask.
-           Values are TAB0, TAB1,TAB2, TAB3 (or XTABS).
-           A value  of  TAB3, that is, XTABS, expands tabs to spaces
-           (with tab  stops every eight columns).")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (bsdly "BSDLY")
-          :documentation "Backspace  delay mask. Values are BS0 or BS1.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (vtdly "VTDLY")
-          :documentation "Vertical tab delay mask.  Values are VT0 or VT1.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+(or linux bsd)
-(constant (ffdly "FFDLY")
-          :documentation "Form  feed delay  mask. Values  are   FF0  or  FF1.")
-;; </ oflags >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; < control-characters >
-(constant (vintr "VINTR")
-          :documentation
-          "(003, ETX, Ctrl-C, or also 0177, DEL, rubout) Interrupt character.
-           Send a SIGINT signal. Recognized when ISIG is set,
-           and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (vquit "VQUIT")
-          :documentation
-          "(034, FS, Ctrl-) Quit character.  Send SIGQUIT signal.
-           Recognized  when ISIG is  set, and  then not  passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (verase "VERASE")
-          :documentation
-          "(0177, DEL, rubout,  or 010,  BS, Ctrl-H, or also #)
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:ixoff "IXOFF")
+   :documentation "Enable XON/XOFF flow control on input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:imaxbel "IMAXBEL")
+   :documentation "Ring bell when input queue is full.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+linux
+  ((:iutf8 "IUTF8")
+   :documentation
+   "Input is UTF8; this allows character-erase to be correctly performed
+    in cooked mode."))                  ; </iflags>
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; <oflags>
+(constantenum (oflag :define-constants t)
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:opost "OPOST")
+   :documentation "Enable implementation-defined output processing.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+linux
+  ((:olcuc "OLCUC")
+   :documentation "Map lowercase characters to uppercase on output.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:onlcr "ONLCR") :documentation "Map NL to CR-NL on output.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:ocrnl "OCRNL") :documentation "Map CR to NL on output.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:onocr "ONOCR") :documentation "Don't output CR at column 0.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:onlret "ONLRET") :documentation "Don't output CR.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:ofill "OFILL")
+   :documentation
+   "Send fill characters for a delay, rather than using a timed delay.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:ofdel "OFDEL")
+   :documentation
+   "Fill character is ASCII DEL (0177). If unset, fill character
+    is ASCII NUL ('0').")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:nldly "NLDLY")
+   :documentation
+   "Newline delay mask. Values are NL0 and NL1.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:crdly "CRDLY")
+   :documentation
+   "Carriage return delay mask. Values are CR0, CR1, CR2,or  CR3.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:tabdly "TABDLY")
+   :documentation
+   "Horizontal tab delay mask.
+    Values are TAB0, TAB1,TAB2, TAB3 (or XTABS).
+    A value  of  TAB3, that is, XTABS, expands tabs to spaces
+    (with tab  stops every eight columns).")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:bsdly "BSDLY")
+   :documentation "Backspace  delay mask. Values are BS0 or BS1.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:vtdly "VTDLY")
+   :documentation "Vertical tab delay mask.  Values are VT0 or VT1.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+(or linux bsd)
+  ((:ffdly "FFDLY")
+   :documentation "Form feed delay mask. Values are FF0 or FF1.")) ;</oflags>
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; <control characters>
+(constantenum (control-character :define-constants t)
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:vintr "VINTR")
+   :documentation
+   "(003, ETX, Ctrl-C, or also 0177, DEL, rubout) Interrupt character.
+    Send a SIGINT signal. Recognized when ISIG is set,
+    and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:vquit "VQUIT")
+   :documentation
+   "(034, FS, Ctrl-) Quit character.  Send SIGQUIT signal.
+    Recognized  when ISIG is  set, and  then not  passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:verase "VERASE")
+   :documentation
+   "(0177, DEL, rubout,  or 010,  BS, Ctrl-H, or also #)
            Erase    character.    This    erases    the   previous
            not-yet-erased character,  but does not  erase past EOF
 	   or beginning-of-line.   Recognized when ICANON  is set,
 	   and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (vkill "VKILL")
-          :documentation
-          "(025, NAK, Ctrl-U, or Ctrl-X, or also @) Kill character.
-           This erases the input since the last EOF or beginning-of-line.
-           Recognized when ICANON is set, and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (veof "VEOF")
-          :documentation
-          "(004, EOT, Ctrl-D) End-of-file character.
-           More precisely: this character causes the pending tty buffer
-           to be sent to the waiting user program without waiting for
-           end-of-line.  If it is the first character of the line,
-           the read(2) in the user program returns 0, which signifies
-           end-of-file.
-           Recognized  when ICANON is set, and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (vmin "VMIN")
-          :documentation
-          "Minimum number of characters for non-canonical read.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (veol "VEOL")
-          :documentation
-          "(0, NUL) Additional end-of-line character.
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:vkill "VKILL")
+   :documentation
+   "(025, NAK, Ctrl-U, or Ctrl-X, or also @) Kill character.
+    This erases the input since the last EOF or beginning-of-line.
+    Recognized when ICANON is set, and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:veof "VEOF")
+   :documentation
+   "(004, EOT, Ctrl-D) End-of-file character.
+    More precisely: this character causes the pending tty buffer
+    to be sent to the waiting user program without waiting for
+    end-of-line.  If it is the first character of the line,
+    the read(2) in the user program returns 0, which signifies
+    end-of-file.
+    Recognized  when ICANON is set, and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:vmin "VMIN")
+   :documentation
+   "Minimum number of characters for non-canonical read.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:veol "VEOL")
+   :documentation
+   "(0, NUL) Additional end-of-line character.
            Recognized when ICANON is set.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (vtime "VTIME")
-          :documentation "Timeout in deciseconds for non-canonical read.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+linux
-(constant (veol2 "VEOL2")
-          :documentation
-          "Yet another end-of-line character.
-           Recognized when ICANON is set.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (vswtch "VSWTCH")
-          :documentation "Switch character.  (Used by shl only.)")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (vstart "VSTART")
-          :documentation
-          "(021, DC1, Ctrl-Q) Start character.
-            Restarts output stopped by the Stop character.
-            Recognized when IXON is set, and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (vstop "VSTOP")
-          :documentation
-          "(023, DC3, Ctrl-S) Stop character.
-           Stop output until Start character typed.
-           Recognized  when IXON  is set, and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (vsusp "VSUSP")
-          :documentation
-          "(032, SUB, Ctrl-Z) Suspend character.
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:vtime "VTIME")
+   :documentation "Timeout in deciseconds for non-canonical read.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+linux
+  ((:veol2 "VEOL2")
+   :documentation
+   "Yet another end-of-line character.
+    Recognized when ICANON is set.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:vswtch "VSWTCH")
+   :documentation "Switch character.  (Used by shl only.)")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:vstart "VSTART")
+   :documentation
+   "(021, DC1, Ctrl-Q) Start character.
+    Restarts output stopped by the Stop character.
+    Recognized when IXON is set, and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:vstop "VSTOP")
+   :documentation
+   "(023, DC3, Ctrl-S) Stop character.
+    Stop output until Start character typed.
+    Recognized  when IXON  is set, and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:vsusp "VSUSP")
+   :documentation
+   "(032, SUB, Ctrl-Z) Suspend character.
            Send SIGTSTP signal. Recognized when ISIG is set,
            and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (vdsusp "VDSUSP")
-          :documentation
-          "031, EM, Ctrl-Y) Delayed suspend  character: send SIGTSTP signal
-           when  the  character  is  read  by  the  user  program.
-           Recognized when IEXTEN and ISIG are set, and the system
-	   supports job control, and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+linux
-(constant (vlnext "VLNEXT")
-          :documentation
-          "(026, SYN, Ctrl-V) Literal next.
-           Quotes the next  input character,  depriving it of  a possible
-           special  meaning.  Recognized when  IEXTEN is  set,
-           and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+linux
-(constant (vwerase "VWERASE")
-          :documentation
-          "(027, ETB, Ctrl-W) Word  erase.
-           Recognized when ICANON and IEXTEN are set,
-           and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#+linux
-(constant (vreprint "VREPRINT")
-          :documentation
-          "(022, DC2, Ctrl-R) Reprint unread characters.
-           Recognized when ICANON and IEXTEN are set,
-           and then not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (vdiscard "VDISCARD")
-          :documentation
-          "017, SI, Ctrl-O) Toggle: start/stop discarding  pending output.
-           Recognized when  IEXTEN is set, and then  not passed as input.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#-linux
-(constant (vstatus "VSTATUS")
-          :documentation "Status request: 024, DC4, Ctrl-T).")
-;; </ control characters >
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:vdsusp "VDSUSP")
+   :documentation
+   "031, EM, Ctrl-Y) Delayed suspend  character: send SIGTSTP signal
+    when  the  character  is  read  by  the  user  program.
+    Recognized when IEXTEN and ISIG are set, and the system
+    supports job control, and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+linux
+  ((:vlnext "VLNEXT")
+   :documentation
+   "(026, SYN, Ctrl-V) Literal next.
+    Quotes the next  input character,  depriving it of  a possible
+    special  meaning.  Recognized when  IEXTEN is  set,
+   and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+linux
+  ((:vwerase "VWERASE")
+   :documentation
+   "(027, ETB, Ctrl-W) Word  erase.
+    Recognized when ICANON and IEXTEN are set,
+    and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #+linux
+  ((:vreprint "VREPRINT")
+   :documentation
+   "(022, DC2, Ctrl-R) Reprint unread characters.
+    Recognized when ICANON and IEXTEN are set,
+    and then not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:vdiscard "VDISCARD")
+   :documentation
+   "017, SI, Ctrl-O) Toggle: start/stop discarding  pending output.
+    Recognized when  IEXTEN is set, and then  not passed as input.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  #-linux
+  ((:vstatus "VSTATUS")
+   :documentation "Status request: 024, DC4, Ctrl-T).")) ;</control characters>
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; < tcssetattr actions >
-(constant (tcsanow "TCSANOW")
-          :documentation "The change (by tcssetattr) occurs immediately.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (tcsadrain "TCSADRAIN")
-          :documentation
-          "The change occurs (by tcssetattr) after all output written to fd
-           has been  transmitted.  This function  should be used when
-	   changing parameters that affect output.")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (tcsaflush "TCSAFLUSH")
-          :documentation
-          "The change (by tcssetattr) occurs after all output written to the
-           object referred by fd has been transmitted, and all
-	   input that has been received but not read will be
-           discarded before the change is made.")
-;; </ tcssetattr actions >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; < Posix baud rates >
-(constant (b0 "B0"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b50 "B50"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b75 "B75"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b110 "B110"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b134 "B134"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b150 "B150"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b200 "B200"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b300 "B300"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b600 "B600"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b1200 "B1200"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b1800 "B1800"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b2400 "B2400"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b4800 "B4800"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b9600 "B9600"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b19200 "B19200"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b38400 "B38400"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b57600 "B57600"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b115200 "B115200"))
-;; </ Posix baud rates >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; < Non posix baud rates >
-(constant (b230400 "B230400"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b460800 "B460800"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b500000 "B500000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b576000 "B576000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b921600 "B921600"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b1000000 "B1000000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b1152000 "B1152000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b1500000 "B1500000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b2000000 "B2000000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b2500000 "B2500000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b3000000 "B3000000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b3500000 "B3500000"))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(constant (b4000000 "B4000000"))
-;; </ Non posix baud rates >
+(constantenum (tcssetattr-action :define-constants t)
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:tcsanow "TCSANOW")
+   :documentation "The change (by tcssetattr) occurs immediately.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:tcsadrain "TCSADRAIN")
+   :documentation
+   "The change occurs (by tcssetattr) after all output written to fd
+    has been  transmitted.  This function  should be used when
+    changing parameters that affect output.")
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ((:tcsaflush "TCSAFLUSH")
+   :documentation
+   "The change (by tcssetattr) occurs after all output written to the
+    object referred by fd has been transmitted, and all
+    input that has been received but not read will be
+    discarded before the change is made.")) ; </tcssetattr actions>
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; <baud rates >
+(constantenum (baud-rate :define-constants t)
+  ;; <Posix baud rates>
+  ((:b0       "B0"))
+  ((:b50      "B50"))
+  ((:b75      "B75"))
+  ((:b110     "B110"))
+  ((:b134     "B134"))
+  ((:b150     "B150"))
+  ((:b200     "B200"))
+  ((:b300     "B300"))
+  ((:b600     "B600"))
+  ((:b1200    "B1200"))
+  ((:b1800    "B1800"))
+  ((:b2400    "B2400"))
+  ((:b4800    "B4800"))
+  ((:b9600    "B9600"))
+  ((:b19200   "B19200"))
+  ((:b38400   "B38400"))
+  ((:b57600   "B57600"))
+  ((:b115200  "B115200"))
+  ;; </Posix baud rates>
+  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  ;; <Non posix baud rates>
+  ((:b230400  "B230400"))
+  ((:b460800  "B460800"))
+  ((:b500000  "B500000"))
+  ((:b576000  "B576000"))
+  ((:b921600  "B921600"))
+  ((:b1000000 "B1000000"))
+  ((:b1152000 "B1152000"))
+  ((:b1500000 "B1500000"))
+  ((:b2000000 "B2000000"))
+  ((:b2500000 "B2500000"))
+  ((:b3000000 "B3000000"))
+  ((:b3500000 "B3500000"))
+  ((:b4000000 "B4000000")))             ;</Non posix baud rates> </baud rates>
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/ffi-termios-functions-unix.lisp b/ffi-termios-functions-unix.lisp
index 74bec69..c544996 100644
--- a/ffi-termios-functions-unix.lisp
+++ b/ffi-termios-functions-unix.lisp
@@ -3,19 +3,20 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (in-package :iolib.termios)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defsyscall (%cfgetispeed "cfgetispeed") termios-speed
+;; No errors are defined for cfget{i,o}speed, so I'm using defcfun*
+(defcfun* (%cfgetispeed "cfgetispeed") baud-rate
   (termios :pointer))			; const struct termios *
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defsyscall (%cfgetospeed "cfgetospeed") termios-speed
+(defcfun* (%cfgetospeed "cfgetospeed") baud-rate
   (termios :pointer))			; const struct termios *
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defsyscall (%cfsetispeed "cfsetispeed") :int
   (termios :pointer)			; struct termios *
-  (speed   termios-speed))
+  (speed   baud-rate))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defsyscall (%cfsetospeed "cfsetospeed") :int
   (termios :pointer) 			; struct termios *
-  (speed   termios-speed))
+  (speed   baud-rate))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defsyscall (%tcdrain "tcdrain") :int
   (fd :int))
@@ -41,6 +42,6 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defsyscall (%tcsetattr "tcsetattr") (:int :restart t :handle fd)
   (fd             :int)
-  (optional-ation :int)
+  (optional-ation tcssetattr-action)
   (termios        :pointer))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/pkgdcl.lisp b/pkgdcl.lisp
index 55131ed..2e6a107 100644
--- a/pkgdcl.lisp
+++ b/pkgdcl.lisp
@@ -9,119 +9,13 @@
   (:export
    ;; Struct termios:
    #:termios
-   ;; cflags:
-   #:cbaud
-   #:exta
-   #:extb
-   #:csize
-   #:cs5
-   #:cs6
-   #:cs7
-   #:cs8
-   #:cstopb
-   #:cread
-   #:parenb
-   #:parodd
-   #:hupcl
-   #:clocal
-   #:loblk
-   #:crtscts
-   ;; baud rates:
-   #:b0
-   #:b50
-   #:b75
-   #:b110
-   #:b134
-   #:b150
-   #:b200
-   #:b300
-   #:b600
-   #:b1200
-   #:b1800
-   #:b2400
-   #:b4800
-   #:b9600
-   #:b19200
-   #:b38400
-   #:b57600
-   #:b76800
-   #:b115200
-   ;; tcsetattr actions:
-   #:tcsanow
-   #:tcsadrain
-   #:tcsaflush
-   ;; lflags:
-   #:isig
-   #:icanon
-   #:xcase
-   #:echo
-   #:echoe
-   #:echok
-   #:echonl
-   #:noflsh
-   #:iexten
-   #:echoctl
-   #:echoprt
-   #:echoke
-   #:flusho
-   #:pendin
-   #:tostop
-   ;; iflags:
-   #:inpck
-   #:ignpar
-   #:parmrk
-   #:istrip
-   #:ixon
-   #:ixoff
-   #:ixany
-   #:ignbrk
-   #:brkint
-   #:inlcr
-   #:igncr
-   #:icrnl
-   #:iuclc
-   #:imaxbel
-   ;; oflags:
-   #:opost
-   #:olcuc
-   #:onlcr
-   #:ocrnl
-   #:nocr
-   #:onlret
-   #:ofill
-   #:ofdel
-   #:nldly
-   #:nl0
-   #:nl1
-   #:crdly
-   #:cr0
-   #:cr1
-   #:cr2
-   #:cr3
-   #:tabdly
-   #:tab0
-   #:tab1
-   #:tab2
-   #:tab3
-   #:bsdly
-   #:bs0
-   #:bs1
-   #:vtdly
-   #:vt0
-   #:vt1
-   #:ffdly
-   #:ff0
-   #:ff1
-   ;; control characters:
-   #:vintr
-   #:vquit
-   #:verase
-   #:vkill
-   #:veof
-   #:veol
-   #:veol2
-   #:vmin
-   #:vtime
+   ;; and settings constantenums
+   #:iflag
+   #:oflag
+   #:cflag
+   #:lflag
+   #:control-character
+   #:baud-rate
    ;; termios.h (0p) functions:
    #:%cfgetispeed
    #:%cfgetospeed
@@ -144,17 +38,12 @@
    ;; coditions:
    #:termios-error
    #:termios-set-failled
-   #:termios-speed-failled
-   ;; additional stty options:
-   #:raw
-   #:cooked
-   #:oddp
-   #:parity
-   #:really-raw
+   #:termios-set-flag-failled
+   #:termios-set-control-character-failled
+   #:termios-set-baud-rate-failled
+   ;; serila stream manipulation
    #:open-serial-stream
    #:with-serial-stream
-   ;; List of all open serial streams. Could be used in signal handlers.
-   #:*open-serial-streams*
-   ;; Known baud rates constants list
-   #:*baud-rates*))			; </ defpackage >
+   ;; List of all open serial streams. Can be used in signal handlers.
+   #:*open-serial-streams*))            ;</ defpackage>
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/streams.lisp b/streams.lisp
index b5d6191..d385dd0 100644
--- a/streams.lisp
+++ b/streams.lisp
@@ -20,7 +20,7 @@
   "List of all open serial streams for restoring original serial devices
    settings via signal handlers.")
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun open-serial-stream (path &key (flag (logior o-rdwr o-nonblock))
+(defun open-serial-stream (path &key (flag (logior o-rdwr o-nonblock o-noctty))
                         (mode *default-open-mode*)
 			(external-format :default))
   "Return `dual-channel-tty-gray-stream' instances associated
@@ -42,7 +42,7 @@
 (defmethod close :around ((stream dual-channel-tty-gray-stream) &key abort)
   (declare (ignorable abort))
   (when (fd-of stream)
-    (%tcsetattr (fd-of stream) tcsanow (original-settings stream))
+    (%tcsetattr (fd-of stream) :tcsanow (original-settings stream))
     (foreign-free (original-settings stream))
     (setf (slot-value stream 'original-settings) nil)
     (removef *open-serial-streams* stream))
@@ -66,13 +66,13 @@
     (stream-finish-output stream)))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defmacro with-serial-stream ((stream path
-                                      &key (speed 115200)
+                                      &key (speed :b115200)
                                       (parity :n)
                                       (byte-size 8)
                                       ;; not an posix option
                                       #+(or bsd linux)hardware-flow-control
                                       software-flow-control
-                                      (flag (logior o-rdwr o-nonblock))
+                                      (flag (logior o-rdwr o-nonblock o-noctty))
                                       (mode *default-open-mode*)
                                       (external-format :default)
                                       timeout read-timeout write-timeout)
@@ -90,8 +90,8 @@
      (disable by default). Note, what hardware flow control (crtscts) is not an
      posix feature, so it can be not implemented on some platforms.

-     I.e. 9600-8n1 mode will be `:speed 9600 :parity :n :byte-size 8',
-     and 300-5e1 `:speed 300 :parity :e :byte-size 5'. 115200-8n1 is default.
+     I.e. 9600-8n1 mode will be `:speed :b9600 :parity :n :byte-size 8`,
+     and 300-5e1 `:speed :b300 :parity :e :byte-size 5`. 115200-8n1 is default.

    Other &key parameters is:
    - flag & mode: passed to `isys:%sys-open',
@@ -102,7 +102,7 @@

    Example (if rx of /dev/ttyUSB0 connected with rx should return T):
    (with-serial-stream (tty \"/dev/ttyUSB0\"
-                            :speed 57600
+                            :speed :b57600
                             :parity :n)
      (let* ((out \"hello\")
             (ln (length out))
@@ -121,29 +121,27 @@
            ;; speed first
            ,speed
            ;; do not block on reading
-           'raw '(vtime 0) '(vmin 0)
+           :raw t :vtime 0 :vmin 0
            ;; allways reset csize before set byte size
-           'csize
+           :csize nil
            ;; parity
            ,@(case parity
-                   (:n `('parenb 'cstopb))
-                   (:e `('(parenb t) 'parodd 'cstopb))
-                                 (:o `('(parenb t) '(parodd t) 'cstopb))
-                                 (:s `('parenb 'parodd 'cstopb))
-                                 (t
-                                  (error
-                                   "Unsupported parity checking mode ~a"
-                                   parity)))
+                   (:n '(:parenb nil :cstopb nil))
+                   (:e '(:parenb t :parodd nil :cstopb nil))
+                   (:o '(:parenb t :parodd t :cstopb nil))
+                   (:s '(:parenb nil :parodd nil :cstopb nil))
+                   (t
+                    (error "Unknown parity checking mode ~a" parity)))
            ;; byte size
            ,@(case byte-size
-                   (5 `('(cs5 t)))
-                   (6 `('(cs6 t)))
-                   (7 `('(cs7 t)))
-                   (8 `('(cs8 t)))
+                   (5 '(:cs5 t))
+                   (6 '(:cs6 t))
+                   (7 '(:cs7 t))
+                   (8 '(:cs8 t))
                    (t (error "Byte size ~a is unsupported" byte-size)))
            ;; hardware flow control
-           #+(or bsd linux),@(when hardware-flow-control `('(crtscts t)))
-           ,@(when software-flow-control `('(ixon t) '(ixoff t))))
+           #+(or bsd linux),@(when hardware-flow-control '(:crtscts t))
+           ,@(when software-flow-control '(:ixon t :ixoff t)))
      ,(when timeout
             `(setf (read-timeout ,stream) ,timeout)
             `(setf (read-timeout ,stream) ,timeout))
diff --git a/wrapers.lisp b/wrapers.lisp
index f0ca7f1..68cc40a 100644
--- a/wrapers.lisp
+++ b/wrapers.lisp
@@ -3,148 +3,118 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (in-package :iolib.termios)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Sort flags by termios fileds:
-;; (as described in ,,Posix serial programming manual``)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; don't using defconstant case sbcl singnal constant redefining error
-;; with and w/o eval-when case results are not eql
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(eval-when (:compile-toplevel :load-toplevel)
-  (defparameter *cflags* '(cbaud cbaudex csize cs5 cs6 cs7 cs8 cstopb cread
-                           parenb parodd hupcl clocal loblk cibaud cmspar
-                           crtscts)
-    "Termios cflag filed constant")
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  (defparameter *baud-rates* '(b0 b50 b75 b110 b134 b150 b200 b300 b600 b1200
-                               b1800 b2400 b4800 b9600 b19200 b38400 b57600
-                               b115200 b230400 b460800 b500000 b576000 b921600
-                               b1000000 b1152000 b1500000 b2000000 b2500000
-                               b3000000 b3500000 b4000000)
-    "Baud rates constants")
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  (defparameter *tcssetattr-actions* '(tcsanow tcsadrain tcsaflush)
-    "Valid constants for tcsetattr action parameter")
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  (defparameter *lflags* '(isig icanon xcase echo echoe echok echonl echoctl
-                           echoprt echoke defecho flusho noflsh tostop pendin
-                           iexten)
-    "Termios lflag filed constants")
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  (defparameter *iflags* '(ignbrk brkint ignpar parmrk inpck istrip inlcr igncr
-                           icrnl iuclc ixon ixany ixoff imaxbel iutf8)
-    "Termios iflag filed constants")
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  (defparameter *oflags* '(opost olcuc onlcr ocrnl onocr onlret ofill ofdel
-                           nldly crdly tabdly bsdly vtdly ffdly)
-    "Termios oflag filed constants")
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  (defparameter *control-characters* '(vintr vquit verase vkill veof vmin veol
-                                       vtime veol2 vswtch vstart vstop vsusp
-                                       vdsusp vlnext vwerase vreprint vdiscard
-                                       vstatus)
-    "Termios control character constants for termios cc field")
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  (defparameter *termios-options* (make-hash-table :test #'eql)
-    "Hash table of all valid termios options.
-     Each entry is dot pair in (<option value> . <option designation>) form,
-     i.e. (2 . lflag) etc.")
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  (defmacro define-termios-option (option filed)
-    "Fill `*termios-options*' hash-table with valid termios options values."
-    `(when (boundp ,option)
-       (setf (gethash ,option *termios-options*)
-             (cons (symbol-value ,option) ',filed))))
-  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-  ;; Filling *termios-options*
-  (mapcar #'(lambda (x) (define-termios-option x iflag)) *iflags*)
-  (mapcar #'(lambda (x) (define-termios-option x oflag)) *oflags*)
-  (mapcar #'(lambda (x) (define-termios-option x lflag)) *lflags*)
-  (mapcar #'(lambda (x) (define-termios-option x cflag)) *cflags*)
-  (mapcar #'(lambda (x) (define-termios-option x control-chars))
-          *control-characters*)
-  (mapcar #'(lambda (x) (define-termios-option x baud-rates))
-          *baud-rates*))                ;</ (eval-when
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; </ Termios flags by fields >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; < Termios options manipulation routines >
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun set-termios-option (termios flag-or-control-character &optional value)
-  "Setup termios flag or control character. If `flag-or-control-character'
-   is one of the termios flags (i.e. icanon) and `value' is not specified
-   then flag in corresponding termios field is reseted, otherwise seted.
-   If  `flag-or-control-character' is control character corresponding
-   value in termios cc field is seted to the `value' parameter.
-
-   Reset icanon flag: (set-termios-option term 'icanon)
-   Set   icanon flag: (set-termios-option term 'icanon t)
-   Set vtime value to 0: (set-termios-option 'vtime 0)
+;; <Termios options manipulation routines>
+(defmacro membercase (form &rest clauses)
+  "(membercase 'a
+	    ('(b c e) 1)
+	    ('(e d b) 2)
+	    ('(a b c) 3))
+    ==> 3
   "
-  (let ((flag-value (gethash flag-or-control-character *termios-options*)))
-    (cond
-      ;; on of the {c,l,i,o}flag fields options:
-      ((member (cdr flag-value) '(iflag oflag cflag lflag) :test #'eql)
-       (setf (foreign-slot-value termios 'termios (cdr flag-value))
-             ;; value specified => set (logior), reset over otherwise
-             (funcall (if value #'logior #'logandc2)
-                      (foreign-slot-value termios 'termios (cdr flag-value))
-                      (car flag-value))))
-      ;; control characters
-      ((eql (cdr flag-value) 'control-chars)
-       (setf (mem-aref (foreign-slot-pointer termios
-                                             'termios
-                                             'control-chars)
+  `(cond ,@(mapcar #'(lambda (x)
+                       (let ((lst (first x))
+                             (body (rest x)))
+                         `((member ,form ,lst) ,@body)))
+                   clauses)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defmacro enumcase (form &rest clauses)
+  "(enumcase :b115200
+		   (baud-rates 1)
+		   (iflags 2)
+   		   (cflags 3))
+   ==> 1
+  "
+  `(membercase ,form ,@(mapcar #'(lambda (x)
+                                   (let ((enum (first x))
+                                         (body (rest x)))
+                                     `((foreign-enum-keyword-list ',enum)
+                                       ,@body)))
+                               clauses)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun which-termios-keyword (keyword)
+  (enumcase keyword
+   (iflag 'iflag)
+   (oflag 'oflag)
+   (lflag 'lflag)
+   (cflag 'cflag)
+   (control-character 'control-character)
+   (baud-rate 'baud-rate)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun termios-flag-p (keyword)
+  (member (which-termios-keyword keyword) '(iflag oflag cflag lflag)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun termios-control-character-p (keyword)
+  (eql 'control-character (which-termios-keyword keyword)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun termios-baud-rate-p (keyword)
+  (eql 'baud-rate (which-termios-keyword keyword)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun setup-termios-flag (termios flag &optional setp)
+  "Reset `flag' in corresponding `termios' field, or set in, if `setp' is true."
+  (let ((type (which-termios-keyword flag)))
+    (unless type
+      (error "Unknown termios option ~a" flag))
+    (setf (foreign-slot-value termios 'termios type)
+            ;; value specified => set (logior), reset over otherwise
+            (funcall (if setp #'logior #'logandc2)
+                     (foreign-slot-value termios 'termios type)
+                     (foreign-enum-value type flag)))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun setup-termios-control-character (termios cc value)
+  "Setup corresponding control character value.
+   Value can be `control-character' keyword or integer."
+  (setf (mem-aref (foreign-slot-pointer termios
+                                        'termios
+                                        'control-chars)
                        'cc
-                       (car flag-value)) ;constant name is offset
-             value))
-      ;; baud-rates
-      ((eql (cdr flag-value) 'baud-rates)
-       (%cfsetispeed termios (car flag-value))
-       (%cfsetospeed termios (car flag-value)))
-      (t (error "Unknown termios option ~a" flag-or-control-character)))
-    termios))
+                       ;; constant name is offset
+                       (foreign-enum-value 'control-character cc))
+        (if (integerp value)
+            value
+            (foreign-enum-value 'control-character value))))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun make-raw-termios (termios)
   "Same effect as cfmakeraw()"
-  (dolist (flag '(ignbrk brkint parmrk istrip inlcr igncr icrnl ixon ;iflag
-		  opost						     ;oflag
-		  echo echonl icanon isig iexten		     ;lflag
-		  csize parenb))				     ;cflag
-    (set-termios-option termios flag))
-  (set-termios-option termios 'cs8 t))
+  (dolist (flag
+            '(:ignbrk :brkint :parmrk :istrip :inlcr :igncr :icrnl :ixon ;iflag
+              :opost						         ;oflag
+              :echo :echonl :icanon :isig :iexten		         ;lflag
+              :csize :parenb))				                 ;cflag
+    (setup-termios-flag termios flag))
+  (setup-termios-flag termios :cs8 t))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun make-cooked-termios (termios)
   "Effect is opposite to `make-raw-termios'"
-  (dolist (flag '(ignbrk brkint parmrk istrip inlcr igncr icrnl ixon ;iflag
-		  opost						     ;oflag
-		  echo echonl icanon isig iexten		     ;lflag
-		  csize parenb))				     ;cflag
-    (set-termios-option termios flag t))
+  (dolist (flag
+            '(:ignbrk :brkint :parmrk :istrip :inlcr :igncr :icrnl :ixon ;iflag
+              :opost						         ;oflag
+              :echo :echonl :icanon :isig :iexten	                 ;lflag
+              :csize :parenb))				                 ;cflag
+    (setup-termios-flag termios flag t))
   #|(set-termios-option termios 'cs8 t)|#)
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun make-evenp-termios (termios)
   "Enable parenb and cs7; disable parodd"
-  (set-termios-option termios 'parenb t)
-  (set-termios-option termios 'parodd)
-  (set-termios-option termios 'cstopb)
-  (set-termios-option termios 'csize)
-  (set-termios-option termios 'cs7 t))
+  (setup-termios-flag termios :parenb t)
+  (setup-termios-flag termios :parodd)
+  (setup-termios-flag termios :cstopb)
+  (setup-termios-flag termios :csize)
+  (setup-termios-flag termios :cs7 t))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun make-oddp-termios (termios)
   "Enable parenb, cs7, and parodd"
-  (set-termios-option termios 'parenb t)
-  (set-termios-option termios 'parodd t)
-  (set-termios-option termios 'cstopb)
-  (set-termios-option termios 'csize)
-  (set-termios-option termios 'cs7 t))
+  (setup-termios-flag termios :parenb t)
+  (setup-termios-flag termios :parodd t)
+  (setup-termios-flag termios :cstopb)
+  (setup-termios-flag termios :csize)
+  (setup-termios-flag termios :cs7 t))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun make-8n1-termios (termios)
   "Disable parenb, and set cs8."
-  (set-termios-option termios 'parenb)
-  (set-termios-option termios 'cstopb)
-  (set-termios-option termios 'csize)
-  (set-termios-option termios 'cs8 t))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  (setup-termios-flag termios :parenb)
+  (setup-termios-flag termios :cstopb)
+  (setup-termios-flag termios :csize)
+  (setup-termios-flag termios :cs8 t))
 ;; </ Termios options manipulation routines >
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; I guess that bits manipulation stuff is not a lisp way,
@@ -152,99 +122,106 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun stty (serial &rest options)
   "Impliment stty (1) in lisp way.
-   `serial' can be stream or fd.
-   Each `options' element should be termios option name
-   or list in (option-name option-value) form.
-   '(flag-name t) set corresponding flag,
-   '(flag-name nil) or 'flag-name reset it.
-   'baud-rate-constant set corresponding speed.
-   '(control-character-name control-character-value) setup corresponding
-   control character value.
-   Baud rate can be specified in integer form to.
+   `serial` can be stream or fd.
+   `options` should be list of termios keywords and values:
+   `nil` or `t` for flags or one of `:raw`, `:cooked`, `:evenp` or `:oddp`,
+   integers for control characters.
+
+   `:inlcr t` set corresponding flag,
+   `:inlcr nil` reset it,
+   `:b115200` set corresponding speed,
+   `:vtime 0` setup corresponding control character value.

-   Setup for 8n1 mode: (stty fd '(evenp nil))
-   Setup speed: (stty fd 'b115200) or (stty my-stream 115200)
-   Setup raw mode: (stty fd 'raw)
-   Setup cooked mode: (stty fd '(raw nil) or (stty 'cooked)
+   Setup for 8n1 mode: `(stty fd :evenp nil)`
+   Setup speed: `(stty fd :b115200)` or `(stty my-stream 115200)`
+   Setup raw mode and speed: `(stty fd :b115200 :raw t)`
+   Setup cooked mode: `(stty fd :raw nil)`
   "
-  (labels ((process-option (option termios)
-	     (cond
-	       ((or (member option *baud-rates*)
-                    (integerp option))
-                (let* ((sym (if (integerp option)
-                                (find-symbol (format nil "B~a" option)
-                                             :iolib.termios)
-                                option))
-                       (hash (gethash sym *termios-options*)))
-                  (unless (and hash (eql (cdr hash) 'baud-rates))
-                    (error "Unknown baud rate ~a" option))
-		(%cfsetispeed termios (symbol-value sym))
-		(%cfsetospeed termios (symbol-value sym))))
-	       ((member option '(evenp 'parity))
-		(make-evenp-termios termios))
-	       ((eq option 'oddp)
-		(make-oddp-termios termios))
-	       ((and (consp option)
-		     (null (second option))
-		     (member (first option)
-			     '(parity  evenp oddp)))
-		(make-8n1-termios termios))
-	       ((eql option 'raw)
-		(make-raw-termios termios))
-	       ((or (eql option 'cooked)
-		    (and (consp option)
-			 (eql (first option) 'raw)
-			 (null (second option))))
-		(make-cooked-termios termios))
-	       (t (if (atom option)
-		      (set-termios-option termios option)
-		      (set-termios-option termios (first option)
-					  (second option))))))
-           (compare-termios (set test)
-             (and
-              (every #'(lambda (flag)
-                         (=  (foreign-slot-value set  'termios flag)
-                             (foreign-slot-value test 'termios flag)))
-                     '(iflag oflag cflag lflag))
-              (dotimes (i nccs t)
-                (when
-                    (/= (mem-aref (foreign-slot-pointer set
-                                                        'termios
-                                                        'control-chars)
-                                  'cc
-                                  i)
-                        (mem-aref (foreign-slot-pointer test
-                                                        'termios
-                                                        'control-chars)
-                                  'cc
-                                  i))
-                  (return nil))))))
-    (let ((fd (typecase serial
-                (integer serial)
-                (stream (fd-of serial))
-                (t (error "You should specify stream or fd")))))
-    (with-foreign-objects ((set  'termios)
-                           (test 'termios))
-      (%tcgetattr fd set)
+  (labels
       ;; As said in man termios:
-      ;; "tcsetattr() returns success if any of the
-      ;; requested changes could be successfully carried out."
+      ;; >tcsetattr() returns success if any of the
+      ;; >requested changes could be successfully carried out."
       ;; This manual also recomend to use tcgetattr() in oder to check
       ;; all performed settings. But I really dot't like to find back
       ;; that each zero ore one in coresponding field mead. So I prefer
-      ;; to process each option step by step and singnal a condition
+      ;; to process each option step by step and signal a condition
       ;; when there will be a difference:
-      (dolist (option options)
-	(process-option option set)
-        (%tcsetattr fd tcsanow set)
-        (%tcgetattr fd test)
-        (or (compare-termios set test)
-            (if (or (member option *baud-rates*) (integerp option))
-                (error 'termios-speed-failled
-                       :request (if (integerp option)
-                                    option
-                                    (parse-integer (symbol-name option)
-                                                   :start 1)))
+      ((%set-test-termios (fd set test)
+         (%tcsetattr fd :tcsanow set)
+         (%tcgetattr fd test)
+         (and
+          (every #'(lambda (flag)
+                     (=  (foreign-slot-value set  'termios flag)
+                         (foreign-slot-value test 'termios flag)))
+                 '(iflag oflag cflag lflag))
+          (dotimes (i nccs t)
+            (when
+                (/= (mem-aref (foreign-slot-pointer set
+                                                    'termios
+                                                    'control-chars)
+                              'cc
+                              i)
+                    (mem-aref (foreign-slot-pointer test
+                                                    'termios
+                                                    'control-chars)
+                              'cc
+                              i))
+              (return nil)))))
+       (%stty (set test fd options)
+         (let ((opt  (car options))
+               (setp (cadr options))
+               (rst  (cddr options)))
+           (cond
+             ((termios-flag-p opt)
+              (setup-termios-flag set opt setp)
+              (unless (%set-test-termios fd set test)
+                (error 'termios-set-flag-failled :request opt)))
+             ((termios-control-character-p opt)
+              (setup-termios-control-character set opt setp)
+              (unless (%set-test-termios fd set test)
+                (error 'termios-set-control-character-failled :request opt)))
+             ((eql opt :raw)
+              (if setp (make-raw-termios set) (make-cooked-termios set))
+              (unless (%set-test-termios fd set test)
+                (error 'termios-set-failled
+                        :request (if setp :raw :cooked))))
+             ((eql opt :cooked)
+              (if setp (make-cooked-termios set) (make-raw-termios set))
+              (unless (%set-test-termios fd set test)
                 (error 'termios-set-failled
-                       :request option))))))))
+                        :request (if setp :cooked :raw))))
+             ((eql opt :evenp)
+              (if setp (make-evenp-termios set) (make-oddp-termios set))
+              (unless (%set-test-termios fd set test)
+                (error 'termios-set-failled
+                        :request (if setp :evenp :oddp))))
+             ((eql opt :oddp)
+              (if setp (make-oddp-termios set) (make-evenp-termios set))
+              (unless (%set-test-termios fd set test)
+                (error 'termios-set-failled
+                        :request (if setp :oddp :evenp)))))
+           (if rst
+               (%stty set test fd rst)
+               set))))
+    (let ((fd (typecase serial
+                (integer serial)
+                (stream (fd-of serial))
+                (t (error "You should specify stream or fd"))))
+          (opts-w/o-baud (remove-if #'termios-baud-rate-p options))
+          (baud  (find-if #'termios-baud-rate-p options)))
+      (when (and options (oddp (length opts-w/o-baud)))
+        (error "Mailformed stty options list"))
+      (with-foreign-objects ((set  'termios)
+                             (test 'termios))
+        (%tcgetattr fd set)
+        (when baud
+          (%cfsetispeed set baud)
+          (%cfsetospeed set baud)
+          (%tcsetattr fd :tcsanow set)
+          (%tcgetattr fd test)
+          (let ((ispeed (%cfgetispeed test))
+                (ospeed (%cfgetospeed test)))
+            (unless (and (eql baud ispeed) (eql baud ospeed))
+              (error 'termios-set-baud-rate-failled :request baud))))
+        (%stty set test fd opts-w/o-baud)))))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ViewGit