   This file documents the MIT Scheme system.

   Copyright (C) 1988-2002 Massachusetts Institute of Technology

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts.  A copy of the license is included in the section entitled "GNU
Free Documentation License".

Environment Operations
======================

   Environments are first-class objects in MIT Scheme.  An environment
consists of some bindings and possibly a parent environment, from which
other bindings are inherited.  The operations in this section reveal the
frame-like structure of environments by permitting you to examine the
bindings of a particular environment separately from those of its
parent.

   There are several types of bindings that can occur in an environment.
The most common is the simple variable binding, which associates a value
(any Scheme object) with an identifier (a symbol).  A variable binding
can also be "unassigned", which means that it has no value.  An
unassigned variable is bound, in that is will shadow other bindings of
the same name in ancestor environments, but a reference to that variable
will signal an error of type `condition-type:unassigned-variable'.  An
unassigned variable can be "assigned" (using `set!' or
`environment-assign!') to give it a value.

   In addition to variable bindings, an environment can also have
"keyword bindings".  A keyword binding associates a syntactic keyword
(usually a macro transformer) with an identifier.  Keyword bindings are
special in that they are considered "bound", but ordinary variable
references don't work on them.  So an attempt to reference or assign a
keyword binding results in an error of type
`condition-type:macro-binding'.  However, keyword bindings can be
redefined using `define' or `environment-define'.

 - procedure: environment? object
     Returns `#t' if OBJECT is an environment; otherwise returns `#f'.

 - procedure: environment-has-parent? environment
     Returns `#t' if ENVIRONMENT has a parent environment; otherwise
     returns `#f'.

 - procedure: environment-parent environment
     Returns the parent environment of ENVIRONMENT.  It is an error if
     ENVIRONMENT has no parent.

 - procedure: environment-bound-names environment
     Returns a newly allocated list of the names (symbols) that are
     bound by ENVIRONMENT.  This does not include the names that are
     bound by the parent environment of ENVIRONMENT.  It does include
     names that are unassigned or keywords in ENVIRONMENT.

 - procedure: environment-macro-names environment
     Returns a newly allocated list of the names (symbols) that are
     bound to syntactic keywords in ENVIRONMENT.

 - procedure: environment-bindings environment
     Returns a newly allocated list of the bindings of ENVIRONMENT;
     does not include the bindings of the parent environment.  Each
     element of this list takes one of two forms: `(SYMBOL)' indicates
     that SYMBOL is bound but unassigned, while `(SYMBOL OBJECT)'
     indicates that SYMBOL is bound, and its value is OBJECT.

 - procedure: environment-reference-type environment symbol
     Returns a symbol describing the "reference type" of SYMBOL in
     ENVIRONMENT or one of its ancestor environments.  The result is
     one of the following:

    `normal'
          means SYMBOL is a variable binding with a normal value.

    `unassigned'
          means SYMBOL is a variable binding with no value.

    `macro'
          means SYMBOL is a keyword binding.

    `unbound'
          means SYMBOL has no associated binding.

 - procedure: environment-bound? environment symbol
     Returns `#t' if SYMBOL is bound in ENVIRONMENT or one of its
     ancestor environments; otherwise returns `#f'.  This is equivalent
     to

          (not (eq? 'unbound
                    (environment-reference-type ENVIRONMENT SYMBOL)))

 - procedure: environment-assigned? environment symbol
     Returns `#t' if SYMBOL is bound in ENVIRONMENT or one of its
     ancestor environments, and has a normal value.  Returns `#f' if it
     is bound but unassigned.  Signals an error if it is unbound or is
     bound to a keyword.

 - procedure: environment-lookup environment symbol
     SYMBOL must be bound to a normal value in ENVIRONMENT or one of
     its ancestor environments.  Returns the value to which it is bound.
     Signals an error if unbound, unassigned, or a keyword.

 - procedure: environment-lookup-macro environment symbol
     If SYMBOL is a keyword binding in ENVIRONMENT or one of its
     ancestor environments, returns the value of the binding.
     Otherwise, returns `#f'.  Does not signal any errors other than
     argument-type errors.

 - procedure: environment-assignable? environment symbol
     SYMBOL must be bound in ENVIRONMENT or one of its ancestor
     environments.  Returns `#t' if the binding may be modified by side
     effect.

 - procedure: environment-assign! environment symbol object
     SYMBOL must be bound in ENVIRONMENT or one of its ancestor
     environments, and must be assignable.  Modifies the binding to have
     OBJECT as its value, and returns an unspecified result.

 - procedure: environment-definable? environment symbol
     Returns `#t' if SYMBOL is definable in ENVIRONMENT, and `#f'
     otherwise.  At present, this is false for environments generated
     by application of compiled procedures, and true for all other
     environments.

 - procedure: environment-define environment symbol object
     Defines SYMBOL to be bound to OBJECT in ENVIRONMENT, and returns
     an unspecified value.  Signals an error if SYMBOL isn't definable
     in ENVIRONMENT.

 - procedure: environment-define-macro environment symbol transformer
     Defines SYMBOL to be a keyword bound to TRANSFORMER in
     ENVIRONMENT, and returns an unspecified value.  Signals an error
     if SYMBOL isn't definable in ENVIRONMENT.  The type of TRANSFORMER
     is defined by the syntax engine and is not checked by this
     procedure.  If the type is incorrect this will subsequently signal
     an error during syntax expansion.

 - procedure: eval expression environment
     Evaluates EXPRESSION, a list-structure representation (sometimes
     called s-expression representation) of a Scheme expression, in
     ENVIRONMENT.  You rarely need `eval' in ordinary programs; it is
     useful mostly for evaluating expressions that have been created "on
     the fly" by a program.  `eval' is relatively expensive because it
     must convert EXPRESSION to an internal form before it is executed.

          (define foo (list '+ 1 2))
          (eval foo (the-environment))            =>  3

Environment Variables
=====================

   The `user-initial-environment' is where the top-level
read-eval-print (REP) loop evaluates expressions and binds definitions.
It is a child of `system-global-environment', which is where all of
the Scheme system definitions are bound.  All of the bindings in
`system-global-environment' are available when the current environment
is `user-initial-environment'.  However, any new bindings that you
create in the REP loop (with `define' forms or by loading files
containing `define' forms) occur in `user-initial-environment'.

 - variable: system-global-environment
     The variable `system-global-environment' is bound to the
     distinguished environment that's the ancestor of most other
     environments (except for those created by
     `make-root-top-level-environment').  It is the parent environment
     of `user-initial-environment'.  Primitives, system procedures, and
     most syntactic keywords are bound (and sometimes closed) in this
     environment.

 - variable: user-initial-environment
     The variable `user-initial-environment' is bound to the default
     environment in which typed expressions are evaluated by the
     top-level REP loop.

     Although all bindings in `system-global-environment' are visible to
     the REP loop, definitions that are typed at, or loaded by, the REP
     loop occur in the `user-initial-environment'.  This is partly a
     safety measure: if you enter a definition that happens to have the
     same name as a critical system procedure, your definition will be
     visible only to the procedures you define in the
     `user-initial-environment'; the MIT Scheme system procedures, which
     are defined in `system-global-environment', will continue to see
     the original definition.

REPL Environment
================

 - procedure: nearest-repl/environment
     Returns the current REP loop environment (i.e. the current
     environment of the closest enclosing REP loop).  When Scheme first
     starts up, this is the same as `user-initial-environment'.

 - procedure: ge environment
     Changes the current REP loop environment to ENVIRONMENT.
     ENVIRONMENT can be either an environment or a procedure object.
     If it's a procedure, the environment in which that procedure was
     closed is the new environment.

Top-level Environments
======================

   The operations in this section manipulate "top-level environments",
as opposed to environments created by the application of procedures.
For historical reasons, top-level environments are referred to as
"interpreter environments".

 - special form: the-environment
     Returns the current environment.  This form may only be evaluated
     in a top-level environment.  An error is signalled if it appears
     elsewhere.

 - procedure: top-level-environment? object
 - procedure: interpreter-environment? object
     Returns `#t' if OBJECT is an top-level environment; otherwise
     returns `#f'.

     `interpreter-environment?' is an alias for
     `top-level-environment?'.

 - procedure: extend-top-level-environment environment [names [values]]
 - procedure: make-root-top-level-environment [names [values]]
     Returns a newly allocated top-level environment.
     `extend-top-level-environment' creates an environment that has
     parent ENVIRONMENT, while `make-root-top-level-environment'
     creates an environment that has no parent.

     The optional arguments NAMES and VALUES are used to specify
     initial bindings in the new environment.  If specified, NAMES must
     be a list of symbols, and VALUES must be a list of objects.  If
     only NAMES is specified, each name in NAMES will be bound in the
     environment, but unassigned.  If NAMES and VALUES are both
     specified, they must be the same length, and each name in NAMES
     will be bound to the corresponding value in VALUES.  If neither
     NAMES nor VALUES is specified, the environment will have no
     initial bindings.

 - procedure: link-variables environment1 symbol1 environment2 symbol2
     Defines SYMBOL1 in ENVIRONMENT1 to have the same binding as
     SYMBOL2 in ENVIRONMENT2, and returns an unspecified value.  Prior
     to the call, SYMBOL2 must be bound in ENVIRONMENT2, but the type
     of binding is irrelevant; it may be a normal binding, an
     unassigned binding, or a keyword binding.  Signals an error if
     SYMBOL1 isn't definable in ENVIRONMENT1, or if SYMBOL2 is unbound
     in ENVIRONMENT2.

     By "the same binding", we mean that the value cell is shared
     between the two environments.  If a value is assigned to SYMBOL1 in
     ENVIRONMENT1, a subsequent reference to SYMBOL2 in ENVIRONMENT2
     will see that value, and vice versa.

 - procedure: unbind-variable environment symbol
     If SYMBOL is bound in ENVIRONMENT or one of its ancestor
     environments, removes the binding, so that subsequent accesses to
     that symbol behave as if the binding never existed.  Returns `#t'
     if there was a binding prior to the call, and `#f' if there wasn't.

Input/Output
************

   This chapter describes the procedures that are used for input and
output (I/O).  The chapter first describes "ports" and how they are
manipulated, then describes the I/O operations.  Finally, some
low-level procedures are described that permit the implementation of
custom ports and high-performance I/O.

Ports
=====

   Scheme uses ports for I/O.  A "port", which can be treated like any
other Scheme object, serves as a source or sink for data.  A port must
be open before it can be read from or written to.  The standard I/O
port, `console-i/o-port', is opened automatically when you start
Scheme.  When you use a file for input or output, you need to
explicitly open and close a port to the file (with procedures described
in this chapter).  Additional procedures let you open ports to strings.

   Many input procedures, such as `read-char' and `read', read data
from the current input port by default, or from a port that you
specify.  The current input port is initially `console-i/o-port', but
Scheme provides procedures that let you change the current input port
to be a file or string.

   Similarly, many output procedures, such as `write-char' and
`display', write data to the current output port by default, or to a
port that you specify.  The current output port is initially
`console-i/o-port', but Scheme provides procedures that let you change
the current output port to be a file or string.

   All ports read or write only ISO-8859-1 characters.

   Every port is either an input port, an output port, or both.  The
following predicates distinguish all of the possible cases.

 - procedure: port? object
     Returns `#t' if OBJECT is a port, otherwise returns `#f'.

 - procedure: input-port? object
     Returns `#t' if OBJECT is an input port, otherwise returns `#f'.
     Any object satisfying this predicate also satisfies `port?'.

 - procedure: output-port? object
     Returns `#t' if OBJECT is an output port, otherwise returns `#f'.
     Any object satisfying this predicate also satisfies `port?'.

 - procedure: i/o-port? object
     Returns `#t' if OBJECT is both an input port and an output port,
     otherwise returns `#f'.  Any object satisfying this predicate also
     satisfies `port?', `input-port?', and `output-port?'.

 - procedure: guarantee-port object
 - procedure: guarantee-input-port object
 - procedure: guarantee-output-port object
 - procedure: guarantee-i/o-port object
     These procedures check the type of OBJECT, signalling an error of
     type
     `condition-type:wrong-type-argument' if it is not a port, input
     port, output port, or I/O port, respectively.  Otherwise they
     return OBJECT.

   The next five procedures return the runtime system's "standard
ports".  All of the standard ports are dynamically bound by the REP
loop; this means that when a new REP loop is started, for example by an
error, each of these ports is dynamically bound to the I/O port of the
REP loop.  When the REP loop exits, the ports revert to their original
values.

 - procedure: current-input-port
     Returns the current input port.  This is the default port used by
     many input procedures.  Initially, `current-input-port' returns the
     value of `console-i/o-port'.

 - procedure: current-output-port
     Returns the current output port.  This is the default port used by
     many output procedures.  Initially, `current-output-port' returns
     the value of `console-i/o-port'.

 - procedure: notification-output-port
     Returns an output port suitable for generating "notifications",
     that is, messages to the user that supply interesting information
     about the execution of a program.  For example, the `load'
     procedure writes messages to this port informing the user that a
     file is being loaded.  Initially, `notification-output-port'
     returns the value of `console-i/o-port'.

 - procedure: trace-output-port
     Returns an output port suitable for generating "tracing"
     information about a program's execution.  The output generated by
     the `trace' procedure is sent to this port.  Initially,
     `trace-output-port' returns the value of `console-i/o-port'.

 - procedure: interaction-i/o-port
     Returns an I/O port suitable for querying or prompting the user.
     The standard prompting procedures use this port by default (see
     Prompting).  Initially, `interaction-i/o-port' returns the value
     of `console-i/o-port'.

 - procedure: with-input-from-port input-port thunk
 - procedure: with-output-to-port output-port thunk
 - procedure: with-notification-output-port output-port thunk
 - procedure: with-trace-output-port output-port thunk
 - procedure: with-interaction-i/o-port i/o-port thunk
     THUNK must be a procedure of no arguments.  Each of these
     procedures binds one of the standard ports to its first argument,
     calls THUNK with no arguments, restores the port to its original
     value, and returns the result that was yielded by THUNK.  This
     temporary binding is performed the same way as dynamic binding of
     a variable, including the behavior in the presence of
     continuations (see Dynamic Binding).

     `with-input-from-port' binds the current input port,
     `with-output-to-port' binds the current output port,
     `with-notification-output-port' binds the "notification" output
     port, `with-trace-output-port' binds the "trace" output port, and
     `with-interaction-i/o-port' binds the "interaction" I/O port.

 - procedure: set-current-input-port! input-port
 - procedure: set-current-output-port! output-port
 - procedure: set-notification-output-port! output-port
 - procedure: set-trace-output-port! output-port
 - procedure: set-interaction-i/o-port! i/o-port
     Each of these procedures alters the binding of one of the standard
     ports and returns an unspecified value.  The binding that is
     modified corresponds to the name of the procedure.

 - variable: console-i/o-port
     `console-i/o-port' is an I/O port that communicates with the
     "console".  Under unix, the console is the controlling terminal of
     the Scheme process.  Under Windows and OS/2, the console is the
     window that is created when Scheme starts up.

     This variable is rarely used; instead programs should use one of
     the standard ports defined above.  This variable should not be
     modified.

 - procedure: close-port port
     Closes PORT and returns an unspecified value.  If PORT is a file
     port, the file is closed.

 - procedure: close-input-port port
     Closes PORT and returns an unspecified value.  PORT must be an
     input port or an I/O port; if it is an I/O port, then only the
     input side of the port is closed.

 - procedure: close-output-port port
     Closes PORT and returns an unspecified value.  PORT must be an
     output port or an I/O port; if it is an I/O port, then only the
     output side of the port is closed.

File Ports
==========

   Before Scheme can access a file for reading or writing, it is
necessary to open a port to the file.  This section describes
procedures used to open ports to files.  Such ports are closed (like
any other port) by `close-port'.  File ports are automatically closed
if and when they are reclaimed by the garbage collector.

   Before opening a file for input or output, by whatever method, the
FILENAME argument is converted to canonical form by calling the
procedure `merge-pathnames' with FILENAME as its sole argument.  Thus,
FILENAME can be either a string or a pathname, and it is merged with
the current pathname defaults to produce the pathname that is then
opened.

   Any file can be opened in one of two modes, "normal" or "binary".
Normal mode is for accessing text files, and binary mode is for
accessing other files.  Unix does not distinguish these modes, but
Windows and OS/2 do: in normal mode, their file ports perform "newline
translation", mapping between the carriage-return/linefeed sequence
that terminates text lines in files, and the `#\newline' that
terminates lines in Scheme.  In binary mode, such ports do not perform
newline translation.  Unless otherwise mentioned, the procedures in
this section open files in normal mode.

 - procedure: open-input-file filename
     Takes a filename referring to an existing file and returns an
     input port capable of delivering characters from the file.  If the
     file cannot be opened, an error of type
     `condition-type:file-operation-error' is signalled.

 - procedure: open-output-file filename [append?]
     Takes a filename referring to an output file to be created and
     returns an output port capable of writing characters to a new file
     by that name.  If the file cannot be opened, an error of type
     `condition-type:file-operation-error' is signalled.

     The optional argument APPEND? is an MIT Scheme extension.  If
     APPEND? is given and not `#f', the file is opened in "append"
     mode.  In this mode, the contents of the file are not overwritten;
     instead any characters written to the file are appended to the end
     of the existing contents.  If the file does not exist, append mode
     creates the file and writes to it in the normal way.

 - procedure: open-i/o-file filename
     Takes a filename referring to an existing file and returns an I/O
     port capable of both reading and writing the file.  If the file
     cannot be opened, an error of type
     `condition-type:file-operation-error' is signalled.

     This procedure is often used to open special files.  For example,
     under unix this procedure can be used to open terminal device
     files, PTY device files, and named pipes.

 - procedure: open-binary-input-file filename
 - procedure: open-binary-output-file filename [append?]
 - procedure: open-binary-i/o-file filename
     These procedures open files in binary mode.  In all other respects
     they are identical to `open-input-file', `open-output-file', and
     `open-i/o-file', respectively.

 - procedure: close-all-open-files
     This procedure closes all file ports that are open at the time
     that it is called, and returns an unspecified value.

 - procedure: call-with-input-file filename procedure
 - procedure: call-with-output-file filename procedure
     These procedures call PROCEDURE with one argument: the port
     obtained by opening the named file for input or output,
     respectively.  If the file cannot be opened, an error of type
     `condition-type:file-operation-error' is signalled.  If PROCEDURE
     returns, then the port is closed automatically and the value
     yielded by PROCEDURE is returned.  If PROCEDURE does not return,
     then the port will not be closed automatically unless it is
     reclaimed by the garbage collector.(1)

 - procedure: call-with-binary-input-file filename procedure
 - procedure: call-with-binary-output-file filename procedure
     These procedures open files in binary mode.  In all other respects
     they are identical to `call-with-input-file' and
     `call-with-output-file', respectively.

 - procedure: with-input-from-file filename thunk
 - procedure: with-output-to-file filename thunk
     THUNK must be a procedure of no arguments.  The file is opened for
     input or output, an input or output port connected to it is made
     the default value returned by `current-input-port' or
     `current-output-port', and the THUNK is called with no arguments.
     When the THUNK returns, the port is closed and the previous
     default is restored.  `with-input-from-file' and
     `with-output-to-file' return the value yielded by THUNK.  If an
     escape procedure is used to escape from the continuation of these
     procedures, their behavior is implementation-dependent; in that
     situation MIT Scheme leaves the files open.

 - procedure: with-input-from-binary-file filename thunk
 - procedure: with-output-to-binary-file filename thunk
     These procedures open files in binary mode.  In all other respects
     they are identical to `with-input-from-file' and
     `with-output-to-file', respectively.

   ---------- Footnotes ----------

   (1) Because Scheme's escape procedures have unlimited extent, it is
possible to escape from the current continuation but later to escape
back in.  If implementations were permitted to close the port on any
escape from the current continuation, then it would be impossible to
write portable code using both `call-with-current-continuation' and
`call-with-input-file' or `call-with-output-file'.

String Ports
============

   This section describes the simplest kinds of ports: input ports that
read their input from given strings, and output ports that accumulate
their output and return it as a string.  It also describes "truncating"
output ports, which can limit the length of the resulting string to a
given value.

 - procedure: string->input-port string [start [end]]
     Returns a new string port that delivers characters from STRING.
     The optional arguments START and END may be used to specify that
     the string port delivers characters from a substring of STRING; if
     not given, START defaults to `0' and END defaults to
     `(string-length STRING)'.

 - procedure: with-input-from-string string thunk
     THUNK must be a procedure of no arguments.
     `with-input-from-string' creates a new input port that reads from
     STRING, makes that port the current input port, and calls THUNK.
     When THUNK returns, `with-input-from-string' restores the previous
     current input port and returns the result yielded by THUNK.

          (with-input-from-string "(a b c) (d e f)" read)  =>  (a b c)

     Note: this procedure is equivalent to:

          (with-input-from-port (string->input-port STRING) THUNK)

 - procedure: with-string-output-port procedure
     PROCEDURE is called with one argument, an output port.  The value
     yielded by PROCEDURE is ignored.  When PROCEDURE returns,
     `with-string-output-port' returns the port's accumulated output as
     a newly allocated string.

 - procedure: with-output-to-string thunk
     THUNK must be a procedure of no arguments.
     `with-output-to-string' creates a new output port that accumulates
     output, makes that port the default value returned by
     `current-output-port', and calls THUNK with no arguments.  When
     THUNK returns, `with-output-to-string' restores the previous
     default and returns the accumulated output as a newly allocated
     string.

          (with-output-to-string
            (lambda ()
              (write 'abc)))                    =>  "abc"

     Note: this procedure is equivalent to:

          (with-string-output-port
           (lambda (port)
             (with-output-to-port port THUNK)))

 - procedure: with-output-to-truncated-string k thunk
     Similar to `with-output-to-string', except that the output is
     limited to K characters.  If THUNK attempts to write more than K
     characters, it will be aborted by invoking an escape procedure
     that returns from `with-output-to-truncated-string'.

     The value of this procedure is a pair; the car of the pair is `#t'
     if THUNK attempted to write more than K characters, and `#f'
     otherwise.  The cdr of the pair is a newly allocated string
     containing the accumulated output.

     This procedure is helpful for displaying circular lists, as shown
     in this example:

          (define inf (list 'inf))
          (with-output-to-truncated-string 40
            (lambda ()
              (write inf)))                       =>  (#f . "(inf)")
          (set-cdr! inf inf)
          (with-output-to-truncated-string 40
            (lambda ()
              (write inf)))
                  =>  (#t . "(inf inf inf inf inf inf inf inf inf inf")

 - procedure: write-to-string object [k]
     Writes OBJECT to a string output port, and returns the resulting
     newly allocated string.  If K is supplied and not `#f', this
     procedure is equivalent to

          (with-output-to-truncated-string K
            (lambda ()
              (write OBJECT)))

     otherwise it is equivalent to

          (with-output-to-string
           (lambda ()
             (write OBJECT)))

Input Procedures
================

   This section describes the procedures that read input.  Input
procedures can read either from the current input port or from a given
port.  Remember that to read from a file, you must first open a port to
the file.

   Input ports can be divided into two types, called "interactive" and
"non-interactive".  Interactive input ports are ports that read input
from a source that is time-dependent; for example, a port that reads
input from a terminal or from another program.  Non-interactive input
ports read input from a time-independent source, such as an ordinary
file or a character string.

   All optional arguments called INPUT-PORT, if not supplied, default
to the current input port.

 - procedure: read-char [input-port]
     Returns the next character available from INPUT-PORT, updating
     INPUT-PORT to point to the following character.  If no more
     characters are available, an end-of-file object is returned.

     In MIT Scheme, if INPUT-PORT is an interactive input port and no
     characters are immediately available, `read-char' will hang waiting
     for input, even if the port is in non-blocking mode.

 - procedure: peek-char [input-port]
     Returns the next character available from INPUT-PORT, _without_
     updating INPUT-PORT to point to the following character.  If no
     more characters are available, an end-of-file object is
     returned.(1)

     In MIT Scheme, if INPUT-PORT is an interactive input port and no
     characters are immediately available, `peek-char' will hang waiting
     for input, even if the port is in non-blocking mode.

 - procedure: char-ready? [input-port]
     Returns `#t' if a character is ready on INPUT-PORT and returns
     `#f' otherwise.  If `char-ready?' returns `#t' then the next
     `read-char' operation on INPUT-PORT is guaranteed not to hang.  If
     INPUT-PORT is a file port at end of file then `char-ready?' returns
     `#t'.(2)

 - procedure: read [input-port]
     Converts external representations of Scheme objects into the
     objects themselves.  `read' returns the next object parsable from
     INPUT-PORT, updating INPUT-PORT to point to the first character
     past the end of the written representation of the object.  If an
     end of file is encountered in the input before any characters are
     found that can begin an object, `read' returns an end-of-file
     object.  The INPUT-PORT remains open, and further attempts to read
     will also return an end-of-file object.  If an end of file is
     encountered after the beginning of an object's written
     representation, but the written representation is incomplete and
     therefore not parsable, an error is signalled.

 - procedure: eof-object? object
     Returns `#t' if OBJECT is an end-of-file object; otherwise returns
     `#f'.

 - procedure: read-char-no-hang [input-port]
     If INPUT-PORT can deliver a character without blocking, this
     procedure acts exactly like `read-char', immediately returning that
     character.  Otherwise, `#f' is returned, unless INPUT-PORT is a
     file port at end of file, in which case an end-of-file object is
     returned.  In no case will this procedure block waiting for input.

 - procedure: read-string char-set [input-port]
     Reads characters from INPUT-PORT until it finds a terminating
     character that is a member of CHAR-SET (see Character Sets) or
     encounters end of file.  The port is updated to point to the
     terminating character, or to end of file if no terminating
     character was found.  `read-string' returns the characters, up to
     but excluding the terminating character, as a newly allocated
     string.

     This procedure ignores the blocking mode of the port, blocking
     unconditionally until it sees either a delimiter or eof of file.
     If end of file is encountered before any characters are read, an
     end-of-file object is returned.

     On many input ports, this operation is significantly faster than
     the following equivalent code using `peek-char' and `read-char':

          (define (read-string char-set input-port)
            (let ((char (peek-char input-port)))
              (if (eof-object? char)
                  char
                  (list->string
                   (let loop ((char char))
                     (if (or (eof-object? char)
                             (char-set-member? char-set char))
                         '()
                         (begin
                           (read-char input-port)
                           (cons char
                                 (loop (peek-char input-port))))))))))

 - procedure: read-line [input-port]
     `read-line' reads a single line of text from INPUT-PORT, and
     returns that line as a newly allocated string.  The `#\newline'
     terminating the line, if any, is discarded and does not appear in
     the returned string.

     This procedure ignores the blocking mode of the port, blocking
     unconditionally until it has read an entire line.  If end of file
     is encountered before any characters are read, an end-of-file
     object is returned.

 - procedure: read-string! string [input-port]
 - procedure: read-substring! string start end [input-port]
     `read-string!' and `read-substring!' fill the specified region of
     STRING with characters read from INPUT-PORT until the region is
     full or else there are no more characters available from the port.
     For `read-string!', the region is all of STRING, and for
     `read-substring!', the region is that part of STRING specified by
     START and END.

     The returned value is the number of characters filled into the
     region.  However, there are several interesting cases to consider:

        * If `read-string!' (`read-substring!') is called when
          INPUT-PORT is at "end-of-file", then the returned value is
          `0'.  Note that "end-of-file" can mean a file port that is at
          the file's end, a string port that is at the string's end, or
          any other port that will never produce more characters.

        * If INPUT-PORT is an interactive port (e.g. a terminal), and
          one or more characters are immediately available, the region
          is filled using the available characters.  The procedure then
          returns immediately, without waiting for further characters,
          even if the number of available characters is less than the
          size of the region.  The returned value is the number of
          characters actually filled in.

        * If INPUT-PORT is an interactive port and no characters are
          immediately available, the result of the operation depends on
          the blocking mode of the port.  If the port is in
          non-blocking mode, `read-string!' (`read-substring!')
          immediately returns the value `#f'.  Otherwise, the operation
          blocks until a character is available.  As soon as at least
          one character is available, the region is filled using the
          available characters.  The procedure then returns
          immediately, without waiting for further characters, even if
          the number of available characters is less than the size of
          the region.  The returned value is the number of characters
          actually filled in.

     The importance of `read-string!' and `read-substring!' are that
     they are both flexible and extremely fast, especially for large
     amounts of data.

   The following variables may be dynamically bound to change the
behavior of the `read' procedure.

 - variable: *parser-radix*
     This variable defines the radix used by the reader when it parses
     numbers.  This is similar to passing a radix argument to
     `string->number'.  The value of this variable must be one of `2',
     `8', `10', or `16'; any other value is ignored, and the reader
     uses radix `10'.

     Note that much of the number syntax is invalid for radixes other
     than `10'.  The reader detects cases where such invalid syntax is
     used and signals an error.  However, problems can still occur when
     `*parser-radix*' is set to `16', because syntax that normally
     denotes symbols can now denote numbers (e.g. `abc').  Because of
     this, it is usually undesirable to set this variable to anything
     other than the default.

     The default value of this variable is `10'.

 - variable: *parser-canonicalize-symbols?*
     This variable controls how the parser handles case-sensitivity of
     symbols.  If it is bound to its default value of `#t', symbols read
     by the parser are converted to lower case before being interned.
     Otherwise, symbols are interned without case conversion.

     In general, it is a bad idea to use this feature, as it doesn't
     really make Scheme case-sensitive, and therefore can break
     features of the Scheme runtime that depend on case-insensitive
     symbols.

   ---------- Footnotes ----------

   (1) The value returned by a call to `peek-char' is the same as the
value that would have been returned by a call to `read-char' on the
same port.  The only difference is that the very next call to
`read-char' or `peek-char' on that INPUT-PORT will return the value
returned by the preceding call to `peek-char'.  In particular, a call
to `peek-char' on an interactive port will hang waiting for input
whenever a call to `read-char' would have hung.

   (2) `char-ready?' exists to make it possible for a program to accept
characters from interactive ports without getting stuck waiting for
input.  Any input editors associated with such ports must make sure
that characters whose existence has been asserted by `char-ready?'
cannot be rubbed out.  If `char-ready?' were to return `#f' at end of
file, a port at end of file would be indistinguishable from an
interactive port that has no ready characters.

Output Procedures
=================

   Output ports may or may not support "buffering" of output, in which
output characters are collected together in a buffer and then sent to
the output device all at once.  (Most of the output ports implemented by
the runtime system support buffering.)  Sending all of the characters in
the buffer to the output device is called "flushing" the buffer.  In
general, output procedures do not flush the buffer of an output port
unless the buffer is full.

   However, the standard output procedures described in this section
perform what is called "discretionary" flushing of the buffer.
Discretionary output flushing works as follows.  After a procedure
performs its output (writing characters to the output buffer), it checks
to see if the port implements an operation called
`discretionary-flush-output'.  If so, then that operation is invoked to
flush the buffer.  At present, only the console port defines
`discretionary-flush-output'; this is used to guarantee that output to
the console appears immediately after it is written, without requiring
calls to `flush-output'.

   All optional arguments called OUTPUT-PORT, if not supplied, default
to the current output port.

 - procedure: write-char char [output-port]
     Writes CHAR (the character itself, not a written representation of
     the character) to OUTPUT-PORT, performs discretionary output
     flushing, and returns an unspecified value.

 - procedure: write-string string [output-port]
     Writes STRING to OUTPUT-PORT, performs discretionary output
     flushing, and returns an unspecified value.  This is equivalent to
     writing the contents of STRING, one character at a time using
     `write-char', except that it is usually much faster.

 - procedure: write-substring string start end [output-port]
     Writes the substring defined by STRING, START, and END to
     OUTPUT-PORT, performs discretionary output flushing, and returns
     an unspecified value.  This is equivalent to writing the contents
     of the substring, one character at a time using `write-char',
     except that it is usually much faster.

 - procedure: write object [output-port]
     Writes a written representation of OBJECT to OUTPUT-PORT, and
     returns an unspecified value.  If OBJECT has a standard external
     representation, then the written representation generated by
     `write' shall be parsable by `read' into an equivalent object.
     Thus strings that appear in the written representation are
     enclosed in doublequotes, and within those strings backslash and
     doublequote are escaped by backslashes.  `write' performs
     discretionary output flushing and returns an unspecified value.

 - procedure: display object [output-port]
     Writes a representation of OBJECT to OUTPUT-PORT.  Strings appear
     in the written representation as if written by `write-string'
     instead of by `write'.  Character objects appear in the
     representation as if written by `write-char' instead of by
     `write'.  `display' performs discretionary output flushing and
     returns an unspecified value.(1)

 - procedure: newline [output-port]
     Writes an end-of-line to OUTPUT-PORT, performs discretionary
     output flushing, and returns an unspecified value.  Equivalent to
     `(write-char #\newline OUTPUT-PORT)'.

 - procedure: fresh-line [output-port]
     Most output ports are able to tell whether or not they are at the
     beginning of a line of output.  If OUTPUT-PORT is such a port,
     this procedure writes an end-of-line to the port only if the port
     is not already at the beginning of a line.  If OUTPUT-PORT is not
     such a port, this procedure is identical to `newline'.  In either
     case, `fresh-line' performs discretionary output flushing and
     returns an unspecified value.

 - procedure: write-line object [output-port]
     Like `write', except that it writes an end-of-line to OUTPUT-PORT
     after writing OBJECT's representation.  This procedure performs
     discretionary output flushing and returns an unspecified value.

 - procedure: flush-output [output-port]
     If OUTPUT-PORT is buffered, this causes the contents of its buffer
     to be written to the output device.  Otherwise it has no effect.
     Returns an unspecified value.

 - procedure: beep [output-port]
     Performs a "beep" operation on OUTPUT-PORT, performs discretionary
     output flushing, and returns an unspecified value.  On the console
     port, this usually causes the console bell to beep, but more
     sophisticated interactive ports may take other actions, such as
     flashing the screen.  On most output ports, e.g. file and string
     output ports, this does nothing.

 - procedure: clear [output-port]
     "Clears the screen" of OUTPUT-PORT, performs discretionary output
     flushing, and returns an unspecified value.  On a terminal or
     window, this has a well-defined effect.  On other output ports,
     e.g.  file and string output ports, this does nothing.

 - procedure: pp object [output-port [as-code?]]
     `pp' prints OBJECT in a visually appealing and structurally
     revealing manner on OUTPUT-PORT.  If object is a procedure, `pp'
     attempts to print the source text.  If the optional argument
     AS-CODE? is true, `pp' prints lists as Scheme code, providing
     appropriate indentation; by default this argument is false.  `pp'
     performs discretionary output flushing and returns an unspecified
     value.

   The following variables may be dynamically bound to change the
behavior of the `write' and `display' procedures.

 - variable: *unparser-radix*
     This variable specifies the default radix used to print numbers.
     Its value must be one of the exact integers `2', `8', `10', or
     `16'; the default is `10'.  If `*unparser-radix*' is not `10',
     numbers are prefixed to indicate their radix.

 - variable: *unparser-list-breadth-limit*
     This variable specifies a limit on the length of the printed
     representation of a list or vector; for example, if the limit is
     `4', only the first four elements of any list are printed, followed
     by ellipses to indicate any additional elements.  The value of this
     variable must be an exact non-negative integer, or `#f' meaning no
     limit; the default is `#f'.

          (fluid-let ((*unparser-list-breadth-limit* 4))
            (write-to-string '(a b c d)))
                                          => "(a b c d)"
          (fluid-let ((*unparser-list-breadth-limit* 4))
            (write-to-string '(a b c d e)))
                                          => "(a b c d ...)"

 - variable: *unparser-list-depth-limit*
     This variable specifies a limit on the nesting of lists and
     vectors in the printed representation.  If lists (or vectors) are
     more deeply nested than the limit, the part of the representation
     that exceeds the limit is replaced by ellipses.  The value of this
     variable must be an exact non-negative integer, or `#f' meaning no
     limit; the default is `#f'.

          (fluid-let ((*unparser-list-depth-limit* 4))
            (write-to-string '((((a))) b c d)))
                                          => "((((a))) b c d)"
          (fluid-let ((*unparser-list-depth-limit* 4))
            (write-to-string '(((((a)))) b c d)))
                                          => "((((...))) b c d)"

 - variable: *unparser-string-length-limit*
     This variable specifies a limit on the length of the printed
     representation of strings.  If a string's length exceeds this
     limit, the part of the printed representation for the characters
     exceeding the limit is replaced by ellipses.  The value of this
     variable must be an exact non-negative integer, or `#f' meaning no
     limit; the default is `#f'.

          (fluid-let ((*unparser-string-length-limit* 4))
            (write-to-string "abcd"))
                                          => "\"abcd\""
          (fluid-let ((*unparser-string-length-limit* 4))
            (write-to-string "abcde"))
                                          => "\"abcd...\""

 - variable: *unparse-with-maximum-readability?*
     This variable, which takes a boolean value, tells the printer to
     use a special printed representation for objects that normally
     print in a form that cannot be recognized by `read'.  These
     objects are printed using the representation `#@N', where N is the
     result of calling `hash' on the object to be printed.  The reader
     recognizes this syntax, calling `unhash' on N to get back the
     original object.  Note that this printed representation can only be
     recognized by the Scheme program in which it was generated, because
     these hash numbers are different for each invocation of Scheme.

   ---------- Footnotes ----------

   (1) `write' is intended for producing machine-readable output and
`display' is for producing human-readable output.