perlcall.pod SAVETMPS/FREETMPS bracket
[p5sagit/p5-mst-13.2.git] / utils / h2xs.PL
index 535ec41..52f590b 100644 (file)
@@ -2,6 +2,7 @@
 
 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
@@ -12,11 +13,10 @@ use File::Basename qw(&basename &dirname);
 
 # 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 ($Config{'osname'} eq 'VMS' or
-           $Config{'osname'} 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: $!";
 
@@ -26,9 +26,9 @@ print "Extracting $file (with variable substitutions)\n";
 # 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.
@@ -41,19 +41,19 @@ h2xs - convert .h C header files to Perl extensions
 
 =head1 SYNOPSIS
 
-B<h2xs> [B<-APcf>] [B<-v> version] [B<-n> module_name] [headerfile [extra_libraries]]
+B<h2xs> [B<-AOPXcdf>] [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
@@ -73,15 +73,33 @@ in the extra-libraries argument.
 Omit all autoload facilities.  This is the same as B<-c> but also removes the
 S<C<require AutoLoader>> statement from the .pm file.
 
+=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>
+
+Allows a pre-existing extension directory to be overwritten.
+
 =item B<-P>
 
 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.
+
 =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
@@ -95,11 +113,35 @@ Print the usage, help and version for this h2xs and exit.
 
 Specifies a name to be used for the extension, e.g., S<-n RPC::DCE>
 
+=item B<-p> I<prefix>
+
+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.
+
+=item B<-s> I<sub1,sub2>
+
+Create a perl subroutine for the specified macros rather than autoload with the constant() subroutine.
+These macros are assumed to have a return type of B<char *>, e.g., S<-s sec_rgy_wildcard_name,sec_rgy_wildcard_sid>.
+
 =item B<-v> I<version>
 
 Specify a version number for this extension.  This version number is added
 to the templates.  The default is 0.01.
 
+=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 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.
+
 =back
 
 =head1 EXAMPLES
@@ -130,6 +172,26 @@ to the templates.  The default is 0.01.
        # additional directory /opt/net/lib
        h2xs rpcsvc/rusers -L/opt/net/lib -lrpc
 
+        # Extension is DCE::rgynbase
+        # prefix "sec_rgy_" is dropped from perl function names
+        h2xs -n DCE::rgynbase -p sec_rgy_ dce/rgynbase
+
+        # Extension is DCE::rgynbase
+        # prefix "sec_rgy_" is dropped from perl function names
+        # subroutines are created for sec_rgy_wildcard_name and sec_rgy_wildcard_sid
+        h2xs -n DCE::rgynbase -p sec_rgy_ \
+        -s sec_rgy_wildcard_name,sec_rgy_wildcard_sid dce/rgynbase
+
+       # Make XS without defines in perl.h, but with function declarations
+       # visible from perl.h. Name of the extension is perl1.
+       # When scanning perl.h, define -DEXT=extern -DdEXT= -DINIT(x)=
+       # Extra backslashes below because the string is passed to shell.
+       # Note that a directory with perl header files would 
+       #  be added automatically to include path.
+       h2xs -xAn perl1 -F "-DEXT=extern -DdEXT= -DINIT\(x\)=" perl.h
+
+       # Same with function declaration in proto.h as visible from perl.h.
+       h2xs -xAn perl2 perl.h,proto.h
 
 =head1 ENVIRONMENT
 
@@ -145,26 +207,33 @@ L<perl>, L<perlxstut>, L<ExtUtils::MakeMaker>, and L<AutoLoader>.
 
 =head1 DIAGNOSTICS
 
-The usual warnings if it can't read or write the files involved.
+The usual warnings if it cannot read or write the files involved.
 
 =cut
 
-my( $H2XS_VERSION ) = '$Revision: 1.12 $' =~ /\$Revision:\s+([^\s]+)/;
+my( $H2XS_VERSION ) = ' $Revision: 1.18 $ ' =~ /\$Revision:\s+([^\s]+)/;
 my $TEMPLATE_VERSION = '0.01';
 
 use Getopt::Std;
 
 sub usage{
        warn "@_\n" if @_;
-    die "h2xs [-APcfh] [-v version] [-n module_name] [headerfile [extra_libraries]]
+    die "h2xs [-AOPXcdfh] [-v version] [-n module_name] [-p prefix] [-s subs] [headerfile [extra_libraries]]
 version: $H2XS_VERSION
-    -f   Force creation of the extension even if the C header does not exist.
-    -n   Specify a name to use for the extension (recommended).
-    -c   Omit the constant() function and specialised AUTOLOAD from the XS file.
     -A   Omit all autoloading facilities (implies -c).
+    -F   Additional flags for C preprocessor (used with -x).
+    -O   Allow overwriting of a pre-existing extension directory.
     -P   Omit the stub POD section.
-    -v   Specify a version number for this extension.
+    -X   Omit the XS portion.
+    -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).
+    -p   Specify a prefix which should be removed from the Perl function names.
+    -s   Create subroutines for specified macros.
+    -v   Specify a version number for this extension.
+    -x   Autogenerate XSUBs using C::Scan.
 extra_libraries
          are any libraries that might be needed for loading the
          extension, e.g. -lm would try to link in the math library.
@@ -172,7 +241,7 @@ extra_libraries
 }
 
 
-getopts("APcfhv:n:") || usage;
+getopts("AF:OPXcdfhn:p:s:v:x") || usage;
 
 usage if $opt_h;
 
@@ -180,35 +249,74 @@ if( $opt_v ){
        $TEMPLATE_VERSION = $opt_v;
 }
 $opt_c = 1 if $opt_A;
+%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";
     }
     $path_h .= ".h" unless $path_h =~ /\.h$/;
-    $path_h = "/usr/include/$path_h" unless $path_h =~ m#^[./]#;
-    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.
-    open(CH, "<$path_h") || die "Can't open $path_h: $!\n";
-    while (<CH>) {
-       if (/^#[ \t]*define\s+(\w+)\b\s*[^("]/) {
+    $fullpath = $path_h;
+    $path_h =~ s/,.*$// if $opt_x;
+    if ($^O eq 'VMS') {  # Consider overrides of default location
+       if ($path_h !~ m![:>\[]!) {
+           my($hadsys) = ($path_h =~ s!^sys/!!i);
+           if ($ENV{'DECC$System_Include'})     { $path_h = "DECC\$System_Include:$path_h";    }
+           elsif ($ENV{'DECC$Library_Include'}) { $path_h = "DECC\$Library_Include:$path_h";   }
+           elsif ($ENV{'GNU_CC_Include'})       { $path_h = 'GNU_CC_Include:' .
+                                                   ($hadsys ? '[vms]' : '[000000]') . $path_h; }
+           elsif ($ENV{'VAXC$Include'})         { $path_h = "VAXC\$_Include:$path_h";          }
+           else                                 { $path_h = "Sys\$Library:$path_h";            }
+       }
+    }
+    elsif ($^O eq 'os2') {
+       $path_h = "/usr/include/$path_h" 
+         if $path_h !~ m#^([a-z]:)?[./]#i and -r "/usr/include/$path_h"; 
+    }
+    else { 
+      $path_h = "/usr/include/$path_h" 
+       if $path_h !~ m#^[./]# and -r "/usr/include/$path_h"; 
+    }
+
+    if (!$opt_c) {
+      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 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 $opt_d;
            $_ = $1;
            next if /^_.*_h_*$/i; # special case, but for what?
+           if (defined $opt_p) {
+             if (!/^$opt_p(\d)/) {
+               ++$prefix{$_} if s/^$opt_p//;
+             }
+             else {
+               warn "can't remove $opt_p prefix from '$_'!\n";
+             }
+           }
            $const_names{$_}++;
-       }
+         }
+      }
+      close(CH);
+    }
     }
-    close(CH);
     @const_names = sort keys %const_names;
 }
 
@@ -237,13 +345,54 @@ else {
 }
 
 
-die "Won't overwrite existing $ext$modpname\n" if -e $modpname;
-# quick hack, should really loop over @modparts
-mkdir($modparts[0], 0777) if $nested;
+if ($opt_O) {
+       warn "Overwriting existing $ext$modpname!!!\n" if -e $modpname;
+} else {
+       die "Won't overwrite existing $ext$modpname\n" if -e $modpname;
+}
+if( $nested ){
+       $modpath = "";
+       foreach (@modparts){
+               mkdir("$modpath$_", 0777);
+               $modpath .= "$_/";
+       }
+}
 mkdir($modpname, 0777);
 chdir($modpname) || die "Can't chdir $ext$modpname: $!\n";
 
-open(XS, ">$modfname.xs") || die "Can't create $ext$modpname/$modfname.xs: $!\n";
+my %types_seen;
+my %std_types;
+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";
+  if ($opt_x) {
+    require C::Scan;           # Run-time directive
+    require Config;            # Run-time directive
+    warn "Scanning typemaps...\n";
+    get_typemap();
+    my $c;
+    my $filter;
+        my @fdecls;
+        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"]);
+    
+    $fdecls_parsed = $c->get('parsed_fdecls');
+            push(@fdecls, @{$c->get('fdecls')});
+        }
+        $fdecls = [ @fdecls ];
+  }
+}
+
 open(PM, ">$modfname.pm") || die "Can't create $ext$modpname/$modfname.pm: $!\n";
 
 $" = "\n\t";
@@ -252,31 +401,72 @@ warn "Writing $ext$modpname/$modfname.pm\n";
 print PM <<"END";
 package $module;
 
+use strict;
+END
+
+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 @EXPORT_OK);
+END
+}
+else{
+       # we'll have an AUTOLOAD(), and it will have $AUTOLOAD and
+       # will want Carp.
+       print PM <<'END';
+use Carp;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
+END
+}
+
+print PM <<'END';
+
 require Exporter;
+END
+
+print PM <<"END" if ! $opt_X;  # use DynaLoader, unless XS was disabled
 require DynaLoader;
 END
 
-if( ! $opt_A ){
+# require autoloader if XS is disabled.
+# if XS is enabled, require autoloader unless autoloading is disabled.
+if( ($opt_X && (! $opt_A)) || (!$opt_X) ) {
        print PM <<"END";
 require AutoLoader;
 END
 }
 
-if( $opt_c && ! $opt_A ){
+if( $opt_X || ($opt_c && ! $opt_A) ){
        # we won't have our own AUTOLOAD(), so we'll inherit it.
-       print PM <<"END";
+       if( ! $opt_X ) { # use DynaLoader, unless XS was disabled
+               print PM <<"END";
 
 \@ISA = qw(Exporter AutoLoader DynaLoader);
 END
+       }
+       else{
+               print PM <<"END";
+
+\@ISA = qw(Exporter AutoLoader);
+END
+       }
 }
 else{
        # 1) we have our own AUTOLOAD(), so don't need to inherit it.
        # or
        # 2) we don't want autoloading mentioned.
-       print PM <<"END";
+       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
+       }
 }
 
 print PM<<"END";
@@ -290,37 +480,49 @@ print PM<<"END";
 
 END
 
-print PM <<"END" unless $opt_c;
+print PM <<"END" unless $opt_c or $opt_X;
 sub AUTOLOAD {
     # This AUTOLOAD is used to 'autoload' constants from the constant()
     # XS function.  If a constant is not found then control is passed
     # to the AUTOLOAD in AutoLoader.
 
-    local(\$constname);
+    my \$constname;
     (\$constname = \$AUTOLOAD) =~ s/.*:://;
-    \$val = constant(\$constname, \@_ ? \$_[0] : 0);
+    croak "&$module::constant not defined" if \$constname eq 'constant';
+    my \$val = constant(\$constname, \@_ ? \$_[0] : 0);
     if (\$! != 0) {
        if (\$! =~ /Invalid/) {
            \$AutoLoader::AUTOLOAD = \$AUTOLOAD;
            goto &AutoLoader::AUTOLOAD;
        }
        else {
-           (\$pack,\$file,\$line) = caller;
-           die "Your vendor has not defined $module macro \$constname, used at \$file line \$line.\n";
+               croak "Your vendor has not defined $module macro \$constname";
        }
     }
-    eval "sub \$AUTOLOAD { \$val }";
+    *\$AUTOLOAD = sub () { \$val };
     goto &\$AUTOLOAD;
 }
 
 END
 
-print PM <<"END";
+if( ! $opt_X ){ # print bootstrap, unless XS is disabled
+       print PM <<"END";
 bootstrap $module \$VERSION;
+END
+}
+
+if( $opt_P ){ # if POD is disabled
+       $after = '__END__';
+}
+else {
+       $after = '=cut';
+}
+
+print PM <<"END";
 
 # Preloaded methods go here.
 
-# Autoload methods go after __END__, and are processed by the autosplit program.
+# Autoload methods go after $after, and are processed by the autosplit program.
 
 1;
 __END__
@@ -329,6 +531,25 @@ END
 $author = "A. U. Thor";
 $email = 'a.u.thor@a.galaxy.far.far.away';
 
+my $const_doc = '';
+my $fdecl_doc = '';
+if (@const_names and not $opt_P) {
+  $const_doc = <<EOD;
+\n=head1 Exported constants
+
+  @{[join "\n  ", @const_names]}
+
+EOD
+}
+if (defined $fdecls and @$fdecls and not $opt_P) {
+  $fdecl_doc = <<EOD;
+\n=head1 Exported functions
+
+  @{[join "\n  ", @$fdecls]}
+
+EOD
+}
+
 $pod = <<"END" unless $opt_P;
 ## Below is the stub of documentation for your module. You better edit it!
 #
@@ -348,7 +569,7 @@ $pod = <<"END" unless $opt_P;
 #unedited.
 #
 #Blah blah blah.
-#
+#$const_doc$fdecl_doc
 #=head1 AUTHOR
 #
 #$author, $email
@@ -366,6 +587,7 @@ print PM $pod unless $opt_P;
 close PM;
 
 
+if( ! $opt_X ){ # print XS, unless it is disabled
 warn "Writing $ext$modpname/$modfname.xs\n";
 
 print XS <<"END";
@@ -380,13 +602,14 @@ extern "C" {
 #endif
 
 END
-if( $path_h ){
+if( @path_h ){
+    foreach my $path_h (@path_h) {
        my($h) = $path_h;
        $h =~ s#^/usr/include/##;
-print XS <<"END";
-#include <$h>
-
-END
+       if ($^O eq 'VMS') { $h =~ s#.*vms\]#sys/# or $h =~ s#.*[:>\]]##; }
+        print XS qq{#include <$h>\n};
+    }
+    print XS "\n";
 }
 
 if( ! $opt_c ){
@@ -424,10 +647,12 @@ foreach $letter (@AZ, @az, @under) {
     my($name);
     while (substr($const_names[0],0,1) eq $letter) {
        $name = shift(@const_names);
+       $macro = $prefix{$name} ? "$opt_p$name" : $name;
+       next if $const_xsub{$macro};
        print XS <<"END";
        if (strEQ(name, "$name"))
-#ifdef $name
-           return $name;
+#ifdef $macro
+           return $macro;
 #else
            goto not_there;
 #endif
@@ -450,13 +675,32 @@ not_there:
 END
 }
 
+$prefix = "PREFIX = $opt_p" if defined $opt_p;
 # Now switch from C to XS by issuing the first MODULE declaration:
 print XS <<"END";
 
-MODULE = $module               PACKAGE = $module
+MODULE = $module               PACKAGE = $module               $prefix
 
 END
 
+foreach (sort keys %const_xsub) {
+    print XS <<"END";
+char *
+$_()
+
+    CODE:
+#ifdef $_
+    RETVAL = $_;
+#else
+    croak("Your vendor has not defined the $module macro $_");
+#endif
+
+    OUTPUT:
+    RETVAL
+
+END
+}
+
 # If a constant() function was written then output a corresponding
 # XS declaration:
 print XS <<"END" unless $opt_c;
@@ -468,8 +712,114 @@ constant(name,arg)
 
 END
 
+my %seen_decl;
+
+
+sub print_decl {
+  my $fh = shift;
+  my $decl = shift;
+  my ($type, $name, $args) = @$decl;
+  return if $seen_decl{$name}++; # Need to do the same for docs as well?
+
+  my @argnames = map {$_->[1]} @$args;
+  my @argtypes = map { normalize_type( $_->[0] ) } @$args;
+  my @argarrays = map { $_->[4] || '' } @$args;
+  my $numargs = @$args;
+  if ($numargs and $argtypes[-1] eq '...') {
+    $numargs--;
+    $argnames[-1] = '...';
+  }
+  local $" = ', ';
+  $type = normalize_type($type);
+  
+  print $fh <<"EOP";
+
+$type
+$name(@argnames)
+EOP
+
+  for $arg (0 .. $numargs - 1) {
+    print $fh <<"EOP";
+       $argtypes[$arg] $argnames[$arg]$argarrays[$arg]
+EOP
+  }
+}
+
+# Should be called before any actual call to normalize_type().
+sub get_typemap {
+  # We do not want to read ./typemap by obvios reasons.
+  my @tm =  qw(../../../typemap ../../typemap ../typemap);
+  my $stdtypemap =  "$Config::Config{privlib}/ExtUtils/typemap";
+  unshift @tm, $stdtypemap;
+  my $proto_re = "[" . quotemeta('\$%&*@;') . "]" ;
+  my $image;
+  
+  foreach $typemap (@tm) {
+    next unless -e $typemap ;
+    # skip directories, binary files etc.
+    warn " Scanning $typemap\n";
+    warn("Warning: ignoring non-text typemap file '$typemap'\n"), next 
+      unless -T $typemap ;
+    open(TYPEMAP, $typemap) 
+      or warn ("Warning: could not open typemap file '$typemap': $!\n"), next;
+    my $mode = 'Typemap';
+    while (<TYPEMAP>) {
+      next if /^\s*\#/;
+      if (/^INPUT\s*$/)   { $mode = 'Input'; next; }
+      elsif (/^OUTPUT\s*$/)  { $mode = 'Output'; next; }
+      elsif (/^TYPEMAP\s*$/) { $mode = 'Typemap'; next; }
+      elsif ($mode eq 'Typemap') {
+       next if /^\s*($|\#)/ ;
+       if ( ($type, $image) = 
+            /^\s*(.*?\S)\s+(\S+)\s*($proto_re*)\s*$/o
+            # This may reference undefined functions:
+            and not ($image eq 'T_PACKED' and $typemap eq $stdtypemap)) {
+         normalize_type($type);
+       }
+      }
+    }
+    close(TYPEMAP) or die "Cannot close $typemap: $!";
+  }
+  %std_types = %types_seen;
+  %types_seen = ();
+}
+
+
+sub normalize_type {
+  my $ignore_mods = '(?:\b(?:__const__|static|inline|__inline__)\b\s*)*';
+  my $type = shift;
+  $type =~ s/$ignore_mods//go;
+  $type =~ s/([\]\[()])/ \1 /g;
+  $type =~ s/\s+/ /g;
+  $type =~ s/\s+$//;
+  $type =~ s/^\s+//;
+  $type =~ s/\b\*/ */g;
+  $type =~ s/\*\b/* /g;
+  $type =~ s/\*\s+(?=\*)/*/g;
+  $types_seen{$type}++ 
+    unless $type eq '...' or $type eq 'void' or $std_types{$type};
+  $type;
+}
+
+if ($opt_x) {
+    for $decl (@$fdecls_parsed) { print_decl(\*XS, $decl) }
+}
+
 close XS;
 
+if (%types_seen) {
+  my $type;
+  warn "Writing $ext$modpname/typemap\n";
+  open TM, ">typemap" or die "Cannot open typemap file for write: $!";
+
+  for $type (keys %types_seen) {
+    print TM $type, "\t" x (6 - int((length $type)/8)), "T_PTROBJ\n"
+  }
+
+  close TM or die "Cannot close typemap file for write: $!";
+}
+
+} # if( ! $opt_X )
 
 warn "Writing $ext$modpname/Makefile.PL\n";
 open(PL, ">Makefile.PL") || die "Can't create $ext$modpname/Makefile.PL: $!\n";
@@ -481,10 +831,12 @@ use ExtUtils::MakeMaker;
 END
 print PL "WriteMakefile(\n";
 print PL "    'NAME'   => '$module',\n";
-print PL "    'VERSION'        => '$TEMPLATE_VERSION',\n";
-print PL "    'LIBS'   => ['$extralibs'],   # e.g., '-lm' \n";
-print PL "    'DEFINE' => '',     # e.g., '-DHAVE_SOMETHING' \n";
-print PL "    'INC'    => '',     # e.g., '-I/usr/include/other' \n";
+print PL "    'VERSION_FROM' => '$modfname.pm', # finds \$VERSION\n"; 
+if( ! $opt_X ){ # print C stuff, unless XS is disabled
+  print PL "    'LIBS' => ['$extralibs'],   # e.g., '-lm' \n";
+  print PL "    'DEFINE'       => '',     # e.g., '-DHAVE_SOMETHING' \n";
+  print PL "    'INC'  => '',     # e.g., '-I/usr/include/other' \n";
+}
 print PL ");\n";
 close(PL) || die "Can't close $ext$modpname/Makefile.PL: $!\n";
 
@@ -499,7 +851,7 @@ print EX <<'_END_';
 # Change 1..1 below to 1..last_test_to_print .
 # (It may become useful if the test is moved to ./t subdirectory.)
 
-BEGIN {print "1..1\n";}
+BEGIN { $| = 1; print "1..1\n"; }
 END {print "not ok 1\n" unless $loaded;}
 _END_
 print EX <<_END_;
@@ -518,9 +870,36 @@ print "ok 1\n";
 _END_
 close(EX) || die "Can't close $ext$modpname/test.pl: $!\n";
 
-system '/bin/ls > MANIFEST' or system 'ls > MANIFEST';
+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: $!";
+@files = <*>;
+if (!@files) {
+  eval {opendir(D,'.');};
+  unless ($@) { @files = readdir(D); closedir(D); }
+}
+if (!@files) { @files = map {chomp && $_} `ls`; }
+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;