📄 error.pm.svn-base
字号:
# Error.pm## Copyright (c) 1997-8 Graham Barr <gbarr@ti.com>. All rights reserved.# This program is free software; you can redistribute it and/or# modify it under the same terms as Perl itself.## Based on my original Error.pm, and Exceptions.pm by Peter Seibel# <peter@weblogic.com> and adapted by Jesse Glick <jglick@sig.bsh.com>.## but modified ***significantly***package Error;use strict;use vars qw($VERSION);use 5.004;$VERSION = "0.15"; use overload ( '""' => 'stringify', '0+' => 'value', 'bool' => sub { return 1; }, 'fallback' => 1);$Error::Depth = 0; # Depth to pass to caller()$Error::Debug = 0; # Generate verbose stack traces@Error::STACK = (); # Clause stack for try$Error::THROWN = undef; # last error thrown, a workaround until die $ref worksmy $LAST; # Last error createdmy %ERROR; # Last error associated with package# Exported subs are defined in Error::subssub import { shift; local $Exporter::ExportLevel = $Exporter::ExportLevel + 1; Error::subs->import(@_);}# I really want to use last for the name of this method, but it is a keyword# which prevent the syntax last Errorsub prior { shift; # ignore return $LAST unless @_; my $pkg = shift; return exists $ERROR{$pkg} ? $ERROR{$pkg} : undef unless ref($pkg); my $obj = $pkg; my $err = undef; if($obj->isa('HASH')) { $err = $obj->{'__Error__'} if exists $obj->{'__Error__'}; } elsif($obj->isa('GLOB')) { $err = ${*$obj}{'__Error__'} if exists ${*$obj}{'__Error__'}; } $err;}# Return as much information as possible about where the error# happened. The -stacktrace element only exists if $Error::DEBUG# was set when the error was createdsub stacktrace { my $self = shift; return $self->{'-stacktrace'} if exists $self->{'-stacktrace'}; my $text = exists $self->{'-text'} ? $self->{'-text'} : "Died"; $text .= sprintf(" at %s line %d.\n", $self->file, $self->line) unless($text =~ /\n$/s); $text;}# Allow error propagation, ie## $ber->encode(...) or# return Error->prior($ber)->associate($ldap);sub associate { my $err = shift; my $obj = shift; return unless ref($obj); if($obj->isa('HASH')) { $obj->{'__Error__'} = $err; } elsif($obj->isa('GLOB')) { ${*$obj}{'__Error__'} = $err; } $obj = ref($obj); $ERROR{ ref($obj) } = $err; return;}sub new { my $self = shift; my($pkg,$file,$line) = caller($Error::Depth); my $err = bless { '-package' => $pkg, '-file' => $file, '-line' => $line, @_ }, $self; $err->associate($err->{'-object'}) if(exists $err->{'-object'}); # To always create a stacktrace would be very inefficient, so # we only do it if $Error::Debug is set if($Error::Debug) { require Carp; local $Carp::CarpLevel = $Error::Depth; my $text = defined($err->{'-text'}) ? $err->{'-text'} : "Error"; my $trace = Carp::longmess($text); # Remove try calls from the trace $trace =~ s/(\n\s+\S+__ANON__[^\n]+)?\n\s+eval[^\n]+\n\s+Error::subs::try[^\n]+(?=\n)//sog; $trace =~ s/(\n\s+\S+__ANON__[^\n]+)?\n\s+eval[^\n]+\n\s+Error::subs::run_clauses[^\n]+\n\s+Error::subs::try[^\n]+(?=\n)//sog; $err->{'-stacktrace'} = $trace } $@ = $LAST = $ERROR{$pkg} = $err;}# Throw an error. this contains some very gory code.sub throw { my $self = shift; local $Error::Depth = $Error::Depth + 1; # if we are not rethrow-ing then create the object to throw $self = $self->new(@_) unless ref($self); die $Error::THROWN = $self;}# syntactic sugar for## die with Error( ... );sub with { my $self = shift; local $Error::Depth = $Error::Depth + 1; $self->new(@_);}# syntactic sugar for## record Error( ... ) and return;sub record { my $self = shift; local $Error::Depth = $Error::Depth + 1; $self->new(@_);}# catch clause for## try { ... } catch CLASS with { ... }sub catch { my $pkg = shift; my $code = shift; my $clauses = shift || {}; my $catch = $clauses->{'catch'} ||= []; unshift @$catch, $pkg, $code; $clauses;}# Object query methodssub object { my $self = shift; exists $self->{'-object'} ? $self->{'-object'} : undef;}sub file { my $self = shift; exists $self->{'-file'} ? $self->{'-file'} : undef;}sub line { my $self = shift; exists $self->{'-line'} ? $self->{'-line'} : undef;}sub text { my $self = shift; exists $self->{'-text'} ? $self->{'-text'} : undef;}# overload methodssub stringify { my $self = shift; defined $self->{'-text'} ? $self->{'-text'} : "Died";}sub value { my $self = shift; exists $self->{'-value'} ? $self->{'-value'} : undef;}package Error::Simple;@Error::Simple::ISA = qw(Error);sub new { my $self = shift; my $text = "" . shift; my $value = shift; my(@args) = (); local $Error::Depth = $Error::Depth + 1; @args = ( -file => $1, -line => $2) if($text =~ s/ at (\S+) line (\d+)(\.\n)?$//s); push(@args, '-value', 0 + $value) if defined($value); $self->SUPER::new(-text => $text, @args);}sub stringify { my $self = shift; my $text = $self->SUPER::stringify; $text .= sprintf(" at %s line %d.\n", $self->file, $self->line) unless($text =~ /\n$/s); $text;}##################################################################################################################################################### Inspired by code from Jesse Glick <jglick@sig.bsh.com> and# Peter Seibel <peter@weblogic.com>package Error::subs;use Exporter ();use vars qw(@EXPORT_OK @ISA %EXPORT_TAGS);@EXPORT_OK = qw(try with finally except otherwise);%EXPORT_TAGS = (try => \@EXPORT_OK);@ISA = qw(Exporter);sub run_clauses ($$$\@) { my($clauses,$err,$wantarray,$result) = @_; my $code = undef; $err = new Error::Simple($err) unless ref($err); CATCH: { # catch my $catch; if(defined($catch = $clauses->{'catch'})) { my $i = 0; CATCHLOOP: for( ; $i < @$catch ; $i += 2) { my $pkg = $catch->[$i]; unless(defined $pkg) { #except splice(@$catch,$i,2,$catch->[$i+1]->()); $i -= 2; next CATCHLOOP; } elsif($err->isa($pkg)) { $code = $catch->[$i+1]; while(1) { my $more = 0; local($Error::THROWN); my $ok = eval { if($wantarray) { @{$result} = $code->($err,\$more); } elsif(defined($wantarray)) { @{$result} = (); $result->[0] = $code->($err,\$more); } else { $code->($err,\$more); } 1; }; if( $ok ) { next CATCHLOOP if $more; undef $err; } else { $err = defined($Error::THROWN) ? $Error::THROWN : $@; $err = new Error::Simple($err) unless ref($err); } last CATCH; }; } } } # otherwise my $owise; if(defined($owise = $clauses->{'otherwise'})) { my $code = $clauses->{'otherwise'}; my $more = 0; my $ok = eval { if($wantarray) { @{$result} = $code->($err,\$more); } elsif(defined($wantarray)) { @{$result} = (); $result->[0] = $code->($err,\$more); } else { $code->($err,\$more); } 1; }; if( $ok ) { undef $err; } else { $err = defined($Error::THROWN) ? $Error::THROWN : $@; $err = new Error::Simple($err) unless ref($err); } } } $err;}sub try (&;$) { my $try = shift; my $clauses = @_ ? shift : {}; my $ok = 0; my $err = undef; my @result = (); unshift @Error::STACK, $clauses; my $wantarray = wantarray(); do { local $Error::THROWN = undef; $ok = eval { if($wantarray) { @result = $try->();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -