Make compile on NetBSD.
[wine/multimedia.git] / tools / winapi_check / modules.pm
blob1904ff37db7b4a9bb86b51047a8aa7dac6d979f3
2 # Copyright 1999, 2000, 2001 Patrik Stridvall
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 package modules;
21 use strict;
23 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
24 require Exporter;
26 @ISA = qw(Exporter);
27 @EXPORT = qw();
28 @EXPORT_OK = qw($modules);
30 use vars qw($modules);
32 use config qw(
33 &file_type &files_skip
34 &file_directory
35 &get_c_files &get_spec_files
36 $current_dir $wine_dir
37 $winapi_check_dir
39 use options qw($options);
40 use output qw($output);
42 $modules = 'modules'->new;
44 sub get_spec_file_type {
45 my $file = shift;
47 my $module;
48 my $type;
50 $module = $file;
51 $module =~ s%^.*?([^/]+)\.spec$%$1%;
53 open(IN, "< $file") || die "$file: $!\n";
54 local $/ = "\n";
55 my $header = 1;
56 my $lookahead = 0;
57 while($lookahead || defined($_ = <IN>)) {
58 $lookahead = 0;
59 s/^\s*(.*?)\s*$/$1/;
60 s/^(.*?)\s*#.*$/$1/;
61 /^$/ && next;
63 if($header) {
64 if(/^\d+|@/) { $header = 0; $lookahead = 1; }
65 next;
68 if(/^(\d+|@)\s+pascal(?:16)?/) {
69 $type = "win16";
70 last;
73 close(IN);
75 if(!defined($type)) {
76 $type = "win32";
79 return ($type, $module);
82 sub new {
83 my $proto = shift;
84 my $class = ref($proto) || $proto;
85 my $self = {};
86 bless ($self, $class);
88 my $spec_files16 = \@{$self->{SPEC_FILES16}};
89 my $spec_files32 = \@{$self->{SPEC_FILES32}};
90 my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
91 my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
92 my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
93 my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
95 my $module_file = "$winapi_check_dir/modules.dat";
97 $output->progress("modules.dat");
99 my %spec_file_found;
100 my $allowed_dir;
101 my $spec_file;
103 open(IN, "< $module_file");
104 local $/ = "\n";
105 while(<IN>) {
106 s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begining and end of line
107 s/^(.*?)\s*#.*$/$1/; # remove comments
108 /^$/ && next; # skip empty lines
110 if(/^%\s+(.*?)$/) {
111 $spec_file = $1;
113 if(!-f "$wine_dir/$spec_file") {
114 $output->write("modules.dat: $spec_file: file ($spec_file) doesn't exist or is no file\n");
117 $spec_file_found{$spec_file}++;
118 $$spec_file2dir{$spec_file} = {};
119 next;
120 } else {
121 $allowed_dir = $1;
122 $$spec_file2dir{$spec_file}{$allowed_dir}++;
124 $$dir2spec_file{$allowed_dir}{$spec_file}++;
126 if(!-d "$wine_dir/$allowed_dir") {
127 $output->write("modules.dat: $spec_file: directory ($allowed_dir) doesn't exist or is no directory\n");
130 close(IN);
132 my @spec_files;
133 if($wine_dir eq ".") {
134 @spec_files = get_spec_files("winelib");
135 } else {
136 my %spec_files = ();
137 foreach my $dir ($options->directories) {
138 $dir = "$current_dir/$dir";
139 $dir =~ s%/\.$%%;
140 foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
141 $spec_files{$spec_file}++;
144 @spec_files = sort(keys(%spec_files));
147 @$spec_files16 = ();
148 @$spec_files32 = ();
149 foreach my $spec_file (@spec_files) {
150 (my $type, my $module) = get_spec_file_type("$wine_dir/$spec_file");
152 $$spec_file2module{$spec_file} = $module;
153 $$module2spec_file{$module} = $spec_file;
155 if($type eq "win16") {
156 push @$spec_files16, $spec_file;
157 } elsif($type eq "win32") {
158 push @$spec_files32, $spec_file;
159 } else {
160 $output->write("$spec_file: unknown type '$type'\n");
164 foreach my $spec_file (@spec_files) {
165 if(!$spec_file_found{$spec_file} && $spec_file !~ m%tests/[^/]+$%) {
166 $output->write("modules.dat: $spec_file: exists but is not specified\n");
170 $modules = $self;
172 return $self;
175 sub all_modules {
176 my $self = shift;
178 my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
180 return sort(keys(%$module2spec_file));
183 sub complete_modules {
184 my $self = shift;
186 my $c_files = shift;
188 my %dirs;
190 foreach my $file (@$c_files) {
191 my $dir = file_directory("$current_dir/$file");
192 $dirs{$dir}++;
195 my @c_files = get_c_files("winelib");
196 @c_files = files_skip(@c_files);
197 foreach my $file (@c_files) {
198 my $dir = file_directory($file);
199 if(exists($dirs{$dir})) {
200 $dirs{$dir}--;
204 my @complete_modules = ();
205 foreach my $module ($self->all_modules) {
206 my $index = -1;
207 my @dirs = $self->allowed_dirs_for_module($module);
208 foreach my $dir (@dirs) {
209 if(exists($dirs{$dir}) && $dirs{$dir} == 0) {
210 $index++;
213 if($index == $#dirs) {
214 push @complete_modules, $module;
218 return @complete_modules;
221 sub is_allowed_module {
222 my $self = shift;
224 my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
226 my $module = shift;
228 return defined($$module2spec_file{$module});
231 sub is_allowed_module_in_file {
232 my $self = shift;
234 my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
235 my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
237 my $module = shift;
238 my $file = shift;
239 $file =~ s/^\.\///;
241 my $dir = $file;
242 $dir =~ s/\/[^\/]*$//;
244 if($dir =~ m%^include%) {
245 return 1;
248 foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
249 if($$spec_file2module{$spec_file} eq $module) {
250 return 1;
254 return 0;
257 sub allowed_modules_in_file {
258 my $self = shift;
260 my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
261 my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
263 my $file = shift;
264 $file =~ s/^\.\///;
266 my $dir = $file;
267 $dir =~ s/\/[^\/]*$//;
269 my %allowed_modules = ();
270 foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
271 my $module = $$spec_file2module{$spec_file};
272 $allowed_modules{$module}++;
275 my $module = join(" & ", sort(keys(%allowed_modules)));
277 return $module;
280 sub allowed_dirs_for_module {
281 my $self = shift;
283 my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
284 my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
286 my $module = shift;
288 my $spec_file = $$module2spec_file{$module};
290 return sort(keys(%{$$spec_file2dir{$spec_file}}));
293 sub allowed_spec_files16 {
294 my $self = shift;
296 my $spec_files16 = \@{$self->{SPEC_FILES16}};
298 return @$spec_files16;
301 sub allowed_spec_files32 {
302 my $self = shift;
304 my $spec_files32 = \@{$self->{SPEC_FILES32}};
306 return @$spec_files32;
309 sub found_module_in_dir {
310 my $self = shift;
312 my $module = shift;
313 my $dir = shift;
315 my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
317 $dir = "$current_dir/$dir";
318 $dir =~ s%/\.$%%;
320 $$used_module_dirs{$module}{$dir}++;
323 sub global_report {
324 my $self = shift;
326 my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
327 my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
328 my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
330 my @messages;
331 foreach my $dir ($options->directories) {
332 $dir = "$current_dir/$dir";
333 $dir =~ s%/\.$%%;
334 foreach my $module ($self->all_modules) {
335 if(!$$used_module_dirs{$module}{$dir}) {
336 my $spec_file = $$module2spec_file{$module};
337 push @messages, "modules.dat: $spec_file: directory ($dir) is not used\n";
342 foreach my $message (sort(@messages)) {
343 $output->write($message);