blob: 895bd9193ed53b4d85d087f3a9e3495c10b4d6c7 [file] [log] [blame]
Patrik Stridvall37fd2d11999-09-23 15:14:20 +00001package winapi_options;
2
3use strict;
4
Patrik Stridvall37fd2d11999-09-23 15:14:20 +00005sub parser_comma_list {
6 my $prefix = shift;
7 my $value = shift;
8 if(defined($prefix) && $prefix eq "no") {
9 return { active => 0, filter => 0, hash => {} };
10 } elsif(defined($value)) {
11 my %names;
12 for my $name (split /,/, $value) {
13 $names{$name} = 1;
14 }
15 return { active => 1, filter => 1, hash => \%names };
16 } else {
17 return { active => 1, filter => 0, hash => {} };
18 }
19}
20
21my %options = (
22 "debug" => { default => 0, description => "debug mode" },
23 "help" => { default => 0, description => "help mode" },
24 "verbose" => { default => 0, description => "verbose mode" },
25
Patrik Stridvall5b3b6d91999-10-24 21:45:39 +000026 "progress" => { default => 1, description => "show progress" },
27
Patrik Stridvall37fd2d11999-09-23 15:14:20 +000028 "win16" => { default => 1, description => "Win16 checking" },
29 "win32" => { default => 1, description => "Win32 checking" },
30
31 "shared" => { default => 0, description => "show shared functions between Win16 and Win32" },
32 "shared-segmented" => { default => 0, description => "segmented shared functions between Win16 and Win32 checking" },
33
Patrik Stridvallc5f948c2000-07-15 21:32:55 +000034 "config" => { default => 1, parent => "local", description => "check configuration include consistancy" },
Patrik Stridvall5b3b6d91999-10-24 21:45:39 +000035 "config-unnessary" => { default => 0, parent => "config", description => "check for unnessary #include \"config.h\"" },
36
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +000037 "spec-mismatch" => { default => 0, description => "spec file mismatch checking" },
38
Patrik Stridvall37fd2d11999-09-23 15:14:20 +000039 "local" => { default => 1, description => "local checking" },
40 "module" => {
41 default => { active => 1, filter => 0, hash => {} },
42 parent => "local",
43 parser => \&parser_comma_list,
44 description => "module filter"
45 },
46
47 "argument" => { default => 1, parent => "local", description => "argument checking" },
48 "argument-count" => { default => 1, parent => "argument", description => "argument count checking" },
49 "argument-forbidden" => {
Patrik Stridvall5b3b6d91999-10-24 21:45:39 +000050 default => { active => 1, filter => 0, hash => {} },
Patrik Stridvall37fd2d11999-09-23 15:14:20 +000051 parent => "argument",
52 parser => \&parser_comma_list,
53 description => "argument forbidden checking"
54 },
55 "argument-kind" => {
Patrik Stridvall360c3f22000-06-11 20:02:29 +000056 default => { active => 1, filter => 1, hash => { double => 1 } },
Patrik Stridvall37fd2d11999-09-23 15:14:20 +000057 parent => "argument",
58 parser => \&parser_comma_list,
59 description => "argument kind checking"
60 },
Patrik Stridvalld18837b2000-06-07 02:11:42 +000061 "calling-convention" => { default => 1, parent => "local", description => "calling convention checking" },
62 "calling-convention-win16" => { default => 0, parent => "calling-convention", description => "calling convention checking (Win16)" },
63 "calling-convention-win32" => { default => 1, parent => "calling-convention", description => "calling convention checking (Win32)" },
Patrik Stridvall14bb7f12000-04-24 18:02:32 +000064 "misplaced" => { default => 1, parent => "local", description => "check for misplaced functions" },
Patrik Stridvallf93f9982000-05-11 21:46:17 +000065 "statements" => { default => 0, parent => "local", description => "check for statements inconsistances" },
Patrik Stridvall0d974812000-05-23 23:37:51 +000066 "cross-call" => { default => 0, parent => "statements", description => "check for cross calling functions" },
Patrik Stridvall5dadbf32000-04-29 14:24:11 +000067 "cross-call-win32-win16" => {
68 default => 0, parent => "cross-call", description => "check for cross calls between win32 and win16"
69 },
70 "cross-call-unicode-ascii" => {
71 default => 0, parent => "cross-call", description => "check for cross calls between Unicode and ASCII"
72 },
Patrik Stridvallf93f9982000-05-11 21:46:17 +000073 "debug-messages" => { default => 0, parent => "statements", description => "check for debug messages inconsistances" },
Patrik Stridvall6d529952000-03-28 19:29:13 +000074 "documentation" => { default => 1, parent => "local", description => "check for documentation inconsistances\n" },
Patrik Stridvalld7298192000-12-21 21:05:52 +000075 "documentation-pedantic" => { default => 0, parent => "documentation", description => "be pendantic when checking for documentation inconsistances\n" },
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +000076 "documentation-width" => { default => 0, parent => "documentation", description => "check for documentation width inconsistances\n" },
Patrik Stridvallfa29de72000-12-16 21:54:49 +000077 "documentation-arguments" => { default => 1, parent => "documentation", description => "check for arguments documentation inconsistances\n" },
Patrik Stridvalld7298192000-12-21 21:05:52 +000078 "documentation-ordinal" => { default => 0, parent => "documentation", description => "check for ordinal documentation inconsistances\n" },
Patrik Stridvall0d974812000-05-23 23:37:51 +000079 "prototype" => { default => 0, parent => ["local", "headers"], description => "prototype checking" },
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +000080
81 "global" => { default => 1, description => "global checking" },
Patrik Stridvall0d974812000-05-23 23:37:51 +000082 "declared" => { default => 1, parent => "global", description => "declared checking" },
Patrik Stridvalld7298192000-12-21 21:05:52 +000083 "implemented" => { default => 0, parent => "local", description => "implemented checking" },
Patrik Stridvall5b3b6d91999-10-24 21:45:39 +000084 "implemented-win32" => { default => 0, parent => "implemented", description => "implemented as win32 checking" },
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +000085 "include" => { default => 1, parent => "global", description => "include checking" },
86 "headers" => { default => 0, parent => "global", description => "headers checking" },
Patrik Stridvall0d974812000-05-23 23:37:51 +000087 "headers-duplicated" => { default => 0, parent => "headers", description => "duplicated function declarations checking" },
88 "headers-misplaced" => { default => 0, parent => "headers", description => "misplaced function declarations checking" },
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +000089 "stubs" => { default => 0, parent => "global", description => "stubs checking" }
Patrik Stridvall37fd2d11999-09-23 15:14:20 +000090);
91
92my %short_options = (
93 "d" => "debug",
94 "?" => "help",
95 "v" => "verbose"
96);
97
98sub new {
99 my $proto = shift;
100 my $class = ref($proto) || $proto;
101 my $self = {};
102 bless ($self, $class);
103
Patrik Stridvall5dadbf32000-04-29 14:24:11 +0000104 my $output = \${$self->{OUTPUT}};
105
106 $$output = shift;
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000107 my $refarguments = shift;
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +0000108 my $wine_dir = shift;
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000109
Patrik Stridvall1932d402000-04-15 20:39:55 +0000110 $self->options_set("default");
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000111
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +0000112 my $c_files = \@{$self->{C_FILES}};
113 my $h_files = \@{$self->{H_FILES}};
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000114 my $module = \${$self->{MODULE}};
115 my $global = \${$self->{GLOBAL}};
116
Patrik Stridvall0d974812000-05-23 23:37:51 +0000117 my @files;
118
Patrik Stridvall5dadbf32000-04-29 14:24:11 +0000119 if($wine_dir eq ".") {
120 $$global = 1;
121 } else {
122 $$global = 0;
123 }
124
125 while(defined($_ = shift @$refarguments)) {
Patrik Stridvall1932d402000-04-15 20:39:55 +0000126 if(/^--(all|none)$/) {
127 $self->options_set("$1");
128 next;
129 } elsif(/^-([^=]*)(=(.*))?$/) {
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000130 my $name;
131 my $value;
132 if(defined($2)) {
133 $name = $1;
134 $value = $3;
135 } else {
136 $name = $1;
137 }
138
139 if($name =~ /^([^-].*)$/) {
140 $name = $short_options{$1};
141 } else {
142 $name =~ s/^-(.*)$/$1/;
143 }
144
145 my $prefix;
Patrik Stridvall1932d402000-04-15 20:39:55 +0000146 if(defined($name) && $name =~ /^no-(.*)$/) {
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000147 $name = $1;
148 $prefix = "no";
149 if(defined($value)) {
Patrik Stridvall5dadbf32000-04-29 14:24:11 +0000150 $$output->write("options with prefix 'no' can't take parameters\n");
151
152 return undef;
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000153 }
154 }
155
Patrik Stridvall1932d402000-04-15 20:39:55 +0000156 my $option;
157 if(defined($name)) {
158 $option = $options{$name};
159 }
160
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000161 if(defined($option)) {
162 my $key = $$option{key};
163 my $parser = $$option{parser};
164 my $refvalue = \${$self->{$key}};
Patrik Stridvall0d974812000-05-23 23:37:51 +0000165 my @parents = ();
166
167 if(defined($$option{parent})) {
168 if(ref($$option{parent}) eq "ARRAY") {
169 @parents = @{$$option{parent}};
170 } else {
171 @parents = $$option{parent};
172 }
173 }
Patrik Stridvall1932d402000-04-15 20:39:55 +0000174
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000175 if(defined($parser)) {
176 $$refvalue = &$parser($prefix,$value);
177 } else {
178 if(defined($value)) {
179 $$refvalue = $value;
180 } elsif(!defined($prefix)) {
181 $$refvalue = 1;
182 } else {
183 $$refvalue = 0;
184 }
185 }
Patrik Stridvall1932d402000-04-15 20:39:55 +0000186
187 if((ref($$refvalue) eq "HASH" && $$refvalue->{active}) || $$refvalue) {
Patrik Stridvall0d974812000-05-23 23:37:51 +0000188 while($#parents >= 0) {
189 my @old_parents = @parents;
190 @parents = ();
191 foreach my $parent (@old_parents) {
192 my $parentkey = $options{$parent}{key};
193 my $refparentvalue = \${$self->{$parentkey}};
194
195 $$refparentvalue = 1;
196
197 if(defined($options{$parent}{parent})) {
198 if(ref($options{$parent}{parent}) eq "ARRAY") {
199 push @parents, @{$options{$parent}{parent}};
200 } else {
201 push @parents, $options{$parent}{parent};
202 }
203 }
204 }
Patrik Stridvall1932d402000-04-15 20:39:55 +0000205 }
206 }
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000207 next;
208 }
209 }
210
211 if(/^--module-dlls$/) {
Patrik Stridvall1932d402000-04-15 20:39:55 +0000212 my @dirs = `cd dlls && find . -type d ! -name CVS`;
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000213 my %names;
214 for my $dir (@dirs) {
215 chomp $dir;
216 $dir =~ s/^\.\/(.*)$/$1/;
217 next if $dir eq "";
218 $names{$dir} = 1;
219 }
220 $$module = { active => 1, filter => 1, hash => \%names };
221 }
222 elsif(/^-(.*)$/) {
Patrik Stridvall5dadbf32000-04-29 14:24:11 +0000223 $$output->write("unknown option: $_\n");
224
225 return undef;
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000226 } else {
Patrik Stridvall5dadbf32000-04-29 14:24:11 +0000227 if(!-e $_) {
228 $$output->write("$_: no such file or directory\n");
229
230 return undef;
231 }
232
Patrik Stridvall0d974812000-05-23 23:37:51 +0000233 push @files, $_;
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000234 }
235 }
236
Patrik Stridvall54e15522000-05-18 00:07:31 +0000237 if($self->help) {
238 return $self;
239 }
240
Patrik Stridvall0d974812000-05-23 23:37:51 +0000241 my @paths = ();
242 my @c_files = ();
243 my @h_files = ();
244 foreach my $file (@files) {
245 if($file =~ /\.c$/) {
246 push @c_files, $file;
247 } elsif($file =~ /\.h$/) {
248 push @h_files, $file;
249 } else {
250 push @paths, $file;
251 }
252 }
253
254 if($#c_files == -1 && $#h_files == -1 &&
255 ($#paths == -1 || ($#paths == 0 && $paths[0] eq $wine_dir)))
256 {
257 @paths = ".";
258 push @h_files, "$wine_dir/include";
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000259 } else {
Patrik Stridvall1932d402000-04-15 20:39:55 +0000260 $$global = 0;
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000261 }
Patrik Stridvallafe3b0c1999-09-29 10:22:00 +0000262
Patrik Stridvall0d974812000-05-23 23:37:51 +0000263 if($#paths != -1 || $#c_files != -1) {
264 my $c_command = "find " . join(" ", @paths, @c_files) . " -name \\*.c";
265 my %found;
266 @$c_files = sort(map {
267 s/^\.\/(.*)$/$1/;
268 if(defined($found{$_}) || /glue\.c|spec\.c$/) {
269 ();
270 } else {
271 $found{$_}++;
272 $_;
273 }
274 } split(/\n/, `$c_command`));
275 }
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +0000276
Patrik Stridvall0d974812000-05-23 23:37:51 +0000277 if($#h_files != -1) {
278 my $h_command = "find " . join(" ", @h_files) . " -name \\*.h";
279 my %found;
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +0000280
Patrik Stridvall0d974812000-05-23 23:37:51 +0000281 @$h_files = sort(map {
282 s/^\.\/(.*)$/$1/;
283 if(defined($found{$_})) {
284 ();
285 } else {
286 $found{$_}++;
287 $_;
288 }
289 } split(/\n/, `$h_command`));
290 }
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000291 return $self;
292}
293
Patrik Stridvall94a50772000-12-01 23:51:33 +0000294sub DESTROY {
295}
296
Patrik Stridvall1932d402000-04-15 20:39:55 +0000297sub options_set {
298 my $self = shift;
299
300 local $_ = shift;
301 for my $name (sort(keys(%options))) {
302 my $option = $options{$name};
303 my $key = uc($name);
304 $key =~ tr/-/_/;
305 $$option{key} = $key;
306 my $refvalue = \${$self->{$key}};
307
308 if(/^default$/) {
309 $$refvalue = $$option{default};
310 } elsif(/^all$/) {
311 if($name !~ /^help|debug|verbose|module$/) {
312 if(ref($$refvalue) ne "HASH") {
313 $$refvalue = 1;
314 } else {
315 $$refvalue = { active => 1, filter => 0, hash => {} };
316 }
317 }
318 } elsif(/^none$/) {
319 if($name !~ /^help|debug|verbose|module$/) {
320 if(ref($$refvalue) ne "HASH") {
321 $$refvalue = 0;
322 } else {
323 $$refvalue = { active => 0, filter => 0, hash => {} };
324 }
325 }
326 }
327 }
328}
329
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000330sub show_help {
331 my $self = shift;
332
333 my $maxname = 0;
334 for my $name (sort(keys(%options))) {
335 if(length($name) > $maxname) {
336 $maxname = length($name);
337 }
338 }
339
340 print "usage: winapi-check [--help] [<files>]\n";
341 print "\n";
342 for my $name (sort(keys(%options))) {
343 my $option = $options{$name};
344 my $description = $$option{description};
345 my $default = $$option{default};
Patrik Stridvall1932d402000-04-15 20:39:55 +0000346 my $current = ${$self->{$$option{key}}};
347
348 my $value = $current;
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000349
350 my $output;
Patrik Stridvall1932d402000-04-15 20:39:55 +0000351 if(ref($value) ne "HASH") {
352 if($value) {
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000353 $output = "--no-$name";
354 } else {
355 $output = "--$name";
356 }
357 } else {
Patrik Stridvall1932d402000-04-15 20:39:55 +0000358 if($value->{active}) {
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000359 $output = "--[no-]$name\[=<value>]";
360 } else {
361 $output = "--$name\[=<value>]";
362 }
363 }
364
365 print "$output";
Patrik Stridvall1932d402000-04-15 20:39:55 +0000366 for (0..(($maxname - length($name) + 17) - (length($output) - length($name) + 1))) { print " "; }
367 if(ref($value) ne "HASH") {
368 if($value) {
369 print "Disable ";
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000370 } else {
Patrik Stridvall1932d402000-04-15 20:39:55 +0000371 print "Enable ";
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000372 }
373 } else {
Patrik Stridvall1932d402000-04-15 20:39:55 +0000374 if($value->{active}) {
375 print "(Disable) ";
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000376 } else {
Patrik Stridvall1932d402000-04-15 20:39:55 +0000377 print "Enable ";
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000378 }
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000379 }
Patrik Stridvall1932d402000-04-15 20:39:55 +0000380 if($default == $current) {
381 print "$description (default)\n";
382 } else {
383 print "$description\n";
384 }
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000385 }
386}
387
388sub AUTOLOAD {
389 my $self = shift;
390
391 my $name = $winapi_options::AUTOLOAD;
392 $name =~ s/^.*::(.[^:]*)$/\U$1/;
393
394 my $refvalue = $self->{$name};
395 if(!defined($refvalue)) {
396 die "<internal>: winapi_options.pm: member $name does not exists\n";
397 }
Patrik Stridvall1932d402000-04-15 20:39:55 +0000398
399 if(ref($$refvalue) ne "HASH") {
400 return $$refvalue;
401 } else {
402 return $$refvalue->{active};
403 }
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000404}
405
Patrik Stridvall6a4e8a52000-04-06 20:11:04 +0000406sub c_files { my $self = shift; return @{$self->{C_FILES}}; }
407
408sub h_files { my $self = shift; return @{$self->{H_FILES}}; }
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000409
410sub report_module {
411 my $self = shift;
Patrik Stridvall1932d402000-04-15 20:39:55 +0000412 my $refvalue = $self->{MODULE};
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000413
414 my $name = shift;
415
416 if(defined($name)) {
Patrik Stridvall1932d402000-04-15 20:39:55 +0000417 return $$refvalue->{active} && (!$$refvalue->{filter} || $$refvalue->{hash}->{$name});
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000418 } else {
419 return 0;
420 }
421}
422
423sub report_argument_forbidden {
424 my $self = shift;
Patrik Stridvall1932d402000-04-15 20:39:55 +0000425 my $refargument_forbidden = $self->{ARGUMENT_FORBIDDEN};
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000426
427 my $type = shift;
428
Patrik Stridvall1932d402000-04-15 20:39:55 +0000429 return $$refargument_forbidden->{active} && (!$$refargument_forbidden->{filter} || $$refargument_forbidden->{hash}->{$type});
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000430}
431
432sub report_argument_kind {
433 my $self = shift;
Patrik Stridvall1932d402000-04-15 20:39:55 +0000434 my $refargument_kind = $self->{ARGUMENT_KIND};
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000435
436 my $kind = shift;
437
Patrik Stridvall1932d402000-04-15 20:39:55 +0000438 return $$refargument_kind->{active} && (!$$refargument_kind->{filter} || $$refargument_kind->{hash}->{$kind});
Patrik Stridvall37fd2d11999-09-23 15:14:20 +0000439
440}
441
4421;
443