4.2BSD/usr/lisp/ch5.n

." $Header: ch5.n 1.3 83/07/23 12:40:05 layer Exp $
.Lc Input/Output 5
.pp
The following functions are used to read from and write to external devices
(e.g. files)
and programs (through pipes).
All I/O goes through the lisp data type called the port.
A port may be open for either reading or writing, but usually not both
simultaneously (see 
.i fileopen
).
There are only a limited number of ports (20) and they will not be reclaimed
unless they are 
.i close d.
All ports are reclaimed by a 
.i resetio
call,
but this drastic step won't be necessary if the program closes
what it uses.
.pp
If a port argument is not supplied to a function which requires one
or if a bad port argument (such as nil) is given,
then 
.Fr
will use the default port according to this scheme:
If input is being done then the default port is the value
of the symbol
.b piport 
and if output is being done then the default port is the value 
of the symbol
.b poport .
Furthermore,
if the value of piport or poport is not a valid port,
then the standard input or standard output will be used, respectively.
.pp
The standard input and standard output are usually the keyboard and
terminal display unless your job is running in the background and its
input or output is connected to a pipe.
All output which goes to the standard output will also go to the 
port
.b ptport
if it is a valid port.
Output destined for the standard output will not reach 
the standard output if the symbol 
.b ^w
is non nil (although it will still go to 
.b ptport 
if 
.b ptport 
is a valid port).
.pp
Some of the functions listed below reference files directly.
.Fr
has borrowed a convenient shorthand notation from
.i /bin/csh ,
concerning naming files.
If a file name begins with ~ (tilde),
and the symbol
.b tilde-expansion

is bound to something other than nil,
then
.Fr
expands the file name.
It takes the string of characters between the leading tilde, and
the first slash as a user-name.
Then, that initial segment of the filename is replaced by the home
directory of the user.  The null username is taken to be the current
user.
.pp
Having gone to the effort of searching the password file,
.Fr
remembers the user directory, in case it gets asked to do so again.
Tilde-expansion is performed in the following functions:
\fIcfasl, chdir, fasl, ffasl, fileopen, infile, load, outfile,
probef, sys:access, sys:unlink\fP.
.Lf cfasl "'st_file 'st_entry 'st_funcname ['st_disc ['st_library]]"
.Re
t
.Se
This is used to load in a foreign function (see \(sc8.4).
The object file st_file is loaded into the lisp system.
St_entry should be an entry point in the file just loaded.
The function binding of the symbol s_funcname will be set to point
to st_entry, so that when the lisp function s_funcname is called,
st_entry will be run.
st_disc is the discipline to be given to s_funcname. 
st_disc defaults to "subroutine" if it is not given or if it is given as nil.
If st_library is non-null, then after st_file is loaded, the libraries
given in st_library will be searched to resolve external references.
The form of st_library should be something like "-lS -lm".
The C library  (" -lc " ) is always searched so when loading in a C
file you probably won't need to specify a library.
For Fortran files, you should specify "-lF77" and if you are doing 
any I/O, the library entry should be "-lI77 -lF77".
For Pascal files "-lpc" is required.
.No
This function may be used to load the output of the assembler, C compiler,
Fortran compiler, and Pascal compiler  but NOT the lisp compiler (use 
.i fasl 
for that).
If a file has more than one entry point, then use 
.i getaddress 
to locate and setup other foreign functions.
.br
It is an error to load in a file which has a global entry point of the same
name as a global entry point in the running lisp.
As soon as you load in a file with 
.i cfasl , 
its global entry points become part of the 
lisp's entry points.
Thus you cannot 
.i cfasl
in the same file twice unless you 
use 
.i removeaddress
to change certain global entry points to local entry points.
.Lf close "'p_port" 
.Re 
t
.Se
the specified port is drained and closed, releasing the port.
.No
The standard defaults are not used in this case since you probably never
want to close the standard output or standard input.
.Lf cprintf "'st_format 'xfst_val ['p_port]"
.Re
xfst_val
.Se
The UNIX formatted output function printf is called with arguments st_format
and xfst_val.
If xfst_val is a symbol then its print name is passed to printf.
The format string may contain characters which are just printed literally
and it may contain special formatting commands preceded by a percent
sign.
The complete set of formatting characters is described in the UNIX manual.
Some useful ones are %d for printing a fixnum in decimal, %f or %e for printing
a flonum, and %s for printing a character string (or print name of a symbol).
.Ex
\fI(cprintf "Pi equals %f" 3.14159)\fP prints `Pi equals 3.14159'
.Lf drain "['p_port]"
.Re
nil
.Se
If this is an output port then
the characters in the output buffer are all sent to the device.
If this is an input port then all pending characters are flushed.
The default port for this function is the default output port.
.Lf ex "[s_filename]"
.Lx vi "[s_filename]"
.Lx exl "[s_filename]"
.Lx vil "[s_filename]"
.Re t
.Se
The lisp system starts up an editor on the file named as the argument.
It will try appending .l to the file if it can't find it.
The functions \fIexl\fP and \fIvil\fP will load the file after
you finish editing it.  These functions will also remember the name
of the file so that on subsequent invocations, you don't need to
provide the argument.
.No
These functions do not evaluate their argument.
.Lf fasl "'st_name ['st_mapf ['g_warn]]"
.Wh
st_mapf and g_warn default to nil.
.Re
t if the function succeeded, nil otherwise.
.Se
this function is designed to load in an object file generated by
the lisp compiler Liszt.
File names for object files usually end in `.o', so 
.i fasl
will append `.o' to st_name (if it is not already present).
If st_mapf is non nil, then it is the name of the map file to 
create.
.i Fasl 
writes in the map file the names and addresses of the functions
it loads and defines.
Normally the map file is created (i.e. truncated if it 
exists), but if \fI(sstatus\ appendmap\ t)\fP is done then the map file
will be appended.
If g_warn is non nil and if a function is loaded from  the file which
is already defined, then a warning message will be printed.
.No
.i fasl
only looks in the current directory for the file to load. 
The function
.i load
looks through a user-supplied search path and will call
.i fasl
if it finds a file with the same root name and a `.o' extension.
In  most cases the user 
would be better off using the function
.i load
rather than calling
.i fasl
directly.
.Lf ffasl "'st_file 'st_entry 'st_funcname ['st_discipline ['st_library]]"
.Re
the binary object created.
.Se
the Fortran object file st_file is loaded into the lisp system.
St_entry should be an entry point in the file just loaded. 
A binary object will be created and its entry field will be set to point 
to st_entry.
The discipline field of the binary will be set to st_discipline or
"subroutine" by default.
If st_library is present and non-null, then after st_file is loaded, the libraries
given in st_library will be searched to resolve external references.
The form of st_library should be something like "-lS -ltermcap".
In any case, the standard Fortran libraries will be
searched also to resolve external references.
.No
in F77 on Unix, the entry point for the fortran function foo
is named `_foo_'.
.Lf filepos "'p_port ['x_pos]"
.Re
the current position in the file if x_pos is not 
given or else x_pos if x_pos is given.
.Se
If x_pos is given, the next byte to be read or written to the
port will be at 
position x_pos.
.Lf filestat 'st_filename
.Re
a vector containing various numbers which the UNIX operating
system assigns to files.  if the file doesn't exist, an error is
invoked.  Use \fIprobef\fP to determine if the file exists.
.No
The individual entries can be accesed by mnemonic functions
of the form filestat:\fIfield\fP, where field may be any of
atime, ctime, dev, gid, ino, mode,mtime, nlink, rdev, size,
type, uid.  See the UNIX programmers manual for a more detailed
description of these quantities.
.Lf flatc "'g_form ['x_max]"
.Re
the number of characters required to print g_form using \fIpatom\fP.
If x_max is given, and if \fIflatc\fP determines that it will return a value
greater than x_max, then it gives up and returns the current value it
has computed.
This is useful if you just want to see if an expression is larger than
a certain size.
.Lf flatsize "'g_form ['x_max]"
.Re
the number of characters required to print g_form using \fIprint\fP.
The meaning of x_max is the same as for flatc.
.No
Currently this just 
.i explode 's
g_form and checks its length.
.Lf fileopen "'st_filename 'st_mode"
.Re
a port for reading or writing (depending on st_mode) the file st_name.
.Se
the given file is opened (or created if opened for writing and it 
doesn't yet exist).
.No
this function call provides a direct
interface to the operating system's fopen function.
The mode may be more than just "r" for read, "w" for write or "a" for
append.  The modes "r+", "w+" and "a+" permit both reading and writing
on a port provided that
.i fseek
is done between changes in direction.
See the UNIX manual description of fopen for more details.
This routine does not look through a search path for a given file.
.Lf fseek "'p_port 'x_offset 'x_flag"
.Re
the position in the file after the function is performed.
.Se
this function positions the read/write pointer before a certain byte
in the file.
If x_flag is 0 then the pointer is set to x_offset bytes from the 
beginning of the file.
If x_flag is 1 then the pointer is set to x_offset bytes from the
current location in the file.
If x_flag is 2 then the pointer is set to x_offset bytes from the 
end of the file.
.Lf infile "'s_filename"
.Re
a port ready to read s_filename.
.Se
this tries to open s_filename and if it cannot or if there are no
ports available it gives an error message.
.No
to allow your program to continue on a file-not-found error,
you can use something like:
.br
\fI(cond ((null (setq myport (car (errset (infile name) nil))))
.br      
\ \ \ \ \ \ \ \ \ \ \ \ (patom '"couldn't open the file")))\fP
.br
which will set myport to the port to read from if the file exists
or will print a message if it couldn't open it and also set myport to nil.
To simply determine if a file exists, there is a function named
.i probef .
.Lf load "'s_filename ['st_map ['g_warn]]"
.Re
t
.No
The function of 
.i load
has changed since previous releases of 
.Fr 
and the following description should be read carefully.
.Se
.i load 
now serves the function of both
.i fasl
and the old 
.i load .
.i Load
will search a user defined search path for a lisp source or object file
with the filename s_filename (with the extension .l or .o added as
appropriate).
The search path which
.i load
uses is the value of \fI(status\ load-search-path)\fP.
The default is (|.|\ /usr/lib/lisp) which means look in the current
directory first and then /usr/lib/lisp.
The file which 
.i load
looks for depends on the last two characters of s_filename.
If s_filename ends with ".l" then 
.i load 
will only look for a file name
s_filename and will assume that this is a
.Fr
source file.
If s_filename ends with ".o" then 
.i load
will only look for a file named s_filename and will assume that this is
a 
.Fr 
object file to be 
.i fasl ed
in.
Otherwise, 
.i load
will first look for s_filename.o, then s_filename.l and finally
s_filename itself.
If it finds s_filename.o it will assume that this is an object file,
otherwise it will assume that it is a source file.
An object file is loaded using
.i fasl
and a source file is loaded by reading and evaluating each form in the
file.
The optional arguments st_map and g_warn are passed to 
.i fasl
should 
.i fasl
be called.
.No
\fIload\fP requires a port to open the file s_filename.
It then lambda binds the symbol piport to this port and reads and
evaluates the forms.
.Lf makereadtable "['s_flag]"
.Wh
if s_flag is not present it is assumed to be nil.
.Re
a readtable equal to the original readtable if s_flag is non-null, or else
equal to the current readtable.
See chapter 7 for a description of readtables and their uses.
.Lf msg "[l_option ...] ['g_msg ...]"
.No
This function is intended for printing short messages.
Any of the arguments or options
presented can be used any number of times, in any
order.  The messages themselves (g_msg) are evaluated, and then
they are transmitted to
.i patom .
Typically, they are strings, which evaluate to themselves.
The options are interpreted specially:
.Eb
\fImsg Option Summary\fP

\fI(P\ p_portname)\fP 		causes subsequent output to go to the port p_portname
				(port should be opened previously)

\fIB\fP			print a single blank.

\fI(B\ 'n_b)\fP\ \ 		evaluate n_b and print that many blanks.

\fIN\fP			print a single by calling \fIterpr\fP.

\fI(N\ 'n_n)\fP\ \ 		evaluate n_n and transmit
				that many newlines to the stream.

\fID\fP			\fIdrain\fP the current port.
.Ee
.Lf nwritn "['p_port]"
.Re
the number of characters in the buffer
of the given port but not yet written out to the file or device.
The buffer is flushed 
automatically when filled,
or when 
.i terpr
is called.
.Lf outfile "'s_filename ['st_type]"
.Re
a port or nil
.Se
this opens a port to write s_filename.
If st_type is given and if it is  a symbol or string whose name 
begins with `a', then the file will be opened in append mode, 
that is the current contents will not be lost and the next data
will be written at the end of the file.
Otherwise, 
the file opened is truncated by \fIoutfile\fP if it existed beforehand.
If there are no free ports, outfile returns nil.
If one cannot write on s_filename, an error is signalled.
.\".pg
.Lf patom "'g_exp ['p_port]"
.Re
g_exp
.Se
g_exp is printed to the given port or the default port.
If g_exp is a symbol or string, the print name is printed without
any escape characters around special characters in the print name.
If g_exp is a list then \fIpatom\fP has the same effect as \fIprint\fP.
.Lf pntlen "'xfs_arg"
.Re
the number of characters needed to print xfs_arg.
.Lf portp "'g_arg"
.Re
t iff g_arg is a port.
.Lf pp "[l_option] s_name1 ..."
.Re
t
.Se
If s_name\fIi\fP has a function binding, it is pretty-printed,
otherwise if s_name\fIi\fP has a value then that is pretty-printed.
Normally the output of the pretty-printer goes to the standard
output port poport.
The options allow you to redirect it.
.Eb
\fIPP Option Summary\fP

\fI(F\ s_filename)\fP 		direct future printing to s_filename

\fI(P\ p_portname)\fP 		causes output to go to the port p_portname
				(port should be opened previously)

\fI(E\ g_expression)\fP		evaluate g_expression and don't print
.Ee
.Lf princ "'g_arg ['p_port]"
.Eq
patom.
.Lf print "'g_arg ['p_port]"
.Re
nil
.Se
prints g_arg on the port p_port or the default port.
.Lf probef "'st_file"
.Re
t iff the file st_file exists.
.No
Just because it exists doesn't mean you can read it.
.Lf pp-form "'g_form ['p_port]"
.Re 
t
.Se
g_form is pretty-printed to the port p_port (or poport if
p_port is not given).
This is the  function which \fIpp\fP uses. 
\fIpp-form\fP does not look for
function definitions or values of variables, it just prints out the form
it is given.
.No
This is useful as a top-level-printer, c.f. 
.i top-level
in Chapter 6.
.Lf ratom  "['p_port ['g_eof]]"
.Re
the next atom read from the given or default port.
On end of file, g_eof (default nil) is returned.
.Lf read "['p_port ['g_eof]]"
.Re
the next lisp expression read from the given or default port.
On end of file, g_eof (default nil) is returned.
.No
An error will occur if the reader is given an ill formed expression.
The most common error is too many right parentheses (note that this is
not considered an error in Maclisp).
.Lf readc "['p_port ['g_eof]]"
.Re
the next character read from the given or default port.
On end of file, g_eof (default nil) is returned.
.Lf readlist "'l_arg"
.Re
the lisp expression read from the list of characters in l_arg.
.Lf removeaddress "'s_name1 ['s_name2 ...]"
.Re
nil
.Se
the entries for the s_name\fIi\fP in the Lisp symbol table are removed.
This is useful if you wish to 
.i cfasl
or
.i ffasl
in a file twice, since it is illegal for a symbol in the file you
are loading to already exist in the lisp symbol table.
.Lf resetio
.Re
nil
.Se
all ports except the standard input, output and error
are closed.
.Lf setsyntax "'s_symbol 's_synclass ['ls_func]"
.Re
t
.Se
this sets the code for s_symbol to sx_code in the current readtable.
If s_synclass is 
.i macro
or 
.i splicing
then ls_func is the associated function.
See Chapter  7 on the reader for more details.
.Lf sload "'s_file"
.Se
the file s_file (in the current directory) is opened for reading and
each form is read, printed and evaluated.
If the form is recognizable as a function definition, only its name
will be printed, otherwise the whole form is printed.
.No
This function is useful when a file refuses to load because
of a syntax error and you would like to narrow down
where the error is.
.Lf tab "'x_col ['p_port]"
.Se
enough spaces are printed to put the cursor on column x_col.
If the cursor is beyond x_col to start with, a 
.i terpr
is done first.
.Lf terpr "['p_port]"
.Re
nil
.Se
a terminate line  character sequence
is sent to the given port or the default port.
This will also drain the port.
.Lf terpri "['p_port]"
.Eq
terpr.
.Lf tilde-expand 'st_filename
.Re
a symbol whose pname is the tilde-expansion of the argument,
(as discussed at the beginning of this chapter).
If the argument does not begin with a tilde, the argument itself is
returned.
.Lf tyi "['p_port]"
.Re
the fixnum representation of the next character read.
On end of file, -1 is returned.
.Lf tyipeek "['p_port]"
.Re
the fixnum representation of the next character to be read.
.No
This does not actually read the character, it just peeks at it.
.Lf tyo "'x_char ['p_port]"
.Re
x_char.
.Se
the character whose fixnum representation is 
x_code, is printed as a
on the given output port or the default output port.
.Lf untyi "'x_char ['p_port]"
.Se
x_char is put back in the input buffer so a subsequent
.i tyi
or 
.i read
will read it first.
.No
a maximum of one character may be put back.
.Lf username-to-dir 'st_name
.Re
the home directory of the given user.
The result is stored, to avoid unnecessarily searching the 
password file.
.Lf zapline 
.Re
nil
.Se
all characters up to and including the line termination character
are read and discarded from the last port used
for input.
.No
this is used as the macro function for the semicolon character when
it acts as a comment character.