This can be done, but not quite as simply as you had perhaps hoped
use strict;
use warnings;
## disable perl's warning mechanism
no warnings 'recursion';
use B 'svref_2object';
use Symbol 'qualify_to_ref';
sub change_depth_warn {
my($subname, $limit) = @_;
my $subref = \&$subname;
my $gv = svref_2object($subref)->GV;
my $lineno = 0;
no warnings 'redefine';
*{ qualify_to_ref $subname } = sub {
if( $gv->CV->DEPTH % $limit == 0 ) {
$lineno = do {
my $i = 0;
1 while caller $i++;
(caller($i - 2))[2]
} unless $lineno;
warn
sprintf "Deep recursion on subroutine '%s' at %s line %d.\n",
join('::', $gv->STASH->NAME, $gv->NAME), $0, $lineno;
}
&$subref(@_);
};
}
my $cnt = 0;
sub foo { &foo while $cnt++ < $_[0] }
my $maxdepth = 1000;
my $recdepth = 3000;
change_depth_warn('foo', $maxdepth);
printf "calling foo(), expecting %d warnings ...\n",
$recdepth / $maxdepth;
foo($recdepth);
__output__
calling foo(), expecting 3 warnings ...
Deep recursion on subroutine 'main::foo' at perlmonks/pmsopw_324564.pl
+ line 43.
Deep recursion on subroutine 'main::foo' at perlmonks/pmsopw_324564.pl
+ line 43.
Deep recursion on subroutine 'main::foo' at perlmonks/pmsopw_324564.pl
+ line 43.
So that disables the recursion warning, and then wraps the foo() in a closure that emits a recursion warning for every $limitth recursion.
| [reply] [Watch: Dir/Any] [d/l] |
Post that on CPAN in something - anything. I can see great utility in that. Maybe as a pragma?
use warnings::recursion 1000;
------
We are the carpenters and bricklayers of the Information Age.
Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.
| [reply] [Watch: Dir/Any] [d/l] |
pp_hot.c
if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION)
&& !(PERLDB_SUB && cv == GvCV(PL_DBsub)))
sub_crush_depth(cv);
pp_ctl.c
if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION))
sub_crush_depth(cv);
| [reply] [Watch: Dir/Any] [d/l] [select] |
In addition to the debugging and recompilation tips supplied by others above, I would recommend perhaps taking a look at the recursion algorithm itself - It may be more efficient to unroll the recursion employing a stack over which to iterate. For this task, you may find the threads Turning a recursive function into an iterator and Unrolling recursion of interest.
perl -le "print unpack'N', pack'B32', '00000000000000000000001010110110'"
| [reply] [Watch: Dir/Any] |
You'd have to "hack" perl (modify pp_hot.c ) and recompile to actually raise the limit.
It's easier just to override the $SIG{__WARN__}. See `perldoc -f warn'.
MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!" | I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README). | ** The third rule of perl club is a statement of fact: pod is sexy. |
| [reply] [Watch: Dir/Any] [d/l] |
No, its hardcoded (in two places, no less). You can rebuild perl with it changed, though (look for calls to sub_crush_depth in pp_ctl.c and pp_hot.c). | [reply] [Watch: Dir/Any] |
| [reply] [Watch: Dir/Any] [d/l] |