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;