| #!/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; |