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

question

How can one write a perl script in such a way that the code can report on itself?

details
given the code in foo_file.pl
### foo_file.pl sub FooBegin{ return('begin now'); } sub FooProcess{ ### this is the subroutine where we ### do the foo processing $foo = "blahblahblah"; $result = $foo x 12; return $result; } sub FooEnd{ return('done'); }
how to generate a report ... something like:
script: foo_file.pl found 3 subroutines FooBegin 1 lines of code (click here to see src) FooProcess 5 lines of code (click here to see src) FooEnd 1 lines of code (click here to see src) found 0 imported modules found 0 global variables

Replies are listed 'Best First'.
Re: self-reporting perl code: how can it be done?
by diotalevi (Canon) on Oct 29, 2004 at 16:06 UTC

    Try perl -MO=Xref your_script.pl which produces this sort of output.

    ... skipping more output ... File GraphLotusScript.pl ... skipping some output ... Package main &class s158 &const s164 &function s152 &library s171 &main s41 &read_source s63 &subroutine s146 &unhandled s263 &usage s132 &variable s141 Subroutine (main) Package main $GRAPHVIZ 19 $OUT_FILE 22 $OUT_FMT 21 $SHOW_ALL 31 $SHOW_CLASSES 31 $SHOW_CODE 30, 31 $SHOW_CONSTANTS 31 $SHOW_FUNCTIONS 31 $SHOW_LIBRARIES 31 $SHOW_SUBS 31 $SHOW_VARIABLES 31 $VIEW 20 %SHAPES 23 &GetOptions &31 &main &41 @ARGV 41 Subroutine class Package (lexical) $name i200, 202 $self i202, 203 %$self 203, 204 %%$self 204, 206 %%%$self 206, 210 %%%%$self 210 Package main $ORDER 203 $_ 210, 210 %STASH 202 @_ 200 Subroutine const Package (lexical) $name i233, 235 $self i235, 236 %$self 236, 237 %%$self 237, 238 %%%$self 238 Package main $ORDER 236 %STASH 235 @_ 233 Subroutine function Package (lexical) $name i183, 185 $self i185, 186 %$self 186, 187 %%$self 187, 189 %%%$self 189, 193 %%%%$self 193 Package main $ORDER 186 $_ 193, 193 %STASH 185 @_ 183 Subroutine library Package (lexical) $name i243, 245 $self i245, 246 %$self 246, 247 %%$self 247, 248 %%%$self 248 Package main $ORDER 246 %STASH 245 @_ 243 Subroutine main Package (lexical) $file i64, 60, 60 $first_file i46, 47, 49, 49, 120, 120, 124 $match 105, 106 $object 77, 91 $shape i78, 81 $source i91, 93 $type i77, 78, 78 %$object 77, 81, 91, 105, 105 %%$object 105, 106 @files i45, 64 Package CORE::GLOBAL &glob &45 Package main $! 49, 60 $GRAPHVIZ 120 $OBJECT 55 $OUT_FILE 120, 124 $OUT_FMT 120 $VIEW 124 $_ 45, 45, 72, 86, 93, 93 %SHAPES 78 %STASH 55, 72, 77, 86, 91, 93, 105, 110 &read_source &63 *DOT 51, 81, 84, 106, 116 *SOURCE 60, 64 @_ 45 Subroutine read_source Package main $1 141, 146, 152, 158, 164, 171 $OBJECT 138 $SHOW_ALL 141, 146, 152, 158, 164, 171 $SHOW_CLASSES 158 $SHOW_CODE 146, 152, 158 $SHOW_CONSTANTS 164 $SHOW_FUNCTIONS 152 $SHOW_LIBRARIES 171 $SHOW_SUBS 146 $SHOW_VARIABLES 141 $_ 138, 141 %$OBJECT 138 &class &158 &const &164 &function &152 &library &171 &subroutine &146 &variable &141 Subroutine subroutine Package (lexical) $name i217, 219 $self i219, 220 %$self 220, 221 %%$self 221, 222 %%%$self 222, 227 %%%%$self 227 Package main $ORDER 220 $_ 227, 227 %STASH 219 @_ 217 Subroutine usage Package main $0 130 Subroutine variable Package (lexical) $name i253, 254 $self i254, 255 %$self 255, 256 %%$self 256, 257 %%%$self 257 Package main $ORDER 255 %STASH 254 @_ 253 ... skipping more output ...

    Considered: radiantmatrix Serious need for trimming or readmore tags
    Unconsidered: ysth upon consultation with author - Keep/Edit/Delete: 6/21/0

Re: self-reporting perl code: how can it be done?
by Happy-the-monk (Canon) on Oct 29, 2004 at 14:49 UTC

    write a module, so you don't have to report on the reporter-code.

    open the file itself - open( 0 ) -, read, parse and report...

    Cheers, Sören

    Update: s/\$0/0/ ... I got it wrong, it's seldom used, sorry.

    Another update, now with code that's tested, as the first should have been.
    A simple Perl quine:

    open ( 0 ) or die $!; while ( <0> ) { print };

Re: self-reporting perl code: how can it be done?
by dragonchild (Archbishop) on Oct 29, 2004 at 14:54 UTC
    Sounds like you want to parse Perl. For simple situations, you might want to consider using a source filter. For complex situations, especially regarding AUTOLOAD or modules like Class::MethodMaker, that's not going to work.

    For what you seem to be talking about, a source filter is probably the way to go. Start with Filter::Simple.

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re: self-reporting perl code: how can it be done?
by revdiablo (Prior) on Oct 29, 2004 at 16:36 UTC
    How can one write a perl script in such a way that the code can report on itself?

    If you have a __DATA__ section at the end, you can seek on the DATA filehandle, and read the source of your current program. Note that without the __DATA__ section, it will not work. Here's a quick example:

    #!/usr/bin/perl use strict; use warnings; my %chars; seek DATA, 0, 0; while (<DATA>) { chomp; $chars{$_}++ for split //; } for (sort keys %chars) { printf "%s => %2d\n", $_, $chars{$_}; } __DATA__