App-PerlXLock
view release on metacpan or search on metacpan
inc/Inline.pm view on Meta::CPAN
# reason that I've commented it out. I've left it here (including its associated comments)
# in case it later becomes evident that there *is* good reason to include it. --sisyphus
#
## This bit tries to enable UNTAINT automatically if required when running the test suite.
# my $env_ha = $ENV{HARNESS_ACTIVE} || 0 ;
# my ($harness_active) = $env_ha =~ /(.*)/ ;
# if (($harness_active)&&(! $o->{CONFIG}{UNTAINT})){
# eval {
# require Scalar::Util;
# $o->{CONFIG}{UNTAINT} =
# (Scalar::Util::tainted(Cwd::cwd()) ? 1 : 0) ;
## Disable SAFEMODE in the test suite, we know what we are doing...
# $o->{CONFIG}{SAFEMODE} = 0 ;
# warn "\n-[tT] enabled for test suite.
#Automatically setting UNTAINT=1 and SAFEMODE=0.\n"
# unless $Inline::_TAINT_WARNING_ ;
# $Inline::_TAINT_WARNING_ = 1 ;
# } ;
# }
##
$untaint = $o->{CONFIG}{UNTAINT} || 0;
$safemode = (($o->{CONFIG}{SAFEMODE} == -1) ?
($untaint ? 1 : 0) :
$o->{CONFIG}{SAFEMODE}
);
if (UNTAINT and
SAFEMODE and
not $o->{CONFIG}{DIRECTORY}) {
croak M49_usage_unsafe(1) if ($< == 0 or $> == 0);
warn M49_usage_unsafe(0) if $^W;
}
if ($o->{CONFIG}{AUTONAME} == -1) {
$o->{CONFIG}{AUTONAME} = length($o->{CONFIG}{NAME}) ? 0 : 1;
}
$o->{API}{cleanup} =
($o->{CONFIG}{CLEAN_AFTER_BUILD} and not $o->{CONFIG}{REPORTBUG});
}
#==============================================================================
# Check if Inline extension is preinstalled
#==============================================================================
sub check_installed {
my $o = shift;
$o->{INLINE}{object_ready} = 0;
unless ($o->{API}{code} =~ /^[A-Fa-f0-9]{32}$/) {
require Digest::MD5;
$o->{INLINE}{md5} = Digest::MD5::md5_hex($o->{API}{code});
}
else {
$o->{INLINE}{md5} = $o->{API}{code};
}
return if $o->{CONFIG}{_INSTALL_};
return unless $o->{CONFIG}{VERSION};
croak M26_error_version_without_name()
unless $o->{CONFIG}{NAME};
my @pkgparts = split(/::/, $o->{API}{pkg});
my $realname = File::Spec->catfile(@pkgparts) . '.pm';
my $realname_unix = File::Spec::Unix->catfile(@pkgparts) . '.pm';
my $realpath = $INC{$realname_unix}
or croak M27_module_not_indexed($realname_unix);
my ($volume,$dir,$file) = File::Spec->splitpath($realpath);
my @dirparts = File::Spec->splitdir($dir);
pop @dirparts unless $dirparts[-1];
push @dirparts, $file;
my @endparts = splice(@dirparts, 0 - @pkgparts);
$dirparts[-1] = 'arch'
if $dirparts[-2] eq 'blib' && $dirparts[-1] eq 'lib';
File::Spec->catfile(@endparts) eq $realname
or croak M28_error_grokking_path($realpath);
$realpath =
File::Spec->catpath($volume,File::Spec->catdir(@dirparts),"");
$o->{API}{version} = $o->{CONFIG}{VERSION};
$o->{API}{module} = $o->{CONFIG}{NAME};
my @modparts = split(/::/,$o->{API}{module});
$o->{API}{modfname} = $modparts[-1];
$o->{API}{modpname} = File::Spec->catdir(@modparts);
my $suffix = $Config{dlext};
my $obj = File::Spec->catfile($realpath,'auto',$o->{API}{modpname},
"$o->{API}{modfname}.$suffix");
croak M30_error_no_obj($o->{CONFIG}{NAME}, $o->{API}{pkg},
$realpath) unless -f $obj;
@{$o->{CONFIG}}{qw( PRINT_INFO
REPORTBUG
FORCE_BUILD
_INSTALL_
)} = (0, 0, 0, 0);
$o->{install_lib} = $realpath;
$o->{INLINE}{ILSM_type} = 'compiled';
$o->{INLINE}{ILSM_module} = 'Inline::C';
$o->{INLINE}{ILSM_suffix} = $suffix;
$o->{INLINE}{object_ready} = 1;
}
#==============================================================================
# Dynamically load the object module
#==============================================================================
sub load {
my $o = shift;
return if $o->{CONFIG}{_INSTALL_};
my ($pkg, $module) = @{$o->{API}}{qw(pkg module)};
croak M42_usage_loader() unless $o->{INLINE}{ILSM_type} eq 'compiled';
require DynaLoader;
@Inline::ISA = qw(DynaLoader);
my $global = $o->{CONFIG}{GLOBAL_LOAD} ? '0x01' : '0x00';
my $version = $o->{API}{version} || '0.00';
eval <<END;
package $pkg;
push \@$ {pkg}::ISA, qw($module)
unless \$module eq "$pkg";
inc/Inline.pm view on Meta::CPAN
for my $option (@_) {
my $OPTION = uc($option);
if ($OPTION eq 'SITE_INSTALL') {
croak M58_site_install();
}
elsif ($shortcuts{$OPTION}) {
my ($method, $arg) = @{$shortcuts{$OPTION}};
$CONFIG{$pkg}{template}{$method} = $arg;
}
else {
croak M48_usage_shortcuts($option);
}
}
}
#==============================================================================
# Process the with command
#==============================================================================
sub handle_with {
my $pkg = shift;
croak M45_usage_with() unless @_;
for (@_) {
croak M02_usage() unless /^[\w:]+$/;
eval "require $_;";
croak M46_usage_with_bad($_) . $@ if $@;
push @{$CONFIG{$pkg}{template}{WITH}}, $_;
}
}
#==============================================================================
# Perform cleanup duties
#==============================================================================
sub DESTROY {
my $o = shift;
$o->clean_build if $o->{CONFIG}{CLEAN_BUILD_AREA};
}
#==============================================================================
# Get the source code
#==============================================================================
sub receive_code {
my $o = shift;
my $code = shift;
croak M02_usage() unless (defined $code and $code);
if (ref $code eq 'CODE') {
$o->{API}{code} = &$code;
}
elsif (ref $code eq 'ARRAY') {
$o->{API}{code} = join '', @$code;
}
elsif ($code =~ m|[/\\:]| and
$code =~ m|^[/\\:\w.\-\ \$\[\]<>]+$|) {
if (-f $code) {
local ($/, *CODE);
open CODE, "< $code" or croak M06_code_file_failed_open($code);
$o->{API}{code} = <CODE>;
}
else {
croak M07_code_file_does_not_exist($code);
}
}
else {
$o->{API}{code} = $code;
}
}
#==============================================================================
# Get the source code from an Inline::Files filehandle
#==============================================================================
sub read_inline_file {
my $o = shift;
my ($lang, $pkg) = @{$o->{API}}{qw(language_id pkg)};
my $langfile = uc($lang);
croak M59_bad_inline_file($lang) unless $langfile =~ /^[A-Z]\w*$/;
croak M60_no_inline_files()
unless (defined $INC{File::Spec::Unix->catfile("Inline","Files.pm")} and
$Inline::Files::VERSION =~ /^\d\.\d\d$/ and
$Inline::Files::VERSION ge '0.51');
croak M61_not_parsed() unless $lang = Inline::Files::get_filename($pkg);
{
no strict 'refs';
local $/;
$Inline::FILE = \*{"${pkg}::$langfile"};
# open $Inline::FILE;
$o->{API}{code} = <$Inline::FILE>;
# close $Inline::FILE;
}
}
#==============================================================================
# Read the cached config file from the Inline directory. This will indicate
# whether the Language code is valid or not.
#==============================================================================
sub check_config_file {
my ($DIRECTORY, %config);
my $o = shift;
croak M14_usage_Config() if $Inline::Config::VERSION;
croak M63_no_source($o->{API}{pkg})
if $o->{INLINE}{md5} eq $o->{API}{code};
# First make sure we have the DIRECTORY
if ($o->{CONFIG}{_INSTALL_}) {
croak M15_usage_install_directory()
if $o->{CONFIG}{DIRECTORY};
my $cwd = Cwd::cwd();
$DIRECTORY =
$o->{INLINE}{DIRECTORY} = File::Spec->catdir($cwd, $did);
if (not -d $DIRECTORY) {
_mkdir($DIRECTORY, 0777)
or croak M16_DIRECTORY_mkdir_failed($DIRECTORY);
}
}
else {
$DIRECTORY = $o->{INLINE}{DIRECTORY} =
$o->{CONFIG}{DIRECTORY} || $o->find_temp_dir;
}
if($o->{CONFIG}{REWRITE_CONFIG_FILE}) {
if(-e File::Spec->catfile($DIRECTORY, $configuration_file)) {
my $unlink = unlink(File::Spec->catfile($DIRECTORY, $configuration_file));
if(!$unlink) {warn "REWRITE_CONFIG_FILE is set, but removal of config file failed"}
else {warn "config file removal successful\n" if $o->{CONFIG}{_TESTING}}
}
}
my $load_cfg = sub {
$o->create_config_file($DIRECTORY)
if not -e File::Spec->catfile($DIRECTORY, $configuration_file);
open CONFIG, "< ".File::Spec->catfile($DIRECTORY,$configuration_file)
or croak M17_config_open_failed($DIRECTORY);
flock(CONFIG, LOCK_EX) if $^O !~ /^VMS|riscos|VOS$/;
my $config = join '', <CONFIG>;
flock(CONFIG, LOCK_UN) if $^O !~ /^VMS|riscos|VOS$/;
close CONFIG;
unless($config =~ /^version :/) {
warn "\$load_cfg sub: \$config: *${config}*\n";
inc/Inline.pm view on Meta::CPAN
$o->{API}{suffix} = $o->{INLINE}{ILSM_suffix};
$o->{API}{directory} = $o->{INLINE}{DIRECTORY};
my $auto_level = 2;
while ($auto_level <= 5) {
if ($o->{CONFIG}{AUTONAME}) {
$module2 =
$module . '_' . substr($o->{INLINE}{md5}, 0, 2 + $auto_level);
$auto_level++;
} else {
$module2 = $module;
$auto_level = 6; # Don't loop on non-autoname objects
}
$o->{API}{module} = $module2;
my @modparts = split /::/, $module2;
$o->{API}{modfname} = $modparts[-1];
$o->{API}{modpname} = File::Spec->catdir(@modparts);
$o->{API}{build_dir} =
File::Spec->catdir($o->{INLINE}{DIRECTORY},
'build',$o->{API}{modpname});
$o->{API}{install_lib} =
File::Spec->catdir($o->{INLINE}{DIRECTORY}, 'lib');
my $inl = File::Spec->catfile($o->{API}{install_lib},"auto",
$o->{API}{modpname},"$o->{API}{modfname}.inl");
$o->{API}{location} =
File::Spec->catfile($o->{API}{install_lib},"auto",$o->{API}{modpname},
"$o->{API}{modfname}.$o->{INLINE}{ILSM_suffix}");
last unless -f $inl;
my %inl;
{ local ($/, *INL);
open INL, $inl or croak M31_inline_open_failed($inl);
%inl = Inline::denter->new()->undent(<INL>);
}
next unless ($o->{INLINE}{md5} eq $inl{md5});
next unless ($inl{inline_version} ge '0.40');
next unless ($inl{Config}{version} eq $Config::Config{version});
next unless ($inl{Config}{archname} eq $Config::Config{archname});
unless (-f $o->{API}{location}) {
warn <<END if $^W;
Missing object file: $o->{API}{location}
For Inline file: $inl
END
next;
}
$o->{INLINE}{object_ready} = 1 unless $o->{CONFIG}{FORCE_BUILD};
last;
}
unshift @::INC, $o->{API}{install_lib};
}
#==============================================================================
# Set things up so that the extension gets installed into the blib/arch.
# Then 'make install' will do the right thing.
#==============================================================================
sub install {
my ($module, $DIRECTORY);
my $o = shift;
croak M64_install_not_c($o->{API}{language_id})
unless uc($o->{API}{language_id}) =~ /^(C|CPP|Java|Python|Ruby|Lisp|Pdlpp)$/ ;
croak M36_usage_install_main()
if ($o->{API}{pkg} eq 'main');
croak M37_usage_install_auto()
if $o->{CONFIG}{AUTONAME};
croak M38_usage_install_name()
unless $o->{CONFIG}{NAME};
croak M39_usage_install_version()
unless $o->{CONFIG}{VERSION};
croak M40_usage_install_badname($o->{CONFIG}{NAME}, $o->{API}{pkg})
unless $o->{CONFIG}{NAME} eq $o->{API}{pkg};
# $o->{CONFIG}{NAME} =~ /^$o->{API}{pkg}::\w(\w|::)+$/
# );
my ($mod_name, $mod_ver, $ext_name, $ext_ver) =
($o->{API}{pkg}, $ARGV[0], @{$o->{CONFIG}}{qw(NAME VERSION)});
croak M41_usage_install_version_mismatch($mod_name, $mod_ver,
$ext_name, $ext_ver)
unless ($mod_ver eq $ext_ver);
$o->{INLINE}{INST_ARCHLIB} = $ARGV[1];
$o->{API}{version} = $o->{CONFIG}{VERSION};
$o->{API}{module} = $o->{CONFIG}{NAME};
my @modparts = split(/::/,$o->{API}{module});
$o->{API}{modfname} = $modparts[-1];
$o->{API}{modpname} = File::Spec->catdir(@modparts);
$o->{API}{modinlname} = join('-',@modparts).'.inl';
$o->{API}{suffix} = $o->{INLINE}{ILSM_suffix};
$o->{API}{build_dir} = File::Spec->catdir($o->{INLINE}{DIRECTORY},'build',
$o->{API}{modpname});
$o->{API}{directory} = $o->{INLINE}{DIRECTORY};
my $cwd = Cwd::cwd();
$o->{API}{install_lib} =
File::Spec->catdir($cwd,$o->{INLINE}{INST_ARCHLIB});
$o->{API}{location} =
File::Spec->catfile($o->{API}{install_lib},"auto",$o->{API}{modpname},
"$o->{API}{modfname}.$o->{INLINE}{ILSM_suffix}");
unshift @::INC, $o->{API}{install_lib};
$o->{INLINE}{object_ready} = 0;
}
#==============================================================================
# Create the .inl file for an object
#==============================================================================
sub write_inl_file {
my $o = shift;
my $inl =
File::Spec->catfile($o->{API}{install_lib},"auto",$o->{API}{modpname},
"$o->{API}{modfname}.inl");
open INL, "> $inl"
or croak "Can't create Inline validation file $inl: $!";
my $apiversion = $Config{apiversion} || $Config{xs_apiversion};
print INL Inline::denter->new()
->indent(*md5, $o->{INLINE}{md5},
*name, $o->{API}{module},
*version, $o->{CONFIG}{VERSION},
*language, $o->{API}{language},
*language_id, $o->{API}{language_id},
*installed, $o->{CONFIG}{_INSTALL_},
*date_compiled, scalar localtime,
*inline_version, $Inline::VERSION,
*ILSM, { map {($_, $o->{INLINE}{"ILSM_$_"})}
(qw( module suffix type ))
},
*Config, { (map {($_,$Config{$_})}
(qw( archname osname osvers
cc ccflags ld so version
))),
(apiversion => $apiversion),
},
);
close INL;
}
#==============================================================================
# Get config hints
#==============================================================================
sub with_configs {
my $o = shift;
my @configs;
for my $mod (@{$o->{CONFIG}{WITH}}) {
my $ref = eval { $mod->Inline($o->{API}{language}); };
croak M25_no_WITH_support($mod, $@) if $@;
croak M65_WITH_not_lang($mod, $o->{API}{language}) unless $ref;
push @configs, %$ref;
}
return @configs;
}
#==============================================================================
# Blindly untaint tainted fields in %ENV.
#==============================================================================
sub env_untaint {
my $o = shift;
warn "In Inline::env_untaint() : Blindly untainting tainted fields in %ENV.\n" unless $o->{CONFIG}{NO_UNTAINT_WARN};
{
no warnings ('uninitialized'); # In case $ENV{$_} is set to undef.
for (keys %ENV) {
($ENV{$_}) = $ENV{$_} =~ /(.*)/;
}
}
# only accept dirs that are absolute and not world-writable
$ENV{PATH} = $^O eq 'MSWin32' ?
join ';', grep {not /^\./ and -d $_
} split /;/, $ENV{PATH}
:
join ':', grep {/^\// and -d $_ and $< == $> ? 1 : not (-W $_ or -O $_)
} split /:/, $ENV{PATH};
map {($_) = /(.*)/} @INC;
# list cherry-picked from `perldoc perlrun`
delete @ENV{qw(PERL5OPT PERL5SHELL PERL_ROOT IFS CDPATH ENV BASH_ENV)};
$ENV{SHELL} = '/bin/sh' if -x '/bin/sh';
$< = $> if $< != $>; # so child processes retain euid - ignore failure
}
#==============================================================================
# Blindly untaint tainted fields in Inline object.
#==============================================================================
sub obj_untaint {
my $o = shift;
warn "In Inline::obj_untaint() : Blindly untainting tainted fields in Inline object.\n" unless $o->{CONFIG}{NO_UNTAINT_WARN};
($o->{INLINE}{ILSM_module}) = $o->{INLINE}{ILSM_module} =~ /(.*)/;
($o->{API}{directory}) = $o->{API}{directory} =~ /(.*)/;
($o->{API}{build_dir}) = $o->{API}{build_dir} =~ /(.*)/;
($o->{CONFIG}{DIRECTORY}) = $o->{CONFIG}{DIRECTORY} =~ /(.*)/;
($o->{API}{install_lib}) = $o->{API}{install_lib} =~ /(.*)/;
($o->{API}{modpname}) = $o->{API}{modpname} =~ /(.*)/;
($o->{API}{modfname}) = $o->{API}{modfname} =~ /(.*)/;
($o->{API}{language}) = $o->{API}{language} =~ /(.*)/;
($o->{API}{pkg}) = $o->{API}{pkg} =~ /(.*)/;
($o->{API}{module}) = $o->{API}{module} =~ /(.*)/;
}
#==============================================================================
# Clean the build directory from previous builds
#==============================================================================
sub clean_build {
use strict;
my ($prefix, $dir);
my $o = shift;
inc/Inline.pm view on Meta::CPAN
use Inline language => 'DATA', config-pair-list;
use Inline language => 'Config', config-pair-list;
use Inline Config => config-pair-list;
use Inline with => module-list;
use Inline shortcut-list;
END
# This is broken ????????????????????????????????????????????????????
$usage .= <<END if defined $Inline::languages;
Supported languages:
${\ join(', ', sort keys %$Inline::languages)}
END
return $usage;
}
sub M03_usage_bind {
my $usage = <<END;
Invalid usage of the Inline->bind() function. Valid usages are:
Inline->bind(language => "source-string", config-pair-list);
Inline->bind(language => "source-file", config-pair-list);
Inline->bind(language => [source-line-list], config-pair-list);
END
$usage .= <<END if defined $Inline::languages;
Supported languages:
${\ join(', ', sort keys %$Inline::languages)}
END
return $usage;
}
sub M04_error_nocode {
my ($language) = @_;
return <<END;
No $language source code found for Inline.
END
}
sub M05_error_eval {
my ($subroutine, $msg) = @_;
return <<END;
An eval() failed in Inline::$subroutine:
$msg
END
}
sub M06_code_file_failed_open {
my ($file) = @_;
return <<END;
Couldn't open Inline code file '$file':
$!
END
#'
}
sub M07_code_file_does_not_exist {
my ($file) = @_;
return <<END;
Inline assumes '$file' is a filename,
and that file does not exist.
END
}
sub M08_no_DATA_source_code {
my ($lang) = @_;
return <<END;
No source code in DATA section for Inline '$lang' section.
END
}
sub M09_marker_mismatch {
my ($marker, $lang) = @_;
return <<END;
Marker '$marker' does not match Inline '$lang' section.
END
}
sub M10_usage_WITH_USING {
return <<END;
Config option WITH or USING must be a module name or an array ref
of module names.
END
}
sub M11_usage_DIRECTORY {
my ($value) = @_;
return <<END;
Invalid value '$value' for config option DIRECTORY
END
}
sub M12_usage_NAME {
my ($name) = @_;
return <<END;
Invalid value for NAME config option: '$name'
END
}
sub M13_usage_VERSION {
my ($version) = @_;
return <<END;
Invalid value for VERSION config option: '$version'
Must be of the form '#.##'.
(Should also be specified as a string rather than a floating point number)
END
}
sub M14_usage_Config {
return <<END;
inc/Inline.pm view on Meta::CPAN
return <<END;
Can't open directory '$dir'.
END
#'
}
sub M22_usage_register {
my ($language, $error) = @_;
return <<END;
The module Inline::$language does not support the Inline API, because it does
properly support the register() method. This module will not work with Inline
and should be uninstalled from your system. Please advise your sysadmin.
The following error was generating from this module:
$error
END
}
sub M23_usage_alias_used {
my ($new_mod, $alias, $old_mod) = @_;
return <<END;
The module Inline::$new_mod is attempting to define $alias as an alias.
But $alias is also an alias for Inline::$old_mod.
One of these modules needs to be corrected or removed.
Please notify the system administrator.
END
}
sub M24_open_for_output_failed {
my ($file) = @_;
return <<END;
Can't open $file for output.
$!
END
#'
}
sub M25_no_WITH_support {
my ($mod, $err) = @_;
return <<END;
You have requested "use Inline with => '$mod'"
but '$mod' does not work with Inline.
$err
END
}
sub M26_error_version_without_name {
return <<END;
Specifying VERSION option without NAME option is not permitted.
END
}
sub M27_module_not_indexed {
my ($mod) = @_;
return <<END;
You are attempting to load an extension for '$mod',
but there is no entry for that module in %INC.
END
}
sub M28_error_grokking_path {
my ($path) = @_;
return <<END;
Can't calculate a path from '$path' in %INC
END
}
sub M29_error_relative_path {
my ($name, $path) = @_;
return <<END;
Can't load installed extension '$name'
from relative path '$path'.
END
#'
}
sub M30_error_no_obj {
my ($name, $pkg, $path) = @_;
<<END;
The extension '$name' is not properly installed in path:
'$path'
If this is a CPAN/distributed module, you may need to reinstall it on your
system.
To allow Inline to compile the module in a temporary cache, simply remove the
Inline config option 'VERSION=' from the $pkg module.
END
}
sub M31_inline_open_failed {
my ($file) = @_;
return <<END;
Can't open Inline validate file:
$file
$!
END
#'
}
sub M32_error_md5_validation {
my ($md5, $inl) = @_;
return <<END;
The source code fingerprint:
$md5
inc/Inline.pm view on Meta::CPAN
END
#'
}
sub M55_unlink_failed {
my ($file) = @_;
return <<END;
Can't unlink file '$file':
$!
END
#'
}
sub M56_no_DIRECTORY_found {
return <<END;
Couldn't find an appropriate DIRECTORY for Inline to use.
END
#'
}
sub M57_wrong_architecture {
my ($ext, $arch, $thisarch) = @_;
return <<END;
The extension '$ext'
is built for perl on the '$arch' platform.
This is the '$thisarch' platform.
END
}
sub M58_site_install {
return <<END;
You have specified the SITE_INSTALL command. Support for this option has
been removed from Inline since version 0.40. It has been replaced by the
use of Inline::MakeMaker in your Makefile.PL. Please see the Inline
documentation for more help on creating and installing Inline based modules.
END
}
sub M59_bad_inline_file {
my ($lang) = @_;
return <<END;
Could not find any Inline source code for the '$lang' language using
the Inline::Files module.
END
}
sub M60_no_inline_files {
return <<END;
It appears that you have requested to use Inline with Inline::Files.
You need to explicitly 'use Inline::Files;' before your 'use Inline'.
END
}
sub M61_not_parsed {
return <<END;
It does not appear that your program has been properly parsed by Inline::Files.
END
}
sub M62_invalid_config_file {
my ($config) = @_;
return <<END;
You are using a config file that was created by an older version of Inline:
$config
This file and all the other components in its directory are no longer valid
for this version of Inline. The best thing to do is simply delete all the
contents of the directory and let Inline rebuild everything for you. Inline
will do this automatically when you run your programs.
END
}
sub M63_no_source {
my ($pkg) = @_;
return <<END;
This module $pkg can not be loaded and has no source code.
You may need to reinstall this module.
END
}
sub M64_install_not_c {
my ($lang) = @_;
return <<END;
Invalid attempt to install an Inline module using the '$lang' language.
Only C and CPP (C++) based modules are currently supported.
END
}
sub M65_WITH_not_lang {
my ($mod, $lang) = @_;
return <<END;
$mod gave no 'with' hints for $lang.
END
}
1;
( run in 1.554 second using v1.01-cache-2.11-cpan-39bf76dae61 )