From: Mitch Berkson
Subject: Getting list of functions and macros in a file
Date: 
Message-ID: <zfYyj.9774$QC.10@newsfe20.lga>
Is there a nice way to get a list of the functions and macros defined in 
a file?  Or in a package?

Mitch Berkson

From: Matthias Benkard
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <4205e2f4-7cd5-4351-915b-5e1a9216dfd0@d4g2000prg.googlegroups.com>
Hi,

For packages, you can use DO-SYMBOLS/DO-EXTERNAL-SYMBOLS/DO-ALL-
SYMBOLS:

  (let ((functions (list))
        (macros (list)))
    (do-symbols (symbol package)
      (when (fboundp symbol)
        (if (macro-function symbol)
            (push symbol macros)
            (push symbol functions))))
    (values functions macros))

~ Matthias
From: Mitch Berkson
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <tWZyj.22771$y05.22099@newsfe22.lga>
Thanks. I added a test to exclude inherited functions and macros.

(defun functions-and-macros (&optional (package *package*))
   "Returns all function and macros internal or external to package. Does
not return those inherited by package"
   (let ((functions (list))
         (macros (list)))
     (do-symbols (symbol package)
       (when (fboundp symbol)
         (multiple-value-bind (sym status)
             (find-symbol symbol package)
           (declare (ignore sym))
           (when (not (eql status :inherited))
             (if (macro-function symbol)
               (push symbol macros)
               (push symbol functions))))))
     (values functions macros)))

Mitch

Matthias Benkard wrote:
> Hi,
> 
> For packages, you can use DO-SYMBOLS/DO-EXTERNAL-SYMBOLS/DO-ALL-
> SYMBOLS:
> 
>   (let ((functions (list))
>         (macros (list)))
>     (do-symbols (symbol package)
>       (when (fboundp symbol)
>         (if (macro-function symbol)
>             (push symbol macros)
>             (push symbol functions))))
>     (values functions macros))
> 
> ~ Matthias
From: Ken Tilton
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <47cc8f37$0$5650$607ed4bc@cv.net>
You might find something here:

   http://common-lisp.net/project/cldoc/index.html

Maybe the group remembers something similar? I just have a vague 
recollection of some tool and I am not sure the above is it.

Speaking of the above... nice design! Man, I'd be up to $4.71 with a 
look like that.

kenny

\\\\\ This reply brought to you by Budweiser, the King of Beers. /////

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Holger Schauer
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <yxz4pbm67j8.fsf@gmx.de>
On 5298 September 1993, Ken Tilton wrote:
> You might find something here:

>   http://common-lisp.net/project/cldoc/index.html

> Maybe the group remembers something similar? I just have a vague
> recollection of some tool and I am not sure the above is it.

There is also tinaa which does something similar, I think. I haven't
looked at either system but would be interested to read a comparison.

Holger

-- 
---          http://hillview.bugwriter.net/            ---
Fachbegriffe der Informatik - Einfach erkl�rt
65: Internet-Boom
       Schwachsinn (Theo Lieven)
From: Thomas A. Russ
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <ymiwsoj79gw.fsf@blackcat.isi.edu>
Mitch Berkson <········@bermita.com> writes:

> Is there a nice way to get a list of the functions and macros defined in
> a file?  Or in a package?

To do this from a file, you would have to write some code that reads the
file and can properly process the included forms to locate the
definitions.  This would mean, perhaps, walking certain top-level forms
such as PROGN and EVAL-WHEN.

If macros are used that expand into function or macro definitions, then
one may also need to macroexpand the heads of forms to make this work
properly.  It could get at least a little bit hairy.

The code for finding definitions on symbols in a particular package is
much more straightforward, but it isn't completely foolproof.  That is
because one can always define a function on a symbol that is imported
into a package from somewhere else.  This doesn't happen often, but it
can occur if the symbol is used, for example, as a class name in the
package A, and then the same symbol names a function in a package B
that inherits the symbol from package A.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal J. Bourguignon
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <7c63w2yiao.fsf@pbourguignon.anevia.com>
···@sevak.isi.edu (Thomas A. Russ) writes:

> Mitch Berkson <········@bermita.com> writes:
>
>> Is there a nice way to get a list of the functions and macros defined in
>> a file?  Or in a package?
>
> To do this from a file, you would have to write some code that reads the
> file and can properly process the included forms to locate the
> definitions.  This would mean, perhaps, walking certain top-level forms
> such as PROGN and EVAL-WHEN.

Really?

---------------------------
#.(loop for f in '(a b c) collect `(defun ,f () ',f))
(defun g () 1)
(defparameter *h* (1+ (g)))
(fmakunbound 'g)
---------------------------


-- 
__Pascal Bourguignon__
From: Thomas A. Russ
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <ymiod9u6zan.fsf@blackcat.isi.edu>
···@informatimago.com (Pascal J. Bourguignon) writes:

> ···@sevak.isi.edu (Thomas A. Russ) writes:
> 
> > Mitch Berkson <········@bermita.com> writes:
> >
> >> Is there a nice way to get a list of the functions and macros defined in
> >> a file?  Or in a package?
> >
> > To do this from a file, you would have to write some code that reads the
> > file and can properly process the included forms to locate the
> > definitions.  This would mean, perhaps, walking certain top-level forms
> > such as PROGN and EVAL-WHEN.
> 
> Really?
> 
> ---------------------------
> #.(loop for f in '(a b c) collect `(defun ,f () ',f))

Did you mean for there to be a progn in here somewhere?  Otherwise you
have a list of ((DEFUN A ...)...) which is not valid Lisp.  With a
progn, in front, this reduces to the top-level forms.

> (defun g () 1)
> (defparameter *h* (1+ (g)))
> (fmakunbound 'g)

Well, this is somewhat pathological, but one could argue that the
function G is, in fact, defined in the file.  After LOADing the file, it
might not be defined anymore, but it does get defined in the file.  ;)

I suppose one could also write something odd like

(defun foo () 
  (defun bar () ...))

and variations on 

(setf (symbol-function 'baz) ...)

so it does get a bit tricky to handle all of the cases.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal Bourguignon
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <878x0y2pcn.fsf@thalassa.informatimago.com>
···@sevak.isi.edu (Thomas A. Russ) writes:

> ···@informatimago.com (Pascal J. Bourguignon) writes:
>
>> ···@sevak.isi.edu (Thomas A. Russ) writes:
>> 
>> > Mitch Berkson <········@bermita.com> writes:
>> >
>> >> Is there a nice way to get a list of the functions and macros defined in
>> >> a file?  Or in a package?
>> >
>> > To do this from a file, you would have to write some code that reads the
>> > file and can properly process the included forms to locate the
>> > definitions.  This would mean, perhaps, walking certain top-level forms
>> > such as PROGN and EVAL-WHEN.
>> 
>> Really?
>> 
>> ---------------------------
>> #.(loop for f in '(a b c) collect `(defun ,f () ',f))
>
> Did you mean for there to be a progn in here somewhere?  Otherwise you
> have a list of ((DEFUN A ...)...) which is not valid Lisp.  With a
> progn, in front, this reduces to the top-level forms.

Yes I meant that.
There's also this variation:

(quote #.(defun f () 'f))

When read, f is defined, but if you try to parse the read item, you
only get a symbol.

>> (defun g () 1)
>> (defparameter *h* (1+ (g)))
>> (fmakunbound 'g)
>
> Well, this is somewhat pathological, but one could argue that the
> function G is, in fact, defined in the file.  After LOADing the file, it
> might not be defined anymore, but it does get defined in the file.  ;)
>
> I suppose one could also write something odd like
>
> (defun foo () 
>   (defun bar () ...))
>
> and variations on 
>
> (setf (symbol-function 'baz) ...)
>
> so it does get a bit tricky to handle all of the cases.

Anyways, my point is that the OP should define more precisely his
requirements, and probably reduce them.  Reading a Common Lisp source
file is a Turing Complete operation. (or should I say lambda-calculus
complete? ;-))

Happily, he mentionned "or in a package", and he got good answers for
this part of the alternative.  For the other part, one could ask for a
list of symbols appearing in second position of top-level defun-forms
read from the given file.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: vanekl
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <fqkmjo$v99$1@aioe.org>
Mitch Berkson wrote:
> Is there a nice way to get a list of the functions and macros defined in 
> a file?  Or in a package?
> 
> Mitch Berkson

I don't know, this might be cheating:
   ctags -e *.lisp
From: Marco Antoniotti
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <ea5b80bd-05d8-4555-a731-1207ec799e7e@y77g2000hsy.googlegroups.com>
On Mar 5, 12:40 am, vanekl <·····@acd.net> wrote:
> Mitch Berkson wrote:
> > Is there a nice way to get a list of the functions and macros defined in
> > a file?  Or in a package?
>
> > Mitch Berkson
>
> I don't know, this might be cheating:
>    ctags -e *.lisp

Cheating is *wrong* :)

Cheers
--
Marco
From: Samik
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <51d30fd4-3ecd-4ebe-83c0-29ad64385258@i29g2000prf.googlegroups.com>
On Mar 5, 1:45 pm, Marco Antoniotti <·······@gmail.com> wrote:
> On Mar 5, 12:40 am, vanekl <·····@acd.net> wrote:
>
> > Mitch Berkson wrote:
> > > Is there a nice way to get a list of the functions and macros defined in
> > > a file?  Or in a package?
>
> > > Mitch Berkson
>
Here is my solution:

(defun ana-file(filename)
	   (let ((in (open filename :if-does-not-exist nil)) (function-
counter 0) (macro-counter 0)(functions (list))(macros (list)))
	     (when in
	       (loop for line = (read in nil)
		     while line do
		     (progn
		       (when(eq (car line) 'defmacro)
			 (incf macro-counter)
			 (push (nth 1 line) macros))
		       (when (eq (car line) 'defun)
			 (incf function-counter)
			 (push (nth 1 line) functions))))
	       (close in))
	     (values function-counter functions macro-counter macros)))

There may be some problem in it which I do not know.

-Samik
From: Thomas A. Russ
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <ymik5kh57ex.fsf@blackcat.isi.edu>
Samik <······@gmail.com> writes:

> Here is my solution:
> 
> (defun ana-file(filename)
>   (let ((in (open filename :if-does-not-exist nil))
>         (function-counter 0)
>         (macro-counter 0)
>         (functions (list))
>         (macros (list)))
>   (when in
>     (loop for line = (read in nil)
>           while line
>           do (when (eq (car line) 'defmacro)
> 		 (incf macro-counter)
> 		 (push (nth 1 line) macros))
>	       (when (eq (car line) 'defun)
>		 (incf function-counter)
>		 (push (nth 1 line) functions)))
>      (close in))
>  (values function-counter functions macro-counter macros)))
> 
> There may be some problem in it which I do not know.

For one thing, its safer to use the WITH-OPEN-FILE macro instead of your
own explicit OPEN and CLOSE pairs, since the macro takes care to include
the proper UNWIND-PROTECT to ensure closing the file if an error occurs
during the body.  You could, of course, do this yourself, but using the
macro is easier.

Secondly, there is the issue of also handling DEFGENERIC and the implied
generic function creation from DEFMETHOD.

Thirdly, this doesn't handle top-level PROGN or EVAL-WHEN constructs,
so that if one has definitions inside them, they won't be processed.
Fortunately, this can be handled by just iterating over the body forms
inside those constructs.

Fourthly, this doesn't handle any definitions that would be introduced by
the use of top-level definition macros.  These are not terribly common,
but in some cases they can be used in code.  One approach would be to
try to MACROEXPAND forms and process them.  It would probably make the
most sense to use MACROEXPAND-1 repeatedly, since DEFUN and DEFMACRO
themselves are macros that would generally expand into something
implementation dependent, and thus otherwise escape the counting of this
system.

Fifth, there is the issue of making sure that the appropriate
environment is setup, since one could define a macro early in a file and
then use that macro to create additional definitions later in that
file.  So one would have to evaluate macro definitions when they are
encountered, and to be safe attendant other items inside EVAL-WHEN
forms, since the macro expansions may depend upon them.


Of course, for specific source files one may know that some of the
thornier of these problems do not appear.

Perhaps the simplest method is to first enumerate all of the functions
that are defined in a lisp implementation, load the file, and then
collect only those new functions that are defined.  (Even this will fail
to detect functions that are redefined by the file, but if you start
with a new lisp image, you should be safe.  Conforming programs are not
allowed to change the built-in common lisp functions.)

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: vanekl
Subject: Re: Getting list of functions and macros in a file
Date: 
Message-ID: <fqn0mk$mjb$1@aioe.org>
Marco Antoniotti wrote:
> On Mar 5, 12:40 am, vanekl <·····@acd.net> wrote:

(snip prattle :test 'irrational-exuberance-and-all-that-jazz)

>> I don't know, this might be cheating:
>>    ctags -e *.lisp
> 
> Cheating is *wrong* :)
> 
> Cheers
> --
> Marco

Faith-as-Buffy: Why, yes, I would be Buffy. May I help you? Buffy.
    [sounding]: Buff-y.
    [She shakes her finger.]
    You can't do that. it's wrong. [She shakes her head.]
    You can't do that because it's naughty.
    [louder]
    Because it's wrong.