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