
Documentation of the "usrhunk" apparatus for SENDing messages.

   (SSTATUS USRHUNK <predicate>) specifies the "user hunk" predicate, which
	determines whether to "hook into" a user-provided definition for
	some system facility, or to treat the data strictly as a hunk.
   (SSTATUS SENDI <function>)  specifies a "SEND" interpreter -- <function>
	is invoked in order to send a "message" to a "user hunk", when a
	hunk which passes the "usrhunk" test is given as argument to any of
	    EQUAL  SUBST  PURCOPY  EVAL  SXHASH  PRINT  EXPLODE 
	    FLATSIZE  ALPHALESSP  SAMEPNAMEP  NAMESTRING 
	or to any of the following out-of-core facilities
	    GFLATSIZE  SPRINT  USERATOMS-HOOK  DESCRIBE  WHICH-OPERATIONS    
   (SSTATUS CALLI <function>)

	The usrhunk <predicate> takes one argument, and should return 
   non-null for objects that LISP should send messages to.  It is invoked 
   via (CALL 1,) so this link gets snapped,  which means that if you redefine 
   the predicate then the new definition may not take effect unless you 
   un-snap by doing  (SSTATUS USRHUNK (STATUS USRHNK)).
	The usrhunk SEND interpreter, <function>, is invoked via (JCALL 16,)
   so its link too may be snapped.  This function is responsible for 
   delivering the message to the apropriate code for handling it;  return 
   values are sometimes significant.  See below for documentation on specific 
   messages which will be sent by LISP.  Note that an lsubr "SEND" is assumed; 
   this function could be the function that is given to (SSTATUS SENDI ...).

   For the dozen or so system functions which will send a message to
   a usrhunk, the action is as follows.  Suppose the message is, say, DOIT;
   then (DOIT <weirdo> <another>) will be interpreted by doing a send like
   (SEND <weirdo> 'DOIT <another>), and this will cause the send interpreter
   function to select some specialized function, say, FROBULATE, which will
   then be applied to the arguments in the same order as given to SEND.  E.g.,
	(DEFUN FROBULATE (actor msg-key other-arg)
		(caseq msg-key 
			(DOIT   <happiness>)
			(DONT   <ugliness>)
			(T      <error?>)))
   Actually, the "msg-key" argument could be ignored, but this example shows
   how several different messages could be dispatched to the same function.
   The argument spectrum of the frobulator should match that of the original
   function;  thus for the SXHASH message it might be
	(DEFUN HASH-IT-ALL (ob () ) ...)
   where the "()" means to ignore the message key (which should be sent as
   SXHASH).  On the other hand, there may be some importance to the order
   of arguments, as this example for the SUBST message shows:
	(DEFUN SUBST-FOR-TRICKY-HUNK (hunk () old new)
		(hunkify (subst old new (extract-data hunk))))
   Here is a table of the actions taken by the system functions which
   resort to SENDing, and of the meanings of the arguments being "sent":
	EQUAL -- (send obj1 'EQUAL obj2) -- "obj1" and "obj2" are two objects 
		to be compared, and of course "equal" is commutative.
	SUBST -- (send object 'SUBST a b) --  Substitute a for b in object.
	PURCOPY -- (send object 'SUBST a b) -- Substitute a for b in object,
		using static (potentially read-only) consing areas.
	EVAL -- (send object 'EVAL) --  Return the value of this object.  
		Typically, just returns itself for "implicit quoting".
	FLATSIZE -- (send object 'FLATSIZE printp level slashifyp)
		"printp" -- non-null if called from inside print as part of the
		    autoterpri hackery; in this case it should return 
		    characters before next legal place to break.  This doesn't 
		    matter if you're not doing autoterpri hacking.
		"level" -- fixnum level of recursion of PRINT/FLATSIZE; can
		    be passed on to PRINT-OBJECT or FLATSIZE-OBJECT (see 
		    below for their definitions).  This is used to limit 
		    recursion with PRINLEVEL set non-null. 
		"slashifyp" -- If non-null, include slashes where print would.
	PRINT -- First, there will be done 
		    (send object 'FLATSIZE 'T -1 slashifyp)
		  and then 
		    (send object 'PRINT stream level slashifyp)
		"stream" -- SFA, file, T, or () to print to
		"level"  -- recursion level of PRINT calling print or print
		    methods recursively.  If you do printing that may wish 
		    to be limited in depth by PRINLEVEL, you should do your 
		    output with PRINT-OBJECT, which takes the current nesting 
		    level as one of it's arguments.	;
		"slashify-p" -- if non-null, this is PRIN1, not PRINC
	EXPLODE -- As with PRINT, there will first be done
		    (send object 'FLATSIZE 'T -1 slashifyp)
		  and then 
		    (send object 'EXPLODE slashify-p number-p)
		"slashify-p" -- non-null if slashes should be output where  
			print would put them.
		"number-p" -- non-null if characters should be returned as 
		    fixnums;  otherwise, they are single-character symbols.
	ALPHALESSP  --  Will send either a LESSP or GREATERP message, 
		with one argument, which is the 'other' object for comparison. 
	SAMEPNAMEP  -- Sends a SAMEPNAMEP message, with one argument which is 
		the 'other' object for comparison.
	SXHASH -- Sends a SXHASH message, which should  return a FIXNUM to 
		be the SXHASH of the object.
	NAMESTRING  -- Sends a NAMESTRING message, which should return a SYMBOL
		whose pname characters are a 'namestring' for the object.

   Two new functions have been added to the initial MacLISP for the sake 
   of recursive calls to PRINT and FLATSIZE by various PRINT and FLATSIZE 
   methods, and they have arguments similarly.
	PRINT-OBJECT (object level slashifyp stream &optional ignored)
	FLATSIZE-OBJECT (object printp level slashifyp &optional ignored)
     "object" -- object to be printed or to have it's FLATSIZE computed.
     "level"  -- recursive printing level, for PRINLEVEL detection.  You should
		pass in the current LEVEL, zero-origen.
     "slashifyp" -- non-null indicates slashification should be done
     "stream" -- file or SFA
     "printp" -- non-null if FLATSIZE is being called originally from PRINT
		This will be passed in to any FLATSIZE methods called 
		recursively and means "This is a FLATSIZE up to first place 
		OK to break", for print's TERPRI hacking.  If you see this 
		and want to punt, return zero.
     "ignored" -- for compatability with an irrelevant LISPM feature.



   *** CALLI processing ***

   CALLI interpreters must be hand coded; they cannot be coded in LISP.
   This is because of the way they are invoked:  They get invoked with
   the stack in the format for IAPPLY.  IAPPLY is LISP's Internal APPLY.
   The arguments are on the stack, like for an LSUBR call, and T contains
   the negative of the number of args, just like for an LSUBR call.  However,
   where the return address would be is found the object to be applied.  What
   LISP does is to take that object, figure out how to apply it, replace it's
   slot on the stack with <object>,,CPOPJ .  CPOPJ is the address of a POPJ P,
   thus returning to it returns to the caller of the IAPPLY, who's return 
   address is just below that.
       |arg n
       |arg n-1
	 ..
	 ..
	 ..
       |arg 1
       |arg 0
       object-to-be-applied
       return-address
   Register T (accumulator 6) contains -n, and the slot containing 
   object-to-be-applied is clobbered to <object-to-be-applied>,,CPOPJ 
   and the function is invoked.

   The user CALLI handler can act in several ways.  You can figure out the
   function you wish to invoke, clobber the <object-to-be-applied> slot to
   contain a CPOPJ (or whatever routine you want executed later) and do
   a JCALLF 16,(routine) or you can replace the <object-to-be-applied> with
   another object to be used instead, and JRST off to IAPPLY.  IAPPLY will
   then recompute what to do (possibly invoking the user CALLI handler if
   it answers true to the USRHUNK test), apply the function and return.

   Since the CALLI handler is not a function, it does not live in a SUBR
   or LSUBR property, but instead in a CALLI property.  (SSTATUS CALLI 'FOO)
   looks for a CALLI property on FOO.  If it finds it, it stores a JRST to
   that routine internally, and saves the symbol FOO to be returned by
   (STATUS CALLI).


____________________________________________________________________________

2/19/80 -- RWK
1) **SELF-EVAL** hook
   PRINC/PRIN1 now send a FLATC/FLATSIZE message first.  This should be
   improved some more but it really does work.  PRINLEVEL info needs to be
   passed back and forth between MACLISP and user printers, and FLATC/FLATSIZE
   should be told whether or not it is for PRINT so they can give the FLATC
   before the first break.

