Sometimes even peppering your perl with prints is more than you care for just to debug your code. Well, install Devel::Trace and you get a sh -x analog that's as easy as tacking -d:Trace onto the commandline like so:
C:}/~/perl -d:Trace bin/whichpm Exporter >> bin/whichpm:6: $VERSION = 0.02; >> bin/whichpm:8: foreach my $PM ( @ARGV ){ >> bin/whichpm:9: eval "require $PM" || next; Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/site_perl/5.8.8/Devel/Trace.pm line 12. >> (eval 2)[bin/whichpm:9]:3: >> bin/whichpm:10: $PM = File::Spec->catfile(split(/::/, $PM)); >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:92: my $self = shift; >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:93: my $file = $self->canonpath(pop @_); >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:43: my ($self,$path) = @_; >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:50: my $node = ''; >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:51: if ( $^O =~ m/^(?:qnx|nto|cygwin)$/ && $path =~ s:^(//[^/]+)(/|\z):/:s ) { >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:59: $path =~ s|/+|/|g; # xx////xx -> xx/xx >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:60: $path =~ s@(/\.)+(/|\Z(?!\n))@/@g; # xx/././xx -> xx/xx >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:61: $path =~ s|^(\./)+||s unless $path eq "./"; # ./xx -> xx >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:62 $path =~ s|^/(\.\./)+|/|; # /../../xx -> xx >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:63 $path =~ s|^/\.\.$|/|; # /.. -> / >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:64: $path =~ s|/\Z(?!\n)|| unless $path eq "/"; # xx/ -> xx >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:65: return "$node$path"; >> /usr/lib/perl5/5.8.8/File/Spec/Unix.pm:94: return $file unless @_; >> bin/whichpm:12: $PM .= '.pm' unless $PM =~ /\.pm$/; >> bin/whichpm:13: print $INC{$PM}, ' '; >> bin/whichpm:15: print "\n"; /usr/lib/perl5/5.8.8/Exporter.pm
Unfortunately, many of the TODO items remain undone, probably because besides suffering from buffering and some occasional indigestion with string evals, the elegantly simple code does what it's supposed to. Alas, this also means it's not yet possible to use Devel::Trace as a quine cheat, or tweak the output into a more convincing Hollywood-esque code crawl. However, in my experience, everyone's favorite octopus-loving hacker is usually willing to share commit bits to his toys with those willing to persistently provide patches.
To make up for perfunctory review, and recent gaps, we've amassed a collection of other advent calendars you might want to frequent this year in addition to this one. Some of them also feature perl, but all are geeky. Follow the Links here, or the footer of the front page.
1 #!/usr/bin/perl -w 2 use strict; 3 use vars '$VERSION'; 4 use File::Spec; 5 6 $VERSION = 0.03; 7 8 foreach my $PM ( @ARGV ){ 9 eval "require $PM" || next; 10 $PM = File::Spec->catfile(split(/::/, $PM)); 11 $PM .= '.pm' unless $PM =~ /\.pm$/; 12 print $INC{$PM}, ' '; 13 } 14 print "\n"; 15 __END__ 16 17 =pod 18 19 =head1 NAME 20 21 whichpm - lists real paths of specified modules 22 23 =head1 SYNOPSIS 24 25 less `whichpm Bar` 26 27 =head1 DESCRIPTION 28 29 Analogous to the UN*X command which. 30 31 Even with TAB completion entering paths like 32 F</afs/athena.mit.edu/user/u/s/user/lib/perl5/site_perl/5.8.0/IO/Pager> 33 can be gruesome. ~ makes it a bit more bearable 34 F<~/lib/perl5/site_perl/5.8.0/IO/Pager>. 35 Then inspiration struck, perl knows where its libraries are; modulo @INC. 36 Better yet, you don't have to know if it's a core module or site specific 37 nor architecture specific vs. platform independent. 38 39 =head1 AUTHOR 40 41 Jerrad Pierce <jpierce@cpan.org> 42 43 =cut