$VERSION
= (
qw$Revision: 1.10 $
)[1];
sub
valid_package_name {
my
(
$self
,
$string
) =
@_
;
$string
=~ s/([^A-Za-z0-9\/])/
sprintf
(
"_%2x"
,
unpack
(
"C"
,$1))/eg;
$string
=~ s{
(/)
(\d?)
}[
"::"
. ($2 ?
sprintf
(
"_%2x"
,
unpack
(
"C"
,$2)) :
""
)
]egx;
return
"Embed"
.
$string
;
}
sub
cached {
my
(
$self
,
$filename
,
$package
,
$mtime
) =
@_
;
$$mtime
= -M
$filename
;
if
(
defined
$self
->{FileCache}{
$package
}{mtime}
&&
$self
->{FileCache}{
$package
}{mtime} <=
$$mtime
) {
return
1;
}
return
0;
}
sub
cache {
my
(
$self
,
$package
,
$mtime
) =
@_
;
$self
->{FileCache}{
$package
}{mtime} =
$mtime
;
}
sub
uncache {
my
(
$self
,
$package
) =
@_
;
delete
$self
->{FileCache}{
$package
};
}
sub
new {
my
$class
=
shift
;
return
bless
{
FileCache
=> {
},
@_
,
} =>
$class
;
}
sub
prepare {
my
(
$self
,
$filename
,
$package
) =
@_
;
my
$fh
= FileHandle->new(
$filename
) or
die
"open '$filename' $!"
;
local
($/) =
undef
;
my
$sub
= <
$fh
>;
$fh
->
close
;
return
bless
{
CODE
=>
$sub
,
FILENAME
=>
$filename
,
PACKAGE
=>
$package
,
},
ref
(
$self
) ||
$self
;
}
sub
compile {
my
(
$self
) =
@_
;
my
$code
=
$self
->{CODE};
my
$package
=
$self
->{PACKAGE};
my
$eval
=
qq{package $package; sub handler { $code; }
};
{
my
(
$package
,
$code
);
eval
$eval
;
}
croak $@
if
$@;
}
sub
run {
my
(
$self
) =
@_
;
eval
{
$self
->{PACKAGE}->handler;};
croak $@
if
$@;
}
sub
delete
{
my
(
$self
) =
@_
;
my
$pkg
=
$self
->{PACKAGE};
$self
->uncache(
$pkg
);
my
(
$stem
,
$leaf
);
no
strict
'refs'
;
$pkg
=
"main::$pkg\::"
;
(
$stem
,
$leaf
) =
$pkg
=~ m/(.*::)(\w+::)$/;
my
$stem_symtab
= *{
$stem
}{HASH};
delete
$stem_symtab
->{
$leaf
};
}
sub
eval_file {
my
(
$self
,
$filename
,
$delete
) =
@_
;
my
$package
=
$self
->valid_package_name(
$filename
);
my
$mtime
;
if
(
$self
->cached(
$filename
,
$package
, \
$mtime
))
{
print
STDERR
"already compiled $package->handler\n"
if
$self
->{DEBUG};
}
else
{
my
$code
=
$self
->prepare(
$filename
,
$package
);
$code
->compile;
$self
->cache(
$package
,
$mtime
)
unless
$delete
;
$code
->run;
$code
->
delete
if
$delete
;
}
}
1;