2907 lines
124 KiB
Common Lisp
2907 lines
124 KiB
Common Lisp
|
;;; -*- Mode: LISP; Package: XREF; Syntax: Common-lisp; -*-
|
|||
|
;;; Mon Jan 21 16:21:20 1991 by Mark Kantrowitz <mkant@GLINDA.OZ.CS.CMU.EDU>
|
|||
|
;;; xref.lisp
|
|||
|
|
|||
|
;;; ****************************************************************
|
|||
|
;;; List Callers: A Static Analysis Cross Referencing Tool for Lisp
|
|||
|
;;; ****************************************************************
|
|||
|
;;;
|
|||
|
;;; The List Callers system is a portable Common Lisp cross referencing
|
|||
|
;;; utility. It grovels over a set of files and compiles a database of the
|
|||
|
;;; locations of all references for each symbol used in the files.
|
|||
|
;;; List Callers is similar to the Symbolics Who-Calls and the
|
|||
|
;;; Xerox Masterscope facilities.
|
|||
|
;;;
|
|||
|
;;; When you change a function or variable definition, it can be useful
|
|||
|
;;; to know its callers, in order to update each of them to the new
|
|||
|
;;; definition. Similarly, having a graphic display of the structure
|
|||
|
;;; (e.g., call graph) of a program can help make undocumented code more
|
|||
|
;;; understandable. This static code analyzer facilitates both capabilities.
|
|||
|
;;; The database compiled by xref is suitable for viewing by a graphical
|
|||
|
;;; browser. (Note: the reference graph is not necessarily a DAG. Since many
|
|||
|
;;; graphical browsers assume a DAG, this will lead to infinite loops.
|
|||
|
;;; Some code which is useful in working around this problem is included,
|
|||
|
;;; as well as a sample text-indenting outliner and an interface to Bates'
|
|||
|
;;; PSGraph Postscript Graphing facility.)
|
|||
|
;;;
|
|||
|
;;; Written by Mark Kantrowitz, July 1990.
|
|||
|
;;;
|
|||
|
;;; Address: School of Computer Science
|
|||
|
;;; Carnegie Mellon University
|
|||
|
;;; Pittsburgh, PA 15213
|
|||
|
;;;
|
|||
|
;;; Copyright (c) 1990. All rights reserved.
|
|||
|
;;;
|
|||
|
;;; See general license below.
|
|||
|
;;;
|
|||
|
|
|||
|
;;; ****************************************************************
|
|||
|
;;; General License Agreement and Lack of Warranty *****************
|
|||
|
;;; ****************************************************************
|
|||
|
;;;
|
|||
|
;;; This software is distributed in the hope that it will be useful (both
|
|||
|
;;; in and of itself and as an example of lisp programming), but WITHOUT
|
|||
|
;;; ANY WARRANTY. The author(s) do not accept responsibility to anyone for
|
|||
|
;;; the consequences of using it or for whether it serves any particular
|
|||
|
;;; purpose or works at all. No warranty is made about the software or its
|
|||
|
;;; performance.
|
|||
|
;;;
|
|||
|
;;; Use and copying of this software and the preparation of derivative
|
|||
|
;;; works based on this software are permitted, so long as the following
|
|||
|
;;; conditions are met:
|
|||
|
;;; o The copyright notice and this entire notice are included intact
|
|||
|
;;; and prominently carried on all copies and supporting documentation.
|
|||
|
;;; o No fees or compensation are charged for use, copies, or
|
|||
|
;;; access to this software. You may charge a nominal
|
|||
|
;;; distribution fee for the physical act of transferring a
|
|||
|
;;; copy, but you may not charge for the program itself.
|
|||
|
;;; o If you modify this software, you must cause the modified
|
|||
|
;;; file(s) to carry prominent notices (a Change Log)
|
|||
|
;;; describing the changes, who made the changes, and the date
|
|||
|
;;; of those changes.
|
|||
|
;;; o Any work distributed or published that in whole or in part
|
|||
|
;;; contains or is a derivative of this software or any part
|
|||
|
;;; thereof is subject to the terms of this agreement. The
|
|||
|
;;; aggregation of another unrelated program with this software
|
|||
|
;;; or its derivative on a volume of storage or distribution
|
|||
|
;;; medium does not bring the other program under the scope
|
|||
|
;;; of these terms.
|
|||
|
;;; o Permission is granted to manufacturers and distributors of
|
|||
|
;;; lisp compilers and interpreters to include this software
|
|||
|
;;; with their distribution.
|
|||
|
;;;
|
|||
|
;;; This software is made available AS IS, and is distributed without
|
|||
|
;;; warranty of any kind, either expressed or implied.
|
|||
|
;;;
|
|||
|
;;; In no event will the author(s) or their institutions be liable to you
|
|||
|
;;; for damages, including lost profits, lost monies, or other special,
|
|||
|
;;; incidental or consequential damages arising out of or in connection
|
|||
|
;;; with the use or inability to use (including but not limited to loss of
|
|||
|
;;; data or data being rendered inaccurate or losses sustained by third
|
|||
|
;;; parties or a failure of the program to operate as documented) the
|
|||
|
;;; program, even if you have been advised of the possibility of such
|
|||
|
;;; damanges, or for any claim by any other party, whether in an action of
|
|||
|
;;; contract, negligence, or other tortious action.
|
|||
|
;;;
|
|||
|
;;; The current version of this software and a variety of related utilities
|
|||
|
;;; may be obtained by anonymous ftp from ftp.cs.cmu.edu in the directory
|
|||
|
;;; user/ai/lang/lisp/code/tools/xref/
|
|||
|
;;;
|
|||
|
;;; Please send bug reports, comments, questions and suggestions to
|
|||
|
;;; mkant@cs.cmu.edu. We would also appreciate receiving any changes
|
|||
|
;;; or improvements you may make.
|
|||
|
;;;
|
|||
|
;;; If you wish to be added to the Lisp-Utilities@cs.cmu.edu mailing list,
|
|||
|
;;; send email to Lisp-Utilities-Request@cs.cmu.edu with your name, email
|
|||
|
;;; address, and affiliation. This mailing list is primarily for
|
|||
|
;;; notification about major updates, bug fixes, and additions to the lisp
|
|||
|
;;; utilities collection. The mailing list is intended to have low traffic.
|
|||
|
;;;
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Change Log *********************
|
|||
|
;;; ********************************
|
|||
|
;;;
|
|||
|
;;; 27-FEB-91 mk Added insert arg to psgraph-xref to allow the postscript
|
|||
|
;;; graphs to be inserted in Scribe documents.
|
|||
|
;;; 21-FEB-91 mk Added warning if not compiled.
|
|||
|
;;; 07-FEB-91 mk Fixed bug in record-callers with regard to forms at
|
|||
|
;;; toplevel.
|
|||
|
;;; 21-JAN-91 mk Added file xref-test.lisp to test xref.
|
|||
|
;;; 16-JAN-91 mk Added definition WHO-CALLS to parallel the Symbolics syntax.
|
|||
|
;;; 16-JAN-91 mk Added macroexpansion capability to record-callers. Also
|
|||
|
;;; added parameter *handle-macro-forms*, defaulting to T.
|
|||
|
;;; 16-JAN-91 mk Modified print-caller-tree and related functions
|
|||
|
;;; to allow the user to specify root nodes. If the user
|
|||
|
;;; doesn't specify them, it will default to all root
|
|||
|
;;; nodes, as before.
|
|||
|
;;; 16-JAN-91 mk Added parameter *default-graphing-mode* to specify
|
|||
|
;;; the direction of the graphing. Either :call-graph,
|
|||
|
;;; where the children of a node are those functions called
|
|||
|
;;; by the node, or :caller-graph where the children of a
|
|||
|
;;; node are the callers of the node. :call-graph is the
|
|||
|
;;; default.
|
|||
|
;;; 16-JAN-91 mk Added parameter *indent-amount* to control the indentation
|
|||
|
;;; in print-indented-tree.
|
|||
|
;;; 16-JUL-90 mk Functions with argument lists of () were being ignored
|
|||
|
;;; because of a (when form) wrapped around the body of
|
|||
|
;;; record-callers. Then intent of (when form) was as an extra
|
|||
|
;;; safeguard against infinite looping. This wasn't really
|
|||
|
;;; necessary, so it has been removed.
|
|||
|
;;; 16-JUL-90 mk PSGraph-XREF now has keyword arguments, instead of
|
|||
|
;;; optionals.
|
|||
|
;;; 16-JUL-90 mk Added PRINT-CLASS-HIERARCHY to use psgraph to graph the
|
|||
|
;;; CLOS class hierarchy. This really doesn't belong here,
|
|||
|
;;; and should be moved to psgraph.lisp as an example of how
|
|||
|
;;; to use psgraph.
|
|||
|
;;; 16-JUL-90 mk Fixed several caller patterns. The pattern for member
|
|||
|
;;; had an error which caused many references to be missed.
|
|||
|
;;; 16-JUL-90 mk Added ability to save/load processed databases.
|
|||
|
;;; 5-JUL-91 mk Fixed warning of needing compilation to occur only when the
|
|||
|
;;; source is loaded.
|
|||
|
;;; 20-SEP-93 mk Added fix from Peter Norvig to allow Xref to xref itself.
|
|||
|
;;; The arg to macro-function must be a symbol.
|
|||
|
;;; 7-APR-12 heller Break lines at 80 columns.
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; To Do **************************
|
|||
|
;;; ********************************
|
|||
|
;;;
|
|||
|
;;; Verify that:
|
|||
|
;;; o null forms don't cause it to infinite loop.
|
|||
|
;;; o nil matches against null argument lists.
|
|||
|
;;; o declarations and doc are being ignored.
|
|||
|
;;;
|
|||
|
;;; Would be nice if in addition to showing callers of a function, it
|
|||
|
;;; displayed the context of the calls to the function (e.g., the
|
|||
|
;;; immediately surrounding form). This entails storing entries of
|
|||
|
;;; the form (symbol context*) in the database and augmenting
|
|||
|
;;; record-callers to keep the context around. The only drawbacks is
|
|||
|
;;; that it would cons a fair bit. If we do this, we should store
|
|||
|
;;; additional information as well in the database, such as the caller
|
|||
|
;;; pattern type (e.g., variable vs. function).
|
|||
|
;;;
|
|||
|
;;; Write a translator from BNF (at least as much of BNF as is used
|
|||
|
;;; in CLtL2), to the format used here.
|
|||
|
;;;
|
|||
|
;;; Should automatically add new patterns for new functions and macros
|
|||
|
;;; based on their arglists. Probably requires much more than this
|
|||
|
;;; simple code walker, so there isn't much we can do.
|
|||
|
;;;
|
|||
|
;;; Defmacro is a problem, because it often hides internal function
|
|||
|
;;; calls within backquote and quote, which we normally ignore. If
|
|||
|
;;; we redefine QUOTE's pattern so that it treats the arg like a FORM,
|
|||
|
;;; we'll probably get them (though maybe the syntax will be mangled),
|
|||
|
;;; but most likely a lot of spurious things as well.
|
|||
|
;;;
|
|||
|
;;; Define an operation for Defsystem which will run XREF-FILE on the
|
|||
|
;;; files of the system. Or yet simpler, when XREF sees a LOAD form
|
|||
|
;;; for which the argument is a string, tries to recursively call
|
|||
|
;;; XREF-FILE on the specified file. Then one could just XREF-FILE
|
|||
|
;;; the file which loads the system. (This should be a program
|
|||
|
;;; parameter.)
|
|||
|
;;;
|
|||
|
;;; Have special keywords which the user may place in a file to have
|
|||
|
;;; XREF-FILE ignore a region.
|
|||
|
;;;
|
|||
|
;;; Should we distinguish flet and labels from defun? I.e., note that
|
|||
|
;;; flet's definitions are locally defined, instead of just lumping
|
|||
|
;;; them in with regular definitions.
|
|||
|
;;;
|
|||
|
;;; Add patterns for series, loop macro.
|
|||
|
;;;
|
|||
|
;;; Need to integrate the variable reference database with the other
|
|||
|
;;; databases, yet maintain separation. So we can distinguish all
|
|||
|
;;; the different types of variable and function references, without
|
|||
|
;;; multiplying databases.
|
|||
|
;;;
|
|||
|
;;; Would pay to comment record-callers and record-callers* in more
|
|||
|
;;; depth.
|
|||
|
;;;
|
|||
|
;;; (&OPTIONAL &REST &KEY &AUX &BODY &WHOLE &ALLOW-OTHER-KEYS &ENVIRONMENT)
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Notes **************************
|
|||
|
;;; ********************************
|
|||
|
;;;
|
|||
|
;;; XREF has been tested (successfully) in the following lisps:
|
|||
|
;;; CMU Common Lisp (M2.9 15-Aug-90, Compiler M1.8 15-Aug-90)
|
|||
|
;;; Macintosh Allegro Common Lisp (1.3.2)
|
|||
|
;;; ExCL (Franz Allegro CL 3.1.12 [DEC 3100] 3/30/90)
|
|||
|
;;; Lucid CL (Version 2.1 6-DEC-87)
|
|||
|
;;;
|
|||
|
;;; XREF has been tested (unsuccessfully) in the following lisps:
|
|||
|
;;; Ibuki Common Lisp (01/01, October 15, 1987)
|
|||
|
;;; - if interpreted, runs into stack overflow
|
|||
|
;;; - does not compile (tried ibcl on Suns, PMAXes and RTs)
|
|||
|
;;; seems to be due to a limitation in the c compiler.
|
|||
|
;;;
|
|||
|
;;; XREF needs to be tested in the following lisps:
|
|||
|
;;; Symbolics Common Lisp (8.0)
|
|||
|
;;; Lucid Common Lisp (3.0, 4.0)
|
|||
|
;;; KCL (June 3, 1987 or later)
|
|||
|
;;; AKCL (1.86, June 30, 1987 or later)
|
|||
|
;;; TI (Release 4.1 or later)
|
|||
|
;;; Golden Common Lisp (3.1 IBM-PC)
|
|||
|
;;; VAXLisp (2.0, 3.1)
|
|||
|
;;; HP Common Lisp (same as Lucid?)
|
|||
|
;;; Procyon Common Lisp
|
|||
|
|
|||
|
|
|||
|
;;; ****************************************************************
|
|||
|
;;; Documentation **************************************************
|
|||
|
;;; ****************************************************************
|
|||
|
;;;
|
|||
|
;;; XREF analyzes a user's program, determining which functions call a
|
|||
|
;;; given function, and the location of where variables are bound/assigned
|
|||
|
;;; and used. The user may retrieve this information for either a single
|
|||
|
;;; symbol, or display the call graph of portions of the program
|
|||
|
;;; (including the entire program). This allows the programmer to debug
|
|||
|
;;; and document the program's structure.
|
|||
|
;;;
|
|||
|
;;; XREF is primarily intended for analyzing large programs, where it is
|
|||
|
;;; difficult, if not impossible, for the programmer to grasp the structure
|
|||
|
;;; of the whole program. Nothing precludes using XREF for smaller programs,
|
|||
|
;;; where it can be useful for inspecting the relationships between pieces
|
|||
|
;;; of the program and for documenting the program.
|
|||
|
;;;
|
|||
|
;;; Two aspects of the Lisp programming language greatly simplify the
|
|||
|
;;; analysis of Lisp programs:
|
|||
|
;;; o Lisp programs are naturally represented as data.
|
|||
|
;;; Successive definitions from a file are easily read in
|
|||
|
;;; as list structure.
|
|||
|
;;; o The basic syntax of Lisp is uniform. A list program
|
|||
|
;;; consists of a set of nested forms, where each form is
|
|||
|
;;; a list whose car is a tag (e.g., function name) that
|
|||
|
;;; specifies the structure of the rest of the form.
|
|||
|
;;; Thus Lisp programs, when represented as data, can be considered to be
|
|||
|
;;; parse trees. Given a grammar of syntax patterns for the language, XREF
|
|||
|
;;; recursively descends the parse tree for a given definition, computing
|
|||
|
;;; a set of relations that hold for the definition at each node in the
|
|||
|
;;; tree. For example, one kind of relation is that the function defined
|
|||
|
;;; by the definition calls the functions in its body. The relations are
|
|||
|
;;; stored in a database for later examination by the user.
|
|||
|
;;;
|
|||
|
;;; While XREF currently only works for programs written in Lisp, it could
|
|||
|
;;; be extended to other programming languages by writing a function to
|
|||
|
;;; generate parse trees for definitions in that language, and a core
|
|||
|
;;; set of patterns for the language's syntax.
|
|||
|
;;;
|
|||
|
;;; Since XREF normally does a static syntactic analysis of the program,
|
|||
|
;;; it does not detect references due to the expansion of a macro definition.
|
|||
|
;;; To do this in full generality XREF would have to have knowledge about the
|
|||
|
;;; semantics of the program (e.g., macros which call other functions to
|
|||
|
;;; do the expansion). This entails either modifying the compiler to
|
|||
|
;;; record the relationships (e.g., Symbolics Who-Calls Database) or doing
|
|||
|
;;; a walk of loaded code and macroexpanding as needed (PCL code walker).
|
|||
|
;;; The former is not portable, while the latter requires that the code
|
|||
|
;;; used by macros be loaded and in working order. On the other hand, then
|
|||
|
;;; we would need no special knowledge about macros (excluding the 24 special
|
|||
|
;;; forms of Lisp).
|
|||
|
;;;
|
|||
|
;;; Parameters may be set to enable macro expansion in XREF. Then XREF
|
|||
|
;;; will expand any macros for which it does not have predefined patterns.
|
|||
|
;;; (For example, most Lisps will implement dolist as a macro. Since XREF
|
|||
|
;;; has a pattern defined for dolist, it will not call macroexpand-1 on
|
|||
|
;;; a form whose car is dolist.) For this to work properly, the code must
|
|||
|
;;; be loaded before being processed by XREF, and XREF's parameters should
|
|||
|
;;; be set so that it processes forms in their proper packages.
|
|||
|
;;;
|
|||
|
;;; If macro expansion is disabled, the default rules for handling macro
|
|||
|
;;; references may not be sufficient for some user-defined macros, because
|
|||
|
;;; macros allow a variety of non-standard syntactic extensions to the
|
|||
|
;;; language. In this case, the user may specify additional templates in
|
|||
|
;;; a manner similar to that in which the core Lisp grammar was specified.
|
|||
|
;;;
|
|||
|
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; User Guide *********************
|
|||
|
;;; ********************************
|
|||
|
;;; -----
|
|||
|
;;; The following functions are called to cross reference the source files.
|
|||
|
;;;
|
|||
|
;;; XREF-FILES (&rest files) [FUNCTION]
|
|||
|
;;; Grovels over the lisp code located in source file FILES, using
|
|||
|
;;; xref-file.
|
|||
|
;;;
|
|||
|
;;; XREF-FILE (filename &optional clear-tables verbose) [Function]
|
|||
|
;;; Cross references the function and variable calls in FILENAME by
|
|||
|
;;; walking over the source code located in the file. Defaults type of
|
|||
|
;;; filename to ".lisp". Chomps on the code using record-callers and
|
|||
|
;;; record-callers*. If CLEAR-TABLES is T (the default), it clears the
|
|||
|
;;; callers database before processing the file. Specify CLEAR-TABLES as
|
|||
|
;;; nil to append to the database. If VERBOSE is T (the default), prints
|
|||
|
;;; out the name of the file, one progress dot for each form processed,
|
|||
|
;;; and the total number of forms.
|
|||
|
;;;
|
|||
|
;;; -----
|
|||
|
;;; The following functions display information about the uses of the
|
|||
|
;;; specified symbol as a function, variable, or constant.
|
|||
|
;;;
|
|||
|
;;; LIST-CALLERS (symbol) [FUNCTION]
|
|||
|
;;; Lists all functions which call SYMBOL as a function (function
|
|||
|
;;; invocation).
|
|||
|
;;;
|
|||
|
;;; LIST-READERS (symbol) [FUNCTION]
|
|||
|
;;; Lists all functions which refer to SYMBOL as a variable
|
|||
|
;;; (variable reference).
|
|||
|
;;;
|
|||
|
;;; LIST-SETTERS (symbol) [FUNCTION]
|
|||
|
;;; Lists all functions which bind/set SYMBOL as a variable
|
|||
|
;;; (variable mutation).
|
|||
|
;;;
|
|||
|
;;; LIST-USERS (symbol) [FUNCTION]
|
|||
|
;;; Lists all functions which use SYMBOL as a variable or function.
|
|||
|
;;;
|
|||
|
;;; WHO-CALLS (symbol &optional how) [FUNCTION]
|
|||
|
;;; Lists callers of symbol. HOW may be :function, :reader, :setter,
|
|||
|
;;; or :variable."
|
|||
|
;;;
|
|||
|
;;; WHAT-FILES-CALL (symbol) [FUNCTION]
|
|||
|
;;; Lists names of files that contain uses of SYMBOL
|
|||
|
;;; as a function, variable, or constant.
|
|||
|
;;;
|
|||
|
;;; SOURCE-FILE (symbol) [FUNCTION]
|
|||
|
;;; Lists the names of files in which SYMBOL is defined/used.
|
|||
|
;;;
|
|||
|
;;; LIST-CALLEES (symbol) [FUNCTION]
|
|||
|
;;; Lists names of functions and variables called by SYMBOL.
|
|||
|
;;;
|
|||
|
;;; -----
|
|||
|
;;; The following functions may be useful for viewing the database and
|
|||
|
;;; debugging the calling patterns.
|
|||
|
;;;
|
|||
|
;;; *LAST-FORM* () [VARIABLE]
|
|||
|
;;; The last form read from the file. Useful for figuring out what went
|
|||
|
;;; wrong when xref-file drops into the debugger.
|
|||
|
;;;
|
|||
|
;;; *XREF-VERBOSE* t [VARIABLE]
|
|||
|
;;; When T, xref-file(s) prints out the names of the files it looks at,
|
|||
|
;;; progress dots, and the number of forms read.
|
|||
|
;;;
|
|||
|
;;; *TYPES-TO-IGNORE* (quote (:lisp :lisp2)) [VARIABLE]
|
|||
|
;;; Default set of caller types (as specified in the patterns) to ignore
|
|||
|
;;; in the database handling functions. :lisp is CLtL 1st edition,
|
|||
|
;;; :lisp2 is additional patterns from CLtL 2nd edition.
|
|||
|
;;;
|
|||
|
;;; *HANDLE-PACKAGE-FORMS* () [VARIABLE]
|
|||
|
;;; When non-NIL, and XREF-FILE sees a package-setting form like
|
|||
|
;;; IN-PACKAGE, sets the current package to the specified package by
|
|||
|
;;; evaluating the form. When done with the file, xref-file resets the
|
|||
|
;;; package to its original value. In some of the displaying functions,
|
|||
|
;;; when this variable is non-NIL one may specify that all symbols from a
|
|||
|
;;; particular set of packages be ignored. This is only useful if the
|
|||
|
;;; files use different packages with conflicting names.
|
|||
|
;;;
|
|||
|
;;; *HANDLE-FUNCTION-FORMS* t [VARIABLE]
|
|||
|
;;; When T, XREF-FILE tries to be smart about forms which occur in
|
|||
|
;;; a function position, such as lambdas and arbitrary Lisp forms.
|
|||
|
;;; If so, it recursively calls record-callers with pattern 'FORM.
|
|||
|
;;; If the form is a lambda, makes the caller a caller of
|
|||
|
;;; :unnamed-lambda.
|
|||
|
;;;
|
|||
|
;;; *HANDLE-MACRO-FORMS* t [VARIABLE]
|
|||
|
;;; When T, if the file was loaded before being processed by XREF, and
|
|||
|
;;; the car of a form is a macro, it notes that the parent calls the
|
|||
|
;;; macro, and then calls macroexpand-1 on the form.
|
|||
|
;;;
|
|||
|
;;; *DEFAULT-GRAPHING-MODE* :call-graph [VARIABLE]
|
|||
|
;;; Specifies whether we graph up or down. If :call-graph, the children
|
|||
|
;;; of a node are the functions it calls. If :caller-graph, the
|
|||
|
;;; children of a node are the functions that call it.
|
|||
|
;;;
|
|||
|
;;; *INDENT-AMOUNT* 3 [VARIABLE]
|
|||
|
;;; Number of spaces to indent successive levels in PRINT-INDENTED-TREE.
|
|||
|
;;;
|
|||
|
;;; DISPLAY-DATABASE (&optional database types-to-ignore) [FUNCTION]
|
|||
|
;;; Prints out the name of each symbol and all its callers. Specify
|
|||
|
;;; database :callers (the default) to get function call references,
|
|||
|
;;; :file to the get files in which the symbol is called, :readers to get
|
|||
|
;;; variable references, and :setters to get variable binding and
|
|||
|
;;; assignments. Ignores functions of types listed in types-to-ignore.
|
|||
|
;;;
|
|||
|
;;; PRINT-CALLER-TREES (&key (mode *default-graphing-mode*) [FUNCTION]
|
|||
|
;;; (types-to-ignore *types-to-ignore*)
|
|||
|
;;; compact root-nodes)
|
|||
|
;;; Prints the calling trees (which may actually be a full graph and not
|
|||
|
;;; necessarily a DAG) as indented text trees using
|
|||
|
;;; PRINT-INDENTED-TREE. MODE is :call-graph for trees where the children
|
|||
|
;;; of a node are the functions called by the node, or :caller-graph for
|
|||
|
;;; trees where the children of a node are the functions the node calls.
|
|||
|
;;; TYPES-TO-IGNORE is a list of funcall types (as specified in the
|
|||
|
;;; patterns) to ignore in printing out the database. For example,
|
|||
|
;;; '(:lisp) would ignore all calls to common lisp functions. COMPACT is
|
|||
|
;;; a flag to tell the program to try to compact the trees a bit by not
|
|||
|
;;; printing trees if they have already been seen. ROOT-NODES is a list
|
|||
|
;;; of root nodes of trees to display. If ROOT-NODES is nil, tries to
|
|||
|
;;; find all root nodes in the database.
|
|||
|
;;;
|
|||
|
;;; MAKE-CALLER-TREE (&optional (mode *default-graphing-mode*) [FUNCTION]
|
|||
|
;;; (types-to-ignore *types-to-ignore*)
|
|||
|
;;; compact)
|
|||
|
;;; Outputs list structure of a tree which roughly represents the
|
|||
|
;;; possibly cyclical structure of the caller database.
|
|||
|
;;; If mode is :call-graph, the children of a node are the functions
|
|||
|
;;; it calls. If mode is :caller-graph, the children of a node are the
|
|||
|
;;; functions that call it.
|
|||
|
;;; If compact is T, tries to eliminate the already-seen nodes, so
|
|||
|
;;; that the graph for a node is printed at most once. Otherwise it will
|
|||
|
;;; duplicate the node's tree (except for cycles). This is usefull
|
|||
|
;;; because the call tree is actually a directed graph, so we can either
|
|||
|
;;; duplicate references or display only the first one.
|
|||
|
;;;
|
|||
|
;;; DETERMINE-FILE-DEPENDENCIES (&optional database) [FUNCTION]
|
|||
|
;;; Makes a hash table of file dependencies for the references listed in
|
|||
|
;;; DATABASE. This function may be useful for automatically resolving
|
|||
|
;;; file references for automatic creation of a system definition
|
|||
|
;;; (defsystem).
|
|||
|
;;;
|
|||
|
;;; PRINT-FILE-DEPENDENCIES (&optional database) [FUNCTION]
|
|||
|
;;; Prints a list of file dependencies for the references listed in
|
|||
|
;;; DATABASE. This function may be useful for automatically computing
|
|||
|
;;; file loading constraints for a system definition tool.
|
|||
|
;;;
|
|||
|
;;; WRITE-CALLERS-DATABASE-TO-FILE (filename) [FUNCTION]
|
|||
|
;;; Saves the contents of the current callers database to a file. This
|
|||
|
;;; file can be loaded to restore the previous contents of the
|
|||
|
;;; database. (For large systems it can take a long time to crunch
|
|||
|
;;; through the code, so this can save some time.)
|
|||
|
;;;
|
|||
|
;;; -----
|
|||
|
;;; The following macros define new function and macro call patterns.
|
|||
|
;;; They may be used to extend the static analysis tool to handle
|
|||
|
;;; new def forms, extensions to Common Lisp, and program defs.
|
|||
|
;;;
|
|||
|
;;; DEFINE-PATTERN-SUBSTITUTION (name pattern) [MACRO]
|
|||
|
;;; Defines NAME to be equivalent to the specified pattern. Useful for
|
|||
|
;;; making patterns more readable. For example, the LAMBDA-LIST is
|
|||
|
;;; defined as a pattern substitution, making the definition of the
|
|||
|
;;; DEFUN caller-pattern simpler.
|
|||
|
;;;
|
|||
|
;;; DEFINE-CALLER-PATTERN (name pattern &optional caller-type) [MACRO]
|
|||
|
;;; Defines NAME as a function/macro call with argument structure
|
|||
|
;;; described by PATTERN. CALLER-TYPE, if specified, assigns a type to
|
|||
|
;;; the pattern, which may be used to exclude references to NAME while
|
|||
|
;;; viewing the database. For example, all the Common Lisp definitions
|
|||
|
;;; have a caller-type of :lisp or :lisp2, so that you can exclude
|
|||
|
;;; references to common lisp functions from the calling tree.
|
|||
|
;;;
|
|||
|
;;; DEFINE-VARIABLE-PATTERN (name &optional caller-type) [MACRO]
|
|||
|
;;; Defines NAME as a variable reference of type CALLER-TYPE. This is
|
|||
|
;;; mainly used to establish the caller-type of the variable.
|
|||
|
;;;
|
|||
|
;;; DEFINE-CALLER-PATTERN-SYNONYMS (source destinations) [MACRO]
|
|||
|
;;; For defining function caller pattern syntax synonyms. For each name
|
|||
|
;;; in DESTINATIONS, defines its pattern as a copy of the definition
|
|||
|
;;; of SOURCE. Allows a large number of identical patterns to be defined
|
|||
|
;;; simultaneously. Must occur after the SOURCE has been defined.
|
|||
|
;;;
|
|||
|
;;; -----
|
|||
|
;;; This system includes pattern definitions for the latest
|
|||
|
;;; common lisp specification, as published in Guy Steele,
|
|||
|
;;; Common Lisp: The Language, 2nd Edition.
|
|||
|
;;;
|
|||
|
;;; Patterns may be either structures to match, or a predicate
|
|||
|
;;; like symbolp/numberp/stringp. The pattern specification language
|
|||
|
;;; is similar to the notation used in CLtL2, but in a more lisp-like
|
|||
|
;;; form:
|
|||
|
;;; (:eq name) The form element must be eq to the symbol NAME.
|
|||
|
;;; (:test test) TEST must be true when applied to the form element.
|
|||
|
;;; (:typep type) The form element must be of type TYPE.
|
|||
|
;;; (:or pat1 pat2 ...) Tries each of the patterns in left-to-right order,
|
|||
|
;;; until one succeeds.
|
|||
|
;;; Equivalent to { pat1 | pat2 | ... }
|
|||
|
;;; (:rest pattern) The remaining form elements are grouped into a
|
|||
|
;;; list which is matched against PATTERN.
|
|||
|
;;; (:optional pat1 ...) The patterns may optionally match against the
|
|||
|
;;; form element.
|
|||
|
;;; Equivalent to [ pat1 ... ].
|
|||
|
;;; (:star pat1 ...) The patterns may match against the patterns
|
|||
|
;;; any number of times, including 0.
|
|||
|
;;; Equivalent to { pat1 ... }*.
|
|||
|
;;; (:plus pat1 ...) The patterns may match against the patterns
|
|||
|
;;; any number of times, but at least once.
|
|||
|
;;; Equivalent to { pat1 ... }+.
|
|||
|
;;; &optional, &key, Similar in behavior to the corresponding
|
|||
|
;;; &rest lambda-list keywords.
|
|||
|
;;; FORM A random lisp form. If a cons, assumes the
|
|||
|
;;; car is a function or macro and tries to
|
|||
|
;;; match the args against that symbol's pattern.
|
|||
|
;;; If a symbol, assumes it's a variable reference.
|
|||
|
;;; :ignore Ignores the corresponding form element.
|
|||
|
;;; NAME The corresponding form element should be
|
|||
|
;;; the name of a new definition (e.g., the
|
|||
|
;;; first arg in a defun pattern is NAME.
|
|||
|
;;; FUNCTION, MACRO The corresponding form element should be
|
|||
|
;;; a function reference not handled by FORM.
|
|||
|
;;; Used in the definition of apply and funcall.
|
|||
|
;;; VAR The corresponding form element should be
|
|||
|
;;; a variable definition or mutation. Used
|
|||
|
;;; in the definition of let, let*, etc.
|
|||
|
;;; VARIABLE The corresponding form element should be
|
|||
|
;;; a variable reference.
|
|||
|
;;;
|
|||
|
;;; In all other pattern symbols, it looks up the symbols pattern substitution
|
|||
|
;;; and recursively matches against the pattern. Automatically destructures
|
|||
|
;;; list structure that does not include consing dots.
|
|||
|
;;;
|
|||
|
;;; Among the pattern substitution names defined are:
|
|||
|
;;; STRING, SYMBOL, NUMBER Appropriate :test patterns.
|
|||
|
;;; LAMBDA-LIST Matches against a lambda list.
|
|||
|
;;; BODY Matches against a function body definition.
|
|||
|
;;; FN Matches against #'function, 'function,
|
|||
|
;;; and lambdas. This is used in the definition
|
|||
|
;;; of apply, funcall, and the mapping patterns.
|
|||
|
;;; and others...
|
|||
|
;;;
|
|||
|
;;; Here's some sample pattern definitions:
|
|||
|
;;; (define-caller-pattern defun
|
|||
|
;;; (name lambda-list
|
|||
|
;;; (:star (:or documentation-string declaration))
|
|||
|
;;; (:star form))
|
|||
|
;;; :lisp)
|
|||
|
;;; (define-caller-pattern funcall (fn (:star form)) :lisp)
|
|||
|
;;;
|
|||
|
;;; In general, the system is intelligent enough to handle any sort of
|
|||
|
;;; simple funcall. One only need specify the syntax for functions and
|
|||
|
;;; macros which use optional arguments, keyword arguments, or some
|
|||
|
;;; argument positions are special, such as in apply and funcall, or
|
|||
|
;;; to indicate that the function is of the specified caller type.
|
|||
|
;;;
|
|||
|
;;;
|
|||
|
;;; NOTES:
|
|||
|
;;;
|
|||
|
;;; XRef assumes syntactically correct lisp code.
|
|||
|
;;;
|
|||
|
;;; This is by no means perfect. For example, let and let* are treated
|
|||
|
;;; identically, instead of differentiating between serial and parallel
|
|||
|
;;; binding. But it's still a useful tool. It can be helpful in
|
|||
|
;;; maintaining code, debugging problems with patch files, determining
|
|||
|
;;; whether functions are multiply defined, and help you remember where
|
|||
|
;;; a function is defined or called.
|
|||
|
;;;
|
|||
|
;;; XREF runs best when compiled.
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; References *********************
|
|||
|
;;; ********************************
|
|||
|
;;;
|
|||
|
;;; Xerox Interlisp Masterscope Program:
|
|||
|
;;; Larry M Masinter, Global program analysis in an interactive environment
|
|||
|
;;; PhD Thesis, Stanford University, 1980.
|
|||
|
;;;
|
|||
|
;;; Symbolics Who-Calls Database:
|
|||
|
;;; User's Guide to Symbolics Computers, Volume 1, Cambridge, MA, July 1986
|
|||
|
;;; Genera 7.0, pp 183-185.
|
|||
|
;;;
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Example ************************
|
|||
|
;;; ********************************
|
|||
|
;;;
|
|||
|
;;; Here is an example of running XREF on a short program.
|
|||
|
;;; [In Scribe documentation, give a simple short program and resulting
|
|||
|
;;; XREF output, including postscript call graphs.]
|
|||
|
#|
|
|||
|
<cl> (xref:xref-file "/afs/cs/user/mkant/Lisp/Graph-Dag/graph-dag.lisp")
|
|||
|
Cross-referencing file /afs/cs/user/mkant/Lisp/Graph-Dag/graph-dag.lisp.
|
|||
|
................................................
|
|||
|
48 forms processed.
|
|||
|
<cl> (xref:display-database :readers)
|
|||
|
|
|||
|
*DISPLAY-CUTOFF-DEPTH* is referenced by CALCULATE-LEVEL-POSITION
|
|||
|
CALCULATE-LEVEL-POSITION-BEFORE CALCULATE-POSITION-IN-LEVEL.
|
|||
|
*OFFSET-FROM-EDGE-OF-PANE* is referenced by CALCULATE-LEVEL-POSITION
|
|||
|
CALCULATE-LEVEL-POSITION-BEFORE.
|
|||
|
*WITHIN-LEVEL-SPACING* is referenced by BREADTH CALCULATE-POSITION-INFO.
|
|||
|
*DIRECTION* is referenced by CREATE-POSITION-INFO.
|
|||
|
*LINK-OFFSET* is referenced by OFFSET-OF-LINK-FROM-ATTACHMENT-POINT.
|
|||
|
*ROOT-IS-SEQUENCE* is referenced by GRAPH.
|
|||
|
*LEVEL-SPACING* is referenced by CALCULATE-LEVEL-POSITION
|
|||
|
CALCULATE-LEVEL-POSITION-BEFORE.
|
|||
|
*ORIENTATION* is referenced by BREADTH CALCULATE-LEVEL-POSITION
|
|||
|
CALCULATE-LEVEL-POSITION-BEFORE CALCULATE-POSITION-IN-LEVEL.
|
|||
|
*DEFAULT-GRAPH-POSITION* is referenced by CREATE-POSITION-INFO.
|
|||
|
*GRAPHING-CUTOFF-DEPTH* is referenced by CREATE-NODE-STRUCTURE.
|
|||
|
*LIST-OF-NODES* is referenced by CALCULATE-LEVEL-POSITION
|
|||
|
CALCULATE-LEVEL-POSITION-BEFORE CREATE-NODE FIND-NODE.
|
|||
|
*GRAPH-TYPE* is referenced by CREATE-NODE-STRUCTURE.
|
|||
|
<cl> (xref:print-caller-trees :root-nodes '(display-graph))
|
|||
|
|
|||
|
Rooted calling trees:
|
|||
|
DISPLAY-GRAPH
|
|||
|
CREATE-POSITION-INFO
|
|||
|
CALCULATE-POSITION-INFO
|
|||
|
CALCULATE-POSITION
|
|||
|
NODE-POSITION-ALREADY-SET-FLAG
|
|||
|
NODE-LEVEL-ALREADY-SET-FLAG
|
|||
|
CALCULATE-POSITION-IN-LEVEL
|
|||
|
NODE-CHILDREN
|
|||
|
NODE-LEVEL
|
|||
|
CALCULATE-POSITION
|
|||
|
NEW-CALCULATE-BREADTH
|
|||
|
NODE-CHILDREN
|
|||
|
BREADTH
|
|||
|
OPPOSITE-DIMENSION
|
|||
|
NODE-HEIGHT
|
|||
|
NODE-WIDTH
|
|||
|
NEW-CALCULATE-BREADTH
|
|||
|
NODE-PARENTS
|
|||
|
OPPOSITE-DIMENSION
|
|||
|
NODE-HEIGHT
|
|||
|
NODE-WIDTH
|
|||
|
OPPOSITE-POSITION
|
|||
|
NODE-Y
|
|||
|
NODE-X
|
|||
|
NODE-LEVEL
|
|||
|
CALCULATE-LEVEL-POSITION
|
|||
|
NODE-LEVEL
|
|||
|
NODE-POSITION
|
|||
|
NODE-X
|
|||
|
NODE-Y
|
|||
|
DIMENSION
|
|||
|
NODE-WIDTH
|
|||
|
NODE-HEIGHT
|
|||
|
CALCULATE-LEVEL-POSITION-BEFORE
|
|||
|
NODE-LEVEL
|
|||
|
NODE-POSITION
|
|||
|
NODE-X
|
|||
|
NODE-Y
|
|||
|
NODE-WIDTH
|
|||
|
NODE-HEIGHT
|
|||
|
DIMENSION
|
|||
|
NODE-WIDTH
|
|||
|
NODE-HEIGHT
|
|||
|
|#
|
|||
|
|
|||
|
;;; ****************************************************************
|
|||
|
;;; List Callers ***************************************************
|
|||
|
;;; ****************************************************************
|
|||
|
|
|||
|
(defpackage :pxref
|
|||
|
(:use :common-lisp)
|
|||
|
(:export #:list-callers
|
|||
|
#:list-users
|
|||
|
#:list-readers
|
|||
|
#:list-setters
|
|||
|
#:what-files-call
|
|||
|
#:who-calls
|
|||
|
#:list-callees
|
|||
|
#:source-file
|
|||
|
#:clear-tables
|
|||
|
#:define-pattern-substitution
|
|||
|
#:define-caller-pattern
|
|||
|
#:define-variable-pattern
|
|||
|
#:define-caller-pattern-synonyms
|
|||
|
#:clear-patterns
|
|||
|
#:*last-form*
|
|||
|
#:*xref-verbose*
|
|||
|
#:*handle-package-forms*
|
|||
|
#:*handle-function-forms*
|
|||
|
#:*handle-macro-forms*
|
|||
|
#:*types-to-ignore*
|
|||
|
#:*last-caller-tree*
|
|||
|
#:*default-graphing-mode*
|
|||
|
#:*indent-amount*
|
|||
|
#:xref-file
|
|||
|
#:xref-files
|
|||
|
#:write-callers-database-to-file
|
|||
|
#:display-database
|
|||
|
#:print-caller-trees
|
|||
|
#:make-caller-tree
|
|||
|
#:print-indented-tree
|
|||
|
#:determine-file-dependencies
|
|||
|
#:print-file-dependencies
|
|||
|
#:psgraph-xref
|
|||
|
))
|
|||
|
|
|||
|
(in-package "PXREF")
|
|||
|
|
|||
|
;;; Warn user if they're loading the source instead of compiling it first.
|
|||
|
;(eval-when (compile load eval)
|
|||
|
; (defvar compiled-p nil))
|
|||
|
;(eval-when (compile load)
|
|||
|
; (setq compiled-p t))
|
|||
|
;(eval-when (load eval)
|
|||
|
; (unless compiled-p
|
|||
|
; (warn "This file should be compiled before loading for best results.")))
|
|||
|
(eval-when (eval)
|
|||
|
(warn "This file should be compiled before loading for best results."))
|
|||
|
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Primitives *********************
|
|||
|
;;; ********************************
|
|||
|
(defun lookup (symbol environment)
|
|||
|
(dolist (frame environment)
|
|||
|
(when (member symbol frame)
|
|||
|
(return symbol))))
|
|||
|
|
|||
|
(defun car-eq (list item)
|
|||
|
(and (consp list)
|
|||
|
(eq (car list) item)))
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Callers Database ***************
|
|||
|
;;; ********************************
|
|||
|
(defvar *file-callers-database* (make-hash-table :test #'equal)
|
|||
|
"Contains name and list of file callers (files which call) for that name.")
|
|||
|
(defvar *callers-database* (make-hash-table :test #'equal)
|
|||
|
"Contains name and list of callers (function invocation) for that name.")
|
|||
|
(defvar *readers-database* (make-hash-table :test #'equal)
|
|||
|
"Contains name and list of readers (variable use) for that name.")
|
|||
|
(defvar *setters-database* (make-hash-table :test #'equal)
|
|||
|
"Contains name and list of setters (variable mutation) for that name.")
|
|||
|
(defvar *callees-database* (make-hash-table :test #'equal)
|
|||
|
"Contains name and list of functions and variables it calls.")
|
|||
|
(defun callers-list (name &optional (database :callers))
|
|||
|
(case database
|
|||
|
(:file (gethash name *file-callers-database*))
|
|||
|
(:callees (gethash name *callees-database*))
|
|||
|
(:callers (gethash name *callers-database*))
|
|||
|
(:readers (gethash name *readers-database*))
|
|||
|
(:setters (gethash name *setters-database*))))
|
|||
|
(defsetf callers-list (name &optional (database :callers)) (caller)
|
|||
|
`(setf (gethash ,name (case ,database
|
|||
|
(:file *file-callers-database*)
|
|||
|
(:callees *callees-database*)
|
|||
|
(:callers *callers-database*)
|
|||
|
(:readers *readers-database*)
|
|||
|
(:setters *setters-database*)))
|
|||
|
,caller))
|
|||
|
|
|||
|
(defun list-callers (symbol)
|
|||
|
"Lists all functions which call SYMBOL as a function (function invocation)."
|
|||
|
(callers-list symbol :callers))
|
|||
|
(defun list-readers (symbol)
|
|||
|
"Lists all functions which refer to SYMBOL as a variable
|
|||
|
(variable reference)."
|
|||
|
(callers-list symbol :readers))
|
|||
|
(defun list-setters (symbol)
|
|||
|
"Lists all functions which bind/set SYMBOL as a variable
|
|||
|
(variable mutation)."
|
|||
|
(callers-list symbol :setters))
|
|||
|
(defun list-users (symbol)
|
|||
|
"Lists all functions which use SYMBOL as a variable or function."
|
|||
|
(values (list-callers symbol)
|
|||
|
(list-readers symbol)
|
|||
|
(list-setters symbol)))
|
|||
|
(defun who-calls (symbol &optional how)
|
|||
|
"Lists callers of symbol. HOW may be :function, :reader, :setter,
|
|||
|
or :variable."
|
|||
|
;; would be nice to have :macro and distinguish variable
|
|||
|
;; binding from assignment. (i.e., variable binding, assignment, and use)
|
|||
|
(case how
|
|||
|
(:function (list-callers symbol))
|
|||
|
(:reader (list-readers symbol))
|
|||
|
(:setter (list-setters symbol))
|
|||
|
(:variable (append (list-readers symbol)
|
|||
|
(list-setters symbol)))
|
|||
|
(otherwise (append (list-callers symbol)
|
|||
|
(list-readers symbol)
|
|||
|
(list-setters symbol)))))
|
|||
|
(defun what-files-call (symbol)
|
|||
|
"Lists names of files that contain uses of SYMBOL
|
|||
|
as a function, variable, or constant."
|
|||
|
(callers-list symbol :file))
|
|||
|
(defun list-callees (symbol)
|
|||
|
"Lists names of functions and variables called by SYMBOL."
|
|||
|
(callers-list symbol :callees))
|
|||
|
|
|||
|
(defvar *source-file* (make-hash-table :test #'equal)
|
|||
|
"Contains function name and source file for that name.")
|
|||
|
(defun source-file (symbol)
|
|||
|
"Lists the names of files in which SYMBOL is defined/used."
|
|||
|
(gethash symbol *source-file*))
|
|||
|
(defsetf source-file (name) (value)
|
|||
|
`(setf (gethash ,name *source-file*) ,value))
|
|||
|
|
|||
|
(defun clear-tables ()
|
|||
|
(clrhash *file-callers-database*)
|
|||
|
(clrhash *callers-database*)
|
|||
|
(clrhash *callees-database*)
|
|||
|
(clrhash *readers-database*)
|
|||
|
(clrhash *setters-database*)
|
|||
|
(clrhash *source-file*))
|
|||
|
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Pattern Database ***************
|
|||
|
;;; ********************************
|
|||
|
;;; Pattern Types
|
|||
|
(defvar *pattern-caller-type* (make-hash-table :test #'equal))
|
|||
|
(defun pattern-caller-type (name)
|
|||
|
(gethash name *pattern-caller-type*))
|
|||
|
(defsetf pattern-caller-type (name) (value)
|
|||
|
`(setf (gethash ,name *pattern-caller-type*) ,value))
|
|||
|
|
|||
|
;;; Pattern Substitutions
|
|||
|
(defvar *pattern-substitution-table* (make-hash-table :test #'equal)
|
|||
|
"Stores general patterns for function destructuring.")
|
|||
|
(defun lookup-pattern-substitution (name)
|
|||
|
(gethash name *pattern-substitution-table*))
|
|||
|
(defmacro define-pattern-substitution (name pattern)
|
|||
|
"Defines NAME to be equivalent to the specified pattern. Useful for
|
|||
|
making patterns more readable. For example, the LAMBDA-LIST is
|
|||
|
defined as a pattern substitution, making the definition of the
|
|||
|
DEFUN caller-pattern simpler."
|
|||
|
`(setf (gethash ',name *pattern-substitution-table*)
|
|||
|
',pattern))
|
|||
|
|
|||
|
;;; Function/Macro caller patterns:
|
|||
|
;;; The car of the form is skipped, so we don't need to specify
|
|||
|
;;; (:eq function-name) like we would for a substitution.
|
|||
|
;;;
|
|||
|
;;; Patterns must be defined in the XREF package because the pattern
|
|||
|
;;; language is tested by comparing symbols (using #'equal) and not
|
|||
|
;;; their printreps. This is fine for the lisp grammer, because the XREF
|
|||
|
;;; package depends on the LISP package, so a symbol like 'xref::cons is
|
|||
|
;;; translated automatically into 'lisp::cons. However, since
|
|||
|
;;; (equal 'foo::bar 'baz::bar) returns nil unless both 'foo::bar and
|
|||
|
;;; 'baz::bar are inherited from the same package (e.g., LISP),
|
|||
|
;;; if package handling is turned on the user must specify package
|
|||
|
;;; names in the caller pattern definitions for functions that occur
|
|||
|
;;; in packages other than LISP, otherwise the symbols will not match.
|
|||
|
;;;
|
|||
|
;;; Perhaps we should enforce the definition of caller patterns in the
|
|||
|
;;; XREF package by wrapping the body of define-caller-pattern in
|
|||
|
;;; the XREF package:
|
|||
|
;;; (defmacro define-caller-pattern (name value &optional caller-type)
|
|||
|
;;; (let ((old-package *package*))
|
|||
|
;;; (setf *package* (find-package "XREF"))
|
|||
|
;;; (prog1
|
|||
|
;;; `(progn
|
|||
|
;;; (when ',caller-type
|
|||
|
;;; (setf (pattern-caller-type ',name) ',caller-type))
|
|||
|
;;; (when ',value
|
|||
|
;;; (setf (gethash ',name *caller-pattern-table*)
|
|||
|
;;; ',value)))
|
|||
|
;;; (setf *package* old-package))))
|
|||
|
;;; Either that, or for the purpose of pattern testing we should compare
|
|||
|
;;; printreps. [The latter makes the primitive patterns like VAR
|
|||
|
;;; reserved words.]
|
|||
|
(defvar *caller-pattern-table* (make-hash-table :test #'equal)
|
|||
|
"Stores patterns for function destructuring.")
|
|||
|
(defun lookup-caller-pattern (name)
|
|||
|
(gethash name *caller-pattern-table*))
|
|||
|
(defmacro define-caller-pattern (name pattern &optional caller-type)
|
|||
|
"Defines NAME as a function/macro call with argument structure
|
|||
|
described by PATTERN. CALLER-TYPE, if specified, assigns a type to
|
|||
|
the pattern, which may be used to exclude references to NAME while
|
|||
|
viewing the database. For example, all the Common Lisp definitions
|
|||
|
have a caller-type of :lisp or :lisp2, so that you can exclude
|
|||
|
references to common lisp functions from the calling tree."
|
|||
|
`(progn
|
|||
|
(when ',caller-type
|
|||
|
(setf (pattern-caller-type ',name) ',caller-type))
|
|||
|
(when ',pattern
|
|||
|
(setf (gethash ',name *caller-pattern-table*)
|
|||
|
',pattern))))
|
|||
|
|
|||
|
;;; For defining variables
|
|||
|
(defmacro define-variable-pattern (name &optional caller-type)
|
|||
|
"Defines NAME as a variable reference of type CALLER-TYPE. This is
|
|||
|
mainly used to establish the caller-type of the variable."
|
|||
|
`(progn
|
|||
|
(when ',caller-type
|
|||
|
(setf (pattern-caller-type ',name) ',caller-type))))
|
|||
|
|
|||
|
;;; For defining synonyms. Means much less space taken up by the patterns.
|
|||
|
(defmacro define-caller-pattern-synonyms (source destinations)
|
|||
|
"For defining function caller pattern syntax synonyms. For each name
|
|||
|
in DESTINATIONS, defines its pattern as a copy of the definition of SOURCE.
|
|||
|
Allows a large number of identical patterns to be defined simultaneously.
|
|||
|
Must occur after the SOURCE has been defined."
|
|||
|
`(let ((source-type (pattern-caller-type ',source))
|
|||
|
(source-pattern (gethash ',source *caller-pattern-table*)))
|
|||
|
(when source-type
|
|||
|
(dolist (dest ',destinations)
|
|||
|
(setf (pattern-caller-type dest) source-type)))
|
|||
|
(when source-pattern
|
|||
|
(dolist (dest ',destinations)
|
|||
|
(setf (gethash dest *caller-pattern-table*)
|
|||
|
source-pattern)))))
|
|||
|
|
|||
|
(defun clear-patterns ()
|
|||
|
(clrhash *pattern-substitution-table*)
|
|||
|
(clrhash *caller-pattern-table*)
|
|||
|
(clrhash *pattern-caller-type*))
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Cross Reference Files **********
|
|||
|
;;; ********************************
|
|||
|
(defvar *last-form* ()
|
|||
|
"The last form read from the file. Useful for figuring out what went wrong
|
|||
|
when xref-file drops into the debugger.")
|
|||
|
|
|||
|
(defvar *xref-verbose* t
|
|||
|
"When T, xref-file(s) prints out the names of the files it looks at,
|
|||
|
progress dots, and the number of forms read.")
|
|||
|
|
|||
|
;;; This needs to first clear the tables?
|
|||
|
(defun xref-files (&rest files)
|
|||
|
"Grovels over the lisp code located in source file FILES, using xref-file."
|
|||
|
;; If the arg is a list, use it.
|
|||
|
(when (listp (car files)) (setq files (car files)))
|
|||
|
(dolist (file files)
|
|||
|
(xref-file file nil))
|
|||
|
(values))
|
|||
|
|
|||
|
(defvar *handle-package-forms* nil ;'(lisp::in-package)
|
|||
|
"When non-NIL, and XREF-FILE sees a package-setting form like IN-PACKAGE,
|
|||
|
sets the current package to the specified package by evaluating the
|
|||
|
form. When done with the file, xref-file resets the package to its
|
|||
|
original value. In some of the displaying functions, when this variable
|
|||
|
is non-NIL one may specify that all symbols from a particular set of
|
|||
|
packages be ignored. This is only useful if the files use different
|
|||
|
packages with conflicting names.")
|
|||
|
|
|||
|
(defvar *normal-readtable* (copy-readtable nil)
|
|||
|
"Normal, unadulterated CL readtable.")
|
|||
|
|
|||
|
(defun xref-file (filename &optional (clear-tables t) (verbose *xref-verbose*))
|
|||
|
"Cross references the function and variable calls in FILENAME by
|
|||
|
walking over the source code located in the file. Defaults type of
|
|||
|
filename to \".lisp\". Chomps on the code using record-callers and
|
|||
|
record-callers*. If CLEAR-TABLES is T (the default), it clears the callers
|
|||
|
database before processing the file. Specify CLEAR-TABLES as nil to
|
|||
|
append to the database. If VERBOSE is T (the default), prints out the
|
|||
|
name of the file, one progress dot for each form processed, and the
|
|||
|
total number of forms."
|
|||
|
;; Default type to "lisp"
|
|||
|
(when (and (null (pathname-type filename))
|
|||
|
(not (probe-file filename)))
|
|||
|
(cond ((stringp filename)
|
|||
|
(setf filename (concatenate 'string filename ".lisp")))
|
|||
|
((pathnamep filename)
|
|||
|
(setf filename (merge-pathnames filename
|
|||
|
(make-pathname :type "lisp"))))))
|
|||
|
(when clear-tables (clear-tables))
|
|||
|
(let ((count 0)
|
|||
|
(old-package *package*)
|
|||
|
(*readtable* *normal-readtable*))
|
|||
|
(when verbose
|
|||
|
(format t "~&Cross-referencing file ~A.~&" filename))
|
|||
|
(with-open-file (stream filename :direction :input)
|
|||
|
(do ((form (read stream nil :eof) (read stream nil :eof)))
|
|||
|
((eq form :eof))
|
|||
|
(incf count)
|
|||
|
(when verbose
|
|||
|
(format *standard-output* ".")
|
|||
|
(force-output *standard-output*))
|
|||
|
(setq *last-form* form)
|
|||
|
(record-callers filename form)
|
|||
|
;; Package Magic.
|
|||
|
(when (and *handle-package-forms*
|
|||
|
(consp form)
|
|||
|
(member (car form) *handle-package-forms*))
|
|||
|
(eval form))))
|
|||
|
(when verbose
|
|||
|
(format t "~&~D forms processed." count))
|
|||
|
(setq *package* old-package)
|
|||
|
(values)))
|
|||
|
|
|||
|
(defvar *handle-function-forms* t
|
|||
|
"When T, XREF-FILE tries to be smart about forms which occur in
|
|||
|
a function position, such as lambdas and arbitrary Lisp forms.
|
|||
|
If so, it recursively calls record-callers with pattern 'FORM.
|
|||
|
If the form is a lambda, makes the caller a caller of :unnamed-lambda.")
|
|||
|
|
|||
|
(defvar *handle-macro-forms* t
|
|||
|
"When T, if the file was loaded before being processed by XREF, and the
|
|||
|
car of a form is a macro, it notes that the parent calls the macro,
|
|||
|
and then calls macroexpand-1 on the form.")
|
|||
|
|
|||
|
(defvar *callees-database-includes-variables* nil)
|
|||
|
|
|||
|
(defun record-callers (filename form
|
|||
|
&optional pattern parent (environment nil)
|
|||
|
funcall)
|
|||
|
"RECORD-CALLERS is the main routine used to walk down the code. It matches
|
|||
|
the PATTERN against the FORM, possibly adding statements to the database.
|
|||
|
PARENT is the name defined by the current outermost definition; it is
|
|||
|
the caller of the forms in the body (e.g., FORM). ENVIRONMENT is used
|
|||
|
to keep track of the scoping of variables. FUNCALL deals with the type
|
|||
|
of variable assignment and hence how the environment should be modified.
|
|||
|
RECORD-CALLERS handles atomic patterns and simple list-structure patterns.
|
|||
|
For complex list-structure pattern destructuring, it calls RECORD-CALLERS*."
|
|||
|
; (when form)
|
|||
|
(unless pattern (setq pattern 'FORM))
|
|||
|
(cond ((symbolp pattern)
|
|||
|
(case pattern
|
|||
|
(:IGNORE
|
|||
|
;; Ignores the rest of the form.
|
|||
|
(values t parent environment))
|
|||
|
(NAME
|
|||
|
;; This is the name of a new definition.
|
|||
|
(push filename (source-file form))
|
|||
|
(values t form environment))
|
|||
|
((FUNCTION MACRO)
|
|||
|
;; This is the name of a call.
|
|||
|
(cond ((and *handle-function-forms* (consp form))
|
|||
|
;; If we're a cons and special handling is on,
|
|||
|
(when (eq (car form) 'lambda)
|
|||
|
(pushnew filename (callers-list :unnamed-lambda :file))
|
|||
|
(when parent
|
|||
|
(pushnew parent (callers-list :unnamed-lambda
|
|||
|
:callers))
|
|||
|
(pushnew :unnamed-lambda (callers-list parent
|
|||
|
:callees))))
|
|||
|
(record-callers filename form 'form parent environment))
|
|||
|
(t
|
|||
|
;; If we're just a regular function name call.
|
|||
|
(pushnew filename (callers-list form :file))
|
|||
|
(when parent
|
|||
|
(pushnew parent (callers-list form :callers))
|
|||
|
(pushnew form (callers-list parent :callees)))
|
|||
|
(values t parent environment))))
|
|||
|
(VAR
|
|||
|
;; This is the name of a new variable definition.
|
|||
|
;; Includes arglist parameters.
|
|||
|
(when (and (symbolp form) (not (keywordp form))
|
|||
|
(not (member form lambda-list-keywords)))
|
|||
|
(pushnew form (car environment))
|
|||
|
(pushnew filename (callers-list form :file))
|
|||
|
(when parent
|
|||
|
; (pushnew form (callers-list parent :callees))
|
|||
|
(pushnew parent (callers-list form :setters)))
|
|||
|
(values t parent environment)))
|
|||
|
(VARIABLE
|
|||
|
;; VAR reference
|
|||
|
(pushnew filename (callers-list form :file))
|
|||
|
(when (and parent (not (lookup form environment)))
|
|||
|
(pushnew parent (callers-list form :readers))
|
|||
|
(when *callees-database-includes-variables*
|
|||
|
(pushnew form (callers-list parent :callees))))
|
|||
|
(values t parent environment))
|
|||
|
(FORM
|
|||
|
;; A random form (var or funcall).
|
|||
|
(cond ((consp form)
|
|||
|
;; Get new pattern from TAG.
|
|||
|
(let ((new-pattern (lookup-caller-pattern (car form))))
|
|||
|
(pushnew filename (callers-list (car form) :file))
|
|||
|
(when parent
|
|||
|
(pushnew parent (callers-list (car form) :callers))
|
|||
|
(pushnew (car form) (callers-list parent :callees)))
|
|||
|
(cond ((and new-pattern (cdr form))
|
|||
|
;; Special Pattern and there's stuff left
|
|||
|
;; to be processed. Note that we check if
|
|||
|
;; a pattern is defined for the form before
|
|||
|
;; we check to see if we can macroexpand it.
|
|||
|
(record-callers filename (cdr form) new-pattern
|
|||
|
parent environment :funcall))
|
|||
|
((and *handle-macro-forms*
|
|||
|
(symbolp (car form)) ; pnorvig 9/9/93
|
|||
|
(macro-function (car form)))
|
|||
|
;; The car of the form is a macro and
|
|||
|
;; macro processing is turned on. Macroexpand-1
|
|||
|
;; the form and try again.
|
|||
|
(record-callers filename
|
|||
|
(macroexpand-1 form)
|
|||
|
'form parent environment
|
|||
|
:funcall))
|
|||
|
((null (cdr form))
|
|||
|
;; No more left to be processed. Note that
|
|||
|
;; this must occur after the macros clause,
|
|||
|
;; since macros can expand into more code.
|
|||
|
(values t parent environment))
|
|||
|
(t
|
|||
|
;; Random Form. We assume it is a function call.
|
|||
|
(record-callers filename (cdr form)
|
|||
|
'((:star FORM))
|
|||
|
parent environment :funcall)))))
|
|||
|
(t
|
|||
|
(when (and (not (lookup form environment))
|
|||
|
(not (numberp form))
|
|||
|
;; the following line should probably be
|
|||
|
;; commented out?
|
|||
|
(not (keywordp form))
|
|||
|
(not (stringp form))
|
|||
|
(not (eq form t))
|
|||
|
(not (eq form nil)))
|
|||
|
(pushnew filename (callers-list form :file))
|
|||
|
;; ??? :callers
|
|||
|
(when parent
|
|||
|
(pushnew parent (callers-list form :readers))
|
|||
|
(when *callees-database-includes-variables*
|
|||
|
(pushnew form (callers-list parent :callees)))))
|
|||
|
(values t parent environment))))
|
|||
|
(otherwise
|
|||
|
;; Pattern Substitution
|
|||
|
(let ((new-pattern (lookup-pattern-substitution pattern)))
|
|||
|
(if new-pattern
|
|||
|
(record-callers filename form new-pattern
|
|||
|
parent environment)
|
|||
|
(when (eq pattern form)
|
|||
|
(values t parent environment)))))))
|
|||
|
((consp pattern)
|
|||
|
(case (car pattern)
|
|||
|
(:eq (when (eq (second pattern) form)
|
|||
|
(values t parent environment)))
|
|||
|
(:test (when (funcall (eval (second pattern)) form)
|
|||
|
(values t parent environment)))
|
|||
|
(:typep (when (typep form (second pattern))
|
|||
|
(values t parent environment)))
|
|||
|
(:or (dolist (subpat (rest pattern))
|
|||
|
(multiple-value-bind (processed parent environment)
|
|||
|
(record-callers filename form subpat
|
|||
|
parent environment)
|
|||
|
(when processed
|
|||
|
(return (values processed parent environment))))))
|
|||
|
(:rest ; (:star :plus :optional :rest)
|
|||
|
(record-callers filename form (second pattern)
|
|||
|
parent environment))
|
|||
|
(otherwise
|
|||
|
(multiple-value-bind (d p env)
|
|||
|
(record-callers* filename form pattern
|
|||
|
parent (cons nil environment))
|
|||
|
(values d p (if funcall environment env))))))))
|
|||
|
|
|||
|
(defun record-callers* (filename form pattern parent environment
|
|||
|
&optional continuation
|
|||
|
in-optionals in-keywords)
|
|||
|
"RECORD-CALLERS* handles complex list-structure patterns, such as
|
|||
|
ordered lists of subpatterns, patterns involving :star, :plus,
|
|||
|
&optional, &key, &rest, and so on. CONTINUATION is a stack of
|
|||
|
unprocessed patterns, IN-OPTIONALS and IN-KEYWORDS are corresponding
|
|||
|
stacks which determine whether &rest or &key has been seen yet in
|
|||
|
the current pattern."
|
|||
|
;; form must be a cons or nil.
|
|||
|
; (when form)
|
|||
|
(if (null pattern)
|
|||
|
(if (null continuation)
|
|||
|
(values t parent environment)
|
|||
|
(record-callers* filename form (car continuation) parent environment
|
|||
|
(cdr continuation)
|
|||
|
(cdr in-optionals)
|
|||
|
(cdr in-keywords)))
|
|||
|
(let ((pattern-elt (car pattern)))
|
|||
|
(cond ((car-eq pattern-elt :optional)
|
|||
|
(if (null form)
|
|||
|
(values t parent environment)
|
|||
|
(multiple-value-bind (processed par env)
|
|||
|
(record-callers* filename form (cdr pattern-elt)
|
|||
|
parent environment
|
|||
|
(cons (cdr pattern) continuation)
|
|||
|
(cons (car in-optionals) in-optionals)
|
|||
|
(cons (car in-keywords) in-keywords))
|
|||
|
(if processed
|
|||
|
(values processed par env)
|
|||
|
(record-callers* filename form (cdr pattern)
|
|||
|
parent environment continuation
|
|||
|
in-optionals in-keywords)))))
|
|||
|
((car-eq pattern-elt :star)
|
|||
|
(if (null form)
|
|||
|
(values t parent environment)
|
|||
|
(multiple-value-bind (processed par env)
|
|||
|
(record-callers* filename form (cdr pattern-elt)
|
|||
|
parent environment
|
|||
|
(cons pattern continuation)
|
|||
|
(cons (car in-optionals) in-optionals)
|
|||
|
(cons (car in-keywords) in-keywords))
|
|||
|
(if processed
|
|||
|
(values processed par env)
|
|||
|
(record-callers* filename form (cdr pattern)
|
|||
|
parent environment continuation
|
|||
|
in-optionals in-keywords)))))
|
|||
|
((car-eq pattern-elt :plus)
|
|||
|
(record-callers* filename form (cdr pattern-elt)
|
|||
|
parent environment
|
|||
|
(cons (cons (cons :star (cdr pattern-elt))
|
|||
|
(cdr pattern))
|
|||
|
continuation)
|
|||
|
(cons (car in-optionals) in-optionals)
|
|||
|
(cons (car in-keywords) in-keywords)))
|
|||
|
((car-eq pattern-elt :rest)
|
|||
|
(record-callers filename form pattern-elt parent environment))
|
|||
|
((eq pattern-elt '&optional)
|
|||
|
(record-callers* filename form (cdr pattern)
|
|||
|
parent environment continuation
|
|||
|
(cons t in-optionals)
|
|||
|
(cons (car in-keywords) in-keywords)))
|
|||
|
((eq pattern-elt '&rest)
|
|||
|
(record-callers filename form (second pattern)
|
|||
|
parent environment))
|
|||
|
((eq pattern-elt '&key)
|
|||
|
(record-callers* filename form (cdr pattern)
|
|||
|
parent environment continuation
|
|||
|
(cons (car in-optionals) in-optionals)
|
|||
|
(cons t in-keywords)))
|
|||
|
((null form)
|
|||
|
(when (or (car in-keywords) (car in-optionals))
|
|||
|
(values t parent environment)))
|
|||
|
((consp form)
|
|||
|
(multiple-value-bind (processed parent environment)
|
|||
|
(record-callers filename (if (car in-keywords)
|
|||
|
(cadr form)
|
|||
|
(car form))
|
|||
|
pattern-elt
|
|||
|
parent environment)
|
|||
|
(cond (processed
|
|||
|
(record-callers* filename (if (car in-keywords)
|
|||
|
(cddr form)
|
|||
|
(cdr form))
|
|||
|
(cdr pattern)
|
|||
|
parent environment
|
|||
|
continuation
|
|||
|
in-optionals in-keywords))
|
|||
|
((or (car in-keywords)
|
|||
|
(car in-optionals))
|
|||
|
(values t parent environment)))))))))
|
|||
|
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Misc Utilities *****************
|
|||
|
;;; ********************************
|
|||
|
(defvar *types-to-ignore*
|
|||
|
'(:lisp ; CLtL 1st Edition
|
|||
|
:lisp2 ; CLtL 2nd Edition additional patterns
|
|||
|
)
|
|||
|
"Default set of caller types (as specified in the patterns) to ignore
|
|||
|
in the database handling functions. :lisp is CLtL 1st edition,
|
|||
|
:lisp2 is additional patterns from CLtL 2nd edition.")
|
|||
|
|
|||
|
(defun display-database (&optional (database :callers)
|
|||
|
(types-to-ignore *types-to-ignore*))
|
|||
|
"Prints out the name of each symbol and all its callers. Specify database
|
|||
|
:callers (the default) to get function call references, :fill to the get
|
|||
|
files in which the symbol is called, :readers to get variable references,
|
|||
|
and :setters to get variable binding and assignments. Ignores functions
|
|||
|
of types listed in types-to-ignore."
|
|||
|
(maphash #'(lambda (name callers)
|
|||
|
(unless (or (member (pattern-caller-type name)
|
|||
|
types-to-ignore)
|
|||
|
;; When we're doing fancy package crap,
|
|||
|
;; allow us to ignore symbols based on their
|
|||
|
;; packages.
|
|||
|
(when *handle-package-forms*
|
|||
|
(member (symbol-package name)
|
|||
|
types-to-ignore
|
|||
|
:key #'find-package)))
|
|||
|
(format t "~&~S is referenced by~{ ~S~}."
|
|||
|
name callers)))
|
|||
|
(ecase database
|
|||
|
(:file *file-callers-database*)
|
|||
|
(:callers *callers-database*)
|
|||
|
(:readers *readers-database*)
|
|||
|
(:setters *setters-database*))))
|
|||
|
|
|||
|
(defun write-callers-database-to-file (filename)
|
|||
|
"Saves the contents of the current callers database to a file. This
|
|||
|
file can be loaded to restore the previous contents of the
|
|||
|
database. (For large systems it can take a long time to crunch
|
|||
|
through the code, so this can save some time.)"
|
|||
|
(with-open-file (stream filename :direction :output)
|
|||
|
(format stream "~&(clear-tables)")
|
|||
|
(maphash #'(lambda (x y)
|
|||
|
(format stream "~&(setf (source-file '~S) '~S)"
|
|||
|
x y))
|
|||
|
*source-file*)
|
|||
|
(maphash #'(lambda (x y)
|
|||
|
(format stream "~&(setf (callers-list '~S :file) '~S)"
|
|||
|
x y))
|
|||
|
*file-callers-database*)
|
|||
|
(maphash #'(lambda (x y)
|
|||
|
(format stream "~&(setf (callers-list '~S :callers) '~S)"
|
|||
|
x y))
|
|||
|
*callers-database*)
|
|||
|
(maphash #'(lambda (x y)
|
|||
|
(format stream "~&(setf (callers-list '~S :callees) '~S)"
|
|||
|
x y))
|
|||
|
*callees-database*)
|
|||
|
(maphash #'(lambda (x y)
|
|||
|
(format stream "~&(setf (callers-list '~S :readers) '~S)"
|
|||
|
x y))
|
|||
|
*readers-database*)
|
|||
|
(maphash #'(lambda (x y)
|
|||
|
(format stream "~&(setf (callers-list '~S :setters) '~S)"
|
|||
|
x y))
|
|||
|
*setters-database*)))
|
|||
|
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Print Caller Trees *************
|
|||
|
;;; ********************************
|
|||
|
;;; The following function is useful for reversing a caller table into
|
|||
|
;;; a callee table. Possibly later we'll extend xref to create two
|
|||
|
;;; such database hash tables. Needs to include vars as well.
|
|||
|
(defun invert-hash-table (table &optional (types-to-ignore *types-to-ignore*))
|
|||
|
"Makes a copy of the hash table in which (name value*) pairs
|
|||
|
are inverted to (value name*) pairs."
|
|||
|
(let ((target (make-hash-table :test #'equal)))
|
|||
|
(maphash #'(lambda (key values)
|
|||
|
(dolist (value values)
|
|||
|
(unless (member (pattern-caller-type key)
|
|||
|
types-to-ignore)
|
|||
|
(pushnew key (gethash value target)))))
|
|||
|
table)
|
|||
|
target))
|
|||
|
|
|||
|
;;; Resolve file references for automatic creation of a defsystem file.
|
|||
|
(defun determine-file-dependencies (&optional (database *callers-database*))
|
|||
|
"Makes a hash table of file dependencies for the references listed in
|
|||
|
DATABASE. This function may be useful for automatically resolving
|
|||
|
file references for automatic creation of a system definition (defsystem)."
|
|||
|
(let ((file-ref-ht (make-hash-table :test #'equal)))
|
|||
|
(maphash #'(lambda (key values)
|
|||
|
(let ((key-file (source-file key)))
|
|||
|
(when key
|
|||
|
(dolist (value values)
|
|||
|
(let ((value-file (source-file value)))
|
|||
|
(when value-file
|
|||
|
(dolist (s key-file)
|
|||
|
(dolist (d value-file)
|
|||
|
(pushnew d (gethash s file-ref-ht))))))))))
|
|||
|
database)
|
|||
|
file-ref-ht))
|
|||
|
|
|||
|
(defun print-file-dependencies (&optional (database *callers-database*))
|
|||
|
"Prints a list of file dependencies for the references listed in DATABASE.
|
|||
|
This function may be useful for automatically computing file loading
|
|||
|
constraints for a system definition tool."
|
|||
|
(maphash #'(lambda (key value) (format t "~&~S --> ~S" key value))
|
|||
|
(determine-file-dependencies database)))
|
|||
|
|
|||
|
;;; The following functions demonstrate a possible way to interface
|
|||
|
;;; xref to a graphical browser such as psgraph to mimic the capabilities
|
|||
|
;;; of Masterscope's graphical browser.
|
|||
|
|
|||
|
(defvar *last-caller-tree* nil)
|
|||
|
|
|||
|
(defvar *default-graphing-mode* :call-graph
|
|||
|
"Specifies whether we graph up or down. If :call-graph, the children
|
|||
|
of a node are the functions it calls. If :caller-graph, the children
|
|||
|
of a node are the functions that call it.")
|
|||
|
|
|||
|
(defun gather-tree (parents &optional already-seen
|
|||
|
(mode *default-graphing-mode*)
|
|||
|
(types-to-ignore *types-to-ignore*) compact)
|
|||
|
"Extends the tree, copying it into list structure, until it repeats
|
|||
|
a reference (hits a cycle)."
|
|||
|
(let ((*already-seen* nil)
|
|||
|
(database (case mode
|
|||
|
(:call-graph *callees-database*)
|
|||
|
(:caller-graph *callers-database*))))
|
|||
|
(declare (special *already-seen*))
|
|||
|
(labels
|
|||
|
((amass-tree
|
|||
|
(parents &optional already-seen)
|
|||
|
(let (result this-item)
|
|||
|
(dolist (parent parents)
|
|||
|
(unless (member (pattern-caller-type parent)
|
|||
|
types-to-ignore)
|
|||
|
(pushnew parent *already-seen*)
|
|||
|
(if (member parent already-seen)
|
|||
|
(setq this-item nil) ; :ignore
|
|||
|
(if compact
|
|||
|
(multiple-value-setq (this-item already-seen)
|
|||
|
(amass-tree (gethash parent database)
|
|||
|
(cons parent already-seen)))
|
|||
|
(setq this-item
|
|||
|
(amass-tree (gethash parent database)
|
|||
|
(cons parent already-seen)))))
|
|||
|
(setq parent (format nil "~S" parent))
|
|||
|
(when (consp parent) (setq parent (cons :xref-list parent)))
|
|||
|
(unless (eq this-item :ignore)
|
|||
|
(push (if this-item
|
|||
|
(list parent this-item)
|
|||
|
parent)
|
|||
|
result))))
|
|||
|
(values result ;(reverse result)
|
|||
|
already-seen))))
|
|||
|
(values (amass-tree parents already-seen)
|
|||
|
*already-seen*))))
|
|||
|
|
|||
|
(defun find-roots-and-cycles (&optional (mode *default-graphing-mode*)
|
|||
|
(types-to-ignore *types-to-ignore*))
|
|||
|
"Returns a list of uncalled callers (roots) and called callers (potential
|
|||
|
cycles)."
|
|||
|
(let ((uncalled-callers nil)
|
|||
|
(called-callers nil)
|
|||
|
(database (ecase mode
|
|||
|
(:call-graph *callers-database*)
|
|||
|
(:caller-graph *callees-database*)))
|
|||
|
(other-database (ecase mode
|
|||
|
(:call-graph *callees-database*)
|
|||
|
(:caller-graph *callers-database*))))
|
|||
|
(maphash #'(lambda (name value)
|
|||
|
(declare (ignore value))
|
|||
|
(unless (member (pattern-caller-type name)
|
|||
|
types-to-ignore)
|
|||
|
(if (gethash name database)
|
|||
|
(push name called-callers)
|
|||
|
(push name uncalled-callers))))
|
|||
|
other-database)
|
|||
|
(values uncalled-callers called-callers)))
|
|||
|
|
|||
|
(defun make-caller-tree (&optional (mode *default-graphing-mode*)
|
|||
|
(types-to-ignore *types-to-ignore*) compact)
|
|||
|
"Outputs list structure of a tree which roughly represents the possibly
|
|||
|
cyclical structure of the caller database.
|
|||
|
If mode is :call-graph, the children of a node are the functions it calls.
|
|||
|
If mode is :caller-graph, the children of a node are the functions that
|
|||
|
call it.
|
|||
|
If compact is T, tries to eliminate the already-seen nodes, so that
|
|||
|
the graph for a node is printed at most once. Otherwise it will duplicate
|
|||
|
the node's tree (except for cycles). This is usefull because the call tree
|
|||
|
is actually a directed graph, so we can either duplicate references or
|
|||
|
display only the first one."
|
|||
|
;; Would be nice to print out line numbers and whenever we skip a duplicated
|
|||
|
;; reference, print the line number of the full reference after the node.
|
|||
|
(multiple-value-bind (uncalled-callers called-callers)
|
|||
|
(find-roots-and-cycles mode types-to-ignore)
|
|||
|
(multiple-value-bind (trees already-seen)
|
|||
|
(gather-tree uncalled-callers nil mode types-to-ignore compact)
|
|||
|
(setq *last-caller-tree* trees)
|
|||
|
(let ((more-trees (gather-tree (set-difference called-callers
|
|||
|
already-seen)
|
|||
|
already-seen
|
|||
|
mode types-to-ignore compact)))
|
|||
|
(values trees more-trees)))))
|
|||
|
|
|||
|
(defvar *indent-amount* 3
|
|||
|
"Number of spaces to indent successive levels in PRINT-INDENTED-TREE.")
|
|||
|
|
|||
|
(defun print-indented-tree (trees &optional (indent 0))
|
|||
|
"Simple code to print out a list-structure tree (such as those created
|
|||
|
by make-caller-tree) as indented text."
|
|||
|
(when trees
|
|||
|
(dolist (tree trees)
|
|||
|
(cond ((and (listp tree) (eq (car tree) :xref-list))
|
|||
|
(format t "~&~VT~A" indent (cdr tree)))
|
|||
|
((listp tree)
|
|||
|
(format t "~&~VT~A" indent (car tree))
|
|||
|
(print-indented-tree (cadr tree) (+ indent *indent-amount*)))
|
|||
|
(t
|
|||
|
(format t "~&~VT~A" indent tree))))))
|
|||
|
|
|||
|
(defun print-caller-trees (&key (mode *default-graphing-mode*)
|
|||
|
(types-to-ignore *types-to-ignore*)
|
|||
|
compact
|
|||
|
root-nodes)
|
|||
|
"Prints the calling trees (which may actually be a full graph and not
|
|||
|
necessarily a DAG) as indented text trees using PRINT-INDENTED-TREE.
|
|||
|
MODE is :call-graph for trees where the children of a node are the
|
|||
|
functions called by the node, or :caller-graph for trees where the
|
|||
|
children of a node are the functions the node calls. TYPES-TO-IGNORE
|
|||
|
is a list of funcall types (as specified in the patterns) to ignore
|
|||
|
in printing out the database. For example, '(:lisp) would ignore all
|
|||
|
calls to common lisp functions. COMPACT is a flag to tell the program
|
|||
|
to try to compact the trees a bit by not printing trees if they have
|
|||
|
already been seen. ROOT-NODES is a list of root nodes of trees to
|
|||
|
display. If ROOT-NODES is nil, tries to find all root nodes in the
|
|||
|
database."
|
|||
|
(multiple-value-bind (rooted cycles)
|
|||
|
(if root-nodes
|
|||
|
(values (gather-tree root-nodes nil mode types-to-ignore compact))
|
|||
|
(make-caller-tree mode types-to-ignore compact))
|
|||
|
(when rooted
|
|||
|
(format t "~&Rooted calling trees:")
|
|||
|
(print-indented-tree rooted 2))
|
|||
|
(when cycles
|
|||
|
(when rooted
|
|||
|
(format t "~2%"))
|
|||
|
(format t "~&Cyclic calling trees:")
|
|||
|
(print-indented-tree cycles 2))))
|
|||
|
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Interface to PSGraph ***********
|
|||
|
;;; ********************************
|
|||
|
#|
|
|||
|
;;; Interface to Bates' PostScript Graphing Utility
|
|||
|
(load "/afs/cs/user/mkant/Lisp/PSGraph/psgraph")
|
|||
|
|
|||
|
(defparameter *postscript-output-directory* "")
|
|||
|
(defun psgraph-xref (&key (mode *default-graphing-mode*)
|
|||
|
(output-directory *postscript-output-directory*)
|
|||
|
(types-to-ignore *types-to-ignore*)
|
|||
|
(compact t)
|
|||
|
(shrink t)
|
|||
|
root-nodes
|
|||
|
insert)
|
|||
|
;; If root-nodes is a non-nil list, uses that list as the starting
|
|||
|
;; position. Otherwise tries to find all roots in the database.
|
|||
|
(multiple-value-bind (rooted cycles)
|
|||
|
(if root-nodes
|
|||
|
(values (gather-tree root-nodes nil mode types-to-ignore compact))
|
|||
|
(make-caller-tree mode types-to-ignore compact))
|
|||
|
(psgraph-output (append rooted cycles) output-directory shrink insert)))
|
|||
|
|
|||
|
(defun psgraph-output (list-of-trees directory shrink &optional insert)
|
|||
|
(let ((psgraph:*fontsize* 9)
|
|||
|
(psgraph:*second-fontsize* 7)
|
|||
|
; (psgraph:*boxkind* "fill")
|
|||
|
(psgraph:*boxgray* "0") ; .8
|
|||
|
(psgraph:*edgewidth* "1")
|
|||
|
(psgraph:*edgegray* "0"))
|
|||
|
(labels ((stringify (thing)
|
|||
|
(cond ((stringp thing) (string-downcase thing))
|
|||
|
((symbolp thing) (string-downcase (symbol-name thing)))
|
|||
|
((and (listp thing) (eq (car thing) :xref-list))
|
|||
|
(stringify (cdr thing)))
|
|||
|
((listp thing) (stringify (car thing)))
|
|||
|
(t (string thing)))))
|
|||
|
(dolist (item list-of-trees)
|
|||
|
(let* ((fname (stringify item))
|
|||
|
(filename (concatenate 'string directory
|
|||
|
(string-trim '(#\: #\|) fname)
|
|||
|
".ps")))
|
|||
|
(format t "~&Creating PostScript file ~S." filename)
|
|||
|
(with-open-file (*standard-output* filename
|
|||
|
:direction :output
|
|||
|
:if-does-not-exist :create
|
|||
|
:if-exists :supersede)
|
|||
|
;; Note that the #'eq prints the DAG as a tree. If
|
|||
|
;; you replace it with #'equal, it will print it as
|
|||
|
;; a DAG, which I think is slightly ugly.
|
|||
|
(psgraph:psgraph item
|
|||
|
#'caller-tree-children #'caller-info shrink
|
|||
|
insert #'eq)))))))
|
|||
|
|
|||
|
(defun caller-tree-children (tree)
|
|||
|
(when (and tree (listp tree) (not (eq (car tree) :xref-list)))
|
|||
|
(cadr tree)))
|
|||
|
|
|||
|
(defun caller-tree-node (tree)
|
|||
|
(when tree
|
|||
|
(cond ((and (listp tree) (eq (car tree) :xref-list))
|
|||
|
(cdr tree))
|
|||
|
((listp tree)
|
|||
|
(car tree))
|
|||
|
(t
|
|||
|
tree))))
|
|||
|
|
|||
|
(defun caller-info (tree)
|
|||
|
(let ((node (caller-tree-node tree)))
|
|||
|
(list node)))
|
|||
|
|#
|
|||
|
#|
|
|||
|
;;; Code to print out graphical trees of CLOS class hierarchies.
|
|||
|
(defun print-class-hierarchy (&optional (start-class 'anything)
|
|||
|
(file "classes.ps"))
|
|||
|
(let ((start (find-class start-class)))
|
|||
|
(when start
|
|||
|
(with-open-file (*standard-output* file :direction :output)
|
|||
|
(psgraph:psgraph start
|
|||
|
#'clos::class-direct-subclasses
|
|||
|
#'(lambda (x)
|
|||
|
(list (format nil "~A" (clos::class-name x))))
|
|||
|
t nil #'eq)))))
|
|||
|
|
|||
|
|#
|
|||
|
|
|||
|
|
|||
|
;;; ****************************************************************
|
|||
|
;;; Cross Referencing Patterns for Common Lisp *********************
|
|||
|
;;; ****************************************************************
|
|||
|
(clear-patterns)
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Pattern Substitutions **********
|
|||
|
;;; ********************************
|
|||
|
(define-pattern-substitution integer (:test #'integerp))
|
|||
|
(define-pattern-substitution rational (:test #'rationalp))
|
|||
|
(define-pattern-substitution symbol (:test #'symbolp))
|
|||
|
(define-pattern-substitution string (:test #'stringp))
|
|||
|
(define-pattern-substitution number (:test #'numberp))
|
|||
|
(define-pattern-substitution lambda-list
|
|||
|
((:star var)
|
|||
|
(:optional (:eq &optional)
|
|||
|
(:star (:or var
|
|||
|
(var (:optional form (:optional var))))))
|
|||
|
(:optional (:eq &rest) var)
|
|||
|
(:optional (:eq &key) (:star (:or var
|
|||
|
((:or var
|
|||
|
(keyword var))
|
|||
|
(:optional form (:optional var)))))
|
|||
|
(:optional &allow-other-keys))
|
|||
|
(:optional (:eq &aux)
|
|||
|
(:star (:or var
|
|||
|
(var (:optional form)))))))
|
|||
|
(define-pattern-substitution test form)
|
|||
|
(define-pattern-substitution body
|
|||
|
((:star (:or declaration documentation-string))
|
|||
|
(:star form)))
|
|||
|
(define-pattern-substitution documentation-string string)
|
|||
|
(define-pattern-substitution initial-value form)
|
|||
|
(define-pattern-substitution tag symbol)
|
|||
|
(define-pattern-substitution declaration ((:eq declare)(:rest :ignore)))
|
|||
|
(define-pattern-substitution destination form)
|
|||
|
(define-pattern-substitution control-string string)
|
|||
|
(define-pattern-substitution format-arguments
|
|||
|
((:star form)))
|
|||
|
(define-pattern-substitution fn
|
|||
|
(:or ((:eq quote) function)
|
|||
|
((:eq function) function)
|
|||
|
function))
|
|||
|
|
|||
|
;;; ********************************
|
|||
|
;;; Caller Patterns ****************
|
|||
|
;;; ********************************
|
|||
|
|
|||
|
;;; Types Related
|
|||
|
(define-caller-pattern coerce (form :ignore) :lisp)
|
|||
|
(define-caller-pattern type-of (form) :lisp)
|
|||
|
(define-caller-pattern upgraded-array-element-type (:ignore) :lisp2)
|
|||
|
(define-caller-pattern upgraded-complex-part-type (:ignore) :lisp2)
|
|||
|
|
|||
|
;;; Lambdas and Definitions
|
|||
|
(define-variable-pattern lambda-list-keywords :lisp)
|
|||
|
(define-variable-pattern lambda-parameters-limit :lisp)
|
|||
|
(define-caller-pattern lambda (lambda-list (:rest body)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern defun
|
|||
|
(name lambda-list
|
|||
|
(:star (:or documentation-string declaration))
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
|
|||
|
;;; perhaps this should use VAR, instead of NAME
|
|||
|
(define-caller-pattern defvar
|
|||
|
(var (:optional initial-value (:optional documentation-string)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern defparameter
|
|||
|
(var initial-value (:optional documentation-string))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern defconstant
|
|||
|
(var initial-value (:optional documentation-string))
|
|||
|
:lisp)
|
|||
|
|
|||
|
(define-caller-pattern eval-when
|
|||
|
(:ignore ; the situations
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
|
|||
|
;;; Logical Values
|
|||
|
(define-variable-pattern nil :lisp)
|
|||
|
(define-variable-pattern t :lisp)
|
|||
|
|
|||
|
;;; Predicates
|
|||
|
(define-caller-pattern typep (form form) :lisp)
|
|||
|
(define-caller-pattern subtypep (form form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern null (form) :lisp)
|
|||
|
(define-caller-pattern symbolp (form) :lisp)
|
|||
|
(define-caller-pattern atom (form) :lisp)
|
|||
|
(define-caller-pattern consp (form) :lisp)
|
|||
|
(define-caller-pattern listp (form) :lisp)
|
|||
|
(define-caller-pattern numberp (form) :lisp)
|
|||
|
(define-caller-pattern integerp (form) :lisp)
|
|||
|
(define-caller-pattern rationalp (form) :lisp)
|
|||
|
(define-caller-pattern floatp (form) :lisp)
|
|||
|
(define-caller-pattern realp (form) :lisp2)
|
|||
|
(define-caller-pattern complexp (form) :lisp)
|
|||
|
(define-caller-pattern characterp (form) :lisp)
|
|||
|
(define-caller-pattern stringp (form) :lisp)
|
|||
|
(define-caller-pattern bit-vector-p (form) :lisp)
|
|||
|
(define-caller-pattern vectorp (form) :lisp)
|
|||
|
(define-caller-pattern simple-vector-p (form) :lisp)
|
|||
|
(define-caller-pattern simple-string-p (form) :lisp)
|
|||
|
(define-caller-pattern simple-bit-vector-p (form) :lisp)
|
|||
|
(define-caller-pattern arrayp (form) :lisp)
|
|||
|
(define-caller-pattern packagep (form) :lisp)
|
|||
|
(define-caller-pattern functionp (form) :lisp)
|
|||
|
(define-caller-pattern compiled-function-p (form) :lisp)
|
|||
|
(define-caller-pattern commonp (form) :lisp)
|
|||
|
|
|||
|
;;; Equality Predicates
|
|||
|
(define-caller-pattern eq (form form) :lisp)
|
|||
|
(define-caller-pattern eql (form form) :lisp)
|
|||
|
(define-caller-pattern equal (form form) :lisp)
|
|||
|
(define-caller-pattern equalp (form form) :lisp)
|
|||
|
|
|||
|
;;; Logical Operators
|
|||
|
(define-caller-pattern not (form) :lisp)
|
|||
|
(define-caller-pattern or ((:star form)) :lisp)
|
|||
|
(define-caller-pattern and ((:star form)) :lisp)
|
|||
|
|
|||
|
;;; Reference
|
|||
|
|
|||
|
;;; Quote is a problem. In Defmacro & friends, we'd like to actually
|
|||
|
;;; look at the argument, 'cause it hides internal function calls
|
|||
|
;;; of the defmacro.
|
|||
|
(define-caller-pattern quote (:ignore) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern function ((:or fn form)) :lisp)
|
|||
|
(define-caller-pattern symbol-value (form) :lisp)
|
|||
|
(define-caller-pattern symbol-function (form) :lisp)
|
|||
|
(define-caller-pattern fdefinition (form) :lisp2)
|
|||
|
(define-caller-pattern boundp (form) :lisp)
|
|||
|
(define-caller-pattern fboundp (form) :lisp)
|
|||
|
(define-caller-pattern special-form-p (form) :lisp)
|
|||
|
|
|||
|
;;; Assignment
|
|||
|
(define-caller-pattern setq ((:star var form)) :lisp)
|
|||
|
(define-caller-pattern psetq ((:star var form)) :lisp)
|
|||
|
(define-caller-pattern set (form form) :lisp)
|
|||
|
(define-caller-pattern makunbound (form) :lisp)
|
|||
|
(define-caller-pattern fmakunbound (form) :lisp)
|
|||
|
|
|||
|
;;; Generalized Variables
|
|||
|
(define-caller-pattern setf ((:star form form)) :lisp)
|
|||
|
(define-caller-pattern psetf ((:star form form)) :lisp)
|
|||
|
(define-caller-pattern shiftf ((:plus form) form) :lisp)
|
|||
|
(define-caller-pattern rotatef ((:star form)) :lisp)
|
|||
|
(define-caller-pattern define-modify-macro
|
|||
|
(name
|
|||
|
lambda-list
|
|||
|
fn
|
|||
|
(:optional documentation-string))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern defsetf
|
|||
|
(:or (name name (:optional documentation-string))
|
|||
|
(name lambda-list (var)
|
|||
|
(:star (:or declaration documentation-string))
|
|||
|
(:star form)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern define-setf-method
|
|||
|
(name lambda-list
|
|||
|
(:star (:or declaration documentation-string))
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern get-setf-method (form) :lisp)
|
|||
|
(define-caller-pattern get-setf-method-multiple-value (form) :lisp)
|
|||
|
|
|||
|
|
|||
|
;;; Function invocation
|
|||
|
(define-caller-pattern apply (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern funcall (fn (:star form)) :lisp)
|
|||
|
|
|||
|
|
|||
|
;;; Simple sequencing
|
|||
|
(define-caller-pattern progn ((:star form)) :lisp)
|
|||
|
(define-caller-pattern prog1 (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern prog2 (form form (:star form)) :lisp)
|
|||
|
|
|||
|
;;; Variable bindings
|
|||
|
(define-caller-pattern let
|
|||
|
(((:star (:or var (var &optional form))))
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern let*
|
|||
|
(((:star (:or var (var &optional form))))
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern compiler-let
|
|||
|
(((:star (:or var (var form))))
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern progv
|
|||
|
(form form (:star form)) :lisp)
|
|||
|
(define-caller-pattern flet
|
|||
|
(((:star (name lambda-list
|
|||
|
(:star (:or declaration
|
|||
|
documentation-string))
|
|||
|
(:star form))))
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern labels
|
|||
|
(((:star (name lambda-list
|
|||
|
(:star (:or declaration
|
|||
|
documentation-string))
|
|||
|
(:star form))))
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern macrolet
|
|||
|
(((:star (name lambda-list
|
|||
|
(:star (:or declaration
|
|||
|
documentation-string))
|
|||
|
(:star form))))
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern symbol-macrolet
|
|||
|
(((:star (var form))) (:star declaration) (:star form))
|
|||
|
:lisp2)
|
|||
|
|
|||
|
;;; Conditionals
|
|||
|
(define-caller-pattern if (test form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern when (test (:star form)) :lisp)
|
|||
|
(define-caller-pattern unless (test (:star form)) :lisp)
|
|||
|
(define-caller-pattern cond ((:star (test (:star form)))) :lisp)
|
|||
|
(define-caller-pattern case
|
|||
|
(form
|
|||
|
(:star ((:or symbol
|
|||
|
((:star symbol)))
|
|||
|
(:star form))))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern typecase (form (:star (symbol (:star form))))
|
|||
|
:lisp)
|
|||
|
|
|||
|
;;; Blocks and Exits
|
|||
|
(define-caller-pattern block (name (:star form)) :lisp)
|
|||
|
(define-caller-pattern return-from (function (:optional form)) :lisp)
|
|||
|
(define-caller-pattern return ((:optional form)) :lisp)
|
|||
|
|
|||
|
;;; Iteration
|
|||
|
(define-caller-pattern loop ((:star form)) :lisp)
|
|||
|
(define-caller-pattern do
|
|||
|
(((:star (:or var
|
|||
|
(var (:optional form (:optional form)))))) ; init step
|
|||
|
(form (:star form)) ; end-test result
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form))) ; statement
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern do*
|
|||
|
(((:star (:or var
|
|||
|
(var (:optional form (:optional form))))))
|
|||
|
(form (:star form))
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern dolist
|
|||
|
((var form (:optional form))
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern dotimes
|
|||
|
((var form (:optional form))
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form)))
|
|||
|
:lisp)
|
|||
|
|
|||
|
;;; Mapping
|
|||
|
(define-caller-pattern mapcar (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern maplist (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern mapc (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern mapl (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern mapcan (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern mapcon (fn form (:star form)) :lisp)
|
|||
|
|
|||
|
;;; The "Program Feature"
|
|||
|
(define-caller-pattern tagbody ((:star (:or tag form))) :lisp)
|
|||
|
(define-caller-pattern prog
|
|||
|
(((:star (:or var (var (:optional form)))))
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern prog*
|
|||
|
(((:star (:or var (var (:optional form)))))
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern go (tag) :lisp)
|
|||
|
|
|||
|
;;; Multiple Values
|
|||
|
(define-caller-pattern values ((:star form)) :lisp)
|
|||
|
(define-variable-pattern multiple-values-limit :lisp)
|
|||
|
(define-caller-pattern values-list (form) :lisp)
|
|||
|
(define-caller-pattern multiple-value-list (form) :lisp)
|
|||
|
(define-caller-pattern multiple-value-call (fn (:star form)) :lisp)
|
|||
|
(define-caller-pattern multiple-value-prog1 (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern multiple-value-bind
|
|||
|
(((:star var)) form
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern multiple-value-setq (((:star var)) form) :lisp)
|
|||
|
(define-caller-pattern nth-value (form form) :lisp2)
|
|||
|
|
|||
|
;;; Dynamic Non-Local Exits
|
|||
|
(define-caller-pattern catch (tag (:star form)) :lisp)
|
|||
|
(define-caller-pattern throw (tag form) :lisp)
|
|||
|
(define-caller-pattern unwind-protect (form (:star form)) :lisp)
|
|||
|
|
|||
|
;;; Macros
|
|||
|
(define-caller-pattern macro-function (form) :lisp)
|
|||
|
(define-caller-pattern defmacro
|
|||
|
(name
|
|||
|
lambda-list
|
|||
|
(:star (:or declaration documentation-string))
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern macroexpand (form (:optional :ignore)) :lisp)
|
|||
|
(define-caller-pattern macroexpand-1 (form (:optional :ignore)) :lisp)
|
|||
|
(define-variable-pattern *macroexpand-hook* :lisp)
|
|||
|
|
|||
|
;;; Destructuring
|
|||
|
(define-caller-pattern destructuring-bind
|
|||
|
(lambda-list form
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
|
|||
|
;;; Compiler Macros
|
|||
|
(define-caller-pattern define-compiler-macro
|
|||
|
(name lambda-list
|
|||
|
(:star (:or declaration documentation-string))
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern compiler-macro-function (form) :lisp2)
|
|||
|
(define-caller-pattern compiler-macroexpand (form (:optional :ignore)) :lisp2)
|
|||
|
(define-caller-pattern compiler-macroexpand-1 (form (:optional :ignore))
|
|||
|
:lisp2)
|
|||
|
|
|||
|
;;; Environments
|
|||
|
(define-caller-pattern variable-information (form &optional :ignore)
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern function-information (fn &optional :ignore) :lisp2)
|
|||
|
(define-caller-pattern declaration-information (form &optional :ignore) :lisp2)
|
|||
|
(define-caller-pattern augment-environment (form &key (:star :ignore)) :lisp2)
|
|||
|
(define-caller-pattern define-declaration
|
|||
|
(name
|
|||
|
lambda-list
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern parse-macro (name lambda-list form) :lisp2)
|
|||
|
(define-caller-pattern enclose (form &optional :ignore) :lisp2)
|
|||
|
|
|||
|
|
|||
|
;;; Declarations
|
|||
|
(define-caller-pattern declare ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern proclaim ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern locally ((:star declaration) (:star form)) :lisp)
|
|||
|
(define-caller-pattern declaim ((:rest :ignore)) :lisp2)
|
|||
|
(define-caller-pattern the (form form) :lisp)
|
|||
|
|
|||
|
;;; Symbols
|
|||
|
(define-caller-pattern get (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern remprop (form form) :lisp)
|
|||
|
(define-caller-pattern symbol-plist (form) :lisp)
|
|||
|
(define-caller-pattern getf (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern remf (form form) :lisp)
|
|||
|
(define-caller-pattern get-properties (form form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern symbol-name (form) :lisp)
|
|||
|
(define-caller-pattern make-symbol (form) :lisp)
|
|||
|
(define-caller-pattern copy-symbol (form (:optional :ignore)) :lisp)
|
|||
|
(define-caller-pattern gensym ((:optional :ignore)) :lisp)
|
|||
|
(define-variable-pattern *gensym-counter* :lisp2)
|
|||
|
(define-caller-pattern gentemp ((:optional :ignore :ignore)) :lisp)
|
|||
|
(define-caller-pattern symbol-package (form) :lisp)
|
|||
|
(define-caller-pattern keywordp (form) :lisp)
|
|||
|
|
|||
|
;;; Packages
|
|||
|
(define-variable-pattern *package* :lisp)
|
|||
|
(define-caller-pattern make-package ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern in-package ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern find-package ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern package-name ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern package-nicknames ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern rename-package ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern package-use-list ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern package-used-by-list ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern package-shadowing-symbols ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern list-all-packages () :lisp)
|
|||
|
(define-caller-pattern delete-package ((:rest :ignore)) :lisp2)
|
|||
|
(define-caller-pattern intern (form &optional :ignore) :lisp)
|
|||
|
(define-caller-pattern find-symbol (form &optional :ignore) :lisp)
|
|||
|
(define-caller-pattern unintern (form &optional :ignore) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern export ((:or symbol ((:star symbol)))
|
|||
|
&optional :ignore) :lisp)
|
|||
|
(define-caller-pattern unexport ((:or symbol ((:star symbol)))
|
|||
|
&optional :ignore) :lisp)
|
|||
|
(define-caller-pattern import ((:or symbol ((:star symbol)))
|
|||
|
&optional :ignore) :lisp)
|
|||
|
(define-caller-pattern shadowing-import ((:or symbol ((:star symbol)))
|
|||
|
&optional :ignore) :lisp)
|
|||
|
(define-caller-pattern shadow ((:or symbol ((:star symbol)))
|
|||
|
&optional :ignore) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern use-package ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern unuse-package ((:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern defpackage (name (:rest :ignore)) :lisp2)
|
|||
|
(define-caller-pattern find-all-symbols (form) :lisp)
|
|||
|
(define-caller-pattern do-symbols
|
|||
|
((var (:optional form (:optional form)))
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern do-external-symbols
|
|||
|
((var (:optional form (:optional form)))
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern do-all-symbols
|
|||
|
((var (:optional form))
|
|||
|
(:star declaration)
|
|||
|
(:star (:or tag form)))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern with-package-iterator
|
|||
|
((name form (:plus :ignore))
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
|
|||
|
;;; Modules
|
|||
|
(define-variable-pattern *modules* :lisp)
|
|||
|
(define-caller-pattern provide (form) :lisp)
|
|||
|
(define-caller-pattern require (form &optional :ignore) :lisp)
|
|||
|
|
|||
|
|
|||
|
;;; Numbers
|
|||
|
(define-caller-pattern zerop (form) :lisp)
|
|||
|
(define-caller-pattern plusp (form) :lisp)
|
|||
|
(define-caller-pattern minusp (form) :lisp)
|
|||
|
(define-caller-pattern oddp (form) :lisp)
|
|||
|
(define-caller-pattern evenp (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern = (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern /= (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern > (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern < (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern <= (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern >= (form (:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern max (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern min (form (:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern - (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern + (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern * (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern / (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern 1+ (form) :lisp)
|
|||
|
(define-caller-pattern 1- (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern incf (form form) :lisp)
|
|||
|
(define-caller-pattern decf (form form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern conjugate (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern gcd ((:star form)) :lisp)
|
|||
|
(define-caller-pattern lcm ((:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern exp (form) :lisp)
|
|||
|
(define-caller-pattern expt (form form) :lisp)
|
|||
|
(define-caller-pattern log (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern sqrt (form) :lisp)
|
|||
|
(define-caller-pattern isqrt (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern abs (form) :lisp)
|
|||
|
(define-caller-pattern phase (form) :lisp)
|
|||
|
(define-caller-pattern signum (form) :lisp)
|
|||
|
(define-caller-pattern sin (form) :lisp)
|
|||
|
(define-caller-pattern cos (form) :lisp)
|
|||
|
(define-caller-pattern tan (form) :lisp)
|
|||
|
(define-caller-pattern cis (form) :lisp)
|
|||
|
(define-caller-pattern asin (form) :lisp)
|
|||
|
(define-caller-pattern acos (form) :lisp)
|
|||
|
(define-caller-pattern atan (form &optional form) :lisp)
|
|||
|
(define-variable-pattern pi :lisp)
|
|||
|
|
|||
|
(define-caller-pattern sinh (form) :lisp)
|
|||
|
(define-caller-pattern cosh (form) :lisp)
|
|||
|
(define-caller-pattern tanh (form) :lisp)
|
|||
|
(define-caller-pattern asinh (form) :lisp)
|
|||
|
(define-caller-pattern acosh (form) :lisp)
|
|||
|
(define-caller-pattern atanh (form) :lisp)
|
|||
|
|
|||
|
;;; Type Conversions and Extractions
|
|||
|
(define-caller-pattern float (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern rational (form) :lisp)
|
|||
|
(define-caller-pattern rationalize (form) :lisp)
|
|||
|
(define-caller-pattern numerator (form) :lisp)
|
|||
|
(define-caller-pattern denominator (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern floor (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern ceiling (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern truncate (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern round (form (:optional form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern mod (form form) :lisp)
|
|||
|
(define-caller-pattern rem (form form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern ffloor (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern fceiling (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern ftruncate (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern fround (form (:optional form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern decode-float (form) :lisp)
|
|||
|
(define-caller-pattern scale-float (form form) :lisp)
|
|||
|
(define-caller-pattern float-radix (form) :lisp)
|
|||
|
(define-caller-pattern float-sign (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern float-digits (form) :lisp)
|
|||
|
(define-caller-pattern float-precision (form) :lisp)
|
|||
|
(define-caller-pattern integer-decode-float (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern complex (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern realpart (form) :lisp)
|
|||
|
(define-caller-pattern imagpart (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern logior ((:star form)) :lisp)
|
|||
|
(define-caller-pattern logxor ((:star form)) :lisp)
|
|||
|
(define-caller-pattern logand ((:star form)) :lisp)
|
|||
|
(define-caller-pattern logeqv ((:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern lognand (form form) :lisp)
|
|||
|
(define-caller-pattern lognor (form form) :lisp)
|
|||
|
(define-caller-pattern logandc1 (form form) :lisp)
|
|||
|
(define-caller-pattern logandc2 (form form) :lisp)
|
|||
|
(define-caller-pattern logorc1 (form form) :lisp)
|
|||
|
(define-caller-pattern logorc2 (form form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern boole (form form form) :lisp)
|
|||
|
(define-variable-pattern boole-clr :lisp)
|
|||
|
(define-variable-pattern boole-set :lisp)
|
|||
|
(define-variable-pattern boole-1 :lisp)
|
|||
|
(define-variable-pattern boole-2 :lisp)
|
|||
|
(define-variable-pattern boole-c1 :lisp)
|
|||
|
(define-variable-pattern boole-c2 :lisp)
|
|||
|
(define-variable-pattern boole-and :lisp)
|
|||
|
(define-variable-pattern boole-ior :lisp)
|
|||
|
(define-variable-pattern boole-xor :lisp)
|
|||
|
(define-variable-pattern boole-eqv :lisp)
|
|||
|
(define-variable-pattern boole-nand :lisp)
|
|||
|
(define-variable-pattern boole-nor :lisp)
|
|||
|
(define-variable-pattern boole-andc1 :lisp)
|
|||
|
(define-variable-pattern boole-andc2 :lisp)
|
|||
|
(define-variable-pattern boole-orc1 :lisp)
|
|||
|
(define-variable-pattern boole-orc2 :lisp)
|
|||
|
|
|||
|
(define-caller-pattern lognot (form) :lisp)
|
|||
|
(define-caller-pattern logtest (form form) :lisp)
|
|||
|
(define-caller-pattern logbitp (form form) :lisp)
|
|||
|
(define-caller-pattern ash (form form) :lisp)
|
|||
|
(define-caller-pattern logcount (form) :lisp)
|
|||
|
(define-caller-pattern integer-length (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern byte (form form) :lisp)
|
|||
|
(define-caller-pattern byte-size (form) :lisp)
|
|||
|
(define-caller-pattern byte-position (form) :lisp)
|
|||
|
(define-caller-pattern ldb (form form) :lisp)
|
|||
|
(define-caller-pattern ldb-test (form form) :lisp)
|
|||
|
(define-caller-pattern mask-field (form form) :lisp)
|
|||
|
(define-caller-pattern dpb (form form form) :lisp)
|
|||
|
(define-caller-pattern deposit-field (form form form) :lisp)
|
|||
|
|
|||
|
;;; Random Numbers
|
|||
|
(define-caller-pattern random (form (:optional form)) :lisp)
|
|||
|
(define-variable-pattern *random-state* :lisp)
|
|||
|
(define-caller-pattern make-random-state ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern random-state-p (form) :lisp)
|
|||
|
|
|||
|
;;; Implementation Parameters
|
|||
|
(define-variable-pattern most-positive-fixnum :lisp)
|
|||
|
(define-variable-pattern most-negative-fixnum :lisp)
|
|||
|
(define-variable-pattern most-positive-short-float :lisp)
|
|||
|
(define-variable-pattern least-positive-short-float :lisp)
|
|||
|
(define-variable-pattern least-negative-short-float :lisp)
|
|||
|
(define-variable-pattern most-negative-short-float :lisp)
|
|||
|
(define-variable-pattern most-positive-single-float :lisp)
|
|||
|
(define-variable-pattern least-positive-single-float :lisp)
|
|||
|
(define-variable-pattern least-negative-single-float :lisp)
|
|||
|
(define-variable-pattern most-negative-single-float :lisp)
|
|||
|
(define-variable-pattern most-positive-double-float :lisp)
|
|||
|
(define-variable-pattern least-positive-double-float :lisp)
|
|||
|
(define-variable-pattern least-negative-double-float :lisp)
|
|||
|
(define-variable-pattern most-negative-double-float :lisp)
|
|||
|
(define-variable-pattern most-positive-long-float :lisp)
|
|||
|
(define-variable-pattern least-positive-long-float :lisp)
|
|||
|
(define-variable-pattern least-negative-long-float :lisp)
|
|||
|
(define-variable-pattern most-negative-long-float :lisp)
|
|||
|
(define-variable-pattern least-positive-normalized-short-float :lisp2)
|
|||
|
(define-variable-pattern least-negative-normalized-short-float :lisp2)
|
|||
|
(define-variable-pattern least-positive-normalized-single-float :lisp2)
|
|||
|
(define-variable-pattern least-negative-normalized-single-float :lisp2)
|
|||
|
(define-variable-pattern least-positive-normalized-double-float :lisp2)
|
|||
|
(define-variable-pattern least-negative-normalized-double-float :lisp2)
|
|||
|
(define-variable-pattern least-positive-normalized-long-float :lisp2)
|
|||
|
(define-variable-pattern least-negative-normalized-long-float :lisp2)
|
|||
|
(define-variable-pattern short-float-epsilon :lisp)
|
|||
|
(define-variable-pattern single-float-epsilon :lisp)
|
|||
|
(define-variable-pattern double-float-epsilon :lisp)
|
|||
|
(define-variable-pattern long-float-epsilon :lisp)
|
|||
|
(define-variable-pattern short-float-negative-epsilon :lisp)
|
|||
|
(define-variable-pattern single-float-negative-epsilon :lisp)
|
|||
|
(define-variable-pattern double-float-negative-epsilon :lisp)
|
|||
|
(define-variable-pattern long-float-negative-epsilon :lisp)
|
|||
|
|
|||
|
;;; Characters
|
|||
|
(define-variable-pattern char-code-limit :lisp)
|
|||
|
(define-variable-pattern char-font-limit :lisp)
|
|||
|
(define-variable-pattern char-bits-limit :lisp)
|
|||
|
(define-caller-pattern standard-char-p (form) :lisp)
|
|||
|
(define-caller-pattern graphic-char-p (form) :lisp)
|
|||
|
(define-caller-pattern string-char-p (form) :lisp)
|
|||
|
(define-caller-pattern alpha-char-p (form) :lisp)
|
|||
|
(define-caller-pattern upper-case-p (form) :lisp)
|
|||
|
(define-caller-pattern lower-case-p (form) :lisp)
|
|||
|
(define-caller-pattern both-case-p (form) :lisp)
|
|||
|
(define-caller-pattern digit-char-p (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern alphanumericp (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern char= ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char/= ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char< ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char> ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char<= ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char>= ((:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern char-equal ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char-not-equal ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char-lessp ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char-greaterp ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char-not-greaterp ((:star form)) :lisp)
|
|||
|
(define-caller-pattern char-not-lessp ((:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern char-code (form) :lisp)
|
|||
|
(define-caller-pattern char-bits (form) :lisp)
|
|||
|
(define-caller-pattern char-font (form) :lisp)
|
|||
|
(define-caller-pattern code-char (form (:optional form form)) :lisp)
|
|||
|
(define-caller-pattern make-char (form (:optional form form)) :lisp)
|
|||
|
(define-caller-pattern characterp (form) :lisp)
|
|||
|
(define-caller-pattern char-upcase (form) :lisp)
|
|||
|
(define-caller-pattern char-downcase (form) :lisp)
|
|||
|
(define-caller-pattern digit-char (form (:optional form form)) :lisp)
|
|||
|
(define-caller-pattern char-int (form) :lisp)
|
|||
|
(define-caller-pattern int-char (form) :lisp)
|
|||
|
(define-caller-pattern char-name (form) :lisp)
|
|||
|
(define-caller-pattern name-char (form) :lisp)
|
|||
|
(define-variable-pattern char-control-bit :lisp)
|
|||
|
(define-variable-pattern char-meta-bit :lisp)
|
|||
|
(define-variable-pattern char-super-bit :lisp)
|
|||
|
(define-variable-pattern char-hyper-bit :lisp)
|
|||
|
(define-caller-pattern char-bit (form form) :lisp)
|
|||
|
(define-caller-pattern set-char-bit (form form form) :lisp)
|
|||
|
|
|||
|
;;; Sequences
|
|||
|
(define-caller-pattern complement (fn) :lisp2)
|
|||
|
(define-caller-pattern elt (form form) :lisp)
|
|||
|
(define-caller-pattern subseq (form form &optional form) :lisp)
|
|||
|
(define-caller-pattern copy-seq (form) :lisp)
|
|||
|
(define-caller-pattern length (form) :lisp)
|
|||
|
(define-caller-pattern reverse (form) :lisp)
|
|||
|
(define-caller-pattern nreverse (form) :lisp)
|
|||
|
(define-caller-pattern make-sequence (form form &key form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern concatenate (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern map (form fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern map-into (form fn (:star form)) :lisp2)
|
|||
|
|
|||
|
(define-caller-pattern some (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern every (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern notany (fn form (:star form)) :lisp)
|
|||
|
(define-caller-pattern notevery (fn form (:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern reduce (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern fill (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern replace (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern remove (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern remove-if (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern remove-if-not (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern delete (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern delete-if (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern delete-if-not (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern remove-duplicates (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern delete-duplicates (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern substitute (form form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern substitute-if (form fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern substitute-if-not (form fn form &key (:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern nsubstitute (form form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nsubstitute-if (form fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nsubstitute-if-not (form fn form &key (:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern find (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern find-if (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern find-if-not (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern position (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern position-if (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern position-if-not (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern count (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern count-if (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern count-if-not (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern mismatch (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern search (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern sort (form fn &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern stable-sort (form fn &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern merge (form form form fn &key (:star form)) :lisp)
|
|||
|
|
|||
|
;;; Lists
|
|||
|
(define-caller-pattern car (form) :lisp)
|
|||
|
(define-caller-pattern cdr (form) :lisp)
|
|||
|
(define-caller-pattern caar (form) :lisp)
|
|||
|
(define-caller-pattern cadr (form) :lisp)
|
|||
|
(define-caller-pattern cdar (form) :lisp)
|
|||
|
(define-caller-pattern cddr (form) :lisp)
|
|||
|
(define-caller-pattern caaar (form) :lisp)
|
|||
|
(define-caller-pattern caadr (form) :lisp)
|
|||
|
(define-caller-pattern cadar (form) :lisp)
|
|||
|
(define-caller-pattern caddr (form) :lisp)
|
|||
|
(define-caller-pattern cdaar (form) :lisp)
|
|||
|
(define-caller-pattern cdadr (form) :lisp)
|
|||
|
(define-caller-pattern cddar (form) :lisp)
|
|||
|
(define-caller-pattern cdddr (form) :lisp)
|
|||
|
(define-caller-pattern caaaar (form) :lisp)
|
|||
|
(define-caller-pattern caaadr (form) :lisp)
|
|||
|
(define-caller-pattern caadar (form) :lisp)
|
|||
|
(define-caller-pattern caaddr (form) :lisp)
|
|||
|
(define-caller-pattern cadaar (form) :lisp)
|
|||
|
(define-caller-pattern cadadr (form) :lisp)
|
|||
|
(define-caller-pattern caddar (form) :lisp)
|
|||
|
(define-caller-pattern cadddr (form) :lisp)
|
|||
|
(define-caller-pattern cdaaar (form) :lisp)
|
|||
|
(define-caller-pattern cdaadr (form) :lisp)
|
|||
|
(define-caller-pattern cdadar (form) :lisp)
|
|||
|
(define-caller-pattern cdaddr (form) :lisp)
|
|||
|
(define-caller-pattern cddaar (form) :lisp)
|
|||
|
(define-caller-pattern cddadr (form) :lisp)
|
|||
|
(define-caller-pattern cdddar (form) :lisp)
|
|||
|
(define-caller-pattern cddddr (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern cons (form form) :lisp)
|
|||
|
(define-caller-pattern tree-equal (form form &key (:star fn)) :lisp)
|
|||
|
(define-caller-pattern endp (form) :lisp)
|
|||
|
(define-caller-pattern list-length (form) :lisp)
|
|||
|
(define-caller-pattern nth (form form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern first (form) :lisp)
|
|||
|
(define-caller-pattern second (form) :lisp)
|
|||
|
(define-caller-pattern third (form) :lisp)
|
|||
|
(define-caller-pattern fourth (form) :lisp)
|
|||
|
(define-caller-pattern fifth (form) :lisp)
|
|||
|
(define-caller-pattern sixth (form) :lisp)
|
|||
|
(define-caller-pattern seventh (form) :lisp)
|
|||
|
(define-caller-pattern eighth (form) :lisp)
|
|||
|
(define-caller-pattern ninth (form) :lisp)
|
|||
|
(define-caller-pattern tenth (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern rest (form) :lisp)
|
|||
|
(define-caller-pattern nthcdr (form form) :lisp)
|
|||
|
(define-caller-pattern last (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern list ((:star form)) :lisp)
|
|||
|
(define-caller-pattern list* ((:star form)) :lisp)
|
|||
|
(define-caller-pattern make-list (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern append ((:star form)) :lisp)
|
|||
|
(define-caller-pattern copy-list (form) :lisp)
|
|||
|
(define-caller-pattern copy-alist (form) :lisp)
|
|||
|
(define-caller-pattern copy-tree (form) :lisp)
|
|||
|
(define-caller-pattern revappend (form form) :lisp)
|
|||
|
(define-caller-pattern nconc ((:star form)) :lisp)
|
|||
|
(define-caller-pattern nreconc (form form) :lisp)
|
|||
|
(define-caller-pattern push (form form) :lisp)
|
|||
|
(define-caller-pattern pushnew (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern pop (form) :lisp)
|
|||
|
(define-caller-pattern butlast (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern nbutlast (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern ldiff (form form) :lisp)
|
|||
|
(define-caller-pattern rplaca (form form) :lisp)
|
|||
|
(define-caller-pattern rplacd (form form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern subst (form form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern subst-if (form fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern subst-if-not (form fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nsubst (form form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nsubst-if (form fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nsubst-if-not (form fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern sublis (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nsublis (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern member (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern member-if (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern member-if-not (fn form &key (:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern tailp (form form) :lisp)
|
|||
|
(define-caller-pattern adjoin (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern union (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nunion (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern intersection (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nintersection (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern set-difference (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nset-difference (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern set-exclusive-or (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nset-exclusive-or (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern subsetp (form form &key (:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern acons (form form form) :lisp)
|
|||
|
(define-caller-pattern pairlis (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern assoc (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern assoc-if (fn form) :lisp)
|
|||
|
(define-caller-pattern assoc-if-not (fn form) :lisp)
|
|||
|
(define-caller-pattern rassoc (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern rassoc-if (fn form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern rassoc-if-not (fn form &key (:star form)) :lisp)
|
|||
|
|
|||
|
;;; Hash Tables
|
|||
|
(define-caller-pattern make-hash-table (&key (:star form)) :lisp)
|
|||
|
(define-caller-pattern hash-table-p (form) :lisp)
|
|||
|
(define-caller-pattern gethash (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern remhash (form form) :lisp)
|
|||
|
(define-caller-pattern maphash (fn form) :lisp)
|
|||
|
(define-caller-pattern clrhash (form) :lisp)
|
|||
|
(define-caller-pattern hash-table-count (form) :lisp)
|
|||
|
(define-caller-pattern with-hash-table-iterator
|
|||
|
((name form) (:star form)) :lisp2)
|
|||
|
(define-caller-pattern hash-table-rehash-size (form) :lisp2)
|
|||
|
(define-caller-pattern hash-table-rehash-threshold (form) :lisp2)
|
|||
|
(define-caller-pattern hash-table-size (form) :lisp2)
|
|||
|
(define-caller-pattern hash-table-test (form) :lisp2)
|
|||
|
(define-caller-pattern sxhash (form) :lisp)
|
|||
|
|
|||
|
;;; Arrays
|
|||
|
(define-caller-pattern make-array (form &key (:star form)) :lisp)
|
|||
|
(define-variable-pattern array-rank-limit :lisp)
|
|||
|
(define-variable-pattern array-dimension-limit :lisp)
|
|||
|
(define-variable-pattern array-total-size-limit :lisp)
|
|||
|
(define-caller-pattern vector ((:star form)) :lisp)
|
|||
|
(define-caller-pattern aref (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern svref (form form) :lisp)
|
|||
|
(define-caller-pattern array-element-type (form) :lisp)
|
|||
|
(define-caller-pattern array-rank (form) :lisp)
|
|||
|
(define-caller-pattern array-dimension (form form) :lisp)
|
|||
|
(define-caller-pattern array-dimensions (form) :lisp)
|
|||
|
(define-caller-pattern array-total-size (form) :lisp)
|
|||
|
(define-caller-pattern array-in-bounds-p (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern array-row-major-index (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern row-major-aref (form form) :lisp2)
|
|||
|
(define-caller-pattern adjustable-array-p (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern bit (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern sbit (form (:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern bit-and (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-ior (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-xor (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-eqv (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-nand (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-nor (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-andc1 (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-andc2 (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-orc1 (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-orc2 (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern bit-not (form (:optional form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern array-has-fill-pointer-p (form) :lisp)
|
|||
|
(define-caller-pattern fill-pointer (form) :lisp)
|
|||
|
(define-caller-pattern vector-push (form form) :lisp)
|
|||
|
(define-caller-pattern vector-push-extend (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern vector-pop (form) :lisp)
|
|||
|
(define-caller-pattern adjust-array (form form &key (:star form)) :lisp)
|
|||
|
|
|||
|
;;; Strings
|
|||
|
(define-caller-pattern char (form form) :lisp)
|
|||
|
(define-caller-pattern schar (form form) :lisp)
|
|||
|
(define-caller-pattern string= (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-equal (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string< (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string> (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string<= (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string>= (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string/= (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-lessp (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-greaterp (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-not-greaterp (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-not-lessp (form form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-not-equal (form form &key (:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern make-string (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-trim (form form) :lisp)
|
|||
|
(define-caller-pattern string-left-trim (form form) :lisp)
|
|||
|
(define-caller-pattern string-right-trim (form form) :lisp)
|
|||
|
(define-caller-pattern string-upcase (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-downcase (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string-capitalize (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nstring-upcase (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nstring-downcase (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern nstring-capitalize (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern string (form) :lisp)
|
|||
|
|
|||
|
;;; Structures
|
|||
|
(define-caller-pattern defstruct
|
|||
|
((:or name (name (:rest :ignore)))
|
|||
|
(:optional documentation-string)
|
|||
|
(:plus :ignore))
|
|||
|
:lisp)
|
|||
|
|
|||
|
;;; The Evaluator
|
|||
|
(define-caller-pattern eval (form) :lisp)
|
|||
|
(define-variable-pattern *evalhook* :lisp)
|
|||
|
(define-variable-pattern *applyhook* :lisp)
|
|||
|
(define-caller-pattern evalhook (form fn fn &optional :ignore) :lisp)
|
|||
|
(define-caller-pattern applyhook (fn form fn fn &optional :ignore) :lisp)
|
|||
|
(define-caller-pattern constantp (form) :lisp)
|
|||
|
|
|||
|
;;; Streams
|
|||
|
(define-variable-pattern *standard-input* :lisp)
|
|||
|
(define-variable-pattern *standard-output* :lisp)
|
|||
|
(define-variable-pattern *error-output* :lisp)
|
|||
|
(define-variable-pattern *query-io* :lisp)
|
|||
|
(define-variable-pattern *debug-io* :lisp)
|
|||
|
(define-variable-pattern *terminal-io* :lisp)
|
|||
|
(define-variable-pattern *trace-output* :lisp)
|
|||
|
(define-caller-pattern make-synonym-stream (symbol) :lisp)
|
|||
|
(define-caller-pattern make-broadcast-stream ((:star form)) :lisp)
|
|||
|
(define-caller-pattern make-concatenated-stream ((:star form)) :lisp)
|
|||
|
(define-caller-pattern make-two-way-stream (form form) :lisp)
|
|||
|
(define-caller-pattern make-echo-stream (form form) :lisp)
|
|||
|
(define-caller-pattern make-string-input-stream (form &optional form form)
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern make-string-output-stream (&key (:star form)) :lisp)
|
|||
|
(define-caller-pattern get-output-stream-string (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern with-open-stream
|
|||
|
((var form)
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
|
|||
|
(define-caller-pattern with-input-from-string
|
|||
|
((var form &key (:star form))
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
|
|||
|
(define-caller-pattern with-output-to-string
|
|||
|
((var (:optional form))
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern streamp (form) :lisp)
|
|||
|
(define-caller-pattern open-stream-p (form) :lisp2)
|
|||
|
(define-caller-pattern input-stream-p (form) :lisp)
|
|||
|
(define-caller-pattern output-stream-p (form) :lisp)
|
|||
|
(define-caller-pattern stream-element-type (form) :lisp)
|
|||
|
(define-caller-pattern close (form (:rest :ignore)) :lisp)
|
|||
|
(define-caller-pattern broadcast-stream-streams (form) :lisp2)
|
|||
|
(define-caller-pattern concatenated-stream-streams (form) :lisp2)
|
|||
|
(define-caller-pattern echo-stream-input-stream (form) :lisp2)
|
|||
|
(define-caller-pattern echo-stream-output-stream (form) :lisp2)
|
|||
|
(define-caller-pattern synonym-stream-symbol (form) :lisp2)
|
|||
|
(define-caller-pattern two-way-stream-input-stream (form) :lisp2)
|
|||
|
(define-caller-pattern two-way-stream-output-stream (form) :lisp2)
|
|||
|
(define-caller-pattern interactive-stream-p (form) :lisp2)
|
|||
|
(define-caller-pattern stream-external-format (form) :lisp2)
|
|||
|
|
|||
|
;;; Reader
|
|||
|
(define-variable-pattern *read-base* :lisp)
|
|||
|
(define-variable-pattern *read-suppress* :lisp)
|
|||
|
(define-variable-pattern *read-eval* :lisp2)
|
|||
|
(define-variable-pattern *readtable* :lisp)
|
|||
|
(define-caller-pattern copy-readtable (&optional form form) :lisp)
|
|||
|
(define-caller-pattern readtablep (form) :lisp)
|
|||
|
(define-caller-pattern set-syntax-from-char (form form &optional form form)
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern set-macro-character (form fn &optional form) :lisp)
|
|||
|
(define-caller-pattern get-macro-character (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern make-dispatch-macro-character (form &optional form form)
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern set-dispatch-macro-character
|
|||
|
(form form fn (:optional form)) :lisp)
|
|||
|
(define-caller-pattern get-dispatch-macro-character
|
|||
|
(form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern readtable-case (form) :lisp2)
|
|||
|
(define-variable-pattern *print-readably* :lisp2)
|
|||
|
(define-variable-pattern *print-escape* :lisp)
|
|||
|
(define-variable-pattern *print-pretty* :lisp)
|
|||
|
(define-variable-pattern *print-circle* :lisp)
|
|||
|
(define-variable-pattern *print-base* :lisp)
|
|||
|
(define-variable-pattern *print-radix* :lisp)
|
|||
|
(define-variable-pattern *print-case* :lisp)
|
|||
|
(define-variable-pattern *print-gensym* :lisp)
|
|||
|
(define-variable-pattern *print-level* :lisp)
|
|||
|
(define-variable-pattern *print-length* :lisp)
|
|||
|
(define-variable-pattern *print-array* :lisp)
|
|||
|
(define-caller-pattern with-standard-io-syntax
|
|||
|
((:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
|
|||
|
(define-caller-pattern read (&optional form form form form) :lisp)
|
|||
|
(define-variable-pattern *read-default-float-format* :lisp)
|
|||
|
(define-caller-pattern read-preserving-whitespace
|
|||
|
(&optional form form form form) :lisp)
|
|||
|
(define-caller-pattern read-delimited-list (form &optional form form) :lisp)
|
|||
|
(define-caller-pattern read-line (&optional form form form form) :lisp)
|
|||
|
(define-caller-pattern read-char (&optional form form form form) :lisp)
|
|||
|
(define-caller-pattern unread-char (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern peek-char (&optional form form form form) :lisp)
|
|||
|
(define-caller-pattern listen ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern read-char-no-hang ((:star form)) :lisp)
|
|||
|
(define-caller-pattern clear-input ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern read-from-string (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern parse-integer (form &rest :ignore) :lisp)
|
|||
|
(define-caller-pattern read-byte ((:star form)) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern write (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern prin1 (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern print (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern pprint (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern princ (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern write-to-string (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern prin1-to-string (form) :lisp)
|
|||
|
(define-caller-pattern princ-to-string (form) :lisp)
|
|||
|
(define-caller-pattern write-char (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern write-string (form &optional form &key (:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern write-line (form &optional form &key (:star form))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern terpri ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern fresh-line ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern finish-output ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern force-output ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern clear-output ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern print-unreadable-object
|
|||
|
((form form &key (:star form))
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern write-byte (form form) :lisp)
|
|||
|
(define-caller-pattern format
|
|||
|
(destination
|
|||
|
control-string
|
|||
|
(:rest format-arguments))
|
|||
|
:lisp)
|
|||
|
|
|||
|
(define-caller-pattern y-or-n-p (control-string (:star form)) :lisp)
|
|||
|
(define-caller-pattern yes-or-no-p (control-string (:star form)) :lisp)
|
|||
|
|
|||
|
;;; Pathnames
|
|||
|
(define-caller-pattern wild-pathname-p (form &optional form) :lisp2)
|
|||
|
(define-caller-pattern pathname-match-p (form form) :lisp2)
|
|||
|
(define-caller-pattern translate-pathname (form form form &key (:star form))
|
|||
|
:lisp2)
|
|||
|
|
|||
|
(define-caller-pattern logical-pathname (form) :lisp2)
|
|||
|
(define-caller-pattern translate-logical-pathname (form &key (:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern logical-pathname-translations (form) :lisp2)
|
|||
|
(define-caller-pattern load-logical-pathname-translations (form) :lisp2)
|
|||
|
(define-caller-pattern compile-file-pathname (form &key form) :lisp2)
|
|||
|
|
|||
|
(define-caller-pattern pathname (form) :lisp)
|
|||
|
(define-caller-pattern truename (form) :lisp)
|
|||
|
(define-caller-pattern parse-namestring ((:star form)) :lisp)
|
|||
|
(define-caller-pattern merge-pathnames ((:star form)) :lisp)
|
|||
|
(define-variable-pattern *default-pathname-defaults* :lisp)
|
|||
|
(define-caller-pattern make-pathname ((:star form)) :lisp)
|
|||
|
(define-caller-pattern pathnamep (form) :lisp)
|
|||
|
(define-caller-pattern pathname-host (form) :lisp)
|
|||
|
(define-caller-pattern pathname-device (form) :lisp)
|
|||
|
(define-caller-pattern pathname-directory (form) :lisp)
|
|||
|
(define-caller-pattern pathname-name (form) :lisp)
|
|||
|
(define-caller-pattern pathname-type (form) :lisp)
|
|||
|
(define-caller-pattern pathname-version (form) :lisp)
|
|||
|
(define-caller-pattern namestring (form) :lisp)
|
|||
|
(define-caller-pattern file-namestring (form) :lisp)
|
|||
|
(define-caller-pattern directory-namestring (form) :lisp)
|
|||
|
(define-caller-pattern host-namestring (form) :lisp)
|
|||
|
(define-caller-pattern enough-namestring (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern user-homedir-pathname (&optional form) :lisp)
|
|||
|
(define-caller-pattern open (form &key (:star form)) :lisp)
|
|||
|
(define-caller-pattern with-open-file
|
|||
|
((var form (:rest :ignore))
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp)
|
|||
|
|
|||
|
(define-caller-pattern rename-file (form form) :lisp)
|
|||
|
(define-caller-pattern delete-file (form) :lisp)
|
|||
|
(define-caller-pattern probe-file (form) :lisp)
|
|||
|
(define-caller-pattern file-write-date (form) :lisp)
|
|||
|
(define-caller-pattern file-author (form) :lisp)
|
|||
|
(define-caller-pattern file-position (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern file-length (form) :lisp)
|
|||
|
(define-caller-pattern file-string-length (form form) :lisp2)
|
|||
|
(define-caller-pattern load (form &key (:star form)) :lisp)
|
|||
|
(define-variable-pattern *load-verbose* :lisp)
|
|||
|
(define-variable-pattern *load-print* :lisp2)
|
|||
|
(define-variable-pattern *load-pathname* :lisp2)
|
|||
|
(define-variable-pattern *load-truename* :lisp2)
|
|||
|
(define-caller-pattern make-load-form (form) :lisp2)
|
|||
|
(define-caller-pattern make-load-form-saving-slots (form &optional form)
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern directory (form &key (:star form)) :lisp)
|
|||
|
|
|||
|
;;; Errors
|
|||
|
(define-caller-pattern error (form (:star form)) :lisp)
|
|||
|
(define-caller-pattern cerror (form form (:star form)) :lisp)
|
|||
|
(define-caller-pattern warn (form (:star form)) :lisp)
|
|||
|
(define-variable-pattern *break-on-warnings* :lisp)
|
|||
|
(define-caller-pattern break (&optional form (:star form)) :lisp)
|
|||
|
(define-caller-pattern check-type (form form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern assert
|
|||
|
(form
|
|||
|
(:optional ((:star var))
|
|||
|
(:optional form (:star form))))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern etypecase (form (:star (symbol (:star form)))) :lisp)
|
|||
|
(define-caller-pattern ctypecase (form (:star (symbol (:star form)))) :lisp)
|
|||
|
(define-caller-pattern ecase
|
|||
|
(form
|
|||
|
(:star ((:or symbol ((:star symbol)))
|
|||
|
(:star form))))
|
|||
|
:lisp)
|
|||
|
(define-caller-pattern ccase
|
|||
|
(form
|
|||
|
(:star ((:or symbol ((:star symbol)))
|
|||
|
(:star form))))
|
|||
|
:lisp)
|
|||
|
|
|||
|
;;; The Compiler
|
|||
|
(define-caller-pattern compile (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern compile-file (form &key (:star form)) :lisp)
|
|||
|
(define-variable-pattern *compile-verbose* :lisp2)
|
|||
|
(define-variable-pattern *compile-print* :lisp2)
|
|||
|
(define-variable-pattern *compile-file-pathname* :lisp2)
|
|||
|
(define-variable-pattern *compile-file-truename* :lisp2)
|
|||
|
(define-caller-pattern load-time-value (form (:optional form)) :lisp2)
|
|||
|
(define-caller-pattern disassemble (form) :lisp)
|
|||
|
(define-caller-pattern function-lambda-expression (fn) :lisp2)
|
|||
|
(define-caller-pattern with-compilation-unit (((:star :ignore)) (:star form))
|
|||
|
:lisp2)
|
|||
|
|
|||
|
;;; Documentation
|
|||
|
(define-caller-pattern documentation (form form) :lisp)
|
|||
|
(define-caller-pattern trace ((:star form)) :lisp)
|
|||
|
(define-caller-pattern untrace ((:star form)) :lisp)
|
|||
|
(define-caller-pattern step (form) :lisp)
|
|||
|
(define-caller-pattern time (form) :lisp)
|
|||
|
(define-caller-pattern describe (form &optional form) :lisp)
|
|||
|
(define-caller-pattern describe-object (form &optional form) :lisp2)
|
|||
|
(define-caller-pattern inspect (form) :lisp)
|
|||
|
(define-caller-pattern room ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern ed ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern dribble ((:optional form)) :lisp)
|
|||
|
(define-caller-pattern apropos (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern apropos-list (form (:optional form)) :lisp)
|
|||
|
(define-caller-pattern get-decoded-time () :lisp)
|
|||
|
(define-caller-pattern get-universal-time () :lisp)
|
|||
|
(define-caller-pattern decode-universal-time (form &optional form) :lisp)
|
|||
|
(define-caller-pattern encode-universal-time
|
|||
|
(form form form form form form &optional form) :lisp)
|
|||
|
(define-caller-pattern get-internal-run-time () :lisp)
|
|||
|
(define-caller-pattern get-internal-real-time () :lisp)
|
|||
|
(define-caller-pattern sleep (form) :lisp)
|
|||
|
|
|||
|
(define-caller-pattern lisp-implementation-type () :lisp)
|
|||
|
(define-caller-pattern lisp-implementation-version () :lisp)
|
|||
|
(define-caller-pattern machine-type () :lisp)
|
|||
|
(define-caller-pattern machine-version () :lisp)
|
|||
|
(define-caller-pattern machine-instance () :lisp)
|
|||
|
(define-caller-pattern software-type () :lisp)
|
|||
|
(define-caller-pattern software-version () :lisp)
|
|||
|
(define-caller-pattern short-site-name () :lisp)
|
|||
|
(define-caller-pattern long-site-name () :lisp)
|
|||
|
(define-variable-pattern *features* :lisp)
|
|||
|
|
|||
|
(define-caller-pattern identity (form) :lisp)
|
|||
|
|
|||
|
;;; Pretty Printing
|
|||
|
(define-variable-pattern *print-pprint-dispatch* :lisp2)
|
|||
|
(define-variable-pattern *print-right-margin* :lisp2)
|
|||
|
(define-variable-pattern *print-miser-width* :lisp2)
|
|||
|
(define-variable-pattern *print-lines* :lisp2)
|
|||
|
(define-caller-pattern pprint-newline (form &optional form) :lisp2)
|
|||
|
(define-caller-pattern pprint-logical-block
|
|||
|
((var form &key (:star form))
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern pprint-exit-if-list-exhausted () :lisp2)
|
|||
|
(define-caller-pattern pprint-pop () :lisp2)
|
|||
|
(define-caller-pattern pprint-indent (form form &optional form) :lisp2)
|
|||
|
(define-caller-pattern pprint-tab (form form form &optional form) :lisp2)
|
|||
|
(define-caller-pattern pprint-fill (form form &optional form form) :lisp2)
|
|||
|
(define-caller-pattern pprint-linear (form form &optional form form) :lisp2)
|
|||
|
(define-caller-pattern pprint-tabular (form form &optional form form form)
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern formatter (control-string) :lisp2)
|
|||
|
(define-caller-pattern copy-pprint-dispatch (&optional form) :lisp2)
|
|||
|
(define-caller-pattern pprint-dispatch (form &optional form) :lisp2)
|
|||
|
(define-caller-pattern set-pprint-dispatch (form form &optional form form)
|
|||
|
:lisp2)
|
|||
|
|
|||
|
;;; CLOS
|
|||
|
(define-caller-pattern add-method (fn form) :lisp2)
|
|||
|
(define-caller-pattern call-method (form form) :lisp2)
|
|||
|
(define-caller-pattern call-next-method ((:star form)) :lisp2)
|
|||
|
(define-caller-pattern change-class (form form) :lisp2)
|
|||
|
(define-caller-pattern class-name (form) :lisp2)
|
|||
|
(define-caller-pattern class-of (form) :lisp2)
|
|||
|
(define-caller-pattern compute-applicable-methods (fn (:star form)) :lisp2)
|
|||
|
(define-caller-pattern defclass (name &rest :ignore) :lisp2)
|
|||
|
(define-caller-pattern defgeneric (name lambda-list &rest :ignore) :lisp2)
|
|||
|
(define-caller-pattern define-method-combination
|
|||
|
(name lambda-list ((:star :ignore))
|
|||
|
(:optional ((:eq :arguments) :ignore))
|
|||
|
(:optional ((:eq :generic-function) :ignore))
|
|||
|
(:star (:or declaration documentation-string))
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern defmethod
|
|||
|
(name (:star symbol) lambda-list
|
|||
|
(:star (:or declaration documentation-string))
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern ensure-generic-function (name &key (:star form)) :lisp2)
|
|||
|
(define-caller-pattern find-class (form &optional form form) :lisp2)
|
|||
|
(define-caller-pattern find-method (fn &rest :ignore) :lisp2)
|
|||
|
(define-caller-pattern function-keywords (&rest :ignore) :lisp2)
|
|||
|
(define-caller-pattern generic-flet (((:star (name lambda-list))) (:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern generic-labels
|
|||
|
(((:star (name lambda-list))) (:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern generic-function (lambda-list) :lisp2)
|
|||
|
(define-caller-pattern initialize-instance (form &key (:star form)) :lisp2)
|
|||
|
(define-caller-pattern invalid-method-error (fn form (:star form)) :lisp2)
|
|||
|
(define-caller-pattern make-instance (fn (:star form)) :lisp2)
|
|||
|
(define-caller-pattern make-instances-obsolete (fn) :lisp2)
|
|||
|
(define-caller-pattern method-combination-error (form (:star form)) :lisp2)
|
|||
|
(define-caller-pattern method-qualifiers (fn) :lisp2)
|
|||
|
(define-caller-pattern next-method-p () :lisp2)
|
|||
|
(define-caller-pattern no-applicable-method (fn (:star form)) :lisp2)
|
|||
|
(define-caller-pattern no-next-method (fn (:star form)) :lisp2)
|
|||
|
(define-caller-pattern print-object (form form) :lisp2)
|
|||
|
(define-caller-pattern reinitialize-instance (form (:star form)) :lisp2)
|
|||
|
(define-caller-pattern remove-method (fn form) :lisp2)
|
|||
|
(define-caller-pattern shared-initialize (form form (:star form)) :lisp2)
|
|||
|
(define-caller-pattern slot-boundp (form form) :lisp2)
|
|||
|
(define-caller-pattern slot-exists-p (form form) :lisp2)
|
|||
|
(define-caller-pattern slot-makeunbound (form form) :lisp2)
|
|||
|
(define-caller-pattern slot-missing (fn form form form &optional form) :lisp2)
|
|||
|
(define-caller-pattern slot-unbound (fn form form) :lisp2)
|
|||
|
(define-caller-pattern slot-value (form form) :lisp2)
|
|||
|
(define-caller-pattern update-instance-for-different-class
|
|||
|
(form form (:star form)) :lisp2)
|
|||
|
(define-caller-pattern update-instance-for-redefined-class
|
|||
|
(form form (:star form)) :lisp2)
|
|||
|
(define-caller-pattern with-accessors
|
|||
|
(((:star :ignore)) form
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern with-added-methods
|
|||
|
((name lambda-list) form
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern with-slots
|
|||
|
(((:star :ignore)) form
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
|
|||
|
;;; Conditions
|
|||
|
(define-caller-pattern signal (form (:star form)) :lisp2)
|
|||
|
(define-variable-pattern *break-on-signals* :lisp2)
|
|||
|
(define-caller-pattern handler-case (form (:star (form ((:optional var))
|
|||
|
(:star form))))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern ignore-errors ((:star form)) :lisp2)
|
|||
|
(define-caller-pattern handler-bind (((:star (form form)))
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern define-condition (name &rest :ignore) :lisp2)
|
|||
|
(define-caller-pattern make-condition (form &rest :ignore) :lisp2)
|
|||
|
(define-caller-pattern with-simple-restart
|
|||
|
((name form (:star form)) (:star form)) :lisp2)
|
|||
|
(define-caller-pattern restart-case
|
|||
|
(form
|
|||
|
(:star (form form (:star form))))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern restart-bind
|
|||
|
(((:star (name fn &key (:star form))))
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern with-condition-restarts
|
|||
|
(form form
|
|||
|
(:star declaration)
|
|||
|
(:star form))
|
|||
|
:lisp2)
|
|||
|
(define-caller-pattern compute-restarts (&optional form) :lisp2)
|
|||
|
(define-caller-pattern restart-name (form) :lisp2)
|
|||
|
(define-caller-pattern find-restart (form &optional form) :lisp2)
|
|||
|
(define-caller-pattern invoke-restart (form (:star form)) :lisp2)
|
|||
|
(define-caller-pattern invoke-restart-interactively (form) :lisp2)
|
|||
|
(define-caller-pattern abort (&optional form) :lisp2)
|
|||
|
(define-caller-pattern continue (&optional form) :lisp2)
|
|||
|
(define-caller-pattern muffle-warning (&optional form) :lisp2)
|
|||
|
(define-caller-pattern store-value (form &optional form) :lisp2)
|
|||
|
(define-caller-pattern use-value (form &optional form) :lisp2)
|
|||
|
(define-caller-pattern invoke-debugger (form) :lisp2)
|
|||
|
(define-variable-pattern *debugger-hook* :lisp2)
|
|||
|
(define-caller-pattern simple-condition-format-string (form) :lisp2)
|
|||
|
(define-caller-pattern simple-condition-format-arguments (form) :lisp2)
|
|||
|
(define-caller-pattern type-error-datum (form) :lisp2)
|
|||
|
(define-caller-pattern type-error-expected-type (form) :lisp2)
|
|||
|
(define-caller-pattern package-error-package (form) :lisp2)
|
|||
|
(define-caller-pattern stream-error-stream (form) :lisp2)
|
|||
|
(define-caller-pattern file-error-pathname (form) :lisp2)
|
|||
|
(define-caller-pattern cell-error-name (form) :lisp2)
|
|||
|
(define-caller-pattern arithmetic-error-operation (form) :lisp2)
|
|||
|
(define-caller-pattern arithmetic-error-operands (form) :lisp2)
|
|||
|
|
|||
|
;;; For ZetaLisp Flavors
|
|||
|
(define-caller-pattern send (form fn (:star form)) :flavors)
|