advpack: Put function declarations in advpack_private.h.
[wine] / tools / winapi / modules.pm
1 #
2 # Copyright 1999, 2000, 2001 Patrik Stridvall
3 #
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.
8 #
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.
13 #
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
17 #
18
19 package modules;
20
21 use strict;
22
23 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
24 require Exporter;
25
26 @ISA = qw(Exporter);
27 @EXPORT = qw();
28 @EXPORT_OK = qw($modules);
29
30 use vars qw($modules);
31
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 );
38 use options qw($options);
39 use output qw($output);
40
41 sub import(@) {
42     $Exporter::ExportLevel++;
43     Exporter::import(@_);
44     $Exporter::ExportLevel--;
45
46     if (defined($modules)) {
47         return;
48     }
49
50     $modules = 'modules'->new;
51 }
52
53 sub get_spec_file_type($) {
54     my $file = shift;
55
56     my $module;
57     my $type;
58
59     $module = $file;
60     $module =~ s%^.*?([^/]+)\.spec$%$1%;
61
62     open(IN, "< $file") || die "$file: $!\n";
63     local $/ = "\n";
64     my $header = 1;
65     my $lookahead = 0;
66     while($lookahead || defined($_ = <IN>)) {
67         $lookahead = 0;
68         s/^\s*(.*?)\s*$/$1/;
69         s/^(.*?)\s*#.*$/$1/;
70         /^$/ && next;
71
72         if($header)  {
73             if(/^(?:\d+|@)/) { $header = 0; $lookahead = 1; }
74             next;
75         }
76
77         if(/^(\d+|@)\s+pascal(?:16)?/) {
78             $type = "win16";
79             last;
80         }
81     }
82     close(IN);
83
84     if(!defined($type)) {
85         $type = "win32";
86     }
87
88     return ($type, $module);
89 }
90
91 sub find_spec_files($) {
92     my $self = shift;
93
94     my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
95     my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
96
97     $output->progress("modules");
98
99     my $spec_file_found = {};
100     my $allowed_dir;
101     my $spec_file;
102
103     my @spec_files = <{dlls/*/*.spec,dlls/*/*/*.spec}>;
104
105     foreach $spec_file (@spec_files) {
106         $spec_file =~ /(.*)\/.*\.spec/;
107
108         $allowed_dir = $1;
109
110         $$spec_file_found{$spec_file}++;
111         $$spec_file2dir{$spec_file}{$allowed_dir}++;
112         $$dir2spec_file{$allowed_dir}{$spec_file}++;
113     }
114
115     return $spec_file_found;
116 }
117
118 sub read_spec_files($$) {
119     my $self = shift;
120
121     my $spec_file_found = shift;
122
123     my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
124     my $spec_files16 = \@{$self->{SPEC_FILES16}};
125     my $spec_files32 = \@{$self->{SPEC_FILES32}};
126     my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
127     my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
128
129     my @spec_files;
130     if($wine_dir eq ".") {
131         @spec_files = get_spec_files("winelib");
132     } else {
133         my %spec_files = ();
134         foreach my $dir ($options->directories) {
135             $dir = "$current_dir/$dir";
136             $dir =~ s%/\.$%%;
137             foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
138                 $spec_files{$spec_file}++;
139             }
140         }
141         @spec_files = sort(keys(%spec_files));
142     }
143
144     @$spec_files16 = ();
145     @$spec_files32 = ();
146     foreach my $spec_file (@spec_files) {
147         (my $type, my $module) = get_spec_file_type("$wine_dir/$spec_file");
148
149         $$spec_file2module{$spec_file} = $module;
150         $$module2spec_file{$module} = $spec_file;
151
152         if($type eq "win16") {
153             push @$spec_files16, $spec_file;
154         } elsif($type eq "win32") {
155             push @$spec_files32, $spec_file;
156         } else {
157             $output->write("$spec_file: unknown type '$type'\n");
158         }
159     }
160
161     foreach my $spec_file (@spec_files) {
162         if(!$$spec_file_found{$spec_file} && $spec_file !~ m%tests/[^/]+$%) {
163             $output->write("modules: $spec_file: exists but is not specified\n");
164         }
165     }
166 }
167
168 sub new($) {
169     my $proto = shift;
170     my $class = ref($proto) || $proto;
171     my $self  = {};
172     bless ($self, $class);
173
174     my $spec_file_found = $self->find_spec_files();
175     $self->read_spec_files($spec_file_found);
176
177     return $self;
178 }
179
180 sub all_modules($) {
181     my $self = shift;
182
183     my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
184
185     return sort(keys(%$module2spec_file));
186 }
187
188 sub is_allowed_module($$) {
189     my $self = shift;
190
191     my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
192
193     my $module = shift;
194
195     return defined($$module2spec_file{$module});
196 }
197
198 sub is_allowed_module_in_file($$$) {
199     my $self = shift;
200
201     my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
202     my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
203
204     my $module = shift;
205     my $file = shift;
206     $file =~ s/^\.\///;
207
208     my $dir = $file;
209     $dir =~ s/\/[^\/]*$//;
210
211     if($dir =~ m%^include%) {
212         return 1;
213     }
214
215     foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
216         if($$spec_file2module{$spec_file} eq $module) {
217             return 1;
218         }
219     }
220
221     return 0;
222 }
223
224 sub allowed_modules_in_file($$) {
225     my $self = shift;
226
227     my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
228     my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
229
230     my $file = shift;
231     $file =~ s/^\.\///;
232
233     my $dir = $file;
234     $dir =~ s/\/[^\/]*$//;
235
236     my %allowed_modules = ();
237     foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
238         my $module = $$spec_file2module{$spec_file};
239         $allowed_modules{$module}++;
240     }
241
242     my $module = join(" & ", sort(keys(%allowed_modules)));
243
244     return $module;
245 }
246
247 sub allowed_dirs_for_module($$) {
248    my $self = shift;
249
250    my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
251    my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
252
253    my $module = shift;
254
255    my $spec_file = $$module2spec_file{$module};
256
257    return sort(keys(%{$$spec_file2dir{$spec_file}}));
258 }
259
260 sub allowed_spec_files16($) {
261     my $self = shift;
262
263     my $spec_files16 = \@{$self->{SPEC_FILES16}};
264
265     return @$spec_files16;
266 }
267
268 sub allowed_spec_files32($) {
269     my $self = shift;
270
271     my $spec_files32 = \@{$self->{SPEC_FILES32}};
272
273     return @$spec_files32;
274 }
275
276 sub found_module_in_dir($$$) {
277     my $self = shift;
278
279     my $module = shift;
280     my $dir = shift;
281
282     my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
283
284     $dir = "$current_dir/$dir";
285     $dir =~ s%/\.$%%;
286
287     $$used_module_dirs{$module}{$dir}++;
288 }
289
290 sub complete_modules($$) {
291     my $self = shift;
292
293     my $c_files = shift;
294
295     my %dirs;
296
297     foreach my $file (@$c_files) {
298         my $dir = file_directory("$current_dir/$file");
299         $dirs{$dir}++;
300     }
301
302     my @c_files = get_c_files("winelib");
303     @c_files = files_skip(@c_files);
304     foreach my $file (@c_files) {
305         my $dir = file_directory($file);
306         if(exists($dirs{$dir})) {
307             $dirs{$dir}--;
308         }
309     }
310
311     my @complete_modules = ();
312     foreach my $module ($self->all_modules) {
313         my $index = -1;
314         my @dirs = $self->allowed_dirs_for_module($module);
315         foreach my $dir (@dirs) {
316             if(exists($dirs{$dir}) && $dirs{$dir} == 0) {
317                 $index++;
318             }
319         }
320         if($index == $#dirs) {
321             push @complete_modules, $module;
322         }
323     }
324
325     return @complete_modules;
326 }
327
328 sub global_report($) {
329     my $self = shift;
330
331     my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
332     my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
333
334     my @messages;
335     foreach my $dir ($options->directories) {
336         $dir = "$current_dir/$dir";
337         $dir =~ s%/\.$%%;
338         foreach my $module ($self->all_modules) {
339             if(!$$used_module_dirs{$module}{$dir}) {
340                 my $spec_file = $$module2spec_file{$module};
341                 push @messages, "modules: $spec_file: directory ($dir) is not used\n";
342             }
343         }
344     }
345
346     foreach my $message (sort(@messages)) {
347         $output->write($message);
348     }
349 }
350
351 1;