X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCarp.pm;h=393b126d4a22f08ea3fb2a5d31a5489f4f1f31e6;hb=8d5f6fc7a37e9f9386ec9c97cc0b1609d9c13e71;hp=ec08d30c1943b9a9860eaa38fd8398ac65b8fb60;hpb=d43563dda8f974d66e255d10af6e34c09bb46cb4;p=p5sagit%2Fp5-mst-13.2.git diff --git a/lib/Carp.pm b/lib/Carp.pm index ec08d30..393b126 100644 --- a/lib/Carp.pm +++ b/lib/Carp.pm @@ -1,10 +1,62 @@ package Carp; +our $VERSION = '1.08'; +# this file is an utra-lightweight stub. The first time a function is +# called, Carp::Heavy is loaded, and the real short/longmessmess_jmp +# subs are installed + +our $MaxEvalLen = 0; +our $Verbose = 0; +our $CarpLevel = 0; +our $MaxArgLen = 64; # How much of each argument to print. 0 = all. +our $MaxArgNums = 8; # How many arguments to print. 0 = all. + +require Exporter; +our @ISA = ('Exporter'); +our @EXPORT = qw(confess croak carp); +our @EXPORT_OK = qw(cluck verbose longmess shortmess); +our @EXPORT_FAIL = qw(verbose); # hook to enable verbose mode + +# if the caller specifies verbose usage ("perl -MCarp=verbose script.pl") +# then the following method will be called by the Exporter which knows +# to do this thanks to @EXPORT_FAIL, above. $_[1] will contain the word +# 'verbose'. + +sub export_fail { shift; $Verbose = shift if $_[0] eq 'verbose'; @_ } + +# fixed hooks for stashes to point to +sub longmess { goto &longmess_jmp } +sub shortmess { goto &shortmess_jmp } +# these two are replaced when Carp::Heavy is loaded +sub longmess_jmp { + local($@, $!); + eval { require Carp::Heavy }; + return $@ if $@; + goto &longmess_real; +} +sub shortmess_jmp { + local($@, $!); + eval { require Carp::Heavy }; + return $@ if $@; + goto &shortmess_real; +} + +sub croak { die shortmess @_ } +sub confess { die longmess @_ } +sub carp { warn shortmess @_ } +sub cluck { warn longmess @_ } + +1; +__END__ + =head1 NAME -carp - warn of errors (from perspective of caller) +carp - warn of errors (from perspective of caller) + +cluck - warn of errors with stack backtrace + (not exported by default) -croak - die of errors (from perspective of caller) +croak - die of errors (from perspective of caller) confess - die of errors with stack backtrace @@ -13,118 +65,173 @@ confess - die of errors with stack backtrace use Carp; croak "We're outta here!"; + use Carp qw(cluck); + cluck "This is how we got here!"; + =head1 DESCRIPTION The Carp routines are useful in your own modules because -they act like die() or warn(), but report where the error -was in the code they were called from. Thus if you have a -routine Foo() that has a carp() in it, then the carp() -will report the error as occurring where Foo() was called, -not where carp() was called. +they act like die() or warn(), but with a message which is more +likely to be useful to a user of your module. In the case of +cluck, confess, and longmess that context is a summary of every +call in the call-stack. For a shorter message you can use C +or C which report the error as being from where your module +was called. There is no guarantee that that is where the error +was, but it is a good educated guess. -=cut +You can also alter the way the output and logic of C works, by +changing some global variables in the C namespace. See the +section on C below. -# This package implements handy routines for modules that wish to throw -# exceptions outside of the current package. +Here is a more complete description of how c and c work. +What they do is search the call-stack for a function call stack where +they have not been told that there shouldn't be an error. If every +call is marked safe, they give up and give a full stack backtrace +instead. In other words they presume that the first likely looking +potential suspect is guilty. Their rules for telling whether +a call shouldn't generate errors work as follows: -$CarpLevel = 0; # How many extra package levels to skip on carp. -$MaxEvalLen = 0; # How much eval '...text...' to show. 0 = all. -$MaxArgLen = 64; # How much of each argument to print. 0 = all. -$MaxArgNums = 8; # How many arguments to print. 0 = all. +=over 4 -require Exporter; -@ISA = Exporter; -@EXPORT = qw(confess croak carp); - -sub longmess { - my $error = join '', @_; - my $mess = ""; - my $i = 1 + $CarpLevel; - my ($pack,$file,$line,$sub,$hargs,$eval,$require); - my (@a); - while (do { { package DB; @a = caller($i++) } } ) { - ($pack,$file,$line,$sub,$hargs,undef,$eval,$require) = @a; - if ($error =~ m/\n$/) { - $mess .= $error; - } else { - if (defined $eval) { - if ($require) { - $sub = "require $eval"; - } else { - $eval =~ s/([\\\'])/\\$1/g; - if ($MaxEvalLen && length($eval) > $MaxEvalLen) { - substr($eval,$MaxEvalLen) = '...'; - } - $sub = "eval '$eval'"; - } - } elsif ($sub eq '(eval)') { - $sub = 'eval {...}'; - } - if ($hargs) { - @a = @DB::args; # must get local copy of args - if ($MaxArgNums and @a > $MaxArgNums) { - $#a = $MaxArgNums; - $a[$#a] = "..."; - } - for (@a) { - $_ = "undef", next unless defined $_; - s/'/\\'/g; - substr($_,$MaxArgLen) = '...' if $MaxArgLen and $MaxArgLen < length; - s/([^\0]*)/'$1'/ unless /^-?[\d.]+$/; - s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg; - s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg; - } - $sub .= '(' . join(', ', @a) . ')'; - } - $mess .= "\t$sub " if $error eq "called"; - $mess .= "$error at $file line $line\n"; - } - $error = "called"; - } - $mess || $error; -} +=item 1. -sub shortmess { # Short-circuit &longmess if called via multiple packages - my $error = join '', @_; - my ($prevpack) = caller(1); - my $extra = $CarpLevel; - my $i = 2; - my ($pack,$file,$line); - my %isa = ($prevpack,1); - - @isa{@{"${prevpack}::ISA"}} = () - if(defined @{"${prevpack}::ISA"}); - - while (($pack,$file,$line) = caller($i++)) { - if(defined @{$pack . "::ISA"}) { - my @i = @{$pack . "::ISA"}; - my %i; - @i{@i} = (); - @isa{@i,$pack} = () - if(exists $i{$prevpack} || exists $isa{$pack}); - } - - next - if(exists $isa{$pack}); - - if ($extra-- > 0) { - %isa = ($pack,1); - @isa{@{$pack . "::ISA"}} = () - if(defined @{$pack . "::ISA"}); - } - else { - return "$error at $file line $line\n"; - } - } - continue { - $prevpack = $pack; - } - - goto &longmess; -} +Any call from a package to itself is safe. -sub confess { die longmess @_; } -sub croak { die shortmess @_; } -sub carp { warn shortmess @_; } +=item 2. + +Packages claim that there won't be errors on calls to or from +packages explicitly marked as safe by inclusion in C<@CARP_NOT>, or +(if that array is empty) C<@ISA>. The ability to override what +@ISA says is new in 5.8. + +=item 3. + +The trust in item 2 is transitive. If A trusts B, and B +trusts C, then A trusts C. So if you do not override C<@ISA> +with C<@CARP_NOT>, then this trust relationship is identical to, +"inherits from". + +=item 4. + +Any call from an internal Perl module is safe. (Nothing keeps +user modules from marking themselves as internal to Perl, but +this practice is discouraged.) + +=item 5. + +Any call to Perl's warning system (eg Carp itself) is safe. +(This rule is what keeps it from reporting the error at the +point where you call C or C.) + +=item 6. + +C<$Carp::CarpLevel> can be set to skip a fixed number of additional +call levels. Using this is not recommended because it is very +difficult to get it to behave correctly. + +=back + +=head2 Forcing a Stack Trace + +As a debugging aid, you can force Carp to treat a croak as a confess +and a carp as a cluck across I modules. In other words, force a +detailed stack trace to be given. This can be very helpful when trying +to understand why, or from where, a warning or error is being generated. + +This feature is enabled by 'importing' the non-existent symbol +'verbose'. You would typically enable it by saying + + perl -MCarp=verbose script.pl + +or by including the string C in the PERL5OPT +environment variable. + +Alternately, you can set the global variable C<$Carp::Verbose> to true. +See the C section below. + +=head1 GLOBAL VARIABLES + +=head2 $Carp::MaxEvalLen + +This variable determines how many characters of a string-eval are to +be shown in the output. Use a value of C<0> to show all text. + +Defaults to C<0>. + +=head2 $Carp::MaxArgLen + +This variable determines how many characters of each argument to a +function to print. Use a value of C<0> to show the full length of the +argument. + +Defaults to C<64>. + +=head2 $Carp::MaxArgNums + +This variable determines how many arguments to each function to show. +Use a value of C<0> to show all arguments to a function call. + +Defaults to C<8>. + +=head2 $Carp::Verbose + +This variable makes C and C generate stack backtraces +just like C and C. This is how C +is implemented internally. + +Defaults to C<0>. + +=head2 %Carp::Internal + +This says what packages are internal to Perl. C will never +report an error as being from a line in a package that is internal to +Perl. For example: + + $Carp::Internal{ __PACKAGE__ }++; + # time passes... + sub foo { ... or confess("whatever") }; + +would give a full stack backtrace starting from the first caller +outside of __PACKAGE__. (Unless that package was also internal to +Perl.) + +=head2 %Carp::CarpInternal + +This says which packages are internal to Perl's warning system. For +generating a full stack backtrace this is the same as being internal +to Perl, the stack backtrace will not start inside packages that are +listed in C<%Carp::CarpInternal>. But it is slightly different for +the summary message generated by C or C. There errors +will not be reported on any lines that are calling packages in +C<%Carp::CarpInternal>. + +For example C itself is listed in C<%Carp::CarpInternal>. +Therefore the full stack backtrace from C will not start +inside of C, and the short message from calling C is +not placed on the line where C was called. + +=head2 $Carp::CarpLevel + +This variable determines how many additional call frames are to be +skipped that would not otherwise be when reporting where an error +occurred on a call to one of C's functions. It is fairly easy +to count these call frames on calls that generate a full stack +backtrace. However it is much harder to do this accounting for calls +that generate a short message. Usually people skip too many call +frames. If they are lucky they skip enough that C goes all of +the way through the call stack, realizes that something is wrong, and +then generates a full stack backtrace. If they are unlucky then the +error is reported from somewhere misleading very high in the call +stack. + +Therefore it is best to avoid C<$Carp::CarpLevel>. Instead use +C<@CARP_NOT>, C<%Carp::Internal> and %Carp::CarpInternal>. + +Defaults to C<0>. + +=head1 BUGS + +The Carp routines don't handle exception objects currently. +If called with a first argument that is a reference, they simply +call die() or warn(), as appropriate. -1;