- Minor API files update.
[wine.git] / tools / winapi_check / winapi_options.pm
blob1f15aebd7561825470b451eef208130b2b5eb661
1 package winapi_options;
3 use strict;
5 sub 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;
15 return { active => 1, filter => 1, hash => \%names };
16 } else {
17 return { active => 1, filter => 0, hash => {} };
21 my %options = (
22 "debug" => { default => 0, description => "debug mode" },
23 "help" => { default => 0, description => "help mode" },
24 "verbose" => { default => 0, description => "verbose mode" },
26 "progress" => { default => 1, description => "show progress" },
28 "win16" => { default => 1, description => "Win16 checking" },
29 "win32" => { default => 1, description => "Win32 checking" },
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" },
34 "config" => { default => 1, description => "check configuration include consistancy" },
35 "config-unnessary" => { default => 0, parent => "config", description => "check for unnessary #include \"config.h\"" },
37 "spec-mismatch" => { default => 0, description => "spec file mismatch checking" },
39 "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"
47 "argument" => { default => 1, parent => "local", description => "argument checking" },
48 "argument-count" => { default => 1, parent => "argument", description => "argument count checking" },
49 "argument-forbidden" => {
50 default => { active => 1, filter => 0, hash => {} },
51 parent => "argument",
52 parser => \&parser_comma_list,
53 description => "argument forbidden checking"
55 "argument-kind" => {
56 default => { active => 0, filter => 0, hash => {} },
57 parent => "argument",
58 parser => \&parser_comma_list,
59 description => "argument kind checking"
61 "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)" },
64 "misplaced" => { default => 1, parent => "local", description => "check for misplaced functions" },
65 "statements" => { default => 0, parent => "local", description => "check for statements inconsistances" },
66 "cross-call" => { default => 0, parent => "statements", description => "check for cross calling functions" },
67 "cross-call-win32-win16" => {
68 default => 0, parent => "cross-call", description => "check for cross calls between win32 and win16"
70 "cross-call-unicode-ascii" => {
71 default => 0, parent => "cross-call", description => "check for cross calls between Unicode and ASCII"
73 "debug-messages" => { default => 0, parent => "statements", description => "check for debug messages inconsistances" },
74 "documentation" => { default => 1, parent => "local", description => "check for documentation inconsistances\n" },
75 "documentation-width" => { default => 0, parent => "documentation", description => "check for documentation width inconsistances\n" },
76 "prototype" => { default => 0, parent => ["local", "headers"], description => "prototype checking" },
78 "global" => { default => 1, description => "global checking" },
79 "declared" => { default => 1, parent => "global", description => "declared checking" },
80 "implemented" => { default => 1, parent => "global", description => "implemented checking" },
81 "implemented-win32" => { default => 0, parent => "implemented", description => "implemented as win32 checking" },
82 "include" => { default => 1, parent => "global", description => "include checking" },
83 "headers" => { default => 0, parent => "global", description => "headers checking" },
84 "headers-duplicated" => { default => 0, parent => "headers", description => "duplicated function declarations checking" },
85 "headers-misplaced" => { default => 0, parent => "headers", description => "misplaced function declarations checking" },
86 "stubs" => { default => 0, parent => "global", description => "stubs checking" }
89 my %short_options = (
90 "d" => "debug",
91 "?" => "help",
92 "v" => "verbose"
95 sub new {
96 my $proto = shift;
97 my $class = ref($proto) || $proto;
98 my $self = {};
99 bless ($self, $class);
101 my $output = \${$self->{OUTPUT}};
103 $$output = shift;
104 my $refarguments = shift;
105 my $wine_dir = shift;
107 $self->options_set("default");
109 my $c_files = \@{$self->{C_FILES}};
110 my $h_files = \@{$self->{H_FILES}};
111 my $module = \${$self->{MODULE}};
112 my $global = \${$self->{GLOBAL}};
114 my @files;
116 if($wine_dir eq ".") {
117 $$global = 1;
118 } else {
119 $$global = 0;
122 while(defined($_ = shift @$refarguments)) {
123 if(/^--(all|none)$/) {
124 $self->options_set("$1");
125 next;
126 } elsif(/^-([^=]*)(=(.*))?$/) {
127 my $name;
128 my $value;
129 if(defined($2)) {
130 $name = $1;
131 $value = $3;
132 } else {
133 $name = $1;
136 if($name =~ /^([^-].*)$/) {
137 $name = $short_options{$1};
138 } else {
139 $name =~ s/^-(.*)$/$1/;
142 my $prefix;
143 if(defined($name) && $name =~ /^no-(.*)$/) {
144 $name = $1;
145 $prefix = "no";
146 if(defined($value)) {
147 $$output->write("options with prefix 'no' can't take parameters\n");
149 return undef;
153 my $option;
154 if(defined($name)) {
155 $option = $options{$name};
158 if(defined($option)) {
159 my $key = $$option{key};
160 my $parser = $$option{parser};
161 my $refvalue = \${$self->{$key}};
162 my @parents = ();
164 if(defined($$option{parent})) {
165 if(ref($$option{parent}) eq "ARRAY") {
166 @parents = @{$$option{parent}};
167 } else {
168 @parents = $$option{parent};
172 if(defined($parser)) {
173 $$refvalue = &$parser($prefix,$value);
174 } else {
175 if(defined($value)) {
176 $$refvalue = $value;
177 } elsif(!defined($prefix)) {
178 $$refvalue = 1;
179 } else {
180 $$refvalue = 0;
184 if((ref($$refvalue) eq "HASH" && $$refvalue->{active}) || $$refvalue) {
185 while($#parents >= 0) {
186 my @old_parents = @parents;
187 @parents = ();
188 foreach my $parent (@old_parents) {
189 my $parentkey = $options{$parent}{key};
190 my $refparentvalue = \${$self->{$parentkey}};
192 $$refparentvalue = 1;
194 if(defined($options{$parent}{parent})) {
195 if(ref($options{$parent}{parent}) eq "ARRAY") {
196 push @parents, @{$options{$parent}{parent}};
197 } else {
198 push @parents, $options{$parent}{parent};
204 next;
208 if(/^--module-dlls$/) {
209 my @dirs = `cd dlls && find . -type d ! -name CVS`;
210 my %names;
211 for my $dir (@dirs) {
212 chomp $dir;
213 $dir =~ s/^\.\/(.*)$/$1/;
214 next if $dir eq "";
215 $names{$dir} = 1;
217 $$module = { active => 1, filter => 1, hash => \%names };
219 elsif(/^-(.*)$/) {
220 $$output->write("unknown option: $_\n");
222 return undef;
223 } else {
224 if(!-e $_) {
225 $$output->write("$_: no such file or directory\n");
227 return undef;
230 push @files, $_;
234 if($self->help) {
235 return $self;
238 my @paths = ();
239 my @c_files = ();
240 my @h_files = ();
241 foreach my $file (@files) {
242 if($file =~ /\.c$/) {
243 push @c_files, $file;
244 } elsif($file =~ /\.h$/) {
245 push @h_files, $file;
246 } else {
247 push @paths, $file;
251 if($#c_files == -1 && $#h_files == -1 &&
252 ($#paths == -1 || ($#paths == 0 && $paths[0] eq $wine_dir)))
254 @paths = ".";
255 push @h_files, "$wine_dir/include";
256 } else {
257 $$global = 0;
260 if($#paths != -1 || $#c_files != -1) {
261 my $c_command = "find " . join(" ", @paths, @c_files) . " -name \\*.c";
262 my %found;
263 @$c_files = sort(map {
264 s/^\.\/(.*)$/$1/;
265 if(defined($found{$_}) || /glue\.c|spec\.c$/) {
267 } else {
268 $found{$_}++;
271 } split(/\n/, `$c_command`));
274 if($#h_files != -1) {
275 my $h_command = "find " . join(" ", @h_files) . " -name \\*.h";
276 my %found;
278 @$h_files = sort(map {
279 s/^\.\/(.*)$/$1/;
280 if(defined($found{$_})) {
282 } else {
283 $found{$_}++;
286 } split(/\n/, `$h_command`));
288 return $self;
291 sub options_set {
292 my $self = shift;
294 local $_ = shift;
295 for my $name (sort(keys(%options))) {
296 my $option = $options{$name};
297 my $key = uc($name);
298 $key =~ tr/-/_/;
299 $$option{key} = $key;
300 my $refvalue = \${$self->{$key}};
302 if(/^default$/) {
303 $$refvalue = $$option{default};
304 } elsif(/^all$/) {
305 if($name !~ /^help|debug|verbose|module$/) {
306 if(ref($$refvalue) ne "HASH") {
307 $$refvalue = 1;
308 } else {
309 $$refvalue = { active => 1, filter => 0, hash => {} };
312 } elsif(/^none$/) {
313 if($name !~ /^help|debug|verbose|module$/) {
314 if(ref($$refvalue) ne "HASH") {
315 $$refvalue = 0;
316 } else {
317 $$refvalue = { active => 0, filter => 0, hash => {} };
324 sub show_help {
325 my $self = shift;
327 my $maxname = 0;
328 for my $name (sort(keys(%options))) {
329 if(length($name) > $maxname) {
330 $maxname = length($name);
334 print "usage: winapi-check [--help] [<files>]\n";
335 print "\n";
336 for my $name (sort(keys(%options))) {
337 my $option = $options{$name};
338 my $description = $$option{description};
339 my $default = $$option{default};
340 my $current = ${$self->{$$option{key}}};
342 my $value = $current;
344 my $output;
345 if(ref($value) ne "HASH") {
346 if($value) {
347 $output = "--no-$name";
348 } else {
349 $output = "--$name";
351 } else {
352 if($value->{active}) {
353 $output = "--[no-]$name\[=<value>]";
354 } else {
355 $output = "--$name\[=<value>]";
359 print "$output";
360 for (0..(($maxname - length($name) + 17) - (length($output) - length($name) + 1))) { print " "; }
361 if(ref($value) ne "HASH") {
362 if($value) {
363 print "Disable ";
364 } else {
365 print "Enable ";
367 } else {
368 if($value->{active}) {
369 print "(Disable) ";
370 } else {
371 print "Enable ";
374 if($default == $current) {
375 print "$description (default)\n";
376 } else {
377 print "$description\n";
382 sub AUTOLOAD {
383 my $self = shift;
385 my $name = $winapi_options::AUTOLOAD;
386 $name =~ s/^.*::(.[^:]*)$/\U$1/;
388 my $refvalue = $self->{$name};
389 if(!defined($refvalue)) {
390 die "<internal>: winapi_options.pm: member $name does not exists\n";
393 if(ref($$refvalue) ne "HASH") {
394 return $$refvalue;
395 } else {
396 return $$refvalue->{active};
400 sub c_files { my $self = shift; return @{$self->{C_FILES}}; }
402 sub h_files { my $self = shift; return @{$self->{H_FILES}}; }
404 sub report_module {
405 my $self = shift;
406 my $refvalue = $self->{MODULE};
408 my $name = shift;
410 if(defined($name)) {
411 return $$refvalue->{active} && (!$$refvalue->{filter} || $$refvalue->{hash}->{$name});
412 } else {
413 return 0;
417 sub report_argument_forbidden {
418 my $self = shift;
419 my $refargument_forbidden = $self->{ARGUMENT_FORBIDDEN};
421 my $type = shift;
423 return $$refargument_forbidden->{active} && (!$$refargument_forbidden->{filter} || $$refargument_forbidden->{hash}->{$type});
426 sub report_argument_kind {
427 my $self = shift;
428 my $refargument_kind = $self->{ARGUMENT_KIND};
430 my $kind = shift;
432 return $$refargument_kind->{active} && (!$$refargument_kind->{filter} || $$refargument_kind->{hash}->{$kind});