You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl-cvs@perl.apache.org by do...@apache.org on 2001/01/08 00:18:58 UTC
cvs commit: modperl-2.0/util cvsize.pl source_scan.pl
dougm 01/01/07 15:18:58
Added: lib/Apache ParseSource.pm
patches c-scan.pat
util cvsize.pl source_scan.pl
Log:
some C::Scan fiddlings
Revision Changes Path
1.1 modperl-2.0/lib/Apache/ParseSource.pm
Index: ParseSource.pm
===================================================================
package Apache::ParseSource;
use strict;
use Apache::Build ();
use Config ();
our $VERSION = '0.01';
BEGIN {
unless ($0 eq '-e') {
my $filter = join '::', __PACKAGE__, 'cscan_filter';
my $cpp = join ' ', $^X, '-M'.__PACKAGE__, '-e', $filter, '--';
(tied %Config::Config)->{cppstdin} = $cpp;
}
}
sub new {
my $class = shift;
#$C::Scan::Warn = 1;
bless {
config => Apache::Build->new,
}, $class;
}
sub config {
shift->{config};
}
sub parse {
my $self = shift;
$self->{scan_filename} = $self->generate_cscan_file;
$self->{c} = $self->scan;
}
sub DESTROY {
my $self = shift;
unlink $self->{scan_filename}
}
{
package Apache::ParseSource::Scan;
our @ISA = qw(C::Scan);
sub get {
local $SIG{__DIE__} = \&Carp::confess;
shift->SUPER::get(@_);
}
}
sub scan {
require C::Scan;
require Carp;
my $self = shift;
my $c = C::Scan->new(filename => $self->{scan_filename});
$c->set(includeDirs => $self->config->includes);
bless $c, 'Apache::ParseSource::Scan';
}
sub generate_cscan_file {
my $self = shift;
require File::Find;
my $dir = $self->config->apxs(-q => 'INCLUDEDIR');
unless (-d $dir) {
die "could not find include directory";
}
my @includes;
my $unwanted = join '|', qw(ap_listen);
File::Find::finddepth({
wanted => sub {
return unless /\.h$/;
return if /($unwanted)/o;
my $dir = $File::Find::dir;
push @includes, "$dir/$_";
},
follow => 1,
}, $dir);
my $filename = '.apache_includes';
open my $fh, '>', $filename or die "can't open $filename: $!";
for (@includes) {
print $fh qq(\#include "$_"\n);
}
close $fh;
return $filename;
}
sub get_functions {
my $self = shift;
my $key = 'parsed_fdecls';
return $self->{$key} if $self->{$key};
my $c = $self->{c};
my $fdecls = $c->get($key);
my %seen;
my $wanted = join '|', qw(ap_ apr_ apu_);
my @functions;
for my $entry (@$fdecls) {
my($rtype, $name, $args) = @$entry;
next unless $name =~ /^($wanted)/o;
next if $seen{$name}++;
my $func = {
name => $name,
return_type => $rtype,
args => [map {
{ type => $_->[0], name => $_->[1] }
} @$args],
};
push @functions, $func;
}
$self->{$key} = \@functions;
}
sub get_structs {
my $self = shift;
my $key = 'typedef_structs';
return $self->{$key} if $self->{$key};
my $c = $self->{c};
my $typedef_structs = $c->get($key);
my %seen;
my $prefix = join '|', qw(ap_ apr_ apu_);
my @structures;
while (my($type, $elts) = each %$typedef_structs) {
next unless $type =~ /^($prefix)/o or $type =~ /_rec$/;
next if $seen{$type}++;
my $struct = {
type => $type,
elts => [map {
{ type => $_->[0], name => $_->[2] }
} @$elts],
};
push @structures, $struct;
}
$self->{$key} = \@structures;
}
sub write_functions_pm {
my $self = shift;
my $file = shift || 'FunctionTable.pm';
my $name = shift || 'Apache::FunctionTable';
$self->write_pm($file, $name, $self->get_functions);
}
sub write_structs_pm {
my $self = shift;
my $file = shift || 'StructureTable.pm';
my $name = shift || 'Apache::StructureTable';
$self->write_pm($file, $name, $self->get_structs);
}
sub write_pm {
my($self, $file, $name, $data) = @_;
require Data::Dumper;
local $Data::Dumper::Indent = 1;
if (-d "lib/Apache") {
$file = "lib/Apache/$file";
}
open my $pm, '>', $file or die "open $file: $!";
my $dump = Data::Dumper->new([$data],
[$name])->Dump;
my $package = __PACKAGE__;
my $date = scalar localtime;
print $pm <<EOF;
package $name;
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# ! WARNING: generated by $package/$VERSION
# ! $date
# ! do NOT edit, any changes will be lost !
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$dump
1;
EOF
close $pm;
}
#rewrite some constructs that C::Scan cannot parse
sub cscan_filter {
chomp(my $include = scalar <STDIN>);
my $command = "echo \'$include\' | $Config::Config{cppstdin} @ARGV|";
open my $cmd, $command or die;
my %typedef;
my $apache_file = 0;
while (<$cmd>) {
#C::Scan cannot parse this
s/const\s+char\s*\*\s+const\s*\*/const char **/g;
if (m(^\s*\#\s* # Leading hash
(line\s*)? # 1: Optional line
([0-9]+)\s* # 2: Line number
(.*) # 3: The rest
)x) {
my $file = $3;
$file = $1 if $file =~ /"(.*)"/;
$apache_file = ($file =~ m:apache-2\.0: or $file =~ /\.c$/);
#only rewrite forward typedef struct declarations for apache files
print;
} elsif (s/typedef\s+(const\s+char\s+\*\s*)(\w+)/typedef ($1)$2/) {
#C::Scan cannot parse this construct without ()'s
print;
} elsif ($apache_file and /^\s*typedef\s+struct\s+(\w+)\s+(\w+)\;/ and $1 eq $2) {
$typedef{$1} = 1;
#rewrite forward typedef struct declaration (done below)
print;
} elsif (/^\s*struct\s+(\w+)\s+\{/ and $typedef{$1}) {
my $name = $1;
s/^\s*struct\s+\w+/typedef struct/;
print;
while (my $line = <$cmd>) {
if ($line =~ s/^\s*\}\;\s*$/\} $name\;/) {
print $line;
last;
}
print $line;
}
} else {
print;
}
}
close $cmd;
}
1;
__END__
1.1 modperl-2.0/patches/c-scan.pat
Index: c-scan.pat
===================================================================
--- Scan.pm~ Thu Mar 23 06:14:18 2000
+++ Scan.pm Sun Jan 7 11:56:04 2001
@@ -400,7 +400,12 @@
} else {
$vars = parse_vars($chunk);
}
- push @$struct, @$vars;
+ if ($vars) {
+ push @$struct, @$vars;
+ }
+ else {
+ warn "unable to parse chunk: `$chunk'" if $C::Scan::Warn;
+ }
}
$structs->{$structname} = $struct;
$structname;
1.1 modperl-2.0/util/cvsize.pl
Index: cvsize.pl
===================================================================
#get an idea of how much space the XS interface will eat
#util/source_scan.pl must be run first
#see pod/modperl_sizeof.pod
use strict;
use Apache::FunctionTable ();
use Apache::StructureTable ();
use constant sizeofCV => 254;
my $size = 0;
my $subs = 0;
for my $entry (@$Apache::FunctionTable) {
$size += sizeofCV + ((length($entry->{name}) + 1) * 2);
$subs++;
}
for my $entry (@$Apache::StructureTable) {
my $elts = $entry->{elts} || [];
next unless @$elts;
for my $e (@$elts) {
$size += sizeofCV + ((length($e->{name}) + 1) * 2);
$subs++;
}
}
print "$subs subs, $size estimated bytes\n";
1.1 modperl-2.0/util/source_scan.pl
Index: source_scan.pl
===================================================================
#need apply patches/c-scan.pat against C-Scan-0.74
BEGIN {
#rather than use lib cos were gonna fork
$ENV{PERL5LIB} = "lib";
}
use strict;
use Apache::ParseSource ();
my $p = Apache::ParseSource->new;
$p->parse;
$p->write_functions_pm;
$p->write_structs_pm;