Sunday December 9,1979  FM+5D.18H.52M.12S. LISP 1914/COMPLR 904  - JONL, RWK - 

WARNING!  The two new macro-characters, items 1 and 2 below, may become 
    standard someday (set up as macros in the initial lisp environment); 
    anyone who will have trouble accommodating should send mail to BUG-LISP.

1)  +INTERNAL-#-MACRO is autoloadable, for use as a reader-macro-character 
    function for "#";  fully compatible with NIL/LISPM usage.
2)  +INTERNAL-/"-MACRO is defined for use in making " a string macro character.
    TTYSCAN-STRINGERS| helps TTY-rubout processing in string-like sequences.
3)  Two **INCOMPATIBILITIES**:
      Carriage-Return, no longer invisible,  is now a "white-space" character.
      TERPRI is initially non-null, meaning no automatic insertion of <cr>'s.
4)  PROG1 -- Like PROG2 but return first argument instead of second.
5)  SETF is an FSUBR like the LISPM's general update operator
    DEFSETF is an autoloadable macro to help one extend the SETF range.
6)  As on LISPM, PUSH and POP have been extended to use SETF instead of SETQ.
7)  INCLUDEF is a subr version of INCLUDE, for the sake of transportable code.
8)  A new "Software device" convention for NAMELIST-series functions.
    Namelists of the form ((LISP) * *) refer to the maclisp system area.
9)  LDB and DPB and other new AUTOLOADable software as fasl file on LISP:
    files  ((LISP) DEFVST FASL),  ((LISP)  MACAID FASL),  ((LISP) LODBYT FASL) 
10) VSAID  - VECTOR support package; STRING - support and  NILAID on LISP:
11) (STATUS FILESYSTEM-TYPE), (STATUS OPSYSTEM-TYPE), and (STATUS SITE)
    Warning! (LAST (STATUS FEATURES)) for non-ITS systems will be different.
12) Some things that failed to be documented previously about DEFUN/DEFUN&
    &WHOLE  -  DEFMACRO now permits a keyword &WHOLE, to get at whole call form
    DEFUN reverts to DEFUN& "if necessary"; e.g. for keywords and destructuring
13) FRETRY, a new function which is in many ways like FRETURN.
14) The setting of "+" in the toplevel and break loops modified.
15) SPRIN1, a Pretty-printing version of PRIN1 autoloadable from GRINDEF
16) CLEAR-INPUT and CLEAR-OUTPUT on SFA's now works

17) USERATOMS-HOOKS,  for compiling user-defined  "SQUIDified" datatypes  
18) EOF-COMPILE-QUEUE, for queueing forms to be "done" at the end of file.

____________________________________________________________________________

** NOTE **  In the commentary which follows, this marker marks sections 
** NOTE **  explaining features not yet present on the LISP machine.  
** NOTE **  At some point in the future it is expected they will be added, 
** NOTE **  but in the interim, people writing code for both systems should 
** NOTE **  be careful.

1) +INTERNAL-#-MACRO is autoloadable, for use as a reader-macro-character 
   function for "#";  fully compatible with NIL/LISPM usage.
     +INTERNAL-#-MACRO  is provided with an autoload property such that
   if the user does (SETSYNTAX '/# 'SPLICING '|+INTERNAL-#-MACRO|) he will
   get a MACLISP/LISPM/NIL compatible version of the read macro character 
   for #.  Lately, this "generalized" macro character has been especially 
   useful for conditionalizing out lines of code based on which dialect of
   lisp the code is being read into.  Needless to say, it would be nice
   if users could begin to accommodate this macro-character definition,
   so that it can turned initailly on some day - it currently is
   set on by LISPM and NIL.
       The read-time meaning of a "#" instance is determined by a "dispatch"
   character, which immediately follows the "#" (except when there is a 
   numeric "argument", in which case the base-10. digits occur between the 
   "#" and the dispatch character, or if there is a "control,meta" argument
   in which case the argument is between the "#" and the dispatch).  
   The dispatch character is completely programmable (by the user too) in 
   essentially the same way that macro characters in general are programmable.
       The function SETSYNTAX-SHARP-MACRO is like SETSYNTAX, but is for the 
   meanings of the character following a #.  However, the associated function 
   must take one argument, which will be bound to any "argument" as indicated
   above - null for no argument, a fixnum if the argument is a digit string,
   and a symbol if the argument is one of ^B ("CONTROL"), ^C ("META"), 
   or ^F ("CONTROL-META").   DEFSHARP, an autoloadable macro,  provides an 
   easy way to set up "macro character functions", to which the general # 
   macro character function will dispatch, depending on the character 
   immediately following the #.
	(DEFSHARP /% (() ) (MACROEXPAND (/#SUB-READ () READ-STREAM)))
   defines (and activates using SETSYNTAX-SHARP-MACRO) a function to be run 
   when #% occurs.  There are several more options, for which the interested 
   party is referred to the commentary in the source code near the definition
   of DEFSHARP.

	Currently, the following characters are set up as "SHARP-MACRO"s:
   /  -  Input the following character, and give out its ascii value - 
	 thus #/A  yields 65. (101 octal).   A "cntrl,meta" argument will 
	 add in amount to make a 9-bit ascii code, with "cntrol" adding 2^7, 
	 and "meta" adding 2^8;  thus #/A yields 449. (701 octal).
   ^  -  Input the following character, and XOR 2^6 into its ascii value - 
	 this generally has an effect similar to holding the control key
	 down while typing that character.  Any argument is ignored.
   .  -  Read-time ealuation of the next form.  Any argument is ignored.
	 Thus,  (A #.(1+ BPORG) B)  might read in like (A 125755 B).
   ,  -  Load time evaluation of the next form.  "#," is the same is "#."
	 except when compiling, in which case a "SQUID" is returned.
	 Any argument is ignored.
   %  -  Read-time macro expansion;  thus #%(FOO 3)  will be read in
	 like  #.(MACROEXPAND '(FOO 3))
   '  -  #'<foo> reads in like (FUNCTION <foo>).  Any argument is ignored.
   *  -  Numeric read in the "natural base" or your machine - thus for
	 the PDP10 and LISPM,  #*xxxx*  will read the digits "xxxx" in
	 octal; likely some other machines will use hexadecimal.
	 Any argument is ignored.  [This is intended for use by machine
	 dependent code.]
   \  -  Following this is an alphabetic name of a character, and its
	 ascii value is returned; as with "#/", a "cntrl,meta" argument
	 will potentially convert to a 9-bit code.  The correspondence
	 between names and values is as follows:
	NULL - 0,  BS - 8,  BACKSPACE - 8.,  TAB - 9,  
	LF - 10.,  LINEFEED - 10.,  VT - 11.,  FF - 12.,  FORMFEED - 12., 
	CR  - 13.,  RETURN - 13.,  NL - 13.,  NEWLINE - 13.,  ALTMODE - 27.,  
	SP - 32.,  SPACE - 32., RUBOUT - 127.,  DELETE - 127., 
	ALPHA - 2,  BETA - 3,  EPSILON - 6,  HELP - 2110. BELL - 7.,
	FORM - 12., BACK-NEXT - 31.
   +  -  Next form should be a feature name, or boolean combination of
	 feature names, and the form after that will be read in and flushed  
	 unless the specified featues are on the (STATUS FEATURES) list.
	 E.g.   (A #+SAIL B C)   
	    Will be "(A B C)" on the SAIL system but "(A C)" elsewhere.
		(A #+(and (or VSAID STRINGS) (not EXPERIMENTAL)) B C)
	    As above, but the "B" is present only for non-experimental
	    systems which have either a VSAID or STRINGS feature.
   -  -  Just like "+" above, but with the sense reversed.  Thus
	 #-{...}  is equivalent to #+(not {...})
   M  -  Equivalent to #+MACLISP 
   N  -  Equivalent to #+NIL, except that additional NIL syntax is
	 permitted in the forms to be passed over.  For example,
	 #B"10110" and #T  and #(...)  would normally be illegal for
	 maclisp, but within the scope of a #N they are readable
	 (for the primary purpose of correct parsing, since they would
	 normally be thrown away; but if the NILAID pacakge is present,
	 supporting a sort of NIL-in-maclisp, then a cooperative answer 
	 is returned).
   O  -  Octal reading - a number should follow
   Q  -  Equivalent to #+LISPM 
   R  -  Temporary radix change for reading a number;  e.g. #3R2010 
	 reads in base 3 and returns 57.   The "base" must be a
	 number between (not inclusive) 1 and 37., expressed as digits
	 in base ten;  thus #16R...  would indicate a hexadecimal notation.
	 Due to a shortcoming of maclisp, if you want to use digits greater 
	 than 9, as in #16R-1A9 (= -425.), you must preceed the number with 
	 an algebraic sign.
   X  -  Hexadecimal reading - a number should follow

   On the ITS systems, the source code (or a link to it) will be in the file
   LIBDOC;SHARPM NIL

2) +INTERNAL-/"-MACRO is defined for use in making " a string macro character.
   TTYSCAN-STRINGERS| helps TTY-rubout processing in string-like sequences.
	The function defined for +INTERNAL-/"-MACRO returns an uninterned
   symbol which has been set to itself;  as with "#", it is up to the
   user to do (SETSYNTAX '/" 'MACRO '+INTERNAL-/"-MACRO) if he wants.
	TTYSCAN-STRINGERS|  is a variable set up to an a-list of start
   and stop (ascii values of) characters so that the system-supplied
   tty prescan function can know about which (read macro) characters are 
   string-like  delimiters.  
	Of course, you may supply your own macro function for doublequote if 
   you don't like the style of +INTERNAL-/"-MACRO.  The compiler version of 
   this function  -  +INTERNAL-/"-MACRO  -  in addition to the abovementioned 
   action, puts a "+INTERNAL-STRING-MARKER" property on the symbol as well, 
   so that it may output 
	`(PROGN (SETQ ,symbol ',symbol)
		(PUTPROP ,symbol T '+INTERNAL-STRING-MARKER))
   This allows a macro to use a string compiled into it in producing code
   which gets output to yet another FASL file, and have that final one still
   have the same characteristics of the original.  Code which produces symbols
   for strings can put this property on when in the compiler, to cause this 
   processing to happen for his strings as well.  This saves the user from 
   having to write his own USERATOMS-HOOK  (see below).

3)  Two **INCOMPATIBILITIES**:
      Carriage-Return, no longer invisible,  is now a "white-space" character.
      TERPRI is initially non-null, meaning no automatic insertion of <cr>'s.
   This means that <cr> will terminate an atom, just like space does,
   and also that it is not necessary to "slashify" <cr>'s occurring within
   a vertical-bar or double-quote string.  Actually, many persons may prefer
   to reset TERPRI to (), so that symbols will not appear to "wrap-around"
   at the end of a line;  the only danger is that atoms (symbols or bignums)
   which are longer than the line-length will have a carriage-return inserted
   "in the middle" of them, thereby destroying read-back capability.
 
4) PROG1 -- Like PROG2 but return first argument instead of second.
   (PROG1 e1 e2 ... en) is like (PROG2 () e1 e2 ... en)
   So if you had this defined as macro in your files, you can relax now.

5) SETF is an FSUBR like the LISPM's general update operator.
   DEFSETF is an autoloadable macro to help one extend the SETF range.
      SETF is particularly useful with structure accessing macros, such 
   as DEFVST (or other packages) would define.  It's syntax is like a 
   generalized SETQ.   For example, assume there is a macro  defined by
	(DEFMACRO SHIP-LABEL (X) `(CXR 6 ,x))
   then
      (SETF (CADDAR A) 'BAR 
	    (CDR B) (LIST 4)
	    Y 'BUZZ 
	    (SHIP-LABEL MYSHIP) 'JOLLY-ROGER)
   is equivalent to
         (PROGN (RPLACA (CDDAR A) 'BAR) 
		(RPLACD B (LIST 4)) 
		(SETQ Y 'BUZZ)
		(RPLACX 6 MYSHIP 'JOLLY-ROGER))
   Five standard cases are "built-in" in the interpreter, but are 
   redefinable with the generalized SETF expander package which will be
   autoloaded when used.
     a) symbols, in which case SETF acts just like SETQ;  
     b) car/cdr operations up to depth 4, inversion is either 
	a RPLACA or RPLACD;  e.g.  (SETF (CADR X) Y) operates
	like  (RPLACA (CDR X) Y);
     c) GET, is inverted by PUTPROP;  e.g. (SETF (GET (MUMBLE) BAR) 'LO)
	works like  (PUTPROP (MUMBLE) 'LO BAR) ,  however, correct
	order of evaluation is obeyed, namely strict left-to-right
	from the original form;  [as of 12/10/79, the order-of-evaluation
	specification has a bug in it, but this may be corrected - JONL ]
     d) PLIST, inverted by SETPLIST, and 
     e) ARRAYCALL inverted by STORE;
   Macros are expanded 1 step at a time, and a SETF-X property is 
   checked for, in case the user has an overriding expander.
   If the access is not a SETF-X expansion, or one of the 5 recognized 
   cases, (or a macro or "autoload" which expands into such), then the 
   function  +INTERNAL-SETF-X  is called on the list of remaining 
   access/value pairs  and the result is EVAL'd.  
      The return value is the result of the last form;  *note* that the 
   last form is not evaluated twice unless it is safe and cheap to do so.
     ** NOTE **  On the LISP Machine, only one access/value pair is allowed
     ** NOTE **  and the return value is not defined.  This is a superset of
     ** NOTE **  the LISP Machine definition.  If you wish your code to run
     ** NOTE **  on the LISP Machine, you will have to limit your usage to
     ** NOTE **	 these constraints, and the similar constrains it places on
     ** NOTE **	 PUSH and POP.
   In compiled code, no extra overhead is associated with the return value 
   being defined, unless you actually make use of it; the form is analyzed
   (possibly) differently depending on whether the resultant value is needed.

       DEFSETF, an autoloadable macro, allows telling SETF, PUSH, and 
   POP how to invert an access;  for simple cases, DEFSETF makes accessor 
   inversion definition very easy.
      (DEFSETF <function> (( () <destructure>) <value>) <retval>
	  <invert-form>)
   where <function> is the name of the function to invert, <destructure>
   is a series of symbols to be bound to arguments to the function to be
   inverted.  <value> is the symbol to be bound to the value to be stored.
   <retval> is T or (), according to whether the return value from the
   inverted form is the same as <value>.  <retval> is a form to CONS up
   the apropriate code to store into the slot specified.
   For example, the DEFSETF for CXR:
      (DEFSETF CXR (( () INDEX HUNK) VALUE)
	         ()				;RPLACX returns HUNK, not VALUE
	         `(RPLACX ,INDEX ,HUNK ,VALUE))
   Handling LSUBRs and FSUBRs and macros with variable numbers of arguments
   is not quite as simple.  Those interested should see MC:NILCOM;SETF >
   It is also possible to write other macros which make use of this
   information in such a way to avoid duplicating forms in the macro in the
   code, etc.  A mechanism to make this easy to use will be provided.

6)  As on LISPM, PUSH and POP have been extended to use SETF instead of SETQ.
    Thus (PUSH 'BAR (CAR (FOO))) 			is like
	 (SETF (CAR (FOO)) (CONS 'BAR (CAR (FOO)))
   **  EXCEPT:  **
   ** NOTE **   Unlike on the LISP Machine, the return value of PUSH is 
   ** NOTE **	defined to be the new value of the list ("stack").  Also,
   ** NOTE **	there will be no multiple evaluation of the function FOO,
   ** NOTE **	as would occur on the LISP machine, and the order of evaluation
   ** NOTE **	is guarenteed to be left-to-right
   Also, you can do
   (POP (SAVED-LOCS (GET-FROB)) (CURRENT-LOC (GET-NEW-FROB))) where SAVED-LOCS
   and CURRENT-LOC are suitable accessor macros to a stack of "LOC"s in a
   "FROB" and a single "LOC" in a "FROB", respectively.  The second argument is
   optional, and in all cases, the return value is the CAR of the list accessed
   ** NOTE **  The LISP Machine supports only the 1 argument case, and does
   ** NOTE **  NOT guarentee single-evaluation of the accessor nor left-right
   ** NOTE **  order.

7) INCLUDEF is a subr version of INCLUDE, for the sake of transportable code.
   (INCLUDEF '((NILSRC) DRAMMP >)) is like (INCLUDE ((NILSRC) DRAMMP >))
   This allows conditional inclusion, such as according to site or filesystem.

8) A new "Software device" convention for NAMELIST-series functions.
   Namelists of the form ((LISP) * *) refer to the maclisp system area.

    I/O  functions which accept namelists will look for a PPN property 
    on a symbol before deciding that it is not a device; if found, then
    that property is substituted for the device-directory field, and
    the "namelist" tries again.  In particular, the symbol LISP, on
    non-ITS systems, will have an initial PPN property (if in fact there 
    is no "LISP" device), which will link to the directory with the autoload 
    files on it.  On the ITS systems, "LISP" has a PPN property of NIL,
    but the NAMELIST functions have always converted an unknown device
    name into a directory name.

9) LDB and DPB and other new AUTOLOADable software as fasl file on LISP:
   files  ((LISP) DEFVST FASL),  ((LISP)  MACAID FASL),  ((LISP) LODBYT FASL) 
 
    DEFVST - a structure-defining package for MACLISP/LISPM/NIL
	 documentation is on LISP;DEFVST DOC
    MACAID - many "aids" to macro usage.  "(HERALD <module> /30)" produces a
	 form which will print out the version number of the <module> when
	 it is being loaded - a number obtained from the second file name
	 of the source when it is being compiled.  The reader is referred to
	 commentary in the source file of MACAID for further information.
    LODBYT -  LDB and DPB are LISPM-compatible macros (which in some cases 
	 will call the small subroutines *LDB and *DPB).  "LOAD-BYTE", a 
	 macro with args (<word> <bit-position> <byte-size>) assumes that
	 "<word>" is a 36-bit word, "<bit-position>" is the low-order bit 
	 of a byte of length "<byte-size>" bits (0-origin indexing). 
	 Bits are numbered from low-order high-order ("right-to-left") with 
	 the lowest-order bit being 0.
	 "(DEPOSIT-BYTE <word> <bit-position> <byte-size> <new-byte>)" is
	 similar, but the <new-byte> is inserted into the return copy of
	 the <word>.   Although LDB and DPB are documented in the LISP Machine 
	 Manual, there is a definition  here below for benefit of those who 
	 couldn't get a LISPM manual.
     For LDB and DPB - 
	 The representation "<ppss>" assumes that in base 8, this argument
	 is expressing two octal digits "pp" followed by another two octal
	 digits "ss".   Then  "(LDB <ppss> <word>)"  selects a byte of  
	 (\ <ppss> 64.)  bits in length, which is positioned in <word> with 
	 (\ (// <ppss> 64.) 64.)  bits to the right of the byte;  in other 
	 words, <ppss> is a PDP10 byte-pointer right-shifted by 24. bits.  
	 For "(DPB <byte> <ppss> <word>)", note that DPB is a non-destructive 
	 operation which returns a new value.  Some cases of the 
	 macro-expansions of LDB and DPB (and LOAD-BYTE and DEPOSITE-BYTE) 
	 produce LSH and BOOLE, but others produce calls to the functions 
	 *LDB and *DPB;  thus, until the compiler begins to open-code *LDB 
	 and *DPB, you will need this "macros" file loaded into your run-time 
	 environment also.

10) VSAID  - VECTOR support package; STRING - support, and  NILAID on LISP:

   NILAID is a NIL-compatibility support package for maclisp.
   VSAID  is a limited support package for using VECTORs and EXTENDs, which 
		is required by DEFVST, STRING and NILAID.
   STRING has the NIL and LISPM string handling primitives in it, with a
		few basic ones coded "by hand" for speed.  Garbage-collection
		strategy requires the use of the GC-DAEMON.  See the first
		page of the source file for more information.

11) (STATUS FILESYSTEM-TYPE), (STATUS OPSYSTEM-TYPE), and (STATUS SITE)
   Warning! (LAST (STATUS FEATURES)) for non-ITS systems will be different.
      The last item in the "features" list will be (STATUS FILESYSTEM-TYPE)
   and the next-to-last will be (STATUS SITE);  this will mean no
   change for ITS-supported systems, but will be different on the other
   kinds of systems.  
      The FILESYSTEM-TYPE is either "ITS", "DEC20", or "DEC10" and is a
   kind of general "operating-system type".  The OPSYSTEM-TYPE is either 
   "TOPS-20" or "TENEX", when the file-system type is DEC20; or, if the 
   file-system type is DEC10, it is among "TOPS-10" (for vanilla-flavoured 
   TOPS-10), "CMU" (for CMU-hacked-up TOPS-10), or "SAIL" (for a 
   SAIL-perverted-WAITS TOPS-10. The SITE name was originally meant to 
   distinguish running on the MIT-AI machine from the MIT-ML machine (but 
   nowadays, the same maclisp system runs unmodified on all ITS machines);  
   nevertheless, the SITE name is among "AI", "ML", "MC", or "DM" for ITS 
   systems, "TOPS-20" or "TENEX" for DEC20 style systems, "SAIL" for (r.i.p)
   the SU-AI system, and "TOPS-10" or "CMU" for non-SAIL DEC10 style systems.
      Someday, the DEC10/DEC20 site names may be more informative, 
   e.g. "CMU-10A", "XX", "BBN-D" or whatever.

12) Some things that failed to be documented previously about DEFUN/DEFUN&
    &WHOLE  -  DEFMACRO now permits a keyword &WHOLE, to get at whole call form
	by specifying a variable to be bound to the whole call form.
	    (DEFMACRO FOOM (&WHOLE X) <mumble>)  would bind X just like
	    (MACRO FOOM (X) <mumble>)
    DEFUN reverts to DEFUN& "if necessary"; e.g. for keywords and destructuring
	Thus in MACLISP, you can use the & keywords, and argument
	destructuring without expliciting using DEFUN&.
	For example, (DEFUN FOO ((A . B) &REST W) (LIST A B W))
 	becomes essentially
	    (DEFUN FOO G0005 
	       (LET ((W (AND (> G0005 1) (LISTIFY (- 1 G0005))))
		     ((A . B) (ARG 1))) 
		    (LIST A B W)))
   Any required, optional, or rest variable may be null, meaning "ignore".
   DEFUN& with "&optional" and/or "&rest" keywords (and DEFUNs that are 
	turned into DEFUN& with these keywords) cause the function to become 
	an LEXPR type - (compiled into LSUBR instead of SUBR).  Thus, in order
	to compile other functions calling these functions, you will likely 
	have to give *LEXPR declarations for these functions, even though they
	are not explicitly of the maclisp LEXPR format.
   ** DEFUN&-CHECK-ARGS controls whether or not there is run-time
	checking to see if a DEFUN& with &OPTIONAL or &REST arguments
	has too many or two few arguments passed.

13) FRETRY, a new function which is in many ways like FRETURN.
      FRETRY  "unwinds" the stack to the point indicated by the first 
   argument, which should be a PDL pointer such as would be in the list 
   returned by EVALFRAME, and it then evaluates the form extracted from 
   its second argument, which should be a list such as would be returned 
   by EVALFRAME.  It was intended primarily to be used to "re-try" something 
   that appears to be losing, but which has been corrected (say, in an error 
   break loop).  E.g.
	    (SETQ EF (EVALFRAME ...))
	    (FRETRY (CADR EF) EF)
   But it could be used more generally, e.g.
	    (SETQ PP (GET-PDL-PTR <some-state>))
	    (FRETRY PP `(EVAL ,pp (BREAK STOP-AND-LOOK)))
   In fact, one could define
	(DEFUN FRETURN (PP X)
	       (SETQ PP (EVALFRAME (1+ PP)))
	       (FRETRY (CADR PP)
		       (CASEQ (CAR PP)
			      (EVAL  `(EVAL ,(cadr pp) (QUOTE ,x)))
			      (APPLY `(APPLY ,(cadr pp) (QUOTE (,x)))))))

14) The setting of "+" in the toplevel and break loops modified.
    If "+" is input to the toplevel or break loops, then the value of
    "+" will not be set for that time around, thus leaving "+" with
    a value corresping to the previous input to toplevel or break.

15) SPRIN1, a Pretty-printing version of PRIN1 autoloadable from GRINDEF
        SPRIN1 is an autoloadable function suitable for assigning to
    PRIN1, so that the general top-level printer becomes a "SPRINTER".
    Try, for example,  (SETQ PRIN1 'SPRIN1)

16) CLEAR-INPUT and CLEAR-OUTPUT on SFA's now works
    Hurray!  They give it the CLEAR-INPUT and CLEAR-OUTPUT operation,
    if defined.  The argument is always ().

17) USERATOMS-HOOKS,  for compiling user-defined  "SQUIDified" datatypes  
	This hook provides a means for the user to manipulate user-defined
    "atomic" datatypes in the compiler, and then substitute a SQUIDform-like
    piece of code to construct such an object when the form is output
    to the FASL file.  For example, if the user has macros which manipulate
    strings represented as (STRING-MARKER . <fixnum array>), he would be
    unable to include any of these strings as literal data in the FASL
    file, since there is no representation for arrays in FASL files.
    However, with this hook it would be possible to achieve the effects
    of outputing these strings directly.  The alternative until now has
    been to use "SQUID" forms, but this has the disadvantage that you cannot
    then manipualate these things in the same manner as in the interpreter.
	If the symbol USERATOMS-HOOKS is non-nil, it should be a list of
    functions of one argument, which will be called on every piece (atomic
    or not) of any literal object being output to the FASL file.  If the object
    does not need special handling, the function should return ().  Otherwise
    it should return the NCONS of an s-expression to evaluate at load time
    to create the object.
	The hook will not be called on an object more than once.  EQness is
    preserved, if two strings or whatever are EQ in the compiler, they
    will be made EQ in the interpreter (using the atom-table, for you
    low-level hackers).
  
    (eval-when (COMPILE)
     (defun MYSTRINGHOOK (form)
       (cond ((atom form) ())	   ;If we don't recognize it, return ()
	     ((eq (car form) 'STRING-MARKER)	 ;One of ourse
	      `((CONS 'STRING-MARKER
		      (fillarray (array () ,(arraysize (cdr form)))
				 ',(listarray (cdr form))))))
	     (t ())))		   ;Not one of ours, return ().
    
     (push 'MYSTRINGHOOK USERATOMS-HOOKS))
    
    This is not implemented as efficiently as it might be.  If it is too slow,
    it can be speeded up.
  
    [Note:  the resulting FASL file may not work in LISP 1861 or before, due to
	    a but in FASLOAD] 

18) EOF-COMPILE-QUEUE, for queueing forms to be "done" at the end of file.
    EOF-COMPILE-QUEUE provides a means to "add forms to the end of the file"
    in the compiler.  Thus if you need certain cleanup actions performed
    at the end of the file, you can push forms onto this queue, which will
    be compiled in the order they were pushed when the end of the file
    is reached.  It is OK for forms on this queue to push new forms onto the
    queue.