| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # From `The UNIX-HATERS Handbook', p.55: | 
| 2 |  |  |  |  |  |  | # | 
| 3 |  |  |  |  |  |  | #	Anyone who had both access to the source code and the | 
| 4 |  |  |  |  |  |  | #	inclination to read it soon found themselves in for a rude | 
| 5 |  |  |  |  |  |  | #	surprise: | 
| 6 |  |  |  |  |  |  | # | 
| 7 |  |  |  |  |  |  | #		/* You are not expected to understand this */ | 
| 8 |  |  |  |  |  |  | # | 
| 9 |  |  |  |  |  |  | #	Although this comment originally appeared in the Unix V6 kernel | 
| 10 |  |  |  |  |  |  | #	source code, it could easily have applied to any of the original | 
| 11 |  |  |  |  |  |  | #	AT&T code, which was a nightmare of in-line hand-optimizations | 
| 12 |  |  |  |  |  |  | #	and micro hacks. | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | package B::PerlReq; | 
| 15 |  |  |  |  |  |  | our $VERSION = '0.82'; | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 1 |  |  | 1 |  | 25478 | use 5.006; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 40 |  | 
| 18 | 1 |  |  | 1 |  | 4 | use strict; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 26 |  | 
| 19 | 1 |  |  | 1 |  | 440 | use PerlReq::Utils qw(mod2path path2dep verf verf_perl sv_version); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 277 |  | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | our @Skip = ( | 
| 22 |  |  |  |  |  |  | qr(^Makefile\b), | 
| 23 |  |  |  |  |  |  | # OS-specific | 
| 24 |  |  |  |  |  |  | qr(^machine/ansi\b),		# gcc 3.3 stddef.h (FreeBSD 4) | 
| 25 |  |  |  |  |  |  | qr(^sys/_types\b),		# gcc 3.3 stddef.h (FreeBSD 5) | 
| 26 |  |  |  |  |  |  | qr(^sys/systeminfo\b),		# solaris | 
| 27 |  |  |  |  |  |  | qr(^Convert/EBCDIC\b),		# os390 | 
| 28 |  |  |  |  |  |  | qr(^ExtUtils/XSSymSet\b),	# VMS | 
| 29 |  |  |  |  |  |  | qr(\bOS2|OS2\b), | 
| 30 |  |  |  |  |  |  | qr(\bMacPerl|\bMac\b), | 
| 31 |  |  |  |  |  |  | qr(\bMacOS|MacOS\b), | 
| 32 |  |  |  |  |  |  | qr(\bMacOSX|MacOSX\b), | 
| 33 |  |  |  |  |  |  | qr(\bvmsish\b), | 
| 34 |  |  |  |  |  |  | qr(\bVMS|VMS\b), | 
| 35 |  |  |  |  |  |  | qr(\bWin32|Win32\b), | 
| 36 |  |  |  |  |  |  | qr(\bCygwin|Cygwin\b), | 
| 37 |  |  |  |  |  |  | # most common | 
| 38 |  |  |  |  |  |  | qr(^Carp\.pm$), | 
| 39 |  |  |  |  |  |  | qr(^Exporter\.pm$), | 
| 40 |  |  |  |  |  |  | qr(^strict\.pm$), | 
| 41 |  |  |  |  |  |  | qr(^vars\.pm$), | 
| 42 |  |  |  |  |  |  | qr(^warnings\.pm$), | 
| 43 |  |  |  |  |  |  | ); | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | our ($Strict, $Relaxed, $Verbose, $Debug); | 
| 46 |  |  |  |  |  |  |  | 
| 47 | 1 |  |  | 1 |  | 449 | use B::Walker qw(const_sv); | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 2721 |  | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | sub RequiresPerl ($) { | 
| 50 | 0 |  |  | 0 | 0 |  | my $v = shift; | 
| 51 | 0 |  |  |  |  |  | my $dep = "perl-base >= " . verf_perl($v); | 
| 52 | 0 |  |  |  |  |  | my $msg = "$dep at line $B::Walker::Line (depth $B::Walker::Level)"; | 
| 53 | 0 | 0 | 0 |  |  |  | if (not $Strict and $v < 5.010) { | 
| 54 | 0 | 0 |  |  |  |  | print STDERR "# $msg old perl SKIP\n" if $Verbose; | 
| 55 | 0 |  |  |  |  |  | return; | 
| 56 |  |  |  |  |  |  | } | 
| 57 | 0 | 0 |  |  |  |  | print STDERR "# $msg REQ\n" if $Verbose; | 
| 58 | 0 |  |  |  |  |  | print "$dep\n"; | 
| 59 |  |  |  |  |  |  | } | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | # XXX prevDepF is a hack to please t/01-B-PerlReq.t | 
| 62 |  |  |  |  |  |  | my $prevDepF; | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | sub Requires ($;$) { | 
| 65 | 0 |  |  | 0 | 0 |  | my ($f, $v) = @_; | 
| 66 | 0 | 0 |  |  |  |  | my $dep = path2dep($f) . ($v ? " >= " . verf($v) : ""); | 
| 67 | 0 |  |  |  |  |  | my $msg = "$dep at line $B::Walker::Line (depth $B::Walker::Level)"; | 
| 68 | 0 | 0 |  |  |  |  | if ($f !~ m#^\w+(?:[/-]\w+)*[.]p[lmh]$#) { # bits/ioctl-types.ph | 
| 69 | 0 |  |  |  |  |  | print STDERR "# $msg invalid SKIP\n"; | 
| 70 | 0 |  |  |  |  |  | return; | 
| 71 |  |  |  |  |  |  | } | 
| 72 | 0 | 0 | 0 |  |  |  | if ($B::Walker::Sub eq "BEGIN" and not $INC{$f} and $B::Walker::Opname ne "autouse") { | 
|  |  |  | 0 |  |  |  |  | 
| 73 | 0 |  |  |  |  |  | print STDERR "# $msg not loaded at BEGIN SKIP\n"; | 
| 74 | 0 |  |  |  |  |  | return; | 
| 75 |  |  |  |  |  |  | } | 
| 76 | 0 | 0 | 0 |  |  |  | if (not $Strict and grep { $f =~ $_ } @Skip) { | 
|  | 0 |  |  |  |  |  |  | 
| 77 | 0 | 0 |  |  |  |  | print STDERR "# $msg builtin SKIP\n" if $Verbose; | 
| 78 | 0 |  |  |  |  |  | return; | 
| 79 |  |  |  |  |  |  | } | 
| 80 | 0 | 0 | 0 |  |  |  | if ($B::Walker::Sub eq "BEGIN" and $INC{$f}) { | 
| 81 | 0 |  |  |  |  |  | goto req; | 
| 82 |  |  |  |  |  |  | } | 
| 83 | 0 | 0 | 0 |  |  |  | if (not $Strict and $B::Walker::BlockData{Eval}) { | 
| 84 | 0 |  |  |  |  |  | print STDERR "# $msg inside eval SKIP\n"; | 
| 85 | 0 |  |  |  |  |  | return; | 
| 86 |  |  |  |  |  |  | } | 
| 87 | 0 | 0 | 0 |  |  |  | if ($Relaxed and $B::Walker::Level > 4) { | 
| 88 | 0 |  |  |  |  |  | print STDERR "# $msg deep SKIP\n"; | 
| 89 | 0 |  |  |  |  |  | return; | 
| 90 |  |  |  |  |  |  | } | 
| 91 | 0 | 0 |  |  |  |  | req:	print STDERR "# $msg REQ\n" if $Verbose; | 
| 92 | 0 | 0 | 0 |  |  |  | if ($prevDepF and $prevDepF ne $f) { | 
| 93 | 0 |  |  |  |  |  | print path2dep($prevDepF) . "\n"; | 
| 94 |  |  |  |  |  |  | } | 
| 95 | 0 |  |  |  |  |  | undef $prevDepF; | 
| 96 | 0 | 0 |  |  |  |  | if ($v) { | 
| 97 | 0 |  |  |  |  |  | print "$dep\n"; | 
| 98 |  |  |  |  |  |  | } else { | 
| 99 | 0 |  |  |  |  |  | $prevDepF = $f; | 
| 100 |  |  |  |  |  |  | } | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  | sub finalize { | 
| 103 | 0 | 0 |  | 0 | 0 |  | print path2dep($prevDepF) . "\n" | 
| 104 |  |  |  |  |  |  | if $prevDepF; | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | sub check_encoding ($) { | 
| 108 | 0 |  |  | 0 | 0 |  | my $enc = shift; | 
| 109 | 0 | 0 |  |  |  |  | eval { local $SIG{__DIE__}; require Encode; } or do { | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 110 | 0 |  |  |  |  |  | print STDERR "Encode.pm not available at $0 line $B::Walker::Line\n"; | 
| 111 | 0 |  |  |  |  |  | return; | 
| 112 |  |  |  |  |  |  | }; | 
| 113 | 0 | 0 |  |  |  |  | my $e = Encode::resolve_alias($enc) or do { | 
| 114 | 0 |  |  |  |  |  | print STDERR "invalid encoding $enc at $0 line $B::Walker::Line\n"; | 
| 115 | 0 |  |  |  |  |  | return; | 
| 116 |  |  |  |  |  |  | }; | 
| 117 | 0 | 0 | 0 |  |  |  | my $mod = $Encode::ExtModule{$e} || $Encode::ExtModule{lc($e)} or do { | 
| 118 | 0 |  |  |  |  |  | print STDERR "no module for encoding $enc at $0 line $B::Walker::Line\n"; | 
| 119 | 0 |  |  |  |  |  | return; | 
| 120 |  |  |  |  |  |  | }; | 
| 121 | 0 |  |  |  |  |  | Requires(mod2path($mod)); | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | sub check_perlio_string ($) { | 
| 125 | 0 |  |  | 0 | 0 |  | local $_ = shift; | 
| 126 | 0 |  |  |  |  |  | while (s/\b(\w+)[(](\S+?)[)]//g) { | 
| 127 | 0 |  |  |  |  |  | Requires("PerlIO.pm"); | 
| 128 | 0 |  |  |  |  |  | Requires("PerlIO/$1.pm"); | 
| 129 | 0 | 0 |  |  |  |  | if ($1 eq "encoding") { | 
| 130 | 0 |  |  |  |  |  | Requires("Encode.pm"); | 
| 131 | 0 |  |  |  |  |  | check_encoding($2); | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  | } | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | sub grok_perlio ($) { | 
| 137 | 0 |  |  | 0 | 0 |  | my $op = shift; | 
| 138 | 0 |  |  |  |  |  | my $opname = $op->name; | 
| 139 | 0 | 0 |  |  |  |  | $op = $op->first; return unless $$op;		# pushmark | 
|  | 0 |  |  |  |  |  |  | 
| 140 | 0 | 0 |  |  |  |  | $op = $op->sibling; return unless $$op;		# gv[*FH] -- arg1 | 
|  | 0 |  |  |  |  |  |  | 
| 141 | 0 | 0 | 0 |  |  |  | $op = $op->sibling; return unless $$op and $op->name eq "const"; | 
|  | 0 |  |  |  |  |  |  | 
| 142 | 0 | 0 |  |  |  |  | my $sv = const_sv($op); return unless $sv->can("PV"); | 
|  | 0 |  |  |  |  |  |  | 
| 143 | 0 |  |  |  |  |  | local $B::Walker::Opname = $opname; | 
| 144 | 0 |  |  |  |  |  | my $arg2 = $sv->PV; $arg2 =~ s/\s//g; | 
|  | 0 |  |  |  |  |  |  | 
| 145 | 0 | 0 |  |  |  |  | if ($opname eq "open") { | 
| 146 | 0 | 0 |  |  |  |  | return unless $arg2 =~ s/^[+]?[<>]+//;	# validate arg2 | 
| 147 | 0 | 0 |  |  |  |  | $op = $op->sibling; return unless $$op;	# arg3 required | 
|  | 0 |  |  |  |  |  |  | 
| 148 | 0 | 0 |  |  |  |  | if ($op->name eq "srefgen") {		# check arg3 | 
| 149 | 0 |  |  |  |  |  | Requires("PerlIO.pm"); | 
| 150 | 0 |  |  |  |  |  | Requires("PerlIO/scalar.pm"); | 
| 151 |  |  |  |  |  |  | } | 
| 152 |  |  |  |  |  |  | } | 
| 153 | 0 |  |  |  |  |  | check_perlio_string($arg2); | 
| 154 |  |  |  |  |  |  | } | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  | sub grok_require ($) { | 
| 157 | 0 |  |  | 0 | 0 |  | my $op = shift; | 
| 158 | 0 | 0 |  |  |  |  | return unless $op->first->name eq "const"; | 
| 159 | 0 |  |  |  |  |  | my $sv = const_sv($op->first); | 
| 160 | 0 |  |  |  |  |  | my $v = sv_version($sv); | 
| 161 | 0 | 0 |  |  |  |  | defined($v) | 
| 162 |  |  |  |  |  |  | ? RequiresPerl($v) | 
| 163 |  |  |  |  |  |  | : Requires($sv->PV) | 
| 164 |  |  |  |  |  |  | ; | 
| 165 |  |  |  |  |  |  | } | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | sub grok_args ($) { | 
| 168 | 0 |  |  | 0 | 0 |  | my $op = shift; | 
| 169 | 0 |  |  |  |  |  | my @args; | 
| 170 | 0 |  | 0 |  |  |  | while ($$op and $op->name eq "const") { | 
| 171 | 0 |  |  |  |  |  | my $sv = const_sv($op); | 
| 172 | 0 |  |  |  |  |  | my $arg; | 
| 173 | 0 | 0 |  |  |  |  | if (ref($sv) eq "B::SPECIAL") { | 
| 174 | 0 | 0 |  |  |  |  | if ($$sv == ${B::sv_yes()}) { | 
|  | 0 | 0 |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 175 | 0 |  |  |  |  |  | $arg = (1 == 1); | 
| 176 |  |  |  |  |  |  | } | 
| 177 |  |  |  |  |  |  | elsif ($$sv == ${B::sv_no()}) { | 
| 178 | 0 |  |  |  |  |  | $arg = (1 == 0); | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  | } | 
| 181 |  |  |  |  |  |  | else { | 
| 182 | 0 |  |  |  |  |  | $arg = ${$sv->object_2svref}; | 
|  | 0 |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | } | 
| 184 | 0 |  |  |  |  |  | push @args, $arg; | 
| 185 | 0 |  |  |  |  |  | $op = $op->sibling; | 
| 186 |  |  |  |  |  |  | } | 
| 187 | 0 |  |  |  |  |  | return @args; | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | sub grok_import ($$$) { | 
| 191 | 0 |  |  | 0 | 0 |  | my ($class, undef, $op) = @_; | 
| 192 | 0 | 0 |  |  |  |  | my @args = grok_args($op) or return; | 
| 193 | 0 |  |  |  |  |  | local $B::Walker::Opname = $class; | 
| 194 | 0 | 0 | 0 |  |  |  | if ($class eq "base" or $class eq "parent") { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 195 | 0 |  |  |  |  |  | foreach my $m (@args) { | 
| 196 | 0 |  |  |  |  |  | my $f = mod2path($m); | 
| 197 |  |  |  |  |  |  | # XXX Requires($f) if $INC{$f}; | 
| 198 | 0 |  |  |  |  |  | foreach (@INC) { | 
| 199 | 0 | 0 |  |  |  |  | if (-f "$_/$f") { | 
| 200 | 0 |  |  |  |  |  | Requires($f); | 
| 201 | 0 |  |  |  |  |  | last; | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  | } | 
| 204 |  |  |  |  |  |  | } | 
| 205 |  |  |  |  |  |  | } | 
| 206 |  |  |  |  |  |  | elsif ($class eq "autouse") { | 
| 207 | 0 |  |  |  |  |  | my $f = mod2path($args[0]); | 
| 208 | 0 |  |  |  |  |  | Requires($f); | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  | elsif ($class eq "encoding") { | 
| 211 | 0 |  |  |  |  |  | require Config; | 
| 212 | 0 | 0 |  |  |  |  | Requires("PerlIO/encoding.pm") if $Config::Config{useperlio}; | 
| 213 | 0 | 0 |  |  |  |  | check_encoding($args[0]) if $args[0] =~ /^[^:]/; | 
| 214 | 0 | 0 |  |  |  |  | Requires("Filter/Util/Call.pm") if grep { $_ eq "Filter" } @args; | 
|  | 0 |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | } | 
| 216 |  |  |  |  |  |  | elsif ($class eq "overload") { | 
| 217 |  |  |  |  |  |  | # avoid version check for << use overload "0+" => ... >> | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  | elsif ($class eq "if") { | 
| 220 | 0 |  |  |  |  |  | my $f = mod2path($args[1]); | 
| 221 | 0 | 0 |  |  |  |  | Requires($f) if $args[0]; | 
| 222 |  |  |  |  |  |  | } | 
| 223 |  |  |  |  |  |  | elsif ($args[0] =~ /^\d/) { | 
| 224 |  |  |  |  |  |  | # the first import arg is possibly a version, see Exporter/Heavy.pm | 
| 225 | 0 |  |  |  |  |  | my $sv = const_sv($op); | 
| 226 | 0 |  |  |  |  |  | my $v = sv_version($sv); | 
| 227 | 0 |  |  |  |  |  | my $f = mod2path($class); | 
| 228 | 0 | 0 |  |  |  |  | Requires($f, $v) if $v; | 
| 229 |  |  |  |  |  |  | } | 
| 230 |  |  |  |  |  |  | } | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  | sub grok_version ($$$) { | 
| 233 | 0 |  |  | 0 | 0 |  | my ($class, undef, $op) = @_; | 
| 234 | 0 | 0 |  |  |  |  | return unless $op->name eq "const"; | 
| 235 | 0 |  |  |  |  |  | my $sv = const_sv($op); | 
| 236 | 0 |  |  |  |  |  | my $version = sv_version($sv); | 
| 237 | 0 | 0 |  |  |  |  | return unless $version; | 
| 238 | 0 |  |  |  |  |  | my $f = mod2path($class); | 
| 239 | 0 |  |  |  |  |  | local $B::Walker::Opname = "version"; | 
| 240 | 0 |  |  |  |  |  | Requires($f, $version); | 
| 241 |  |  |  |  |  |  | } | 
| 242 |  |  |  |  |  |  |  | 
| 243 |  |  |  |  |  |  | sub grok_new { | 
| 244 | 0 |  |  | 0 | 0 |  | my ($class, undef, $op) = @_; | 
| 245 | 0 | 0 |  |  |  |  | if ($class eq "IO::File") { | 
| 246 | 0 | 0 |  |  |  |  | if ($op->name eq "srefgen") { | 
| 247 | 0 |  |  |  |  |  | Requires("PerlIO.pm"); | 
| 248 | 0 |  |  |  |  |  | Requires("PerlIO/scalar.pm"); | 
| 249 |  |  |  |  |  |  | } | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  | } | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | our %methods = ( | 
| 254 |  |  |  |  |  |  | 'import' => \&grok_import, | 
| 255 |  |  |  |  |  |  | 'VERSION' => \&grok_version, | 
| 256 |  |  |  |  |  |  | 'require_version' => \&grok_version, | 
| 257 |  |  |  |  |  |  | 'new' => \&grok_new, | 
| 258 |  |  |  |  |  |  | ); | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | sub grok_with { | 
| 261 | 0 | 0 |  | 0 | 0 |  | return unless $INC{"Moose.pm"}; | 
| 262 | 0 |  |  |  |  |  | my (undef, $op) = @_; | 
| 263 | 0 |  |  |  |  |  | my @args = grok_args($op); | 
| 264 | 0 |  |  |  |  |  | for my $m (@args) { | 
| 265 | 0 | 0 |  |  |  |  | next unless $m =~ /^\w+(?:::\w+)+\z/; | 
| 266 | 0 |  |  |  |  |  | my $f = mod2path($m); | 
| 267 | 0 |  |  |  |  |  | Requires($f); | 
| 268 |  |  |  |  |  |  | } | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | my %TryCV; | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | sub grok_try { | 
| 274 | 0 | 0 |  | 0 | 0 |  | return unless $INC{"Try/Tiny.pm"}; | 
| 275 | 0 |  |  |  |  |  | my (undef, $op) = @_; | 
| 276 | 0 | 0 |  |  |  |  | return unless $op->name eq "refgen"; | 
| 277 | 0 |  |  |  |  |  | $op = $op->first->first->sibling; | 
| 278 | 0 | 0 |  |  |  |  | return unless $op->name eq "anoncode"; | 
| 279 | 0 |  |  |  |  |  | my $cv = padval($op->targ); | 
| 280 | 0 |  |  |  |  |  | $TryCV{$$cv} = 1; | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | sub grok_catch { | 
| 284 |  |  |  |  |  |  | # suppress nested catch/finally deps | 
| 285 | 0 | 0 |  | 0 | 0 |  | &grok_try if $TryCV{$$B::Walker::CV}; | 
| 286 |  |  |  |  |  |  | } | 
| 287 |  |  |  |  |  |  |  | 
| 288 |  |  |  |  |  |  | our %funcs = ( | 
| 289 |  |  |  |  |  |  | 'with' => \&grok_with, | 
| 290 |  |  |  |  |  |  | 'try' => \&grok_try, | 
| 291 |  |  |  |  |  |  | 'catch' => \&grok_catch, | 
| 292 |  |  |  |  |  |  | 'finally' => \&grok_catch, | 
| 293 |  |  |  |  |  |  | ); | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | sub grok_entersub ($) { | 
| 296 | 0 |  |  | 0 | 0 |  | my $op = shift; | 
| 297 | 0 |  |  |  |  |  | $op = $op->first; | 
| 298 | 0 | 0 |  |  |  |  | $op = $op->first unless ${$op->sibling}; | 
|  | 0 |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  | # die "not pushmark" unless $op->name eq "pushmark"; | 
| 300 | 0 |  |  |  |  |  | my $args = $op = $op->sibling; | 
| 301 | 0 |  |  |  |  |  | while (${$op->sibling}) { | 
|  | 0 |  |  |  |  |  |  | 
| 302 | 0 | 0 | 0 |  |  |  | last if $op->name eq "method" or | 
| 303 |  |  |  |  |  |  | $op->name eq "method_named"; | 
| 304 | 0 |  |  |  |  |  | $op = $op->sibling; | 
| 305 |  |  |  |  |  |  | } | 
| 306 | 0 | 0 |  |  |  |  | if ($op->name eq "method_named") { | 
|  |  | 0 |  |  |  |  |  | 
| 307 | 0 |  |  |  |  |  | my $method = const_sv($op)->PV; | 
| 308 | 0 | 0 |  |  |  |  | return unless $methods{$method}; | 
| 309 | 0 | 0 |  |  |  |  | return unless $args->name eq "const"; | 
| 310 | 0 |  |  |  |  |  | my $sv = const_sv($args); | 
| 311 | 0 | 0 |  |  |  |  | return unless $sv->can("PV"); | 
| 312 | 0 |  |  |  |  |  | my $class = $sv->PV; | 
| 313 | 0 |  |  |  |  |  | $args = $args->sibling; | 
| 314 | 0 |  |  |  |  |  | $methods{$method}->($class, $method, $args); | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  | elsif ($op->first->name eq "gv") { | 
| 317 | 0 |  |  |  |  |  | $op = $op->first; | 
| 318 | 1 |  |  | 1 |  | 8 | use B::Walker qw(padval); | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 137 |  | 
| 319 | 0 |  |  |  |  |  | my $func = padval($op->padix)->NAME; | 
| 320 | 0 | 0 |  |  |  |  | return unless $funcs{$func}; | 
| 321 | 0 |  |  |  |  |  | $funcs{$func}->($func, $args); | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | sub grok_padsv { | 
| 326 | 0 |  |  | 0 | 0 |  | my $op = shift; | 
| 327 | 1 |  |  | 1 |  | 4 | use B qw(OPpLVAL_INTRO); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 75 |  | 
| 328 | 0 | 0 |  |  |  |  | return unless $op->private & OPpLVAL_INTRO; | 
| 329 | 1 |  |  | 1 |  | 5 | use B::Walker qw(padname); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 116 |  | 
| 330 | 0 |  |  |  |  |  | my $padsv = padname($op->targ); | 
| 331 | 0 | 0 |  |  |  |  | return unless $padsv->can('PV'); | 
| 332 | 0 | 0 |  |  |  |  | RequiresPerl(5.010) if $padsv->PV eq '$_'; | 
| 333 | 1 | 50 |  |  |  | 942 | use constant OPpPAD_STATE => | 
| 334 | 1 |  |  | 1 |  | 5 | defined &B::OPpPAD_STATE ? &B::OPpPAD_STATE : 0; | 
|  | 1 |  |  |  |  | 2 |  | 
| 335 | 0 | 0 |  |  |  |  | RequiresPerl(5.010) if $op->private & OPpPAD_STATE; | 
| 336 |  |  |  |  |  |  | } | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | my %filetests = map { $_ => 1 } | 
| 339 |  |  |  |  |  |  | qw(ftrread ftrwrite ftrexec fteread ftewrite fteexec ftis ftsize | 
| 340 |  |  |  |  |  |  | ftmtime ftatime ftctime ftrowned fteowned ftzero ftsock ftchr ftblk | 
| 341 |  |  |  |  |  |  | ftfile ftdir ftpipe ftsuid ftsgid ftsvtx ftlink fttty fttext ftbinary); | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | sub grok_filetest { | 
| 344 | 0 |  |  | 0 | 0 |  | my $op = shift; | 
| 345 | 0 | 0 |  |  |  |  | return unless $filetests{$op->next->name}; | 
| 346 | 0 | 0 |  |  |  |  | return if $filetests{$op->first->name}; | 
| 347 | 0 |  |  |  |  |  | RequiresPerl(5.010); | 
| 348 |  |  |  |  |  |  | } | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | %B::Walker::Ops = ( | 
| 351 |  |  |  |  |  |  | 'require'	=> \&grok_require, | 
| 352 |  |  |  |  |  |  | 'dofile'	=> \&grok_require, | 
| 353 |  |  |  |  |  |  | 'entersub'	=> \&grok_entersub, | 
| 354 |  |  |  |  |  |  | 'open'		=> \&grok_perlio, | 
| 355 |  |  |  |  |  |  | 'binmode'	=> \&grok_perlio, | 
| 356 |  |  |  |  |  |  | 'dbmopen'	=> sub { Requires("AnyDBM_File.pm") }, | 
| 357 |  |  |  |  |  |  | 'leavetry'	=> sub { $B::Walker::BlockData{Eval} = $B::Walker::Level }, | 
| 358 |  |  |  |  |  |  | 'leavesub'	=> sub { $B::Walker::BlockData{Eval} = $B::Walker::Level if $TryCV{$$B::Walker::CV} }, | 
| 359 |  |  |  |  |  |  | 'leave'		=> sub { $B::Walker::BlockData{Eval} = $B::Walker::Level if $TryCV{$$B::Walker::CV} }, | 
| 360 |  |  |  |  |  |  | 'dor'		=> sub { RequiresPerl(5.010) }, | 
| 361 |  |  |  |  |  |  | 'dorassign'	=> sub { RequiresPerl(5.010) }, | 
| 362 |  |  |  |  |  |  | 'leavegiven'	=> sub { RequiresPerl(5.010) }, | 
| 363 |  |  |  |  |  |  | 'leavewhen'	=> sub { RequiresPerl(5.010) }, | 
| 364 |  |  |  |  |  |  | 'smartmatch'	=> sub { RequiresPerl(5.010) }, | 
| 365 |  |  |  |  |  |  | 'say'		=> sub { RequiresPerl(5.010) }, | 
| 366 |  |  |  |  |  |  | 'padsv'		=> \&grok_padsv, | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | map { $_	=> \&grok_filetest } keys %filetests, | 
| 369 |  |  |  |  |  |  | ); | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | sub compile { | 
| 372 | 0 |  |  | 0 | 0 |  | my $pkg = __PACKAGE__; | 
| 373 | 0 |  |  |  |  |  | for my $opt (@_) { | 
| 374 | 0 | 0 | 0 |  |  |  | $opt =~ /^-(?:s|-?strict)$/	and $Strict = 1 or | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 375 |  |  |  |  |  |  | $opt =~ /^-(?:r|-?relaxed)$/	and $Relaxed = 1 or | 
| 376 |  |  |  |  |  |  | $opt =~ /^-(?:v|-?verbose)$/	and $Verbose = 1 or | 
| 377 |  |  |  |  |  |  | $opt =~ /^-(?:d|-?debug)$/	and $Verbose = $Debug = 1 or | 
| 378 |  |  |  |  |  |  | die "$pkg: unknown option: $opt\n"; | 
| 379 |  |  |  |  |  |  | } | 
| 380 | 0 | 0 | 0 |  |  |  | die "$pkg: options -strict and -relaxed are mutually exclusive\n" | 
| 381 |  |  |  |  |  |  | if $Strict and $Relaxed; | 
| 382 |  |  |  |  |  |  | return sub { | 
| 383 | 0 |  |  | 0 |  |  | $| = 1; | 
| 384 |  |  |  |  |  |  | local $SIG{__DIE__} = sub { | 
| 385 |  |  |  |  |  |  | # checking $^S is unreliable because O.pm uses eval | 
| 386 | 0 |  |  |  |  |  | print STDERR "dying at $0 line $B::Walker::Line\n"; | 
| 387 | 0 |  |  |  |  |  | require Carp; | 
| 388 | 0 |  |  |  |  |  | Carp::cluck(); | 
| 389 | 0 |  |  |  |  |  | }; | 
| 390 | 0 |  |  |  |  |  | B::Walker::walk_blocks(); | 
| 391 | 0 |  |  |  |  |  | B::Walker::walk_main(); | 
| 392 | 0 | 0 |  |  |  |  | B::Walker::walk_subs() if not $Relaxed; | 
| 393 | 0 |  |  |  |  |  | finalize(); | 
| 394 | 0 |  |  |  |  |  | }; | 
| 395 |  |  |  |  |  |  | } | 
| 396 |  |  |  |  |  |  |  | 
| 397 |  |  |  |  |  |  | END { | 
| 398 | 1 | 50 |  | 1 |  | 6434559 | print STDERR "# Eval=$B::Walker::BlockData{Eval}\n" if $B::Walker::BlockData{Eval}; | 
| 399 |  |  |  |  |  |  | } | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | 1; | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | __END__ |