howto list package symbols 
Author Message
 howto list package symbols

hello,

i would like to get a list of all package symbols, at least subroutines.
If this is possible, how can i distinguish inherited stuff from non-inherited
stuff ?

Best regards,
Volker



Wed, 08 Dec 2004 01:02:47 GMT  
 howto list package symbols

Quote:

> i would like to get a list of all package symbols, at least subroutines.

while (my ($name, $glob)=each(%Package::)) {
  if (defined(*{$glob}{'SCALAR'})) {
    print('$Package::', $name, " exists.\n");
  }
  if (defined(*{$glob}{'ARRAY'})) {

  }
  if (defined(*{$glob}{'HASH'})) {
    print('%Package::', $name, " exists.\n");
  }
  if (defined(*{$glob}{'CODE'})) {
    print('&Package::', $name, " exists.\n");
  }

Quote:
}
> If this is possible, how can i distinguish inherited stuff from non-inherited
> stuff ?


name and also have (*{$glob1}{'CODE'} eq *{$glob2}{'CODE'}).

There may be a module that hides all this messiness; I don't know CPAN
as well as I know Perl.

paul



Wed, 08 Dec 2004 01:45:19 GMT  
 howto list package symbols
: hello,

: i would like to get a list of all package symbols, at least subroutines.

the names of package variables are stored in a hash with the name
"package_name::"

e.g.
        foreach $var_name (keys %main:: )
        { print $var_name,"\n";
        }


I assume that once you have a name string then you could check for
subroutines using a symbolic reference using the name string with the &
character

somthing like (untested)  

        if ( defined( &"$var_name") ) { print "$var_name is a sub\n";}

: how can i distinguish inherited stuff from non-inherited
: stuff ?

inherited stuff isn't in the package so you won't find them.  They are
in the packages from which you are inheriting.  


package to find the other package names, and then check each of those
packages as shown above.



Wed, 08 Dec 2004 03:03:11 GMT  
 howto list package symbols

[Mailed and posted]

Quote:
> i would like to get a list of all package symbols, at least subroutines.

If the package is 'Foo', then there is a special hash, %Foo::, whose
keys are the package symbols, and whose values are the globs.

For example:

        package Foo;
        sub do_i_like_pie { 1 }
        $fish = "Herring";

        package main;

        for my $name (keys %Foo::) {
          print "Symbol: Foo::$name\n";
        }

This prints:

        Symbol: Foo::do_i_like_pie
        Symbol: Foo::fish

To detect subroutines, you may use 'defined' as usual:

        package Foo;
        sub do_i_like_pie { 1 }
        $fish = "Herring";

        package main;

        for my $name (keys %Foo::) {
          print "Subroutine: Foo::$name\n"
                if defined &{"Foo::$name"};
        }

This prints:

        Subroutine: Foo::do_i_like_pie

Note that Foo::fish was not printed because there is no subroutine Foo::fish.

If there were a Foo::Bar package, we would expect its symbol table to
be found in %Foo::Bar:: .  We would find the entry for "Bar::" in the
symbol table for package 'Foo'.  Thus the symbol tables are linked
into a tree.  We can write a recursive function to traverse this tree
and print out the name of *every* function in the program:

        sub dump_symtab {
          my $package = shift || "";
          return if $package eq "main::";  # Special case
          my $symtab = \%{"::$package"};



            my $fullname = "$package$name";
            print "$fullname\n" if defined &$fullname; # print subroutine name

          }

            dump_symtab($subpackage);
          }
        }

        dump_symtab();

To get a more interesting output, add "use DBI;" at the top of this program.

"main::" is a synonym for the root package, so we do not want to
traverse it; if we did, we would be stuck in an infinite loop,
traversing "main::", then "main::main::", "main::main::main::", and so
on.

Quote:
> If this is possible, how can i distinguish inherited stuff from non-inherited
> stuff ?

                A
                |
                B

It's not really clear how these two problems are related.

If package B inherits method 'm' from package A, then that means that
A::m exists but B::m does not.  (If B::m did exist, it would override
the method m that would have been inherited from A.)

If you have a method, say "Class::method", and you want to know
whether it is inherited, just ask

        if (Class->can('method')) {
          if (defined &Class::method) {
            # it was not inherited
          } else {
            # it is inherited from some base class
          }
        } else {
          # it is not defined at all
        }

If you wanted to make a list of all the methods supported by a

something like this:

        sub dump_methods {
          my $class = shift or return;
          my $seen = shift || {};
          my $depth = shift || 0;
          my $I = "  " x $depth;

          # locate methods in this class
          my $symtab = \%{"$class\::"};


            my $fullname = "$class\::$method";
            next unless defined &$fullname;
            print $I;                       # indentation
            if ($seen{$method}) {
              print "($fullname overridden by $seen{$method})\n";
            } else {
              # we found a new method
              print "* $method";
              print $depth == 0 ? "\n" : " inherited from $class\n";
              $seen{$method} = $fullname;
            }
          }

          # traverse parent classes of this one


            print "${I}Base class $class:\n";
            dump_methods($class, $seen, $depth+1);
          }
        }

Suppose you have the following class hierarchy:

                R (foo, baz)
                |
     (foo, bar) A1  A2 (foo, bar)
                 \ /
                  B  (foo)

The output for class B (dump_methods('B')) looks like this:

        * foo
        Base class A1:
          (A1::foo overridden by B::foo)
          * bar inherited from A1
          Base class R:
            (R::foo overridden by B::foo)
            * baz inherited from R
        Base class A2:
          (A2::foo overridden by B::foo)
          (A2::bar overridden by A1::bar)

The *'s indicate methods that you can call on class B.  Class B has
three methods.  It defines its own 'foo' method, which overrides the
various 'foo' methods in its parent classes.  It also has a 'bar'
method which it inherits from class A1 and a 'baz' method which it
inherits from class R.  

The output for A1 (dump_methods('A1')) looks like this:

        * foo
        * bar
        Base class R:
          (R::foo overridden by A1::foo)
          * baz inherited from R

A1 defines its own 'foo' and 'bar' methods and also inherits 'baz'
from class R.

All that said, it's not clear that this is really useful, for several
reasons.

First, not every subroutine is a method or is intended to be treated
like one.  An example that is on my mind lately is my Tie::File
module.  Tie::File object support many different methods.  But the
Tie::File package also contains a utility function, called _bufsize,
which is *not* a method, and which will produce bizarre results if you
try to call it like a method.  The program above cannot discover this;
it will report that Tie::File contains a method '_bufsize'.

Second, such functions may be exported from other modules.  For
example, Tie::File begins with 'use Carp' and 'use POSIX' and so
imports a lot of functions from these modules, including 'confess' and
'SEEK_SET'.  These are not methods, but the program above cannot
discover this; it reports that Tie::File contains a method 'confess'.

Third, many modules provide methods via Perl's 'AUTOLOAD' feature,
which means that the code for the method is not generated until the
moment it is used.  For example, objects in the CGI class support many
methods including 'start_form' and 'end_form'.  The program above will
not detect these methods unless you have already invoked them, because
until you call these methods, they do not exist in the symbol table.

I apologize for making my answer so long.  I hope some of all of this
is helpful.  Good luck with whatever you are trying to do.



Wed, 08 Dec 2004 02:27:34 GMT  
 howto list package symbols

Quote:


[snip]
> > If this is possible, how can i distinguish inherited stuff from
> > non-inherited stuff ?


> name and also have (*{$glob1}{'CODE'} eq *{$glob2}{'CODE'}).

> There may be a module that hides all this messiness; I don't know CPAN
> as well as I know Perl.

Use the B module.

use B qw(svref_2object);
my $CV = svref_2object($subref);
print "&" . $CV->GV->STASH->NAME . "::" . $CV->GV->NAME;
# CV is codevalue, GV is globvalue, STASH is symbol table hash.

--

pack 'u', pack 'H*', 'ab5cf4021bafd28972030972b00a218eb9720000';



Wed, 08 Dec 2004 13:45:19 GMT  
 howto list package symbols

Quote:


>> i would like to get a list of all package symbols, at least subroutines.

>while (my ($name, $glob)=each(%Package::)) {
>  if (defined(*{$glob}{'SCALAR'})) {
>    print('$Package::', $name, " exists.\n");
>  }
>  if (defined(*{$glob}{'ARRAY'})) {

>  }
>  if (defined(*{$glob}{'HASH'})) {
>    print('%Package::', $name, " exists.\n");
>  }
>  if (defined(*{$glob}{'CODE'})) {
>    print('&Package::', $name, " exists.\n");
>  }
>}

There's a problem with that.  If you have code like:

sub foo;
sub AUTOLOAD { $AUTOLOAD =~ /\bfoo\z/ && &do_foo }

and there is nothing else to create a *foo glob (e.g. a mention of

called), the symbol table hash will have a key 'foo' but the value
will *NOT* be a glob but rather a placeholder.  (The placeholder seems
to be an IV set to -1 if there is no prototype and a PV set to the
prototype otherwise.)

This not only makes your defined(*{$glob}{'CODE'}) test fail, but
makes it (and all the other defined checks) use a symbolic ref (of -1
or the prototype) and croak under use strict.

I think this is a bug, but I can see the point of saving the memory
where possible.



Wed, 08 Dec 2004 06:43:22 GMT  
 howto list package symbols

Quote:


> : how can i distinguish inherited stuff from non-inherited
> : stuff ?

> inherited stuff isn't in the package so you won't find them.

AIUI, inherited stuff *is* in the package, even though it wasn't
written in explicitly, because Exporter creates aliases in the symbol
table.

paul



Thu, 09 Dec 2004 03:38:11 GMT  
 howto list package symbols

Quote:



>>while (my ($name, $glob)=each(%Package::)) {
>>  if (defined(*{$glob}{'SCALAR'})) {
...
> This not only makes your defined(*{$glob}{'CODE'}) test fail, but
> makes it (and all the other defined checks) use a symbolic ref (of -1
> or the prototype) and croak under use strict.

Ok, so guard against that with:
  next unless ref($glob) eq 'GLOB';
Of course, we still don't get information about autoloads this way.
Is there a way to force loading of an autoload without actually
calling the function?

paul



Thu, 09 Dec 2004 03:37:00 GMT  
 howto list package symbols

Quote:




> >> i would like to get a list of all package symbols, at least
> >> subroutines.

> >while (my ($name, $glob)=each(%Package::)) {
> >  if (defined(*{$glob}{'SCALAR'})) {
> >    print('$Package::', $name, " exists.\n");
> >  }
> >  if (defined(*{$glob}{'ARRAY'})) {

> >  }
> >  if (defined(*{$glob}{'HASH'})) {
> >    print('%Package::', $name, " exists.\n");
> >  }
> >  if (defined(*{$glob}{'CODE'})) {
> >    print('&Package::', $name, " exists.\n");
> >  }
> >}

> There's a problem with that.  If you have code like:

> sub foo;
> sub AUTOLOAD { $AUTOLOAD =~ /\bfoo\z/ && &do_foo }

> and there is nothing else to create a *foo glob (e.g. a mention of

> called), the symbol table hash will have a key 'foo' but the value
> will *NOT* be a glob but rather a placeholder.  (The placeholder seems
> to be an IV set to -1 if there is no prototype and a PV set to the
> prototype otherwise.)

That placeholder gets replaced with a real glob as soon as the thing is
referenced.  Compare:

perl -e "sub x; print \$::{x}"
perl -e "sub x; \*x; print \$::{x}"
perl -e "sub x; \&x; print \$::{x}"

Quote:
> This not only makes your defined(*{$glob}{'CODE'}) test fail, but
> makes it (and all the other defined checks) use a symbolic ref (of -1
> or the prototype) and croak under use strict.

> I think this is a bug, but I can see the point of saving the memory
> where possible.

--

pack 'u', pack 'H*', 'ab5cf4021bafd28972030972b00a218eb9720000';


Thu, 09 Dec 2004 12:44:09 GMT  
 howto list package symbols

Quote:




> >>while (my ($name, $glob)=each(%Package::)) {
> >>  if (defined(*{$glob}{'SCALAR'})) {
> ...
> > This not only makes your defined(*{$glob}{'CODE'}) test fail, but
> > makes it (and all the other defined checks) use a symbolic ref (of
> > -1 or the prototype) and croak under use strict.

> Ok, so guard against that with:
>   next unless ref($glob) eq 'GLOB';

No, that won't work, since each $glob is NOT a ref to a glob, but an
actual glob (well, sorta... really it's a "fakeglob" type thingy, but
anyway, it's not a ref).

What you have to do is check if ref(\$glob) eq "GLOB";

Quote:
> Of course, we still don't get information about autoloads this way.
> Is there a way to force loading of an autoload without actually
> calling the function?

Sorry, no.

--

pack 'u', pack 'H*', 'ab5cf4021bafd28972030972b00a218eb9720000';



Thu, 09 Dec 2004 12:47:12 GMT  
 howto list package symbols

Quote:


> > i would like to get a list of all package symbols, at least
> > subroutines.

> while (my ($name, $glob)=each(%Package::)) {
>   if (defined(*{$glob}{'SCALAR'})) {
>     print('$Package::', $name, " exists.\n");
>   }
>   if (defined(*{$glob}{'ARRAY'})) {

>   }
>   if (defined(*{$glob}{'HASH'})) {
>     print('%Package::', $name, " exists.\n");
>   }
>   if (defined(*{$glob}{'CODE'})) {
>     print('&Package::', $name, " exists.\n");
>   }
> }

This could be shorted:


while( my ($name, $glob) = each %Package:: ) {
   if( ref(\$glob) ne "GLOB" ) {
      print "&Package::$name has a prototype.\n";
      next;
   }
   defined *{$glob}{$_}
      and print "$sigils{$_}Package::$name exists.\n"
      for qw(SCLAR ARRAY HASH CODE);

Quote:
}

--

pack 'u', pack 'H*', 'ab5cf4021bafd28972030972b00a218eb9720000';


Thu, 09 Dec 2004 12:53:37 GMT  
 howto list package symbols

Quote:


> > inherited stuff isn't in the package so you won't find them.

> AIUI, inherited stuff *is* in the package, even though it wasn't
> written in explicitly, because Exporter creates aliases in the symbol
> table.

Exported stuff is in the package; inherited stuff isn't.
The exporter has nothing to do with inheritance.


Thu, 09 Dec 2004 06:34:21 GMT  
 howto list package symbols

Quote:

> If there were a Foo::Bar package, we would expect its symbol table to
> be found in %Foo::Bar:: .  We would find the entry for "Bar::" in the
> symbol table for package 'Foo'.  Thus the symbol tables are linked
> into a tree.

I never understood why this is the case. There is no physical
relationship between packages Foo and Foo::Bar, except for this one
implementation detail. Why was it done this way? Now, to get through
to a variable $x in package Foo::Bar, you have to follow the links:

    $::{'Foo::'}->{'Bar::'}->{'x'}

(and use this as a glob: dereference with ${GLOB}). You can't do this,
in the general case, without a loop.

So, why is it like this? I think it would have made sense to just
store all package symbol tables in the main stash -- it's not like it
would easily overflow so that it becomes remarkably slower, would it.
After all it's just a hash. Then, you would have been able to simply
use

    $::{'Foo::Bar::'}->{'x'}

but now, you can't.

--
        Bart.



Thu, 09 Dec 2004 09:03:53 GMT  
 howto list package symbols

Quote:

> Is there a way to force loading of an autoload without actually
> calling the function?

That is impossible in general:

        sub AUTOLOAD {
          my $caller = caller;
          my $result = missile_strike_against('Pumpkin Center, LA');
          if ($result eq "successful") {
            *{"$caller\::AAAAA"} = sub { ... };
          } else {
            *{"$caller\::BBBBB"} = sub { ... };
          }
        }

Now you cannot know what function will be created by AUTOLOAD without
actually launching the missles to see.

Perhaps a more realistic example:

        sub AUTOLOAD {
          my $caller = caller;
          my $remote = make_remote_network_connection();


        }

I think the SOAP::Lite module does something very much like this.



Fri, 10 Dec 2004 04:51:12 GMT  
 howto list package symbols

Quote:

>Ok, so guard against that with:
>  next unless ref($glob) eq 'GLOB';
>Of course, we still don't get information about autoloads this way.
>Is there a way to force loading of an autoload without actually
>calling the function?

No, but you don't actually want an autoload, you just want the real
glob created (or just assume there is a sub there if !ref($glob)).  To
create the glob you just use a symbolic ref (e.g. *{"Package::$name"})
or (I think) call Package::->can($name).


Fri, 10 Dec 2004 04:06:29 GMT  
 
 [ 20 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Reading synonyms and grants from Oracle via the BDE

2. Turbo Pascal 7 Exec Command Trouble

3. How to sort a table ?

4. fpeelo@portablesolutions.com - SORRY!

5. How to play Mp3?

6. howto get names of packages and subs in files similar to caller and Devel::Symdump

7. Package name (symbol table) for usub.

8. Howto uninstall packages

9. Devel::Symdump-1.19 fancy dump-the-symbol-table package

10. Have package use another symbol table?

11. Global Symbol $Bla Requires Explicit Package Name

12. Devel::Symdump-1.19 fancy dump-the-symbol-table package

 

 
Powered by phpBB® Forum Software