(DEFINE-FILE-INFO PACKAGE "INTERLISP" READTABLE "INTERLISP" BASE 10)

(FILECREATED " 4-Jan-2022 14:09:48" {DSK}<Users>kaplan>Local>medley3.5>my-medley>library>SPY.;2 63314  

      :CHANGES-TO (VARS SPYCOMS)
                  (FNS SPY.MAKE.TREE)

      :PREVIOUS-DATE "29-Apr-94 14:13:52" {DSK}<Users>kaplan>Local>medley3.5>my-medley>library>SPY.;1
)


(* ; "
Copyright (c) 1984-1985, 1987-1988, 1990-1991, 1993-1994 by Venue & Xerox Corporation.
")

(PRETTYCOMPRINT SPYCOMS)

(RPAQQ SPYCOMS
       [(VARS SPY.BORDERS SPY.BUFFER.SIZE SPY.FRAGMENTS SPY.NOMERGEFNS SPY.MERGEINFO (SPY.HASH)
              (SPY.GRAPH.MENU)
              SPY.SHOW.PERCENTAGES SPY.SMALLGHOSTS SPY.ICON)
        (INITVARS (SPY.NEXT 0)
               (SPY.BUFFER)
               (SPY.SHOWCOUNTS T)
               (SPY.SHOW.THRESHOLD 1)
               (SPY.MAXLINES 10)
               (SPY.FREQUENCY 10)
               (SPY.FONT '(GACHA 8))
               (SPY.TREE))
        (COMS * SPYOBJCOMS)
        (FNS SPY.FIND.TREE SPY.TOGGLE SPY.TREE SPY.LEGEND SPY.GRAPH.EDITOR SPY.END SPY.MAKEGRAPHNODES
             SPY.MAX SPY.MERGE SPY.MERGE1 SPY.MERGETREE SPY.NEXT.TREE SPY.SUM SPY.TITLE SPY.MAKE.TREE
             SPY.UPDATE.TITLE SPY.DELETE SPY.DRAWBOX SPY.BUFFER.ENTRY SPY.BUTTON SPY.END.ENTRY 
             SPY.START SPY.INIT \SPY.INTERRUPT SPY.DUMP.BUFFER SPY.START.ENTRY SPY.ADD.ENTRY 
             SPY.ORIGINAL SPY.OVERFLOW SPY.MERGE.CALLEES SPY.PRINT)
        (COMS (INITVARS (SPY.BUTTON))
              (VARS SPY.OPEN SPY.CLOSED))
        (VARIABLES SPY.POINTERS)
        (GLOBALVARS SPY.OVERFLOWED \PERIODIC.INTERRUPT SPY.TREE SPY.BUFFER.SIZE SPY.NEXT 
               SPY.BUFFER.THRESHOLD SPY.BUFFER SPY.FREQUENCY SPY.SHOW.THRESHOLD SPY.MAXLINES SPY.FONT
               )
        (MACROS WITH-SPY WITH.SPY)
        (DECLARE%: DONTCOPY (RECORDS SPYRECORD SPYDATA))
        (INITRECORDS SPYRECORD)
        (DECLARE%: DOCOPY DOEVAL@COMPILE (FILES GRAPHER READNUMBER IMAGEOBJ))
        (P (MOVD? 'NILL 'MODERNWINDOW])

(RPAQQ SPY.BORDERS
       ((NORMAL "Normal" 2 -1)
        (GHOST "Shown elsewhere" 2 8840)
        (RECURSIVEGHOST "End of recursive chain" 2 0 -1)
        (MERGED "Includes other branches" 4 42405)
        (SELFRECURSIVE "Includes self-recursive calls" 2 61375)
        (RECURSIVE "Head of recursive chain" 4 28086)
        (ENDOFLINE "exceeded depth limit" 6 64510)))

(RPAQQ SPY.BUFFER.SIZE 5120)

(RPAQQ SPY.FRAGMENTS T)

(RPAQQ SPY.NOMERGEFNS (SI::*UNWIND-PROTECT* CL:EVAL \EVAL-PROGN \INTERPRET-ARGUMENTS \INTERPRETER 
                             \INTERPRETER1 ERRORSET \EVAL \EVALFORM APPLY \PROGV EVAL))

(RPAQQ SPY.MERGEINFO
       ((EXEC :EXEC)
        (EXEC-READ-LINE :EXEC)
        (EXEC-READ :EXEC)
        (XCL-USER::LEX-DO-EVENT :EXEC)
        (DO-EVENT :EXEC)
        (EVAL-INPUT :EXEC)
        (SI::*UNWIND-PROTECT* :ANY)
        (\MAKE.PROCESS0 T)
        (\PROC.REPEATEDLYEVALQT T)
        (\EVALFORM T :EVAL)
        (PROGN PROGN :EVAL T)
        (TTYIN1 TTYIN)
        (TTBIN TTYIN)
        (TTWAITFORINPUT TTYIN)
        (\PROGV :ANY)))

(RPAQQ SPY.HASH NIL)

(RPAQQ SPY.GRAPH.MENU NIL)

(RPAQQ SPY.SHOW.PERCENTAGES T)

(RPAQQ SPY.SMALLGHOSTS T)

(RPAQQ SPY.ICON #*(56 28)OOOOOOOOOOOOOO@@OOOOOOOOOOOOOO@@L@@@@@@@@@@@@C@@L@@@@@@@@@@@@C@@L@@@@@@@@@@@@C@@L@@@@@@@@COONC@@L@@@@@@@@B@@BC@@L@@@@@@@@B@@BC@@L@GOOOO@@N@@BC@@L@D@@@A@CB@@BC@@L@ENODE@LB@@BC@@L@E@IBIC@COONC@@L@ENOAAL@@@@@C@@L@DBHAAF@COONC@@L@ENHAAAHB@@BC@@L@D@@@A@FB@@BC@@L@GOOOO@AJ@@BC@@L@@@@@@@@F@@BC@@L@@@@@@@@B@@BC@@L@@@@@@@@B@@BC@@L@@@@@@@@B@@BC@@L@@@@@@@@B@@BC@@L@@@@@@@@B@@BC@@L@@@@@@@@COONC@@L@@@@@@@@@@@@C@@L@@@@@@@@@@@@C@@OOOOOOOOOOOOOO@@OOOOOOOOOOOOOO@@
)

(RPAQ? SPY.NEXT 0)

(RPAQ? SPY.BUFFER )

(RPAQ? SPY.SHOWCOUNTS T)

(RPAQ? SPY.SHOW.THRESHOLD 1)

(RPAQ? SPY.MAXLINES 10)

(RPAQ? SPY.FREQUENCY 10)

(RPAQ? SPY.FONT '(GACHA 8))

(RPAQ? SPY.TREE )

(RPAQQ SPYOBJCOMS
       ((FNS SPYOBJ SPYOBJ.BUTTON SPYOBJ.SAVE SPYOBJ.COPY SPYOBJ.GET SPYOBJ.IMAGEBOX SPYOBJ.DISPLAY 
             SPYOBJ.LABEL SPYOBJ.HEIGHT SPYOBJ.COPYIN SPY.COPYBUTTON SPY.MERGEINFO)
        [VARS (SPYOBJ.IMAGEFNS (IMAGEFNSCREATE (FUNCTION SPYOBJ.DISPLAY)
                                      (FUNCTION SPYOBJ.IMAGEBOX)
                                      (FUNCTION SPYOBJ.SAVE)
                                      (FUNCTION SPYOBJ.GET)
                                      (FUNCTION SPYOBJ.COPY)
                                      (FUNCTION SPYOBJ.BUTTON)
                                      (FUNCTION SPYOBJ.COPYIN)
                                      NIL NIL NIL NIL NIL NIL 'SPYNODE]
        (DECLARE%: DONTCOPY DOEVAL@COMPILE (RECORDS FX SPYOBJDATA))
        (INITRECORDS SPYOBJDATA)))
(DEFINEQ

(SPYOBJ
(LAMBDA (NAME PERCENT STATUS) (* ; "Edited  9-Sep-87 17:56 by Masinter") (IMAGEOBJCREATE (create SPYOBJDATA LABEL _ NAME PERCENT _ PERCENT CACHEDLABEL _ (LET ((*PRINT-PRETTY* NIL) (*PRINT-LEVEL* 1) (*PRINT-LENGTH* 1)) (CL:FORMAT NIL "~D ~S" PERCENT LABEL))) SPYOBJ.IMAGEFNS))
)

(SPYOBJ.BUTTON
(LAMBDA (OBJ WINDOWSTREAM SEL RELX RELY WINDOW TEXT BUTTON) (* lmm " 9-Jun-85 00:40") NIL))

(SPYOBJ.SAVE
(LAMBDA (OBJ STREAM) (* edited%: "11-Jun-85 05:03") (PRIN2 (fetch OBJECTDATUM OBJ) STREAM FILERDTBL)))

(SPYOBJ.COPY
(LAMBDA (OBJ) (* lmm " 9-Jun-85 00:43") OBJ))

(SPYOBJ.GET
(LAMBDA (STREAM TEXTSTREAM) (* lmm " 9-Jun-85 00:44") (IMAGEOBJCREATE (READ STREAM FILERDTBL) SPYOBJ.IMAGEFNS))
)

(SPYOBJ.IMAGEBOX
  [LAMBDA (OBJ FONTSOURCE)                               (* ; "Edited 16-Aug-88 11:07 by sye")
    (OR FONTSOURCE (SETQ FONTSOURCE SPY.FONT))
    (LET ((DATA (fetch OBJECTDATUM OBJ)))
         (LET ((HEIGHT (SPYOBJ.HEIGHT OBJ FONTSOURCE)))
              (create IMAGEBOX
                     XSIZE _ (STRINGWIDTH (SPYOBJ.LABEL OBJ)
                                    FONTSOURCE)
                     YSIZE _ HEIGHT
                     YDESC _ 0
                     XKERN _ 0])

(SPYOBJ.DISPLAY
(LAMBDA (OBJ STREAM) (* lmm " 9-Jun-85 01:13") (DSPFONT SPY.FONT STREAM) (LET ((DATA (fetch OBJECTDATUM OBJ))) (LET ((HEIGHT (SPYOBJ.HEIGHT OBJ STREAM))) (RELMOVETO 0 (QUOTIENT (DIFFERENCE HEIGHT (QUOTIENT (FONTHEIGHT STREAM) 2)) 2) STREAM) (PRIN3 (SPYOBJ.LABEL OBJ) STREAM))))
)

(SPYOBJ.LABEL
(LAMBDA (OBJ) (* lmm " 9-Jun-85 01:24") (LET ((DATUM (fetch OBJECTDATUM OBJ))) (with SPYOBJDATA DATUM CACHEDLABEL)))
)

(SPYOBJ.HEIGHT
(LAMBDA (OBJ STREAM) (* lmm " 9-Jun-85 00:51") (LET ((DATUM (fetch OBJECTDATUM OBJ)) (FH (FONTHEIGHT STREAM))) (with SPYOBJDATA DATUM (MAX FH (QUOTIENT (TIMES PERCENT SPY.MAXLINES FH) 100)))))
)

(SPYOBJ.COPYIN
(LAMBDA (A B C) (HELP)))

(SPY.COPYBUTTON
(LAMBDA (WINDOW) (* lmm " 9-Jun-85 01:55") (SPY.GRAPH.EDITOR WINDOW T)))

(SPY.MERGEINFO
  [LAMBDA (NAME SPYDATA PARENT-NAME)                  (* ; "Edited 28-Apr-94 14:00 by sybalsky")
    (OR [AND (fetch (SPYDATA MERGEINFO) of SPYDATA)
             (for X in (fetch (SPYDATA MERGEINFO) of SPYDATA)
                when (AND (EQ (CAR X)
                                  NAME)
                              (FMEMB PARENT-NAME (CDR X))) do (RETURN (CDR X]
        (CDR (FASSOC NAME SPY.MERGEINFO))
        (if (STRPOS "\interpret-" NAME)
            then '(:INTERPRETER CL:EVAL])
)

(RPAQ SPYOBJ.IMAGEFNS
      (IMAGEFNSCREATE (FUNCTION SPYOBJ.DISPLAY)
             (FUNCTION SPYOBJ.IMAGEBOX)
             (FUNCTION SPYOBJ.SAVE)
             (FUNCTION SPYOBJ.GET)
             (FUNCTION SPYOBJ.COPY)
             (FUNCTION SPYOBJ.BUTTON)
             (FUNCTION SPYOBJ.COPYIN)
             NIL NIL NIL NIL NIL NIL 'SPYNODE))
(DECLARE%: DONTCOPY DOEVAL@COMPILE 
(DECLARE%: EVAL@COMPILE

(ACCESSFNS FX ((FXBLOCK (ADDSTACKBASE DATUM)))               (* ; "frame extension index")
              (BLOCKRECORD FXBLOCK ((FLAGS BITS 3)           (* ; "= \STK.FX")
                                    (FAST FLAG)
                                    (NIL FLAG)
                                    (INCALL FLAG)            (* ; 
                                                             "set when fncall microcode has to punt")
                                    (VALIDNAMETABLE FLAG)    (* ; 
                                  "if on, NAMETABLE field is filled in.  If off, is same as FNHEADER")
                                    (NOPUSH FLAG)            (* ; 
                           "when returning to this frame, don't push a value.  Set by interrupt code")
                                    (USECNT BITS 8)
                                    (%#ALINK WORD)           (* ; "low bit is SLOWP")
                                    (FNHEADER FULLXPOINTER)
                                    (NEXTBLOCK WORD)
                                    (PC WORD)
                                    (NAMETABLE# FULLXPOINTER)
                                    (%#BLINK WORD)
                                    (%#CLINK WORD)))
              (BLOCKRECORD FXBLOCK ((FLAGBYTE BYTE)
                                    (NIL BYTE)
                                    (NIL BITS 15)            (* ; "most of the bits of #ALINK")
                                    (SLOWP FLAG)             (* ; 
                           "if on, then BLINK and CLINK fields are valid.  If off, they are implicit")
                                    (NIL FULLXPOINTER 2)
                                    (NAMETABHI WORD)
                                    (NAMETABLO WORD)))
              (TYPE? (IEQ (fetch (FX FLAGS) of DATUM)
                          \STK.FX))
              [ACCESSFNS FX ((NAMETABLE (COND
                                           ((fetch (FX VALIDNAMETABLE) of DATUM)
                                            (fetch (FX NAMETABLE#) of DATUM))
                                           (T (fetch (FX FNHEADER) of DATUM)))
                                    (PROGN (replace (FX FAST) of DATUM with NIL)
                                           (replace (FX NAMETABLE#) of DATUM with NEWVALUE)
                                           (replace (FX VALIDNAMETABLE) of DATUM with T)))
                             (FRAMENAME (fetch (FNHEADER FRAMENAME) of (fetch (FX NAMETABLE)
                                                                          of DATUM)))
                             (INVALIDP (EQ DATUM 0))         (* ; 
                                     "true when A/CLink points at nobody, i.e. FX is bottom of stack")
                             [FASTP (NOT (fetch (FX SLOWP) of DATUM))
                                    (PROGN (CHECK (NULL NEWVALUE))
                                           (COND
                                              ((fetch (FX FASTP) of DATUM)
                                               (replace (FX %#BLINK) of DATUM
                                                  with (fetch (FX DUMMYBF) of DATUM))
                                               (replace (FX %#CLINK) of DATUM
                                                  with (fetch (FX %#ALINK) of DATUM))
                                               (replace (FX SLOWP) of DATUM with T]
                             [BLINK (COND
                                       ((fetch (FX FASTP) of DATUM)
                                        (fetch (FX DUMMYBF) of DATUM))
                                       (T (fetch (FX %#BLINK) of DATUM)))
                                    (PROGN (replace (FX %#BLINK) of DATUM with NEWVALUE)
                                           (COND
                                              ((fetch (FX FASTP) of DATUM)
                                               (replace (FX %#CLINK) of DATUM
                                                  with (fetch (FX %#ALINK) of DATUM))
                                               (replace (FX SLOWP) of DATUM with T]
                             [CLINK (IDIFFERENCE (COND
                                                    ((fetch (FX FASTP) of DATUM)
                                                     (fetch (FX %#ALINK) of DATUM))
                                                    (T (fetch (FX %#CLINK) of DATUM)))
                                           \#ALINK.OFFSET)
                                    (PROGN (replace (FX %#CLINK) of DATUM with (IPLUS NEWVALUE 
                                                                                      \#ALINK.OFFSET)
                                                  )
                                           (COND
                                              ((fetch (FX FASTP) of DATUM)
                                               (replace (FX %#BLINK) of DATUM
                                                  with (fetch (FX DUMMYBF) of DATUM))
                                               (replace (FX SLOWP) of DATUM with T]
                             [ALINK (IDIFFERENCE (FLOOR (fetch (FX %#ALINK) of DATUM)
                                                        WORDSPERCELL)
                                           \#ALINK.OFFSET)
                                    (PROGN [COND
                                              ((fetch (FX FASTP) of DATUM)
                                               (replace (FX %#BLINK) of DATUM
                                                  with (fetch (FX DUMMYBF) of DATUM))
                                               (replace (FX %#CLINK) of DATUM
                                                  with (fetch (FX %#ALINK) of DATUM]
                                           (replace (FX %#ALINK) of DATUM with (IPLUS NEWVALUE 
                                                                                      \#ALINK.OFFSET
                                                                                      (SUB1 
                                                                                         WORDSPERCELL
                                                                                            ]
                             [ACLINK (SHOULDNT)
                                    (PROGN [COND
                                              ((fetch (FX FASTP) of DATUM)
                                               (replace (FX %#BLINK) of DATUM
                                                  with (fetch (FX DUMMYBF) of DATUM]
                                           (replace (FX %#CLINK) of DATUM with (IPLUS NEWVALUE 
                                                                                      \#ALINK.OFFSET)
                                                  )
                                           (replace (FX %#ALINK) of DATUM with (IPLUS NEWVALUE 
                                                                                      \#ALINK.OFFSET
                                                                                      (SUB1 
                                                                                         WORDSPERCELL
                                                                                            ]
                                                             (* ; 
                                      "replaces A & C Links at once more efficiently than separately")
                             (DUMMYBF (IDIFFERENCE DATUM WORDSPERCELL))

                             (* ;; "This is either an actual BF or %"residual%" BF that provides enough BF to find its IVAR slot.  This means that when a FX is copied, the cell preceding the FX is copied too.")

                             (IVAR (fetch (BF IVAR) of (fetch (FX DUMMYBF) of DATUM)))
                             [CHECKED (AND (type? FX DATUM)
                                           (OR (IEQ (fetch (FX DUMMYBF) of DATUM)
                                                    (fetch (FX BLINK) of DATUM))
                                               (AND (fetch (BF RESIDUAL) of (fetch (FX DUMMYBF)
                                                                               of DATUM))
                                                    (IEQ (fetch (BF IVAR) of (fetch (FX DUMMYBF)
                                                                                of DATUM))
                                                         (fetch (BF IVAR) of (fetch (FX BLINK)
                                                                                of DATUM]
                             (FIRSTPVAR (IPLUS DATUM (fetch (FX FXSIZE) of T)))
                                                             (* ; "stack offset of PVAR0")
                             (FXSIZE (PROGN 10))             (* ; 
                                                             "fixed overhead from flags thru clink")
                             (PADDING (PROGN 4))             (* ; 
                                                            "doublecell of garbage for microcode use")
                             (FIRSTTEMP (IPLUS (fetch (FX FIRSTPVAR) of DATUM)
                                               (fetch (FX NPVARWORDS) of DATUM)
                                               (fetch (FX PADDING) of DATUM)))
                                                             (* ; 
                                                 "note that NPVARWORDS is obtained from the FNHEADER")
                             (SIZE (IDIFFERENCE (fetch (FX NEXTBLOCK) of DATUM)
                                          DATUM])

(RECORD SPYOBJDATA (CACHEDLABEL PERCENT LABEL))
)
)
(DEFINEQ

(SPY.FIND.TREE
  [LAMBDA (FN)                                               (* ; "Edited 25-Sep-87 16:23 by jop")

    (OR (find X in SPY.TREE suchthat (EQ (fetch (SPYRECORD NAME) of X)
                                         FN))
        (CAR (push SPY.TREE (create SPYRECORD
                                   NAME _ FN
                                   COUNT _ 0])

(SPY.TOGGLE
(LAMBDA NIL (* lmm "24-Oct-84 22:49") (if (EQ \PERIODIC.INTERRUPT (QUOTE \SPY.INTERRUPT)) then (SPY.END) (RESETFORM (CURSOR WAITINGCURSOR) (SPY.TREE 10)) else (SPY.START)))
)

(SPY.TREE
  [LAMBDA (THRESHOLD INDIVIDUALP MERGETYPE DEPTHLIMIT)   (* ; "Edited  9-Dec-87 13:10 by sye")

    (COND
       ((NULL SPY.TREE)
        "no spy samples have been gathered")
       (T (PROG ((SPYDATA (create SPYDATA
                                 PACKAGE _ *PACKAGE*
                                 READTABLE _ *READTABLE*
                                 PRINT-CASE _ *PRINT-CASE*
                                 CUMULATIVE _ (NOT INDIVIDUALP)
                                 THRESHOLD _ (OR THRESHOLD SPY.SHOW.THRESHOLD)
                                 MERGETYPE _ (OR (if (EQ MERGETYPE 'DEFAULT)
                                                     then T
                                                   else MERGETYPE)
                                                 (COND
                                                    (INDIVIDUALP 'ALL)
                                                    (T T)))
                                 DEPTH _ DEPTHLIMIT)))
                (SPY.MAKE.TREE (SPY.MERGE SPY.TREE SPYDATA)
                       SPYDATA])

(SPY.LEGEND
(LAMBDA NIL (* lmm "28-Sep-84 21:27") (SHOWGRAPH (LAYOUTGRAPH (for X in SPY.BORDERS collect (create GRAPHNODE NODEID _ X NODELABEL _ (CADR X) TONODES _ NIL NODEFONT _ SPY.FONT NODEBORDER _ (CDDR X) NODELABELSHADE _ (CADDR (CDDR X)))) (REVERSE SPY.BORDERS) NIL SPY.FONT NIL 10) "SPY border interpretation" (QUOTE NILL) (QUOTE NILL)))
)

(SPY.GRAPH.EDITOR
  [LAMBDA (W COPY)                                    (* ; "Edited 29-Apr-94 14:03 by sybalsky")
    (PROG* ((TREES (WINDOWPROP W 'TREES))
            NEW-TREES
            (TOPCOUNT (WINDOWPROP W 'TOPCOUNT))
            (WINDOW W)
            NODE LASTNODE ACTION (SPYDATA (WINDOWPROP W 'SPYDATA))
            PENDING
            [MULTIPLE (AND (= (LOGAND LASTKEYBOARD 32)
                              32)
                           (MOUSESTATE (OR LEFT MIDDLE]
            (*READTABLE* (fetch (SPYDATA READTABLE) of SPYDATA))
            (*PACKAGE* (fetch (SPYDATA PACKAGE) of SPYDATA))
            (*PRINT-CASE* (fetch (SPYDATA PRINT-CASE) of SPYDATA)))
           (TOTOPW W)
           (do (SETQ NODE (OR (NODELST/AS/MENU (fetch (GRAPH GRAPHNODES)
                                                      of (WINDOWPROP W 'GRAPH))
                                         (CONS (LASTMOUSEX W)
                                               (LASTMOUSEY W)))
                                  COPY))
                  (if (NEQ NODE LASTNODE)
                      then [COND
                                  (LASTNODE (if (EQ LASTNODE T)
                                                then (INVERTW W)
                                              else (FLIPNODE LASTNODE W]
                            [COND
                               (NODE (if (EQ NODE T)
                                         then (INVERTW W)
                                       else (FLIPNODE NODE W]
                            (SETQ LASTNODE NODE)) repeatwhile (MOUSESTATE (OR MIDDLE LEFT)))
           [COND
              (COPY (RETURN (COND
                               ((EQ NODE T)
                                (INVERTW W)
                                (GRAPHERCOPYBUTTONEVENTFN W))
                               (T (FLIPNODE NODE W)
                                  (COPYINSERT (fetch (SPYRECORD NAME) of (fetch
                                                                                  (GRAPHNODE NODEID)
                                                                                    of NODE]
           (if NODE
               then
               (LET [(NAME (fetch (SPYRECORD NAME) of (fetch (GRAPHNODE NODEID)
                                                                 of NODE]
                    (SELECTQ [SETQ ACTION (MENU (CONSTANT (create MENU
                                                                 ITEMS _
                                                                 '(NewSubTree SubTree Delete Merge 
                                                                         Edit InspectCode]
                        (NIL (FLIPNODE NODE W)               (* ; "no tree action ")
                             )
                        (Edit (FLIPNODE NODE W)
                              (ED NAME '(FUNCTIONS FNS :DONTWAIT :DISPLAY)))
                        (InspectCode (FLIPNODE NODE W)
                                     (INSPECTCODE NAME))
                        (Delete                              (* ; 
                                                           "remove this node. Leave still marked")
                                (push (fetch (SPYDATA DELETED) of SPYDATA)
                                       NAME)
                                (SETQ PENDING "delete"))
                        (Merge [if (fetch (GRAPHNODE FROMNODES) of NODE)
                                   then (push (fetch (SPYDATA MERGEINFO) of SPYDATA)
                                                   (LIST NAME (fetch (SPYRECORD NAME)
                                                                 of (CAR (fetch (GRAPHNODE
                                                                                         FROMNODES)
                                                                                of NODE]
                               (SETQ PENDING "merge"))
                        (NewSubTree (FLIPNODE NODE W)
                                    (SPY.MAKE.TREE (SPY.MERGE
                                                        (SPY.ORIGINAL (LIST (fetch
                                                                                 (GRAPHNODE NODEID)
                                                                                   of NODE)))
                                                        SPYDATA)
                                           (create SPYDATA
                                              using SPYDATA PENDING _ NIL DELETED _ NIL)))
                        ((SubTree) 
                             (SETQ NEW-TREES (SPY.MERGE (SPY.ORIGINAL
                                                             (LIST (fetch (GRAPHNODE NODEID)
                                                                      of NODE)))
                                                    SPYDATA)))
                        (printout PROMPTWINDOW T "SORRY, FEATURE NOT IMPLEMENTED YET")))
             elseif (INSIDE? (WINDOWPROP W 'REGION)
                               LASTMOUSEX LASTMOUSEY)
               then (SELECTQ [MENU (create
                                        MENU
                                        ITEMS _
                                        `(Legend Inspect SetThreshold ,(COND
                                                                          ((fetch (SPYDATA 
                                                                                           CUMULATIVE
                                                                                             )
                                                                              of SPYDATA)
                                                                           'Individual)
                                                                          (T 'Cumulative))
                                                ,@(SELECTQ (fetch (SPYDATA MERGETYPE)
                                                              of SPYDATA)
                                                      (ALL '(MergeDefault MergeNone))
                                                      (T '(MergeNone MergeAll))
                                                      ((NIL NONE) 
                                                           '(MergeDefault MergeAll))
                                                      (SHOULDNT]
                            (NIL)
                            (Legend (SPY.LEGEND))
                            (Inspect (INSPECT/PLIST SPYDATA))
                            (SetThreshold                    (* ; "no need to remerge")
                                          (replace (SPYDATA THRESHOLD) of SPYDATA
                                             with (RNUMBER "Threshold (percent)" NIL DEFAULTFONT
                                                             DEFAULTFONT))
                                          (SETQ PENDING "threshold"))
                            (MergeAll (replace (SPYDATA MERGETYPE) of SPYDATA
                                         with 'ALL)
                                      (SETQ PENDING "merge-type"))
                            (MergeNone (replace (SPYDATA MERGETYPE) of SPYDATA
                                          with 'NONE)
                                       (SETQ PENDING "merge-type"))
                            (MergeDefault (replace (SPYDATA MERGETYPE) of SPYDATA
                                             with T)
                                          (SETQ PENDING "merge-type"))
                            ((Cumulative Individual) 
                                 [replace (SPYDATA MERGETYPE) of SPYDATA
                                    with (COND
                                                ((change (fetch (SPYDATA CUMULATIVE)
                                                                of SPYDATA)
                                                        (NOT DATUM))
                                                 T)
                                                (T 'ALL]
                                 (SETQ PENDING "merge-type"))
                            (SHOULDNT)))
       DOIT
           (if (AND (NOT NEW-TREES)
                        MULTIPLE)
               then                                      (* ; 
                                                           "multiple action while shift down")
                     (if PENDING
                         then [if [NOT (STRPOS PENDING (WINDOWPROP W 'TITLE]
                                      then (WINDOWPROP W 'TITLE (CONCAT PENDING "/"
                                                                           (WINDOWPROP W 'TITLE]
                               (replace (SPYDATA PENDING) of SPYDATA with T))
             elseif (OR NEW-TREES PENDING (fetch (SPYDATA PENDING) of SPYDATA))
               then (SPY.MAKE.TREE (OR NEW-TREES (SPY.MERGE (SPY.ORIGINAL TREES)
                                                                SPYDATA))
                               (create SPYDATA using SPYDATA PENDING _ NIL DELETED _ NIL)
                               WINDOW])

(SPY.END
(LAMBDA NIL (* ; "Edited  9-Sep-87 17:51 by Masinter") (if (EQ \PERIODIC.INTERRUPT (QUOTE \SPY.INTERRUPT)) then (SETQ \PERIODIC.INTERRUPT) (SPY.DUMP.BUFFER) (if (OPENWP SPY.BUTTON) then (BITBLT SPY.CLOSED NIL NIL SPY.BUTTON))))
)

(SPY.MAKEGRAPHNODES
  [LAMBDA (TREE THRESHOLD SPYDATA)                    (* ; "Edited 28-Apr-94 14:00 by sybalsky")

(* ;;; "RETURNS NODE ID FOR TREE")

    (PROG ((LABEL (fetch (SPYRECORD NAME) of TREE))
           [COUNT (COND
                         ((fetch (SPYDATA CUMULATIVE)
                                 SPYDATA)
                          (fetch (SPYRECORD SUM) of TREE))
                         (T (fetch (SPYRECORD COUNT) of TREE]
           (STATUS (fetch (SPYRECORD STATUS) of TREE))
           HEIGHT BORDER WIDTH NODEBITMAP TOOSMALL)
          [SETQ BORDER (CDDR (OR (ASSOC STATUS SPY.BORDERS)
                                 (SHOULDNT]
          (push SPY.NODES (create
                               GRAPHNODE
                               NODEID _ TREE
                               NODELABEL _ (SPYOBJ LABEL (QUOTIENT (TIMES COUNT 100)
                                                                    TOPCOUNT)
                                                  STATUS)
                               TONODES _ (for X in (fetch (SPYRECORD CALLEES)
                                                              of TREE)
                                            when (OR (ZEROP THRESHOLD)
                                                         (IGEQ (SPY.MAX
                                                                (LIST X)
                                                                (NOT (fetch (SPYDATA CUMULATIVE)
                                                                            SPYDATA)))
                                                               THRESHOLD)) bind VAL
                                            do (push VAL (SPY.MAKEGRAPHNODES X THRESHOLD
                                                                        SPYDATA))
                                            finally (RETURN VAL))
                               NODEBORDER _ BORDER
                               NODEFONT _ SPY.FONT)))
    TREE])

(SPY.MAX
  [LAMBDA (TREES COUNTP MAX)                          (* ; "Edited 28-Apr-94 13:59 by sybalsky")
    [for X in TREES do (SETQ MAX (SPY.MAX (fetch (SPYRECORD CALLEES) of
                                                                                         X)
                                                    COUNTP
                                                    (IMAX (OR MAX (IMAX))
                                                          (if COUNTP
                                                              then (fetch (SPYRECORD COUNT)
                                                                          of X)
                                                            else (fetch (SPYRECORD SUM)
                                                                        of X]
    MAX])

(SPY.MERGE
  [LAMBDA (TREES SPYDATA)                             (* ; "Edited 28-Apr-94 14:00 by sybalsky")
    [COND
       (SPY.HASH (CLRHASH SPY.HASH))
       (T (SETQ SPY.HASH (HASHARRAY 100]
    (if (fetch (SPYDATA DELETED) of SPYDATA)
        then (SETQ TREES (SPY.DELETE (fetch (SPYDATA DELETED) of SPYDATA)
                                    TREES)))
    (for X in TREES do (SPY.SUM X))
    (for NEWNODE in TREES bind VAL Z
       do [for OLDNODE in VAL when (EQ (fetch (SPYRECORD NAME) of OLDNODE)
                                                       (fetch (SPYRECORD NAME) of NEWNODE))
                 do (RETURN (SPY.MERGETREE NEWNODE OLDNODE SPYDATA NIL (fetch
                                                                                (SPYDATA DEPTH)
                                                                                SPYDATA)))
                 finally (AND (SETQ Z (SPY.MERGE1 NEWNODE SPYDATA NIL NIL (fetch
                                                                                   (SPYDATA DEPTH)
                                                                                   SPYDATA)))
                                  (SETQ VAL (NCONC1 VAL Z] finally (CLRHASH SPY.HASH)
                                                                 (RETURN VAL])

(SPY.MERGE1
  [LAMBDA (NEWORIGINAL SPYDATA PARENTS CALLER DEPTH)  (* ; "Edited 28-Apr-94 14:00 by sybalsky")
                                                             (* ; 
                                        "return the 'merged' tree for TREE, a copy of the original")
    (PROG* ((NAME (fetch (SPYRECORD NAME) of NEWORIGINAL))
            [PARENT-NAME (AND PARENTS (fetch (SPYRECORD NAME) of (CAR PARENTS]
            (NEW-NAME NAME)
            MERGE-LIST MERGEP OLDCOPY NEWCOPY)
           [SELECTQ (fetch (SPYDATA MERGETYPE) of SPYDATA)
               ((NIL NONE))
               (PROGN (if (AND PARENTS (CL:SYMBOLP NAME)
                                   (CL:SYMBOLP PARENT-NAME)
                                   (GENSYM? NAME)
                                   (if (CL:KEYWORDP PARENT-NAME)
                                       then (STRPOS (LET* [(ORIG (fetch (SPYRECORD TREEFROM)
                                                                        of (CAR PARENTS]
                                                              (fetch (SPYRECORD NAME)
                                                                 of (if (LISTP ORIG)
                                                                            then (CAR ORIG)
                                                                          else ORIG)))
                                                       NAME 1 NIL T)
                                     elseif (EQ (CL:SYMBOL-PACKAGE NAME)
                                                    (CL:SYMBOL-PACKAGE PARENT-NAME))
                                       then (STRPOS PARENT-NAME NAME 1 NIL T)))
                          then (SETQ NEW-NAME PARENT-NAME))
                      (SETQ MERGE-LIST (if (LITATOM NEW-NAME)
                                           then (SPY.MERGEINFO NEW-NAME SPYDATA PARENT-NAME))
                       )
                      (if MERGE-LIST
                          then (if (EQ (CAR MERGE-LIST)
                                               ':ANY)
                                       then (if PARENTS
                                                    then (SETQ NEW-NAME PARENT-NAME))
                                     elseif (EQ (CAR MERGE-LIST)
                                                    ':NONE)
                                       then (SETQ MERGEP NIL)
                                             (GO NO-MERGE)
                                     elseif (OR (NULL PARENTS)
                                                    (NOT (FMEMB PARENT-NAME MERGE-LIST)))
                                       then (SETQ NEW-NAME (CAR MERGE-LIST))
                                     else (SETQ NEW-NAME PARENT-NAME)))
                      (SELECTQ (fetch (SPYDATA MERGETYPE) of SPYDATA)
                          ((NIL NONE) 
                               NIL)
                          ((RECURSIVE-ONLY) 
                               NIL)
                          (T [SETQ MERGEP (OR (NOT (CL:SYMBOLP NEW-NAME))
                                              (AND (NOT MERGE-LIST)
                                                   (NOT (FMEMB NEW-NAME SPY.NOMERGEFNS))
                                                   (NOT (FMEMB NEW-NAME OPENFNS))
                                                   (NOT (STRPOS "\interpret" NEW-NAME])
                          (ALL (SETQ MERGEP T))
                          (SHOULDNT]
           [COND
              ([OR (AND MERGEP (SETQ OLDCOPY (GETHASH NEW-NAME SPY.HASH)))
                   (SELECTQ (fetch (SPYDATA MERGETYPE) of SPYDATA)
                       ((NIL NONE) 
                            NIL)
                       (AND PARENTS (EQ NEW-NAME (fetch (SPYRECORD NAME) of (SETQ OLDCOPY
                                                                                     (CAR PARENTS]
                                                             (* ; 
                                                        "mergeable, and we found one to merge into")
                                                             (* ; "show this node only as a ghost")
               (SPY.MERGETREE NEWORIGINAL OLDCOPY SPYDATA PARENTS DEPTH)
               (COND
                  ((OR (fetch (SPYDATA NOGHOSTS) of SPYDATA)
                       (EQ OLDCOPY (CAR PARENTS)))
                   (RETURN NIL))
                  ([AND CALLER (SETQ NEWCOPY (find X in (fetch (SPYRECORD CALLEES)
                                                                   of CALLER)
                                                suchthat (EQ (fetch (SPYRECORD NAME)
                                                                    of X)
                                                                 NEW-NAME]
                   (SELECTQ (fetch (SPYRECORD STATUS) of NEWCOPY)
                       (GHOST (AND (FMEMB OLDCOPY PARENTS)
                                   (replace (SPYRECORD STATUS) of NEWCOPY with
                                                                                  'RECURSIVEGHOST)))
                       ((RECURSIVEGHOST ENDOFLINE))
                       (HELP "spy: never seen this case before"))
                   (RETURN NIL))
                  (T (SETQ NEWCOPY (create SPYRECORD using NEWORIGINAL CALLEES _ NIL STATUS _
                                                               'GHOST TREEFROM _ NEWORIGINAL))
                     (AND CALLER (push (fetch (SPYRECORD CALLEES) of CALLER)
                                        NEWCOPY))
                     (RETURN NEWCOPY]
       NO-MERGE
           (SETQ NEWCOPY (create SPYRECORD
                            using NEWORIGINAL CALLEES _ NIL TREEFROM _ NEWORIGINAL NAME _ 
                                  NEW-NAME))                 (* ; "create the copy")
           (AND MERGEP (PUTHASH NEW-NAME NEWCOPY SPY.HASH))  (* ; "remember it if it is mergable")
           (AND CALLER (push (fetch (SPYRECORD CALLEES) of CALLER)
                              NEWCOPY))
           (SPY.MERGE.CALLEES NEWORIGINAL NEWCOPY SPYDATA PARENTS DEPTH)
                                                             (* ; "")
           (RETURN NEWCOPY])

(SPY.MERGETREE
  [LAMBDA (NEWORIGINAL OLDCOPY SPYDATA PARENTS DEPTH) (* ; "Edited 28-Apr-94 13:59 by sybalsky")
                                                             (* ; 
                                "insert call tree from NEWORIGINAL into node starting with OLDCOPY")
                                                             (* ; 
                     "this function is only called once we've decided to merge something after all")
    (PROG ((RECURSIVE (FMEMB OLDCOPY PARENTS)))
          [COND
             ((NOT RECURSIVE)
              (add (fetch (SPYRECORD SUM) of OLDCOPY)
                     (fetch (SPYRECORD SUM) of NEWORIGINAL]
          (add (fetch (SPYRECORD COUNT) of OLDCOPY)
                 (fetch (SPYRECORD COUNT) of NEWORIGINAL))
          [if RECURSIVE
              then (SELECTQ (fetch (SPYRECORD STATUS) of OLDCOPY)
                           ((NORMAL SELFRECURSIVE) 
                                (replace (SPYRECORD TREEFROM) of OLDCOPY
                                   with (LIST (fetch (SPYRECORD TREEFROM) of OLDCOPY)))
                                                             (* ; "must be a list")
                                (replace (SPYRECORD STATUS) of OLDCOPY with 'RECURSIVE))
                           ((RECURSIVE GHOST))
                           (MERGED (replace (SPYRECORD STATUS) of OLDCOPY with
                                                                                  'RECURSIVE))
                           (SHOULDNT))
            else                                         (* ; "add to TREEFROM")
                  (replace (SPYRECORD TREEFROM) of OLDCOPY
                     with (CONS NEWORIGINAL (SELECTQ (fetch (SPYRECORD STATUS) of OLDCOPY
                                                                )
                                                    ((NORMAL SELFRECURSIVE) 
                                                         (replace (SPYRECORD STATUS) of
                                                                                         OLDCOPY
                                                            with 'MERGED)
                                                         (LIST (fetch (SPYRECORD TREEFROM)
                                                                  of OLDCOPY)))
                                                    ((MERGED RECURSIVE ENDOFLINE GHOST) 
                                                         (fetch (SPYRECORD TREEFROM) of
                                                                                         OLDCOPY))
                                                    (SHOULDNT]
          (SPY.MERGE.CALLEES NEWORIGINAL OLDCOPY SPYDATA PARENTS DEPTH)
          (RETURN T])

(SPY.NEXT.TREE
  [LAMBDA (TREE FN)                                   (* ; "Edited 28-Apr-94 13:59 by sybalsky")
    (for X in (fetch (SPYRECORD CALLEES) of TREE)
       do (COND
                 ((EQ (fetch (SPYRECORD NAME) of X)
                      FN)
                  (RETURN X))) finally (push (fetch (SPYRECORD CALLEES) of TREE)
                                                  (SETQ X (create SPYRECORD
                                                                 NAME _ FN
                                                                 COUNT _ 0)))
                                     (RETURN X])

(SPY.SUM
  [LAMBDA (TREE)                                      (* ; "Edited 28-Apr-94 13:59 by sybalsky")
    (replace (SPYRECORD SUM) of TREE
       with (PLUS (fetch (SPYRECORD COUNT) of TREE)
                      (PROG1 (for X in (fetch (SPYRECORD CALLEES) of TREE)
                                sum (SPY.SUM X))
                          [SORT (fetch (SPYRECORD CALLEES) of TREE)
                                (FUNCTION (LAMBDA (X Y)
                                            (IGREATERP (fetch (SPYRECORD SUM) of X)
                                                   (fetch (SPYRECORD SUM) of Y])])

(SPY.TITLE
  [LAMBDA (X TOPCOUNT SPYDATA)                               (* ; "Edited 25-Sep-87 16:30 by jop")

    (CONCAT "SPY " (fetch (SPYRECORD NAME) of X)
           ", " TOPCOUNT " samples"])

(SPY.MAKE.TREE
  [LAMBDA (TREES SPYDATA WINDOW)                             (* ; "Edited  4-Jan-2022 14:08 by rmk")
                                                             (* ; 
                                                             "Edited 28-Apr-94 13:59 by sybalsky")
    (PROG (GRAPH IDS W H THRSH TOPCOUNT (*PACKAGE* (fetch (SPYDATA PACKAGE) of SPYDATA))
                 (*READTABLE* (fetch (SPYDATA READTABLE) of SPYDATA))
                 (*PRINT-CASE* (fetch (SPYDATA PRINT-CASE) of SPYDATA)))
          (OR (FONTP SPY.FONT)
              (SETQ SPY.FONT (FONTCREATE SPY.FONT)))
          (SETQ TOPCOUNT (for X in TREES sum (fetch (SPYRECORD SUM) of X)))
          (SETQ THRSH (QUOTIENT (TIMES TOPCOUNT (fetch (SPYDATA THRESHOLD) of SPYDATA))
                             100))
          (SETQ SPY.NODES)
          (SETQ SPY.TOPNODES (for X in TREES collect (SPY.MAKEGRAPHNODES X THRSH SPYDATA)))
          (SETQ TITLE (SPY.TITLE (CAR SPY.TOPNODES)
                             TOPCOUNT SPYDATA))
          (SETQ SPY.WINDOW (SHOWGRAPH (LAYOUTGRAPH (REVERSE SPY.NODES)
                                             SPY.TOPNODES NIL SPY.FONT)
                                  (COND
                                     ((WINDOWP WINDOW)
                                      (WINDOWPROP WINDOW 'TITLE TITLE)
                                      WINDOW)
                                     (T TITLE))
                                  NIL NIL NIL NIL (FUNCTION SPY.COPYBUTTON)))
          (WINDOWPROP SPY.WINDOW 'ICON SPY.ICON)
          (WINDOWPROP SPY.WINDOW 'BUTTONEVENTFN (FUNCTION SPY.GRAPH.EDITOR))
          (WINDOWPROP SPY.WINDOW 'RIGHTBUTTONFN (FUNCTION SPY.UPDATE.TITLE))
          (WINDOWPROP SPY.WINDOW 'SPYDATA SPYDATA)
          (WINDOWPROP SPY.WINDOW 'TREES TREES)
          (WINDOWPROP SPY.WINDOW 'SPYTITLE TITLE)
          (WINDOWPROP SPY.WINDOW 'TOPCOUNT TOPCOUNT)
          (MODERNWINDOW SPY.WINDOW])

(SPY.UPDATE.TITLE
  [LAMBDA (W)                                         (* ; "Edited 29-Apr-94 14:03 by sybalsky")
    (LET [(NODE (NODELST/AS/MENU (fetch (GRAPH GRAPHNODES) of (WINDOWPROP W 'GRAPH))
                       (CONS (LASTMOUSEX W)
                             (LASTMOUSEY W]
         (TOTOPW W)
         (COND
            ((NOT (INSIDE? (DSPCLIPPINGREGION NIL W)
                         (LASTMOUSEX W)
                         (LASTMOUSEY W)))

             (* ;; " display the default window menu")

             (DOWINDOWCOM W))
            (T [if NODE
                   then 

                         (* ;; 
" change the window title to show the function name, and the individual and cumulative percentages ")

                         (WINDOWPROP W 'TITLE (CONCAT (fetch (SPYRECORD NAME)
                                                         of (fetch (GRAPHNODE NODEID)
                                                                   of NODE))
                                                     "    "
                                                     (QUOTIENT (TIMES (fetch (SPYRECORD COUNT)
                                                                         of (fetch
                                                                                 (GRAPHNODE NODEID)
                                                                                   of NODE))
                                                                      100)
                                                            (WINDOWPROP W 'TOPCOUNT))
                                                     "%%    "
                                                     (QUOTIENT (TIMES (fetch (SPYRECORD SUM)
                                                                         of (fetch
                                                                                 (GRAPHNODE NODEID)
                                                                                   of NODE))
                                                                      100)
                                                            (WINDOWPROP W 'TOPCOUNT))
                                                     "%%"))
                 else 

                       (* ;; 
                "change the window title to show the top function name and total number of samples")

                       (WINDOWPROP W 'TITLE (WINDOWPROP W 'SPYTITLE]
               (UNTILMOUSESTATE UP])

(SPY.DELETE
  [LAMBDA (NAMES TREES)                               (* ; "Edited 28-Apr-94 13:59 by sybalsky")
    (for X in TREES when (NOT (EQMEMB (fetch (SPYRECORD NAME) of X)
                                                 NAMES))
       collect (create SPYRECORD using X CALLEES _ (SPY.DELETE NAMES
                                                                      (fetch (SPYRECORD CALLEES)
                                                                         of X])

(SPY.DRAWBOX
(LAMBDA (WIDTH HEIGHT BORDERWIDTH BITMAP TEXTURE) (* ; "Edited  9-Sep-87 17:54 by Masinter") (BITBLT NIL NIL NIL BITMAP 0 0 BORDERWIDTH HEIGHT (QUOTE TEXTURE) (QUOTE PAINT) TEXTURE) (BITBLT NIL NIL NIL BITMAP 0 0 WIDTH BORDERWIDTH (QUOTE TEXTURE) (QUOTE PAINT) TEXTURE) (BITBLT NIL NIL NIL BITMAP 0 (DIFFERENCE HEIGHT BORDERWIDTH) WIDTH BORDERWIDTH (QUOTE TEXTURE) (QUOTE PAINT) TEXTURE) (BITBLT NIL NIL NIL BITMAP (DIFFERENCE WIDTH BORDERWIDTH) 0 BORDERWIDTH HEIGHT (QUOTE TEXTURE) (QUOTE PAINT) TEXTURE))
)

(SPY.BUFFER.ENTRY
(LAMBDA (N) (* ; "Edited  9-Sep-87 18:27 by Masinter") (COND (SPY.POINTERS (AND (ILEQ (SETQ N (LLSH N 1)) SPY.BUFFER.SIZE) (\GETBASEPTR SPY.BUFFER N))) ((ILEQ N SPY.BUFFER.SIZE) (\VAG2 0 (\GETBASE SPY.BUFFER N)))))
)

(SPY.BUTTON
(LAMBDA (POS) (* gbn " 2-Jun-85 13:12") (PROG ((REG (if POS then (CREATEREGION (fetch XCOORD of POS) (fetch YCOORD of POS) (WIDTHIFWINDOW (BITMAPWIDTH SPY.CLOSED)) (HEIGHTIFWINDOW (BITMAPHEIGHT SPY.CLOSED))) else (GETBOXREGION (WIDTHIFWINDOW (BITMAPWIDTH SPY.CLOSED)) (HEIGHTIFWINDOW (BITMAPHEIGHT SPY.CLOSED)) NIL NIL NIL "Specify region for window %"Spy Control%"")))) (BITBLT SPY.CLOSED NIL NIL (SETQ SPY.BUTTON (CREATEW REG NIL NIL T))) (WINDOWPROP SPY.BUTTON (QUOTE BUTTONEVENTFN) (FUNCTION (LAMBDA (W) (AND (LASTMOUSESTATE UP) (SPY.TOGGLE)))))))
)

(SPY.END.ENTRY
(LAMBDA NIL (* ejs%: "27-APR-84 11:37") (SPY.ADD.ENTRY NIL)))

(SPY.START
(LAMBDA (FILE) (* lmm "24-Oct-84 22:49") (if (OPENWP SPY.BUTTON) then (BITBLT SPY.OPEN NIL NIL SPY.BUTTON)) (* ejs%: "27-APR-84 11:37") (SPY.INIT FILE) (SETQ \PERIODIC.INTERRUPT.FREQUENCY (QUOTIENT 60 SPY.FREQUENCY)) (SETQ \PERIODIC.INTERRUPT (QUOTE \SPY.INTERRUPT)))
)

(SPY.INIT
(LAMBDA NIL (* ; "Edited  9-Sep-87 23:47 by Masinter") (OR SPY.BUFFER (SETQ SPY.BUFFER (\ALLOCBLOCK (CL:* SPY.BUFFER.SIZE 2)))) (SETQ SPY.BUFFER.THRESHOLD (QUOTIENT SPY.BUFFER.SIZE 2)) (SETQ SPY.NEXT 0) (SETQ SPY.TREE))
)

(\SPY.INTERRUPT
(LAMBDA NIL (* ; "Edited  9-Sep-87 18:32 by Masinter") (SETQ \PERIODIC.INTERRUPT) (* ; "turn off sampling while gathering sample") (PROG ((FRAME (fetch (FX CLINK) (\MYALINK)))) (COND ((IGEQ (if SPY.POINTERS then (LLSH SPY.NEXT 1) else SPY.NEXT) SPY.BUFFER.THRESHOLD) (COND (\INTERRUPTABLE (SPY.DUMP.BUFFER)) (T (* ; "this sample might overflow;  just don't do it") (RETURN))))) (SPY.START.ENTRY) SAMPLELOOP (SPY.ADD.ENTRY (fetch (FX FRAMENAME) FRAME)) (COND ((NOT (fetch (FX INVALIDP) (SETQ FRAME (fetch (FX CLINK) FRAME)))) (GO SAMPLELOOP)) (T (SPY.END.ENTRY)))) (SETQ \PERIODIC.INTERRUPT (QUOTE \SPY.INTERRUPT)))
)

(SPY.DUMP.BUFFER
  [LAMBDA NIL                                         (* ; "Edited 28-Apr-94 14:00 by sybalsky")
    (bind (I _ 0)
           NEXTI while (ILESSP I SPY.NEXT)
       do (bind [J _ (SETQ NEXTI (for K from I by 1 while (SPY.BUFFER.ENTRY
                                                                                   K)
                                            finally (RETURN K]
                     TREE
                     (NAME _ "NO SUCH NAME") first [SETQ TREE (SPY.FIND.TREE
                                                                   (SPY.BUFFER.ENTRY (add
                                                                                          J -1]
                 while (IGREATERP J I) do [COND
                                                     ([NEQ NAME (SETQ NAME (SPY.BUFFER.ENTRY
                                                                            (add J -1]
                                                      (SETQ TREE (SPY.NEXT.TREE TREE NAME)))
                                                     (T (replace (SPYRECORD STATUS) of TREE
                                                           with 'SELFRECURSIVE]
                 finally (add (fetch (SPYRECORD COUNT) of TREE)
                                    1))
             (SETQ I (ADD1 NEXTI)))
    (SETQ SPY.NEXT 0])

(SPY.START.ENTRY
(LAMBDA NIL (* ejs%: "27-APR-84 11:37") (* do nothing at the start of the entry, do this at the end) NIL)
)

(SPY.ADD.ENTRY
(LAMBDA (NAME) (* ; "Edited  9-Sep-87 18:29 by Masinter") (COND (SPY.POINTERS (\PUTBASEPTR SPY.BUFFER (LLSH SPY.NEXT 1) NAME) (COND ((IGEQ (LLSH (add SPY.NEXT 1) 1) SPY.BUFFER.SIZE) (SPY.OVERFLOW)))) (T (OR (LITATOM NAME) (SETQ NAME (QUOTE *FORM*))) (\PUTBASE SPY.BUFFER SPY.NEXT (\LOLOC NAME)) (COND ((IGEQ (add SPY.NEXT 1) SPY.BUFFER.SIZE) (SPY.OVERFLOW))))))
)

(SPY.ORIGINAL
  [LAMBDA (TREES)                                     (* ; "Edited 28-Apr-94 14:00 by sybalsky")
    (for X in TREES join (SELECTQ (fetch (SPYRECORD STATUS) of X)
                                         ((RECURSIVE MERGED ENDOFLINE) 
                                              (APPEND (OR (LISTP (fetch (SPYRECORD TREEFROM)
                                                                    of X))
                                                          (SHOULDNT))))
                                         ((NORMAL GHOST RECURSIVEGHOST SELFRECURSIVE) 
                                              (LIST (OR (fetch (SPYRECORD TREEFROM) of X)
                                                        X)))
                                         (SHOULDNT])

(SPY.OVERFLOW
(LAMBDA NIL (* ejs%: "27-APR-84 11:37") (add SPY.NEXT -1) (SETQ SPY.OVERFLOWED T)))

(SPY.MERGE.CALLEES
  [LAMBDA (NEWORIGINAL OLDCOPY SPYDATA PARENTS DEPTH) (* ; "Edited 28-Apr-94 14:00 by sybalsky")
                                                             (* ; 
                               "insert copies of the CALLEEs of NEWORIGINAL into OLDTREE's CALLEEs")
    (for ORIGCALLEE in (fetch (SPYRECORD CALLEES) of NEWORIGINAL)
       do (for COPYCALLEE in (fetch (SPYRECORD CALLEES) of OLDCOPY)
                 when (EQ (fetch (SPYRECORD NAME) of COPYCALLEE)
                              (fetch (SPYRECORD NAME) of ORIGCALLEE))
                 do                                      (* ; 
                                                    "found a 'callee' that can merge this one with")
                       [RETURN (if (EQ (fetch (SPYRECORD STATUS) of COPYCALLEE)
                                           'ENDOFLINE)
                                   then (push (fetch (SPYRECORD TREEFROM) of 
                                                                                           COPYCALLEE
                                                             )
                                                   ORIGCALLEE)
                                 else (SPY.MERGETREE
                                           ORIGCALLEE
                                           (SELECTQ (fetch (SPYRECORD STATUS) of COPYCALLEE)
                                               ((NORMAL RECURSIVE SELFRECURSIVE MERGED) 
                                                    COPYCALLEE)
                                               ((GHOST RECURSIVEGHOST) 
                                                    (OR (GETHASH (fetch (SPYRECORD NAME)
                                                                    of ORIGCALLEE)
                                                               SPY.HASH)
                                                        COPYCALLEE))
                                               (SHOULDNT))
                                           SPYDATA
                                           (CONS OLDCOPY PARENTS)
                                           (AND DEPTH (SUB1 DEPTH]
                 finally                                 (* ; "no old node of same name found")
                       (if (AND DEPTH (ILEQ DEPTH 0))
                           then (push (fetch (SPYRECORD CALLEES) of OLDCOPY)
                                           (create SPYRECORD using ORIGCALLEE CALLEES _ NIL 
                                                                       STATUS _ 'ENDOFLINE TREEFROM _
                                                                       (LIST NEWORIGINAL)))
                         else (SPY.MERGE1 ORIGCALLEE SPYDATA (CONS OLDCOPY PARENTS)
                                         OLDCOPY
                                         (AND DEPTH (SUB1 DEPTH])

(SPY.PRINT
  [LAMBDA (X FILE RDTBL)                                     (* ; "Edited 25-Sep-87 16:32 by jop")

    (LIST (CONCAT "spy:" (if (LISTP (fetch (SPYRECORD NAME) of X))
                             then "*form*"
                           else (fetch (SPYRECORD NAME) of X])
)

(RPAQ? SPY.BUTTON )

(RPAQQ SPY.OPEN #*(56 59)@@@@@@@@@@@@@@@@GLOLLC@@@@@@@@@@LFLFLC@@@@@@@@@@LFLFFF@@@@@@@@@@O@LFFF@@GLOL@@@@GLLFCL@@LFLF@@@@ANOLAH@@LFLF@@@@LFL@AH@@LFLF@@@@LFL@AH@@LFLF@@@@LFL@AH@@LFLF@@@@GLL@AH@@GLLF@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@IEGOOJ@@@@J@@HJ@@BOONHH@@BA@@@@HKOOOFNJHA@D@@HHBGOKNOEB@@@B@@@EDOMMBIGNJH@I@@@HBONJMEEKE@HA@@ECONMJB@KOOJCE@@@KOOJJHEAONHDJ@@KONJD@@@@AONIE@@GOMJH@@@BMOJEB@@FOB@@D@B@@AOEM@@GODDHA@@@AENMG@@KLH@@D@@@@BONM@@GM@HB@@@@BEFKG@@JJDBH@@@@@@INM@@ODA@DDD@@@BEOG@@@KJOMKB@@@AEEK@@JJEBNLIB@@DEOG@@DKNOKONHDDABFI@@BBKFOOMD@AAEFM@@IEIABEEOD@@@JJ@@EFLJKKGEB@EFEB@@J@@BOOHNHD@AEE@@EEEDONKEJ@EEBJ@@H@IOOOOOIEB@HD@@MDDOOOOMDHIEBJ@@BAOKOOOGONNJ@A@@HBKGOOOOOJKHBE@@DHLKMGMGOONJ@I@@@EMBOOJOOOKHBD@@BKDEOOJAOONJ@B@@BKIBOOHEOOOH@D@@HNDAONJBOJDDAA@@BO@DMGDEGOEB@A@@A@DBFJ@BL@@@@D@@@E@ICMAEOJDH@A@@B@@D@ADI@@@@BD@@HDA@JDBEFHH@@A@@@@@H@IDID@@B@D@@AA@A@@@B@A@@AA@@@@@D@@B@J@@A@A@@@@@H@@@D@@@@@J@@@A@@@D@AB@@@BA@@@@@@@@E@@@@@@D@@HH@@@B@@@@@@@B@@
)

(RPAQQ SPY.CLOSED #*(56 59)@@@@@@@@@@@@@@@@GLOLLC@@@@CHND@@LFLFLC@@@@FAHA@@LFLFFF@@@@FAH@@@O@LFFF@@GLOKNA@@GLLFCL@@LFFAH@@@ANOLAH@@LFFAHA@@LFL@AH@@LFFAH@@@LFL@AH@@LFFAHJ@@LFL@AH@@LFFAH@@@GLL@AH@@GLFAHB@@@@@@@@@@@@@@@D@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@A@@@@@IEGOOJ@@@@J@@HJ@@BOONHH@@BA@@@@HKOOOFNJHA@D@@HHBGOKNOEB@@@B@@@EDOMMBIGNJH@I@@@HBONJMEEKE@HA@@ECONMJB@KOOBCE@@@KOOJJHEAOOHDJ@@KONJD@@@@AONIE@@GOMJH@@@BMOJEB@@FOB@@D@B@@AOEM@@GODDHA@@@AENMG@@KLH@@D@@@@BONM@@GM@HB@@@@BEFKG@@JJDBH@@@@@@INM@@ODA@DDD@@@BEOG@@@KJOMKB@@@AEEK@@JJEBNLIB@@DEOG@@DKNOKONHDDABFI@@BBKFOOOD@AAEFM@@IEIABEGND@@@JJ@@EFLLDGGGB@EFEB@@J@@@@@IOHD@AEE@@EEAAEA@FI@EEBJ@@H@HDL@EAME@@HD@@MDEB@NHDJHDABJ@@BAB@@ABICF@J@A@@HB@KDDI@BLI@BE@@DID@A@@JHKDJ@I@@@D@DDDE@EBKEBD@@BAD@@@@A@OED@B@@BHAAAAA@CGNH@D@@H@D@@@@@MOE@AA@@BK@DDDDDGOJJ@A@@B@DA@B@CODFBBD@@EE@HBIAENK@@@A@@BLHBDDDON@@@BD@@KGDHJJIGJHB@@A@@BOBBECGOLB@B@D@@AAMLMKGOH@@@AA@@@GGONNON@H@A@A@@@IKKKKOLJ@@@@J@@@DFOKOO@D@@@BA@@@AEGMMD@A@@@@D@@HHBJMBLA@@@@@B@@
)

(DEFGLOBALVAR SPY.POINTERS T)
(DECLARE%: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS SPY.OVERFLOWED \PERIODIC.INTERRUPT SPY.TREE SPY.BUFFER.SIZE SPY.NEXT SPY.BUFFER.THRESHOLD
       SPY.BUFFER SPY.FREQUENCY SPY.SHOW.THRESHOLD SPY.MAXLINES SPY.FONT)
)
(DECLARE%: EVAL@COMPILE 

(PUTPROPS WITH-SPY MACRO [(FORM)
                          (PROGN (SPY.START)
                                 (PROG1 FORM (SPY.END])

(PUTPROPS WITH.SPY MACRO [(FORM)
                          (PROGN (SPY.START)
                                 (PROG1 FORM (SPY.END])
)
(DECLARE%: DONTCOPY 
(DECLARE%: EVAL@COMPILE

(DATATYPE SPYRECORD (NAME COUNT SUM CALLEES STATUS TREEFROM)
                    STATUS _ 'NORMAL (INIT (DEFPRINT 'SPYRECORD 'SPY.PRINT)))

(PROPRECORD SPYDATA (DELETED CUMULATIVE MERGETYPE THRESHOLD SPYMENU DEPTH NOGHOSTS PACKAGE READTABLE
                           PRINT-CASE MERGEINFO PENDING)
                    CUMULATIVE _ T)
)

(/DECLAREDATATYPE 'SPYRECORD '(POINTER POINTER POINTER POINTER POINTER POINTER)
       '((SPYRECORD 0 POINTER)
         (SPYRECORD 2 POINTER)
         (SPYRECORD 4 POINTER)
         (SPYRECORD 6 POINTER)
         (SPYRECORD 8 POINTER)
         (SPYRECORD 10 POINTER))
       '12)

(DEFPRINT 'SPYRECORD 'SPY.PRINT)
)

(/DECLAREDATATYPE 'SPYRECORD '(POINTER POINTER POINTER POINTER POINTER POINTER)
       '((SPYRECORD 0 POINTER)
         (SPYRECORD 2 POINTER)
         (SPYRECORD 4 POINTER)
         (SPYRECORD 6 POINTER)
         (SPYRECORD 8 POINTER)
         (SPYRECORD 10 POINTER))
       '12)

(DEFPRINT 'SPYRECORD 'SPY.PRINT)
(DECLARE%: DOCOPY DOEVAL@COMPILE 

(FILESLOAD GRAPHER READNUMBER IMAGEOBJ)
)

(MOVD? 'NILL 'MODERNWINDOW)
(PUTPROPS SPY COPYRIGHT ("Venue & Xerox Corporation" 1984 1985 1987 1988 1990 1991 1993 1994))
(DECLARE%: DONTCOPY
  (FILEMAP (NIL (4753 7360 (SPYOBJ 4763 . 5052) (SPYOBJ.BUTTON 5054 . 5164) (SPYOBJ.SAVE 5166 . 5285) (
SPYOBJ.COPY 5287 . 5349) (SPYOBJ.GET 5351 . 5480) (SPYOBJ.IMAGEBOX 5482 . 6006) (SPYOBJ.DISPLAY 6008
 . 6307) (SPYOBJ.LABEL 6309 . 6445) (SPYOBJ.HEIGHT 6447 . 6660) (SPYOBJ.COPYIN 6662 . 6705) (
SPY.COPYBUTTON 6707 . 6799) (SPY.MERGEINFO 6801 . 7358)) (18202 59509 (SPY.FIND.TREE 18212 . 18621) (
SPY.TOGGLE 18623 . 18813) (SPY.TREE 18815 . 19927) (SPY.LEGEND 19929 . 20279) (SPY.GRAPH.EDITOR 20281
 . 29846) (SPY.END 29848 . 30090) (SPY.MAKEGRAPHNODES 30092 . 32192) (SPY.MAX 32194 . 33077) (
SPY.MERGE 33079 . 34510) (SPY.MERGE1 34512 . 40995) (SPY.MERGETREE 40997 . 43927) (SPY.NEXT.TREE 43929
 . 44603) (SPY.SUM 44605 . 45294) (SPY.TITLE 45296 . 45513) (SPY.MAKE.TREE 45515 . 47540) (
SPY.UPDATE.TITLE 47542 . 50118) (SPY.DELETE 50120 . 50655) (SPY.DRAWBOX 50657 . 51182) (
SPY.BUFFER.ENTRY 51184 . 51422) (SPY.BUTTON 51424 . 51993) (SPY.END.ENTRY 51995 . 52075) (SPY.START 
52077 . 52361) (SPY.INIT 52363 . 52598) (\SPY.INTERRUPT 52600 . 53236) (SPY.DUMP.BUFFER 53238 . 54698)
 (SPY.START.ENTRY 54700 . 54828) (SPY.ADD.ENTRY 54830 . 55212) (SPY.ORIGINAL 55214 . 56041) (
SPY.OVERFLOW 56043 . 56144) (SPY.MERGE.CALLEES 56146 . 59182) (SPY.PRINT 59184 . 59507)))))
STOP
