369 lines
8.1 KiB
Perl
369 lines
8.1 KiB
Perl
#
|
|
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
|
|
$winapi_check_dir
|
|
);
|
|
use options qw($options);
|
|
use output qw($output);
|
|
|
|
sub import {
|
|
$Exporter::ExportLevel++;
|
|
&Exporter::import(@_);
|
|
$Exporter::ExportLevel--;
|
|
|
|
$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 new {
|
|
my $proto = shift;
|
|
my $class = ref($proto) || $proto;
|
|
my $self = {};
|
|
bless ($self, $class);
|
|
|
|
my $spec_file_found = $self->read_module_file();
|
|
$self->read_spec_files($spec_file_found);
|
|
|
|
return $self;
|
|
}
|
|
|
|
sub read_module_file {
|
|
my $self = shift;
|
|
|
|
my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
|
|
my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
|
|
|
|
my $module_file = "$winapi_check_dir/modules.dat";
|
|
|
|
$output->progress("modules.dat");
|
|
|
|
my $spec_file_found = {};
|
|
my $allowed_dir;
|
|
my $spec_file;
|
|
|
|
open(IN, "< $module_file");
|
|
local $/ = "\n";
|
|
while(<IN>) {
|
|
s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begining and end of line
|
|
s/^(.*?)\s*#.*$/$1/; # remove comments
|
|
/^$/ && next; # skip empty lines
|
|
|
|
if(/^%\s+(.*?)$/) {
|
|
$spec_file = $1;
|
|
|
|
if(!-f "$wine_dir/$spec_file") {
|
|
$output->write("modules.dat: $spec_file: file ($spec_file) doesn't exist or is no file\n");
|
|
}
|
|
|
|
$$spec_file_found{$spec_file}++;
|
|
$$spec_file2dir{$spec_file} = {};
|
|
next;
|
|
} else {
|
|
$allowed_dir = $1;
|
|
$$spec_file2dir{$spec_file}{$allowed_dir}++;
|
|
}
|
|
$$dir2spec_file{$allowed_dir}{$spec_file}++;
|
|
|
|
if(!-d "$wine_dir/$allowed_dir") {
|
|
$output->write("modules.dat: $spec_file: directory ($allowed_dir) doesn't exist or is no directory\n");
|
|
}
|
|
}
|
|
close(IN);
|
|
|
|
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.dat: $spec_file: exists but is not specified\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
sub all_modules {
|
|
my $self = shift;
|
|
|
|
my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
|
|
|
|
return sort(keys(%$module2spec_file));
|
|
}
|
|
|
|
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 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 global_report {
|
|
my $self = shift;
|
|
|
|
my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
|
|
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.dat: $spec_file: directory ($dir) is not used\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach my $message (sort(@messages)) {
|
|
$output->write($message);
|
|
}
|
|
}
|
|
|
|
1;
|