Fixed GetDeviceState and GetDeviceData to use only exported APIs.
[wine] / tools / winapi_check / winapi_documentation.pm
1 package winapi_documentation;
2
3 use strict;
4
5 use config qw($current_dir $wine_dir);
6 use modules qw($modules);
7 use nativeapi qw($nativeapi);
8 use options qw($options);
9 use output qw($output);
10 use winapi qw($win16api $win32api @winapis);
11
12 my %comment_width;
13 my %comment_indent;
14 my %comment_spacing;
15
16 sub check_documentation {
17     local $_;
18
19     my $function = shift;
20
21     my $file = $function->file;
22     my $external_name16 = $function->external_name16;
23     my $external_name32 = $function->external_name32;
24     my $internal_name = $function->internal_name;
25     my $module16 = $function->module16;
26     my $module32 = $function->module32;
27     my $ordinal16 = $function->ordinal16;
28     my $ordinal32 = $function->ordinal32;
29     my $documentation = $function->documentation;
30     my $documentation_line = $function->documentation_line;
31
32     my $documentation_error = 0;
33     my $documentation_warning = 0;
34     if($options->documentation_name || 
35        $options->documentation_ordinal ||
36        $options->documentation_pedantic) 
37     {
38         my @winapis = ($win16api, $win32api);
39         my @modules = ($module16, $module32);
40         my @external_names = ($external_name16, $external_name32);
41         my @ordinals = ($ordinal16, $ordinal32);
42         while(
43               defined(my $winapi = shift @winapis) &&
44               defined(my $external_name = shift @external_names) &&
45               defined(my $module = shift @modules) &&
46               defined(my $ordinal = shift @ordinals))
47         {
48             if($winapi->is_function_stub_in_module($module, $internal_name)) { next; }
49
50             my @external_name = split(/\s*\&\s*/, $external_name);
51             my @modules = split(/\s*\&\s*/, $module);
52             my @ordinals = split(/\s*\&\s*/, $ordinal);
53
54             my $pedantic_failed = 0;
55             while(defined(my $external_name = shift @external_name) && 
56                   defined(my $module = shift @modules) && 
57                   defined(my $ordinal = shift @ordinals)) 
58             {
59                 my $found_name = 0;
60                 my $found_ordinal = 0;
61                 foreach (split(/\n/, $documentation)) {
62                     if(/^(\s*)\*(\s*)(\@|\S+)(\s*)([\(\[])(\w+)\.(\@|\d+)([\)\]])/) {
63                         my $external_name2 = $3;
64                         my $module2 = $6;
65                         my $ordinal2 = $7;
66
67                         if(length($1) != 1 || length($2) < 1 || 
68                            length($4) < 1 || $5 ne "(" || $8 ne ")")
69                         {
70                             $pedantic_failed = 1;
71                         }
72
73                         if($external_name eq $external_name2) {
74                             $found_name = 1;
75                             if("\U$module\E" eq $module2 &&
76                                $ordinal eq $ordinal2)
77                             {
78                                 $found_ordinal = 1;
79                             }
80                         }
81                     }
82                 }
83                 if(($options->documentation_name && !$found_name) || 
84                    ($options->documentation_ordinal && !$found_ordinal))
85                 {
86                     $documentation_error = 1;
87                     $output->write("documentation: expected $external_name (\U$module\E.$ordinal): \\\n$documentation\n");
88                 }
89                 
90             }
91             if($options->documentation_pedantic && $pedantic_failed) {
92                 $documentation_warning = 1;
93                 $output->write("documentation: pedantic failed: \\\n$documentation\n");
94             }
95         }
96     }
97
98     if(!$documentation_error && $options->documentation_wrong) {
99         foreach (split(/\n/, $documentation)) {
100             if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*([^\s\)\]]*)\s*[\)\]].*?$/) {
101                 my $external_name = $1;
102                 my $module = $2;
103                 my $ordinal = $3;
104
105                 my $found = 0;
106                 foreach my $entry2 (winapi::get_all_module_internal_ordinal($internal_name)) {
107                     (my $external_name2, my $module2, my $ordinal2) = @$entry2;
108
109                     if($external_name eq $external_name2 &&
110                        lc($module) eq $module2 &&
111                        $ordinal eq $ordinal2 &&
112                        ($external_name2 eq "@" ||
113                         ($win16api->is_module($module2) && !$win16api->is_function_stub_in_module($module2, $external_name2)) ||
114                         ($win32api->is_module($module2) && !$win32api->is_function_stub_in_module($module2, $external_name2))) &&
115                         $modules->is_allowed_module_in_file($module2, "$current_dir/$file"))
116                     {
117                         $found = 1;
118                     }
119                 }
120                 if(!$found) {
121                     $output->write("documentation: $external_name (\U$module\E.$ordinal) wrong\n");
122                 }
123             }
124         }
125     }
126
127     if($options->documentation_comment_indent) {
128         foreach (split(/\n/, $documentation)) {
129             if(/^\s*\*(\s*)\S+(\s*)[\(\[]\s*\w+\s*\.\s*[^\s\)\]]*\s*[\)\]].*?$/) {
130                 my $indent = $1;
131                 my $spacing = $2;
132                 
133                 $indent =~ s/\t/        /g;
134                 $indent = length($indent);
135                 
136                 $spacing =~ s/\t/        /g;
137                 $spacing = length($spacing);
138                 
139                 $comment_indent{$indent}++;
140                 if($indent >= 20) {
141                     $output->write("documentation: comment indent is $indent\n");
142                 }
143                 $comment_spacing{$spacing}++;
144             }
145         }
146     }
147
148     if($options->documentation_comment_width) {
149         if($documentation =~ /(^\/\*\*+)/) {
150             my $width = length($1);
151
152             $comment_width{$width}++;
153             if($width <= 65 || $width >= 81) {
154                 $output->write("comment is $width columns wide\n");
155             }
156         }
157     }
158
159     if($options->documentation_arguments) {
160         my $refargument_documentations = $function->argument_documentations;
161
162         if(defined($refargument_documentations)) {
163             my $n = 0;
164             for my $argument_documentation (@$refargument_documentations) {
165                 $n++;
166                 if($argument_documentation ne "") {
167                     if($argument_documentation !~ /^\/\*\s+\[(?:in|out|in\/out|\?\?\?)\].*?\*\/$/s) {
168                         $output->write("argument $n documentation: \\\n$argument_documentation\n");
169                     }
170                 }
171             }
172         }
173     }
174 }
175
176 sub report_documentation {
177     if($options->documentation_comment_indent) {
178         foreach my $indent (sort(keys(%comment_indent))) {
179             my $count = $comment_indent{$indent};
180             $output->write("*.c: $count functions have comment that is indented $indent\n");
181         }
182     }
183
184     if($options->documentation_comment_width) {
185         foreach my $width (sort(keys(%comment_width))) {
186             my $count = $comment_width{$width};
187             $output->write("*.c: $count functions have comments of width $width\n");
188         }
189     }
190 }
191
192 1;