.
.sr encode 2encode*
.sr decode 2decode*
.sr arg1 2arg1*
.sr arg2 2arg2*
.sr arg3 2arg3*
.sr arg4 2arg4*
.
.
.de bdfn
.  sp .5
.  begin dfn_block
.    nv indent indent
.    nv ls
.    ls 1
.    keep ndfn
.  em
.
.
.de ndfn
.  end_keep
.  sp .5
.  end dfn_block
.  sr fff em  look, ma! a space
.  if nargs<1
.    sr fff
.    end if
.  \fff!bdfn
.  em
.
.
.de desc
.  sp .5
.  nr indent indent_pos
.  em
.
.
.de pspec
.  br
\0:
.  if hpos>=indent_pos
`
.  else
.    hp indent_pos!m
.    end if
proctype
.  em
.
.
.de args
(
.  for i 0 nargs-1
\\i
.    if i<(nargs-1)
,
.      end if
.    end for
)
.  em
.
.
.de rtns
returns (
.  for i 0 nargs-1
\\i
.    if i<(nargs-1)
,
.      end if
.    end for
)
.  em
.
.
.de sigs
signals (
.  for i 0 nargs-1
\\i
.    if i<(nargs-1)
,
.      end if
.    end for
)
.  em
.
.
.de sse
SSE
.  em
.
.
.de pse
PSE
.  em
.
.
.appendix "Input/Output"
.lbegin
.  es temp
.  sr env temp
.  width "make_output:_"
.  nr indent_pos width
.  end lbegin
.
.para
This appendix describes the suggested set of
standard "library" data types and procedures for CLU,
provided primarily to support I/O.
We do not consider this facility to be part of the language proper,
but felt the need to suggest a set of commonly-used
functions that have some meaning on most systems.
This facility is minimal because we wished it to be general,
i.e, to be implementable, at least in large part, under almost any
operating system.
The facility also provides a framework in which some other operations that are
not always available can be expressed.
.para
Some thought was given to portability of programs, and possibly even
data, but we expect that programs dealing with all but the simplest
I/O will have to be written very carefully to be portable,
and might not be portable no matter how careful one is.
.para
The following additional types are described:
.show
stream     s(1)- provides access to text files
istreamt(1)- provides access to image files
file_namet(1)- a naming scheme for files
datet(1)- calendar date and time
.eshow
No type "file" exists, as will be explained.
.
.achapter "Files"
.
.para
Our notion of file is a general one that includes not only
storage files (disk files), but also terminals and other
devices (e.g. tape drives).  Each file
will in general support only a subset of the operations
described here.
.para
There are two basic kinds of files, 2text files* and
2image files*.
The two kinds of files may be incompatible.  However,
on any particular system, it may not be possible to determine
what kind a given file is.
.para
A text file consists of a sequence of characters, and
is divided into lines terminated by newline ('\n') characters.
The last line of a non-empty file will be terminated.
A line may begin with a newpage ('\p') character
to indicate the termination of the current page
and the beginning of a new page (relevant only
for page-oriented output devices).
.para
A text file will be stored in the (most appropriate)
standard text file format of the local operating
system.  As a result, certain control characters (e.g. NUL,
CR, FF, ^C, ^Z) may be ignored when written.  In addition,
a system may limit the maximum length of lines and
may remove trailing spaces from lines.
.para
Image files are provided to allow more efficient storage
of information than is provided by text files.  Unlike text
files, there is no need for image files to be compatible
with any local file format; thus, image files can be defined
more precisely than text files.
.para
An image file consists of a sequence of encoded objects.
Objects are written and read using encode and decode
operations of their types.
(These in turn will call encode and decode on their components
until basic types are reached.)
The objects stored in an image file are not tagged by
the system according to their types.  Thus,
if a file is written by performing a specific sequence
of encode operations, then it must be read back
using the corresponding sequence of decode operations
to be meaningful.
.
.achapter "File Names"
.
.para
File names are immutable objects used to name files.
The system file name format is viewed as consisting of
four string components:
.ilist 4 0
directory s(1)- specifies a file directory or device
.next
namet(1)- the primary name of the file (e.g. "thesis")
.next
suffixt(1)- a name normally indicating the type of
file (e.g. "clu" for a CLU source file)
.next
othert(1)- all other components of the system file name form
.end_list
The 2directory* and 2other* components may have internal
syntax.  The 2name* and 2suffix* should be short, unstructured
identifiers.
(For example, in the ITS file name "DEV:DIR;NAME1 NAME2",
the 2directory* is "DEV:DIR;", the 2name* is "NAME1",
the 2suffix* is "NAME2", and there is no 2other*.  In the
UNIX path name "/usr/snyder/doc/refman.r", the 2directory*
is "/usr/snyder/doc", the 2name* is "refman", the 2suffix*
is "r", and there is no 2other*.  Examples of 2other*s
are TENEX version numbers and GCOS passwords.)
.para
A null component has the following interpretation:
.ilist 4
directory - denotes the current "working" directory.
(For example, the "current directory" on UNIX and
the "sname" on ITS.)
.next
name - may be illegal, have a unique interpretation,
or be ignored.
(For example, on ITS, a null name is illegal for
most directories, but for some devices, the name
is ignored.)
.next
suffix - may be illegal, have a unique interpretation, or be ignored.
(For example, on UNIX, a null suffix is legal, as
in "/usr/snyder/foo".)
.next
other - should imply a reasonable default.
.end_list
.ne 7
.para
The operations on file names are:
.
.bdfn
.pspec create
.	args string string string string
.	s 1
.	rtns file_name
.	b 1
.	sigs bad_format
.desc
This operation creates a file name from its components.
2Arg1* is the directory part, arg2 is the name part,
arg3 is the suffix part, and arg4 is the other part for the new file_name.
In the process of creating a file name, the string arguments
may be transformed, e.g. by truncation or case-conversion.
.
.ndfn
.pspec get_dir
.	args file_name
.	rtns string
.pspec get_name
.	args file_name
.	rtns string
.pspec get_suffix
.	args file_name
.	rtns string
.pspec get_other
.	args file_name
.	rtns string
.desc
These operations return string forms of the components of a file name.
If the file name was created using the 2create* operation, then
the strings returned may be different than those given as arguments to
2create*, e.g., they may be truncated or case-converted.
.
.ndfn
.pspec parse
.	args string
.	rtns file_name
.	sigs bad_format
.desc
This operation creates a file name given a string in
the system standard file name syntax.
.
.ndfn
.pspec unparse
.	args file_name
.	rtns string
.desc
This operation transforms a file name into
the system standard file name syntax.
We require that	2parse*`(2unparse*`(2fn*))`=`2fn*
for all file names 2fn*.  One implication of this rule is that
there can be no file name that can be created by 2create* but
not by 2parse*; if a system does have file names that have
no string representation in the system standard file name syntax,
then 2create* must reject those file names as having a bad
format.  Alternatively, the file name syntax must be extended so
that it can express all possible file names.
.
.ndfn
.pspec make_output
.	args file_name string
.	rtns file_name
.desc
This operation is used by programs that take input
from a file and write new files whose names are
based on the input file name.
The operation transforms the file name into
one that is suitable for an output file.  The
transformation is done
as follows: (1) the suffix is set to the given suffix (arg2);
(2) if the old directory is not suitable for writing,
then it is set to null; (3) the name, if null and
meaningless, is set to "output".
(Examples of directories that are not suitable for
writing are ITS archive directories and directories that
involve transferring files over a slow network.)
.
.ndfn
.pspec make_temp
.	args string string
.	rtns file_name
.desc
This operation creates a file name appropriate for a temporary
file, using the given program name (arg1) and file identifier (arg2).
The returned file name is guaranteed to be unique over
the entire system for at least the lifetime of the process that
called it.
(For example, the call make_temp ("sort", "a") might create
the file name "_SORT_`A4398" on ITS and the file name "/tmp/sort4398a"
on UNIX.)
To be useful, both the program name and the file identifier should
be short and alphabetic.
.
.ndfn 1
.para
The file name type also has the obvious 2equal*,
2similar*, 2copy*, 2encode*, and 2decode*
operations.
.achapter "A File Type?"
.
.para
Although files are the basic information-containing objects in this
suggested package, we do not recommend that a file type be introduced.
The reason for this recommendation is that few, if any, systems
provide an adequate representation for files.
.para
On many systems, the most reliable representation of a file
(accessible to the user) is a channel (stream) to that file.
However, this representation
is inappropriate for a CLU file type, since possession of a channel
to a file often implies locking that file.
.para
The other possible representation is a file name.  However, file names
are one level indirect from files, via the file directory.  As a
result, the relationship of a file name to a file object is
time-varying.  Using file names as a representation for files would
imply that all file operations could signal 2non_existent_file*.
.para
Therefore, we suggest that operations related to file objects
be performed by two stream clusters, 2stream* and 2istream*,
and that operations related to the directory system be performed by procedures.
.para
Note that two opens for read with the same file name might
return streams to two different files.  We cannot guarantee
anything about what may happen to a file after a program
obtains a stream to it.
.
.achapter "File System Procedures"
.
.para
The file system procedures are:
.
.bdfn
.pspec open_text
.	args file_name string
.	s 1
.	rtns stream
.	b 1
b(1)signals (s(2)non_existent_file, not_possible(string),
b(2)bad_access_mode, wrong_file_type)
.desc
The possible access modes (arg2) are "read", "write", and "append".
The 2wrong_file_type* exception is signalled in those cases
where the system is able to detect that the specified
pre-existing file is not a text file.
.ndfn
.nr indent indent_pos
If the mode is "read", then the named file must exist.
If the file exists, a stream is returned upon which input operations
can be performed.
Otherwise, the 2non_existent_file* exception is signalled.
.ndfn
.nr indent indent_pos
If the mode is "write", a new file is created or an old file is
rewritten.  A stream is returned upon which output
operations can be performed.
.ndfn
.nr indent indent_pos
If the mode is "append", then if the named file does not exist,
one is created.  A stream is returned, positioned at the
end of the file, upon which output operations can be performed.
In the case of files that
represent terminal devices, input operations also are allowed.
Append mode to storage files should guarantee
exclusive access to the file, if possible.
.
.ndfn
.pspec open_image
.	args file_name string
.	s 1
.	rtns istream
b(1)signals (s(2)non_existent_file, not_possible(string),
b(2)bad_access_mode, wrong_file_type)
.desc
The possible access modes (arg2) are "read", "write", and "append".
The 2wrong_file_type* exception is signalled in those cases
where the system is able to detect that the specified
pre-existing file is not an image file.
.ndfn
.nr indent indent_pos
If the mode is "read", then the named file must exist.
If the file exists,
an image stream is returned upon which decode operations
can be performed.
Otherwise, the 2non_existent_file* exception is signalled.
.ndfn
.nr indent indent_pos
If the mode is "write", a new file is created or an old file is
rewritten.  An image stream is returned upon which encode
operations can be performed.
.ndfn
.nr indent indent_pos
If the mode is "append", then if the named file does not exist,
one is created.  An image stream is returned, positioned at the
end of the file, upon which encode operations can be performed.
Append mode to storage files should guarantee
exclusive access to the file, if possible.
.
.
.ndfn
.pspec delete_file
.	args file_name
.	sigs not_possible(string)
.desc
This procedure deletes the specified storage file.  No exception is
signalled if the specified file does not exist.
(The 2not_possible* exception may be signalled if the
file name specifies a non-existent directory, or if it
specifies a device, or if the file exists but cannot be
deleted.)
.
.ndfn
.pspec rename_file
.	s 1
.	args file_name string string string
.	b 1
.	sigs nonexistent_file file_already_exists not_possible(string)
.desc
This procedure renames the specified file according to
the given file name components (arg2 is the new name part,
arg3 is the new suffix part, and arg4 is the new other part.)
The 2nonexistent_file* exception is signalled if the named file does not exist.
The 2file_already_exists* exception is signalled if
the renamed file would conflict with an already-existing file.
.
.ndfn 1
.achapter "Streams"
.
.para
Streams provide the means to read and write text
files, and to perform some other operations on file objects.
The operations allowed on any particular stream
depend upon the access mode.
In addition, certain operations may be null
in some implementations.
.para
When an operation cannot be performed, because of an incorrect
access mode, because of implementation limitations, or
because of properties of an individual file or device,
then the operation will signal 2not_possible* (unless
the description of the operation explicitly says that
the invocation will be ignored).
This condition can be determined for each
operation 2op* by the operation 2op*_possible, which
takes a stream and returns true if the operation on that
stream appears possible.
.ne 8l
.para
The stream operations are:
.
.bdfn
.pspec getc
.	args stream
.	rtns char
.	sigs end_of_file not_possible(string)
.desc
This input operation removes the next character from the stream
and returns it.
.
.ndfn
.pspec peekc
.	args stream
.	rtns char
.	sigs end_of_file not_possible(string)
.desc
This input operation is like 2getc*, except that the character is
not removed from the stream.
.
.ndfn
.pspec empty
.	args stream
.	rtns bool
.	sigs not_possible(string)
.desc
This input operation returns true if and only if there are
no more characters in the stream.  It is equivalent to a call
of 2peekc*, where true is returned if 2peekc*
returns a character and false is returned if 2peekc*
signals 2end_of_file*.
Thus in the case of terminals, for example, this operation
may wait until additional characters have been typed by the
user.
.
.ndfn
.pspec putc
.	args char stream
.	sigs not_possible(string)
.desc
This output operation appends the given character to the stream.
Writing a newline indicates the end of the current line.
.
.ndfn
.pspec putc_image
.	args char stream
.	sigs not_possible(string)
.desc
This output operaton is like 2putc*,
except that an arbitrary character
may be written and the character is not interpreted by the CLU I/O
system.
(For example, the ITS XGP program expects a text file containing
certain escape sequences.  An escape sequence consists of
a special character followed by a fixed number of
arbitrary characters.  These characters could be the same as a
end-of-line mark, but they are recognized as data by their context.
On a record-oriented system, such characters would be part of the data.
In either case, writing a newline in image mode would not be interpreted
by the CLU system as indicating an end-of-line.)
.
.ndfn
.pspec getc_image
.	args stream
.	rtns char
.	sigs end_of_file not_possible(string)
.desc
This input operation is provided to read escape sequences in text files,
as might be written using 2putc_image*.  Using this operation inhibits
the recognition of end-of-line marks, where used.
.
.ndfn
.pspec get_lineno
.	args stream
.	rtns int
.	sigs end_of_file not_possible(string)
.desc
This input operation returns the line number of the current (being
or about to be read) line.  If the system maintains explicit
line numbers in the file,
said line numbers are returned.  Otherwise, lines are implicitly
numbered, starting with 1.
.
.ndfn
.pspec set_lineno
.	args stream int
.	sigs not_possible(string)
.desc
If the system maintains explicit line numbers in the file, this output
operation sets the line number of the next (not yet started) line.
Otherwise, it is ignored.
.
.ndfn
.pspec reset
.	args stream
.	sigs not_possible(string)
.desc
This operation resets the stream so that the next input or output
operation will read or write the first character in the file.
The line number is reset to its initial value.
.
.ndfn
.pspec flush
.	args stream
.desc
Any buffered output is written to the file, if possible.
Otherwise, there is no effect.
This operation should be used for streams that record the
progress of a program.  It can be used to maximize the
amount of recorded status visible to the user or available
in case the program dies.
.
.ndfn
.pspec get_line_length
.	args stream
.	rtns int
.	sigs no_limit
.desc
If the file or device to which the stream is attached has
a natural maximum line length, then that length is returned.
Otherwise, 2no_limit* is signalled.  The line length
does not include newline characters.
.
.ndfn
.pspec get_page_length
.	args stream
.	rtns int
.	sigs no_limit
.desc
If the device to which the stream is attached has a
natural maximum page length, then that length is returned.
Otherwise, 2no_limit* is signalled.  Storage files
will generally not have page lengths.
.
.ndfn
.pspec get_date
.	args stream
.	rtns date
.	sigs not_possible(string)
.desc
This operation returns the date of the last modification of the
corresponding storage file.
.
.ndfn
.pspec set_date
.	args stream date
.	sigs not_possible(string)
.desc
This operation sets the modification date of the corresponding
storage file.
(The modification date is set automatically when a file is
opened in "write" or "append" mode.)
.
.ndfn
.pspec get_name
.	args stream
.	rtns file_name
.	sigs not_possible(string)
.desc
This operation returns the name of the corresponding file.  It may
be different than the name used to open the file, in that defaults
have been resolved and link indirections have been followed.
.
.ndfn
.pspec close
.	args stream
.desc
This operation terminates I/O and removes the association between
the stream and the file.  Further use of operations that signal
2not_possible* will signal 2not_possible*.
.
.ndfn
.pspec is_closed
.	args stream
.	rtns bool
.desc
This operation returns true iff the stream is closed.
.
.ndfn
.pspec is_terminal
.	args stream
.	rtns bool
.desc
This operation returns true iff the stream is attached to
an interactive terminal (see below).
.
.ndfn
.pspec getl
.	args stream
.	rtns string
.	sigs end_of_file not_possible(string)
.desc
This input operation
reads and returns (the remainder of) the current input line and
reads but does not return the terminating newline.
.
.ndfn
.pspec putl
.	args string stream
.	sigs not_possible(string)
.desc
This output operation
writes the characters of the string onto the stream, followed
by a newline.
.
.ndfn
.pspec gets
.	args stream string
.	s 1
.	rtns string
.	b 1
.	sigs end_of_file not_possible(string)
.desc
This input operation reads characters until a terminating
character (one in arg2) or end-of-file is seen.  The characters up to the terminator
are returned; the terminator (if any) is left in the stream.
This operation signals 2end_of_file* only
if there were no characters and end-of-file was detected.
.
.ndfn
.pspec puts
.	args string stream
.	sigs not_possible(string)
.desc
This output operation simply writes the characters in the string using 2putc*.
Naturally it may be somewht more efficient than doing a series of individual
2putc*'s.
.
.ndfn
.pspec putzero
.	args string int stream
.	sigs negative_field_width
.desc
Output the string.
However, if the length of the string is less than arg2, then
also output the appropriate number of extra zeros before the first
digit or '.' in the string (or at the end, if no such characters).
.
.ndfn
.pspec putleft
.	args string int stream
.	sigs negative_field_width
.desc
Output the string.
However, if the length of the string is less than arg2, then
also output the appropriate number of extra spaces after the string.
.
.ndfn
.pspec putright
.	args string int stream
.	sigs negative_field_width
.desc
Output the string.
However, if the length of the string is less than arg2, then
also output the appropriate number of extra spaces before the string.
.
.ndfn
.pspec putspace
.	args int stream
.	sigs negative_field_width
.desc
This operation outputs arg1 spaces.
.ndfn
.pspec equal
.	args stream stream
.	rtns bool
.desc
Returns true if and only if both arguments are the same stream.
.
.ndfn
.pspec similar
.	args stream stream
.	rtns bool
.desc
Returns true if and only both arguments are the same stream.
.
.ndfn
.pspec
.pspec copy
.	args stream
.	rtns stream
.desc
Returns its argument.
.ndfn 1
.achapter "String I/O"
.para
It is occasionally useful to be able to construct a stream
that, rather than being connected to a file, instead simply
collects the output text into a string.  Conversely, it
is occasionally useful to be able to take a string and
convert it into a stream so that it can be given to a procedure
that expects a stream.  The following stream operations are
suggested to allow these functions to be performed:
.
.bdfn
.pspec create_input
.	args string
.	rtns stream
.desc
An input stream is created that will return the characters
in the given string.  If the string is non-empty and does
not end with a newline, then an extra terminating newline
will be appended to the stream.
.
.ndfn
.pspec create_output
.	args
.	rtns stream
.desc
An output stream is created that will collect output text
in an internal buffer.  The text may be extracted using
the 2get_contents* operation.
.
.ndfn
.pspec get_contents
.	args stream
.	rtns string
.	sigs not_possible(string)
.desc
This operation returns the text that has so far been
output to the stream.  It will signal 2not_possible*
if the stream was not created by 2create_output*.
.ndfn 1
.para
A stream to a string does not have a file name, a creation
date, a maximum line or page length, or explicit line numbers.
.
.achapter "Istreams"
.
.para
Istreams provide the means to read and write image
files, and to perform some other operations on file objects.
The operations allowed on any particular istream
depend upon the access mode.
In addition, certain operations may be null
in some implementations.
.para
When an operation cannot be performed, because of an incorrect
access mode, because of implementation limitations, or
because of properties of an individual file or device,
then the operation will signal 2not_possible* (unless
the description of the operation explicitly says that
the invocation will be ignored).
This condition can be determined for each
operation 2op* by the operation 2op*_possible, which
takes an istream and returns true if the operation on that
istream appears possible.
.para
Actual reading and writing of objects is performed by
encode and decode operations of the types involved.
All of the basic CLU types provide these operations.
Designers of abstract types are encouraged to provide them
also.  The type specifications of the encode and decode
operations for a type T are:
.
.bdfn
.pspec encode
.	args T istream
.	sigs not_possible(string)
.desc
The 2encode* operations are output operations.  They write
an encoding of the given object onto the istream.
.ndfn
.pspec decode
.	args istream
.	s 1
.	rtns T
.	b 1
.	sigs end_of_file bad_format not_possible(string)
.desc
The 2decode* operations are input operations.  They decode
the information written by encode operations and return
an object "similar" to the one encoded.  If the sequence
of decode operations used to read a file do not match
the sequence of encode operations used to write it, then
meaningless objects may be returned.  The system may
in some cases be able to detect this condition, in which
case the decode operation will signal 2bad_format*.
The system is not guaranteed to detect all such errors.
.
.ndfn 1
.
.para
The istream operations are:
.
.bdfn
.pspec empty
.	args istream
.	rtns bool
.desc
Returns true if and only if there are no more objects in the file.
.
.ndfn
.pspec reset
.	args istream
.	sigs not_possible(string)
.desc
This operation resets the istream so that the next input or output
operation will read or write the first item in the file.
.
.ndfn
.pspec flush
.	args istream
.desc
Any buffered output is written to the file, if possible.
Otherwise, there is no effect.
.
.ndfn
.pspec get_date
.	args istream
.	rtns date
.	sigs not_possible(string)
.desc
This operation returns the date of the last modification of the
corresponding storage file.
.
.ndfn
.pspec set_date
.	args istream date
.	sigs not_possible(string)
.desc
This operation sets the modification date of the corresponding
storage file.
(The modification date is set automatically when a file is
opened in "write" or "append" mode.)
.
.ndfn
.pspec get_name
.	args istream
.	rtns file_name
.desc
This operation returns the name of the corresponding file.  It may
be different than the name used to open the file, in that defaults
have been resolved and link indirections have been followed.
.
.ndfn
.pspec close
.	args istream
.desc
This operation terminates I/O and removes the association between
the istream and the file.  Further use of operations that signal
2not_possible* will signal 2not_possible*.
.
.ndfn
.pspec is_closed
.	args istream
.	rtns bool
.desc
This operation returns true iff the istream is closed.
.
.ndfn
.pspec equal
.	args istream istream
.	rtns bool
.desc
Returns true if and only both arguments are the same istream.
.
.ndfn
.pspec similar
.	args istream istream
.	rtns bool
.desc
Returns true if and only both arguments are the same istream.
.
.ndfn
.pspec copy
.	args istream
.	rtns istream
.desc
Returns its argument.
.
.ndfn 1
.achapter "Terminal I/O"
.para
Terminal I/O is performed via streams attached to interactive
terminals.  Such a stream is normally obtained as an argument
to the top-level procedure of a program.  A terminal stream
is capable of performing both input and output
operations.  A number of additional operations are possible
on terminal streams, and a number of standard operations have
special interpretations.
.para
Terminal input will normally be buffered so that the user
may perform editing functions, such as deleting the last
character on the current line, deleting the current line,
redisplaying the current line, and redisplaying the current
line after clearing the screen.  Specific characters for
causing these functions are not suggested.  In addition,
some means must be provided for the user to indicate
end-of-file, so that a terminal stream can be given to
a program that expects an arbitrary stream and reads it
until end-of-file.  The end-of-file status of a stream
is cleared by the 2reset* operation.
.para
Input buffering is normally provided on a line basis.
When a program first asks for input (using 2getc*,
for example) an entire line of input is read from
the terminal and stored in an internal buffer.
Further input is not taken from the terminal until
the existing buffered input is read.
.para
However, new input caused to be read by the 2getbuf*
operation
will be buffered as a unit.  Thus, one can read in
a large amount of text and allow "editing" of the
entire amount of text.
In addition, when the internal buffer is empty,
the 2getc_image* operation will
read a character directly from the terminal, without
interpreting it or echoing it.
.para
The user may specify
a prompt string to be printed whenever a new buffer
of input is requested from the terminal;
the prompt string will also be
reprinted when redisplay of the current line is
requested by the user.
However, if at the time that new input
is requested an unfinished line has been output
to the terminal,
then that unfinished line is used instead as a prompt.
.para
The routine 2putc_image* can be used to cause
control functions, e.g. '\007' (bell) and '\p'
(new-page or clear-screen).  We cannot guarantee the effect caused
by any particular control character, but we recommend
that the standard ASCII interpretation of control
characters be supported wherever possible.
.para
Terminal output may be buffered by the system
up to one line at a
time.  However, the buffer must be flushed when
new input is requested from the terminal.
.para
Terminal streams do not have modification dates.
Terminal streams should have file names and implicit
line numbers.
.ne 7l
.para
Additional operations:
.
.bdfn
.pspec getbuf
.	args stream string
.	rtns string
.desc
This operation is the same as 2gets*, except that
for terminals with input buffering, the entire input
read by 2getbuf* is buffered as a unit, allowing
input editing of the entire text.
.
.ndfn
.pspec get_prompt
.	args stream
.	rtns string
.desc
This operation returns the current prompt string.  The
prompt string is initially empty ("").  The empty string is
returned for non-terminal streams.
.
.ndfn
.pspec set_prompt
.	args stream string
.desc
This operation sets the string to be used for
prompting.  If not possible, there is no effect.
.
.ndfn
.pspec get_input_buffered
.	args stream
.	rtns bool
.desc
This operation returns true iff the stream
is attached to a terminal and input is being buffered.
.
.ndfn
.pspec set_input_buffered
.	args stream bool
.	sigs not_possible(string)
.desc
This operation sets the input buffering mode.
.
.ndfn
.pspec get_output_buffered
.	args stream
.	rtns bool
.desc
This operation returns true iff the stream
is attached to a terminal and output is being buffered.
.
.ndfn
.pspec set_output_buffered
.	args stream bool
.	sigs not_possible(string)
.desc
This operation sets the output buffering mode.
Unbuffered output is useful for programs that output
incomplete lines as they are working to allow
the user to watch the progress of the program.
.
.ndfn 1
.achapter "Miscellaneous Procedures"
.bdfn
.pspec user_name
.	args
.	rtns string
.desc
This operation returns some identification of the user who
is associated with the executing process.
.
.ndfn
.pspec now
.	args
.	rtns date
.desc
This operation returns the current date and time.
.
.ndfn 1
.achapter "Dates"
.
.para
Dates are immutable objects that represent calendar dates
and times.  The operations for dates are:
.
.bdfn
.pspec create
.	args int int int int int int
.	rtns date
.	sigs bad_format
.
.desc
The arguments are (in order) day, month, year, hours, minutes, and seconds.
.ndfn
.pspec get_day
.	args date
.	rtns int
.pspec get_month
.	args date
.	rtns int
.pspec get_year
.	args date
.	rtns int
.pspec get_hour
.	args date
.	rtns int
.pspec get_minute
.	args date
.	rtns int
.pspec get_second
.	args date
.	rtns int
.desc
(1 .. 31),  (1 .. 12),  (1 .. ),  (0 .. 23),  (0 .. 59),  (0 .. 59), respectively.
.ndfn
.pspec unparse
.	args date
.	rtns string
.desc
e.g., "12 January 1978 01:36:59";
unparse`(parse`(d))`=`d.
.ndfn
.pspec unparse_date
.	args date
.	rtns string
.desc
e.g. "12 January 1978"
.ndfn
.pspec unparse_time
.	args date
.	rtns string
.desc
e.g. "01:36:59")
.
.ndfn
.pspec equal
.	args date date
.	rtns bool
.desc
The obvious equal.
.ndfn
.pspec similar
.	args date date
.	rtns bool
.desc
Returns date$equal (arg1, arg2).
.ndfn
.pspec copy
.	args date
.	rtns date
.desc
Returns arg1.
.ndfn
.pspec lt
.	args date date
.	rtns bool
.pspec le
.	args date date
.	rtns bool
.pspec ge
.	args date date
.	rtns bool
.pspec gt
.	args date date
.	rtns bool
.desc
The obvious relational operations;
if 2date1*`<`2date2*, then 2date1* occurs earlier than 2date2*.
.ndfn
.pspec encode
.	args istream date
.	sigs not_possible(string)
.pspec decode
.	args istream
.	s 1
.	rtns date
.	b 1
.	sigs end_of_file, bad_format, not_possible(string)
.desc
These perform the obvious function.
.ndfn 1
