(FILECREATED "12-Dec-85 15:28:28" {ERIS}<LISPCORE>LIBRARY>SPY.;27 33855  

      changes to:  (FNS SPY.PRINT)

      previous date: "21-Jun-85 15:50:39" {ERIS}<LISPCORE>LIBRARY>SPY.;26)


(* Copyright (c) 1984, 1985 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT SPYCOMS)

(RPAQQ SPYCOMS ((VARS SPY.BORDERS SPY.BUFFER.SIZE SPY.FRAGMENTS SPY.NOMERGEFNS (SPY.HASH)
			(SPY.GRAPH.MENU)
			SPY.SHOW.PERCENTAGES SPY.SMALLGHOSTS SPY.ICON)
	(INITVARS (SPY.NEXT 0)
		  (SPY.STREAM)
		  (SPY.BUFFER)
		  (SPY.SHOWCOUNTS T)
		  (SPY.SHOW.THRESHOLD 1)
		  (SPY.MAXLINES 10)
		  (SPY.FREQUENCY 10)
		  (SPY.FONT (QUOTE (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.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))
	(GLOBALVARS SPY.OVERFLOWED \PERIODIC.INTERRUPT SPY.STREAM 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)
	(FILES GRAPHER READNUMBER IMAGEOBJ)))

(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 (\INTERPRETER1 ERRORSET \EVAL \EVALFORM APPLY EVAL))

(RPAQQ SPY.HASH NIL)

(RPAQQ SPY.GRAPH.MENU NIL)

(RPAQQ SPY.SHOW.PERCENTAGES T)

(RPAQQ SPY.SMALLGHOSTS T)

(RPAQ SPY.ICON (READBITMAP))
(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.STREAM )

(RPAQ? SPY.BUFFER )

(RPAQ? SPY.SHOWCOUNTS T)

(RPAQ? SPY.SHOW.THRESHOLD 1)

(RPAQ? SPY.MAXLINES 10)

(RPAQ? SPY.FREQUENCY 10)

(RPAQ? SPY.FONT (QUOTE (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 
			  SPYOBJ.PREPRINT)
		     [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
							    (FUNCTION SPYOBJ.PREPRINT)
							    (QUOTE SPYNODE]
		     (RECORDS SPYOBJDATA)))
(DEFINEQ

(SPYOBJ
  [LAMBDA (NAME PERCENT STATUS)                              (* lmm " 9-Jun-85 01:24")
    (IMAGEOBJCREATE (create SPYOBJDATA
			    LABEL ← NAME
			    PERCENT ← PERCENT
			    CACHEDLABEL ←(CONCAT 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)                                   (* lmm " 9-Jun-85 01:12")
    (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 ←(QUOTIENT HEIGHT 2)
		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])

(SPYOBJ.PREPRINT
  [LAMBDA (OBJ)                                              (* lmm "21-Jun-85 14:29")
    (fetch (SPYOBJDATA LABEL)
	   (fetch OBJECTDATUM OBJ])
)

(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 (FUNCTION SPYOBJ.PREPRINT)
					(QUOTE SPYNODE)))
[DECLARE: EVAL@COMPILE 

(RECORD SPYOBJDATA (CACHEDLABEL PERCENT LABEL))
]
(DEFINEQ

(SPY.FIND.TREE
  [LAMBDA (FN)                                               (* ejs: "27-APR-84 11:37")
    (OR (find X in SPY.TREE suchthat (EQ (fetch 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)       (* lmm " 3-Jul-84 10:36")
    (COND
      ((NULL SPY.TREE)
	(QUOTE (no SPY samples have been gathered)))
      (T (PROG ((SPYDATA (create SPYDATA
				 CUMULATIVE ←(NOT INDIVIDUALP)
				 THRESHOLD ←(OR THRESHOLD SPY.SHOW.THRESHOLD)
				 MERGETYPE ←(OR MERGETYPE (COND
						  (INDIVIDUALP (QUOTE 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)                                           (* lmm "21-Jun-85 14:33")
    (PROG [(TREES (WINDOWPROP W (QUOTE TREES)))
	   (TOPCOUNT (WINDOWPROP W (QUOTE TOPCOUNT)))
	   (WINDOW W)
	   NODE LASTNODE (SPYDATA (WINDOWPROP W (QUOTE SPYDATA]
          (TOTOPW W)
          (do (SETQ NODE (OR (NODELST/AS/MENU (fetch (GRAPH GRAPHNODES) of (WINDOWPROP W
										       (QUOTE 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))
			       (OR COPY (WINDOWPROP W (QUOTE TITLE)
						    (SPY.TITLE (fetch NODEID of NODE)
							       TOPCOUNT SPYDATA]
		       (SETQ LASTNODE NODE))
	     repeatwhile (MOUSESTATE LEFT))
          [if COPY
	      then (RETURN (if (EQ NODE T)
			       then (INVERTW W)
				    (GRAPHERCOPYBUTTONEVENTFN W)
			     else (FLIPNODE NODE W)
				  (COPYINSERT (fetch (SPYRECORD NAME) of (fetch (GRAPHNODE NODEID)
									    of NODE]
          (if (NOT (LASTMOUSESTATE MIDDLE))
	      then (AND NODE (FLIPNODE NODE W))
		   (RETURN))
          (if NODE
	      then (SELECTQ (PROG1 [MENU (CONSTANT (create MENU
							   ITEMS ←(QUOTE (SubTree Edit Delete]
				   (FLIPNODE NODE W))
			    (NIL (RETURN))
			    (Edit (PROCESS.EVAL (QUOTE EXEC)
						[BQUOTE (INSPECT/AS/FUNCTION
							  (QUOTE , (fetch NAME of
									  (fetch NODEID of NODE]
						NIL)
				  (RETURN))
			    (Delete                          (* remove this node?)
				    (SETQ TREES (SPY.DELETE (fetch NAME of (fetch NODEID
									      of NODE))
							    (SPY.ORIGINAL TREES)))
				    (MAPC TREES (FUNCTION SPY.SUM))
				    (SETQ TREES (SPY.MERGE TREES SPYDATA)))
			    (SubTree (SETQ TREES (SPY.MERGE (SPY.ORIGINAL (LIST (fetch NODEID
										   of NODE)))
							    SPYDATA))
                                                             (* make sure that it creates a new window)
				     (SETQ WINDOW NIL))
			    (RETURN (printout PROMPTWINDOW T "SORRY, FEATURE NOT IMPLEMENTED YET")))
	    else
	     (SELECTQ
	       (PROG1
		 (OR [MENU (OR (fetch SPYMENU of SPYDATA)
			       (replace SPYMENU of SPYDATA
				  with (create MENU
					       ITEMS ←(CONS (QUOTE SetThreshold)
							    (CONS (COND
								    ((fetch CUMULATIVE of SPYDATA)
								      (QUOTE Individual))
								    (T (QUOTE Cumulative)))
								  (SELECTQ
								    (fetch MERGETYPE of SPYDATA)
								    (ALL (QUOTE (MergeDefault 
											MergeNone)))
								    (T (QUOTE (MergeNone MergeAll)))
								    ((NIL NONE)
								      (QUOTE (MergeDefault MergeAll)))
								    (SHOULDNT]
		     (RETURN))
		 (SETQ SPYDATA (create SPYDATA using SPYDATA SPYMENU ← NIL)))
	       (SetThreshold                                 (* no need to remerge)
			     (replace THRESHOLD of SPYDATA with (RNUMBER "Threshold (percent)" NIL 
									 DEFAULTFONT DEFAULTFONT)))
	       (MergeAll (replace MERGETYPE of SPYDATA with (QUOTE ALL))
			 (SETQ TREES (SPY.MERGE (SPY.ORIGINAL TREES)
						SPYDATA)))
	       (MergeNone (replace MERGETYPE of SPYDATA with (QUOTE NONE))
			  (SETQ TREES (SPY.MERGE (SPY.ORIGINAL TREES)
						 SPYDATA)))
	       (MergeDefault (replace MERGETYPE of SPYDATA with T)
			     (SETQ TREES (SPY.MERGE (SPY.ORIGINAL TREES)
						    SPYDATA)))
	       ((Cumulative Individual)
		 [replace MERGETYPE of SPYDATA with (COND
						      ((change (fetch CUMULATIVE of SPYDATA)
							       (NOT DATUM))
							T)
						      (T (QUOTE ALL]
		 (SETQ TREES (SPY.MERGE (SPY.ORIGINAL TREES)
					SPYDATA)))
	       (SHOULDNT)))
          (SPY.MAKE.TREE TREES SPYDATA WINDOW])

(SPY.END
(LAMBDA NIL (* lmm "24-Oct-84 22:48") (if (EQ \PERIODIC.INTERRUPT (QUOTE \SPY.INTERRUPT)) then (SETQ 
\PERIODIC.INTERRUPT) (SPY.DUMP.BUFFER) (COND (SPY.STREAM (CLOSEF SPY.STREAM))) (if (OPENWP SPY.BUTTON)
 then (BITBLT SPY.CLOSED NIL NIL SPY.BUTTON)))))

(SPY.MAKEGRAPHNODES
  [LAMBDA (TREE THRESHOLD SPYDATA)                           (* lmm " 9-Jun-85 01:41")
                                                             (* RETURNS NODE ID FOR TREE)
    (PROG ((LABEL (fetch (SPYRECORD NAME) of TREE))
	   [COUNT (COND
		    ((fetch CUMULATIVE SPYDATA)
		      (fetch SUM of TREE))
		    (T (fetch 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 CALLEES of TREE)
					      when (OR (ZEROP THRESHOLD)
						       (IGEQ (SPY.MAX (LIST X)
								      (NOT (fetch 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)                                 (* lmm " 1-May-84 13:11")
    [for X in TREES do (SETQ MAX (SPY.MAX (fetch CALLEES of X)
					  COUNTP
					  (IMAX (OR MAX (IMAX))
						(if COUNTP
						    then (fetch COUNT of X)
						  else (fetch SUM of X]
    MAX])

(SPY.MERGE
  [LAMBDA (TREES SPYDATA)                                    (* lmm "29-Apr-85 18:33")
    [COND
      (SPY.HASH (CLRHASH SPY.HASH))
      (T (SETQ SPY.HASH (HASHARRAY 100]
    (for X in TREES do (SPY.SUM X))
    (for NEWNODE in TREES bind VAL Z do [for OLDNODE in VAL when (EQ (fetch NAME of OLDNODE)
								     (fetch NAME of NEWNODE))
					   do (RETURN (SPY.MERGETREE NEWNODE OLDNODE SPYDATA NIL
								     (fetch DEPTH SPYDATA)))
					   finally (AND (SETQ Z (SPY.MERGE1 NEWNODE SPYDATA NIL NIL
									    (fetch DEPTH SPYDATA)))
							(SETQ VAL (NCONC1 VAL Z]
       finally (CLRHASH SPY.HASH)
	       (RETURN VAL])

(SPY.MERGE1
  [LAMBDA (NEWORIGINAL SPYDATA PARENTS CALLER DEPTH)         (* lmm " 5-Oct-84 22:37")
                                                             (* return the "merged" tree for TREE, a copy of the 
							     original)
    (PROG ((MERGEP (SELECTQ (fetch MERGETYPE of SPYDATA)
			    ((NIL NONE)
			      NIL)
			    [T (NOT (OR (FMEMB (fetch NAME of NEWORIGINAL)
					       SPY.NOMERGEFNS)
					(FMEMB (fetch NAME of NEWORIGINAL)
					       OPENFNS]
			    (ALL T)
			    (SHOULDNT)))
	   OLDCOPY NEWCOPY)
          (COND
	    [(AND MERGEP (SETQ OLDCOPY (GETHASH (fetch NAME of NEWORIGINAL)
						SPY.HASH)))
                                                             (* mergeable, and we found one to merge into)
                                                             (* show this node only as a ghost)
	      (SPY.MERGETREE NEWORIGINAL OLDCOPY SPYDATA PARENTS DEPTH)
	      (COND
		((fetch NOGHOSTS of SPYDATA))
		[[AND CALLER (SETQ NEWCOPY (find X in (fetch CALLEES of CALLER)
					      suchthat (EQ (fetch NAME of X)
							   (fetch NAME of NEWORIGINAL]
		  (SELECTQ (fetch STATUS of NEWCOPY)
			   [GHOST (AND (FMEMB OLDCOPY PARENTS)
				       (replace STATUS of NEWCOPY with (QUOTE RECURSIVEGHOST]
			   ((RECURSIVEGHOST ENDOFLINE))
			   (HELP (QUOTE (SPY: never seen this case before]
		(T (SETQ NEWCOPY (create SPYRECORD using NEWORIGINAL CALLEES ← NIL STATUS ←(QUOTE
							   GHOST)
							 TREEFROM ← NEWORIGINAL))
		   (AND CALLER (push (fetch CALLEES of CALLER)
				     NEWCOPY))
		   (RETURN NEWCOPY]
	    (T (SETQ NEWCOPY (create SPYRECORD using NEWORIGINAL CALLEES ← NIL TREEFROM ← NEWORIGINAL)
		 )                                           (* create the copy)
	       (AND MERGEP (PUTHASH (fetch NAME of NEWORIGINAL)
				    NEWCOPY SPY.HASH))       (* remember it if it is mergable)
	       (AND CALLER (push (fetch CALLEES of CALLER)
				 NEWCOPY))
	       (SPY.MERGE.CALLEES NEWORIGINAL NEWCOPY SPYDATA PARENTS DEPTH)
	       (RETURN NEWCOPY])

(SPY.MERGETREE
  [LAMBDA (NEWORIGINAL OLDCOPY SPYDATA PARENTS DEPTH)        (* lmm "27-Sep-84 19:05")
                                                             (* 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 SUM of OLDCOPY)
		   (fetch SUM of NEWORIGINAL]
          (add (fetch COUNT of OLDCOPY)
	       (fetch COUNT of NEWORIGINAL))
          [if RECURSIVE
	      then (SELECTQ (fetch STATUS of OLDCOPY)
			    ((NORMAL SELFRECURSIVE)
			      (replace TREEFROM of OLDCOPY with (LIST (fetch TREEFROM of OLDCOPY)))
                                                             (* must be a list)
			      (replace STATUS of OLDCOPY with (QUOTE RECURSIVE)))
			    (RECURSIVE)
			    (MERGED (replace STATUS of OLDCOPY with (QUOTE RECURSIVE)))
			    (SHOULDNT))
	    else                                             (* add to TREEFROM)
		 (replace TREEFROM of OLDCOPY with (CONS NEWORIGINAL
							 (SELECTQ (fetch STATUS of OLDCOPY)
								  ((NORMAL SELFRECURSIVE)
								    (replace STATUS of OLDCOPY
								       with (QUOTE MERGED))
								    (LIST (fetch TREEFROM
									     of OLDCOPY)))
								  ((MERGED RECURSIVE ENDOFLINE)
								    (fetch TREEFROM of OLDCOPY))
								  (SHOULDNT]
          (SPY.MERGE.CALLEES NEWORIGINAL OLDCOPY SPYDATA PARENTS DEPTH)
          (RETURN T])

(SPY.NEXT.TREE
  [LAMBDA (TREE FN)                                          (* ejs: "27-APR-84 11:37")
    (for X in (fetch CALLEES of TREE) do (COND
					   ((EQ (fetch NAME of X)
						FN)
					     (RETURN X)))
       finally (push (fetch CALLEES of TREE)
		     (SETQ X (create SPYRECORD
				     NAME ← FN
				     COUNT ← 0)))
	       (RETURN X])

(SPY.SUM
  [LAMBDA (TREE)                                             (* lmm "26-Sep-84 10:24")
    (replace SUM of TREE with (PLUS (fetch COUNT of TREE)
				    (PROG1 (for X in (fetch CALLEES of TREE) sum (SPY.SUM X))
					   (SORT (fetch CALLEES of TREE)
						 (FUNCTION (LAMBDA (X Y)
						     (IGREATERP (fetch SUM of X)
								(fetch SUM of Y])

(SPY.TITLE
  [LAMBDA (X TOPCOUNT SPYDATA)                               (* lmm "20-May-84 22:50")
    (CONCAT (QUOTIENT (TIMES 100 (fetch COUNT of X))
		      TOPCOUNT)
	    "%%, "
	    (QUOTIENT (TIMES 100 (fetch SUM of X))
		      TOPCOUNT)
	    "%% cumulative:"
	    (fetch NAME of X])

(SPY.MAKE.TREE
  [LAMBDA (TREES SPYDATA WINDOW)                             (* lmm " 9-Jun-85 01:50")
    (PROG (GRAPH IDS W H THRSH TOPCOUNT)
          (OR (FONTP SPY.FONT)
	      (SETQ SPY.FONT (FONTCREATE SPY.FONT)))
          (SETQ TOPCOUNT (for X in TREES sum (fetch SUM of X)))
          (SETQ THRSH (QUOTIENT (TIMES TOPCOUNT (fetch 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 (QUOTE TITLE)
						      TITLE)
					  WINDOW)
					(T TITLE))
				      NIL NIL NIL NIL (FUNCTION SPY.COPYBUTTON)))
          (WINDOWPROP SPY.WINDOW (QUOTE ICON)
		      SPY.ICON)
          (WINDOWPROP SPY.WINDOW (QUOTE BUTTONEVENTFN)
		      (FUNCTION SPY.GRAPH.EDITOR))
          (WINDOWPROP SPY.WINDOW (QUOTE RIGHTBUTTONFN)
		      NIL)
          (WINDOWPROP SPY.WINDOW (QUOTE SPYDATA)
		      SPYDATA)
          (WINDOWPROP SPY.WINDOW (QUOTE TREES)
		      TREES)
          (WINDOWPROP SPY.WINDOW (QUOTE TOPCOUNT)
		      TOPCOUNT])

(SPY.DELETE
  [LAMBDA (NAMES TREES)                                      (* lmm " 2-May-84 15:32")
    (for X in TREES when (NOT (EQMEMB (fetch NAME of X)
				      NAMES))
       collect (create SPYRECORD using X CALLEES ←(SPY.DELETE NAMES (fetch CALLEES of X])

(SPY.DRAWBOX
  [LAMBDA (WIDTH HEIGHT BORDERWIDTH BITMAP TEXTURE)          (* Crystal: "27-APR-84 15:20")
    (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)                                                (* ejs: "27-APR-84 11:37")
    (AND (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 (FILE)                                             (* ejs: "27-APR-84 11:37")
    [OR SPY.BUFFER (SETQ SPY.BUFFER (\ALLOCBLOCK (FOLDHI SPY.BUFFER.SIZE WORDSPERCELL]
    (SETQ SPY.BUFFER.THRESHOLD (QUOTIENT SPY.BUFFER.SIZE 2))
    (SETQ SPY.NEXT 0)
    (COND
      [FILE (SETQ SPY.STREAM (OR (STREAMP FILE)
				 (OPENSTREAM FILE (QUOTE OUTPUT)
					     (QUOTE NEW]
      (T (SETQ SPY.STREAM)))
    (SETQ SPY.TREE])

(\SPY.INTERRUPT
  [LAMBDA NIL                                                (* lmm " 1-May-84 09:50")
    (SETQ \PERIODIC.INTERRUPT)                               (* turn off sampling while gathering sample)
    [PROG [(FRAME (fetch (FX CLINK)
			 (\MYALINK]
          [COND
	    ((IGEQ 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                                                (* lmm "27-Sep-84 15:34")
    [COND
      (SPY.STREAM (\BOUTS SPY.STREAM SPY.BUFFER 0 (TIMES 2 SPY.NEXT))
                                                             (* dump buffer into stream and reset buffer size)
		  )
      (T (bind (I ← 0)
	       NEXTI while (ILESSP I SPY.NEXT)
	    do (bind [J ←(SETQ NEXTI (for K from I 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 STATUS of TREE with (QUOTE SELFRECURSIVE]
		  finally (add (fetch 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)                                             (* ejs: "27-APR-84 11:37")
    (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)                                            (* lmm "27-Sep-84 19:01")
    (for X in TREES join (SELECTQ (fetch STATUS of X)
				  [(RECURSIVE MERGED ENDOFLINE)
				    (APPEND (OR (LISTP (fetch TREEFROM of X))
						(SHOULDNT]
				  ((NORMAL GHOST RECURSIVEGHOST SELFRECURSIVE)
				    (LIST (OR (fetch 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)        (* lmm "27-Sep-84 18:59")
                                                             (* insert copies of the CALLEEs of NEWORIGINAL into 
							     OLDTREE's CALLEEs)
    (for ORIGCALLEE in (fetch CALLEES of NEWORIGINAL)
       do (for COPYCALLEE in (fetch CALLEES of OLDCOPY) when (EQ (fetch NAME of COPYCALLEE)
								 (fetch NAME of ORIGCALLEE))
	     do                                              (* found a "callee" that can merge this one with)
		[RETURN (if (EQ (fetch STATUS of COPYCALLEE)
				(QUOTE ENDOFLINE))
			    then (push (fetch TREEFROM of COPYCALLEE)
				       ORIGCALLEE)
			  else (SPY.MERGETREE ORIGCALLEE
					      (SELECTQ (fetch STATUS of COPYCALLEE)
						       ((NORMAL RECURSIVE SELFRECURSIVE MERGED)
							 COPYCALLEE)
						       ((GHOST RECURSIVEGHOST)
							 (OR (GETHASH (fetch NAME of ORIGCALLEE)
								      SPY.HASH)
							     (SHOULDNT)))
						       (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 CALLEES of OLDCOPY)
				    (create SPYRECORD using ORIGCALLEE CALLEES ← NIL STATUS ←(QUOTE
							      ENDOFLINE)
							    TREEFROM ←(LIST NEWORIGINAL)))
		       else (SPY.MERGE1 ORIGCALLEE SPYDATA (CONS OLDCOPY PARENTS)
					OLDCOPY
					(AND DEPTH (SUB1 DEPTH])

(SPY.PRINT
  [LAMBDA (X FILE RDTBL)                                     (* lmm "12-Dec-85 15:20")
    (LIST (CONCAT "spy:" (\HILOC X)
		      ","
		      (\LOLOC X])
)

(RPAQ? SPY.BUTTON )

(RPAQ SPY.OPEN (READBITMAP))
(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@@")

(RPAQ SPY.CLOSED (READBITMAP))
(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@@")
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS SPY.OVERFLOWED \PERIODIC.INTERRUPT SPY.STREAM 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 ←(QUOTE NORMAL)
		      (INIT (DEFPRINT (QUOTE SPYRECORD)
					(QUOTE SPY.PRINT))))

(PROPRECORD SPYDATA (CUMULATIVE MERGETYPE THRESHOLD SPYMENU DEPTH NOGHOSTS)
		      CUMULATIVE ← T)
]
(/DECLAREDATATYPE (QUOTE SPYRECORD)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER POINTER))
		  (QUOTE ((SPYRECORD 0 POINTER)
			  (SPYRECORD 2 POINTER)
			  (SPYRECORD 4 POINTER)
			  (SPYRECORD 6 POINTER)
			  (SPYRECORD 8 POINTER)
			  (SPYRECORD 10 POINTER)))
		  (QUOTE 12))
(DEFPRINT (QUOTE SPYRECORD)
	  (QUOTE SPY.PRINT))
)
(/DECLAREDATATYPE (QUOTE SPYRECORD)
		  (QUOTE (POINTER POINTER POINTER POINTER POINTER POINTER))
		  (QUOTE ((SPYRECORD 0 POINTER)
			  (SPYRECORD 2 POINTER)
			  (SPYRECORD 4 POINTER)
			  (SPYRECORD 6 POINTER)
			  (SPYRECORD 8 POINTER)
			  (SPYRECORD 10 POINTER)))
		  (QUOTE 12))
(DEFPRINT (QUOTE SPYRECORD)
	  (QUOTE SPY.PRINT))
(FILESLOAD GRAPHER READNUMBER IMAGEOBJ)
(PUTPROPS SPY COPYRIGHT ("Xerox Corporation" 1984 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (3570 6268 (SPYOBJ 3580 . 3850) (SPYOBJ.BUTTON 3852 . 4033) (SPYOBJ.SAVE 4035 . 4212) (
SPYOBJ.COPY 4214 . 4331) (SPYOBJ.GET 4333 . 4515) (SPYOBJ.IMAGEBOX 4517 . 4941) (SPYOBJ.DISPLAY 4943
 . 5372) (SPYOBJ.LABEL 5374 . 5576) (SPYOBJ.HEIGHT 5578 . 5883) (SPYOBJ.COPYIN 5885 . 5937) (
SPY.COPYBUTTON 5939 . 6086) (SPYOBJ.PREPRINT 6088 . 6266)) (6667 29972 (SPY.FIND.TREE 6677 . 6962) (
SPY.TOGGLE 6964 . 7154) (SPY.TREE 7156 . 7665) (SPY.LEGEND 7667 . 8227) (SPY.GRAPH.EDITOR 8229 . 12719
) (SPY.END 12721 . 12987) (SPY.MAKEGRAPHNODES 12989 . 14251) (SPY.MAX 14253 . 14605) (SPY.MERGE 14607
 . 15390) (SPY.MERGE1 15392 . 17691) (SPY.MERGETREE 17693 . 19537) (SPY.NEXT.TREE 19539 . 19947) (
SPY.SUM 19949 . 20398) (SPY.TITLE 20400 . 20720) (SPY.MAKE.TREE 20722 . 22195) (SPY.DELETE 22197 . 
22511) (SPY.DRAWBOX 22513 . 23105) (SPY.BUFFER.ENTRY 23107 . 23290) (SPY.BUTTON 23292 . 24042) (
SPY.END.ENTRY 24044 . 24183) (SPY.START 24185 . 24469) (SPY.INIT 24471 . 24913) (\SPY.INTERRUPT 24915
 . 25761) (SPY.DUMP.BUFFER 25763 . 26828) (SPY.START.ENTRY 26830 . 27095) (SPY.ADD.ENTRY 27097 . 27396
) (SPY.ORIGINAL 27398 . 27856) (SPY.OVERFLOW 27858 . 28022) (SPY.MERGE.CALLEES 28024 . 29779) (
SPY.PRINT 29781 . 29970)))))
STOP