1 |
wakaba |
1.1 |
# Error.pm |
2 |
|
|
# |
3 |
|
|
# Copyright (c) 1997-8 Graham Barr <gbarr@ti.com>. All rights reserved. |
4 |
|
|
# This program is free software; you can redistribute it and/or |
5 |
|
|
# modify it under the same terms as Perl itself. |
6 |
|
|
# |
7 |
|
|
# Based on my original Error.pm, and Exceptions.pm by Peter Seibel |
8 |
|
|
# <peter@weblogic.com> and adapted by Jesse Glick <jglick@sig.bsh.com>. |
9 |
|
|
# |
10 |
|
|
# but modified ***significantly*** |
11 |
|
|
|
12 |
|
|
package Error; |
13 |
|
|
|
14 |
|
|
use strict; |
15 |
|
|
use vars qw($VERSION); |
16 |
|
|
use 5.004; |
17 |
|
|
|
18 |
|
|
$VERSION = "0.15"; |
19 |
|
|
|
20 |
|
|
use overload ( |
21 |
|
|
'""' => 'stringify', |
22 |
|
|
'0+' => 'value', |
23 |
|
|
'bool' => sub { return 1; }, |
24 |
|
|
'fallback' => 1 |
25 |
|
|
); |
26 |
|
|
|
27 |
|
|
$Error::Depth = 0; # Depth to pass to caller() |
28 |
|
|
$Error::Debug = 0; # Generate verbose stack traces |
29 |
|
|
@Error::STACK = (); # Clause stack for try |
30 |
|
|
$Error::THROWN = undef; # last error thrown, a workaround until die $ref works |
31 |
|
|
|
32 |
|
|
my $LAST; # Last error created |
33 |
|
|
my %ERROR; # Last error associated with package |
34 |
|
|
|
35 |
|
|
# Exported subs are defined in Error::subs |
36 |
|
|
|
37 |
|
|
sub import { |
38 |
|
|
shift; |
39 |
|
|
local $Exporter::ExportLevel = $Exporter::ExportLevel + 1; |
40 |
|
|
Error::subs->import(@_); |
41 |
|
|
} |
42 |
|
|
|
43 |
|
|
# I really want to use last for the name of this method, but it is a keyword |
44 |
|
|
# which prevent the syntax last Error |
45 |
|
|
|
46 |
|
|
sub prior { |
47 |
|
|
shift; # ignore |
48 |
|
|
|
49 |
|
|
return $LAST unless @_; |
50 |
|
|
|
51 |
|
|
my $pkg = shift; |
52 |
|
|
return exists $ERROR{$pkg} ? $ERROR{$pkg} : undef |
53 |
|
|
unless ref($pkg); |
54 |
|
|
|
55 |
|
|
my $obj = $pkg; |
56 |
|
|
my $err = undef; |
57 |
|
|
if($obj->isa('HASH')) { |
58 |
|
|
$err = $obj->{'__Error__'} |
59 |
|
|
if exists $obj->{'__Error__'}; |
60 |
|
|
} |
61 |
|
|
elsif($obj->isa('GLOB')) { |
62 |
|
|
$err = ${*$obj}{'__Error__'} |
63 |
|
|
if exists ${*$obj}{'__Error__'}; |
64 |
|
|
} |
65 |
|
|
|
66 |
|
|
$err; |
67 |
|
|
} |
68 |
|
|
|
69 |
|
|
# Return as much information as possible about where the error |
70 |
|
|
# happened. The -stacktrace element only exists if $Error::DEBUG |
71 |
|
|
# was set when the error was created |
72 |
|
|
|
73 |
|
|
sub stacktrace { |
74 |
|
|
my $self = shift; |
75 |
|
|
|
76 |
|
|
return $self->{'-stacktrace'} |
77 |
|
|
if exists $self->{'-stacktrace'}; |
78 |
|
|
|
79 |
|
|
my $text = exists $self->{'-text'} ? $self->{'-text'} : "Died"; |
80 |
|
|
|
81 |
|
|
$text .= sprintf(" at %s line %d.\n", $self->file, $self->line) |
82 |
|
|
unless($text =~ /\n$/s); |
83 |
|
|
|
84 |
|
|
$text; |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
# Allow error propagation, ie |
88 |
|
|
# |
89 |
|
|
# $ber->encode(...) or |
90 |
|
|
# return Error->prior($ber)->associate($ldap); |
91 |
|
|
|
92 |
|
|
sub associate { |
93 |
|
|
my $err = shift; |
94 |
|
|
my $obj = shift; |
95 |
|
|
|
96 |
|
|
return unless ref($obj); |
97 |
|
|
|
98 |
|
|
if($obj->isa('HASH')) { |
99 |
|
|
$obj->{'__Error__'} = $err; |
100 |
|
|
} |
101 |
|
|
elsif($obj->isa('GLOB')) { |
102 |
|
|
${*$obj}{'__Error__'} = $err; |
103 |
|
|
} |
104 |
|
|
$obj = ref($obj); |
105 |
|
|
$ERROR{ ref($obj) } = $err; |
106 |
|
|
|
107 |
|
|
return; |
108 |
|
|
} |
109 |
|
|
|
110 |
|
|
sub new { |
111 |
|
|
my $self = shift; |
112 |
|
|
my($pkg,$file,$line) = caller($Error::Depth); |
113 |
|
|
|
114 |
|
|
my $err = bless { |
115 |
|
|
'-package' => $pkg, |
116 |
|
|
'-file' => $file, |
117 |
|
|
'-line' => $line, |
118 |
|
|
@_ |
119 |
|
|
}, $self; |
120 |
|
|
|
121 |
|
|
$err->associate($err->{'-object'}) |
122 |
|
|
if(exists $err->{'-object'}); |
123 |
|
|
|
124 |
|
|
# To always create a stacktrace would be very inefficient, so |
125 |
|
|
# we only do it if $Error::Debug is set |
126 |
|
|
|
127 |
|
|
if($Error::Debug) { |
128 |
|
|
require Carp; |
129 |
|
|
local $Carp::CarpLevel = $Error::Depth; |
130 |
|
|
my $text = defined($err->{'-text'}) ? $err->{'-text'} : "Error"; |
131 |
|
|
my $trace = Carp::longmess($text); |
132 |
|
|
# Remove try calls from the trace |
133 |
|
|
$trace =~ s/(\n\s+\S+__ANON__[^\n]+)?\n\s+eval[^\n]+\n\s+Error::subs::try[^\n]+(?=\n)//sog; |
134 |
|
|
$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; |
135 |
|
|
$err->{'-stacktrace'} = $trace |
136 |
|
|
} |
137 |
|
|
|
138 |
|
|
$@ = $LAST = $ERROR{$pkg} = $err; |
139 |
|
|
} |
140 |
|
|
|
141 |
|
|
# Throw an error. this contains some very gory code. |
142 |
|
|
|
143 |
|
|
sub throw { |
144 |
|
|
my $self = shift; |
145 |
|
|
local $Error::Depth = $Error::Depth + 1; |
146 |
|
|
|
147 |
|
|
# if we are not rethrow-ing then create the object to throw |
148 |
|
|
$self = $self->new(@_) unless ref($self); |
149 |
|
|
|
150 |
|
|
die $Error::THROWN = $self; |
151 |
|
|
} |
152 |
|
|
|
153 |
|
|
# syntactic sugar for |
154 |
|
|
# |
155 |
|
|
# die with Error( ... ); |
156 |
|
|
|
157 |
|
|
sub with { |
158 |
|
|
my $self = shift; |
159 |
|
|
local $Error::Depth = $Error::Depth + 1; |
160 |
|
|
|
161 |
|
|
$self->new(@_); |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
# syntactic sugar for |
165 |
|
|
# |
166 |
|
|
# record Error( ... ) and return; |
167 |
|
|
|
168 |
|
|
sub record { |
169 |
|
|
my $self = shift; |
170 |
|
|
local $Error::Depth = $Error::Depth + 1; |
171 |
|
|
|
172 |
|
|
$self->new(@_); |
173 |
|
|
} |
174 |
|
|
|
175 |
|
|
# catch clause for |
176 |
|
|
# |
177 |
|
|
# try { ... } catch CLASS with { ... } |
178 |
|
|
|
179 |
|
|
sub catch { |
180 |
|
|
my $pkg = shift; |
181 |
|
|
my $code = shift; |
182 |
|
|
my $clauses = shift || {}; |
183 |
|
|
my $catch = $clauses->{'catch'} ||= []; |
184 |
|
|
|
185 |
|
|
unshift @$catch, $pkg, $code; |
186 |
|
|
|
187 |
|
|
$clauses; |
188 |
|
|
} |
189 |
|
|
|
190 |
|
|
# Object query methods |
191 |
|
|
|
192 |
|
|
sub object { |
193 |
|
|
my $self = shift; |
194 |
|
|
exists $self->{'-object'} ? $self->{'-object'} : undef; |
195 |
|
|
} |
196 |
|
|
|
197 |
|
|
sub file { |
198 |
|
|
my $self = shift; |
199 |
|
|
exists $self->{'-file'} ? $self->{'-file'} : undef; |
200 |
|
|
} |
201 |
|
|
|
202 |
|
|
sub line { |
203 |
|
|
my $self = shift; |
204 |
|
|
exists $self->{'-line'} ? $self->{'-line'} : undef; |
205 |
|
|
} |
206 |
|
|
|
207 |
|
|
sub text { |
208 |
|
|
my $self = shift; |
209 |
|
|
exists $self->{'-text'} ? $self->{'-text'} : undef; |
210 |
|
|
} |
211 |
|
|
|
212 |
|
|
# overload methods |
213 |
|
|
|
214 |
|
|
sub stringify { |
215 |
|
|
my $self = shift; |
216 |
|
|
defined $self->{'-text'} ? $self->{'-text'} : "Died"; |
217 |
|
|
} |
218 |
|
|
|
219 |
|
|
sub value { |
220 |
|
|
my $self = shift; |
221 |
|
|
exists $self->{'-value'} ? $self->{'-value'} : undef; |
222 |
|
|
} |
223 |
|
|
|
224 |
|
|
package Error::Simple; |
225 |
|
|
|
226 |
|
|
@Error::Simple::ISA = qw(Error); |
227 |
|
|
|
228 |
|
|
sub new { |
229 |
|
|
my $self = shift; |
230 |
|
|
my $text = "" . shift; |
231 |
|
|
my $value = shift; |
232 |
|
|
my(@args) = (); |
233 |
|
|
|
234 |
|
|
local $Error::Depth = $Error::Depth + 1; |
235 |
|
|
|
236 |
|
|
@args = ( -file => $1, -line => $2) |
237 |
|
|
if($text =~ s/ at (\S+) line (\d+)(\.\n)?$//s); |
238 |
|
|
|
239 |
|
|
push(@args, '-value', 0 + $value) |
240 |
|
|
if defined($value); |
241 |
|
|
|
242 |
|
|
$self->SUPER::new(-text => $text, @args); |
243 |
|
|
} |
244 |
|
|
|
245 |
|
|
sub stringify { |
246 |
|
|
my $self = shift; |
247 |
|
|
my $text = $self->SUPER::stringify; |
248 |
|
|
$text .= sprintf(" at %s line %d.\n", $self->file, $self->line) |
249 |
|
|
unless($text =~ /\n$/s); |
250 |
|
|
$text; |
251 |
|
|
} |
252 |
|
|
|
253 |
|
|
########################################################################## |
254 |
|
|
########################################################################## |
255 |
|
|
|
256 |
|
|
# Inspired by code from Jesse Glick <jglick@sig.bsh.com> and |
257 |
|
|
# Peter Seibel <peter@weblogic.com> |
258 |
|
|
|
259 |
|
|
package Error::subs; |
260 |
|
|
|
261 |
|
|
use Exporter (); |
262 |
|
|
use vars qw(@EXPORT_OK @ISA %EXPORT_TAGS); |
263 |
|
|
|
264 |
|
|
@EXPORT_OK = qw(try with finally except otherwise); |
265 |
|
|
%EXPORT_TAGS = (try => \@EXPORT_OK); |
266 |
|
|
|
267 |
|
|
@ISA = qw(Exporter); |
268 |
|
|
|
269 |
|
|
sub run_clauses ($$$\@) { |
270 |
|
|
my($clauses,$err,$wantarray,$result) = @_; |
271 |
|
|
my $code = undef; |
272 |
|
|
|
273 |
|
|
$err = new Error::Simple($err) unless ref($err); |
274 |
|
|
|
275 |
|
|
CATCH: { |
276 |
|
|
|
277 |
|
|
# catch |
278 |
|
|
my $catch; |
279 |
|
|
if(defined($catch = $clauses->{'catch'})) { |
280 |
|
|
my $i = 0; |
281 |
|
|
|
282 |
|
|
CATCHLOOP: |
283 |
|
|
for( ; $i < @$catch ; $i += 2) { |
284 |
|
|
my $pkg = $catch->[$i]; |
285 |
|
|
unless(defined $pkg) { |
286 |
|
|
#except |
287 |
|
|
splice(@$catch,$i,2,$catch->[$i+1]->()); |
288 |
|
|
$i -= 2; |
289 |
|
|
next CATCHLOOP; |
290 |
|
|
} |
291 |
|
|
elsif($err->isa($pkg)) { |
292 |
|
|
$code = $catch->[$i+1]; |
293 |
|
|
while(1) { |
294 |
|
|
my $more = 0; |
295 |
|
|
local($Error::THROWN); |
296 |
|
|
my $ok = eval { |
297 |
|
|
if($wantarray) { |
298 |
|
|
@{$result} = $code->($err,\$more); |
299 |
|
|
} |
300 |
|
|
elsif(defined($wantarray)) { |
301 |
|
|
@{$result} = (); |
302 |
|
|
$result->[0] = $code->($err,\$more); |
303 |
|
|
} |
304 |
|
|
else { |
305 |
|
|
$code->($err,\$more); |
306 |
|
|
} |
307 |
|
|
1; |
308 |
|
|
}; |
309 |
|
|
if( $ok ) { |
310 |
|
|
next CATCHLOOP if $more; |
311 |
|
|
undef $err; |
312 |
|
|
} |
313 |
|
|
else { |
314 |
|
|
$err = defined($Error::THROWN) |
315 |
|
|
? $Error::THROWN : $@; |
316 |
|
|
$err = new Error::Simple($err) |
317 |
|
|
unless ref($err); |
318 |
|
|
} |
319 |
|
|
last CATCH; |
320 |
|
|
}; |
321 |
|
|
} |
322 |
|
|
} |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
# otherwise |
326 |
|
|
my $owise; |
327 |
|
|
if(defined($owise = $clauses->{'otherwise'})) { |
328 |
|
|
my $code = $clauses->{'otherwise'}; |
329 |
|
|
my $more = 0; |
330 |
|
|
my $ok = eval { |
331 |
|
|
if($wantarray) { |
332 |
|
|
@{$result} = $code->($err,\$more); |
333 |
|
|
} |
334 |
|
|
elsif(defined($wantarray)) { |
335 |
|
|
@{$result} = (); |
336 |
|
|
$result->[0] = $code->($err,\$more); |
337 |
|
|
} |
338 |
|
|
else { |
339 |
|
|
$code->($err,\$more); |
340 |
|
|
} |
341 |
|
|
1; |
342 |
|
|
}; |
343 |
|
|
if( $ok ) { |
344 |
|
|
undef $err; |
345 |
|
|
} |
346 |
|
|
else { |
347 |
|
|
$err = defined($Error::THROWN) |
348 |
|
|
? $Error::THROWN : $@; |
349 |
|
|
$err = new Error::Simple($err) |
350 |
|
|
unless ref($err); |
351 |
|
|
} |
352 |
|
|
} |
353 |
|
|
} |
354 |
|
|
$err; |
355 |
|
|
} |
356 |
|
|
|
357 |
|
|
sub try (&;$) { |
358 |
|
|
my $try = shift; |
359 |
|
|
my $clauses = @_ ? shift : {}; |
360 |
|
|
my $ok = 0; |
361 |
|
|
my $err = undef; |
362 |
|
|
my @result = (); |
363 |
|
|
|
364 |
|
|
unshift @Error::STACK, $clauses; |
365 |
|
|
|
366 |
|
|
my $wantarray = wantarray(); |
367 |
|
|
|
368 |
|
|
do { |
369 |
|
|
local $Error::THROWN = undef; |
370 |
|
|
|
371 |
|
|
$ok = eval { |
372 |
|
|
if($wantarray) { |
373 |
|
|
@result = $try->(); |
374 |
|
|
} |
375 |
|
|
elsif(defined $wantarray) { |
376 |
|
|
$result[0] = $try->(); |
377 |
|
|
} |
378 |
|
|
else { |
379 |
|
|
$try->(); |
380 |
|
|
} |
381 |
|
|
1; |
382 |
|
|
}; |
383 |
|
|
|
384 |
|
|
$err = defined($Error::THROWN) ? $Error::THROWN : $@ |
385 |
|
|
unless $ok; |
386 |
|
|
}; |
387 |
|
|
|
388 |
|
|
shift @Error::STACK; |
389 |
|
|
|
390 |
|
|
$err = run_clauses($clauses,$err,wantarray,@result) |
391 |
|
|
unless($ok); |
392 |
|
|
|
393 |
|
|
$clauses->{'finally'}->() |
394 |
|
|
if(defined($clauses->{'finally'})); |
395 |
|
|
|
396 |
|
|
throw $err if defined($err); |
397 |
|
|
|
398 |
|
|
wantarray ? @result : $result[0]; |
399 |
|
|
} |
400 |
|
|
|
401 |
|
|
# Each clause adds a sub to the list of clauses. The finally clause is |
402 |
|
|
# always the last, and the otherwise clause is always added just before |
403 |
|
|
# the finally clause. |
404 |
|
|
# |
405 |
|
|
# All clauses, except the finally clause, add a sub which takes one argument |
406 |
|
|
# this argument will be the error being thrown. The sub will return a code ref |
407 |
|
|
# if that clause can handle that error, otherwise undef is returned. |
408 |
|
|
# |
409 |
|
|
# The otherwise clause adds a sub which unconditionally returns the users |
410 |
|
|
# code reference, this is why it is forced to be last. |
411 |
|
|
# |
412 |
|
|
# The catch clause is defined in Error.pm, as the syntax causes it to |
413 |
|
|
# be called as a method |
414 |
|
|
|
415 |
|
|
sub with (&;$) { |
416 |
|
|
@_ |
417 |
|
|
} |
418 |
|
|
|
419 |
|
|
sub finally (&) { |
420 |
|
|
my $code = shift; |
421 |
|
|
my $clauses = { 'finally' => $code }; |
422 |
|
|
$clauses; |
423 |
|
|
} |
424 |
|
|
|
425 |
|
|
# The except clause is a block which returns a hashref or a list of |
426 |
|
|
# key-value pairs, where the keys are the classes and the values are subs. |
427 |
|
|
|
428 |
|
|
sub except (&;$) { |
429 |
|
|
my $code = shift; |
430 |
|
|
my $clauses = shift || {}; |
431 |
|
|
my $catch = $clauses->{'catch'} ||= []; |
432 |
|
|
|
433 |
|
|
my $sub = sub { |
434 |
|
|
my $ref; |
435 |
|
|
my(@array) = $code->($_[0]); |
436 |
|
|
if(@array == 1 && ref($array[0])) { |
437 |
|
|
$ref = $array[0]; |
438 |
|
|
$ref = [ %$ref ] |
439 |
|
|
if(UNIVERSAL::isa($ref,'HASH')); |
440 |
|
|
} |
441 |
|
|
else { |
442 |
|
|
$ref = \@array; |
443 |
|
|
} |
444 |
|
|
@$ref |
445 |
|
|
}; |
446 |
|
|
|
447 |
|
|
unshift @{$catch}, undef, $sub; |
448 |
|
|
|
449 |
|
|
$clauses; |
450 |
|
|
} |
451 |
|
|
|
452 |
|
|
sub otherwise (&;$) { |
453 |
|
|
my $code = shift; |
454 |
|
|
my $clauses = shift || {}; |
455 |
|
|
|
456 |
|
|
if(exists $clauses->{'otherwise'}) { |
457 |
|
|
require Carp; |
458 |
|
|
Carp::croak("Multiple otherwise clauses"); |
459 |
|
|
} |
460 |
|
|
|
461 |
|
|
$clauses->{'otherwise'} = $code; |
462 |
|
|
|
463 |
|
|
$clauses; |
464 |
|
|
} |
465 |
|
|
|
466 |
|
|
1; |
467 |
|
|
__END__ |
468 |
|
|
|
469 |
|
|
=head1 NAME |
470 |
|
|
|
471 |
|
|
Error - Error/exception handling in an OO-ish way |
472 |
|
|
|
473 |
|
|
=head1 SYNOPSIS |
474 |
|
|
|
475 |
|
|
use Error qw(:try); |
476 |
|
|
|
477 |
|
|
throw Error::Simple( "A simple error"); |
478 |
|
|
|
479 |
|
|
sub xyz { |
480 |
|
|
... |
481 |
|
|
record Error::Simple("A simple error") |
482 |
|
|
and return; |
483 |
|
|
} |
484 |
|
|
|
485 |
|
|
unlink($file) or throw Error::Simple("$file: $!",$!); |
486 |
|
|
|
487 |
|
|
try { |
488 |
|
|
do_some_stuff(); |
489 |
|
|
die "error!" if $condition; |
490 |
|
|
throw Error::Simple -text => "Oops!" if $other_condition; |
491 |
|
|
} |
492 |
|
|
catch Error::IO with { |
493 |
|
|
my $E = shift; |
494 |
|
|
print STDERR "File ", $E->{'-file'}, " had a problem\n"; |
495 |
|
|
} |
496 |
|
|
except { |
497 |
|
|
my $E = shift; |
498 |
|
|
my $general_handler=sub {send_message $E->{-description}}; |
499 |
|
|
return { |
500 |
|
|
UserException1 => $general_handler, |
501 |
|
|
UserException2 => $general_handler |
502 |
|
|
}; |
503 |
|
|
} |
504 |
|
|
otherwise { |
505 |
|
|
print STDERR "Well I don't know what to say\n"; |
506 |
|
|
} |
507 |
|
|
finally { |
508 |
|
|
close_the_garage_door_already(); # Should be reliable |
509 |
|
|
}; # Don't forget the trailing ; or you might be surprised |
510 |
|
|
|
511 |
|
|
=head1 DESCRIPTION |
512 |
|
|
|
513 |
|
|
The C<Error> package provides two interfaces. Firstly C<Error> provides |
514 |
|
|
a procedural interface to exception handling. Secondly C<Error> is a |
515 |
|
|
base class for errors/exceptions that can either be thrown, for |
516 |
|
|
subsequent catch, or can simply be recorded. |
517 |
|
|
|
518 |
|
|
Errors in the class C<Error> should not be thrown directly, but the |
519 |
|
|
user should throw errors from a sub-class of C<Error>. |
520 |
|
|
|
521 |
|
|
=head1 PROCEDURAL INTERFACE |
522 |
|
|
|
523 |
|
|
C<Error> exports subroutines to perform exception handling. These will |
524 |
|
|
be exported if the C<:try> tag is used in the C<use> line. |
525 |
|
|
|
526 |
|
|
=over 4 |
527 |
|
|
|
528 |
|
|
=item try BLOCK CLAUSES |
529 |
|
|
|
530 |
|
|
C<try> is the main subroutine called by the user. All other subroutines |
531 |
|
|
exported are clauses to the try subroutine. |
532 |
|
|
|
533 |
|
|
The BLOCK will be evaluated and, if no error is throw, try will return |
534 |
|
|
the result of the block. |
535 |
|
|
|
536 |
|
|
C<CLAUSES> are the subroutines below, which describe what to do in the |
537 |
|
|
event of an error being thrown within BLOCK. |
538 |
|
|
|
539 |
|
|
=item catch CLASS with BLOCK |
540 |
|
|
|
541 |
|
|
This clauses will cause all errors that satisfy C<$err-E<gt>isa(CLASS)> |
542 |
|
|
to be caught and handled by evaluating C<BLOCK>. |
543 |
|
|
|
544 |
|
|
C<BLOCK> will be passed two arguments. The first will be the error |
545 |
|
|
being thrown. The second is a reference to a scalar variable. If this |
546 |
|
|
variable is set by the catch block then, on return from the catch |
547 |
|
|
block, try will continue processing as if the catch block was never |
548 |
|
|
found. |
549 |
|
|
|
550 |
|
|
To propagate the error the catch block may call C<$err-E<gt>throw> |
551 |
|
|
|
552 |
|
|
If the scalar reference by the second argument is not set, and the |
553 |
|
|
error is not thrown. Then the current try block will return with the |
554 |
|
|
result from the catch block. |
555 |
|
|
|
556 |
|
|
=item except BLOCK |
557 |
|
|
|
558 |
|
|
When C<try> is looking for a handler, if an except clause is found |
559 |
|
|
C<BLOCK> is evaluated. The return value from this block should be a |
560 |
|
|
HASHREF or a list of key-value pairs, where the keys are class names |
561 |
|
|
and the values are CODE references for the handler of errors of that |
562 |
|
|
type. |
563 |
|
|
|
564 |
|
|
=item otherwise BLOCK |
565 |
|
|
|
566 |
|
|
Catch any error by executing the code in C<BLOCK> |
567 |
|
|
|
568 |
|
|
When evaluated C<BLOCK> will be passed one argument, which will be the |
569 |
|
|
error being processed. |
570 |
|
|
|
571 |
|
|
Only one otherwise block may be specified per try block |
572 |
|
|
|
573 |
|
|
=item finally BLOCK |
574 |
|
|
|
575 |
|
|
Execute the code in C<BLOCK> either after the code in the try block has |
576 |
|
|
successfully completed, or if the try block throws an error then |
577 |
|
|
C<BLOCK> will be executed after the handler has completed. |
578 |
|
|
|
579 |
|
|
If the handler throws an error then the error will be caught, the |
580 |
|
|
finally block will be executed and the error will be re-thrown. |
581 |
|
|
|
582 |
|
|
Only one finally block may be specified per try block |
583 |
|
|
|
584 |
|
|
=back |
585 |
|
|
|
586 |
|
|
=head1 CLASS INTERFACE |
587 |
|
|
|
588 |
|
|
=head2 CONSTRUCTORS |
589 |
|
|
|
590 |
|
|
The C<Error> object is implemented as a HASH. This HASH is initialized |
591 |
|
|
with the arguments that are passed to it's constructor. The elements |
592 |
|
|
that are used by, or are retrievable by the C<Error> class are listed |
593 |
|
|
below, other classes may add to these. |
594 |
|
|
|
595 |
|
|
-file |
596 |
|
|
-line |
597 |
|
|
-text |
598 |
|
|
-value |
599 |
|
|
-object |
600 |
|
|
|
601 |
|
|
If C<-file> or C<-line> are not specified in the constructor arguments |
602 |
|
|
then these will be initialized with the file name and line number where |
603 |
|
|
the constructor was called from. |
604 |
|
|
|
605 |
|
|
If the error is associated with an object then the object should be |
606 |
|
|
passed as the C<-object> argument. This will allow the C<Error> package |
607 |
|
|
to associate the error with the object. |
608 |
|
|
|
609 |
|
|
The C<Error> package remembers the last error created, and also the |
610 |
|
|
last error associated with a package. This could either be the last |
611 |
|
|
error created by a sub in that package, or the last error which passed |
612 |
|
|
an object blessed into that package as the C<-object> argument. |
613 |
|
|
|
614 |
|
|
=over 4 |
615 |
|
|
|
616 |
|
|
=item throw ( [ ARGS ] ) |
617 |
|
|
|
618 |
|
|
Create a new C<Error> object and throw an error, which will be caught |
619 |
|
|
by a surrounding C<try> block, if there is one. Otherwise it will cause |
620 |
|
|
the program to exit. |
621 |
|
|
|
622 |
|
|
C<throw> may also be called on an existing error to re-throw it. |
623 |
|
|
|
624 |
|
|
=item with ( [ ARGS ] ) |
625 |
|
|
|
626 |
|
|
Create a new C<Error> object and returns it. This is defined for |
627 |
|
|
syntactic sugar, eg |
628 |
|
|
|
629 |
|
|
die with Some::Error ( ... ); |
630 |
|
|
|
631 |
|
|
=item record ( [ ARGS ] ) |
632 |
|
|
|
633 |
|
|
Create a new C<Error> object and returns it. This is defined for |
634 |
|
|
syntactic sugar, eg |
635 |
|
|
|
636 |
|
|
record Some::Error ( ... ) |
637 |
|
|
and return; |
638 |
|
|
|
639 |
|
|
=back |
640 |
|
|
|
641 |
|
|
=head2 STATIC METHODS |
642 |
|
|
|
643 |
|
|
=over 4 |
644 |
|
|
|
645 |
|
|
=item prior ( [ PACKAGE ] ) |
646 |
|
|
|
647 |
|
|
Return the last error created, or the last error associated with |
648 |
|
|
C<PACKAGE> |
649 |
|
|
|
650 |
|
|
=back |
651 |
|
|
|
652 |
|
|
=head2 OBJECT METHODS |
653 |
|
|
|
654 |
|
|
=over 4 |
655 |
|
|
|
656 |
|
|
=item stacktrace |
657 |
|
|
|
658 |
|
|
If the variable C<$Error::Debug> was non-zero when the error was |
659 |
|
|
created, then C<stacktrace> returns a string created by calling |
660 |
|
|
C<Carp::longmess>. If the variable was zero the C<stacktrace> returns |
661 |
|
|
the text of the error appended with the filename and line number of |
662 |
|
|
where the error was created, providing the text does not end with a |
663 |
|
|
newline. |
664 |
|
|
|
665 |
|
|
=item object |
666 |
|
|
|
667 |
|
|
The object this error was associated with |
668 |
|
|
|
669 |
|
|
=item file |
670 |
|
|
|
671 |
|
|
The file where the constructor of this error was called from |
672 |
|
|
|
673 |
|
|
=item line |
674 |
|
|
|
675 |
|
|
The line where the constructor of this error was called from |
676 |
|
|
|
677 |
|
|
=item text |
678 |
|
|
|
679 |
|
|
The text of the error |
680 |
|
|
|
681 |
|
|
=back |
682 |
|
|
|
683 |
|
|
=head2 OVERLOAD METHODS |
684 |
|
|
|
685 |
|
|
=over 4 |
686 |
|
|
|
687 |
|
|
=item stringify |
688 |
|
|
|
689 |
|
|
A method that converts the object into a string. This method may simply |
690 |
|
|
return the same as the C<text> method, or it may append more |
691 |
|
|
information. For example the file name and line number. |
692 |
|
|
|
693 |
|
|
By default this method returns the C<-text> argument that was passed to |
694 |
|
|
the constructor, or the string C<"Died"> if none was given. |
695 |
|
|
|
696 |
|
|
=item value |
697 |
|
|
|
698 |
|
|
A method that will return a value that can be associated with the |
699 |
|
|
error. For example if an error was created due to the failure of a |
700 |
|
|
system call, then this may return the numeric value of C<$!> at the |
701 |
|
|
time. |
702 |
|
|
|
703 |
|
|
By default this method returns the C<-value> argument that was passed |
704 |
|
|
to the constructor. |
705 |
|
|
|
706 |
|
|
=back |
707 |
|
|
|
708 |
|
|
=head1 PRE-DEFINED ERROR CLASSES |
709 |
|
|
|
710 |
|
|
=over 4 |
711 |
|
|
|
712 |
|
|
=item Error::Simple |
713 |
|
|
|
714 |
|
|
This class can be used to hold simple error strings and values. It's |
715 |
|
|
constructor takes two arguments. The first is a text value, the second |
716 |
|
|
is a numeric value. These values are what will be returned by the |
717 |
|
|
overload methods. |
718 |
|
|
|
719 |
|
|
If the text value ends with C<at file line 1> as $@ strings do, then |
720 |
|
|
this infomation will be used to set the C<-file> and C<-line> arguments |
721 |
|
|
of the error object. |
722 |
|
|
|
723 |
|
|
This class is used internally if an eval'd block die's with an error |
724 |
|
|
that is a plain string. |
725 |
|
|
|
726 |
|
|
=back |
727 |
|
|
|
728 |
|
|
=head1 KNOWN BUGS |
729 |
|
|
|
730 |
|
|
None, but that does not mean there are not any. |
731 |
|
|
|
732 |
|
|
=head1 AUTHORS |
733 |
|
|
|
734 |
|
|
Graham Barr <gbarr@pobox.com> |
735 |
|
|
|
736 |
|
|
The code that inspired me to write this was originally written by |
737 |
|
|
Peter Seibel <peter@weblogic.com> and adapted by Jesse Glick |
738 |
|
|
<jglick@sig.bsh.com>. |
739 |
|
|
|
740 |
|
|
=head1 MAINTAINER |
741 |
|
|
|
742 |
|
|
Arun Kumar U <u_arunkumar@yahoo.com> |
743 |
|
|
|
744 |
|
|
=cut |