From: William J. Bouma
Subject: Lucid specific stream question
Date: 
Message-ID: <13256@medusa.cs.purdue.edu>
I want to make *standard-output* and *standard-input* into binary
streams.  (stream-element-type *standard-output*) returns 'string-char
as one would expect.  But there is no setf method for stream-element-
type.  Does anyone know how I could make those streams be of type
'(unsigned-byte 8)?
-- 
Bill <·····@cs.purdue.edu>

From: Barry Margolin
Subject: Re: Lucid specific stream question
Date: 
Message-ID: <1991Feb1.062927.2260@Think.COM>
In article <·····@medusa.cs.purdue.edu> ·····@cs.purdue.EDU (William J. Bouma) writes:
>I want to make *standard-output* and *standard-input* into binary
>streams.  (stream-element-type *standard-output*) returns 'string-char
>as one would expect.  

Actually, I would expect it to return STRING-CHAR, not 'STRING-CHAR.

>		       But there is no setf method for stream-element-
>type.  Does anyone know how I could make those streams be of type
>'(unsigned-byte 8)?

You can't do (setf (stream-element-type ...) ...) for the same reason you
can't do (setf (oddp ...) ...).  STREAM-ELEMENT-TYPE and ODDP are simply
inquiries about the object, not accessors.  Binary and character streams
are different types of objects (in systems with object-oriented I/O
systems, such as Symbolics Genera, they really are different types), so
changing the element type would require changing a fundamental aspect of
the object.

Why would you want to do this to the *standard-xxx* streams, anyway?  All
functions that use these streams expect them to carry character data.
Instead, why don't you construct new streams that interface to the standard
streams, but convert between bytes and characters using CHAR-CODE and
CODE-CHAR.  I believe the mechanisms for creating streams that invoke
arbitrary functions are defined in the Advanced User's Guide section of the
Lucid manual.

If you're expecting this to prevent transformation of your I/O (e.g.
converting LF to CR/LF on output, translating CR to LF on input), just
setting the element type isn't enough.  The default bindings of the
*standard-xxx* streams simply forward the data to the Unix stdxx streams.,
and those transformations are done by the Unix tty driver (when stdout and
stdin happen to be terminals), not by Lisp.  Disabling this requires
performing Unix ioctl() system calls.
--
Barry Margolin, Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: William J. Bouma
Subject: Re: Lucid specific stream question
Date: 
Message-ID: <13262@medusa.cs.purdue.edu>
In article <····················@Think.COM> ······@think.com (Barry Margolin) writes:
>Actually, I would expect it to return STRING-CHAR, not 'STRING-CHAR.

  Whatever...

>systems, such as Symbolics Genera, they really are different types), so
>changing the element type would require changing a fundamental aspect of
>the object.

  When I posed the question I thought it would probably be something more
  involved than just the setf.  Are you saying there is no way to do what
  I want?  Maybe this would work:

  (setq *standard-input*
    (make-lisp-stream :input-handle 0 
		      :element-type '(unsigned-byte 8)))

>Why would you want to do this to the *standard-xxx* streams, anyway?  All
>functions that use these streams expect them to carry character data.
>Instead, why don't you construct new streams that interface to the standard
>streams, but convert between bytes and characters using CHAR-CODE and
>CODE-CHAR.  I believe the mechanisms for creating streams that invoke

  I use CODE-CHAR and CHAR-CODE now, but that is ugly since I never want to
  send chars on these streams anyway!  What I do is have a server on a unix
  machine that dup2s the socket over 0 and 1 and then forks a lisp process.
  Thus the lisp process is communicating to the socket through *standard-io*.
  I use the XDR data protocol.  Seems a waste to do the char conversions all
  the time.

  Anyway, it was a pretty stupid question.  Sorry now I asked it!
-- 
Bill <·····@cs.purdue.edu>
From: Barry Margolin
Subject: Re: Lucid specific stream question
Date: 
Message-ID: <1991Feb1.200830.12352@Think.COM>
In article <·····@medusa.cs.purdue.edu> ·····@cs.purdue.EDU (William J. Bouma) writes:
>  When I posed the question I thought it would probably be something more
>  involved than just the setf.  Are you saying there is no way to do what
>  I want?  Maybe this would work:
>
>  (setq *standard-input*
>    (make-lisp-stream :input-handle 0 
>		      :element-type '(unsigned-byte 8)))

That should work, and should do what you want.  However, I suggest that you
do something like:

(setq *binary-input* ...)

rather than setting *standard-input*.  Internal functions in the
implementation may be dependent on being able to do character input from
*standard-input*.  Your XDR software can use *binary-input* and
*binary-output* as its default streams.  Even better would be to use
explicit parameters rather than global variables, if feasible.

>  What I do is have a server on a unix
>  machine that dup2s the socket over 0 and 1 and then forks a lisp process.
>  Thus the lisp process is communicating to the socket through *standard-io*.
>  I use the XDR data protocol.  Seems a waste to do the char conversions all
>  the time.

You are confusing Unix stdin and stdout with Lisp's *STANDARD-INPUT* and
*STANDARD-OUTPUT*.  What you want are Lisp byte streams connected to Unix
stdin and stdout; you don't need to change *STANDARD-INPUT* and
*STANDARD-OUTPUT* to do this.  You've admitted that portability to other
Common Lisp implementations isn't an overriding concern (and if it were, it
would be easy to push the above into a file containing
implementation-dependent pieces with lots of #+); the most portable scheme
is to call CHAR-CODE and CODE-CHAR alot (this isn't even completely
portable, because CODE-CHAR is not required to work for all codes).

However, one possible relationship between *BINARY-xxx* and *STANDARD-xxx*
that you might want to guarantee is that they communicate with the same
Unix fd's.  I.e. if your XDR software is used after someone has done

(setq *standard-input* (make-lisp-stream :input-handle 5
					 :element-type 'string-char))

then *BINARY-INPUT* should also read from file descriptor 5.  In that case,
you can do:

(defun binary-stream-like (stream direction)
  (make-lisp-stream (case direction
		      (:input :input-handle)
		      (:output :output-handle))
		    (extract-stream-handle stream direction)
		    :element-type '(unsigned-byte)))

(setq *binary-input* (binary-stream-like *standard-input* :input))
(setq *binary-output* (binary-stream-like *standard-output* :output))

By the way, I just learned the hard way that you shouldn't call CLOSE on
these binary streams.  Apparently, closing a stream created with
MAKE-LISP-STREAM closes the associated Unix fd, even if Lisp has other
streams with the same handle.  Closing stdin and then returning to the
read-eval-print loop (or doing anything that uses *STANDARD-INPUT*) is an
easy way to get into a recursive error loop.
--
Barry Margolin, Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar