blob: c780fe0bcb7f2b2ac2b6385ad22be24e339a16ff [file] [log] [blame]
#!/usr/bin/perl
#
# Usage: cd glue/perl; ../../build/xsbuilder.pl
#
#
# This script is responsible for building the
#
# glue/perl/xsbuilder/tables
#
# directory by parsing the header files in src/.
use strict;
use warnings FATAL => 'all';
use File::Basename;
use constant WIN32 => ($^O =~ /Win32/i);
use Cwd;
my $cwd = WIN32 ?
Win32::GetLongPathName(cwd) : cwd;
$cwd =~ m{^(.+)/glue/perl$} or die "Can't find base directory";
my $base_dir = $1;
my $src_dir = "$base_dir/src";
my $xs_dir = "$base_dir/glue/perl/xsbuilder";
sub slurp($$)
{
open my $file, $_[1] or die "Can't open $_[1]: $!";
read $file, $_[0], -s $file;
}
my %c_macro_cache = (
XS => sub {s/XS\s*\(([^)]+)\)/void $1()/g},
);
sub c_macro
{
return $c_macro_cache{"@_"} if exists $c_macro_cache{"@_"};
my ($name, $header) = @_;
my $src;
if (defined $header) {
slurp local $_ => "$src_dir/$header";
/^#define $name\s*\(([^)]+)\)\s+(.+?[^\\])$/ms
or die "Can't find definition for '$name': $_";
my $def = $2;
my @args = split /\s*,\s*/, $1;
for (1..@args) {
$def =~ s/\b$args[$_-1]\b/ \$$_ /g;
}
my $args = join ',' => ('([^,)]+)') x @args;
$src = "sub { /^#define $name.+?[^\\\\]\$/gms +
s{$name\\s*\\($args\\)}{$def}g}";
}
else {
$src = "sub { /^#define $name.+?[^\\\\]\$/gms +
s{$name\\s*\\(([^)]+)\\)}{\$1}g}";
}
return $c_macro_cache{"@_"} = eval $src;
}
package My::ParseSource;
use constant WIN32 => ($^O =~ /Win32/i);
my @dirs = ("$base_dir/src", "$base_dir/glue/perl/xsbuilder");
use base qw/ExtUtils::XSBuilder::ParseSource/;
__PACKAGE__->run;
system("touch $base_dir/glue/perl/xsbuilder") == 0
or die "touch $base_dir/glue/perl/xsbuilder failed: $!"
unless WIN32;
sub package {'Apache::libapreq2'}
sub unwanted_includes {[qw/apreq_tables.h apreq_config.h/]}
# ParseSource.pm v 0.23 bug: line 214 should read
# my @dirs = @{$self->include_dirs};
# for now, we override it here just to work around the bug
sub find_includes {
my $self = shift;
return $self->{includes} if $self->{includes};
require File::Find;
my(@dirs) = @{$self->include_dirs};
unless (-d $dirs[0]) {
die "could not find include directory";
}
# print "Will search @dirs for include files...\n" if ($verbose) ;
my @includes;
my $unwanted = join '|', @{$self -> unwanted_includes} ;
for my $dir (@dirs) {
File::Find::finddepth({
wanted => sub {
return unless /\.h$/;
return if ($unwanted && (/^($unwanted)/o));
my $dir = $File::Find::dir;
push @includes, "$dir/$_";
},
follow => not WIN32,
}, $dir);
}
return $self->{includes} = $self -> sort_includes (\@includes) ;
}
sub include_dirs {\@dirs}
sub preprocess
{
# need to macro-expand APREQ_DECLARE et.al. so P::RD can DTRT with
# ExtUtils::XSBuilder::C::grammar
for ($_[1]) {
::c_macro("APREQ_DECLARE", "apreq.h")->();
::c_macro("APREQ_DECLARE_HOOK", "apreq_params.h")->();
::c_macro("APREQ_DECLARE_PARSER", "apreq_params.h")->();
::c_macro("APR_DECLARE")->();
::c_macro("XS")-> ();
}
}
1;