in reply to List of subs defined by a file?

I need a list of all the subs brought in by the file, not all the subs in the current or main package, and file.pm does not conatin any package declarations.

You can require that file in an ad-hoc package and inspect its symbol table:

#!/usr/bin/perl # file.pm use strict; our ($baz, $quux); sub blorf; $quux = sub { 3 }; sub foo { 1 } sub bar { 2 }
#!/usr/bin/perl # main script use strict; { package Query; require "file.pm"; } print "in package ", __PACKAGE__, $/; for my $sym ( keys %Query:: ) { no strict 'refs'; print "file.pm: $sym\n" if defined *{'Query::'.$sym}{CODE}; print "file.pm: subref \$$sym\n" if ref ${*{'Query::'.$sym}{SCALAR}} + eq 'CODE'; }

Output:

in package main file.pm: sub bar file.pm: subref $quux file.pm: sub blorf file.pm: sub foo

Replies are listed 'Best First'.
Re^2: List of subs defined by a file?
by sflitman (Hermit) on Dec 21, 2008 at 09:00 UTC
    I tried to generalize your script by substituting $file for file.pm, and when I ran it on a regular script it runs the script in require (so that would need to be suppressed somehow) and when I ran it on a perl module like Tie::Scalar (path supplied by perldoc -l) it gave me nothing, since the module doesn't export globals.

    My code, for what it's worth:

    #!/usr/bin/perl # listsubs - display list of subroutines in a package or script use strict; my $file=shift @ARGV; { package Query; require $file; } for my $sym ( keys %Query:: ) { no strict 'refs'; print "Query::$sym\n" if defined *{'Query::'.$sym}{CODE}; print "$file: subref \$$sym\n" if ref ${*{'Query::'.$sym}{SCALAR}} e +q 'CODE'; }

    I think the right answer to this is to simply grep the file for /^sub/, unless you're trying to get a list of dynamically generated coderefs??

    SSF

      and when I ran it on a perl module like Tie::Scalar (path supplied by perldoc -l) it gave me nothing, since the module doesn't export globals.

      Well, the script I provided is for the case you mentioned - just a file with subs in it, without any package declaration whatsoever (and inspecting the symbol table hasn't anything to do with what is exported - the ad-hoc package Query doen't export anything, either). Now, Tie::Scalar has a package declaration - package Tie::Scalar; - and the script isn't suitable for that case. You would have to inspect %Tie::Scalar. I'd reach for something else for the general case, maybe even PPI.

      I think the right answer to this is to simply grep the file for /^sub/, unless you're trying to get a list of dynamically generated coderefs??

      That heavily depends on what is "right" for you and the task at hand. More general would be grepping for /^\s*sub/. But that won't give you not only dynamically generated subrefs, but also typeglob-bound code generated at module use, such as generated by Class::Accessor:

      package Foo; BEGIN { our ($VERSION, @ISA, @METHODS); @METHODS = qw(foo bar quux); for my $field (@METHODS) { *{__PACKAGE__.'::'.$field} = sub { my $self = shift @_; if (@_) { return $self->set($field, @_); } else { return $self->get($field); } }; } for (qw(set get)) { *{__PACKAGE__.'::'.$_} = sub { my $self = shift @_; if (@_ == 1) { return $$self{$_[0]}; } elsif (@_ > 1) { return $self->{$_[0]} = $_[1]; } else { $self->_croak('Wrong number of arguments received'); } }; } }