Stupid Slash Tricks: Auto-Encapsulation of Tasks
The slashd program in slash runs "tasks" which are separate files. It performs a require(). The problem is that sometimes symbols in each task can conflict with another.
We have many tasks so rather than edit each one, we decided to handle the encapsulation in slashd itself. It creates a package name, and has code to import symbols from main into the package, and then sets the line number correctly.
(my $tmppackage = $file) =~ s/\.pl$//; $tmppackage =~ s/\W/_/g; $tmppackage =~ s/^([^a-zA-Z])/a_$1/g; $tmppackage = "Slash::Task::$tmppackage"; # replace tmppackage in string where appropriate (my $addtxt = <<'EOT') =~ s/\${?tmppackage}?/$tmppackage/g; package $tmppackage; { no strict 'refs'; my @scalar = qw(me task_exit_flag); my @hash = qw(task); my @code = (qw( slashdLog slashdErrnote slashdLogDie tagboxLog verbosity db_time init_cron ), grep { *{"main::$_"}{CODE} } @Slash::EXPORT, @Slash::Display::EXPORT, @Slash::Utility::EXPORT, @File::Spec::Functions::EXPORT, @LWP::UserAgent::EXPORT, @URI::Escape::EXPORT, @File::Basename::EXPORT, @File::Path::EXPORT, @Time::Local::EXPORT, @Time::HiRes::EXPORT ); *{"${tmppackage}::$_"} = *{"main::$_"}{HASH} for @hash; *{"${tmppackage}::$_"} = *{"main::$_"}{SCALAR} for @scalar; *{"${tmppackage}::$_"} = *{"main::$_"}{CODE} for @code; } #line 1 EOT my($tmpfh, $tmpfile) = tempfile(); my $tmptxt = do { open my $fh, '<', $fullname; local $/; <$fh> }; print $tmpfh $addtxt, $tmptxt; $tmpfh->flush; # can't close fh until we require the file, # else the file might disappear my $ok = 0; eval { local $me = $file; $ok = require $tmpfile };
Leave a comment