Added an unknown VxD error code.
[wine] / tools / winapi_check / modules.pm
1 package modules;
2
3 use strict;
4
5 sub new {
6     my $proto = shift;
7     my $class = ref($proto) || $proto;
8     my $self  = {};
9     bless ($self, $class);
10
11     my $options = \${$self->{OPTIONS}};
12     my $output = \${$self->{OUTPUT}};
13     my $spec_files = \%{$self->{SPEC_FILES}};
14     my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
15
16     $$options = shift;
17     $$output = shift;
18     my $wine_dir = shift;
19     my $current_dir = shift;
20     my $file_type = shift;    
21     my $module_file = shift;
22
23     $module_file =~ s/^\.\///;
24
25     my @all_spec_files = map {
26         s/^.\/(.*)$/$1/;
27         if(&$file_type($_) eq "library") {
28             $_;
29         } else {
30             ();
31         }
32     } split(/\n/, `find $wine_dir -name \\*.spec`);
33
34     my %all_spec_files;
35     foreach my $file (@all_spec_files) {
36         $all_spec_files{$file}++ ;
37     }
38
39     if($$options->progress) {
40         $$output->progress("modules.dat");
41     }
42
43     my $allowed_dir;
44     my $spec_file;
45
46     open(IN, "< $module_file");
47     local $/ = "\n";
48     while(<IN>) {
49         s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begining and end of line
50         s/^(.*?)\s*#.*$/$1/;  # remove comments
51         /^$/ && next;         # skip empty lines
52
53         if(/^%\s+(.*?)$/) {
54             $spec_file = $1;
55            
56             if(!-f "$wine_dir/$spec_file") {
57                 $$output->write("modules.dat: $spec_file: file ($spec_file) doesn't exist or is no file\n");
58             } 
59
60             if($wine_dir eq ".") {
61                 $all_spec_files{$spec_file}--;
62             } else {
63                 $all_spec_files{"$wine_dir/$spec_file"}--;
64             }
65             $$spec_files{""}{$spec_file}++; # FIXME: Kludge
66             next;
67         } else {
68             $allowed_dir = $1;
69         }
70         $$spec_files{$allowed_dir}{$spec_file}++;
71
72         if(!-d "$wine_dir/$allowed_dir") {
73             $$output->write("modules.dat: $spec_file: directory ($allowed_dir) doesn't exist or is no directory\n");
74         } 
75     }
76     close(IN);
77
78     foreach my $spec_file (sort(keys(%all_spec_files))) {
79         if($all_spec_files{$spec_file} > 0) {
80             $$output->write("modules.dat: $spec_file: exists but is not specified\n");
81         }
82     }
83
84     return $self;
85 }
86
87 sub spec_file_module {
88     my $self = shift;
89
90     my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
91     my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
92
93     my $spec_file = shift;
94     $spec_file =~ s/^\.\///;
95
96     my $module = shift;
97   
98     $$spec_file2module{$spec_file}{$module}++;
99     $$module2spec_file{$module}{$spec_file}++;
100 }
101
102 sub is_allowed_module_in_file {
103     my $self = shift;
104
105     my $spec_files = \%{$self->{SPEC_FILES}};
106     my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
107
108     my $module = shift;
109     my $file = shift;
110     $file =~ s/^\.\///;
111
112     my $dir = $file;
113     $dir =~ s/\/[^\/]*$//;
114
115     foreach my $spec_file (sort(keys(%{$$spec_files{$dir}}))) {
116         if($$spec_file2module{$spec_file}{$module}) {
117             return 1;
118         }
119     }
120
121     return 0;
122 }
123
124 sub allowed_modules_in_file {
125     my $self = shift;
126
127     my $spec_files = \%{$self->{SPEC_FILES}};
128     my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
129
130     my $file = shift;
131     $file =~ s/^\.\///;
132
133     my $dir = $file;
134     $dir =~ s/\/[^\/]*$//;
135
136     my %allowed_modules = ();
137     foreach my $spec_file (sort(keys(%{$$spec_files{$dir}}))) {
138         foreach my $module (sort(keys(%{$$spec_file2module{$spec_file}}))) {
139             $allowed_modules{$module}++;
140         }
141     }
142
143     return join(" & ", sort(keys(%allowed_modules)));
144 }
145
146 sub allowed_spec_files {
147     my $self = shift;
148
149     my $options = \${$self->{OPTIONS}};
150     my $output = \${$self->{OUTPUT}};
151     my $spec_files = \%{$self->{SPEC_FILES}};
152
153     my $wine_dir = shift;
154     my $current_dir = shift;
155
156     my @dirs = map {
157         s/^\.\/(.*)$/$1/;
158         if(/^\.$/) {
159             $current_dir;
160         } else {
161             if($current_dir ne ".") {
162                 "$current_dir/$_";
163             } else {
164                 $_;
165             }
166         }
167     } split(/\n/, `find . -type d ! -name CVS`);
168
169     my %allowed_spec_files = ();
170     foreach my $dir (sort(@dirs)) {
171         foreach my $spec_file (sort(keys(%{$$spec_files{$dir}}))) {
172             $allowed_spec_files{$spec_file}++; 
173         }
174     }
175
176     return sort(keys(%allowed_spec_files));
177 }
178
179 sub found_module_in_dir {
180     my $self = shift;
181
182     my $module = shift;
183     my $dir = shift;
184
185     my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
186
187     $$used_module_dirs{$module}{$dir}++;
188 }
189
190 sub global_report {
191     my $self = shift;
192
193     my $output = \${$self->{OUTPUT}};
194     my $spec_files = \%{$self->{SPEC_FILES}};
195     my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
196     my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
197
198     my @messages;
199     foreach my $dir (sort(keys(%$spec_files))) {
200         if($dir eq "") { next; }
201         foreach my $spec_file (sort(keys(%{$$spec_files{$dir}}))) {
202             foreach my $module (sort(keys(%{$$spec_file2module{$spec_file}}))) {
203                 if(!$$used_module_dirs{$module}{$dir}) {
204                     push @messages, "modules.dat: $spec_file: directory ($dir) is not used\n";
205                 }
206             }
207         }
208     }
209
210     foreach my $message (sort(@messages)) {
211         $$output->write($message);
212     }
213 }
214
215 1;