Handle forwarded functions properly (based on a patch by Francois
Gouget).
diff --git a/tools/winapi/winapi.pm b/tools/winapi/winapi.pm
index 430680d..20c7347 100644
--- a/tools/winapi/winapi.pm
+++ b/tools/winapi/winapi.pm
@@ -74,12 +74,13 @@
$self->parse_api_file("$$name.api");
- foreach my $forward_name (sort(keys(%$function_forward))) {
- $$function_forward{$forward_name} =~ /^(\S*):(\S*)\.(\S*)$/;
- (my $from_module, my $to_module, my $external_name) = ($1, $2, $3);
- my $internal_name = $$function_internal_name{$external_name};
- if(defined($internal_name)) {
- $$function_module{$internal_name} .= " & $from_module";
+ foreach my $module (sort(keys(%$function_forward))) {
+ foreach my $external_name (sort(keys(%{$$function_forward{$module}}))) {
+ (my $forward_module, my $forward_external_name) = @{$$function_forward{$module}{$external_name}};
+ my $forward_internal_name = $$function_internal_name{$forward_external_name};
+ if(defined($forward_internal_name)) {
+ $$function_module{$forward_internal_name} .= " & $module";
+ }
}
}
@@ -212,12 +213,12 @@
my $function_external_calling_convention = \%{$self->{FUNCTION_EXTERNAL_CALLING_CONVENTION}};
my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
- my $function_stub = \%{$self->{FUNCTION_STUB}};
my $function_forward = \%{$self->{FUNCTION_FORWARD}};
my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
my $modules = \%{$self->{MODULES}};
my $module_files = \%{$self->{MODULE_FILES}};
+ my $module_external_calling_convention = \%{$self->{MODULE_EXTERNAL_CALLING_CONVENTION}};
my $file = shift;
$file =~ s%^\./%%;
@@ -230,6 +231,7 @@
$module = $file;
$module =~ s/^.*?([^\/]*)\.spec$/$1/;
+
open(IN, "< $file") || die "$file: $!\n";
$/ = "\n";
my $header = 1;
@@ -265,6 +267,11 @@
$arguments .= "ptr";
}
+ if($external_name ne "@") {
+ $$module_external_calling_convention{$module}{$external_name} = $calling_convention;
+ } else {
+ $$module_external_calling_convention{$module}{"\@$ordinal"} = $calling_convention;
+ }
if(!$$function_internal_name{$external_name}) {
$$function_internal_name{$external_name} = $internal_name;
} else {
@@ -338,7 +345,11 @@
my $internal_name = $external_name;
- $$function_stub{$module}{$external_name} = 1;
+ if ($external_name ne "@") {
+ $$module_external_calling_convention{$module}{$external_name} = "stub";
+ } else {
+ $$module_external_calling_convention{$module}{"\@$ordinal"} = "stub";
+ }
if(!$$function_internal_name{$external_name}) {
$$function_internal_name{$external_name} = $internal_name;
} else {
@@ -376,8 +387,24 @@
my $forward_module = lc($3);
my $forward_name = $4;
- $$function_forward{$external_name} = "$module:$forward_module.$forward_name";
- } elsif(/^(\d+|@)\s+(equate|extern|variable)/) {
+ if ($external_name ne "@") {
+ $$module_external_calling_convention{$module}{$external_name} = "forward";
+ } else {
+ $$module_external_calling_convention{$module}{"\@$ordinal"} = "forward";
+ }
+ $$function_forward{$module}{$external_name} = [$forward_module, $forward_name];
+ } elsif(/^(\d+|@)\s+extern\s+(\S+)\s+(\S+)$/) {
+ $ordinal = $1;
+
+ my $external_name = $2;
+ my $internal_name = $3;
+
+ if ($external_name ne "@") {
+ $$module_external_calling_convention{$module}{$external_name} = "extern";
+ } else {
+ $$module_external_calling_convention{$module}{"\@$ordinal"} = "extern";
+ }
+ } elsif(/^(\d+|@)\s+(equate|variable)/) {
# ignore
} else {
my $next_line = <IN>;
@@ -638,20 +665,20 @@
sub all_external_functions {
my $self = shift;
- my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
+ my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
- return sort(keys(%$function_internal_name));
+ return sort(keys(%$function_external_name));
}
sub all_external_functions_in_module {
my $self = shift;
- my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
+ my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
my $module = shift;
my @names;
- foreach my $name (keys(%$function_internal_name)) {
+ foreach my $name (keys(%$function_external_name)) {
if($$function_external_module{$name} eq $module) {
push @names, $name;
}
@@ -660,27 +687,36 @@
return sort(@names);
}
-sub all_functions_stub {
+sub all_functions_in_module {
my $self = shift;
- my $function_stub = \%{$self->{FUNCTION_STUB}};
- my $modules = \%{$self->{MODULES}};
-
- my @stubs = ();
- foreach my $module (keys(%$modules)) {
- push @stubs, keys(%{$$function_stub{$module}});
- }
- return sort(@stubs);
-}
-
-sub all_functions_stub_in_module {
- my $self = shift;
- my $function_stub = \%{$self->{FUNCTION_STUB}};
+ my $module_external_calling_convention = \%{$self->{MODULE_EXTERNAL_CALLING_CONVENTION}};
my $module = shift;
- return sort(keys(%{$$function_stub{$module}}));
+ return sort(keys(%{$$module_external_calling_convention{$module}}));
}
+sub all_broken_forwards {
+ my $self = shift;
+ my $function_forward = \%{$self->{FUNCTION_FORWARD}};
+
+ my @broken_forwards = ();
+ foreach my $module (sort(keys(%$function_forward))) {
+ foreach my $external_name (sort(keys(%{$$function_forward{$module}}))) {
+ (my $forward_module, my $forward_external_name) = @{$$function_forward{$module}{$external_name}};
+
+ my $forward_external_calling_convention =
+ $self->function_external_calling_convention_in_module($forward_module, $forward_external_name);
+
+ if(!defined($forward_external_calling_convention)) {
+ push @broken_forwards, [$module, $external_name, $forward_module, $forward_external_name];
+ }
+ }
+ }
+ return @broken_forwards;
+}
+
+
sub function_internal_ordinal {
my $self = shift;
my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}};
@@ -717,6 +753,16 @@
return $$function_external_calling_convention{$name};
}
+sub function_external_calling_convention_in_module {
+ my $self = shift;
+ my $module_external_calling_convention = \%{$self->{MODULE_EXTERNAL_CALLING_CONVENTION}};
+
+ my $module = shift;
+ my $name = shift;
+
+ return $$module_external_calling_convention{$module}{$name};
+}
+
sub function_internal_name {
my $self = shift;
my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
@@ -735,6 +781,23 @@
return $$function_external_name{$name};
}
+sub function_forward_final_destination {
+ my $self = shift;
+
+ my $function_forward = \%{$self->{FUNCTION_FORWARD}};
+
+ my $module = shift;
+ my $name = shift;
+
+ my $forward_module = $module;
+ my $forward_name = $name;
+ while(defined(my $forward = $$function_forward{$forward_module}{$forward_name})) {
+ ($forward_module, $forward_name) = @$forward;
+ }
+
+ return ($forward_module, $forward_name);
+}
+
sub is_function {
my $self = shift;
my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
@@ -807,14 +870,14 @@
sub is_function_stub {
my $self = shift;
- my $function_stub = \%{$self->{FUNCTION_STUB}};
+ my $module_external_calling_convention = \%{$self->{MODULE_EXTERNAL_CALLING_CONVENTION}};
my $modules = \%{$self->{MODULES}};
my $module = shift;
my $name = shift;
foreach my $module (keys(%$modules)) {
- if($$function_stub{$module}{$name}) {
+ if($$module_external_calling_convention{$module}{$name} eq "stub") {
return 1;
}
}
@@ -824,12 +887,15 @@
sub is_function_stub_in_module {
my $self = shift;
- my $function_stub = \%{$self->{FUNCTION_STUB}};
+ my $module_external_calling_convention = \%{$self->{MODULE_EXTERNAL_CALLING_CONVENTION}};
my $module = shift;
my $name = shift;
- return $$function_stub{$module}{$name};
+ if(!defined($$module_external_calling_convention{$module}{$name})) {
+ return 0;
+ }
+ return $$module_external_calling_convention{$module}{$name} eq "stub";
}
########################################################################