(DEFINE-FILE-INFO READTABLE "XCL" PACKAGE "SYSTEM")(IL:FILECREATED "16-May-90 11:55:52" IL:|{DSK}<usr>local>lde>lispcore>sources>ADVISE.;2| 40413        IL:|changes| IL:|to:|  (IL:VARS IL:ADVISECOMS)      IL:|previous| IL:|date:| "15-Aug-88 12:29:50" IL:|{DSK}<usr>local>lde>lispcore>sources>ADVISE.;1|); Copyright (c) 1978, 1984, 1986, 1987, 1988, 1990 by Venue & Xerox Corporation.  All rights reserved.; The following program was created in 1978 but has not been published; within the meaning of the copyright law, is furnished under license,; and may not be used, copied and/or disclosed except in accordance; with the terms of said license.(IL:PRETTYCOMPRINT IL:ADVISECOMS)(IL:RPAQQ IL:ADVISECOMS          ((IL:STRUCTURES ADVICE)           (IL:VARIABLES IL:ADVISEDFNS *UNADVISED-FNS*)                      (IL:* IL:|;;| "")                      (IL:* IL:|;;| "Interlisp entry points.")           (IL:FNS IL:ADVISE IL:UNADVISE IL:READVISE)           (IL:PROP IL:ARGNAMES IL:ADVISE)                      (IL:* IL:|;;| "")                      (IL:* IL:|;;| "XCL entry points.")           (IL:FUNCTIONS XCL:ADVISE-FUNCTION XCL:UNADVISE-FUNCTION XCL:READVISE-FUNCTION)           (IL:FUNCTIONS UNADVISE-FROM-RESTORE-CALLS FINISH-ADVISING FINISH-UNADVISING)                      (IL:* IL:|;;| "")                      (IL:* IL:|;;| "The advice database.")           (IL:VARIABLES *ADVICE-HASH-TABLE*)           (IL:FUNCTIONS ADD-ADVICE DELETE-ADVICE GET-ADVICE-MIDDLE-MAN SET-ADVICE-MIDDLE-MAN                   INSERT-ADVICE-FORM)           (IL:SETFS GET-ADVICE-MIDDLE-MAN)                      (IL:* IL:|;;| "")                      (IL:* IL:|;;| "Hacking the actual advice forms.")           (IL:FUNCTIONS CREATE-ADVISED-DEFINITION MAKE-AROUND-BODY)                      (IL:* IL:|;;| "")                      (IL:* IL:|;;| "Dealing with the File Manager")           (IL:FILEPKGCOMS IL:ADVICE IL:ADVISE)           (IL:FUNCTIONS XCL:REINSTALL-ADVICE)           (IL:FUNCTIONS ADVICE-GETDEF ADVICE-PUTDEF ADVICE-DELDEF ADVICE-HASDEF ADVICE-NEWCOM                   ADVICE-FILE-DEFINITIONS ADVISE-CONTENTS ADVICE-ADDTOCOM)           (IL:PROP IL:PROPTYPE IL:ADVISED)                      (IL:* IL:|;;| "")                      (IL:* IL:|;;| "Dealing with old-style advice")           (IL:FUNCTIONS IL:READVISE1 ADD-OLD-STYLE-ADVICE CANONICALIZE-ADVICE-SYMBOL                   CANONICALIZE-ADVICE-WHEN-SPEC CANONICALIZE-ADVICE-WHERE-SPEC)           (IL:DEFINE-TYPES XCL:ADVISED-FUNCTIONS)           (IL:FUNCTIONS XCL:DEFADVICE)                      (IL:* IL:|;;| "Arrange for the proper package.  Because of the DEFSTRUCT above, we must have the file dumped in the SYSTEM package.")           (IL:PROP (IL:MAKEFILE-ENVIRONMENT IL:FILETYPE)                  IL:ADVISE)           (IL:DECLARE\: IL:DONTEVAL@LOAD IL:DOEVAL@COMPILE IL:DONTCOPY IL:COMPILERVARS                  (IL:ADDVARS (IL:NLAMA IL:READVISE IL:UNADVISE)                         (IL:NLAML)                         (IL:LAMA IL:ADVISE)))))(DEFSTRUCT (ADVICE (:TYPE LIST))   BEFORE   AFTER   AROUND)(DEFVAR IL:ADVISEDFNS NIL)(DEFVAR *UNADVISED-FNS* NIL)(IL:* IL:|;;| "")(IL:* IL:|;;| "Interlisp entry points.")(IL:DEFINEQ(il:advise  (il:lambda il:args                                  (il:* il:\; "Edited  6-Apr-87 18:00 by Pavel")(il:* il:|;;;| "ADVISE the FN given.  ADVISE1 is for advice of the type (foo IN bar)")    (let (il:fn il:when il:where il:what)                    (il:* il:|;;| "First we straighten out the arguments given to us")         (il:setq il:fn (il:arg il:args 1))         (case il:args (2 (il:setq il:what (il:arg il:args 2)))               (3 (il:setq il:when (il:arg il:args 2))                  (il:setq il:what (il:arg il:args 3)))               (4 (il:setq il:when (il:arg il:args 2))                  (il:setq il:where (il:arg il:args 3))                  (il:setq il:what (il:arg il:args 4)))               (t (il:if (< il:args 2)                      il:then (error 'il:too-few-arguments :callee 'il:advise :actual il:args                                      :minimum 2)                    il:else (error 'il:too-many-arguments :callee 'il:advise :actual il:args :maximum                                    4))))         (il:setq il:when (canonicalize-advice-when-spec il:when))         (il:setq il:where (canonicalize-advice-where-spec il:where))         (il:if (il:nlistp il:fn)             il:then (xcl:advise-function il:fn il:what :when il:when :priority il:where)           il:elseif (il:string.equal (cadr il:fn)                            "IN")             il:then (xcl:advise-function (first il:fn)                            il:what :in (third il:fn)                            :when il:when :priority il:where)           il:else (il:for il:x il:in il:fn                      il:join (il:if (il:nlistp il:x)                                  il:then (xcl:advise-function il:x il:what :when il:when :priority                                                  il:where)                                il:else (xcl:advise-function (first il:x)                                               il:what :in (third il:x)                                               :when il:when :priority il:where)))))))(il:unadvise  (il:nlambda il:fns                                  (il:* il:\; "Edited  6-Apr-87 16:21 by Pavel")    (il:setq il:fns (il:nlambda.args il:fns))    (flet ((il:unadvise-entry (il:entry)                  (il:if (il:listp il:entry)                      il:then (xcl::unadvise-function (first il:entry)                                     :in                                     (third il:entry))                    il:else (xcl::unadvise-function il:entry))))          (cond             ((null il:fns)              (il:for il:entry il:in (il:reverse il:advisedfns) il:join (il:unadvise-entry il:entry))              )             ((il:equal il:fns '(t))              (and (not (null il:advisedfns))                   (il:unadvise-entry (car il:advisedfns))))             (t (il:for il:entry il:in il:fns il:join (il:unadvise-entry il:entry)))))))(il:readvise  (il:nlambda il:fns                                  (il:* il:\; "Edited  6-Apr-87 16:52 by Pavel")    (il:setq il:fns (il:nlambda.args il:fns))    (flet ((il:readvise-entry (il:entry)                  (il:if (il:listp il:entry)                      il:then (xcl::readvise-function (first il:entry)                                     :in                                     (third il:entry))                    il:else (xcl::readvise-function il:entry))))          (cond             ((null il:fns)                                  (il:* il:\;                                                              "readvise them all, in reverse order.")              (il:for il:entry il:in (il:reverse *unadvised-fns*) il:join (il:readvise-entry il:entry                                                                                 )))             ((il:equal il:fns '(t))                         (il:* il:\;                                         "simple case, readvise just the last one that was unadvised.")              (and (not (null *unadvised-fns*))                   (il:readvise-entry (car *unadvised-fns*))))             (t                                              (il:* il:\; "they gave us some functions, so readvise THEM.  We can't use READVISE-ENTRY here, because we may have to deal with old-style advice.")                (il:for il:entry il:in il:fns il:join (il:readvise1 il:entry))))))))(IL:PUTPROPS IL:ADVISE IL:ARGNAMES (IL:WHO IL:WHEN IL:WHERE IL:WHAT))(IL:* IL:|;;| "")(IL:* IL:|;;| "XCL entry points.")(DEFUN XCL:ADVISE-FUNCTION (XCL::FN-TO-ADVISE XCL::FORM &KEY ((:IN XCL::IN-FN))                                      (WHEN :BEFORE)                                      (XCL::PRIORITY :LAST))   (COND      ((CONSP XCL::FN-TO-ADVISE)       (IL:FOR XCL::FN IL:IN XCL::FN-TO-ADVISE          IL:JOIN (XCL:ADVISE-FUNCTION XCL::FN XCL::FORM :IN XCL::IN-FN :WHEN WHEN :PRIORITY                              XCL::PRIORITY)))      ((CONSP XCL::IN-FN)       (IL:FOR XCL::FN IL:IN XCL::IN-FN          IL:JOIN (XCL:ADVISE-FUNCTION XCL::FN-TO-ADVISE XCL::FORM :IN XCL::FN :WHEN WHEN                              :PRIORITY XCL::PRIORITY)))      ((NULL XCL::FORM)       (FORMAT *ERROR-OUTPUT* "No advice given, so nothing done.")       NIL)      ((IL:UNSAFE.TO.MODIFY XCL::FN-TO-ADVISE "advise")       (FORMAT *ERROR-OUTPUT* "~S not advised.~%" XCL::FN-TO-ADVISE)       NIL)      (T (COND            (XCL::IN-FN (IF (NOT (HAS-CALLS XCL::IN-FN XCL::FN-TO-ADVISE))                            (ERROR "~S is not called from ~S." XCL::FN-TO-ADVISE XCL::IN-FN)))            (T (IF (NULL (IL:GETD XCL::FN-TO-ADVISE))                   (ERROR 'XCL:UNDEFINED-FUNCTION :NAME XCL::FN-TO-ADVISE))))         (XCL:UNBREAK-FUNCTION XCL::FN-TO-ADVISE :IN XCL::IN-FN :NO-ERROR T)         (COND            ((NULL XCL::IN-FN)             (IL:* IL:|;;| "Adjust the database of advice for this function.")             (WHEN (NOT (MEMBER XCL::FN-TO-ADVISE IL:ADVISEDFNS :TEST 'EQ))                                                             (IL:* IL:\; "If FN-TO-ADVISE is not currently advised, the new advice replaces any that may have been given before.")                 (DELETE-ADVICE XCL::FN-TO-ADVISE))             (ADD-ADVICE XCL::FN-TO-ADVISE WHEN XCL::PRIORITY XCL::FORM)             (IL:* IL:|;;| "Finish off the process.  This part is shared with READVISE-FUNCTION.")             (FINISH-ADVISING XCL::FN-TO-ADVISE NIL))            (T (LET* ((XCL::ADVICE-NAME `(,XCL::FN-TO-ADVISE :IN ,XCL::IN-FN))                      (XCL::ALREADY-ADVISED? (MEMBER XCL::ADVICE-NAME IL:ADVISEDFNS :TEST                                                    'EQUAL)))                     (IL:* IL:|;;| "Adjust the database of advice for this request.")                     (WHEN (NOT XCL::ALREADY-ADVISED?)       (IL:* IL:\;            "If not currently advised, the new advice replaces any that may have been given before.")                         (DELETE-ADVICE XCL::ADVICE-NAME))                     (ADD-ADVICE XCL::ADVICE-NAME WHEN XCL::PRIORITY XCL::FORM)                     (IL:* IL:|;;|                    "Finish off the process.  This part is shared with READVISE-FUNCTION.")                     (FINISH-ADVISING XCL::FN-TO-ADVISE XCL::IN-FN)))))))(DEFUN XCL:UNADVISE-FUNCTION (XCL::FN-TO-UNADVISE &KEY ((:IN XCL::IN-FN))                                        XCL::NO-ERROR)   (COND      ((CONSP XCL::FN-TO-UNADVISE)       (IL:FOR XCL::FN IL:IN XCL::FN-TO-UNADVISE IL:JOIN (XCL:UNADVISE-FUNCTION XCL::FN                                                                             :IN XCL::IN-FN)))      ((CONSP XCL::IN-FN)       (IL:FOR XCL::FN IL:IN XCL::IN-FN IL:JOIN (XCL:UNADVISE-FUNCTION                                                                    XCL::FN-TO-UNADVISE :IN XCL::FN)))      (T (XCL:UNBREAK-FUNCTION XCL::FN-TO-UNADVISE :IN XCL::IN-FN :NO-ERROR T)         (IF (NULL XCL::IN-FN)             (LET ((XCL::ORIGINAL (GET XCL::FN-TO-UNADVISE 'IL:ADVISED)))                  (COND                     ((NULL XCL::ORIGINAL)                      (UNLESS XCL::NO-ERROR (FORMAT *ERROR-OUTPUT* "~S is not advised.~%"                                                    XCL::FN-TO-UNADVISE))                      NIL)                     (T (IL:PUTD XCL::FN-TO-UNADVISE (IL:GETD XCL::ORIGINAL)                               T)                        (REMPROP XCL::FN-TO-UNADVISE 'IL:ADVISED)                        (PUSH XCL::FN-TO-UNADVISE *UNADVISED-FNS*)                        (SETQ IL:ADVISEDFNS (DELETE XCL::FN-TO-UNADVISE IL:ADVISEDFNS))                        (LIST XCL::FN-TO-UNADVISE))))             (LET* ((XCL::ADVICE-NAME `(,XCL::FN-TO-UNADVISE :IN ,XCL::IN-FN))                    (XCL::MIDDLE-MAN (GET-ADVICE-MIDDLE-MAN XCL::ADVICE-NAME)))                   (COND                      ((NULL XCL::MIDDLE-MAN)                       (UNLESS XCL::NO-ERROR (FORMAT *ERROR-OUTPUT* "~S is not advised.~%"                                                     XCL::ADVICE-NAME))                       NIL)                      (T (CHANGE-CALLS XCL::MIDDLE-MAN XCL::FN-TO-UNADVISE XCL::IN-FN)                         (FINISH-UNADVISING XCL::ADVICE-NAME XCL::MIDDLE-MAN)                         (LIST XCL::ADVICE-NAME))))))))(DEFUN XCL:READVISE-FUNCTION (XCL::FN-TO-READVISE &KEY ((:IN XCL::IN-FN)))   (COND      ((CONSP XCL::FN-TO-READVISE)       (IL:FOR XCL::FN IL:IN XCL::FN-TO-READVISE IL:JOIN (XCL:READVISE-FUNCTION XCL::FN                                                                             :IN XCL::IN-FN)))      ((CONSP XCL::IN-FN)       (IL:FOR XCL::FN IL:IN XCL::IN-FN IL:JOIN (XCL:READVISE-FUNCTION                                                                    XCL::FN-TO-READVISE :IN XCL::FN)))      (T (XCL:UNADVISE-FUNCTION XCL::FN-TO-READVISE :IN XCL::IN-FN :NO-ERROR T)         (FINISH-ADVISING XCL::FN-TO-READVISE XCL::IN-FN))))(DEFUN UNADVISE-FROM-RESTORE-CALLS (FROM TO FN)   (LET ((ENTRY (FIND-IF #'(LAMBDA (ENTRY)                                  (AND (CONSP ENTRY)                                       (EQ (FIRST ENTRY)                                           FROM)                                       (EQ (THIRD ENTRY)                                           FN)))                       IL:ADVISEDFNS)))        (ASSERT (NOT (NULL ENTRY))               NIL "BUG: Inconsistency in SI::UNADVISE-FROM-RESTORE-CALLS")        (FINISH-UNADVISING ENTRY TO)        (FORMAT *TERMINAL-IO* "~S unadvised.~%" ENTRY)))(DEFUN FINISH-ADVISING (FN-TO-ADVISE IN-FN)   (COND      ((NULL IN-FN)       (LET* ((ALREADY-ADVISED? (MEMBER FN-TO-ADVISE IL:ADVISEDFNS :TEST 'EQ))              (ORIGINAL (IF ALREADY-ADVISED?                            (GET FN-TO-ADVISE 'IL:ADVISED)                            (LET ((*PRINT-CASE* :UPCASE))                                 (MAKE-SYMBOL (FORMAT NIL "Original ~A" FN-TO-ADVISE))))))             (IL:* IL:|;;| "Adjust the database of advice for this function.")             (WHEN (NOT ALREADY-ADVISED?)                 (IL:PUTD ORIGINAL (IL:GETD FN-TO-ADVISE)                        T))             (IL:PUTD FN-TO-ADVISE (COMPILE NIL (CREATE-ADVISED-DEFINITION FN-TO-ADVISE ORIGINAL                                                        FN-TO-ADVISE)))             (WHEN (NOT ALREADY-ADVISED?)                 (SETF (GET FN-TO-ADVISE 'IL:ADVISED)                       ORIGINAL))             (IL:* IL:|;;|       "These are outside the WHEN because COMPILE calls VIRGINFN, which may unadvise the function.")             (SETQ *UNADVISED-FNS* (DELETE FN-TO-ADVISE *UNADVISED-FNS* :TEST 'EQ))             (SETQ IL:ADVISEDFNS                             (IL:* IL:\;         "Move FN-TO-ADVISE to the front of IL:ADVISEDFNS if there already, else just add to front.")                   (CONS FN-TO-ADVISE (DELETE FN-TO-ADVISE IL:ADVISEDFNS :TEST 'EQ)))             (IL:MARKASCHANGED FN-TO-ADVISE 'IL:ADVICE)             (LIST FN-TO-ADVISE)))      (T (LET* ((ADVICE-NAME `(,FN-TO-ADVISE :IN ,IN-FN))                (ALREADY-ADVISED? (MEMBER ADVICE-NAME IL:ADVISEDFNS :TEST 'EQUAL))                MIDDLE-MAN)               (IL:* IL:|;;|              "Create a middle-man for this request.  If one has already been created, use it.")               (SETQ MIDDLE-MAN (OR (GET-ADVICE-MIDDLE-MAN ADVICE-NAME)                                    (SETF (GET-ADVICE-MIDDLE-MAN ADVICE-NAME)                                          (CONSTRUCT-MIDDLE-MAN FN-TO-ADVISE IN-FN))))               (IL:* IL:|;;| "Give the middle-man the new advised definition.")               (IL:PUTD MIDDLE-MAN (COMPILE NIL (CREATE-ADVISED-DEFINITION FN-TO-ADVISE FN-TO-ADVISE                                                       ADVICE-NAME)))               (WHEN (NOT ALREADY-ADVISED?)                   (IL:* IL:|;;|                  "Redirect any calls to FN-TO-ADVISE in IN-FN to call the middle-man.")                   (CHANGE-CALLS FN-TO-ADVISE MIDDLE-MAN IN-FN 'UNADVISE-FROM-RESTORE-CALLS))               (IL:* IL:|;;| "Save a trail of information. These are outside the WHEN because COMPILE calls VIRGINFN, which may unadvise the function.")               (SETQ *UNADVISED-FNS* (DELETE ADVICE-NAME *UNADVISED-FNS* :TEST 'EQUAL))               (SETQ IL:ADVISEDFNS                           (IL:* IL:\;          "Move ADVICE-NAME to the front of IL:ADVISEDFNS if there already, else just add to front.")                     (CONS ADVICE-NAME (DELETE ADVICE-NAME IL:ADVISEDFNS :TEST 'EQUAL)))               (IL:MARKASCHANGED ADVICE-NAME 'IL:ADVICE)               (LIST ADVICE-NAME)))))(DEFUN FINISH-UNADVISING (ADVICE-NAME MIDDLE-MAN)   (SETQ IL:ADVISEDFNS (DELETE ADVICE-NAME IL:ADVISEDFNS :TEST 'EQUAL))   (PUSH ADVICE-NAME *UNADVISED-FNS*))(IL:* IL:|;;| "")(IL:* IL:|;;| "The advice database.")(DEFVAR *ADVICE-HASH-TABLE* (MAKE-HASH-TABLE :TEST 'EQUAL)(IL:* IL:|;;;| "Hash-table mapping either a function name or a list in the form (FOO :IN BAR) to a pair (advice . middle-man).")                                )(DEFUN ADD-ADVICE (NAME WHEN PRIORITY FORM)(IL:* IL:|;;;| "Advice is stored on the hash table SI::*ADVICE-HASH-TABLE*.  It is actually stored as a cons whose CAR is the advice and CDR is the middle-man name (for advice of the type (FOO :IN BAR)).")   (LET* ((OLD-ADVICE (GETHASH NAME *ADVICE-HASH-TABLE*))          (ADVICE (IF (NULL OLD-ADVICE)                      (MAKE-ADVICE)                      (CAR OLD-ADVICE))))         (ECASE WHEN             (:BEFORE (SETF (ADVICE-BEFORE ADVICE)                            (INSERT-ADVICE-FORM FORM PRIORITY (ADVICE-BEFORE ADVICE))))             (:AFTER (SETF (ADVICE-AFTER ADVICE)                           (INSERT-ADVICE-FORM FORM PRIORITY (ADVICE-AFTER ADVICE))))             (:AROUND (SETF (ADVICE-AROUND ADVICE)                            (INSERT-ADVICE-FORM FORM PRIORITY (ADVICE-AROUND ADVICE)))))         (WHEN (NULL OLD-ADVICE)             (SETF (GETHASH NAME *ADVICE-HASH-TABLE*)                   (CONS ADVICE NIL)))))(DEFUN DELETE-ADVICE (NAME)   (REMHASH NAME *ADVICE-HASH-TABLE*))(DEFUN GET-ADVICE-MIDDLE-MAN (NAME)   (CDR (GETHASH NAME *ADVICE-HASH-TABLE*)))(DEFUN SET-ADVICE-MIDDLE-MAN (NAME MIDDLE-MAN)   (SETF (CDR (GETHASH NAME *ADVICE-HASH-TABLE*))         MIDDLE-MAN))(DEFUN INSERT-ADVICE-FORM (FORM PRIORITY ENTRY-LIST)(IL:* IL:|;;;| "Insert the new advice FORM into ENTRY-LIST using PRIORITY as a specification of where in that list to put it. If an equalish piece of advice already exists, remove it first.")   (LET    ((ENTRY (LIST PRIORITY FORM)))    (SETF     ENTRY-LIST     (LABELS      ((EQUALISH (X Y)              (IL:* IL:|;;| "EQUALP, but don't ignore case in strings.")              (TYPECASE X                  (SYMBOL (EQ X Y))                  (CONS (AND (CONSP Y)                             (EQUALISH (CAR X)                                    (CAR Y))                             (EQUALISH (CDR X)                                    (CDR Y))))                  (NUMBER (AND (NUMBERP Y)                               (= X Y)))                  (CHARACTER (AND (CHARACTERP Y)                                  (CHAR= X Y)))                  (STRING (AND (STRINGP Y)                               (STRING= X Y)))                  (PATHNAME (AND (PATHNAMEP Y)                                 (IL:%PATHNAME-EQUAL X Y)))                  (VECTOR (AND (VECTORP Y)                               (LET ((SX (LENGTH X)))                                    (AND (EQL SX (LENGTH Y))                                         (DOTIMES (I SX T)                                             (IF (NOT (EQUALISH (AREF X I)                                                             (AREF Y I)))                                                 (RETURN NIL)))))))                  (ARRAY (AND (ARRAYP Y)                              (EQUAL (ARRAY-DIMENSIONS X)                                     (ARRAY-DIMENSIONS Y))                              (LET ((FX (IL:%FLATTEN-ARRAY X))                                    (FY (IL:%FLATTEN-ARRAY Y)))                                   (DOTIMES (I (ARRAY-TOTAL-SIZE X)                                               T)                                       (IF (NOT (EQUALISH (AREF FX I)                                                       (AREF FY I)))                                           (RETURN NIL))))))                  (T                      (IL:* IL:|;;| "so that datatypes will be properly compared")                     (OR (EQ X Y)                         (LET ((TYPENAME (IL:TYPENAME X)))                              (AND (EQ TYPENAME (IL:TYPENAME Y))                                   (LET ((DESCRIPTORS (IL:GETDESCRIPTORS TYPENAME)))                                        (IF DESCRIPTORS                                            (IL:FOR FIELD IL:IN DESCRIPTORS                                               IL:ALWAYS (EQUALISH (IL:FFETCHFIELD FIELD X)                                                                    (IL:FFETCHFIELD FIELD Y))))))))))              ))      (DELETE-IF #'(LAMBDA (OLD-ENTRY)                          (XCL:DESTRUCTURING-BIND (OLD-PRIORITY OLD-FORM)                                 OLD-ENTRY                                 (AND (EQUAL PRIORITY OLD-PRIORITY)                                      (EQUALISH FORM OLD-FORM))))             ENTRY-LIST)))    (COND       ((NULL ENTRY-LIST)        (LIST ENTRY))       ((EQ PRIORITY :FIRST)        (CONS ENTRY ENTRY-LIST))       ((EQ PRIORITY :LAST)        (NCONC ENTRY-LIST (LIST ENTRY)))       (T                                                    (IL:* IL:\;                                                      "PRIORITY is a command to the old TTY Editor.")          (UNLESS (AND (CONSP PRIORITY)                       (MEMBER (CAR PRIORITY)                              '(IL:BEFORE IL:AFTER)))                 (ERROR "Malformed priority argument to ADVISE: ~S" PRIORITY))          (XCL:CONDITION-CASE (IL:EDITE ENTRY-LIST `((IL:LC ,@(CDR PRIORITY))                                                     (IL:BELOW IL:^)                                                     (,(CAR PRIORITY)                                                      ,ENTRY)))                 (ERROR (C)                        (ERROR "Error from EDITE during insertion of new advice:~%  ~A~%" C)))          ENTRY-LIST))))(DEFSETF GET-ADVICE-MIDDLE-MAN SET-ADVICE-MIDDLE-MAN)(IL:* IL:|;;| "")(IL:* IL:|;;| "Hacking the actual advice forms.")(DEFUN CREATE-ADVISED-DEFINITION (ADVISED-FN FN-TO-CALL ADVICE-NAME)   (MULTIPLE-VALUE-BIND    (LAMBDA-CAR ARG-LIST CALLING-FORM)    (FUNCTION-WRAPPER-INFO ADVISED-FN FN-TO-CALL)    (LET* ((ADVICE (CAR (GETHASH ADVICE-NAME *ADVICE-HASH-TABLE*)))           (BEFORE-FORMS (MAPCAR 'SECOND (ADVICE-BEFORE ADVICE)))           (AFTER-FORMS (MAPCAR 'SECOND (ADVICE-AFTER ADVICE)))           (AROUND-FORMS (MAPCAR 'SECOND (ADVICE-AROUND ADVICE)))           (BODY-FORM (MAKE-AROUND-BODY CALLING-FORM AROUND-FORMS)))          `(,LAMBDA-CAR ,(IF (EQ LAMBDA-CAR 'LAMBDA)                             '(&REST XCL:ARGLIST)                             ARG-LIST)                  ,@(AND ARG-LIST (MEMBER LAMBDA-CAR '(IL:LAMBDA IL:NLAMBDA))                         `((DECLARE (SPECIAL ,@(IF (SYMBOLP ARG-LIST)                                                       (LIST ARG-LIST)                                                       ARG-LIST)))))                  (IL:\\CALLME '(:ADVISED ,ADVICE-NAME))                  (BLOCK NIL                      (XCL:DESTRUCTURING-BIND (IL:!VALUE . IL:!OTHER-VALUES)                             (MULTIPLE-VALUE-LIST (PROGN ,@BEFORE-FORMS ,BODY-FORM))                             ,@AFTER-FORMS                             (APPLY 'VALUES IL:!VALUE IL:!OTHER-VALUES)))))))(DEFUN MAKE-AROUND-BODY (CALLING-FORM AROUND-FORMS)   (REDUCE #'(LAMBDA (CURRENT-BODY NEXT-AROUND-FORM)                    (LET ((CANONICALIZED-AROUND-FORM (SUBST '(XCL:INNER)                                                            'IL:* NEXT-AROUND-FORM)))                         `(MACROLET ((XCL:INNER NIL ',CURRENT-BODY))                                 ,CANONICALIZED-AROUND-FORM)))          AROUND-FORMS :INITIAL-VALUE CALLING-FORM))(IL:* IL:|;;| "")(IL:* IL:|;;| "Dealing with the File Manager")(IL:PUTDEF (QUOTE IL:ADVICE) (QUOTE IL:FILEPKGCOMS) '((IL:COM IL:MACRO                                                             (IL:X (IL:P IL:* (                                                                              ADVICE-FILE-DEFINITIONS                                                                               'IL:X NIL)))                                                             IL:CONTENTS IL:NILL IL:ADD                                                              ADVICE-ADDTOCOM)                                                      (TYPE IL:DESCRIPTION "advice" IL:NEWCOM                                                             ADVICE-NEWCOM IL:GETDEF ADVICE-GETDEF                                                             IL:DELDEF ADVICE-DELDEF IL:PUTDEF                                                             ADVICE-PUTDEF IL:HASDEF ADVICE-HASDEF)))(IL:PUTDEF (QUOTE IL:ADVISE) (QUOTE IL:FILEPKGCOMS) '((IL:COM IL:MACRO                                                             (IL:X (IL:P IL:* (                                                                              ADVICE-FILE-DEFINITIONS                                                                               'IL:X T)))                                                             IL:CONTENTS ADVISE-CONTENTS IL:ADD                                                              ADVICE-ADDTOCOM)))(DEFUN XCL:REINSTALL-ADVICE (XCL::NAME &KEY XCL::BEFORE XCL::AFTER XCL::AROUND)   (IL:FOR XCL::ADVICE IL:IN XCL::BEFORE IL:DO (XCL:DESTRUCTURING-BIND (XCL::PRIORITY                                                                                    XCL::FORM)                                                                  XCL::ADVICE                                                                  (ADD-ADVICE XCL::NAME :BEFORE                                                                          XCL::PRIORITY XCL::FORM)))   (IL:FOR XCL::ADVICE IL:IN XCL::AFTER IL:DO (XCL:DESTRUCTURING-BIND (XCL::PRIORITY                                                                                   XCL::FORM)                                                                 XCL::ADVICE                                                                 (ADD-ADVICE XCL::NAME :AFTER                                                                         XCL::PRIORITY XCL::FORM)))   (IL:FOR XCL::ADVICE IL:IN XCL::AROUND IL:DO (XCL:DESTRUCTURING-BIND (XCL::PRIORITY                                                                                    XCL::FORM)                                                                  XCL::ADVICE                                                                  (ADD-ADVICE XCL::NAME :AROUND                                                                          XCL::PRIORITY XCL::FORM))))(DEFUN ADVICE-GETDEF (NAME TYPE OPTIONS)   (LET ((ADVICE (CAR (GETHASH NAME *ADVICE-HASH-TABLE*))))        (AND ADVICE (APPEND (IL:FOR ENTRY IL:IN (ADVICE-BEFORE ADVICE)                               IL:COLLECT (CONS ':BEFORE (COPY-TREE ENTRY)))                           (IL:FOR ENTRY IL:IN (ADVICE-AFTER ADVICE)                              IL:COLLECT (CONS ':AFTER (COPY-TREE ENTRY)))                           (IL:FOR ENTRY IL:IN (ADVICE-AROUND ADVICE)                              IL:COLLECT (CONS ':AROUND (COPY-TREE ENTRY)))))))(DEFUN ADVICE-PUTDEF (NAME TYPE DEFINITION)   (LET ((CANONICAL-DEFN (IL:FOR ENTRY IL:IN DEFINITION                            IL:COLLECT (LIST (CANONICALIZE-ADVICE-WHEN-SPEC (CAR ENTRY))                                                 (CANONICALIZE-ADVICE-WHERE-SPEC (COPY-TREE                                                                                  (CADR ENTRY)))                                                 (COPY-TREE (CADDR ENTRY)))))         (CURRENT-ADVICE (OR (CAR (GETHASH NAME *ADVICE-HASH-TABLE*))                             (CAR (SETF (GETHASH NAME *ADVICE-HASH-TABLE*)                                        (CONS (MAKE-ADVICE)                                              NIL))))))        (SETF (ADVICE-BEFORE CURRENT-ADVICE)              (MAPCAR #'REST (IL:FOR ENTRY IL:IN CANONICAL-DEFN                                IL:WHEN (EQ (CAR ENTRY)                                                :BEFORE) IL:COLLECT ENTRY)))        (SETF (ADVICE-AFTER CURRENT-ADVICE)              (MAPCAR #'REST (IL:FOR ENTRY IL:IN CANONICAL-DEFN                                IL:WHEN (EQ (CAR ENTRY)                                                :AFTER) IL:COLLECT ENTRY)))        (SETF (ADVICE-AROUND CURRENT-ADVICE)              (MAPCAR #'REST (IL:FOR ENTRY IL:IN CANONICAL-DEFN                                IL:WHEN (EQ (CAR ENTRY)                                                :AROUND) IL:COLLECT ENTRY)))        (IF (CONSP NAME)            (XCL:READVISE-FUNCTION (FIRST NAME)                   :IN                   (THIRD NAME))            (XCL:READVISE-FUNCTION NAME))))(DEFUN ADVICE-DELDEF (NAME TYPE)   (DECLARE (IGNORE TYPE))   (WHEN (MEMBER NAME IL:ADVISEDFNS :TEST 'EQUAL)       (IF (CONSP NAME)           (XCL:UNADVISE-FUNCTION (FIRST NAME)                  :IN                  (THIRD NAME))           (XCL:UNADVISE-FUNCTION NAME))       (FORMAT *TERMINAL-IO* "~S unadvised." NAME))   (REMHASH NAME *ADVICE-HASH-TABLE*))(DEFUN ADVICE-HASDEF (NAME TYPE SOURCE)   (AND (GETHASH NAME *ADVICE-HASH-TABLE*)        (OR NAME T)))(DEFUN ADVICE-NEWCOM (NAME TYPE LISTNAME FILE)(IL:* IL:|;;;| "If you make a new com for ADVICE, you should make an ADVISE command.")   (IL:DEFAULTMAKENEWCOM NAME 'IL:ADVISE LISTNAME FILE))(DEFUN ADVICE-FILE-DEFINITIONS (NAMES READVISE?)(IL:* IL:|;;;| "READVISE? is true for the File Manager command ADVISE and false for the command ADVICE.  For ADVISE, we want to emit a form to readvise the named functions after reinstalling the advice.")   (LET    ((REAL-NAMES NIL))    `(,@(IL:FOR FN IL:IN NAMES           IL:COLLECT (LET* ((NAME (IL:IF (CONSP FN)                                           IL:THEN (ASSERT (AND (EQ (SECOND FN)                                                                        :IN)                                                                    (= 3 (LENGTH FN)))                                                              NIL                                                              "~S should be of the form (FOO :IN BAR)"                                                              FN)                                                 FN                                         IL:ELSE (LET ((NAME (CANONICALIZE-ADVICE-SYMBOL FN))                                                           (OLD-ADVICE (GET FN 'IL:READVICE)))                                                          (WHEN OLD-ADVICE                                                              (ADD-OLD-STYLE-ADVICE NAME OLD-ADVICE)                                                              (REMPROP FN 'IL:READVICE))                                                          NAME)))                                 (ADVICE (CAR (GETHASH NAME *ADVICE-HASH-TABLE*))))                                (ASSERT (NOT (NULL ADVICE))                                       NIL "Can't find advice for ~S" NAME)                                (PUSH NAME REAL-NAMES)                                `(XCL:REINSTALL-ADVICE                                  ',NAME                                  ,@(AND (ADVICE-BEFORE ADVICE)                                         `(:BEFORE ',(ADVICE-BEFORE ADVICE)))                                  ,@(AND (ADVICE-AFTER ADVICE)                                         `(:AFTER ',(ADVICE-AFTER ADVICE)))                                  ,@(AND (ADVICE-AROUND ADVICE)                                         `(:AROUND ',(ADVICE-AROUND ADVICE))))))      ,@(AND READVISE? `((IL:READVISE ,@(REVERSE REAL-NAMES)))))))(DEFUN ADVISE-CONTENTS (COM NAME TYPE)   (AND (EQ TYPE 'IL:ADVICE)        (COND           ((NULL NAME)                                      (IL:* IL:\;                                                   "Return a list of the ADVICE's in the given COM.")            (CDR COM))           ((EQ NAME 'T)                                     (IL:* IL:\;                                              "Return T if there are ANY ADVICE's in the given COM.")            (NOT (NULL (CDR COM))))           ((OR (SYMBOLP NAME)                (= (LENGTH NAME)                   3)                (EQ (SECOND NAME)                    :IN))                                    (IL:* IL:\;                                               "Return T iff an ADVICE named NAME in the given COM.")            (AND (MEMBER NAME (CDR COM)                        :TEST                        'EQUAL)                 T))           (T                                                (IL:* IL:\; "NAME is a list of names.  Return the intersection of that list with the ADVICE's in the given COM.")              (INTERSECTION NAME (CDR COM)                     :TEST                     'EQUAL)))))(DEFUN ADVICE-ADDTOCOM (COM NAME TYPE NEAR)(IL:* IL:|;;;| "This is the ADD method for both of the ADVICE and ADVISE commands.")(IL:* IL:|;;;| "Add the given name only if the type is ADVICE.  Also, add it to ADVICE commands only if a NEAR was specified.  We want to normally create only ADVISE commands.  If the user really wants an ADVICE command, they'll have to create it themselves.")   (AND (EQ TYPE 'IL:ADVICE)        (OR (EQ (CAR COM)                'IL:ADVISE)            (NOT (NULL NEAR)))        (IL:ADDTOCOM1 COM NAME NEAR NIL)))(IL:PUTPROPS IL:ADVISED IL:PROPTYPE IGNORE)(IL:* IL:|;;| "")(IL:* IL:|;;| "Dealing with old-style advice")(DEFUN IL:READVISE1 (IL:FN)   (FLET ((IL:READVISE-ENTRY (IL:ENTRY)                 (IL:IF (IL:LISTP IL:ENTRY)                     IL:THEN (XCL:READVISE-FUNCTION (FIRST IL:ENTRY)                                        :IN                                        (THIRD IL:ENTRY))                   IL:ELSE (XCL:READVISE-FUNCTION IL:ENTRY))))         (IL:IF (IL:LISTP IL:FN)             IL:THEN (ASSERT (IL:STRING.EQUAL (SECOND IL:FN)                                        "IN")                                NIL "~S should be in the form (FOO IN BAR).~%" IL:FN)                   (IL:READVISE-ENTRY IL:FN)           IL:ELSE (LET ((IL:NAME (CANONICALIZE-ADVICE-SYMBOL IL:FN))                             (IL:OLD-ADVICE (GET IL:FN 'IL:READVICE)))                            (IL:IF IL:OLD-ADVICE                                IL:THEN (ADD-OLD-STYLE-ADVICE IL:NAME IL:OLD-ADVICE)                                      (REMPROP IL:FN 'IL:READVICE))                            (IL:READVISE-ENTRY IL:NAME)))))(DEFUN ADD-OLD-STYLE-ADVICE (NAME OLD-ADVICE)(IL:* IL:|;;;| "OLD-ADVICE should the value of the READVICE property of some symbol.  Note that the CAR of that value is the old middle-man used for -IN- advice.  Thus, we take the CDR below.")   (WHEN (NOT (MEMBER NAME IL:ADVISEDFNS :TEST 'EQUAL))         (DELETE-ADVICE NAME))   (IL:FOR ADVICE IL:IN (CDR OLD-ADVICE) IL:DO (XCL:DESTRUCTURING-BIND                                                            (WHEN WHERE WHAT)                                                            ADVICE                                                            (IL:* IL:|;;|                                                    "Translate Interlisp names to the new standard.")                                                            (ADD-ADVICE NAME (                                                                        CANONICALIZE-ADVICE-WHEN-SPEC                                                                              WHEN)                                                                   (CANONICALIZE-ADVICE-WHERE-SPEC                                                                    WHERE)                                                                   WHAT))))(DEFUN CANONICALIZE-ADVICE-SYMBOL (SYMBOL)   (LET ((IN-POS (IL:STRPOS "-IN-" SYMBOL)))        (IF (NULL IN-POS)            SYMBOL            (LIST (IL:SUBATOM SYMBOL 1 (1- IN-POS))                  :IN                  (IL:SUBATOM SYMBOL (+ IN-POS 4)                         NIL)))))(DEFUN CANONICALIZE-ADVICE-WHEN-SPEC (SPEC)   (IF (NULL SPEC)       ':BEFORE       (INTERN (STRING SPEC)              "KEYWORD")))(DEFUN CANONICALIZE-ADVICE-WHERE-SPEC (SPEC)   (CASE SPEC       ((NIL LAST IL:BOTTOM IL:END :LAST) ':LAST)       ((IL:TOP IL:FIRST :FIRST) ':FIRST)       (T (IF (CONSP SPEC)              SPEC              (ERROR "Illegal WHERE specification to ADVISE: ~S" SPEC)))))(XCL:DEF-DEFINE-TYPE XCL:ADVISED-FUNCTIONS "Advised function definitions")(XCL:DEFDEFINER (XCL:DEFADVICE (:PROTOTYPE (LAMBDA (XCL::NAME)                                                      `(XCL:DEFADVICE ,XCL::NAME                                                          "advice")))) XCL:ADVISED-FUNCTIONS (                                                                                            XCL::NAME                                                                                              &BODY                                                                                     XCL::ADVICE-FORMS                                                                                              )   `(PROGN     ,.(XCL:WITH-COLLECTION        (DOLIST (XCL::ADVICE XCL::ADVICE-FORMS)            (XCL:COLLECT (XCL:DESTRUCTURING-BIND                          (XCL::FN-TO-ADVISE XCL::FORM &KEY XCL::IN WHEN XCL::PRIORITY)                          XCL::ADVICE                          `(XCL:ADVISE-FUNCTION ',XCL::FN-TO-ADVISE ',XCL::FORM                                  ,@(AND XCL::IN `(:IN ',XCL::IN))                                  ,@(AND WHEN `(:WHEN ,WHEN))                                  ,@(AND XCL::PRIORITY `(:PRIORITY ,XCL::PRIORITY)))))))))(IL:* IL:|;;| "Arrange for the proper package.  Because of the DEFSTRUCT above, we must have the file dumped in the SYSTEM package.")(IL:PUTPROPS IL:ADVISE IL:MAKEFILE-ENVIRONMENT (:READTABLE "XCL" :PACKAGE "SYSTEM"))(IL:PUTPROPS IL:ADVISE IL:FILETYPE :COMPILE-FILE)(IL:DECLARE\: IL:DONTEVAL@LOAD IL:DOEVAL@COMPILE IL:DONTCOPY IL:COMPILERVARS (IL:ADDTOVAR IL:NLAMA IL:READVISE IL:UNADVISE)(IL:ADDTOVAR IL:NLAML )(IL:ADDTOVAR IL:LAMA IL:ADVISE))(IL:PUTPROPS IL:ADVISE IL:COPYRIGHT ("Venue & Xerox Corporation" T 1978 1984 1986 1987 1988 1990))(IL:DECLARE\: IL:DONTCOPY  (IL:FILEMAP (NIL (3354 7926 (IL:ADVISE 3367 . 5496) (IL:UNADVISE 5498 . 6418) (IL:READVISE 6420 . 7924)))))IL:STOP