-
use Config;
sub to_string {
return "'$value'";
}
+#
+# subroutine expand_os_specific expands $^O-specific preprocessing information
+# so that it will not be re-calculated at runtime in Dynaloader.pm
+#
+# Syntax of preprocessor should be kept extremely simple:
+# - directives are in double angle brackets <<...>>
+# - <<=string>> will be just evaluated
+# - for $^O-specific there are two forms:
+# <<$^O-eq-osname>>
+# <<$^O-ne-osname>>
+# this directive should be closed with respectively
+# <</$^O-eq-osname>>
+# <</$^O-ne-osname>>
+# construct <<|$^O-ne-osname>> means #else
+# nested <<$^O...>>-constructs are allowed but nested values must be for
+# different OS-names!
+#
+# -- added by VKON, 03-10-2004 to separate $^O-specific between OSes
+# (so that Win32 never checks for $^O eq 'VMS' for example)
+#
+# The $^O tests test both for $^O and for $Config{osname}.
+# The latter is better for some for cross-compilation setups.
+#
+sub expand_os_specific {
+ my $s = shift;
+ for ($s) {
+ s/<<=(.*?)>>/$1/gee;
+ s/<<\$\^O-(eq|ne)-(\w+)>>(.*?)<<\/\$\^O-\1-\2>>/
+ my ($op, $os, $expr) = ($1,$2,$3);
+ if ($op ne 'eq' and $op ne 'ne') {die "wrong eq-ne arg in $&"};
+ if ($expr =~ m[^(.*?)<<\|\$\^O-$op-$os>>(.*?)$]s) {
+ # #if;#else;#endif
+ my ($if,$el) = ($1,$2);
+ if (($op eq 'eq' and ($^O eq $os || $Config{osname} eq $os)) || ($op eq 'ne' and ($^O ne $os || $Config{osname} ne $os))) {
+ $if
+ }
+ else {
+ $el
+ }
+ }
+ else {
+ # #if;#endif
+ if (($op eq 'eq' and ($^O eq $os || $Config{osname} eq $os)) || ($op eq 'ne' and ($^O ne $os || $Config{osname} ne $os))) {
+ $expr
+ }
+ else {
+ ""
+ }
+ }
+ /ges;
+ if (/<<(=|\$\^O-)/) {die "bad <<\$^O-eq/ne-osname>> expression.".
+ " Unclosed brackets?";
+ }
+ }
+ $s;
+}
+
unlink "DynaLoader.pm" if -f "DynaLoader.pm";
open OUT, ">DynaLoader.pm" or die $!;
print OUT <<'EOT';
-# Generated from DynaLoader.pm.PL (resolved %Config::Config values)
+# Generated from DynaLoader.pm.PL
package DynaLoader;
#
# Tim.Bunce@ig.co.uk, August 1994
-$VERSION = "1.04"; # avoid typo warning
+$VERSION = '1.07';
require AutoLoader;
*AUTOLOAD = \&AutoLoader::AUTOLOAD;
-# The following require can't be removed during maintenance
-# releases, sadly, because of the risk of buggy code that does
-# require Carp; Carp::croak "..."; without brackets dying
-# if Carp hasn't been loaded in earlier compile time. :-(
-# We'll let those bugs get found on the development track.
-require Carp if $] < 5.00450;
-
+use Config;
# enable debug/trace messages from DynaLoader perl code
$dl_debug = $ENV{PERL_DL_DEBUG} || 0 unless defined $dl_debug;
# = @Config::Config{'dlext', 'dlsrc'};
EOT
-print OUT " (\$dl_dlext, \$dlsrc) = (",
- to_string($Config::Config{'dlext'}), ",",
- to_string($Config::Config{'dlsrc'}), ")\n;" ;
+$dl_dlext = $Config::Config{'dlext'};
+$dl_so = $Config::Config{'so'};
+print OUT " (\$dl_dlext, \$dlsrc) = ('$dl_dlext', ",
+ to_string($Config::Config{'dlsrc'}), ")\n;";
-print OUT <<'EOT';
+print OUT expand_os_specific(<<'EOT');
+<<$^O-eq-VMS>>
# Some systems need special handling to expand file specifications
# (VMS support by Charles Bailey <bailey@HMIVAX.HUMGEN.UPENN.EDU>)
# See dl_expandspec() for more details. Should be harmless but
# inefficient to define on systems that don't need it.
-$do_expand = $Is_VMS = $^O eq 'VMS';
-$Is_MacOS = $^O eq 'MacOS';
+$Is_VMS = $^O eq 'VMS';
+<</$^O-eq-VMS>>
+$do_expand = <<$^O-eq-VMS>>1<<|$^O-eq-VMS>>0<</$^O-eq-VMS>>;
+
+<<$^O-eq-MacOS>>
+my $Mac_FS;
+$Mac_FS = eval { require Mac::FileSpec::Unixish };
+<</$^O-eq-MacOS>>
@dl_require_symbols = (); # names of symbols we need
@dl_resolve_using = (); # names of files to link with
@dl_library_path = (); # path to look for files
+
+#XSLoader.pm may have added elements before we were required
+#@dl_shared_objects = (); # shared objects for symbols we have
#@dl_librefs = (); # things we have loaded
#@dl_modules = (); # Modules we have loaded
# This is a fix to support DLD's unfortunate desire to relink -lc
@dl_resolve_using = dl_findfile('-lc') if $dlsrc eq "dl_dld.xs";
-# Initialise @dl_library_path with the 'standard' library path
-# for this platform as determined by Configure
+EOT
-# push(@dl_library_path, split(' ', $Config::Config{'libpth'});
+my $cfg_dl_library_path = <<'EOT';
+push(@dl_library_path, split(' ', $Config::Config{libpth}));
EOT
-print OUT "push(\@dl_library_path, split(' ', ",
- to_string($Config::Config{'libpth'}), "));\n";
+sub dquoted_comma_list {
+ join(", ", map {'"'.quotemeta($_).'"'} @_);
+}
-print OUT <<'EOT';
+if ($ENV{PERL_BUILD_EXPAND_CONFIG_VARS}) {
+ eval $cfg_dl_library_path;
+ if (!$ENV{PERL_BUILD_EXPAND_ENV_VARS}) {
+ my $dl_library_path = dquoted_comma_list(@dl_library_path);
+ print OUT <<EOT;
+# The below \@dl_library_path has been expanded (%Config) in Perl build time.
+
+\@dl_library_path = ($dl_library_path);
+
+EOT
+ }
+}
+else {
+ print OUT <<EOT;
+# Initialise \@dl_library_path with the 'standard' library path
+# for this platform as determined by Configure.
+
+$cfg_dl_library_path
+
+EOT
+}
+
+my $ldlibpthname;
+my $ldlibpthname_defined;
+my $pthsep;
+
+if ($ENV{PERL_BUILD_EXPAND_CONFIG_VARS}) {
+ $ldlibpthname = to_string($Config::Config{ldlibpthname});
+ $ldlibpthname_defined = to_string(defined $Config::Config{ldlibpthname} ? 1 : 0);
+ $pthsep = to_string($Config::Config{path_sep});
+}
+else {
+ $ldlibpthname = q($Config::Config{ldlibpthname});
+ $ldlibpthname_defined = q(defined $Config::Config{ldlibpthname});
+ $pthsep = q($Config::Config{path_sep});
+}
+print OUT <<EOT;
+my \$ldlibpthname = $ldlibpthname;
+my \$ldlibpthname_defined = $ldlibpthname_defined;
+my \$pthsep = $pthsep;
+
+EOT
+
+my $env_dl_library_path = <<'EOT';
+if ($ldlibpthname_defined &&
+ exists $ENV{$ldlibpthname}) {
+ push(@dl_library_path, split(/$pthsep/, $ENV{$ldlibpthname}));
+}
-# Add to @dl_library_path any extra directories we can gather
-# from environment variables.
-if ($Is_MacOS) {
- push(@dl_library_path, split(/,/, $ENV{LD_LIBRARY_PATH}))
- if exists $ENV{LD_LIBRARY_PATH};
-} else {
-# push(@dl_library_path, split(/:/, $ENV{$Config::Config{ldlibpthname}}))
-# if exists $Config::Config{ldlibpthname} &&
-# $Config::Config{ldlibpthname} ne '' &&
-# exists $ENV{$Config::Config{ldlibpthname}} ;;
-# push(@dl_library_path, split(/:/, $ENV{$Config::Config{ldlibpthname}}))
-# if exists $Config::Config{ldlibpthname} &&
-# $Config::Config{ldlibpthname} ne '' &&
-# exists $ENV{$Config::Config{ldlibpthname}} ;;
# E.g. HP-UX supports both its native SHLIB_PATH *and* LD_LIBRARY_PATH.
-# push(@dl_library_path, split(/:/, $ENV{LD_LIBRARY_PATH}))
-# if exists $ENV{LD_LIBRARY_PATH};
+
+if ($ldlibpthname_defined &&
+ $ldlibpthname ne 'LD_LIBRARY_PATH' &&
+ exists $ENV{LD_LIBRARY_PATH}) {
+ push(@dl_library_path, split(/$pthsep/, $ENV{LD_LIBRARY_PATH}));
+}
EOT
-# Make a list of paths to print.
-# HP-UX supports both its native SHLIB_PATH *and* LD_LIBRARY_PATH,
-# but for other OSes no point pushing 'LD_LIBRARY_PATH' twice.
-my @ldlibpthname = 'LD_LIBRARY_PATH';
-if (exists $Config::Config{ldlibpthname}
- and length $Config::Config{ldlibpthname}
- and $Config::Config{ldlibpthname} ne 'LD_LIBRARY_PATH') {
- unshift @ldlibpthname, $Config::Config{ldlibpthname};
+if ($ENV{PERL_BUILD_EXPAND_CONFIG_VARS} && $ENV{PERL_BUILD_EXPAND_ENV_VARS}) {
+ eval $env_dl_library_path;
}
+else {
+ print OUT <<EOT;
+# Add to \@dl_library_path any extra directories we can gather from environment
+# during runtime.
+
+$env_dl_library_path
-foreach (@ldlibpthname) {
- print OUT " push(\@dl_library_path, split(/:/, \$ENV{", to_string($_),
- "}))\n\tif exists \$ENV{", to_string($_), "};\n";
+EOT
}
-print OUT <<'EOT';
+if ($ENV{PERL_BUILD_EXPAND_CONFIG_VARS} && $ENV{PERL_BUILD_EXPAND_ENV_VARS}) {
+ my $dl_library_path = dquoted_comma_list(@dl_library_path);
+ print OUT <<EOT;
+# The below \@dl_library_path has been expanded (%Config, %ENV)
+# in Perl build time.
+
+\@dl_library_path = ($dl_library_path);
+
+EOT
}
+
+# following long string contains $^O-specific stuff, which is factored out
+print OUT expand_os_specific(<<'EOT');
# No prizes for guessing why we don't say 'bootstrap DynaLoader;' here.
# NOTE: All dl_*.xs (including dl_none.xs) define a dl_error() XSUB
boot_DynaLoader('DynaLoader') if defined(&boot_DynaLoader) &&
" dynamic loading or has the $module module statically linked into it.)\n")
unless defined(&dl_load_file);
+
+ <<$^O-eq-os2>>
+ # Can dynaload, but cannot dynaload Perl modules...
+ die 'Dynaloaded Perl modules are not available in this build of Perl' if $OS2::is_static;
+
+ <</$^O-eq-os2>>
my @modparts = split(/::/,$module);
my $modfname = $modparts[-1];
# It may also edit @modparts if required.
$modfname = &mod2fname(\@modparts) if defined &mod2fname;
- my $modpname = join(($Is_MacOS ? ':' : '/'),@modparts);
+ <<$^O-eq-NetWare>>
+ # Truncate the module name to 8.3 format for NetWare
+ if ((length($modfname) > 8)) {
+ $modfname = substr($modfname, 0, 8);
+ }
+ <</$^O-eq-NetWare>>
+
+ my $modpname = join(<<$^O-eq-MacOS>>':'<<|$^O-eq-MacOS>>'/'<</$^O-eq-MacOS>>,@modparts);
print STDERR "DynaLoader::bootstrap for $module ",
- ($Is_MacOS
- ? "(:auto:$modpname:$modfname.$dl_dlext)\n" :
- "(auto/$modpname/$modfname.$dl_dlext)\n")
+ <<$^O-eq-MacOS>> "(:auto:$modpname:$modfname.<<=$dl_dlext>>)\n"
+ <<|$^O-eq-MacOS>>"(auto/$modpname/$modfname.<<=$dl_dlext>>)\n"<</$^O-eq-MacOS>>
if $dl_debug;
foreach (@INC) {
- chop($_ = VMS::Filespec::unixpath($_)) if $Is_VMS;
- my $dir;
- if ($Is_MacOS) {
- chop $_ if /:$/;
- $dir = "$_:auto:$modpname";
- } else {
- $dir = "$_/auto/$modpname";
- }
+ <<$^O-eq-VMS>>chop($_ = VMS::Filespec::unixpath($_));<</$^O-eq-VMS>>
+ <<$^O-eq-MacOS>>
+ my $path = $_;
+ if ($Mac_FS && ! -d $path) {
+ $path = Mac::FileSpec::Unixish::nativize($path);
+ }
+ $path .= ":" unless /:$/;
+ my $dir = "${path}auto:$modpname";
+ <<|$^O-eq-MacOS>>
+ my $dir = "$_/auto/$modpname";
+ <</$^O-eq-MacOS>>
+
next unless -d $dir; # skip over uninteresting directories
-
+
# check for common cases to avoid autoload of dl_findfile
- my $try = $Is_MacOS ? "$dir:$modfname.$dl_dlext" : "$dir/$modfname.$dl_dlext";
- last if $file = ($do_expand) ? dl_expandspec($try) : (-f $try && $try);
-
+ my $try = <<$^O-eq-MacOS>> "$dir:$modfname.<<=$dl_dlext>>" <<|$^O-eq-MacOS>> "$dir/$modfname.<<=$dl_dlext>>"<</$^O-eq-MacOS>>;
+ last if $file = <<$^O-eq-VMS>>($do_expand) ? dl_expandspec($try) : ((-f $try) && $try);
+ <<|$^O-eq-VMS>>(-f $try) && $try;
+ <</$^O-eq-VMS>>
+
# no luck here, save dir for possible later dl_findfile search
push @dirs, $dir;
}
croak("Can't locate loadable object for module $module in \@INC (\@INC contains: @INC)")
unless $file; # wording similar to error from 'require'
- $file = uc($file) if $Is_VMS && $Config{d_vms_case_sensitive_symbols};
+ <<$^O-eq-VMS>>$file = uc($file) if $Config::Config{d_vms_case_sensitive_symbols};<</$^O-eq-VMS>>
my $bootname = "boot_$module";
$bootname =~ s/\W/_/g;
@dl_require_symbols = ($bootname);
warn "$bs: $@\n" if $@;
}
+ my $boot_symbol_ref;
+
+ <<$^O-eq-darwin>>
+ if ($boot_symbol_ref = dl_find_symbol(0, $bootname)) {
+ goto boot; #extension library has already been loaded, e.g. darwin
+ }
+ <</$^O-eq-darwin>>
+
# Many dynamic extension loading problems will appear to come from
# this section of code: XYZ failed at line 123 of DynaLoader.pm.
# Often these errors are actually occurring in the initialisation
Carp::carp("Undefined symbols present after loading $file: @unresolved\n");
}
- my $boot_symbol_ref = dl_find_symbol($libref, $bootname) or
+ $boot_symbol_ref = dl_find_symbol($libref, $bootname) or
croak("Can't find '$bootname' symbol in $file\n");
- my $xs = dl_install_xsub("${module}::bootstrap", $boot_symbol_ref, $file);
-
push(@dl_modules, $module); # record loaded module
+ boot:
+ my $xs = dl_install_xsub("${module}::bootstrap", $boot_symbol_ref, $file);
+
# See comment block above
+
+ push(@dl_shared_objects, $file); # record files loaded
+
&$xs(@args);
}
my (@args) = @_;
my (@dirs, $dir); # which directories to search
my (@found); # full paths to real files we have found
-EOT
-
-print OUT ' my $dl_ext= ' . to_string($Config::Config{'dlext'}) .
- "; # \$Config::Config{'dlext'} suffix for perl extensions\n";
-print OUT ' my $dl_so = ' . to_string($Config::Config{'so'}) .
- "; # \$Config::Config{'so'} suffix for shared libraries\n";
-
-print OUT <<'EOT';
+ #my $dl_ext= <<=to_string($Config::Config{'dlext'})>>; # $Config::Config{'dlext'} suffix for perl extensions
+ #my $dl_so = <<=to_string($Config::Config{'so'})>>; # $Config::Config{'so'} suffix for shared libraries
print STDERR "dl_findfile(@args)\n" if $dl_debug;
# accumulate directories but process files as they appear
arg: foreach(@args) {
# Special fast case: full filepath requires no search
- if ($Is_VMS && m%[:>/\]]% && -f $_) {
+ <<$^O-eq-VMS>>
+ if (m%[:>/\]]% && -f $_) {
push(@found,dl_expandspec(VMS::Filespec::vmsify($_)));
last arg unless wantarray;
next;
}
- elsif ($Is_MacOS) {
+ <</$^O-eq-VMS>>
+ <<$^O-eq-MacOS>>
if (m/:/ && -f $_) {
push(@found,$_);
last arg unless wantarray;
}
- }
- elsif (m:/: && -f $_ && !$do_expand) {
+ <</$^O-eq-MacOS>>
+ <<$^O-ne-VMS>>
+ if (m:/: && -f $_) {
push(@found,$_);
last arg unless wantarray;
next;
}
+ <</$^O-ne-VMS>>
# Deal with directories first:
# Using a -L prefix is the preferred option (faster and more robust)
if (m:^-L:) { s/^-L//; push(@dirs, $_); next; }
- if ($Is_MacOS) {
+ <<$^O-eq-MacOS>>
# Otherwise we try to try to spot directories by a heuristic
# (this is a more complicated issue than it first appears)
if (m/:/ && -d $_) { push(@dirs, $_); next; }
}
}
next;
- }
+ <</$^O-eq-MacOS>>
# Otherwise we try to try to spot directories by a heuristic
# (this is a more complicated issue than it first appears)
if (m:/: && -d $_) { push(@dirs, $_); next; }
- # VMS: we may be using native VMS directry syntax instead of
+ <<$^O-eq-VMS>>
+ # VMS: we may be using native VMS directory syntax instead of
# Unix emulation, so check this as well
- if ($Is_VMS && /[:>\]]/ && -d $_) { push(@dirs, $_); next; }
+ if (/[:>\]]/ && -d $_) { push(@dirs, $_); next; }
+ <</$^O-eq-VMS>>
# Only files should get this far...
my(@names, $name); # what filenames to look for
if (m:-l: ) { # convert -lname to appropriate library name
s/-l//;
- push(@names,"lib$_.$dl_so");
+ push(@names,"lib$_.<<=to_string($Config::Config{'so'})>>");
push(@names,"lib$_.a");
} else { # Umm, a bare name. Try various alternatives:
# these should be ordered with the most likely first
- push(@names,"$_.$dl_ext") unless m/\.$dl_ext$/o;
- push(@names,"$_.$dl_so") unless m/\.$dl_so$/o;
- push(@names,"lib$_.$dl_so") unless m:/:;
+ push(@names,"$_.<<=$dl_dlext>>") unless m/\.<<=$dl_dlext>>$/o;
+ push(@names,"$_.<<=$dl_so>>") unless m/\.<<=$dl_so>>$/o;
+ push(@names,"lib$_.<<=$dl_so>>") unless m:/:;
push(@names,"$_.a") if !m/\.a$/ and $dlsrc eq "dl_dld.xs";
push(@names, $_);
}
+ my $dirsep = '/';
+ <<$^O-eq-symbian>>
+ $dirsep = '\\';
+ if ($0 =~ /^([a-z]):/i) {
+ my $drive = $1;
+ @dirs = map { "$drive:$_" } @dirs;
+ @dl_library_path = map { "$drive:$_" } @dl_library_path;
+ }
+ <</$^O-eq-symbian>>
foreach $dir (@dirs, @dl_library_path) {
next unless -d $dir;
- chop($dir = VMS::Filespec::unixpath($dir)) if $Is_VMS;
+ <<$^O-eq-VMS>>
+ chop($dir = VMS::Filespec::unixpath($dir));
+ <</$^O-eq-VMS>>
foreach $name (@names) {
- my($file) = "$dir/$name";
+ my($file) = "$dir$dirsep$name";
print STDERR " checking in $dir for $name\n" if $dl_debug;
$file = ($do_expand) ? dl_expandspec($file) : (-f $file && $file);
#$file = _check_file($file);
my $file = $spec; # default output to input
- if ($Is_VMS) { # dl_expandspec should be defined in dl_vms.xs
+ <<$^O-eq-VMS>>
+ # dl_expandspec should be defined in dl_vms.xs
require Carp;
Carp::croak("dl_expandspec: should be defined in XS file!\n");
- } else {
+ <<|$^O-eq-VMS>>
return undef unless -f $file;
- }
+ <</$^O-eq-VMS>>
print STDERR "dl_expandspec($spec) => $file\n" if $dl_debug;
$file;
}
DynaLoader - Dynamically load C libraries into Perl code
-dl_error(), dl_findfile(), dl_expandspec(), dl_load_file(), dl_unload_file(), dl_find_symbol(), dl_find_symbol_anywhere(), dl_undef_symbols(), dl_install_xsub(), dl_load_flags(), bootstrap() - routines used by DynaLoader modules
-
=head1 SYNOPSIS
package YourPackage;
Perl-to-C 'glue'. There is, for example, no mechanism for calling a C
library function or supplying arguments. A C::DynaLib module
is available from CPAN sites which performs that function for some
-common system types.
+common system types. And since the year 2000, there's also Inline::C,
+a module that allows you to write Perl subroutines in C. Also available
+from your local CPAN site.
DynaLoader Interface Summary
$dl_debug
@dl_librefs
@dl_modules
+ @dl_shared_objects
Implemented in:
bootstrap($modulename) Perl
@filepaths = dl_findfile(@names) Perl
An array of module (package) names that have been bootstrap'ed.
+=item @dl_shared_objects
+
+An array of file names for the shared objects that were loaded.
+
=item dl_error()
Syntax:
Linux, and is a common choice when providing a "wrapper" on other
mechanisms as is done in the OS/2 port.)
-=item dl_loadflags()
+=item dl_load_flags()
Syntax:
- $flags = dl_loadflags $modulename;
+ $flags = dl_load_flags $modulename;
Designed to be a method call, and to be overridden by a derived class
(i.e. a class which has DynaLoader in its @ISA). The definition in