Several additions and bug fixes.
[wine] / tools / winapi_check / nativeapi.pm
1 package nativeapi;
2
3 use strict;
4
5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
6 require Exporter;
7
8 @ISA = qw(Exporter);
9 @EXPORT = qw();
10 @EXPORT_OK = qw($nativeapi);
11
12 use vars qw($nativeapi);
13
14 sub new {
15     my $proto = shift;
16     my $class = ref($proto) || $proto;
17     my $self  = {};
18     bless ($self, $class);
19
20     my $options = \${$self->{OPTIONS}};
21     my $output = \${$self->{OUTPUT}};
22     my $functions = \%{$self->{FUNCTIONS}};
23     my $conditionals = \%{$self->{CONDITIONALS}};
24     my $conditional_headers = \%{$self->{CONDITIONAL_HEADERS}};
25     my $conditional_functions = \%{$self->{CONDITIONAL_FUNCTIONS}};
26
27     $$options = shift;
28     $$output = shift;
29     my $api_file = shift;
30     my $configure_in_file = shift;
31     my $config_h_in_file = shift;
32
33     $api_file =~ s/^\.\///;
34     $configure_in_file =~ s/^\.\///;
35     $config_h_in_file =~ s/^\.\///;
36
37     if($$options->progress) {
38         $$output->progress("$api_file");
39     }
40
41     open(IN, "< $api_file");
42     local $/ = "\n";
43     while(<IN>) {
44         s/^\s*(.*?)\s*$/$1/; # remove whitespace at begin and end of line
45         s/^(.*?)\s*#.*$/$1/; # remove comments
46         /^$/ && next;        # skip empty lines   
47
48         $$functions{$_}++;
49     }
50     close(IN);
51
52     if($$options->progress) {
53         $$output->progress("$configure_in_file");
54     }
55
56     my $again = 0;
57     open(IN, "< $configure_in_file");   
58     local $/ = "\n";
59     while($again || (defined($_ = <IN>))) {
60         $again = 0;
61         chomp;
62         if(/^(.*?)\\$/) {
63             my $current = $1;
64             my $next = <IN>;
65             if(defined($next)) {
66                 # remove trailing whitespace
67                 $current =~ s/\s+$//;
68
69                 # remove leading whitespace
70                 $next =~ s/^\s+//;
71
72                 $_ = $current . " " . $next;
73
74                 $again = 1;
75                 next;
76             }
77         }
78
79         # remove leading and trailing whitespace
80         s/^\s*(.*?)\s*$/$1/;
81
82         # skip emty lines
83         if(/^$/) { next; }
84
85         # skip comments
86         if(/^dnl/) { next; }
87
88         if(/^AC_CHECK_HEADERS\(\s*([^,\)]*)(?:,|\))?/) {
89             foreach my $name (split(/\s+/, $1)) {
90                 $$conditional_headers{$name}++;
91             }
92         } elsif(/^AC_CHECK_FUNCS\(\s*([^,\)]*)(?:,|\))?/) {
93             foreach my $name (split(/\s+/, $1)) {
94                 $$conditional_functions{$name}++;
95             }
96         } elsif(/^AC_FUNC_ALLOCA/) {
97             $$conditional_headers{"alloca.h"}++;
98         }
99
100     }
101     close(IN);
102
103     if($$options->progress) {
104         $$output->progress("$config_h_in_file");
105     }
106
107     open(IN, "< $config_h_in_file");
108     local $/ = "\n";
109     while(<IN>) {
110         # remove leading and trailing whitespace
111         s/^\s*(.*?)\s*$/$1/;
112
113         # skip emty lines
114         if(/^$/) { next; }
115
116         if(/^\#undef\s+(\S+)$/) {
117             $$conditionals{$1}++;
118         }
119     }
120     close(IN);
121
122     $nativeapi = $self;
123
124     return $self;
125 }
126
127 sub is_function {
128     my $self = shift;
129     my $functions = \%{$self->{FUNCTIONS}};
130
131     my $name = shift;
132
133     return $$functions{$name};
134 }
135
136 sub is_conditional {
137     my $self = shift;
138     my $conditionals = \%{$self->{CONDITIONALS}};
139
140     my $name = shift;
141
142     return $$conditionals{$name};
143 }
144
145 sub found_conditional {
146     my $self = shift;
147     my $conditional_found = \%{$self->{CONDITIONAL_FOUND}};
148
149     my $name = shift;
150
151     $$conditional_found{$name}++;
152 }
153
154 sub is_conditional_header {
155     my $self = shift;
156     my $conditional_headers = \%{$self->{CONDITIONAL_HEADERS}};
157
158     my $name = shift;
159
160     return $$conditional_headers{$name};
161 }
162
163 sub is_conditional_function {
164     my $self = shift;
165     my $conditional_functions = \%{$self->{CONDITIONAL_FUNCTIONS}};
166
167     my $name = shift;
168
169     return $$conditional_functions{$name};
170 }
171
172 sub global_report {
173     my $self = shift;
174
175     my $output = \${$self->{OUTPUT}};
176     my $conditional_found = \%{$self->{CONDITIONAL_FOUND}};
177     my $conditionals = \%{$self->{CONDITIONALS}};
178
179     my @messages;
180     foreach my $name (sort(keys(%$conditionals))) {
181         if($name =~ /^const|inline|size_t$/) { next; }
182
183         if(0 && !$$conditional_found{$name}) {
184             push @messages, "config.h.in: conditional $name not used\n";
185         }
186     }
187
188     foreach my $message (sort(@messages)) {
189         $$output->write($message);
190     }
191 }
192
193 1;