2 # Copyright 1999, 2000, 2001 Patrik Stridvall
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
28 @EXPORT_OK = qw($win16api $win32api @winapis);
30 use vars qw($win16api $win32api @winapis);
32 use config qw($current_dir $wine_dir $winapi_dir);
33 use modules qw($modules);
34 use options qw($options);
35 use output qw($output);
37 my @spec_files16 = $modules->allowed_spec_files16;
38 $win16api = 'winapi'->new("win16", \@spec_files16);
40 my @spec_files32 = $modules->allowed_spec_files32;
41 $win32api = 'winapi'->new("win32", \@spec_files32);
43 @winapis = ($win16api, $win32api);
45 for my $internal_name ($win32api->all_internal_functions) {
46 my $module16 = $win16api->function_internal_module($internal_name);
47 my $module32 = $win16api->function_internal_module($internal_name);
48 if(defined($module16) &&
49 !$win16api->is_function_stub_in_module($module16, $internal_name) &&
50 !$win32api->is_function_stub_in_module($module32, $internal_name))
52 $win16api->found_shared_internal_function($internal_name);
53 $win32api->found_shared_internal_function($internal_name);
59 my $class = ref($proto) || $proto;
61 bless ($self, $class);
63 my $name = \${$self->{NAME}};
64 my $function_forward = \%{$self->{FUNCTION_FORWARD}};
65 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
66 my $function_module = \%{$self->{FUNCTION_MODULE}};
69 my $refspec_files = shift;
71 foreach my $file (@$refspec_files) {
72 $self->parse_spec_file("$wine_dir/$file");
75 $self->parse_api_file("$$name.api");
77 foreach my $forward_name (sort(keys(%$function_forward))) {
78 $$function_forward{$forward_name} =~ /^(\S*):(\S*)\.(\S*)$/;
79 (my $from_module, my $to_module, my $external_name) = ($1, $2, $3);
80 my $internal_name = $$function_internal_name{$external_name};
81 if(defined($internal_name)) {
82 $$function_module{$internal_name} .= " & $from_module";
100 my $allowed_kind = \%{$self->{ALLOWED_KIND}};
101 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
102 my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
103 my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}};
104 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
105 my $type_format = \%{$self->{TYPE_FORMAT}};
115 $output->lazy_progress("$file");
117 open(IN, "< $winapi_dir/$file") || die "$winapi_dir/$file: $!\n";
120 s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line
121 s/^(.*?)\s*#.*$/$1/; # remove comments
122 /^$/ && next; # skip empty lines
126 $module =~ s/\.dll$//; # FIXME: Kludge
127 } elsif(!$modules->is_allowed_module($module)) {
129 } elsif(s/^%(\S+)\s*//) {
135 $$allowed_kind{$kind} = 1;
138 } elsif(/^--extension/) {
140 } elsif(/^--format=(\".*?\"|\S*)/) {
142 $format =~ s/^\"(.*?)\"$/$1/;
145 if(!defined($format)) {
146 if($kind eq "long") {
147 $format = "%d|%u|%x|%X|";
148 $format .= "%hd|%hu|%hx|%hX|";
149 $format .= "%ld|%lu|%lx|%lX|";
150 $format .= "%04x|%04X|0x%04x|0x%04X|";
151 $format .= "%08x|%08X|0x%08x|0x%08X|";
152 $format .= "%08lx|%08lX|0x%08lx|0x%08lX";
153 } elsif($kind eq "longlong") {
155 } elsif($kind eq "ptr") {
157 } elsif($kind eq "segptr") {
159 } elsif($kind eq "str") {
161 } elsif($kind eq "wstr") {
163 } elsif($kind eq "word") {
164 $format = "%d|%u|%x|%X|";
165 $format .= "%hd|%hu|%hx|%hX|";
166 $format .= "%04x|%04X|0x%04x|0x%04X";
168 $format = "<unknown>";
171 } elsif(defined($kind)) {
174 if(defined($module)) {
175 if($$allowed_modules_unlimited{$type}) {
176 $output->write("$file: type ($type) already specificed as an unlimited type\n");
177 } elsif(!$$allowed_modules{$type}{$module}) {
178 $$allowed_modules{$type}{$module} = 1;
179 $$allowed_modules_limited{$type} = 1;
181 $output->write("$file: type ($type) already specificed\n");
184 $$allowed_modules_unlimited{$type} = 1;
187 $$allowed_modules_limited{$type} = 1;
189 if(defined($$translate_argument{$type}) && $$translate_argument{$type} ne $kind) {
190 $output->write("$file: type ($type) respecified as different kind ($kind != $$translate_argument{$type})\n");
192 $$translate_argument{$type} = $kind;
195 $$type_format{$module}{$type} = $format;
197 $output->write("$file: file must begin with %<type> statement\n");
204 sub parse_spec_file {
207 my $function_internal_arguments = \%{$self->{FUNCTION_INTERNAL_ARGUMENTS}};
208 my $function_external_arguments = \%{$self->{FUNCTION_EXTERNAL_ARGUMENTS}};
209 my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}};
210 my $function_external_ordinal = \%{$self->{FUNCTION_EXTERNAL_ORDINAL}};
211 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
212 my $function_external_calling_convention = \%{$self->{FUNCTION_EXTERNAL_CALLING_CONVENTION}};
213 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
214 my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
215 my $function_stub = \%{$self->{FUNCTION_STUB}};
216 my $function_forward = \%{$self->{FUNCTION_FORWARD}};
217 my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
218 my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
219 my $modules = \%{$self->{MODULES}};
220 my $module_files = \%{$self->{MODULE_FILES}};
229 $output->lazy_progress("$file");
232 $module =~ s/^.*?([^\/]*)\.spec$/$1/;
234 open(IN, "< $file") || die "$file: $!\n";
238 while($lookahead || defined($_ = <IN>)) {
245 if(/^name\s*(\S*)/) { $module = $1; }
246 if(/^file\s*(\S*)/) { $module_file = $1; }
247 if(/^\d+|@/) { $header = 0; $lookahead = 1; }
253 (pascal|pascal16|stdcall|cdecl|varargs)\s+
254 ((?:(?:-noimport|-norelay|-i386|-ret64|-register|-interrupt)\s+)*)(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/x)
256 my $calling_convention = $2;
258 my $external_name = $4;
260 my $internal_name = $6;
266 if($flags =~ /(?:-register|-interrupt)/) {
267 if($arguments) { $arguments .= " "; }
271 if(!$$function_internal_name{$external_name}) {
272 $$function_internal_name{$external_name} = $internal_name;
274 $$function_internal_name{$external_name} .= " & $internal_name";
276 if(!$$function_external_name{$internal_name}) {
277 $$function_external_name{$internal_name} = $external_name;
279 $$function_external_name{$internal_name} .= " & $external_name";
281 $$function_internal_arguments{$internal_name} = $arguments;
282 $$function_external_arguments{$external_name} = $arguments;
283 if(!$$function_internal_ordinal{$internal_name}) {
284 $$function_internal_ordinal{$internal_name} = $ordinal;
286 $$function_internal_ordinal{$internal_name} .= " & $ordinal";
288 if(!$$function_external_ordinal{$external_name}) {
289 $$function_external_ordinal{$external_name} = $ordinal;
291 $$function_external_ordinal{$external_name} .= " & $ordinal";
293 $$function_internal_calling_convention{$internal_name} = $calling_convention;
294 $$function_external_calling_convention{$external_name} = $calling_convention;
295 if(!$$function_internal_module{$internal_name}) {
296 $$function_internal_module{$internal_name} = "$module";
298 $$function_internal_module{$internal_name} .= " & $module";
300 if(!$$function_external_module{$external_name}) {
301 $$function_external_module{$external_name} = "$module";
303 $$function_external_module{$external_name} .= " & $module";
306 if(0 && $options->spec_mismatch) {
307 if($external_name eq "@") {
308 if($internal_name !~ /^\U$module\E_$ordinal$/) {
309 $output->write("$file: $external_name: the internal name ($internal_name) mismatch\n");
312 my $name = $external_name;
318 $name2 =~ s/^(?:_|Rtl|k32|K32)//;
321 $name3 =~ s/^INT_Int[0-9a-f]{2}Handler$/BUILTIN_DefaultIntHandler/;
324 $name4 =~ s/^(VxDCall)\d$/$1/;
326 # FIXME: This special case is becuase of a very ugly kludge that should be fixed IMHO
328 $name5 =~ s/^(.*?16)_(.*?)$/$1_fn$2/;
330 if(uc($internal_name) ne uc($external_name) &&
331 $internal_name !~ /(\Q$name\E|\Q$name1\E|\Q$name2\E|\Q$name3\E|\Q$name4\E|\Q$name5\E)/)
333 $output->write("$file: $external_name: internal name ($internal_name) mismatch\n");
337 } elsif(/^(\d+|@)\s+stub(?:\s+(?:-noimport|-norelay|-i386|-ret64))?\s+(\S+)$/) {
338 my $external_name = $2;
342 my $internal_name = $external_name;
344 $$function_stub{$module}{$external_name} = 1;
345 if(!$$function_internal_name{$external_name}) {
346 $$function_internal_name{$external_name} = $internal_name;
348 $$function_internal_name{$external_name} .= " & $internal_name";
350 if(!$$function_external_name{$internal_name}) {
351 $$function_external_name{$internal_name} = $external_name;
353 $$function_external_name{$internal_name} .= " & $external_name";
355 if(!$$function_internal_ordinal{$internal_name}) {
356 $$function_internal_ordinal{$internal_name} = $ordinal;
358 $$function_internal_ordinal{$internal_name} .= " & $ordinal";
360 if(!$$function_external_ordinal{$external_name}) {
361 $$function_external_ordinal{$external_name} = $ordinal;
363 $$function_external_ordinal{$external_name} .= " & $ordinal";
365 if(!$$function_internal_module{$internal_name}) {
366 $$function_internal_module{$internal_name} = "$module";
367 } else { # if($$function_internal_module{$internal_name} !~ /$module/) {
368 $$function_internal_module{$internal_name} .= " & $module";
370 if(!$$function_external_module{$external_name}) {
371 $$function_external_module{$external_name} = "$module";
372 } else { # if($$function_external_module{$external_name} !~ /$module/) {
373 $$function_external_module{$external_name} .= " & $module";
375 } elsif(/^(\d+|@)\s+forward(?:\s+(?:-noimport|-norelay|-i386|-ret64))?\s+(\S+)\s+(\S+)\.(\S+)$/) {
378 my $external_name = $2;
379 my $forward_module = lc($3);
380 my $forward_name = $4;
382 $$function_forward{$external_name} = "$module:$forward_module.$forward_name";
383 } elsif(/^(\d+|@)\s+(equate|extern|variable)/) {
386 my $next_line = <IN>;
387 if(!defined($next_line) || $next_line =~ /^\s*\d|@/) {
388 die "$file: $.: syntax error: '$_'\n";
395 if(defined($ordinal)) {
396 if($ordinal ne "@" && $ordinals{$ordinal}) {
397 $output->write("$file: ordinal redefined: $_\n");
399 $ordinals{$ordinal}++;
404 $$modules{$module}++;
406 $$module_files{$module} = $file;
411 my $name = \${$self->{NAME}};
416 sub is_allowed_kind {
418 my $allowed_kind = \%{$self->{ALLOWED_KIND}};
422 return $$allowed_kind{$kind};
431 my $allowed_kind = \%{$self->{ALLOWED_KIND}};
435 $$allowed_kind{$kind}++;
438 sub is_limited_type {
440 my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
444 return $$allowed_modules_limited{$type};
447 sub is_allowed_type_in_module {
449 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
450 my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
453 my @modules = split(/ \& /, shift);
455 if(!$$allowed_modules_limited{$type}) { return 1; }
457 foreach my $module (@modules) {
458 if($$allowed_modules{$type}{$module}) { return 1; }
464 sub allow_type_in_module {
466 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
469 my @modules = split(/ \& /, shift);
471 foreach my $module (@modules) {
472 $$allowed_modules{$type}{$module}++;
476 sub type_used_in_module {
478 my $used_modules = \%{$self->{USED_MODULES}};
481 my @modules = split(/ \& /, shift);
483 foreach my $module (@modules) {
484 $$used_modules{$type}{$module} = 1;
492 my $used_modules = \%{$self->{USED_MODULES}};
493 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
496 foreach my $type (sort(keys(%$allowed_modules))) {
497 foreach my $module (sort(keys(%{$$allowed_modules{$type}}))) {
498 if(!$$used_modules{$type}{$module}) {
499 $$not_used{$module}{$type} = 1;
506 sub types_unlimited_used_in_modules {
509 my $used_modules = \%{$self->{USED_MODULES}};
510 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
511 my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}};
514 foreach my $type (sort(keys(%$allowed_modules_unlimited))) {
517 foreach my $module (sort(keys(%{$$used_modules{$type}}))) {
519 push @modules, $module;
522 foreach my $module (@modules) {
523 $$used_types{$type}{$module} = 1;
530 sub translate_argument {
532 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
536 return $$translate_argument{$type};
539 sub declare_argument {
541 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
546 $$translate_argument{$type} = $kind;
549 sub all_declared_types {
551 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
553 return sort(keys(%$translate_argument));
556 sub is_allowed_type_format {
558 my $type_format = \%{$self->{TYPE_FORMAT}};
566 if(defined($module) && defined($type)) {
568 foreach (split(/ & /, $module)) {
569 if(defined($formats)) {
574 if(defined($$type_format{$_}{$type})) {
575 $formats .= $$type_format{$_}{$type};
580 if(defined($formats)) {
582 foreach (split(/\|/, $formats)) {
594 my $modules = \%{$self->{MODULES}};
596 return sort(keys(%$modules));
601 my $modules = \%{$self->{MODULES}};
605 return $$modules{$name};
613 my $module_files = \%{$self->{MODULE_FILES}};
615 return $$module_files{$module};
618 sub all_internal_functions {
620 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
622 return sort(keys(%$function_internal_calling_convention));
625 sub all_internal_functions_in_module {
627 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
628 my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
633 foreach my $name (keys(%$function_internal_calling_convention)) {
634 if($$function_internal_module{$name} eq $module) {
642 sub all_external_functions {
644 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
646 return sort(keys(%$function_internal_name));
649 sub all_external_functions_in_module {
651 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
652 my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
657 foreach my $name (keys(%$function_internal_name)) {
658 if($$function_external_module{$name} eq $module) {
666 sub all_functions_stub {
668 my $function_stub = \%{$self->{FUNCTION_STUB}};
669 my $modules = \%{$self->{MODULES}};
672 foreach my $module (keys(%$modules)) {
673 push @stubs, keys(%{$$function_stub{$module}});
678 sub all_functions_stub_in_module {
680 my $function_stub = \%{$self->{FUNCTION_STUB}};
684 return sort(keys(%{$$function_stub{$module}}));
687 sub function_internal_ordinal {
689 my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}};
693 return $$function_internal_ordinal{$name};
696 sub function_external_ordinal {
698 my $function_external_ordinal = \%{$self->{FUNCTION_EXTERNAL_ORDINAL}};
702 return $$function_external_ordinal{$name};
705 sub function_internal_calling_convention {
707 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
711 return $$function_internal_calling_convention{$name};
714 sub function_external_calling_convention {
716 my $function_external_calling_convention = \%{$self->{FUNCTION_EXTERNAL_CALLING_CONVENTION}};
720 return $$function_external_calling_convention{$name};
723 sub function_internal_name {
725 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
729 return $$function_internal_name{$name};
732 sub function_external_name {
734 my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
738 return $$function_external_name{$name};
743 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
747 return $$function_internal_calling_convention{$name};
750 sub all_shared_internal_functions {
752 my $function_shared = \%{$self->{FUNCTION_SHARED}};
754 return sort(keys(%$function_shared));
757 sub is_shared_internal_function {
759 my $function_shared = \%{$self->{FUNCTION_SHARED}};
763 return $$function_shared{$name};
766 sub found_shared_internal_function {
768 my $function_shared = \%{$self->{FUNCTION_SHARED}};
772 $$function_shared{$name} = 1;
775 sub function_internal_arguments {
777 my $function_internal_arguments = \%{$self->{FUNCTION_INTERNAL_ARGUMENTS}};
781 return $$function_internal_arguments{$name};
784 sub function_external_arguments {
786 my $function_external_arguments = \%{$self->{FUNCTION_EXTERNAL_ARGUMENTS}};
790 return $$function_external_arguments{$name};
793 sub function_internal_module {
795 my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
799 return $$function_internal_module{$name};
802 sub function_external_module {
804 my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
808 return $$function_external_module{$name};
811 sub is_function_stub {
813 my $function_stub = \%{$self->{FUNCTION_STUB}};
814 my $modules = \%{$self->{MODULES}};
819 foreach my $module (keys(%$modules)) {
820 if($$function_stub{$module}{$name}) {
828 sub is_function_stub_in_module {
830 my $function_stub = \%{$self->{FUNCTION_STUB}};
835 return $$function_stub{$module}{$name};
838 ########################################################################
842 sub _get_all_module_internal_ordinal {
844 my $internal_name = shift;
849 my $name = $winapi->function_external_name($internal_name);
851 @name = split(/ & /, $name);
856 my $module = $winapi->function_internal_module($internal_name);
857 if(defined($module)) {
858 @module = split(/ & /, $module);
863 my $ordinal = $winapi->function_internal_ordinal($internal_name);
864 if(defined($ordinal)) {
865 @ordinal = split(/ & /, $ordinal);
872 while(defined($name = shift @name) &&
873 defined($module = shift @module) &&
874 defined($ordinal = shift @ordinal))
876 push @entries, [$name, $module, $ordinal];
882 sub get_all_module_internal_ordinal16 {
883 return _get_all_module_internal_ordinal($win16api, @_);
886 sub get_all_module_internal_ordinal32 {
887 return _get_all_module_internal_ordinal($win32api, @_);
890 sub get_all_module_internal_ordinal {
892 foreach my $winapi (@winapis) {
893 push @entries, _get_all_module_internal_ordinal($winapi, @_);
899 sub _get_all_module_external_ordinal {
901 my $external_name = shift;
906 my $name = $winapi->function_internal_name($external_name);
908 @name = split(/ & /, $name);
913 my $module = $winapi->function_external_module($external_name);
914 if(defined($module)) {
915 @module = split(/ & /, $module);
920 my $ordinal = $winapi->function_external_ordinal($external_name);
921 if(defined($ordinal)) {
922 @ordinal = split(/ & /, $ordinal);
929 while(defined($name = shift @name) &&
930 defined($module = shift @module) &&
931 defined($ordinal = shift @ordinal))
933 push @entries, [$name, $module, $ordinal];
939 sub get_all_module_external_ordinal16 {
940 return _get_all_module_external_ordinal($win16api, @_);
943 sub get_all_module_external_ordinal32 {
944 return _get_all_module_external_ordinal($win32api, @_);
947 sub get_all_module_external_ordinal {
949 foreach my $winapi (@winapis) {
950 push @entries, _get_all_module_external_ordinal($winapi, @_);