1 package winapi_options;
5 sub parser_comma_list {
8 if(defined($prefix) && $prefix eq "no") {
9 return { active => 0, filter => 0, hash => {} };
10 } elsif(defined($value)) {
12 for my $name (split /,/, $value) {
15 return { active => 1, filter => 1, hash => \%names };
17 return { active => 1, filter => 0, hash => {} };
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, parent => "local", 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" },
41 default => { active => 1, filter => 0, hash => {} },
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 => {} },
52 parser => \&parser_comma_list,
53 description => "argument forbidden checking"
56 default => { active => 1, filter => 1, hash => { double => 1 } },
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" },
78 description => "check for documentation inconsistances"
80 "documentation-pedantic" => {
82 parent => "documentation",
83 description => "be pendantic when checking for documentation inconsistances"
86 "documentation-arguments" => {
88 parent => "documentation",
89 description => "check for arguments documentation inconsistances\n"
91 "documentation-comment-indent" => {
93 parent => "documentation", description => "check for documentation comment indent inconsistances"
95 "documentation-comment-width" => {
97 parent => "documentation", description => "check for documentation comment width inconsistances"
99 "documentation-name" => {
101 parent => "documentation",
102 description => "check for documentation name inconsistances\n"
104 "documentation-ordinal" => {
106 parent => "documentation",
107 description => "check for documentation ordinal inconsistances\n"
109 "documentation-wrong" => {
111 parent => "documentation",
112 description => "check for wrong documentation\n"
115 "prototype" => {default => 0, parent => ["local", "headers"], description => "prototype checking" },
116 "global" => { default => 1, description => "global checking" },
117 "declared" => { default => 1, parent => "global", description => "declared checking" },
118 "implemented" => { default => 0, parent => "local", description => "implemented checking" },
119 "implemented-win32" => { default => 0, parent => "implemented", description => "implemented as win32 checking" },
120 "include" => { default => 1, parent => "global", description => "include checking" },
121 "headers" => { default => 0, parent => "global", description => "headers checking" },
122 "headers-duplicated" => { default => 0, parent => "headers", description => "duplicated function declarations checking" },
123 "headers-misplaced" => { default => 0, parent => "headers", description => "misplaced function declarations checking" },
124 "stubs" => { default => 0, parent => "global", description => "stubs checking" }
127 my %short_options = (
135 my $class = ref($proto) || $proto;
137 bless ($self, $class);
139 my $output = \${$self->{OUTPUT}};
142 my $refarguments = shift;
143 my $wine_dir = shift;
145 $self->options_set("default");
147 my $c_files = \@{$self->{C_FILES}};
148 my $h_files = \@{$self->{H_FILES}};
149 my $module = \${$self->{MODULE}};
150 my $global = \${$self->{GLOBAL}};
154 if($wine_dir eq ".") {
160 while(defined($_ = shift @$refarguments)) {
161 if(/^--(all|none)$/) {
162 $self->options_set("$1");
164 } elsif(/^-([^=]*)(=(.*))?$/) {
174 if($name =~ /^([^-].*)$/) {
175 $name = $short_options{$1};
177 $name =~ s/^-(.*)$/$1/;
181 if(defined($name) && $name =~ /^no-(.*)$/) {
184 if(defined($value)) {
185 $$output->write("options with prefix 'no' can't take parameters\n");
193 $option = $options{$name};
196 if(defined($option)) {
197 my $key = $$option{key};
198 my $parser = $$option{parser};
199 my $refvalue = \${$self->{$key}};
202 if(defined($$option{parent})) {
203 if(ref($$option{parent}) eq "ARRAY") {
204 @parents = @{$$option{parent}};
206 @parents = $$option{parent};
210 if(defined($parser)) {
211 $$refvalue = &$parser($prefix,$value);
213 if(defined($value)) {
215 } elsif(!defined($prefix)) {
222 if((ref($$refvalue) eq "HASH" && $$refvalue->{active}) || $$refvalue) {
223 while($#parents >= 0) {
224 my @old_parents = @parents;
226 foreach my $parent (@old_parents) {
227 my $parentkey = $options{$parent}{key};
228 my $refparentvalue = \${$self->{$parentkey}};
230 $$refparentvalue = 1;
232 if(defined($options{$parent}{parent})) {
233 if(ref($options{$parent}{parent}) eq "ARRAY") {
234 push @parents, @{$options{$parent}{parent}};
236 push @parents, $options{$parent}{parent};
246 if(/^--module-dlls$/) {
247 my @dirs = `cd dlls && find . -type d ! -name CVS`;
249 for my $dir (@dirs) {
251 $dir =~ s/^\.\/(.*)$/$1/;
255 $$module = { active => 1, filter => 1, hash => \%names };
258 $$output->write("unknown option: $_\n");
263 $$output->write("$_: no such file or directory\n");
279 foreach my $file (@files) {
280 if($file =~ /\.c$/) {
281 push @c_files, $file;
282 } elsif($file =~ /\.h$/) {
283 push @h_files, $file;
289 if($#c_files == -1 && $#h_files == -1 &&
290 ($#paths == -1 || ($#paths == 0 && $paths[0] eq $wine_dir)))
293 push @h_files, "$wine_dir/include";
298 if($#paths != -1 || $#c_files != -1) {
299 my $c_command = "find " . join(" ", @paths, @c_files) . " -name \\*.c";
301 @$c_files = sort(map {
303 if(defined($found{$_}) || /glue\.c|spec\.c$/) {
309 } split(/\n/, `$c_command`));
312 if($#h_files != -1) {
313 my $h_command = "find " . join(" ", @h_files) . " -name \\*.h";
316 @$h_files = sort(map {
318 if(defined($found{$_})) {
324 } split(/\n/, `$h_command`));
336 for my $name (sort(keys(%options))) {
337 my $option = $options{$name};
340 $$option{key} = $key;
341 my $refvalue = \${$self->{$key}};
344 $$refvalue = $$option{default};
346 if($name !~ /^help|debug|verbose|module$/) {
347 if(ref($$refvalue) ne "HASH") {
350 $$refvalue = { active => 1, filter => 0, hash => {} };
354 if($name !~ /^help|debug|verbose|module$/) {
355 if(ref($$refvalue) ne "HASH") {
358 $$refvalue = { active => 0, filter => 0, hash => {} };
369 for my $name (sort(keys(%options))) {
370 if(length($name) > $maxname) {
371 $maxname = length($name);
375 print "usage: winapi-check [--help] [<files>]\n";
377 for my $name (sort(keys(%options))) {
378 my $option = $options{$name};
379 my $description = $$option{description};
380 my $default = $$option{default};
381 my $current = ${$self->{$$option{key}}};
383 my $value = $current;
386 if(ref($value) ne "HASH") {
388 $output = "--no-$name";
393 if($value->{active}) {
394 $output = "--[no-]$name\[=<value>]";
396 $output = "--$name\[=<value>]";
401 for (0..(($maxname - length($name) + 17) - (length($output) - length($name) + 1))) { print " "; }
402 if(ref($value) ne "HASH") {
409 if($value->{active}) {
415 if($default == $current) {
416 print "$description (default)\n";
418 print "$description\n";
426 my $name = $winapi_options::AUTOLOAD;
427 $name =~ s/^.*::(.[^:]*)$/\U$1/;
429 my $refvalue = $self->{$name};
430 if(!defined($refvalue)) {
431 die "<internal>: winapi_options.pm: member $name does not exists\n";
434 if(ref($$refvalue) ne "HASH") {
437 return $$refvalue->{active};
441 sub c_files { my $self = shift; return @{$self->{C_FILES}}; }
443 sub h_files { my $self = shift; return @{$self->{H_FILES}}; }
447 my $refvalue = $self->{MODULE};
452 return $$refvalue->{active} && (!$$refvalue->{filter} || $$refvalue->{hash}->{$name});
458 sub report_argument_forbidden {
460 my $refargument_forbidden = $self->{ARGUMENT_FORBIDDEN};
464 return $$refargument_forbidden->{active} && (!$$refargument_forbidden->{filter} || $$refargument_forbidden->{hash}->{$type});
467 sub report_argument_kind {
469 my $refargument_kind = $self->{ARGUMENT_KIND};
473 return $$refargument_kind->{active} && (!$$refargument_kind->{filter} || $$refargument_kind->{hash}->{$kind});