(FILECREATED " 8-Feb-86 15:22:57" {DSK}<LISPFILES2>IMPROVEDDCOMS>FINDDEFN.;1 12941  

      previous date: " 3-Feb-86 00:06:54" {GOEDEL}<usr2/pds/updating/lisp>FINDDEFN)


(* Copyright (c) 1986 by Quintus Computer Systems, Inc. All rights reserved.)

(PRETTYCOMPRINT FINDDEFNCOMS)

(RPAQQ FINDDEFNCOMS ((SCCS) (* WARNING: This material is CONFIDENTIAL and proprietary to Quintus 
Computer Systems Inc.) (* Find-definition: Pre-Prolog call stage - gather the predicate name and arity
 from the cursor position and a user prompt.) (FNS QP.GET.CURSOR) (MACROS QP.VALID.UPPER.CASE.CHAR 
QP.CHAR.IS.WHITE.SPACE) (FNS QP.SKIP.WHITE.SPACE) (MACROS QP.SKIP.OVER.CHAR.IN.PRED.HEAD) (FNS 
QP.FIND.PRED.BEGINNING) (MACROS QP.NAME.INCLUDES.ARITY) (FNS QP.GET.NAME.ARITY.DEFAULT) (MACROS 
QP.CONVERT.NAME.ARITY.TO.NAME) (FNS QP.REMOVE.SPACES) (MACROS QP.GET.USER.NAME.ARITY) (MACROS 
QP.GET.USER.NAME.ARITY.NO.DEFAULT) (FNS QP.GET.NAME.FROM.STRING) (FNS QP.GET.ARITY.FROM.STRING) (FNS 
QP.FIND.DEFINITION) (* Find-definition: Post-Prolog call stage: display the file that the predicate 
was defined in and show the definition.) (* Note that the global variable 
QP.FIND.DEFINITION.SOURCE.FILES holds the list of files to be visited for the predicate definitions 
for find.definition.part.two. It is declared global in the file TELLEDITOR.LSP) (FNS 
QP.FIND.DEFINITION.PART.TWO) (FNS QP.LOCATE.PREDICATE.FOR.FD) (MACROS QP.FD.GET.FILENAME) (* 
fd-get-filename takes the filenames off the top/front of the list and then removes the filename from 
the list. The original file insertion mechanism in &fd-insert inserts the file names at the bottom/end
 of the list. QP.FD.FILE adds filenames to the end of the list stored in 
QP.FIND.DEFINITION.SOURCE.FILES) (FNS QP.FIND.MORE.DEFINITION) (FNS QP.LOCATE.DEFINITION)))
(* %%G%  %%W% )



(* WARNING: This material is CONFIDENTIAL and proprietary to Quintus Computer Systems Inc.)




(* Find-definition: Pre-Prolog call stage - gather the predicate name and arity from the 
cursor position and a user prompt.)

(DEFINEQ

(QP.GET.CURSOR
(LAMBDA (STREAM) (* pds: "20-Jan-86 11:07") (LET ((SEL (TEDIT.GETSEL STREAM))) (SELECTQ (fetch (
SELECTION POINT) of SEL) (LEFT (fetch (SELECTION CH#) of SEL)) (RIGHT (IDIFFERENCE (fetch (SELECTION 
CHLIM) of SEL) 1)) (fetch (SELECTION CH#) of SEL)))))
)
(DECLARE: EVAL@COMPILE 
(PUTPROPS QP.VALID.UPPER.CASE.CHAR MACRO (**MACROARG** (LET ((CHAR (CAR (NTH **MACROARG** 1)))) (
BQUOTE (PROGN (AND (IGEQ (\, CHAR) (CHARCODE A)) (ILEQ (\, CHAR) (CHARCODE Z))))))))
(PUTPROPS QP.CHAR.IS.WHITE.SPACE MACRO (**MACROARG** (LET ((CHAR (CAR (NTH **MACROARG** 1)))) (BQUOTE 
(PROGN (OR (EQ (\, CHAR) (CHARCODE SPACE)) (EQ (\, CHAR) (CHARCODE TAB)) (EQ (\, CHAR) (CHARCODE EOL))
))))))
)
(DEFINEQ

(QP.SKIP.WHITE.SPACE
(LAMBDA (STREAM) (* This routine will return either the next non-white-space character, or nil if it 
found the EOF first.) (LET ((CHAR (QP.GET.NEXT.CHAR STREAM))) (while (AND (NOT (NULL CHAR)) (
QP.CHAR.IS.WHITE.SPACE CHAR)) do (SETQ CHAR (QP.GET.NEXT.CHAR STREAM))) (\BACKBIN STREAM) CHAR)))
)
(DECLARE: EVAL@COMPILE 
(PUTPROPS QP.SKIP.OVER.CHAR.IN.PRED.HEAD MACRO ((CHAR) (OR (EQ CHAR (CHARCODE SPACE)) (EQ CHAR (
CHARCODE TAB)) (EQ CHAR (CHARCODE EOL)) (EQ CHAR 44) (EQ CHAR (CHARCODE %;)) (EQ CHAR (CHARCODE %()) (
EQ CHAR (CHARCODE >)) (EQ CHAR (CHARCODE %[)) (EQ CHAR (CHARCODE {)))))
)
(DEFINEQ

(QP.FIND.PRED.BEGINNING
(LAMBDA (STREAM) (* pds: " 2-Feb-86 23:30") (* 1st make sure the file pointer is where the cursor is:)
 (\SETUPGETCH (QP.GET.CURSOR STREAM) (TEXTOBJ STREAM)) (LET ((CHAR (QP.GET.NEXT.CHAR STREAM))) (
SELCHARQ CHAR (NIL NIL) (* No character) ((SPACE TAB EOL) (* The routine started in white-space) (LET 
((CHAR (QP.SKIP.WHITE.SPACE STREAM))) (* not at EOF, not at EOL, not a variable) (AND (NOT (NULL CHAR)
) (NOT (EQ CHAR (CHARCODE EOL))) (NOT (QP.VALID.UPPER.CASE.CHAR CHAR))))) (LET ((POSITION (
\TEXTGETFILEPTR STREAM)) (BACKMODE NIL)) (while (AND (NEQ POSITION 0) (NOT (
QP.SKIP.OVER.CHAR.IN.PRED.HEAD CHAR))) do (SETQ CHAR (\BACKBIN STREAM)) (SETQ POSITION (SUB1 POSITION)
) (SETQ BACKMODE T)) (if (QP.SKIP.OVER.CHAR.IN.PRED.HEAD CHAR) then (if BACKMODE then (\BIN STREAM) (*
 Now at first valid character)) (SETQ CHAR (\BIN STREAM)) (\BACKBIN STREAM)) (if (NOT (
QP.VALID.UPPER.CASE.CHAR CHAR)) then T))))))
)
(DECLARE: EVAL@COMPILE 
(PUTPROPS QP.NAME.INCLUDES.ARITY MACRO (**MACROARG** (LET ((NAME (CAR (NTH **MACROARG** 1)))) (BQUOTE 
(PROGN (MEMB (CHARCODE /) (\, NAME)))))))
)
(DEFINEQ

(QP.GET.NAME.ARITY.DEFAULT
(LAMBDA (STREAM) (* pds: "20-Jan-86 12:13") (* This returns a list consisting of the character codes 
that represent the predicate name followed by the character code for a "/" followed by the arity 
number (not character code)) (LET ((CHAR (QP.GET.NEXT.CHAR STREAM))) (* see FINDPRED.LSP for source) (
if (NEQ CHAR (CHARCODE EOL)) then (* a default value was attempted) (LET ((FND.FLAG (
QP.FIND.PRED.BEGINNING STREAM)) (ORI.POSITION (ADD1 (\TEXTGETFILEPTR STREAM)))) (if FND.FLAG then (* 
now at the beginning of the name) (* see FINDPRED.LSP for source of QP.GET.PRED.NAME) (LET* ((P.NAME (
QP.GET.PRED.NAME STREAM)) (ARITY.LIST (QP.NAME.INCLUDES.ARITY P.NAME))) (if (NOT ARITY.LIST) then (
\BACKBIN STREAM) (LET ((P.ARITY (QP.FIND.ARITY.AUX STREAM (TEXTOBJ STREAM) ORI.POSITION))) (if (AND 
P.NAME P.ARITY) then (APPEND P.NAME (LIST (CHARCODE /) P.ARITY)))) else (* P.NAME includes arity but 
as char codes) (* convert the arity char codes) (APPEND (CAR (LASTN P.NAME (SUB1 (LENGTH ARITY.LIST)))
) (LIST (PACKC (CDR ARITY.LIST))))))))))))
)
(DECLARE: EVAL@COMPILE 
(PUTPROPS QP.CONVERT.NAME.ARITY.TO.NAME MACRO (**MACROARG** (LET ((NAME.ARITY (CAR (NTH **MACROARG** 1
)))) (BQUOTE (PROGN (PACKC (CAR (LASTN (\, NAME.ARITY) 2))))))))
)
(DEFINEQ

(QP.REMOVE.SPACES
(LAMBDA (STRING) (* This trick taken from TEDIT source file TEDITWINDOW It removes the leading and 
trailing blanks) (LET ((FIRSTNONSPACE (STRPOSL (QUOTE (% )) STRING NIL T)) (LASTNONSPACE (STRPOSL (
QUOTE (% )) STRING NIL T T))) (if (AND FIRSTNONSPACE LASTNONSPACE) then (SUBSTRING STRING 
FIRSTNONSPACE LASTNONSPACE) else STRING))))
)
(DECLARE: EVAL@COMPILE 
(PUTPROPS QP.GET.USER.NAME.ARITY MACRO (**MACROARG** (LET ((NAME (CAR (NTH **MACROARG** 1))) (ARITY (
CAR (NTH **MACROARG** 2)))) (BQUOTE (QP.REMOVE.SPACES (TEDIT.GETINPUT (TEXTOBJ STREAM) "name/arity = "
 (CONCAT (\, NAME) "/" (\, ARITY))))))))
)
(DECLARE: EVAL@COMPILE 
(PUTPROPS QP.GET.USER.NAME.ARITY.NO.DEFAULT MACRO (**MACROARG** (LET NIL (BQUOTE (QP.REMOVE.SPACES (
TEDIT.GETINPUT (TEXTOBJ STREAM) "name/arity = "))))))
)
(DEFINEQ

(QP.GET.NAME.FROM.STRING
(LAMBDA (STRING) (LET ((SLASH.POSITION (STRPOS "/" STRING 1))) (SELECTQ SLASH.POSITION (1 "no←name") (
NIL STRING) (SUBSTRING STRING 1 (SUB1 SLASH.POSITION))))))
)
(DEFINEQ

(QP.GET.ARITY.FROM.STRING
(LAMBDA (STRING) (LET ((SLASH.POSITION (STRPOS "/" STRING 1)) (STRING.LENGTH (NCHARS STRING))) (if (OR
 (NOT SLASH.POSITION) (EQ SLASH.POSITION STRING.LENGTH)) then "No←arity" else (PACK (UNPACK (SUBSTRING
 STRING (ADD1 SLASH.POSITION) (NCHARS STRING))))))))
)
(DEFINEQ

(QP.FIND.DEFINITION
(LAMBDA (STREAM) (* pds: " 1-Feb-86 15:32") (SETQ QP.FD.ORI.STREAM STREAM) (CLEARW (fetch (TEXTOBJ 
PROMPTWINDOW) of (TEXTOBJ STREAM))) (QP.CLEAR.FD.BUFFER) (if (QP.NOT.SAFE.TO.LOAD.CODE) then (
TEDIT.PROMPTPRINT STREAM "cannot use find-definition unless Prolog is at top-level" T) else (LET ((
DEFAULT.NAME.ARITY (QP.GET.NAME.ARITY.DEFAULT STREAM)) (ABORT NIL) USER.INPUT P.NAME P.ARITY) (if 
DEFAULT.NAME.ARITY then (* a default was found) (SETQ P.ARITY (CAR (LAST DEFAULT.NAME.ARITY))) (SETQ 
P.NAME (QP.CONVERT.NAME.ARITY.TO.NAME DEFAULT.NAME.ARITY)) (SETQ USER.INPUT (QP.GET.USER.NAME.ARITY 
P.NAME P.ARITY)) else (* no default was found) (SETQ USER.INPUT (QP.GET.USER.NAME.ARITY.NO.DEFAULT))) 
(if (NOT (EQUAL USER.INPUT "NIL")) then (* process any user input) (* There was user input) (SETQ 
P.NAME (QP.GET.NAME.FROM.STRING USER.INPUT)) (SETQ P.ARITY (QP.GET.ARITY.FROM.STRING USER.INPUT)) else
 (* There was no user input) (if (NOT DEFAULT.NAME.ARITY) then (SETQ ABORT T))) (CLEARW (fetch (
TEXTOBJ PROMPTWINDOW) of (TEXTOBJ STREAM))) (if (NOT ABORT) then (* see QPROCESS.LSP for the 
definition of QP.SEND.PROLOG) (QP.SEND.PROLOG (CONCAT "find←predicate1(('" P.NAME "')," P.ARITY ")")) 
(TEDIT.PROMPTPRINT STREAM " finding definition ..." T) else (TEDIT.PROMPTPRINT STREAM 
" find-definition canceled" T))))))
)



(* Find-definition: Post-Prolog call stage: display the file that the predicate was defined in
 and show the definition.)




(* Note that the global variable QP.FIND.DEFINITION.SOURCE.FILES holds the list of files to be
 visited for the predicate definitions for find.definition.part.two. It is declared global in 
the file TELLEDITOR.LSP)

(DEFINEQ

(QP.FIND.DEFINITION.PART.TWO
(LAMBDA (DATA.LIST) (* pds: " 2-Feb-86 20:25") (if QP.FIND.DEFINITION.SOURCE.FILES then (for FILENAME 
in QP.FIND.DEFINITION.SOURCE.FILES do (LET ((WORKING.STREAM (QP.TEXTSTREAM FILENAME))) (if (NOT 
WORKING.STREAM) then (* no open stream.) (QP.LOCATE.PREDICATE.FOR.FD DATA.LIST (TEXTSTREAM (TEDIT 
FILENAME NIL NIL (QUOTE (TEDIT.MODE Prolog))))) elseif (NOT (QP.TEDIT.WINDOW FILENAME)) then (
TEDIT.PROMPTPRINT QP.FD.ORI.STREAM (CONCAT (CAR DATA.LIST) "/" (CADR DATA.LIST) " has been lost") T) 
else (PROMPTPRINT "   Revisiting: " FILENAME) (QP.LOCATE.PREDICATE.FOR.FD DATA.LIST WORKING.STREAM))))
 else (TEDIT.PROMPTPRINT QP.FD.ORI.STREAM (CONCAT (CAR DATA.LIST) "/" (CADR DATA.LIST) " not found") T
))))
)
(DEFINEQ

(QP.LOCATE.PREDICATE.FOR.FD
(LAMBDA (DATA.LIST WORKING.STREAM) (* pds: " 1-Feb-86 16:08") (LET* ((P.NAME (CAR DATA.LIST)) (P.ARITY
 (CADR DATA.LIST)) (FLAG (CADDR DATA.LIST)) (ENVIRONMENT (CADDDR DATA.LIST)) (FD.SLASH.ARITY (if (
EQUAL P.ARITY (QUOTE ←)) then "" else (CONCAT "/" P.ARITY)))) (CLEARW (fetch (TEXTOBJ PROMPTWINDOW) of
 (TEXTOBJ WORKING.STREAM))) (if (EQ (QUOTE built←in) FLAG) then (TEDIT.PROMPTPRINT WORKING.STREAM (
CONCAT P.NAME FD.SLASH.ARITY " is a built-in predicate") T) elseif (EQ (QUOTE undefined) FLAG) then (
TEDIT.PROMPTPRINT WORKING.STREAM (CONCAT P.NAME FD.SLASH.ARITY " is undefined") T) elseif (EQ (QUOTE 
none) FLAG) then (TEDIT.PROMPTPRINT WORKING.STREAM (CONCAT "no file associated with " P.NAME 
FD.SLASH.ARITY) T) elseif (EQ (QUOTE ok) FLAG) then (if (EQUAL P.NAME "") then (* No Pred Name) (
TEDIT.PROMPTPRINT WORKING.STREAM "you must use find-definition first" T) else (QP.FIND.MORE.DEFINITION
 WORKING.STREAM P.NAME P.ARITY ENVIRONMENT FD.SLASH.ARITY)) else (TEDIT.PROMPTPRINT WORKING.STREAM (
CONCAT "find definition error = " FLAG) T)) (* Last transfer control to the editor window if calling 
from the editor) (if QP.FD.ORI.STREAM then (TEDIT.PROMPTPRINT QP.FD.ORI.STREAM " " T) (SETQ 
QP.FD.ORI.STREAM NIL)) (if (EQ ENVIRONMENT (QUOTE ed)) then (TTY.PROCESS (WINDOWPROP (QP.TEDIT.WINDOW 
WORKING.STREAM) (QUOTE PROCESS))) else (TTY.PROCESS (FIND.PROCESS QP.PROLOG.NAME))))))
)
(DECLARE: EVAL@COMPILE 
(PUTPROPS QP.FD.GET.FILENAME MACRO (NIL (pop QP.FIND.DEFINITION.SOURCE.FILES)))
)



(* fd-get-filename takes the filenames off the top/front of the list and then removes the 
filename from the list. The original file insertion mechanism in &fd-insert inserts the file 
names at the bottom/end of the list. QP.FD.FILE adds filenames to the end of the list stored in
 QP.FIND.DEFINITION.SOURCE.FILES)

(DEFINEQ

(QP.FIND.MORE.DEFINITION
(LAMBDA (STREAM NAME ARITY ENVIRONMENT FD.SLASH.ARITY) (* pds: "20-Jan-86 15:05") (LET ((FD.FILE.NAME 
(QP.FD.GET.FILENAME))) (if (NOT FD.FILE.NAME) then (* filename is a null string) (SETQ 
QP.FIND.DEFINITION.SOURCE.FILES NIL) (TEDIT.PROMPTPRINT STREAM (CONCAT "no more source files for " 
NAME FD.SLASH.ARITY) T) elseif (EQUAL "user" FD.FILE.NAME) then (TEDIT.PROMPTPRINT STREAM (CONCAT NAME
 FD.SLASH.ARITY "was defined from user" (if QP.FIND.DEFINITION.SOURCE.FILES then 
" - type %"↑X,%" for more" else "")) T) else (* we must have a valid filename) (* need an if statement
 on the environment = "debug" case) (QP.LOCATE.DEFINITION STREAM NAME ARITY)))))
)
(DEFINEQ

(QP.LOCATE.DEFINITION
(LAMBDA (STREAM NAME ARITY) (LET ((STOP NIL) (TEXT (TEXTOBJ STREAM)) (START 1) (POS (TEDIT.FIND STREAM
 NAME 1))) (while (AND POS (NOT STOP)) do (if POS then (\SETUPGETCH POS TEXT) (if (EQ (QP.FIND.ARITY 
STREAM NAME) ARITY) then (SETQ STOP T) else (SETQ START (ADD1 POS)) (SETQ POS (TEDIT.FIND STREAM (
CONCAT (CHARACTER (CHARCODE CR)) NAME) START)) (if POS then (SETQ POS (ADD1 POS))) (* skip the CR)) 
else (SETQ STOP T))) (if POS then (* found it) (LET ((SELECTION (TEDIT.SETSEL STREAM POS 1 (QUOTE LEFT
)))) (TEDIT.NORMALIZECARET TEXT SELECTION) (TEDIT.SETSEL STREAM SELECTION)) else (TEDIT.PROMPTPRINT 
STREAM (CONCAT "cannot find " NAME "/" ARITY) T)))))
)
(PUTPROPS FINDDEFN COPYRIGHT ("Quintus Computer Systems, Inc" 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (2061 2344 (QP.GET.CURSOR 2071 . 2342)) (2767 3097 (QP.SKIP.WHITE.SPACE 2777 . 3095)) (
3396 4349 (QP.FIND.PRED.BEGINNING 3406 . 4347)) (4521 5606 (QP.GET.NAME.ARITY.DEFAULT 4531 . 5604)) (
5801 6169 (QP.REMOVE.SPACES 5811 . 6167)) (6623 6825 (QP.GET.NAME.FROM.STRING 6633 . 6823)) (6826 7126
 (QP.GET.ARITY.FROM.STRING 6836 . 7124)) (7127 8481 (QP.FIND.DEFINITION 7137 . 8479)) (8835 9586 (
QP.FIND.DEFINITION.PART.TWO 8845 . 9584)) (9587 11020 (QP.LOCATE.PREDICATE.FOR.FD 9597 . 11018)) (
11450 12150 (QP.FIND.MORE.DEFINITION 11460 . 12148)) (12151 12850 (QP.LOCATE.DEFINITION 12161 . 12848)
))))
STOP