perm filename LSPMAN.F77[206,LSP] blob sn#326613 filedate 1978-01-03 generic text, type C, neo UTF8
C00001 00001
C00002 00002	.IF FALSE THEN BEGIN "title"
C00003 00003	.<< Organization of Manual >>
C00011 00004	.<< Using LISP at LOTS >>
C00022 00005	.IF FALSE THEN START "hide i/o"
C00071 00006	.IF FALSE THEN START "hide editor"
C00100 ENDMK
.<<Title page for MACLISP at LOTS manual>>
.evenleftborder ← oddleftborder ← 1000;
.area text lines 4 to 52;
.sname ← SSNAME ← NULL
.FONT 1 "NGR40L"
.FONT 2 "SIGN57"
.FONT 3 "SGN114"
.skip 20
Edited by Carolyn Talcott
Stanford University
September 1977
.END "title" ;;
.<< Organization of Manual >>
.require "[1,clt]" source_file;
.portion mainportion
.sname ← ssname ← null
.count subsection in section
.cb Organization of the Manual

.skip 3
	This manual is collected from several sources and aims to document
those features of MACLISP that are available in the student version of
MACLISP implemented at LOTS by R._Gabriel.
The various sections of the manual are described below.

.ss LISP at LOTS

	How to invoke the student LISP system at LOTS.  Special I/O features.
The log of a sample session.

.ss MACLISP Reference Manual.

	Contains parts 1, 2, 3 and the indices of the manual currently
in production at MIT under the direction of Ellen Lewis.  The initial
page gives an index for the entire proposed manual.

.ss Input and Output.

	This section is taken from the I/O section of the old MACLISP
Reference Manual (written by D. Moon at MIT).  It includes mainly information
that pertains to "Old I/O" which is the available form.

.ss The LISP Editor.

	This section contains the documentation for the Editor written
by R. Gabriel and T. Finin. 

.<< Using LISP at LOTS >>
.count page
.next page
.count subsection in section
.sname ← "LISP at LOTS"
.ss  Using LISP at LOTS

	The following is a brief introduction to the use of the "student"
version of MACLISP at LOTS.  
This version can be run at LOTS  by typing  LISP to the "@" prompt.
Allocation, initialization
of the Editor and other useful things are done automatically.
As with other LISP interpreters, the top level is a 
read-eval-print loop.  Type in an S-expression and LISP returns the value.
To exit LISP type ↑C.  (↑ in front of a character means to depress the
<control> key while typing the character.)

	This version of MACLISP has the I/O functions DSKIN and DSKOUT 
which are similar to the functions of the same name in LISP1.6.  
To input a file named  FOO.BAR on your directory say (DSKIN_FOO_BAR).
If the file resides on one of the additional directories known to LISP
then (DSKIN_FOO_BAR_<name>) will read <name>FOO.BAR.  One such directory 
is CS206.  Ask a LISP hacker to find out others.  
If the file resides on a directory unknown to LIPS then the form of
the instruction is (DSKIN_FOO_BAR_DSK_(m_n)) where (m_n) is the system
account information for the directory concerned.  
The Editor functions SAVE and REFILE can be used to save or update 
function definitions. 
The function DSKOUT can be used to write the result of a computation on a file.
For example if FF is a function name and X is and S-expression then
(DKSOUT_(PRINC_(FF_X))_FOO_BAR) creates a file FOO.BAR on your directory and 
PRINC's the result of evaluating (FF X) on that file.
More primitive
but flexible I/O functions are the usual MACLISP "old I/O" functions
UREAD/UWRITE together with the appropriate control switches.  These
are described in the I/O section of the manual.  The syntax for these
functions is  (UREAD_<name>_<ext>)  for a file on your directory or
(UREAD_<name>_<ext>_DSK_(m_n))  for a file on the directory with
account numbers (m_n).

	Sometimes you may encounter an error and a breakpoint will occur.
  The system will type a message preceded by a ";" and perhaps
give you the option of correcting the error on the fly.  
Usually the information that  is typed will alert  you to the
cause of the error; if  not, you should read about errors and debugging
aids in the manual.  In any case,  to  get back to
the  toplevel of MACLISP  you type: ↑G or  (IOC_G).   
.skip 2

.ss A Sample Session with LISP at LOTS.

	Things typed by the user appear in ⊗THIS_FONT and things typed by LISP 
appear in  $THIS_FONT.  Instructions typed to the Editor are preceded by
a "←" which is the prompt used by the Editor.  Messages from the LISP system
(such as error messages) are preceded by ";".   Comments are preceded by 
the character "#".

$$Student MacLisp Interpreter$
$$RIGHT! $

# Type in an S-expression

⊗⊗(QUOTE (A B C))⊗

# LISP returns the value

$$(A B C) $

# Try another. Note that 'A is short for (QUOTE A).

⊗⊗(EQ 'A 'B)⊗

# Define a function

⊗⊗(DEFUN FOO (X) (COND ((ATOM X) XX ) (T (FOO (CAR X)))))⊗

# Try it out

⊗⊗(FOO '(A.B))⊗

$$;XX Unbound variable. Either type a value to use or ↑G:$ ⊗X 

# Oops! a misprint.  Tell LISP that you really meant X and it will finish the evaluation.


# Now use the Editor to fix the mistake.


# First prettyprint the current expression (CE).

← ⊗PP 

$$(DEFUN FOO (X) (COND ((ATOM X) XX) (T (FOO (CAR X)))))$  

# Now point to the 2nd element of the 4th element of the CE

← ⊗⊗4 2⊗

← ⊗PP 

$$((ATOM X) XX)$

# Replace the XX by the intended X  

← ⊗⊗(R XX X)⊗

← ⊗P 

$$((ATOM X) X) $

# Return to the top of the expression

← ⊗TOP 

# Print the "skeleton" of the expression

← ⊗P 

$$DEFUN FOO (X) (COND # #)) $

# Save the definition on the file FOODEF.LSP in your directory 

← ⊗SAVE 

$$<file-specification>:$  ⊗(FOODEF) 

$$(DSK (4 1381)) $

# Leave the Editor and return to LISP

← ⊗EXIT 

# This mode of leaving the Editor forgets about the changes made to FOO, so
# read in the definition written on FOODEF.LSP
# (There are ways of getting the Editor to redefine the function using REMEMBER or OK)



# Try it

⊗⊗(FOO '(A B))⊗

# Read from a previously created file on your directory called FOO.BAR.
# It contains function definitions for ALT and ZEQUAL.



⊗⊗(ALT '(A B C D E))⊗
$$(A C E) $

# Sesson is over. Return to EXEC

.IF FALSE THEN START "hide i/o"
.<< Input and Output >>
.count page
.next page
.sname ← "Input and Output"

                    ***** ROUGH DRAFT #9905 *****
13.         Input and Output
13.1          Basic I/O
   Input  and  output can be done in LISP in terms of S-expressions or
in terms of characters.  Operations may also be performed  on  certain
devices,  such  as  displays,  robot  arms,  etc.,  in terms which are
peculiar to the particular device,  using  the  so-called  "moby  I/O"
   Initially we will discuss just I/O on the user's terminal.
   S-expressions  can  be  input  by  using the function read.  (read)
reads one S-expression, which is either a list  enclosed  in  matching
parentheses  or  an  atom  delimited  by a special character such as a
space or a parenthesis. (A parenthesis would be saved up and  used  on
the  next call to read.)  Read returns the S-expression which it read,
converting it from the external representation as characters  to  LISP
internal form.  See Chapter 2 and section 13.1.2.
   (readch)  reads  in  one  character  and  returns it as a character
   (tyi) reads in one character and returns  a  number  which  is  the
ascii code for the character.
   (print x) prints out the S-expression x in a form which is readable
by  humans  but  which  could  also  be  read back into LISP if it was
printed to a file rather than to the terminal.  See section 13.2.3 for
an explanation of how to do this.
   The expression printed out is preceded by a newline and followed by
a space.  If special characters are used with other than their  normal
meanings,  for  example  if  a  parenthesis appears in the pname of an
atom, they are preceded by slashes so that the output  could  be  read
back in.  Strings are enclosed in double quotes for the same reason.
   (prin1  x) is the same as (print x) except that the leading newline
and trailing space are omitted.  Prin1 can be used to  print  multiple
items  on  a  line, but spacing between the items must be provided for
explicitly, for example by evaluating (tyo 40).
   (princ x) is like (prin1 x) except that special characters are  not
slashified  and  strings  are  not quoted.  This makes the output more
pleasing in certain situations, however it cannot be  read  back  into
   (terpri) types out a newline.
   Output of characters can be accomplished using either tyo or princ.
(tyo n) outputs a character whose ascii code is given by the number n.
princ may be used to output character objects.
   As  implied  above,  these  functions can also be used to do I/O on
devices other than  the  terminal.   The  ways  to  do  this  will  be
explained in section 13.2.3.
   Note  that  what  LISP  does when it is at its "top level," that is
when you first start talking to it, is first to  call  read,  then  to
call  eval  on what was read, then to print the result and advance the
terminal to a new line on which the next piece of input may be  typed.
This may be expressed as repeated evaluation of:
    (prog2 (terpri)
           (print (eval (read))) )

13.2          Files
   I/O  in LISP consists of communication between the LISP environment
and sequences of characters called  files,  located  in  the  external
world.   LISP refers to these files by using "file objects," which are
special  objects  within  the  LISP   environment   which   serve   as
representatives  of,  or symbols for, the files in the external world.
Because there is a one-to-one correspondence between  files  and  file
objects,  it is often convenient to confuse the two and call them both
   The LISP system includes functions which can  manipulate  files  in
various  ways:   A  file may be "opened," that is a file object may be
created and associated with a named file in the external world.
   A file may  be  "closed,"  that  is  the  association  between  the
file-object  and  the  external file may be broken and the file-object
   The file-accessing information contained in a  file-object  may  be
examined  or  changed;  for example, the line length of an output file
may be adjusted.
   The characters of information in the external file may be  read  or
   The  attributes  of  the  external  file,  such as its name, may be
   In order to "open" a file, the external file and  the  file  object
must  be  named  so that a connection may be established between them.
The problem of naming file objects is solved trivially by  making  the
rule that whenever a file object is created its name is decided by the
system  and  returned  as  the  value of the function that created it.
File objects are then referred to in the same way as any S-expression.
Note that the name of a file object does not have a printable form, so
that if you want to manipulate the file  object  by  typing  from  the
terminal  (rather  than from a program), you must keep the file object
as the value of an atomic symbol.
   The naming of files in the outside world is more difficult  because
MACLISP has to operate with several different outside worlds, that is,
under several different operating systems.  It was thought undesirable
to  build  too  many  assumptions  about the operating system into the
language, because that would restrict  the  transporting  of  programs
between MACLISP implementations.
   The  assumptions  that  are  built in are that the operating system
provides named files located in named directories or on named devices,
which may be accessed sequentially  as  streams  of  characters.   The
function   filepos   makes   the  additional  assumption  that  simple
random-access facilities are available.  An interactive environment is
also assumed.  Some of the I/O functions  assume  that  the  names  of
files may be broken up into an arbitrary number of components, so that
names  take on a form such as "" or "moby mess".  However,
it is  possible  for  a  MACLISP  to  operate  with  somewhat  reduced
effectiveness  under an operating system which does not satisfy all of
these assumptions.
   The user of a program or a subsystem written in LISP  wants  to  be
able  to  type  in  file names in the form customary in the particular
operating system being used, and he wants to see them typed out in the
same form.  But if a program wants to  do  more  with  the  file  name
supplied  by  the  user  than  simply  pass  it  on  to the system I/O
functions, it needs to have that name translated to a uniform internal
format, in which the interesting components of the name  are  seperate
atoms  in a list, not buried inside a character string whose format is
not even known to the program.  To resolve this  conflict,  two  forms
for  file  names have been defined, and functions are provided to make
the implementation-dependent translation from one form to  the  other.
The forms of a file name are called the namelist and the namestring.
   The  namestring  is the implementation dependent form.  Namestrings
are represented as LISP character strings, however atomic symbols  may
also  be used, in which case the pname of the atomic symbol is used as
the character string.  The contents of a namestring is just a sequence
of characters which have meaning to  the  user  and  to  the  function
"namelist,"  which  converts  a namestring to a namelist.  Namestrings
should be read in using the  "readstring"  function  and  printed  out
using "princ," so that no quotes will appear around them.
   A  namelist is a list whose car somehow specifies the device and/or
directory which contains the file, and whose cdr specifies the name of
the  file.   The  exact  way  in   which   the   car   specifies   the
device/directory  is  implementation-dependent.   It  should not be of
concern to programs.  The cdr of a namelist is a list of  names  which
are  the  components  of  the  file  name if the operating system uses
multi-component file names.  Each name is  represented  as  an  atomic
symbol, which is "interned" so that it may be tested with the function
   An  additional  feature  of  namelists is the "star convention," by
which  a  namelist  may  contain  unspecified  components,  which  are
indicated  by  the  atom *.  Certain other constructions, explained in
section 13.3, may also be used.  The star convention allows  a  single
namelist  to  specify  a  class of files, and allows programs to apply
defaults to their file-name arguments in a straightforward fashion.
   Some additional information about file objects has  been  collected
here.  It is in brief form and will be elaborated in later sections.
   There  is  no way to input file objects to the reader, because they
do not have pnames or anything of that sort, but  for  convenience  in
error messages and debugging the printer will print a file object as a
sharp  sign  (#),  followed  by the namestring of the external file to
which the file object is attached.  # is the character which  is  used
to indicate that an object of unknown type is being printed.
   The  information  contained  within a file object is here described
Namelist            the namelist for the external file  of  which  the
                    file object is a representative.
Eoffn               a function which is applied when  the  end  of  an
                    input file is reached.
Endpagefn a function which is applied  when  the  end  of  a  page  is
                    reached (on an output file.)
Linel               the number of characters per  line  on  an  output
Charpos   the horizontal position on the line, where  0  is  the  left
Chrct               the number of character positions remaining on the
                    current line of an output file,
Pagel     the number of lines per page.
Linenum   the number of the current line, with 0 being the top of  the
Pagenum   the number of the current page, with the first page being 0.
Filepos             the position within  the  file  of  the  character
                    currently   being   accessed.    (Not  necessarily
                    meaningful for all kinds of files.)
Other               internal  information  used  by   the   LISP   I/O
                    functions   in  transactions  with  the  operating
Note that as a special case nil is considered  to  be  a  file  object
which  represents  the  terminal.   This is in addition to nil's other
identities as an atomic symbol and as a list.  

13.2.3           Specifying the Source or Destination for I/O
   When  an I/O function is called, the source (file) from which it is
to take its input or the destinations (files) on which it  is  to  put
its  output  may be specified directly as an argument to the function,
or they may be specified by default.  The  default  input  source  and
output  destinations  are specified by several system variables, which
may be setq'ed or lambda-bound by the user.  They are described below.
   infile is the default input source,  if the switch ↑q is t.  If  ↑q
is nil the terminal is used as the default input source.
   outfiles  is a list of default output destinations.  Output is sent
to all of these files if the ↑r switch is t.  Output also goes to  the
terminal unless the ↑w switch is t.
   Note  that  in  the  values  of  infile  and outfiles nil means the
terminal, any anything other than nil must be a file object.

infile		VARIABLE
     The value of infile is a file object which is the  default  input
     source  if ↑q is non-nil.  Infile can also be nil which specifies
     that input will be from the terminal even if ↑q is not nil.   The
     initial value of infile is nil.
     If  the  value  of ↑q is non-nil, the default input source is the
     value of the atom infile.  If ↑q is nil, the default input source
     is nil, i.e. the terminal.
instack		VARIABLE
     The value of instack is a list of pushed-down values  of  infile.
     It is managed by the function inpush.  The initial value is nil.
outfiles		VARIABLE
     The  value of outfiles is a list of file objects which are output
     destinations if ↑r is not nil.  Elements of the list outfiles may
     be either file objects created by openo or opena, or nil  meaning
     output  to  the  terminal.  Note that output goes to the terminal
     anyway if ↑w is nil, so it is possible to get  double  characters
     this way.
     If  the  value  of ↑r is non-nil, the default output destinations
     include the files in the list which is  the  value  of  the  atom
     If the value of ↑w is non-nil, the default output destinations do
     not  include  the terminal.  (Unless ↑r is on and nil is a member
     of the outfiles list.)

Now the basic I/O functions can be explained in full detail:
read		LSUBR 0 to 2 args
     This is the S-expression input function.
     (read) reads an S-expression from the default input source.
     (read f), where f is a file or nil meaning the terminal, reads an
     S-expression from f.  During the reading, infile and ↑q are bound
     so that evaluation of (read) within  a  macro-character  function
     will read from the correct input source.
     (read  x),  where  x  is  not  a file and not nil, passes x as an
     argument to the end-of-file function of the input source  if  the
     end  of  the  file is reached.  Usually this means that read will
     return x if there are no more S-expressions in the file.
     (read t) suppresses the calling of the  end-of-file  function  if
     the end of the file is reached.  Instead, read just returns t.
     (read  x  f)  or (read f x) specifies the end-of-file value x and
     selects the input source f.
readch		LSUBR 0 to 2 args
     Readch reads in one character and  returns  a  character  object.
     The arguments are the same as for read.
readline		LSUBR 0 to 2 args
     readline  reads  in  a  line  of  text,  strips  off  the newline
     character or characters at the end, and returns it in the form of
     a character string.  The arguments are the same as for read.  The
     main use for readline is reading in file names typed by the  user
     at his terminal in response to a question.
tyi		LSUBR 0 to 2 args
     Tyi  inputs one character and returns a fixnum which is the ascii
     code for that character.  The arguments are the same as for read.
tyipeek		LSUBR 0 or 1 arg
     (tyipeek) is like (tyi) except that the character is  not  eaten;
     it  is  still in the input stream where the next call to an input
     function will find it.  Thus (= (tyipeek) (tyi)) is  t.   If  the
     end  of  the  file is reached, tyipeek returns 3, (the ascii code
     for "end of text.") The end of file function is not called.
     (tyipeek n), where  n  is  a  fixnum  <  200  octal,  skips  over
     characters of input until one is reached with an ascii code of n.
     That character is not eaten.
     (tyipeek  n),  where  n  is  a  fixnum  >  1000 octal, skips over
     characters of input until one is reached whose syntax  bits  from
     the readtable, logically anded with (lsh n -9.), are nonzero.
     (tyipeek t) skips over characters of input until the beginning of
     an  S-expression  is reached.  Splicing macro characters, such as
     ";" comments, are not considered to begin an object.  If  one  is
     encountered,  its associated function is called as usual (so that
     the text of the comment  can  be  gobbled  up  or  whatever)  and
     tyipeek continues scanning characters.
prin1		LSUBR 1 or 2 args
     (prin1  x)  outputs x  to the current output destination(s), in a
     form suitable for reading back in.
     (prin1 x  f) outputs x on the file f, or the  terminal  if  f  is
print		LSUBR 1 or 2 args
     Print  is  like  prin1  except  that  the output is preceded by a
     newline and followed by a space.  This  is  the  output  function
     most often used.
     (print x) prints x to the default output destinations.
     (print  x  f)  prints x to the file f, or to the terminal if f is
princ		LSUBR 1 or 2 args
     Princ is  like prin1  except  that  special  characters  are  not
     slashified and strings are  not quoted.
     (princ x) outputs x to  the current output destination(s).
     (princ x f) outputs x to the file f, or the terminal if f is nil.
tyo		LSUBR 1 or 2 args
     (tyo  n)  types  out  the  character whose ascii code is n on the
     current output destination(s).
     (tyo n f) types out the character whoe ascii code  is  n  on  the
     file  f  or  on  the terminal if f is nil.  Tyo returns its first
terpri		LSUBR 0 or 1 arg
     (terpri) sends a newline to the current output destination(s).
     (terpri x) sends a newline to x, where x may be an output file or
     nil meaning the terminal.
inpush		SUBR 1 arg
     (inpush x), where x is a file object open for  input  or  nil  to
     specify  the  terminal,  pushes the current input source onto the
     input stack and selects x as the current input source.   This  is
         (setq instack (cons infile instack))
         (setq infile x)
     x is returned.
     (inpush 0) just returns infile.
     (inpush -1) pops a new input source off of the input stack:
         (setq infile (car instack)
               instack (cdr instack))
     The  above  code  is wrong in the case where instack is nil, i.e.
     empty.  In this case inpush leaves instack nil and  makes  infile
     nil, which means the terminal.
     (inpush -n) does (inpush -1) n times.
     (inpush  1)  does  (inpush  (inpush  0)), (inpush +n) does that n
     The value of inpush is  the  newly  selected  input  source.   If
     inpush causes infile to be set to nil, ↑q is set to nil since the
     terminal has become the input source.

13.2.4           Handling End of File
   Calls  to  the  input  functions  read, readch, readstring, and tyi
specify an argument called the "eofval."  If this argument is  omitted
nil  is  assumed.   If the end of the input file is reached during the
execution of  the  function,  the  eofval  argument  is  used  by  the
following procedure:
   Each  file  object  has an end-of-file handler, its eoffn.  When an
end of file occurs while input is being  taken  from  this  file,  the
eoffn  is  examined. (Eof on the terminal cannot occur.)  If the eoffn
is nil, then the following default action is taken:  If eofval on  the
call  to read was not supplied, then the input file is closed and read
continues taking characters from a new input file popped off the input
stack.  If the input stack is empty, (setq ↑q nil) is  done  and  read
continues reading from the terminal.  If an eofval was supplied on the
call to read, then read immediately returns it.  The input file is not
   This  is  not strictly true in the case where the input function is
read or readstring and it is in the middle  of  an  object.   In  this
case, rather than allowing the object to cross files, a fail-act error
occurs.  The argument passed to the user interrupt service function is
the  list  (read-eof).   If  the interrupt service function returns an
atom (such as nil), read errs out;  but if it  returns  a  list,  read
goes on reading from the new input source as if there had not been any
   If  the  eoffn for the input file is not nil, then it is a function
and it is applied with two arguments.  The first argument is the  file
object  that eof'ed.  The second argument is the eofval on the call to
read, or, if an eofval was not supplied, nil.  If  the  eoffn  returns
nil,  the  file  is closed and reading continues from the input source
popped off the input stack.  The above prohibition of objects crossing
eofs applies.  If the eoffn returns t, reading continues from whatever
input source was made the current default one by the  eoffn.   If  the
eoffn  returns  something  other  than t or nil, then read immediately
returns whatever the eoffn returned, and the file is not closed unless
the eoffn closes it.

eoffn		LSUBR 1 or 2 args
     (eoffn x), where  x  is  an  input  file,  gets  x's  end-of-file
     function.   The  end-of-file function is called if the end of the
     file is reached during input.
     (eoffn nil) gets the default end-of-file function.
     (eoffn x f) sets x's end-of-file function to f.
     (eoffn nil f) sets the default end-of-file function to f.
     f may be nil, which means that no end-of-file function is  to  be

13.5          The Old "Uread" I/O System
        The functions uread, uwrite, ufile, ukill, and crunit are part
     of  an  older  LISP  I/O   system.    They   are   retained   for
     compatibility.   Various "status" functions are also part of this
     older I/O system.  (See section 12.7)
        These five functions name files in a different  way  from  the
     other I/O functions.  A file is named by a 4-list,
                           (name1 name2 dev dir)
     Name1  and  name2  together  make  up  the "filename," dev is the
     "device," and dir is the "directory."  In the ITS  implementation
     of MACLISP, these go together to make up the ITS file name:
                           DEV: DIR; NAME1 NAME2
     In  the  DEC-10  implementation, dev is the device name, name1 is
     the file name, name2 is the extension, and dir is a list  of  two
     fixnums,  the project number and the programmer number.  Thus the
                        (name1 ext dev (proj prog))
     represents the file
     In the Multics implementation, dev is  ignored  and  dir  is  the
     directory  pathname.   The  entry-name  is name1.name2.  Thus the
     Multics filename is:
        These five functions maintain their own set of defaults, which
     are updated every time one of these functions is called, so  that
     the  defaults  correspond  to  the  last file that was used.  The
     defaults may be examined with (status crfile), which returns  the
     first  two  elements  of  the default 4-list, and (status crunit)
     which returns the last two.
        It is not necessary to specify all four parts  of  the  4-list
     when  one of these five functions is used.  Any omitted parts are
     taken from the defaults.
        These  functions  are  fsubrs  which  do  not  evaluate  their
     arguments.  They may be applied to a 4-list, e.g.
                   (apply 'uread '(foo bar dsk comlap))
     or they may be called with the 4-list as four arguments, which is
     convenient when calling them from top level.

uread		FSUBR
     This  function  selects  an  input  file.  The argument list is a
     4-list as described  above.   The  specified  file  is  made  the
     default  input  source.   Note  that  the ↑q switch mst be turned
     onbefore input will be automatically taken from this file.
uwrite		FSUBR
     Uwrite opens an output file.  When done  with  this  file,  ufile
     must  be  used to close it and give it a name.  The arguments are
     the last two elements of a  4-list,  specifying  the  device  and
     directory  on  which  the  file  is to be written.  The first two
     parts of the 4-list are not specified until the file is ufile'd.
ufile		FSUBR
     (ufile name1 name2) closes the uwrite output file  and  gives  it
     the  name  name1.name2.   (ufile)  takes name1 and name2 from the
crunit		FSUBR
     (crunit) gets the current device and directory.
     (crunit dev dir) sets the device and directory  and  returns  it.
     The arguments are not evaluated.  Example:
         (crunit) => (dsk >udd>Bar>Foo>subdirectory)
ukill		FSUBR
     (ukill   -args-),  where  -args-  are  like  uread,  deletes  the
     specified file.
     The value of  uread  is  a  file  object  being  used  for  input
     initiated  by  the uread function, or nil if no file is currently
     being uread.
uwrite		VARIABLE
     The value of uwrite is  a  file  object  being  used  for  output
     initiated  by the uwrite function, or nil if no file is currently
     being uwritten.
There are also some status/sstatus functions  associated  with  these.
These  are  (status  crunit),  (status  crfile),  (status  uread), and
(status uwrite).
.END "i/o"
.END "hide i/o" ;;
.IF FALSE THEN START "hide editor"
.<< The LISP Editor>>
.count page
.sname ← "The LISP Editor"

          The following is a very brief introduction to  the  use
     of the LISP Editor.

                       Loading the Editor
                       ------- --- ------

     1). To run the LISP Editor, one simply types  (EDIT)
         or  (EDIT  FOO)  to  edit  the in-core function "FOO" or
         (EDIT FOO FOO BAR DSK (COM RPG)) to  edit  the  function
         "FOO" in file FOO.BAR in the directory of COM,RPG.

     2). (EDIT) or (EDIT FOO) or (EDIT FOO FOO BAR) or (EDIT  FOO
         FOO  BAR  DSK (COM RPG)) can be done in LISP's that have
         an autoload property for EDIT. Typing (EDIT) causes the
	 Editor to be initialized and entered. (EDIT1 <exp>) will make
	 <exp> the toplevel editable expression. (EDIT2 <var>) will
	 make (PROG2 (SETQ <var> <current value of var>) T) the 
	 toplevel while (EDIT2 (GET <var> <indicator>)) will make it:
	 (DEFPROP <var> <value> <indicator>).

              How to Look at the Current Expression (CE)
              --- -- ---- -- --- ------- ----------  --

     P        prints  the  CE  using  the  current  print   depth
              (sublist cutoff) and print length (length cutoff)
     PP       pretty-prints the entire CE
     PS       pretty-prints the CE using the print depth cutoff
     W	      prints the "window" surrounding the CE. Thus if
	      window size is 2, it prints the 2 preceeding and 2 following
	      tokens around the CE, where "token" means expression or 

     (WINDOW n) 
	      changes the window size to n.

     (PL n)   changes the print length to n (initially 5)
     (PD n)   changes the print depth to n (initially 2)

                         Changing the CE
                         -------- --- --

     (CR E1...En) changes the  CE  to  E1...En  (i.e. splices  in
                  E1...En), and makes the CE E1.
     (n E1...En)  n>0, changes the n-th  element  of  the  CE  to
     (n E1...En)  n<0 changes the n-th element of the CE from the
                  end to E1...En
     (n)          n>0 deletes the n-th element of the CE
     (n)          n<0, deletes the n-th element from the end
     RI           moves the right parenthesis in one expression
     RO           moves the right parenthesis out one expression
     LI           similar to RI
     LO           similar to RO
     DELETE       deletes the CE  (if  the  CE  is  the  toplevel
                  expression, the Editor assumes that the user
		  wants to edit a different function and requests:

          (function name <file specifications>):

     The answer can be of several forms;  examples:
        1)  FOO - loads FOO from core
        2)  (FOO FOO BAR) - loads FOO from FOO.BAR
        3)  (FOO BAR DSK (COM RPG)) - loads FOO from  FOO.BAR  in
            the directory of COM,RPG.
        4)  NEW - gives a fresh top-level expression
        5)  cntrl-G - quits back to the Editor command decoder
        6)  UNDO - <see below>.

               Moving around within the Expression
               ------ ------ ------ --- ----------

     n        n>0 makes the new CE the n-th element of the CE
     n        n<0, makes the new CE the n-th element from the end
              of the CE
     ↑        makes the CE the immediate parent of the CE
     TOP      makes the CE the toplevel expression
     NX       makes the CE the next one after the CE
     BK       makes the CE the one before the CE
     MARK     marks the current location so that it can be JUMPed
              to by the command JUMP.  Note:  MARKing and JUMPing
              is not guaranteed  to  work  in  all  cases,  since
              modification  of  the thing being edited can render
              the MARK meaningless.
     JUMP     jumps to the last MARKed location
     UNMARK   forgets  where  the  last  MARK  was  set   (speeds

                       Adding Expressions
                       ------ -----------
     (A n E1...En) puts E1...En after the n-th element of the CE
     (B n E1...En) puts E1...En before the n-th element of the CE
     (AI E1...En)  puts E1...En after the CE and makes E1 the new CE
     (BI E1...En)  puts E1...En before the CE and  makes  E1  the new CE
     (R exp1 exp2) replaces all occurrences of exp1 with exp2  in the CE, viewed
		   as a list, returns nil? if no occurrences found
     (TR exp1 exp2)replaces all occurrences of exp1 with exp2  in the CE, viewed
		   as a tree

                       Finding Expressions (i.e. changing the CE)
                       ------- -----------  ---  -------- --- --

     (F pat)    finds the next occurrence of  pat,  searching  in
                print order
     (BF pat)   finds the next occurrence of  pat,  searching  in
                inverse print order
     (F pat T)  finds the next occurrence of pat but looks at the
                topmost  elements  of  the  CE  first (useful for
                getting to PROG tags)
     (BF pat T) similar to above
     (F pat n)  finds the n-th occurrence of pat
     (BF pat n) similar to above
     F          finds the next  occurrence  of  the  last  search
     BF         similar to above


          Pat, as used above, can contain any of the following:
           Element of pat         What it matches
           ------- -- ---         ---- -- -------

           atom                   atoms EQ to it
           list                   calls matcher recursively
           ?                      any   atom   or   single   list
                                  (i.e. an s-expression)
           ?X                     any  element;   binds   ?X   to
                                  whatever it matched
           *                      any   non-empty    string    of
           *X                     matches as *, but binds  *X  to
                                  the list of elements it matched
           =?X                    whatever ?X matched last time
           =*X                    whatever *X matched last time
           (RESTRICT  ?   P1...Pn)  any  element  satisfying  the
                                  predicates P1,...,Pn
	   ($R ? P1...Pn)	  same as above.
           (RESTRICT ?X P1...Pn)  similar to above but  binds  ?X
                                  to what it matched.
	   ($R ?X P1...Pn)	  same as above.

          Note:  (A ?X IS A ?X) matches (a word is  a  word)  but
     not (a word is a sentence).  Simlarly for (*X is a *X).

                      Invoking the Matcher
                      -------- --- -------

     (MATCH pat)               attempts to match pat against the CE
     (MATCH pat var1 ... varn) attempts to match pat against the
			       CE while retaining the values of the
			       variables var1,..., varn. (E.g. 
			       (MATCH (* *A *B ?A) *A ?A).
     MATCH		       attempts to match the last pat against the
			       CE. Like F and BF above.
     REMATCH		       attempts to get the next match of pat against
			       the CE. Usually this only makes sense if
			       pat contains some * variables.
     (REMATCH var1 ... varn)   rematches but will retain var1,...,varn.

                       Hairy Matching Uses
                       ----- -------- ----

     (PR pat)         replaces the CE with the  instantiation  of
                      pat  (substitutes the values of ?-variables
                      and *-variables)
     (PA n P1...Pn)   similar to (A n E1...En)
     (PB n P1...Pn)   similar to (B n E1...En)
     (PAI P1...Pn)    similar to (AI E1...En)
     (PRA exp1 pat)   similar to (R exp1 exp2)
     (TPRA exp1 pat)  similar to (TR exp1 exp2)

                          Other Commands
                          ----- --------

     (SAVE <file specs>)           saves the toplevel  expression
                                   in  the file given by the file
                                   specs (will create  files  not
     SAVE			   saves the  toplevel expression
				   in the  file last saved in. If
				   there was none, the file spec.
				   is requested.
     (REFILE FOO <file specs>)     replaces the function  FOO  in
                                   the  file  given  by  the file
                                   specs with  that  found  under
                                   the "draft" property of FOO
     (REFILE (FOO1...FOOn)<file specs>)
				   similar to above but refiles
     (REFILE (FOO1...FOOn)<infile specs><outfile specs>)
     (REFILE * <infile><optional outfile>) updates every function
				   in infile.

                                   similar to above but files the
                                   result in the outfile
     REMEMBER                      puts the  toplevel  expression
                                   under   the  "draft"  property
                                   (preserves  DEFUN  format  and
     OK                            REMEMBER's  and   EVAL's   the
                                   toplevel            expression
                                   (i.e. defines the function  as
                                   well as remembers it)
     (COMMENT T)                   allows comments to be  in  the
                                   toplevel  expression (uses the
     (COMMENT NIL)                 disables above
     HELP                          either    provides     helpful
                                   information or confuses you

                        The Undo Feature
                        --- ---- -------

          The Editor allows the user to "undo" any editing he has
     done.    Thus  if  he  has  made  a  mistake  or  simply  is
     experimenting, he can invoke the undo feature to  undo  each
     step.   However the undoer requires a history of the edit to
     be kept and so uses a lot of space.  Be warned!

     (UNDO T)    enables undoing
     (UNDO n)    enables  undoing  with  only  the  last undoable 
		 commands being saved (initially 6.)
     (UNDO NIL)  disables undoing and flushes the  undoqueue (the
     UNDO        undoes the last command.  Successive UNDO's will
                 undo prior edit commands.
     The following commands can be undone:
        -) (A -) (B -) (R -) (PA -) (PB -) (PAI -) (PBI -) (PL -)
        (PD -) (PRA -) (BF -) (F -) (CR -) (PR -) (AI -)  (BI  -)
        (N -) (N) N (EDPROG -).

                     Programming the Editor
                     ----------- --- ------

***** Flushed 12/4/76 *****
     (EDPROG T)          enables the " read-macro
     (EDPROG NIL)        disables above
*****  End Of Flush   *****
     (EDITCOMMAND A B)   a FEXPR which allows the atom A to  mean
                         B in the Editor.  For instance,
                              (EDITCOMMAND LEN (LENGTH %#CE))
                         tells the Editor that when you type  LEN
                         to  it,  the  length  of the CE is to be

	  It is possible  to write LISP  programs to do  editing:
     one can cause the  editor to evaluate  a command by  saying:
     (%EVALUATE exp),  where  exp  must  EVAL  to  a  valid  edit
     command.  A  simple way  to abbreviate  these calls  to  the
     editor is  to  define a  read  macro which  expands  to  the
     desired call.

          One  may  also  have  an  initialization  file   called
     EDIT.INI which will be read when the Editor is being loaded.
     This file can either contain functions like any  other  LISP
     file or LINKTO statements, which are of the form:

          (LINKTO (<filespec1>)(<filespec2>)...)

     This statement will cause  the  Editor  to  read  the  files
     specified  in order.  Functions and LINKTO statements may be
     interspersed.  No FASLOADs may occur in  the  initialization
     file nor in any of the files LINKTOed.
          A nice  subset of  an  EDIT.INI  file  can  be seen  in
     EDIT.IN[AID,RPG]      which       is      documented      in
     FASMAC.DOC[AID,RPG].  Basically it  uses a hoakey fast  read
     macro facility and  allows one to use  the control/meta keys
     as fast  macros to do atomic edit commands with a minimum of
     key strokes.

          The following global variables are useful:
       %#CE            contains the CE (munging the CE must  be  done
                       using the Editor)
       %TOP-EDIT-EXP   contains the toplevel expression
       %#UNDOLIST      contains the undolist
       %#UNDOFLAG      tells whether or you you are in the undo mode

                        Exiting and Etc.
                        ------- --- ---

     EXIT                exits the Editor (to the LISP toplevel)
     (EDIT)              gets you back to the Editor
     (REMEDIT)           flushes the Editor.
     Any other command is handed to LISP to be EVAL'ed.

.END "editor"

∂21-Oct-77  1314	RPG  
 ∂21-Oct-77  1235	CLT  	maclisp editor
Is there some good reason why refile munges comments (in the file)?
Is there a way of avoiding scrambled comments short not using refile?

Try saying (COMMENT T) to the editor first.

.END "hide editor";;