5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
10 @EXPORT_OK = qw($win16api $win32api @winapis);
12 use vars qw($win16api $win32api @winapis);
17 $current_dir $wine_dir
19 use modules qw($modules);
20 use options qw($options);
21 use output qw($output);
23 my @spec_files16 = $modules->allowed_spec_files16;
24 $win16api = 'winapi'->new("win16", \@spec_files16);
26 my @spec_files32 = $modules->allowed_spec_files32;
27 $win32api = 'winapi'->new("win32", \@spec_files32);
29 @winapis = ($win16api, $win32api);
31 for my $internal_name ($win32api->all_internal_functions) {
32 my $module16 = $win16api->function_internal_module($internal_name);
33 my $module32 = $win16api->function_internal_module($internal_name);
34 if(defined($module16) &&
35 !$win16api->is_function_stub_in_module($module16, $internal_name) &&
36 !$win32api->is_function_stub_in_module($module32, $internal_name))
38 $win16api->found_shared_internal_function($internal_name);
39 $win32api->found_shared_internal_function($internal_name);
45 my $class = ref($proto) || $proto;
47 bless ($self, $class);
49 my $name = \${$self->{NAME}};
50 my $function_forward = \%{$self->{FUNCTION_FORWARD}};
51 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
52 my $function_module = \%{$self->{FUNCTION_MODULE}};
55 my $refspec_files = shift;
57 foreach my $file (@$refspec_files) {
58 $self->parse_spec_file("$wine_dir/$file");
61 foreach my $file (get_api_files($$name)) {
63 $module =~ s/.*?\/([^\/]*?)\.api$/$1/;
65 if($modules->is_allowed_module($module)) {
66 $self->parse_api_file($file,$module);
70 foreach my $forward_name (sort(keys(%$function_forward))) {
71 $$function_forward{$forward_name} =~ /^(\S*):(\S*)\.(\S*)$/;
72 (my $from_module, my $to_module, my $external_name) = ($1, $2, $3);
73 my $internal_name = $$function_internal_name{$external_name};
74 if(defined($internal_name)) {
75 $$function_module{$internal_name} .= " & $from_module";
93 my $allowed_kind = \%{$self->{ALLOWED_KIND}};
94 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
95 my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
96 my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}};
97 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
98 my $type_format = \%{$self->{TYPE_FORMAT}};
108 if($options->progress) {
109 $output->lazy_progress("$file");
112 open(IN, "< $wine_dir/$file") || die "$wine_dir/$file: $!\n";
115 s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line
116 s/^(.*?)\s*#.*$/$1/; # remove comments
117 /^$/ && next; # skip empty lines
125 $$allowed_kind{$kind} = 1;
128 } elsif(/^--extension/) {
130 } elsif(/^--format=(\".*?\"|\S*)/) {
132 $format =~ s/^\"(.*?)\"$/$1/;
135 if(!defined($format)) {
136 if($kind eq "long") {
137 $format = "%d|%u|%x|%X|";
138 $format .= "%hd|%hu|%hx|%hX|";
139 $format .= "%ld|%lu|%lx|%lX|";
140 $format .= "%04x|%04X|0x%04x|0x%04X|";
141 $format .= "%08x|%08X|0x%08x|0x%08X|";
142 $format .= "%08lx|%08lX|0x%08lx|0x%08lX";
143 } elsif($kind eq "longlong") {
145 } elsif($kind eq "ptr") {
147 } elsif($kind eq "segptr") {
149 } elsif($kind eq "str") {
151 } elsif($kind eq "wstr") {
153 } elsif($kind eq "word") {
154 $format = "%d|%u|%x|%X|";
155 $format .= "%hd|%hu|%hx|%hX|";
156 $format .= "%04x|%04X|0x%04x|0x%04X";
158 $format = "<unknown>";
161 } elsif(defined($kind)) {
164 if(defined($module)) {
165 if($$allowed_modules_unlimited{$type}) {
166 $output->write("$file: type ($type) already specificed as an unlimited type\n");
167 } elsif(!$$allowed_modules{$type}{$module}) {
168 $$allowed_modules{$type}{$module} = 1;
169 $$allowed_modules_limited{$type} = 1;
171 $output->write("$file: type ($type) already specificed\n");
174 $$allowed_modules_unlimited{$type} = 1;
177 $$allowed_modules_limited{$type} = 1;
179 if(defined($$translate_argument{$type}) && $$translate_argument{$type} ne $kind) {
180 $output->write("$file: type ($type) respecified as different kind ($kind != $$translate_argument{$type})\n");
182 $$translate_argument{$type} = $kind;
185 $$type_format{$module}{$type} = $format;
187 $output->write("$file: file must begin with %<type> statement\n");
194 sub parse_spec_file {
197 my $function_internal_arguments = \%{$self->{FUNCTION_INTERNAL_ARGUMENTS}};
198 my $function_external_arguments = \%{$self->{FUNCTION_EXTERNAL_ARGUMENTS}};
199 my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}};
200 my $function_external_ordinal = \%{$self->{FUNCTION_EXTERNAL_ORDINAL}};
201 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
202 my $function_external_calling_convention = \%{$self->{FUNCTION_EXTERNAL_CALLING_CONVENTION}};
203 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
204 my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
205 my $function_stub = \%{$self->{FUNCTION_STUB}};
206 my $function_forward = \%{$self->{FUNCTION_FORWARD}};
207 my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
208 my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
209 my $modules = \%{$self->{MODULES}};
210 my $module_files = \%{$self->{MODULE_FILES}};
220 if($options->progress) {
221 $output->lazy_progress("$file");
224 open(IN, "< $file") || die "$file: $!\n";
228 while($lookahead || defined($_ = <IN>)) {
235 if(/^name\s*(\S*)/) { $module = $1; }
236 if(/^file\s*(\S*)/) { $module_file = $1; }
237 if(/^type\s*(\w+)/) { $type = $1; }
238 if(/^\d+|@/) { $header = 0; $lookahead = 1; }
244 (pascal|pascal16|stdcall|cdecl|register|interrupt|varargs)
245 (?:\s+(?:-noimport|-norelay|-i386|-ret64))*\s+(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/x)
247 my $calling_convention = $2;
248 my $external_name = $3;
250 my $internal_name = $5;
254 if(!$$function_internal_name{$external_name}) {
255 $$function_internal_name{$external_name} = $internal_name;
257 $$function_internal_name{$external_name} .= " & $internal_name";
259 if(!$$function_external_name{$internal_name}) {
260 $$function_external_name{$internal_name} = $external_name;
262 $$function_external_name{$internal_name} .= " & $external_name";
264 $$function_internal_arguments{$internal_name} = $arguments;
265 $$function_external_arguments{$external_name} = $arguments;
266 if(!$$function_internal_ordinal{$internal_name}) {
267 $$function_internal_ordinal{$internal_name} = $ordinal;
269 $$function_internal_ordinal{$internal_name} .= " & $ordinal";
271 if(!$$function_external_ordinal{$external_name}) {
272 $$function_external_ordinal{$external_name} = $ordinal;
274 $$function_external_ordinal{$external_name} .= " & $ordinal";
276 $$function_internal_calling_convention{$internal_name} = $calling_convention;
277 $$function_external_calling_convention{$external_name} = $calling_convention;
278 if(!$$function_internal_module{$internal_name}) {
279 $$function_internal_module{$internal_name} = "$module";
281 $$function_internal_module{$internal_name} .= " & $module";
283 if(!$$function_external_module{$external_name}) {
284 $$function_external_module{$external_name} = "$module";
286 $$function_external_module{$external_name} .= " & $module";
289 if(0 && $options->spec_mismatch) {
290 if($external_name eq "@") {
291 if($internal_name !~ /^\U$module\E_$ordinal$/) {
292 $output->write("$file: $external_name: the internal name ($internal_name) mismatch\n");
295 my $name = $external_name;
301 $name2 =~ s/^(?:_|Rtl|k32|K32)//;
304 $name3 =~ s/^INT_Int[0-9a-f]{2}Handler$/BUILTIN_DefaultIntHandler/;
307 $name4 =~ s/^(VxDCall)\d$/$1/;
309 # FIXME: This special case is becuase of a very ugly kludge that should be fixed IMHO
311 $name5 =~ s/^(.*?16)_(.*?)$/$1_fn$2/;
313 if(uc($internal_name) ne uc($external_name) &&
314 $internal_name !~ /(\Q$name\E|\Q$name1\E|\Q$name2\E|\Q$name3\E|\Q$name4\E|\Q$name5\E)/)
316 $output->write("$file: $external_name: internal name ($internal_name) mismatch\n");
320 } elsif(/^(\d+|@)\s+stub(?:\s+(?:-noimport|-norelay|-i386|-ret64))?\s+(\S+)$/) {
321 my $external_name = $2;
326 if(0 && $type eq "win16") {
327 if($external_name =~ /\d$/) {
328 $internal_name = $external_name . "_16";
330 $internal_name = $external_name . "16";
333 $internal_name = $external_name;
336 $$function_stub{$module}{$external_name} = 1;
337 if(!$$function_internal_name{$external_name}) {
338 $$function_internal_name{$external_name} = $internal_name;
340 $$function_internal_name{$external_name} .= " & $internal_name";
342 if(!$$function_external_name{$internal_name}) {
343 $$function_external_name{$internal_name} = $external_name;
345 $$function_external_name{$internal_name} .= " & $external_name";
347 if(!$$function_internal_ordinal{$internal_name}) {
348 $$function_internal_ordinal{$internal_name} = $ordinal;
350 $$function_internal_ordinal{$internal_name} .= " & $ordinal";
352 if(!$$function_external_ordinal{$external_name}) {
353 $$function_external_ordinal{$external_name} = $ordinal;
355 $$function_external_ordinal{$external_name} .= " & $ordinal";
357 if(!$$function_internal_module{$internal_name}) {
358 $$function_internal_module{$internal_name} = "$module";
359 } else { # if($$function_internal_module{$internal_name} !~ /$module/) {
360 $$function_internal_module{$internal_name} .= " & $module";
362 if(!$$function_external_module{$external_name}) {
363 $$function_external_module{$external_name} = "$module";
364 } else { # if($$function_external_module{$external_name} !~ /$module/) {
365 $$function_external_module{$external_name} .= " & $module";
367 } elsif(/^(\d+|@)\s+forward(?:\s+(?:-noimport|-norelay|-i386|-ret64))?\s+(\S+)\s+(\S+)\.(\S+)$/) {
370 my $external_name = $2;
371 my $forward_module = lc($3);
372 my $forward_name = $4;
374 $$function_forward{$external_name} = "$module:$forward_module.$forward_name";
375 } elsif(/^(\d+|@)\s+(equate|extern|variable)/) {
378 my $next_line = <IN>;
379 if(!defined($next_line) || $next_line =~ /^\s*\d|@/) {
380 die "$file: $.: syntax error: '$_'\n";
387 if(defined($ordinal)) {
388 if($ordinal ne "@" && $ordinals{$ordinal}) {
389 $output->write("$file: ordinal redefined: $_\n");
391 $ordinals{$ordinal}++;
396 $$modules{$module}++;
398 $$module_files{$module} = $file;
403 my $name = \${$self->{NAME}};
408 sub is_allowed_kind {
410 my $allowed_kind = \%{$self->{ALLOWED_KIND}};
414 return $$allowed_kind{$kind};
420 sub is_limited_type {
422 my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
426 return $$allowed_modules_limited{$type};
429 sub allowed_type_in_module {
431 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
432 my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
435 my @modules = split(/ \& /, shift);
437 if(!$$allowed_modules_limited{$type}) { return 1; }
439 foreach my $module (@modules) {
440 if($$allowed_modules{$type}{$module}) { return 1; }
446 sub type_used_in_module {
448 my $used_modules = \%{$self->{USED_MODULES}};
451 my @modules = split(/ \& /, shift);
453 foreach my $module (@modules) {
454 $$used_modules{$type}{$module} = 1;
462 my $used_modules = \%{$self->{USED_MODULES}};
463 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
466 foreach my $type (sort(keys(%$allowed_modules))) {
467 foreach my $module (sort(keys(%{$$allowed_modules{$type}}))) {
468 if(!$$used_modules{$type}{$module}) {
469 $$not_used{$module}{$type} = 1;
476 sub types_unlimited_used_in_modules {
479 my $used_modules = \%{$self->{USED_MODULES}};
480 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
481 my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}};
484 foreach my $type (sort(keys(%$allowed_modules_unlimited))) {
487 foreach my $module (sort(keys(%{$$used_modules{$type}}))) {
489 push @modules, $module;
492 foreach my $module (@modules) {
493 $$used_types{$type}{$module} = 1;
500 sub translate_argument {
502 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
504 my $argument = shift;
506 return $$translate_argument{$argument};
509 sub all_declared_types {
511 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
513 return sort(keys(%$translate_argument));
516 sub is_allowed_type_format {
518 my $type_format = \%{$self->{TYPE_FORMAT}};
526 if(defined($module) && defined($type)) {
528 foreach (split(/ & /, $module)) {
529 if(defined($formats)) {
534 if(defined($$type_format{$_}{$type})) {
535 $formats .= $$type_format{$_}{$type};
540 if(defined($formats)) {
542 foreach (split(/\|/, $formats)) {
554 my $modules = \%{$self->{MODULES}};
556 return sort(keys(%$modules));
561 my $modules = \%{$self->{MODULES}};
565 return $$modules{$name};
573 my $module_files = \%{$self->{MODULE_FILES}};
575 return $$module_files{$module};
578 sub all_internal_functions {
580 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
582 return sort(keys(%$function_internal_calling_convention));
585 sub all_internal_functions_in_module {
587 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
588 my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
593 foreach my $name (keys(%$function_internal_calling_convention)) {
594 if($$function_internal_module{$name} eq $module) {
602 sub all_external_functions {
604 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
606 return sort(keys(%$function_internal_name));
609 sub all_external_functions_in_module {
611 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
612 my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
617 foreach my $name (keys(%$function_internal_name)) {
618 if($$function_external_module{$name} eq $module) {
626 sub all_functions_stub {
628 my $function_stub = \%{$self->{FUNCTION_STUB}};
629 my $modules = \%{$self->{MODULES}};
632 foreach my $module (keys(%$modules)) {
633 push @stubs, keys(%{$$function_stub{$module}});
638 sub all_functions_stub_in_module {
640 my $function_stub = \%{$self->{FUNCTION_STUB}};
644 return sort(keys(%{$$function_stub{$module}}));
647 sub function_internal_ordinal {
649 my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}};
653 return $$function_internal_ordinal{$name};
656 sub function_external_ordinal {
658 my $function_external_ordinal = \%{$self->{FUNCTION_EXTERNAL_ORDINAL}};
662 return $$function_external_ordinal{$name};
665 sub function_internal_calling_convention {
667 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
671 return $$function_internal_calling_convention{$name};
674 sub function_external_calling_convention {
676 my $function_external_calling_convention = \%{$self->{FUNCTION_EXTERNAL_CALLING_CONVENTION}};
680 return $$function_external_calling_convention{$name};
683 sub function_internal_name {
685 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
689 return $$function_internal_name{$name};
692 sub function_external_name {
694 my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
698 return $$function_external_name{$name};
703 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
707 return $$function_internal_calling_convention{$name};
710 sub all_shared_internal_functions {
712 my $function_shared = \%{$self->{FUNCTION_SHARED}};
714 return sort(keys(%$function_shared));
717 sub is_shared_internal_function {
719 my $function_shared = \%{$self->{FUNCTION_SHARED}};
723 return $$function_shared{$name};
726 sub found_shared_internal_function {
728 my $function_shared = \%{$self->{FUNCTION_SHARED}};
732 $$function_shared{$name} = 1;
735 sub function_internal_arguments {
737 my $function_internal_arguments = \%{$self->{FUNCTION_INTERNAL_ARGUMENTS}};
741 return $$function_internal_arguments{$name};
744 sub function_external_arguments {
746 my $function_external_arguments = \%{$self->{FUNCTION_EXTERNAL_ARGUMENTS}};
750 return $$function_external_arguments{$name};
753 sub function_internal_module {
755 my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
759 return $$function_internal_module{$name};
762 sub function_external_module {
764 my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
768 return $$function_external_module{$name};
771 sub is_function_stub {
773 my $function_stub = \%{$self->{FUNCTION_STUB}};
774 my $modules = \%{$self->{MODULES}};
779 foreach my $module (keys(%$modules)) {
780 if($$function_stub{$module}{$name}) {
788 sub is_function_stub_in_module {
790 my $function_stub = \%{$self->{FUNCTION_STUB}};
795 return $$function_stub{$module}{$name};
798 ########################################################################
802 sub _get_all_module_internal_ordinal {
804 my $internal_name = shift;
809 my $name = $winapi->function_external_name($internal_name);
811 @name = split(/ & /, $name);
816 my $module = $winapi->function_internal_module($internal_name);
817 if(defined($module)) {
818 @module = split(/ & /, $module);
823 my $ordinal = $winapi->function_internal_ordinal($internal_name);
824 if(defined($ordinal)) {
825 @ordinal = split(/ & /, $ordinal);
832 while(defined($name = shift @name) &&
833 defined($module = shift @module) &&
834 defined($ordinal = shift @ordinal))
836 push @entries, [$name, $module, $ordinal];
842 sub get_all_module_internal_ordinal16 {
843 return _get_all_module_internal_ordinal($win16api, @_);
846 sub get_all_module_internal_ordinal32 {
847 return _get_all_module_internal_ordinal($win32api, @_);
850 sub get_all_module_internal_ordinal {
852 foreach my $winapi (@winapis) {
853 push @entries, _get_all_module_internal_ordinal($winapi, @_);
859 sub _get_all_module_external_ordinal {
861 my $external_name = shift;
866 my $name = $winapi->function_internal_name($external_name);
868 @name = split(/ & /, $name);
873 my $module = $winapi->function_external_module($external_name);
874 if(defined($module)) {
875 @module = split(/ & /, $module);
880 my $ordinal = $winapi->function_external_ordinal($external_name);
881 if(defined($ordinal)) {
882 @ordinal = split(/ & /, $ordinal);
889 while(defined($name = shift @name) &&
890 defined($module = shift @module) &&
891 defined($ordinal = shift @ordinal))
893 push @entries, [$name, $module, $ordinal];
899 sub get_all_module_external_ordinal16 {
900 return _get_all_module_external_ordinal($win16api, @_);
903 sub get_all_module_external_ordinal32 {
904 return _get_all_module_external_ordinal($win32api, @_);
907 sub get_all_module_external_ordinal {
909 foreach my $winapi (@winapis) {
910 push @entries, _get_all_module_external_ordinal($winapi, @_);