Lisp Machine System Release 91 Notes

System 91 comes with microcode 204.  It does not run with earlier microcode versions,
and system 89 does not run with microcode 204.

System 91 will not run code compiled by Systems 93 and later unless microcode
226 or later is used with it.  System 91 will run properly with this microcode,
but most existing copies of 91 are not set to want it by default.

There are some major incompatibilities related to the presence of a new,
flavor-based error system, documented in the file 1SYS: MAN; ERRORS TEXT.*
The major incompatibilities alone are documented here.
       
       1[A]* 1ERROR-RESTART* Works Differently.
       1[B]* Condition Handler Functions Called Differently.
       1[C]* Interfacing with the 1ABORT* key.
       1[D]* 1ERROR-HANDLER-IO* renamed to 1DEBUG-IO.*
       1[E]* Time-Parsing Functions Now Signal Errors.
       1[F]* 1OPEN* and Other Functions Return Condition Instances.
       1[G]* 1OPEN* and Other Functions No Longer Ask for New Pathnames.
       1[H]* 1WITH-OPEN-FILE-CASE* and 1WITH-OPEN-STREAM-CASE* Defined.
       1[I]* 1PROBEF* Changed.

1[A]* 1ERROR-RESTART* Works Differently.

The meaning and usage of the 1ERROR-RESTART* special form have changed;
all uses will have to be modified.  The full details are in 1SYS: MAN; ERRORS TEXT*.

1[B]* Condition Handler Functions Called Differently.

 The calling conventions of condition handler functions (used in
1CONDITION-BIND*) have changed, so all uses of 1CONDITION-BIND* will have to be
modified.

1[C]* Interfacing with the 1ABORT* key.

Places for the 1ABORT* key to go back to are no longer created using the
catch tag 1SYS:COMMAND-LEVEL*.  In fact, a catch for this tag now has no effect.
The new way to define a place to abort to is to make a resume handler
for the 1SYS:ABORT* condition using 1CATCH-ERROR-RESTART*.  Example:

1    (CATCH-ERROR-RESTART ((SYS:ABORT ERROR) "Return to ~A loop." PROGNAME)*
	2...body...1)

[D]** 1ERROR-HANDLER-IO* renamed to 1DEBUG-IO.*

The stream used for interactive I/O by the debugger is now called 1DEBUG-IO.*
Furthermore, its default value is a synonym stream for 1TERMINAL-IO*,
rather than 1NIL*.

1[E]* Time-Parsing Functions Now Signal Errors.

The time-parsing functions 1TIME:PARSE-UNIVERSAL-TIME* and 1TIME:PARSE*,
and the chaosnet connection functions 1CHAOS:CONNECT* and 1CHAOS:SIMPLE*,
now signal errors when there is a problem with parsing the argument,
rather than returning a string describing the problem.  1CHAOS:FINGER* and
1CHAOS:WHOIS* also have this change.

1[F]* 1OPEN* and Other Functions Return Condition Instances.

1OPEN* and the other functions for operating on files still return an object
describing the error if the caller specifies 1:ERROR NIL*, but this object is now a
flavor instance rather than a string.  1ERRORP* returns 1T* for both error instances
and strings, in system 91.  In system 92, however, it will be changed to return
1NIL* for strings.  The two-step change is to give users time to convert.

1[G]* 1OPEN* and Other Functions No Longer Ask for New Pathnames.

3OPEN* and other file accessing functions now by default simply signal an error
for problems such as "file not found", rather than asking for a new pathname.  If
you would like to ask the user for a new pathname, you can specify the value
1:REPROMPT* for the 1ERROR-P* or 1:ERROR* argument; or you can use the special forms
1FILE-RETRY-NEW-PATHNAME* or 1WITH-OPEN-FILE-RETRY* which give the caller more
information about what is going on.

1FILE-RETRY-NEW-PATHNAME (2pathname-variable condition-names...*) 2body...**
  Executes 2body*, returning its values if it returns normally.
  If a condition with one of the condition names 2condition-names* is signaled
  during the execution of 2body*, then a condition handler set up by this
  macro reads a new pathname from 1QUERY-IO*, setq's 2pathname-variable* to it,
  and starts 2body* over again.  2pathname-variable* is not bound by the
  1FILE-RETRY-NEW-PATHNAME* form; it is used free.  Normally, on entry, its
  value will be the pathname you originally intend to use, and on exit you
  can expect it to contain the pathname actually opened, deleted or whatever.

1FILE-RETRY-NEW-PATHNAME-IF 2cond-form* (2pathname-variable condition-names...*) 2body...**
  Like 1FILE-RETRY-NEW-PATHNAME*, but provides the condition handler only
  if the value of 2cond-form* is non-1NIL*.

1WITH-OPEN-FILE-RETRY (2stream-var *(2pathname-var condition-names...*) 2options...*) 2body...**
  This is like 1WITH-OPEN-FILE* except that the opening is done using the value of
  2pathname-var* as the pathname, inside a 1FILE-RETRY-NEW-PATHNAME*.

1[H]* 1WITH-OPEN-FILE-CASE* and 1WITH-OPEN-STREAM-CASE* Defined.

These two new special forms are combinations of 1WITH-OPEN-FILE* or 3WITH-OPEN-STREAM*
with 1CONDITION-CASE* (see 1SYS: MAN; ERRORS TEXT*).  They allow you to open a stream,
use it, and close it, while dispatching on whether there was an error in opening,
and on what kind of error it was.

1WITH-OPEN-FILE-CASE (2stream-var pathname options...*) 2clauses...**

This opens the file and binds 2stream-var* just like 1WITH-OPEN-FILE*.  The
difference is that instead of a simple body made of forms to be executed, there
is a sequence of 2clauses* like the clauses in a 3SELECTQ*.  A clause starts with a
condition name or a list of condition names, or else with the keyword 1:NO-ERROR*.
This is followed in the clause by forms to be executed.

If opening the file succeeds (does not signal an error), the 1:NO-ERROR* clause is
executed.  Otherwise, the first clause whose condition names match the error is
executed.  Then 2stream-var* holds the condition instance that was signaled.  If no
clause matches, the error is not handled here; it may be handled elsewhere or it
may enter the debugger.

Example:

1   (WITH-OPEN-FILE-CASE (STREAM FILENAME ':CHARACTERS ':DEFAULT)
     (:NO-ERROR (SELECTQ (SEND STREAM ':CHARACTERS) ...))
     (FS:FILE-NOT-FOUND (FORMAT T "~&(New File)"))
     (ERROR (BARF "Error: ~A" STREAM)))  ;STREAM* here is the condition instance.

1WITH-OPEN-STREAM-CASE* is similar, but takes an explicit form which says
how to create the stream.

1[I]* 1PROBEF* Changed.

1PROBEF* now returns 1NIL* only for "file not found".
If any other error happens, 1PROBEF* does not handle it.  You can handle it
yourself with your own condition handler, established around the call to 1PROBEF.*

Programming Changes:
1    
    [A]* 1CATCH-CONTINUATION*.
1    [B]* 3READLINE-TRIM* 2stream* 2eof-option
1    [C]** 3(PROMPT-AND-READ* 2keyword3 *format-string3 *format-arguments3...)
1    [D]*** 3:FILL-POINTER* Keyword Argument to3 MAKE-ARRAY*.
1    [E]* 3WITH-STACK-LIST* and 3WITH-STACK-LIST**.
1    [F]* The Applyhook.
1    [E]* New Flavor Feature: 3:ABSTRACT-FLAVOR
1    [G]**3:CASE* Method Combination
1    [H]* 3(STRING-CAPITALIZE-WORDS 2string* &optional (2copy-flag* t))
1    [I]** Restrictions Lifted on 3UNWIND-PROTECT* and Peculiar Multiple-Value Constructs
1    [J]* 3:NEW-SUGGESTED-NAME* and 3:NEW-SUGGESTED-DIRECTORY* Pathname Operations.
1    [K]* Readmacros 1#M*, 1#Q*, 1#+*, 1#-* Work Better.
1    [L]* 1:ITEM* Operation on 1TV:TEXT-SCROLL-WINDOW* Changed.
1    [M]* Reading and Printing of Hex Numbers Improved.
1    [N]* 1CURRENT-STACK-GROUP* and 1CURRENT-STACK-GROUP-RESUMER*.
1    [O]* New Stack Analysis Functions.
1    [P]* Lambda List Keyword 1&KEY*.
1    [Q]* 2units* Argument to Window Operations 1:INSERT-LINE*, etc.
1    [R]* New 1DEFSTRUCT* Options.
1    [S]* New 1FORMAT* Directives1 ~$*, 1~\DATE\*, 1~\TIME\*, 1~\DATIME\*, 1~\TIME-INTERVAL\*.
1    [T]* Asynchronous Characters.
1    [U]* New Window Graphics Operations in 1TV:GRAPHICS-MIXIN*.
1    [V]* 1DONT-OPTIMIZE* Works Inside 1SETF*.
1    [W]* 1#?NIL* Allowed in 1SELECT-MATCH*.

1[A]* 1CATCH-CONTINUATION*.

The new special form 1CATCH-CONTINUATION* makes it easy to write a catch,
pass back all multiple values from its body, and still find out whether the
catch was exited normally or thrown to.  The syntax is

1CATCH-CONTINUATION* 2tagexp* 2throw-cont* 2non-throw-cont* 2body...

body* is executed with a catch for a tag which is the value of 2tagexp*.

If 2body* returns normally, what happens is determined by the value of
2non-throw-cont*, a function used as a continuation.  If it is 1NIL*, the values of 2body*
are simply returned.  Otherwise, they are passed as arguments to 2non-throw-cont*,
and 2its* values are returned.  Usually 2non-throw-cont* is 1NIL*.

If 2body* throws to this catch, the four standard values of 1*CATCH* are collected,
and what happens to them is determined by the value of 2throw-cont*, another
continuation.  If it is 1NIL*, those values are returned from the 1CATCH-CONTINUATION.*
Otherwise, they are passed to the continuation function, and its values are returned.

If the continuation function is written as 1#'(LAMBDA ...)*, then only as many
values are collected as the continuation function wants, and no consing is needed.
The continuation function is also open-coded.  This is the most usual form of use.

1CATCH-CONTINUATION-IF* is also provided.  Its first argument is a conditional form.
The catch is only in effect if the conditional's value is non-1NIL*.  The remaining
arguments are the same as those of 1CATCH-CONTINUATION*.

1[B]* 3READLINE-TRIM* 2stream* 2eof-option

3READLINE-TRIM** is line 3READLINE* except that any leading or trailing spaces and
tabs are discarded from the line before the value is returned.

3  (READLINE-TRIM 2args*...)*

is almost the same as

3  (STRING-TRIM '(#\SP #\TAB) (READLINE 2args*...))*

the difference being that3 READLINE-TRIM* will return the 2eof-option* on end of file
without trying to trim it.

1[C]* 3(PROMPT-AND-READ* 2keyword3 *format-string3 *format-arguments3...)**

The function 3PROMPT-AND-READ* serves to read and return an object after
prompting.  You specify the way to read the object with a keyword, and the way
to prompt with a string and arguments that are passd to 3FORMAT*.

The 2keyword* is one of these: 3:READ, :NUMBER, :EVAL-READ,* 3:EVAL-READ-OR-END,
:STRING, :STRING-OR-NIL, :PATHNAME.

:READ - *the object is read by calling 3READ*.
3:NUMBER* - the object is read by calling 3READ* in base ten.  If it is not a number,
  the user gets an error message and must rub it out and try over.
3:EVAL-READ* - the object is read by 3(EVAL (READ))*.
3:EVAL-READ-OR-END* - the object is read by 3(EVAL (READ))*.  However, the user
 can type the 3End* character instead of an object.  In this case, 3PROMPT-AND-READ*
 returns 3NIL* as the first value, and 3#\End* as the second.
3:STRING* - the object is read by 3READLINE*, so the value is a string.
3:STRING-OR-NIL* - the object is read by 3READLINE-TRIM*, except that if
 the resulting string is empty, 3NIL* is returned instead.
3:PATHNAME* - the object is read by 3(FS:MERGE-PATHNAME-DEFAULTS (READLINE))*.
3(:PATHNAME :DEFAULTS* 2defaults-list3)** - like just 3:PATHNAME*, except that
 2defaults-list* will be passed to 3FS:MERGE-PATHNAME-DEFAULTS* for use as the
 defaults.  2defaults-list* must be literally present in the list passed to
 3PROMPT-AND-READ*.

3PROMPT-AND-READ* always uses 3QUERY-IO* to do the i/o.  It uses the rubout handler
if the stream supports one, and tells the rubout handler how to reprint the
prompt when that is appropriate.

1[D]* 3:FILL-POINTER* Keyword Argument to3 MAKE-ARRAY*.

A new convenient way to make an array with a fill pointer is to use the
3:FILL-POINTER* argument to 3MAKE-ARRAY*.  The presence of this argument requests
a leader of length one, and the value of the argument is used to initialize the
leader slot.

  3(MAKE-ARRAY 5 ':TYPE ART-STRING ':INITIAL-VALUE #\A ':FILL-POINTER 2)
    => "AA"

1[E]** 3WITH-STACK-LIST* and 3WITH-STACK-LIST**.

These two new special forms allow you to create and use a list whose memory is
allocated inside the stack.  The list will automatically be reclaimed when the 
3WITH-STACK-LIST* is exited, with no permanent consumption of space; but you
had better have no pointers to the list at that time, for they will become garbled.

A use of 3WITH-STACK-LIST* looks like this:

  3(with-stack-list (2variable* 2list-elements*...)*
  3  2body*...)*

During the execution of 2body*, 2variable* will be bound to the temporary list.
2list-elements* are used as the elements when the list is constructed.
The stack list can be 3RPLACA*'d but it cannot be 3RPLACD*'d.

3WITH-STACK-LIST** is called like 3WITH-STACK-LIST*.  The only difference is that it
constructs the list to have a specified final cdr rather than 3NIL*--just as 3LIST**
does.

1[F]* The Applyhook.

The applyhook is a new companion to the old 3EVALHOOK* feature.  While the
evalhook is called when the interpreter calls 3EVAL*, the applyhook is called when
3EVAL* would normally call 3APPLY*.  (Never mind that 3EVAL* does not actually call
3APPLY* per se; it does something equivalent).

To use the applyhook, call 3EVALHOOK* with a third argument, which is the
applyhook function.  As usual, 3EVALHOOK* will evaluate its first argument; but if
that evaluation would apply a function, the applyhook is called instead.
The second argument to 3EVALHOOK*, if non-3NIL*, is used as the evalhook function,
which is called if the evaluation would call 3EVAL* recursively.

The applyhook function receives two arguments: the function that 3EVAL* was
about to apply, and the list of arguments the function was going to get.  These
are the same sorts of arguments that 3APPLY* expects.  An applyhook function
which simply passes its arguments to 3APPLY* is the same as no applyhook at all.

When either the applyhook function or the evalhook function is called,
both the applyhook and the evalhook are bound off.

1[E]* New Flavor Feature: 3:ABSTRACT-FLAVOR

:ABSTRACT-FLAVOR* is a new 3DEFFLAVOR* option.  Its purpose is to suppress the
warning that you would normally get from 3COMPILE-FLAVOR-METHODS* if there are
any required flavors, methods or instance variables that are missing.  This allows
you to do 3COMPILE-FLAVOR-METHODS* on a flavor which is not actually suited for
instantiation.  (This is useful if the combined methods of this flavor could be
inherited without change by several other flavors which can be instantiated).

Since 3:ABSTRACT-FLAVOR* is intended for flavors that are not suitable for
instantiation, it also marks the flavor so that you are not allowed to try to
instantiate it.  This is not logically necessary, but otherwise, once the
3COMPILE-FLAVOR-METHODS* had been done with its warning suppressed, you would
be able to instantiate the flavor with never any warning about the missing
required flavors, methods or instance variables.

1[G]*3:CASE* Method Combination

3:CASE* is a new type of method combination for flavor methods.

Recall that each type of method combination is a way of taking the various
methods for a given flavor and operation and deciding what order to call them
in, and how.  3:DAEMON* method combination, which looks for 3:BEFORE* and 3:AFTER*
methods, is just the default method combination type, not the only one.

3:CASE* method combination provides an automatic subdispatch on the first
argument to the operation.  Each method says which first argument it wants to
handle.  When a message is sent, only one method is called, according to the
first argument in the message.

For example, 

3  (defflavor foo (a b) ()
    (:method-combination :case :base-flavor-last :do-something))

  (defflavor bar (c) (foo))

  (defmethod (foo :case :do-something :print-a) ()
    (print a))

  (defmethod (foo :case :do-something :clear-b) ()
    (setq b nil))

  (defmethod (bar :case :do-something :set-c) (new-c)
    (*setq3 c* 3new-c))*

defines a 3:DO-SOMETHING* operation which, for flavor 3FOO*, understands only
3:PRINT-A* as its first argument, but for flavor 3BAR* understands either 3:PRINT-A* or
3:SET-C*.  3:PRINT-A* and 3:SET-C* are called 2suboperations*.  Each flavor can define
any number of 3:CASE* methods for the same operation if they are for different
suboperations.

You would use this operation in this manner:

3  (send my-bar ':do-something ':set-c 'new-value-for-c)*

The internals of 3:CASE* method combination would automatically dispatch to the
3(BAR :CASE :DO-SOMETHING :SET-C)* method to handle this.  Note that you do not
specify any argument variable in the 3DEFMETHOD* to correspond to the 3:SET-C*.

In addition to the 3:CASE* methods, you can also have a primary method.  It gets
called if none of the 3:CASE* methods applies; that is, when the suboperation
does not match any of the3:CASE* methods.  It is a sort of default handler.  It 2does*
receive the suboperation explicitly as an argument.

You can also have one or more 3:OR* methods.  These are called just before the
primary method, after determining that no 3:CASE* method applies.  If an 3:OR*
method returns non-3NIL*, that is the end: its first value is the value of the
operation.  If all the 3:OR* methods return 3NIL*, the primary method is used.

The suboperations 3:WHICH-OPERATIONS, :SEND-IF-HANDLES,
:OPERATION-HANDLED-P, :GET-HANDLER-FOR* and 3:CASE-DOCUMENTATION* are
handled specially and automatically.  The first four have meanings analogous to
the operations of the same name.  Note that they consider a suboperation to be
handled only if there is a 3:CASE* method for it.  3:CASE-DOCUMENTATION* takes one
argument, a suboperation, and returns the documentation string of the 3:CASE*
method for that suboperation, otherwise 3NIL*.

1[H]* 3(STRING-CAPITALIZE-WORDS 2string* &optional (2copy-flag* t))*

This function performs two transformations on 2string*: it changes all dashes into
spaces, and capitalizes each word.  The initial becomes upper case, and the rest
of each word lower case.

The original string is unchanged, and the value is a new string, unless 2copy-flag*
is 3nil*.

1[I]* Restrictions Lifted on 3UNWIND-PROTECT* and Peculiar Multiple-Value Constructs

3UNWIND-PROTECT* now interacts correctly with 3GO* and 3RETURN* in all cases.  For
example,

3  (prog ()
    (unwind-protect
      (print (if a b (go tag)) stream)
      (close stream))
   tag
    ...)*

will now close the stream even if the 3GO* takes place.

3RETURN* of multiple values to internal destinations now works also.  For example,

3  (multiple-value (a b)
    (prog ()
      (print (if c d (return base t)))
      (return ibase nil)))*

will set 3A* and 3B* properly, and no longer crash the machine.

These two improvements are often useful together, as in

3  (multiple-value (a b)
    (prog ()
      (unwind-protect
        (.... (return x y) ...)
        (close stream))))

1[J]** 3:NEW-SUGGESTED-NAME* and 3:NEW-SUGGESTED-DIRECTORY* Pathname Operations.

The 3:NEW-SUGGESTED-DIRECTORY* operation is nearly the same as the
3:NEW-DIRECTORY* operation, but it has a slightly different purpose.  The new
directory name is not precisely what is desired, but just a suggestion, based on
some sort of default.  For example, it might be a user name.  Similarly,
3:NEW-SUGGESTED-NAME* supplies a suggestion for the name, rather than a precise
desired name.  It might be the name of an editor buffer.

The difference between the actions of the new operations and the actions of
3:NEW-NAME* and 3:NEW-DIRECTORY* is that the new operations may make
file-system-dependent changes in their arguments.  For example, on systems
such as Twenex, where filenames can contain lowercase characters but normally
do not, the 3-SUGGESTED-* operations convert the name to upper case.

1[K]* Readmacros 1#M*, 1#Q*, 1#+*, 1#-* Work Better.

These read-time conditional constructs now do not intern the symbols in the
following s-expression, if the conditional fails.  As a result, there will be no
error if the s-expression contains symbols with package prefixes for packages
that do not, and should not, exist.

1[L]* 1:ITEM* Operation on 1TV:TEXT-SCROLL-WINDOW* Changed.

The 1:ITEM* operation on these windows is now compatible with the 1:ITEM*
operation provided by typeout windows.  As a result, objects which print
themselves in a mouse-sensitive fashion using the 1:ITEM* operation when it is
available will now work properly in the inspector.

The old calling conventions for the 1:ITEM* operation are now available as
the 1:ITEM1* operation.

1[M]* Reading and Printing of Hex Numbers Improved.

You can now read in Hexadecimal numbers successfully using either
1#X* or 1#16R* followd by the number.  However, in order to cause the
characters 1A* through 1F* to be recognized as digits, you must begin
the number with a sign (1+* or 1-*).

To print hexadecimal numbers, it suffices to set 1BASE* to 16 in any fashion.

1[N]* 1CURRENT-STACK-GROUP* and 1CURRENT-STACK-GROUP-RESUMER*.

These are new, global names for 1SI:%CURRENT-STACK-GROUP* and
1SI:%CURRENT-STACK-GROUP-PREVIOUS-STACK-GROUP.

[O]* New Stack Analysis Functions.

Several functions in the 1EH* package used for finding stack frames and extacting
arguments, locals, etc. from them are now documented in the file 1SYS: MAN; FD-SG TEXT.

[P]* Lambda List Keyword 1&KEY*.

This feature still exists as announced a year ago.  Refer to 1SYS: MAN; FD-EVA
TEXT*, until the new manual is out.

1[Q]* 2units* Argument to Window Operations 1:INSERT-LINE*, etc.

The operations 1:INSERT-LINE*, 1:DELETE-LINE*, 1:INSERT-CHAR* and 1:DELETE-CHAR*
now take two arguments.  The second argument says what units are used
to interpret the first argument.  If the second argument is 1:PIXEL*, then
the first argument is taken as the number of pixels of space to insert.
If the second argument is 1:CHARACTER*, which is the default, the first argument
is the number of characters or lines.

1[R]* New 1DEFSTRUCT* Options.

There are three new options for 1DEFSTRUCT*: 1:PRINT*, 1:PREDICATE* and 1:COPIER.*

1) 1:PRINT*

This allows the user to control the printed representation of his structure in
an implementation independent way:
1    
    (DEFSTRUCT (FOO :NAMED
                (:PRINT "#" (FOO-A FOO) (FOO-B FOO)))*
	1FOO-A*
	1FOO-B)*

The arguments to the 1:PRINT* option are arguments to the 1FORMAT* function (except
for the stream of course!).  They are evaluated in an environment where the
name symbol of the structure (1FOO* in this case) is bound to the instance of the
structure to be printed.

This works by creating a simple named structure handler.  You should not use
the 1:PRINT* option if you are defining a named structure handler explicitly.

2) 1:PREDICATE*

The 1:PREDICATE* option causes 1DEFSTRUCT* to generate a predicate to recognize
instances of the structure.  Naturally it only works for "named" defstruct types1.*
The argument to the 1:PREDICATE* option is the name to give the predicate.  If it
is present without an argument, then the name is formed by concatenating "1-P*"
to the end of the name symbol of the structure.  If the option is not present,
then no predicate is generated.  Example:

1    (DEFSTRUCT (FOO :NAMED :PREDICATE)*
	1FOO-A*
	1FOO-B)*

defines a single argument function, 1FOO-P*, that is true only of instances of
this structure.

3) 1:COPIER*

This option causes 1DEFSTRUCT* to generate a single argument function that will
copy instances of this structure.  Its argument is the name of the copying
function.  If the option is present without an argument, then the name is
formed by concatenating "1COPY-*" with the name of the structure.  Example:

1    (DEFSTRUCT (FOO (:TYPE :LIST) :COPIER)*
	1FOO-A*
	1FOO-B)*

Generates a function approximately like:

1    (DEFUN COPY-FOO (X)*
	1(LIST (CAR X) (CADR X)))

[S]* New 1FORMAT* Directives1 ~$*, 1~\DATE\*, 1~\TIME\*, 1~\DATIME\*, 1~\TIME-INTERVAL\*.

1~$

3~2rdig*,2ldig*,2field*,2padchar*** 3$* prints 2arg*, a flonum, with exactly
2rdig* digits after the decimal point.  The default for 2rdig* is 2,
which is convenient for printing amounts of money.

At least 2ldig* digits will be printed preceding the decimal point;
leading zeros will be printed if there would be fewer than 2ldig*.
The default for 2ldig* is 1.  The number is right justified in a field 2field*
columns long, padded out with 2padchar*.  The colon modifier means
that the sign character is to be at the beginning of the field, before
the padding, rather than just to the left of the number.  The atsign modifier
says that the sign character should always be output.

If 2arg* is not a number, or is unreasonably large, it will be printed
in 3~2field*,,,2padchar*@A* format; i.e. it will be 3PRINC*'ed
right-justified in the specified field width.

1~\DATE\*

This expects an argument which is a universal time, and prints it as a date and
time using 3TIME:PRINT-UNIVERSAL-DATE*.  Example:
1    (FORMAT T "It is now ~\DATE\" (TIME:GET-UNIVERSAL-TIME))*
prints
1    It is now Saturday the fourth of December, 1982; 4:00:32 am

~\TIME\*

This expects an argument which is a universal time and prints it in a brief
format using 3TIME:PRINT-UNIVERSAL-TIME*.  Example:
1    (FORMAT T "It is now ~\TIME\" (TIME:GET-UNIVERSAL-TIME))*
prints
1    It is now 12/04/82 04:01:38

~\DATIME\*

This prints the current time and date.  It does not use an argument.
It is equivalent to using the 3~\TIME\* directive with
3(TIME:GET-UNIVERSAL-TIME)* as argument.

1~\TIME-INTERVAL~\*
This prints a time interval measured in seconds using the function
3TIME:PRINT-INTERVAL-OR-NEVER*.  Example:

1    (FORMAT T "It took ~\TIME-INTERVAL\." 3601.)*
prints
1    It took 1 hour 1 second.

[T]* Asynchronous Characters.

The characters 1Control-ABORT* and 1Control-Meta-BREAK* are examples of
"asynchronous characters", characters processed specially as soon as they are
typed, even if the program is not reading input.  Programs can now define
their own asynchronous characters on a per-window basis.  This facility is
provided by the flavor 1TV:STREAM-MIXIN.*

The basic way to specify the asynchronous characters for a window is with the
init option 1:ASYNCHRONOUS-CHARACTERS* in 1TV:MAKE-WINDOW.*  The value you
specify should be an alist of characters and their handlers.  Each element of the
alist contains a character, a function to call, and some additional arguments to
pass to the function.  When the function is called, its arguments will be the
character typed (the same function can handle more than one character),
the selected window, and any specified additional args.

If the init option 1:ASYNCHRONOUS-CHARACTERS* is not specified, the default comes
from the value of 1TV:KBD-STANDARD-ASYNCHRONOUS-CHARACTERS*, the initial value
of which is
    1'((#\C-ABORT TV:KBD-ASYNCHRONOUS-INTERCEPT-CHARACTER*
	1(:NAME "Abort" :PRIORITY 50.)*
	1TV:KBD-INTERCEPT-ABORT)*
      1(#\C-M-ABORT TV:KBD-ASYNCHRONOUS-INTERCEPT-CHARACTER*
       1(:NAME "Abort All" :PRIORITY 50.)*
       1TV:KBD-INTERCEPT-ABORT-ALL)*
      1(#\C-BREAK TV:KBD-ASYNCHRONOUS-INTERCEPT-CHARACTER*
       1(:NAME "Break" :PRIORITY 40.)*
       1TV:KBD-INTERCEPT-BREAK)*
      1(#\C-M-BREAK TV:KBD-ASYNCHRONOUS-INTERCEPT-CHARACTER*
       1(:NAME "Error Break" :PRIORITY 40.)*
       1TV:KBD-INTERCEPT-ERROR-BREAK))*

An asynchronous character is handled by a process called the 2keyboard process*.  It
handles the character by calling a function associated with it.  The function runs
in the keyboard process rather than your program's process, and must obey some
strict conventions.  It must not do any I/O, or wait for anything; it should not
run for very long; it should not get an error.  It is usually easiest to create
another process and do the real work there, using 1PROCESS-RUN-FUNCTION*.  This
is usually done with the function1 TV:KBD-ASYNCHRONOUS-INTERCEPT-CHARACTER*.
It is used with two additional arguments: the process name and options for
1PROCESS-RUN-FUNCTION*, and the function to call in the new process.

You can examine and change a window's asynchronous characters with these
window operations:

1:ASYNCHRONOUS-CHARACTER-P 2character**

  Returns non-1NIL* if the window defines 2character* to be an asynchronous
  character.

1:HANDLE-ASYNCHRONOUS-CHARACTER 2character**

  Run the handler associated with the asynchronous character 2character*.
  This runs the handler function in your current process.  But since most
  handler functions just do 1PROCESS-RUN-FUNCTION*, it probably doesn't matter.

1:ADD-ASYNCHRONOUS-CHARACTER 2character handler-function *&REST 2additional-args**

  Add 2character* to this window's list of asynchronous characters, defined to
  call 2handler-function*.  2additional-args* are passed to the handler function
  when it is called.  The arguments to this operation, all of them, simply become
  the alist element.

1:REMOVE-ASYNCHRONOUS-CHARACTER 2character**

  Removes 2character* from this window's list of asynchronous characters.

1[U]* New Window Graphics Operations in 1TV:GRAPHICS-MIXIN*.

1:DRAW-CIRCULAR-ARC* 2center-x center-y radius start-theta end-theta 1&OPTIONAL* alu*

  This operation draws a specified part of a circle centered at the point
  2center-x*, 2center-y* and of radius 2radius*.  The part of the circle to be drawn
  is specified by 2start-theta* and 2end-theta*.  Both angles should be in the
  interval 1[0,2)*; an angle of zero goes to the right, and small positive
  angles point slightly upward.  The arc starts at 2start-theta* and goes through
  increasing angles, passing through zero if necessary, to stop at 2end-theta.

  alu* controls how the points are drawn (or erased).

1:DRAW-CLOSED-CURVE* 2px py 1&OPTIONAL** 2end alu*

  This is the same as the 1:DRAW-CURVE* operation except that the last point is
  connected back to the first.  2px* and 2py* are vectors of coordinates, and 2end*
  is an optional index in those arrays to stop drawing at.

1:DRAW-DASHED-LINE 2x0 y0 x1 y1** 3&OPTIONAL* 2alu
1    (*dash-spacing1 20.) *space-literally-p1 (*offset1 0)
    (*dash-length1 (FLOOR *dash-spacing1 2)))**

  This operation draws a line divided into dashes.  The first five arguments are
  the same as those of the 1:DRAW-LINE* operation.

  The argument 2dash-spacing* specifies the period of repetition of the dashes;
  it is the length of a dash plus the length of a space between dashes.
  2dash-length* is the length of the actual dash; it defaults to half the spacing.

  If 2space-literally-p* is 1NIL*, the spacing between dashes is adjusted so that
  the dashes fit evenly into the length of line to be drawn.  If it is non-1NIL*,
  the spacing is used exactly as specified, even though that might put the
  end point in the middle of a space between dashes.

  A nonzero 2offset* is used if you want a space between the starting point and the
  beginning of the first dash.  The value is the amount of space desired, in
  pixels.  The same space will be provided at the end point, if 2space-literally-p*
  is 1NIL*.

1[V]* 1DONT-OPTIMIZE* Works Inside 1SETF*.

1DONT*-1OPTIMIZE*, which is used around calls to 1DEFSUBST*s to avoid expanding them
at compile time, can now be used inside a 1SETF*.  For example,

    1(SETF (ZWEI:BUFFER-PACKAGE BUFFER) (PKG-FIND-PACKAGE "USER"))*

sets the package of 1BUFFER*, but needs to be recompiled if the definition of
1BUFFER-PACKAGE* is changed.

    1(SETF (DONT-OPTIMIZE (ZWEI:BUFFER-PACKAGE BUFFER))*
	1   (PKG-FIND-PACKAGE "USER"))*

does the same job but never needs to be recompiled.

1[W]* 1#?NIL* Allowed in 1SELECT-MATCH*.

1#?NIL* may now be used in a 1SELECT-MATCH* pattern to match anything and bind
no variable.
1
User* Interface Changes:

    1[A]* 1LOGIN* Calling Conventions Change.
    1[B]* Debugger Command 1Control-M* for Sending Bug Reports.
    1[C] *New Calling Conventions for 1APROPOS*.
    1[D]* 1ZWEI:*DEFAULT-MAJOR-MODE** Values Change.
    1[E]* 1ZWEI:EDITING-TYPE *Property.
    1[F]* Reading Files into ZWEI May Look Slower, But It Is Not.
    1[G]* 1M-X Find File No Sectionize*.
    1[H]* New Editor Variable 1ZWEI:*ONE-WINDOW-DEFAULT* *Controls 1C-X 1.*
    1[I]* 1C-M-.* is 1Edit Zmacs Command*.
    1[J]* Balance Directories Editor.
    1[K]* 3COMPILER:COMPILER-VERBOSE*.
    1[L]* Compiler Peephole Optimizer1.*
    1[M]* 1DUMP-FORMS-TO-FILE* Writes A QFASL File.
    1[N]* Completion in 1M-X Bug*.  How to Add New Bug Report Lists. 
    1[O]* Negative Arguments Allowed in the Rubout Handler.
    1[P]* Wait States for Chaosnet Connecting Show the Host Name.
    1[Q]* New Function 1LISTF* Lists a Directory.
    1[R]* 1DISASSEMBLE* Now Describes Any Complex Function Entry Initializations
    1[S]* Better Truncation of Pathnames in the Who Line
    1[T]* 1(DECLARE (VALUES ...))*
    1[U]* 1GC-IMMEDIATELY*.
    1[V]* PEEK Improvements.
    1[W]* New function 1(teach-zmacs)*.
    1[X] M-X Teach Zmacs

[A]* 1LOGIN* Calling Conventions Change.

The sense of the third argument to 1LOGIN* is now reversed.
1T* now means 2do not* load the init file, and 1NIL* (the default) means do load it.
This is so that the 1T* in 1(LOGIN "FOO" "OZ" T)* means the same thing as the 1T*
in 1(LOGIN "FOO" T)*.

1[B]* Debugger Command 1Control-M* for Sending Bug Reports.

In the debugger, you can conveniently send a bug report containing the error
message and a backtrace by typing 1Control-M*.  This puts you into an editor
window by calling the function 1BUG*, and preinitializes it with the error message
and stack information.  You edit in your description of the circumstances
and type 1End*.

The new 1:MAIL* command in CC performs a similar function for reporting
bugs that crash the machine.  It sends a report starting with the same text that
1:WHY* prints.

1[C] *New Calling Conventions for 1APROPOS*.

1APROPOS* used to take arguments 2substring* 2package superiors inferiors dont-print.*

Now all but the first argument are keyword arguments.  The keywords are
  1:PACKAGE* -- specify the package to look through.  Default is 1GLOBAL*.
  1:SUPERIORS* -- if 1NIL*, the superiors of that package are not searched.
     The default is 1T*.
  1:INFERIORS* -- if 1NIL*, the subpackages of that package are not searched.
     The default is 1T*.
  1:DONT-PRINT* -- if non-1NIL*, the symbols are not printed when they are found.
     Then the only thing 1APROPOS* does is return a list of them.
  1:PREDICATE* -- if non-1NIL*, a predicate to filter symbols with.
     A symbol is ignored unless the predicate returns non-1NIL*.
     For example, use 1FBOUNDP* to find only defined functions.

1SUB-APROPOS* has been changed in the same fashion.
It takes two positional arguments, the substring and a list of symbols,
and then allows 1:PREDICATE* and 1:DONT-PRINT* as keyword arguments.

1[D]* 1ZWEI:*DEFAULT-MAJOR-MODE** Values Change.

The meaningful values of this variable used to be symbols such as
1ZWEI:LISP-MODE*.  They are now keywords such as 1:LISP*.  The values you can
use here are keywords which are the name of a mode, without the "1-MODE*", just
like what you would use in 1ZWEI:*MAJOR-MODE-TRANSLATIONS** or
1FS:*FILE-TYPE-MODE-ALIST*.

[E]* 1ZWEI:EDITING-TYPE *Property.

A ZWEI mode symbol such as 1ZWEI:LISP-MODE* may have a 1ZWEI:EDITING-TYPE*
property which says how to analyze the syntax of the contents of the file.  The
two defined values for this property are 1:LISP* and 1:TEXT*.  1:LISP* means to
assume Lisp syntax, and 1:TEXT* means to recognize some kinds of text-justifier
input syntax.

For example, when files are scanned for definitions for the sake of the 1Meta-.*
command, 1:LISP* means look for lines starting with "1(DEF"*, etc., whereas 1:TEXT*
means to look for lines starting with "1.def*", which might identify the
documentation of some object, in a text justifier input file.

1[F]* Reading Files into ZWEI May Look Slower, But It Is Not.

Files used to be divided up into sections as they were read into the editor.
Now the whole file is read in, and then divided up into sections.
This is done to fix a class of bugs in sectionization.

The result is that the file is read in quickly, and then there is a long pause at
end of file.  Tests show that the total amount of time taken is about the same as
it used to be.

1[G]* 1M-X Find File No Sectionize*.

This editor command is like 1C-X C-F* except that it does not search the file
for definitions and record them for 1Meta-Period*.  It is useful if you do not
want 1Meta-Period* to see the definitions in that file (for example, if it is
an old version, and you want 1Meta-Period* to show you the latest version always).

If you do 1M-X List Sections*, 1M-X List Buffer Changed Sections*, or any other
command which specifically operates on the sectionization of the buffer, it will
be sectionized then.  In system 92 this will be changed not to sectionize the
buffer ever1 *unless you give an explicit 1M-X Sectionize Buffer* command.

1[H]* New Editor Variable 1ZWEI:*ONE-WINDOW-DEFAULT* *Controls 1C-X 1.*

Which window is selected after a 1C-X 1* command is determined by the value of
1ZWEI:*ONE-WINDOW-DEFAULT**.  The possibilities are:

  1:TOP* -- leave the uppermost window selected.
  1:BOTTOM* -- leave the lowest window selected.
  1:CURRENT* -- leave the selected window selected.
  1:OTHER* -- select the uppermost window other than the window selected now.

1:CURRENT* is the default.

In any case, a numeric argument tells 1C-X 1* to leave the selected window selected.
If there is no numeric argument, 1C-X 1* will never pick a window whose buffer
is in 1Warnings* mode; it will used the other window.

1[I]* 1C-M-.* is 1Edit Zmacs Command*.

This command asks you to type another editor command, and visits the source
for that command.  The command you visit can include prefix characters such as
1Control-X*, and it can also be an extended command starting with 1Meta-X* or
1Control-Meta-X*.

1[J]* Balance Directories Editor.

In addition to the function 1FS:BALANCE-DIRECTORIES*, which was
implemented in System 89, there is now a ZWEI interface 1M-X BDIRED.*
This command will prompt for two pathnames.  The pathnames default
1to* name and type wild, version newest.  Given the pathnames, two
directory lists are made, and these lists are then compared.  The
resulting directory lists are displayed in normal 1DIRED* format,
one above the other, with "T" next to each file that needs to be
transferred to the other directory.  The algorithm used to determine
which files are to be transferred is identical to that used by
1FS:BALANCE-DIRECTORIES*.

Once the buffer is displayed, you can move around in it in much the
same way as in 1DIRED*.  By means of the T and U commands it is
possible to edit which files will actually get transferred.  The
1End* key terminates the editing process and causes the transfers
to take place.

1[K]* 3COMPILER:COMPILER-VERBOSE*.

If this variable is non-3NIL* the compiler prints a message at the beginning of
each function it compiles, stating the function's name.

1[L]* Compiler Peephole Optimizer1.*

There is now an optimizer that works on the code generated by the compiler.
This should be of no concern to you unless you suspect you are running into a
bug in it.  If so, you can set the variable 1COMPILER:PEEP-ENABLE* to 1NIL* and recompile.

The peephole optimizer is extremely fast, examining few instructions more than once,
so there is no other reason to turn it off.  The code is available to everyone.

1[M]* 1DUMP-FORMS-TO-FILE* Writes A QFASL File.

The function 1DUMP-FORMS-TO-FILE* can be used to construct a QFASL file
that when loaded performs arbitrary actions you specify.  The calling sequence is

1DUMP-FORMS-TO-FILE 2filename forms-list** 3&optional* 2attribute-list*

This writes a QFASL file named 2filename* which contains, in effect, the
forms in 2forms-list*.  That is to say, when the file is loaded, its
effect will the same as evaluating those forms.  Example:

1    (dump-forms-to-file "foo" '((setq x 1) (setq y 2)))
    (load "foo")
    x => 1
    y => 2

2attribute-list** specifies the file attribute list to store in the QFASL file.  It is a
list of alternating keywords and values, and corresponds to the 1-*-* line of a
source file.  The most useful keyword in this context is 3:PACKAGE*, whose
value in the attribute list specifies the package to be used both in dumping the
forms and in loading the file.  If no 3:PACKAGE* keyword is present, the file will
be loaded in whatever package is current at the time.

1[N]* Completion in 1M-X Bug*.  How to Add New Bug Report Lists. 

The editor command 1M-X Bug* now offers completion.  The primary benefit is
that you can type 1Control-?* and get a list of the standard bug reporting lists.

There are two ways you can add another entry to the list of standard bug report
addresses.  The function 1ZWEI:ADD-BUG-REPORT* takes two arguments, the
name to send mail to and a line of documentation (both strings).
Alternatively, you can define a bug report list when you define a system.
Use the 1DEFSYSTEM* keyword 1:BUG-REPORTS* in a list like this
1    (:BUG-REPORTS "MYSYSTEM" "Report a bug in MYSYSTEM.")*
in your 1DEFSYSTEM*.

1[O]* Negative Arguments Allowed in the Rubout Handler.

Yes, you can now do 1Meta-Minus Meta-C.

[P]* Wait States for Chaosnet Connecting Show the Host Name.

1[Q]* New Function 1LISTF* Lists a Directory.

1[R]* 1DISASSEMBLE* Now Describes Any Complex Function Entry Initializations

When you 1DISASSEMBLE* a function which provides complicated default values for
optional arguments or 1&AUX* variables as part of function entry, it used to be hard
to tell what was going on, since the compiled code per se does not explain it.

Now 1DISASSEMBLE* prints a description of such variable binding activities at the
beginning of the output.

1[S]* Better Truncation of Pathnames in the Who Line

You may notice that, when you are doing file i/o, the who line tries to be intelligent
about what part of the filename to truncate from, if it will not all fit.

1[T]* 1(DECLARE (VALUES ...))

(DECLARE (VALUES 2variables...*))* is now equivalent to 1(DECLARE (RETURN-LIST 2variables...*))

[U]* 1GC-IMMEDIATELY*.

This function performs a complete garbage collection, in the current process.
It is the same as the guts of 1SI:FULL-GC*; but it does not reset temporary areas
or run the 1FULL-GC* initializations.  Use 1SI:FULL-GC* before saving a band, and
1GC-IMMEDIATELY* if you are going to continue running the machine.

1[V]* PEEK Improvements.

PEEK no longer does weird things when the 1ABORT* key is typed.

The 1Space* key is now a command that tells PEEK to update its display immediately.

While looking at the display of chaosnet connections, you can mouse on the
words "1Connection to 2contactname**" to get a menu of operations on the
connection, including closing the connection.  You can also mouse on the host name
to get some operations that pertain to the host.

1[W] (teach-zmacs)*

This new function makes a private copy, if needed, of the ZMacs tutorial file 
1SYS: ZWEI: TEACH-ZMACS* 1TEXT*, then enters ZMacs with that file specified.
The tutorial file is based on the one used by Teach-EMACS, with appropriate
changes for the Lisp Machine.

1[X] M-X Teach Zmacs*

This does much the same thing as the function, but from within an editor.
`
A Comparison of the MIT and Symbolics Error Systems

[A] Major Differences

The primary difference between the MIT new error system and the Symbolics
one is that theirs requires defining a new flavor whenever a condition is to
be signaled in a slightly different way.  This required the creation of a very
large number of new flavors, greatly increasing the size of the saved world.
It is also a hassle for the user who wishes to define ways of signaling errors.

In the MIT system it is not necessary to define a new flavor just to represent a
hierarchy of classifications of conditions.  Additional condition names can be
specified in a signal name, instead.

In the Symbolics system, to remember an additional piece of information in a
condition instance, one must define a new flavor and give it an instance variable.
This works in the MIT system as well, but it is easier to use 1DEFSIGNAL* and
the "implicit instance variable" feature.

The cost of this is that in addition to the concept of condition flavor names, one
must know the concepts of condition names and signal names.

Another significant difference is that in the MIT system it is possible to signal
the same condition instance more than once.  The Symbolics documentation says
this is forbidden; I do not know what would happen if you tried.  This is useful
in several ways.  For one thing, it makes the 3ABORT* key much faster.  For
another, the caller of 1OPEN* could call with 1:ERROR NIL* and then possibly resignal
the condition instance that 1OPEN* returns.  A 1CONDITION-CASE* handler can do this
too.  (I don't know yet whether this is useful).  Finally, a condition handler can
recursively signal the condition it is handling; this provides for a clean solution
to the problem of generalizing default handlers, which the Symbolics
documentation throws up its hands at.  (I did not have this in mind when I
decided to make conditions resignalable; my intuition told me it would be good
for something).

Another difference is that the Symbolics system makes restart handlers and
proceeding two ideosyncratically different things.  In the MIT system, restart
handlers are just proceed types that are provided nonlocally rather than by the
immediate signaler.  The 1:USER-PROCEED-TYPES* operation does the same job as
the Symbolics "special commands" feature, but in a simpler and more general
way.

Also, in the MIT system I have tried to preserve the usefulness of the old
error-signaling functions 1FERROR* and 1CERROR*.  Rather than being semi-obsolete,
they are perfectly good ways of signaling errors, using their traditional calling
conventions.  The amount of change required to old programs is thus much less.

[B] Compatibility

Nearly all the condition-2handling* facilities of the MIT system are upward
compatibile with those of the Symbolics system.  The standard system condition
names are also for the most part the same, and the same extra operations and
proceed types are provided.  So no special care is needed to move between
systems for simple programs that only handle conditions.

The main exception is that you must use 1CONDITION-TYPEP* in place of 1TYPEP*,
if you want to look at a condition instance and ask whether it has a certain
condition name.  Also, a few operations work only inside condition handlers,
including 1:PROCEED-TYPES*, because they refer to global variables bound by
1SIGNAL-CONDITION* rather than to instance variables (the condition
instance does not contain information about the particular signaler, since
that would not be reentrant).

For 2signaling* conditions, the MIT system is upward compatible in its general
facilities, with a few exceptions.  Flavors which would work in the Symbolics
system will also work, the same way, in the MIT system.  However, the standard
system conditions, which in the Symbolics system are all flavor names, are
mostly just condition names in the MIT system.  As a result, your flavor
definition may refer to flavors which do not exist.  If this happens, your best bet
is just to 2define the flavor yourself*.  Write a definition which "could have been
used to define it" in the Symbolics system, and use it in the MIT system.
The system will not be confused by the existence of a flavor it does not know
about, with the same name as a condition it is using, and handlers will not care
whether the condition name came from a flavor component or from a 3DEFSIGNAL*.

The MIT system expects signalers to specify exactly which proceed types they
will handle.  The function 3SIGNAL* will still default this as in the Symbolics
system, but the flavor definitions of the MIT system may define more proceed
types than you expect.  Mentioning them explicitly will not hurt.  (I think the
feature of defaulting them is a bad idea).

Many Symbolics ways of doing things exist, undocumented, in the MIT system,
for compatibility only (because more general or better ways of doing those
things are recommended).  These include special commands, the handling of the
1:PROCEED* operation, and 3EH:1INVOKE-RESTART-HANDLERS**.  1DBG:* is accepted as a
synonym of EH:.
    

Last modified: 2021/08/24 14:29:11 (UTC) by ams