use Config;
use File::Basename qw(&basename &dirname);
+use Cwd;
# List explicitly here the variables you want Configure to
# generate. Metaconfig only looks for shell variables, so you
# This forces PL files to create target in same directory as PL file.
# This is so that make depend always knows where to find PL derivatives.
-chdir(dirname($0));
-($file = basename($0)) =~ s/\.PL$//;
-$file =~ s/\.pl$//
- if ($^O eq 'VMS' or $^O eq 'os2'); # "case-forgiving"
+$origdir = cwd;
+chdir dirname($0);
+$file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
open OUT,">$file" or die "Can't create $file: $!";
# You can use $Config{...} to use Configure variables.
print OUT <<"!GROK!THIS!";
-$Config{'startperl'}
- eval 'exec perl -S \$0 "\$@"'
- if 0;
+$Config{startperl}
+ eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+ if \$running_under_some_shell;
!GROK!THIS!
# In the following, perl variables are not expanded during extraction.
=head1 SYNOPSIS
-B<h2xs> [B<-AOPXcf>] [B<-v> version] [B<-n> module_name] [B<-p> prefix] [B<-s> sub] [headerfile [extra_libraries]]
+B<h2xs> [B<-ACOPXcdf>] [B<-v> version] [B<-n> module_name] [B<-p> prefix] [B<-s> sub] [headerfile ... [extra_libraries]]
B<h2xs> B<-h>
=head1 DESCRIPTION
-I<h2xs> builds a Perl extension from any C header file. The extension will
-include functions which can be used to retrieve the value of any #define
-statement which was in the C header.
+I<h2xs> builds a Perl extension from C header files. The extension
+will include functions which can be used to retrieve the value of any
+#define statement which was in the C header files.
The I<module_name> will be used for the name of the extension. If
-module_name is not supplied then the name of the header file will be used,
-with the first character capitalized.
+module_name is not supplied then the name of the first header file
+will be used, with the first character capitalized.
If the extension might need extra libraries, they should be included
here. The extension Makefile.PL will take care of checking whether
=item B<-A>
Omit all autoload facilities. This is the same as B<-c> but also removes the
-S<C<require AutoLoader>> statement from the .pm file.
+S<C<use AutoLoader>> statement from the .pm file.
+
+=item B<-C>
+
+Omits creation of the F<Changes> file, and adds a HISTORY section to
+the POD template.
+
+=item B<-F>
+
+Additional flags to specify to C preprocessor when scanning header for
+function declarations. Should not be used without B<-x>.
=item B<-O>
Omit the autogenerated stub POD section.
+=item B<-X>
+
+Omit the XS portion. Used to generate templates for a module which is not
+XS-based. C<-c> and C<-f> are implicitly enabled.
+
=item B<-c>
Omit C<constant()> from the .xs file and corresponding specialised
C<AUTOLOAD> from the .pm file.
+=item B<-d>
+
+Turn on debugging messages.
+
=item B<-f>
Allows an extension to be created for a header even if that header is
Specify a prefix which should be removed from the Perl function names, e.g., S<-p sec_rgy_>
This sets up the XS B<PREFIX> keyword and removes the prefix from functions that are
-autoloaded via the C<constant()> mechansim.
+autoloaded via the C<constant()> mechanism.
=item B<-s> I<sub1,sub2>
Specify a version number for this extension. This version number is added
to the templates. The default is 0.01.
-=item B<-X>
-
-Omit the XS portion. Used to generate templates for a module which is not
-XS-based.
-
=item B<-x>
Automatically generate XSUBs basing on function declarations in the
header file. The package C<C::Scan> should be installed. If this
option is specified, the name of the header file may look like
C<NAME1,NAME2>. In this case NAME1 is used instead of the specified string,
-but XSUBS are emited only for the declarations included from file NAME2.
+but XSUBs are emitted only for the declarations included from file NAME2.
Note that some types of arguments/return-values for functions may
result in XSUB-declarations/typemap-entries which need
hand-editing. Such may be objects which cannot be converted from/to a
pointer (like C<long long>), pointers to functions, or arrays.
-=item B<-F>
-
-Additional flags to specify to C preprocessor when scanning header for
-function declarations. Should not be used without B<-x>.
-
=back
=head1 EXAMPLES
=cut
-my( $H2XS_VERSION ) = ' $Revision: 1.16 $ ' =~ /\$Revision:\s+([^\s]+)/;
+my( $H2XS_VERSION ) = ' $Revision: 1.19 $ ' =~ /\$Revision:\s+([^\s]+)/;
my $TEMPLATE_VERSION = '0.01';
use Getopt::Std;
sub usage{
warn "@_\n" if @_;
- die "h2xs [-AOPXcfh] [-v version] [-n module_name] [-p prefix] [-s subs] [headerfile [extra_libraries]]
+ die "h2xs [-ACOPXcdfh] [-v version] [-n module_name] [-p prefix] [-s subs] [headerfile [extra_libraries]]
version: $H2XS_VERSION
+ -A Omit all autoloading facilities (implies -c).
+ -C Omit creating the Changes file, add HISTORY heading to stub POD.
+ -F Additional flags for C preprocessor (used with -x).
+ -O Allow overwriting of a pre-existing extension directory.
+ -P Omit the stub POD section.
+ -X Omit the XS portion (implies both -c and -f).
+ -c Omit the constant() function and specialised AUTOLOAD from the XS file.
+ -d Turn on debugging messages.
-f Force creation of the extension even if the C header does not exist.
+ -h Display this help message
-n Specify a name to use for the extension (recommended).
- -c Omit the constant() function and specialised AUTOLOAD from the XS file.
-p Specify a prefix which should be removed from the Perl function names.
-s Create subroutines for specified macros.
- -A Omit all autoloading facilities (implies -c).
- -O Allow overwriting of a pre-existing extension directory.
- -P Omit the stub POD section.
- -X Omit the XS portion.
-v Specify a version number for this extension.
-x Autogenerate XSUBs using C::Scan.
- -F Additional flags for C preprocessor (used with -x).
- -h Display this help message
extra_libraries
are any libraries that might be needed for loading the
extension, e.g. -lm would try to link in the math library.
}
-getopts("AOPXcfhxv:n:p:s:F:") || usage;
+getopts("ACF:OPXcdfhn:p:s:v:x") || usage;
usage if $opt_h;
if( $opt_v ){
$TEMPLATE_VERSION = $opt_v;
}
+
+# -A implies -c.
$opt_c = 1 if $opt_A;
+
+# -X implies -c and -f
+$opt_c = $opt_f = 1 if $opt_X;
+
%const_xsub = map { $_,1 } split(/,+/, $opt_s) if $opt_s;
-$path_h = shift;
-$extralibs = "@ARGV";
+while (my $arg = shift) {
+ if ($arg =~ /^-l/i) {
+ $extralibs = "$arg @ARGV";
+ last;
+ }
+ push(@path_h, $arg);
+}
usage "Must supply header file or module name\n"
- unless ($path_h or $opt_n);
+ unless (@path_h or $opt_n);
-if( $path_h ){
- $name = $path_h;
+if( @path_h ){
+ foreach my $path_h (@path_h) {
+ $name ||= $path_h;
if( $path_h =~ s#::#/#g && $opt_n ){
warn "Nesting of headerfile ignored with -n\n";
}
die "Can't find $path_h\n" if ( ! $opt_f && ! -f $path_h );
# Scan the header file (we should deal with nested header files)
# Record the names of simple #define constants into const_names
- # Function prototypes are not (currently) processed.
+ # Function prototypes are processed below.
open(CH, "<$path_h") || die "Can't open $path_h: $!\n";
while (<CH>) {
- if (/^ #[ \t]*define\s+([\$\w]+)\b\s*[^("]/) {
- print "Matched $_ ($1)\n";
+ if (/^#[ \t]*define\s+([\$\w]+)\b\s*[^("]/) {
+ print "Matched $_ ($1)\n" if $opt_d;
$_ = $1;
next if /^_.*_h_*$/i; # special case, but for what?
if (defined $opt_p) {
}
}
close(CH);
- @const_names = sort keys %const_names;
}
+ }
+ @const_names = sort keys %const_names;
}
my %types_seen;
my %std_types;
-my $fdecls;
-my $fdecls_parsed;
+my $fdecls = [];
+my $fdecls_parsed = [];
if( ! $opt_X ){ # use XS, unless it was disabled
open(XS, ">$modfname.xs") || die "Can't create $ext$modpname/$modfname.xs: $!\n";
get_typemap();
my $c;
my $filter;
- my $filename = $path_h;
- my $addflags = $opt_F || '';
- if ($fullpath =~ /,/) {
- $filename = $`;
- $filter = $';
+ foreach my $filename (@path_h) {
+ my $addflags = $opt_F || '';
+ if ($fullpath =~ /,/) {
+ $filename = $`;
+ $filter = $';
+ }
+ warn "Scanning $filename for functions...\n";
+ $c = new C::Scan 'filename' => $filename, 'filename_filter' => $filter,
+ 'add_cppflags' => $addflags;
+ $c->set('includeDirs' => ["$Config::Config{archlib}/CORE"]);
+
+ push @$fdecls_parsed, @{ $c->get('parsed_fdecls') };
+ push(@$fdecls, @{$c->get('fdecls')});
}
- warn "Scanning $filename for functions...\n";
- $c = new C::Scan 'filename' => $filename, 'filename_filter' => $filter,
- 'add_cppflags' => $addflags;
- $c->set('includeDirs' => ["$Config::Config{archlib}/CORE"]);
-
- $fdecls_parsed = $c->get('parsed_fdecls');
- $fdecls = $c->get('fdecls');
}
}
if( $opt_X || $opt_c || $opt_A ){
# we won't have our own AUTOLOAD(), so won't have $AUTOLOAD
print PM <<'END';
-use vars qw($VERSION @ISA @EXPORT);
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
END
}
else{
# will want Carp.
print PM <<'END';
use Carp;
-use vars qw($VERSION @ISA @EXPORT $AUTOLOAD);
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
END
}
require DynaLoader;
END
-# require autoloader if XS is disabled.
-# if XS is enabled, require autoloader unless autoloading is disabled.
-if( $opt_X || (! $opt_A) ){
- print PM <<"END";
-require AutoLoader;
-END
-}
-if( $opt_X || ($opt_c && ! $opt_A) ){
- # we won't have our own AUTOLOAD(), so we'll inherit it.
- if( ! $opt_X ) { # use DynaLoader, unless XS was disabled
- print PM <<"END";
-
-\@ISA = qw(Exporter AutoLoader DynaLoader);
-END
+# Are we using AutoLoader or not?
+unless ($opt_A) { # no autoloader whatsoever.
+ unless ($opt_c) { # we're doing the AUTOLOAD
+ print PM "use AutoLoader;\n";
}
- else{
- print PM <<"END";
-
-\@ISA = qw(Exporter AutoLoader);
-END
+ else {
+ print PM "use AutoLoader qw(AUTOLOAD);\n"
}
}
-else{
- # 1) we have our own AUTOLOAD(), so don't need to inherit it.
- # or
- # 2) we don't want autoloading mentioned.
- if( ! $opt_X ){ # use DynaLoader, unless XS was disabled
- print PM <<"END";
-
-\@ISA = qw(Exporter DynaLoader);
-END
- }
- else{
- print PM <<"END";
-\@ISA = qw(Exporter);
-END
- }
-}
+# Determine @ISA.
+my $myISA = '@ISA = qw(Exporter'; # We seem to always want this.
+$myISA .= ' DynaLoader' unless $opt_X; # no XS
+$myISA .= ');';
+print PM "\n$myISA\n\n";
print PM<<"END";
# Items to export into callers namespace by default. Note: do not export
my \$constname;
(\$constname = \$AUTOLOAD) =~ s/.*:://;
+ croak "&$module::constant not defined" if \$constname eq 'constant';
my \$val = constant(\$constname, \@_ ? \$_[0] : 0);
if (\$! != 0) {
- if (\$! =~ /Invalid/) {
+ if (\$! =~ /Invalid/ || \$!{EINVAL}) {
\$AutoLoader::AUTOLOAD = \$AUTOLOAD;
goto &AutoLoader::AUTOLOAD;
}
croak "Your vendor has not defined $module macro \$constname";
}
}
- eval "sub \$AUTOLOAD { \$val }";
+ no strict 'refs';
+ *\$AUTOLOAD = sub () { \$val };
goto &\$AUTOLOAD;
}
print PM <<"END";
# Preloaded methods go here.
+END
+
+print PM <<"END" unless $opt_A;
# Autoload methods go after $after, and are processed by the autosplit program.
+END
+
+print PM <<"END";
1;
__END__
$author = "A. U. Thor";
$email = 'a.u.thor@a.galaxy.far.far.away';
+my $revhist = '';
+$revhist = <<EOT if $opt_C;
+
+=head1 HISTORY
+
+=over 8
+
+=item $TEMPLATE_VERSION
+
+Original version; created by h2xs $H2XS_VERSION
+
+=back
+
+EOT
+
my $const_doc = '';
my $fdecl_doc = '';
if (@const_names and not $opt_P) {
$const_doc = <<EOD;
-
-=head1 Exported constants
+\n=head2 Exported constants
@{[join "\n ", @const_names]}
}
if (defined $fdecls and @$fdecls and not $opt_P) {
$fdecl_doc = <<EOD;
-
-=head1 Exported functions
+\n=head2 Exported functions
@{[join "\n ", @$fdecls]}
#unedited.
#
#Blah blah blah.
-#$const_doc$fdecl_doc
+#$const_doc$fdecl_doc$revhist
#=head1 AUTHOR
#
#$author, $email
warn "Writing $ext$modpname/$modfname.xs\n";
print XS <<"END";
-#ifdef __cplusplus
-extern "C" {
-#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
-#ifdef __cplusplus
-}
-#endif
END
-if( $path_h ){
+if( @path_h ){
+ foreach my $path_h (@path_h) {
my($h) = $path_h;
$h =~ s#^/usr/include/##;
if ($^O eq 'VMS') { $h =~ s#.*vms\]#sys/# or $h =~ s#.*[:>\]]##; }
-print XS <<"END";
-#include <$h>
-
-END
+ print XS qq{#include <$h>\n};
+ }
+ print XS "\n";
}
if( ! $opt_c ){
print XS <<"END";
static int
-not_here(s)
-char *s;
+not_here(char *s)
{
croak("$module::%s not implemented on this architecture", s);
return -1;
}
static double
-constant(name, arg)
-char *name;
-int arg;
+constant(char *name, int arg)
{
errno = 0;
switch (*name) {
_END_
close(EX) || die "Can't close $ext$modpname/test.pl: $!\n";
-warn "Writing $ext$modpname/Changes\n";
-open(EX, ">Changes") || die "Can't create $ext$modpname/Changes: $!\n";
-print EX "Revision history for Perl extension $module.\n\n";
-print EX "$TEMPLATE_VERSION ",scalar localtime,"\n";
-print EX "\t- original version; created by h2xs $H2XS_VERSION\n\n";
-close(EX) || die "Can't close $ext$modpname/Changes: $!\n";
+unless ($opt_C) {
+ warn "Writing $ext$modpname/Changes\n";
+ open(EX, ">Changes") || die "Can't create $ext$modpname/Changes: $!\n";
+ print EX "Revision history for Perl extension $module.\n\n";
+ print EX "$TEMPLATE_VERSION ",scalar localtime,"\n";
+ print EX "\t- original version; created by h2xs $H2XS_VERSION\n\n";
+ close(EX) || die "Can't close $ext$modpname/Changes: $!\n";
+}
warn "Writing $ext$modpname/MANIFEST\n";
open(MANI,'>MANIFEST') or die "Can't create MANIFEST: $!";
unless ($@) { @files = readdir(D); closedir(D); }
}
if (!@files) { @files = map {chomp && $_} `ls`; }
-print MANI join("\n",@files);
+if ($^O eq 'VMS') {
+ foreach (@files) {
+ # Clip trailing '.' for portability -- non-VMS OSs don't expect it
+ s%\.$%%;
+ # Fix up for case-sensitive file systems
+ s/$modfname/$modfname/i && next;
+ $_ = "\U$_" if $_ eq 'manifest' or $_ eq 'changes';
+ $_ = 'Makefile.PL' if $_ eq 'makefile.pl';
+ }
+}
+print MANI join("\n",@files), "\n";
close MANI;
!NO!SUBS!
close OUT or die "Can't close $file: $!";
chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;