blob: efae0ed662e3bc48c2d3ab4019514bee497f15fe [file] [log] [blame]
Patrik Stridvall6a012e22001-06-13 19:38:29 +00001#!/usr/bin/perl -w
2
3# Copyright 2001 Patrik Stridvall
4
5use strict;
6
7BEGIN {
8 $0 =~ m%^(.*?/?tools)/winapi/winapi_extract$%;
9 require "$1/winapi/setup.pm";
10}
11
12use config qw(
Patrik Stridvall027c7a12001-07-19 19:10:03 +000013 &file_type &files_skip &files_filter &get_spec_files
Patrik Stridvall6a012e22001-06-13 19:38:29 +000014 $current_dir $wine_dir $winapi_dir $winapi_check_dir
15);
Patrik Stridvall1c61b3b2001-07-23 23:20:56 +000016use output qw($output);
Patrik Stridvall67f0a702001-07-26 21:42:12 +000017use winapi_extract_options qw($options);
18
Patrik Stridvallaeb023f2001-08-22 18:09:15 +000019if($options->progress) {
20 $output->enable_progress;
21} else {
22 $output->disable_progress;
23}
24
Patrik Stridvall67f0a702001-07-26 21:42:12 +000025use function;
26use type;
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +000027use winapi_function;
Patrik Stridvall6a012e22001-06-13 19:38:29 +000028use winapi_parser;
Patrik Stridvall67f0a702001-07-26 21:42:12 +000029use winapi qw(@winapis);
Patrik Stridvall6a012e22001-06-13 19:38:29 +000030
31my %module2spec_file;
32my %module2type;
Patrik Stridvall67f0a702001-07-26 21:42:12 +000033if($options->spec_files) {
Patrik Stridvall6a012e22001-06-13 19:38:29 +000034 local $_;
35
Patrik Stridvalld07a6462001-07-18 20:09:12 +000036 foreach my $spec_file (get_spec_files("winelib")) {
Patrik Stridvall6a012e22001-06-13 19:38:29 +000037 my $module;
38 my $type;
39
40 open(IN, "< $wine_dir/$spec_file");
41 while(<IN>) {
42 s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begining and end of line
43 s/^(.*?)\s*#.*$/$1/; # remove comments
44 /^$/ && next; # skip empty lines
45
46 if(/^name\s+(.*?)$/) {
47 $module = $1;
48 $module2spec_file{$module} = $spec_file;
49 } elsif(/^type\s+(.*?)$/) {
50 $type = $1;
51 $module2type{$module} = $type;
52 }
53 }
54 close(IN);
55 }
56}
57
Patrik Stridvall6a012e22001-06-13 19:38:29 +000058my %specifications;
59
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +000060sub documentation_specifications {
61 my $function = shift;
62
63 my @debug_channels = @{$function->debug_channels};
64 my $documentation = $function->documentation;
65 my $documentation_line = $function->documentation_line;
66 my $return_type = $function->return_type;
67 my $linkage = $function->linkage;
68 my $internal_name = $function->internal_name;
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +000069
70 if($linkage eq "static") {
71 return;
72 }
73
74 local $_;
75 foreach (split(/\n/, $documentation)) {
76 if(/^\s*\*\s*(\S+)\s*[\(\[]\s*(\w+)\s*\.\s*(\S+)\s*[\)\]]/) {
77 my $external_name = $1;
78 my $module = lc($2);
79 my $ordinal = $3;
80
81 if($ordinal eq "@") {
82 if(1 || !exists($specifications{$module}{unfixed}{$external_name})) {
83 $specifications{$module}{unfixed}{$external_name}{ordinal} = $ordinal;
84 $specifications{$module}{unfixed}{$external_name}{external_name} = $external_name;
85 $specifications{$module}{unfixed}{$external_name}{function} = $function;
86 } else {
87 $output->write("$external_name ($module.$ordinal) already exists\n");
88 }
89 } elsif($ordinal =~ /^\d+$/) {
90 if(1 || !exists($specifications{$module}{fixed}{$ordinal})) {
91 $specifications{$module}{fixed}{$ordinal}{ordinal} = $ordinal;
92 $specifications{$module}{fixed}{$ordinal}{external_name} = $external_name;
93 $specifications{$module}{fixed}{$ordinal}{function} = $function;
94 } else {
95 $output->write("$external_name ($module.$ordinal) already exists\n");
96 }
97 } elsif($ordinal eq "init") {
98 if(!exists($specifications{$module}{init})) {
99 $specifications{$module}{init}{function} = $function;
100 } else {
101 $output->write("$external_name ($module.$ordinal) already exists\n");
102 }
103 } else {
104 if(!exists($specifications{$module}{unknown}{$external_name})) {
105 $specifications{$module}{unknown}{$external_name}{ordinal} = $ordinal;
106 $specifications{$module}{unknown}{$external_name}{external_name} = $external_name;
107 $specifications{$module}{unknown}{$external_name}{function} = $function;
108 } else {
109 $output->write("$external_name ($module.$ordinal) already exists\n");
110 }
111 }
112
113 if($options->debug) {
114 $output->write("$external_name ($module.$ordinal)\n");
115 }
116 }
117 }
118}
119
120my %module_pseudo_stub_count16;
121my %module_pseudo_stub_count32;
122
123sub statements_stub {
124 my $function = shift;
125
126 my $statements = $function->statements;
127 if(defined($statements) && $statements =~ /FIXME[^;]*stub/s) {
128 if($options->win16) {
129 foreach my $module16 ($function->modules16) {
130 $module_pseudo_stub_count16{$module16}++;
131 }
132 }
133 if($options->win32) {
134 foreach my $module32 ($function->modules32) {
135 $module_pseudo_stub_count32{$module32}++;
136 }
137 }
138 }
139}
140
Patrik Stridvalld07a6462001-07-18 20:09:12 +0000141my @c_files = $options->c_files;
142@c_files = files_skip(@c_files);
143@c_files = files_filter("winelib", @c_files);
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000144
145my $progress_output;
146my $progress_current = 0;
Patrik Stridvalld07a6462001-07-18 20:09:12 +0000147my $progress_max = scalar(@c_files);
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000148
Patrik Stridvalld07a6462001-07-18 20:09:12 +0000149foreach my $file (@c_files) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000150 my %functions;
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000151
152 $progress_current++;
Patrik Stridvallaeb023f2001-08-22 18:09:15 +0000153 $output->progress("$file (file $progress_current of $progress_max)");
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000154
Patrik Stridvall67f0a702001-07-26 21:42:12 +0000155 my $create_function = sub {
156 if($options->stub_statistics) {
157 return 'winapi_function'->new;
158 } else {
159 return 'function'->new;
160 }
161 };
162
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000163 my $found_function = sub {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000164 my $function = shift;
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000165
Patrik Stridvallaeb023f2001-08-22 18:09:15 +0000166 my $internal_name = $function->internal_name;
167 $functions{$internal_name} = $function;
168
169 $output->progress("$file (file $progress_current of $progress_max): $internal_name");
170 $output->prefix_callback(sub { return $function->prefix; });
171
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000172 my $documentation_line = $function->documentation_line;
173 my $documentation = $function->documentation;
174 my $function_line = $function->function_line;
175 my $linkage = $function->linkage;
176 my $return_type = $function->return_type;
177 my $calling_convention = $function->calling_convention;
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000178 my $statements = $function->statements;
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000179
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000180 if($options->spec_files) {
181 documentation_specifications($function);
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000182 }
183
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000184 if($options->stub_statistics) {
185 statements_stub($function);
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000186 }
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000187
188 $output->prefix("");
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000189 };
190
Patrik Stridvall67f0a702001-07-26 21:42:12 +0000191 my $create_type = sub {
192 return 'type'->new;
193 };
194
195 my $found_type = sub {
196 my $type = shift;
197 };
198
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000199 my $found_preprocessor = sub {
200 my $directive = shift;
201 my $argument = shift;
202 };
203
Patrik Stridvall67f0a702001-07-26 21:42:12 +0000204 &winapi_parser::parse_c_file($file, $create_function, $found_function, $create_type, $found_type, $found_preprocessor);
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000205
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000206 my @internal_names = keys(%functions);
207 if($#internal_names < 0) {
208 $output->write("$file: doesn't contain any functions\n");
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000209 }
210}
211
212sub output_function {
213 local *OUT = shift;
214 my $type = shift;
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000215 my $ordinal = shift;
216 my $external_name = shift;
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000217 my $function = shift;
218
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000219 my $internal_name = $function->internal_name;
Patrik Stridvall163652b2001-06-19 03:34:39 +0000220
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000221 my $return_kind;
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000222 my $calling_convention;
Patrik Stridvall1c61b3b2001-07-23 23:20:56 +0000223 my $refargument_kinds;
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000224 if($type eq "win16") {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000225 $return_kind = $function->return_kind16 || "undef";
226 $calling_convention = $function->calling_convention16 || "undef";
Patrik Stridvall1c61b3b2001-07-23 23:20:56 +0000227 $refargument_kinds = $function->argument_kinds16;
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000228 } elsif($type eq "win32") {
229 $return_kind = $function->return_kind32 || "undef";
230 $calling_convention = $function->calling_convention32 || "undef";
Patrik Stridvall1c61b3b2001-07-23 23:20:56 +0000231 $refargument_kinds = $function->argument_kinds32;
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000232 }
233
Patrik Stridvall1c61b3b2001-07-23 23:20:56 +0000234 if(defined($refargument_kinds)) {
235 my @argument_kinds = map { $_ || "undef"; } @$refargument_kinds;
236 print OUT "$ordinal $calling_convention $external_name(@argument_kinds) $internal_name\n";
237 } else {
238 print OUT "$ordinal $calling_convention $external_name() $internal_name # FIXME: arguments undefined\n";
239 }
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000240}
241
242if($options->spec_files) {
243 foreach my $module (keys(%specifications)) {
244 my $spec_file = $module2spec_file{$module};
245 my $type = $module2type{$module};
246
247 if(!defined($spec_file) || !defined($type)) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000248 $output->write("$module: doesn't exist\n");
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000249 next;
250 }
251
252 $spec_file .= "2";
253
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000254 $output->progress("$spec_file");
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000255 open(OUT, "> $wine_dir/$spec_file");
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000256
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000257 print OUT "name $module\n";
258 print OUT "type $type\n";
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000259 if(exists($specifications{$module}{init})) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000260 my $function = $specifications{$module}{init}{function};
261 print OUT "init " . $function->internal_name . "\n";
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000262 }
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000263 print OUT "\n";
264
265 my %debug_channels;
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000266 if(exists($specifications{$module}{init})) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000267 my $function = $specifications{$module}{init}{function};
268 foreach my $debug_channel (@{$function->debug_channels}) {
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000269 $debug_channels{$debug_channel}++;
270 }
271 }
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000272 foreach my $ordinal (sort {$a <=> $b} keys(%{$specifications{$module}{fixed}})) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000273 my $function = $specifications{$module}{fixed}{$ordinal}{function};
274 foreach my $debug_channel (@{$function->debug_channels}) {
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000275 $debug_channels{$debug_channel}++;
276 }
277 }
278 foreach my $name (sort(keys(%{$specifications{$module}{unfixed}}))) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000279 my $function = $specifications{$module}{unfixed}{$name}{function};
280 foreach my $debug_channel (@{$function->debug_channels}) {
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000281 $debug_channels{$debug_channel}++;
282 }
283 }
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000284 foreach my $name (sort(keys(%{$specifications{$module}{unknown}}))) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000285 my $function = $specifications{$module}{unknown}{$name}{function};
286 foreach my $debug_channel (@{$function->debug_channels}) {
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000287 $debug_channels{$debug_channel}++;
288 }
289 }
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000290
291 my @debug_channels = sort(keys(%debug_channels));
292 if($#debug_channels >= 0) {
293 print OUT "debug_channels (" . join(" ", @debug_channels) . ")\n";
294 print OUT "\n";
295 }
296
297 my $empty = 1;
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000298
299 if(!$empty) {
300 print OUT "\n";
301 $empty = 1;
302 }
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000303 foreach my $external_name (sort(keys(%{$specifications{$module}{unknown}}))) {
304 my $entry = $specifications{$module}{unknown}{$external_name};
305 my $ordinal = $entry->{ordinal};
306 my $function = $entry->{function};
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000307 print OUT "# ";
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000308 output_function(\*OUT, $type, $ordinal, $external_name, $function);
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000309 $empty = 0;
310 }
311
312 if(!$empty) {
313 print OUT "\n";
314 $empty = 1;
315 }
316 foreach my $ordinal (sort {$a <=> $b} keys(%{$specifications{$module}{fixed}})) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000317 my $entry = $specifications{$module}{fixed}{$ordinal};
318 my $external_name = $entry->{external_name};
319 my $function = $entry->{function};
320 output_function(\*OUT, $type, $ordinal, $external_name, $function);
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000321 $empty = 0;
322 }
323
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000324 if(!$empty) {
325 print OUT "\n";
326 $empty = 1;
327 }
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000328 foreach my $external_name (sort(keys(%{$specifications{$module}{unfixed}}))) {
329 my $entry = $specifications{$module}{unfixed}{$external_name};
330 my $ordinal = $entry->{ordinal};
331 my $function = $entry->{function};
332 output_function(\*OUT, $type, $ordinal, $external_name, $function);
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000333 $empty = 0;
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000334 }
Patrik Stridvall47a99e12001-07-08 20:33:20 +0000335
Patrik Stridvall6a012e22001-06-13 19:38:29 +0000336 close(OUT);
337 }
338}
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000339
340if($options->stub_statistics) {
341 foreach my $winapi (@winapis) {
342 if($winapi->name eq "win16" && !$options->win16) { next; }
343 if($winapi->name eq "win32" && !$options->win32) { next; }
344
345 my %module_stub_count;
346 my %module_total_count;
347
348 foreach my $internal_name ($winapi->all_internal_functions,$winapi->all_functions_stub) {
349 foreach my $module (split(/ \& /, $winapi->function_internal_module($internal_name))) {
Patrik Stridvall67f0a702001-07-26 21:42:12 +0000350 if($winapi->is_function_stub_in_module($module, $internal_name)) {
Patrik Stridvallc3e8ac32001-07-11 17:27:45 +0000351 $module_stub_count{$module}++;
352 }
353 $module_total_count{$module}++;
354 }
355 }
356
357 foreach my $module ($winapi->all_modules) {
358 my $pseudo_stubs;
359 if($winapi->name eq "win16") {
360 $pseudo_stubs = $module_pseudo_stub_count16{$module};
361 } elsif($winapi->name eq "win32") {
362 $pseudo_stubs = $module_pseudo_stub_count32{$module};
363 }
364
365 my $real_stubs = $module_stub_count{$module};
366 my $total = $module_total_count{$module};
367
368 if(!defined($real_stubs)) { $real_stubs = 0; }
369 if(!defined($pseudo_stubs)) { $pseudo_stubs = 0; }
370 if(!defined($total)) { $total = 0;}
371
372 my $stubs = $real_stubs + $pseudo_stubs;
373
374 $output->write("*.c: $module: ");
375 $output->write("$stubs of $total functions are stubs ($real_stubs real, $pseudo_stubs pseudo)\n");
376 }
377 }
378}
379