[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-unattended/var/se3/unattended/install/linuxaux/opt/perl/lib/5.10.0/Module/Build/ -> ModuleInfo.pm (source)

   1  package Module::Build::ModuleInfo;
   2  
   3  # This module provides routines to gather information about
   4  # perl modules (assuming this may be expanded in the distant
   5  # parrot future to look at other types of modules).
   6  
   7  use strict;
   8  use vars qw($VERSION);
   9  $VERSION = '0.2808_01';
  10  $VERSION = eval $VERSION;
  11  
  12  use File::Spec;
  13  use IO::File;
  14  use Module::Build::Version;
  15  
  16  
  17  my $PKG_REGEXP  = qr/   # match a package declaration
  18    ^[\s\{;]*             # intro chars on a line
  19    package               # the word 'package'
  20    \s+                   # whitespace
  21    ([\w:]+)              # a package name
  22    \s*                   # optional whitespace
  23    ;                     # semicolon line terminator
  24  /x;
  25  
  26  my $VARNAME_REGEXP = qr/ # match fully-qualified VERSION name
  27    ([\$*])         # sigil - $ or *
  28    (
  29      (             # optional leading package name
  30        (?:::|\')?  # possibly starting like just :: (ala $::VERSION)
  31        (?:\w+(?:::|\'))*  # Foo::Bar:: ...
  32      )?
  33      VERSION
  34    )\b
  35  /x;
  36  
  37  my $VERS_REGEXP = qr/ # match a VERSION definition
  38    (?:
  39      \(\s*$VARNAME_REGEXP\s*\) # with parens
  40    |
  41      $VARNAME_REGEXP           # without parens
  42    )
  43    \s*
  44    =[^=~]  # = but not ==, nor =~
  45  /x;
  46  
  47  
  48  sub new_from_file {
  49    my $package  = shift;
  50    my $filename = File::Spec->rel2abs( shift );
  51    return undef unless defined( $filename ) && -f $filename;
  52    return $package->_init( undef, $filename, @_ );
  53  }
  54  
  55  sub new_from_module {
  56    my $package = shift;
  57    my $module  = shift;
  58    my %props   = @_;
  59    $props{inc} ||= \@INC;
  60    my $filename = $package->find_module_by_name( $module, $props{inc} );
  61    return undef unless defined( $filename ) && -f $filename;
  62    return $package->_init( $module, $filename, %props );
  63  }
  64  
  65  sub _init {
  66    my $package  = shift;
  67    my $module   = shift;
  68    my $filename = shift;
  69  
  70    my %props = @_;
  71    my( %valid_props, @valid_props );
  72    @valid_props = qw( collect_pod inc );
  73    @valid_props{@valid_props} = delete( @props{@valid_props} );
  74    warn "Unknown properties: @{[keys %props]}\n" if scalar( %props );
  75  
  76    my %data = (
  77      module   => $module,
  78      filename => $filename,
  79      version  => undef,
  80      packages => [],
  81      versions => {},
  82      pod          => {},
  83      pod_headings => [],
  84      collect_pod  => 0,
  85  
  86      %valid_props,
  87    );
  88  
  89    my $self = bless( \%data, $package );
  90  
  91    $self->_parse_file();
  92  
  93    unless ( $self->{module} && length( $self->{module} ) ) {
  94      my( $v, $d, $f ) = File::Spec->splitpath( $self->{filename} );
  95      if ( $f =~ /\.pm$/ ) {
  96        $f =~ s/\..+$//;
  97        my @candidates = grep /$f$/, @{$self->{packages}};
  98        $self->{module} = shift( @candidates ); # punt
  99      } else {
 100        if ( grep /main/, @{$self->{packages}} ) {
 101      $self->{module} = 'main';
 102        } else {
 103          $self->{module} = $self->{packages}[0] || '';
 104        }
 105      }
 106    }
 107  
 108    $self->{version} = $self->{versions}{$self->{module}}
 109        if defined( $self->{module} );
 110  
 111    return $self;
 112  }
 113  
 114  # class method
 115  sub _do_find_module {
 116    my $package = shift;
 117    my $module  = shift || die 'find_module_by_name() requires a package name';
 118    my $dirs    = shift || \@INC;
 119  
 120    my $file = File::Spec->catfile(split( /::/, $module));
 121    foreach my $dir ( @$dirs ) {
 122      my $testfile = File::Spec->catfile($dir, $file);
 123      return [ File::Spec->rel2abs( $testfile ), $dir ]
 124      if -e $testfile and !-d _;  # For stuff like ExtUtils::xsubpp
 125      return [ File::Spec->rel2abs( "$testfile.pm" ), $dir ]
 126      if -e "$testfile.pm";
 127    }
 128    return;
 129  }
 130  
 131  # class method
 132  sub find_module_by_name {
 133    my $found = shift()->_do_find_module(@_) or return;
 134    return $found->[0];
 135  }
 136  
 137  # class method
 138  sub find_module_dir_by_name {
 139    my $found = shift()->_do_find_module(@_) or return;
 140    return $found->[1];
 141  }
 142  
 143  
 144  # given a line of perl code, attempt to parse it if it looks like a
 145  # $VERSION assignment, returning sigil, full name, & package name
 146  sub _parse_version_expression {
 147    my $self = shift;
 148    my $line = shift;
 149  
 150    my( $sig, $var, $pkg );
 151    if ( $line =~ $VERS_REGEXP ) {
 152      ( $sig, $var, $pkg ) = $2 ? ( $1, $2, $3 ) : ( $4, $5, $6 );
 153      if ( $pkg ) {
 154        $pkg = ($pkg eq '::') ? 'main' : $pkg;
 155        $pkg =~ s/::$//;
 156      }
 157    }
 158  
 159    return ( $sig, $var, $pkg );
 160  }
 161  
 162  sub _parse_file {
 163    my $self = shift;
 164  
 165    my $filename = $self->{filename};
 166    my $fh = IO::File->new( $filename )
 167      or die( "Can't open '$filename': $!" );
 168  
 169    $self->_parse_fh($fh);
 170  }
 171  
 172  sub _parse_fh {
 173    my ($self, $fh) = @_;
 174  
 175    my( $in_pod, $seen_end, $need_vers ) = ( 0, 0, 0 );
 176    my( @pkgs, %vers, %pod, @pod );
 177    my $pkg = 'main';
 178    my $pod_sect = '';
 179    my $pod_data = '';
 180  
 181    while (defined( my $line = <$fh> )) {
 182  
 183      chomp( $line );
 184      next if $line =~ /^\s*#/;
 185  
 186      $in_pod = ($line =~ /^=(?!cut)/) ? 1 : ($line =~ /^=cut/) ? 0 : $in_pod;
 187  
 188      # Would be nice if we could also check $in_string or something too
 189      last if !$in_pod && $line =~ /^__(?:DATA|END)__$/;
 190  
 191      if ( $in_pod || $line =~ /^=cut/ ) {
 192  
 193        if ( $line =~ /^=head\d\s+(.+)\s*$/ ) {
 194      push( @pod, $1 );
 195      if ( $self->{collect_pod} && length( $pod_data ) ) {
 196            $pod{$pod_sect} = $pod_data;
 197            $pod_data = '';
 198          }
 199      $pod_sect = $1;
 200  
 201  
 202        } elsif ( $self->{collect_pod} ) {
 203      $pod_data .= "$line\n";
 204  
 205        }
 206  
 207      } else {
 208  
 209        $pod_sect = '';
 210        $pod_data = '';
 211  
 212        # parse $line to see if it's a $VERSION declaration
 213        my( $vers_sig, $vers_fullname, $vers_pkg ) =
 214        $self->_parse_version_expression( $line );
 215  
 216        if ( $line =~ $PKG_REGEXP ) {
 217      $pkg = $1;
 218      push( @pkgs, $pkg ) unless grep( $pkg eq $_, @pkgs );
 219      $vers{$pkg} = undef unless exists( $vers{$pkg} );
 220      $need_vers = 1;
 221  
 222        # VERSION defined with full package spec, i.e. $Module::VERSION
 223        } elsif ( $vers_fullname && $vers_pkg ) {
 224      push( @pkgs, $vers_pkg ) unless grep( $vers_pkg eq $_, @pkgs );
 225      $need_vers = 0 if $vers_pkg eq $pkg;
 226  
 227      unless ( defined $vers{$vers_pkg} && length $vers{$vers_pkg} ) {
 228        $vers{$vers_pkg} = 
 229          $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
 230      } else {
 231        # Warn unless the user is using the "$VERSION = eval
 232        # $VERSION" idiom (though there are probably other idioms
 233        # that we should watch out for...)
 234        warn <<"EOM" unless $line =~ /=\s*eval/;
 235  Package '$vers_pkg' already declared with version '$vers{$vers_pkg}',
 236  ignoring subsequent declaration.
 237  EOM
 238      }
 239  
 240        # first non-comment line in undeclared package main is VERSION
 241        } elsif ( !exists($vers{main}) && $pkg eq 'main' && $vers_fullname ) {
 242      $need_vers = 0;
 243      my $v =
 244        $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
 245      $vers{$pkg} = $v;
 246      push( @pkgs, 'main' );
 247  
 248        # first non-comement line in undeclared packge defines package main
 249        } elsif ( !exists($vers{main}) && $pkg eq 'main' && $line =~ /\w+/ ) {
 250      $need_vers = 1;
 251      $vers{main} = '';
 252      push( @pkgs, 'main' );
 253  
 254        # only keep if this is the first $VERSION seen
 255        } elsif ( $vers_fullname && $need_vers ) {
 256      $need_vers = 0;
 257      my $v =
 258        $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
 259  
 260  
 261      unless ( defined $vers{$pkg} && length $vers{$pkg} ) {
 262        $vers{$pkg} = $v;
 263      } else {
 264        warn <<"EOM";
 265  Package '$pkg' already declared with version '$vers{$pkg}'
 266  ignoring new version '$v'.
 267  EOM
 268      }
 269  
 270        }
 271  
 272      }
 273  
 274    }
 275  
 276    if ( $self->{collect_pod} && length($pod_data) ) {
 277      $pod{$pod_sect} = $pod_data;
 278    }
 279  
 280    $self->{versions} = \%vers;
 281    $self->{packages} = \@pkgs;
 282    $self->{pod} = \%pod;
 283    $self->{pod_headings} = \@pod;
 284  }
 285  
 286  sub _evaluate_version_line {
 287    my $self = shift;
 288    my( $sigil, $var, $line ) = @_;
 289  
 290    # Some of this code came from the ExtUtils:: hierarchy.
 291  
 292    # We compile into $vsub because 'use version' would cause
 293    # compiletime/runtime issues with local()
 294    my $vsub;
 295    my $eval = qq{BEGIN { q#  Hide from _packages_inside()
 296      #; package Module::Build::ModuleInfo::_version;
 297      no strict;
 298  
 299      local $sigil$var;
 300      \$$var=undef;
 301        \$vsub = sub {
 302          $line;
 303          \$$var
 304        };
 305    }};
 306  
 307    local $^W;
 308    # Try to get the $VERSION
 309    eval $eval;
 310    warn "Error evaling version line '$eval' in $self->{filename}: $@\n"
 311      if $@;
 312    (ref($vsub) eq 'CODE') or
 313      die "failed to build version sub for $self->{filename}";
 314    my $result = $vsub->();
 315  
 316    # Bless it into our own version class
 317    $result = Module::Build::Version->new($result);
 318  
 319    return $result;
 320  }
 321  
 322  
 323  ############################################################
 324  
 325  # accessors
 326  sub name            { $_[0]->{module}           }
 327  
 328  sub filename        { $_[0]->{filename}         }
 329  sub packages_inside { @{$_[0]->{packages}}      }
 330  sub pod_inside      { @{$_[0]->{pod_headings}}  }
 331  sub contains_pod    { $#{$_[0]->{pod_headings}} }
 332  
 333  sub version {
 334      my $self = shift;
 335      my $mod  = shift || $self->{module};
 336      my $vers;
 337      if ( defined( $mod ) && length( $mod ) &&
 338       exists( $self->{versions}{$mod} ) ) {
 339      return $self->{versions}{$mod};
 340      } else {
 341      return undef;
 342      }
 343  }
 344  
 345  sub pod {
 346      my $self = shift;
 347      my $sect = shift;
 348      if ( defined( $sect ) && length( $sect ) &&
 349       exists( $self->{pod}{$sect} ) ) {
 350      return $self->{pod}{$sect};
 351      } else {
 352      return undef;
 353      }
 354  }
 355  
 356  1;
 357  
 358  __END__
 359  
 360  =head1 NAME
 361  
 362  ModuleInfo - Gather package and POD information from a perl module files
 363  
 364  
 365  =head1 DESCRIPTION
 366  
 367  =over 4
 368  
 369  =item new_from_file($filename, collect_pod => 1)
 370  
 371  Construct a ModuleInfo object given the path to a file. Takes an optional
 372  arguement C<collect_pod> which is a boolean that determines whether
 373  POD data is collected and stored for reference. POD data is not
 374  collected by default. POD headings are always collected.
 375  
 376  =item new_from_module($module, collect_pod => 1, inc => \@dirs)
 377  
 378  Construct a ModuleInfo object given a module or package name. In addition
 379  to accepting the C<collect_pod> argument as described above, this
 380  method accepts a C<inc> arguemnt which is a reference to an array of
 381  of directories to search for the module. If none are given, the
 382  default is @INC.
 383  
 384  =item name()
 385  
 386  Returns the name of the package represented by this module. If there
 387  are more than one packages, it makes a best guess based on the
 388  filename. If it's a script (i.e. not a *.pm) the package name is
 389  'main'.
 390  
 391  =item version($package)
 392  
 393  Returns the version as defined by the $VERSION variable for the
 394  package as returned by the C<name> method if no arguments are
 395  given. If given the name of a package it will attempt to return the
 396  version of that package if it is specified in the file.
 397  
 398  =item filename()
 399  
 400  Returns the absolute path to the file.
 401  
 402  =item packages_inside()
 403  
 404  Returns a list of packages.
 405  
 406  =item pod_inside()
 407  
 408  Returns a list of POD sections.
 409  
 410  =item contains_pod()
 411  
 412  Returns true if there is any POD in the file.
 413  
 414  =item pod($section)
 415  
 416  Returns the POD data in the given section.
 417  
 418  =item find_module_by_name($module, \@dirs)
 419  
 420  Returns the path to a module given the module or package name. A list
 421  of directories can be passed in as an optional paramater, otherwise
 422  @INC is searched.
 423  
 424  Can be called as either an object or a class method.
 425  
 426  =item find_module_dir_by_name($module, \@dirs)
 427  
 428  Returns the entry in C<@dirs> (or C<@INC> by default) that contains
 429  the module C<$module>. A list of directories can be passed in as an
 430  optional paramater, otherwise @INC is searched.
 431  
 432  Can be called as either an object or a class method.
 433  
 434  =back
 435  
 436  
 437  =head1 AUTHOR
 438  
 439  Ken Williams <kwilliams@cpan.org>, Randy W. Sims <RandyS@ThePierianSpring.org>
 440  
 441  
 442  =head1 COPYRIGHT
 443  
 444  Copyright (c) 2001-2006 Ken Williams.  All rights reserved.
 445  
 446  This library is free software; you can redistribute it and/or
 447  modify it under the same terms as Perl itself.
 448  
 449  
 450  =head1 SEE ALSO
 451  
 452  perl(1), L<Module::Build>(3)
 453  
 454  =cut
 455  


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1