1#!/usr/bin/perl 2# 3# Usage: cd glue/perl; ../../build/xsbuilder.pl 4# 5# 6# This script is responsible for building the 7# 8# glue/perl/xsbuilder/tables 9# 10# directory by parsing the header files in src/. 11 12use strict; 13use warnings FATAL => 'all'; 14use File::Basename; 15use constant WIN32 => ($^O =~ /Win32/i); 16use Cwd; 17 18my $cwd = WIN32 ? 19 Win32::GetLongPathName(cwd) : cwd; 20 21$cwd =~ m{^(.+)/glue/perl$} or die "Can't find base directory"; 22my $base_dir = $1; 23my $inc_dir = "$base_dir/include"; 24my $mod_dir = "$base_dir/module"; 25my $xs_dir = "$base_dir/glue/perl/xsbuilder"; 26 27sub slurp($$) 28{ 29 open my $file, $_[1] or die "Can't open $_[1]: $!"; 30 read $file, $_[0], -s $file; 31} 32 33my %c_macro_cache = ( 34 XS => sub {s/XS\s*\(([^)]+)\)/void $1()/g}, 35 ); 36sub c_macro 37{ 38 return $c_macro_cache{"@_"} if exists $c_macro_cache{"@_"}; 39 40 my ($name, $header) = @_; 41 my $src; 42 if (defined $header) { 43 slurp local $_ => "$inc_dir/$header"; 44 /^#define $name\s*\(([^)]+)\)\s+(.+?[^\\])$/ms 45 or die "Can't find definition for '$name': $_"; 46 my $def = $2; 47 my @args = split /\s*,\s*/, $1; 48 for (1..@args) { 49 $def =~ s/\b$args[$_-1]\b/ \$$_ /g; 50 } 51 my $args = join ',' => ('([^,)]+)') x @args; 52 $src = "sub { /^#define $name.+?[^\\\\]\$/gms + 53 s{$name\\s*\\($args\\)}{$def}g}"; 54 } 55 else { 56 $src = "sub { /^#define $name.+?[^\\\\]\$/gms + 57 s{$name\\s*\\(([^)]+)\\)}{\$1}g}"; 58 } 59 return $c_macro_cache{"@_"} = eval $src; 60} 61 62 63 64package My::ParseSource; 65use constant WIN32 => ($^O =~ /Win32/i); 66my @dirs = ("$inc_dir", "$mod_dir/apache2/", "$base_dir/glue/perl/xsbuilder"); 67use base qw/ExtUtils::XSBuilder::ParseSource/; 68 69 70__PACKAGE__->run; 71 72system("touch $base_dir/glue/perl/xsbuilder") == 0 73 or die "touch $base_dir/glue/perl/xsbuilder failed: $!" 74 unless WIN32; 75 76 77sub package {'APR::Request'} 78sub unwanted_includes {[qw/apreq_config.h apreq_private_apache2.h/]} 79 80# ParseSource.pm v 0.23 bug: line 214 should read 81# my @dirs = @{$self->include_dirs}; 82# for now, we override it here just to work around the bug 83 84sub find_includes { 85 my $self = shift; 86 return $self->{includes} if $self->{includes}; 87 require File::Find; 88 my(@dirs) = @{$self->include_dirs}; 89 unless (-d $dirs[0]) { 90 die "could not find include directory"; 91 } 92 # print "Will search @dirs for include files...\n" if ($verbose) ; 93 my @includes; 94 my $unwanted = join '|', @{$self -> unwanted_includes} ; 95 96 for my $dir (@dirs) { 97 File::Find::finddepth({ 98 wanted => sub { 99 return unless /\.h$/; 100 return if ($unwanted && (/^($unwanted)/o)); 101 my $dir = $File::Find::dir; 102 push @includes, "$dir/$_"; 103 }, 104 follow => not WIN32, 105 }, $dir); 106 } 107 return $self->{includes} = $self -> sort_includes (\@includes) ; 108} 109 110sub include_dirs {\@dirs} 111 112sub preprocess 113{ 114 # need to macro-expand APREQ_DECLARE et.al. so P::RD can DTRT with 115 # ExtUtils::XSBuilder::C::grammar 116 117 for ($_[1]) { 118 ::c_macro("APREQ_DECLARE", "apreq.h")->(); 119 ::c_macro("APREQ_DECLARE_HOOK", "apreq_parser.h")->(); 120 ::c_macro("APREQ_DECLARE_PARSER", "apreq_parser.h")->(); 121 ::c_macro("APR_DECLARE")->(); 122 ::c_macro("XS")-> (); 123 s/APR_INLINE//g; 124 s/static//g; 125 } 126} 127 1281; 129