diff options
Diffstat (limited to 'debian/perl-framework/Apache-Test/lib/Apache/TestConfigC.pm')
-rw-r--r-- | debian/perl-framework/Apache-Test/lib/Apache/TestConfigC.pm | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/debian/perl-framework/Apache-Test/lib/Apache/TestConfigC.pm b/debian/perl-framework/Apache-Test/lib/Apache/TestConfigC.pm new file mode 100644 index 0000000..c9d8fd1 --- /dev/null +++ b/debian/perl-framework/Apache-Test/lib/Apache/TestConfigC.pm @@ -0,0 +1,492 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +package Apache::TestConfig; #not TestConfigC on purpose + +use strict; +use warnings FATAL => 'all'; + +use Config; +use Apache::TestConfig (); +use Apache::TestConfigPerl (); +use Apache::TestTrace; +use File::Find qw(finddepth); + +sub cmodule_find { + my($self, $mod) = @_; + + return unless $mod =~ /^mod_(\w+)\.c$/; + my $sym = $1; + + my $dir = $File::Find::dir; + my $file = catfile $dir, $mod; + + unless ($self->{APXS}) { + $self->{cmodules_disabled}->{$mod} = "no apxs configured"; + return; + } + + my $fh = Symbol::gensym(); + open $fh, $file or die "open $file: $!"; + my $v = <$fh>; + if ($v =~ /^\#define\s+HTTPD_TEST_REQUIRE_APACHE\s+(\d+)\s*$/) { + #define HTTPD_TEST_REQUIRE_APACHE 1 + unless ($self->{server}->{rev} == $1) { + my $reason = "requires Apache version $1"; + $self->{cmodules_disabled}->{$mod} = $reason; + notice "$mod $reason, skipping."; + return; + } + } + elsif ($v =~ /^\#define\s+HTTPD_TEST_REQUIRE_APACHE\s+(\d\.\d+(\.\d+)?)/) { + #define HTTPD_TEST_REQUIRE_APACHE 2.1 + my $wanted = $1; + (my $current) = $self->{server}->{version} =~ m:^Apache/(\d\.\d+\.\d+):; + + if (Apache::Test::normalize_vstring($current) < + Apache::Test::normalize_vstring($wanted)) { + my $reason = "requires Apache version $wanted"; + $self->{cmodules_disabled}->{$mod} = $reason; + notice "$mod $reason, skipping."; + return; + } + } + close $fh; + + push @{ $self->{cmodules} }, { + name => "mod_$sym", + sym => "${sym}_module", + dir => $dir, + subdir => basename $dir, + }; +} + +sub cmodules_configure { + my($self, $dir) = @_; + + $self->{cmodules_disabled} = {}; #for have_module to check + + $dir ||= catfile $self->{vars}->{top_dir}, 'c-modules'; + + unless (-d $dir) { + return; + } + + $self->{cmodules_dir} = $dir; + + finddepth(sub { cmodule_find($self, $_) }, $dir); + + unless ($self->{APXS}) { + warning "cannot build c-modules without apxs"; + return; + } + + $self->cmodules_generate_include; + $self->cmodules_write_makefiles; + $self->cmodules_compile; + $self->cmodules_httpd_conf; +} + +sub cmodules_makefile_vars { + return <<EOF; +MAKE = $Config{make} +EOF +} + +my %lib_dir = Apache::TestConfig::WIN32 + ? (1 => "", 2 => "") + : (1 => "", 2 => ".libs/"); + +sub cmodules_build_so { + my($self, $name) = @_; + $name = "mod_$name" unless $name =~ /^mod_/; + my $libdir = $self->server->version_of(\%lib_dir); + my $lib = "$libdir$name.so"; +} + +sub cmodules_write_makefiles { + my $self = shift; + + my $modules = $self->{cmodules}; + + for (@$modules) { + $self->cmodules_write_makefile($_); + } + + my $file = catfile $self->{cmodules_dir}, 'Makefile'; + my $fh = $self->genfile($file); + + print $fh $self->cmodules_makefile_vars; + + my @dirs = map { $_->{subdir} } @$modules; + + my @targets = qw(clean); + my @libs; + + for my $dir (@dirs) { + for my $targ (@targets) { + print $fh "$dir-$targ:\n\tcd $dir && \$(MAKE) $targ\n\n"; + } + + my $lib = $self->cmodules_build_so($dir); + my $cfile = "$dir/mod_$dir.c"; + push @libs, "$dir/$lib"; + print $fh "$libs[-1]: $cfile\n\tcd $dir && \$(MAKE) $lib\n\n"; + } + + for my $targ (@targets) { + print $fh "$targ: ", (map { "$_-$targ " } @dirs), "\n\n"; + } + + print $fh "all: @libs\n\n"; + + close $fh or die "close $file: $!"; +} + +sub cmodules_write_makefile { + my ($self, $mod) = @_; + my $write = \&{"cmodules_write_makefile_$^O"}; + $write = \&cmodules_write_makefile_default unless defined &$write; + $write->($self, $mod); +} + +sub cmodules_write_makefile_default { + my($self, $mod) = @_; + + my $dversion = $self->server->dversion; + my $name = $mod->{name}; + my $makefile = catfile $mod->{dir}, 'Makefile'; + + my $extra = $ENV{EXTRA_CFLAGS} || ''; + + debug "writing $makefile"; + + my $lib = $self->cmodules_build_so($name); + + my $fh = $self->genfile($makefile); + + print $fh <<EOF; +APXS=$self->{APXS} +all: $lib + +$lib: $name.c + \$(APXS) $dversion $extra -I$self->{cmodules_dir} -c $name.c + +clean: + -rm -rf $name.o $name.lo $name.slo $name.la $name.i $name.s $name.gcno .libs +EOF + + close $fh or die "close $makefile: $!"; +} + +sub cmodules_write_makefile_aix { + my($self, $mod) = @_; + + my $dversion = $self->server->dversion; + my $name = $mod->{name}; + my $makefile = catfile $mod->{dir}, 'Makefile'; + my $apxsflags = ''; + + # + # Only do this for Apache 1.* + # + if ($self->server->{rev} == 1) { + $apxsflags = "-Wl,-bE:$name.exp"; + my $expfile = catfile $mod->{dir}, "$name.exp"; + if (! -f $expfile) { + my $fh = Symbol::gensym(); + $name =~ /^mod_(\w+)(?:\.c)?$/; + my $sym = $1 . '_module'; + open $fh, ">$expfile" or die "open $expfile: $!"; + print $fh "$sym\n"; + close $fh; + } + } + + my $extra = $ENV{EXTRA_CFLAGS} || ''; + + debug "writing $makefile"; + + my $lib = $self->cmodules_build_so($name); + + my $fh = Symbol::gensym(); + open $fh, ">$makefile" or die "open $makefile: $!"; + + print $fh <<EOF; +APXS=$self->{APXS} +APXSFLAGS=$apxsflags +all: $lib + +$lib: $name.c + \$(APXS) $dversion $extra -I$self->{cmodules_dir} \$(APXSFLAGS) -c $name.c + +clean: + -rm -rf $name.o $name.lo $name.slo $name.la .libs +EOF + + close $fh or die "close $makefile: $!"; +} + +sub cmodules_write_makefile_MSWin32 { + my($self, $mod) = @_; + + my $dversion = $self->server->dversion; + my $name = $mod->{name}; + my $makefile = "$mod->{dir}/Makefile"; + debug "writing $makefile"; + my $extras = ''; + + my $lib = $self->cmodules_build_so($name); + $extras = ' -llibhttpd -p ' if ($self->server->{rev} != 1); + my $goners = join ' ', (map {$name . '.' . $_} qw(exp lib so lo)); + + my $fh = Symbol::gensym(); + open $fh, ">$makefile" or die "open $makefile: $!"; + + my $extra = $ENV{EXTRA_CFLAGS} || ''; + + debug "writing $makefile"; + + print $fh <<EOF; +APXS=$self->{APXS} +all: $lib + +$lib: $name.c + \$(APXS) $dversion $extra -I$self->{cmodules_dir} $extras -c $name.c + +clean: + -erase $goners +EOF + + close $fh or die "close $makefile: $!"; +} + +sub cmodules_make { + my $self = shift; + my $targ = shift || 'all'; + + my $cmd = "cd $self->{cmodules_dir} && $Config{make} $targ"; + debug $cmd; + system $cmd; + if ($?) { + die "Failed to build c-modules"; + } +} + +sub cmodules_compile { + shift->cmodules_make('all'); +} + +sub cmodules_httpd_conf { + my $self = shift; + + my @args; + + for my $mod (@{ $self->{cmodules} }) { + my $dir = $mod->{dir}; + my $lib = $self->cmodules_build_so($mod->{name}); + my $so = "$dir/$lib"; + + next unless -e $so; + + $self->preamble(LoadModule => "$mod->{sym} $so"); + + my $cname = "$mod->{name}.c"; + my $cfile = "$dir/$cname"; + $self->{modules}->{$cname} = 1; + + $self->add_module_config($cfile, \@args); + } + + $self->postamble(\@args) if @args; +} + +sub cmodules_clean { + my $self = shift; + + my $dir = $self->{cmodules_dir}; + return unless $dir and -e "$dir/Makefile"; + + unless ($self->{clean_level} > 1) { + #skip t/TEST -conf + warning "skipping rebuild of c-modules; run t/TEST -clean to force"; + return; + } + + $self->cmodules_make('clean'); + + for my $mod (@{ $self->{cmodules} }) { + my $makefile = "$mod->{dir}/Makefile"; + debug "unlink $makefile"; + unlink $makefile; + } + + unlink "$dir/Makefile"; +} + +#try making it easier for test modules to compile with both 1.x and 2.x +sub cmodule_define_name { + my $name = shift; + $name eq 'NULL' ? $name : "APACHE_HTTPD_TEST_\U$name"; +} + +sub cmodule_define { + my $hook = cmodule_define_name(@_); + "#ifndef $hook\n#define $hook NULL\n#endif\n"; +} + +my @cmodule_config_names = qw(per_dir_create per_dir_merge + per_srv_create per_srv_merge + commands); + +my @cmodule_config_defines = map { + cmodule_define($_); +} @cmodule_config_names; + +my $cmodule_config_extra = + "#ifndef APACHE_HTTPD_TEST_EXTRA_HOOKS\n". + "#define APACHE_HTTPD_TEST_EXTRA_HOOKS(p) do { } while (0)\n". + "#endif\n"; + +my $cmodule_config_hooks = join ",\n ", map { + cmodule_define_name($_); +} @cmodule_config_names; + +my @cmodule_phases = qw(post_read_request translate_name header_parser + access_checker check_user_id auth_checker + type_checker fixups handler log_transaction + child_init); + +my $cmodule_hooks_1 = join ",\n ", map { + cmodule_define_name($_); +} qw(translate_name check_user_id auth_checker access_checker + type_checker fixups log_transaction header_parser + child_init NULL post_read_request); + +my $cmodule_template_1 = <<"EOF", +static const handler_rec name ## _handlers[] = +{ + {#name, APACHE_HTTPD_TEST_HANDLER}, /* ok if handler is NULL */ + {NULL} +}; + +module MODULE_VAR_EXPORT name ## _module = +{ + STANDARD_MODULE_STUFF, + NULL, /* initializer */ + $cmodule_config_hooks, + name ## _handlers, /* handlers */ + $cmodule_hooks_1 +} +EOF + +my @cmodule_hooks = map { + my $hook = cmodule_define_name($_); + <<EOF; + if ($hook != NULL) + ap_hook_$_($hook, + NULL, NULL, + APACHE_HTTPD_TEST_HOOK_ORDER); +EOF +} @cmodule_phases; + +my @cmodule_hook_defines = map { + cmodule_define($_); +} @cmodule_phases; + +my $cmodule_template_2 = <<"EOF"; +static void name ## _register_hooks(apr_pool_t *p) +{ +@cmodule_hooks + APACHE_HTTPD_TEST_EXTRA_HOOKS(p); +} + +module AP_MODULE_DECLARE_DATA name ## _module = { + STANDARD20_MODULE_STUFF, + $cmodule_config_hooks, + name ## _register_hooks, /* register hooks */ +} +EOF + +my %cmodule_templates = (1 => $cmodule_template_1, 2 => $cmodule_template_2); + +sub cmodules_module_template { + my $self = shift; + my $template = $self->server->version_of(\%cmodule_templates); + chomp $template; + + $template =~ s,$, \\,mg; + $template =~ s, \\$,,s; + + local $" = ', '; + + return <<EOF; +#define APACHE_HTTPD_TEST_MODULE(name) \\ + $template +EOF +} + +sub cmodules_generate_include { + my $self = shift; + + my $file = "$self->{cmodules_dir}/apache_httpd_test.h"; + my $fh = $self->genfile($file); + + while (read Apache::TestConfigC::DATA, my $buf, 1024) { + print $fh $buf; + } + + print $fh @cmodule_hook_defines, @cmodule_config_defines; + + print $fh $cmodule_config_extra; + + print $fh $self->cmodules_module_template; + + close $fh; +} + +package Apache::TestConfigC; #Apache/TestConfig.pm also has __DATA__ +1; +__DATA__ +#ifndef APACHE_HTTPD_TEST_H +#define APACHE_HTTPD_TEST_H + +/* headers present in both 1.x and 2.x */ +#include "httpd.h" +#include "http_config.h" +#include "http_protocol.h" +#include "http_request.h" +#include "http_log.h" +#include "http_main.h" +#include "http_core.h" +#include "ap_config.h" + +#ifdef APACHE1 +#define AP_METHOD_BIT 1 +typedef size_t apr_size_t; +typedef array_header apr_array_header_t; +#define APR_OFF_T_FMT "ld" +#define APR_SIZE_T_FMT "lu" +#endif /* APACHE1 */ + +#ifdef APACHE2 +#ifndef APACHE_HTTPD_TEST_HOOK_ORDER +#define APACHE_HTTPD_TEST_HOOK_ORDER APR_HOOK_MIDDLE +#endif +#include "ap_compat.h" +#endif /* APACHE2 */ + +#endif /* APACHE_HTTPD_TEST_H */ + |