use
5.005_64;
our
(
$AUTOLOAD
,
$Debug
,
$VERSION
);
$VERSION
= 1.02;
$Debug
= 0
unless
defined
$Debug
;
sub
import
{
my
$self
=
shift
(
@_
);
my
(
$sym
,
$pkg
);
$pkg
= (
caller
)[0];
foreach
$sym
(
@_
) {
&_make_fatal
(
$sym
,
$pkg
);
}
};
sub
AUTOLOAD {
my
$cmd
=
$AUTOLOAD
;
$cmd
=~ s/.*:://;
&_make_fatal
(
$cmd
, (
caller
)[0]);
goto
&$AUTOLOAD
;
}
sub
fill_protos {
my
$proto
=
shift
;
my
(
$n
,
$isref
,
@out
,
@out1
,
$seen_semi
) = -1;
while
(
$proto
=~ /\S/) {
$n
++;
push
(
@out1
,[
$n
,
@out
])
if
$seen_semi
;
push
(
@out
, $1 .
"{\$_[$n]}"
),
next
if
$proto
=~ s/^\s*\\([\@%\$\&])//;
push
(
@out
,
"\$_[$n]"
),
next
if
$proto
=~ s/^\s*([*\$&])//;
push
(
@out
,
"\@_[$n..\$#_]"
),
last
if
$proto
=~ s/^\s*(;\s*)?\@//;
$seen_semi
= 1,
$n
--,
next
if
$proto
=~ s/^\s*;//;
die
"Unknown prototype letters: \"$proto\""
;
}
push
(
@out1
,[
$n
+1,
@out
]);
@out1
;
}
sub
write_invocation {
my
(
$core
,
$call
,
$name
,
@argvs
) =
@_
;
if
(
@argvs
== 1) {
my
@argv
= @{
$argvs
[0]};
shift
@argv
;
return
"\t"
. one_invocation(
$core
,
$call
,
$name
,
@argv
) .
";\n"
;
}
else
{
my
$else
=
"\t"
;
my
(
@out
,
@argv
,
$n
);
while
(
@argvs
) {
@argv
= @{
shift
@argvs
};
$n
=
shift
@argv
;
push
@out
,
"$ {else}if (\@_ == $n) {\n"
;
$else
=
"\t} els"
;
push
@out
,
"\t\treturn "
. one_invocation(
$core
,
$call
,
$name
,
@argv
) .
";\n"
;
}
push
@out
,
<<EOC;
}
die "$name(\@_): Do not expect to get ", scalar \@_, " arguments";
EOC
return
join
''
,
@out
;
}
}
sub
one_invocation {
my
(
$core
,
$call
,
$name
,
@argv
) =
@_
;
local
$" =
', '
;
return
qq{$call(@argv) || croak "Can't $name(\@_)}
.
(
$core
?
': $!'
:
', \$! is \"$!\"'
) .
'"'
;
}
sub
_make_fatal {
my
(
$sub
,
$pkg
) =
@_
;
my
(
$name
,
$code
,
$sref
,
$real_proto
,
$proto
,
$core
,
$call
);
my
$ini
=
$sub
;
$sub
=
"${pkg}::$sub"
unless
$sub
=~ /::/;
$name
=
$sub
;
$name
=~ s/.*::// or
$name
=~ s/^&//;
print
"# _make_fatal: sub=$sub pkg=$pkg name=$name\n"
if
$Debug
;
croak
"Bad subroutine name for Fatal: $name"
unless
$name
=~ /^\w+$/;
if
(
defined
(
&$sub
)) {
$sref
= \
&$sub
;
$proto
=
prototype
$sref
;
$call
=
'&$sref'
;
}
elsif
(
$sub
eq
$ini
) {
die
"$sub is not a Perl subroutine"
}
else
{
$proto
=
eval
{
prototype
"CORE::$name"
};
die
"$name is neither a builtin, nor a Perl subroutine"
if
$@;
die
"Cannot make a non-overridable builtin fatal"
if
not
defined
$proto
;
$core
= 1;
$call
=
"CORE::$name"
;
}
if
(
defined
$proto
) {
$real_proto
=
" ($proto)"
;
}
else
{
$real_proto
=
''
;
$proto
=
'@'
;
}
$code
=
<<EOS;
sub$real_proto {
local(\$", \$!) = (', ', 0);
EOS
my
@protos
= fill_protos(
$proto
);
$code
.= write_invocation(
$core
,
$call
,
$name
,
@protos
);
$code
.=
"}\n"
;
print
$code
if
$Debug
;
{
no
strict
'refs'
;
$code
=
eval
(
"package $pkg; use Carp; $code"
);
die
if
$@;
no
warnings;
*{
$sub
} =
$code
;
}
}
1;