Add libwx-perl
[pkg-perl] / deb-src / libwx-perl / libwx-perl-0.96 / blib / lib / Wx / build / Utils.pm
diff --git a/deb-src/libwx-perl/libwx-perl-0.96/blib/lib/Wx/build/Utils.pm b/deb-src/libwx-perl/libwx-perl-0.96/blib/lib/Wx/build/Utils.pm
new file mode 100644 (file)
index 0000000..786765a
--- /dev/null
@@ -0,0 +1,326 @@
+package Wx::build::Utils;
+
+use strict;
+use Config;
+use base 'Exporter';
+use File::Spec::Functions qw(curdir catdir catfile updir);
+use File::Find qw(find);
+use File::Path qw(mkpath);
+use File::Basename qw(dirname);
+use Carp;
+
+use vars qw(@EXPORT @EXPORT_OK);
+@EXPORT_OK = qw(obj_from_src xs_dependencies write_string
+                lib_file arch_file arch_auto_file
+                path_search files_with_overload files_with_constants
+                pipe_stderr read_file write_file);
+
+=head1 NAME
+
+Wx::build::Utils - utility routines
+
+=head1 SUBROUTINES
+
+=head2 xs_dependencies
+
+  my %dependencies = xs_dependencies( $mm_object, [ 'dir1', 'dir2' ] );
+
+=cut
+
+sub _uniq {
+    my( %x );
+    $x{$_} = 1 foreach @_;
+    return sort keys %x;
+}
+
+sub xs_dependencies {
+  my( $this, $dirs, $top_dir ) = @_;
+
+  my( %depend );
+  my( $c, $o, $cinclude, $xsinclude );
+
+  foreach ( keys %{ $this->{XS} } ) {
+    ( $cinclude, $xsinclude ) = scan_xs( $_, $dirs, $top_dir );
+
+    $c = $this->{XS}{$_};
+    $o = obj_from_src( $c );
+
+    $depend{$c} = $_ . ' ' . join( ' ', _uniq( @$xsinclude ) );
+    $depend{$o} = $c . ' ' . join( ' ', _uniq( @$cinclude ) );
+  }
+
+  return %depend;
+}
+
+=head2 obj_from_src
+
+  my @obj_files = obj_from_src( 'Foo.xs', 'bar.c', 'cpp/bar.cpp' );
+
+Calculates the object file name from the source file name.
+In scalar context returns the first file.
+
+=cut
+
+sub obj_from_src {
+  my @xs = @_;
+  my $obj_ext = $Config{obj_ext} || $Config{_o};
+
+  foreach ( @xs ) { s[\.(?:xs|c|cc|cpp)$][$obj_ext] }
+
+  return wantarray ? @xs : $xs[0];
+}
+
+sub src_dir {
+  my( $file ) = @_;
+  my $d = curdir;
+
+  for ( 1 .. 5 ) {
+    return $d if -f catfile( $d, $file );
+    $d = catdir( updir, $d );
+  }
+
+  confess "Unable to find top level directory ($file)";
+}
+
+#
+# quick and dirty method for creating dependencies:
+# considers files included via #include "..." or INCLUDE: ...
+# (not #include <...>) and does not take into account preprocessor directives
+#
+sub scan_xs($$$);
+
+sub scan_xs($$$) {
+  my( $xs, $incpath, $top_dir ) = @_;
+
+  local( *IN, $_ );
+  my( @cinclude, @xsinclude );
+
+  open IN, $xs;
+
+  my $file;
+  my $arr;
+
+  while( defined( $_ = <IN> ) ) {
+    undef $file;
+
+    m/^\#\s*include\s+"([^"]*)"\s*$/ and $file = $1 and $arr = \@cinclude;
+    m/^\s*INCLUDE:\s+(.*)$/ and $file = $1 and $arr = \@xsinclude;
+    m/^\s*INCLUDE:\s+.*\s(\S+\.xsp?)\s*\|/ and $file = $1 and
+      $arr = \@xsinclude;
+
+    if( defined $file ) {
+      $file = catfile( split '/', $file );
+
+      foreach my $dir ( @$incpath ) {
+        my $f = $dir eq curdir() ? $file : catfile( $dir, $file );
+        if( -f $f ) {
+          push @$arr, $f;
+          my( $cinclude, $xsinclude ) = scan_xs( $f, $incpath, $top_dir );
+          push @cinclude, @$cinclude;
+          push @xsinclude, @$xsinclude;
+          last;
+        } elsif(    $file =~ m/ovl_const\.(?:cpp|h)/i
+                 || $file =~ m/v_cback_def\.h/i
+                 || $file =~ m/ItemContainer(?:Immutable)?\.xs/i
+                 || $file =~ m/Var[VH]{0,2}ScrollHelper(?:Base)?\.xs/i ) {
+          push @$arr, ( ( $top_dir eq curdir() ) ?
+                        $file :
+                        catfile( $top_dir, $file ) );
+        }
+      }
+    }
+  }
+
+  close IN;
+
+  ( \@cinclude, \@xsinclude );
+}
+
+=head2 write_string, write_file
+
+  write_string( 'file', $scalar );
+  write_file( 'file', $scalar );
+
+Like File::Slurp.
+
+=head2 read_file
+
+  my $string = read_file( 'file' );
+
+=cut
+
+*write_string = \&write_file;
+
+sub write_file {
+  my( $file, $string ) = @_;
+
+  mkpath( dirname( $file ) ) if dirname( $file );
+  open my $fh, ">", $file or die "open '$file': $!";
+  binmode $fh;
+  print $fh $string or die "print '$file': $!";
+  close $fh or die "close '$file': $!";
+}
+
+sub read_file {
+  my( $file ) = @_;
+
+  local $/ = wantarray ? $/ : undef;;
+  open my $fh, "<", $file or die "open '$file': $!";
+  binmode $fh;
+
+  return <$fh>;
+}
+
+=head2 lib_file, arch_file, arch_auto_file
+
+  my $file = lib_file( 'Foo.pm' );          # blib/lib/Foo.pm     on *nix
+  my $file = lib_file( 'Foo/Bar.pm' );      # blib\lib\Foo\Bar.pm on Win32
+  my $file = arch_auto_file( 'My\My.dll' ); # blib\arch\auto\My\My.dll
+
+All input paths must be relative, output paths may be absolute.
+
+=cut
+
+sub _split {
+  require File::Spec::Unix;
+
+  my $path = shift;
+  my( $volume, $dir, $file ) = File::Spec::Unix->splitpath( $path );
+  my @dirs = File::Spec::Unix->splitdir( $dir );
+
+  return ( @dirs, $file );
+}
+
+sub lib_file {
+  my @split = _split( shift );
+
+  return File::Spec->catfile( 'blib', 'lib', @split );
+}
+
+sub arch_file {
+  my @split = _split( shift );
+
+  return File::Spec->catfile( 'blib', 'arch', @split );
+}
+
+sub arch_auto_file {
+  my @split = _split( shift );
+
+  return File::Spec->catfile( 'blib', 'arch', 'auto', @split );
+}
+
+=head2 path_search
+
+  my $file = path_search( 'foo.exe' );
+
+Searches PATH for the given executable.
+
+=cut
+
+sub path_search {
+  my $file = shift;
+
+  foreach my $d ( File::Spec->path ) {
+    my $full = File::Spec->catfile( $d, $file );
+    return $full if -f $full;
+  }
+
+  return;
+}
+
+=head2 files_with_constants
+
+  my @files = files_with_constants;
+
+Finds files containing constants
+
+=cut
+
+sub files_with_constants {
+  my @files;
+
+  my $wanted = sub {
+    my $name = $File::Find::name;
+
+    m/\.(?:pm|xsp?|cpp|h)$/i && do {
+      local *IN;
+      my $line;
+
+      open IN, "< $_" || warn "unable to open '$_'";
+      while( defined( $line = <IN> ) ) {
+        $line =~ m/^\W+\!\w+:/ && do {
+          push @files, $name;
+          return;
+        };
+      };
+    };
+  };
+
+  find( $wanted, curdir );
+
+  return @files;
+}
+
+=head2 files_with_overload
+
+  my @files = files_with_overload;
+
+Finds files containing overloaded XS/Perl subroutines
+
+=cut
+
+sub files_with_overload {
+  my @files;
+
+  my $wanted = sub {
+    my $name = $File::Find::name;
+
+    m/\.pm$/i && do {
+      my $line;
+      local *IN;
+
+      open IN, "< $_" || warn "unable to open '$_'";
+      while( defined( $line = <IN> ) ) {
+        $line =~ m/Wx::_match/ && do {
+          push @files, $name;
+          return;
+        };
+      }
+    };
+
+    m/\.xsp?$/i && do {
+      my $line;
+      local *IN;
+
+      open IN, "< $_" || warn "unable to open '$_'";
+      while( defined( $line = <IN> ) ) {
+        $line =~ m/wxPli_match_arguments|BEGIN_OVERLOAD\(\)/ && do {
+          push @files, $name;
+          return;
+        };
+      }
+    };
+  };
+
+  find( $wanted, curdir );
+
+  return @files;
+}
+
+sub pipe_stderr {
+  my( $cmd ) = @_;
+  my $pipe = File::Spec->catfile( 'script', 'pipe.pl' );
+
+  if( -f $pipe ) {
+    return qx{$^X $pipe $cmd};
+  } else {
+    # fix quoting later if necessary
+    return qx[$^X -e "open STDERR, q{>&STDOUT}; exec q{$cmd}"];
+  }
+}
+
+1;
+
+# local variables:
+# mode: cperl
+# end: