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}};
228 $output->lazy_progress("$file");
231 $module =~ s/^.*?([^\/]*)\.spec$/$1/;
233 open(IN, "< $file") || die "$file: $!\n";
237 while($lookahead || defined($_ = <IN>)) {
244 if(/^\d+|@/) { $header = 0; $lookahead = 1; }
250 (pascal|pascal16|stdcall|cdecl|varargs)\s+
251 ((?:(?:-noimport|-norelay|-i386|-ret64|-register|-interrupt)\s+)*)(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/x)
253 my $calling_convention = $2;
255 my $external_name = $4;
257 my $internal_name = $6;
263 if($flags =~ /(?:-register|-interrupt)/) {
264 if($arguments) { $arguments .= " "; }
268 if(!$$function_internal_name{$external_name}) {
269 $$function_internal_name{$external_name} = $internal_name;
271 $$function_internal_name{$external_name} .= " & $internal_name";
273 if(!$$function_external_name{$internal_name}) {
274 $$function_external_name{$internal_name} = $external_name;
276 $$function_external_name{$internal_name} .= " & $external_name";
278 $$function_internal_arguments{$internal_name} = $arguments;
279 $$function_external_arguments{$external_name} = $arguments;
280 if(!$$function_internal_ordinal{$internal_name}) {
281 $$function_internal_ordinal{$internal_name} = $ordinal;
283 $$function_internal_ordinal{$internal_name} .= " & $ordinal";
285 if(!$$function_external_ordinal{$external_name}) {
286 $$function_external_ordinal{$external_name} = $ordinal;
288 $$function_external_ordinal{$external_name} .= " & $ordinal";
290 $$function_internal_calling_convention{$internal_name} = $calling_convention;
291 $$function_external_calling_convention{$external_name} = $calling_convention;
292 if(!$$function_internal_module{$internal_name}) {
293 $$function_internal_module{$internal_name} = "$module";
295 $$function_internal_module{$internal_name} .= " & $module";
297 if(!$$function_external_module{$external_name}) {
298 $$function_external_module{$external_name} = "$module";
300 $$function_external_module{$external_name} .= " & $module";
303 if(0 && $options->spec_mismatch) {
304 if($external_name eq "@") {
305 if($internal_name !~ /^\U$module\E_$ordinal$/) {
306 $output->write("$file: $external_name: the internal name ($internal_name) mismatch\n");
309 my $name = $external_name;
315 $name2 =~ s/^(?:_|Rtl|k32|K32)//;
318 $name3 =~ s/^INT_Int[0-9a-f]{2}Handler$/BUILTIN_DefaultIntHandler/;
321 $name4 =~ s/^(VxDCall)\d$/$1/;
323 # FIXME: This special case is becuase of a very ugly kludge that should be fixed IMHO
325 $name5 =~ s/^(.*?16)_(.*?)$/$1_fn$2/;
327 if(uc($internal_name) ne uc($external_name) &&
328 $internal_name !~ /(\Q$name\E|\Q$name1\E|\Q$name2\E|\Q$name3\E|\Q$name4\E|\Q$name5\E)/)
330 $output->write("$file: $external_name: internal name ($internal_name) mismatch\n");
334 } elsif(/^(\d+|@)\s+stub(?:\s+(?:-noimport|-norelay|-i386|-ret64))?\s+(\S+)$/) {
335 my $external_name = $2;
339 my $internal_name = $external_name;
341 $$function_stub{$module}{$external_name} = 1;
342 if(!$$function_internal_name{$external_name}) {
343 $$function_internal_name{$external_name} = $internal_name;
345 $$function_internal_name{$external_name} .= " & $internal_name";
347 if(!$$function_external_name{$internal_name}) {
348 $$function_external_name{$internal_name} = $external_name;
350 $$function_external_name{$internal_name} .= " & $external_name";
352 if(!$$function_internal_ordinal{$internal_name}) {
353 $$function_internal_ordinal{$internal_name} = $ordinal;
355 $$function_internal_ordinal{$internal_name} .= " & $ordinal";
357 if(!$$function_external_ordinal{$external_name}) {
358 $$function_external_ordinal{$external_name} = $ordinal;
360 $$function_external_ordinal{$external_name} .= " & $ordinal";
362 if(!$$function_internal_module{$internal_name}) {
363 $$function_internal_module{$internal_name} = "$module";
364 } else { # if($$function_internal_module{$internal_name} !~ /$module/) {
365 $$function_internal_module{$internal_name} .= " & $module";
367 if(!$$function_external_module{$external_name}) {
368 $$function_external_module{$external_name} = "$module";
369 } else { # if($$function_external_module{$external_name} !~ /$module/) {
370 $$function_external_module{$external_name} .= " & $module";
372 } elsif(/^(\d+|@)\s+forward(?:\s+(?:-noimport|-norelay|-i386|-ret64))?\s+(\S+)\s+(\S+)\.(\S+)$/) {
375 my $external_name = $2;
376 my $forward_module = lc($3);
377 my $forward_name = $4;
379 $$function_forward{$external_name} = "$module:$forward_module.$forward_name";
380 } elsif(/^(\d+|@)\s+(equate|extern|variable)/) {
383 my $next_line = <IN>;
384 if(!defined($next_line) || $next_line =~ /^\s*\d|@/) {
385 die "$file: $.: syntax error: '$_'\n";
392 if(defined($ordinal)) {
393 if($ordinal ne "@" && $ordinals{$ordinal}) {
394 $output->write("$file: ordinal redefined: $_\n");
396 $ordinals{$ordinal}++;
401 $$modules{$module}++;
403 $$module_files{$module} = $file;
408 my $name = \${$self->{NAME}};
413 sub is_allowed_kind {
415 my $allowed_kind = \%{$self->{ALLOWED_KIND}};
419 return $$allowed_kind{$kind};
428 my $allowed_kind = \%{$self->{ALLOWED_KIND}};
432 $$allowed_kind{$kind}++;
435 sub is_limited_type {
437 my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
441 return $$allowed_modules_limited{$type};
444 sub is_allowed_type_in_module {
446 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
447 my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
450 my @modules = split(/ \& /, shift);
452 if(!$$allowed_modules_limited{$type}) { return 1; }
454 foreach my $module (@modules) {
455 if($$allowed_modules{$type}{$module}) { return 1; }
461 sub allow_type_in_module {
463 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
466 my @modules = split(/ \& /, shift);
468 foreach my $module (@modules) {
469 $$allowed_modules{$type}{$module}++;
473 sub type_used_in_module {
475 my $used_modules = \%{$self->{USED_MODULES}};
478 my @modules = split(/ \& /, shift);
480 foreach my $module (@modules) {
481 $$used_modules{$type}{$module} = 1;
489 my $used_modules = \%{$self->{USED_MODULES}};
490 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
493 foreach my $type (sort(keys(%$allowed_modules))) {
494 foreach my $module (sort(keys(%{$$allowed_modules{$type}}))) {
495 if(!$$used_modules{$type}{$module}) {
496 $$not_used{$module}{$type} = 1;
503 sub types_unlimited_used_in_modules {
506 my $used_modules = \%{$self->{USED_MODULES}};
507 my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
508 my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}};
511 foreach my $type (sort(keys(%$allowed_modules_unlimited))) {
514 foreach my $module (sort(keys(%{$$used_modules{$type}}))) {
516 push @modules, $module;
519 foreach my $module (@modules) {
520 $$used_types{$type}{$module} = 1;
527 sub translate_argument {
529 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
533 return $$translate_argument{$type};
536 sub declare_argument {
538 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
543 $$translate_argument{$type} = $kind;
546 sub all_declared_types {
548 my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
550 return sort(keys(%$translate_argument));
553 sub is_allowed_type_format {
555 my $type_format = \%{$self->{TYPE_FORMAT}};
563 if(defined($module) && defined($type)) {
565 foreach (split(/ & /, $module)) {
566 if(defined($formats)) {
571 if(defined($$type_format{$_}{$type})) {
572 $formats .= $$type_format{$_}{$type};
577 if(defined($formats)) {
579 foreach (split(/\|/, $formats)) {
591 my $modules = \%{$self->{MODULES}};
593 return sort(keys(%$modules));
598 my $modules = \%{$self->{MODULES}};
602 return $$modules{$name};
610 my $module_files = \%{$self->{MODULE_FILES}};
612 return $$module_files{$module};
615 sub all_internal_functions {
617 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
619 return sort(keys(%$function_internal_calling_convention));
622 sub all_internal_functions_in_module {
624 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
625 my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
630 foreach my $name (keys(%$function_internal_calling_convention)) {
631 if($$function_internal_module{$name} eq $module) {
639 sub all_external_functions {
641 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
643 return sort(keys(%$function_internal_name));
646 sub all_external_functions_in_module {
648 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
649 my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
654 foreach my $name (keys(%$function_internal_name)) {
655 if($$function_external_module{$name} eq $module) {
663 sub all_functions_stub {
665 my $function_stub = \%{$self->{FUNCTION_STUB}};
666 my $modules = \%{$self->{MODULES}};
669 foreach my $module (keys(%$modules)) {
670 push @stubs, keys(%{$$function_stub{$module}});
675 sub all_functions_stub_in_module {
677 my $function_stub = \%{$self->{FUNCTION_STUB}};
681 return sort(keys(%{$$function_stub{$module}}));
684 sub function_internal_ordinal {
686 my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}};
690 return $$function_internal_ordinal{$name};
693 sub function_external_ordinal {
695 my $function_external_ordinal = \%{$self->{FUNCTION_EXTERNAL_ORDINAL}};
699 return $$function_external_ordinal{$name};
702 sub function_internal_calling_convention {
704 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
708 return $$function_internal_calling_convention{$name};
711 sub function_external_calling_convention {
713 my $function_external_calling_convention = \%{$self->{FUNCTION_EXTERNAL_CALLING_CONVENTION}};
717 return $$function_external_calling_convention{$name};
720 sub function_internal_name {
722 my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
726 return $$function_internal_name{$name};
729 sub function_external_name {
731 my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
735 return $$function_external_name{$name};
740 my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
744 return $$function_internal_calling_convention{$name};
747 sub all_shared_internal_functions {
749 my $function_shared = \%{$self->{FUNCTION_SHARED}};
751 return sort(keys(%$function_shared));
754 sub is_shared_internal_function {
756 my $function_shared = \%{$self->{FUNCTION_SHARED}};
760 return $$function_shared{$name};
763 sub found_shared_internal_function {
765 my $function_shared = \%{$self->{FUNCTION_SHARED}};
769 $$function_shared{$name} = 1;
772 sub function_internal_arguments {
774 my $function_internal_arguments = \%{$self->{FUNCTION_INTERNAL_ARGUMENTS}};
778 return $$function_internal_arguments{$name};
781 sub function_external_arguments {
783 my $function_external_arguments = \%{$self->{FUNCTION_EXTERNAL_ARGUMENTS}};
787 return $$function_external_arguments{$name};
790 sub function_internal_module {
792 my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
796 return $$function_internal_module{$name};
799 sub function_external_module {
801 my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
805 return $$function_external_module{$name};
808 sub is_function_stub {
810 my $function_stub = \%{$self->{FUNCTION_STUB}};
811 my $modules = \%{$self->{MODULES}};
816 foreach my $module (keys(%$modules)) {
817 if($$function_stub{$module}{$name}) {
825 sub is_function_stub_in_module {
827 my $function_stub = \%{$self->{FUNCTION_STUB}};
832 return $$function_stub{$module}{$name};
835 ########################################################################
839 sub _get_all_module_internal_ordinal {
841 my $internal_name = shift;
846 my $name = $winapi->function_external_name($internal_name);
848 @name = split(/ & /, $name);
853 my $module = $winapi->function_internal_module($internal_name);
854 if(defined($module)) {
855 @module = split(/ & /, $module);
860 my $ordinal = $winapi->function_internal_ordinal($internal_name);
861 if(defined($ordinal)) {
862 @ordinal = split(/ & /, $ordinal);
869 while(defined($name = shift @name) &&
870 defined($module = shift @module) &&
871 defined($ordinal = shift @ordinal))
873 push @entries, [$name, $module, $ordinal];
879 sub get_all_module_internal_ordinal16 {
880 return _get_all_module_internal_ordinal($win16api, @_);
883 sub get_all_module_internal_ordinal32 {
884 return _get_all_module_internal_ordinal($win32api, @_);
887 sub get_all_module_internal_ordinal {
889 foreach my $winapi (@winapis) {
890 push @entries, _get_all_module_internal_ordinal($winapi, @_);
896 sub _get_all_module_external_ordinal {
898 my $external_name = shift;
903 my $name = $winapi->function_internal_name($external_name);
905 @name = split(/ & /, $name);
910 my $module = $winapi->function_external_module($external_name);
911 if(defined($module)) {
912 @module = split(/ & /, $module);
917 my $ordinal = $winapi->function_external_ordinal($external_name);
918 if(defined($ordinal)) {
919 @ordinal = split(/ & /, $ordinal);
926 while(defined($name = shift @name) &&
927 defined($module = shift @module) &&
928 defined($ordinal = shift @ordinal))
930 push @entries, [$name, $module, $ordinal];
936 sub get_all_module_external_ordinal16 {
937 return _get_all_module_external_ordinal($win16api, @_);
940 sub get_all_module_external_ordinal32 {
941 return _get_all_module_external_ordinal($win32api, @_);
944 sub get_all_module_external_ordinal {
946 foreach my $winapi (@winapis) {
947 push @entries, _get_all_module_external_ordinal($winapi, @_);