So I've been playing around with trying to get to the real code for a subroutine as determined by the subroutine ref. While I know that this is not always obtainable, I would like to try to track it down nonetheless. I've looked at B::Deparse and that I don't believe it to be quite what I'm looking for as I would like to see comments and the like in the code. Module::Info->subroutines will give me a pointer to the file (which I can also get from %INC) along with the line number of the first and last op in the sub, but those don't quite get me what I want either since the beginning and the end of the routine is chopped off. While finding the beginning of the routine in this case is pretty easy, finding the end is more difficult.

Does anyone out there in Monkland have any tips on how to do this? I've included my very-much-in-progress code below.

#!/usr/bin/perl use Module::Info; use IO::File; use Data::Dumper; my %modinfos; sub _showcode { my ($pkg, $sub) = @_; my $fh; if (!exists($modinfos{$pkg}{parsedfile})){ if ($fh = new IO::File($modinfos{$pkg}{mod}->file())){ my $count = 0; do { my $offset = $fh->tell(); $modinfos{$pkg}{parsedfile}[$count++] = $offset; } while ($fh->getline); } else { die("Could not open $filename"); } } else { $fh = new IO::File($modinfos{$pkg}{mod}->file()); } if ($fh){ my $s = $modinfos{$pkg}{subs}->{$sub}->{start}; my $f = $modinfos{$pkg}{subs}->{$sub}->{end}; my $sp = $modinfos{$pkg}{parsedfile}[$s]; my $fp = $modinfos{$pkg}{parsedfile}[$f]; my $delta = $fp - $sp; if ($delta <= 0){ warn("Error retrieving code for $varName, start $s->$sp, end $ +f->$fp, delta = $delta, $filename"); $s = $f - 1; $sp = $modinfos{$pkg}{parsedfile}[$s]; $fp = $modinfos{$pkg}{parsedfile}[$f]; $delta = $fp - $sp; } print("$s($sp) to $f($fp) delta = $delta for $sub\n"); $fh->seek($sp, 0); my $cbuf; my $r = $fh->read($cbuf, $delta); # Need to back up to beginning of sub from the "start" while ($cbuf !~ /sub\s+$sub/){ $s--; last if ($s < 0); $sp = $modinfos{$pkg}{parsedfile}[$s]; $fp = $modinfos{$pkg}{parsedfile}[$s+1]; my $delta = $fp - $sp; $fh->seek($sp, 0); my $cbuf2; my $r = $fh->read($cbuf2, $delta); $cbuf = $cbuf2 . $cbuf; } $s = $f-1; my @used = $modinfos{$pkg}{mod}->modules_used(); my $usedstr = ""; foreach my $used (@used){ $usedstr .= "use $used;\n"; } while (1){ print("Sending to eval => $usedstr$cbuf\n"); my $ref = eval "$usedstr$cbuf"; if ($@){ # warn($@); } else { last; } $s++; last if ($s > $modinfos{$pkg}{parsedfile}); $sp = $modinfos{$pkg}{parsedfile}[$s]; $fp = $modinfos{$pkg}{parsedfile}[$s+1]; my $delta = $fp - $sp; $fh->seek($sp, 0); my $cbuf2; my $r = $fh->read($cbuf2, $delta); $cbuf .= $cbuf2; } print("Code is => \n$cbuf\n"); } } sub UNIVERSAL::Introspect { my @recurse = (@_); while (@recurse){ my $cur = shift @recurse; my $pkg; if ($pkg = ref($cur)){ print("$cur is a $pkg\n"); } else { $pkg = $cur; $cur = $pkg->new(); } if (!exists($modinfos{$pkg}{mod})){ my @mods = Module::Info->all_installed($pkg); if (@mods != 1){ warn("Did not get proper number of modules: " . Dumper(\@mods) +); return; } $modinfos{$pkg}{mod} = shift @mods; } if (grep /^$pkg$/, @done){ print "Skipping $pkg\n"; next; } my %subs = $modinfos{$pkg}{mod}->subroutines(); if (%subs){ my $ncur = $pkg; print("$ncur ==>\n"); foreach my $ok (keys %subs){ my $nk = $ok; $nk =~ s/$pkg\:\://; print "$pkg->$ok => $nk\n"; $subs{$nk} = $subs{$ok}; delete $subs{$ok}; } $modinfos{$pkg}{subs} = \%subs; foreach my $sub (sort keys %subs){ _showcode($pkg, $sub); } } push @done, $pkg; } } my $fh = new IO::File(); $fh->Introspect;

In reply to Find the real code for a subroutine ref? by bschmer

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.