Fixed ==/!= mismatch.
[wine/testsucceed.git] / tools / winapi / winapi_fixup_documentation.pm
blob15d22eab11b1996f9db113cafe1516e4c1f72b2a
1 package winapi_fixup_documentation;
3 use strict;
5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
6 require Exporter;
8 @ISA = qw(Exporter);
9 @EXPORT = qw();
10 @EXPORT_OK = qw(&fixup_documentation);
12 use config qw($current_dir $wine_dir);
13 use modules qw($modules);
14 use options qw($options);
15 use output qw($output);
16 use winapi qw($win16api $win32api @winapis);
18 my %documentation_line_used;
20 sub fixup_documentation {
21 my $function = shift;
22 my $editor = shift;
24 my $file = $function->file;
25 my $documentation_line = $function->documentation_line;
26 my $documentation = $function->documentation;
27 my $function_line = $function->function_line;
28 my $linkage = $function->linkage;
29 my $return_type = $function->return_type;
30 my $calling_convention = $function->calling_convention;
31 my $internal_name = $function->internal_name;
32 my $statements = $function->statements;
34 if($linkage eq "static" ||
35 ($linkage eq "extern" && !defined($statements)) ||
36 ($linkage eq "" && !defined($statements)))
38 return;
41 my @external_names = $function->external_names;
42 if($#external_names < 0) {
43 return;
46 if($documentation_line_used{$file}{documentation_line}) {
47 $documentation = undef;
49 $documentation_line_used{$file}{$documentation_line}++;
51 my @module_ordinal_entries = ();
52 foreach my $entry2 ($function->get_all_module_ordinal) {
53 (my $external_name2, my $module2, my $ordinal2) = @$entry2;
54 if(($external_name2 eq "@" ||
55 ($win16api->is_module($module2) && !$win16api->is_function_stub_in_module($module2, $external_name2)) ||
56 ($win32api->is_module($module2) && !$win32api->is_function_stub_in_module($module2, $external_name2))) &&
57 $modules->is_allowed_module_in_file($module2, "$current_dir/$file"))
59 push @module_ordinal_entries, $entry2;
63 my $spec_modified = 0;
65 if($options->stub && defined($documentation)) {
66 my $calling_convention16 = $function->calling_convention16;
67 my $calling_convention32 = $function->calling_convention32;
69 foreach my $winapi (@winapis) {
70 my @entries = ();
71 my $module = $winapi->function_internal_module($internal_name);
72 my $ordinal = $winapi->function_internal_ordinal($internal_name);
74 if($winapi->is_function_stub_in_module($module, $internal_name)) {
75 my $external_name = $internal_name;
76 if($winapi->name eq "win16") {
77 $external_name =~ s/(?:_)?16([AW]?)$//;
78 if(defined($1)) {
79 $external_name .= $1;
82 push @entries, [$external_name, $module, $ordinal];
85 foreach (split(/\n/, $documentation)) {
86 if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*([^\s\)\]]*)\s*[\)\]].*?$/) {
87 my $external_name = $1;
88 my $module = lc($2);
89 my $ordinal = $3;
91 if($external_name ne "@" &&
92 $winapi->is_module($module) &&
93 $winapi->is_function_stub_in_module($module, $external_name) &&
94 $internal_name !~ /^\U$module\E_\Q$external_name\E$/)
96 push @entries, [$external_name, $module, $ordinal];
101 foreach my $entry (@entries) {
102 (my $external_name, my $module, my $ordinal) = @$entry;
104 my $refargument_types = $function->argument_types;
106 if(!defined($refargument_types)) {
107 next;
110 my $abort = 0;
111 my $n;
112 my @argument_kinds = map {
113 my $type = $_;
114 my $kind;
115 if($type ne "..." && !defined($kind = $winapi->translate_argument($type))) {
116 $output->write("no translation defined: " . $type . "\n");
119 # FIXME: Kludge
120 if(defined($kind) && $kind eq "longlong") {
121 $n += 2;
122 ("long", "long");
123 } elsif(defined($kind)) {
124 $n++;
125 $kind;
126 } elsif($type eq "...") {
127 if($winapi->name eq "win16") {
128 $calling_convention16 = "pascal"; # FIXME: Is this correct?
129 } else {
130 $calling_convention32 = "varargs";
133 } else {
134 $abort = 1;
135 $n++;
136 "undef";
138 } @$refargument_types;
140 my $search = "^\\s*$ordinal\\s+stub\\s+$external_name\\s*(?:#.*?)?\$";
141 my $replace;
142 if($winapi->name eq "win16") {
143 $replace = "$ordinal $calling_convention16 $external_name(@argument_kinds) $internal_name";
144 } else {
145 $replace = "$ordinal $calling_convention32 $external_name(@argument_kinds) $internal_name";
148 if(!$abort) {
149 $spec_modified = 1;
150 $editor->replace_spec_file($module, $search, $replace);
156 my %found_external_names;
157 foreach my $external_name (@external_names) {
158 $found_external_names{$external_name} = {};
161 my $documentation_modified = 0;
163 if(!$spec_modified &&
164 (defined($documentation) && !$documentation_modified) &&
165 ($options->documentation_name || $options->documentation_ordinal ||
166 $options->documentation_missing))
168 local $_;
170 my $line3;
171 my $search;
172 my $replace;
174 my $count = 0;
175 my $line2 = $documentation_line - 1;
176 foreach (split(/\n/, $documentation)) {
177 $line2++;
178 if(/^(\s*\*\s*(\S+)\s*)((?:\s*[\(\[]\s*\w+(?:\s*\.\s*[^\s\)\]]*\s*)?[\)\]])+)(.*?)$/) {
179 my $part1 = $1;
180 my $external_name = $2;
181 my $part3 = $3;
182 my $part4 = $4;
184 $part4 =~ s/\s*$//;
186 my @entries = ();
187 while($part3 =~ s/^\s*([\(\[]\s*(\w+)(?:\s*\.\s*([^\s\)\]]*)\s*)?[\)\]])//) {
188 push @entries, [$1, $2, $3];
191 my $found = 0;
192 foreach my $external_name2 (@external_names) {
193 if($external_name eq $external_name2) {
194 foreach my $entry (@entries) {
195 (undef, my $module, undef) = @$entry;
196 $found_external_names{$external_name2}{$module} = 1;
198 $found = 1;
199 last;
203 my $replaced = 0;
204 my $replace2 = "";
205 foreach my $entry (@entries) {
206 my $part12 = $part1;
207 (my $part32, my $module, my $ordinal) = @$entry;
209 foreach my $entry2 (@module_ordinal_entries) {
210 (my $external_name2, my $module2, my $ordinal2) = @$entry2;
212 if($options->documentation_name && lc($module) eq $module2 &&
213 $external_name ne $external_name2)
215 if(!$found && $part12 =~ s/\b\Q$external_name\E\b/$external_name2/) {
216 $external_name = $external_name2;
217 $replaced++;
221 if($options->documentation_ordinal &&
222 $external_name eq $external_name2 &&
223 lc($module) eq $module2 &&
224 ($#entries > 0 || !defined($ordinal) || ($ordinal ne $ordinal2)))
226 if(defined($ordinal)) {
227 if($part32 =~ s/\Q$module\E\s*.\s*\Q$ordinal\E/\U$module2\E.$ordinal2/ || $#entries > 0) {
228 $replaced++;
230 } else {
231 if($part32 =~ s/\Q$module\E/\U$module2\E.$ordinal2/ || $#entries > 0) {
232 $replaced++;
237 if($replace2) { $replace2 .= "\n"; }
238 $replace2 .= "$part12$part32$part4";
241 if($replaced > 0) {
242 $line3 = $line2;
243 $search = "^\Q$_\E\$";
244 $replace = $replace2;
246 $count++;
247 } elsif(/^(\s*\*\s*)([^\s\(]+)(?:\(\))?\s*$/) {
248 my $part1 = $1;
249 my $external_name = $2;
251 if($internal_name =~ /^(?:\S+_)?\Q$external_name\E(?:16)?$/) {
252 foreach my $entry (@module_ordinal_entries) {
253 (my $external_name2, my $module, my $ordinal) = @$entry;
255 $line3 = $line2;
256 $search = "^\Q$_\E\$";
257 $replace = "$part1$external_name2 (\U$module\E.$ordinal)";
259 $count++;
264 if(defined($line3) && defined($search) && defined($replace)) {
265 if($count > 1 || $#external_names >= 1) {
266 $output->write("multiple entries (fixup not supported)\n");
267 # $output->write("s/$search/$replace/\n");
268 # $output->write("@external_names\n");
269 } else {
270 $documentation_modified = 1;
271 $editor->substitute_line($line3, $search, $replace);
276 if(!$spec_modified && !$documentation_modified &&
277 $options->documentation_missing && defined($documentation))
279 my $part1;
280 my $part2;
281 my $part3;
282 my $part4;
283 my $line3 = 0;
285 my $line2 = $documentation_line - 1;
286 foreach (split(/\n/, $documentation)) {
287 $line2++;
288 if(/^(\s*\*\s*)(\S+\s*)([\(\[])\s*\w+\s*\.\s*[^\s\)\]]*\s*([\)\]]).*?$/) {
289 $part1 = $1;
290 $part2 = $2;
291 $part3 = $3;
292 $part4 = $4;
294 $part2 =~ s/\S/ /g;
296 $line3 = $line2 + 1;
300 foreach my $entry2 (@module_ordinal_entries) {
301 (my $external_name2, my $module2, my $ordinal2) = @$entry2;
303 my $found = 0;
304 foreach my $external_name (keys(%found_external_names)) {
305 foreach my $module3 (keys(%{$found_external_names{$external_name}})) {
306 if($external_name eq $external_name2 && uc($module2) eq $module3) {
307 $found = 1;
311 # FIXME: Not 100% correct
312 if(!$found &&
313 !$win16api->is_function_stub_in_module($module2, $internal_name) &&
314 !$win32api->is_function_stub_in_module($module2, $internal_name))
316 if($line3 > 0) {
317 $documentation_modified = 1;
318 $part2 = $external_name2 . " " x (length($part2) - length($external_name2));
319 $editor->insert_line($line3, "$part1$part2$part3\U$module2\E.$ordinal2$part4\n");
320 } else {
321 $output->write("$external_name2 (\U$module2\E.$ordinal2) missing (fixup not supported)\n");
327 if(!$documentation_modified &&
328 defined($documentation) &&
329 $options->documentation_wrong)
331 my $line2 = $documentation_line - 1;
332 foreach (split(/\n/, $documentation)) {
333 $line2++;
334 if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*([^\s\)\]]*)\s*[\)\]].*?$/) {
335 my $external_name = $1;
336 my $module = $2;
337 my $ordinal = $3;
339 my $found = 0;
340 foreach my $entry2 (@module_ordinal_entries) {
341 (my $external_name2, my $module2, my $ordinal2) = @$entry2;
343 if($external_name eq $external_name2 &&
344 lc($module) eq $module2 &&
345 $ordinal eq $ordinal2)
347 $found = 1;
350 if(!$found) {
351 if(1) {
352 $documentation_modified = 1;
354 $editor->delete_line($line2, "^\Q$_\E\$");
355 } else {
356 $output->write("$external_name (\U$module\E.$ordinal) wrong (fixup not supported)\n");
363 if(!$spec_modified && !$documentation_modified && !defined($documentation))
365 my $insert = "";
366 foreach my $winapi (@winapis) {
367 my $external_name = $winapi->function_external_name($internal_name);
368 my $module = $winapi->function_internal_module($internal_name);
369 my $ordinal = $winapi->function_internal_ordinal($internal_name);
371 if(defined($external_name) && defined($module) && defined($ordinal)) {
372 $insert .= " *\t\t$external_name (\U$module\E.$ordinal)\n";
375 if($insert) {
376 $editor->insert_line($function_line,
377 "/" . "*" x 71 . "\n" .
378 "$insert" .
379 " */\n");