blob: cbf1a2a97da957d74f9eeb05a5930404248d66cd [file] [log] [blame]
#
# Copyright 1999, 2000, 2001 Patrik Stridvall
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#
package modules;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw();
@EXPORT_OK = qw($modules);
use vars qw($modules);
use config qw(
file_type files_skip
file_directory
get_c_files get_spec_files
$current_dir $wine_dir
);
use options qw($options);
use output qw($output);
sub import(@) {
$Exporter::ExportLevel++;
Exporter::import(@_);
$Exporter::ExportLevel--;
if (defined($modules)) {
return;
}
$modules = 'modules'->new;
}
sub get_spec_file_type($) {
my $file = shift;
my $module;
my $type;
$module = $file;
$module =~ s%^.*?([^/]+)\.spec$%$1%;
open(IN, "< $file") || die "$file: $!\n";
local $/ = "\n";
my $header = 1;
my $lookahead = 0;
while($lookahead || defined($_ = <IN>)) {
$lookahead = 0;
s/^\s*(.*?)\s*$/$1/;
s/^(.*?)\s*#.*$/$1/;
/^$/ && next;
if($header) {
if(/^(?:\d+|@)/) { $header = 0; $lookahead = 1; }
next;
}
if(/^(\d+|@)\s+pascal(?:16)?/) {
$type = "win16";
last;
}
}
close(IN);
if(!defined($type)) {
$type = "win32";
}
return ($type, $module);
}
sub find_spec_files($) {
my $self = shift;
my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
$output->progress("modules");
my $spec_file_found = {};
my $allowed_dir;
my $spec_file;
my @spec_files = <{dlls/*/*.spec}>;
foreach $spec_file (@spec_files) {
$spec_file =~ /(.*)\/.*\.spec/;
$allowed_dir = $1;
$$spec_file_found{$spec_file}++;
$$spec_file2dir{$spec_file}{$allowed_dir}++;
$$dir2spec_file{$allowed_dir}{$spec_file}++;
# gdi32.dll and gdi.exe have some extra sources in subdirectories
if ($spec_file =~ m!/gdi32\.spec$!)
{
$$spec_file2dir{$spec_file}{"$allowed_dir/enhmfdrv"}++;
$$dir2spec_file{"$allowed_dir/enhmfdrv"}{$spec_file}++;
}
if ($spec_file =~ m!/gdi(?:32|\.exe)\.spec$!)
{
$$spec_file2dir{$spec_file}{"$allowed_dir/mfdrv"}++;
$$dir2spec_file{"$allowed_dir/mfdrv"}{$spec_file}++;
}
}
return $spec_file_found;
}
sub read_spec_files($$) {
my $self = shift;
my $spec_file_found = shift;
my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
my $spec_files16 = \@{$self->{SPEC_FILES16}};
my $spec_files32 = \@{$self->{SPEC_FILES32}};
my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
my @spec_files;
if($wine_dir eq ".") {
@spec_files = get_spec_files("winelib");
} else {
my %spec_files = ();
foreach my $dir ($options->directories) {
$dir = "$current_dir/$dir";
$dir =~ s%/\.$%%;
foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
$spec_files{$spec_file}++;
}
}
@spec_files = sort(keys(%spec_files));
}
@$spec_files16 = ();
@$spec_files32 = ();
foreach my $spec_file (@spec_files) {
(my $type, my $module) = get_spec_file_type("$wine_dir/$spec_file");
$$spec_file2module{$spec_file} = $module;
$$module2spec_file{$module} = $spec_file;
if($type eq "win16") {
push @$spec_files16, $spec_file;
} elsif($type eq "win32") {
push @$spec_files32, $spec_file;
} else {
$output->write("$spec_file: unknown type '$type'\n");
}
}
foreach my $spec_file (@spec_files) {
if(!$$spec_file_found{$spec_file} && $spec_file !~ m%tests/[^/]+$%) {
$output->write("modules: $spec_file: exists but is not specified\n");
}
}
}
sub new($) {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
bless ($self, $class);
my $spec_file_found = $self->find_spec_files();
$self->read_spec_files($spec_file_found);
return $self;
}
sub all_modules($) {
my $self = shift;
my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
return sort(keys(%$module2spec_file));
}
sub is_allowed_module($$) {
my $self = shift;
my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
my $module = shift;
return defined($$module2spec_file{$module});
}
sub is_allowed_module_in_file($$$) {
my $self = shift;
my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
my $module = shift;
my $file = shift;
$file =~ s/^\.\///;
my $dir = $file;
$dir =~ s/\/[^\/]*$//;
if($dir =~ m%^include%) {
return 1;
}
foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
if($$spec_file2module{$spec_file} eq $module) {
return 1;
}
}
return 0;
}
sub allowed_modules_in_file($$) {
my $self = shift;
my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
my $file = shift;
$file =~ s/^\.\///;
my $dir = $file;
$dir =~ s/\/[^\/]*$//;
my %allowed_modules = ();
foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
my $module = $$spec_file2module{$spec_file};
$allowed_modules{$module}++;
}
my $module = join(" & ", sort(keys(%allowed_modules)));
return $module;
}
sub allowed_dirs_for_module($$) {
my $self = shift;
my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
my $module = shift;
my $spec_file = $$module2spec_file{$module};
return sort(keys(%{$$spec_file2dir{$spec_file}}));
}
sub allowed_spec_files16($) {
my $self = shift;
my $spec_files16 = \@{$self->{SPEC_FILES16}};
return @$spec_files16;
}
sub allowed_spec_files32($) {
my $self = shift;
my $spec_files32 = \@{$self->{SPEC_FILES32}};
return @$spec_files32;
}
sub found_module_in_dir($$$) {
my $self = shift;
my $module = shift;
my $dir = shift;
my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
$dir = "$current_dir/$dir";
$dir =~ s%/\.$%%;
$$used_module_dirs{$module}{$dir}++;
}
sub complete_modules($$) {
my $self = shift;
my $c_files = shift;
my %dirs;
foreach my $file (@$c_files) {
my $dir = file_directory("$current_dir/$file");
$dirs{$dir}++;
}
my @c_files = get_c_files("winelib");
@c_files = files_skip(@c_files);
foreach my $file (@c_files) {
my $dir = file_directory($file);
if(exists($dirs{$dir})) {
$dirs{$dir}--;
}
}
my @complete_modules = ();
foreach my $module ($self->all_modules) {
my $index = -1;
my @dirs = $self->allowed_dirs_for_module($module);
foreach my $dir (@dirs) {
if(exists($dirs{$dir}) && $dirs{$dir} == 0) {
$index++;
}
}
if($index == $#dirs) {
push @complete_modules, $module;
}
}
return @complete_modules;
}
sub global_report($) {
my $self = shift;
my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
my @messages;
foreach my $dir ($options->directories) {
$dir = "$current_dir/$dir";
$dir =~ s%/\.$%%;
foreach my $module ($self->all_modules) {
if(!$$used_module_dirs{$module}{$dir}) {
my $spec_file = $$module2spec_file{$module};
push @messages, "modules: $spec_file: directory ($dir) is not used\n";
}
}
}
foreach my $message (sort(@messages)) {
$output->write($message);
}
}
1;