bikeNomad has asked for the wisdom of the Perl Monks concerning the following question:

I haven't been able to find an answer to this in my (probably limited) reading of perlvar and perldebguts. I'm trying to provide access to the text of subroutines from within a program. I can get the line numbers of the defined routines just fine using the %DB::sub hash and setting bits in $^P. But there doesn't seem to be anything in the source text arrays (the ones that are named @{"_<$filename"} for a given $filename) unless I also specify the -d switch. Is there some way to get this text into my program without -d? (Yes, I realize that I could go and read the files, but this is a speed optimization I'd like to do).

The following program prints the source text when called with -d, but not without it:

use strict; package DB; BEGIN { $^P |= 0x310 } package main; sub a { print "this is a test"; } printf("\$^P is %x\n", $^P); while (my ($name, $range) = each(%DB::sub)) { my ($filename, $start, $end) = $range =~ /(.+):(\d*)-(\d*)/; next if $filename =~ /^\(/; print "$name\t$filename\t$start - $end\n"; no strict 'refs'; my $lines = \@{'_<' . $filename}; foreach my $lineNumber ($start .. $end) { my $line = $$lines[$lineNumber]; print $line; } }

Edit ar0n -- fixed title

Replies are listed 'Best First'.
Re: Using @{"_<$filename"}
by tachyon (Chancellor) on Jul 07, 2001 at 22:21 UTC

    From my limited understanding of how Perl works I doubt it is possible to get the original text that comprises your program at runtime without directly reading the source file. The logic for this assertion is based on how Perl actually executes the textfile that contains your code.

    When you run a Perl program this is what happens:

    0. First the Perl executable reads textfile that comprises your code.

    1. Next comes: The Compilation Phase which converts your textfile program into a data structure called a parse tree. During this process it discards superfluous elements like whitespace and comments.

    2. Next it moves on to the optional Code Generation Phase.

    3. Next comes: The Parse Tree Reconstruction Phase where it reanimates the program by reconstructing the parse tree. This too is optional and occurs only if the phase 2 code generation occurs and you chose to generate bytecode.

    4. Finally comes: The Execution Phase where the interpreter takes the parse tree data structure and executes it. This is runtime. Because it executes the parse tree data structure rather than the original textfile you think of as your program, when your program runs it is in the form of Perl's internal opcodes not the original code that generated them.

    I would therefore suggest that what you want to do may not be possible as the source code that you wish to get no longer exists per se. It is still in the source file but is not being used by Perl in its original form anymore.

    Chapter 18 of the Camel (3rd ed) goes into this in more detail. Thankfully I don't have to understand this to write Perl code - otherwise I would be stuffed because I don't!

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

that's @{"_$filename"}
by bikeNomad (Priest) on Jul 07, 2001 at 20:57 UTC
    Hm... well, the title was supposed to say Using @{"_<$filename"} but it ate my quotes.

    Anyway, the other advantage of using this method is that the text of evals is available; this is the only way I know to get to them.

    update: no, the text of evals aren't available. I guess the debugger just scans the file contents for these, since it's got line numbers.

Re: Using @{"_$filename"}
by japhy (Canon) on Jul 08, 2001 at 19:34 UTC
    That's because perl5db.pl is doing that itself. If you want to do that, you can do something like:
    open SELF, $0; @lines = <SELF>; close SELF; # or, more sneakily open 0; @lines = <0>; close 0;


    japhy -- Perl and Regex Hacker