[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Issue: STANDARD-OUTPUT-INITIAL-BINDING (version 5)



Issue:         STANDARD-INPUT-INITIAL-BINDING
References:    Standard streams (pp. 327-329)
Category:      CHANGE
Edit history:  Version 1 by Pierson and Haflich 1/19/87
    	       Version 2 by Pierson 2/29/88
	       Version 3 by Pierson 5/23/88, per comments by Moon
               Version 4 by Pierson 5/26/88, clean up
    	       Version 5 by Pierson 6/28/88, simple design per Masinter
Status:        For Internal Discussion

Problem description:

CLtL requires that *STANDARD-INPUT*, *STANDARD-OUTPUT*,
*ERROR-OUTPUT*, *TRACE-OUTPUT*, *QUERY-IO*, and *DEBUG-IO* are
initially bound to synonym streams to *TERMINAL-IO*.  This requirement
hampers the integration of Common Lisp with many existing and
potential operating environments.

For example, a Unix implementation is currently unable to legally
support Unix standard error output even though Common Lisp defines
*ERROR-OUTPUT* because *ERROR-OUTPUT* is required to start out bound
to the same stream as *STANDARD-OUTPUT*.  A workstation environnment
which provides stream access to windows as an extension is currently
forbidden to make trace output appear in a separate window by default
because *TRACE-OUTPUT* is required to start out bound to the same
stream as *STANDARD-OUTPUT*.

Proposal (STANDARD-INPUT-INITIAL-BINDING:CONTRACTS-AND-FUNCTIONS):

A Common Lisp implementation is required to provide the following
initial streams.  Each initial stream has a specific purpose as defined
in CLtL.

    *TERMINAL-IO*
    	Is always bound to a writable two-way stream.  It is legal for
	input from *TERMINAL-IO* to always return EOF.

    *STANDARD-INPUT*
    *STANDARD-OUTPUT*
    *ERROR-OUTPUT*
    *TRACE-OUTPUT*
    *QUERY-IO*
    *DEBUG-IO*
    	The initial bindings of these streams are undefined except
	that none of these streams may be synonym-streams for another
	one of these streams.  Any or all of these streams may be
	synonym streams for *TERMINAL-IO*.  Any or all of these
	streams may be synonyms for the same implementation-sepcific
	stream. 

Add the following inquiry functions to Common Lisp:

    STREAM-SAME-DESTINATION-P stream1 stream2	    	    [Function]

      Returns T if the Lisp can prove that the two streams send their
      output to the same "destination".  For example, this function
      would return true for two streams that output to Unix files iff
      the streams resulted either in output to the same file
      descriptor or in output to two different file descriptors for
      the same inode.

    STREAM-SAME-SOURCE-P stream1 stream2    	    	    [Function]

      Returns T if the Lisp can prove that the two streams receive
      their input from the same "source", where same source mans that
      input on one stream will change what the other stream would next
      read.  For example, this function would return true for two
      streams that read from Unix files iff the streams resulted in
      input from the same file descriptor but not if the streams
      resulted in in input from two different file descriptors for the
      same inode because then reading one stream would not change what
      the other stream saw.

    STREAM-INTERACTIVE-P stream	    	    	    	    [Function]

      Returns T if the Lisp can prove that the stream is interactive,
      where interactive means that the stream is a two way stream
      connected in such a way that output can result in a change in
      succeeding input.

Test Cases/Examples:

(PROGN
   (PRINT "Output" *STANDARD-OUTPUT*)
   (PRINT "Error" *STANDARD-ERROR*))

In current Common Lisp will write:
------
Output
Error
------

With proposal *might* write:
------
Output
------
and "Error" appears somewhere else.

(LET* ((IN1 (OPEN "foo" :DIRECTION :INPUT))
       (IN2 (OPEN "foo" :DIRECTION :INPUT))
       (OUT1 (OPEN "foo" :DIRECTION :OUTPUT))
       (OUT2 (OPEN "foo" :DIRECTION :OUTPUT))
       (STREAM1 (MAKE-TWO-WAY-STREAM IN1 OUT1))
       (STREAM2 (MAKE-TWO-WAY-STREAM IN2 OUT2)))
  (LIST (STREAM-SAME-DESTINATION-P STREAM1 OUT1)
        (STREAM-SAME-DESTINATION-P STREAM1 STREAM2)
	(STREAM-SAME-SOURCE-P STREAM1 IN1)
	(STREAM-SAME-SOURCE-P STREAM1 STREAM2)
	(STREAM-INTERACTIVE-P STREAM1)
	(STREAM-INTERACTIVE-P *TERMINAL-IO*)))

==> (T T T NIL NIL ?) ; *TERMINAL-IO* might or might not be interactive

Rationale:

This proposal attempts to provide a balance between over-specifying
behavior to the point that Lisp programs can't behave like other
programs in conventional operating systems and providing enough
specification that Common Lisp programs can perform portable input and
output.  The inquiry functions answer questions that portable Lisp
programs can't answer on their own because the information is
frequently only maintained at an operating system level.

Current practice:

Lucid binds *TERMINAL-IO* to a special internal stream type.  Franz
binds *TERMINAL-IO* to a special internal stream type for terminal
streams which reads from Unix standard input and writes to Unix
standard output.  KCL binds *TERMINAL-IO* to a standard two-way-stream
with input from Unix standard input and output to Unix standard
output.

Cost to Implementors:

All implementations will have to change to some degree but the changes
will probably be simple and localized.  All known implementations
already support the underlying streams required to implement this
proposal.  The new inquiry functions will require some work to write
correctly for each environment.

Cost to Users:

User code which depends on the strict binding hierarchy in CLtL may
have to change.  

Cost of non-Adoption:

It will continue to be difficult or impossible to integrate portable
Common Lisp progams in conventional operating system environments.
Many implementations will have to continue to choose between
conforming to the standard and providing a superior user environment.

Benefits:

Implementations will be more able to match their IO behavior to their
environment and their user's expectations.  Portable programs will
have more tools for reasoning about stream relationships.

Aesthetics:

Improved because this area becomes better defined.

Discussion:

Pitman was concerned that the initial version of this proposal didn't
provide a guaranteed way to get back the initial streams after
rebinding, e.g. *standard-io*.  The second version of this proposal
offered a solution to that problem which was generally considered too
complex.  This problem should now be solved.

Moon says that *TERMINAL-IO* (and, by extension, *QUERY-IO*, and
*DEBUG-IO*) should fail to work in a non-interactive environment where
nothing like a terminal exists.

Masinter notes that:
    ``In many multi-processing multi-window environments,
      the "initial binding" for *STANDARD-INPUT*, *QUERY-INPUT*
      differs for each process.''  

Masinter doesn't believe that STREAM-SAME-SOURCE-P is needed; Pierson
disagrees.

The definition of STREAM-INTERACTIVE-P is intentionally vague because
it is not reasonable for the Lisp to try and distinguish between, say,
a terminal connection to a human and a pseudo terminal connection to
another program.

Pierson supports STANDARD-OUTPUT-INITIAL-BINDING:CONTRACTS-AND-FUNCTIONS.